-
Notifications
You must be signed in to change notification settings - Fork 9
Closed
Description
Summary
When a client reconnects after a brief sleep/wake cycle (shorter than the server's client_timeout of 5 seconds), the server continues sending RPC and NetworkVariable messages to the old ZeroMQ ROUTER identity, which no longer exists. This causes all control messages (RPC, NV sync, device ID mapping) to be silently dropped, while transform synchronization continues to work normally.
Symptoms
- After one or more sleep/wake cycles on a Pico 4 UE device, the client:
- CAN connect to the server and send avatar transforms
- CAN receive transform updates from other clients (via PUB-SUB)
- CANNOT receive NetworkVariable changes (via ROUTER-DEALER)
- CANNOT receive RPC messages (via ROUTER-DEALER)
Root Cause
In server.py, _handle_client_transform() (line 1184-1212), when a client reconnects before the 5-second timeout:
is_new_client = False(the device ID is still inself.rooms[room_id])- The
elsebranch updatestransform_data,last_update,client_no, andis_stealth - But it does NOT update
"identity"to the new ZeroMQ identity
# server.py:1201-1206
else:
self.rooms[room_id][device_id]["transform_data"] = data_with_client_no
self.rooms[room_id][device_id]["last_update"] = time.monotonic()
self.rooms[room_id][device_id]["client_no"] = client_no
self.rooms[room_id][device_id]["is_stealth"] = is_stealth
# ⚠️ "identity" is NOT updated hereWhy this happens
- Client connects → DEALER socket gets ZMQ identity A → server stores identity A
- App sleeps →
OnApplicationPause(true)→StopNetworking()→ sockets destroyed - App resumes →
OnApplicationPause(false)→StartNetworking()→ new sockets → identity B - Client sends transform with identity B
- Server:
device_idstill inself.rooms(timeout not yet reached) →is_new_client = False - Server updates everything except
identity→ still holds identity A - Server sends RPC/NV via
_send_ctrl_to_room_via_router()→ sends to identity A → no socket → message lost - Transforms still work because PUB-SUB is topic-based, not identity-based
Why "multiple sleep/wake cycles" triggers it
- If sleep duration > 5s: client times out, gets removed from
rooms, next connect hasis_new_client = True→ identity correctly stored → works fine - If sleep duration < 5s: client still in
rooms,is_new_client = False→ identity mismatch → broken - Repeated cycles increase the probability of hitting a short sleep window
Proposed Fix
Add identity update to the else branch in _handle_client_transform():
else:
self.rooms[room_id][device_id]["transform_data"] = data_with_client_no
self.rooms[room_id][device_id]["last_update"] = time.monotonic()
self.rooms[room_id][device_id]["client_no"] = client_no
self.rooms[room_id][device_id]["is_stealth"] = is_stealth
self.rooms[room_id][device_id]["identity"] = client_identity # ← Add this lineThis ensures the server always uses the client's current ZeroMQ identity for ROUTER-based message delivery, regardless of whether the client is new or reconnecting.
Affected Components
- Server:
server.py→_handle_client_transform()(lines 1201-1206) - Client:
ConnectionManager.cs→NetworkLoop()creates new sockets on everyConnect(), generating new ZMQ identities - Client:
NetSyncManager.cs→OnApplicationPause()callsStopNetworking()/StartNetworking()which triggers socket recreation
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels