Author: Amaury Forgeot d'Arc <[email protected]>
Branch:
Changeset: r60499:ea8199da498f
Date: 2013-01-25 22:58 +0100
http://bitbucket.org/pypy/pypy/changeset/ea8199da498f/
Log: Add a cross-platform rsocket.dup(), which also works on win32. py3k
needs it, but it's not exposed in any way on 2.7.
diff --git a/rpython/rlib/_rsocket_rffi.py b/rpython/rlib/_rsocket_rffi.py
--- a/rpython/rlib/_rsocket_rffi.py
+++ b/rpython/rlib/_rsocket_rffi.py
@@ -343,6 +343,12 @@
('iErrorCode', rffi.CFixedArray(rffi.INT, 10)), #FD_MAX_EVENTS
])
+ CConfig.WSAPROTOCOL_INFO = platform.Struct(
+ 'struct WSAPROTOCOL_INFO',
+ []) # Struct is just passed between functions
+ CConfig.FROM_PROTOCOL_INFO = platform.DefinedConstantInteger(
+ 'FROM_PROTOCOL_INFO')
+
CConfig.timeval = platform.Struct('struct timeval',
[('tv_sec', rffi.LONG),
('tv_usec', rffi.LONG)])
@@ -602,6 +608,18 @@
rffi.INT)
tcp_keepalive = cConfig.tcp_keepalive
+ WSAPROTOCOL_INFO = cConfig.WSAPROTOCOL_INFO
+ FROM_PROTOCOL_INFO = cConfig.FROM_PROTOCOL_INFO
+ WSADuplicateSocket = external('WSADuplicateSocket',
+ [socketfd_type, rwin32.DWORD,
+ lltype.Ptr(WSAPROTOCOL_INFO)],
+ rffi.INT)
+ WSASocket = external('WSASocket',
+ [rffi.INT, rffi.INT, rffi.INT,
+ lltype.Ptr(WSAPROTOCOL_INFO),
+ rffi.DWORD, rffi.DWORD],
+ socketfd_type)
+
if WIN32:
WSAData = cConfig.WSAData
WSAStartup = external('WSAStartup', [rffi.INT, lltype.Ptr(WSAData)],
diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py
--- a/rpython/rlib/rsocket.py
+++ b/rpython/rlib/rsocket.py
@@ -1044,7 +1044,21 @@
return (make_socket(fd0, family, type, proto, SocketClass),
make_socket(fd1, family, type, proto, SocketClass))
-if hasattr(_c, 'dup'):
+if _c.WIN32:
+ def dup(fd):
+ with lltype.scoped_alloc(_c.WSAData, zero=True) as info:
+ if _c.WSADuplicateSocket(fd, rwin32.GetCurrentProcessId(), info):
+ raise last_error()
+ result = _c.WSASocket(
+ _c.FROM_PROTOCOL_INFO, _c.FROM_PROTOCOL_INFO,
+ _c.FROM_PROTOCOL_INFO, info, 0, 0)
+ if result == INVALID_SOCKET:
+ raise last_error()
+ return result
+else:
+ def dup(fd):
+ return _c.dup(fd)
+
def fromfd(fd, family, type, proto=0, SocketClass=RSocket):
# Dup the fd so it and the socket can be closed independently
fd = _c.dup(fd)
diff --git a/rpython/rlib/test/test_rsocket.py
b/rpython/rlib/test/test_rsocket.py
--- a/rpython/rlib/test/test_rsocket.py
+++ b/rpython/rlib/test/test_rsocket.py
@@ -373,6 +373,15 @@
assert s.fd != s2.fd
assert s.getsockname().eq(s2.getsockname())
+def test_c_dup():
+ # rsocket.dup() duplicates fd, it also works on Windows
+ # (but only on socket handles!)
+ s = RSocket(AF_INET, SOCK_STREAM)
+ s.setsockopt_int(SOL_SOCKET, SO_REUSEADDR, 1)
+ s.bind(INETAddress('localhost', 50007))
+ fd2 = dup(s.fd)
+ assert s.fd != fd2
+
def test_inet_aton():
assert inet_aton('1.2.3.4') == '\x01\x02\x03\x04'
assert inet_aton('127.0.0.1') == '\x7f\x00\x00\x01'
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit