From 666b9684f8b133a77402d6a986ea1119ac17fb95 Mon Sep 17 00:00:00 2001 From: Aperence Date: Tue, 13 Aug 2024 14:20:22 +0200 Subject: [PATCH] Add Multipath TCP (MPTCP) support Multipath TCP or MPTCP is an extension to the standard TCP and is described in RFC 8684. It allows a device to make use of multiple interfaces at once to send and receive TCP packets over a single MPTCP connection. MPTCP can aggregate the bandwidth of multiple interfaces or prefer the one with the lowest latency. It also allows a fail-over if one path is down, and the traffic is seamlessly reinjected on other paths. For more details about MPTCP, refer to the official website https://mptcp.dev Typical uses cases for this library would be to leverage the fail-over capacity of MPTCP to enhance the user experience on mobile devices (android/iOS). Changes to this repository consist of replacing the protocol field value, previously IPPROTO_TCP, by IPPROTO_MPTCP (if this symbol is available) when creating sockets. --- src/belle_sip_resolver.c | 4 ++++ src/transports/stream_channel.c | 8 ++++++++ src/transports/stream_listeningpoint.c | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/src/belle_sip_resolver.c b/src/belle_sip_resolver.c index 06921947..2a847e51 100644 --- a/src/belle_sip_resolver.c +++ b/src/belle_sip_resolver.c @@ -831,7 +831,11 @@ static void *_resolver_getaddrinfo_thread(void *ptr) { snprintf(serv, sizeof(serv), "%i", ctx->port); hints.ai_family = ctx->family; hints.ai_flags = AI_NUMERICSERV; + #ifdef IPPROTO_MPTCP + hints.ai_protocol = strstr(ctx->name, "udp") ? IPPROTO_UDP : IPPROTO_MPTCP; + #else hints.ai_protocol = strstr(ctx->name, "udp") ? IPPROTO_UDP : IPPROTO_TCP; + #endif err = getaddrinfo(ctx->name, serv, &hints, &res); if (err != 0) { belle_sip_error("getaddrinfo DNS resolution of %s failed: %s", ctx->name, gai_strerror(err)); diff --git a/src/transports/stream_channel.c b/src/transports/stream_channel.c index c2304318..238671d2 100644 --- a/src/transports/stream_channel.c +++ b/src/transports/stream_channel.c @@ -127,7 +127,15 @@ int stream_channel_connect(belle_sip_stream_channel_t *obj, const struct addrinf tmp = 1; obj->base.ai_family = ai->ai_family; + #ifdef IPPROTO_MPTCP + sock = bctbx_socket(ai->ai_family, SOCK_STREAM, IPPROTO_MPTCP); + if (sock == (belle_sip_socket_t)-1) { + // fallback to TCP if MPTCP encounter an error + sock = bctbx_socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP); + } + #else sock = bctbx_socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP); + #endif if (sock == (belle_sip_socket_t)-1) { belle_sip_error("Could not create socket: %s", belle_sip_get_socket_error_string()); diff --git a/src/transports/stream_listeningpoint.c b/src/transports/stream_listeningpoint.c index 1559dcc8..fca2faea 100644 --- a/src/transports/stream_listeningpoint.c +++ b/src/transports/stream_listeningpoint.c @@ -66,7 +66,11 @@ BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_stream_listening_point_t){ snprintf(portnum, sizeof(portnum), "%i", *port); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; + #ifdef IPPROTO_MPTCP + hints.ai_protocol = IPPROTO_MPTCP; + #else hints.ai_protocol = IPPROTO_TCP; + #endif hints.ai_flags = AI_NUMERICSERV; err = getaddrinfo(addr, portnum, &hints, &res); if (err != 0) {