1- //! Request/Response Pattern Example (Client + Server)
1+ //! Request/Response Pattern Example (Server-Only )
22//!
3- //! Demonstrates both client and server sides of the Echo protocol .
4- //! Can run as either client (via lightweight fastn-p2p-client) or server (using fastn-p2p server APIs) .
3+ //! Pure Echo protocol server using fastn-p2p server APIs .
4+ //! Clients use fastn-p2p CLI commands to test this server .
55//!
66//! Usage:
7- //! Server: cargo run --bin request_response server [identity_name]
8- //! Client: cargo run --bin request_response client <peer_id52> [message]
7+ //! Server: cargo run --bin request_response [identity_name]
8+ //! Client: echo '{"message":"Hello"}' | fastn-p2p call <server_peer_id> Echo
99
10- use fastn_p2p_client;
1110use serde:: { Serialize , Deserialize } ;
1211
1312// Echo Protocol Definition
@@ -34,78 +33,58 @@ pub enum EchoError {
3433
3534type EchoResult = Result < EchoResponse , EchoError > ;
3635
37- #[ fastn_p2p_client :: main]
36+ #[ fastn_p2p :: main]
3837async fn main ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
3938 let args: Vec < String > = std:: env:: args ( ) . collect ( ) ;
4039
41- if args. len ( ) < 2 {
42- eprintln ! ( "Usage:" ) ;
43- eprintln ! ( " {} server [identity_name] # Start Echo protocol server" , args[ 0 ] ) ;
44- eprintln ! ( " {} client <peer_id52> [message] # Send Echo request to server" , args[ 0 ] ) ;
45- eprintln ! ( "" ) ;
46- eprintln ! ( "Two-daemon testing setup:" ) ;
47- eprintln ! ( " 1. Terminal 1: FASTN_HOME=/tmp/alice fastn-p2p daemon" ) ;
48- eprintln ! ( " 2. Terminal 2: FASTN_HOME=/tmp/bob fastn-p2p daemon" ) ;
49- eprintln ! ( " 3. Terminal 3: FASTN_HOME=/tmp/alice {} server alice" , args[ 0 ] ) ;
50- eprintln ! ( " 4. Terminal 4: FASTN_HOME=/tmp/bob {} client <alice_id52> \" Hello!\" " , args[ 0 ] ) ;
51- return Ok ( ( ) ) ;
52- }
40+ let identity = args. get ( 1 ) . unwrap_or ( & "alice" . to_string ( ) ) . clone ( ) ;
5341
54- match args[ 1 ] . as_str ( ) {
55- "server" => {
56- let identity = args. get ( 2 ) . unwrap_or ( & "alice" . to_string ( ) ) . clone ( ) ;
57- run_server ( identity) . await
58- }
59- "client" => {
60- if args. len ( ) < 3 {
61- return Err ( "Client mode requires peer_id52 argument" . into ( ) ) ;
62- }
63- let target_id52 = & args[ 2 ] ;
64- let message = args. get ( 3 ) . unwrap_or ( & "Hello P2P via daemon!" . to_string ( ) ) . clone ( ) ;
65- run_client ( target_id52, message) . await
66- }
67- _ => {
68- return Err ( "First argument must be 'server' or 'client'" . into ( ) ) ;
69- }
70- }
42+ println ! ( "🎧 Starting Echo protocol server for identity: {}" , identity) ;
43+ println ! ( "📡 Testing setup:" ) ;
44+ println ! ( " 1. Make sure daemon is running: fastn-p2p daemon" ) ;
45+ println ! ( " 2. Create identity: fastn-p2p create-identity {}" , identity) ;
46+ println ! ( " 3. Add protocol: fastn-p2p add-protocol {} --protocol Echo --config '{{\" max_length\" : 1000}}'" , identity) ;
47+ println ! ( " 4. Set online: fastn-p2p identity-online {}" , identity) ;
48+ println ! ( " 5. Test with CLI: echo '{{\" message\" :\" Hello\" }}' | fastn-p2p call <peer_id> Echo" ) ;
49+ println ! ( "" ) ;
50+
51+ run_server ( identity) . await
7152}
7253
7354async fn run_server ( identity : String ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
7455 println ! ( "🎧 Starting Echo protocol server for identity: {}" , identity) ;
75- println ! ( "📡 Server will handle Echo requests via fastn-p2p server APIs" ) ;
7656
77- // TODO: Use fastn_p2p server APIs to listen for Echo protocol requests
78- // This will use the clean server APIs from fastn-p2p crate
79- todo ! ( "Implement Echo protocol server using fastn_p2p::listen() or similar server API" ) ;
57+ // Load identity private key (server applications need the full fastn-p2p crate)
58+ let private_key = load_identity_key ( & identity) . await ?;
59+ println ! ( "🔑 Loaded identity key for: {} ({})" , identity, private_key. public_key( ) . id52( ) ) ;
60+
61+ // Start P2P server listening for Echo protocol requests
62+ println ! ( "📡 Starting P2P listener for Echo protocol..." ) ;
63+ fastn_p2p:: listen ( private_key)
64+ . handle_requests ( EchoProtocol :: Echo , echo_handler)
65+ . await ?;
66+
67+ Ok ( ( ) )
8068}
8169
82- async fn run_client (
83- target_id52 : & str ,
84- message : String ,
85- ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
86- // Parse target peer ID to PublicKey for type safety
87- let target_peer: fastn_p2p_client:: PublicKey = target_id52. parse ( )
88- . map_err ( |e| format ! ( "Invalid peer ID '{}': {}" , target_id52, e) ) ?;
89-
90- println ! ( "📤 Sending '{}' to {} via daemon" , message, target_peer. id52( ) ) ;
91-
92- let request = EchoRequest { message } ;
70+ /// Load identity private key from current environment
71+ async fn load_identity_key ( identity : & str ) -> Result < fastn_p2p:: SecretKey , Box < dyn std:: error:: Error > > {
72+ // Use FASTN_HOME environment variable to locate identity
73+ let fastn_home = std:: env:: var ( "FASTN_HOME" )
74+ . unwrap_or_else ( |_| {
75+ let home = std:: env:: var ( "HOME" ) . unwrap_or ( "/tmp" . to_string ( ) ) ;
76+ format ! ( "{}/.fastn" , home)
77+ } ) ;
9378
94- // Use lightweight client that routes through daemon
95- let result: EchoResult = fastn_p2p_client:: call (
96- "bob" , // From bob identity (daemon manages keys)
97- target_peer, // To target peer (alice)
98- "Echo" , // Echo protocol
99- "default" , // Default Echo instance
100- request // Request data
101- ) . await ?;
102-
103- match result {
104- Ok ( response) => println ! ( "✅ Response: {}" , response. echoed) ,
105- Err ( error) => println ! ( "❌ Error: {:?}" , error) ,
106- }
79+ let identity_dir = std:: path:: PathBuf :: from ( fastn_home)
80+ . join ( "identities" )
81+ . join ( identity) ;
10782
108- Ok ( ( ) )
83+ // Load the private key using fastn-id52
84+ match fastn_p2p:: SecretKey :: load_from_dir ( & identity_dir, "identity" ) {
85+ Ok ( ( _id52, secret_key) ) => Ok ( secret_key) ,
86+ Err ( e) => Err ( format ! ( "Failed to load identity '{}': {}" , identity, e) . into ( ) ) ,
87+ }
10988}
11089
11190/// Echo request handler (server-side logic)
0 commit comments