Esempio n. 1
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. 2
0
 def read_until(self, regex, maxrange=None):
     if not self._read_buf:
         return ""
     maxrange = maxrange or self.MAX_HEADER_LEN
     utils.merge_prefix(self._read_buf, maxrange)
     pattern = re.compile(regex)
     m = pattern.search(self._read_buf[0])
     if m:
         endpos = m.end()
         utils.merge_prefix(self._read_buf, endpos)
         data = self._read_buf.popleft()
         self._rbuf_size -= endpos
         return data
     else:
         if len(self._read_buf[0]) >= maxrange:
             # not found regex in specified range
             # bad request, need to close socket soon
             raise HttpRequestError(413, "Entity Too Large")
         else:
             # need more data
             return ""
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
        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()
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 _pop_from_rbuf(self, bufsize):
     utils.merge_prefix(self._read_buf, bufsize)
     data = self._read_buf.popleft()
     self._rbuf_size -= len(data)
     return data