Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Starscream as dependency, use Apple's URLSession-based websockets instead #124

Merged
merged 14 commits into from
Jul 11, 2022

Conversation

oscahie
Copy link
Contributor

@oscahie oscahie commented Jul 7, 2022

This PR removes Starscream as dependency in favour of using Apple's URLSessionWebSocketTask directly in the WebSocketConnection class (see motivation).

The minimum required iOS version has been updated to iOS 13.0 due URLSessionWebSocketTask having been introduced on iOS 13.

I did quite a bit of testing trying to cover various edge cases related to connectivity issues, such as attempting to initiate a new session with no network availability, or having the app lose the connection temporarily. Since it uses URLSession's built-in waitsForConnectivity configuration option, I think it now behaves significantly better than what it was before (retrying indefinitely at a very rapid pace, using lots of CPU and memory).

The disconnect detection issues reported in 1.6.2 do not occur with these changes.

Finally, it also addresses the issue mentioned here that happened with Startscream's native engine (a light wrapper around URLSessionWebSocketTask). The solution revolves around requesting additional background execution time from the OS whenever the app moves to the background, so that the socket can continue working enough time for the wallet peer to accept or reject the session. I tested it particularly with the Metamask app and it worked great.

return URLSession(configuration: configuration, delegate: delegate, delegateQueue: nil)
}()

#if os(iOS)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm using #if os(iOS) just because I saw it in #81 but I wonder, is it really necessary? Doesn't look like other platforms are explicitly supported (beyond M1 macs running iOS apps)?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Package's platform include macOS and the UIBackgroundTaskIdentifier does not exist on macOS, so I thing we're fine here

@oscahie
Copy link
Contributor Author

oscahie commented Jul 7, 2022

Note that one thing that is not supported in this implementation is responding to incoming ping frames, unless Apple's stack does it automatically, but I've found no evidence of that so far. It does of course send outgoing pings, so perhaps that's enough? In any case, I'm not sure it'd be even possible to implement, since it doesn't look like Apple exposes those kind of messages in their API.

@DmitryBespalov
Copy link
Collaborator

@oscahie ok, so we're still testing the changes.

I found some errors when trying to integrate to our main projects and this is the branch with fixes which is based on your changes and on other library tweaks we made before:

https://github.com/gnosis/WalletConnectSwift/tree/oscar/drop-starscream

I believe these changes are good for a next minor release, I'll bump the version number.

Also, do you want to be mentioned in the Contributors section in the Readme?

@acecilia
Copy link

acecilia commented Jul 8, 2022

Great work 💪 Would it be possible to update CryptoSwift to the latest version? (maybe in another PR?)

@oscahie
Copy link
Contributor Author

oscahie commented Jul 8, 2022

@DmitryBespalov cool, please give it as much testing as you need until you feel comfortable with merging the changes.

It's also nice to see you've been making some improvements in that gnosis fork, specially for the session approval delegate method, which is the thing I was just implementing today in our wallet app, and indeed, the current API is quite cumbersome to work with when asynchronous user approval is involved. It'd just have been awesome though if you had decided to move away entirely from using the delegation pattern and instead use closure callbacks, IMHO :)

It's cool if you want to add me to the contributors, though I can't promise that I'll be contributing regularly. It just so happens that the project I'm working on at the moment needs to use this library, and so I've been tasked with the integration and making the necessary changes for it to succeed. In the hopefully-not-so-distant future we expect to move to v2 of the protocol though.

@DmitryBespalov
Copy link
Collaborator

@acecilia OK!

@oscahie yes, my view of the current version of the library is that it is hard to use and its domain model is awkward. For going forward I have a vision for making the library modular and adding other companion libraries which would handle persistence of connections, and a standard UI with the list of wallets or dapps, as well as handling of requests/responses. Ideally, this would be all-in-one package that wallet and dapp developers integrate in their app, because I think that additional use cases around wallet-connect are repeated over and over for each project.

Then, the v2 of the protocol will also be added, and the library would gracefully switch between the protocols based on the protocol version in the link.

This way, if it's easy to integrate into other projects and with v2/v1 handling in the same library, we can advance the transition to the v2 across wallets and dapps on iOS.

@DmitryBespalov
Copy link
Collaborator

@oscahie regarding PONG messages from the client to the channel

Note that one thing that is not supported in this implementation is responding to incoming ping frames, unless Apple's stack does it automatically, but I've found no evidence of that so far. It does of course send outgoing pings, so perhaps that's enough? In any case, I'm not sure it'd be even possible to implement, since it doesn't look like Apple exposes those kind of messages in their API.

As far as the specs go about the ping/pong https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.2 and based on apple's documentation https://developer.apple.com/documentation/foundation/urlsessionwebsockettask/3181206-sendping there's no way to send a pong with Apple's API.

My assumption is as yours, that the framework handles the PONG frames received automatically.

… reliability of the connection in general and have the socket reconnected quicker when needed.
@oscahie
Copy link
Contributor Author

oscahie commented Jul 11, 2022

Added a small improvement today that treats any errors while sending data or pings as connection errors, which should help to detect failing connections quicker. In fact I had a rare case today in which I disabled all connectivity in my phone and Apple's task.receive API, despite printing lots of error messages to the console, did not report it back after several minutes (normally it takes about 1 minute to do so), and so our websocket didn't know it was actually disconnected. This change should fix that too.

@DmitryBespalov
Copy link
Collaborator

@oscahie we completed testing of the fork I shared before with your changes. To the best of our knowledge, everything still works well.

To be able to merge, your branch needs to be updated with the changes in the gnosis fork. I'll create a merge request to your repository first, and after merging that, we'll be able to merge this one.

Then, in another PR, I'll also update a CryptoSwift library and double check the package manager configurations, and then release new version.

@DmitryBespalov
Copy link
Collaborator

oscahie#1

@oscahie
Copy link
Contributor Author

oscahie commented Jul 11, 2022

Cool, I merged that one. Also would be great if you could take a look at #125 I just opened, hopefully can be included in the next release too.

@DmitryBespalov DmitryBespalov merged commit 030c988 into WalletConnect:master Jul 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants