[pypy-svn] r18901 - in pypy/dist/pypy: module/_socket module/_socket/rpython module/_socket/rpython/test translator/c translator/c/src translator/c/test
afa at codespeak.net
afa at codespeak.net
Tue Oct 25 02:52:08 CEST 2005
Author: afa
Date: Tue Oct 25 02:51:56 2005
New Revision: 18901
Modified:
pypy/dist/pypy/module/_socket/interp_socket.py
pypy/dist/pypy/module/_socket/rpython/exttable.py
pypy/dist/pypy/module/_socket/rpython/ll__socket.py
pypy/dist/pypy/module/_socket/rpython/test/test_ll__socket.py
pypy/dist/pypy/translator/c/extfunc.py
pypy/dist/pypy/translator/c/src/ll__socket.h
pypy/dist/pypy/translator/c/test/test_extfunc.py
Log:
Implemented socket.getaddrinfo()
- Only support for ipv4 addresses
- Hard, because I need 2 structures: an opaque object that works
as an iterator, and a tuple to get each result.
- Each string is IncRef'd twice: in RPyString_FromString, and when inserted
into the tuple. Is there a way to DecRef a rstring from custom C code?
I had to mark the test "in-progress" because of this.
- There must be an easier way. For example, ll__socket.ADDRINFO_RESULT
and exttable.ann_addrinfo should come from a unique source.
Comments are welcome!
- This line, and those below, will be ignored--
M pypy/module/_socket/interp_socket.py
M pypy/module/_socket/rpython/test/test_ll__socket.py
M pypy/module/_socket/rpython/exttable.py
M pypy/module/_socket/rpython/ll__socket.py
M pypy/translator/c/test/test_extfunc.py
M pypy/translator/c/src/ll__socket.h
M pypy/translator/c/extfunc.py
Modified: pypy/dist/pypy/module/_socket/interp_socket.py
==============================================================================
--- pypy/dist/pypy/module/_socket/interp_socket.py (original)
+++ pypy/dist/pypy/module/_socket/interp_socket.py Tue Oct 25 02:51:56 2005
@@ -4,6 +4,7 @@
from pypy.interpreter.error import OperationError
from pypy.interpreter.gateway import W_Root, NoneNotWrapped
from pypy.interpreter.gateway import ObjSpace, interp2app
+from pypy.module._socket.rpython import rsocket
if sys.platform == 'win32':
WIN32_ERROR_MESSAGES = {
@@ -325,25 +326,53 @@
raise wrap_socketerror(space, e)
inet_ntop.unwrap_spec = [ObjSpace, int, str]
+def enumerateaddrinfo(space, addr):
+ result = []
+ while addr.nextinfo():
+ info = (addr.family, addr.socktype, addr.proto,
+ addr.canonname, addr.sockaddr)
+ result.append(space.wrap(info))
+ return space.newlist(result)
+
def getaddrinfo(space, w_host, w_port, family=0, socktype=0, proto=0, flags=0):
"""getaddrinfo(host, port [, family, socktype, proto, flags])
-> list of (family, socktype, proto, canonname, sockaddr)
Resolve host and port into addrinfo struct.
"""
- if space.is_true(space.isinstance(w_host, space.w_unicode)):
- w_host = space.call_method(w_host, "encode", space.wrap("idna"))
- host = space.unwrap(w_host)
+ # host can be None, string or unicode
+ if space.is_w(w_host, space.w_None):
+ host = None
+ elif space.is_true(space.isinstance(w_host, space.w_str)):
+ host = space.str_w(w_host)
+ elif space.is_true(space.isinstance(w_host, space.w_unicode)):
+ w_shost = space.call_method(w_host, "encode", space.wrap("idna"))
+ host = space.str_w(w_shost)
+ else:
+ raise OperationError(space.w_TypeError,
+ space.wrap(
+ "getaddrinfo() argument 1 must be string or None"))
- if space.is_true(space.isinstance(w_port, space.w_int)):
+ # port can be None, int or string
+ if space.is_w(w_port, space.w_None):
+ port = None
+ elif space.is_true(space.isinstance(w_port, space.w_int)):
port = str(space.int_w(w_port))
- else:
+ elif space.is_true(space.isinstance(w_port, space.w_str)):
port = space.str_w(w_port)
+ else:
+ raise OperationError(space.w_TypeError,
+ space.wrap("Int or String expected"))
try:
- return space.wrap(socket.getaddrinfo(host, port, family, socktype, proto, flags))
+ addr = rsocket.getaddrinfo(host, port, family, socktype, proto, flags)
except socket.error, e:
raise wrap_socketerror(space, e)
+
+ try:
+ return enumerateaddrinfo(space, addr)
+ finally:
+ addr.free()
getaddrinfo.unwrap_spec = [ObjSpace, W_Root, W_Root, int, int, int, int]
def getnameinfo(space, w_sockaddr, flags):
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 Tue Oct 25 02:51:56 2005
@@ -3,15 +3,38 @@
"""
import _socket
-from pypy.rpython.extfunctable import declare
+from pypy.module._socket.rpython import rsocket
+from pypy.rpython.extfunctable import declare, declareptrtype
+from pypy.annotation.model import Constant, SomeTuple, SomeList, SomeInteger, SomeString
+from pypy.annotation.listdef import ListDef
+from pypy.annotation.model import unionof
module = 'pypy.module._socket.rpython.ll__socket'
# ____________________________________________________________
# Built-in functions needed in the rtyper
+def ann_addrinfo(*s_args):
+ # Address info is a tuple: (family, socktype, proto, canonname, sockaddr)
+ # where sockaddr is either a 2-tuple or a 4-tuple
+ addrinfo = SomeTuple([SomeInteger(),
+ SomeInteger(),
+ SomeInteger(),
+ SomeString(),
+ SomeString(),
+ SomeInteger(),
+ SomeInteger(),
+ SomeInteger(),
+ ])
+ return addrinfo
+
declare(_socket.gethostname, str, '%s/gethostname' % module)
+declare(rsocket.getaddrinfo, rsocket.ADDRINFO, '%s/getaddrinfo' % module)
+declareptrtype(rsocket.ADDRINFO, "ADDRINFO",
+ nextinfo = (ann_addrinfo, '%s/nextaddrinfo' % module),
+ free = (type(None), '%s/freeaddrinfo' % module))
+
declare(_socket.ntohs, int, '%s/ntohs' % module)
declare(_socket.htons, int, '%s/ntohs' % module)
declare(_socket.ntohl, int, '%s/ntohl' % module)
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 Tue Oct 25 02:51:56 2005
@@ -1,11 +1,58 @@
import _socket
-from pypy.rpython.module.support import to_rstr
+from pypy.rpython.rstr import STR
+from pypy.rpython.lltype import GcStruct, Signed, Array, Char, Ptr, malloc
+from pypy.rpython.module.support import to_rstr, from_rstr
+from pypy.rpython.module.support import to_opaque_object, from_opaque_object
+from pypy.module._socket.rpython import rsocket
def ll__socket_gethostname():
return to_rstr(_socket.gethostname())
ll__socket_gethostname.suggested_primitive = True
+def ll__socket_getaddrinfo(host, port, family, socktype, proto, flags):
+ addr = rsocket.getaddrinfo(from_rstr(host), port,
+ family, socktype, proto, flags)
+ return to_opaque_object(addr)
+ll__socket_getaddrinfo.suggested_primitive = True
+
+
+# XXX The tag and the items names must have the same name as
+# the structure computed from ann_addrinfo
+ADDRINFO_RESULT = GcStruct('tuple8',
+ ('item0', Signed),
+ ('item1', Signed),
+ ('item2', Signed),
+ ('item3', Ptr(STR)),
+ ('item4', Ptr(STR)),
+ ('item5', Signed),
+ ('item6', Signed),
+ ('item7', Signed),
+ )
+
+def ll__socket_addrinfo(family, socktype, proto, canonname,
+ ipaddr, port, flowinfo, scopeid):
+ tup = malloc(ADDRINFO_RESULT)
+ tup.item0 = family
+ tup.item1 = socktype
+ tup.item2 = proto
+ tup.item3 = canonname
+ tup.item4 = ipaddr
+ tup.item5 = port
+ tup.item6 = flowinfo # ipV6
+ tup.item7 = scopeid # ipV6
+ return tup
+
+def ll__socket_nextaddrinfo(opaqueaddr):
+ addr = from_opaque_object(opaqueaddr)
+ return addr.nextinfo()
+ll__socket_nextaddrinfo.suggested_primitive = True
+
+def ll__socket_freeaddrinfo(opaqueaddr):
+ addr = from_opaque_object(opaqueaddr)
+ return addr.free()
+ll__socket_freeaddrinfo.suggested_primitive = True
+
def ll__socket_ntohs(htons):
return _socket.ntohs(htons)
ll__socket_ntohs.suggested_primitive = True
Modified: pypy/dist/pypy/module/_socket/rpython/test/test_ll__socket.py
==============================================================================
--- pypy/dist/pypy/module/_socket/rpython/test/test_ll__socket.py (original)
+++ pypy/dist/pypy/module/_socket/rpython/test/test_ll__socket.py Tue Oct 25 02:51:56 2005
@@ -5,6 +5,7 @@
from pypy.translator.annrpython import RPythonAnnotator
from pypy.rpython.test.test_llinterp import interpret
from pypy.rpython.module.support import from_rstr
+from pypy.rpython.module.support import to_opaque_object, from_opaque_object
def test_ntohs():
def fn():
@@ -19,3 +20,12 @@
a = RPythonAnnotator()
res = interpret(fn, [])
assert from_rstr(res) == _socket.gethostname()
+
+def test_getaddrinfo():
+ host = "localhost"
+ port = 25
+ result = []
+ addr = ll__socket_getaddrinfo(to_rstr(host), port, 0, 0, 0, 0)
+ info = ll__socket_nextaddrinfo(addr)
+ info = info[:4] + (info[4:],)
+ assert info == _socket.getaddrinfo(host, port)[0]
Modified: pypy/dist/pypy/translator/c/extfunc.py
==============================================================================
--- pypy/dist/pypy/translator/c/extfunc.py (original)
+++ pypy/dist/pypy/translator/c/extfunc.py Tue Oct 25 02:51:56 2005
@@ -58,6 +58,9 @@
ll_stack.ll_stack_unwind: 'LL_stack_unwind',
ll_stack.ll_stack_too_big: 'LL_stack_too_big',
ll__socket.ll__socket_gethostname: 'LL__socket_gethostname',
+ ll__socket.ll__socket_getaddrinfo: 'LL__socket_getaddrinfo',
+ ll__socket.ll__socket_nextaddrinfo: 'LL__socket_nextaddrinfo',
+ ll__socket.ll__socket_freeaddrinfo: 'LL__socket_freeaddrinfo',
ll__socket.ll__socket_ntohs: 'LL__socket_ntohs',
ll__socket.ll__socket_htons: 'LL__socket_htons',
ll__socket.ll__socket_htonl: 'LL__socket_htonl',
@@ -85,6 +88,7 @@
yield ('RPyFREXP_RESULT', ll_math.FREXP_RESULT)
yield ('RPyMODF_RESULT', ll_math.MODF_RESULT)
yield ('RPySTAT_RESULT', ll_os.STAT_RESULT)
+ yield ('RPySOCKET_ADDRINFO', ll__socket.ADDRINFO_RESULT)
def predeclare_utility_functions(db, rtyper):
# Common utility functions
@@ -123,6 +127,10 @@
yield annotate(ll_math.ll_modf_result, lltype.Float, lltype.Float)
yield annotate(ll_os.ll_stat_result, *([lltype.Signed] * 10))
+ 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)
+
def predeclare_extfuncs(db, rtyper):
for func, funcobj in db.externalfuncs.items():
c_name = EXTERNALS[func]
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 Tue Oct 25 02:51:56 2005
@@ -9,41 +9,40 @@
int LL__socket_htons(int ntohs);
long LL__socket_ntohl(long htonl);
long LL__socket_htonl(long ntohl);
+struct RPyOpaque_ADDRINFO *LL__socket_getaddrinfo(RPyString *host, RPyString *port,
+ int family, int socktype,
+ int proto, int flags);
+RPySOCKET_ADDRINFO *LL__socket_nextaddrinfo(struct RPyOpaque_ADDRINFO *addr);
#ifndef PYPY_NOT_MAIN_FILE
+#ifdef MS_WINDOWS
+# include <Ws2tcpip.h>
+#endif
int LL__socket_ntohs(int htons)
{
-
return (int)ntohs((short) htons);
-
}
int LL__socket_htons(int ntohs)
{
-
return (int)htons((short) ntohs);
-
}
long LL__socket_ntohl(long htonl)
{
-
return ntohl(htonl);
-
}
long LL__socket_htonl(long ntohl)
{
-
return htonl(ntohl);
-
}
RPyString *LL__socket_gethostname()
{
char buf[1024];
- char *res;
+ int res;
res = gethostname(buf, sizeof buf - 1);
if (res < 0) {
//XXX
@@ -56,4 +55,78 @@
return RPyString_FromString(buf);
}
+struct RPyOpaque_ADDRINFO {
+ struct addrinfo *info0;
+ struct addrinfo *info;
+};
+
+struct RPyOpaque_ADDRINFO *LL__socket_getaddrinfo(RPyString *host, RPyString *port,
+ int family, int socktype,
+ int proto, int flags)
+{
+ struct addrinfo hints;
+ struct addrinfo *res0;
+ struct RPyOpaque_ADDRINFO *addr;
+ int error;
+ char *hptr = RPyString_AsString(host);
+ char *pptr = RPyString_AsString(port);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_socktype = socktype;
+ hints.ai_protocol = proto;
+ hints.ai_flags = flags;
+ error = getaddrinfo(hptr, pptr, &hints, &res0);
+ addr = malloc(sizeof (struct RPyOpaque_ADDRINFO));
+ addr->info0 = res0;
+ addr->info = res0;
+ return addr;
+}
+
+RPyString *makeipaddr(struct sockaddr *addr)
+{
+ char buf[NI_MAXHOST];
+ int error;
+
+ error = getnameinfo(addr, sizeof (struct sockaddr), buf, sizeof(buf), NULL, 0,
+ NI_NUMERICHOST);
+ if (error) {
+ return RPyString_FromString("Error"); // XXX
+ }
+ return RPyString_FromString(buf);
+}
+
+RPySOCKET_ADDRINFO *LL__socket_nextaddrinfo(struct RPyOpaque_ADDRINFO *addr)
+{
+ struct addrinfo *info = addr->info;
+
+ if( !info )
+ return ll__socket_addrinfo(0,0,0,NULL,NULL,0,0,0);
+
+ addr->info = addr->info->ai_next;
+
+ {
+ RPySOCKET_ADDRINFO *ret;
+ struct sockaddr_in *a = (struct sockaddr_in *)info->ai_addr;
+
+ RPyString *canonname = RPyString_FromString(
+ info->ai_canonname?info->ai_canonname:"");
+ RPyString *ipaddr = makeipaddr(info->ai_addr);
+
+ ret = ll__socket_addrinfo(info->ai_family,
+ info->ai_socktype,
+ info->ai_protocol,
+ canonname,
+ ipaddr, // XXX AF_INET Only!
+ ntohs(a->sin_port),0,0);
+ // XXX DECREF(canonname)
+ // XXX DECREF(ipaddr)
+ }
+}
+
+void LL__socket_freeaddrinfo(struct RPyOpaque_ADDRINFO *addr)
+{
+ freeaddrinfo(addr->info0);
+ free(addr2);
+}
#endif
Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_extfunc.py (original)
+++ pypy/dist/pypy/translator/c/test/test_extfunc.py Tue Oct 25 02:51:56 2005
@@ -562,3 +562,24 @@
res = f1()
assert res == _socket.gethostname()
+def test_getaddrinfo():
+ #py.test.skip("In progress")
+ # XXX fails on 'assert mallocs == frees'
+ # needs a way to decref rstrings from ll__socket.h
+ import pypy.module._socket.rpython.exttable # for declare()/declaretype()
+ from pypy.module._socket.rpython import rsocket
+ def does_stuff(host, port):
+ addr = rsocket.getaddrinfo(host, port, 0, 0, 0, 0)
+ result = []
+ while True:
+ info = addr.nextinfo()
+ if info[0] == 0:
+ break
+ result.append("(%d, %d, %d, '%s', ('%s', %d))" %
+ (info[0],info[1],info[2],info[3],info[4],info[5]))
+ addr.free()
+ return str(result)
+ f1 = compile(does_stuff, [str, str])
+ res = f1("localhost", "25")
+ assert eval(res) == _socket.getaddrinfo("localhost", "25")
+
More information about the Pypy-commit
mailing list