Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorConrad Scott <conrad.scott@dsl.pipex.com>2002-09-04 13:55:01 +0400
committerConrad Scott <conrad.scott@dsl.pipex.com>2002-09-04 13:55:01 +0400
commit30db55355e1969ed0c1d7e6376710f4748fb2ff7 (patch)
treea95e9a141ce2dfb9fa70cb82c9ac74eb50bd1375
parent4693b67947f4eb09878f84d6ac5fa0154ee9b807 (diff)
Merged changes from HEAD
-rw-r--r--winsup/cygwin/ChangeLog18
-rw-r--r--winsup/cygwin/fhandler.h8
-rw-r--r--winsup/cygwin/fhandler_socket.cc395
-rw-r--r--winsup/cygwin/net.cc16
4 files changed, 324 insertions, 113 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 62b649679..04bf33a76 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,21 @@
+2002-09-03 Conrad Scott <conrad.scott@dsl.pipex.com>
+
+ * fhandler.h (fhandler_socket::read): Remove method.
+ (fhandler_socket::write): Ditto.
+ (fhandler_socket::readv): New method.
+ (fhandler_socket::writev): Ditto.
+ (fhandler_socket::recvmsg): Add new optional argument.
+ (fhandler_socket::sendmsg): Ditto.
+ * fhandler.cc (fhandler_socket::read): Remove method.
+ (fhandler_socket::write): Ditto.
+ (fhandler_socket::readv): New method.
+ (fhandler_socket::writev): Ditto.
+ (fhandler_socket::recvmsg): Use win32's scatter/gather IO where
+ possible.
+ (fhandler_socket::sendmsg): Ditto.
+ * net.cc (cygwin_recvmsg): Check the msghdr's iovec fields.
+ (cygwin_sendmsg): Ditto. Add omitted sigframe.
+
2002-09-02 Kazuhiro Fujieda <fujieda@jaist.ac.jp>
* cygwin.din: Revert exporting new wchar functions.
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 786c2ad02..a1e530430 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -400,15 +400,15 @@ class fhandler_socket: public fhandler_base
int getsockname (struct sockaddr *name, int *namelen);
int getpeername (struct sockaddr *name, int *namelen);
- int __stdcall read (void *ptr, size_t len) __attribute__ ((regparm (3)));
+ ssize_t readv (const struct iovec *, int iovcnt, ssize_t tot = -1);
int recvfrom (void *ptr, size_t len, int flags,
struct sockaddr *from, int *fromlen);
- int recvmsg (struct msghdr *msg, int flags);
+ int recvmsg (struct msghdr *msg, int flags, ssize_t tot = -1);
- int write (const void *ptr, size_t len);
+ ssize_t writev (const struct iovec *, int iovcnt, ssize_t tot = -1);
int sendto (const void *ptr, size_t len, int flags,
const struct sockaddr *to, int tolen);
- int sendmsg (const struct msghdr *msg, int flags);
+ int sendmsg (const struct msghdr *msg, int flags, ssize_t tot = -1);
int ioctl (unsigned int cmd, void *);
int fcntl (int cmd, void *);
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 94866e3fe..f0a819528 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -660,60 +660,69 @@ fhandler_socket::getpeername (struct sockaddr *name, int *namelen)
return res;
}
-int __stdcall
-fhandler_socket::read (void *ptr, size_t len)
+int
+fhandler_socket::readv (const struct iovec *const iov, const int iovcnt,
+ ssize_t tot)
{
- return recvfrom (ptr, len, 0, NULL, NULL);
+ struct msghdr msg =
+ {
+ msg_name: NULL,
+ msg_namelen: 0,
+ msg_iov: (struct iovec *) iov, // const_cast
+ msg_iovlen: iovcnt,
+ msg_accrights: NULL,
+ msg_accrightslen: 0
+ };
+
+ return recvmsg (&msg, 0, tot);
}
int
fhandler_socket::recvfrom (void *ptr, size_t len, int flags,
struct sockaddr *from, int *fromlen)
{
- int res = -1;
- wsock_event wsock_evt;
- LPWSAOVERLAPPED ovr;
+ int res;
+ DWORD ret;
flags &= MSG_WINMASK;
- if (is_nonblocking () || !(ovr = wsock_evt.prepare ()))
- {
- debug_printf ("Fallback to winsock 1 recvfrom call");
- if ((res = ::recvfrom (get_socket (), (char *) ptr, len, flags, from,
- fromlen))
- == SOCKET_ERROR)
- {
- set_winsock_errno ();
- res = -1;
- }
- }
+ if (!winsock2_active)
+ ret = res = ::recvfrom (get_socket (),
+ (char *) ptr, len, flags,
+ from, fromlen);
else
{
WSABUF wsabuf = { len, (char *) ptr };
- DWORD ret = 0;
- if (WSARecvFrom (get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags,
- from, fromlen, ovr, NULL) != SOCKET_ERROR)
- res = ret;
- else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
+
+ if (is_nonblocking ())
+ res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret, (DWORD *) &flags,
+ from, fromlen,
+ NULL, NULL);
+ else
{
- set_winsock_errno ();
- res = -1;
+ wsock_event wsock_evt;
+ res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret, (DWORD *) &flags,
+ from, fromlen,
+ wsock_evt.prepare (), NULL);
+
+ if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING)
+ ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags);
}
- else if ((res = wsock_evt.wait (get_socket (), (DWORD *)&flags)) == -1)
- set_winsock_errno ();
}
+ if (res == SOCKET_ERROR)
+ {
+ res = -1;
+ set_winsock_errno ();
+ }
+ else
+ res = ret;
+
return res;
}
int
-fhandler_socket::recvmsg (struct msghdr *msg, int flags)
+fhandler_socket::recvmsg (struct msghdr *msg, int flags, ssize_t tot)
{
- int res = -1;
- int nb;
- size_t tot = 0;
- char *buf, *p;
- struct iovec *iov = msg->msg_iov;
-
if (get_addr_family () == AF_LOCAL)
{
/* On AF_LOCAL sockets the (fixed-size) name of the shared memory
@@ -723,120 +732,294 @@ fhandler_socket::recvmsg (struct msghdr *msg, int flags)
special handling for descriptor passing. */
/*TODO*/
}
- for (int i = 0; i < msg->msg_iovlen; ++i)
- tot += iov[i].iov_len;
- buf = (char *) alloca (tot);
- if (tot != 0 && buf == NULL)
+
+ struct iovec *const iov = msg->msg_iov;
+ const int iovcnt = msg->msg_iovlen;
+
+ int res;
+
+ if (!winsock2_active)
{
- set_errno (ENOMEM);
- return -1;
+ if (iovcnt == 1)
+ res = recvfrom (iov->iov_base, iov->iov_len, flags,
+ (struct sockaddr *) msg->msg_name,
+ &msg->msg_namelen);
+ else
+ {
+ if (tot == -1) // i.e. if not pre-calculated by the caller.
+ {
+ tot = 0;
+ const struct iovec *iovptr = iov + iovcnt;
+ do
+ {
+ iovptr -= 1;
+ tot += iovptr->iov_len;
+ }
+ while (iovptr != iov);
+ }
+
+ char *buf = (char *) alloca (tot);
+
+ if (!buf)
+ {
+ set_errno (ENOMEM);
+ res = -1;
+ }
+ else
+ {
+ res = recvfrom (buf, tot, flags,
+ (struct sockaddr *) msg->msg_name,
+ &msg->msg_namelen);
+
+ const struct iovec *iovptr = iov;
+ int nbytes = res;
+
+ while (nbytes > 0)
+ {
+ const int frag = min (nbytes, (ssize_t) iovptr->iov_len);
+ memcpy (iovptr->iov_base, buf, frag);
+ buf += frag;
+ iovptr += 1;
+ nbytes -= frag;
+ }
+ }
+ }
}
- nb = res = recvfrom (buf, tot, flags, (struct sockaddr *) msg->msg_name,
- (int *) &msg->msg_namelen);
- p = buf;
- while (nb > 0)
+ else
{
- ssize_t cnt = iov->iov_len;
- if (nb < cnt)
- cnt = nb;
- memcpy (iov->iov_base, p, cnt);
- p += cnt;
- nb -= cnt;
- ++iov;
+ WSABUF wsabuf[iovcnt];
+
+ {
+ const struct iovec *iovptr = iov + iovcnt;
+ WSABUF *wsaptr = wsabuf + iovcnt;
+ do
+ {
+ iovptr -= 1;
+ wsaptr -= 1;
+ wsaptr->len = iovptr->iov_len;
+ wsaptr->buf = (char *) iovptr->iov_base;
+ }
+ while (wsaptr != wsabuf);
+ }
+
+ DWORD ret;
+
+ if (is_nonblocking ())
+ res = WSARecvFrom (get_socket (),
+ wsabuf, iovcnt, &ret, (DWORD *) &flags,
+ (struct sockaddr *) msg->msg_name,
+ &msg->msg_namelen,
+ NULL, NULL);
+ else
+ {
+ wsock_event wsock_evt;
+ res = WSARecvFrom (get_socket (),
+ wsabuf, iovcnt, &ret, (DWORD *) &flags,
+ (struct sockaddr *) msg->msg_name,
+ &msg->msg_namelen,
+ wsock_evt.prepare (), NULL);
+
+ if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING)
+ ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags);
+ }
+
+ if (res == SOCKET_ERROR)
+ {
+ res = -1;
+ set_winsock_errno ();
+ }
+ else
+ res = ret;
}
+
return res;
}
int
-fhandler_socket::write (const void *ptr, size_t len)
+fhandler_socket::writev (const struct iovec *const iov, const int iovcnt,
+ ssize_t tot)
{
- return sendto (ptr, len, 0, NULL, 0);
+ struct msghdr msg =
+ {
+ msg_name: NULL,
+ msg_namelen: 0,
+ msg_iov: (struct iovec *) iov, // const_cast
+ msg_iovlen: iovcnt,
+ msg_accrights: NULL,
+ msg_accrightslen: 0
+ };
+
+ return sendmsg (&msg, 0, tot);
}
int
fhandler_socket::sendto (const void *ptr, size_t len, int flags,
const struct sockaddr *to, int tolen)
{
- int res = -1;
- wsock_event wsock_evt;
- LPWSAOVERLAPPED ovr;
sockaddr_in sin;
if (to && !get_inet_addr (to, tolen, &sin, &tolen))
return -1;
- if (is_nonblocking () || !(ovr = wsock_evt.prepare ()))
- {
- debug_printf ("Fallback to winsock 1 sendto call");
- if ((res = ::sendto (get_socket (), (const char *) ptr, len,
- flags & MSG_WINMASK,
- (to ? (sockaddr *) &sin : NULL),
- tolen)) == SOCKET_ERROR)
- {
- set_winsock_errno ();
- res = -1;
- }
- }
+ int res;
+ DWORD ret;
+
+ if (!winsock2_active)
+ res = ::sendto (get_socket (), (const char *) ptr, len,
+ flags & MSG_WINMASK,
+ (to ? (const struct sockaddr *) &sin : NULL), tolen);
else
{
WSABUF wsabuf = { len, (char *) ptr };
- DWORD ret = 0;
- if (WSASendTo (get_socket (), &wsabuf, 1, &ret,
- (DWORD)(flags & MSG_WINMASK),
- (to ? (sockaddr *) &sin : NULL),
- tolen,
- ovr, NULL) != SOCKET_ERROR)
- res = ret;
- else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
+
+ if (is_nonblocking ())
+ res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
+ flags & MSG_WINMASK,
+ (to ? (const struct sockaddr *) &sin : NULL), tolen,
+ NULL, NULL);
+ else
{
- set_winsock_errno ();
- res = -1;
+ wsock_event wsock_evt;
+ res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
+ flags & MSG_WINMASK,
+ (to ? (const struct sockaddr *) &sin : NULL), tolen,
+ wsock_evt.prepare (), NULL);
+
+ if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING)
+ ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags);
}
- else if ((res = wsock_evt.wait (get_socket (), (DWORD *)&flags)) == -1)
- set_winsock_errno ();
}
+ if (res == SOCKET_ERROR)
+ {
+ res = -1;
+ set_winsock_errno ();
+ }
+ else
+ res = ret;
+
/* Special handling for SIGPIPE */
- if (get_errno () == ESHUTDOWN)
+ if (res == -1 && get_errno () == ESHUTDOWN)
{
set_errno (EPIPE);
if (! (flags & MSG_NOSIGNAL))
_raise (SIGPIPE);
}
+
return res;
}
int
-fhandler_socket::sendmsg (const struct msghdr *msg, int flags)
+fhandler_socket::sendmsg (const struct msghdr *msg, int flags, ssize_t tot)
{
- size_t tot = 0;
- char *buf, *p;
- struct iovec *iov = msg->msg_iov;
-
- if (get_addr_family () == AF_LOCAL)
- {
- /* For AF_LOCAL/AF_UNIX sockets, if descriptors are given, start
- the special handling for descriptor passing. Otherwise just
- transmit an empty string to tell the receiver that no
- descriptor passing is done. */
+ if (get_addr_family () == AF_LOCAL)
+ {
+ /* For AF_LOCAL/AF_UNIX sockets, if descriptors are given, start
+ the special handling for descriptor passing. Otherwise just
+ transmit an empty string to tell the receiver that no
+ descriptor passing is done. */
/*TODO*/
- }
- for(int i = 0; i < msg->msg_iovlen; ++i)
- tot += iov[i].iov_len;
- buf = (char *) alloca (tot);
- if (tot != 0 && buf == NULL)
- {
- set_errno (ENOMEM);
- return -1;
- }
- p = buf;
- for (int i = 0; i < msg->msg_iovlen; ++i)
+ }
+
+ struct iovec *const iov = msg->msg_iov;
+ const int iovcnt = msg->msg_iovlen;
+
+ int res;
+
+ if (!winsock2_active)
+ {
+ if (iovcnt == 1)
+ res = sendto (iov->iov_base, iov->iov_len, flags,
+ (struct sockaddr *) msg->msg_name,
+ msg->msg_namelen);
+ else
+ {
+ if (tot == -1) // i.e. if not pre-calculated by the caller.
+ {
+ tot = 0;
+ const struct iovec *iovptr = iov + iovcnt;
+ do
+ {
+ iovptr -= 1;
+ tot += iovptr->iov_len;
+ }
+ while (iovptr != iov);
+ }
+
+ char *const buf = (char *) alloca (tot);
+
+ if (!buf)
+ {
+ set_errno (ENOMEM);
+ res = -1;
+ }
+ else
+ {
+ char *bufptr = buf;
+ const struct iovec *iovptr = iov;
+ int nbytes = tot;
+
+ while (nbytes != 0)
+ {
+ const int frag = min (nbytes, (ssize_t) iovptr->iov_len);
+ memcpy (bufptr, iovptr->iov_base, frag);
+ bufptr += frag;
+ iovptr += 1;
+ nbytes -= frag;
+ }
+
+ res = sendto (buf, tot, flags,
+ (struct sockaddr *) msg->msg_name,
+ msg->msg_namelen);
+ }
+ }
+ }
+ else
+ {
+ WSABUF wsabuf[iovcnt];
+
{
- memcpy (p, iov[i].iov_base, iov[i].iov_len);
- p += iov[i].iov_len;
+ const struct iovec *iovptr = iov + iovcnt;
+ WSABUF *wsaptr = wsabuf + iovcnt;
+ do
+ {
+ iovptr -= 1;
+ wsaptr -= 1;
+ wsaptr->len = iovptr->iov_len;
+ wsaptr->buf = (char *) iovptr->iov_base;
+ }
+ while (wsaptr != wsabuf);
}
- return sendto (buf, tot, flags, (struct sockaddr *) msg->msg_name,
- msg->msg_namelen);
+
+ DWORD ret;
+
+ if (is_nonblocking ())
+ res = WSASendTo (get_socket (), wsabuf, iovcnt, &ret, flags,
+ (struct sockaddr *) msg->msg_name,
+ msg->msg_namelen,
+ NULL, NULL);
+ else
+ {
+ wsock_event wsock_evt;
+ res = WSASendTo (get_socket (), wsabuf, iovcnt, &ret, flags,
+ (struct sockaddr *) msg->msg_name,
+ msg->msg_namelen,
+ wsock_evt.prepare (), NULL);
+
+ if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING)
+ ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags);
+ }
+
+ if (res == SOCKET_ERROR)
+ {
+ res = -1;
+ set_winsock_errno ();
+ }
+ else
+ res = ret;
+ }
+
+ return res;
}
int
diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc
index aa52a3cd5..7733d6e78 100644
--- a/winsup/cygwin/net.cc
+++ b/winsup/cygwin/net.cc
@@ -2112,7 +2112,11 @@ cygwin_recvmsg (int fd, struct msghdr *msg, int flags)
|| !fh)
res = -1;
else
- res = fh->recvmsg (msg, flags);
+ {
+ res = check_iovec_for_read (msg->msg_iov, msg->msg_iovlen);
+ if (res > 0)
+ res = fh->recvmsg (msg, flags, res); // res == iovec tot
+ }
syscall_printf ("%d = recvmsg (%d, %p, %x)", res, fd, msg, flags);
return res;
@@ -2123,6 +2127,8 @@ extern "C" int
cygwin_sendmsg (int fd, const struct msghdr *msg, int flags)
{
int res;
+ sigframe thisframe (mainthread);
+
fhandler_socket *fh = get (fd);
if (__check_invalid_read_ptr_errno (msg, sizeof msg)
@@ -2131,8 +2137,12 @@ cygwin_sendmsg (int fd, const struct msghdr *msg, int flags)
(unsigned) msg->msg_namelen))
|| !fh)
res = -1;
- else
- res = fh->sendmsg (msg, flags);
+ else
+ {
+ res = check_iovec_for_write (msg->msg_iov, msg->msg_iovlen);
+ if (res > 0)
+ res = fh->sendmsg (msg, flags, res); // res == iovec tot
+ }
syscall_printf ("%d = sendmsg (%d, %p, %x)", res, fd, msg, flags);
return res;