ws2_32: Handle SO_RCVTIMEO in the server.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
8aaf9e6460
commit
f4df896e06
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue