summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Cunningham <joel.cunningham@me.com>2017-01-09 14:54:47 -0600
committerMichael Niedermayer <michael@niedermayer.cc>2017-01-26 20:19:18 +0100
commitf3778108d3eb8e6e5fa77d645a79f75c703ff0bc (patch)
tree99c95b25f222b97eee6dfb5c47f7dba42c280491
parentee8e00b70396e380211801b26b68c46fe5b62f7a (diff)
tcp: set socket buffer sizes before listen/connect/accept
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> Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
-rw-r--r--libavformat/tcp.c17
1 files changed, 9 insertions, 8 deletions
diff --git a/libavformat/tcp.c b/libavformat/tcp.c
index 25abafc5eb..5f00ba7588 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;