Ejemplo n.º 1
0
 def handle_event(self, sock, fd, event):
     # handle events and dispatch to handlers
     if sock:
         logging.log(shell.VERBOSE_LEVEL, 'fd %d %s', fd,
                     eventloop.EVENT_NAMES.get(event, event))
     if sock == self._server_socket:
         if event & eventloop.POLL_ERR:
             # TODO
             raise Exception('server_socket error')
         try:
             logging.debug('accept')
             conn = self._server_socket.accept()
             TCPRelayHandler(self, self._fd_to_handlers, self._eventloop,
                             conn[0], self._config, self._dns_resolver,
                             self._is_local)
         except (OSError, IOError) as e:
             error_no = eventloop.errno_from_exception(e)
             if error_no in (errno.EAGAIN, errno.EINPROGRESS,
                             errno.EWOULDBLOCK):
                 return
             else:
                 shell.print_exception(e)
                 if self._config['verbose']:
                     traceback.print_exc()
     else:
         if sock:
             handler = self._fd_to_handlers.get(fd, None)
             if handler:
                 handler.handle_event(sock, event)
         else:
             logging.warn('poll removed fd')
Ejemplo n.º 2
0
    def _on_remote_read(self):
        # handle all remote read events
        data = None
        try:
            data = self._remote_sock.recv(BUF_SIZE)

        except (OSError, IOError) as e:
            if eventloop.errno_from_exception(e) in \
                    (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK):
                return
        if not data:
            self.destroy()
            return
        self._update_activity(len(data))
        if self._is_local:
            data = self._encryptor.decrypt(data)
        else:
            data = self._encryptor.encrypt(data)
        try:
            self._write_to_sock(data, self._local_sock)
        except Exception as e:
            shell.print_exception(e)
            if self._config['verbose']:
                traceback.print_exc()
            # TODO use logging when debug completed
            self.destroy()
Ejemplo n.º 3
0
 def _send_control_data(self, data):
     if self._control_client_addr:
         try:
             self._control_socket.sendto(data, self._control_client_addr)
         except (socket.error, OSError, IOError) as e:
             error_no = eventloop.errno_from_exception(e)
             if error_no in (errno.EAGAIN, errno.EINPROGRESS,
                             errno.EWOULDBLOCK):
                 return
             else:
                 shell.print_exception(e)
                 if self._config['verbose']:
                     traceback.print_exc()
Ejemplo n.º 4
0
 def _handle_stage_connecting(self, data):
     if self._is_local:
         data = self._encryptor.encrypt(data)
     self._data_to_write_to_remote.append(data)
     if self._is_local and not self._fastopen_connected and \
             self._config['fast_open']:
         # for sslocal and fastopen, we basically wait for data and use
         # sendto to connect
         try:
             # only connect once
             self._fastopen_connected = True
             remote_sock = \
                 self._create_remote_socket(self._chosen_server[0],
                                            self._chosen_server[1])
             self._loop.add(remote_sock, eventloop.POLL_ERR, self._server)
             data = b''.join(self._data_to_write_to_remote)
             l = len(data)
             s = remote_sock.sendto(data, MSG_FASTOPEN, self._chosen_server)
             if s < l:
                 data = data[s:]
                 self._data_to_write_to_remote = [data]
             else:
                 self._data_to_write_to_remote = []
             self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING)
         except (OSError, IOError) as e:
             if eventloop.errno_from_exception(e) == errno.EINPROGRESS:
                 # in this case data is not sent at all
                 self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING)
             elif eventloop.errno_from_exception(e) == errno.ENOTCONN:
                 logging.error('fast open not supported on this OS')
                 self._config['fast_open'] = False
                 self.destroy()
             else:
                 shell.print_exception(e)
                 if self._config['verbose']:
                     traceback.print_exc()
                 self.destroy()
Ejemplo n.º 5
0
    def _handle_dns_resolved(self, result, error):
        if error:
            self._log_error(error)
            self.destroy()
            return
        if result:
            ip = result[1]
            if ip:

                try:
                    self._stage = STAGE_CONNECTING
                    remote_addr = ip
                    if self._is_local:
                        remote_port = self._chosen_server[1]
                    else:
                        remote_port = self._remote_address[1]

                    if self._is_local and self._config['fast_open']:
                        # for fastopen:
                        # wait for more data to arrive and send them in one SYN
                        self._stage = STAGE_CONNECTING
                        # we don't have to wait for remote since it's not
                        # created
                        self._update_stream(STREAM_UP, WAIT_STATUS_READING)
                        # TODO when there is already data in this packet
                    else:
                        # else do connect
                        remote_sock = self._create_remote_socket(
                            remote_addr, remote_port)
                        try:
                            remote_sock.connect((remote_addr, remote_port))
                        except (OSError, IOError) as e:
                            if eventloop.errno_from_exception(e) == \
                                    errno.EINPROGRESS:
                                pass
                        self._loop.add(remote_sock,
                                       eventloop.POLL_ERR | eventloop.POLL_OUT,
                                       self._server)
                        self._stage = STAGE_CONNECTING
                        self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING)
                        self._update_stream(STREAM_DOWN, WAIT_STATUS_READING)
                    return
                except Exception as e:
                    shell.print_exception(e)
                    if self._config['verbose']:
                        traceback.print_exc()
        self.destroy()
Ejemplo n.º 6
0
 def _write_to_sock(self, data, sock):
     # write data to sock
     # if only some of the data are written, put remaining in the buffer
     # and update the stream to wait for writing
     if not data or not sock:
         return False
     uncomplete = False
     try:
         l = len(data)
         s = sock.send(data)
         if s < l:
             data = data[s:]
             uncomplete = True
     except (OSError, IOError) as e:
         error_no = eventloop.errno_from_exception(e)
         if error_no in (errno.EAGAIN, errno.EINPROGRESS,
                         errno.EWOULDBLOCK):
             uncomplete = True
         else:
             shell.print_exception(e)
             self.destroy()
             return False
     if uncomplete:
         if sock == self._local_sock:
             self._data_to_write_to_local.append(data)
             self._update_stream(STREAM_DOWN, WAIT_STATUS_WRITING)
         elif sock == self._remote_sock:
             self._data_to_write_to_remote.append(data)
             self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
         else:
             logging.error('write_all_to_sock:unknown socket')
     else:
         if sock == self._local_sock:
             self._update_stream(STREAM_DOWN, WAIT_STATUS_READING)
         elif sock == self._remote_sock:
             self._update_stream(STREAM_UP, WAIT_STATUS_READING)
         else:
             logging.error('write_all_to_sock:unknown socket')
     return True
Ejemplo n.º 7
0
 def _on_local_read(self):
     # handle all local read events and dispatch them to methods for
     # each stage
     if not self._local_sock:
         return
     is_local = self._is_local
     data = None
     try:
         data = self._local_sock.recv(BUF_SIZE)
     except (OSError, IOError) as e:
         if eventloop.errno_from_exception(e) in \
                 (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK):
             return
     if not data:
         self.destroy()
         return
     self._update_activity(len(data))
     if not is_local:
         data = self._encryptor.decrypt(data)
         if not data:
             return
     if self._stage == STAGE_STREAM:
         if self._is_local:
             data = self._encryptor.encrypt(data)
         self._write_to_sock(data, self._remote_sock)
         return
     elif is_local and self._stage == STAGE_INIT:
         # TODO check auth method
         self._write_to_sock(b'\x05\00', self._local_sock)
         self._stage = STAGE_ADDR
         return
     elif self._stage == STAGE_CONNECTING:
         self._handle_stage_connecting(data)
     elif (is_local and self._stage == STAGE_ADDR) or \
             (not is_local and self._stage == STAGE_INIT):
         self._handle_stage_addr(data)
Ejemplo n.º 8
0
    def _handle_server(self):
        server = self._server_socket
        data, r_addr = server.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_server: data is empty')
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))
        if self._is_local:
            frag = common.ord(data[2])
            if frag != 0:
                logging.warn('drop a message since frag is not 0')
                return
            else:
                data = data[3:]
        else:
            data = encrypt.encrypt_all(self._password, self._method, 0, data)
            # decrypt data
            if not data:
                logging.debug('UDP handle_server: data is empty after decrypt')
                return
        header_result = parse_header(data)
        if header_result is None:
            return
        addrtype, dest_addr, dest_port, header_length = header_result

        if self._is_local:
            server_addr, server_port = self._get_a_server()
        else:
            server_addr, server_port = dest_addr, dest_port

        addrs = self._dns_cache.get(server_addr, None)
        if addrs is None:
            addrs = socket.getaddrinfo(server_addr, server_port, 0,
                                       socket.SOCK_DGRAM, socket.SOL_UDP)
            if not addrs:
                # drop
                return
            else:
                self._dns_cache[server_addr] = addrs

        af, socktype, proto, canonname, sa = addrs[0]
        key = client_key(r_addr, af)
        client = self._cache.get(key, None)
        if not client:
            # TODO async getaddrinfo
            if self._forbidden_iplist:
                if common.to_str(sa[0]) in self._forbidden_iplist:
                    logging.debug('IP %s is in forbidden list, drop' %
                                  common.to_str(sa[0]))
                    # drop
                    return
            client = socket.socket(af, socktype, proto)
            client.setblocking(False)
            self._cache[key] = client
            self._client_fd_to_server_addr[client.fileno()] = r_addr

            self._sockets.add(client.fileno())
            self._eventloop.add(client, eventloop.POLL_IN, self)

        if self._is_local:
            data = encrypt.encrypt_all(self._password, self._method, 1, data)
            if not data:
                return
        else:
            data = data[header_length:]
        if not data:
            return
        try:
            client.sendto(data, (server_addr, server_port))
        except IOError as e:
            err = eventloop.errno_from_exception(e)
            if err in (errno.EINPROGRESS, errno.EAGAIN):
                pass
            else:
                shell.print_exception(e)