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 jinoh.kang.kr@gmail.com ---
Notes: v1 -> v2: - adjust patch for new field "data_size" in send_socket_request v2 -> v3: no changes
dlls/ntdll/unix/socket.c | 8 ++------ server/protocol.def | 5 ++--- server/sock.c | 40 ++++++++-------------------------------- 3 files changed, 12 insertions(+), 41 deletions(-)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index ad03907523d..11ce652fed5 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -921,13 +921,10 @@ static NTSTATUS sock_send( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, voi data_size += len; }
- status = force_async ? STATUS_PENDING : STATUS_DEVICE_NOT_READY; - SERVER_START_REQ( send_socket ) { req->data_size = data_size; - 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 ); @@ -1131,8 +1128,7 @@ static NTSTATUS sock_transmit( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, SERVER_START_REQ( send_socket ) { req->data_size = async->head_len + async->file_len + async->tail_len; - 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/server/protocol.def b/server/protocol.def index 334abb66a77..5d8038d58b9 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1461,10 +1461,9 @@ enum server_fd_type
/* Perform a send on a socket */ @REQ(send_socket) - data_size_t data_size; /* total number of bytes to send (>= total) */ + data_size_t data_size; /* total number of bytes to send */ 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/sock.c b/server/sock.c index 3cb1b5f3dab..1112708369d 100644 --- a/server/sock.c +++ b/server/sock.c @@ -3498,7 +3498,7 @@ static void send_socket_initial_callback( void *private, struct async *async, st 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; @@ -3506,32 +3506,11 @@ DECL_HANDLER(send_socket) if (!sock) return; fd = sock->fd;
- /* 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 (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 @@ -3550,14 +3529,11 @@ 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 ))) { - if (status == STATUS_SUCCESS) - { - struct iosb *iosb = async_get_iosb( async ); - iosb->result = req->total; - release_object( iosb ); - } set_error( status );
async_set_initial_status_callback( async, send_socket_initial_callback, (void *)(unsigned long)req->data_size );