* 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>
* 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 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 *);

View File

@ -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)
}
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];
{
set_errno (ENOMEM);
return -1;
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);
}
p = buf;
for (int i = 0; i < msg->msg_iovlen; ++i)
{
memcpy (p, iov[i].iov_base, iov[i].iov_len);
p += iov[i].iov_len;
}
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

View File

@ -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;