Author: Dodan Mihai <[email protected]>
Branch: py3.5-sendmsg-recvmsg
Changeset: r91915:4396f9d022d5
Date: 2017-07-18 11:25 +0300
http://bitbucket.org/pypy/pypy/changeset/4396f9d022d5/

Log:    Sendmsg and recvmsg implemented. Some test fail. Some mem leaks

diff --git a/pypy/module/_socket/__init__.py b/pypy/module/_socket/__init__.py
--- a/pypy/module/_socket/__init__.py
+++ b/pypy/module/_socket/__init__.py
@@ -34,6 +34,7 @@
             ntohs ntohl htons htonl inet_aton inet_ntoa inet_pton inet_ntop
             getaddrinfo getnameinfo
             getdefaulttimeout setdefaulttimeout
+            CMSG_SPACE CMSG_LEN
             """.split():
 
             if (name in ('inet_pton', 'inet_ntop', 'socketpair') and
diff --git a/pypy/module/_socket/interp_func.py 
b/pypy/module/_socket/interp_func.py
--- a/pypy/module/_socket/interp_func.py
+++ b/pypy/module/_socket/interp_func.py
@@ -327,6 +327,28 @@
             for (family, socktype, protocol, canonname, addr) in lst]
     return space.newlist(lst1)
 
+@unwrap_spec(size=int)
+def CMSG_SPACE(space, size):
+    if size < 0:
+        raise oefmt(space.w_OverflowError,
+                    "CMSG_SPACE() argument out of range")
+    retval = rsocket.CMSG_SPACE(size)
+    if retval == 0:
+        raise oefmt(space.w_OverflowError,
+                    "CMSG_SPACE() argument out of range")
+    return space.newint(retval)
+
+@unwrap_spec(len=int)
+def CMSG_LEN(space, len):
+    if len < 0:
+        raise oefmt(space.w_OverflowError,
+                    "CMSG_LEN() argument out of range")
+    retval = rsocket.CMSG_LEN(len)
+    if retval == 0:
+        raise oefmt(space.w_OverflowError,
+                    "CMSG_LEN() argument out of range")
+    return space.newint(retval)
+
 def getdefaulttimeout(space):
     """getdefaulttimeout() -> timeout
 
diff --git a/pypy/module/_socket/interp_socket.py 
b/pypy/module/_socket/interp_socket.py
--- a/pypy/module/_socket/interp_socket.py
+++ b/pypy/module/_socket/interp_socket.py
@@ -285,6 +285,8 @@
         except SocketError as e:
             raise converted_error(space, e)
 
+
+
     def close_w(self, space):
         """close()
 
@@ -446,6 +448,38 @@
                 converted_error(space, e, eintr_retry=True)
         return space.newtuple([space.newbytes(data), w_addr])
 
+    @unwrap_spec(message_size=int, ancbufsize=int, flags=int)
+    def recvmsg_w(self,space,message_size, ancbufsize = 0, flags = 0):
+        if (message_size < 0):
+            raise oefmt(space.w_ValueError, "negative buffer size in 
recvmsg()")
+        if ancbufsize < 0:
+            raise oefmt(space.w_ValueError, "invalid ancillary data buffer 
length")
+        try:
+            tuple = self.sock.recvmsg(message_size, ancbufsize, flags)
+            message = space.newbytes(tuple[0])
+            # print(tuple[0])
+            list = []
+            for l in tuple[1]:
+                tup = space.newtuple([space.newint(l[0]), space.newint(l[1]), 
space.newbytes(l[2])])
+                list.append(tup)
+
+            anc = space.newlist(list)
+
+            flag = space.newint(tuple[2])
+            if (tuple[3] is not None):
+                address = addr_as_object(tuple[3], self.sock.fd, space)
+            else:
+                address = space.w_None
+
+            rettup = space.newtuple([message, anc, flag, address])
+            return rettup
+        except SocketError as e:
+            converted_error(space, e, eintr_retry=True)
+
+
+
+
+
     @unwrap_spec(data='bufferstr', flags=int)
     def send_w(self, space, data, flags=0):
         """send(data[, flags]) -> count
@@ -501,6 +535,110 @@
                 converted_error(space, e, eintr_retry=True)
         return space.newint(count)
 
