Zebediah Figura : ws2_32: Handle SO_SNDTIMEO in the server.
Alexandre Julliard
julliard at winehq.org
Wed Jun 30 16:10:59 CDT 2021
Module: wine
Branch: master
Commit: 20c19903721faf7bbb0afc1cd878c4199abc6f96
URL: https://source.winehq.org/git/wine.git/?a=commit;h=20c19903721faf7bbb0afc1cd878c4199abc6f96
Author: Zebediah Figura <z.figura12 at gmail.com>
Date: Tue Jun 29 23:25:43 2021 -0500
ws2_32: Handle SO_SNDTIMEO in the server.
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ws2_32/socket.c | 70 +++-------------------------------------------------
include/wine/afd.h | 2 ++
server/sock.c | 40 ++++++++++++++++++++++++------
3 files changed, 39 insertions(+), 73 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 562d05ed4be..ce71e25d63d 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -913,34 +913,6 @@ static int convert_sockopt(INT *level, INT *optname)
return 0;
}
-/* Utility: get the SO_RCVTIMEO or SO_SNDTIMEO socket option
- * from an fd and return the value converted to milli seconds
- * or 0 if there is an infinite time out */
-static inline INT64 get_rcvsnd_timeo( int fd, BOOL is_recv)
-{
- struct timeval tv;
- socklen_t len = sizeof(tv);
- int optname, res;
-
- if (is_recv)
-#ifdef SO_RCVTIMEO
- optname = SO_RCVTIMEO;
-#else
- return 0;
-#endif
- else
-#ifdef SO_SNDTIMEO
- optname = SO_SNDTIMEO;
-#else
- return 0;
-#endif
-
- res = getsockopt(fd, SOL_SOCKET, optname, &tv, &len);
- if (res < 0)
- return 0;
- return (UINT64)tv.tv_sec * 1000 + tv.tv_usec / 1000;
-}
-
int
convert_socktype_w2u(int windowssocktype) {
unsigned int i;
@@ -2283,23 +2255,8 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level,
return server_getsockopt( s, IOCTL_AFD_WINE_GET_SO_SNDBUF, optval, optlen );
case WS_SO_SNDTIMEO:
- {
- INT64 timeout;
+ return server_getsockopt( s, IOCTL_AFD_WINE_GET_SO_SNDTIMEO, optval, optlen );
- if (!optlen || *optlen < sizeof(int)|| !optval)
- {
- SetLastError(WSAEFAULT);
- return SOCKET_ERROR;
- }
- if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
- return SOCKET_ERROR;
-
- timeout = get_rcvsnd_timeo(fd, optname == WS_SO_RCVTIMEO);
- *(int *)optval = timeout <= UINT_MAX ? timeout : UINT_MAX;
-
- release_sock_fd( s, fd );
- return ret;
- }
case WS_SO_TYPE:
{
int sock_type;
@@ -3504,7 +3461,6 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
{
int fd;
int woptval;
- struct timeval tval;
struct ip_mreq_source mreq_source;
TRACE("(socket %04lx, %s, optval %s, optlen %d)\n", s,
@@ -3567,6 +3523,9 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
case WS_SO_SNDBUF:
return server_setsockopt( s, IOCTL_AFD_WINE_SET_SO_SNDBUF, optval, optlen );
+ case WS_SO_SNDTIMEO:
+ return server_setsockopt( s, IOCTL_AFD_WINE_SET_SO_SNDTIMEO, optval, optlen );
+
/* SO_DEBUG is a privileged operation, ignore it. */
case WS_SO_DEBUG:
TRACE("Ignoring SO_DEBUG\n");
@@ -3607,27 +3566,6 @@ 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_SNDTIMEO
- case WS_SO_SNDTIMEO:
- if (optval && optlen == sizeof(UINT32)) {
- /* WinSock passes milliseconds instead of struct timeval */
- tval.tv_usec = (*(const UINT32*)optval % 1000) * 1000;
- tval.tv_sec = *(const UINT32*)optval / 1000;
- /* min of 500 milliseconds */
- if (tval.tv_sec == 0 && tval.tv_usec && tval.tv_usec < 500000)
- tval.tv_usec = 500000;
- optlen = sizeof(struct timeval);
- optval = (char*)&tval;
- } else if (optlen == sizeof(struct timeval)) {
- WARN("SO_SND/RCVTIMEO for %d bytes: assuming unixism\n", optlen);
- } else {
- WARN("SO_SND/RCVTIMEO for %d bytes is weird: ignored\n", optlen);
- return 0;
- }
- convert_sockopt(&level, &optname);
- break;
-#endif
-
case WS_SO_RANDOMIZE_PORT:
FIXME("Ignoring WS_SO_RANDOMIZE_PORT\n");
return 0;
diff --git a/include/wine/afd.h b/include/wine/afd.h
index f2a5abf726d..44a8b1a5ff9 100644
--- a/include/wine/afd.h
+++ b/include/wine/afd.h
@@ -177,6 +177,8 @@ struct afd_get_events_params
#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)
+#define IOCTL_AFD_WINE_GET_SO_SNDTIMEO CTL_CODE(FILE_DEVICE_NETWORK, 237, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_AFD_WINE_SET_SO_SNDTIMEO CTL_CODE(FILE_DEVICE_NETWORK, 238, METHOD_BUFFERED, FILE_ANY_ACCESS)
struct afd_create_params
{
diff --git a/server/sock.c b/server/sock.c
index 9a99e512c0d..befa9117c13 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -210,6 +210,7 @@ struct sock
unsigned int rcvbuf; /* advisory recv buffer size */
unsigned int sndbuf; /* advisory send buffer size */
unsigned int rcvtimeo; /* receive timeout in ms */
+ unsigned int sndtimeo; /* send 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? */
@@ -1392,6 +1393,7 @@ static struct sock *create_socket(void)
sock->rcvbuf = 0;
sock->sndbuf = 0;
sock->rcvtimeo = 0;
+ sock->sndtimeo = 0;
init_async_queue( &sock->read_q );
init_async_queue( &sock->write_q );
init_async_queue( &sock->ifchange_q );
@@ -2697,6 +2699,35 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
return 0;
}
+ case IOCTL_AFD_WINE_GET_SO_SNDTIMEO:
+ {
+ DWORD sndtimeo = sock->sndtimeo;
+
+ if (get_reply_max_size() < sizeof(sndtimeo))
+ {
+ set_error( STATUS_BUFFER_TOO_SMALL );
+ return 0;
+ }
+
+ set_reply_data( &sndtimeo, sizeof(sndtimeo) );
+ return 1;
+ }
+
+ case IOCTL_AFD_WINE_SET_SO_SNDTIMEO:
+ {
+ DWORD sndtimeo;
+
+ if (get_req_data_size() < sizeof(sndtimeo))
+ {
+ set_error( STATUS_BUFFER_TOO_SMALL );
+ return 0;
+ }
+ sndtimeo = *(DWORD *)get_req_data();
+
+ sock->sndtimeo = sndtimeo;
+ return 0;
+ }
+
default:
set_error( STATUS_NOT_SUPPORTED );
return 0;
@@ -3217,19 +3248,14 @@ DECL_HANDLER(send_socket)
/* send() returned EWOULDBLOCK or a short write, i.e. cannot send all data yet */
if (status == STATUS_DEVICE_NOT_READY && !sock->nonblocking)
{
-#ifdef SO_SNDTIMEO
- 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 WSASend*() 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_SNDTIMEO, (char *)&tv, &len ))
- timeout = tv.tv_sec * -10000000 + tv.tv_usec * -10;
-#endif
+ if (is_fd_overlapped( fd ))
+ timeout = (timeout_t)sock->sndtimeo * -10000;
status = STATUS_PENDING;
}
More information about the wine-cvs
mailing list