summaryrefslogtreecommitdiff
path: root/win32/win32.c
diff options
context:
space:
mode:
authorusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-07-24 06:05:29 +0000
committerusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-07-24 06:05:29 +0000
commit8122db83ce2110883ec7e50bcbecbaa16c342fd3 (patch)
tree740d45deb9fcc0bab1f5776b2b160770b120898a /win32/win32.c
parent7b8e78f74701a12aeab0de34a662d0a51610e722 (diff)
* win32/win32.c (rb_w32_socket, rb_w32_socketpair): remember the family
in the high word of socklist value. * win32/win32.c (overlapped_socket_io, recvmsg, sendmsg, setfl): follow above changes. * win32/win32.c (rb_w32_getsockname): set remembered family to the argument when OS's function fails. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36518 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'win32/win32.c')
-rw-r--r--win32/win32.c44
1 files changed, 33 insertions, 11 deletions
diff --git a/win32/win32.c b/win32/win32.c
index 2ef80404f2..f330ee1591 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -663,6 +663,10 @@ StartSockets(void)
NtSocketsInitialized = 1;
}
+#define MAKE_SOCKDATA(af, fl) ((int)((((int)af)<<4)|((fl)&0xFFFF)))
+#define GET_FAMILY(v) ((int)(((v)>>4)&0xFFFF))
+#define GET_FLAGS(v) ((int)((v)&0xFFFF))
+
/* License: Ruby's */
static inline int
socklist_insert(SOCKET sock, int flag)
@@ -2994,16 +2998,31 @@ rb_w32_getpeername(int s, struct sockaddr *addr, int *addrlen)
/* License: Artistic or GPL */
int WSAAPI
-rb_w32_getsockname(int s, struct sockaddr *addr, int *addrlen)
+rb_w32_getsockname(int fd, struct sockaddr *addr, int *addrlen)
{
+ int sock;
int r;
if (!NtSocketsInitialized) {
StartSockets();
}
RUBY_CRITICAL({
- r = getsockname(TO_SOCKET(s), addr, addrlen);
- if (r == SOCKET_ERROR)
- errno = map_errno(WSAGetLastError());
+ sock = TO_SOCKET(fd);
+ r = getsockname(sock, addr, addrlen);
+ if (r == SOCKET_ERROR) {
+ DWORD wsaerror = WSAGetLastError();
+ if (wsaerror == WSAEINVAL) {
+ int flags;
+ if (socklist_lookup(sock, &flags)) {
+ int af = GET_FAMILY(flags);
+ if (af) {
+ memset(addr, 0, *addrlen);
+ addr->sa_family = af;
+ return 0;
+ }
+ }
+ }
+ errno = map_errno(wsaerror);
+ }
});
return r;
}
@@ -3130,7 +3149,7 @@ overlapped_socket_io(BOOL input, int fd, char *buf, int len, int flags,
s = TO_SOCKET(fd);
socklist_lookup(s, &mode);
- if (!cancel_io || (mode & O_NONBLOCK)) {
+ if (!cancel_io || (GET_FLAGS(mode) & O_NONBLOCK)) {
RUBY_CRITICAL({
if (input) {
if (addr && addrlen)
@@ -3281,7 +3300,7 @@ recvmsg(int fd, struct msghdr *msg, int flags)
wsamsg.dwFlags |= flags;
socklist_lookup(s, &mode);
- if (!cancel_io || (mode & O_NONBLOCK)) {
+ if (!cancel_io || (GET_FLAGS(mode) & O_NONBLOCK)) {
RUBY_CRITICAL({
if ((ret = pWSARecvMsg(s, &wsamsg, &len, NULL, NULL)) == SOCKET_ERROR) {
errno = map_errno(WSAGetLastError());
@@ -3338,7 +3357,7 @@ sendmsg(int fd, const struct msghdr *msg, int flags)
msghdr_to_wsamsg(msg, &wsamsg);
socklist_lookup(s, &mode);
- if (!cancel_io || (mode & O_NONBLOCK)) {
+ if (!cancel_io || (GET_FLAGS(mode) & O_NONBLOCK)) {
RUBY_CRITICAL({
if ((ret = pWSASendMsg(s, &wsamsg, flags, &len, NULL, NULL)) == SOCKET_ERROR) {
errno = map_errno(WSAGetLastError());
@@ -3466,7 +3485,7 @@ rb_w32_socket(int af, int type, int protocol)
else {
fd = rb_w32_open_osfhandle(s, O_RDWR|O_BINARY|O_NOINHERIT);
if (fd != -1)
- socklist_insert(s, 0);
+ socklist_insert(s, MAKE_SOCKDATA(af, 0));
else
closesocket(s);
}
@@ -3711,8 +3730,8 @@ rb_w32_socketpair(int af, int type, int protocol, int *sv)
closesocket(pair[1]);
return -1;
}
- socklist_insert(pair[0], 0);
- socklist_insert(pair[1], 0);
+ socklist_insert(pair[0], MAKE_SOCKDATA(af, 0));
+ socklist_insert(pair[1], MAKE_SOCKDATA(af, 0));
return 0;
}
@@ -3749,10 +3768,13 @@ static int
setfl(SOCKET sock, int arg)
{
int ret;
+ int af = 0;
int flag = 0;
u_long ioctlArg;
socklist_lookup(sock, &flag);
+ af = GET_FAMILY(flag);
+ flag = GET_FLAGS(flag);
if (arg & O_NONBLOCK) {
flag |= O_NONBLOCK;
ioctlArg = 1;
@@ -3764,7 +3786,7 @@ setfl(SOCKET sock, int arg)
RUBY_CRITICAL({
ret = ioctlsocket(sock, FIONBIO, &ioctlArg);
if (ret == 0)
- socklist_insert(sock, flag);
+ socklist_insert(sock, MAKE_SOCKDATA(af, flag));
else
errno = map_errno(WSAGetLastError());
});