Harden GNS gameplay reliability handling
This commit is contained in:
@@ -1,13 +1,12 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from client_session import ClientSession
|
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 packet_codec import EncodedPacket, PacketCodecError, decode_packet
|
||||||
from transport_policy import delivery_for_packet_type, is_snapshot_packet
|
from transport_policy import delivery_for_packet_type, is_snapshot_packet
|
||||||
|
|
||||||
@@ -51,8 +50,12 @@ class GnsConnectionAdapter:
|
|||||||
packet_type = packet["type"]
|
packet_type = packet["type"]
|
||||||
encoded = EncodedPacket(packet_type, payload, delivery_for_packet_type(packet_type))
|
encoded = EncodedPacket(packet_type, payload, delivery_for_packet_type(packet_type))
|
||||||
result = self.transport.send_encoded(self.connection_id, encoded)
|
result = self.transport.send_encoded(self.connection_id, encoded)
|
||||||
if result in (SendResult.SENT, SendResult.DROPPED):
|
if result is SendResult.SENT:
|
||||||
return
|
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):
|
if result is SendResult.BACKPRESSURE and is_snapshot_packet(packet_type):
|
||||||
return
|
return
|
||||||
if result is SendResult.BACKPRESSURE:
|
if result is SendResult.BACKPRESSURE:
|
||||||
@@ -94,13 +97,15 @@ class GnsGameplayAdapter:
|
|||||||
self.transport.send_packet(connection_id, packet)
|
self.transport.send_packet(connection_id, packet)
|
||||||
|
|
||||||
def _welcome_packet(self, client: ClientSession) -> dict:
|
def _welcome_packet(self, client: ClientSession) -> dict:
|
||||||
|
from server_core import PROTOCOL_VERSION
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"type": "welcome",
|
"type": "welcome",
|
||||||
"playerId": client.player_id,
|
"playerId": client.player_id,
|
||||||
"serverTime": time.time(),
|
"serverTime": time.time(),
|
||||||
"serverName": self.server.server_name,
|
"serverName": self.server.server_name,
|
||||||
"serverDescription": self.server.server_description,
|
"serverDescription": self.server.server_description,
|
||||||
"protocolVersion": self.server.PROTOCOL_VERSION if hasattr(self.server, "PROTOCOL_VERSION") else 2,
|
"protocolVersion": PROTOCOL_VERSION,
|
||||||
"capabilities": [
|
"capabilities": [
|
||||||
"interest-v1",
|
"interest-v1",
|
||||||
"hello-v2",
|
"hello-v2",
|
||||||
@@ -270,7 +275,13 @@ class GnsGameplayAdapter:
|
|||||||
with self._lock:
|
with self._lock:
|
||||||
if not self._thread_running:
|
if not self._thread_running:
|
||||||
break
|
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:
|
if processed == 0:
|
||||||
time.sleep(0.002)
|
time.sleep(0.002)
|
||||||
|
|
||||||
@@ -293,7 +304,10 @@ class GnsGameplayAdapter:
|
|||||||
for connection_id, client in clients:
|
for connection_id, client in clients:
|
||||||
if isinstance(client.connection, GnsConnectionAdapter):
|
if isinstance(client.connection, GnsConnectionAdapter):
|
||||||
client.connection.mark_remote_closed()
|
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)
|
self.server._disconnect_client(client)
|
||||||
with self._lock:
|
with self._lock:
|
||||||
self._clients.clear()
|
self._clients.clear()
|
||||||
|
|||||||
Reference in New Issue
Block a user