+    #@unwrap_spec(data='bufferstr', flags = int)
+    def sendmsg_w(self, space, w_data, w_ancillary=None, w_flags=None 
,w_address=None):
+        """sendmsg(messages, [ancillaries, [flags, [address]]])
+        """
+        flags = 0
+        if space.is_none(w_flags) is False:
+            flags = space.int_w(w_flags)
+
+        address = None
+        if space.is_none(w_address) is False:
+            address = self.addr_from_object(space, w_address)
+
+        data = []
+        if (w_data.typedef.name == 'list'):
+            for i in w_data.getitems():
+                if space.isinstance_w(i,space.w_bytes):
+                    data.append(space.bytes_w(i))
+                else:
+                    if (i.typedef.name == 'array.array'):
+                        data.append(space.bytes_w(i.descr_tobytes(space)))
+                    else:
+                        raise oefmt(space.w_TypeError, "a bytes-like object is 
required")
+        else:
+            while True:
+                try:
+                    if (space.is_generator(w_data) is False):
+                        raise oefmt(space.w_TypeError, "sendmsg(): argument 1 
must be iterable")
+                    i = space.next(w_data)
+                    if space.isinstance_w(i, space.w_bytes):
+                        data.append(space.bytes_w(i))
+                    else:
+                        if (i.typedef.name == 'array.array'):
+                            data.append(space.bytes_w(i.descr_tobytes(space)))
+                        else:
+                            raise oefmt(space.w_TypeError, "a bytes-like 
object is required")
+                except OperationError as e:
+                    if not e.match(space,space.w_StopIteration):
+                        raise
+                    break
+        ancillary = []
+
+        if w_ancillary is not None:
+            if (space.isinstance_w(w_ancillary,space.w_list)):
+                for i in w_ancillary.getitems():
+                    if (space.isinstance_w(i, space.w_tuple) is False):
+                        raise oefmt(space.w_TypeError,"[sendmsg() ancillary 
data items]() argument must be sequence")
+                    if (space.len_w(i) == 3):
+                        level = space.int_w(space.getitem(i, space.newint(0)))
+                        type = space.int_w(space.getitem(i, space.newint(1)))
+                        if (space.getitem(i, space.newint(2)).typedef.name == 
'array.array'):
+                            cont = space.bytes_w(space.getitem(i, 
space.newint(2)).descr_tobytes(space))
+                        else:
+                            if (space.isinstance_w(space.getitem(i, 
space.newint(2)), space.w_bytes)):
+                                cont = space.bytes_w(space.getitem(i, 
space.newint(2)))
+                            else:
+                                raise oefmt(space.w_TypeError,"a bytes-like 
object is required")
+                        tup = (level, type, cont)
+                        ancillary.append(tup)
+                    else:
+                        raise oefmt(space.w_TypeError,"[sendmsg() ancillary 
data items]() argument must be sequence of length 3")
+
+            else:
+                while True:
+                    try:
+                        if (space.is_generator(w_ancillary) is False):
+                            raise oefmt(space.w_TypeError,"[sendmsg() 
ancillary data items]() argument must be sequence")
+                        i = space.next(w_ancillary)
+                        if (space.isinstance_w(i, space.w_tuple) is False):
+                            raise oefmt(space.w_TypeError,
+                                        "[sendmsg() ancillary data items]() 
argument must be sequence of length 3")
+                        if (space.len_w(i) != 3):
+                            raise oefmt(space.w_TypeError,"[sendmsg() 
ancillary data items]() argument must be sequence of length 3")
+                    except OperationError as e:
+                        if not e.match(space,space.w_StopIteration):
+                            raise
+                        break
+                    level = space.int_w(space.getitem(i, space.newint(0)))
+                    type = space.int_w(space.getitem(i, space.newint(1)))
+                    if (space.getitem(i, space.newint(2)).typedef.name == 
'array.array'):
+                        cont = space.bytes_w(space.getitem(i, 
space.newint(2)).descr_tobytes(space))
+                    else:
+                        if (space.isinstance_w(space.getitem(i, 
space.newint(2)), space.w_bytes)):
+                            cont = space.bytes_w(space.getitem(i, 
space.newint(2)))
+                        else:
+                            raise oefmt(space.w_TypeError, "a bytes-like 
object is required")
+                    tup = (level, type, cont)
+                    ancillary.append(tup)
+
+        try:
+            count = self.sock.sendmsg(data, ancillary, flags, address)
+            if count < 0:
+                if (count == -1000):
+                    raise oefmt(space.w_OSError, "sending multiple control 
messages not supported")
+                if (count == -1001):
+                    raise oefmt(space.w_OSError, "ancillary data item too 
large")
+                if (count == -1002):
+                    raise oefmt(space.w_OSError, "too much ancillary data")
+
+            return space.newint(count)
+        except SocketError as e:
+            converted_error(space, e, eintr_retry=True)
+
+
+
     @unwrap_spec(flag=int)
     def setblocking_w(self, flag):
         """setblocking(flag)
@@ -772,7 +910,7 @@
 socketmethodnames = """
 _accept bind close connect connect_ex fileno detach
 getpeername getsockname getsockopt gettimeout listen
-recv recvfrom send sendall sendto setblocking
+recv recvfrom recvmsg send sendall sendto sendmsg setblocking
 setsockopt settimeout shutdown _reuse _drop recv_into recvfrom_into
 """.split()
 if hasattr(rsocket._c, 'WSAIoctl'):
@@ -813,6 +951,8 @@
 sendall(data[, flags]) -- send all data
 send(data[, flags]) -- send data, may not send all of it
 sendto(data[, flags], addr) -- send data to a given address
+sendmsg(messages[, ancillary[, flags[, address]]]) -- send data and ancillary 
payload in a packet. May specifiy flags or the address
+recvmsg(message_size,[ ancillary_size,[ flags]]) -- receive data and ancillary 
payload. Return a tup of message, ancdata, flags and address
 setblocking(0 | 1) -- set or clear the blocking I/O flag
 setsockopt(level, optname, value) -- set socket options
 settimeout(None | float) -- set or clear the timeout
diff --git a/rpython/rlib/_rsocket_rffi.py b/rpython/rlib/_rsocket_rffi.py
--- a/rpython/rlib/_rsocket_rffi.py
+++ b/rpython/rlib/_rsocket_rffi.py
@@ -2,6 +2,7 @@
 from rpython.rtyper.lltypesystem import lltype
 from rpython.rtyper.tool import rffi_platform as platform
 from rpython.rtyper.lltypesystem.rffi import CCHARP
+from rpython.rlib import jit
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
 from rpython.translator.platform import platform as target_platform
 
@@ -190,6 +191,8 @@
 
 IPX_TYPE
 
+SCM_RIGHTS
+
 POLLIN POLLPRI POLLOUT POLLERR POLLHUP POLLNVAL
 POLLRDNORM POLLRDBAND POLLWRNORM POLLWEBAND POLLMSG
 
@@ -260,6 +263,7 @@
 sockaddr_ptr = lltype.Ptr(lltype.ForwardReference())
 addrinfo_ptr = lltype.Ptr(lltype.ForwardReference())
 
+
 # struct types
 CConfig.sockaddr = platform.Struct('struct sockaddr',
                                              [('sa_family', rffi.INT),
@@ -343,6 +347,675 @@
                                 [('ifr_ifindex', rffi.INT),
                                  ('ifr_name', rffi.CFixedArray(rffi.CHAR, 8))])
 
+# insert handler for sendmsg / recvmsg here
+if _POSIX:
+    includes = ['stddef.h',
+                'sys/socket.h',
+                'unistd.h',
+                'string.h',
+                'stdlib.h',
+                'errno.h',
+                'limits.h',
+                'stdio.h',
+                'sys/types.h']
+    separate_module_sources = ['''
+
+        //defines for recvmsg
+        #define SUCCESS 0
+        #define BAD_MSG_SIZE_GIVEN -1
+        #define BAD_ANC_SIZE_GIVEN -2
+        #define WOULD_BLOCK -3
+        #define AGAIN -4
+        #define BADDESC -5
+        #define CON_REF -6
+        #define FAULT -7
+        #define INTR -8
+        #define NOMEM -9
+        #define NOTCONN -10
+        #define NOTSOCK -11
+        #define MAL_ANC -12
+
+        //defines for sendmsg
+        #define MUL_MSGS_NOT_SUP -1000
+        #define ANC_DATA_TOO_LARGE -1001
+        #define ANC_DATA_TOO_LARGEX -1002
+
+        #define MSG_IOVLEN 1 // CPyhton has hardcoded this as well.
+        #if INT_MAX > 0x7fffffff
+            #define SOCKLEN_T_LIMIT 0x7fffffff
+        #else
+        #define SOCKLEN_T_LIMIT INT_MAX
+        #endif
+
+
+        #ifdef CMSG_SPACE
+        static int
+        cmsg_min_space(struct msghdr *msg, struct cmsghdr *cmsgh, size_t space)
+        {
+            size_t cmsg_offset;
+            static const size_t cmsg_len_end = (offsetof(struct cmsghdr, 
cmsg_len) +
+                                                sizeof(cmsgh->cmsg_len));
+
+            /* Note that POSIX allows msg_controllen to be of signed type. */
+            if (cmsgh == NULL || msg->msg_control == NULL)
+                return 0;
+            /* Note that POSIX allows msg_controllen to be of a signed type. 
This is
+               annoying under OS X as it's unsigned there and so it triggers a
+               tautological comparison warning under Clang when compared 
against 0.
+               Since the check is valid on other platforms, silence the 
warning under
+               Clang. */
+            #ifdef __clang__
+            #pragma clang diagnostic push
+            #pragma clang diagnostic ignored "-Wtautological-compare"
+            #endif
+            #if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && 
(__GNUC_MINOR__ > 5)))
+            #pragma GCC diagnostic push
+            #pragma GCC diagnostic ignored "-Wtype-limits"
+            #endif
+            if (msg->msg_controllen < 0)
+                return 0;
+            #if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && 
(__GNUC_MINOR__ > 5)))
+            #pragma GCC diagnostic pop
+            #endif
+            #ifdef __clang__
+            #pragma clang diagnostic pop
+            #endif
+            if (space < cmsg_len_end)
+                space = cmsg_len_end;
+            cmsg_offset = (char *)cmsgh - (char *)msg->msg_control;
+            return (cmsg_offset <= (size_t)-1 - space &&
+                    cmsg_offset + space <= msg->msg_controllen);
+        }
+        #endif
+
+        #ifdef CMSG_LEN
+
+        /* If pointer CMSG_DATA(cmsgh) is in buffer msg->msg_control, set
+           *space to number of bytes following it in the buffer and return
+           true; otherwise, return false.  Assumes cmsgh, msg->msg_control and
+           msg->msg_controllen are valid. */
+        static int
+        get_cmsg_data_space(struct msghdr *msg, struct cmsghdr *cmsgh, size_t 
*space)
+        {
+            size_t data_offset;
+            char *data_ptr;
+
+            if ((data_ptr = (char *)CMSG_DATA(cmsgh)) == NULL)
+                return 0;
+            data_offset = data_ptr - (char *)msg->msg_control;
+            if (data_offset > msg->msg_controllen)
+                return 0;
+            *space = msg->msg_controllen - data_offset;
+            return 1;
+        }
+
+        /* If cmsgh is invalid or not contained in the buffer pointed to by
+           msg->msg_control, return -1.  If cmsgh is valid and its associated
+           data is entirely contained in the buffer, set *data_len to the
+           length of the associated data and return 0.  If only part of the
+           associated data is contained in the buffer but cmsgh is otherwise
+           valid, set *data_len to the length contained in the buffer and
+           return 1. */
+        static int
+        get_cmsg_data_len(struct msghdr *msg, struct cmsghdr *cmsgh, size_t 
*data_len)
+        {
+            size_t space, cmsg_data_len;
+
+            if (!cmsg_min_space(msg, cmsgh, CMSG_LEN(0)) ||
+                cmsgh->cmsg_len < CMSG_LEN(0))
+                return -1;
+            cmsg_data_len = cmsgh->cmsg_len - CMSG_LEN(0);
+            if (!get_cmsg_data_space(msg, cmsgh, &space))
+                return -1;
+            if (space >= cmsg_data_len) {
+                *data_len = cmsg_data_len;
+                return 0;
+            }
+            *data_len = space;
+            return 1;
+        }
+        #endif    /* CMSG_LEN */
+
+        struct recvmsg_info
+        {
+            int error_code;
+            struct sockaddr* address;
+            socklen_t addrlen;
+            int* length_of_messages;
+            char** messages;
+            int no_of_messages;
+            int size_of_ancillary;
+            int* levels;
+            int* types;
+            char** file_descr;
+            int* descr_per_ancillary;
+            int flags;
+        };
+
+
+        RPY_EXTERN
+        int recvmsg_implementation(
+                                  int socket_fd,
+                                  int message_size,
+                                  int ancillary_size,
+                                  int flags,
+                                  struct sockaddr* address,
+                                  socklen_t* addrlen,
+                                  int** length_of_messages,
+                                  char** messages,
+                                  int* no_of_messages,
+                                  int* size_of_ancillary,
+                                  int** levels,
+                                  int** types,
+                                  char** file_descr,
+                                  int** descr_per_ancillary,
+                                  int* flag)
+
+        {
+
+            struct sockaddr* recvd_address;
+            socklen_t recvd_addrlen;
+            struct msghdr msg = {0};
+            void *controlbuf = NULL;
+            struct cmsghdr *cmsgh;
+            int cmsg_status;
+            struct iovec iov;
+            struct recvmsg_info* retinfo;
+            int error_flag;
+            int cmsgdatalen = 0;
+
+            //allocation flags for failure
+            int iov_alloc = 0;
+            int anc_alloc = 0;
+
+            retinfo = (struct recvmsg_info*) malloc(sizeof(struct 
recvmsg_info));
+            /*
+            if (message_size < 0){
+                error_flag = BAD_MSG_SIZE_GIVEN;
+                goto fail;
+            }
+            */
+            if (ancillary_size > SOCKLEN_T_LIMIT){
+                error_flag = BAD_ANC_SIZE_GIVEN;
+                goto fail;
+            }
+
+
+            iov.iov_base = (char*) malloc(message_size);
+            memset(iov.iov_base, 0, message_size);
+            iov.iov_len = message_size;
+            controlbuf = malloc(ancillary_size);
+            recvd_addrlen = sizeof(struct sockaddr);
+            recvd_address = (struct sockaddr*) malloc(recvd_addrlen);
+
+            memset(recvd_address, 0,recvd_addrlen);
+
+            msg.msg_name = recvd_address;
+            msg.msg_namelen = recvd_addrlen;
+            msg.msg_iov = &iov;
+            msg.msg_iovlen = MSG_IOVLEN;
+            msg.msg_control = controlbuf;
+            msg.msg_controllen = ancillary_size;
+
+            retinfo->address = msg.msg_name;
+            retinfo->length_of_messages = (int*) malloc (MSG_IOVLEN * 
sizeof(int));
+            retinfo->no_of_messages = 1;
+            retinfo->messages = (char**) malloc (MSG_IOVLEN * sizeof(char*));
+            retinfo->messages[0] = msg.msg_iov->iov_base;
+
+            iov_alloc = 1;
+
+            ssize_t bytes_recvd = 0;
+
+            bytes_recvd = recvmsg(socket_fd, &msg, flags);
+
+            if (bytes_recvd < 0){
+                switch (errno){
+                    case EAGAIN:
+                        error_flag = -3;
+                        break;
+                    case EBADF:
+                        error_flag = -5;
+                        break;
+                    case ECONNREFUSED:
+                        error_flag = -6;
+                        break;
+                    case EFAULT:
+                        error_flag = -7;
+                        break;
+                    case EINTR:
+                        error_flag = -8;
+                        break;
+                    case ENOMEM:
+                        error_flag = -9;
+                        break;
+                    case ENOTCONN:
+                        error_flag = -10;
+                        break;
+                    case ENOTSOCK:
+                        error_flag = -11;
+                        break;
+                 }
+
+                 goto fail;
+            }
+
+            retinfo->addrlen = (socklen_t) msg.msg_namelen;
+            retinfo->length_of_messages[0] = msg.msg_iov->iov_len;
+
+
+            int anc_counter = 0;
+            /*
+            struct recv_list* first_item = (struct recv_list*) 
malloc(sizeof(struct recv_list));
+            struct recv_list* iter = first_item;
+            */
+            for (cmsgh = ((msg.msg_controllen > 0) ? CMSG_FIRSTHDR(&msg) : 
NULL);
+                 cmsgh != NULL; cmsgh = CMSG_NXTHDR(&msg, cmsgh)) {
+
+                 anc_counter++;
+            }
+
+            retinfo->size_of_ancillary = anc_counter;
+            retinfo->file_descr = (char**) malloc (anc_counter * 
sizeof(char*));
+            retinfo->levels = (int*) malloc(anc_counter * sizeof(int));
+            retinfo->types = (int*) malloc(anc_counter * sizeof(int));
+            retinfo->descr_per_ancillary = (int*) malloc(anc_counter * 
sizeof(int));
+            anc_alloc = 1;
+
+            int i=0;
+            for (cmsgh = ((msg.msg_controllen > 0) ? CMSG_FIRSTHDR(&msg) : 
NULL);
+                 cmsgh != NULL; cmsgh = CMSG_NXTHDR(&msg, cmsgh)) {
+                 size_t local_size = 0;
+                 cmsg_status = get_cmsg_data_len(&msg, cmsgh, &local_size);
+                 if (cmsg_status !=0 ){
+                    error_flag = MAL_ANC;
+                    goto err_closefds;
+                 }
+                 retinfo->file_descr[i] = (char*) malloc(local_size);
+                 memcpy(retinfo->file_descr[i], CMSG_DATA(cmsgh), local_size);
+                 retinfo->levels[i] = cmsgh->cmsg_level;
+                 retinfo->types[i] = cmsgh->cmsg_type;
+                 retinfo->descr_per_ancillary[i] =local_size;
+                 i++;
+
+            }
+            retinfo->flags = msg.msg_flags;
+            retinfo->error_code = 0;
+
+            //address = (struct sockaddr*) malloc (sizeof(struct sockaddr));
+            memcpy(address,retinfo->address,sizeof(struct sockaddr));
+
+
+            *addrlen = retinfo->addrlen;
+            *no_of_messages = retinfo->no_of_messages;
+            *size_of_ancillary = retinfo->size_of_ancillary;
+
+            *length_of_messages = (int*) malloc (sizeof(int) * 
retinfo->no_of_messages);
+            //*length_of_messages =
+            memcpy(*length_of_messages, retinfo->length_of_messages, 
sizeof(int) * retinfo->no_of_messages);
+
+            int counter = 0;
+            for (i=0; i< retinfo->no_of_messages; i++)
+                counter += retinfo->length_of_messages[i];
+
+            //*messages = (char*) malloc(sizeof(char) * counter);
+            memset(*messages, 0, sizeof(char) * counter);
+            counter = 0;
+            for(i=0; i< retinfo->no_of_messages; i++){
+                
memcpy(*messages+counter,retinfo->messages[i],retinfo->length_of_messages[i]);
+                counter += retinfo->length_of_messages[i];
+            }
+
+            *levels = (int*) malloc (sizeof(int) * retinfo->size_of_ancillary);
+            //*levels =
+            memcpy(*levels, retinfo->levels, sizeof(int) * 
retinfo->size_of_ancillary);
+            *types = (int*) malloc (sizeof(int) * retinfo->size_of_ancillary);
+            //*types =
+            memcpy(*types, retinfo->types, sizeof(int) * 
retinfo->size_of_ancillary);
+            *descr_per_ancillary = (int*) malloc (sizeof(int) * 
retinfo->size_of_ancillary);
+            //*descr_per_ancillary =
+            memcpy(*descr_per_ancillary, retinfo->descr_per_ancillary, 
sizeof(int) * retinfo->size_of_ancillary);
+
+            counter = 0;
+            for (i=0; i < retinfo->size_of_ancillary; i++)
+                counter += retinfo->descr_per_ancillary[i];
+
+            *file_descr = (char*) malloc (sizeof(char) * counter);
+            memset(*file_descr, 0, sizeof(char) * counter);
+            counter = 0;
+            for (i=0; i<retinfo->size_of_ancillary; i++){
+                memcpy(*file_descr+counter,retinfo->file_descr[i], 
retinfo->descr_per_ancillary[i]);
+                counter += retinfo->descr_per_ancillary[i];
+            }
+
+            *flag = retinfo->flags;
+            //int k;
+            //char* dsadas;
+            //dsadas = (char*) (*file_descr[0]);
+            //for (k=0; k<retinfo->no_of_messages * sizeof(int); k++)
+            //                printf("0x%X ", dsadas[k]);
+
+            free(retinfo->address);
+            free(retinfo->length_of_messages);
+            free(retinfo->levels);
+            free(retinfo->types);
+            free(retinfo->descr_per_ancillary);
+            for(i = 0; i<retinfo->no_of_messages; i++)
+                free(retinfo->messages[i]);
+            for (i = 0; i < retinfo->size_of_ancillary; i++)
+                free(retinfo->file_descr[i]);
+            free(retinfo->file_descr);
+            free(retinfo->messages);
+            free(retinfo);
+            free(controlbuf);
+
+            return bytes_recvd;
+
+        fail:
+            if (anc_alloc){
+                free(retinfo->file_descr);
+                free(retinfo->levels);
+                free(retinfo->types);
+                free(retinfo->descr_per_ancillary);
+                free(retinfo->length_of_messages);
+                free(retinfo->messages[0]);
+                free(retinfo->messages);
+                free(retinfo->address);
+                free(controlbuf);
+                file_descr = NULL;
+                levels = NULL;
+                types = NULL;
+                descr_per_ancillary = NULL;
+                length_of_messages = NULL;
+                messages =NULL;
+                address = NULL;
+                addrlen = NULL;
+                no_of_messages = NULL;
+                size_of_ancillary = NULL;
+
+            }else{
+                if (iov_alloc){
+                    free(retinfo->length_of_messages);
+                    free(retinfo->messages[0]);
+                    free(retinfo->messages);
+                    free(retinfo->address);
+                    free(controlbuf);
+                    length_of_messages = NULL;
+                    messages =NULL;
+                    address = NULL;
+                    file_descr = NULL;
+                    levels = NULL;
+                    types = NULL;
+                    descr_per_ancillary = NULL;
+                    addrlen = NULL;
+                    no_of_messages = NULL;
+                    size_of_ancillary = NULL;
+
+                }
+            }
+            return error_flag;
+
+        err_closefds:
+        #ifdef SCM_RIGHTS
+            /* Close all descriptors coming from SCM_RIGHTS, so they don't 
leak. */
+            for (cmsgh = ((msg.msg_controllen > 0) ? CMSG_FIRSTHDR(&msg) : 
NULL);
+                 cmsgh != NULL; cmsgh = CMSG_NXTHDR(&msg, cmsgh)) {
+                size_t dataleng;
+                cmsg_status = get_cmsg_data_len(&msg, cmsgh, &dataleng);
+                cmsgdatalen = (int) dataleng;
+                if (cmsg_status < 0)
+                    break;
+                if (cmsgh->cmsg_level == SOL_SOCKET &&
+                    cmsgh->cmsg_type == SCM_RIGHTS) {
+                    size_t numfds;
+                    int *fdp;
+
+                    numfds = cmsgdatalen / sizeof(int);
+                    fdp = (int *)CMSG_DATA(cmsgh);
+                    while (numfds-- > 0)
+                        close(*fdp++);
+                }
+                if (cmsg_status != 0)
+                    break;
+            }
+        #endif /* SCM_RIGHTS */
+            goto fail;
+        }
+
+
+        
//################################################################################################
+        //send goes from here
+
+        #ifdef CMSG_LEN
+        static int
+        get_CMSG_LEN(size_t length, size_t *result)
+        {
+            size_t tmp;
+
+            if (length > (SOCKLEN_T_LIMIT - CMSG_LEN(0)))
+                return 0;
+            tmp = CMSG_LEN(length);
+            if ((tmp > SOCKLEN_T_LIMIT) || (tmp < length))
+                return 0;
+            *result = tmp;
+            return 1;
+        }
+        #endif
+
+        #ifdef CMSG_SPACE
+        /* If length is in range, set *result to CMSG_SPACE(length) and return
+           true; otherwise, return false. */
+        static int
+        get_CMSG_SPACE(size_t length, size_t *result)
+        {
+            size_t tmp;
+
+            /* Use CMSG_SPACE(1) here in order to take account of the padding
+               necessary before *and* after the data. */
+            if (length > (SOCKLEN_T_LIMIT - CMSG_SPACE(1)))
+                return 0;
+            tmp = CMSG_SPACE(length);
+            if ((tmp > SOCKLEN_T_LIMIT) || (tmp < length))
+                return 0;
+            *result = tmp;
+            return 1;
+        }
+        #endif
+
+        RPY_EXTERN
+        int sendmsg_implementation(int socket, struct sockaddr* address, 
socklen_t addrlen, long* length_of_messages, char** messages, int 
no_of_messages, long* levels, long* types, char** file_descriptors, long* 
no_of_fds, int control_length, int flag )
+        {
+
+            struct msghdr        msg = {0};
+            struct cmsghdr       *cmsg;
+            void* controlbuf = NULL;
+            int retval;
+            size_t i;
+
+            // Add the address
+
+            if (address != NULL) {
+                msg.msg_name = address;
+                msg.msg_namelen = addrlen;
+            }
+            // Add the message
+            struct iovec *iovs = NULL;
+
+            if (no_of_messages > 0){
+
+                iovs = (struct iovec*) malloc(no_of_messages * sizeof(struct 
iovec));
+                memset(iovs, 0, no_of_messages * sizeof(struct iovec));
+                msg.msg_iov = iovs;
+                msg.msg_iovlen = no_of_messages;
+
+                for (i=0; i< no_of_messages; i++){
+                    iovs[i].iov_base = messages[i];
+                    iovs[i].iov_len = length_of_messages[i];
+                }
+            }
+            // Add the ancillary
+
+            #ifndef CMSG_SPACE
+                if (control_length > 1){
+                    free(iovs);
+                    return MUL_MSGS_NOT_SUP;
+                }
+            #endif
+            if (control_length > 0){
+                //compute the total size of the ancillary
+                size_t total_size_of_ancillary = 0;
+                size_t space;
+                size_t controllen = 0, controllen_last = 0;
+                for (i = 0; i< control_length; i++){
+                    total_size_of_ancillary = no_of_fds[i];
+                    #ifdef CMSG_SPACE
+                        if (!get_CMSG_SPACE(total_size_of_ancillary, &space)) {
+                    #else
+                        if (!get_CMSG_LEN(total_size_of_ancillary, &space)) {
+                    #endif
+                            if (iovs != NULL)
+                                free(iovs);
+                            return ANC_DATA_TOO_LARGE;
+                        }
+                    controllen +=space;
+                    if ((controllen > SOCKLEN_T_LIMIT) || (controllen < 
controllen_last)) {
+                        if (iovs != NULL)
+                                free(iovs);
+                        return ANC_DATA_TOO_LARGEX;
+                    }
+                    controllen_last = controllen;
+
+                }
+
+                controlbuf = malloc(controllen); //* sizeof(int)
+
+                msg.msg_control= controlbuf;
+                msg.msg_controllen = controllen;
+
+                memset(controlbuf, 0, controllen);
+
+                cmsg = NULL;
+                for (i = 0; i< control_length; i++){
+                    cmsg = (i == 0) ? CMSG_FIRSTHDR(&msg) : CMSG_NXTHDR(&msg, 
cmsg);
+
+                    cmsg->cmsg_level = (int) levels[i];
+                    cmsg->cmsg_type = (int) types[i];
+                    cmsg->cmsg_len = CMSG_LEN(sizeof(char) * no_of_fds[i]);
+                    memcpy(CMSG_DATA(cmsg), file_descriptors[i], sizeof(char) 
* no_of_fds[i]);
+                }
+
+
+            }
+            // Add the flags
+            msg.msg_flags = flag;
+
+            // Send the data
+            retval = sendmsg(socket, &msg, flag);
+
+            if (iovs != NULL)
+                free(iovs);
+            if (controlbuf !=NULL)
+               free(controlbuf);
+
+            return retval;
+        }
+        #ifdef CMSG_SPACE
+        RPY_EXTERN
+        size_t CMSG_SPACE_wrapper(size_t desired_space){
+            size_t result;
+            if (!get_CMSG_SPACE(desired_space, &result)){
+                return 0;
+            }
+            return result;
+        }
+        #endif
+
+        #ifdef CMSG_LEN
+
+        RPY_EXTERN
+        size_t CMSG_LEN_wrapper(size_t desired_len){
+            size_t result;
+            if (!get_CMSG_LEN(desired_len, &result)){
+                return 0;
+            }
+            return result;
+        }
+        #endif
+
+        RPY_EXTERN
+        char* memcpy_from_CCHARP_at_offset_and_size(char* string, int offset, 
int size){
+            char* buffer;
+            buffer = (char*)malloc(sizeof(char)*size);
+            buffer = memcpy(buffer, string + offset, size);
+            return buffer;
+        }
+
+        RPY_EXTERN
+        int free_pointer_to_signedp(int** ptrtofree){
+            free(*ptrtofree);
+            return 0;
+        }
+
+        RPY_EXTERN
+        int free_ptr_to_charp(char** ptrtofree){
+            free(*ptrtofree);
+            return 0;
+        }
+
+    ''',]
+
+    post_include_bits =[ "RPY_EXTERN "
+                         "int sendmsg_implementation(int socket, struct 
sockaddr* address, socklen_t addrlen, long* length_of_messages, char** 
messages, int no_of_messages, long* levels, long* types, char** 
file_descriptors, long* no_of_fds, int control_length, int flag );\n"
+                         "RPY_EXTERN "
+                         "int recvmsg_implementation(int socket_fd, int 
message_size, int ancillary_size, int flags, struct sockaddr* address, 
socklen_t* addrlen, int** length_of_messages, char** messages, int* 
no_of_messages, int* size_of_ancillary, int** levels, int** types, char** 
file_descr, int** descr_per_ancillary, int* flag);\n"
+                         "static "
+                         "int cmsg_min_space(struct msghdr *msg, struct 
cmsghdr *cmsgh, size_t space);\n"
+                         "static "
+                         "int get_cmsg_data_space(struct msghdr *msg, struct 
cmsghdr *cmsgh, size_t *space);\n"
+                         "static "
+                         "int get_cmsg_data_len(struct msghdr *msg, struct 
cmsghdr *cmsgh, size_t *data_len);\n"
+                         "static "
+                         "int get_CMSG_LEN(size_t length, size_t *result);\n"
+                         "static "
+                         "int get_CMSG_SPACE(size_t length, size_t *result);\n"
+                         "RPY_EXTERN "
+                         "size_t CMSG_LEN_wrapper(size_t desired_len);\n"
+                         "RPY_EXTERN "
+                         "size_t CMSG_SPACE_wrapper(size_t desired_space);\n"
+                         "RPY_EXTERN "
+                         "char* memcpy_from_CCHARP_at_offset_and_size(char* 
string, int offset, int size);\n"
+                         "RPY_EXTERN "
+                         "int free_pointer_to_signedp(int** ptrtofree);\n"
+                         "RPY_EXTERN "
+                         "int free_ptr_to_charp(char** ptrtofree);\n"
+                         ]
+
+    #CConfig.SignedPP = lltype.Ptr(lltype.Array(rffi.SIGNEDP, 
hints={'nolength': True}))
+
+
+    # CConfig.recvmsginfo = platform.Struct('struct recvmsg_info',
+    #                                       [('error_code',rffi.SIGNED),
+    #                                        ('address',sockaddr_ptr),
+    #                                        ('addrlen',socklen_t_ptr),
+    #                                        ('length_of_messages', 
rffi.SIGNEDP),
+    #                                        ('messages',rffi.CCHARPP),
+    #                                        ('no_of_messages',rffi.INT),
+    #                                        ('size_of_ancillary',rffi.INT),
+    #                                        ('levels', rffi.SIGNEDP),
+    #                                        ('types', rffi.SIGNEDP),
+    #                                        ('file_descr', rffi.CCHARPP),
+    #                                        ('descr_per_ancillary', 
rffi.SIGNEDP),
+    #                                        ('flags', rffi.INT),
+    #                                       ])
+
+    #
+
+    compilation_info = ExternalCompilationInfo(
+                                    includes=includes,
+                                    
separate_module_sources=separate_module_sources,
+                                    post_include_bits=post_include_bits,
+                               )
+
 if _WIN32:
     CConfig.WSAEVENT = platform.SimpleType('WSAEVENT', rffi.VOIDP)
     CConfig.WSANETWORKEVENTS = platform.Struct(
@@ -387,6 +1060,7 @@
 sockaddr_ptr.TO.become(cConfig.sockaddr)
 addrinfo_ptr.TO.become(cConfig.addrinfo)
 
+
 # fill in missing constants with reasonable defaults
 cConfig.NI_MAXHOST = cConfig.NI_MAXHOST or 1025
 cConfig.NI_MAXSERV = cConfig.NI_MAXSERV or 32
@@ -571,11 +1245,32 @@
 recvfrom = external('recvfrom', [socketfd_type, rffi.VOIDP, size_t,
                            rffi.INT, sockaddr_ptr, socklen_t_ptr], rffi.INT,
                     save_err=SAVE_ERR)
+recvmsg = jit.dont_look_inside(rffi.llexternal("recvmsg_implementation",
+                                               [rffi.INT, rffi.INT, rffi.INT, 
rffi.INT,sockaddr_ptr, socklen_t_ptr, rffi.SIGNEDPP, rffi.CCHARPP,
+                                                rffi.SIGNEDP,rffi.SIGNEDP, 
rffi.SIGNEDPP, rffi.SIGNEDPP, rffi.CCHARPP, rffi.SIGNEDPP, rffi.SIGNEDP],
+                                               rffi.INT, save_err=SAVE_ERR,
+                                               
compilation_info=compilation_info))
+
+memcpy_from_CCHARP_at_offset = 
jit.dont_look_inside(rffi.llexternal("memcpy_from_CCHARP_at_offset_and_size",
+                                    
[rffi.CCHARP,rffi.INT,rffi.INT],rffi.CCHARP,save_err=SAVE_ERR,compilation_info=compilation_info))
+freeccharp = jit.dont_look_inside(rffi.llexternal("free_ptr_to_charp",
+                                    
[rffi.CCHARPP],rffi.INT,save_err=SAVE_ERR,compilation_info=compilation_info))
+freesignedp = jit.dont_look_inside(rffi.llexternal("free_pointer_to_signedp",
+                                    
[rffi.SIGNEDPP],rffi.INT,save_err=SAVE_ERR,compilation_info=compilation_info))
+
 send = external('send', [socketfd_type, rffi.CCHARP, size_t, rffi.INT],
                        ssize_t, save_err=SAVE_ERR)
 sendto = external('sendto', [socketfd_type, rffi.VOIDP, size_t, rffi.INT,
                                     sockaddr_ptr, socklen_t], ssize_t,
                   save_err=SAVE_ERR)
+sendmsg = jit.dont_look_inside(rffi.llexternal("sendmsg_implementation",
+                               [rffi.INT, sockaddr_ptr, socklen_t, 
rffi.SIGNEDP, rffi.CCHARPP, rffi.INT,
+                                rffi.SIGNEDP, rffi.SIGNEDP, rffi.CCHARPP, 
rffi.SIGNEDP, rffi.INT, rffi.INT],
+                               rffi.INT, save_err=SAVE_ERR,
+                               compilation_info=compilation_info))
+CMSG_SPACE = 
jit.dont_look_inside(rffi.llexternal("CMSG_SPACE_wrapper",[size_t], size_t, 
save_err=SAVE_ERR,compilation_info=compilation_info))
+CMSG_LEN = jit.dont_look_inside(rffi.llexternal("CMSG_LEN_wrapper",[size_t], 
size_t, save_err=SAVE_ERR,compilation_info=compilation_info))
+
 socketshutdown = external('shutdown', [socketfd_type, rffi.INT], rffi.INT,
                           save_err=SAVE_ERR)
 gethostname = external('gethostname', [rffi.CCHARP, rffi.INT], rffi.INT,
diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py
--- a/rpython/rlib/rsocket.py
+++ b/rpython/rlib/rsocket.py
@@ -963,6 +963,104 @@
                 return (read_bytes, address)
             raise self.error_handler()
 
+    @jit.dont_look_inside
+    def recvmsg(self, message_size, ancbufsize = 0, flags = 0):
+        if message_size < 0:
+            raise RSocketError("Invalid message size")
+        if ancbufsize < 0:
+            raise RSocketError("invalid ancillary data buffer length")
+
+        # addr, maxlen = make_null_address(self.family)
+        # addrlen_p = lltype.malloc(_c.socklen_t_ptr.TO, flavor='raw')
+        # addrlen_p[0] = rffi.cast(_c.socklen_t, maxlen)
+        address, addr_p, addrlen_p  = self._addrbuf()
+        len_of_msgs = 
lltype.malloc(rffi.SIGNEDPP.TO,1,flavor='raw',track_allocation=True,nonmovable=False)
+        messages = 
lltype.malloc(rffi.CCHARPP.TO,1,flavor='raw',track_allocation=True,nonmovable=False
 )
+        messages[0] = lltype.malloc(rffi.CCHARP.TO, 
message_size,flavor='raw',track_allocation=True,nonmovable=False)
+        rffi.c_memset(messages[0], 0, message_size)
+        no_of_messages  = 
lltype.malloc(rffi.SIGNEDP.TO,1,flavor='raw',track_allocation=True,nonmovable=False
 )
+        no_of_messages[0] = rffi.cast(rffi.SIGNED, 0)
+        size_of_anc = 
lltype.malloc(rffi.SIGNEDP.TO,1,flavor='raw',track_allocation=True,nonmovable=False
 )
+        size_of_anc[0] = rffi.cast(rffi.SIGNED,0)
+        levels = 
lltype.malloc(rffi.SIGNEDPP.TO,1,flavor='raw',track_allocation=True,nonmovable=False)
+        types = 
lltype.malloc(rffi.SIGNEDPP.TO,1,flavor='raw',track_allocation=True,nonmovable=False)
+        file_descr = 
lltype.malloc(rffi.CCHARPP.TO,1,flavor='raw',track_allocation=True,nonmovable=False
 )
+        descr_per_anc = 
lltype.malloc(rffi.SIGNEDPP.TO,1,flavor='raw',track_allocation=True,nonmovable=False)
+        retflag = 
lltype.malloc(rffi.SIGNEDP.TO,1,flavor='raw',track_allocation=True,nonmovable=False
 )
+        retflag[0] = rffi.cast(rffi.SIGNED,0)
+
+        LONG_MASK =  2**32 - 1
+        reply = _c.recvmsg(self.fd, rffi.cast(lltype.Signed,message_size),
+                           
rffi.cast(lltype.Signed,ancbufsize),rffi.cast(lltype.Signed,flags),
+                           addr_p, addrlen_p, len_of_msgs, messages, 
no_of_messages,size_of_anc,
+                           levels, types,file_descr,descr_per_anc,retflag)
+        if reply >= 0:
+            msg_no = rffi.cast(rffi.SIGNED,no_of_messages[0])
+            anc_size  = rffi.cast(rffi.SIGNED,size_of_anc[0])
+            returnflag  = rffi.cast(rffi.SIGNED,retflag[0])
+            addrlen = rffi.cast(rffi.SIGNED,addrlen_p[0])
+            retmsg = ""
+
+            for i in range(msg_no):
+                x = rffi.cast(rffi.SIGNED,len_of_msgs[0][i])
+                x &= LONG_MASK
+                retmsg = rffi.charp2strn(messages[0],x)
+
+            offset = 0
+            list_of_tuples = []
+            for i in range(anc_size):
+                x = rffi.cast(rffi.SIGNED, levels[0][i])
+                x &= LONG_MASK
+                level = x
+                x = rffi.cast(rffi.SIGNED,types[0][i])
+                x &= LONG_MASK
+                type = x
+                x =  rffi.cast(rffi.SIGNED,descr_per_anc[0][i])
+                x &= LONG_MASK
+                bytes_in_anc = x
+                pre_anc = 
_c.memcpy_from_CCHARP_at_offset(file_descr[0],rffi.cast(rffi.SIGNED,offset), 
bytes_in_anc)
+                anc = rffi.charpsize2str(pre_anc,bytes_in_anc)
+                tup = (level,type, anc)
+                list_of_tuples.append(tup)
+                offset += bytes_in_anc
+                #lltype.free(pre_anc, flavor='raw')
+            #address.unlock()
+            if addrlen:
+                address.addrlen = addrlen
+            else:
+                address = None
+
+
+            rettup = (retmsg,list_of_tuples,returnflag,address)
+
+            #free underlying complexity first
+            if address is not None:
+                address.unlock()
+            # lltype.free(messages[0],flavor='raw')
+            _c.freeccharp(file_descr)
+            _c.freesignedp(len_of_msgs)
+            _c.freesignedp(levels)
+            _c.freesignedp(types)
+            _c.freesignedp(descr_per_anc)
+
+            lltype.free(messages,flavor='raw')
+            lltype.free(file_descr,flavor='raw')
+            lltype.free(len_of_msgs,flavor='raw')
+            lltype.free(no_of_messages, flavor='raw')
+            lltype.free(size_of_anc, flavor='raw')
+            lltype.free(levels, flavor='raw')
+            lltype.free(descr_per_anc, flavor='raw')
+            lltype.free(retflag, flavor='raw')
+            lltype.free(addrlen_p,flavor='raw')
+
+            return rettup
+        else:
+            if address is not None:
+                address.unlock()
+            raise last_error()
+
+
+
     def send_raw(self, dataptr, length, flags=0):
         """Send data from a CCHARP buffer."""
         self.wait_for_data(True)
@@ -1009,6 +1107,77 @@
             raise self.error_handler()
         return res
 
+    @jit.dont_look_inside
+    def sendmsg(self, messages, ancillary=None, flags=0, address=None):
+        # addr = address.lock()
+        # addrlen = address.addrlen
+        need_to_free_address = True
+        if address is None:
+            need_to_free_address = False
+            addr = lltype.nullptr(_c.sockaddr)
+            addrlen = 0
+        else:
+            addr = address.lock()
+            addrlen = address.addrlen
+
+        no_of_messages = len(messages)
+        messages_ptr = 
lltype.malloc(rffi.CCHARPP.TO,no_of_messages+1,flavor='raw',track_allocation=True,nonmovable=False)
+        messages_length_ptr = 
lltype.malloc(rffi.SIGNEDP.TO,no_of_messages,flavor='raw',zero=True, 
track_allocation=True,nonmovable=False)
+        counter = 0
+        for message in messages:
+            messages_ptr[counter] = rffi.str2charp(message)
+            messages_length_ptr[counter] = rffi.cast(rffi.SIGNED, len(message))
+            #messages_length_ptr[counter] = rffi.cast(rffi.SIGNED, 
0x00cabc00abcabc00)
+            counter += 1
+        messages_ptr[counter] = lltype.nullptr(rffi.CCHARP.TO)
+        if ancillary is not None:
+            size_of_ancillary = len(ancillary)
+        else:
+            size_of_ancillary = 0
+        levels = lltype.malloc(rffi.SIGNEDP.TO, 
size_of_ancillary,flavor='raw',zero=True, 
track_allocation=True,nonmovable=False)
+        types = lltype.malloc(rffi.SIGNEDP.TO, 
size_of_ancillary,flavor='raw',zero=True, 
track_allocation=True,nonmovable=False)
+        desc_per_ancillary = lltype.malloc(rffi.SIGNEDP.TO, 
size_of_ancillary,flavor='raw',zero=True, 
track_allocation=True,nonmovable=False)
+        file_descr = lltype.malloc(rffi.CCHARPP.TO, 
size_of_ancillary,flavor='raw', track_allocation=True,nonmovable=False)
+        if ancillary is not None:
+            counter = 0
+            for level, type, content in ancillary:
+                assert isinstance(type,int)
+                assert isinstance(level, int)
+                levels[counter] = rffi.cast(rffi.SIGNED,level)
+                types[counter] = rffi.cast(rffi.SIGNED,type)
+                desc_per_ancillary[counter] = rffi.cast(rffi.SIGNED, 
(len(content)))
+                #file_descr[counter] = 
lltype.malloc(rffi.CCHARP.TO,len(content),flavor='raw',zero=True, 
track_allocation=True,nonmovable=False)
+                file_descr[counter] = rffi.str2charp(content, 
track_allocation=True)
+                counter +=1
+        else:
+            size_of_ancillary = 0
+        snd_no_msgs = rffi.cast(rffi.SIGNED, no_of_messages)
+        snd_anc_size =rffi.cast(rffi.SIGNED, size_of_ancillary)
+        bytes_sent = _c.sendmsg(self.fd, addr, addrlen, messages_length_ptr, 
messages_ptr, 
snd_no_msgs,levels,types,file_descr,desc_per_ancillary,snd_anc_size,flags)
+
+
+        if need_to_free_address:
+            address.unlock()
+        for i in range(len(messages)):
+            lltype.free(messages_ptr[i], flavor='raw', track_allocation=True)
+        lltype.free(messages_ptr, flavor='raw', track_allocation=True)
+        lltype.free(messages_length_ptr, flavor='raw', track_allocation=True)
+
+        if size_of_ancillary > 0:
+            for i in range(len(ancillary)):
+                lltype.free(file_descr[i], flavor='raw', track_allocation=True)
+        lltype.free(desc_per_ancillary, flavor='raw', track_allocation=True)
+        lltype.free(types, flavor='raw', track_allocation=True)
+        lltype.free(levels, flavor='raw', track_allocation=True)
+        lltype.free(file_descr, flavor='raw', track_allocation=True)
+
+        if (bytes_sent < 0) and (bytes_sent!=-1000) and (bytes_sent!=-1001) 
and (bytes_sent!=-1002):
+            raise last_error()
+
+        return bytes_sent
+
+
+
     def setblocking(self, block):
         if block:
             timeout = -1.0
@@ -1190,6 +1359,19 @@
         return (make_socket(fd0, family, type, proto, SocketClass),
                 make_socket(fd1, family, type, proto, SocketClass))
 
+if _c._POSIX:
+    def CMSG_LEN( demanded_len):
+        if demanded_len < 0:
+            return 0
+        result = _c.CMSG_LEN(demanded_len)
+        return result
+
+    def CMSG_SPACE( demanded_size):
+        if demanded_size < 0:
+            return 0
+        result = _c.CMSG_SPACE(demanded_size)
+        return result
+
 if _c.WIN32:
     def dup(fd, inheritable=True):
         with lltype.scoped_alloc(_c.WSAPROTOCOL_INFO, zero=True) as info:
diff --git a/rpython/rtyper/lltypesystem/rffi.py 
b/rpython/rtyper/lltypesystem/rffi.py
--- a/rpython/rtyper/lltypesystem/rffi.py
+++ b/rpython/rtyper/lltypesystem/rffi.py
@@ -752,7 +752,8 @@
 
 # Signed, Signed *
 SIGNED = lltype.Signed
-SIGNEDP = lltype.Ptr(lltype.Array(SIGNED, hints={'nolength': True}))
+SIGNEDP = lltype.Ptr(lltype.Array(lltype.Signed, hints={'nolength': True}))
+SIGNEDPP = lltype.Ptr(lltype.Array(SIGNEDP, hints={'nolength': True}))
 
 
 # various type mapping
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to