diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2007-11-28 18:54:17 +0300 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2007-11-28 18:54:17 +0300 |
commit | 023a2fa789b7700ed32f8d78655c03b4b273d42b (patch) | |
tree | f36b6def4a4268ebaa763e617002748e0fa3d393 /winsup/cygwin/fhandler_socket.cc | |
parent | 02cb1fd853c30addf67b6d39f8cf506737ed96ab (diff) |
* 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.
Diffstat (limited to 'winsup/cygwin/fhandler_socket.cc')
-rw-r--r-- | winsup/cygwin/fhandler_socket.cc | 53 |
1 files changed, 44 insertions, 9 deletions
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; |