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

Add an option to enable Multipath TCP on clients #766

Merged
merged 5 commits into from
Sep 20, 2024

Conversation

Aperence
Copy link
Contributor

Multipath TCP (MPTCP) is a TCP extension allowing to enhance the reliability of the network by using multiple interfaces. This extension provides a seamless handover between interfaces in case of deterioration of the connection on the original one. In the context of iOS and Mac OS X, it could be really interesting to leverage the capabilities of MPTCP as they could benefit from their multiple interfaces (ethernet + Wi-fi for Mac OS X, Wi-fi + cellular for iOS).

This contribution introduces patches to HTTPClient.Configuration and establishment of the Bootstraps. A supplementary field "enableMultipath" was added to the configuration, allowing to request the use of MPTCP. This flag is then used when creating the channels to configure the client.

Note that in the future, it might also be potentially interesting to offer more precise configuration options for MPTCP on MacOS, as the Network framework allows also to select a type of service, instead of just offering the option to create MPTCP connections. Currently, when enabling MPTCP, only the Handover mode is used.

@Lukasa
Copy link
Collaborator

Lukasa commented Sep 9, 2024

Hi @Aperence, sorry for the delay in getting a review here. I'll take a look now.

Copy link
Collaborator

@Lukasa Lukasa left a comment

Choose a reason for hiding this comment

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

Thanks for this! Generally it looks like a great addition. I've noted that we need to tweak the API surface a bit.

Can I also ask that you add at least one unit test that uses the feature? That'll ensure that we don't break it.

}

public init(tlsConfiguration: TLSConfiguration? = nil,
redirectConfiguration: RedirectConfiguration? = nil,
timeout: Timeout = Timeout(),
proxy: Proxy? = nil,
ignoreUncleanSSLShutdown: Bool = false,
decompression: Decompression = .disabled) {
decompression: Decompression = .disabled,
enableMultipath: Bool = false) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Unfortunately, we can't add new parameters to public methods. This will need a new method that has the extra parameter.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Does it require a new method, or do you prefer simply having the field enableMPTCP as public in the configuration, allowing to set it freely ?

public init(
tlsConfiguration: TLSConfiguration? = nil,
redirectConfiguration: RedirectConfiguration? = nil,
timeout: Timeout = Timeout(),
connectionPool: ConnectionPool = ConnectionPool(),
proxy: Proxy? = nil,
ignoreUncleanSSLShutdown: Bool = false,
decompression: Decompression = .disabled
decompression: Decompression = .disabled,
enableMultipath: Bool = false
Copy link
Collaborator

Choose a reason for hiding this comment

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

Unfortunately, we can't add new parameters here. We need a new method, with the new parameter.

@@ -780,7 +788,8 @@ public class HTTPClient {
maximumAllowedIdleTimeInConnectionPool: TimeAmount = .seconds(60),
proxy: Proxy? = nil,
ignoreUncleanSSLShutdown: Bool = false,
decompression: Decompression = .disabled) {
decompression: Decompression = .disabled,
enableMultipath: Bool = false) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same note here.

@@ -799,7 +809,8 @@ public class HTTPClient {
proxy: Proxy? = nil,
ignoreUncleanSSLShutdown: Bool = false,
decompression: Decompression = .disabled,
backgroundActivityLogger: Logger?) {
backgroundActivityLogger: Logger?,
enableMultipath: Bool = false) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same note here.

}

public init(certificateVerification: CertificateVerification,
redirectConfiguration: RedirectConfiguration? = nil,
timeout: Timeout = Timeout(),
proxy: Proxy? = nil,
ignoreUncleanSSLShutdown: Bool = false,
decompression: Decompression = .disabled) {
decompression: Decompression = .disabled,
enableMultipath: Bool = false) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same note here.

@Aperence
Copy link
Contributor Author

Aperence commented Sep 9, 2024

Hello @Lukasa,

First, thanks for the review !

I've removed the changes to the methods' signatures. It is still possible to set the enableMultipath field as it is public, but if you prefer, I can also introduce a method for it.

I've added also another test that enables MPTCP, and check that we can still fetch https://httpbin.org/get, as requested.

I remain available if other changes are needed.
Have a nice day !

@Aperence Aperence requested a review from Lukasa September 9, 2024 13:41
@Lukasa Lukasa added the semver/minor For PRs that when merged cause a bump of the minor version, ie. 1.x.0 -> 1.(x+1).0 label Sep 16, 2024
@Lukasa
Copy link
Collaborator

Lukasa commented Sep 16, 2024

@swift-server-bot test this please

@Lukasa
Copy link
Collaborator

Lukasa commented Sep 16, 2024

Ok, looks like the linux tests fail with EINVAL. This happens with kernels that don't support MPTCP, so you'll need to add a try-catch that checks for this case and skips the test in that context.

@Aperence
Copy link
Contributor Author

Just added the do-catch now !

Multipath TCP (MPTCP) is a TCP extension allowing to enhance
the reliability of the network by using multiple interfaces.
This extension provides a seamless handover between interfaces
in case of deterioration of the connection on the original one.
In the context of iOS and Mac OS X, it could be really interesting
to leverage the capabilities of MPTCP as they could benefit from
their multiple interfaces (ethernet + Wi-fi for Mac OS X, Wi-fi +
cellular for iOS).

This contribution introduces patches to HTTPClient.Configuration and
establishment of the Bootstraps. A supplementary field "enableMultipath"
was added to the configuration, allowing to request the use of MPTCP.
This flag is then used when creating the channels to configure the client.

Note that in the future, it might also be potentially interesting to offer
more precise configuration options for MPTCP on MacOS, as the Network
framework allows also to select a type of service, instead of just offering
the option to create MPTCP connections. Currently, when enabling MPTCP, only
the Handover mode is used.
@Aperence
Copy link
Contributor Author

Applied required changes

@Lukasa
Copy link
Collaborator

Lukasa commented Sep 18, 2024

@swift-server-bot test this please

}
let response = try client.get(url: self.defaultHTTPBinURLPrefix + "get").wait()
XCTAssertEqual(.ok, response.status)
} catch let error as IOError where error.errnoCode == EINVAL {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just tried running this locally, it turns out EPROTONOSUPPORT is also sometimes thrown on Linux, so we need to add that to the list.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added this, I've checked the documentation and it seems that it could also raise an ENOPROTOOPT error, so I've added this one too to the list

@Lukasa
Copy link
Collaborator

Lukasa commented Sep 20, 2024

@swift-server-bot test this please

@Lukasa Lukasa enabled auto-merge (squash) September 20, 2024 11:15
Copy link
Collaborator

@Lukasa Lukasa left a comment

Choose a reason for hiding this comment

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

Nice one, thanks!

@Lukasa Lukasa merged commit 15dbe6d into swift-server:main Sep 20, 2024
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
semver/minor For PRs that when merged cause a bump of the minor version, ie. 1.x.0 -> 1.(x+1).0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants