def _handle_stage_reply(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']: try: 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) data = ''.join(self._data_to_write_to_local) l = len(data) s = remote_sock.sendto(data, MSG_FASTOPEN, self._chosen_server) if s < l: data = data[s:] self._data_to_write_to_local = [data] self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) else: self._data_to_write_to_local = [] self._update_stream(STREAM_UP, WAIT_STATUS_READING) self._stage = STAGE_STREAM except (OSError, IOError) as e: if eventloop.errno_from_exception(e) == errno.EINPROGRESS: 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: logging.error(e) if self._config['verbose']: traceback.print_exc() self.destroy()
def _handle_stage_connecting(self, data): # 客户端读取web数据进行ota生成,服务器获取客户端数据,进行ota校验 # upstream数据才进行ota,downstream不进行ota # 收到local_sock数据,放到data_to_write_to_remote if self._is_local: # 客户端接收到浏览器的数据要加密 if self._ota_enable: data = self._ota_chunk_data_gen(data) data = self._encryptor.encrypt(data) self._data_to_write_to_remote.append(data) else: # 服务器接收客户端的数据,在数据读取的时候已经解密 if self._ota_enable: self._ota_chunk_data(data, self._data_to_write_to_remote.append) else: 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) # tcp 直接sendto 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()
def _write_to_sock(self, data, sock): if not data or not sock: return 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): uncomplete = True else: logging.error(e) self.destroy() 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')
def _handle_events(self, events): for sock, fd, event in events: # if sock: # logging.debug('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._is_local) except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in (errno.EAGAIN, errno.EINPROGRESS): continue else: logging.error(e) else: if sock: handler = self._fd_to_handlers.get(fd, None) if handler: handler.handle_event(sock, event) else: logging.warn('poll removed fd') now = time.time() if now - self._last_time > TIMEOUT_PRECISION: self._sweep_timeout() self._last_time = now
def _receive_data(self, task): self._active_task(task) _socket = task.task_info["socket"] data = None try: data = _socket.recv(self.conf["buf_size"]) logger.debug("Receive\n%s" % data) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in \ (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return else: self._remove_task(task, why="Receive err") if not data: func = task.task_info["callback"] try: func(task) except: self._remove_task(task, why="Call back err") return else: logger.debug("Finish remove task") self._remove_task(task) # Finish return task.task_info["recv_buf"] += data
def _send_data(self, task): self._active_task(task) _socket = task.task_info["socket"] send_buf = task.task_info["send_buf"] if not send_buf or not _socket: return True uncomplete = False try: s = _socket.send(send_buf) if s < len(send_buf): task.task_info["send_buf"] = send_buf[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: logger.error(e) if self.conf['verbose']: import traceback traceback.print_exc() self._remove_task(task, why="Send error") return False if uncomplete: event = eventloop.POLL_ERR | eventloop.POLL_OUT self.eventloop.modify(_socket, event) else: task.task_info["send_buf"] = "" event = eventloop.POLL_ERR | eventloop.POLL_IN self.eventloop.modify(_socket, event) return True
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)) # 注意,往local发送的数据不经过ota if self._is_local: # 服务器的数据经过加密,客户端进行解密 data = self._encryptor.decrypt(data) else: # 收到web的数据,服务器加密之后才能发给客户端 data = self._encryptor.encrypt(data) try: # 立即就写?写失败也不放到data_write_to_local吗 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()
def _handle_events(self, events): for sock, fd, event in events: if sock: logging.info('fd %d %s', fd, eventloop.EVENT_NAMES.get(event, event)) if sock == self._server_socket: if event & eventloop.EPOLL_ERR: # TODO raise Exception('server_socket error') try: client_sock, address = self._server_socket.accept() logging.info('accept client from %s', address) UserOnServer(self, self._fd_to_users, self._userid_login_status, self._userid_to_fd, self._eventloop, client_sock) except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in (errno.EAGAIN, errno.EINPROGRESS): continue else: logging.error(e) traceback.print_exc() else: if sock: user = self._fd_to_users.get(fd, None) if user: user.handle_event(sock, event) else: logging.warn('poll removed fd')
def write_to_sock(self, data, sock): if not data or not sock: return 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): uncomplete = True else: logging.error(e) self.destroy() 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')
def _run(self): server_socket = self._server_socket self._eventloop.add(server_socket, eventloop.POLL_IN) last_time = time.time() while True: try: events = self._eventloop.poll(10) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) == errno.EPIPE: # Happens when the client closes the connection continue else: logging.error(e) continue for sock, event in events: if sock == self._server_socket: self._handle_server() else: self._handle_client(sock) now = time.time() if now - last_time > 3.5: self._cache.sweep() if now - last_time > 7: self._client_fd_to_server_addr.sweep() last_time = now
def _handle_events(self, events): for sock, fd, event in events: if sock: logging.debug('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._is_local) except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in (errno.EAGAIN, errno.EINPROGRESS): continue else: logging.error(e) 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') now = time.time() if now - self._last_time > TIMEOUT_PRECISION: self._sweep_timeout() self._last_time = now
def _on_remote_read(self): # handle all remote read events data = None if self._is_local: buf_size = UP_STREAM_BUF_SIZE else: buf_size = DOWN_STREAM_BUF_SIZE 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._cryptor.decrypt(data) else: data = self._cryptor.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()
def _on_local_read(self): self._update_activity() 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._server.server_transfer_ul += 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('\x05\00', self._local_sock) self._stage = STAGE_HELLO return elif self._stage == STAGE_REPLY: self._handle_stage_reply(data) elif (is_local and self._stage == STAGE_HELLO) or \ (not is_local and self._stage == STAGE_INIT): self._handle_stage_hello(data)
def callback(self, address, err): if address: ip = address[1] addrs = socket.getaddrinfo(ip, self.port, 0, socket.SOCK_STREAM, socket.SOL_TCP) if len(addrs) == 0: raise Exception("getaddrinfo failed for %s:%d" % (addrs[1], self.port)) print addrs af, socktype, proto, canonname, sa = addrs[0] remote_sock = socket.socket(af, socktype, proto) remote_sock.setblocking(False) remote_sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) self.sock = remote_sock try: self.sock.connect((ip, self.port)) except (OSError, IOError) as e: traceback.print_exc() if eventloop.errno_from_exception(e) == \ errno.EINPROGRESS: pass self.sock.sendall(self.data) eventloop.SockManage.add(self, eventloop.POLL_ERR | eventloop.POLL_OUT) pass
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: # 服务器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: # 其他socket,可能是与客户端的,也可能是web的(相对ssserver) if sock: # 回调之 handler = self._fd_to_handlers.get(fd, None) if handler: handler.handle_event(sock, event) else: logging.warn('poll removed fd')
def _run(self): server_socket = self._server_socket self._eventloop = eventloop.EventLoop() self._eventloop.add(server_socket, eventloop.POLL_IN) last_time = time.time() while not self._closed: try: events = self._eventloop.poll(10) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) == errno.EPIPE: # Happens when the client closes the connection continue else: logging.error(e) continue for sock, event in events: if sock == self._server_socket: self._handle_server() else: self._handle_client(sock) now = time.time() if now - last_time > 3.5: self._cache.sweep() if now - last_time > 7: self._client_fd_to_server_addr.sweep() last_time = now
def _on_remote_read(self): self._update_activity() 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._server.server_transfer_dl += 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: logging.error(e) if self._config['verbose']: traceback.print_exc() # TODO use logging when debug completed self.destroy()
def handle_tcp(sock, remote, encryptor, pending_data=None, server=None, port=None): connected = False try: if config_fast_open: fdset = [sock] else: fdset = [sock, remote] while True: should_break = False r, w, e = select.select(fdset, [], [], config_timeout) if not r: logging.warn('read time out') break if sock in r: if not connected and config_fast_open: data = sock.recv(4096) data = encryptor.encrypt(pending_data + data) pending_data = None logging.info('fast open %s:%d' % (server, port)) try: remote.sendto(data, MSG_FASTOPEN, (server, port)) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) == errno.EINPROGRESS: pass else: raise e connected = True fdset = [sock, remote] else: data = sock.recv(4096) if pending_data: data = pending_data + data pending_data = None data = encryptor.encrypt(data) if len(data) <= 0: should_break = True else: result = send_all(remote, data) if result < len(data): raise Exception('failed to send all data') if remote in r: data = encryptor.decrypt(remote.recv(4096)) if len(data) <= 0: should_break = True else: result = send_all(sock, data) if result < len(data): raise Exception('failed to send all data') if should_break: # make sure all data are read before we close the sockets # TODO: we haven't read ALL the data, actually # http://cs.ecs.baylor.edu/~donahoo/practical/CSockets/TCPRST.pdf break finally: sock.close() remote.close()
def _handle_server(self): server = self._server_socket data, r_addr = server.recvfrom(BUF_SIZE) if self._is_local: frag = ord(data[2]) if frag != 0: logging.warn('drop a message since frag is not 0') return else: data = data[3:] else: # decrypt data data = encrypt.encrypt_all(self._password, self._method, 0, data) if not data: 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._remote_addr, self._remote_port else: server_addr, server_port = dest_addr, dest_port key = client_key(r_addr[0], r_addr[1], dest_addr, dest_port) client = self._cache.get(key, None) if not client: # TODO async getaddrinfo addrs = socket.getaddrinfo(server_addr, server_port, 0, socket.SOCK_DGRAM, socket.SOL_UDP) if addrs: af, socktype, proto, canonname, sa = addrs[0] client = socket.socket(af, socktype, proto) client.setblocking(False) self._cache[key] = client self._client_fd_to_server_addr[client.fileno()] = r_addr else: # drop return self._sockets.add(client.fileno()) self._eventloop.add(client, eventloop.POLL_IN) data = data[header_length:] if not data: return if self._is_local: data = encrypt.encrypt_all(self._password, self._method, 1, data) 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: logging.error(e)
def _handle_stage_connecting(self, data): if not self._is_local: if self._ota_enable_session: self._ota_chunk_data(data, self._data_to_write_to_remote.append) else: self._data_to_write_to_remote.append(data) return if self._ota_enable_session: data = self._ota_chunk_data_gen(data) data = self._cryptor.encrypt(data) self._data_to_write_to_remote.append(data) if self._config['fast_open'] and not self._fastopen_connected: # 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()
def _handle_dns_resolved(self, result, error): if error: logging.error(error) self.destroy() return if result: ip = result[1] if ip: try: self._stage = STAGE_REPLY remote_addr = self._remote_address[0] remote_port = self._remote_address[1] if self._is_local: remote_addr, remote_port = self._chosen_server addrs = socket.getaddrinfo(ip, remote_port, 0, socket.SOCK_STREAM, socket.SOL_TCP) if len(addrs) == 0: raise Exception("getaddrinfo failed for %s:%d" % (remote_addr, remote_port)) af, socktype, proto, canonname, sa = addrs[0] remote_sock = socket.socket(af, socktype, proto) self._remote_sock = remote_sock self._fd_to_handlers[remote_sock.fileno()] = self remote_sock.setblocking(False) remote_sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) if self._is_local and self._config['fast_open']: # wait for more data to arrive and send them in one SYN self._stage = STAGE_REPLY self._loop.add(remote_sock, eventloop.POLL_ERR) self._update_stream(STREAM_UP, WAIT_STATUS_READING) # TODO when there is already data in this packet else: try: remote_sock.connect(sa) 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._stage = STAGE_REPLY self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) return except (OSError, IOError) as e: logging.error(e) if self._config['verbose']: traceback.print_exc() self.destroy()
def handle_tcp(sock, remote, encryptor, pending_data=None, server=None, port=None): connected = False try: if config_fast_open: fdset = [sock] else: fdset = [sock, remote] while True: r, w, e = select.select(fdset, [], []) if sock in r: if not connected and config_fast_open: data = sock.recv(4096) data = encryptor.encrypt(pending_data + data) pending_data = None logging.info('fast open %s:%d' % (server, port)) try: remote.sendto(data, MSG_FASTOPEN, (server, port)) except (OSError, IOError) as e: if eventloop.errno_from_exception( e) == errno.EINPROGRESS: pass else: raise e connected = True fdset = [sock, remote] else: data = sock.recv(4096) if pending_data: data = pending_data + data pending_data = None data = encryptor.encrypt(data) if len(data) <= 0: break result = send_all(remote, data) if result < len(data): raise Exception('failed to send all data') if remote in r: data = encryptor.decrypt(remote.recv(4096)) if len(data) <= 0: break result = send_all(sock, data) if result < len(data): raise Exception('failed to send all data') finally: sock.close() remote.close()
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()
def _handle_dns_resolved(self, result, error): # 解析成功,remote_sock连接远端,开始收发数据 # 状态变为STAGE_CONNECTING if error: self._log_error(error) self.destroy() return if result and result[1]: ip = result[1] try: self._stage = STAGE_CONNECTING remote_addr = ip if self._is_local: # sslocal得到ssserver的端口 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 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 # 服务器创建连接远程的socket 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()
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) 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()
def _on_local_read(self): data = None try: data = self.sock.recv(BUF_SIZE) print data self.data.append(data) context = "".join(self.data) if not data and context.strip(): RemoteSockHandler(context, self) self.destroy() except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in \ (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return self.destroy()
def _on_remote_write(self): data = None try: data = self.sock.recv(BUF_SIZE) print data if data: self.local_sock_handler.sock.send(data) if not data: self.destroy() pass except (OSError, IOError) as e: if eventloop.errno_from_exception(e) in \ (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return self.destroy() pass
def handle_tcp(sock, remote, encryptor, pending_data=None, server=None, port=None): connected = False try: if config_fast_open: fdset = [sock] else: fdset = [sock, remote] while True: r, w, e = select.select(fdset, [], []) if sock in r: if not connected and config_fast_open: data = sock.recv(4096) data = encryptor.encrypt(pending_data + data) pending_data = None logging.info('fast open %s:%d' % (server, port)) try: remote.sendto(data, MSG_FASTOPEN, (server, port)) except (OSError, IOError) as e: if eventloop.errno_from_exception(e) == errno.EINPROGRESS: pass else: raise e connected = True fdset = [sock, remote] else: data = sock.recv(4096) if pending_data: data = pending_data + data pending_data = None data = encryptor.encrypt(data) if len(data) <= 0: break result = send_all(remote, data) if result < len(data): raise Exception('failed to send all data') if remote in r: data = encryptor.decrypt(remote.recv(4096)) if len(data) <= 0: break result = send_all(sock, data) if result < len(data): raise Exception('failed to send all data') finally: sock.close() remote.close()
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._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()
def _handle_events(self, events): # handle events and dispatch to handlers for sock, fd, event in events: 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): continue 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') now = time.time() if now - self._last_time > TIMEOUT_PRECISION: self._sweep_timeout() self._last_time = now if self._closed: if self._server_socket: self._eventloop.remove(self._server_socket) self._server_socket.close() self._server_socket = None logging.info('closed listen port %d', self._listen_port) if not self._fd_to_handlers: self._eventloop.remove_handler(self._handle_events)
def _handle_events(self, events): # handle events and dispatch to handlers for sock, fd, event in events: 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): continue 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') now = time.time() if now - self._last_time > TIMEOUT_PRECISION: self._sweep_timeout() self._last_time = now if self._closed: if self._server_socket: self._eventloop.remove(self._server_socket) self._server_socket.close() self._server_socket = None logging.info('closed listen port %d', self._listen_port) if not self._fd_to_handlers:
def _handle_dns_resolved(self, result, error): if error: addr, port = self._client_address[0], self._client_address[1] logging.error('%s when handling connection from %s:%d' % (error, addr, port)) self.destroy() return if not (result and result[1]): self.destroy() return ip = result[1] 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 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)
def write_to_server_socket(self, data, addr): uncomplete = False retry = 0 try: self._server_socket.sendto(data, addr) data = None while self._data_to_write_to_server_socket: data_buf = self._data_to_write_to_server_socket[0] retry = data_buf[1] + 1 del self._data_to_write_to_server_socket[0] data, addr = data_buf[0] self._server_socket.sendto(data, addr) except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) uncomplete = True if error_no in (errno.EWOULDBLOCK, ): pass else: logging.error(e) return False
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_REPLY 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']: # wait for more data to arrive and send them in one SYN self._stage = STAGE_REPLY self._update_stream(STREAM_UP, WAIT_STATUS_READING) # TODO when there is already data in this packet else: 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._stage = STAGE_REPLY self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) return except (OSError, IOError) as e: logging.error(e) if self._config['verbose']: traceback.print_exc() self.destroy()
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
def _handle_events(self, events): for sock, fd, event in events: if sock: logging.log(utils.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): continue else: logging.error(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") now = time.time() if now - self._last_time > TIMEOUT_PRECISION: self._sweep_timeout() self._last_time = now
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 if is_local: buf_size = UP_STREAM_BUF_SIZE else: buf_size = DOWN_STREAM_BUF_SIZE 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._cryptor.decrypt(data) if not data: return if self._stage == STAGE_STREAM: self._handle_stage_stream(data) return elif is_local and self._stage == STAGE_INIT: # jump over socks5 init if self._is_tunnel: self._handle_stage_addr(data) return else: self._handle_stage_init(data) 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)
def handle_event(self, sock, fd, event): if sock: print 'handle fd %d %s' % (fd, eventloop.EVENT_NAMES.get(event, event)) # (bt) new connection trigger server_socket if sock == self._server_socket: if event & eventloop.POLL_ERR: raise Exception('server_socket error') try: logging.debug('accept') conn = self._server_socket.accept() conn_sock = conn[0] conn_sock.setblocking(False) conn_sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) # (bt) self is the handler loop = self._eventloop loop.add(conn_sock, eventloop.POLL_IN | eventloop.POLL_ERR, self) except (OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK): return else: print("%s" % str(e)) else: if sock: data = None try: data = sock.recv(BUF_SIZE) except (OSError, IOError) as e: return if not data: return print "reveived: %s" % data sock.send("hello, world") self.close_connection(sock) else: logging.warn('poll removed fd')
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
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: # socket读取数据 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: # socket关闭 self.destroy() return # 更新活动时间哟,不然server以为超时会被close的 self._update_activity(len(data)) if not is_local: # 服务器端的,解密呀 data = self._encryptor.decrypt(data) if not data: return if self._stage == STAGE_STREAM: self._handle_stage_stream(data) return elif is_local and self._stage == STAGE_INIT: # sslocal客户端的初始socket self._handle_stage_init(data) 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): # 服务器收到连,建立通信,或者客户端STAGE_ADDR self._handle_stage_addr(data)
def _handle_dns_resolved(self, result, error): if error: logging.error(error) self.destroy() return if result: ip = result[1] if ip: try: self._stage = STAGE_REPLY 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"]: # wait for more data to arrive and send them in one SYN self._stage = STAGE_REPLY self._update_stream(STREAM_UP, WAIT_STATUS_READING) # TODO when there is already data in this packet else: 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._stage = STAGE_REPLY self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) return except (OSError, IOError) as e: logging.error(e) if self._config["verbose"]: traceback.print_exc() self.destroy()
def on_remote_read(self): self.update_activity() 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): return if not data: self.destroy() return 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: import traceback traceback.print_exc() # TODO use logging when debug completed self.destroy()
def _on_remote_read(self): self._update_activity() 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): return if not data: self.destroy() return 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: import traceback traceback.print_exc() # TODO use logging when debug completed self.destroy()
def _on_local_read(self): # handle all local read events and dispatch them to methods for # each stage self._update_activity() 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._server.server_transfer_ul += 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)
def _write_to_sock(self, data, sock): 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: logging.error(e) if self._config["verbose"]: traceback.print_exc() 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
def on_local_read(self): self.update_activity() 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): return if not data: self.destroy() return 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('\x05\00', self._local_sock) self._stage = STAGE_HELLO return elif self._stage == STAGE_REPLY: if is_local: data = self._encryptor.encrypt(data) self._data_to_write_to_remote.append(data) elif (is_local and self._stage == STAGE_HELLO) or \ (not is_local and self._stage == STAGE_INIT): try: if is_local: cmd = ord(data[1]) if cmd == CMD_UDP_ASSOCIATE: logging.debug('UDP associate') if self._local_sock.family == socket.AF_INET6: header = '\x05\x00\x00\x04' else: header = '\x05\x00\x00\x01' addr, port = self._local_sock.getsockname() addr_to_send = socket.inet_pton(self._local_sock.family, addr) port_to_send = struct.pack('>H', port) self.write_to_sock(header + addr_to_send + port_to_send, self._local_sock) self._stage = STAGE_UDP_ASSOC # just wait for the client to disconnect return elif cmd == CMD_CONNECT: # just trim VER CMD RSV data = data[3:] else: logging.error('unknown command %d', cmd) self.destroy() return header_result = parse_header(data) if header_result is None: raise Exception('can not parse header') addrtype, remote_addr, remote_port, header_length =\ header_result logging.info('connecting %s:%d' % (remote_addr, remote_port)) self._remote_address = (remote_addr, remote_port) if is_local: # forward address to remote self.write_to_sock('\x05\x00\x00\x01' + '\x00\x00\x00\x00\x10\x10', self._local_sock) data_to_send = self._encryptor.encrypt(data) self._data_to_write_to_remote.append(data_to_send) remote_addr = self._config['server'] remote_port = self._config['server_port'] else: if len(data) > header_length: self._data_to_write_to_remote.append( data[header_length:]) # TODO async DNS addrs = socket.getaddrinfo(remote_addr, remote_port, 0, socket.SOCK_STREAM, socket.SOL_TCP) if len(addrs) == 0: raise Exception("can't get addrinfo for %s:%d" % (remote_addr, remote_port)) af, socktype, proto, canonname, sa = addrs[0] remote_sock = socket.socket(af, socktype, proto) self._remote_sock = remote_sock self._fd_to_handlers[remote_sock.fileno()] = self remote_sock.setblocking(False) remote_sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) # TODO support TCP fast open try: remote_sock.connect(sa) 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._stage = STAGE_REPLY self.update_stream(STREAM_UP, WAIT_STATUS_READWRITING) self.update_stream(STREAM_DOWN, WAIT_STATUS_READING) return except Exception: import traceback traceback.print_exc() # TODO use logging when debug completed self.destroy()
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._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) logging.debug(key) 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) 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)
def _handle_stage_hello(self, data): try: if self._is_local: cmd = ord(data[1]) if cmd == CMD_UDP_ASSOCIATE: logging.debug('UDP associate') if self._local_sock.family == socket.AF_INET6: header = '\x05\x00\x00\x04' else: header = '\x05\x00\x00\x01' addr, port = self._local_sock.getsockname() addr_to_send = socket.inet_pton(self._local_sock.family, addr) port_to_send = struct.pack('>H', port) self._write_to_sock(header + addr_to_send + port_to_send, self._local_sock) self._stage = STAGE_UDP_ASSOC # just wait for the client to disconnect return elif cmd == CMD_CONNECT: # just trim VER CMD RSV data = data[3:] else: logging.error('unknown command %d', cmd) self.destroy() return header_result = parse_header(data) if header_result is None: raise Exception('can not parse header') addrtype, remote_addr, remote_port, header_length = header_result logging.info('connecting %s:%d' % (remote_addr, remote_port)) self._remote_address = (remote_addr, remote_port) if self._is_local: # forward address to remote self._write_to_sock('\x05\x00\x00\x01\x00\x00\x00\x00\x10\x10', self._local_sock) data_to_send = self._encryptor.encrypt(data) self._data_to_write_to_remote.append(data_to_send) remote_addr = self._config['server'] remote_port = self._config['server_port'] else: if len(data) > header_length: self._data_to_write_to_remote.append(data[header_length:]) # TODO async DNS addrs = socket.getaddrinfo(remote_addr, remote_port, 0, socket.SOCK_STREAM, socket.SOL_TCP) if len(addrs) == 0: raise Exception("can't get addrinfo for %s:%d" % (remote_addr, remote_port)) af, socktype, proto, canonname, sa = addrs[0] remote_sock = socket.socket(af, socktype, proto) self._remote_sock = remote_sock self._fd_to_handlers[remote_sock.fileno()] = self remote_sock.setblocking(False) remote_sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) if self._is_local and self._config['fast_open']: # wait for more data to arrive and send them in one SYN self._stage = STAGE_REPLY self._loop.add(remote_sock, eventloop.POLL_ERR) # TODO when there is already data in this packet else: try: remote_sock.connect(sa) 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._stage = STAGE_REPLY self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) except Exception as e: logging.error(e) traceback.print_exc() # TODO use logging when debug completed self.destroy()