fixed server status uptime for coldeve
This commit is contained in:
parent
ca12f4807b
commit
72de9b0f7f
3 changed files with 56 additions and 39 deletions
92
main.py
92
main.py
|
|
@ -171,53 +171,67 @@ AC_LOGIN_PACKET = bytes([
|
|||
])
|
||||
|
||||
async def check_server_health(address: str, port: int, timeout: float = 3.0) -> tuple[bool, float, int]:
|
||||
"""Check AC server health via UDP packet.
|
||||
"""Check AC server health via UDP packet with retry logic.
|
||||
|
||||
Retries 6 times with 5-second delays before declaring server down.
|
||||
Returns: (is_up, latency_ms, player_count)
|
||||
"""
|
||||
logger.debug(f"🔍 Starting health check for {address}:{port}")
|
||||
start_time = time.time()
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
sock.setblocking(False)
|
||||
max_retries = 6
|
||||
retry_delay = 5.0
|
||||
|
||||
try:
|
||||
# Send login packet (same as ThwargLauncher)
|
||||
await asyncio.get_event_loop().sock_sendto(sock, AC_LOGIN_PACKET, (address, port))
|
||||
for attempt in range(max_retries):
|
||||
logger.debug(f"🔍 Health check attempt {attempt + 1}/{max_retries} for {address}:{port}")
|
||||
start_time = time.time()
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
sock.setblocking(False)
|
||||
|
||||
# Wait for response with timeout
|
||||
try:
|
||||
data, addr = await asyncio.wait_for(
|
||||
asyncio.get_event_loop().sock_recvfrom(sock, 1024),
|
||||
timeout=timeout
|
||||
)
|
||||
# Send login packet (same as ThwargLauncher)
|
||||
await asyncio.get_event_loop().sock_sendto(sock, AC_LOGIN_PACKET, (address, port))
|
||||
|
||||
latency_ms = (time.time() - start_time) * 1000
|
||||
logger.debug(f"📥 Received response from {addr}: {len(data)} bytes, latency: {latency_ms:.1f}ms")
|
||||
|
||||
# Check if valid response (support both TimeSynch 0x800000 and ConnectRequest 0x40000)
|
||||
if len(data) >= 24:
|
||||
flags = struct.unpack('<I', data[4:8])[0]
|
||||
# Wait for response with timeout
|
||||
try:
|
||||
data, addr = await asyncio.wait_for(
|
||||
asyncio.get_event_loop().sock_recvfrom(sock, 1024),
|
||||
timeout=timeout
|
||||
)
|
||||
|
||||
# Accept both TimeSynch (0x800000) and ConnectRequest (0x40000) as valid responses
|
||||
if (flags & 0x800000) or (flags & 0x40000):
|
||||
# UDP health check is for server status and latency only
|
||||
# Player count comes from TreeStats.net API (like ThwargLauncher)
|
||||
logger.debug(f"✅ Valid server response: latency: {latency_ms:.1f}ms")
|
||||
return True, latency_ms, None
|
||||
|
||||
# Any response indicates server is up, even if not the expected format
|
||||
logger.info(f"✅ Server response (non-standard format): latency: {latency_ms:.1f}ms")
|
||||
return True, latency_ms, None
|
||||
|
||||
except asyncio.TimeoutError:
|
||||
logger.debug(f"⏰ TIMEOUT: No response from {address}:{port} after {timeout}s - server down")
|
||||
return False, None, None
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Server health check error: {e}")
|
||||
return False, None, None
|
||||
finally:
|
||||
sock.close()
|
||||
latency_ms = (time.time() - start_time) * 1000
|
||||
logger.debug(f"📥 Received response from {addr}: {len(data)} bytes, latency: {latency_ms:.1f}ms")
|
||||
|
||||
# Check if valid response (support both TimeSynch 0x800000 and ConnectRequest 0x40000)
|
||||
if len(data) >= 24:
|
||||
flags = struct.unpack('<I', data[4:8])[0]
|
||||
|
||||
# Accept both TimeSynch (0x800000) and ConnectRequest (0x40000) as valid responses
|
||||
if (flags & 0x800000) or (flags & 0x40000):
|
||||
# UDP health check is for server status and latency only
|
||||
# Player count comes from TreeStats.net API (like ThwargLauncher)
|
||||
logger.debug(f"✅ Valid server response: latency: {latency_ms:.1f}ms")
|
||||
return True, latency_ms, None
|
||||
|
||||
# Any response indicates server is up, even if not the expected format
|
||||
logger.info(f"✅ Server response (non-standard format): latency: {latency_ms:.1f}ms")
|
||||
return True, latency_ms, None
|
||||
|
||||
except asyncio.TimeoutError:
|
||||
logger.debug(f"⏰ TIMEOUT: No response from {address}:{port} after {timeout}s")
|
||||
if attempt < max_retries - 1:
|
||||
logger.debug(f"Retrying in {retry_delay} seconds...")
|
||||
await asyncio.sleep(retry_delay)
|
||||
continue
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Server health check error on attempt {attempt + 1}: {e}")
|
||||
if attempt < max_retries - 1:
|
||||
await asyncio.sleep(retry_delay)
|
||||
continue
|
||||
finally:
|
||||
sock.close()
|
||||
|
||||
# Only declare down after all retries fail
|
||||
logger.warning(f"❌ Server {address}:{port} is DOWN after {max_retries} attempts over {max_retries * retry_delay} seconds")
|
||||
return False, None, None
|
||||
|
||||
async def get_player_count_from_treestats(server_name: str) -> int:
|
||||
"""Get player count from TreeStats.net API (same as ThwargLauncher)."""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue