Skip to content

Commit

Permalink
over_tls_client_run_with_ssr_url
Browse files Browse the repository at this point in the history
  • Loading branch information
ssrlive committed Jun 17, 2024
1 parent 8255432 commit 13256ae
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 39 deletions.
47 changes: 25 additions & 22 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,18 @@ pub unsafe extern "C" fn over_tls_client_run(
/// # Safety
///
/// Run the overtls client with SSR URL.
/// The callback function will be called when the client is listening on a port.
/// It should be thread-safe and will be called with the port number and should be called only once.
/// Parameters:
/// - `url`: SSR style URL string of the server node, e.g. "ssr://server:port:protocol:method:obfs:password_base64/?params_base64".
/// - `listen_addr`: The address to listen on, in the format of "ip:port".
/// - `verbosity`: The verbosity level of the logger.
/// - `callback`: The callback function to be called when the client is listening on a port.
/// It should be thread-safe and will be called with the port number and should be called only once.
/// - `ctx`: The context pointer to be passed to the callback function.
///
#[no_mangle]
pub unsafe extern "C" fn over_tls_client_run_with_ssr_url(
url: *const c_char,
listen_addr: *const c_char,
verbosity: ArgVerbosity,
callback: Option<unsafe extern "C" fn(c_int, *mut c_void)>,
ctx: *mut c_void,
Expand All @@ -89,31 +95,28 @@ pub unsafe extern "C" fn over_tls_client_run_with_ssr_url(
log::warn!("failed to set logger, error={:?}", err);
}
}
let url = match std::ffi::CStr::from_ptr(url).to_str() {
Err(err) => {
log::error!("invalid config path, error={:?}", err);
return -1;
}
Ok(url) => url,

let result = || {
let url = std::ffi::CStr::from_ptr(url).to_str()?;
let listen_addr = if listen_addr.is_null() {
std::net::SocketAddr::from(([127, 0, 0, 1], 1080))
} else {
std::ffi::CStr::from_ptr(listen_addr).to_str()?.parse()?
};

let mut config = Config::from_ssr_url(url)?;
config.set_listen_addr(listen_addr);
config.check_correctness(false)?;
_over_tls_client_run(config, callback, ctx)
};

let mut config = match Config::from_ssr_url(url) {
match result() {
Ok(_) => 0,
Err(err) => {
log::error!("failed to load config, error={:?}", err);
return -2;
log::error!("failed to run client, error={:?}", err);
-1
}
Ok(config) => config,
};

if let Err(err) = config.check_correctness(false) {
log::error!("invalid config, error={:?}", err);
return -3;
}
if let Err(err) = _over_tls_client_run(config, callback, ctx) {
log::error!("failed to run client, error={:?}", err);
return -4;
}
0
}

fn _over_tls_client_run(config: Config, callback: Option<unsafe extern "C" fn(c_int, *mut c_void)>, ctx: *mut c_void) -> Result<()> {
Expand Down
37 changes: 25 additions & 12 deletions src/bin/overtls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,6 @@ fn main() -> Result<(), BoxError> {
return Err("C API is not supported for server".into());
}

// TODO: Using opt.node_url to generate a config file for client is not supported yet.
let cfg = opt.config.as_ref().ok_or("Config file is required for client")?;

// Test the C API usage
let config_path_str = cfg.as_path().to_string_lossy().into_owned();
let c_string = std::ffi::CString::new(config_path_str)?;
let config_path: *const std::os::raw::c_char = c_string.as_ptr();

let join = ctrlc2::set_handler(|| {
log::info!("Ctrl-C received, exiting...");
unsafe { overtls::over_tls_client_stop() };
Expand All @@ -30,9 +22,30 @@ fn main() -> Result<(), BoxError> {
unsafe extern "C" fn port_cb(port: i32, _ctx: *mut std::os::raw::c_void) {
log::info!("Listening on {}", port);
}
unsafe { overtls::over_tls_client_run(config_path, opt.verbosity, Some(port_cb), std::ptr::null_mut()) };

join.join().expect("Couldn't join on the associated thread");
if let Some(cfg) = opt.config.as_ref() {
// Test the C API usage
let config_path_str = cfg.as_path().to_string_lossy().into_owned();
let c_string = std::ffi::CString::new(config_path_str)?;
let config_path: *const std::os::raw::c_char = c_string.as_ptr();

unsafe { overtls::over_tls_client_run(config_path, opt.verbosity, Some(port_cb), std::ptr::null_mut()) };

join.join().expect("Couldn't join on the associated thread");
} else if let Some(url) = opt.url_of_node.as_ref() {
let url_str = std::ffi::CString::new(url.as_str())?;
let url_ptr = url_str.as_ptr();

let listen_addr = opt.listen_addr.unwrap_or(std::net::SocketAddr::from(([127, 0, 0, 1], 1080)));
let listen_addr = std::ffi::CString::new(listen_addr.to_string())?;
let listen_addr = listen_addr.as_ptr();

unsafe { overtls::over_tls_client_run_with_ssr_url(url_ptr, listen_addr, opt.verbosity, Some(port_cb), std::ptr::null_mut()) };

join.join().expect("Couldn't join on the associated thread");
} else {
return Err("Config file or node URL is required".into());
}
return Ok(());
}

Expand All @@ -45,8 +58,8 @@ fn main() -> Result<(), BoxError> {

let mut config = if let Some(file) = opt.config {
Config::from_config_file(file)?
} else if let Some(ref node_url) = opt.node_url {
let mut cfg = Config::from_ssr_url(node_url)?;
} else if let Some(ref url_of_node) = opt.url_of_node {
let mut cfg = Config::from_ssr_url(url_of_node)?;
cfg.set_listen_addr(opt.listen_addr.unwrap_or(std::net::SocketAddr::from(([127, 0, 0, 1], 1080))));
cfg
} else {
Expand Down
10 changes: 5 additions & 5 deletions src/cmdopt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,15 @@ pub struct CmdOpt {
pub role: Role,

/// Config file path
#[arg(short, long, value_name = "file path", conflicts_with = "node_url")]
#[arg(short, long, value_name = "file path", conflicts_with = "url_of_node")]
pub config: Option<std::path::PathBuf>,

/// URL of the server node used by client
#[arg(short, long, value_name = "url", conflicts_with = "config")]
pub node_url: Option<String>,
pub url_of_node: Option<String>,

/// Local listening address associated with the URL
#[arg(short, long, value_name = "addr:port", requires = "node_url", conflicts_with = "config")]
#[arg(short, long, value_name = "addr:port", requires = "url_of_node", conflicts_with = "config")]
pub listen_addr: Option<std::net::SocketAddr>,

/// Cache DNS Query result
Expand Down Expand Up @@ -139,11 +139,11 @@ impl CmdOpt {
if args.listen_addr.is_some() {
output_error_and_exit("Listen address is not supported for server");
}
if args.node_url.is_some() {
if args.url_of_node.is_some() {
output_error_and_exit("Node URL is not supported for server");
}
}
if args.role == Role::Client && args.config.is_none() && args.node_url.is_none() {
if args.role == Role::Client && args.config.is_none() && args.url_of_node.is_none() {
output_error_and_exit("Config file or node URL is required for client");
}
args
Expand Down

0 comments on commit 13256ae

Please sign in to comment.