2022-01-15 23:24:37 +00:00
use crate ::settings ::* ;
2022-03-10 16:10:11 +00:00
use clap ::{ Arg , ArgMatches , Command } ;
2022-01-19 02:21:11 +00:00
use std ::ffi ::OsStr ;
2022-05-17 20:55:53 +00:00
use std ::path ::Path ;
2022-01-15 23:24:37 +00:00
use std ::str ::FromStr ;
2022-05-16 15:52:48 +00:00
use veilid_core ::{ DHTKey , DHTKeySecret } ;
2022-01-15 23:24:37 +00:00
fn do_clap_matches ( default_config_path : & OsStr ) -> Result < clap ::ArgMatches , clap ::Error > {
2022-03-10 16:10:11 +00:00
let matches = Command ::new ( " veilid-server " )
2022-01-15 23:24:37 +00:00
. version ( " 0.1 " )
. about ( " Veilid Server " )
. color ( clap ::ColorChoice ::Auto )
. arg (
Arg ::new ( " daemon " )
. long ( " daemon " )
. short ( 'd' )
. help ( " Run in daemon mode in the background " ) ,
)
2022-05-18 14:17:04 +00:00
. arg (
Arg ::new ( " foreground " )
. long ( " foreground " )
. short ( 'f' )
. conflicts_with ( " daemon " )
. help ( " Run in the foreground " ) ,
)
2022-01-15 23:24:37 +00:00
. arg (
Arg ::new ( " config-file " )
. short ( 'c' )
. long ( " config-file " )
. takes_value ( true )
. value_name ( " FILE " )
. default_value_os ( default_config_path )
2022-01-19 02:21:11 +00:00
. allow_invalid_utf8 ( true )
2022-01-15 23:24:37 +00:00
. help ( " Specify a configuration file to use " ) ,
) . arg (
Arg ::new ( " attach " )
. long ( " attach " )
. takes_value ( true )
. value_name ( " BOOL " )
. possible_values ( & [ " false " , " true " ] )
. help ( " Automatically attach the server to the Veilid network " ) ,
)
// Dev options
. arg (
Arg ::new ( " debug " )
. long ( " debug " )
. help ( " Turn on debug logging on the terminal " ) ,
)
. arg (
Arg ::new ( " trace " )
. long ( " trace " )
. conflicts_with ( " debug " )
. help ( " Turn on trace logging on the terminal " ) ,
)
. arg (
2022-05-16 15:52:48 +00:00
Arg ::new ( " subnode-index " )
. long ( " subnode-index " )
2022-01-15 23:24:37 +00:00
. takes_value ( true )
. help ( " Run as an extra daemon on the same machine for testing purposes, specify a number greater than zero to offset the listening ports " ) ,
)
. arg (
Arg ::new ( " generate-dht-key " )
. long ( " generate-dht-key " )
. help ( " Only generate a new dht key and print it " ) ,
)
2022-05-16 15:52:48 +00:00
. arg (
Arg ::new ( " set-node-id " )
. long ( " set-node-id " )
. takes_value ( true )
. value_name ( " ID " )
. help ( " Set the node id and secret key " )
. long_help ( " To specify both node id and secret key on the command line, use a ID:SECRET syntax with a colon, like: \n zsVXz5aTU98vZxwTcDmvpcnO5g1B2jRO3wpdNiDrRgw:gJzQLmzuBvA-dFvEmLcYvLoO5bh7hzCWFzfpJHapZKg \n If no colon is used, the node id is specified, and a prompt appears to enter the secret key interactively. " )
)
2022-01-19 02:21:11 +00:00
. arg (
Arg ::new ( " delete-protected-store " )
. long ( " delete-protected-store " )
. help ( " Delete the entire contents of the protected store (DANGER, NO UNDO!) " ) ,
)
. arg (
Arg ::new ( " delete-table-store " )
. long ( " delete-table-store " )
. help ( " Delete the entire contents of the table store (DANGER, NO UNDO!) " ) ,
)
. arg (
Arg ::new ( " delete-block-store " )
. long ( " delete-block-store " )
. help ( " Delete the entire contents of the block store (DANGER, NO UNDO!) " ) ,
)
2022-01-15 23:24:37 +00:00
. arg (
Arg ::new ( " dump-config " )
. long ( " dump-config " )
. help ( " Instead of running the server, print the configuration it would use to the console " ) ,
)
2022-05-16 15:52:48 +00:00
. arg (
Arg ::new ( " dump-txt-record " )
. long ( " dump-txt-record " )
. help ( " Prints the bootstrap TXT record for this node and then quits " )
)
2022-01-15 23:24:37 +00:00
. arg (
Arg ::new ( " bootstrap " )
. long ( " bootstrap " )
. takes_value ( true )
. value_name ( " BOOTSTRAP_LIST " )
2022-05-16 15:52:48 +00:00
. help ( " Specify a list of bootstrap hostnames to use " )
)
. arg (
Arg ::new ( " bootstrap-nodes " )
. conflicts_with ( " bootstrap " )
. long ( " bootstrap-nodes " )
. takes_value ( true )
. value_name ( " BOOTSTRAP_NODE_LIST " )
. help ( " Specify a list of bootstrap node dialinfos to use " ) ,
2022-01-15 23:24:37 +00:00
)
. arg (
Arg ::new ( " local " )
. long ( " local " )
. help ( " Enable local peer scope " )
) ;
2022-01-19 02:21:11 +00:00
#[ cfg(debug_assertions) ]
let matches = matches . arg (
Arg ::new ( " wait-for-debug " )
. long ( " wait-for-debug " )
. help ( " Wait for debugger to attach " ) ,
) ;
2022-01-15 23:24:37 +00:00
Ok ( matches . get_matches ( ) )
}
pub fn process_command_line ( ) -> Result < ( Settings , ArgMatches ) , String > {
// Get command line options
let default_config_path = Settings ::get_default_config_path ( ) ;
let matches = do_clap_matches ( default_config_path . as_os_str ( ) )
. map_err ( | e | format! ( " failed to parse command line: {} " , e ) ) ? ;
// Check for one-off commands
#[ cfg(debug_assertions) ]
if matches . occurrences_of ( " wait-for-debug " ) ! = 0 {
use bugsalot ::debugger ;
debugger ::wait_until_attached ( None ) . expect ( " state() not implemented on this platform " ) ;
}
// Attempt to load configuration
2022-05-17 20:55:53 +00:00
let settings_path = if let Some ( config_file ) = matches . value_of_os ( " config-file " ) {
if Path ::new ( config_file ) . exists ( ) {
Some ( config_file )
} else {
None
}
2022-03-10 16:10:11 +00:00
} else {
2022-05-17 20:55:53 +00:00
None
} ;
let settings =
Settings ::new ( settings_path ) . map_err ( | e | format! ( " configuration is invalid: {} " , e ) ) ? ;
2022-01-15 23:24:37 +00:00
// write lock the settings
let mut settingsrw = settings . write ( ) ;
// Set config from command line
if matches . occurrences_of ( " daemon " ) ! = 0 {
2022-05-16 15:52:48 +00:00
settingsrw . daemon . enabled = true ;
2022-01-15 23:24:37 +00:00
settingsrw . logging . terminal . enabled = false ;
}
2022-05-18 14:17:04 +00:00
if matches . occurrences_of ( " foreground " ) ! = 0 {
settingsrw . daemon . enabled = false ;
}
2022-05-16 15:52:48 +00:00
if matches . occurrences_of ( " subnode-index " ) ! = 0 {
let subnode_index = match matches . value_of ( " subnode-index " ) {
2022-01-15 23:24:37 +00:00
Some ( x ) = > x
. parse ( )
. map_err ( | e | format! ( " couldn't parse subnode index: {} " , e ) ) ? ,
None = > {
2022-05-16 15:52:48 +00:00
return Err ( " value not specified for subnode-index " . to_owned ( ) ) ;
2022-01-15 23:24:37 +00:00
}
} ;
if subnode_index = = 0 {
return Err ( " value of subnode_index should be between 1 and 65535 " . to_owned ( ) ) ;
}
settingsrw . testing . subnode_index = subnode_index ;
}
2022-01-19 02:21:11 +00:00
2022-01-15 23:24:37 +00:00
if matches . occurrences_of ( " debug " ) ! = 0 {
settingsrw . logging . terminal . enabled = true ;
settingsrw . logging . terminal . level = LogLevel ::Debug ;
}
if matches . occurrences_of ( " trace " ) ! = 0 {
settingsrw . logging . terminal . enabled = true ;
settingsrw . logging . terminal . level = LogLevel ::Trace ;
}
if matches . is_present ( " attach " ) {
settingsrw . auto_attach = ! matches! ( matches . value_of ( " attach " ) , Some ( " true " ) ) ;
}
if matches . is_present ( " local " ) {
settingsrw . core . network . enable_local_peer_scope = true ;
}
2022-01-19 02:21:11 +00:00
if matches . occurrences_of ( " delete-protected-store " ) ! = 0 {
settingsrw . core . protected_store . delete = true ;
}
if matches . occurrences_of ( " delete-block-store " ) ! = 0 {
settingsrw . core . block_store . delete = true ;
}
if matches . occurrences_of ( " delete-table-store " ) ! = 0 {
settingsrw . core . table_store . delete = true ;
}
2022-05-16 15:52:48 +00:00
if matches . occurrences_of ( " dump-txt-record " ) ! = 0 {
// Turn off terminal logging so we can be interactive
settingsrw . logging . terminal . enabled = false ;
}
if let Some ( v ) = matches . value_of ( " set-node-id " ) {
// Turn off terminal logging so we can be interactive
settingsrw . logging . terminal . enabled = false ;
// Split or get secret
let ( k , s ) = if let Some ( ( k , s ) ) = v . split_once ( ':' ) {
let k = DHTKey ::try_decode ( k ) ? ;
let s = DHTKeySecret ::try_decode ( s ) ? ;
( k , s )
} else {
let k = DHTKey ::try_decode ( v ) ? ;
let buffer = rpassword ::prompt_password ( " Enter secret key (will not echo): " )
. map_err ( | e | e . to_string ( ) ) ? ;
let buffer = buffer . trim ( ) . to_string ( ) ;
let s = DHTKeySecret ::try_decode ( & buffer ) ? ;
( k , s )
} ;
settingsrw . core . network . node_id = k ;
settingsrw . core . network . node_id_secret = s ;
}
2022-01-15 23:24:37 +00:00
if matches . occurrences_of ( " bootstrap " ) ! = 0 {
2022-05-18 14:17:04 +00:00
let bootstrap_list = match matches . value_of ( " bootstrap " ) {
2022-05-16 15:52:48 +00:00
Some ( x ) = > {
println! ( " Overriding bootstrap list with: " ) ;
let mut out : Vec < String > = Vec ::new ( ) ;
for x in x . split ( ',' ) {
let x = x . trim ( ) . to_string ( ) ;
println! ( " {} " , x ) ;
out . push ( x ) ;
}
out
}
None = > {
2022-05-18 14:17:04 +00:00
return Err ( " value not specified for bootstrap " . to_owned ( ) ) ;
2022-05-16 15:52:48 +00:00
}
} ;
settingsrw . core . network . bootstrap = bootstrap_list ;
}
if matches . occurrences_of ( " bootstrap-nodes " ) ! = 0 {
2022-05-18 14:17:04 +00:00
let bootstrap_list = match matches . value_of ( " bootstrap-nodes " ) {
2022-01-15 23:24:37 +00:00
Some ( x ) = > {
2022-05-16 15:52:48 +00:00
println! ( " Overriding bootstrap node list with: " ) ;
2022-01-15 23:24:37 +00:00
let mut out : Vec < ParsedNodeDialInfo > = Vec ::new ( ) ;
for x in x . split ( ',' ) {
2022-05-16 15:52:48 +00:00
let x = x . trim ( ) ;
2022-01-15 23:24:37 +00:00
println! ( " {} " , x ) ;
out . push ( ParsedNodeDialInfo ::from_str ( x ) . map_err ( | e | {
format! (
2022-05-16 15:52:48 +00:00
" unable to parse dial info in bootstrap node list: {} for {} " ,
2022-01-15 23:24:37 +00:00
e , x
)
} ) ? ) ;
}
out
}
None = > {
2022-05-16 15:52:48 +00:00
return Err ( " value not specified for bootstrap node list " . to_owned ( ) ) ;
2022-01-15 23:24:37 +00:00
}
} ;
2022-05-16 15:52:48 +00:00
settingsrw . core . network . bootstrap_nodes = bootstrap_list ;
2022-01-15 23:24:37 +00:00
}
// Apply subnode index if we're testing
drop ( settingsrw ) ;
settings
. apply_subnode_index ( )
. map_err ( | _ | " failed to apply subnode index " . to_owned ( ) ) ? ;
Ok ( ( settings , matches ) )
2022-01-19 02:21:11 +00:00
}