Esempio n. 1
0
    def run(self):
        self._stopping = False
        events = []
        while not self._stopping:
            asap = False
            try:
                events = self.poll(TIMEOUT_PRECISION)
            except (OSError, IOError) as e:
                if utils.errno_from_exception(e) in (errno.EPIPE, errno.EINTR):
                    # EPIPE: Happens when the client closes the connection
                    # EINTR: Happens when received a signal
                    # handles them as soon as possible
                    asap = True
                    print('poll:%s', e)
                else:
                    print('poll:%s', e)
                    import traceback
                    traceback.print_exc()
                    continue

            for sock, fd, event in events:
                handler = self._fdmap.get(fd, None)
                if handler is not None:
                    handler = handler[1]
                    try:
                        if not getattr(handler, "_keepalive", False):
                            self._timeout.update_activity(fd, handler)
                        handler.handle_events(sock, fd, event)
                    except (OSError, IOError) as e:
                        print(e)
            now = time.time()
            if asap or now - self._last_time >= TIMEOUT_PRECISION:
                self._timeout.cleanup()
                self._last_time = now
        print("proxy service stopped!!!")
Esempio n. 2
0
    def _create_peer_socket(self, ip, port):
        addrs = socket.getaddrinfo(ip, port, 0, socket.SOCK_STREAM,
                                   socket.SOL_TCP)
        if len(addrs) == 0:
            raise Exception("getaddrinfo failed for %s:%d" % (ip, port))
        af, socktype, proto, canonname, sa = addrs[0]
        sock = socket.socket(af, socktype, proto)
        sock.setblocking(False)
        sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
        try:
            sock.connect(sa)
        except (OSError, IOError) as e:
            err = utils.errno_from_exception(e)
            if err not in _ERRNO_INPROGRESS and \
                err not in _ERRNO_WOULDBLOCK:
                self.destroy()
                return

        peer_handler = self.__class__(self.io_loop, sock, sa,
                                      self._dns_resolver, self.HDL_POSITIVE)
        peer_handler._direct_conn = self._direct_conn
        self.relate(peer_handler)
        peer_handler.relate(self)

        event = IOLoop.WRITE if peer_handler.writable else None
        peer_handler.register(event)
        self._status = self.STAGE_PEER_CONNECTED
        peer_handler._status = self.STAGE_PEER_CONNECTED
Esempio n. 3
0
 def on_recv_syn(self):
     if self._status == self.STAGE_CLOSED:
         logging.warning("read on closed socket!")
         self.destroy()
         return
     data = None
     try:
         data = self._sock.recv(self.BUF_SIZE)
     except (OSError, IOError) as e:
         if utils.errno_from_exception(e) in \
             (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK):
             return
     if not data:
         self.destroy()
         return
     cmd = utils.ord(data[1])
     if cmd == socks5.CMD_UDPFWD:
         logging.debug('UDP associate')
         if self._sock.family == socket.AF_INET6:
             header = b'\x05\x00\x00\x04'
         else:
             header = b'\x05\x00\x00\x01'
         addr, port = self._sock.getsockname()[:2]
         addr_to_send = socket.inet_pton(self._sock.family, addr)
         port_to_send = struct.pack('>H', port)
         data = header + addr_to_send + port_to_send
         self._write_buf.append(data)  # send back ack
         self._wbuf_size += len(data)
         return
     elif cmd == socks5.CMD_CONNECT:
         data = data[3:]
     else:
         logging.error('unknown command %d', cmd)
         self.destroy()
         return
     self._append_to_rbuf(data)
     utils.merge_prefix(self._read_buf, self.BUF_SIZE)
     if not self._read_buf:
         return
     data = self._read_buf[0]
     header_result = socks5.parse_header(data)
     if not header_result:
         return
     addrtype, remote_addr, remote_port, header_length = header_result
     logging.info("connecting %s:%d from %s:%d" % (\
         (remote_addr, remote_port, ) +  self._addr))
     data = self._pop_from_rbuf(self.BUF_SIZE)
     self._status = self.STAGE_SOCKS5_SYN
     ack, l = socks5.gen_ack()
     self._write_buf.append(ack)  # send back ack
     self._wbuf_size += l
     if self._exclusive_host(remote_addr):  #
         self._append_to_rbuf(data, codec=True)
         self._peer_addr = self._sshost()  # connect ssserver
     else:
         self._direct_conn = True
         self._peer_addr = (utils.to_str(remote_addr), remote_port)  #直连
     self._dns_resolver.resolve(self._peer_addr[0], self._on_dns_resolved)
Esempio n. 4
0
    def on_write(self):
        # NOTICE 写数据时, 都是从对方的read_buf取出数据写的
        num_bytes = 0
        peer_handler = self.peer     
               
        if not peer_handler:    # if peer not created
            write_buf = self._write_buf
        else:
            write_buf = peer_handler._read_buf
            if self._write_buf:     
                # self._write_buf中一般不会有数据, 有数据时
                # peer_handler._read_buf肯定为空, 此次操作
                # 时间为O(1)
                utils.merge_prefix(self._write_buf, self.BUF_SIZE)                    
                data = self._write_buf.popleft()
                write_buf.appendleft(data)   
                peer_handler._rbuf_size += len(data)
                self._wbuf_size -= len(data)


        if not write_buf:
            return num_bytes
        utils.merge_prefix(write_buf, self.BUF_SIZE)
        while write_buf:
            try:
                if not self._sock:
                    break
                length = self._sock.send(write_buf[0])
                if length:
                    utils.merge_prefix(write_buf, length)
                    write_buf.popleft()
                    num_bytes += length
                else:
                    break
            except (socket.error, IOError, OSError) as e:
                error_no = utils.errno_from_exception(e)
                if error_no in (errno.EAGAIN, errno.EINPROGRESS,
                                errno.EWOULDBLOCK):     # 缓冲区满
                    break
                else:
                    logging.error(e)
                    self.destroy()
                    break
        if not peer_handler:
            self._wbuf_size -= num_bytes
        else:
            peer_handler._rbuf_size -= num_bytes
        logging.info("send {:6d} B to   {:15s}:{:5d} ".format(num_bytes, *self._addr))
        return num_bytes
