FSM-Based Message Gating

LiteP2P uses a Finite State Machine (FSM) to control message flow. This ensures reliable, ordered communication that respects connection state.

What is Message Gating?

Message gating prevents messages from being sent when the connection is not in an appropriate state. This avoids:

  • Lost messages sent to disconnected peers
  • Security issues from data sent before handshake completes
  • Protocol violations that cause connection drops
  • Wasted battery on futile send attempts

FSM States

LiteP2P enforces strict state-based messaging:

FSM State Allowed Messages Description
CONNECTED Handshake only TCP connected, handshake not started
HANDSHAKING Handshake only Cryptographic handshake in progress
READY Application data Fully authenticated, ready for data
DEGRADED Control only Connection unstable, limiting traffic
DISCONNECTED None Not connected
FAILED None Connection failed, awaiting cleanup

State Diagram

                    ┌─────────────────┐
                    │   DISCONNECTED  │
                    └────────┬────────┘
                             │ connect()
                             ▼
                    ┌─────────────────┐
                    │    CONNECTED    │
                    └────────┬────────┘
                             │ startHandshake()
                             ▼
                    ┌─────────────────┐
                    │   HANDSHAKING   │
                    └────────┬────────┘
                             │ handshakeComplete()
                             ▼
                    ┌─────────────────┐
           ┌───────│      READY      │───────┐
           │       └─────────────────┘       │
           │ networkDegraded()    disconnect()│
           ▼                                  ▼
   ┌───────────────┐                ┌─────────────────┐
   │   DEGRADED    │                │   DISCONNECTED  │
   └───────┬───────┘                └─────────────────┘
           │ recovered() or timeout
           ▼
   ┌───────────────┐
   │    FAILED     │
   └───────────────┘

Message Types

LiteP2P categorizes messages for state-based filtering:

Handshake Messages

Only allowed in CONNECTED and HANDSHAKING states:

  • HELLO – Initial connection greeting
  • KEY_EXCHANGE – Cryptographic key exchange
  • AUTH – Authentication challenge/response
  • HANDSHAKE_COMPLETE – Finalize handshake

Control Messages

Allowed in READY and DEGRADED states:

  • PING / PONG – Connection health check
  • CLOSE – Graceful disconnect
  • ERROR – Error notification

Application Messages

Only allowed in READY state:

  • DATA – Application data payload
  • FILE_TRANSFER – File transfer frames
  • STREAM – Streaming data

Working with FSM

val peer = LiteP2P.getInstance().getPeer(peerId)

// Check state before sending
if (peer.state == PeerState.READY) {
    peer.send(data) { result ->
        when (result) {
            is SendResult.Success -> { /* sent */ }
            is SendResult.Error -> { /* handle error */ }
        }
    }
} else {
    // Queue for later or notify user
    messageQueue.add(data)
}

// Listen for state changes
peer.onStateChange { newState ->
    when (newState) {
        PeerState.READY -> {
            // Flush queued messages
            messageQueue.forEach { peer.send(it) }
            messageQueue.clear()
        }
        PeerState.DISCONNECTED -> {
            // Store messages for later
        }
    }
}

Automatic Message Handling

LiteP2P can automatically queue and retry messages:

val config = PeerConfig.Builder()
    .setAppId("your-app-id")
    .setMessageQueueSize(100)
    .setAutoRetry(true)
    .setRetryOnReconnect(true)
    .build()

// Messages sent to non-ready peers are automatically queued
LiteP2P.getInstance().sendMessage(peerId, data) { result ->
    // Called when message is actually delivered (may be after reconnect)
}
Why FSM Matters

FSM-based messaging prevents common P2P bugs: race conditions during handshake, data leaks before encryption is established, and wasted resources on dead connections.