Message Propagation in DroneEngage Communication Server
This document describes the message routing and propagation logic in the server-to-server mesh relay system.
Architecture Overview
┌─────────────────────┐
│ Super Server │
│ (ParentCommServer) │
└──────────┬──────────┘
│
┌────────────────┼────────────────┐
│ │ │
▼ ▼ ▼
┌────────────┐ ┌────────────┐ ┌────────────┐
│ Child A │ │ Child B │ │ Child C │
│(ChildComm) │ │(ChildComm) │ │(ChildComm) │
└─────┬──────┘ └─────┬──────┘ └─────┬──────┘
│ │ │
Local Units Local Units Local Units
(WS Clients) (WS Clients) (WS Clients)
Key Components
Files
| File | Role |
|——|——|
| server/chat_server/js_andruav_chat_server.js | Main message routing logic |
| server/server_to_server/js_parent_comm_server.js | Super server - accepts child connections |
| server/server_to_server/js_child_comm_server.js | Child server - connects to parent |
Core Functions
| Function | Location | Purpose |
|———-|———-|———|
| fn_parseMessage() | chat_server | Handles messages from local WebSocket clients |
| fn_parseExternalMessage() | chat_server | Handles messages from relay servers |
| forwardMessage() | chat_server | Forwards messages to parent/child relay servers |
| getServerOriginID() | chat_server | Returns unique server ID for loop prevention |
Data Flow
1. Local Client → Relay Propagation
When a local WebSocket client sends a message:
Local Client (WS)
│
▼
fn_parseMessage()
│
├──► Local delivery (fn_sendToAll*, fn_sendToIndividual)
│
└──► forwardMessage()
│
├──► Parent Server (if enable_super_server=true)
│
└──► Child Servers (if enable_persistant_relay=true)
Code path:
fn_onWsMessage()receives WS messageCalls
fn_parseMessage(p_ws, p_message, p_isBinary)Parses JSON, injects permission (
pfield)Routes to local clients based on
ty(routing type) andtg(target)Calls
forwardMessage()to propagate to relay servers
2. External Server → Local Delivery Only
When a message arrives from a relay server (parent or child):
Relay Server
│
▼
fn_parseExternalMessage()
│
└──► Local delivery ONLY (fn_sendToAll*, fn_sendToIndividual)
✗ NO re-forwarding to other servers
Code path:
ParentCommServer.on('message')orChildCommServer.onReceive()Calls
fn_parseExternalMessage(p_message, p_isBinary)Checks
_patharray for loop preventionRoutes to local clients only
Does NOT call
forwardMessage()- prevents infinite loops
Loop Prevention Mechanism
Path Tracking
Each server has a unique server_id defined in config:
function getServerOriginID() {
return global.m_serverconfig?.m_configuration?.server_id || 'unknown';
}
Injection Point
In forwardMessage(), the server ID is appended to the _path array:
if (!Array.isArray(v_jmsg._path)) v_jmsg._path = [];
v_jmsg._path.push(getServerOriginID());
Check Point
In fn_parseExternalMessage(), messages that have already passed through this server are dropped:
if (Array.isArray(v_jmsg._path) && v_jmsg._path.includes(getServerOriginID())) {
return; // Ignore - this message already passed through us
}
Why This Matters
When ParentCommServer.forwardMessage() broadcasts to all children, it includes the originating child. Without path tracking:
Child A sends message → Parent → broadcasts to [A, B, C]
│
└─► Child A receives its own message back!
With _path check, Child A ignores the bounce-back because its ID is already in the path array.
Message Routing Types
The ty field determines routing behavior:
| Value | Constant | Behavior |
|——-|———-|———-|
| 'g' | CONST_WS_MSG_ROUTING_GROUP | Broadcast to group |
| 'i' | CONST_WS_MSG_ROUTING_INDIVIDUAL | Targeted delivery |
| 's' | CONST_WS_MSG_ROUTING_SYSTEM | System commands (local only) |
Target Field (tg) Special Values
| Value | Constant | Meaning |
|——-|———-|———|
| '_GCS_' | CONST_WS_SENDER_ALL_GCS | All GCS units |
| '_GD_' | CONST_WS_SENDER_ALL | All units (GCS + Agents) |
| '_AGN_' | CONST_WS_SENDER_ALL_AGENTS | All drone agents |
| (other) | - | Specific unit ID (one-to-one) |
Configuration Flags
In server config file:
| Flag | Effect |
|——|——–|
| enable_super_server: true | This server acts as a parent (accepts child connections) |
| enable_persistant_relay: true | This server connects to a parent as a child |
| server_id | Unique identifier for loop prevention |
| s2s_ws_target_ip / s2s_ws_target_port | Parent server address (for child mode) |
Summary Table
| Message Source | Handler | Local Delivery | Relay Forward | Loop Check |
|—————-|———|—————-|—————|————|
| Local WS Client | fn_parseMessage() | ✅ | ✅ | Appends to _path |
| Parent Server | fn_parseExternalMessage() | ✅ | ❌ | Checks _path |
| Child Server | fn_parseExternalMessage() | ✅ | ❌ | Checks _path |