Commit 46cb270c authored by Xavier Thompson's avatar Xavier Thompson

Implement getaddrinfo

parent 9ec014ff
cdef extern from "<sys/types.h>" nogil:
pass
cdef extern from "<sys/socket.h>" nogil:
ctypedef long socklen_t
ctypedef unsigned short sa_family_t
ctypedef struct sockaddr:
sa_family_t sa_family
char sa_data[14]
ctypedef struct sockaddr_storage:
sa_family_t ss_family
ctypedef struct iovec:
void *iov_base
size_t iov_len
ctypedef struct msghdr:
void *msg_name
socklen_t msg_namelen
iovec *msg_iov
int msg_iovlen
void *msg_control
socklen_t msg_controllen
int msg_flags
ctypedef struct cmsghdr:
socklen_t cmsg_len
int cmsg_level
int cmsg_type
int accept(int, sockaddr *, socklen_t *)
int bind(int, const sockaddr *, socklen_t)
int connect(int, const sockaddr *, socklen_t)
int getpeername(int, sockaddr *, socklen_t *)
int getsockname(int, sockaddr *, socklen_t *)
int getsockopt(int, int, int, void *, socklen_t *)
int listen(int, int)
ssize_t recv(int, void *, size_t, int)
ssize_t recvfrom(int, void *, size_t, int, sockaddr *, socklen_t *)
ssize_t recvmsg(int, msghdr *, int)
ssize_t send(int, const void *, size_t, int)
ssize_t sendmsg(int, const msghdr *, int)
ssize_t sendto(int, const void *, size_t, int, const sockaddr *, socklen_t)
int setsockopt(int, int, int, const void *, socklen_t)
int shutdown(int, int)
int sockatmark(int)
int socket(int, int, int)
int socketpair(int, int, int, int [2])
cdef extern from "<netdb.h>" nogil:
ctypedef struct addrinfo:
int ai_flags
int ai_family
int ai_socktype
int ai_protocol
socklen_t ai_addrlen
sockaddr *ai_addr
char *ai_canonname
addrinfo *ai_next
void freeaddrinfo(addrinfo *)
int getaddrinfo(const char *, const char *, const addrinfo *, addrinfo **)
const char *gai_strerror(int)
cdef extern from "<netinet/in.h>" nogil:
ctypedef struct in_addr:
unsigned long s_addr
ctypedef struct sockaddr_in:
sa_family_t sin_family
unsigned short sin_port
in_addr sin_addr
char sin_zero[8]
ctypedef struct in6_addr:
unsigned char s6_addr[16]
ctypedef struct sockaddr_in6:
sa_family_t sin6_family
unsigned short sin6_port
unsigned long sin6_flowinfo
in6_addr sin6_addr
unsigned long sin6_scope_id
enum: INET6_ADDRSTRLEN
cdef extern from "<arpa/inet.h>" nogil:
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)
int inet_pton(int af, const char *src, void *dst);
cimport stdlib._socket as _socket
from libc.string cimport memset, memcpy
from libc.stdlib cimport malloc, free
from stdlib.string cimport Str
from libcythonplus.list cimport cyplist
cdef extern from "<sys/socket.h>" nogil:
enum: SCM_RIGHTS
enum: SOCK_DGRAM
enum: SOCK_RAW
enum: SOCK_SEQPACKET
enum: SOCK_STREAM
enum: SOL_SOCKET
enum: SO_ACCEPTCONN
enum: SO_BROADCAST
enum: SO_DEBUG
enum: SO_DONTROUTE
enum: SO_ERROR
enum: SO_KEEPALIVE
enum: SO_LINGER
enum: SO_OOBINLINE
enum: SO_RCVBUF
enum: SO_RCVLOWAT
enum: SO_RCVTIMEO
enum: SO_REUSEADDR
enum: SO_SNDBUF
enum: SO_SNDLOWAT
enum: SO_SNDTIMEO
enum: SO_TYPE
enum: SOMAXCONN
enum: MSG_CTRUNC
enum: MSG_DONTROUTE
enum: MSG_EOR
enum: MSG_OOB
enum: MSG_NOSIGNAL
enum: MSG_PEEK
enum: MSG_TRUNC
enum: MSG_WAITALL
enum: AF_INET
enum: AF_INET6
enum: AF_UNIX
enum: AF_UNSPEC
enum: SHUT_RD
enum: SHUT_RDWR
enum: SHUT_WR
cdef extern from "<netdb.h>" nogil:
enum: AI_PASSIVE
enum: AI_CANONNAME
enum: AI_NUMERICHOST
enum: AI_NUMERICSERV
enum: AI_V4MAPPED
enum: AI_ALL
enum: AI_ADDRCONFIG
cdef cypclass Sockaddr:
_socket.sockaddr *addr
_socket.socklen_t addrlen
__init__(self, _socket.sockaddr *addr, _socket.socklen_t addrlen):
cdef _socket.sockaddr *sockaddr
sockaddr = <_socket.sockaddr *> malloc(addrlen)
memcpy(sockaddr, addr, addrlen)
self.addr = sockaddr
self.addrlen = addrlen
__dealloc__(self):
addr = self.addr
self.addr = NULL
free(addr)
Str to_string(self):
cdef _socket.sockaddr_in *ipv4
cdef _socket.sockaddr_in6 *ipv6
cdef void *a
cdef char ip[_socket.INET6_ADDRSTRLEN]
cdef _socket.sa_family_t family
family = self.addr.sa_family
if family == AF_INET:
ipv4 = <_socket.sockaddr_in *>(self.addr)
a = &(ipv4.sin_addr)
elif family == AF_INET6:
ipv6 = <_socket.sockaddr_in6 *>(self.addr)
a = &(ipv6.sin6_addr)
else:
return Str("<unsupported>")
_socket.inet_ntop(family, a, ip, sizeof(ip))
return Str(ip)
cdef cypclass Addrinfo:
int family
int socktype
int protocol
Str canonname
Sockaddr sockaddr
__init__(self, int family, int socktype, int protocol, Str canonname, Sockaddr sockaddr):
self.family = family
self.socktype = socktype
self.protocol = protocol
self.canonname = canonname
self.sockaddr = sockaddr
cdef inline cyplist[Addrinfo] getaddrinfo(Str host, Str port, int family, int socktype, int protocol, int flags) nogil except NULL:
cdef _socket.addrinfo hints
cdef _socket.addrinfo *ai
cdef _socket.addrinfo *p
cdef int status
cdef const char *_host
cdef const char *_port
cdef cyplist[Addrinfo] result
memset(&hints, 0, sizeof(hints))
hints.ai_family = family
hints.ai_socktype = socktype
hints.ai_protocol = protocol
hints.ai_flags = flags
status = _socket.getaddrinfo(Str.to_c_str(host), Str.to_c_str(port), &hints, &ai)
if status:
with gil:
raise OSError(_socket.gai_strerror(status))
result = cyplist[Addrinfo]()
p = ai
while p is not NULL:
result.append(Addrinfo(p.ai_family, p.ai_socktype, p.ai_protocol, NULL, Sockaddr(p.ai_addr, p.ai_addrlen)))
p = p.ai_next
_socket.freeaddrinfo(ai)
return result
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment