Harden GNS gameplay reliability handling
This commit is contained in:
@@ -1,13 +1,12 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import threading
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from client_session import ClientSession
|
||||
from gns_transport import EventType, GnsEvent, GnsServerTransport, RemoteEndpoint, SendResult
|
||||
from gns_transport import EventType, GnsEvent, GnsServerTransport, GnsTransportError, SendResult
|
||||
from packet_codec import EncodedPacket, PacketCodecError, decode_packet
|
||||
from transport_policy import delivery_for_packet_type, is_snapshot_packet
|
||||
|
||||
@@ -51,8 +50,12 @@ class GnsConnectionAdapter:
|
||||
packet_type = packet["type"]
|
||||
encoded = EncodedPacket(packet_type, payload, delivery_for_packet_type(packet_type))
|
||||
result = self.transport.send_encoded(self.connection_id, encoded)
|
||||
if result in (SendResult.SENT, SendResult.DROPPED):
|
||||
if result is SendResult.SENT:
|
||||
return
|
||||
if result is SendResult.DROPPED and is_snapshot_packet(packet_type):
|
||||
return
|
||||
if result is SendResult.DROPPED:
|
||||
raise OSError("GNS refused to queue a reliable message")
|
||||
if result is SendResult.BACKPRESSURE and is_snapshot_packet(packet_type):
|
||||
return
|
||||
if result is SendResult.BACKPRESSURE:
|
||||
@@ -94,13 +97,15 @@ class GnsGameplayAdapter:
|
||||
self.transport.send_packet(connection_id, packet)
|
||||
|
||||
def _welcome_packet(self, client: ClientSession) -> dict:
|
||||
from server_core import PROTOCOL_VERSION
|
||||
|
||||
return {
|
||||
"type": "welcome",
|
||||
"playerId": client.player_id,
|
||||
"serverTime": time.time(),
|
||||
"serverName": self.server.server_name,
|
||||
"serverDescription": self.server.server_description,
|
||||
"protocolVersion": self.server.PROTOCOL_VERSION if hasattr(self.server, "PROTOCOL_VERSION") else 2,
|
||||
"protocolVersion": PROTOCOL_VERSION,
|
||||
"capabilities": [
|
||||
"interest-v1",
|
||||
"hello-v2",
|
||||
@@ -270,7 +275,13 @@ class GnsGameplayAdapter:
|
||||
with self._lock:
|
||||
if not self._thread_running:
|
||||
break
|
||||
processed = self.pump_once()
|
||||
try:
|
||||
processed = self.pump_once()
|
||||
except GnsTransportError as error:
|
||||
self.server._log(f"GNS transport loop stopped: {error}", level="error")
|
||||
with self._lock:
|
||||
self._thread_running = False
|
||||
break
|
||||
if processed == 0:
|
||||
time.sleep(0.002)
|
||||
|
||||
@@ -293,7 +304,10 @@ class GnsGameplayAdapter:
|
||||
for connection_id, client in clients:
|
||||
if isinstance(client.connection, GnsConnectionAdapter):
|
||||
client.connection.mark_remote_closed()
|
||||
self.transport.disconnect(connection_id, debug="GNS adapter stopped")
|
||||
try:
|
||||
self.transport.disconnect(connection_id, debug="GNS adapter stopped")
|
||||
except Exception:
|
||||
pass
|
||||
self.server._disconnect_client(client)
|
||||
with self._lock:
|
||||
self._clients.clear()
|
||||
|
||||
Reference in New Issue
Block a user