[pypy-svn] r20938 - in pypy/dist/pypy: module/_socket/rpython module/_socket/test translator/c translator/c/src translator/c/test

nik at codespeak.net nik at codespeak.net
Fri Dec 9 15:32:16 CET 2005


Author: nik
Date: Fri Dec  9 15:32:12 2005
New Revision: 20938

Modified:
   pypy/dist/pypy/module/_socket/rpython/exttable.py
   pypy/dist/pypy/module/_socket/rpython/ll__socket.py
   pypy/dist/pypy/module/_socket/rpython/rsocket.py
   pypy/dist/pypy/module/_socket/test/test_socket2.py
   pypy/dist/pypy/translator/c/extfunc.py
   pypy/dist/pypy/translator/c/src/ll__socket.h
   pypy/dist/pypy/translator/c/test/test_ext__socket.py
Log:
(ale, nik)
low-level implementation of socket.connect() and socket.getpeername(). intermediate
checkin for changing machines.


Modified: pypy/dist/pypy/module/_socket/rpython/exttable.py
==============================================================================
--- pypy/dist/pypy/module/_socket/rpython/exttable.py	(original)
+++ pypy/dist/pypy/module/_socket/rpython/exttable.py	Fri Dec  9 15:32:12 2005
@@ -5,7 +5,7 @@
 import _socket
 from pypy.module._socket.rpython import rsocket
 from pypy.rpython.extfunctable import declare, declaretype, declareptrtype
-from pypy.rpython.extfunctable import standardexceptions
+from pypy.rpython.extfunctable import standardexceptions, noneannotation
 from pypy.annotation.model import SomeTuple, SomeInteger, SomeString
 from pypy.annotation import classdef
 
@@ -28,6 +28,9 @@
                           ])
     return addrinfo
 
+def ann_sockname(*args):
+    return SomeTuple([SomeString(), SomeInteger(), SomeInteger(), SomeInteger()])
+
 declare(_socket.gethostname, str, '%s/gethostname' % module)
 declare(_socket.gethostbyname, str, '%s/gethostbyname' % module)
 
@@ -42,6 +45,9 @@
 declare(_socket.htonl, int, '%s/htonl' % module)
 
 declare(rsocket.newsocket, int, '%s/newsocket' % module)
+declare(rsocket.connect, noneannotation, '%s/connect' % module)
+declare(rsocket.getpeername, ann_sockname, '%s/getpeername' % module)
+declare(rsocket.freesockname, noneannotation, '%s/freesockname' % module)
 
 # ____________________________________________________________
 # _socket.error can be raised by the above

Modified: pypy/dist/pypy/module/_socket/rpython/ll__socket.py
==============================================================================
--- pypy/dist/pypy/module/_socket/rpython/ll__socket.py	(original)
+++ pypy/dist/pypy/module/_socket/rpython/ll__socket.py	Fri Dec  9 15:32:12 2005
@@ -34,6 +34,13 @@
                            ('item7', Signed),
                            )
 
+SOCKNAME = GcStruct('tuple4',
+                           ('item0', Ptr(STR)),
+                           ('item1', Signed),
+                           ('item2', Signed),
+                           ('item3', Signed),
+                           )
+
 def ll__socket_addrinfo(family, socktype, proto, canonname,
                         ipaddr, port, flowinfo, scopeid):
     tup = malloc(ADDRINFO_RESULT)
@@ -47,6 +54,14 @@
     tup.item7 = scopeid   # ipV6
     return tup
 
+def ll__socket_sockname(host, port, flowinfo, scopeid):
+    tup = malloc(SOCKNAME)
+    tup.item0 = host
+    tup.item1 = port
+    tup.item2 = flowinfo  # ipV6
+    tup.item3 = scopeid   # ipV6
+    return tup
+
 def ll__socket_nextaddrinfo(opaqueaddr):
     addr = from_opaque_object(opaqueaddr)
     return addr.nextinfo()
@@ -73,9 +88,21 @@
     return _socket.ntohl(htonl)
 ll__socket_ntohl.suggested_primitive = True
 
+# Can't actually create socket objects in these ll helpers because they are
+# turned into flowgraphs at some point, and that fails on SocketType.__init__.
+
 def ll__socket_newsocket(family, type, protocol):
-#    from pypy.module._socket.rpython import rsocket
-#    return rsocket.newsocket(family, type, protocol).fileno()
     return 0
 ll__socket_newsocket.suggested_primitive = True
 
+def ll__socket_connect(fd, host, port):
+    return None
+ll__socket_connect.suggested_primitive = True
+
+def ll__socket_getpeername(fd):
+    return ("", 0, 0, 0)
+ll__socket_getpeername.suggested_primitive = True
+
+def ll__socket_freesockname(sockname):
+    return None
+ll__socket_freesockname.suggested_primitive = True

Modified: pypy/dist/pypy/module/_socket/rpython/rsocket.py
==============================================================================
--- pypy/dist/pypy/module/_socket/rpython/rsocket.py	(original)
+++ pypy/dist/pypy/module/_socket/rpython/rsocket.py	Fri Dec  9 15:32:12 2005
@@ -52,3 +52,5 @@
     s = socket_cache[fd]
     return s.getpeername()
 
+def freesockname(sockname):
+    pass

Modified: pypy/dist/pypy/module/_socket/test/test_socket2.py
==============================================================================
--- pypy/dist/pypy/module/_socket/test/test_socket2.py	(original)
+++ pypy/dist/pypy/module/_socket/test/test_socket2.py	Fri Dec  9 15:32:12 2005
@@ -315,6 +315,8 @@
         raises(TypeError, s.connect, args)
     s.close()
 
+# XXX also need tests for other connection and timeout errors
+
 
 class AppTestSocket:
     def setup_class(cls):

Modified: pypy/dist/pypy/translator/c/extfunc.py
==============================================================================
--- pypy/dist/pypy/translator/c/extfunc.py	(original)
+++ pypy/dist/pypy/translator/c/extfunc.py	Fri Dec  9 15:32:12 2005
@@ -67,6 +67,9 @@
     ll__socket.ll__socket_htonl: 'LL__socket_htonl',
     ll__socket.ll__socket_ntohl: 'LL__socket_htonl',
     ll__socket.ll__socket_newsocket: 'LL__socket_newsocket',
+    ll__socket.ll__socket_connect: 'LL__socket_connect',
+    ll__socket.ll__socket_getpeername: 'LL__socket_getpeername',
+    ll__socket.ll__socket_freesockname: 'LL__socket_freesockname',
     }
 
 #______________________________________________________
@@ -91,6 +94,7 @@
     yield ('RPyMODF_RESULT', ll_math.MODF_RESULT)
     yield ('RPySTAT_RESULT', ll_os.STAT_RESULT)
     yield ('RPySOCKET_ADDRINFO', ll__socket.ADDRINFO_RESULT)
+    yield ('RPySOCKET_SOCKNAME', ll__socket.SOCKNAME)
 
 def predeclare_utility_functions(db, rtyper):
     # Common utility functions
@@ -132,6 +136,8 @@
     args = [lltype.Signed, lltype.Signed, lltype.Signed, lltype.Ptr(STR),
             lltype.Ptr(STR), lltype.Signed, lltype.Signed, lltype.Signed]
     yield annotate(ll__socket.ll__socket_addrinfo, *args)
+    args = [lltype.Ptr(STR), lltype.Signed, lltype.Signed, lltype.Signed]
+    yield annotate(ll__socket.ll__socket_sockname, *args)
 
 def predeclare_extfuncs(db, rtyper):
     modules = {}

Modified: pypy/dist/pypy/translator/c/src/ll__socket.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/ll__socket.h	(original)
+++ pypy/dist/pypy/translator/c/src/ll__socket.h	Fri Dec  9 15:32:12 2005
@@ -77,6 +77,8 @@
     return htonl(ntohl);
 }
 
+// XXX Check what should be done threading-wise around blocking system calls
+
 int LL__socket_newsocket(int family, int type, int protocol)
 {
     int fd;
@@ -95,6 +97,43 @@
         RPYTHON_RAISE_OSERROR(errno);
     }
 }
+
+void LL__socket_connect(int fd, RPyString *host, int port)
+{
+    struct sockaddr_in addr;
+    
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons((short)port);
+    if (setipaddr(RPyString_AsString(host), (struct sockaddr *) &addr,
+		      sizeof(addr), AF_INET) < 0) {
+        // XXX raise some error here 
+    }
+    if (connect(fd, &addr, sizeof(addr)) < 0) {
+        // XXX raise some error here
+    }
+}
+
+RPySOCKET_SOCKNAME *LL__socket_getpeername(int fd)
+{
+    struct sockaddr_in addr; // XXX IPv4 only
+    int addr_len;
+    RPySOCKET_SOCKNAME* sockname;
+    RPyString* host;
+    
+    memset((void *) &addr, '\0', sizeof(addr));
+    if (getpeername(fd, (struct sockaddr *) &addr, &addr_len) < 0) {
+        // XXX raise some error
+    }
+    
+    host = RPyString_FromString(inet_ntoa(addr.sin_addr));
+    return ll__socket_sockname(host, addr.sin_port, 0, 0);
+}
+
+void LL__socket_freesockname(RPySOCKET_SOCKNAME *sockname)
+{
+	free(sockname);
+}
+
 /* ____________________________________________________________________________ */
 
 /* Lock to allow python interpreter to continue, but only allow one

Modified: pypy/dist/pypy/translator/c/test/test_ext__socket.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_ext__socket.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_ext__socket.py	Fri Dec  9 15:32:12 2005
@@ -89,3 +89,16 @@
     f1 = compile(does_stuff, [int, int, int])
     for args in tests:
         py.test.raises(OSError, f1, *args)
+
+def test_connect():
+    from pypy.module._socket.rpython import rsocket
+    def does_stuff():
+        fd = rsocket.newsocket(_socket.AF_INET, _socket.SOCK_STREAM, 0)
+        # XXX need to think of a test without connecting to outside servers
+        rsocket.connect(fd, "codespeak.net", 80)
+        sockname = rsocket.getpeername(fd)
+        port = sockname[1]
+        rsocket.freesockname(sockname)
+        return port
+    f1 = compile(does_stuff, [])
+    assert f1() == 80



More information about the Pypy-commit mailing list