* 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.
This commit is contained in:
Corinna Vinschen 2002-09-04 09:39:35 +00:00
parent 3573883f9d
commit 4d147a03bd
4 changed files with 324 additions and 113 deletions

View File

@ -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> 2002-09-02 Kazuhiro Fujieda <fujieda@jaist.ac.jp>
* cygwin.din: Revert exporting new wchar functions. * cygwin.din: Revert exporting new wchar functions.

View File

@ -400,15 +400,15 @@ class fhandler_socket: public fhandler_base
int getsockname (struct sockaddr *name, int *namelen); int getsockname (struct sockaddr *name, int *namelen);
int getpeername (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, int recvfrom (void *ptr, size_t len, int flags,
struct sockaddr *from, int *fromlen); 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, int sendto (const void *ptr, size_t len, int flags,
const struct sockaddr *to, int tolen); 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 ioctl (unsigned int cmd, void *);
int fcntl (int cmd, void *); int fcntl (int cmd, void *);

View File

@ -660,60 +660,69 @@ fhandler_socket::getpeername (struct sockaddr *name, int *namelen)
return res; return res;
} }
int __stdcall int
fhandler_socket::read (void *ptr, size_t len) 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 int
fhandler_socket::recvfrom (void *ptr, size_t len, int flags, fhandler_socket::recvfrom (void *ptr, size_t len, int flags,
struct sockaddr *from, int *fromlen) struct sockaddr *from, int *fromlen)
{ {
int res = -1; int res;
wsock_event wsock_evt; DWORD ret;
LPWSAOVERLAPPED ovr;
flags &= MSG_WINMASK; flags &= MSG_WINMASK;
if (is_nonblocking () || !(ovr = wsock_evt.prepare ())) if (!winsock2_active)
{ ret = res = ::recvfrom (get_socket (),
debug_printf ("Fallback to winsock 1 recvfrom call"); (char *) ptr, len, flags,
if ((res = ::recvfrom (get_socket (), (char *) ptr, len, flags, from, from, fromlen);
fromlen))
== SOCKET_ERROR)
{
set_winsock_errno ();
res = -1;
}
}
else else
{ {
WSABUF wsabuf = { len, (char *) ptr }; WSABUF wsabuf = { len, (char *) ptr };
DWORD ret = 0;
if (WSARecvFrom (get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags, if (is_nonblocking ())
from, fromlen, ovr, NULL) != SOCKET_ERROR) res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret, (DWORD *) &flags,
res = ret; from, fromlen,
else if ((res = WSAGetLastError ()) != WSA_IO_PENDING) NULL, NULL);
else
{ {
set_winsock_errno (); wsock_event wsock_evt;
res = -1; 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; return res;
} }
int 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) if (get_addr_family () == AF_LOCAL)
{ {
/* On AF_LOCAL sockets the (fixed-size) name of the shared memory /* 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. */ special handling for descriptor passing. */
/*TODO*/ /*TODO*/
} }
for (int i = 0; i < msg->msg_iovlen; ++i)
tot += iov[i].iov_len; struct iovec *const iov = msg->msg_iov;
buf = (char *) alloca (tot); const int iovcnt = msg->msg_iovlen;
if (tot != 0 && buf == NULL)
int res;
if (!winsock2_active)
{ {
set_errno (ENOMEM); if (iovcnt == 1)
return -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, else
(int *) &msg->msg_namelen);
p = buf;
while (nb > 0)
{ {
ssize_t cnt = iov->iov_len; WSABUF wsabuf[iovcnt];
if (nb < cnt)
cnt = nb; {
memcpy (iov->iov_base, p, cnt); const struct iovec *iovptr = iov + iovcnt;
p += cnt; WSABUF *wsaptr = wsabuf + iovcnt;
nb -= cnt; do
++iov; {
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; return res;
} }
int 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 int
fhandler_socket::sendto (const void *ptr, size_t len, int flags, fhandler_socket::sendto (const void *ptr, size_t len, int flags,
const struct sockaddr *to, int tolen) const struct sockaddr *to, int tolen)
{ {
int res = -1;
wsock_event wsock_evt;
LPWSAOVERLAPPED ovr;
sockaddr_in sin; sockaddr_in sin;
if (to && !get_inet_addr (to, tolen, &sin, &tolen)) if (to && !get_inet_addr (to, tolen, &sin, &tolen))
return -1; return -1;
if (is_nonblocking () || !(ovr = wsock_evt.prepare ())) int res;
{ DWORD ret;
debug_printf ("Fallback to winsock 1 sendto call");
if ((res = ::sendto (get_socket (), (const char *) ptr, len, if (!winsock2_active)
flags & MSG_WINMASK, res = ::sendto (get_socket (), (const char *) ptr, len,
(to ? (sockaddr *) &sin : NULL), flags & MSG_WINMASK,
tolen)) == SOCKET_ERROR) (to ? (const struct sockaddr *) &sin : NULL), tolen);
{
set_winsock_errno ();
res = -1;
}
}
else else
{ {
WSABUF wsabuf = { len, (char *) ptr }; WSABUF wsabuf = { len, (char *) ptr };
DWORD ret = 0;
if (WSASendTo (get_socket (), &wsabuf, 1, &ret, if (is_nonblocking ())
(DWORD)(flags & MSG_WINMASK), res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
(to ? (sockaddr *) &sin : NULL), flags & MSG_WINMASK,
tolen, (to ? (const struct sockaddr *) &sin : NULL), tolen,
ovr, NULL) != SOCKET_ERROR) NULL, NULL);
res = ret; else
else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
{ {
set_winsock_errno (); wsock_event wsock_evt;
res = -1; 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 */ /* Special handling for SIGPIPE */
if (get_errno () == ESHUTDOWN) if (res == -1 && get_errno () == ESHUTDOWN)
{ {
set_errno (EPIPE); set_errno (EPIPE);
if (! (flags & MSG_NOSIGNAL)) if (! (flags & MSG_NOSIGNAL))
_raise (SIGPIPE); _raise (SIGPIPE);
} }
return res; return res;
} }
int 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; if (get_addr_family () == AF_LOCAL)
char *buf, *p; {
struct iovec *iov = msg->msg_iov; /* For AF_LOCAL/AF_UNIX sockets, if descriptors are given, start
the special handling for descriptor passing. Otherwise just
if (get_addr_family () == AF_LOCAL) transmit an empty string to tell the receiver that no
{ descriptor passing is done. */
/* 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*/ /*TODO*/
} }
for(int i = 0; i < msg->msg_iovlen; ++i)
tot += iov[i].iov_len; struct iovec *const iov = msg->msg_iov;
buf = (char *) alloca (tot); const int iovcnt = msg->msg_iovlen;
if (tot != 0 && buf == NULL)
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];
{ {
set_errno (ENOMEM); const struct iovec *iovptr = iov + iovcnt;
return -1; WSABUF *wsaptr = wsabuf + iovcnt;
do
{
iovptr -= 1;
wsaptr -= 1;
wsaptr->len = iovptr->iov_len;
wsaptr->buf = (char *) iovptr->iov_base;
}
while (wsaptr != wsabuf);
} }
p = buf;
for (int i = 0; i < msg->msg_iovlen; ++i) DWORD ret;
{
memcpy (p, iov[i].iov_base, iov[i].iov_len); if (is_nonblocking ())
p += iov[i].iov_len; res = WSASendTo (get_socket (), wsabuf, iovcnt, &ret, flags,
} (struct sockaddr *) msg->msg_name,
return sendto (buf, tot, flags, (struct sockaddr *) msg->msg_name, msg->msg_namelen,
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 int

View File

@ -2112,7 +2112,11 @@ cygwin_recvmsg (int fd, struct msghdr *msg, int flags)
|| !fh) || !fh)
res = -1; res = -1;
else 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); syscall_printf ("%d = recvmsg (%d, %p, %x)", res, fd, msg, flags);
return res; return res;
@ -2123,6 +2127,8 @@ extern "C" int
cygwin_sendmsg (int fd, const struct msghdr *msg, int flags) cygwin_sendmsg (int fd, const struct msghdr *msg, int flags)
{ {
int res; int res;
sigframe thisframe (mainthread);
fhandler_socket *fh = get (fd); fhandler_socket *fh = get (fd);
if (__check_invalid_read_ptr_errno (msg, sizeof msg) 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)) (unsigned) msg->msg_namelen))
|| !fh) || !fh)
res = -1; res = -1;
else else
res = fh->sendmsg (msg, flags); {
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); syscall_printf ("%d = sendmsg (%d, %p, %x)", res, fd, msg, flags);
return res; return res;