From 6759e1c286823a8ea6b004ca256481d16d1852fc Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 31 May 2007 11:55:38 +0200 Subject: [PATCH] ws2_32: Reimplement WSARecvFrom along the lines of NtReadFile. --- dlls/ws2_32/socket.c | 116 ++++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 50 deletions(-) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 1eed70a7ac..85a2269c27 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -4213,7 +4213,8 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, { unsigned int i, options; - int n, fd, err = WSAENOTSOCK, ret; + int n, fd, err; + DWORD timeout_start = GetTickCount(); struct iovec* iovec; struct ws2_async *wsa; IO_STATUS_BLOCK* iosb; @@ -4232,7 +4233,7 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, if ( !iovec ) { err = WSAEFAULT; - goto err_close; + goto error; } for (i = 0; i < dwBufferCount; i++) @@ -4241,65 +4242,84 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, iovec[i].iov_len = lpBuffers[i].len; } - if ( (lpOverlapped || lpCompletionRoutine) && - !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))) + for (;;) { - wsa = WS2_make_async( s, ws2m_read, iovec, dwBufferCount, - lpFlags, lpFrom, lpFromlen, - lpOverlapped, lpCompletionRoutine, &iosb ); + n = WS2_recv( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags ); + if (n != -1) break; - if ( !wsa ) + if (errno == EINTR) continue; + if (errno != EAGAIN) { - err = WSAEFAULT; - goto err_free; + err = wsaErrno(); + goto error; } - if ((ret = ws2_queue_async( wsa, iosb )) != STATUS_PENDING) + if ((lpOverlapped || lpCompletionRoutine) && + !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))) { - err = NtStatusToWSAError( ret ); + wsa = WS2_make_async( s, ws2m_read, iovec, dwBufferCount, + lpFlags, lpFrom, lpFromlen, + lpOverlapped, lpCompletionRoutine, &iosb ); + if ( !wsa ) + { + err = WSAEFAULT; + goto error; + } + release_sock_fd( s, fd ); - if ( !lpOverlapped ) - HeapFree( GetProcessHeap(), 0, iosb ); - HeapFree( GetProcessHeap(), 0, wsa ); - goto err_free; + iosb->u.Status = STATUS_PENDING; + iosb->Information = 0; + + SERVER_START_REQ( register_async ) + { + req->handle = wsa->hSocket; + req->type = ASYNC_TYPE_READ; + req->async.callback = WS2_async_recv; + req->async.iosb = iosb; + req->async.arg = wsa; + req->async.event = lpCompletionRoutine ? 0 : lpOverlapped->hEvent; + err = wine_server_call( req ); + } + SERVER_END_REQ; + + if (err == STATUS_PENDING) + NtCurrentTeb()->num_async_io++; + else + ws2_async_terminate(wsa, iosb, err, 0); + + WSASetLastError( NtStatusToWSAError( err )); + return SOCKET_ERROR; } - release_sock_fd( s, fd ); - /* Try immediate completion */ - if ( lpOverlapped ) + if ( _is_blocking(s) ) { - if ( WSAGetOverlappedResult( s, lpOverlapped, - lpNumberOfBytesRecvd, FALSE, lpFlags) ) - return 0; + struct pollfd pfd; + int timeout = GET_RCVTIMEO(fd); + if (timeout != -1) + { + timeout -= GetTickCount() - timeout_start; + if (timeout < 0) timeout = 0; + } - if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE ) + pfd.fd = fd; + pfd.events = POLLIN; + if (*lpFlags & WS_MSG_OOB) pfd.events |= POLLPRI; + + if (!timeout || !poll( &pfd, 1, timeout )) + { + err = WSAETIMEDOUT; + /* a timeout is not fatal */ + _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0); goto error; + } } - - WSASetLastError( WSA_IO_PENDING ); - return SOCKET_ERROR; - } - - if ( _is_blocking(s) ) - { - /* block here */ - /* FIXME: OOB and exceptfds? */ - int timeout = GET_RCVTIMEO(fd); - if( !do_block(fd, POLLIN, timeout)) { - err = WSAETIMEDOUT; - /* a timeout is not fatal */ - _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0); - goto err_free; + else + { + err = WSAEWOULDBLOCK; + goto error; } } - n = WS2_recv( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags ); - if ( n == -1 ) - { - err = wsaErrno(); - goto err_free; - } - TRACE(" -> %i bytes\n", n); *lpNumberOfBytesRecvd = n; @@ -4309,13 +4329,9 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, return 0; -err_free: +error: HeapFree(GetProcessHeap(), 0, iovec); - -err_close: release_sock_fd( s, fd ); - -error: WARN(" -> ERROR %d\n", err); WSASetLastError( err ); return SOCKET_ERROR; -- 2.32.0.93.g670b81a890