Esempio n. 5
0
 def handle_events(self, sock, fd, events):
     if self._status == self.STAGE_CLOSED:
         logging.warning("handler destoryed!")
         return
     if events & self.io_loop.ERROR:
         self.destroy()
         raise Exception('server_socket error')
     try:
         conn, addr = self._sock.accept()
         logging.debug("accept %s:%d" % addr)
         handler = self._conn_hd_cls(self.io_loop, conn, addr,
                                     self._dns_resolver, self.HDL_NEGATIVE)
         handler.register()
     except (OSError, IOError) as e:
         err_no = utils.errno_from_exception(e)
         if err_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK):
             return
         else:
             logging.error("fatal error: %s" % e)
Esempio n. 6
0
 def on_recv_nego(self):
     if self._status == self.STAGE_CLOSED:
         logging.warning("read on closed socket!")
         self.destroy()
         return
     data = None
     try:
         data = self._sock.recv(self.BUF_SIZE)
     except (OSError, IOError) as e:
         if utils.errno_from_exception(e) in \
             (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK):
             return
     if not data:
         self.destroy()
         return
     resp, length = self._nego_response(data)
     self._write_buf.append(resp)
     self._wbuf_size += length
     self._status = self.STAGET_SOCKS5_NEGO
     return
Esempio n. 7
0
 def on_read(self):
     data = None
     if not self._sock:
         return
     try:
         data = self._sock.recv(self.BUF_SIZE)
     except (OSError, IOError) as e:
         if utils.errno_from_exception(e) in \
                 (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK):
             return
     if not data:
         self.destroy()
         return
     data = self._codec(data)
     self._read_buf.append(data)
     date_length = len(data)
     self._rbuf_size += date_length
     logging.info("recv {:6d} B from {:15s}:{:5d} ".format(date_length, *self._addr))
     if self._rbuf_size >= self.MAX_BUF_SIZE:
         logging.warn("connection: %s:%d read buffer over flow!" % self._addr)
         self.destroy()
Esempio n. 8
0
 def pre_dns_resolved(self, data, hostname, port, r_addr, result, error):
     if error:
         logging.error(error)
         return
     if not result: return
     ip = result[1]
     if not ip: return
     addrs = socket.getaddrinfo(ip, port, 0, socket.SOCK_DGRAM,
                                socket.SOL_UDP)  # for ip, will block??
     if not addrs:
         return
     af, socktype, proto, canonname, sa = addrs[0]
     peer_sock = self.peer_sock((ip, port), af, r_addr)
     try:
         if peer_sock:
             peer_sock.sendto(data, (ip, port))
     except IOError as e:
         err = utils.errno_from_exception(e)
         if err in (errno.EINPROGRESS, errno.EAGAIN):
             pass
         else:
             logging.error(e, exc_info=True)
Esempio n. 9
0
 def on_recv_syn(self):
     if self._status == self.STAGE_CLOSED:
         logging.warning("read on closed socket!")
         self.destroy()
         return
     data = None
     try:
         data = self._sock.recv(self.BUF_SIZE)
     except (OSError, IOError) as e:
         if utils.errno_from_exception(e) in \
             (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK):
             return
     if not data:
         self.destroy()
         return
     self._append_to_rbuf(data)  # method from BaseTcpHandler
     try:
         http_request = self.read_until("\r\n\r\n")
         if not http_request:
             return
         http_response, ss_premble, addr = http2shadosocks(http_request)
         if http_response:
             self._write_buf.append(http_response)
             self._wbuf_size += len(http_response)
         if self._exclusive_host(addr[0]):
             self._append_to_rbuf(ss_premble, codec=True)
             self._peer_addr = self._sshost()  # connect ssserver
         else:
             self._direct_conn = True
             self._peer_addr = addr
         self._status = self.STAGE_SOCKS5_SYN
         self._dns_resolver.resolve(self._peer_addr[0],
                                    self._on_dns_resolved)
     except HttpRequestError as e:
         logging.warn(e)
         self.destroy()
         return
Esempio n. 10
0
    def on_recv_syn(self):
        if self._status == self.STAGE_CLOSED:
            logging.warning("read on closed socket!")
            self.destroy()
            return
        data = None
        try:
            data = self._sock.recv(self.BUF_SIZE)
        except (OSError, IOError) as e:
            if utils.errno_from_exception(e) in \
                (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK):
                return
        if not data:
            self.destroy()
            return
        self._append_to_rbuf(data, codec=True)

        utils.merge_prefix(self._read_buf, self.BUF_SIZE)
        if not self._read_buf:
            return
        data = self._read_buf[0]
        header_result = socks5.parse_header(data)
        if not header_result:
            return
        addrtype, remote_addr, remote_port, header_length = header_result
        self._pop_from_rbuf(header_length)

        self._status = self.STAGE_SOCKS5_SYN
        logging.info("connecting %s:%d from %s:%d" % (\
            (remote_addr, remote_port, ) +  self._addr))
        self._peer_addr = (utils.to_str(remote_addr), remote_port)
        try:
            self._dns_resolver.resolve(remote_addr, self._on_dns_resolved)
        except Exception as e:
            logging.error(e)
            self.destroy()