From 023a2fa789b7700ed32f8d78655c03b4b273d42b Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Wed, 28 Nov 2007 15:54:17 +0000 Subject: [PATCH] * fhandler_socket.cc (fhandler_socket::recv_internal): Add MSG_WAITALL handling. Use explicit flag values instead of MSG_WINMASK. (fhandler_socket::send_internal): Use explicit flag values instead of MSG_WINMASK. * include/cygwin/socket.h (MSG_WINMASK): Remove definition. (MSG_WAITALL): Define. --- winsup/cygwin/ChangeLog | 9 +++++ winsup/cygwin/fhandler_socket.cc | 53 ++++++++++++++++++++++----- winsup/cygwin/include/cygwin/socket.h | 2 +- 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 1968c9f2d..1cb0448a7 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,12 @@ +2007-11-28 Corinna Vinschen + + * fhandler_socket.cc (fhandler_socket::recv_internal): Add MSG_WAITALL + handling. Use explicit flag values instead of MSG_WINMASK. + (fhandler_socket::send_internal): Use explicit flag values instead of + MSG_WINMASK. + * include/cygwin/socket.h (MSG_WINMASK): Remove definition. + (MSG_WAITALL): Define. + 2007-11-27 Corinna Vinschen * posix_ipc.cc (ipc_names): Rename max_len to prefix_len. Store diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index ba87ebe45..bebd44f79 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -1210,23 +1210,59 @@ fhandler_socket::recv_internal (WSABUF *wsabuf, DWORD wsacnt, DWORD flags, struct sockaddr *from, int *fromlen) { ssize_t res = 0; - DWORD ret = 0; + DWORD ret = 0, wret; int evt_mask = FD_READ | ((flags & MSG_OOB) ? FD_OOB : 0); - flags &= MSG_WINMASK; + bool waitall = (flags & MSG_WAITALL); + flags &= (MSG_OOB | MSG_PEEK | MSG_DONTROUTE); + if (waitall) + { + if (get_socket_type () != SOCK_STREAM) + { + WSASetLastError (WSAEOPNOTSUPP); + set_winsock_errno (); + return SOCKET_ERROR; + } + if (is_nonblocking () || (flags & (MSG_OOB | MSG_PEEK))) + waitall = false; + } + /* Note: Don't call WSARecvFrom(MSG_PEEK) without actually having data waiting in the buffers, otherwise the event handling gets messed up for some reason. */ while (!(res = wait_for_events (evt_mask | FD_CLOSE)) || saw_shutdown_read ()) { - res = WSARecvFrom (get_socket (), wsabuf, wsacnt, &ret, + res = WSARecvFrom (get_socket (), wsabuf, wsacnt, &wret, &flags, from, fromlen, NULL, NULL); - if (!res || WSAGetLastError () != WSAEWOULDBLOCK) + if (!res) + { + ret += wret; + if (!waitall) + break; + while (wret && wsacnt) + { + if (wsabuf->len > wret) + { + wsabuf->len -= wret; + wsabuf->buf += wret; + wret = 0; + } + else + { + wret -= wsabuf->len; + ++wsabuf; + --wsacnt; + } + } + if (!wret) + break; + } + else if (WSAGetLastError () != WSAEWOULDBLOCK) break; } - if (res == SOCKET_ERROR) + if (!ret && res == SOCKET_ERROR) { /* According to SUSv3, errno isn't set in that case and no error condition is returned. */ @@ -1239,11 +1275,10 @@ fhandler_socket::recv_internal (WSABUF *wsabuf, DWORD wsacnt, DWORD flags, return 0; set_winsock_errno (); + return SOCKET_ERROR; } - else - res = ret; - return res; + return ret; } int @@ -1317,7 +1352,7 @@ fhandler_socket::send_internal (struct _WSABUF *wsabuf, DWORD wsacnt, int flags, do { if ((res = WSASendTo (get_socket (), wsabuf, wsacnt, &ret, - flags & MSG_WINMASK, to, tolen, NULL, NULL)) + flags & (MSG_OOB | MSG_DONTROUTE), to, tolen, NULL, NULL)) && (err = WSAGetLastError ()) == WSAEWOULDBLOCK) { LOCK_EVENTS; diff --git a/winsup/cygwin/include/cygwin/socket.h b/winsup/cygwin/include/cygwin/socket.h index dd9cd3671..91b80dd13 100644 --- a/winsup/cygwin/include/cygwin/socket.h +++ b/winsup/cygwin/include/cygwin/socket.h @@ -189,7 +189,7 @@ struct OLD_msghdr #define MSG_OOB 0x1 /* process out-of-band data */ #define MSG_PEEK 0x2 /* peek at incoming message */ #define MSG_DONTROUTE 0x4 /* send without using routing tables */ -#define MSG_WINMASK 0x7 /* flags understood by WinSock calls */ +#define MSG_WAITALL 0x8 /* wait for all requested bytes */ #define MSG_NOSIGNAL 0x20 /* Don't raise SIGPIPE */ #define MSG_TRUNC 0x0100 /* Normal data truncated */ #define MSG_CTRUNC 0x0200 /* Control data truncated */