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..24bdfc93cec274 --- /dev/null +++ b/docs/cmdline-opts/mptcp.md @@ -0,0 +1,32 @@ +--- +c: Copyright (C) Dorian Craps, +SPDX-License-Identifier: curl +Long: mptcp +Added: X.XX.XX (Version you added MPTCP) +Help: Enable Multipath TCP (MPTCP) +Category: connection +Multi: boolean +See-also: + - http2 +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 X.XX.XX. diff --git a/include/curl/curl.h b/include/curl/curl.h index eb06022501c6fb..30ca34e723c5a5 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 33ca7e7818052f..645c87a4637455 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; @@ -1609,7 +1613,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 87e0f30a2517aa..913dcb3ced6a4b 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/setopt.c b/lib/setopt.c index e5614cd35140d7..0b284b3e6f6d53 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -2932,6 +2932,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 c0e64451987cce..65558c44402e75 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -894,6 +894,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 @@ -1941,6 +1942,7 @@ struct UserDefined { #ifdef USE_WEBSOCKETS BIT(ws_raw_mode); #endif + bool mptcp; /* enable MPTCP support */ }; struct Names { 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 4c910fd73c912b..1a8c439b541063 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}, @@ -2739,6 +2741,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_operate.c b/src/tool_operate.c index 5a5fc8745ed14b..06cafa1f5059fe 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);