mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* win32/win32.[ch] (recvmsg, sendmsg): new functions to support recvmsg/
sendmsg like UNIX. these functions are experimental and not tested well. bug reports are welcome. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@24218 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
3f0308dbf1
commit
9dd0d27156
3 changed files with 229 additions and 1 deletions
|
@ -1,3 +1,9 @@
|
|||
Tue Jul 21 13:36:20 2009 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||
|
||||
* win32/win32.[ch] (recvmsg, sendmsg): new functions to support recvmsg/
|
||||
sendmsg like UNIX. these functions are experimental and not tested
|
||||
well. bug reports are welcome.
|
||||
|
||||
Tue Jul 21 13:35:21 2009 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||
|
||||
* win32/Makefile.sub (TEST_RUNNABLE): follow r24209.
|
||||
|
|
|
@ -203,6 +203,21 @@ struct timezone {
|
|||
#undef isascii
|
||||
#define isascii __isascii
|
||||
#endif
|
||||
|
||||
struct iovec {
|
||||
void *iov_base;
|
||||
size_t iov_len;
|
||||
};
|
||||
struct msghdr {
|
||||
void *msg_name;
|
||||
int msg_namelen;
|
||||
struct iovec *msg_iov;
|
||||
int msg_iovlen;
|
||||
void *msg_control;
|
||||
int msg_controllen;
|
||||
int msg_flags;
|
||||
};
|
||||
|
||||
#define NtInitialize ruby_sysinit
|
||||
extern int rb_w32_cmdvector(const char *, char ***);
|
||||
extern rb_pid_t rb_w32_pipe_exec(const char *, const char *, int, int *, int *);
|
||||
|
@ -224,6 +239,8 @@ extern int WSAAPI rb_w32_recv(int, char *, int, int);
|
|||
extern int WSAAPI rb_w32_recvfrom(int, char *, int, int, struct sockaddr *, int *);
|
||||
extern int WSAAPI rb_w32_send(int, const char *, int, int);
|
||||
extern int WSAAPI rb_w32_sendto(int, const char *, int, int, const struct sockaddr *, int);
|
||||
extern int recvmsg(int, struct msghdr *, int);
|
||||
extern int sendmsg(int, const struct msghdr *, int);
|
||||
extern int WSAAPI rb_w32_setsockopt(int, int, int, const char *, int);
|
||||
extern int WSAAPI rb_w32_shutdown(int, int);
|
||||
extern int WSAAPI rb_w32_socket(int, int, int);
|
||||
|
|
207
win32/win32.c
207
win32/win32.c
|
@ -2770,7 +2770,7 @@ overlapped_socket_io(BOOL input, int fd, char *buf, int len, int flags,
|
|||
}
|
||||
/* thru */
|
||||
default:
|
||||
errno = map_errno(err);
|
||||
errno = map_errno(WSAGetLastError());
|
||||
/* thru */
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
/* interrupted */
|
||||
|
@ -2816,6 +2816,211 @@ rb_w32_sendto(int fd, const char *buf, int len, int flags,
|
|||
(struct sockaddr *)to, &tolen);
|
||||
}
|
||||
|
||||
#ifndef WSAID_WSARECVMSG
|
||||
typedef struct {
|
||||
SOCKADDR *name;
|
||||
int namelen;
|
||||
WSABUF *lpBuffers;
|
||||
DWORD dwBufferCount;
|
||||
WSABUF Control;
|
||||
DWORD dwFlags;
|
||||
} WSAMSG;
|
||||
#define WSAID_WSARECVMSG {0xf689d7c8,0x6f1f,0x436b,{0x8a,0x53,0xe5,0x4f,0xe3,0x51,0xc3,0x22}}
|
||||
#endif
|
||||
#ifndef WSAID_WSASENDMSG
|
||||
#define WSAID_WSASENDMSG {0xa441e712,0x754f,0x43ca,{0x84,0xa7,0x0d,0xee,0x44,0xcf,0x60,0x6d}}
|
||||
#endif
|
||||
|
||||
#define msghdr_to_wsamsg(msg, wsamsg) \
|
||||
do { \
|
||||
int i; \
|
||||
(wsamsg)->name = (msg)->msg_name; \
|
||||
(wsamsg)->namelen = (msg)->msg_namelen; \
|
||||
(wsamsg)->lpBuffers = ALLOCA_N(WSABUF, (msg)->msg_iovlen); \
|
||||
(wsamsg)->dwBufferCount = (msg)->msg_iovlen; \
|
||||
for (i = 0; i < (msg)->msg_iovlen; ++i) { \
|
||||
(wsamsg)->lpBuffers[i].buf = (msg)->msg_iov[i].iov_base; \
|
||||
(wsamsg)->lpBuffers[i].len = (msg)->msg_iov[i].iov_len; \
|
||||
} \
|
||||
(wsamsg)->Control.buf = (msg)->msg_control; \
|
||||
(wsamsg)->Control.len = (msg)->msg_controllen; \
|
||||
(wsamsg)->dwFlags = (msg)->msg_flags; \
|
||||
} while (0)
|
||||
|
||||
int
|
||||
recvmsg(int fd, struct msghdr *msg, int flags)
|
||||
{
|
||||
typedef int (WSAAPI *WSARecvMsg_t)(SOCKET, WSAMSG *, DWORD *, WSAOVERLAPPED *, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
|
||||
static WSARecvMsg_t pWSARecvMsg = NULL;
|
||||
WSAMSG wsamsg;
|
||||
SOCKET s;
|
||||
st_data_t data;
|
||||
int mode;
|
||||
DWORD len;
|
||||
int ret;
|
||||
|
||||
if (!NtSocketsInitialized)
|
||||
StartSockets();
|
||||
|
||||
s = TO_SOCKET(fd);
|
||||
|
||||
if (!pWSARecvMsg) {
|
||||
static GUID guid = WSAID_WSARECVMSG;
|
||||
DWORD dmy;
|
||||
WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
|
||||
&pWSARecvMsg, sizeof(pWSARecvMsg), &dmy, NULL, NULL);
|
||||
if (!pWSARecvMsg)
|
||||
rb_notimplement();
|
||||
}
|
||||
|
||||
msghdr_to_wsamsg(msg, &wsamsg);
|
||||
wsamsg.dwFlags |= flags;
|
||||
|
||||
st_lookup(socklist, (st_data_t)s, &data);
|
||||
mode = (int)data;
|
||||
if (!cancel_io || (mode & O_NONBLOCK)) {
|
||||
RUBY_CRITICAL({
|
||||
if ((ret = pWSARecvMsg(s, &wsamsg, &len, NULL, NULL)) == SOCKET_ERROR) {
|
||||
errno = map_errno(WSAGetLastError());
|
||||
len = -1;
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
DWORD size;
|
||||
int err;
|
||||
WSAOVERLAPPED wol;
|
||||
memset(&wol, 0, sizeof(wol));
|
||||
RUBY_CRITICAL({
|
||||
wol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
ret = pWSARecvMsg(s, &wsamsg, &len, &wol, NULL);
|
||||
});
|
||||
|
||||
if (ret != SOCKET_ERROR) {
|
||||
/* nothing to do */
|
||||
}
|
||||
else if ((err = WSAGetLastError()) == WSA_IO_PENDING) {
|
||||
DWORD flg;
|
||||
switch (rb_w32_wait_events_blocking(&wol.hEvent, 1, INFINITE)) {
|
||||
case WAIT_OBJECT_0:
|
||||
RUBY_CRITICAL(
|
||||
ret = WSAGetOverlappedResult(s, &wol, &size, TRUE, &flg)
|
||||
);
|
||||
if (ret) {
|
||||
len = size;
|
||||
break;
|
||||
}
|
||||
/* thru */
|
||||
default:
|
||||
errno = map_errno(WSAGetLastError());
|
||||
/* thru */
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
/* interrupted */
|
||||
len = -1;
|
||||
cancel_io((HANDLE)s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
errno = map_errno(err);
|
||||
len = -1;
|
||||
}
|
||||
CloseHandle(&wol.hEvent);
|
||||
}
|
||||
if (ret == SOCKET_ERROR)
|
||||
return -1;
|
||||
|
||||
/* WSAMSG to msghdr */
|
||||
msg->msg_name = wsamsg.name;
|
||||
msg->msg_namelen = wsamsg.namelen;
|
||||
msg->msg_flags = wsamsg.dwFlags;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
sendmsg(int fd, const struct msghdr *msg, int flags)
|
||||
{
|
||||
typedef int (WSAAPI *WSASendMsg_t)(SOCKET, const WSAMSG *, DWORD, DWORD *, WSAOVERLAPPED *, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
|
||||
static WSASendMsg_t pWSASendMsg = NULL;
|
||||
WSAMSG wsamsg;
|
||||
SOCKET s;
|
||||
st_data_t data;
|
||||
int mode;
|
||||
DWORD len;
|
||||
int ret;
|
||||
|
||||
if (!NtSocketsInitialized)
|
||||
StartSockets();
|
||||
|
||||
s = TO_SOCKET(fd);
|
||||
|
||||
if (!pWSASendMsg) {
|
||||
static GUID guid = WSAID_WSASENDMSG;
|
||||
DWORD dmy;
|
||||
WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
|
||||
&pWSASendMsg, sizeof(pWSASendMsg), &dmy, NULL, NULL);
|
||||
if (!pWSASendMsg)
|
||||
rb_notimplement();
|
||||
}
|
||||
|
||||
msghdr_to_wsamsg(msg, &wsamsg);
|
||||
|
||||
st_lookup(socklist, (st_data_t)s, &data);
|
||||
mode = (int)data;
|
||||
if (!cancel_io || (mode & O_NONBLOCK)) {
|
||||
RUBY_CRITICAL({
|
||||
if ((ret = pWSASendMsg(s, &wsamsg, flags, &len, NULL, NULL)) == SOCKET_ERROR) {
|
||||
errno = map_errno(WSAGetLastError());
|
||||
len = -1;
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
DWORD size;
|
||||
int err;
|
||||
WSAOVERLAPPED wol;
|
||||
memset(&wol, 0, sizeof(wol));
|
||||
RUBY_CRITICAL({
|
||||
wol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
ret = pWSASendMsg(s, &wsamsg, flags, &len, &wol, NULL);
|
||||
});
|
||||
|
||||
if (ret != SOCKET_ERROR) {
|
||||
/* nothing to do */
|
||||
}
|
||||
else if ((err = WSAGetLastError()) == WSA_IO_PENDING) {
|
||||
DWORD flg;
|
||||
switch (rb_w32_wait_events_blocking(&wol.hEvent, 1, INFINITE)) {
|
||||
case WAIT_OBJECT_0:
|
||||
RUBY_CRITICAL(
|
||||
ret = WSAGetOverlappedResult(s, &wol, &size, TRUE, &flg)
|
||||
);
|
||||
if (ret) {
|
||||
len = size;
|
||||
break;
|
||||
}
|
||||
/* thru */
|
||||
default:
|
||||
errno = map_errno(WSAGetLastError());
|
||||
/* thru */
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
/* interrupted */
|
||||
len = -1;
|
||||
cancel_io((HANDLE)s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
errno = map_errno(err);
|
||||
len = -1;
|
||||
}
|
||||
CloseHandle(&wol.hEvent);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
#undef setsockopt
|
||||
|
||||
int WSAAPI
|
||||
|
|
Loading…
Add table
Reference in a new issue