qmsk/net/socket/socket.pyx
changeset 14 c44754cc1ffe
parent 13 a1091632a8a7
child 15 8e7037cc05c7
equal deleted inserted replaced
13:a1091632a8a7 14:c44754cc1ffe
    20 cdef parse_buf (void **buf_ptr, size_t *buf_len, object buf, int optional = 0) :
    20 cdef parse_buf (void **buf_ptr, size_t *buf_len, object buf, int optional = 0) :
    21     cdef libc.ssize_t tmp_len
    21     cdef libc.ssize_t tmp_len
    22 
    22 
    23     if buf is not None :
    23     if buf is not None :
    24         # XXX: test that except works right
    24         # XXX: test that except works right
       
    25         # XXX: this complains about const...
    25         py.PyObject_AsCharBuffer(buf, <char **> buf_ptr, &tmp_len)
    26         py.PyObject_AsCharBuffer(buf, <char **> buf_ptr, &tmp_len)
    26         
    27         
    27         # XXX: ensure that this is >= 0
    28         # XXX: ensure that this is >= 0
    28         buf_len[0] = tmp_len
    29         buf_len[0] = tmp_len
    29     
    30     
    64         
    65         
    65         # trap
    66         # trap
    66         if self.fd < 0 :
    67         if self.fd < 0 :
    67             raise_errno('socket')
    68             raise_errno('socket')
    68 
    69 
       
    70     def fileno (self) :
       
    71         """
       
    72             Returns the OS-level file desriptor for this socket as an integer
       
    73         """
       
    74 
       
    75         return self.fd
       
    76 
    69     def bind (self, sockaddr addr) :
    77     def bind (self, sockaddr addr) :
    70         """
    78         """
    71             Bind this socket to the given local socket address. The given sockaddr should be of the same or a
    79             Bind this socket to the given local socket address. The given sockaddr should be of the same or a
    72             compatible address family.
    80             compatible address family.
    73 
    81 
   126         """
   134         """
   127             Accept a connection, dequeueing the first pending connection and returning a new sock object for it. This
   135             Accept a connection, dequeueing the first pending connection and returning a new sock object for it. This
   128             socket must be a connection-based socket (SOCK_STREAM/SOCK_SEQPACKET) and in the passive listening mode
   136             socket must be a connection-based socket (SOCK_STREAM/SOCK_SEQPACKET) and in the passive listening mode
   129             (.listen()).
   137             (.listen()).
   130 
   138 
   131             This returns a (sock, sockaddr) tuple:
   139             This returns a (sock, src_addr) tuple:
   132                 sock        - the newly created sock, corresponding to the incoming connection
   140                 sock        - the newly created sock, corresponding to the incoming connection
   133                 sockaddr    - the remote address of the incoming connection
   141                 src_addr    - the remote address of the incoming connection
   134         """
   142         """
   135         
   143         
   136         # prep the sockaddr that we will return
   144         # prep the sockaddr that we will return
   137         cdef platform.sockaddr_storage ss
   145         cdef platform.sockaddr_storage ss
   138         cdef platform.socklen_t ss_len = sizeof(ss)
   146         cdef platform.socklen_t ss_len = sizeof(ss)
   139 
   147 
   140         cdef socket_t sock_fd
       
   141 
       
   142         # accept()
   148         # accept()
   143         sock_fd = platform.accept(self.fd, <platform.sockaddr *> &ss, &ss_len)
   149         cdef socket_t sock_fd = platform.accept(self.fd, <platform.sockaddr *> &ss, &ss_len)
   144 
   150 
   145         if sock_fd < 0 :
   151         if sock_fd < 0 :
   146             raise_errno('accept')
   152             raise_errno('accept')
   147         
   153         
   148         try :
   154         try :
   154             platform.close(sock_fd)
   160             platform.close(sock_fd)
   155 
   161 
   156             raise
   162             raise
   157 
   163 
   158         # prep the new addr
   164         # prep the new addr
   159         sock_addr = build_sockaddr(<platform.sockaddr *> &ss, ss_len)
   165         cdef sockaddr src_addr = build_sockaddr(<platform.sockaddr *> &ss, ss_len)
   160 
   166 
   161         return sock_obj, sock_addr
   167         return sock_obj, src_addr
   162 
   168 
   163     def send (self, object buf, int flags = 0) :
   169     def send (self, object buf, int flags = 0) :
   164         """
   170         """
   165             Transmit a message to the connected remote endpoint.
   171             Transmit a message to the connected remote endpoint.
   166 
   172 
   321         if ret < 0 :
   327         if ret < 0 :
   322             raise_errno('writev')
   328             raise_errno('writev')
   323 
   329 
   324         else :
   330         else :
   325             return ret
   331             return ret
   326 
   332     
       
   333     def recv (self, size_t len, int flags = 0) :
       
   334         """
       
   335             Recieve a message, reading and returning at most `len` bytes.
       
   336 
       
   337                 len         - size of buffer to use for recv
       
   338                 flags       - (optional) MSG_* flags to use for recv()
       
   339 
       
   340             Returns the recieved data as a newly allocated string of the correct length.
       
   341         """
       
   342         
       
   343         # alloc a new return str
       
   344         # XXX: len overflow...
       
   345         cdef object str = py.PyString_FromStringAndSize(NULL, len)
       
   346         cdef char *buf = py.PyString_AS_STRING(str)
       
   347         
       
   348         # recv()
       
   349         cdef libc.ssize_t ret = platform.recv(self.fd, buf, len, flags)
       
   350 
       
   351         if ret < 0 :
       
   352             raise_errno('recv')
       
   353         
       
   354         # XXX: figure out how to call _PyString_Resize
       
   355         return str[:ret]
       
   356     
       
   357     def recvfrom (self, size_t len, int flags = 0) :
       
   358         """
       
   359             Recieve a message, reading at most `len` bytes, also returning the source address.
       
   360 
       
   361                 len         - size of buffer to use for recv
       
   362                 flags       - (optional) MSG_* flags to use for recvfrom()
       
   363             
       
   364             Returns the recieved data and the source address as a (buf, src_addr) tuple :
       
   365                 buf         - a newly allocated string containing the recieved data, of the correct length
       
   366                 src_addr    - the source address the message was recieved from
       
   367         """
       
   368 
       
   369         # alloc a new return str
       
   370         # XXX: len overflow...
       
   371         cdef object str = py.PyString_FromStringAndSize(NULL, len)
       
   372         cdef char *buf = py.PyString_AS_STRING(str)
       
   373         
       
   374         # prep the sockaddr that we will return
       
   375         cdef platform.sockaddr_storage ss
       
   376         cdef platform.socklen_t ss_len = sizeof(ss)
       
   377         
       
   378         # recvfrom()
       
   379         cdef libc.ssize_t ret = platform.recvfrom(self.fd, buf, len, flags, <platform.sockaddr *> &ss, &ss_len)
       
   380 
       
   381         if ret < 0 :
       
   382             raise_errno('recv')
       
   383         
       
   384         # prep the new addr
       
   385         cdef sock_addr = build_sockaddr(<platform.sockaddr *> &ss, ss_len)
       
   386         
       
   387         # XXX: figure out how to call _PyString_Resize
       
   388         return str[:ret], sock_addr
       
   389     
       
   390     def recvmsg (self, bint recv_addr = True, object iov_lens = None, size_t control_len = 0, int flags = 0) :
       
   391         """
       
   392             Recieve a message along with some extra data.
       
   393 
       
   394                 recv_addr   - ask for and return a sockaddr for the source address of the message?
       
   395                 lenv        - (optional) sequence of buffer sizes to use for the message data iov
       
   396                 control_len - (optional) amount of auxiliary data to recieve
       
   397                 flags       - (optional) flags to pass to recvmsg()
       
   398 
       
   399             Returns a (name, iov, control, flags) tuple :
       
   400                 name        - the source address of the message, or None
       
   401                 iov         - sequence of strings containing the recieved data, each at most lenv[x] bytes long
       
   402                 control     - string containing recieved control message, if any
       
   403                 flags       - recieved flags
       
   404         """
       
   405 
       
   406         cdef platform.msghdr msg
       
   407 
       
   408         libc.memset(&msg, 0, sizeof(msg))
       
   409 
       
   410         # prep the sockaddr that we will return
       
   411         cdef platform.sockaddr_storage ss
       
   412         
       
   413         # ask for a name?
       
   414         if recv_addr :
       
   415             msg.msg_name = <void *> &ss
       
   416             msg.msg_namelen = sizeof(ss)
       
   417 
       
   418         # build iov?
       
   419         if iov_lens :
       
   420             # XXX: implement
       
   421             pass
       
   422 
       
   423         # build control buffer?
       
   424         if control_len :
       
   425             # XXX: implement
       
   426             pass
       
   427 
       
   428         # recvmsg()
       
   429         cdef libc.ssize_t ret = platform.recvmsg(self.fd, &msg, flags)
       
   430 
       
   431         if ret < 0 :
       
   432             raise_errno('recvmsg')
       
   433         
       
   434         # name?
       
   435         cdef sockaddr name = None
       
   436 
       
   437         if msg.msg_name and msg.msg_namelen :
       
   438             name = build_sockaddr(<platform.sockaddr *> msg.msg_name, msg.msg_namelen)
       
   439 
       
   440         # iov?
       
   441         cdef object iov = None
       
   442 
       
   443         if ret :
       
   444             assert msg.msg_iov and msg.msg_iovlen
       
   445             
       
   446             # XXX: implement
       
   447             pass
       
   448 
       
   449         # control?
       
   450         cdef object control = None
       
   451 
       
   452         if msg.msg_control and msg.msg_controllen :
       
   453             # XXX: implement
       
   454             pass
       
   455 
       
   456         return name, iov, control, msg.msg_flags
   327 
   457 
   328     def shutdown (self, how) :
   458     def shutdown (self, how) :
   329         """
   459         """
   330             Shutdown part of a full-duplex connection. 
   460             Shutdown part of a full-duplex connection. 
   331 
   461