From 731a96800308ff9f4a1616c948bb58f6d5ecef9c Mon Sep 17 00:00:00 2001 From: Jinoh Kang Date: Thu, 24 Mar 2022 02:25:28 +0900 Subject: [PATCH] server: Replace redundant send_socket status fields with force_async boolean field. The 'status' field of send_socket_request is always either STATUS_PENDING or STATUS_DEVICE_NOT_READY, and the 'total' field is always zero. Replace the 'status' field with 'force_async' boolean field, and get rid of the 'total' field entirely. Also, clean up the send_socket handler code a bit. Signed-off-by: Jinoh Kang Signed-off-by: Zebediah Figura Signed-off-by: Alexandre Julliard --- dlls/ntdll/unix/socket.c | 8 ++----- include/wine/server_protocol.h | 6 ++--- server/protocol.def | 3 +-- server/request.h | 3 +-- server/sock.c | 41 +++++++++------------------------- server/trace.c | 3 +-- 6 files changed, 19 insertions(+), 45 deletions(-) diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 8e5a1825181..351028d4983 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -908,12 +908,9 @@ static NTSTATUS sock_send( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, voi async->iov_cursor = 0; async->sent_len = 0; - status = force_async ? STATUS_PENDING : STATUS_DEVICE_NOT_READY; - SERVER_START_REQ( send_socket ) { - req->status = status; - req->total = 0; + req->force_async = force_async; req->async = server_async( handle, &async->io, event, apc, apc_user, iosb_client_ptr(io) ); status = wine_server_call( req ); wait_handle = wine_server_ptr_handle( reply->wait ); @@ -1116,8 +1113,7 @@ static NTSTATUS sock_transmit( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, SERVER_START_REQ( send_socket ) { - req->status = STATUS_PENDING; - req->total = 0; + req->force_async = 1; req->async = server_async( handle, &async->io, event, apc, apc_user, iosb_client_ptr(io) ); status = wine_server_call( req ); wait_handle = wine_server_ptr_handle( reply->wait ); diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index b3a5d3ef3d5..6cd901f1e56 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -1783,8 +1783,8 @@ struct send_socket_request struct request_header __header; char __pad_12[4]; async_data_t async; - unsigned int status; - unsigned int total; + int force_async; + char __pad_60[4]; }; struct send_socket_reply { @@ -6286,7 +6286,7 @@ union generic_reply /* ### protocol_version begin ### */ -#define SERVER_PROTOCOL_VERSION 748 +#define SERVER_PROTOCOL_VERSION 749 /* ### protocol_version end ### */ diff --git a/server/protocol.def b/server/protocol.def index 81b44aefd7c..d9bed6855e9 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1462,8 +1462,7 @@ enum server_fd_type /* Perform a send on a socket */ @REQ(send_socket) async_data_t async; /* async I/O parameters */ - unsigned int status; /* status of initial call */ - unsigned int total; /* number of bytes already sent */ + int force_async; /* Force asynchronous mode? */ @REPLY obj_handle_t wait; /* handle to wait on for blocking send */ unsigned int options; /* device open options */ diff --git a/server/request.h b/server/request.h index 32929c146a0..ca99acbdbf6 100644 --- a/server/request.h +++ b/server/request.h @@ -1051,8 +1051,7 @@ C_ASSERT( FIELD_OFFSET(struct recv_socket_reply, options) == 12 ); C_ASSERT( FIELD_OFFSET(struct recv_socket_reply, nonblocking) == 16 ); C_ASSERT( sizeof(struct recv_socket_reply) == 24 ); C_ASSERT( FIELD_OFFSET(struct send_socket_request, async) == 16 ); -C_ASSERT( FIELD_OFFSET(struct send_socket_request, status) == 56 ); -C_ASSERT( FIELD_OFFSET(struct send_socket_request, total) == 60 ); +C_ASSERT( FIELD_OFFSET(struct send_socket_request, force_async) == 56 ); C_ASSERT( sizeof(struct send_socket_request) == 64 ); C_ASSERT( FIELD_OFFSET(struct send_socket_reply, wait) == 8 ); C_ASSERT( FIELD_OFFSET(struct send_socket_reply, options) == 12 ); diff --git a/server/sock.c b/server/sock.c index e3779940174..b403541fcbf 100644 --- a/server/sock.c +++ b/server/sock.c @@ -3508,10 +3508,11 @@ static void send_socket_completion_callback( void *private ) DECL_HANDLER(send_socket) { struct sock *sock = (struct sock *)get_handle_obj( current->process, req->async.handle, 0, &sock_ops ); - unsigned int status = req->status; + unsigned int status = STATUS_PENDING; timeout_t timeout = 0; struct async *async; struct fd *fd; + int bind_errno = 0; if (!sock) return; fd = sock->fd; @@ -3520,7 +3521,6 @@ DECL_HANDLER(send_socket) { union unix_sockaddr unix_addr; socklen_t unix_len; - int bind_errno = 0; int unix_fd = get_unix_fd( fd ); unix_len = get_unix_sockaddr_any( &unix_addr, sock->family ); @@ -3532,36 +3532,15 @@ DECL_HANDLER(send_socket) sock->addr_len = sockaddr_from_unix( &unix_addr, &sock->addr.addr, sizeof(sock->addr) ); sock->bound = 1; } - else if (status == STATUS_PENDING || status == STATUS_DEVICE_NOT_READY) - status = sock_get_ntstatus( bind_errno ? bind_errno : errno ); + else if (!bind_errno) bind_errno = errno; } - /* If we had a short write and the socket is nonblocking (and the client is - * not trying to force the operation to be asynchronous), return success. - * Windows actually refuses to send any data in this case, and returns - * EWOULDBLOCK, but we have no way of doing that. */ - if (status == STATUS_DEVICE_NOT_READY && req->total && sock->nonblocking) - status = STATUS_SUCCESS; + if (!req->force_async && !sock->nonblocking && is_fd_overlapped( fd )) + timeout = (timeout_t)sock->sndtimeo * -10000; - /* send() returned EWOULDBLOCK or a short write, i.e. cannot send all data yet */ - if (status == STATUS_DEVICE_NOT_READY && !sock->nonblocking) - { - /* 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 )) - timeout = (timeout_t)sock->sndtimeo * -10000; - - status = STATUS_PENDING; - } - - if ((status == STATUS_PENDING || status == STATUS_DEVICE_NOT_READY) && sock->wr_shutdown) - status = STATUS_PIPE_DISCONNECTED; - - if ((status == STATUS_PENDING || status == STATUS_DEVICE_NOT_READY) && !async_queued( &sock->write_q )) + if (bind_errno) status = sock_get_ntstatus( bind_errno ); + else if (sock->wr_shutdown) status = STATUS_PIPE_DISCONNECTED; + else if (!async_queued( &sock->write_q )) { /* If write_q is not empty, we cannot really tell if the already queued * asyncs will not consume all available space; if there's no space @@ -3580,6 +3559,9 @@ DECL_HANDLER(send_socket) } } + if (status == STATUS_PENDING && !req->force_async && sock->nonblocking) + status = STATUS_DEVICE_NOT_READY; + if ((async = create_request_async( fd, get_fd_comp_flags( fd ), &req->async ))) { struct send_req *send_req; @@ -3594,7 +3576,6 @@ DECL_HANDLER(send_socket) else if (status == STATUS_PENDING || status == STATUS_DEVICE_NOT_READY) status = STATUS_NO_MEMORY; - if (status == STATUS_SUCCESS) iosb->result = req->total; release_object( iosb ); set_error( status ); diff --git a/server/trace.c b/server/trace.c index 8653755e8a6..a792b74dc05 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2045,8 +2045,7 @@ static void dump_recv_socket_reply( const struct recv_socket_reply *req ) static void dump_send_socket_request( const struct send_socket_request *req ) { dump_async_data( " async=", &req->async ); - fprintf( stderr, ", status=%08x", req->status ); - fprintf( stderr, ", total=%08x", req->total ); + fprintf( stderr, ", force_async=%d", req->force_async ); } static void dump_send_socket_reply( const struct send_socket_reply *req )