summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog8
-rw-r--r--winsup/cygwin/fhandler_socket.cc80
2 files changed, 55 insertions, 33 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 425de1085..08013867f 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,11 @@
+2008-07-27 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler_socket.cc (fhandler_socket::send_internal): Send never more
+ then 64K bytes at once. For blocking sockets, loop until entire data
+ has been sent or an error occurs.
+ (fhandler_socket::sendto): Drop code which sends on 64K bytes.
+ (fhandler_socket::sendmsg): Ditto.
+
2008-07-26 Christopher Faylor <me+cygwin@cgf.cx>
* fhandler_tty.cc (fhandler_pty_master::setup): Reorganize so that all
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index e770a7cb0..176838de8 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -1415,38 +1415,57 @@ fhandler_socket::send_internal (struct _WSABUF *wsabuf, DWORD wsacnt, int flags,
const struct sockaddr *to, int tolen)
{
int res = 0;
- DWORD ret = 0, err = 0;
+ DWORD ret = 0, err = 0, sum = 0, off = 0;
+ WSABUF buf;
- do
+ for (DWORD i = 0; i < wsacnt; off >= wsabuf[i].len && (++i, off = 0))
{
- if ((res = WSASendTo (get_socket (), wsabuf, wsacnt, &ret,
- flags & (MSG_OOB | MSG_DONTROUTE), to, tolen, NULL, NULL))
- && (err = WSAGetLastError ()) == WSAEWOULDBLOCK)
+ buf.buf = wsabuf[i].buf + off;
+ buf.len = wsabuf[i].len - off;
+ if (buf.len > 65536) /* See KB 823764 */
+ buf.len = 65536;
+
+ do
{
- LOCK_EVENTS;
- wsock_events->events &= ~FD_WRITE;
- UNLOCK_EVENTS;
+ if ((res = WSASendTo (get_socket (), &buf, 1, &ret,
+ flags & (MSG_OOB | MSG_DONTROUTE), to, tolen,
+ NULL, NULL))
+ && (err = WSAGetLastError ()) == WSAEWOULDBLOCK)
+ {
+ LOCK_EVENTS;
+ wsock_events->events &= ~FD_WRITE;
+ UNLOCK_EVENTS;
+ }
}
- }
- while (res && err == WSAEWOULDBLOCK
- && !(res = wait_for_events (FD_WRITE | FD_CLOSE)));
+ while (res && err == WSAEWOULDBLOCK
+ && !(res = wait_for_events (FD_WRITE | FD_CLOSE)));
- if (res == SOCKET_ERROR)
- set_winsock_errno ();
- else
- res = ret;
+ if (!res)
+ {
+ off += ret;
+ sum += ret;
+ }
+ else if (is_nonblocking () || err != WSAEWOULDBLOCK)
+ break;
+ }
+
+ if (sum)
+ res = sum;
+ else if (res == SOCKET_ERROR)
+ {
+ set_winsock_errno ();
- /* Special handling for EPIPE and SIGPIPE.
+ /* Special handling for EPIPE and SIGPIPE.
- EPIPE is generated if the local end has been shut down on a connection
- oriented socket. In this case the process will also receive a SIGPIPE
- unless MSG_NOSIGNAL is set. */
- if (res == SOCKET_ERROR && get_errno () == ESHUTDOWN
- && get_socket_type () == SOCK_STREAM)
- {
- set_errno (EPIPE);
- if (! (flags & MSG_NOSIGNAL))
- raise (SIGPIPE);
+ EPIPE is generated if the local end has been shut down on a connection
+ oriented socket. In this case the process will also receive a SIGPIPE
+ unless MSG_NOSIGNAL is set. */
+ if (get_errno () == ESHUTDOWN && get_socket_type () == SOCK_STREAM)
+ {
+ set_errno (EPIPE);
+ if (! (flags & MSG_NOSIGNAL))
+ raise (SIGPIPE);
+ }
}
return res;
@@ -1467,7 +1486,7 @@ fhandler_socket::sendto (const void *ptr, size_t len, int flags,
the size of the internal send buffer. A buffer full condition
is only recognized in subsequent calls and, if len is big enough,
the call even might fail with an out-of-memory condition. */
- WSABUF wsabuf = { len > 65536 ? 65536 : len, (char *) ptr };
+ WSABUF wsabuf = { len, (char *) ptr };
return send_internal (&wsabuf, 1, flags,
(to ? (const struct sockaddr *) &sst : NULL), tolen);
}
@@ -1487,14 +1506,9 @@ fhandler_socket::sendmsg (const struct msghdr *msg, int flags)
WSABUF wsabuf[msg->msg_iovlen];
WSABUF *wsaptr = wsabuf;
const struct iovec *iovptr = msg->msg_iov;
- size_t total = 0;
- for (int i = 0; i < msg->msg_iovlen && total < 65536; ++i)
+ for (int i = 0; i < msg->msg_iovlen; ++i)
{
- if (total + iovptr->iov_len > 65536) /* See above. */
- wsaptr->len = 65536 - total;
- else
- wsaptr->len = iovptr->iov_len;
- total += wsaptr->len;
+ wsaptr->len = iovptr->iov_len;
(wsaptr++)->buf = (char *) (iovptr++)->iov_base;
}