@@ -17,7 +17,7 @@ class V2RayCore:
1717 """Represents executable of V2Ray core."""
1818
1919 def __init__ (self ):
20- self .release_tag_url = os .environ .get ("V2RAY_RELASE_TAG_URL" ) or "https://github.com/v2fly/v2ray-core/releases/download/v4.31.0 "
20+ self .release_tag_url = os .environ .get ("V2RAY_RELASE_TAG_URL" ) or "https://github.com/v2fly/v2ray-core/releases/download/v4.45.2 "
2121 if os .environ .get ("V2RAY_EXECUTABLE_DIR" ):
2222 self .executable_dir = os .environ ["V2RAY_EXECUTABLE_DIR" ]
2323 self .executable = os .path .join (self .executable_dir , "v2ray.exe" if os .name == "nt" else "v2ray" )
@@ -199,15 +199,32 @@ def __init__(self, v2ray_link: str, http_port: int = None, socks_port: int = Non
199199 self .start ()
200200
201201 def _is_port_in_use (self , port : int ) -> bool :
202- """Check if a port is currently in use."""
203- with socket .socket (socket .AF_INET , socket .SOCK_STREAM ) as s :
204- return s .connect_ex (("localhost" , port )) == 0
202+ """Check if a port is currently in use by trying to bind to it."""
203+ try :
204+ with socket .socket (socket .AF_INET , socket .SOCK_STREAM ) as s :
205+ s .setsockopt (socket .SOL_SOCKET , socket .SO_REUSEADDR , 1 )
206+ s .bind (('localhost' , port ))
207+ return False
208+ except (socket .error , OSError ):
209+ return True
205210
206211 def _pick_unused_port (self , exclude_port : int = None ) -> int :
207- for _ in range (500 ):
208- port = random .randint (10000 , 65535 )
209- if not self ._is_port_in_use (port ) and port != exclude_port :
212+ # Try to get a system-assigned port first
213+ try :
214+ with socket .socket (socket .AF_INET , socket .SOCK_STREAM ) as s :
215+ s .bind (('localhost' , 0 )) # Let OS choose a free port
216+ _ , port = s .getsockname ()
217+ if port != exclude_port :
218+ return port
219+ except Exception as e :
220+ logging .warning (f"Failed to get system-assigned port: { str (e )} " )
221+
222+ # If that fails, try a few random ports
223+ for _ in range (100 ):
224+ port = random .randint (10000 , 65000 )
225+ if port != exclude_port and not self ._is_port_in_use (port ):
210226 return port
227+
211228 raise RuntimeError ("Could not find an unused port" )
212229
213230 def _parse_vmess_link (self , link : str ) -> dict :
@@ -550,7 +567,7 @@ def start(self):
550567 self .cleanup ()
551568 raise
552569
553- def _terminate_process (self , timeout = 10 ):
570+ def _terminate_process (self , timeout = 10 ) -> bool :
554571 """
555572 Safely terminate the V2Ray process with platform-specific handling.
556573
@@ -652,7 +669,7 @@ def stop(self):
652669 try :
653670 # Terminate the process
654671 if self .v2ray_process is not None :
655- success = self ._terminate_process (timeout = 5 ) # Reduced timeout for faster cleanup
672+ success = self ._terminate_process (timeout = 1 )
656673 if not success :
657674 logging .warning ("V2Ray process may not have terminated cleanly" )
658675
0 commit comments