14 changed files with 284 additions and 56 deletions
@ -0,0 +1,11 @@
|
||||
# Rust example |
||||
|
||||
``` |
||||
cargo install libzt |
||||
``` |
||||
|
||||
Examples: [pkg/crate/libzt/src/examples](pkg/crate/libzt/src/examples) |
||||
|
||||
## Links |
||||
|
||||
- Getting Started: [docs.zerotier.com/sockets](https://docs.zerotier.com/sockets/tutorial.html) |
||||
@ -1,19 +1,36 @@
|
||||
extern crate bindgen; |
||||
|
||||
use cmake::Config; |
||||
use std::env; |
||||
use std::path::PathBuf; |
||||
|
||||
fn main() { |
||||
println!("cargo:rustc-link-lib=zt"); |
||||
println!("cargo:rustc-env=LLVM_CONFIG_PATH=/usr/local/opt/llvm/bin/llvm-config"); |
||||
Config::new("src/native").build_target("zt-static").define("ZTS_ENABLE_RUST", "1").out_dir("target").build(); |
||||
|
||||
println!("cargo:rustc-link-search=target/build/lib"); |
||||
println!("cargo:rustc-link-lib=static=zt"); |
||||
|
||||
// See here for reasoning: https://flames-of-code.netlify.app/blog/rust-and-cmake-cplusplus/
|
||||
|
||||
let target = env::var("TARGET").unwrap(); |
||||
if target.contains("apple") { |
||||
println!("cargo:rustc-link-lib=dylib=c++"); |
||||
} else if target.contains("linux") { |
||||
println!("cargo:rustc-link-lib=dylib=stdc++"); |
||||
} else { |
||||
unimplemented!(); |
||||
} |
||||
|
||||
//println!("cargo:rerun-if-changed=../../../include/ZeroTierSockets.h");
|
||||
//println!("cargo:include=/usr/local/include");
|
||||
//println!("cargo:rustc-env=LLVM_CONFIG_PATH=/usr/local/opt/llvm/bin/llvm-config");
|
||||
|
||||
let bindings = bindgen::Builder::default() |
||||
.header("../../../include/ZeroTierSockets.h") |
||||
.header("src/native/include/ZeroTierSockets.h") |
||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks)) |
||||
.generate() |
||||
.expect("Unable to generate bindings"); |
||||
|
||||
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); |
||||
bindings |
||||
.write_to_file("./src/libzt.rs") |
||||
.write_to_file(out_path.join("libzt.rs")) |
||||
.expect("Couldn't write bindings!"); |
||||
} |
||||
|
||||
@ -0,0 +1,146 @@
|
||||
use libzt; |
||||
|
||||
use std::env; |
||||
|
||||
use libzt::tcp::{TcpListener, TcpStream}; |
||||
use std::io::{Read, Write}; |
||||
use std::net::Shutdown; |
||||
use std::str::from_utf8; |
||||
use std::thread; |
||||
|
||||
// (Optional) Notify application of ZeroTier events, some with context
|
||||
fn user_event_handler(event_code: i16) -> () { |
||||
println!("user_event {}", event_code); |
||||
} |
||||
|
||||
fn handle_client(mut stream: TcpStream) { |
||||
let mut data = [0 as u8; 50]; // using 50 byte buffer
|
||||
while match stream.read(&mut data) { |
||||
Ok(size) => { |
||||
// echo everything!
|
||||
stream.write(&data[0..size]).unwrap(); |
||||
true |
||||
} |
||||
Err(_) => { |
||||
println!( |
||||
"An error occurred, terminating connection with {}", |
||||
stream.peer_addr().unwrap() |
||||
); |
||||
stream.shutdown(Shutdown::Both).unwrap(); |
||||
false |
||||
} |
||||
} {} |
||||
} |
||||
|
||||
fn main() -> std::io::Result<()> { |
||||
let args: Vec<String> = env::args().collect(); |
||||
println!("{:?}", args); |
||||
|
||||
if args.len() != 5 && args.len() != 6 { |
||||
println!("Incorrect number of arguments."); |
||||
println!(" Usage: server <storage_path> <net_id> <local_ip> <local_port>"); |
||||
println!(" Usage: client <storage_path> <net_id> <remote_ip> <remote_port>"); |
||||
} |
||||
|
||||
let storage_path = &args[2]; |
||||
let net_id = u64::from_str_radix(&args[3], 16).unwrap(); |
||||
|
||||
println!("path = {}", storage_path); |
||||
println!("net_id = {:x}", net_id); |
||||
|
||||
// SET UP ZEROTIER
|
||||
|
||||
let nn = libzt::node::ZeroTierNode {}; |
||||
// (Optional) initialization
|
||||
nn.init_set_port(0); |
||||
nn.init_set_event_handler(user_event_handler); |
||||
nn.init_from_storage(&storage_path); |
||||
// Start the node
|
||||
nn.start(); |
||||
println!("Waiting for node to come online..."); |
||||
while !nn.is_online() { |
||||
nn.delay(50); |
||||
} |
||||
println!("Node ID = {:#06x}", nn.id()); |
||||
println!("Joining network"); |
||||
nn.net_join(net_id); |
||||
println!("Waiting for network to assign addresses..."); |
||||
while !nn.net_transport_is_ready(net_id) { |
||||
nn.delay(50); |
||||
} |
||||
let addr = nn.addr_get(net_id).unwrap(); |
||||
println!("Assigned addr = {}", addr); |
||||
|
||||
// Server
|
||||
|
||||
if &args[1] == "server" { |
||||
println!("server mode"); |
||||
let mut addr_str: String = "".to_owned(); |
||||
addr_str.push_str(&args[4]); |
||||
addr_str.push_str(":"); |
||||
addr_str.push_str(&args[5]); |
||||
|
||||
let server: std::net::SocketAddr = |
||||
addr_str.parse().expect("Unable to parse socket address"); |
||||
let listener = TcpListener::bind(&server).unwrap(); |
||||
|
||||
for stream in listener.incoming() { |
||||
match stream { |
||||
Ok(stream) => { |
||||
println!("New connection: {}", stream.peer_addr().unwrap()); |
||||
thread::spawn(move || { |
||||
// connection succeeded
|
||||
handle_client(stream) |
||||
}); |
||||
} |
||||
Err(e) => { |
||||
println!("Error: {}", e); |
||||
// connection failed
|
||||
} |
||||
} |
||||
} |
||||
drop(listener); |
||||
} |
||||
|
||||
// Client
|
||||
|
||||
if &args[1] == "client" { |
||||
println!("client mode"); |
||||
let mut addr_str: String = "".to_owned(); |
||||
addr_str.push_str(&args[4]); |
||||
addr_str.push_str(":"); |
||||
addr_str.push_str(&args[5]); |
||||
match TcpStream::connect(addr_str) { |
||||
Ok(mut stream) => { |
||||
println!("Successfully connected to server"); |
||||
|
||||
let msg = b"Hello!"; |
||||
|
||||
stream.write(msg).unwrap(); |
||||
println!("Sent Hello, awaiting reply..."); |
||||
|
||||
let mut data = [0 as u8; 6]; |
||||
match stream.read_exact(&mut data) { |
||||
Ok(_) => { |
||||
if &data == msg { |
||||
println!("Reply is ok!"); |
||||
} else { |
||||
let text = from_utf8(&data).unwrap(); |
||||
println!("Unexpected reply: {}", text); |
||||
} |
||||
} |
||||
Err(e) => { |
||||
println!("Failed to receive data: {}", e); |
||||
} |
||||
} |
||||
} |
||||
Err(e) => { |
||||
println!("Failed to connect: {}", e); |
||||
} |
||||
} |
||||
println!("Terminated."); |
||||
} |
||||
|
||||
nn.stop(); |
||||
Ok(()) |
||||
} |
||||
Loading…
Reference in new issue