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..a87c28b0c98d9c --- /dev/null +++ b/docs/cmdline-opts/mptcp.md @@ -0,0 +1,37 @@ +--- +c: Copyright (C) Dorian Craps, +SPDX-License-Identifier: curl +Long: mptcp +Added: 8.7.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 Wi-Fi and +cellular data or in wired networks with multiple ISPs. + +## Usage + +To use MPTCP for your connections, add the `--mptcp` option when using `curl`: + +## Requirements + +- Your operating system must support MPTCP, and it must be enabled. +- The server you are connecting to must also support MPTCP. + +## Availability + +The `--mptcp` option is available starting from `curl` version 8.6.1. diff --git a/docs/libcurl/curl_easy_setopt.md b/docs/libcurl/curl_easy_setopt.md index 843673a621862a..4e0a20dd47c3c6 100644 --- a/docs/libcurl/curl_easy_setopt.md +++ b/docs/libcurl/curl_easy_setopt.md @@ -423,6 +423,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..1eba9521774728 --- /dev/null +++ b/docs/libcurl/opts/CURLOPT_MPTCP.md @@ -0,0 +1,76 @@ +--- +c: Copyright (C) Dorian Craps, +SPDX-License-Identifier: curl +Title: CURLOPT_MPTCP +Section: 3 +Source: libcurl +See-also: + - tcp-fastopen (3) +--- + +# 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. + +Multipath TCP (MPTCP) is an extension of TCP that allows multiple paths +to be used simultaneously by a single TCP connection, enhancing redundancy, +bandwidth, and potentially reducing latency. +It works by presenting a standard TCP interface to applications while +managing multiple underlying TCP connections. + +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. Not all networks support MPTCP, and its effectiveness will +vary based on the network configuration and conditions. + +# DEFAULT + +0 + +# PROTOCOLS + +All + +# 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 feature's availability in libcurl can also depend +on the version of libcurl. Added in 8.7.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. \ No newline at end of file diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions index a627dd68b6c37d..450203052e476b 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.7.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..721025a848f719 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.7.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 1de5100062742a..cb57bef648fdf6 100644 --- a/lib/cf-socket.c +++ b/lib/cf-socket.c @@ -244,6 +244,10 @@ void Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest, dest->socktype = SOCK_STREAM; dest->protocol = IPPROTO_IP; break; + case TRNSPRT_MPTCP: + dest->socktype = SOCK_STREAM; + dest->protocol = IPPROTO_MPTCP; + break; default: /* UDP and QUIC */ dest->socktype = SOCK_DGRAM; dest->protocol = IPPROTO_UDP; @@ -1601,7 +1605,12 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf, if(!ctx) { 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/cf-socket.h b/lib/cf-socket.h index 058af5009898db..793ff82633b926 100644 --- a/lib/cf-socket.h +++ b/lib/cf-socket.h @@ -28,6 +28,10 @@ #include "nonblock.h" /* for curlx_nonblock(), formerly Curl_nonblock() */ #include "sockaddr.h" +#ifndef IPPROTO_MPTCP +#define IPPROTO_MPTCP 262 +#endif + struct Curl_addrinfo; struct Curl_cfilter; struct Curl_easy; 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..89911fb00724f0 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..8ba870630b00d0 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 + bool mptcp; /* enable MPTCP support */ }; #ifndef CURL_DISABLE_MIME diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c index 3259bc7a5f0562..48601c18512036 100644 --- a/src/tool_cfgable.c +++ b/src/tool_cfgable.c @@ -45,6 +45,7 @@ void config_init(struct OperationConfig *config) config->http09_allowed = FALSE; config->ftp_skip_ip = TRUE; config->file_clobber_mode = CLOBBER_DEFAULT; + config->mptcp = FALSE; curlx_dyn_init(&config->postdata, MAX_FILE2MEMORY); } diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h index dfa74d81ff4b81..7c7eefc99eaf5f 100644 --- a/src/tool_cfgable.h +++ b/src/tool_cfgable.h @@ -298,6 +298,7 @@ struct OperationConfig { struct State state; /* for create_transfer() */ bool rm_partial; /* on error, remove partially written output files */ + bool mptcp; }; struct GlobalConfig { diff --git a/src/tool_getparam.c b/src/tool_getparam.c index c6a9c935861f86..5f3562376477c6 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}, @@ -2742,6 +2744,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 f2feb27185c054..20d37e35486bad 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 7e2c1eefe02b92..5d750ef5449aef 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);