예제 #1
0
    def peer_address(self):
        if self._address is None:
            raise socket_error(errno.EBADF)
        if self._peer_address is None:
            raise socket_error(errno.ENOTCONN)

        return self._peer_address
예제 #2
0
 def listen(self, backlog):
     if self._address is None:
         raise socket_error(errno.EBADF)
     if self._incoming_error != errno.ENOTCONN:
         raise socket_error(platform.invalid_argument)
     self.backlog = Store(self.env, capacity=backlog)
     self.env._register(self)
예제 #3
0
 def connect(self, address):
     if self._address is None:
         raise socket_error(errno.EBADF)
     if self._peer is not None:
         # Already connected, do nothing.
         return
     if self.backlog is not None:
         raise socket_error(errno.EISCONN)
     self.env._establish_connection(self, address)
예제 #4
0
    def close(self):
        # Stop reader and writer process if they are waiting for the next
        # request.
        if self._in_message_ev and not self._in_message_ev.triggered:
            self._in_message_ev.fail(socket_error(errno.EBADF))
            self._in_message_ev = None
        if self._out_message_ev and not self._out_message_ev.triggered:
            self._out_message_ev.fail(socket_error(errno.EBADF))
            self._out_message_ev = None

        self.sock.close()
예제 #5
0
    def close(self):
        """Closes the socket, all further operations will raise ``EBADF``."""
        if self._address is None:
            return

        self._incoming_error = errno.EBADF
        self._outgoing_error = errno.EBADF
        if self._incoming_avail is not None:
            self._incoming_avail.succeed()
        if self._outgoing_avail is not None:
            self._outgoing_avail.succeed()
        if self._frame_transmission:
            # Wake the reader if it is currently waiting for a frame.
            if not self._frame_transmission.triggered:
                self._frame_transmission.succeed()
                self._frame_transmission = None

        if self.backlog is not None:
            for accepter in self.backlog.get_queue:
                if not accepter.triggered:
                    accepter.fail(socket_error(errno.EBADF))

        self.env._unregister(self)

        self._address = None
        self._peer_address = None
    def close(self):
        # TODO Figure out if this behaviour is really usefull. Might require
        # the addition of methods that check for the sockets state.
        try:
            fileno = self.fileno()

            del self.env.fds[fileno]
            # TODO Remove events.
            if self._reader is not None:
                self._reader.fail(socket_error(errno.EBADF))
                self._reader = None
                self.env._rd.remove(fileno)
            if self._writer is not None:
                self._writer.fail(socket_error(errno.EBADF))
                self._writer = None
                self.env._wd.remove(fileno)
            self.sock.close()
        except SocketError as e:
            if e.errno == errno.EBADF:
                return
            raise e
예제 #7
0
    def _try_read(self):
        if self._incoming_error is not None:
            self._reader.fail(socket_error(self._incoming_error))
            self._reader = None
            return

        if not self.incoming:
            return

        data = self.incoming[:self._reader.amount]
        self.incoming = self.incoming[self._reader.amount:]
        self._reader.succeed(data)
        self._reader = None

        if self._incoming_avail:
            self._incoming_avail.succeed()
            self._incoming_avail = None
예제 #8
0
    def _try_write(self):
        if self._outgoing_error is not None:
            self._writer.fail(socket_error(self._outgoing_error))
            self._writer = None
            return

        available = self.max_buffer_size - len(self.outgoing)
        if not available:
            return

        self.outgoing += self._writer.data[:available]
        self._writer.succeed(min(len(self._writer.data), available))
        self._writer = None

        if self._outgoing_avail:
            # Notify the reader process about the new data.
            self._outgoing_avail.succeed()
            self._outgoing_avail = None
예제 #9
0
    def _get_address(self, address):
        host, port = address
        if host != '0.0.0.0':
            for interface, routes in self.interfaces:
                if interface == host: break
            else:
                errcode = socket.EAI_NONAME
                raise socket.gaierror(errcode, os.strerror(errcode))

        # A port number of zero means auto-choose.
        if port == 0:
            # Search for a free port starting from the current port_ofs.
            for port in range(65535):
                port = 1 + (self._port_ofs + port) % (65535 - 1)
                if port not in self.ports:
                    break
            else:
                raise RuntimeError('No free port left')
            self._port_ofs = port
        elif port in self.ports:
            raise socket_error(errno.EADDRINUSE)

        return (host, port)
예제 #10
0
    def _register(self, sock):
        host, port = sock._address
        if port in self.ports:
            raise socket_error(errno.EADDRINUSE)

        self.ports[port] = sock
예제 #11
0
 def accept(self):
     if self.backlog is None:
         raise socket_error(platform.invalid_argument)
     return self.backlog.get()
예제 #12
0
 def bind(self, address):
     if self._address is None:
         raise socket_error(errno.EBADF)
     if self._incoming_error != errno.ENOTCONN:
         raise socket_error(platform.invalid_argument)
     self._address = self.env._get_address(address)
예제 #13
0
 def address(self):
     if self._address is None:
         raise socket_error(errno.EBADF)
     return self._address
 def fileno(self):
     fileno = self.sock.fileno()
     if fileno < 0:
         raise socket_error(errno.EBADF)
     return fileno
예제 #15
0
    def _reader(self, data=b'', mask=False):
        try:
            read = self.socket.read
            blocksize = self.blocksize
            headers = frame_headers[mask]
            while True:
                event = None
                event = yield self._read_ev
                self._read_ev = self.env.event()

                while len(data) < headers[0].size:
                    data += yield read(4096)

                # Parse header.
                header = bytearray(data[:headers[0].size])
                opcode = header[0]
                if mask and not header[1] & 0x80:
                    raise RuntimeError('Masking bit was not set')

                length_desc = 0x7f & header[1]
                if length_desc == 126:
                    while len(data) < headers[1].size:
                        data += yield read(blocksize)
                    header = headers[1].unpack(data[:headers[1].size])
                    data = data[headers[1].size:]
                    size = header[2]
                elif length_desc == 127:
                    while len(data) < headers[2].size:
                        data += yield read(blocksize)
                    header = headers[2].unpack(data[:headers[2].size])
                    data = data[headers[2].size:]
                    size = header[2]
                else:
                    header = headers[0].unpack(data[:headers[0].size])
                    data = data[headers[0].size:]
                    size = header[1] & 0x7f

                # Read packet.
                while len(data) < size:
                    data += yield read(blocksize)
                packet, data = data[:size], data[size:]

                if mask:
                    # Unmask data.
                    # TODO Is it possible to unmask the data using a builtin
                    # function?
                    if PY2:
                        maskingkey = bytearray(header[-1])
                    else:
                        maskingkey = header[-1]

                    packet = bytearray(packet)
                    for i in range(size):
                        packet[i] ^= maskingkey[i % 4]
                    packet = bytes(packet)

                # Convert packet data if necessary.
                if opcode & 0x7f == 1:
                    packet = packet.decode()
                elif opcode & 0x7f == 2:
                    pass
                elif opcode & 0x7f == 8:
                    # Close connection.
                    # FIXME Should I really send the close control frame?
                    self.socket.close()
                    raise socket_error(errno.ECONNRESET)
                else:
                    raise RuntimeError('Unsupported opcode %x' % opcode)

                event.succeed(packet)
        except BaseException as e:
            # FIXME Add proper error handling.
            self._reader_proc.defused = True
            if event is not None:
                event.fail(e)