diff --git a/.github/scripts/spellcheck.words b/.github/scripts/spellcheck.words index 050513c76f2769..552858573f165d 100644 --- a/.github/scripts/spellcheck.words +++ b/.github/scripts/spellcheck.words @@ -485,6 +485,7 @@ monospace MorphOS MPE MPL +MPTCP mprintf MQTT mqtt @@ -505,6 +506,7 @@ mTLS MUA multicwd multiparts +multipath MultiSSL mumbo musedev diff --git a/docs/cmdline-opts/Makefile.inc b/docs/cmdline-opts/Makefile.inc index 428cc3bab2a066..c546a18c8f89d0 100644 --- a/docs/cmdline-opts/Makefile.inc +++ b/docs/cmdline-opts/Makefile.inc @@ -160,6 +160,7 @@ DPAGES = \ max-redirs.md \ max-time.md \ metalink.md \ + mptcp.md \ negotiate.md \ netrc-file.md \ netrc-optional.md \ diff --git a/docs/cmdline-opts/mptcp.md b/docs/cmdline-opts/mptcp.md new file mode 100644 index 00000000000000..19e68919eb6d0a --- /dev/null +++ b/docs/cmdline-opts/mptcp.md @@ -0,0 +1,38 @@ +--- +c: Copyright (C) Dorian Craps, +SPDX-License-Identifier: curl +Long: mptcp +Added: 8.8.0 +Help: Enable Multipath TCP (MPTCP) +Category: connection +Multi: boolean +See-also: + - tcp-fastopen +Example: + - --mptcp $URL +--- + +# `--mptcp` + +Enables the use of Multipath TCP (MPTCP) for connections. MPTCP is an extension +to the standard TCP that allows multiple TCP streams over different network +paths between the same source and destination. This can enhance bandwidth and +improve reliability by using multiple paths simultaneously. + +MPTCP is beneficial in networks where multiple paths exist between clients and +servers, such as mobile networks where a device may switch between WiFi and +cellular data or in wired networks with multiple Internet Service Providers. + +## Usage + +To use MPTCP for your connections, add the `--mptcp` option when using `curl'. + +## Requirements + +- This feature is currently only supported on Linux starting from kernel 5.6. +- The server you are connecting to must also support MPTCP. If not, the + connection seamlessly falls back to TCP. + +## Availability + +The `--mptcp` option is available starting from `curl` version 8.8.0. diff --git a/docs/libcurl/curl_easy_setopt.md b/docs/libcurl/curl_easy_setopt.md index 770fdc91bc7d69..fcd3fd13915cf0 100644 --- a/docs/libcurl/curl_easy_setopt.md +++ b/docs/libcurl/curl_easy_setopt.md @@ -425,6 +425,10 @@ Path to a Unix domain socket. See CURLOPT_UNIX_SOCKET_PATH(3) Path to an abstract Unix domain socket. See CURLOPT_ABSTRACT_UNIX_SOCKET(3) +## CURLOPT_MPTCP + +Enable Multipath TCP (MPTCP). See CURLOPT_MPTCP(3) + # NAMES and PASSWORDS OPTIONS (Authentication) ## CURLOPT_NETRC diff --git a/docs/libcurl/opts/CURLOPT_MPTCP.md b/docs/libcurl/opts/CURLOPT_MPTCP.md new file mode 100644 index 00000000000000..bae4818af80a34 --- /dev/null +++ b/docs/libcurl/opts/CURLOPT_MPTCP.md @@ -0,0 +1,76 @@ +--- +c: Copyright (C) Dorian Craps, , et al. +SPDX-License-Identifier: curl +Title: CURLOPT_MPTCP +Section: 3 +Source: libcurl +See-also: + - CURLOPT_TCP_FASTOPEN (3) +Protocol: + - All +--- + +# NAME + +CURLOPT_MPTCP - enable Multipath TCP + +# SYNOPSIS + +~~~c +#include + +CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MPTCP, long enable); +~~~ + +# DESCRIPTION + +Pass a long as parameter set to 1L to enable or 0 to disable. + +MPTCP is an extension to the standard TCP that allows multiple TCP streams +over different network paths between the same source and destination. +This can enhance bandwidth and improve reliability by using multiple paths +simultaneously. +MPTCP is beneficial in networks where multiple paths exist between clients +and servers, such as mobile networks where a device may switch between WiFi +and cellular data or in wired networks with multiple Internet Service Providers. + +Enabling MPTCP can improve the performance and reliability of network requests, +particularly in environments where multiple network paths (e.g., WiFi and +cellular) are available. + +Note: MPTCP support depends on the underlying operating system and network +infrastructure. Some networks might drop unknown MPTCP, and its +effectiveness varies based on the network configuration and conditions. +If MPTCP is not supported by the network or the end server, +the connection seamlessly falls back to TCP. + +# DEFAULT + +0 + +# EXAMPLE + +~~~c +int main(void) +{ + CURL *curl = curl_easy_init(); + if(curl) { + curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); + curl_easy_setopt(curl, CURLOPT_MPTCP, 1L); + curl_easy_perform(curl); + } +} +~~~ + +# AVAILABILITY + +Support for MPTCP in libcurl requires Linux 5.6 or later. +The features availability in libcurl can also depend on the version of libcurl. +Added in 8.8.0. + +# RETURN VALUE + +Returns CURLE_OK if MPTCP is successfully enabled for the connection, +otherwise returns an error code specific to the reason it could not be enabled, +which might include lack of operating system support or libcurl not being built +with MPTCP support. diff --git a/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.md b/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.md index 42b44a5674dd69..41d9835b78d2c0 100644 --- a/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.md +++ b/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.md @@ -6,6 +6,7 @@ Section: 3 Source: libcurl See-also: - CURLOPT_SSL_FALSESTART (3) + - CURLOPT_MPTCP (3) Protocol: - All --- diff --git a/docs/libcurl/opts/Makefile.inc b/docs/libcurl/opts/Makefile.inc index 7a292b81d5189d..f1322a45c1d8a7 100644 --- a/docs/libcurl/opts/Makefile.inc +++ b/docs/libcurl/opts/Makefile.inc @@ -244,6 +244,7 @@ man_MANS = \ CURLOPT_MAXREDIRS.3 \ CURLOPT_MIME_OPTIONS.3 \ CURLOPT_MIMEPOST.3 \ + CURLOPT_MPTCP.3 \ CURLOPT_NETRC.3 \ CURLOPT_NETRC_FILE.3 \ CURLOPT_NEW_DIRECTORY_PERMS.3 \ diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions index a627dd68b6c37d..3cc394be76860b 100644 --- a/docs/libcurl/symbols-in-versions +++ b/docs/libcurl/symbols-in-versions @@ -708,6 +708,7 @@ CURLOPT_MAXREDIRS 7.5 CURLOPT_MIME_OPTIONS 7.81.0 CURLOPT_MIMEPOST 7.56.0 CURLOPT_MUTE 7.1 7.8 7.15.5 +CURLOPT_MPTCP 8.8.0 CURLOPT_NETRC 7.1 CURLOPT_NETRC_FILE 7.11.0 CURLOPT_NEW_DIRECTORY_PERMS 7.16.4 diff --git a/docs/options-in-versions b/docs/options-in-versions index 0905809439c35b..0e30c563da059f 100644 --- a/docs/options-in-versions +++ b/docs/options-in-versions @@ -125,6 +125,7 @@ --max-redirs 7.5 --max-time (-m) 4.0 --metalink 7.27.0 +--mptcp 8.8.0 --negotiate 7.10.6 --netrc (-n) 4.6 --netrc-file 7.21.5 diff --git a/include/curl/curl.h b/include/curl/curl.h index b2377b7895b988..7ab968c6572768 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -2206,6 +2206,9 @@ typedef enum { /* millisecond version */ CURLOPT(CURLOPT_SERVER_RESPONSE_TIMEOUT_MS, CURLOPTTYPE_LONG, 324), + /* Set MPTCP */ + CURLOPT(CURLOPT_MPTCP, CURLOPTTYPE_LONG, 325), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff --git a/lib/cf-socket.c b/lib/cf-socket.c index a5feb6b95ab2b6..a852a523193115 100644 --- a/lib/cf-socket.c +++ b/lib/cf-socket.c @@ -244,6 +244,13 @@ void Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest, dest->socktype = SOCK_STREAM; dest->protocol = IPPROTO_IP; break; + case TRNSPRT_MPTCP: +#ifndef IPPROTO_MPTCP +#define IPPROTO_MPTCP 262 +#endif + dest->socktype = SOCK_STREAM; + dest->protocol = IPPROTO_MPTCP; + break; default: /* UDP and QUIC */ dest->socktype = SOCK_DGRAM; dest->protocol = IPPROTO_UDP; @@ -1602,6 +1609,12 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf, result = CURLE_OUT_OF_MEMORY; goto out; } + +#ifdef __linux__ + if(data->set.mptcp) + transport = TRNSPRT_MPTCP; +#endif + cf_socket_ctx_init(ctx, ai, transport); result = Curl_cf_create(&cf, &Curl_cft_tcp, ctx); diff --git a/lib/easyoptions.c b/lib/easyoptions.c index 9c4438a100e2bc..ea284970d33b38 100644 --- a/lib/easyoptions.c +++ b/lib/easyoptions.c @@ -178,6 +178,7 @@ struct curl_easyoption Curl_easyopts[] = { {"MAX_SEND_SPEED_LARGE", CURLOPT_MAX_SEND_SPEED_LARGE, CURLOT_OFF_T, 0}, {"MIMEPOST", CURLOPT_MIMEPOST, CURLOT_OBJECT, 0}, {"MIME_OPTIONS", CURLOPT_MIME_OPTIONS, CURLOT_LONG, 0}, + {"MPTCP", CURLOPT_MPTCP, CURLOT_LONG, 0}, {"NETRC", CURLOPT_NETRC, CURLOT_VALUES, 0}, {"NETRC_FILE", CURLOPT_NETRC_FILE, CURLOT_STRING, 0}, {"NEW_DIRECTORY_PERMS", CURLOPT_NEW_DIRECTORY_PERMS, CURLOT_LONG, 0}, @@ -375,6 +376,6 @@ struct curl_easyoption Curl_easyopts[] = { */ int Curl_easyopts_check(void) { - return ((CURLOPT_LASTENTRY%10000) != (324 + 1)); + return ((CURLOPT_LASTENTRY%10000) != (325 + 1)); } #endif diff --git a/lib/setopt.c b/lib/setopt.c index 8a5a5d7c33d21d..2226ea553d79c0 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -2931,6 +2931,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) result = CURLE_NOT_BUILT_IN; #endif break; + case CURLOPT_MPTCP: + data->set.mptcp = TRUE; + break; case CURLOPT_SSL_ENABLE_NPN: break; case CURLOPT_SSL_ENABLE_ALPN: diff --git a/lib/urldata.h b/lib/urldata.h index ce28f25bba59e9..185e2442307430 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -788,6 +788,7 @@ struct ldapconninfo; #define TRNSPRT_UDP 4 #define TRNSPRT_QUIC 5 #define TRNSPRT_UNIX 6 +#define TRNSPRT_MPTCP 7 /* * The connectdata struct contains all fields and variables that should be @@ -1811,6 +1812,7 @@ struct UserDefined { #ifdef USE_WEBSOCKETS BIT(ws_raw_mode); #endif + BIT(mptcp); /* enable MPTCP support */ }; #ifndef CURL_DISABLE_MIME diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h index dfa74d81ff4b81..534467a27404c7 100644 --- a/src/tool_cfgable.h +++ b/src/tool_cfgable.h @@ -292,6 +292,7 @@ struct OperationConfig { CLOBBER_NEVER, /* If the file exists, always fail */ CLOBBER_ALWAYS /* If the file exists, always overwrite it */ } file_clobber_mode; + bool mptcp; /* enable MPTCP support */ struct GlobalConfig *global; struct OperationConfig *prev; struct OperationConfig *next; /* Always last in the struct */ diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 5cb898852b5e46..d1b4e2b8688081 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -199,6 +199,7 @@ typedef enum { C_MAX_REDIRS, C_MAX_TIME, C_METALINK, + C_MPTCP, C_NEGOTIATE, C_NETRC, C_NETRC_FILE, @@ -480,6 +481,7 @@ static const struct LongShort aliases[]= { {"max-redirs", ARG_STRG, ' ', C_MAX_REDIRS}, {"max-time", ARG_STRG, 'm', C_MAX_TIME}, {"metalink", ARG_BOOL, ' ', C_METALINK}, + {"mptcp", ARG_BOOL, ' ', C_MPTCP}, {"negotiate", ARG_BOOL, ' ', C_NEGOTIATE}, {"netrc", ARG_BOOL, 'n', C_NETRC}, {"netrc-file", ARG_FILE, ' ', C_NETRC_FILE}, @@ -2747,6 +2749,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ } } break; + case C_MPTCP: /* --mptcp */ + config->mptcp = TRUE; + break; default: /* unknown flag */ err = PARAM_OPTION_UNKNOWN; break; diff --git a/src/tool_listhelp.c b/src/tool_listhelp.c index 5d9364405448bf..1a2d98ccfecbb1 100644 --- a/src/tool_listhelp.c +++ b/src/tool_listhelp.c @@ -378,6 +378,9 @@ const struct helptxt helptext[] = { {" --metalink", "Process given URLs as metalink XML file", CURLHELP_MISC}, + {" --mptcp", + "Enable Multipath TCP (MPTCP)", + CURLHELP_CONNECTION}, {" --negotiate", "Use HTTP Negotiate (SPNEGO) authentication", CURLHELP_AUTH | CURLHELP_HTTP}, diff --git a/src/tool_operate.c b/src/tool_operate.c index 49ec7d835cfedb..849c8985860ff3 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -1291,6 +1291,9 @@ static CURLcode single_transfer(struct GlobalConfig *global, if(config->tcp_fastopen) my_setopt(curl, CURLOPT_TCP_FASTOPEN, 1L); + if(config->mptcp) + my_setopt(curl, CURLOPT_MPTCP, 1L); + /* where to store */ my_setopt(curl, CURLOPT_WRITEDATA, per); my_setopt(curl, CURLOPT_INTERLEAVEDATA, per);