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

[Dispatching] Native socket support #911

Open
wants to merge 31 commits into
base: develop
Choose a base branch
from
Open

Conversation

alexander-lsvk
Copy link
Contributor

@alexander-lsvk alexander-lsvk commented Jun 15, 2023

Due Dilligence

Description and motivation can be found here: https://www.notion.so/walletconnect/Native-Socket-Client-bdf981fa68f24a5e8ea4f285040a8e2c

  • Breaking change
  • Requires a documentation update

@alexander-lsvk alexander-lsvk temporarily deployed to internal June 15, 2023 11:07 — with GitHub Actions Inactive
@alexander-lsvk alexander-lsvk temporarily deployed to internal June 15, 2023 11:23 — with GitHub Actions Inactive
@alexander-lsvk alexander-lsvk temporarily deployed to internal June 15, 2023 11:42 — with GitHub Actions Inactive
@alexander-lsvk alexander-lsvk temporarily deployed to internal June 15, 2023 11:55 — with GitHub Actions Inactive
@alexander-lsvk alexander-lsvk temporarily deployed to internal June 15, 2023 12:03 — with GitHub Actions Inactive
@alexander-lsvk alexander-lsvk temporarily deployed to internal June 15, 2023 18:24 — with GitHub Actions Inactive
@alexander-lsvk alexander-lsvk temporarily deployed to internal June 16, 2023 08:48 — with GitHub Actions Inactive
Copy link
Contributor

@radeknovis radeknovis left a comment

Choose a reason for hiding this comment

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

Code-wise looks good. I'm going to spend some time testing it.

let urlRequest = URLRequest(url: url)
socket = urlSession.webSocketTask(with: urlRequest)

isConnected = false
Copy link
Contributor

Choose a reason for hiding this comment

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

Why we're you're setting isConnected = false on reconnect?

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah, strange

Copy link
Contributor Author

@alexander-lsvk alexander-lsvk Jul 2, 2023

Choose a reason for hiding this comment

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

Because we are not actually connected yet but disconnected already. It will happen here

Copy link
Contributor

Choose a reason for hiding this comment

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

I am a bit concerned about handling the state of this flag properly, doesn't websocketTask or anything expose the state from urlsession itself?

}

if self.isConnected == true {
self.receiveMessage()
Copy link
Contributor

Choose a reason for hiding this comment

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

is it safe to call method from it self here? How it's working?

Copy link
Contributor

Choose a reason for hiding this comment

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

I also got confused, but apparently, this is by design from Apple. It needs to be called to receive further messages.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Radek is correct 😅 Agree this looks strange

}
}

final class WebSocketClient: NSObject, WebSocketConnecting {
Copy link
Contributor

Choose a reason for hiding this comment

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

do we still need to conform to WebSocketConnecting protocol?
I was a starscream requirement
wouldn't it be better to refactor Dispatcher and socket would conform to this protocol?

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 believe this protocol is more abstract in terms of testing. In case of conforming to URLSessionWebSocketTask we will need to depend on URLSessionWebSocketTask internal types like Message and CloseCode. But your suggestion is also valid, let's discuss on sync.

var onText: ((String) -> Void)?
var request: URLRequest {
didSet {
if let url = request.url {
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the goal of this didSet closure? I can see request is assigned only once in the init.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's used for the updating socket url (new auth parameter) when automatic reconnect happens. It will be set here.

# Conflicts:
#	Example/ExampleApp.xcodeproj/project.pbxproj
#	Example/IntegrationTests/Auth/AuthTests.swift
#	Example/IntegrationTests/Chat/ChatTests.swift
#	Example/IntegrationTests/Sign/SignClientTests.swift
#	Example/IntegrationTests/Sync/SyncTests.swift
#	Sources/WalletConnectModal/Modal/Modal+Previews.swift
#	Sources/WalletConnectModal/Modal/ModalContainerView.swift
#	Sources/WalletConnectModal/Modal/ModalInteractor.swift
#	Sources/WalletConnectRelay/RelayClient.swift
@alexander-lsvk alexander-lsvk temporarily deployed to internal July 2, 2023 14:32 — with GitHub Actions Inactive
@alexander-lsvk alexander-lsvk temporarily deployed to internal July 2, 2023 15:17 — with GitHub Actions Inactive
@alexander-lsvk alexander-lsvk temporarily deployed to internal July 5, 2023 07:32 — with GitHub Actions Inactive
@asi90sp asi90sp mentioned this pull request Aug 13, 2023
Copy link
Member

@arein arein left a comment

Choose a reason for hiding this comment

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

@alexander-lsvk the PR doesn't have a concise description with motivation, expected result, and how it was tested. Can you pelase add?

@alexander-lsvk alexander-lsvk temporarily deployed to internal September 7, 2023 06:01 — with GitHub Actions Inactive
# Conflicts:
#	Example/ExampleApp.xcodeproj/project.pbxproj
#	Example/IntegrationTests/History/HistoryTests.swift
#	Example/IntegrationTests/Push/PushTests.swift
#	Example/IntegrationTests/Sync/SyncTests.swift
#	Example/RelayIntegrationTests/RelayClientEndToEndTests.swift
#	Example/WalletApp/ApplicationLayer/ConfigurationService.swift
#	Example/WalletApp/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift
#	Sources/WalletConnectRelay/Dispatching.swift
#	Sources/WalletConnectRelay/RelayURLFactory.swift
@alexander-lsvk alexander-lsvk temporarily deployed to internal September 7, 2023 06:08 — with GitHub Actions Inactive
@alexander-lsvk alexander-lsvk temporarily deployed to internal September 12, 2023 11:34 — with GitHub Actions Inactive
@alexander-lsvk alexander-lsvk temporarily deployed to internal September 12, 2023 11:44 — with GitHub Actions Inactive
@alexander-lsvk alexander-lsvk temporarily deployed to internal September 12, 2023 12:46 — with GitHub Actions Inactive
@alexander-lsvk alexander-lsvk temporarily deployed to internal September 12, 2023 12:51 — with GitHub Actions Inactive
@alexander-lsvk alexander-lsvk temporarily deployed to internal September 12, 2023 12:56 — with GitHub Actions Inactive
@alexander-lsvk alexander-lsvk temporarily deployed to internal September 14, 2023 07:15 — with GitHub Actions Inactive
@alexander-lsvk alexander-lsvk temporarily deployed to internal September 14, 2023 07:23 — with GitHub Actions Inactive
@alexander-lsvk alexander-lsvk temporarily deployed to internal October 23, 2023 10:36 — with GitHub Actions Inactive
# Conflicts:
#	Example/ExampleApp.xcodeproj/project.pbxproj
#	Example/WalletApp/ApplicationLayer/ConfigurationService.swift
@simonmcl
Copy link

simonmcl commented Nov 6, 2023

Hi,

@llbartekll asked me to give some feedback here in response to #1205 . I was trying to use my own wrapper around URLSession as the websocket for this library and recently gave up due to some recurring issues I couldn't find the time to debug fully. My 2 cents on the issues and some of the comments in the notion document:

  • Relying on Third party libs:
    I've always been a "don't use a lib unless necessary" type person, but the current project i'm working on really hammered that home. I spent months dealing with dozens of issues making my project impossible. E.g. I needed changes to the Swift version of the sodium crypto library, the creator used a cocoapods template project to set it up, which for opinionated reasons adds "Quick" and "Nimble" libraries for unit tests. The versions used were incompatible with the latest Xcode, causing all PRs to fail with no meaningful error displayed in github actions. The maintainers weren't really around and would only look at each PR to see if the build status failed. If it did they said they would not merge it and then disappear again. The painful part is that Quick and Nimble weren't actually used apart from a single unit test that cocoapods adds as an example, so all of this pain was completely unnecessary. After dozens of similar issues, i'm very cautious of using third party libraries. I've only been using starscream for 2 weeks now and already have 1 crash report from 1 of our internal testers from limited usage. The protocol supplied in WC2 matches an older version of starscream, I wasn't sure how some of the logic translated to the new one, so i've left it on 3.1.2 for now, and it feels very much like i'm back into the types of issues I had with sodium, caught between multiple versions

  • Using URLSession:
    I found it quite easy to get it working in a basic setup, but it times out after 5 minutes of inactivity. I had a lot of trouble getting the reconnection flows to work in WC2 with this issue. Being unfamiliar with the business logic of the project adds some challenges to trying to figure this out. It would work well on simulator + device testing, but some combination of backgrounding / foregrounding / phone going into sleep etc, caused "something" to break a loop somewhere and the socket would just die until the app was killed. Wasn't easy to reproduce and haven't had the time to try investigate it in order to swap starscream back out

In my opinion the need for frequent reconnections is a design issue. I've previously done some work in non mobile spaces (limited web frontend, cloud, IoT, etc) that involved using sockets. Lots of devs love third party sockets like socket.io and starscream, as these custom implementations often don't adhere to the standard timeout rules in the websocket spec, and instead try to keep sockets open artificially longer or indefinitely in situations where it should have timed out. While from an initial developer experience point of view this is handy and easy to setup, it has very poor interoperability with other platforms + implementations. Every project i've worked on with a websocket has always implemented a custom keepalive on the application level. E.g. sending a "ping" every 60 seconds to keep the socket open. To me this is the first thing thats needed in WC2. Reconnections should be logic used for when the app is going to suspend / resume, not just a mechanism to keep the connection alive (outside of network issues obviously). Users will run into all sorts of issue with trying to send a payload to a device thats in the middle of a reconnection

While initially trying to debug this, I was trying to build a reconnect button + popups in my app to allow internal testers to try determine if the socket was down due to an issue connecting to WC server, or due to my handling of reconnections. I found the limitations around automatic versus manual network setup in WC2 to be very strange. I was confused why in automatic mode I was forbidden from calling a function to reset the socket and force it to connect again. I want the SDK to try manage all this for me, but don't see why, when an edge case arises, I can't tell it to manually disconnect + reconnect. I ended up switching to manual mode and handling the sleep / wake up process myself, so that I could add this button for testing. Managing it manually fixed some issues, as being unfamiliar with the logic of the SDK, it was easier and quicker to just clear everything and setup again. But it didn't fix everything (likely needing some kind of queue to manage multiple attempts to connect / reconnect coming in quickly)

I think custom keepalives and the ability to have a semi automatic network setup would go a long way to improving the usage of the library, and i'd be very keen to get rid of starscream and help test a custom implementation. Although my current app is not in production yet, we can run some experiments with beta testers after we get them on boarding in a couple of weeks

Copy link

sonarcloud bot commented Feb 26, 2024

Quality Gate Passed Quality Gate passed

Issues
54 New issues

Measures
0 Security Hotspots
No data about Coverage
0.0% Duplication on New Code

See analysis details on SonarCloud

@alexanderkhitev
Copy link

hello the Wallet Connect team ! Any news/updates? Thanks.

@llbartekll
Copy link
Contributor

hey @alexanderkhitev it's on hold right now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants