Skip to content

Commit 1b9376f

Browse files
amituclaude
andcommitted
feat: implement revolutionary protocol.command architecture
🎯 Advanced multi-command protocol support: Protocol.Command API: - Protocols: mail.fastn.com, echo.fastn.com (proper namespacing) - Commands: get-mails, send-mail, settings.add-forwarding (granular) - Handlers get: identity, bind_alias, protocol, command, protocol_dir Modern API: .handle_requests("mail.fastn.com", "get-mails", get_mails_handler) .handle_requests("mail.fastn.com", "send-mail", send_mail_handler) .handle_streams("filetransfer.fastn.com", "transfer.large-file", handler) Benefits: - Multiple commands per protocol (Mail: get/send/settings) - Professional namespacing with dotted notation - Command-specific handlers with full context - Working directory per protocol instance - Single callback handles multiple identities/bindings This enables complex protocols like Mail with multiple operations! 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 88129c5 commit 1b9376f

2 files changed

Lines changed: 43 additions & 14 deletions

File tree

examples/src/request_response.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ async fn run_server(_identity: String) -> Result<(), Box<dyn std::error::Error>>
5555
println!("🎧 Starting multi-identity Echo protocol server");
5656
println!("📡 Will discover and serve all configured identities and protocols from FASTN_HOME");
5757

58-
// Use modern serve_all() builder that discovers all identities and protocols
58+
// Use modern serve_all() builder with protocol.command API
5959
fastn_p2p::serve_all()
60-
.handle_requests("Echo", fastn_p2p::echo_request_handler)
60+
.handle_requests("echo.fastn.com", "basic-echo", fastn_p2p::echo_request_handler)
6161
.serve()
6262
.await?;
6363

fastn-p2p/src/server/serve_all.rs

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,39 +8,62 @@ use std::collections::HashMap;
88
use std::future::Future;
99
use std::pin::Pin;
1010

11-
/// Async callback type for request/response protocols
11+
/// Async callback type for request/response protocol commands
1212
pub type RequestCallback = fn(
1313
&str, // identity
1414
&str, // bind_alias
15+
&str, // protocol (e.g., "mail.fastn.com")
16+
&str, // command (e.g., "settings.add-forwarding")
1517
&PathBuf, // protocol_dir
1618
serde_json::Value, // request
1719
) -> Pin<Box<dyn Future<Output = Result<serde_json::Value, Box<dyn std::error::Error + Send + Sync>>> + Send>>;
1820

19-
/// Async callback type for streaming protocols
21+
/// Async callback type for streaming protocol commands
2022
pub type StreamCallback = fn(
2123
&str, // identity
2224
&str, // bind_alias
25+
&str, // protocol (e.g., "filetransfer.fastn.com")
26+
&str, // command (e.g., "transfer.large-file")
2327
&PathBuf, // protocol_dir
2428
serde_json::Value, // initial_data
2529
) -> Pin<Box<dyn Future<Output = Result<(), Box<dyn std::error::Error + Send + Sync>>> + Send>>;
2630

2731
/// Multi-identity server builder that discovers and serves all configured protocols
2832
pub struct ServeAllBuilder {
2933
fastn_home: PathBuf,
30-
request_callbacks: HashMap<String, RequestCallback>,
31-
stream_callbacks: HashMap<String, StreamCallback>,
34+
request_callbacks: HashMap<String, RequestCallback>, // Key: "protocol.command"
35+
stream_callbacks: HashMap<String, StreamCallback>, // Key: "protocol.command"
3236
}
3337

3438
impl ServeAllBuilder {
35-
/// Register a request/response callback for a protocol
36-
pub fn handle_requests(mut self, protocol_name: &str, callback: RequestCallback) -> Self {
37-
self.request_callbacks.insert(protocol_name.to_string(), callback);
39+
/// Register a request/response callback for a protocol command
40+
///
41+
/// # Arguments
42+
/// * `protocol` - Protocol name (e.g., "mail.fastn.com", "echo.fastn.com")
43+
/// * `command` - Command name (e.g., "get-mails", "send-mail", "basic-echo")
44+
/// * `callback` - Handler function
45+
///
46+
/// # Example
47+
/// ```rust,no_run
48+
/// fastn_p2p::serve_all()
49+
/// .handle_requests("mail.fastn.com", "get-mails", get_mails_handler)
50+
/// .handle_requests("mail.fastn.com", "send-mail", send_mail_handler)
51+
/// ```
52+
pub fn handle_requests(mut self, protocol: &str, command: &str, callback: RequestCallback) -> Self {
53+
let key = format!("{}.{}", protocol, command);
54+
self.request_callbacks.insert(key, callback);
3855
self
3956
}
4057

41-
/// Register a streaming callback for a protocol
42-
pub fn handle_streams(mut self, protocol_name: &str, callback: StreamCallback) -> Self {
43-
self.stream_callbacks.insert(protocol_name.to_string(), callback);
58+
/// Register a streaming callback for a protocol command
59+
///
60+
/// # Arguments
61+
/// * `protocol` - Protocol name (e.g., "filetransfer.fastn.com")
62+
/// * `command` - Command name (e.g., "large-file", "media-stream")
63+
/// * `callback` - Handler function
64+
pub fn handle_streams(mut self, protocol: &str, command: &str, callback: StreamCallback) -> Self {
65+
let key = format!("{}.{}", protocol, command);
66+
self.stream_callbacks.insert(key, callback);
4467
self
4568
}
4669

@@ -124,21 +147,27 @@ pub fn serve_all() -> ServeAllBuilder {
124147
}
125148
}
126149

127-
/// Echo request handler callback
150+
/// Echo request handler callback for basic-echo command
128151
pub fn echo_request_handler(
129152
identity: &str,
130153
bind_alias: &str,
154+
protocol: &str,
155+
command: &str,
131156
protocol_dir: &PathBuf,
132157
request: serde_json::Value,
133158
) -> Pin<Box<dyn Future<Output = Result<serde_json::Value, Box<dyn std::error::Error + Send + Sync>>> + Send>> {
134159
let identity = identity.to_string();
135160
let bind_alias = bind_alias.to_string();
161+
let protocol = protocol.to_string();
162+
let command = command.to_string();
136163
let protocol_dir = protocol_dir.clone();
137164

138165
Box::pin(async move {
139166
println!("💬 Echo handler called:");
140167
println!(" Identity: {}", identity);
141168
println!(" Bind alias: {}", bind_alias);
169+
println!(" Protocol: {}", protocol);
170+
println!(" Command: {}", command);
142171
println!(" Protocol dir: {}", protocol_dir.display());
143172

144173
// Parse request
@@ -154,7 +183,7 @@ pub fn echo_request_handler(
154183

155184
// Create response
156185
let response = serde_json::json!({
157-
"echoed": format!("Echo from {}: {}", identity, message)
186+
"echoed": format!("Echo from {} ({}): {}", identity, command, message)
158187
});
159188

160189
println!("📤 Echo response: {}", response);

0 commit comments

Comments
 (0)