From: Sebastian Lackner sebastian@fds-team.de
man 7 socket ... SO_SNDBUF/SO_RCVBUF Sets or gets the maximum socket send buffer in bytes. The kernel doubles this value (to allow space for bookkeeping overhead) ...
Signed-off-by: Alistair Leslie-Hughes leslie_alistair@hotmail.com --- dlls/ws2_32/socket.c | 8 ++++++++ dlls/ws2_32/tests/sock.c | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 914df17..3954964 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -3813,6 +3813,14 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level, SetLastError(wsaErrno()); ret = SOCKET_ERROR; } + #ifdef __linux__ + else if (optname == SO_RCVBUF || optname == SO_SNDBUF) + { + /* For SO_RCVBUF / SO_SNDBUF, the Linux kernel always sets twice the value. + * Divide by two to ensure applications do not get confused by the result. */ + *(int *)optval /= 2; + } + #endif release_sock_fd( s, fd ); return ret; case WS_SO_ACCEPTCONN: diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 6dd1491..76506ca 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -1458,7 +1458,7 @@ static void test_set_getsockopt(void) value = 0xdeadbeef; err = getsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&value, &size); ok( !err, "getsockopt(SO_SNDBUF) failed error: %u\n", WSAGetLastError() ); - todo_wine ok( value == 4096, "expected 4096, got %u\n", value ); + ok( value == 4096, "expected 4096, got %u\n", value );
/* SO_RCVBUF */ value = 4096; @@ -1468,7 +1468,7 @@ static void test_set_getsockopt(void) value = 0xdeadbeef; err = getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&value, &size); ok( !err, "getsockopt(SO_RCVBUF) failed error: %u\n", WSAGetLastError() ); - todo_wine ok( value == 4096, "expected 4096, got %u\n", value ); + ok( value == 4096, "expected 4096, got %u\n", value );
/* SO_LINGER */ for( i = 0; i < sizeof(linger_testvals)/sizeof(LINGER);i++) {