fix up circular cimports related to the sockaddr type, and touch up endpoint/getaddrinfo a bit
cimport qmsk.net.libc as libc
cimport qmsk.net.py as py
cdef class sockaddr_in (sockaddr) :
def __init__ (self, object addr=None, platform.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)
"""
# zero
libc.memset(&self.sockaddr, 0, sizeof(self.sockaddr))
# store our family
# XXX: this should be a class attribute...
self._init_family(platform.AF_INET)
# constant af
self.sockaddr.sin_family = self.family
# set the sin_port
self.sockaddr.sin_port = platform.htons(port)
if addr :
# set the sin_addr
# this automatically converts the addr from str -> char *
platform.inet_pton(self.family, addr, &self.sockaddr.sin_addr)
else :
# set as INADDR_ANY
self.sockaddr.sin_addr.s_addr = platform.INADDR_ANY
cdef int _get_sockaddr (self, platform.sockaddr **sa_ptr, platform.socklen_t *sa_len) except -1 :
if sa_ptr :
sa_ptr[0] = <platform.sockaddr *> &self.sockaddr
if sa_len :
sa_len[0] = sizeof(self.sockaddr)
return 0
cdef int _set_sockaddr (self, platform.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
>>> sockaddr_in(port=1234).port
1234
"""
def __get__ (self) :
return platform.ntohs(self.sockaddr.sin_port)
def __cmp__ (self, other_obj) :
"""
A sockaddr_in is equal to any other sockaddr_in which has the same addr and port
>>> assert sockaddr_in() == sockaddr_in()
>>> assert sockaddr_in('127.0.0.1', 80) == sockaddr_in('127.0.0.1', 80)
>>> addr = sockaddr_in(); assert addr == addr
"""
if not isinstance(other_obj, sockaddr_in) :
return <object> py.Py_NotImplemented
cdef sockaddr_in other = other_obj
cdef platform.sockaddr_in *sa1 = &self.sockaddr, *sa2 = &other.sockaddr
if other is self :
return 0
return (
libc.memcmp(<void *> &sa1.sin_port, <void *> &sa2.sin_port, sizeof(sa1.sin_port))
or libc.memcmp(<void *> &sa1.sin_addr, <void *> &sa2.sin_addr, sizeof(sa1.sin_addr))
)
def __str__ (self) :
"""
Return the literal ASCII representation for this sockaddr as an '<addr>:<port> string
>>> str(sockaddr_in())
'0.0.0.0:0'
"""
# format
return "%s:%s" % self.getnameinfo()