This design targets institutional device fleets: healthcare, eldercare, and similar facilities where a failed call cannot depend on a user restarting an app. Many shared devices need to stay online for long periods, recover without local troubleshooting, and keep calls usable in noisy spaces.
In a constrained LAN, the hardest failure is not always a clean disconnect. The more dangerous state is a connection that still looks alive while application messages no longer move. A call system that depends on that connection can leave devices online on the screen, unreachable in practice, and difficult to recover without manual action.
This article focuses on the recovery side of a WebRTC calling system: how to move from a WebSocket-centered signaling path to a gRPC Gateway model with bidirectional reachability, automatic discovery, explicit session state, and predictable hangup behavior.

Problem Context
The media path can still be WebRTC. The question here is the control plane around it.
The audio requirement also changes the design pressure. Devices may be placed away from the speaker, run in shared rooms, and compete with background noise. The system has to preserve enough pickup distance while keeping speech intelligible. That makes long-running gateway state, recovery, and audio observability part of the same reliability problem.
In a simple lab network, a WebSocket connection from each client to a central service may be enough. The client connects, keeps the socket open, receives call events, and forwards offer, answer, and ICE candidate messages. The design is easy to understand and works well while the network stays clean.
The failure mode changes in a constrained LAN:
- network rules may change during operation.
- long-running connections may be cleaned up by intermediate devices.
- a client process may stay alive while its upstream connection becomes useless.
- the UI may still show an online device because no explicit failure was converged.
- recovery may depend on the client noticing the problem and reconnecting first.
That last point is the boundary. If the central side cannot actively reach the edge device, recovery waits for the side that may already be stuck.
WebSocket Limitations
WebSocket is not the problem by itself. The limitation is a design that treats one long-lived client-initiated connection as the only reliable control path.
There are two common failure states.
The first one is a normal disconnect. The socket closes, the client sees the error, and reconnect logic can run.
The second one is harder: the connection appears to exist, but the application can no longer exchange useful messages. The client may not trigger reconnect immediately, the server may still hold stale state, and call control becomes inconsistent.
For a WebRTC call system, that state creates visible defects:
- the caller can start a call request, but the callee never opens the call page.
- the callee looks online, but cannot receive control events.
- a timed-out call keeps stale UI or stale session state.
- one participant leaves a group call, but remote media state is not cleaned up correctly.
The missing piece is a recovery path where both sides can be checked, reached, and moved into explicit state. A protocol swap alone does not clean up stale sessions, stale UI, or stale media mappings.
gRPC Gateway Boundary
In the gateway model, each device runs a local RTC Gateway component. The gateway owns device registration, call control callbacks, session mapping, and WebRTC signaling messages. The media path remains WebRTC.
The model adds bidirectional control. A client can initiate a request, and another gateway or central controller can also initiate a request toward that client. This makes recovery less dependent on one stale upstream connection.
A practical gateway boundary includes:
- device registration.
- automatic peer discovery.
- heartbeat and reachability checks.
- call request routing.
- offer, answer, and ICE candidate forwarding.
- call timeout and hangup convergence.
- session cleanup after abnormal state.
The gateway should not become a media server unless that is a deliberate architecture choice. Keeping media on the WebRTC path avoids mixing real-time media transport with signaling recovery logic.
Discovery and Primary Node State
In a small LAN, automatic discovery can remove a fragile manual configuration step. Edge gateways announce themselves to a primary node or a discovery service. The primary node records gateway identity, reachable address, current state, and recent heartbeat time.
The part the system relies on is the state table created after discovery.
At minimum, the primary node needs:
- gateway id.
- current reachability.
- last heartbeat time.
- current call state.
- active session ids.
- gateway version.
- latest error reason.
This state lets the system answer operational questions:
- which gateway should receive a call event?
- is the peer reachable now, or only previously registered?
- should a stale session be closed before accepting a new call?
- can a group call remove one participant without closing the whole room?
Without this state, recovery logic becomes a set of scattered retries.
Call Lifecycle
The call lifecycle should still end in explicit state when the UI or network path does not behave perfectly.
Start
When gateway A calls gateway B, the primary node creates a session and records the participants. It then sends call-open events to the required gateways. Each gateway prepares its local UI and WebRTC peer connection, then starts signaling.
The primary node should record the time of the call request. That timestamp is the source for timeout and cleanup decisions.
Answer
When gateway B answers, the primary node updates the session state and allows signaling to continue. SDP and ICE candidate messages still belong to the WebRTC negotiation path, but they should be correlated with the same session id.
If the answer never arrives, the system should not wait forever.
Timeout
Timeout is a server-side responsibility. A periodic check can scan sessions that have stayed in ringing or pending state longer than the allowed answer window. When a session times out, the primary node sends close events to affected gateways and marks the session with an explicit timeout reason.
Idempotency matters here. Timeout and manual hangup may happen close together. Closing the same session twice should not create inconsistent UI state.
One-to-One Hangup
For a one-to-one call, either side can request hangup. The primary node verifies the session, sends close events to both gateways, removes media mappings, and marks the session as ended.
The gateway should release local media, renderers, and peer connection resources even if the remote side is already unreachable.
Group Hangup
Group calls need more care. A single participant leaving should remove only that participant’s media. A full hangup should close the entire session for every participant.
The primary node has to decide:
- which gateway requested hangup.
- whether this is a participant leave or a full session close.
- which remote tracks should be removed.
- which gateways should keep their call UI open.
- whether the room has no remaining active participants.
The session table is used here to decide the cleanup scope. Without explicit participant and media mapping, group hangup easily becomes either too weak or too destructive.
Validation and Observability
A recovery design should be verified through failure injection. Logs should show state transitions, not just errors.
Useful fields include:
- session id.
- gateway id.
- peer role.
- discovery state.
- heartbeat time.
- call state.
- timeout deadline.
- hangup reason.
- participant count.
- media track mapping.
- WebRTC ICE state.
Validation should include forced failure cases:
- stop one gateway process during ringing.
- drop the network path between two gateways.
- keep the UI open while the control stream becomes unusable.
- make one participant leave a group call.
- trigger timeout and manual hangup at nearly the same time.
The expected result is not “nothing ever disconnects”. The expected result is that every abnormal path reaches a clear state and leaves no stale UI, stale session, or stale media mapping.
Takeaway
This change is not a simple protocol swap from WebSocket to gRPC. It is a more explicit control model:
- gateways can discover each other.
- the primary node owns session state.
- both sides can be reached by control events.
- timeout and hangup are converged by the server side.
- group call media mappings are explicit.
For WebRTC systems in constrained LANs, recovery should be designed as a first-class part of the architecture. Otherwise the system may work in demos but fail in the exact moments where field reliability matters most.
