--- a/qmsk/net/libc.pxd Sun Aug 16 21:54:46 2009 +0300
+++ b/qmsk/net/libc.pxd Sun Aug 16 23:32:00 2009 +0300
@@ -42,6 +42,7 @@
int close (int fd)
cdef extern from "alloca.h" :
+ # XXX: this is unsafe because there is it may fail nastily for allocations that won't fit on the stack - SIGSEGV
void* alloca (size_t size)
cdef extern from "sys/uio.h" :
--- a/qmsk/net/py.pxd Sun Aug 16 21:54:46 2009 +0300
+++ b/qmsk/net/py.pxd Sun Aug 16 23:32:00 2009 +0300
@@ -1,17 +1,25 @@
-cimport qmsk.net.libc as libc
+from qmsk.net.libc cimport ssize_t, errno
cdef extern from "Python.h" :
struct PyObject :
pass
## string stuff
- int PyObject_AsCharBuffer (object obj, char **buf, libc.ssize_t *len) except -1
+ int PyObject_AsCharBuffer (object obj, char **buf, ssize_t *len) except -1
+
+ object PyString_FromStringAndSize (char *v, ssize_t len)
+ char* PyString_AS_STRING (object) except NULL
+ int _PyString_Resize (PyObject **string, ssize_t newsize) except -1
## except setting
PyObject* PyErr_SetFromErrno (PyObject *type)
PyObject *PyExc_OSError
+## custom haxes
+#cdef extern from "_py.c" :
+# object py_string_resize (object string, ssize_t new_size)
+
# raise OSError with errno
# XXX: doesn't do anything with func
cdef int raise_errno (char *func) except -1
--- a/qmsk/net/socket/platform.pxd Sun Aug 16 21:54:46 2009 +0300
+++ b/qmsk/net/socket/platform.pxd Sun Aug 16 23:32:00 2009 +0300
@@ -120,7 +120,7 @@
ssize_t send (int fd, void *buf, size_t n, int flags)
ssize_t recv (int fd, void *buf, size_t n, int flags)
ssize_t sendto (int fd, void *buf, size_t n, int flags, sockaddr *addr, socklen_t addr_len)
- ssize_t recvfrom (int fd, void *buf, size_t n, int flags, sockaddr *addr, socklen_t addr_len)
+ ssize_t recvfrom (int fd, void *buf, size_t n, int flags, sockaddr *addr, socklen_t *addr_len)
ssize_t sendmsg (int fd, msghdr *msg, int flags)
ssize_t recvmsg (int fd, msghdr *msg, int flags)
--- a/qmsk/net/socket/socket.pyx Sun Aug 16 21:54:46 2009 +0300
+++ b/qmsk/net/socket/socket.pyx Sun Aug 16 23:32:00 2009 +0300
@@ -22,6 +22,7 @@
if buf is not None :
# XXX: test that except works right
+ # XXX: this complains about const...
py.PyObject_AsCharBuffer(buf, <char **> buf_ptr, &tmp_len)
# XXX: ensure that this is >= 0
@@ -66,6 +67,13 @@
if self.fd < 0 :
raise_errno('socket')
+ def fileno (self) :
+ """
+ Returns the OS-level file desriptor for this socket as an integer
+ """
+
+ return self.fd
+
def bind (self, sockaddr addr) :
"""
Bind this socket to the given local socket address. The given sockaddr should be of the same or a
@@ -128,19 +136,17 @@
socket must be a connection-based socket (SOCK_STREAM/SOCK_SEQPACKET) and in the passive listening mode
(.listen()).
- This returns a (sock, sockaddr) tuple:
+ This returns a (sock, src_addr) tuple:
sock - the newly created sock, corresponding to the incoming connection
- sockaddr - the remote address of the incoming connection
+ src_addr - the remote address of the incoming connection
"""
# prep the sockaddr that we will return
cdef platform.sockaddr_storage ss
cdef platform.socklen_t ss_len = sizeof(ss)
- cdef socket_t sock_fd
-
# accept()
- sock_fd = platform.accept(self.fd, <platform.sockaddr *> &ss, &ss_len)
+ cdef socket_t sock_fd = platform.accept(self.fd, <platform.sockaddr *> &ss, &ss_len)
if sock_fd < 0 :
raise_errno('accept')
@@ -156,9 +162,9 @@
raise
# prep the new addr
- sock_addr = build_sockaddr(<platform.sockaddr *> &ss, ss_len)
+ cdef sockaddr src_addr = build_sockaddr(<platform.sockaddr *> &ss, ss_len)
- return sock_obj, sock_addr
+ return sock_obj, src_addr
def send (self, object buf, int flags = 0) :
"""
@@ -323,7 +329,131 @@
else :
return ret
+
+ def recv (self, size_t len, int flags = 0) :
+ """
+ Recieve a message, reading and returning at most `len` bytes.
+ len - size of buffer to use for recv
+ flags - (optional) MSG_* flags to use for recv()
+
+ Returns the recieved data as a newly allocated string of the correct length.
+ """
+
+ # alloc a new return str
+ # XXX: len overflow...
+ cdef object str = py.PyString_FromStringAndSize(NULL, len)
+ cdef char *buf = py.PyString_AS_STRING(str)
+
+ # recv()
+ cdef libc.ssize_t ret = platform.recv(self.fd, buf, len, flags)
+
+ if ret < 0 :
+ raise_errno('recv')
+
+ # XXX: figure out how to call _PyString_Resize
+ return str[:ret]
+
+ def recvfrom (self, size_t len, int flags = 0) :
+ """
+ Recieve a message, reading at most `len` bytes, also returning the source address.
+
+ len - size of buffer to use for recv
+ flags - (optional) MSG_* flags to use for recvfrom()
+
+ Returns the recieved data and the source address as a (buf, src_addr) tuple :
+ buf - a newly allocated string containing the recieved data, of the correct length
+ src_addr - the source address the message was recieved from
+ """
+
+ # alloc a new return str
+ # XXX: len overflow...
+ cdef object str = py.PyString_FromStringAndSize(NULL, len)
+ cdef char *buf = py.PyString_AS_STRING(str)
+
+ # prep the sockaddr that we will return
+ cdef platform.sockaddr_storage ss
+ cdef platform.socklen_t ss_len = sizeof(ss)
+
+ # recvfrom()
+ cdef libc.ssize_t ret = platform.recvfrom(self.fd, buf, len, flags, <platform.sockaddr *> &ss, &ss_len)
+
+ if ret < 0 :
+ raise_errno('recv')
+
+ # prep the new addr
+ cdef sock_addr = build_sockaddr(<platform.sockaddr *> &ss, ss_len)
+
+ # XXX: figure out how to call _PyString_Resize
+ return str[:ret], sock_addr
+
+ def recvmsg (self, bint recv_addr = True, object iov_lens = None, size_t control_len = 0, int flags = 0) :
+ """
+ Recieve a message along with some extra data.
+
+ recv_addr - ask for and return a sockaddr for the source address of the message?
+ lenv - (optional) sequence of buffer sizes to use for the message data iov
+ control_len - (optional) amount of auxiliary data to recieve
+ flags - (optional) flags to pass to recvmsg()
+
+ Returns a (name, iov, control, flags) tuple :
+ name - the source address of the message, or None
+ iov - sequence of strings containing the recieved data, each at most lenv[x] bytes long
+ control - string containing recieved control message, if any
+ flags - recieved flags
+ """
+
+ cdef platform.msghdr msg
+
+ libc.memset(&msg, 0, sizeof(msg))
+
+ # prep the sockaddr that we will return
+ cdef platform.sockaddr_storage ss
+
+ # ask for a name?
+ if recv_addr :
+ msg.msg_name = <void *> &ss
+ msg.msg_namelen = sizeof(ss)
+
+ # build iov?
+ if iov_lens :
+ # XXX: implement
+ pass
+
+ # build control buffer?
+ if control_len :
+ # XXX: implement
+ pass
+
+ # recvmsg()
+ cdef libc.ssize_t ret = platform.recvmsg(self.fd, &msg, flags)
+
+ if ret < 0 :
+ raise_errno('recvmsg')
+
+ # name?
+ cdef sockaddr name = None
+
+ if msg.msg_name and msg.msg_namelen :
+ name = build_sockaddr(<platform.sockaddr *> msg.msg_name, msg.msg_namelen)
+
+ # iov?
+ cdef object iov = None
+
+ if ret :
+ assert msg.msg_iov and msg.msg_iovlen
+
+ # XXX: implement
+ pass
+
+ # control?
+ cdef object control = None
+
+ if msg.msg_control and msg.msg_controllen :
+ # XXX: implement
+ pass
+
+ return name, iov, control, msg.msg_flags
def shutdown (self, how) :
"""