diff -r 59bed837c265 -r 10bd48c9b6ce sock/addr.pyx --- a/sock/addr.pyx Sun Aug 16 16:38:44 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,353 +0,0 @@ -""" - Socket addresses -""" - -cimport libc - -from addr cimport * - -cdef class sockaddr : - cdef void _init_family (self, libc.sa_family_t family=libc.AF_UNSPEC) : - self.family = family - - # XXX:use size_t - cdef int _get_sockaddr (self, libc.sockaddr **sa_ptr, libc.socklen_t *sa_len) except -1 : - """ - Get the sockaddr pointer and sockaddr length for this address - """ - - raise NotImplementedError() - - cdef libc.sockaddr* _get_sockaddr_ptr (self) except NULL : - """ - Get the sockaddr pointer - """ - - cdef libc.sockaddr *sa - cdef libc.socklen_t sa_len - - self._get_sockaddr(&sa, &sa_len) - - return sa - - cdef libc.socklen_t _get_sockaddr_len (self) except -1 : - """ - Get the sockaddr len - """ - - cdef libc.sockaddr *sa - cdef libc.socklen_t sa_len - - self._get_sockaddr(&sa, &sa_len) - - return sa_len - - cdef int _set_sockaddr (self, libc.sockaddr *sa, size_t sa_len) except -1 : - """ - Set the sockaddr value for this address; sa_len must match! - """ - - raise NotImplementedError() - - def getnameinfo (self) : - """ - Returns a (host, serv) tuple for this address à la getnameinfo - """ - - cdef libc.sockaddr *sa - cdef libc.socklen_t sa_len - - # XXX: take as args? - cdef int flags = libc.NI_NUMERICHOST | libc.NI_NUMERICSERV - - # get our abstract sockaddr - self._get_sockaddr(&sa, &sa_len) - - # get nice text format - return libc.getnameinfo(sa, sa_len, flags) - - property addr : - """ - The ASCII literal network address - """ - - def __get__ (self) : - """ - Default implmentation using getnameinfo() - """ - - addr, port = self.getnameinfo() - - return addr - - property port : - """ - The integer port number - """ - - def __get__ (self) : - """ - Default implementation using getnameinfo() and int() - """ - - addr, port = self.getnameinfo() - - return int(port) - -cdef class sockaddr_in (sockaddr) : - """ - AF_INET struct sockaddr_in - - >>> sa = sockaddr_in("127.0.0.1", 80) - >>> sa.addr - '127.0.0.1' - >>> sa.port - 80 - >>> str(sa) - '127.0.0.1:80' - >>> str(sockaddr_in()) - '0.0.0.0:0' - """ - - # the struct sockaddr_in - cdef libc.sockaddr_in sockaddr - - def __init__ (self, object addr=None, libc.in_port_t port=0) : - """ - Construct using given literal IPv4 address and TCP/UDP port - - addr - IPv4 address, defaults to INADDR_ANY (0.0.0.0) - port - TCP/UDP port, defaults to 0 (ephemeral) - """ - - # store our family - # XXX: this should be a class attribute... - self._init_family(libc.AF_INET) - - # constant af - self.sockaddr.sin_family = self.family - - # set the sin_port - self.sockaddr.sin_port = libc.htons(port) - - if addr : - # set the sin_addr - # this automatically converts the addr from str -> char * - libc.inet_pton(self.family, addr, &self.sockaddr.sin_addr) - - else : - # set as INADDR_ANY - self.sockaddr.sin_addr.s_addr = libc.INADDR_ANY - - cdef int _get_sockaddr (self, libc.sockaddr **sa_ptr, libc.socklen_t *sa_len) except -1 : - if sa_ptr : - sa_ptr[0] = &self.sockaddr - - if sa_len : - sa_len[0] = sizeof(self.sockaddr) - - return 0 - - cdef int _set_sockaddr (self, libc.sockaddr *sa, size_t sa_len) except -1 : - assert sa_len == sizeof(self.sockaddr) - - libc.memcpy(&self.sockaddr, sa, sa_len) - - property port : - """ - The integer port number - """ - - def __get__ (self) : - return libc.ntohs(self.sockaddr.sin_port) - - def __str__ (self) : - """ - Return the literal ASCII representation for this sockaddr as an ': string - """ - - # format - return "%s:%s" % self.getnameinfo() - -cdef class sockaddr_in6 (sockaddr) : - """ - AF_INET6 struct sockaddr_in6 - - >>> sa6 = sockaddr_in6("::1", 80) - >>> sa6.addr - '::1' - >>> sa6.port - 80 - >>> str(sa6) - '[::1]:80' - >>> str(sockaddr_in6()) - '[::]:0' - """ - - cdef libc.sockaddr_in6 sockaddr - - def __init__ (self, object addr=None, libc.in_port_t port=0) : - """ - Construct using given literal IPv6 address and TCP/UDP port - - addr - IPv6 address, defaults to in6addr_any (::) - port - TCP/UDP port, defaults to 0 (ephemeral) - """ - - # store our family - # XXX: this should be a class attribute... - self._init_family(libc.AF_INET6) - - # constant af - self.sockaddr.sin6_family = self.family - - # set the sin_port - self.sockaddr.sin6_port = libc.htons(port) - - if addr : - # set the sin_addr - # this automatically converts the addr from str -> char * - libc.inet_pton(self.family, addr, &self.sockaddr.sin6_addr) - - else : - # set as INADDR_ANY - self.sockaddr.sin6_addr = libc.in6addr_any - - cdef int _get_sockaddr (self, libc.sockaddr **sa_ptr, libc.socklen_t *sa_len) except -1 : - if sa_ptr : - sa_ptr[0] = &self.sockaddr - - if sa_len : - sa_len[0] = sizeof(self.sockaddr) - - return 0 - - cdef int _set_sockaddr (self, libc.sockaddr *sa, size_t sa_len) except -1 : - assert sa_len == sizeof(self.sockaddr) - - libc.memcpy(&self.sockaddr, sa, sa_len) - - property port : - """ - The integer port number - """ - - def __get__ (self) : - return libc.ntohs(self.sockaddr.sin6_port) - - - def __str__ (self) : - """ - Return the literal ASCII representation for this sockaddr as a '[]: string - """ - - # format - return "[%s]:%s" % self.getnameinfo() - -# mapping of AF -> sockaddr, user-modifyable -SOCKADDR_BY_FAMILY = { - libc.AF_INET: sockaddr_in, - libc.AF_INET6: sockaddr_in6, -} - -# build a sockaddr from the given sockaddr struct, based on sa_family -cdef sockaddr build_sockaddr (libc.sockaddr *sa, size_t sa_len) : - # lookup correct class to use - addr_type = SOCKADDR_BY_FAMILY[sa.sa_family] - - # construct with defaults - cdef sockaddr addr = addr_type() - - # store - addr._set_sockaddr(sa, sa_len) - - return addr - -cdef class addrinfo : - - cdef _init_addrinfo (self, libc.addrinfo *ai) : - #ai.flags = c_ai.ai_flags - self.family = ai.ai_family - self.socktype = ai.ai_socktype - self.protocol = ai.ai_protocol - self.addr = build_sockaddr(ai.ai_addr, ai.ai_addrlen) - self.canonname = ai.ai_canonname if ai.ai_canonname else None - - def __str__ (self) : - return "family=%d, socktype=%d, protocol=%d, addr=%s, canonname=%s" % (self.family, self.socktype, self.protocol, self.addr, self.canonname) - -cdef addrinfo build_addrinfo (libc.addrinfo *c_ai) : - cdef addrinfo ai = addrinfo() - - ai._init_addrinfo(c_ai) - - return ai - -cdef class endpoint : - - def __init__ (self, hostname=None, service=None) : - """ - Construct with the given hostname/service, either of which may be None. - - A hostname of None implies all valid local addresses (with AI_PASSIVE), and a service of None implies an - ephemeral port. - - hostname - the literal address or DNS hostname or anything else that GAI supports - service - the numeric port or service name - """ - - self.hostname = str(hostname) - self.service = str(service) - - cpdef getaddrinfo (self, int family, int socktype, int protocol = 0, int flags = libc.AI_PASSIVE) : - """ - Look up our hostname/service using the given socket parameters, and return a sequence of addrinfo objects. - """ - - # XXX: Cython doesn't support proper compound value literals... - cdef libc.addrinfo hints - - libc.memset(&hints, 0, sizeof(hints)) - hints.ai_flags = flags - hints.ai_family = family - hints.ai_socktype = socktype - hints.ai_protocol = protocol - - cdef libc.addrinfo *res, *r - cdef int err - cdef object ret = [] - - cdef char *hostname = NULL - cdef char *service = NULL - - if self.hostname is not None : - hostname = self.hostname - - if self.service is not None : - service = self.service - - # operate! - err = libc.c_getaddrinfo(hostname, service, &hints, &res) - - try : - if err : - # XXX: raise a GAIError - raise Exception(libc.gai_strerror(err)) - - # gather results - r = res - - while r : - ret.append(build_addrinfo(r)) - - r = r.ai_next - - # ok - return ret - - finally : - libc.c_freeaddrinfo(res) - - def __str__ (self) : - return "hostname=%s, service=%s" % (self.hostname, self.service) -