@@ -8,7 +8,7 @@ use clap::Parser;
88use dialoguer:: Confirm ;
99use iroh:: protocol:: Router ;
1010use tokio:: task:: JoinSet ;
11- use tracing:: { error, info} ;
11+ use tracing:: { error, info, warn } ;
1212
1313#[ derive( Parser , Debug ) ]
1414#[ command( about = "Call me iroh" , long_about = None ) ]
@@ -19,6 +19,7 @@ struct Args {
1919 /// The audio output device to use.
2020 #[ arg( short, long) ]
2121 output_device : Option < String > ,
22+ /// If set, audio processing and echo cancellation will be disabled.
2223 #[ arg( long) ]
2324 disable_processing : bool ,
2425 #[ clap( subcommand) ]
@@ -27,14 +28,17 @@ struct Args {
2728
2829#[ derive( Debug , Parser ) ]
2930enum Command {
30- /// Accept a single call from a remote node.
31- Accept ,
3231 /// Accept calls from remote nodes.
33- AcceptMany ,
34- /// Make a call to a remote node.
35- Connect { node_id : NodeId } ,
36- /// Make a call to many remote nodes.
37- ConnectMany { node_id : Vec < NodeId > } ,
32+ Accept {
33+ /// Accept more than one call.
34+ #[ clap( long) ]
35+ many : bool ,
36+ /// Auto-accept calls without confirmation.
37+ #[ clap( long) ]
38+ auto : bool ,
39+ } ,
40+ /// Make calls to remote nodes.
41+ Connect { node_id : Vec < NodeId > } ,
3842 /// Create a debug feedback loop through an in-memory channel.
3943 Feedback { mode : Option < FeedbackMode > } ,
4044 /// List the available audio devices
@@ -60,7 +64,7 @@ async fn main() -> anyhow::Result<()> {
6064 let mut endpoint_shutdown = None ;
6165 let fut = async {
6266 match args. command {
63- Command :: Accept | Command :: AcceptMany => {
67+ Command :: Accept { many , auto } => {
6468 let endpoint = net:: bind_endpoint ( ) . await ?;
6569 let proto = RtcProtocol :: new ( endpoint. clone ( ) ) ;
6670 let _router = Router :: builder ( endpoint. clone ( ) )
@@ -74,55 +78,51 @@ async fn main() -> anyhow::Result<()> {
7478 let audio_ctx = AudioContext :: new ( audio_config) . await ?;
7579
7680 while let Some ( conn) = proto. accept ( ) . await ? {
77- match args . command {
78- // Handle a single connection, then close.
79- Command :: Accept => {
80- handle_connection ( audio_ctx , conn ) . await ;
81- break ;
82- }
83- // Handle each connection after a confirm prompt. Close on Ctrl-c only.
84- Command :: AcceptMany => {
85- let peer = conn . transport ( ) . remote_node_id ( ) ? . fmt_short ( ) ;
86- if confirm ( format ! ( "Incoming call from {peer}. Accept?" ) ) . await {
87- tokio :: task :: spawn ( handle_connection ( audio_ctx . clone ( ) , conn ) ) ;
88- }
81+ if !many {
82+ handle_connection ( audio_ctx , conn ) . await ;
83+ break ;
84+ } else {
85+ let peer = conn . transport ( ) . remote_node_id ( ) ? . fmt_short ( ) ;
86+ let accept =
87+ auto || confirm ( format ! ( "Incoming call from {peer}. Accept?" ) ) . await ;
88+ if accept {
89+ n0_future :: task :: spawn ( handle_connection ( audio_ctx . clone ( ) , conn ) ) ;
90+ } else {
91+ info ! ( "reject connection from {peer}" ) ;
92+ conn . transport ( ) . close ( 0u32 . into ( ) , b"bye" ) ;
8993 }
90- _ => unreachable ! ( ) ,
9194 }
9295 }
9396 }
9497 Command :: Connect { node_id } => {
9598 let endpoint = net:: bind_endpoint ( ) . await ?;
9699 endpoint_shutdown = Some ( endpoint. clone ( ) ) ;
97100
98- let proto = RtcProtocol :: new ( endpoint) ;
99- let conn = proto. connect ( node_id) . await ?;
100-
101- info ! ( "established connection to {}" , node_id. fmt_short( ) ) ;
102-
103- let audio_ctx = AudioContext :: new ( audio_config) . await ?;
104- handle_connection ( audio_ctx, conn) . await ;
105- }
106- Command :: ConnectMany { node_id } => {
107- let endpoint = net:: bind_endpoint ( ) . await ?;
108- endpoint_shutdown = Some ( endpoint. clone ( ) ) ;
109-
110101 let proto = RtcProtocol :: new ( endpoint) ;
111102 let audio_ctx = AudioContext :: new ( audio_config) . await ?;
112103
113104 let mut join_set = JoinSet :: new ( ) ;
105+
114106 for node_id in node_id {
107+ info ! ( "connecting to {}" , node_id. fmt_short( ) ) ;
115108 let audio_ctx = audio_ctx. clone ( ) ;
116109 let proto = proto. clone ( ) ;
117110 join_set. spawn ( async move {
118- let conn = proto. connect ( node_id) . await ?;
119- info ! ( "established connection to {}" , node_id. fmt_short( ) ) ;
120- handle_connection ( audio_ctx, conn) . await ;
121- anyhow:: Ok ( ( ) )
111+ let fut = async {
112+ let conn = proto. connect ( node_id) . await ?;
113+ info ! ( "established connection to {}" , node_id. fmt_short( ) ) ;
114+ handle_connection ( audio_ctx, conn) . await ;
115+ anyhow:: Ok ( ( ) )
116+ } ;
117+ ( node_id, fut. await )
122118 } ) ;
123119 }
120+
124121 while let Some ( res) = join_set. join_next ( ) . await {
125- res??;
122+ let ( node_id, res) = res. expect ( "task panicked" ) ;
123+ if let Err ( err) = res {
124+ warn ! ( "failed to connect to {}: {err:?}" , node_id. fmt_short( ) )
125+ }
126126 }
127127 }
128128 Command :: Feedback { mode } => {
0 commit comments