1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//! Protocol multiplexing over P2P connections.
//!
//! This module implements a custom protocol multiplexing system over Iroh P2P
//! connections, deliberately deviating from Iroh's recommended ALPN-per-protocol
//! approach.
//!
//! # Why Not Use Iroh's Built-in ALPN Feature?
//!
//! Iroh [recommends using different ALPNs](https://docs.rs/iroh/latest/iroh/endpoint/struct.Builder.html#method.alpns)
//! for different protocols. However, this approach has a significant limitation:
//! **each protocol requires a separate connection**.
//!
//! ## The Problem with Multiple Connections
//!
//! Consider a typical P2P session where an entity might:
//! - Send periodic pings to check connection health
//! - Proxy HTTP requests through another entity
//! - Tunnel TCP connections simultaneously
//! - Stream real-time data (e.g., during a call while browsing shared files)
//!
//! With Iroh's approach, each protocol would need its own connection, requiring
//! a full TLS handshake for each. ALPN is negotiated during the TLS handshake:
//!
//! ```text
//! Client Hello Message Structure:
//! ┌─────────────────────────────────────┐
//! │ Handshake Type: Client Hello (1) │
//! │ Version: TLS 1.2 (0x0303) │
//! │ Random: dd67b5943e5efd07... │
//! │ Cipher Suites: [...] │
//! │ Extensions: │
//! │ ALPN Extension: │
//! │ - h2 │
//! │ - http/1.1 │
//! └─────────────────────────────────────┘
//! ```
//!
//! Creating additional connections means additional:
//! - TLS handshakes (expensive cryptographic operations)
//! - Network round trips
//! - Memory overhead for connection state
//! - Complexity in connection management
//!
//! ## Our Solution: Application-Layer Multiplexing
//!
//! We use a single ALPN (`/fastn/entity/0.1`) and multiplex different protocols
//! over [bidirectional streams](https://docs.rs/iroh/latest/iroh/endpoint/struct.Connection.html#method.open_bi)
//! within that connection:
//!
//! ```text
//! Single Connection between Entities
//! ├── Stream 1: HTTP Proxy
//! ├── Stream 2: Ping
//! ├── Stream 3: TCP Tunnel
//! └── Stream N: ...
//! ```
//!
//! Each stream starts with a JSON protocol header identifying its type.
//!
//! # The Protocol "Protocol"
//!
//! ## Stream Lifecycle
//!
//! 1. **Client entity** opens a bidirectional stream
//! 2. **Client** sends a JSON protocol header (newline-terminated)
//! 3. **Server entity** sends ACK to confirm protocol support
//! 4. Protocol-specific communication begins
//!
//! ## Protocol Header
//!
//! The first message on each stream is a JSON-encoded [`ProtocolHeader`] containing:
//! - The [`Protocol`] type (Ping, Http, Tcp, etc.)
//! - Optional protocol-specific metadata
//!
//! This allows protocol handlers to receive all necessary information upfront
//! without additional negotiation rounds.
//!
//! # Future Considerations
//!
//! This multiplexing approach may not be optimal for all use cases. Real-time
//! protocols (RTP/RTCP for audio/video) might benefit from dedicated connections
//! to avoid head-of-line blocking. This design decision will be re-evaluated
//! based on performance requirements.
/// Single ALPN protocol identifier for all fastn entity connections.
///
/// Each fastn instance is called an "entity" in the P2P network. Unlike Iroh's
/// recommended approach of using different ALPNs for different protocols, we use
/// a single ALPN and multiplex protocols at the application layer. This avoids
/// the overhead of multiple TLS handshakes when entities need to use multiple
/// protocols (e.g., HTTP proxy + TCP tunnel + ping).
///
/// See module documentation for detailed rationale.
pub const APNS_IDENTITY: & = b"/fastn/entity/0.1";
/// Protocol header with optional metadata.
///
/// Sent at the beginning of each bidirectional stream to identify
/// the protocol and provide any protocol-specific metadata.