Signed-off-by: Zebediah Figura z.figura12@gmail.com --- v2: cast timeout to 64 bits before multiplying
dlls/ws2_32/socket.c | 10 +++++----- dlls/ws2_32/tests/sock.c | 8 ++++---- include/wine/afd.h | 2 ++ server/sock.c | 40 +++++++++++++++++++++++++++++++++------- 4 files changed, 44 insertions(+), 16 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 7ed48124a5a..15c9d0cc940 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2289,6 +2289,8 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level, return server_getsockopt( s, IOCTL_AFD_WINE_GET_SO_RCVBUF, optval, optlen );
case WS_SO_RCVTIMEO: + return server_getsockopt( s, IOCTL_AFD_WINE_GET_SO_RCVTIMEO, optval, optlen ); + case WS_SO_SNDTIMEO: { INT64 timeout; @@ -3565,6 +3567,9 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname, case WS_SO_RCVBUF: return server_setsockopt( s, IOCTL_AFD_WINE_SET_SO_RCVBUF, optval, optlen );
+ case WS_SO_RCVTIMEO: + return server_setsockopt( s, IOCTL_AFD_WINE_SET_SO_RCVTIMEO, optval, optlen ); + /* Some options need some conversion before they can be sent to * setsockopt. The conversions are done here, then they will fall through * to the general case. Special options that are not passed to @@ -3631,13 +3636,8 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname, TRACE("setting global SO_OPENTYPE = 0x%x\n", *((const int*)optval) ); return 0;
-#ifdef SO_RCVTIMEO - case WS_SO_RCVTIMEO: -#endif #ifdef SO_SNDTIMEO case WS_SO_SNDTIMEO: -#endif -#if defined(SO_RCVTIMEO) || defined(SO_SNDTIMEO) if (optval && optlen == sizeof(UINT32)) { /* WinSock passes milliseconds instead of struct timeval */ tval.tv_usec = (*(const UINT32*)optval % 1000) * 1000; diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index ccaa04e4ef5..a3f7e002ce7 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -10919,7 +10919,7 @@ static void test_timeout(void) WSASetLastError(0xdeadbeef); ret = getsockopt(client, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, &len); ok(!ret, "expected success\n"); - todo_wine ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError()); + ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError()); ok(len == sizeof(timeout), "got size %u\n", len); ok(!timeout, "got timeout %u\n", timeout);
@@ -10927,15 +10927,15 @@ static void test_timeout(void) WSASetLastError(0xdeadbeef); ret = setsockopt(client, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); ok(!ret, "expected success\n"); - todo_wine ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError()); + ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError());
timeout = 0xdeadbeef; len = sizeof(timeout); WSASetLastError(0xdeadbeef); ret = getsockopt(client, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, &len); ok(!ret, "expected success\n"); - todo_wine ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError()); - todo_wine ok(timeout == 100, "got timeout %u\n", timeout); + ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError()); + ok(timeout == 100, "got timeout %u\n", timeout);
WSASetLastError(0xdeadbeef); ret = recv(client, &buffer, 1, 0); diff --git a/include/wine/afd.h b/include/wine/afd.h index 0692394459e..c4f7c7a6413 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -171,6 +171,8 @@ struct afd_get_events_params #define IOCTL_AFD_WINE_SET_SO_OOBINLINE CTL_CODE(FILE_DEVICE_NETWORK, 228, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_SET_SO_RCVBUF CTL_CODE(FILE_DEVICE_NETWORK, 229, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_GET_SO_RCVBUF CTL_CODE(FILE_DEVICE_NETWORK, 230, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_AFD_WINE_SET_SO_RCVTIMEO CTL_CODE(FILE_DEVICE_NETWORK, 231, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_AFD_WINE_GET_SO_RCVTIMEO CTL_CODE(FILE_DEVICE_NETWORK, 232, METHOD_BUFFERED, FILE_ANY_ACCESS)
struct afd_create_params { diff --git a/server/sock.c b/server/sock.c index 8bad31efdd1..94dbafe44ee 100644 --- a/server/sock.c +++ b/server/sock.c @@ -208,6 +208,7 @@ struct sock union win_sockaddr addr; /* socket name */ int addr_len; /* socket name length */ unsigned int rcvbuf; /* advisory recv buffer size */ + unsigned int rcvtimeo; /* receive timeout in ms */ unsigned int rd_shutdown : 1; /* is the read end shut down? */ unsigned int wr_shutdown : 1; /* is the write end shut down? */ unsigned int wr_shutdown_pending : 1; /* is a write shutdown pending? */ @@ -1388,6 +1389,7 @@ static struct sock *create_socket(void) sock->nonblocking = 0; sock->bound = 0; sock->rcvbuf = 0; + sock->rcvtimeo = 0; init_async_queue( &sock->read_q ); init_async_queue( &sock->write_q ); init_async_queue( &sock->ifchange_q ); @@ -2619,6 +2621,35 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) return 0; }
+ case IOCTL_AFD_WINE_GET_SO_RCVTIMEO: + { + DWORD rcvtimeo = sock->rcvtimeo; + + if (get_reply_max_size() < sizeof(rcvtimeo)) + { + set_error( STATUS_BUFFER_TOO_SMALL ); + return 0; + } + + set_reply_data( &rcvtimeo, sizeof(rcvtimeo) ); + return 1; + } + + case IOCTL_AFD_WINE_SET_SO_RCVTIMEO: + { + DWORD rcvtimeo; + + if (get_req_data_size() < sizeof(rcvtimeo)) + { + set_error( STATUS_BUFFER_TOO_SMALL ); + return 0; + } + rcvtimeo = *(DWORD *)get_req_data(); + + sock->rcvtimeo = rcvtimeo; + return 0; + } + default: set_error( STATUS_NOT_SUPPORTED ); return 0; @@ -3029,19 +3060,14 @@ DECL_HANDLER(recv_socket) /* recv() returned EWOULDBLOCK, i.e. no data available yet */ if (status == STATUS_DEVICE_NOT_READY && !sock->nonblocking) { -#ifdef SO_RCVTIMEO - struct timeval tv; - socklen_t len = sizeof(tv); - /* Set a timeout on the async if necessary. * * We want to do this *only* if the client gave us STATUS_DEVICE_NOT_READY. * If the client gave us STATUS_PENDING, it expects the async to always * block (it was triggered by WSARecv*() with a valid OVERLAPPED * structure) and for the timeout not to be respected. */ - if (is_fd_overlapped( fd ) && !getsockopt( get_unix_fd( fd ), SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, &len )) - timeout = tv.tv_sec * -10000000 + tv.tv_usec * -10; -#endif + if (is_fd_overlapped( fd )) + timeout = (timeout_t)sock->rcvtimeo * -10000;
status = STATUS_PENDING; }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/unix/socket.c | 3 +++ dlls/ws2_32/socket.c | 4 +++- include/wine/afd.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 0ab30ec6515..549981388c7 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -1652,6 +1652,9 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc case IOCTL_AFD_WINE_SET_SO_OOBINLINE: return do_setsockopt( handle, io, SOL_SOCKET, SO_OOBINLINE, in_buffer, in_size );
+ case IOCTL_AFD_WINE_GET_SO_REUSEADDR: + return do_getsockopt( handle, io, SOL_SOCKET, SO_REUSEADDR, out_buffer, out_size ); + default: { if ((code >> 16) == FILE_DEVICE_NETWORK) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 15c9d0cc940..11e6719fcb0 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2090,7 +2090,6 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level,
/* Handle common cases. The special cases are below, sorted * alphabetically */ - case WS_SO_REUSEADDR: case WS_SO_SNDBUF: if ( (fd = get_sock_fd( s, 0, NULL )) == -1) return SOCKET_ERROR; @@ -2291,6 +2290,9 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level, case WS_SO_RCVTIMEO: return server_getsockopt( s, IOCTL_AFD_WINE_GET_SO_RCVTIMEO, optval, optlen );
+ case WS_SO_REUSEADDR: + return server_getsockopt( s, IOCTL_AFD_WINE_GET_SO_REUSEADDR, optval, optlen ); + case WS_SO_SNDTIMEO: { INT64 timeout; diff --git a/include/wine/afd.h b/include/wine/afd.h index c4f7c7a6413..f337ec361b2 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -173,6 +173,7 @@ struct afd_get_events_params #define IOCTL_AFD_WINE_GET_SO_RCVBUF CTL_CODE(FILE_DEVICE_NETWORK, 230, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_SET_SO_RCVTIMEO CTL_CODE(FILE_DEVICE_NETWORK, 231, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_GET_SO_RCVTIMEO CTL_CODE(FILE_DEVICE_NETWORK, 232, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_AFD_WINE_GET_SO_REUSEADDR CTL_CODE(FILE_DEVICE_NETWORK, 233, METHOD_BUFFERED, FILE_ANY_ACCESS)
struct afd_create_params {
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/unix/socket.c | 20 ++++++++++++++++++++ dlls/ws2_32/socket.c | 13 +++---------- include/wine/afd.h | 1 + 3 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 549981388c7..38cb80997ff 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -1655,6 +1655,26 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc case IOCTL_AFD_WINE_GET_SO_REUSEADDR: return do_getsockopt( handle, io, SOL_SOCKET, SO_REUSEADDR, out_buffer, out_size );
+ /* BSD socket SO_REUSEADDR is not 100% compatible to winsock semantics; + * however, using it the BSD way fixes bug 8513 and seems to be what + * most programmers assume, anyway */ + case IOCTL_AFD_WINE_SET_SO_REUSEADDR: + { + int fd, needs_close = FALSE; + NTSTATUS status; + int ret; + + if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))) + return status; + + ret = setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, in_buffer, in_size ); +#ifdef __APPLE__ + if (!ret) ret = setsockopt( fd, SOL_SOCKET, SO_REUSEPORT, in_buffer, in_size ); +#endif + if (needs_close) close( fd ); + return ret ? sock_errno_to_status( errno ) : STATUS_SUCCESS; + } + default: { if ((code >> 16) == FILE_DEVICE_NETWORK) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 11e6719fcb0..89fb7d3462b 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -3572,6 +3572,9 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname, case WS_SO_RCVTIMEO: return server_setsockopt( s, IOCTL_AFD_WINE_SET_SO_RCVTIMEO, optval, optlen );
+ case WS_SO_REUSEADDR: + return server_setsockopt( s, IOCTL_AFD_WINE_SET_SO_REUSEADDR, optval, optlen ); + /* Some options need some conversion before they can be sent to * setsockopt. The conversions are done here, then they will fall through * to the general case. Special options that are not passed to @@ -3588,16 +3591,6 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname, convert_sockopt(&level, &optname); break;
- /* The options listed here don't need any special handling. Thanks to - * the conversion happening above, options from there will fall through - * to this, too.*/ - /* BSD socket SO_REUSEADDR is not 100% compatible to winsock semantics. - * however, using it the BSD way fixes bug 8513 and seems to be what - * most programmers assume, anyway */ - case WS_SO_REUSEADDR: - convert_sockopt(&level, &optname); - break; - /* SO_DEBUG is a privileged operation, ignore it. */ case WS_SO_DEBUG: TRACE("Ignoring SO_DEBUG\n"); diff --git a/include/wine/afd.h b/include/wine/afd.h index f337ec361b2..d522b8a289f 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -174,6 +174,7 @@ struct afd_get_events_params #define IOCTL_AFD_WINE_SET_SO_RCVTIMEO CTL_CODE(FILE_DEVICE_NETWORK, 231, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_GET_SO_RCVTIMEO CTL_CODE(FILE_DEVICE_NETWORK, 232, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_GET_SO_REUSEADDR CTL_CODE(FILE_DEVICE_NETWORK, 233, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_AFD_WINE_SET_SO_REUSEADDR CTL_CODE(FILE_DEVICE_NETWORK, 234, METHOD_BUFFERED, FILE_ANY_ACCESS)
struct afd_create_params {
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- include/wine/afd.h | 1 + server/sock.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+)
diff --git a/include/wine/afd.h b/include/wine/afd.h index d522b8a289f..ddf780500b7 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -175,6 +175,7 @@ struct afd_get_events_params #define IOCTL_AFD_WINE_GET_SO_RCVTIMEO CTL_CODE(FILE_DEVICE_NETWORK, 232, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_GET_SO_REUSEADDR CTL_CODE(FILE_DEVICE_NETWORK, 233, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_SET_SO_REUSEADDR CTL_CODE(FILE_DEVICE_NETWORK, 234, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_AFD_WINE_SET_SO_SNDBUF CTL_CODE(FILE_DEVICE_NETWORK, 235, METHOD_BUFFERED, FILE_ANY_ACCESS)
struct afd_create_params { diff --git a/server/sock.c b/server/sock.c index 94dbafe44ee..0657a42427a 100644 --- a/server/sock.c +++ b/server/sock.c @@ -2650,6 +2650,22 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) return 0; }
+ case IOCTL_AFD_WINE_SET_SO_SNDBUF: + { + DWORD sndbuf; + + if (get_req_data_size() < sizeof(sndbuf)) + { + set_error( STATUS_BUFFER_TOO_SMALL ); + return 0; + } + sndbuf = *(DWORD *)get_req_data(); + + if (setsockopt( unix_fd, SOL_SOCKET, SO_RCVBUF, (char *)&sndbuf, sizeof(sndbuf) ) < 0) + set_error( sock_get_ntstatus( errno ) ); + return 0; + } + default: set_error( STATUS_NOT_SUPPORTED ); return 0;
On Mon, 2021-06-28 at 22:39 -0500, Zebediah Figura wrote:
diff --git a/server/sock.c b/server/sock.c index 94dbafe44ee..0657a42427a 100644 --- a/server/sock.c +++ b/server/sock.c @@ -2650,6 +2650,22 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) return 0; }
- case IOCTL_AFD_WINE_SET_SO_SNDBUF:
- {
DWORD sndbuf;
if (get_req_data_size() < sizeof(sndbuf))
{
set_error( STATUS_BUFFER_TOO_SMALL );
return 0;
}
sndbuf = *(DWORD *)get_req_data();
if (setsockopt( unix_fd, SOL_SOCKET, SO_RCVBUF, (char *)&sndbuf, sizeof(sndbuf) ) < 0)
set_error( sock_get_ntstatus( errno ) );
return 0;
- }
SO_RCVBUF -> SO_SNDBUF
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- include/wine/afd.h | 1 + server/sock.c | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/include/wine/afd.h b/include/wine/afd.h index ddf780500b7..f2a5abf726d 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -176,6 +176,7 @@ struct afd_get_events_params #define IOCTL_AFD_WINE_GET_SO_REUSEADDR CTL_CODE(FILE_DEVICE_NETWORK, 233, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_SET_SO_REUSEADDR CTL_CODE(FILE_DEVICE_NETWORK, 234, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_SET_SO_SNDBUF CTL_CODE(FILE_DEVICE_NETWORK, 235, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_AFD_WINE_GET_SO_SNDBUF CTL_CODE(FILE_DEVICE_NETWORK, 236, METHOD_BUFFERED, FILE_ANY_ACCESS)
struct afd_create_params { diff --git a/server/sock.c b/server/sock.c index 0657a42427a..0d42a8bebf6 100644 --- a/server/sock.c +++ b/server/sock.c @@ -208,6 +208,7 @@ struct sock union win_sockaddr addr; /* socket name */ int addr_len; /* socket name length */ unsigned int rcvbuf; /* advisory recv buffer size */ + unsigned int sndbuf; /* advisory send buffer size */ unsigned int rcvtimeo; /* receive timeout in ms */ unsigned int rd_shutdown : 1; /* is the read end shut down? */ unsigned int wr_shutdown : 1; /* is the write end shut down? */ @@ -1389,6 +1390,7 @@ static struct sock *create_socket(void) sock->nonblocking = 0; sock->bound = 0; sock->rcvbuf = 0; + sock->sndbuf = 0; sock->rcvtimeo = 0; init_async_queue( &sock->read_q ); init_async_queue( &sock->write_q ); @@ -1552,6 +1554,10 @@ static int init_socket( struct sock *sock, int family, int type, int protocol, u if (!getsockopt( sockfd, SOL_SOCKET, SO_RCVBUF, &value, &len )) sock->rcvbuf = value;
+ len = sizeof(value); + if (!getsockopt( sockfd, SOL_SOCKET, SO_SNDBUF, &value, &len )) + sock->sndbuf = value; + sock->state = (type == WS_SOCK_STREAM ? SOCK_UNCONNECTED : SOCK_CONNECTIONLESS); sock->flags = flags; sock->proto = protocol; @@ -2650,6 +2656,20 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) return 0; }
+ case IOCTL_AFD_WINE_GET_SO_SNDBUF: + { + int sndbuf = sock->sndbuf; + + if (get_reply_max_size() < sizeof(sndbuf)) + { + set_error( STATUS_BUFFER_TOO_SMALL ); + return 0; + } + + set_reply_data( &sndbuf, sizeof(sndbuf) ); + return 1; + } + case IOCTL_AFD_WINE_SET_SO_SNDBUF: { DWORD sndbuf; @@ -2661,7 +2681,9 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) } sndbuf = *(DWORD *)get_req_data();
- if (setsockopt( unix_fd, SOL_SOCKET, SO_RCVBUF, (char *)&sndbuf, sizeof(sndbuf) ) < 0) + if (!setsockopt( unix_fd, SOL_SOCKET, SO_RCVBUF, (char *)&sndbuf, sizeof(sndbuf) )) + sock->sndbuf = sndbuf; + else set_error( sock_get_ntstatus( errno ) ); return 0; }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/socket.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 89fb7d3462b..3f15bb4e39b 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -3575,21 +3575,8 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname, case WS_SO_REUSEADDR: return server_setsockopt( s, IOCTL_AFD_WINE_SET_SO_REUSEADDR, optval, optlen );
- /* Some options need some conversion before they can be sent to - * setsockopt. The conversions are done here, then they will fall through - * to the general case. Special options that are not passed to - * setsockopt follow below that.*/ - case WS_SO_SNDBUF: - if (!*(const int *)optval) - { - FIXME("SO_SNDBUF ignoring request to disable send buffering\n"); -#ifdef __APPLE__ - return 0; -#endif - } - convert_sockopt(&level, &optname); - break; + return server_setsockopt( s, IOCTL_AFD_WINE_SET_SO_SNDBUF, optval, optlen );
/* SO_DEBUG is a privileged operation, ignore it. */ case WS_SO_DEBUG:
On Mon, 2021-06-28 at 22:39 -0500, Zebediah Figura wrote:
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 89fb7d3462b..3f15bb4e39b 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -3575,21 +3575,8 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname, case WS_SO_REUSEADDR: return server_setsockopt( s, IOCTL_AFD_WINE_SET_SO_REUSEADDR, optval, optlen );
/* Some options need some conversion before they can be sent to
* setsockopt. The conversions are done here, then they will fall through
* to the general case. Special options that are not passed to
* setsockopt follow below that.*/
case WS_SO_SNDBUF:
if (!*(const int *)optval)
{
FIXME("SO_SNDBUF ignoring request to disable send buffering\n");
-#ifdef __APPLE__
return 0;
-#endif
}
convert_sockopt(&level, &optname);
break;
return server_setsockopt( s, IOCTL_AFD_WINE_SET_SO_SNDBUF, optval, optlen );
You didn't move the early return for macOS (or the fixme, which should probably be moved into the ifdef). setsockopt(SO_SNDBUF) fails on macOS if a zero value is passed.
On 6/29/21 3:40 AM, Hans Leidekker wrote:
On Mon, 2021-06-28 at 22:39 -0500, Zebediah Figura wrote:
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 89fb7d3462b..3f15bb4e39b 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -3575,21 +3575,8 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname, case WS_SO_REUSEADDR: return server_setsockopt( s, IOCTL_AFD_WINE_SET_SO_REUSEADDR, optval, optlen );
/* Some options need some conversion before they can be sent to
* setsockopt. The conversions are done here, then they will fall through
* to the general case. Special options that are not passed to
* setsockopt follow below that.*/
case WS_SO_SNDBUF:
if (!*(const int *)optval)
{
FIXME("SO_SNDBUF ignoring request to disable send buffering\n");
-#ifdef __APPLE__
return 0;
-#endif
}
convert_sockopt(&level, &optname);
break;
return server_setsockopt( s, IOCTL_AFD_WINE_SET_SO_SNDBUF, optval, optlen );
You didn't move the early return for macOS (or the fixme, which should probably be moved into the ifdef). setsockopt(SO_SNDBUF) fails on macOS if a zero value is passed.
Thanks for pointing out the error; I'll send a new revision.
WRT the fixme, I deleted it because we can at least lie accurately now, and because printing error messages from the server is discouraged.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=8606 Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/socket.c | 17 +++-------------- dlls/ws2_32/tests/sock.c | 2 +- 2 files changed, 4 insertions(+), 15 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 3f15bb4e39b..562d05ed4be 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2088,20 +2088,6 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level, case WS_SO_BROADCAST: return server_getsockopt( s, IOCTL_AFD_WINE_GET_SO_BROADCAST, optval, optlen );
- /* Handle common cases. The special cases are below, sorted - * alphabetically */ - case WS_SO_SNDBUF: - if ( (fd = get_sock_fd( s, 0, NULL )) == -1) - return SOCKET_ERROR; - convert_sockopt(&level, &optname); - if (getsockopt(fd, level, optname, optval, (socklen_t *)optlen) != 0 ) - { - SetLastError(wsaErrno()); - ret = SOCKET_ERROR; - } - release_sock_fd( s, fd ); - return ret; - case WS_SO_BSP_STATE: { CSADDR_INFO *csinfo = (CSADDR_INFO *)optval; @@ -2293,6 +2279,9 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level, case WS_SO_REUSEADDR: return server_getsockopt( s, IOCTL_AFD_WINE_GET_SO_REUSEADDR, optval, optlen );
+ case WS_SO_SNDBUF: + return server_getsockopt( s, IOCTL_AFD_WINE_GET_SO_SNDBUF, optval, optlen ); + case WS_SO_SNDTIMEO: { INT64 timeout; diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index a3f7e002ce7..e579b72ecb5 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -1214,7 +1214,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;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=93254
Your paranoid android.
=== debiant2 (64 bit WoW report) ===
ws2_32: sock.c:5787: Test succeeded inside todo block: expected failure sock.c:5788: Test succeeded inside todo block: got error 64