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)
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 ""
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()
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
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