| 
						
						
							
								
							
						
						
					 | 
					@ -115,6 +115,7 @@ class TCPRelayHandler(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self._fastopen_connected = False | 
					 | 
					 | 
					        self._fastopen_connected = False | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self._data_to_write_to_local = [] | 
					 | 
					 | 
					        self._data_to_write_to_local = [] | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self._data_to_write_to_remote = [] | 
					 | 
					 | 
					        self._data_to_write_to_remote = [] | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        self._udp_data_send_buffer = '' | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self._upstream_status = WAIT_STATUS_READING | 
					 | 
					 | 
					        self._upstream_status = WAIT_STATUS_READING | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self._downstream_status = WAIT_STATUS_INIT | 
					 | 
					 | 
					        self._downstream_status = WAIT_STATUS_INIT | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self._client_address = local_sock.getpeername()[:2] | 
					 | 
					 | 
					        self._client_address = local_sock.getpeername()[:2] | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -128,7 +129,8 @@ class TCPRelayHandler(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        fd_to_handlers[local_sock.fileno()] = self | 
					 | 
					 | 
					        fd_to_handlers[local_sock.fileno()] = self | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        local_sock.setblocking(False) | 
					 | 
					 | 
					        local_sock.setblocking(False) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        local_sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) | 
					 | 
					 | 
					        local_sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        loop.add(local_sock, eventloop.POLL_IN | eventloop.POLL_ERR) | 
					 | 
					 | 
					        loop.add(local_sock, eventloop.POLL_IN | eventloop.POLL_ERR, | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                 self._server) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self.last_activity = 0 | 
					 | 
					 | 
					        self.last_activity = 0 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self._update_activity() | 
					 | 
					 | 
					        self._update_activity() | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -185,6 +187,8 @@ class TCPRelayHandler(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                if self._upstream_status & WAIT_STATUS_WRITING: | 
					 | 
					 | 
					                if self._upstream_status & WAIT_STATUS_WRITING: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    event |= eventloop.POLL_OUT | 
					 | 
					 | 
					                    event |= eventloop.POLL_OUT | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                self._loop.modify(self._remote_sock, event) | 
					 | 
					 | 
					                self._loop.modify(self._remote_sock, event) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                if self._remote_sock_v6: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                    self._loop.modify(self._remote_sock_v6, event) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    def _write_to_sock(self, data, sock): | 
					 | 
					 | 
					    def _write_to_sock(self, data, sock): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        # write data to sock | 
					 | 
					 | 
					        # write data to sock | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -193,20 +197,33 @@ class TCPRelayHandler(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        if not data or not sock: | 
					 | 
					 | 
					        if not data or not sock: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            return False | 
					 | 
					 | 
					            return False | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        #logging.debug("_write_to_sock %s %s %s" % (self._remote_sock, sock, self._remote_udp)) | 
					 | 
					 | 
					        #logging.debug("_write_to_sock %s %s %s" % (self._remote_sock, sock, self._remote_udp)) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        if self._remote_udp and self._remote_sock == sock: | 
					 | 
					 | 
					        uncomplete = False | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        if self._remote_udp and sock == self._remote_sock: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            try: | 
					 | 
					 | 
					            try: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                self._udp_data_send_buffer += data | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                #logging.info('UDP over TCP sendto %d %s' % (len(data), binascii.hexlify(data))) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                while len(self._udp_data_send_buffer) > 6: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                    length = struct.unpack('>H', self._udp_data_send_buffer[:2])[0] | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                    if length > len(self._udp_data_send_buffer): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                        break | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                    data = self._udp_data_send_buffer[:length] | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                    self._udp_data_send_buffer = self._udp_data_send_buffer[length:] | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    frag = common.ord(data[2]) | 
					 | 
					 | 
					                    frag = common.ord(data[2]) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    if frag != 0: | 
					 | 
					 | 
					                    if frag != 0: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        logging.warn('drop a message since frag is %d' % (frag,)) | 
					 | 
					 | 
					                        logging.warn('drop a message since frag is %d' % (frag,)) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                    return False | 
					 | 
					 | 
					                        continue | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					                    else: | 
					 | 
					 | 
					                    else: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        data = data[3:] | 
					 | 
					 | 
					                        data = data[3:] | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    header_result = parse_header(data) | 
					 | 
					 | 
					                    header_result = parse_header(data) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    if header_result is None: | 
					 | 
					 | 
					                    if header_result is None: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                    return False | 
					 | 
					 | 
					                        continue | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					                    connecttype, dest_addr, dest_port, header_length = header_result | 
					 | 
					 | 
					                    connecttype, dest_addr, dest_port, header_length = header_result | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    addrs = socket.getaddrinfo(dest_addr, dest_port, 0, | 
					 | 
					 | 
					                    addrs = socket.getaddrinfo(dest_addr, dest_port, 0, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                            socket.SOCK_DGRAM, socket.SOL_UDP) | 
					 | 
					 | 
					                            socket.SOCK_DGRAM, socket.SOL_UDP) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                    #logging.info('UDP over TCP sendto %s:%d %d bytes from %s:%d' % (dest_addr, dest_port, len(data), self._client_address[0], self._client_address[1])) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    if addrs: | 
					 | 
					 | 
					                    if addrs: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        af, socktype, proto, canonname, server_addr = addrs[0] | 
					 | 
					 | 
					                        af, socktype, proto, canonname, server_addr = addrs[0] | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        data = data[header_length:] | 
					 | 
					 | 
					                        data = data[header_length:] | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -218,10 +235,16 @@ class TCPRelayHandler(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            except Exception as e: | 
					 | 
					 | 
					            except Exception as e: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                #trace = traceback.format_exc() | 
					 | 
					 | 
					                #trace = traceback.format_exc() | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                #logging.error(trace) | 
					 | 
					 | 
					                #logging.error(trace) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                logging.error(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 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            return True | 
					 | 
					 | 
					            return True | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					
 | 
					 | 
					 | 
					        else: | 
				
			
			
				
				
			
		
	
		
		
			
				
					 | 
					 | 
					        uncomplete = False | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					            try: | 
					 | 
					 | 
					            try: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                l = len(data) | 
					 | 
					 | 
					                l = len(data) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                s = sock.send(data) | 
					 | 
					 | 
					                s = sock.send(data) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -270,7 +293,7 @@ class TCPRelayHandler(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                remote_sock = \ | 
					 | 
					 | 
					                remote_sock = \ | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    self._create_remote_socket(self._chosen_server[0], | 
					 | 
					 | 
					                    self._create_remote_socket(self._chosen_server[0], | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                               self._chosen_server[1]) | 
					 | 
					 | 
					                                               self._chosen_server[1]) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                self._loop.add(remote_sock, eventloop.POLL_ERR) | 
					 | 
					 | 
					                self._loop.add(remote_sock, eventloop.POLL_ERR, self._server) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					                data = b''.join(self._data_to_write_to_remote) | 
					 | 
					 | 
					                data = b''.join(self._data_to_write_to_remote) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                l = len(data) | 
					 | 
					 | 
					                l = len(data) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                s = remote_sock.sendto(data, MSG_FASTOPEN, self._chosen_server) | 
					 | 
					 | 
					                s = remote_sock.sendto(data, MSG_FASTOPEN, self._chosen_server) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -382,6 +405,11 @@ class TCPRelayHandler(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            remote_sock_v6 = socket.socket(af, socktype, proto) | 
					 | 
					 | 
					            remote_sock_v6 = socket.socket(af, socktype, proto) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            self._remote_sock_v6 = remote_sock_v6 | 
					 | 
					 | 
					            self._remote_sock_v6 = remote_sock_v6 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            self._fd_to_handlers[remote_sock_v6.fileno()] = self | 
					 | 
					 | 
					            self._fd_to_handlers[remote_sock_v6.fileno()] = self | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            remote_sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1024 * 32) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            remote_sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024 * 32) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            remote_sock_v6.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1024 * 32) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            remote_sock_v6.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024 * 32) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        remote_sock.setblocking(False) | 
					 | 
					 | 
					        remote_sock.setblocking(False) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        if self._remote_udp: | 
					 | 
					 | 
					        if self._remote_udp: | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -421,10 +449,12 @@ class TCPRelayHandler(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                                                 remote_port) | 
					 | 
					 | 
					                                                                 remote_port) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        if self._remote_udp: | 
					 | 
					 | 
					                        if self._remote_udp: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                            self._loop.add(remote_sock, | 
					 | 
					 | 
					                            self._loop.add(remote_sock, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                                           eventloop.POLL_IN) | 
					 | 
					 | 
					                                           eventloop.POLL_IN, | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                                           self._server) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                            if self._remote_sock_v6: | 
					 | 
					 | 
					                            if self._remote_sock_v6: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                self._loop.add(self._remote_sock_v6, | 
					 | 
					 | 
					                                self._loop.add(self._remote_sock_v6, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                                        eventloop.POLL_IN) | 
					 | 
					 | 
					                                        eventloop.POLL_IN, | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                                        self._server) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        else: | 
					 | 
					 | 
					                        else: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                            try: | 
					 | 
					 | 
					                            try: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                remote_sock.connect((remote_addr, remote_port)) | 
					 | 
					 | 
					                                remote_sock.connect((remote_addr, remote_port)) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -433,10 +463,16 @@ class TCPRelayHandler(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                        errno.EINPROGRESS: | 
					 | 
					 | 
					                                        errno.EINPROGRESS: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                    pass | 
					 | 
					 | 
					                                    pass | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                            self._loop.add(remote_sock, | 
					 | 
					 | 
					                            self._loop.add(remote_sock, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                                           eventloop.POLL_ERR | eventloop.POLL_OUT) | 
					 | 
					 | 
					                                       eventloop.POLL_ERR | eventloop.POLL_OUT, | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                                       self._server) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        self._stage = STAGE_CONNECTING | 
					 | 
					 | 
					                        self._stage = STAGE_CONNECTING | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) | 
					 | 
					 | 
					                        self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) | 
					 | 
					 | 
					                        self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                        if self._remote_udp: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                            while self._data_to_write_to_remote: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                                data = self._data_to_write_to_remote[0] | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                                del self._data_to_write_to_remote[0] | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                                self._write_to_sock(data, self._remote_sock) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    return | 
					 | 
					 | 
					                    return | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                except Exception as e: | 
					 | 
					 | 
					                except Exception as e: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    shell.print_exception(e) | 
					 | 
					 | 
					                    shell.print_exception(e) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -495,11 +531,12 @@ class TCPRelayHandler(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                port = struct.pack('>H', addr[1]) | 
					 | 
					 | 
					                port = struct.pack('>H', addr[1]) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                try: | 
					 | 
					 | 
					                try: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    ip = socket.inet_aton(addr[0]) | 
					 | 
					 | 
					                    ip = socket.inet_aton(addr[0]) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                    data = '\x00\x00\x00\x01' + ip + port + data | 
					 | 
					 | 
					                    data = '\x00\x01' + ip + port + data | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					                except Exception as e: | 
					 | 
					 | 
					                except Exception as e: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    ip = socket.inet_pton(socket.AF_INET6, addr[0]) | 
					 | 
					 | 
					                    ip = socket.inet_pton(socket.AF_INET6, addr[0]) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                    data = '\x00\x00\x00\x04' + ip + port + data | 
					 | 
					 | 
					                    data = '\x00\x04' + ip + port + data | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					                logging.info('UDP recvfrom %s:%d %d bytes to %s:%d' % (addr[0], addr[1], len(data), self._client_address[0], self._client_address[1])) | 
					 | 
					 | 
					                data = struct.pack('>H', len(data) + 2) + data | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                #logging.info('UDP over TCP recvfrom %s:%d %d bytes to %s:%d' % (addr[0], addr[1], len(data), self._client_address[0], self._client_address[1])) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            else: | 
					 | 
					 | 
					            else: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                data = self._remote_sock.recv(BUF_SIZE) | 
					 | 
					 | 
					                data = self._remote_sock.recv(BUF_SIZE) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        except (OSError, IOError) as e: | 
					 | 
					 | 
					        except (OSError, IOError) as e: | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -637,7 +674,6 @@ class TCPRelay(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self._closed = False | 
					 | 
					 | 
					        self._closed = False | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self._eventloop = None | 
					 | 
					 | 
					        self._eventloop = None | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self._fd_to_handlers = {} | 
					 | 
					 | 
					        self._fd_to_handlers = {} | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self._last_time = time.time() | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self.server_transfer_ul = 0L | 
					 | 
					 | 
					        self.server_transfer_ul = 0L | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self.server_transfer_dl = 0L | 
					 | 
					 | 
					        self.server_transfer_dl = 0L | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -680,10 +716,9 @@ class TCPRelay(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        if self._closed: | 
					 | 
					 | 
					        if self._closed: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            raise Exception('already closed') | 
					 | 
					 | 
					            raise Exception('already closed') | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self._eventloop = loop | 
					 | 
					 | 
					        self._eventloop = loop | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        loop.add_handler(self._handle_events) | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self._eventloop.add(self._server_socket, | 
					 | 
					 | 
					        self._eventloop.add(self._server_socket, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                            eventloop.POLL_IN | eventloop.POLL_ERR) | 
					 | 
					 | 
					                            eventloop.POLL_IN | eventloop.POLL_ERR, self) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        self._eventloop.add_periodic(self.handle_periodic) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    def remove_handler(self, handler): | 
					 | 
					 | 
					    def remove_handler(self, handler): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        index = self._handler_to_timeouts.get(hash(handler), -1) | 
					 | 
					 | 
					        index = self._handler_to_timeouts.get(hash(handler), -1) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -695,7 +730,7 @@ class TCPRelay(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    def update_activity(self, handler): | 
					 | 
					 | 
					    def update_activity(self, handler): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        # set handler to active | 
					 | 
					 | 
					        # set handler to active | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        now = int(time.time()) | 
					 | 
					 | 
					        now = int(time.time()) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        if now - handler.last_activity < TIMEOUT_PRECISION: | 
					 | 
					 | 
					        if now - handler.last_activity < eventloop.TIMEOUT_PRECISION: | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					            # thus we can lower timeout modification frequency | 
					 | 
					 | 
					            # thus we can lower timeout modification frequency | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            return | 
					 | 
					 | 
					            return | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        handler.last_activity = now | 
					 | 
					 | 
					        handler.last_activity = now | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -741,9 +776,8 @@ class TCPRelay(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                pos = 0 | 
					 | 
					 | 
					                pos = 0 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            self._timeout_offset = pos | 
					 | 
					 | 
					            self._timeout_offset = pos | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					    def _handle_events(self, events): | 
					 | 
					 | 
					    def handle_event(self, sock, fd, event): | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					        # handle events and dispatch to handlers | 
					 | 
					 | 
					        # handle events and dispatch to handlers | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        for sock, fd, event in events: | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        if sock: | 
					 | 
					 | 
					        if sock: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            logging.log(shell.VERBOSE_LEVEL, 'fd %d %s', fd, | 
					 | 
					 | 
					            logging.log(shell.VERBOSE_LEVEL, 'fd %d %s', fd, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        eventloop.EVENT_NAMES.get(event, event)) | 
					 | 
					 | 
					                        eventloop.EVENT_NAMES.get(event, event)) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -761,7 +795,7 @@ class TCPRelay(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                error_no = eventloop.errno_from_exception(e) | 
					 | 
					 | 
					                error_no = eventloop.errno_from_exception(e) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                if error_no in (errno.EAGAIN, errno.EINPROGRESS, | 
					 | 
					 | 
					                if error_no in (errno.EAGAIN, errno.EINPROGRESS, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                errno.EWOULDBLOCK): | 
					 | 
					 | 
					                                errno.EWOULDBLOCK): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                        continue | 
					 | 
					 | 
					                    return | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					                else: | 
					 | 
					 | 
					                else: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    shell.print_exception(e) | 
					 | 
					 | 
					                    shell.print_exception(e) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    if self._config['verbose']: | 
					 | 
					 | 
					                    if self._config['verbose']: | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -774,20 +808,23 @@ class TCPRelay(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            else: | 
					 | 
					 | 
					            else: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                logging.warn('poll removed fd') | 
					 | 
					 | 
					                logging.warn('poll removed fd') | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        now = time.time() | 
					 | 
					 | 
					    def handle_periodic(self): | 
				
			
			
				
				
			
		
	
		
		
			
				
					 | 
					 | 
					        if now - self._last_time > TIMEOUT_PRECISION: | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            self._sweep_timeout() | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            self._last_time = now | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					        if self._closed: | 
					 | 
					 | 
					        if self._closed: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            if self._server_socket: | 
					 | 
					 | 
					            if self._server_socket: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                self._eventloop.remove(self._server_socket) | 
					 | 
					 | 
					                self._eventloop.remove(self._server_socket) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                self._server_socket.close() | 
					 | 
					 | 
					                self._server_socket.close() | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                self._server_socket = None | 
					 | 
					 | 
					                self._server_socket = None | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                logging.info('closed listen port %d', self._listen_port) | 
					 | 
					 | 
					                logging.info('closed TCP port %d', self._listen_port) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					            if not self._fd_to_handlers: | 
					 | 
					 | 
					            if not self._fd_to_handlers: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                self._eventloop.remove_handler(self._handle_events) | 
					 | 
					 | 
					                logging.info('stopping') | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                self._eventloop.stop() | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        self._sweep_timeout() | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    def close(self, next_tick=False): | 
					 | 
					 | 
					    def close(self, next_tick=False): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        logging.debug('TCP close') | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self._closed = True | 
					 | 
					 | 
					        self._closed = True | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        if not next_tick: | 
					 | 
					 | 
					        if not next_tick: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            if self._eventloop: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                self._eventloop.remove_periodic(self.handle_periodic) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                self._eventloop.remove(self._server_socket) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            self._server_socket.close() | 
					 | 
					 | 
					            self._server_socket.close() | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
					 | 
					
  |