| 
						
						
							
								
							
						
						
					 | 
					@ -123,11 +123,33 @@ RSP_STATE_ERROR = b"\x03" | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					RSP_STATE_DISCONNECT = b"\x04" | 
					 | 
					 | 
					RSP_STATE_DISCONNECT = b"\x04" | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					RSP_STATE_REDIRECT = b"\x05" | 
					 | 
					 | 
					RSP_STATE_REDIRECT = b"\x05" | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					class UDPAsyncDNSHandler(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    def __init__(self, params): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        self.params = params | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        self.remote_addr = None | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        self.call_back = None | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    def resolve(self, dns_resolver, remote_addr, call_back): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        self.call_back = call_back | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        self.remote_addr = remote_addr | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        dns_resolver.resolve(remote_addr[0], self._handle_dns_resolved) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    def _handle_dns_resolved(self, result, error): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        if error: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            logging.error("%s when resolve DNS" % (error,)) #drop | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            return | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        if result: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            ip = result[1] | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            if ip: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                if self.call_back: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                    self.call_back(*self.params, self.remote_addr, None, ip, True) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                    return | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        logging.warning("can't resolve %s" % (self.remote_addr,)) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					def client_key(source_addr, server_af): | 
					 | 
					 | 
					def client_key(source_addr, server_af): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    # notice this is server af, not dest af | 
					 | 
					 | 
					    # notice this is server af, not dest af | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    return '%s:%s:%d' % (source_addr[0], source_addr[1], server_af) | 
					 | 
					 | 
					    return '%s:%s:%d' % (source_addr[0], source_addr[1], server_af) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					class UDPRelay(object): | 
					 | 
					 | 
					class UDPRelay(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    def __init__(self, config, dns_resolver, is_local, stat_callback=None, stat_counter=None): | 
					 | 
					 | 
					    def __init__(self, config, dns_resolver, is_local, stat_callback=None, stat_counter=None): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self._config = config | 
					 | 
					 | 
					        self._config = config | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -154,7 +176,7 @@ class UDPRelay(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self._cache_dns_client = lru_cache.LRUCache(timeout=10, | 
					 | 
					 | 
					        self._cache_dns_client = lru_cache.LRUCache(timeout=10, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                         close_callback=self._close_client_pair) | 
					 | 
					 | 
					                                         close_callback=self._close_client_pair) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self._client_fd_to_server_addr = {} | 
					 | 
					 | 
					        self._client_fd_to_server_addr = {} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        self._dns_cache = lru_cache.LRUCache(timeout=1800) | 
					 | 
					 | 
					        #self._dns_cache = lru_cache.LRUCache(timeout=1800) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					        self._eventloop = None | 
					 | 
					 | 
					        self._eventloop = None | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self._closed = False | 
					 | 
					 | 
					        self._closed = False | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self.server_transfer_ul = 0 | 
					 | 
					 | 
					        self.server_transfer_ul = 0 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -375,33 +397,30 @@ class UDPRelay(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        if header_result is None: | 
					 | 
					 | 
					        if header_result is None: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            self._handel_protocol_error(r_addr, ogn_data) | 
					 | 
					 | 
					            self._handel_protocol_error(r_addr, ogn_data) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            return | 
					 | 
					 | 
					            return | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        connecttype, dest_addr, dest_port, header_length = header_result | 
					 | 
					 | 
					        connecttype, addrtype, dest_addr, dest_port, header_length = header_result | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        if self._is_local: | 
					 | 
					 | 
					        if self._is_local: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					            connecttype = 3 | 
					 | 
					 | 
					            addrtype = 3 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					            server_addr, server_port = self._get_a_server() | 
					 | 
					 | 
					            server_addr, server_port = self._get_a_server() | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        else: | 
					 | 
					 | 
					        else: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            server_addr, server_port = dest_addr, dest_port | 
					 | 
					 | 
					            server_addr, server_port = dest_addr, dest_port | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        if (connecttype & 7) == 3: | 
					 | 
					 | 
					        if (addrtype & 7) == 3: | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					            addrs = self._dns_cache.get(server_addr, None) | 
					 | 
					 | 
					            handler = UDPAsyncDNSHandler((data, r_addr, uid, header_length)) | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					            if addrs is None: | 
					 | 
					 | 
					            handler.resolve(self._dns_resolver, (server_addr, server_port), self._handle_server_dns_resolved) | 
				
			
			
				
				
			
		
	
		
		
			
				
					 | 
					 | 
					                # TODO async getaddrinfo | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                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 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					        else: | 
					 | 
					 | 
					        else: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            self._handle_server_dns_resolved(data, r_addr, uid, header_length, (server_addr, server_port), None, server_addr, False) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    def _handle_server_dns_resolved(self, data, r_addr, uid, header_length, remote_addr, addrs, server_addr, dns_resolved): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        try: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            server_port = remote_addr[1] | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            if addrs is None: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                addrs = socket.getaddrinfo(server_addr, server_port, 0, | 
					 | 
					 | 
					                addrs = socket.getaddrinfo(server_addr, server_port, 0, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                            socket.SOCK_DGRAM, socket.SOL_UDP) | 
					 | 
					 | 
					                                            socket.SOCK_DGRAM, socket.SOL_UDP) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					            if not addrs: | 
					 | 
					 | 
					            if not addrs: # drop | 
				
			
			
				
				
			
		
	
		
		
			
				
					 | 
					 | 
					                # drop | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					                return | 
					 | 
					 | 
					                return | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            af, socktype, proto, canonname, sa = addrs[0] | 
					 | 
					 | 
					            af, socktype, proto, canonname, sa = addrs[0] | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            server_addr = sa[0] | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            key = client_key(r_addr, af) | 
					 | 
					 | 
					            key = client_key(r_addr, af) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            client_pair = self._cache.get(key, None) | 
					 | 
					 | 
					            client_pair = self._cache.get(key, None) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            if client_pair is None: | 
					 | 
					 | 
					            if client_pair is None: | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -422,7 +441,7 @@ class UDPRelay(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                client.setblocking(False) | 
					 | 
					 | 
					                client.setblocking(False) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                self._socket_bind_addr(client, af) | 
					 | 
					 | 
					                self._socket_bind_addr(client, af) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                is_dns = False | 
					 | 
					 | 
					                is_dns = False | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					            if len(data) > 20 and data[11:19] == b"\x00\x01\x00\x00\x00\x00\x00\x00": | 
					 | 
					 | 
					                if len(data) > header_length + 13 and data[header_length + 4 : header_length + 12] == b"\x00\x01\x00\x00\x00\x00\x00\x00": | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					                    is_dns = True | 
					 | 
					 | 
					                    is_dns = True | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                else: | 
					 | 
					 | 
					                else: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    pass | 
					 | 
					 | 
					                    pass | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -459,13 +478,17 @@ class UDPRelay(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                data = data[header_length:] | 
					 | 
					 | 
					                data = data[header_length:] | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            if not data: | 
					 | 
					 | 
					            if not data: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                return | 
					 | 
					 | 
					                return | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        except Exception as e: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            shell.print_exception(e) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            logging.error("exception from user %d" % (user_id,)) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        try: | 
					 | 
					 | 
					        try: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            client.sendto(data, (server_addr, server_port)) | 
					 | 
					 | 
					            client.sendto(data, (server_addr, server_port)) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            self.add_transfer_u(client_uid, len(data)) | 
					 | 
					 | 
					            self.add_transfer_u(client_uid, len(data)) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            if client_pair is None: # new request | 
					 | 
					 | 
					            if client_pair is None: # new request | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                addr, port = client.getsockname()[:2] | 
					 | 
					 | 
					                addr, port = client.getsockname()[:2] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                common.connect_log('UDP data to %s:%d from %s:%d by UID %d' % | 
					 | 
					 | 
					                common.connect_log('UDP data to %s(%s):%d from %s:%d by user %d' % | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					                        (common.to_str(server_addr), server_port, addr, port, user_id)) | 
					 | 
					 | 
					                        (common.to_str(remote_addr[0]), common.to_str(server_addr), server_port, addr, port, user_id)) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					        except IOError as e: | 
					 | 
					 | 
					        except IOError as e: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            err = eventloop.errno_from_exception(e) | 
					 | 
					 | 
					            err = eventloop.errno_from_exception(e) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            logging.warning('IOError sendto %s:%d by user %d' % (server_addr, server_port, user_id)) | 
					 | 
					 | 
					            logging.warning('IOError sendto %s:%d by user %d' % (server_addr, server_port, user_id)) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -623,7 +646,7 @@ class UDPRelay(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        if self._closed: | 
					 | 
					 | 
					        if self._closed: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            self._cache.clear(0) | 
					 | 
					 | 
					            self._cache.clear(0) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            self._cache_dns_client.clear(0) | 
					 | 
					 | 
					            self._cache_dns_client.clear(0) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					            self._dns_cache.sweep() | 
					 | 
					 | 
					            #self._dns_cache.sweep() | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					            if self._eventloop: | 
					 | 
					 | 
					            if self._eventloop: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                self._eventloop.remove_periodic(self.handle_periodic) | 
					 | 
					 | 
					                self._eventloop.remove_periodic(self.handle_periodic) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                self._eventloop.remove(self._server_socket) | 
					 | 
					 | 
					                self._eventloop.remove(self._server_socket) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -635,7 +658,7 @@ class UDPRelay(object): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            before_sweep_size = len(self._sockets) | 
					 | 
					 | 
					            before_sweep_size = len(self._sockets) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            self._cache.sweep() | 
					 | 
					 | 
					            self._cache.sweep() | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            self._cache_dns_client.sweep() | 
					 | 
					 | 
					            self._cache_dns_client.sweep() | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					            self._dns_cache.sweep() | 
					 | 
					 | 
					            #self._dns_cache.sweep() | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					            if before_sweep_size != len(self._sockets): | 
					 | 
					 | 
					            if before_sweep_size != len(self._sockets): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                logging.debug('UDP port %5d sockets %d' % (self._listen_port, len(self._sockets))) | 
					 | 
					 | 
					                logging.debug('UDP port %5d sockets %d' % (self._listen_port, len(self._sockets))) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            self._sweep_timeout() | 
					 | 
					 | 
					            self._sweep_timeout() | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					
  |