diff mbox

[FFmpeg-devel] tcp: set socket buffer sizes before listen/connect/accept

Message ID E259280E-7507-4D99-8C76-58830E31E802@me.com
State Accepted
Commit f3778108d3eb8e6e5fa77d645a79f75c703ff0bc
Headers show

Commit Message

Joel Cunningham Jan. 9, 2017, 8:54 p.m. UTC
From e24d95c0e06a878d401ee34fd6742fcaddeeb95f Mon Sep 17 00:00:00 2001
From: Joel Cunningham <joel.cunningham@me.com>
Date: Mon, 9 Jan 2017 13:37:51 -0600
Subject: [PATCH] tcp: set socket buffer sizes before listen/connect/accept

Attempting to set SO_RCVBUF and SO_SNDBUF on TCP sockets after connection
establishment is incorrect and some stacks ignore the set call on the socket at
this point.  This has been observed on MacOS/iOS.  Windows 7 has some peculiar
behavior where setting SO_RCVBUF after applies only if the buffer is increasing
from the default while decreases are ignored.  This is possibly how the incorrect
usage has gone unnoticed

Unix Network Programming Vol. 1: The Sockets Networking API (3rd edition, seciton 7.5):

"When setting the size of the TCP socket receive buffer, the ordering of the
function calls is important.  This is because of TCP's window scale option,
which is exchanged with the peer on SYN segments when the connection is
established. For a client, this means the SO_RCVBUF socket option must be
set before calling connect.  For a server, this means the socket option must
be set for the listening socket before calling listen.  Setting this option
for the connected socket will have no effect whatsoever on the possible window
scale option because accept does not return with the connected socket until
TCP's three-way handshake is complete.  This is why the option must be set on
the listening socket. (The sizes of the socket buffers are always inherited from
the listening socket by the newly created connected socket)"

Signed-off-by: Joel Cunningham <joel.cunningham@me.com>
---
 libavformat/tcp.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

Comments

Joel Cunningham Jan. 25, 2017, 3:06 p.m. UTC | #1
Ping!  Anyone have a chance to look at this issue/patch?

Thanks,

Joel

> On Jan 9, 2017, at 2:54 PM, Joel Cunningham <joel.cunningham@me.com> wrote:
> 
> From e24d95c0e06a878d401ee34fd6742fcaddeeb95f Mon Sep 17 00:00:00 2001
> From: Joel Cunningham <joel.cunningham@me.com>
> Date: Mon, 9 Jan 2017 13:37:51 -0600
> Subject: [PATCH] tcp: set socket buffer sizes before listen/connect/accept
> 
> Attempting to set SO_RCVBUF and SO_SNDBUF on TCP sockets after connection
> establishment is incorrect and some stacks ignore the set call on the socket at
> this point.  This has been observed on MacOS/iOS.  Windows 7 has some peculiar
> behavior where setting SO_RCVBUF after applies only if the buffer is increasing
> from the default while decreases are ignored.  This is possibly how the incorrect
> usage has gone unnoticed
> 
> Unix Network Programming Vol. 1: The Sockets Networking API (3rd edition, seciton 7.5):
> 
> "When setting the size of the TCP socket receive buffer, the ordering of the
> function calls is important.  This is because of TCP's window scale option,
> which is exchanged with the peer on SYN segments when the connection is
> established. For a client, this means the SO_RCVBUF socket option must be
> set before calling connect.  For a server, this means the socket option must
> be set for the listening socket before calling listen.  Setting this option
> for the connected socket will have no effect whatsoever on the possible window
> scale option because accept does not return with the connected socket until
> TCP's three-way handshake is complete.  This is why the option must be set on
> the listening socket. (The sizes of the socket buffers are always inherited from
> the listening socket by the newly created connected socket)"
> 
> Signed-off-by: Joel Cunningham <joel.cunningham@me.com>
> ---
> libavformat/tcp.c | 17 +++++++++--------
> 1 file changed, 9 insertions(+), 8 deletions(-)
> 
> diff --git a/libavformat/tcp.c b/libavformat/tcp.c
> index 25abafc..5f00ba7 100644
> --- a/libavformat/tcp.c
> +++ b/libavformat/tcp.c
> @@ -140,6 +140,15 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
>         goto fail;
>     }
> 
> +    /* Set the socket's send or receive buffer sizes, if specified.
> +       If unspecified or setting fails, system default is used. */
> +    if (s->recv_buffer_size > 0) {
> +        setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &s->recv_buffer_size, sizeof (s->recv_buffer_size));
> +    }
> +    if (s->send_buffer_size > 0) {
> +        setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &s->send_buffer_size, sizeof (s->send_buffer_size));
> +    }
> +
>     if (s->listen == 2) {
>         // multi-client
>         if ((ret = ff_listen(fd, cur_ai->ai_addr, cur_ai->ai_addrlen)) < 0)
> @@ -164,14 +173,6 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
> 
>     h->is_streamed = 1;
>     s->fd = fd;
> -    /* Set the socket's send or receive buffer sizes, if specified.
> -       If unspecified or setting fails, system default is used. */
> -    if (s->recv_buffer_size > 0) {
> -        setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &s->recv_buffer_size, sizeof (s->recv_buffer_size));
> -    }
> -    if (s->send_buffer_size > 0) {
> -        setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &s->send_buffer_size, sizeof (s->send_buffer_size));
> -    }
> 
>     freeaddrinfo(ai);
>     return 0;
> -- 
> 2.10.0
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Michael Niedermayer Jan. 26, 2017, 7:12 p.m. UTC | #2
On Wed, Jan 25, 2017 at 09:06:36AM -0600, Joel Cunningham wrote:
> Ping!  Anyone have a chance to look at this issue/patch?
> 
> Thanks,

patch applied

thx

[...]
diff mbox

Patch

diff --git a/libavformat/tcp.c b/libavformat/tcp.c
index 25abafc..5f00ba7 100644
--- a/libavformat/tcp.c
+++ b/libavformat/tcp.c
@@ -140,6 +140,15 @@  static int tcp_open(URLContext *h, const char *uri, int flags)
         goto fail;
     }
 
+    /* Set the socket's send or receive buffer sizes, if specified.
+       If unspecified or setting fails, system default is used. */
+    if (s->recv_buffer_size > 0) {
+        setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &s->recv_buffer_size, sizeof (s->recv_buffer_size));
+    }
+    if (s->send_buffer_size > 0) {
+        setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &s->send_buffer_size, sizeof (s->send_buffer_size));
+    }
+
     if (s->listen == 2) {
         // multi-client
         if ((ret = ff_listen(fd, cur_ai->ai_addr, cur_ai->ai_addrlen)) < 0)
@@ -164,14 +173,6 @@  static int tcp_open(URLContext *h, const char *uri, int flags)
 
     h->is_streamed = 1;
     s->fd = fd;
-    /* Set the socket's send or receive buffer sizes, if specified.
-       If unspecified or setting fails, system default is used. */
-    if (s->recv_buffer_size > 0) {
-        setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &s->recv_buffer_size, sizeof (s->recv_buffer_size));
-    }
-    if (s->send_buffer_size > 0) {
-        setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &s->send_buffer_size, sizeof (s->send_buffer_size));
-    }
 
     freeaddrinfo(ai);
     return 0;