├── .github └── workflows │ └── release.yml ├── .gitignore ├── Cargo.toml ├── README.md ├── build.rs ├── examples ├── demo-async-tcp.rs ├── demo-tcp.rs └── demo-udp.rs ├── proto └── rndz.proto └── src ├── lib.rs ├── main.rs ├── proto ├── mod.rs └── rndz.rs ├── tcp ├── client.rs ├── client_async.rs ├── mod.rs └── server.rs └── udp ├── client.rs ├── mod.rs └── server.rs /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # .github/workflows/release.yml 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | release: 9 | name: release ${{ matrix.target }} 10 | runs-on: ubuntu-latest 11 | strategy: 12 | fail-fast: false 13 | matrix: 14 | include: 15 | - target: x86_64-pc-windows-gnu 16 | archive: zip 17 | - target: x86_64-unknown-linux-musl 18 | archive: tar.gz 19 | 20 | steps: 21 | - uses: actions/checkout@master 22 | - name: Compile and release 23 | uses: rust-build/rust-build.action@latest 24 | env: 25 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 26 | RUSTTARGET: ${{ matrix.target }} 27 | ARCHIVE_TYPES: ${{ matrix.archive }} 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rndz" 3 | version = "0.1.5" 4 | edition = "2021" 5 | description = "A simple rendezvous protocol implementation to help with NAT traversal or hole punchin" 6 | repository = "https://github.com/optman/rndz" 7 | license = "MIT" 8 | 9 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 10 | # 11 | # 12 | # 13 | 14 | [build-dependencies] 15 | protobuf-codegen = "3.7.1" 16 | 17 | [features] 18 | default = ["client", "server", "async", "env_logger", "structopt"] 19 | server = ["tokio"] 20 | async = ["tokio"] 21 | client = [] 22 | 23 | [dependencies] 24 | log = { version = "0.4.22" } 25 | env_logger = { version = "0.11.5", optional = true } 26 | structopt = { version = "0.3.26", optional = true } 27 | protobuf = "3.7.1" 28 | socket2 = { version = "0.5.8", features = ["all"] } 29 | tokio = { version = "1.42.0", features = ["full"], optional = true } 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rndz 2 | 3 | A simple rendezvous protocol implementation to help with NAT traversal or hole punching. 4 | 5 | The main idea is straightforward: using a rendezvous server to observe peers' addresses and forward connection requests. When both peers send packets to each other, the NAT device or firewall rule then allows the traffic through. 6 | 7 | ## Usage 8 | 9 | ### TCP Listen/Connect 10 | 11 | #### Client 1 12 | 13 | ```rust 14 | use rndz::tcp::Client; 15 | 16 | let c1 = Client::new(rndz_server_addr, "c1", None)?; 17 | c1.listen()?; 18 | while let Ok(stream) = c1.accept()? { 19 | // Handle stream 20 | } 21 | ``` 22 | 23 | #### Client 2 24 | 25 | ```rust 26 | use rndz::tcp::Client; 27 | 28 | let c2 = Client::new(rndz_server_addr, "c2", None)?; 29 | let stream = c2.connect("c1")?; 30 | ``` 31 | 32 | ### Pair Two UDP Sockets 33 | 34 | #### Client 1 35 | 36 | ```rust 37 | use rndz::udp::Client; 38 | 39 | let c1 = Client::new(rndz_server_addr, "c1", None)?; 40 | c1.listen()?; 41 | c1.as_socket().recv_from(...)? 42 | ``` 43 | 44 | #### Client 2 45 | 46 | ```rust 47 | use rndz::udp::Client; 48 | 49 | let c2 = Client::new(rndz_server_addr, "c2", None)?; 50 | c2.connect("c1")?; 51 | c2.as_socket().send(b'hello')? 52 | ``` 53 | 54 | ## Testing 55 | 56 | ### Rndz Server 57 | 58 | ```sh 59 | $ rndz server --listen-addr 0.0.0.0:8888 # To allow clients to communicate with IPv6, use [::]:8888 60 | ``` 61 | 62 | ### Client 1 63 | 64 | ```sh 65 | $ rndz client --id c1 --server-addr rndz_server:8888 66 | ``` 67 | 68 | ### Client 2 69 | 70 | ```sh 71 | $ rndz client --id c2 --server-addr rndz_server:8888 --remote-peer c1 72 | ``` 73 | 74 | ## Portability 75 | 76 | Due to the reliance on socket options `SO_REUSEADDR` and `SO_REUSEPORT` [behavior](https://stackoverflow.com/questions/14388706/how-do-so-reuseaddr-and-so-reuseport-differ/14388707#14388707), and the [`connected` UDP socket](https://blog.cloudflare.com/everything-you-ever-wanted-to-know-about-udp-sockets-but-were-afraid-to-ask-part-1/), it does not work on all platforms. 77 | 78 | Tests pass on Linux; however, `udp::Client::listen()` does not work on Windows. 79 | 80 | ## Used in Projects 81 | 82 | - [quic-tun](https://github.com/optman/quic-tun): A QUIC-based port forward. 83 | - [minivtun-rs](https://github.com/optman/minivtun-rs): A UDP-based VPN. 84 | - [rndz-go](https://github.com/optman/rndz-go): Golang implementation of rndz. -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | //extern crate protobuf_codegen_pure; 2 | 3 | fn main() { 4 | if std::env::var("DOCS_RS").is_ok() { 5 | return; 6 | } 7 | protobuf_codegen::Codegen::new() 8 | .out_dir("src/proto") 9 | .inputs(["proto/rndz.proto"]) 10 | .include("proto") 11 | .run() 12 | .expect("Codegen failed."); 13 | } 14 | -------------------------------------------------------------------------------- /examples/demo-async-tcp.rs: -------------------------------------------------------------------------------- 1 | use rndz::tcp::AsyncClient; 2 | use rndz::tcp::Server; 3 | use std::error::Error; 4 | use std::time::Duration; 5 | use tokio::{ 6 | io::{AsyncReadExt, AsyncWriteExt}, 7 | task::spawn, 8 | time::sleep, 9 | }; 10 | 11 | #[tokio::main] 12 | async fn main() -> Result<(), Box> { 13 | let server_addr = "127.0.0.1:8888"; 14 | 15 | { 16 | spawn(async move { Server::new(server_addr).await?.run().await }); 17 | } 18 | 19 | let t = { 20 | spawn(async move { 21 | let mut c = AsyncClient::new(server_addr, "c1", None).unwrap(); 22 | loop { 23 | match c.listen().await { 24 | Ok(_) => { 25 | let (mut s, _) = c.accept().await.unwrap(); 26 | s.write(b"hello").await.unwrap(); 27 | break; 28 | } 29 | _ => { 30 | sleep(Duration::from_secs(1)).await; 31 | continue; 32 | } 33 | } 34 | } 35 | }) 36 | }; 37 | 38 | let mut c = AsyncClient::new(server_addr, "c2", None)?; 39 | let mut s = loop { 40 | match c.connect("c1").await { 41 | Ok(s) => break s, 42 | _ => sleep(Duration::from_secs(1)).await, 43 | } 44 | }; 45 | 46 | let mut buf = [0; 5]; 47 | s.read(&mut buf).await?; 48 | 49 | t.await?; 50 | 51 | Ok(()) 52 | } 53 | -------------------------------------------------------------------------------- /examples/demo-tcp.rs: -------------------------------------------------------------------------------- 1 | use rndz::tcp::{Client, Server}; 2 | use std::error::Error; 3 | use std::io::{Read, Write}; 4 | use std::thread; 5 | use std::time::Duration; 6 | 7 | fn main() -> Result<(), Box> { 8 | let server_addr = "127.0.0.1:8888"; 9 | 10 | let rt = tokio::runtime::Runtime::new().unwrap(); 11 | { 12 | rt.spawn(async move { Server::new(server_addr).await.unwrap().run().await }); 13 | } 14 | 15 | let t = thread::spawn(move || { 16 | let mut c = Client::new(server_addr, "c1", None).unwrap(); 17 | loop { 18 | match c.listen() { 19 | Ok(_) => { 20 | let (mut s, _) = c.accept().unwrap(); 21 | s.write(b"hello").unwrap(); 22 | break; 23 | } 24 | _ => { 25 | thread::sleep(Duration::from_secs(1)); 26 | continue; 27 | } 28 | } 29 | } 30 | }); 31 | 32 | let mut c = Client::new(server_addr, "c2", None).unwrap(); 33 | let mut s = loop { 34 | match c.connect("c1") { 35 | Ok(s) => break s, 36 | _ => thread::sleep(Duration::from_secs(1)), 37 | } 38 | }; 39 | 40 | let mut buf = [0; 5]; 41 | s.read(&mut buf)?; 42 | 43 | t.join().unwrap(); 44 | 45 | Ok(()) 46 | } 47 | -------------------------------------------------------------------------------- /examples/demo-udp.rs: -------------------------------------------------------------------------------- 1 | use rndz::udp::{Client, Server}; 2 | use std::error::Error; 3 | use std::thread; 4 | use std::time; 5 | 6 | fn main() -> Result<(), Box> { 7 | let server_addr = "127.0.0.1:8888"; 8 | 9 | { 10 | thread::spawn(move || Server::new(server_addr).unwrap().run().unwrap()); 11 | } 12 | 13 | let t = { 14 | thread::spawn(move || { 15 | let mut c = Client::new(server_addr, "c1", None, None).unwrap(); 16 | let s = c.listen().unwrap(); 17 | let mut buf = [0; 10]; 18 | let n = s.recv(&mut buf).unwrap(); 19 | assert_eq!(&buf[..n], b"hello"); 20 | }) 21 | }; 22 | 23 | loop { 24 | let mut c = Client::new(server_addr, "c2", None, None).unwrap(); 25 | match c.connect("c1") { 26 | Ok(s) => { 27 | s.send(b"hello").unwrap(); 28 | break; 29 | } 30 | _ => thread::sleep(time::Duration::from_secs(2)), 31 | } 32 | } 33 | 34 | t.join().unwrap(); 35 | 36 | Ok(()) 37 | } 38 | -------------------------------------------------------------------------------- /proto/rndz.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | message Request{ 4 | string id = 1; 5 | oneof cmd{ 6 | Ping Ping = 2; 7 | Isync Isync = 3; 8 | Fsync Fsync = 4; 9 | Rsync Rsync = 5; 10 | Bye Bye = 6; 11 | } 12 | } 13 | 14 | message Ping{ 15 | } 16 | 17 | 18 | message Isync{ 19 | string id = 1; 20 | } 21 | 22 | message Response{ 23 | string id = 1; 24 | oneof cmd{ 25 | Pong Pong = 2; 26 | Redirect Redirect= 3; 27 | Fsync Fsync = 4; 28 | } 29 | } 30 | 31 | message Pong{ 32 | } 33 | 34 | message Redirect{ 35 | string id = 1; 36 | string addr = 2; 37 | } 38 | 39 | message Fsync{ 40 | string id = 1; 41 | string addr = 2; 42 | } 43 | 44 | message Rsync{ 45 | string id = 1; 46 | } 47 | 48 | message Bye{ 49 | } 50 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! A simple rendezvous protocol implementation to help with NAT traversal or hole punching. 2 | //! 3 | //! To connect a node behind a firewall or NAT (such as a home gateway), which only allows outbound connections, 4 | //! you not only need to know its gateway IP, but you also need the node to send you traffic first. 5 | //! 6 | //! This applies not only to IPv4 but also to IPv6. While IPv4 needs to deal with NAT, both need to handle firewall restrictions. 7 | //! 8 | //! ## How rndz works 9 | //! Setup a publicly accessible server as a rendezvous point to observe all peers' addresses and forward connection requests. 10 | //! 11 | //! Each peer needs a unique identity, and the server will associate this identity with the observed address. 12 | //! A listening peer will keep pinging the server and receive forward requests. 13 | //! A connecting peer will request the server to forward the connection request. 14 | //! After receiving the forwarded connection request from the server, the listening peer will send a dummy packet to the connecting peer. 15 | //! This will open the firewall or NAT rule for the connecting peer; otherwise, all packets from the peer will be blocked. 16 | //! After that, we return the native socket types [`std::net::TcpStream`] and [`std::net::UdpSocket`] to the caller. 17 | //! 18 | //! The essential part is that we must use the same port to communicate with the rendezvous server and peers. 19 | //! 20 | //! The implementation depends on the socket options `SO_REUSEADDR` and `SO_REUSEPORT`, so it is OS-dependent. 21 | //! For TCP, the OS should allow the listening socket and connecting socket to bind to the same port. 22 | //! For UDP, the OS should correctly dispatch traffic to both connected and unconnected UDP sockets bound to the same port. 23 | //! 24 | //! ## Feature flags 25 | //! For convenience, the crate includes both client and server code by default. 26 | //! Mostly, you will only use client or server code, so set features to `client` or `server` instead. 27 | //! 28 | //! ```toml 29 | //! rndz = { version = "0.1", default-features = false, features = ["client"] } 30 | //! ``` 31 | //! 32 | //! - `client`: TCP, UDP client 33 | //! - `server`: rendezvous server 34 | //! - `async`: TCP async client, returns [`tokio::net::TcpStream`] 35 | 36 | #[doc(hidden)] 37 | pub mod proto; 38 | pub mod tcp; 39 | pub mod udp; 40 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io::Result; 2 | use std::net::SocketAddr; 3 | use structopt::StructOpt; 4 | use tokio::{ 5 | io::{AsyncReadExt, AsyncWriteExt}, 6 | task, 7 | }; 8 | 9 | use rndz::{tcp, udp}; 10 | 11 | #[derive(StructOpt, Debug)] 12 | #[structopt(name = "rndz")] 13 | enum Opt { 14 | Client(ClientOpt), 15 | Server(ServerOpt), 16 | } 17 | 18 | #[derive(StructOpt, Debug)] 19 | struct ClientOpt { 20 | #[structopt(long = "id")] 21 | id: String, 22 | 23 | #[structopt(long = "server-addr")] 24 | server_addr: String, 25 | 26 | #[structopt(long = "remote-peer")] 27 | remote_peer: Option, 28 | 29 | #[structopt(long = "tcp")] 30 | tcp: bool, 31 | } 32 | 33 | #[derive(StructOpt, Debug)] 34 | struct ServerOpt { 35 | #[structopt(long = "listen-addr", default_value = "0.0.0.0:8888")] 36 | listen_addr: SocketAddr, 37 | } 38 | 39 | #[tokio::main] 40 | async fn main() -> Result<()> { 41 | let opt: Opt = StructOpt::from_args(); 42 | 43 | env_logger::init_from_env( 44 | env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), 45 | ); 46 | 47 | match opt { 48 | Opt::Server(opt) => run_server(opt).await, 49 | Opt::Client(opt) => run_client(opt).await, 50 | } 51 | } 52 | 53 | async fn run_server(opt: ServerOpt) -> Result<()> { 54 | let s = udp::Server::new(opt.listen_addr)?; 55 | task::spawn_blocking(|| { 56 | s.run().unwrap(); 57 | }); 58 | 59 | let s = tcp::Server::new(opt.listen_addr).await?; 60 | s.run().await 61 | } 62 | 63 | async fn run_client(opt: ClientOpt) -> Result<()> { 64 | if !opt.tcp { 65 | let mut c = udp::Client::new(&opt.server_addr, &opt.id, None, None)?; 66 | 67 | match opt.remote_peer { 68 | Some(peer) => { 69 | let s = c.connect(&peer)?; 70 | s.send(b"hello")?; 71 | let mut buf = [0; 1500]; 72 | let (n, addr) = s.recv_from(&mut buf)?; 73 | log::debug!("receive {} bytes from {}", n, addr.to_string()); 74 | } 75 | None => { 76 | let s = c.listen()?; 77 | let mut buf = [0; 1500]; 78 | while let Ok((n, addr)) = s.recv_from(&mut buf) { 79 | log::debug!("receive {} bytes from {}", n, addr.to_string()); 80 | let _ = s.send_to(&buf[..n], addr); 81 | } 82 | } 83 | } 84 | } else { 85 | let mut c = tcp::AsyncClient::new(&opt.server_addr, &opt.id, None)?; 86 | 87 | match opt.remote_peer { 88 | Some(peer) => { 89 | let mut stream = c.connect(&peer).await?; 90 | log::debug!("connect success"); 91 | let _ = stream.write_all(b"hello").await; 92 | let mut buf = [0; 5]; 93 | let n = stream.read(&mut buf).await.unwrap(); 94 | log::debug!("read {} bytes", n); 95 | } 96 | None => { 97 | c.listen().await?; 98 | while let Ok((mut stream, addr)) = c.accept().await { 99 | log::debug!("accept {}", addr.to_string()); 100 | task::spawn(async move { 101 | let mut buf = [0; 5]; 102 | let n = stream.read(&mut buf).await.unwrap(); 103 | log::debug!("read {} bytes", n); 104 | let _ = stream.write_all(b"hello").await; 105 | }); 106 | } 107 | } 108 | } 109 | } 110 | 111 | Ok(()) 112 | } 113 | -------------------------------------------------------------------------------- /src/proto/mod.rs: -------------------------------------------------------------------------------- 1 | // @generated 2 | 3 | pub mod rndz; 4 | -------------------------------------------------------------------------------- /src/proto/rndz.rs: -------------------------------------------------------------------------------- 1 | // This file is generated by rust-protobuf 3.7.1. Do not edit 2 | // .proto file is parsed by protoc 3.20.0 3 | // @generated 4 | 5 | // https://github.com/rust-lang/rust-clippy/issues/702 6 | #![allow(unknown_lints)] 7 | #![allow(clippy::all)] 8 | 9 | #![allow(unused_attributes)] 10 | #![cfg_attr(rustfmt, rustfmt::skip)] 11 | 12 | #![allow(dead_code)] 13 | #![allow(missing_docs)] 14 | #![allow(non_camel_case_types)] 15 | #![allow(non_snake_case)] 16 | #![allow(non_upper_case_globals)] 17 | #![allow(trivial_casts)] 18 | #![allow(unused_results)] 19 | #![allow(unused_mut)] 20 | 21 | //! Generated file from `rndz.proto` 22 | 23 | /// Generated files are compatible only with the same version 24 | /// of protobuf runtime. 25 | const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_7_1; 26 | 27 | // @@protoc_insertion_point(message:Request) 28 | #[derive(PartialEq,Clone,Default,Debug)] 29 | pub struct Request { 30 | // message fields 31 | // @@protoc_insertion_point(field:Request.id) 32 | pub id: ::std::string::String, 33 | // message oneof groups 34 | pub cmd: ::std::option::Option, 35 | // special fields 36 | // @@protoc_insertion_point(special_field:Request.special_fields) 37 | pub special_fields: ::protobuf::SpecialFields, 38 | } 39 | 40 | impl<'a> ::std::default::Default for &'a Request { 41 | fn default() -> &'a Request { 42 | ::default_instance() 43 | } 44 | } 45 | 46 | impl Request { 47 | pub fn new() -> Request { 48 | ::std::default::Default::default() 49 | } 50 | 51 | // .Ping Ping = 2; 52 | 53 | pub fn Ping(&self) -> &Ping { 54 | match self.cmd { 55 | ::std::option::Option::Some(request::Cmd::Ping(ref v)) => v, 56 | _ => ::default_instance(), 57 | } 58 | } 59 | 60 | pub fn clear_Ping(&mut self) { 61 | self.cmd = ::std::option::Option::None; 62 | } 63 | 64 | pub fn has_Ping(&self) -> bool { 65 | match self.cmd { 66 | ::std::option::Option::Some(request::Cmd::Ping(..)) => true, 67 | _ => false, 68 | } 69 | } 70 | 71 | // Param is passed by value, moved 72 | pub fn set_Ping(&mut self, v: Ping) { 73 | self.cmd = ::std::option::Option::Some(request::Cmd::Ping(v)) 74 | } 75 | 76 | // Mutable pointer to the field. 77 | pub fn mut_Ping(&mut self) -> &mut Ping { 78 | if let ::std::option::Option::Some(request::Cmd::Ping(_)) = self.cmd { 79 | } else { 80 | self.cmd = ::std::option::Option::Some(request::Cmd::Ping(Ping::new())); 81 | } 82 | match self.cmd { 83 | ::std::option::Option::Some(request::Cmd::Ping(ref mut v)) => v, 84 | _ => panic!(), 85 | } 86 | } 87 | 88 | // Take field 89 | pub fn take_Ping(&mut self) -> Ping { 90 | if self.has_Ping() { 91 | match self.cmd.take() { 92 | ::std::option::Option::Some(request::Cmd::Ping(v)) => v, 93 | _ => panic!(), 94 | } 95 | } else { 96 | Ping::new() 97 | } 98 | } 99 | 100 | // .Isync Isync = 3; 101 | 102 | pub fn Isync(&self) -> &Isync { 103 | match self.cmd { 104 | ::std::option::Option::Some(request::Cmd::Isync(ref v)) => v, 105 | _ => ::default_instance(), 106 | } 107 | } 108 | 109 | pub fn clear_Isync(&mut self) { 110 | self.cmd = ::std::option::Option::None; 111 | } 112 | 113 | pub fn has_Isync(&self) -> bool { 114 | match self.cmd { 115 | ::std::option::Option::Some(request::Cmd::Isync(..)) => true, 116 | _ => false, 117 | } 118 | } 119 | 120 | // Param is passed by value, moved 121 | pub fn set_Isync(&mut self, v: Isync) { 122 | self.cmd = ::std::option::Option::Some(request::Cmd::Isync(v)) 123 | } 124 | 125 | // Mutable pointer to the field. 126 | pub fn mut_Isync(&mut self) -> &mut Isync { 127 | if let ::std::option::Option::Some(request::Cmd::Isync(_)) = self.cmd { 128 | } else { 129 | self.cmd = ::std::option::Option::Some(request::Cmd::Isync(Isync::new())); 130 | } 131 | match self.cmd { 132 | ::std::option::Option::Some(request::Cmd::Isync(ref mut v)) => v, 133 | _ => panic!(), 134 | } 135 | } 136 | 137 | // Take field 138 | pub fn take_Isync(&mut self) -> Isync { 139 | if self.has_Isync() { 140 | match self.cmd.take() { 141 | ::std::option::Option::Some(request::Cmd::Isync(v)) => v, 142 | _ => panic!(), 143 | } 144 | } else { 145 | Isync::new() 146 | } 147 | } 148 | 149 | // .Fsync Fsync = 4; 150 | 151 | pub fn Fsync(&self) -> &Fsync { 152 | match self.cmd { 153 | ::std::option::Option::Some(request::Cmd::Fsync(ref v)) => v, 154 | _ => ::default_instance(), 155 | } 156 | } 157 | 158 | pub fn clear_Fsync(&mut self) { 159 | self.cmd = ::std::option::Option::None; 160 | } 161 | 162 | pub fn has_Fsync(&self) -> bool { 163 | match self.cmd { 164 | ::std::option::Option::Some(request::Cmd::Fsync(..)) => true, 165 | _ => false, 166 | } 167 | } 168 | 169 | // Param is passed by value, moved 170 | pub fn set_Fsync(&mut self, v: Fsync) { 171 | self.cmd = ::std::option::Option::Some(request::Cmd::Fsync(v)) 172 | } 173 | 174 | // Mutable pointer to the field. 175 | pub fn mut_Fsync(&mut self) -> &mut Fsync { 176 | if let ::std::option::Option::Some(request::Cmd::Fsync(_)) = self.cmd { 177 | } else { 178 | self.cmd = ::std::option::Option::Some(request::Cmd::Fsync(Fsync::new())); 179 | } 180 | match self.cmd { 181 | ::std::option::Option::Some(request::Cmd::Fsync(ref mut v)) => v, 182 | _ => panic!(), 183 | } 184 | } 185 | 186 | // Take field 187 | pub fn take_Fsync(&mut self) -> Fsync { 188 | if self.has_Fsync() { 189 | match self.cmd.take() { 190 | ::std::option::Option::Some(request::Cmd::Fsync(v)) => v, 191 | _ => panic!(), 192 | } 193 | } else { 194 | Fsync::new() 195 | } 196 | } 197 | 198 | // .Rsync Rsync = 5; 199 | 200 | pub fn Rsync(&self) -> &Rsync { 201 | match self.cmd { 202 | ::std::option::Option::Some(request::Cmd::Rsync(ref v)) => v, 203 | _ => ::default_instance(), 204 | } 205 | } 206 | 207 | pub fn clear_Rsync(&mut self) { 208 | self.cmd = ::std::option::Option::None; 209 | } 210 | 211 | pub fn has_Rsync(&self) -> bool { 212 | match self.cmd { 213 | ::std::option::Option::Some(request::Cmd::Rsync(..)) => true, 214 | _ => false, 215 | } 216 | } 217 | 218 | // Param is passed by value, moved 219 | pub fn set_Rsync(&mut self, v: Rsync) { 220 | self.cmd = ::std::option::Option::Some(request::Cmd::Rsync(v)) 221 | } 222 | 223 | // Mutable pointer to the field. 224 | pub fn mut_Rsync(&mut self) -> &mut Rsync { 225 | if let ::std::option::Option::Some(request::Cmd::Rsync(_)) = self.cmd { 226 | } else { 227 | self.cmd = ::std::option::Option::Some(request::Cmd::Rsync(Rsync::new())); 228 | } 229 | match self.cmd { 230 | ::std::option::Option::Some(request::Cmd::Rsync(ref mut v)) => v, 231 | _ => panic!(), 232 | } 233 | } 234 | 235 | // Take field 236 | pub fn take_Rsync(&mut self) -> Rsync { 237 | if self.has_Rsync() { 238 | match self.cmd.take() { 239 | ::std::option::Option::Some(request::Cmd::Rsync(v)) => v, 240 | _ => panic!(), 241 | } 242 | } else { 243 | Rsync::new() 244 | } 245 | } 246 | 247 | // .Bye Bye = 6; 248 | 249 | pub fn Bye(&self) -> &Bye { 250 | match self.cmd { 251 | ::std::option::Option::Some(request::Cmd::Bye(ref v)) => v, 252 | _ => ::default_instance(), 253 | } 254 | } 255 | 256 | pub fn clear_Bye(&mut self) { 257 | self.cmd = ::std::option::Option::None; 258 | } 259 | 260 | pub fn has_Bye(&self) -> bool { 261 | match self.cmd { 262 | ::std::option::Option::Some(request::Cmd::Bye(..)) => true, 263 | _ => false, 264 | } 265 | } 266 | 267 | // Param is passed by value, moved 268 | pub fn set_Bye(&mut self, v: Bye) { 269 | self.cmd = ::std::option::Option::Some(request::Cmd::Bye(v)) 270 | } 271 | 272 | // Mutable pointer to the field. 273 | pub fn mut_Bye(&mut self) -> &mut Bye { 274 | if let ::std::option::Option::Some(request::Cmd::Bye(_)) = self.cmd { 275 | } else { 276 | self.cmd = ::std::option::Option::Some(request::Cmd::Bye(Bye::new())); 277 | } 278 | match self.cmd { 279 | ::std::option::Option::Some(request::Cmd::Bye(ref mut v)) => v, 280 | _ => panic!(), 281 | } 282 | } 283 | 284 | // Take field 285 | pub fn take_Bye(&mut self) -> Bye { 286 | if self.has_Bye() { 287 | match self.cmd.take() { 288 | ::std::option::Option::Some(request::Cmd::Bye(v)) => v, 289 | _ => panic!(), 290 | } 291 | } else { 292 | Bye::new() 293 | } 294 | } 295 | 296 | fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { 297 | let mut fields = ::std::vec::Vec::with_capacity(6); 298 | let mut oneofs = ::std::vec::Vec::with_capacity(1); 299 | fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( 300 | "id", 301 | |m: &Request| { &m.id }, 302 | |m: &mut Request| { &mut m.id }, 303 | )); 304 | fields.push(::protobuf::reflect::rt::v2::make_oneof_message_has_get_mut_set_accessor::<_, Ping>( 305 | "Ping", 306 | Request::has_Ping, 307 | Request::Ping, 308 | Request::mut_Ping, 309 | Request::set_Ping, 310 | )); 311 | fields.push(::protobuf::reflect::rt::v2::make_oneof_message_has_get_mut_set_accessor::<_, Isync>( 312 | "Isync", 313 | Request::has_Isync, 314 | Request::Isync, 315 | Request::mut_Isync, 316 | Request::set_Isync, 317 | )); 318 | fields.push(::protobuf::reflect::rt::v2::make_oneof_message_has_get_mut_set_accessor::<_, Fsync>( 319 | "Fsync", 320 | Request::has_Fsync, 321 | Request::Fsync, 322 | Request::mut_Fsync, 323 | Request::set_Fsync, 324 | )); 325 | fields.push(::protobuf::reflect::rt::v2::make_oneof_message_has_get_mut_set_accessor::<_, Rsync>( 326 | "Rsync", 327 | Request::has_Rsync, 328 | Request::Rsync, 329 | Request::mut_Rsync, 330 | Request::set_Rsync, 331 | )); 332 | fields.push(::protobuf::reflect::rt::v2::make_oneof_message_has_get_mut_set_accessor::<_, Bye>( 333 | "Bye", 334 | Request::has_Bye, 335 | Request::Bye, 336 | Request::mut_Bye, 337 | Request::set_Bye, 338 | )); 339 | oneofs.push(request::Cmd::generated_oneof_descriptor_data()); 340 | ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( 341 | "Request", 342 | fields, 343 | oneofs, 344 | ) 345 | } 346 | } 347 | 348 | impl ::protobuf::Message for Request { 349 | const NAME: &'static str = "Request"; 350 | 351 | fn is_initialized(&self) -> bool { 352 | true 353 | } 354 | 355 | fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { 356 | while let Some(tag) = is.read_raw_tag_or_eof()? { 357 | match tag { 358 | 10 => { 359 | self.id = is.read_string()?; 360 | }, 361 | 18 => { 362 | self.cmd = ::std::option::Option::Some(request::Cmd::Ping(is.read_message()?)); 363 | }, 364 | 26 => { 365 | self.cmd = ::std::option::Option::Some(request::Cmd::Isync(is.read_message()?)); 366 | }, 367 | 34 => { 368 | self.cmd = ::std::option::Option::Some(request::Cmd::Fsync(is.read_message()?)); 369 | }, 370 | 42 => { 371 | self.cmd = ::std::option::Option::Some(request::Cmd::Rsync(is.read_message()?)); 372 | }, 373 | 50 => { 374 | self.cmd = ::std::option::Option::Some(request::Cmd::Bye(is.read_message()?)); 375 | }, 376 | tag => { 377 | ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; 378 | }, 379 | }; 380 | } 381 | ::std::result::Result::Ok(()) 382 | } 383 | 384 | // Compute sizes of nested messages 385 | #[allow(unused_variables)] 386 | fn compute_size(&self) -> u64 { 387 | let mut my_size = 0; 388 | if !self.id.is_empty() { 389 | my_size += ::protobuf::rt::string_size(1, &self.id); 390 | } 391 | if let ::std::option::Option::Some(ref v) = self.cmd { 392 | match v { 393 | &request::Cmd::Ping(ref v) => { 394 | let len = v.compute_size(); 395 | my_size += 1 + ::protobuf::rt::compute_raw_varint64_size(len) + len; 396 | }, 397 | &request::Cmd::Isync(ref v) => { 398 | let len = v.compute_size(); 399 | my_size += 1 + ::protobuf::rt::compute_raw_varint64_size(len) + len; 400 | }, 401 | &request::Cmd::Fsync(ref v) => { 402 | let len = v.compute_size(); 403 | my_size += 1 + ::protobuf::rt::compute_raw_varint64_size(len) + len; 404 | }, 405 | &request::Cmd::Rsync(ref v) => { 406 | let len = v.compute_size(); 407 | my_size += 1 + ::protobuf::rt::compute_raw_varint64_size(len) + len; 408 | }, 409 | &request::Cmd::Bye(ref v) => { 410 | let len = v.compute_size(); 411 | my_size += 1 + ::protobuf::rt::compute_raw_varint64_size(len) + len; 412 | }, 413 | }; 414 | } 415 | my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); 416 | self.special_fields.cached_size().set(my_size as u32); 417 | my_size 418 | } 419 | 420 | fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { 421 | if !self.id.is_empty() { 422 | os.write_string(1, &self.id)?; 423 | } 424 | if let ::std::option::Option::Some(ref v) = self.cmd { 425 | match v { 426 | &request::Cmd::Ping(ref v) => { 427 | ::protobuf::rt::write_message_field_with_cached_size(2, v, os)?; 428 | }, 429 | &request::Cmd::Isync(ref v) => { 430 | ::protobuf::rt::write_message_field_with_cached_size(3, v, os)?; 431 | }, 432 | &request::Cmd::Fsync(ref v) => { 433 | ::protobuf::rt::write_message_field_with_cached_size(4, v, os)?; 434 | }, 435 | &request::Cmd::Rsync(ref v) => { 436 | ::protobuf::rt::write_message_field_with_cached_size(5, v, os)?; 437 | }, 438 | &request::Cmd::Bye(ref v) => { 439 | ::protobuf::rt::write_message_field_with_cached_size(6, v, os)?; 440 | }, 441 | }; 442 | } 443 | os.write_unknown_fields(self.special_fields.unknown_fields())?; 444 | ::std::result::Result::Ok(()) 445 | } 446 | 447 | fn special_fields(&self) -> &::protobuf::SpecialFields { 448 | &self.special_fields 449 | } 450 | 451 | fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { 452 | &mut self.special_fields 453 | } 454 | 455 | fn new() -> Request { 456 | Request::new() 457 | } 458 | 459 | fn clear(&mut self) { 460 | self.id.clear(); 461 | self.cmd = ::std::option::Option::None; 462 | self.cmd = ::std::option::Option::None; 463 | self.cmd = ::std::option::Option::None; 464 | self.cmd = ::std::option::Option::None; 465 | self.cmd = ::std::option::Option::None; 466 | self.special_fields.clear(); 467 | } 468 | 469 | fn default_instance() -> &'static Request { 470 | static instance: Request = Request { 471 | id: ::std::string::String::new(), 472 | cmd: ::std::option::Option::None, 473 | special_fields: ::protobuf::SpecialFields::new(), 474 | }; 475 | &instance 476 | } 477 | } 478 | 479 | impl ::protobuf::MessageFull for Request { 480 | fn descriptor() -> ::protobuf::reflect::MessageDescriptor { 481 | static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); 482 | descriptor.get(|| file_descriptor().message_by_package_relative_name("Request").unwrap()).clone() 483 | } 484 | } 485 | 486 | impl ::std::fmt::Display for Request { 487 | fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { 488 | ::protobuf::text_format::fmt(self, f) 489 | } 490 | } 491 | 492 | impl ::protobuf::reflect::ProtobufValue for Request { 493 | type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; 494 | } 495 | 496 | /// Nested message and enums of message `Request` 497 | pub mod request { 498 | 499 | #[derive(Clone,PartialEq,Debug)] 500 | #[non_exhaustive] 501 | // @@protoc_insertion_point(oneof:Request.cmd) 502 | pub enum Cmd { 503 | // @@protoc_insertion_point(oneof_field:Request.Ping) 504 | Ping(super::Ping), 505 | // @@protoc_insertion_point(oneof_field:Request.Isync) 506 | Isync(super::Isync), 507 | // @@protoc_insertion_point(oneof_field:Request.Fsync) 508 | Fsync(super::Fsync), 509 | // @@protoc_insertion_point(oneof_field:Request.Rsync) 510 | Rsync(super::Rsync), 511 | // @@protoc_insertion_point(oneof_field:Request.Bye) 512 | Bye(super::Bye), 513 | } 514 | 515 | impl ::protobuf::Oneof for Cmd { 516 | } 517 | 518 | impl ::protobuf::OneofFull for Cmd { 519 | fn descriptor() -> ::protobuf::reflect::OneofDescriptor { 520 | static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::OneofDescriptor> = ::protobuf::rt::Lazy::new(); 521 | descriptor.get(|| ::descriptor().oneof_by_name("cmd").unwrap()).clone() 522 | } 523 | } 524 | 525 | impl Cmd { 526 | pub(in super) fn generated_oneof_descriptor_data() -> ::protobuf::reflect::GeneratedOneofDescriptorData { 527 | ::protobuf::reflect::GeneratedOneofDescriptorData::new::("cmd") 528 | } 529 | } 530 | } 531 | 532 | // @@protoc_insertion_point(message:Ping) 533 | #[derive(PartialEq,Clone,Default,Debug)] 534 | pub struct Ping { 535 | // special fields 536 | // @@protoc_insertion_point(special_field:Ping.special_fields) 537 | pub special_fields: ::protobuf::SpecialFields, 538 | } 539 | 540 | impl<'a> ::std::default::Default for &'a Ping { 541 | fn default() -> &'a Ping { 542 | ::default_instance() 543 | } 544 | } 545 | 546 | impl Ping { 547 | pub fn new() -> Ping { 548 | ::std::default::Default::default() 549 | } 550 | 551 | fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { 552 | let mut fields = ::std::vec::Vec::with_capacity(0); 553 | let mut oneofs = ::std::vec::Vec::with_capacity(0); 554 | ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( 555 | "Ping", 556 | fields, 557 | oneofs, 558 | ) 559 | } 560 | } 561 | 562 | impl ::protobuf::Message for Ping { 563 | const NAME: &'static str = "Ping"; 564 | 565 | fn is_initialized(&self) -> bool { 566 | true 567 | } 568 | 569 | fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { 570 | while let Some(tag) = is.read_raw_tag_or_eof()? { 571 | match tag { 572 | tag => { 573 | ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; 574 | }, 575 | }; 576 | } 577 | ::std::result::Result::Ok(()) 578 | } 579 | 580 | // Compute sizes of nested messages 581 | #[allow(unused_variables)] 582 | fn compute_size(&self) -> u64 { 583 | let mut my_size = 0; 584 | my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); 585 | self.special_fields.cached_size().set(my_size as u32); 586 | my_size 587 | } 588 | 589 | fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { 590 | os.write_unknown_fields(self.special_fields.unknown_fields())?; 591 | ::std::result::Result::Ok(()) 592 | } 593 | 594 | fn special_fields(&self) -> &::protobuf::SpecialFields { 595 | &self.special_fields 596 | } 597 | 598 | fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { 599 | &mut self.special_fields 600 | } 601 | 602 | fn new() -> Ping { 603 | Ping::new() 604 | } 605 | 606 | fn clear(&mut self) { 607 | self.special_fields.clear(); 608 | } 609 | 610 | fn default_instance() -> &'static Ping { 611 | static instance: Ping = Ping { 612 | special_fields: ::protobuf::SpecialFields::new(), 613 | }; 614 | &instance 615 | } 616 | } 617 | 618 | impl ::protobuf::MessageFull for Ping { 619 | fn descriptor() -> ::protobuf::reflect::MessageDescriptor { 620 | static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); 621 | descriptor.get(|| file_descriptor().message_by_package_relative_name("Ping").unwrap()).clone() 622 | } 623 | } 624 | 625 | impl ::std::fmt::Display for Ping { 626 | fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { 627 | ::protobuf::text_format::fmt(self, f) 628 | } 629 | } 630 | 631 | impl ::protobuf::reflect::ProtobufValue for Ping { 632 | type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; 633 | } 634 | 635 | // @@protoc_insertion_point(message:Isync) 636 | #[derive(PartialEq,Clone,Default,Debug)] 637 | pub struct Isync { 638 | // message fields 639 | // @@protoc_insertion_point(field:Isync.id) 640 | pub id: ::std::string::String, 641 | // special fields 642 | // @@protoc_insertion_point(special_field:Isync.special_fields) 643 | pub special_fields: ::protobuf::SpecialFields, 644 | } 645 | 646 | impl<'a> ::std::default::Default for &'a Isync { 647 | fn default() -> &'a Isync { 648 | ::default_instance() 649 | } 650 | } 651 | 652 | impl Isync { 653 | pub fn new() -> Isync { 654 | ::std::default::Default::default() 655 | } 656 | 657 | fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { 658 | let mut fields = ::std::vec::Vec::with_capacity(1); 659 | let mut oneofs = ::std::vec::Vec::with_capacity(0); 660 | fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( 661 | "id", 662 | |m: &Isync| { &m.id }, 663 | |m: &mut Isync| { &mut m.id }, 664 | )); 665 | ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( 666 | "Isync", 667 | fields, 668 | oneofs, 669 | ) 670 | } 671 | } 672 | 673 | impl ::protobuf::Message for Isync { 674 | const NAME: &'static str = "Isync"; 675 | 676 | fn is_initialized(&self) -> bool { 677 | true 678 | } 679 | 680 | fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { 681 | while let Some(tag) = is.read_raw_tag_or_eof()? { 682 | match tag { 683 | 10 => { 684 | self.id = is.read_string()?; 685 | }, 686 | tag => { 687 | ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; 688 | }, 689 | }; 690 | } 691 | ::std::result::Result::Ok(()) 692 | } 693 | 694 | // Compute sizes of nested messages 695 | #[allow(unused_variables)] 696 | fn compute_size(&self) -> u64 { 697 | let mut my_size = 0; 698 | if !self.id.is_empty() { 699 | my_size += ::protobuf::rt::string_size(1, &self.id); 700 | } 701 | my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); 702 | self.special_fields.cached_size().set(my_size as u32); 703 | my_size 704 | } 705 | 706 | fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { 707 | if !self.id.is_empty() { 708 | os.write_string(1, &self.id)?; 709 | } 710 | os.write_unknown_fields(self.special_fields.unknown_fields())?; 711 | ::std::result::Result::Ok(()) 712 | } 713 | 714 | fn special_fields(&self) -> &::protobuf::SpecialFields { 715 | &self.special_fields 716 | } 717 | 718 | fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { 719 | &mut self.special_fields 720 | } 721 | 722 | fn new() -> Isync { 723 | Isync::new() 724 | } 725 | 726 | fn clear(&mut self) { 727 | self.id.clear(); 728 | self.special_fields.clear(); 729 | } 730 | 731 | fn default_instance() -> &'static Isync { 732 | static instance: Isync = Isync { 733 | id: ::std::string::String::new(), 734 | special_fields: ::protobuf::SpecialFields::new(), 735 | }; 736 | &instance 737 | } 738 | } 739 | 740 | impl ::protobuf::MessageFull for Isync { 741 | fn descriptor() -> ::protobuf::reflect::MessageDescriptor { 742 | static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); 743 | descriptor.get(|| file_descriptor().message_by_package_relative_name("Isync").unwrap()).clone() 744 | } 745 | } 746 | 747 | impl ::std::fmt::Display for Isync { 748 | fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { 749 | ::protobuf::text_format::fmt(self, f) 750 | } 751 | } 752 | 753 | impl ::protobuf::reflect::ProtobufValue for Isync { 754 | type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; 755 | } 756 | 757 | // @@protoc_insertion_point(message:Response) 758 | #[derive(PartialEq,Clone,Default,Debug)] 759 | pub struct Response { 760 | // message fields 761 | // @@protoc_insertion_point(field:Response.id) 762 | pub id: ::std::string::String, 763 | // message oneof groups 764 | pub cmd: ::std::option::Option, 765 | // special fields 766 | // @@protoc_insertion_point(special_field:Response.special_fields) 767 | pub special_fields: ::protobuf::SpecialFields, 768 | } 769 | 770 | impl<'a> ::std::default::Default for &'a Response { 771 | fn default() -> &'a Response { 772 | ::default_instance() 773 | } 774 | } 775 | 776 | impl Response { 777 | pub fn new() -> Response { 778 | ::std::default::Default::default() 779 | } 780 | 781 | // .Pong Pong = 2; 782 | 783 | pub fn Pong(&self) -> &Pong { 784 | match self.cmd { 785 | ::std::option::Option::Some(response::Cmd::Pong(ref v)) => v, 786 | _ => ::default_instance(), 787 | } 788 | } 789 | 790 | pub fn clear_Pong(&mut self) { 791 | self.cmd = ::std::option::Option::None; 792 | } 793 | 794 | pub fn has_Pong(&self) -> bool { 795 | match self.cmd { 796 | ::std::option::Option::Some(response::Cmd::Pong(..)) => true, 797 | _ => false, 798 | } 799 | } 800 | 801 | // Param is passed by value, moved 802 | pub fn set_Pong(&mut self, v: Pong) { 803 | self.cmd = ::std::option::Option::Some(response::Cmd::Pong(v)) 804 | } 805 | 806 | // Mutable pointer to the field. 807 | pub fn mut_Pong(&mut self) -> &mut Pong { 808 | if let ::std::option::Option::Some(response::Cmd::Pong(_)) = self.cmd { 809 | } else { 810 | self.cmd = ::std::option::Option::Some(response::Cmd::Pong(Pong::new())); 811 | } 812 | match self.cmd { 813 | ::std::option::Option::Some(response::Cmd::Pong(ref mut v)) => v, 814 | _ => panic!(), 815 | } 816 | } 817 | 818 | // Take field 819 | pub fn take_Pong(&mut self) -> Pong { 820 | if self.has_Pong() { 821 | match self.cmd.take() { 822 | ::std::option::Option::Some(response::Cmd::Pong(v)) => v, 823 | _ => panic!(), 824 | } 825 | } else { 826 | Pong::new() 827 | } 828 | } 829 | 830 | // .Redirect Redirect = 3; 831 | 832 | pub fn Redirect(&self) -> &Redirect { 833 | match self.cmd { 834 | ::std::option::Option::Some(response::Cmd::Redirect(ref v)) => v, 835 | _ => ::default_instance(), 836 | } 837 | } 838 | 839 | pub fn clear_Redirect(&mut self) { 840 | self.cmd = ::std::option::Option::None; 841 | } 842 | 843 | pub fn has_Redirect(&self) -> bool { 844 | match self.cmd { 845 | ::std::option::Option::Some(response::Cmd::Redirect(..)) => true, 846 | _ => false, 847 | } 848 | } 849 | 850 | // Param is passed by value, moved 851 | pub fn set_Redirect(&mut self, v: Redirect) { 852 | self.cmd = ::std::option::Option::Some(response::Cmd::Redirect(v)) 853 | } 854 | 855 | // Mutable pointer to the field. 856 | pub fn mut_Redirect(&mut self) -> &mut Redirect { 857 | if let ::std::option::Option::Some(response::Cmd::Redirect(_)) = self.cmd { 858 | } else { 859 | self.cmd = ::std::option::Option::Some(response::Cmd::Redirect(Redirect::new())); 860 | } 861 | match self.cmd { 862 | ::std::option::Option::Some(response::Cmd::Redirect(ref mut v)) => v, 863 | _ => panic!(), 864 | } 865 | } 866 | 867 | // Take field 868 | pub fn take_Redirect(&mut self) -> Redirect { 869 | if self.has_Redirect() { 870 | match self.cmd.take() { 871 | ::std::option::Option::Some(response::Cmd::Redirect(v)) => v, 872 | _ => panic!(), 873 | } 874 | } else { 875 | Redirect::new() 876 | } 877 | } 878 | 879 | // .Fsync Fsync = 4; 880 | 881 | pub fn Fsync(&self) -> &Fsync { 882 | match self.cmd { 883 | ::std::option::Option::Some(response::Cmd::Fsync(ref v)) => v, 884 | _ => ::default_instance(), 885 | } 886 | } 887 | 888 | pub fn clear_Fsync(&mut self) { 889 | self.cmd = ::std::option::Option::None; 890 | } 891 | 892 | pub fn has_Fsync(&self) -> bool { 893 | match self.cmd { 894 | ::std::option::Option::Some(response::Cmd::Fsync(..)) => true, 895 | _ => false, 896 | } 897 | } 898 | 899 | // Param is passed by value, moved 900 | pub fn set_Fsync(&mut self, v: Fsync) { 901 | self.cmd = ::std::option::Option::Some(response::Cmd::Fsync(v)) 902 | } 903 | 904 | // Mutable pointer to the field. 905 | pub fn mut_Fsync(&mut self) -> &mut Fsync { 906 | if let ::std::option::Option::Some(response::Cmd::Fsync(_)) = self.cmd { 907 | } else { 908 | self.cmd = ::std::option::Option::Some(response::Cmd::Fsync(Fsync::new())); 909 | } 910 | match self.cmd { 911 | ::std::option::Option::Some(response::Cmd::Fsync(ref mut v)) => v, 912 | _ => panic!(), 913 | } 914 | } 915 | 916 | // Take field 917 | pub fn take_Fsync(&mut self) -> Fsync { 918 | if self.has_Fsync() { 919 | match self.cmd.take() { 920 | ::std::option::Option::Some(response::Cmd::Fsync(v)) => v, 921 | _ => panic!(), 922 | } 923 | } else { 924 | Fsync::new() 925 | } 926 | } 927 | 928 | fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { 929 | let mut fields = ::std::vec::Vec::with_capacity(4); 930 | let mut oneofs = ::std::vec::Vec::with_capacity(1); 931 | fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( 932 | "id", 933 | |m: &Response| { &m.id }, 934 | |m: &mut Response| { &mut m.id }, 935 | )); 936 | fields.push(::protobuf::reflect::rt::v2::make_oneof_message_has_get_mut_set_accessor::<_, Pong>( 937 | "Pong", 938 | Response::has_Pong, 939 | Response::Pong, 940 | Response::mut_Pong, 941 | Response::set_Pong, 942 | )); 943 | fields.push(::protobuf::reflect::rt::v2::make_oneof_message_has_get_mut_set_accessor::<_, Redirect>( 944 | "Redirect", 945 | Response::has_Redirect, 946 | Response::Redirect, 947 | Response::mut_Redirect, 948 | Response::set_Redirect, 949 | )); 950 | fields.push(::protobuf::reflect::rt::v2::make_oneof_message_has_get_mut_set_accessor::<_, Fsync>( 951 | "Fsync", 952 | Response::has_Fsync, 953 | Response::Fsync, 954 | Response::mut_Fsync, 955 | Response::set_Fsync, 956 | )); 957 | oneofs.push(response::Cmd::generated_oneof_descriptor_data()); 958 | ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( 959 | "Response", 960 | fields, 961 | oneofs, 962 | ) 963 | } 964 | } 965 | 966 | impl ::protobuf::Message for Response { 967 | const NAME: &'static str = "Response"; 968 | 969 | fn is_initialized(&self) -> bool { 970 | true 971 | } 972 | 973 | fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { 974 | while let Some(tag) = is.read_raw_tag_or_eof()? { 975 | match tag { 976 | 10 => { 977 | self.id = is.read_string()?; 978 | }, 979 | 18 => { 980 | self.cmd = ::std::option::Option::Some(response::Cmd::Pong(is.read_message()?)); 981 | }, 982 | 26 => { 983 | self.cmd = ::std::option::Option::Some(response::Cmd::Redirect(is.read_message()?)); 984 | }, 985 | 34 => { 986 | self.cmd = ::std::option::Option::Some(response::Cmd::Fsync(is.read_message()?)); 987 | }, 988 | tag => { 989 | ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; 990 | }, 991 | }; 992 | } 993 | ::std::result::Result::Ok(()) 994 | } 995 | 996 | // Compute sizes of nested messages 997 | #[allow(unused_variables)] 998 | fn compute_size(&self) -> u64 { 999 | let mut my_size = 0; 1000 | if !self.id.is_empty() { 1001 | my_size += ::protobuf::rt::string_size(1, &self.id); 1002 | } 1003 | if let ::std::option::Option::Some(ref v) = self.cmd { 1004 | match v { 1005 | &response::Cmd::Pong(ref v) => { 1006 | let len = v.compute_size(); 1007 | my_size += 1 + ::protobuf::rt::compute_raw_varint64_size(len) + len; 1008 | }, 1009 | &response::Cmd::Redirect(ref v) => { 1010 | let len = v.compute_size(); 1011 | my_size += 1 + ::protobuf::rt::compute_raw_varint64_size(len) + len; 1012 | }, 1013 | &response::Cmd::Fsync(ref v) => { 1014 | let len = v.compute_size(); 1015 | my_size += 1 + ::protobuf::rt::compute_raw_varint64_size(len) + len; 1016 | }, 1017 | }; 1018 | } 1019 | my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); 1020 | self.special_fields.cached_size().set(my_size as u32); 1021 | my_size 1022 | } 1023 | 1024 | fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { 1025 | if !self.id.is_empty() { 1026 | os.write_string(1, &self.id)?; 1027 | } 1028 | if let ::std::option::Option::Some(ref v) = self.cmd { 1029 | match v { 1030 | &response::Cmd::Pong(ref v) => { 1031 | ::protobuf::rt::write_message_field_with_cached_size(2, v, os)?; 1032 | }, 1033 | &response::Cmd::Redirect(ref v) => { 1034 | ::protobuf::rt::write_message_field_with_cached_size(3, v, os)?; 1035 | }, 1036 | &response::Cmd::Fsync(ref v) => { 1037 | ::protobuf::rt::write_message_field_with_cached_size(4, v, os)?; 1038 | }, 1039 | }; 1040 | } 1041 | os.write_unknown_fields(self.special_fields.unknown_fields())?; 1042 | ::std::result::Result::Ok(()) 1043 | } 1044 | 1045 | fn special_fields(&self) -> &::protobuf::SpecialFields { 1046 | &self.special_fields 1047 | } 1048 | 1049 | fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { 1050 | &mut self.special_fields 1051 | } 1052 | 1053 | fn new() -> Response { 1054 | Response::new() 1055 | } 1056 | 1057 | fn clear(&mut self) { 1058 | self.id.clear(); 1059 | self.cmd = ::std::option::Option::None; 1060 | self.cmd = ::std::option::Option::None; 1061 | self.cmd = ::std::option::Option::None; 1062 | self.special_fields.clear(); 1063 | } 1064 | 1065 | fn default_instance() -> &'static Response { 1066 | static instance: Response = Response { 1067 | id: ::std::string::String::new(), 1068 | cmd: ::std::option::Option::None, 1069 | special_fields: ::protobuf::SpecialFields::new(), 1070 | }; 1071 | &instance 1072 | } 1073 | } 1074 | 1075 | impl ::protobuf::MessageFull for Response { 1076 | fn descriptor() -> ::protobuf::reflect::MessageDescriptor { 1077 | static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); 1078 | descriptor.get(|| file_descriptor().message_by_package_relative_name("Response").unwrap()).clone() 1079 | } 1080 | } 1081 | 1082 | impl ::std::fmt::Display for Response { 1083 | fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { 1084 | ::protobuf::text_format::fmt(self, f) 1085 | } 1086 | } 1087 | 1088 | impl ::protobuf::reflect::ProtobufValue for Response { 1089 | type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; 1090 | } 1091 | 1092 | /// Nested message and enums of message `Response` 1093 | pub mod response { 1094 | 1095 | #[derive(Clone,PartialEq,Debug)] 1096 | #[non_exhaustive] 1097 | // @@protoc_insertion_point(oneof:Response.cmd) 1098 | pub enum Cmd { 1099 | // @@protoc_insertion_point(oneof_field:Response.Pong) 1100 | Pong(super::Pong), 1101 | // @@protoc_insertion_point(oneof_field:Response.Redirect) 1102 | Redirect(super::Redirect), 1103 | // @@protoc_insertion_point(oneof_field:Response.Fsync) 1104 | Fsync(super::Fsync), 1105 | } 1106 | 1107 | impl ::protobuf::Oneof for Cmd { 1108 | } 1109 | 1110 | impl ::protobuf::OneofFull for Cmd { 1111 | fn descriptor() -> ::protobuf::reflect::OneofDescriptor { 1112 | static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::OneofDescriptor> = ::protobuf::rt::Lazy::new(); 1113 | descriptor.get(|| ::descriptor().oneof_by_name("cmd").unwrap()).clone() 1114 | } 1115 | } 1116 | 1117 | impl Cmd { 1118 | pub(in super) fn generated_oneof_descriptor_data() -> ::protobuf::reflect::GeneratedOneofDescriptorData { 1119 | ::protobuf::reflect::GeneratedOneofDescriptorData::new::("cmd") 1120 | } 1121 | } 1122 | } 1123 | 1124 | // @@protoc_insertion_point(message:Pong) 1125 | #[derive(PartialEq,Clone,Default,Debug)] 1126 | pub struct Pong { 1127 | // special fields 1128 | // @@protoc_insertion_point(special_field:Pong.special_fields) 1129 | pub special_fields: ::protobuf::SpecialFields, 1130 | } 1131 | 1132 | impl<'a> ::std::default::Default for &'a Pong { 1133 | fn default() -> &'a Pong { 1134 | ::default_instance() 1135 | } 1136 | } 1137 | 1138 | impl Pong { 1139 | pub fn new() -> Pong { 1140 | ::std::default::Default::default() 1141 | } 1142 | 1143 | fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { 1144 | let mut fields = ::std::vec::Vec::with_capacity(0); 1145 | let mut oneofs = ::std::vec::Vec::with_capacity(0); 1146 | ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( 1147 | "Pong", 1148 | fields, 1149 | oneofs, 1150 | ) 1151 | } 1152 | } 1153 | 1154 | impl ::protobuf::Message for Pong { 1155 | const NAME: &'static str = "Pong"; 1156 | 1157 | fn is_initialized(&self) -> bool { 1158 | true 1159 | } 1160 | 1161 | fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { 1162 | while let Some(tag) = is.read_raw_tag_or_eof()? { 1163 | match tag { 1164 | tag => { 1165 | ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; 1166 | }, 1167 | }; 1168 | } 1169 | ::std::result::Result::Ok(()) 1170 | } 1171 | 1172 | // Compute sizes of nested messages 1173 | #[allow(unused_variables)] 1174 | fn compute_size(&self) -> u64 { 1175 | let mut my_size = 0; 1176 | my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); 1177 | self.special_fields.cached_size().set(my_size as u32); 1178 | my_size 1179 | } 1180 | 1181 | fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { 1182 | os.write_unknown_fields(self.special_fields.unknown_fields())?; 1183 | ::std::result::Result::Ok(()) 1184 | } 1185 | 1186 | fn special_fields(&self) -> &::protobuf::SpecialFields { 1187 | &self.special_fields 1188 | } 1189 | 1190 | fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { 1191 | &mut self.special_fields 1192 | } 1193 | 1194 | fn new() -> Pong { 1195 | Pong::new() 1196 | } 1197 | 1198 | fn clear(&mut self) { 1199 | self.special_fields.clear(); 1200 | } 1201 | 1202 | fn default_instance() -> &'static Pong { 1203 | static instance: Pong = Pong { 1204 | special_fields: ::protobuf::SpecialFields::new(), 1205 | }; 1206 | &instance 1207 | } 1208 | } 1209 | 1210 | impl ::protobuf::MessageFull for Pong { 1211 | fn descriptor() -> ::protobuf::reflect::MessageDescriptor { 1212 | static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); 1213 | descriptor.get(|| file_descriptor().message_by_package_relative_name("Pong").unwrap()).clone() 1214 | } 1215 | } 1216 | 1217 | impl ::std::fmt::Display for Pong { 1218 | fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { 1219 | ::protobuf::text_format::fmt(self, f) 1220 | } 1221 | } 1222 | 1223 | impl ::protobuf::reflect::ProtobufValue for Pong { 1224 | type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; 1225 | } 1226 | 1227 | // @@protoc_insertion_point(message:Redirect) 1228 | #[derive(PartialEq,Clone,Default,Debug)] 1229 | pub struct Redirect { 1230 | // message fields 1231 | // @@protoc_insertion_point(field:Redirect.id) 1232 | pub id: ::std::string::String, 1233 | // @@protoc_insertion_point(field:Redirect.addr) 1234 | pub addr: ::std::string::String, 1235 | // special fields 1236 | // @@protoc_insertion_point(special_field:Redirect.special_fields) 1237 | pub special_fields: ::protobuf::SpecialFields, 1238 | } 1239 | 1240 | impl<'a> ::std::default::Default for &'a Redirect { 1241 | fn default() -> &'a Redirect { 1242 | ::default_instance() 1243 | } 1244 | } 1245 | 1246 | impl Redirect { 1247 | pub fn new() -> Redirect { 1248 | ::std::default::Default::default() 1249 | } 1250 | 1251 | fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { 1252 | let mut fields = ::std::vec::Vec::with_capacity(2); 1253 | let mut oneofs = ::std::vec::Vec::with_capacity(0); 1254 | fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( 1255 | "id", 1256 | |m: &Redirect| { &m.id }, 1257 | |m: &mut Redirect| { &mut m.id }, 1258 | )); 1259 | fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( 1260 | "addr", 1261 | |m: &Redirect| { &m.addr }, 1262 | |m: &mut Redirect| { &mut m.addr }, 1263 | )); 1264 | ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( 1265 | "Redirect", 1266 | fields, 1267 | oneofs, 1268 | ) 1269 | } 1270 | } 1271 | 1272 | impl ::protobuf::Message for Redirect { 1273 | const NAME: &'static str = "Redirect"; 1274 | 1275 | fn is_initialized(&self) -> bool { 1276 | true 1277 | } 1278 | 1279 | fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { 1280 | while let Some(tag) = is.read_raw_tag_or_eof()? { 1281 | match tag { 1282 | 10 => { 1283 | self.id = is.read_string()?; 1284 | }, 1285 | 18 => { 1286 | self.addr = is.read_string()?; 1287 | }, 1288 | tag => { 1289 | ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; 1290 | }, 1291 | }; 1292 | } 1293 | ::std::result::Result::Ok(()) 1294 | } 1295 | 1296 | // Compute sizes of nested messages 1297 | #[allow(unused_variables)] 1298 | fn compute_size(&self) -> u64 { 1299 | let mut my_size = 0; 1300 | if !self.id.is_empty() { 1301 | my_size += ::protobuf::rt::string_size(1, &self.id); 1302 | } 1303 | if !self.addr.is_empty() { 1304 | my_size += ::protobuf::rt::string_size(2, &self.addr); 1305 | } 1306 | my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); 1307 | self.special_fields.cached_size().set(my_size as u32); 1308 | my_size 1309 | } 1310 | 1311 | fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { 1312 | if !self.id.is_empty() { 1313 | os.write_string(1, &self.id)?; 1314 | } 1315 | if !self.addr.is_empty() { 1316 | os.write_string(2, &self.addr)?; 1317 | } 1318 | os.write_unknown_fields(self.special_fields.unknown_fields())?; 1319 | ::std::result::Result::Ok(()) 1320 | } 1321 | 1322 | fn special_fields(&self) -> &::protobuf::SpecialFields { 1323 | &self.special_fields 1324 | } 1325 | 1326 | fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { 1327 | &mut self.special_fields 1328 | } 1329 | 1330 | fn new() -> Redirect { 1331 | Redirect::new() 1332 | } 1333 | 1334 | fn clear(&mut self) { 1335 | self.id.clear(); 1336 | self.addr.clear(); 1337 | self.special_fields.clear(); 1338 | } 1339 | 1340 | fn default_instance() -> &'static Redirect { 1341 | static instance: Redirect = Redirect { 1342 | id: ::std::string::String::new(), 1343 | addr: ::std::string::String::new(), 1344 | special_fields: ::protobuf::SpecialFields::new(), 1345 | }; 1346 | &instance 1347 | } 1348 | } 1349 | 1350 | impl ::protobuf::MessageFull for Redirect { 1351 | fn descriptor() -> ::protobuf::reflect::MessageDescriptor { 1352 | static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); 1353 | descriptor.get(|| file_descriptor().message_by_package_relative_name("Redirect").unwrap()).clone() 1354 | } 1355 | } 1356 | 1357 | impl ::std::fmt::Display for Redirect { 1358 | fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { 1359 | ::protobuf::text_format::fmt(self, f) 1360 | } 1361 | } 1362 | 1363 | impl ::protobuf::reflect::ProtobufValue for Redirect { 1364 | type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; 1365 | } 1366 | 1367 | // @@protoc_insertion_point(message:Fsync) 1368 | #[derive(PartialEq,Clone,Default,Debug)] 1369 | pub struct Fsync { 1370 | // message fields 1371 | // @@protoc_insertion_point(field:Fsync.id) 1372 | pub id: ::std::string::String, 1373 | // @@protoc_insertion_point(field:Fsync.addr) 1374 | pub addr: ::std::string::String, 1375 | // special fields 1376 | // @@protoc_insertion_point(special_field:Fsync.special_fields) 1377 | pub special_fields: ::protobuf::SpecialFields, 1378 | } 1379 | 1380 | impl<'a> ::std::default::Default for &'a Fsync { 1381 | fn default() -> &'a Fsync { 1382 | ::default_instance() 1383 | } 1384 | } 1385 | 1386 | impl Fsync { 1387 | pub fn new() -> Fsync { 1388 | ::std::default::Default::default() 1389 | } 1390 | 1391 | fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { 1392 | let mut fields = ::std::vec::Vec::with_capacity(2); 1393 | let mut oneofs = ::std::vec::Vec::with_capacity(0); 1394 | fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( 1395 | "id", 1396 | |m: &Fsync| { &m.id }, 1397 | |m: &mut Fsync| { &mut m.id }, 1398 | )); 1399 | fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( 1400 | "addr", 1401 | |m: &Fsync| { &m.addr }, 1402 | |m: &mut Fsync| { &mut m.addr }, 1403 | )); 1404 | ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( 1405 | "Fsync", 1406 | fields, 1407 | oneofs, 1408 | ) 1409 | } 1410 | } 1411 | 1412 | impl ::protobuf::Message for Fsync { 1413 | const NAME: &'static str = "Fsync"; 1414 | 1415 | fn is_initialized(&self) -> bool { 1416 | true 1417 | } 1418 | 1419 | fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { 1420 | while let Some(tag) = is.read_raw_tag_or_eof()? { 1421 | match tag { 1422 | 10 => { 1423 | self.id = is.read_string()?; 1424 | }, 1425 | 18 => { 1426 | self.addr = is.read_string()?; 1427 | }, 1428 | tag => { 1429 | ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; 1430 | }, 1431 | }; 1432 | } 1433 | ::std::result::Result::Ok(()) 1434 | } 1435 | 1436 | // Compute sizes of nested messages 1437 | #[allow(unused_variables)] 1438 | fn compute_size(&self) -> u64 { 1439 | let mut my_size = 0; 1440 | if !self.id.is_empty() { 1441 | my_size += ::protobuf::rt::string_size(1, &self.id); 1442 | } 1443 | if !self.addr.is_empty() { 1444 | my_size += ::protobuf::rt::string_size(2, &self.addr); 1445 | } 1446 | my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); 1447 | self.special_fields.cached_size().set(my_size as u32); 1448 | my_size 1449 | } 1450 | 1451 | fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { 1452 | if !self.id.is_empty() { 1453 | os.write_string(1, &self.id)?; 1454 | } 1455 | if !self.addr.is_empty() { 1456 | os.write_string(2, &self.addr)?; 1457 | } 1458 | os.write_unknown_fields(self.special_fields.unknown_fields())?; 1459 | ::std::result::Result::Ok(()) 1460 | } 1461 | 1462 | fn special_fields(&self) -> &::protobuf::SpecialFields { 1463 | &self.special_fields 1464 | } 1465 | 1466 | fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { 1467 | &mut self.special_fields 1468 | } 1469 | 1470 | fn new() -> Fsync { 1471 | Fsync::new() 1472 | } 1473 | 1474 | fn clear(&mut self) { 1475 | self.id.clear(); 1476 | self.addr.clear(); 1477 | self.special_fields.clear(); 1478 | } 1479 | 1480 | fn default_instance() -> &'static Fsync { 1481 | static instance: Fsync = Fsync { 1482 | id: ::std::string::String::new(), 1483 | addr: ::std::string::String::new(), 1484 | special_fields: ::protobuf::SpecialFields::new(), 1485 | }; 1486 | &instance 1487 | } 1488 | } 1489 | 1490 | impl ::protobuf::MessageFull for Fsync { 1491 | fn descriptor() -> ::protobuf::reflect::MessageDescriptor { 1492 | static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); 1493 | descriptor.get(|| file_descriptor().message_by_package_relative_name("Fsync").unwrap()).clone() 1494 | } 1495 | } 1496 | 1497 | impl ::std::fmt::Display for Fsync { 1498 | fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { 1499 | ::protobuf::text_format::fmt(self, f) 1500 | } 1501 | } 1502 | 1503 | impl ::protobuf::reflect::ProtobufValue for Fsync { 1504 | type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; 1505 | } 1506 | 1507 | // @@protoc_insertion_point(message:Rsync) 1508 | #[derive(PartialEq,Clone,Default,Debug)] 1509 | pub struct Rsync { 1510 | // message fields 1511 | // @@protoc_insertion_point(field:Rsync.id) 1512 | pub id: ::std::string::String, 1513 | // special fields 1514 | // @@protoc_insertion_point(special_field:Rsync.special_fields) 1515 | pub special_fields: ::protobuf::SpecialFields, 1516 | } 1517 | 1518 | impl<'a> ::std::default::Default for &'a Rsync { 1519 | fn default() -> &'a Rsync { 1520 | ::default_instance() 1521 | } 1522 | } 1523 | 1524 | impl Rsync { 1525 | pub fn new() -> Rsync { 1526 | ::std::default::Default::default() 1527 | } 1528 | 1529 | fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { 1530 | let mut fields = ::std::vec::Vec::with_capacity(1); 1531 | let mut oneofs = ::std::vec::Vec::with_capacity(0); 1532 | fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( 1533 | "id", 1534 | |m: &Rsync| { &m.id }, 1535 | |m: &mut Rsync| { &mut m.id }, 1536 | )); 1537 | ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( 1538 | "Rsync", 1539 | fields, 1540 | oneofs, 1541 | ) 1542 | } 1543 | } 1544 | 1545 | impl ::protobuf::Message for Rsync { 1546 | const NAME: &'static str = "Rsync"; 1547 | 1548 | fn is_initialized(&self) -> bool { 1549 | true 1550 | } 1551 | 1552 | fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { 1553 | while let Some(tag) = is.read_raw_tag_or_eof()? { 1554 | match tag { 1555 | 10 => { 1556 | self.id = is.read_string()?; 1557 | }, 1558 | tag => { 1559 | ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; 1560 | }, 1561 | }; 1562 | } 1563 | ::std::result::Result::Ok(()) 1564 | } 1565 | 1566 | // Compute sizes of nested messages 1567 | #[allow(unused_variables)] 1568 | fn compute_size(&self) -> u64 { 1569 | let mut my_size = 0; 1570 | if !self.id.is_empty() { 1571 | my_size += ::protobuf::rt::string_size(1, &self.id); 1572 | } 1573 | my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); 1574 | self.special_fields.cached_size().set(my_size as u32); 1575 | my_size 1576 | } 1577 | 1578 | fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { 1579 | if !self.id.is_empty() { 1580 | os.write_string(1, &self.id)?; 1581 | } 1582 | os.write_unknown_fields(self.special_fields.unknown_fields())?; 1583 | ::std::result::Result::Ok(()) 1584 | } 1585 | 1586 | fn special_fields(&self) -> &::protobuf::SpecialFields { 1587 | &self.special_fields 1588 | } 1589 | 1590 | fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { 1591 | &mut self.special_fields 1592 | } 1593 | 1594 | fn new() -> Rsync { 1595 | Rsync::new() 1596 | } 1597 | 1598 | fn clear(&mut self) { 1599 | self.id.clear(); 1600 | self.special_fields.clear(); 1601 | } 1602 | 1603 | fn default_instance() -> &'static Rsync { 1604 | static instance: Rsync = Rsync { 1605 | id: ::std::string::String::new(), 1606 | special_fields: ::protobuf::SpecialFields::new(), 1607 | }; 1608 | &instance 1609 | } 1610 | } 1611 | 1612 | impl ::protobuf::MessageFull for Rsync { 1613 | fn descriptor() -> ::protobuf::reflect::MessageDescriptor { 1614 | static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); 1615 | descriptor.get(|| file_descriptor().message_by_package_relative_name("Rsync").unwrap()).clone() 1616 | } 1617 | } 1618 | 1619 | impl ::std::fmt::Display for Rsync { 1620 | fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { 1621 | ::protobuf::text_format::fmt(self, f) 1622 | } 1623 | } 1624 | 1625 | impl ::protobuf::reflect::ProtobufValue for Rsync { 1626 | type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; 1627 | } 1628 | 1629 | // @@protoc_insertion_point(message:Bye) 1630 | #[derive(PartialEq,Clone,Default,Debug)] 1631 | pub struct Bye { 1632 | // special fields 1633 | // @@protoc_insertion_point(special_field:Bye.special_fields) 1634 | pub special_fields: ::protobuf::SpecialFields, 1635 | } 1636 | 1637 | impl<'a> ::std::default::Default for &'a Bye { 1638 | fn default() -> &'a Bye { 1639 | ::default_instance() 1640 | } 1641 | } 1642 | 1643 | impl Bye { 1644 | pub fn new() -> Bye { 1645 | ::std::default::Default::default() 1646 | } 1647 | 1648 | fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { 1649 | let mut fields = ::std::vec::Vec::with_capacity(0); 1650 | let mut oneofs = ::std::vec::Vec::with_capacity(0); 1651 | ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( 1652 | "Bye", 1653 | fields, 1654 | oneofs, 1655 | ) 1656 | } 1657 | } 1658 | 1659 | impl ::protobuf::Message for Bye { 1660 | const NAME: &'static str = "Bye"; 1661 | 1662 | fn is_initialized(&self) -> bool { 1663 | true 1664 | } 1665 | 1666 | fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { 1667 | while let Some(tag) = is.read_raw_tag_or_eof()? { 1668 | match tag { 1669 | tag => { 1670 | ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; 1671 | }, 1672 | }; 1673 | } 1674 | ::std::result::Result::Ok(()) 1675 | } 1676 | 1677 | // Compute sizes of nested messages 1678 | #[allow(unused_variables)] 1679 | fn compute_size(&self) -> u64 { 1680 | let mut my_size = 0; 1681 | my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); 1682 | self.special_fields.cached_size().set(my_size as u32); 1683 | my_size 1684 | } 1685 | 1686 | fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { 1687 | os.write_unknown_fields(self.special_fields.unknown_fields())?; 1688 | ::std::result::Result::Ok(()) 1689 | } 1690 | 1691 | fn special_fields(&self) -> &::protobuf::SpecialFields { 1692 | &self.special_fields 1693 | } 1694 | 1695 | fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { 1696 | &mut self.special_fields 1697 | } 1698 | 1699 | fn new() -> Bye { 1700 | Bye::new() 1701 | } 1702 | 1703 | fn clear(&mut self) { 1704 | self.special_fields.clear(); 1705 | } 1706 | 1707 | fn default_instance() -> &'static Bye { 1708 | static instance: Bye = Bye { 1709 | special_fields: ::protobuf::SpecialFields::new(), 1710 | }; 1711 | &instance 1712 | } 1713 | } 1714 | 1715 | impl ::protobuf::MessageFull for Bye { 1716 | fn descriptor() -> ::protobuf::reflect::MessageDescriptor { 1717 | static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); 1718 | descriptor.get(|| file_descriptor().message_by_package_relative_name("Bye").unwrap()).clone() 1719 | } 1720 | } 1721 | 1722 | impl ::std::fmt::Display for Bye { 1723 | fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { 1724 | ::protobuf::text_format::fmt(self, f) 1725 | } 1726 | } 1727 | 1728 | impl ::protobuf::reflect::ProtobufValue for Bye { 1729 | type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; 1730 | } 1731 | 1732 | static file_descriptor_proto_data: &'static [u8] = b"\ 1733 | \n\nrndz.proto\"\xb7\x01\n\x07Request\x12\x0e\n\x02id\x18\x01\x20\x01(\t\ 1734 | R\x02id\x12\x1b\n\x04Ping\x18\x02\x20\x01(\x0b2\x05.PingH\0R\x04Ping\x12\ 1735 | \x1e\n\x05Isync\x18\x03\x20\x01(\x0b2\x06.IsyncH\0R\x05Isync\x12\x1e\n\ 1736 | \x05Fsync\x18\x04\x20\x01(\x0b2\x06.FsyncH\0R\x05Fsync\x12\x1e\n\x05Rsyn\ 1737 | c\x18\x05\x20\x01(\x0b2\x06.RsyncH\0R\x05Rsync\x12\x18\n\x03Bye\x18\x06\ 1738 | \x20\x01(\x0b2\x04.ByeH\0R\x03ByeB\x05\n\x03cmd\"\x06\n\x04Ping\"\x17\n\ 1739 | \x05Isync\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\"\x87\x01\n\x08Respo\ 1740 | nse\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x1b\n\x04Pong\x18\x02\ 1741 | \x20\x01(\x0b2\x05.PongH\0R\x04Pong\x12'\n\x08Redirect\x18\x03\x20\x01(\ 1742 | \x0b2\t.RedirectH\0R\x08Redirect\x12\x1e\n\x05Fsync\x18\x04\x20\x01(\x0b\ 1743 | 2\x06.FsyncH\0R\x05FsyncB\x05\n\x03cmd\"\x06\n\x04Pong\".\n\x08Redirect\ 1744 | \x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04addr\x18\x02\x20\ 1745 | \x01(\tR\x04addr\"+\n\x05Fsync\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\ 1746 | \x12\x12\n\x04addr\x18\x02\x20\x01(\tR\x04addr\"\x17\n\x05Rsync\x12\x0e\ 1747 | \n\x02id\x18\x01\x20\x01(\tR\x02id\"\x05\n\x03Byeb\x06proto3\ 1748 | "; 1749 | 1750 | /// `FileDescriptorProto` object which was a source for this generated file 1751 | fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto { 1752 | static file_descriptor_proto_lazy: ::protobuf::rt::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::Lazy::new(); 1753 | file_descriptor_proto_lazy.get(|| { 1754 | ::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap() 1755 | }) 1756 | } 1757 | 1758 | /// `FileDescriptor` object which allows dynamic access to files 1759 | pub fn file_descriptor() -> &'static ::protobuf::reflect::FileDescriptor { 1760 | static generated_file_descriptor_lazy: ::protobuf::rt::Lazy<::protobuf::reflect::GeneratedFileDescriptor> = ::protobuf::rt::Lazy::new(); 1761 | static file_descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::FileDescriptor> = ::protobuf::rt::Lazy::new(); 1762 | file_descriptor.get(|| { 1763 | let generated_file_descriptor = generated_file_descriptor_lazy.get(|| { 1764 | let mut deps = ::std::vec::Vec::with_capacity(0); 1765 | let mut messages = ::std::vec::Vec::with_capacity(9); 1766 | messages.push(Request::generated_message_descriptor_data()); 1767 | messages.push(Ping::generated_message_descriptor_data()); 1768 | messages.push(Isync::generated_message_descriptor_data()); 1769 | messages.push(Response::generated_message_descriptor_data()); 1770 | messages.push(Pong::generated_message_descriptor_data()); 1771 | messages.push(Redirect::generated_message_descriptor_data()); 1772 | messages.push(Fsync::generated_message_descriptor_data()); 1773 | messages.push(Rsync::generated_message_descriptor_data()); 1774 | messages.push(Bye::generated_message_descriptor_data()); 1775 | let mut enums = ::std::vec::Vec::with_capacity(0); 1776 | ::protobuf::reflect::GeneratedFileDescriptor::new_generated( 1777 | file_descriptor_proto(), 1778 | deps, 1779 | messages, 1780 | enums, 1781 | ) 1782 | }); 1783 | ::protobuf::reflect::FileDescriptor::new_generated_2(generated_file_descriptor) 1784 | }) 1785 | } 1786 | -------------------------------------------------------------------------------- /src/tcp/client.rs: -------------------------------------------------------------------------------- 1 | use crate::proto::rndz::{ 2 | request::Cmd as ReqCmd, response::Cmd as RespCmd, Isync, Ping, Request, Response, Rsync, 3 | }; 4 | use protobuf::Message; 5 | use socket2::{Domain, Protocol, Socket, Type}; 6 | use std::io::{Error, ErrorKind::Other, Read, Result, Write}; 7 | use std::net::{Shutdown::Both, SocketAddr, TcpListener, TcpStream, ToSocketAddrs}; 8 | use std::sync::mpsc::{sync_channel, Receiver, RecvTimeoutError::Timeout, SyncSender}; 9 | use std::sync::{Arc, Condvar, Mutex}; 10 | use std::thread::spawn; 11 | use std::time::Duration; 12 | 13 | #[derive(Clone, Default)] 14 | struct Signal { 15 | exit: bool, 16 | broken: bool, 17 | } 18 | 19 | /// Tcp connection builder 20 | /// 21 | /// Bind to a port, connect to a rendezvous server. Wait for peer connection request or initiate a 22 | /// peer connection request. 23 | /// 24 | /// # example 25 | /// 26 | /// ```no_run 27 | /// use rndz::tcp::Client; 28 | /// 29 | /// let mut c1 = Client::new("rndz_server:1234", "c1", None).unwrap(); 30 | /// c1.listen().unwrap(); 31 | /// while let Ok((stream, addr)) = c1.accept(){ 32 | /// //... 33 | /// } 34 | /// ``` 35 | /// 36 | /// client2 37 | /// ```no_run 38 | /// use rndz::tcp::Client; 39 | /// let mut c2 = Client::new("rndz_server:1234", "c2", None).unwrap(); 40 | /// let stream = c2.connect("c1").unwrap(); 41 | /// ``` 42 | /// 43 | pub struct Client { 44 | server_addr: String, 45 | id: String, 46 | listener: Option, 47 | local_addr: Option, 48 | signal: Arc<(Mutex, Condvar)>, 49 | } 50 | 51 | impl Drop for Client { 52 | fn drop(&mut self) { 53 | self.shutdown().unwrap(); 54 | } 55 | } 56 | 57 | impl Client { 58 | /// set rendezvous server, peer identity, local bind address. 59 | /// if no local address set, choose according server address type(ipv4 or ipv6). 60 | pub fn new(server_addr: &str, id: &str, local_addr: Option) -> Result { 61 | Ok(Self { 62 | server_addr: server_addr.to_owned(), 63 | id: id.into(), 64 | local_addr, 65 | listener: None, 66 | signal: Default::default(), 67 | }) 68 | } 69 | 70 | /// expose TcpListener 71 | pub fn as_socket(&self) -> Option { 72 | self.listener 73 | .as_ref() 74 | .map(|l| l.try_clone().unwrap().into()) 75 | } 76 | 77 | fn choose_bind_addr(&self) -> Result { 78 | if let Some(ref addr) = self.local_addr { 79 | return Ok(*addr); 80 | } 81 | 82 | let server_addr = self 83 | .server_addr 84 | .to_socket_addrs()? 85 | .next() 86 | .ok_or_else(|| Error::new(Other, "server name resolve fail"))?; 87 | 88 | let local_addr = match server_addr { 89 | SocketAddr::V4(_) => "0.0.0.0:0".parse().unwrap(), 90 | SocketAddr::V6(_) => "[::]:0".parse().unwrap(), 91 | }; 92 | 93 | Ok(local_addr) 94 | } 95 | 96 | fn connect_server(local_addr: SocketAddr, server_addr: &str) -> Result { 97 | let svr = Self::bind(local_addr)?; 98 | let server_addr = server_addr 99 | .to_socket_addrs()? 100 | .next() 101 | .ok_or_else(|| Error::new(Other, "server name resolve fail"))?; 102 | svr.connect(&server_addr.into())?; 103 | Ok(svr) 104 | } 105 | 106 | fn bind(local_addr: SocketAddr) -> Result { 107 | let domain = Domain::for_address(local_addr); 108 | 109 | let s = Socket::new(domain, Type::STREAM, Some(Protocol::TCP)).unwrap(); 110 | s.set_reuse_address(true)?; 111 | #[cfg(unix)] 112 | s.set_reuse_port(true)?; 113 | s.bind(&local_addr.into())?; 114 | 115 | Ok(s) 116 | } 117 | 118 | /// connect to rendezvous server and request a connection to target node. 119 | /// 120 | /// it will return a TcpStream with remote peer. 121 | /// 122 | /// the connection with rendezvous server will be drop after return. 123 | /// 124 | pub fn connect(&mut self, target_id: &str) -> Result { 125 | let mut svr = Self::connect_server(self.choose_bind_addr()?, &self.server_addr)?; 126 | 127 | let mut isync = Isync::new(); 128 | isync.id = target_id.into(); 129 | 130 | Self::write_req(self.id.clone(), &mut svr, ReqCmd::Isync(isync))?; 131 | 132 | let addr = match Self::read_resp(&mut svr)?.cmd { 133 | Some(RespCmd::Redirect(rdr)) => rdr.addr, 134 | _ => Err(Error::new(Other, "invalid server response"))?, 135 | }; 136 | 137 | log::debug!("Redirect {}", addr); 138 | 139 | let target_addr: SocketAddr = addr 140 | .parse() 141 | .map_err(|_| Error::new(Other, "target id not found"))?; 142 | 143 | let local_addr = svr.local_addr().unwrap(); 144 | 145 | let s = Self::bind(local_addr.as_socket().unwrap())?; 146 | s.connect(&target_addr.into())?; 147 | 148 | Ok(s.into()) 149 | } 150 | 151 | fn new_req(id: String) -> Request { 152 | let mut req = Request::new(); 153 | req.id = id; 154 | 155 | req 156 | } 157 | 158 | fn write_req(id: String, w: &mut dyn Write, cmd: ReqCmd) -> Result<()> { 159 | let mut req = Self::new_req(id); 160 | req.cmd = Some(cmd); 161 | let buf = req.write_to_bytes()?; 162 | 163 | w.write_all(&(buf.len() as u16).to_be_bytes())?; 164 | w.write_all(&buf)?; 165 | Ok(()) 166 | } 167 | 168 | fn read_resp(r: &mut dyn Read) -> Result { 169 | let mut buf = [0; 2]; 170 | r.read_exact(&mut buf)?; 171 | let mut buf = vec![0; u16::from_be_bytes(buf).into()]; 172 | r.read_exact(&mut buf)?; 173 | Response::parse_from_bytes(&buf).map_err(|_| Error::new(Other, "invalid message")) 174 | } 175 | 176 | fn write_loop(id: String, s: &mut dyn Write, rx: Receiver) -> Result<()> { 177 | loop { 178 | let req = match rx.recv_timeout(Duration::from_secs(10)) { 179 | Ok(req) => req, 180 | Err(Timeout) => ReqCmd::Ping(Ping::new()), 181 | _ => break, 182 | }; 183 | 184 | if Self::write_req(id.clone(), s, req).is_err() { 185 | break; 186 | } 187 | } 188 | 189 | Ok(()) 190 | } 191 | 192 | fn read_loop(local_addr: SocketAddr, r: &mut dyn Read, tx: SyncSender) -> Result<()> { 193 | while let Ok(resp) = Self::read_resp(r) { 194 | let req = match resp.cmd { 195 | Some(RespCmd::Pong(_)) => None, 196 | Some(RespCmd::Fsync(fsync)) => { 197 | log::debug!("fsync {}", fsync.id); 198 | 199 | let dst_addr: SocketAddr = fsync 200 | .addr 201 | .parse() 202 | .map_err(|_| Error::new(Other, "invalid fsync addr"))?; 203 | 204 | log::debug!("connect {} -> {}", local_addr, dst_addr); 205 | 206 | let _ = Self::bind(local_addr) 207 | .map(|s| s.connect_timeout(&dst_addr.into(), Duration::from_micros(1))); 208 | 209 | let mut rsync = Rsync::new(); 210 | rsync.id = fsync.id; 211 | Some(ReqCmd::Rsync(rsync)) 212 | } 213 | _ => None, 214 | }; 215 | 216 | if let Some(req) = req { 217 | tx.send(req).unwrap(); 218 | }; 219 | } 220 | 221 | Ok(()) 222 | } 223 | 224 | fn start_background( 225 | id: String, 226 | local_addr: SocketAddr, 227 | server_addr: String, 228 | signal: Arc<(Mutex, Condvar)>, 229 | ) -> Result<()> { 230 | let svr_sk = Self::connect_server(local_addr, &server_addr)?; 231 | 232 | let (tx, rx) = sync_channel(10); 233 | 234 | tx.send(ReqCmd::Ping(Ping::new())).unwrap(); 235 | 236 | let mut hs = vec![]; 237 | 238 | hs.push({ 239 | let mut w = svr_sk.try_clone()?; 240 | spawn(move || Self::write_loop(id, &mut w, rx).unwrap()) 241 | }); 242 | 243 | hs.push({ 244 | let mut r = svr_sk.try_clone()?; 245 | spawn(move || Self::read_loop(local_addr, &mut r, tx).unwrap()) 246 | }); 247 | 248 | { 249 | let signal = signal.clone(); 250 | spawn(move || { 251 | for h in hs { 252 | h.join().unwrap(); 253 | } 254 | let (lock, cvar) = &*signal; 255 | let mut signal = lock.lock().unwrap(); 256 | signal.broken = true; 257 | cvar.notify_all(); 258 | }); 259 | } 260 | 261 | { 262 | spawn(move || { 263 | let (lock, cvar) = &*signal; 264 | let mut signal = lock.lock().unwrap(); 265 | if signal.exit { 266 | let _ = svr_sk.shutdown(Both); 267 | return; 268 | } 269 | signal = cvar.wait(signal).unwrap(); 270 | if signal.exit { 271 | let _ = svr_sk.shutdown(Both); 272 | } 273 | }); 274 | } 275 | 276 | Ok(()) 277 | } 278 | 279 | /// put socket in listen mode, create connection with rendezvous server, wait for peer 280 | /// connection request. if connection with server broken it will auto reconnect. 281 | /// 282 | /// when received `Fsync` request from server, attempt to connect remote peer with a very short timeout, 283 | /// this will open the firwall and nat rule for the peer connection that will follow immediately. 284 | /// When the peer connection finally come, the listening socket then accept it as normal. 285 | pub fn listen(&mut self) -> Result<()> { 286 | let listener = Self::bind(self.choose_bind_addr()?)?; 287 | listener.listen(10)?; 288 | 289 | let id = self.id.clone(); 290 | let local_addr = listener.local_addr().unwrap().as_socket().unwrap(); 291 | let server_addr = self.server_addr.clone(); 292 | let signal = self.signal.clone(); 293 | Self::start_background(id.clone(), local_addr, server_addr.clone(), signal.clone())?; 294 | 295 | spawn(move || loop { 296 | { 297 | let (lock, cvar) = &*signal; 298 | let mut signal = lock.lock().unwrap(); 299 | if signal.exit { 300 | return; 301 | } 302 | signal = cvar.wait(signal).unwrap(); 303 | if signal.exit { 304 | return; 305 | } 306 | 307 | assert!(signal.broken); 308 | 309 | signal.broken = false; 310 | } 311 | 312 | log::debug!("connection with server is broken, try to reconnect."); 313 | 314 | loop { 315 | match Self::start_background( 316 | id.clone(), 317 | local_addr, 318 | server_addr.clone(), 319 | signal.clone(), 320 | ) { 321 | Ok(_) => { 322 | log::debug!("connect server success"); 323 | break; 324 | } 325 | Err(err) => log::debug!("connect server fail, retry later. {}", err), 326 | }; 327 | 328 | let (lock, cvar) = &*signal; 329 | let mut signal = lock.lock().unwrap(); 330 | if signal.exit { 331 | return; 332 | } 333 | signal = cvar 334 | .wait_timeout(signal, Duration::from_secs(120)) 335 | .unwrap() 336 | .0; 337 | if signal.exit { 338 | return; 339 | } 340 | } 341 | }); 342 | 343 | self.listener = Some(listener); 344 | 345 | Ok(()) 346 | } 347 | 348 | /// accept remote peer connection 349 | pub fn accept(&mut self) -> Result<(TcpStream, SocketAddr)> { 350 | self.listener 351 | .as_ref() 352 | .ok_or_else(|| Error::new(Other, "not listening"))? 353 | .accept() 354 | .map(|(s, a)| (s.into(), a.as_socket().unwrap())) 355 | } 356 | 357 | /// stop internal listen thread. 358 | pub fn shutdown(&mut self) -> Result<()> { 359 | let _ = self.listener.take().map(|l| l.shutdown(Both)); 360 | 361 | let (lock, cvar) = &*self.signal; 362 | let mut signal = lock.lock().unwrap(); 363 | signal.exit = true; 364 | cvar.notify_all(); 365 | 366 | Ok(()) 367 | } 368 | } 369 | -------------------------------------------------------------------------------- /src/tcp/client_async.rs: -------------------------------------------------------------------------------- 1 | use crate::proto::rndz::{ 2 | request::Cmd as ReqCmd, response::Cmd as RespCmd, Isync, Ping, Request, Response, Rsync, 3 | }; 4 | use protobuf::Message; 5 | use std::io::{Error, ErrorKind::Other, Result}; 6 | use std::net::SocketAddr; 7 | use std::sync::Arc; 8 | use std::time::Duration; 9 | use tokio::{ 10 | io::{AsyncReadExt, AsyncWriteExt}, 11 | join, 12 | net::{ 13 | lookup_host, 14 | tcp::{OwnedReadHalf, OwnedWriteHalf}, 15 | TcpListener, TcpSocket, TcpStream, 16 | }, 17 | select, 18 | sync::mpsc::{channel, Receiver, Sender}, 19 | sync::Notify, 20 | task::spawn, 21 | time::{sleep, timeout}, 22 | }; 23 | 24 | /// Async TCP connection builder. 25 | /// 26 | /// Async version of [`crate::tcp::Client`], 27 | /// requires Tokio async runtime. 28 | /// 29 | pub struct Client { 30 | server_addr: String, 31 | id: String, 32 | listener: Option, 33 | local_addr: Option, 34 | exit: Arc, 35 | } 36 | 37 | impl Drop for Client { 38 | fn drop(&mut self) { 39 | self.exit.notify_waiters(); 40 | } 41 | } 42 | 43 | impl Client { 44 | /// Sets rendezvous server, peer identity, and local bind address. 45 | /// If no local address is set, chooses according to server address type (IPv4 or IPv6). 46 | pub fn new(server_addr: &str, id: &str, local_addr: Option) -> Result { 47 | Ok(Self { 48 | server_addr: server_addr.to_owned(), 49 | id: id.into(), 50 | local_addr, 51 | listener: None, 52 | exit: Default::default(), 53 | }) 54 | } 55 | 56 | /// Exposes TcpListener. 57 | pub fn as_socket(&self) -> Option<&TcpListener> { 58 | self.listener.as_ref() 59 | } 60 | 61 | async fn choose_bind_addr(&self) -> Result { 62 | if let Some(ref addr) = self.local_addr { 63 | return Ok(*addr); 64 | } 65 | 66 | let server_addr = lookup_host(self.server_addr.clone()) 67 | .await? 68 | .next() 69 | .ok_or_else(|| Error::new(Other, "server name resolve fail"))?; 70 | 71 | let local_addr = match server_addr { 72 | SocketAddr::V4(_) => "0.0.0.0:0".parse().unwrap(), 73 | SocketAddr::V6(_) => "[::]:0".parse().unwrap(), 74 | }; 75 | 76 | Ok(local_addr) 77 | } 78 | 79 | async fn connect_server(local_addr: SocketAddr, server_addr: &str) -> Result { 80 | let svr = Self::bind(local_addr)?; 81 | let server_addr = lookup_host(server_addr) 82 | .await? 83 | .next() 84 | .ok_or_else(|| Error::new(Other, "server name resolve fail"))?; 85 | svr.connect(server_addr).await 86 | } 87 | 88 | fn bind(local_addr: SocketAddr) -> Result { 89 | let s = match local_addr { 90 | SocketAddr::V4(_) => TcpSocket::new_v4(), 91 | SocketAddr::V6(_) => TcpSocket::new_v6(), 92 | }?; 93 | 94 | s.set_reuseaddr(true)?; 95 | #[cfg(unix)] 96 | s.set_reuseport(true)?; 97 | s.bind(local_addr)?; 98 | 99 | Ok(s) 100 | } 101 | 102 | /// Connect to rendezvous server and request a connection to the target node. 103 | /// 104 | /// Returns a TcpStream with the remote peer. 105 | /// 106 | /// The connection with the rendezvous server will be dropped after return. 107 | pub async fn connect(&mut self, target_id: &str) -> Result { 108 | let svr = Self::connect_server(self.choose_bind_addr().await?, &self.server_addr).await?; 109 | let local_addr = svr.local_addr().unwrap(); 110 | let (mut r, mut w) = svr.into_split(); 111 | 112 | let mut isync = Isync::new(); 113 | isync.id = target_id.into(); 114 | 115 | Self::write_req(self.id.clone(), &mut w, ReqCmd::Isync(isync)).await?; 116 | 117 | let addr = match Self::read_resp(&mut r).await?.cmd { 118 | Some(RespCmd::Redirect(rdr)) => rdr.addr, 119 | _ => Err(Error::new(Other, "invalid server response"))?, 120 | }; 121 | 122 | log::debug!("Redirect {}", addr); 123 | 124 | let target_addr: SocketAddr = addr 125 | .parse() 126 | .map_err(|_| Error::new(Other, "target ID not found"))?; 127 | 128 | let s = Self::bind(local_addr)?; 129 | s.connect(target_addr).await 130 | } 131 | 132 | fn new_req(id: String) -> Request { 133 | let mut req = Request::new(); 134 | req.id = id; 135 | req 136 | } 137 | 138 | async fn write_req(id: String, w: &mut OwnedWriteHalf, cmd: ReqCmd) -> Result<()> { 139 | let mut req = Self::new_req(id); 140 | req.cmd = Some(cmd); 141 | let buf = req.write_to_bytes()?; 142 | 143 | w.write_all(&(buf.len() as u16).to_be_bytes()).await?; 144 | w.write_all(&buf).await?; 145 | Ok(()) 146 | } 147 | 148 | async fn read_resp(r: &mut OwnedReadHalf) -> Result { 149 | let mut buf = [0; 2]; 150 | r.read_exact(&mut buf).await?; 151 | let mut buf = vec![0; u16::from_be_bytes(buf).into()]; 152 | r.read_exact(&mut buf).await?; 153 | Response::parse_from_bytes(&buf).map_err(|_| Error::new(Other, "invalid message")) 154 | } 155 | 156 | async fn handle_resp(local_addr: SocketAddr, r: &mut OwnedReadHalf) -> Result> { 157 | let resp = Self::read_resp(r).await; 158 | match resp { 159 | Ok(resp) => match resp.cmd { 160 | Some(RespCmd::Pong(_)) => Ok(None), 161 | Some(RespCmd::Fsync(fsync)) => { 162 | log::debug!("fsync {}", fsync.id); 163 | 164 | let dst_addr: SocketAddr = fsync 165 | .addr 166 | .parse() 167 | .map_err(|_| Error::new(Other, "invalid fsync address"))?; 168 | 169 | if let Ok(s) = Self::bind(local_addr) { 170 | log::debug!("connect {} -> {}", local_addr, dst_addr); 171 | let _ = timeout(Duration::from_micros(1), s.connect(dst_addr)).await; 172 | } 173 | 174 | let mut rsync = Rsync::new(); 175 | rsync.id = fsync.id; 176 | Ok(Some(ReqCmd::Rsync(rsync))) 177 | } 178 | _ => Ok(None), 179 | }, 180 | Err(e) => Err(e), 181 | } 182 | } 183 | 184 | async fn read_loop( 185 | exit: Arc, 186 | local_addr: SocketAddr, 187 | mut r: OwnedReadHalf, 188 | tx: Sender, 189 | ) { 190 | loop { 191 | let resp = select! { 192 | _ = exit.notified() => break, 193 | req = Self::handle_resp(local_addr, &mut r) => req, 194 | }; 195 | 196 | let ok = match resp { 197 | Ok(None) => true, 198 | Ok(Some(req)) => tx.send(req).await.is_ok(), 199 | Err(_) => false, 200 | }; 201 | 202 | if !ok { 203 | break; 204 | } 205 | } 206 | } 207 | 208 | async fn write_loop( 209 | exit: Arc, 210 | id: String, 211 | mut w: OwnedWriteHalf, 212 | mut rx: Receiver, 213 | ) { 214 | loop { 215 | let req = select! { 216 | _ = exit.notified() => break, 217 | _ = sleep(Duration::from_secs(10)) => Some(ReqCmd::Ping(Ping::new())), 218 | req = rx.recv() => req, 219 | }; 220 | 221 | if req.is_none() 222 | || Self::write_req(id.clone(), &mut w, req.unwrap()) 223 | .await 224 | .is_err() 225 | { 226 | break; 227 | } 228 | } 229 | } 230 | 231 | async fn start_background( 232 | id: String, 233 | local_addr: SocketAddr, 234 | server_addr: String, 235 | exit: Arc, 236 | ) -> Result> { 237 | let svr_sk = Self::connect_server(local_addr, &server_addr).await?; 238 | let (r, w) = svr_sk.into_split(); 239 | let (tx, rx) = channel(10); 240 | 241 | let broken: Arc = Default::default(); 242 | tx.send(ReqCmd::Ping(Ping::new())).await.unwrap(); 243 | 244 | let rl = { 245 | let exit = exit.clone(); 246 | spawn(async move { 247 | Self::read_loop(exit, local_addr, r, tx).await; 248 | }) 249 | }; 250 | 251 | let wl = { 252 | let exit = exit.clone(); 253 | let id = id.clone(); 254 | spawn(async move { 255 | Self::write_loop(exit, id, w, rx).await; 256 | }) 257 | }; 258 | 259 | { 260 | let broken = broken.clone(); 261 | spawn(async move { 262 | let _ = join!(rl, wl); 263 | broken.notify_waiters(); 264 | }); 265 | } 266 | 267 | Ok(broken) 268 | } 269 | 270 | /// Puts socket in listen mode, creates a connection with the rendezvous server, and waits for peer 271 | /// connection request. If the connection with the server is broken, it will auto-reconnect. 272 | /// 273 | /// When an `Fsync` request is received from the server, attempts to connect to the remote peer with a very short timeout, 274 | /// this will open the firewall and NAT rule for the peer connection that will follow immediately. 275 | /// When the peer connection finally comes, the listening socket then accepts it as normal. 276 | pub async fn listen(&mut self) -> Result<()> { 277 | let listener = Self::bind(self.choose_bind_addr().await?)?; 278 | let local_addr = listener.local_addr().unwrap(); 279 | let listener = listener.listen(10)?; 280 | 281 | let id = self.id.clone(); 282 | let server_addr = self.server_addr.clone(); 283 | let exit = self.exit.clone(); 284 | let mut broken = 285 | Self::start_background(id.clone(), local_addr, server_addr.clone(), exit.clone()) 286 | .await?; 287 | 288 | spawn(async move { 289 | loop { 290 | select! { 291 | _ = exit.notified() => break, 292 | _ = broken.notified() => {}, 293 | }; 294 | 295 | log::debug!("Connection with server is broken, trying to reconnect"); 296 | 297 | broken = loop { 298 | match Self::start_background( 299 | id.clone(), 300 | local_addr, 301 | server_addr.clone(), 302 | exit.clone(), 303 | ) 304 | .await 305 | { 306 | Ok(broken) => { 307 | log::debug!("Connected to server successfully"); 308 | break broken; 309 | } 310 | Err(err) => { 311 | log::debug!("Failed to connect to server, retrying later. {}", err) 312 | } 313 | }; 314 | 315 | select! { 316 | _ = exit.notified() => return, 317 | _ = sleep(Duration::from_secs(120)) => {}, 318 | }; 319 | }; 320 | } 321 | }); 322 | 323 | self.listener = Some(listener); 324 | 325 | Ok(()) 326 | } 327 | 328 | /// Accepts remote peer connection. 329 | pub async fn accept(&mut self) -> Result<(TcpStream, SocketAddr)> { 330 | select! { 331 | _ = self.exit.notified() => Err(Error::new(Other, "exit")), 332 | r = self.listener 333 | .as_ref() 334 | .ok_or_else(|| Error::new(Other, "not listening"))? 335 | .accept() => r, 336 | } 337 | } 338 | } 339 | -------------------------------------------------------------------------------- /src/tcp/mod.rs: -------------------------------------------------------------------------------- 1 | //! TCP connection. 2 | //! 3 | //! Use `Client` or `AsyncClient` to bind, listen, accept, connect socket. 4 | //! 5 | //! Use `Server` to create a rendezvous server. 6 | 7 | #[cfg(feature = "server")] 8 | mod server; 9 | #[cfg(feature = "server")] 10 | pub use server::Server; 11 | 12 | #[cfg(feature = "client")] 13 | mod client; 14 | #[cfg(feature = "client")] 15 | pub use client::Client; 16 | 17 | #[cfg(feature = "async")] 18 | mod client_async; 19 | #[cfg(feature = "async")] 20 | pub use client_async::Client as AsyncClient; 21 | 22 | #[cfg(test)] 23 | mod tests { 24 | use socket2::{Domain, Protocol, Socket, Type}; 25 | use std::net::SocketAddr; 26 | #[test] 27 | fn test_client() { 28 | let local_addr: SocketAddr = "0.0.0.0:0".parse().unwrap(); 29 | let socket = Socket::new(Domain::IPV4, Type::STREAM, Some(Protocol::TCP)).unwrap(); 30 | socket.set_reuse_address(true).unwrap(); 31 | socket.bind(&local_addr.into()).unwrap(); 32 | let remote_addr: SocketAddr = "1.1.1.1:80".parse().unwrap(); 33 | socket.connect(&remote_addr.into()).unwrap(); 34 | let con_local_addr: SocketAddr = socket.local_addr().unwrap().as_socket().unwrap(); 35 | 36 | let mut local_addr2: SocketAddr = "0.0.0.0:0".parse().unwrap(); 37 | local_addr2.set_port(con_local_addr.port()); 38 | let socket2 = Socket::new(Domain::IPV4, Type::STREAM, Some(Protocol::TCP)).unwrap(); 39 | socket2.set_reuse_address(true).unwrap(); 40 | socket2.bind(&local_addr2.into()).unwrap(); 41 | let remote_addr2: SocketAddr = "1.1.1.1:443".parse().unwrap(); 42 | socket2.connect(&remote_addr2.into()).unwrap(); 43 | } 44 | 45 | #[test] 46 | fn test_server() { 47 | let local_addr: SocketAddr = "0.0.0.0:0".parse().unwrap(); 48 | 49 | let socket = Socket::new(Domain::IPV4, Type::STREAM, Some(Protocol::TCP)).unwrap(); 50 | socket.set_reuse_address(true).unwrap(); 51 | #[cfg(unix)] 52 | socket.set_reuse_port(true).unwrap(); 53 | socket.bind(&local_addr.into()).unwrap(); 54 | socket.listen(1).unwrap(); 55 | 56 | let socket2 = Socket::new(Domain::IPV4, Type::STREAM, Some(Protocol::TCP)).unwrap(); 57 | socket2.set_reuse_address(true).unwrap(); 58 | #[cfg(unix)] 59 | socket2.set_reuse_port(true).unwrap(); 60 | socket2.bind(&socket.local_addr().unwrap()).unwrap(); 61 | let remote_addr2: SocketAddr = "1.1.1.1:80".parse().unwrap(); 62 | socket2.connect(&remote_addr2.into()).unwrap(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/tcp/server.rs: -------------------------------------------------------------------------------- 1 | use crate::proto::rndz::{ 2 | request::Cmd as ReqCmd, response::Cmd as RespCmd, Bye, Fsync, Isync, Ping, Pong, Redirect, 3 | Request, Response, Rsync, 4 | }; 5 | use log; 6 | use protobuf::Message; 7 | use std::collections::HashMap; 8 | use std::io::{Error, ErrorKind::Other, Result}; 9 | use std::net::SocketAddr; 10 | use std::sync::{Arc, Mutex}; 11 | use std::time::{Duration, Instant}; 12 | use tokio::sync::mpsc::{channel, Receiver, Sender}; 13 | use tokio::{ 14 | io::{AsyncReadExt, AsyncWriteExt}, 15 | net::{ 16 | tcp::{ReadHalf, WriteHalf}, 17 | TcpListener, ToSocketAddrs, 18 | }, 19 | select, task, 20 | time::timeout, 21 | }; 22 | 23 | /// Tcp rendezvous server 24 | /// 25 | /// keep traces of all peers, and forward connection request. 26 | pub struct Server { 27 | listener: TcpListener, 28 | peers: PeerMap, 29 | count: u64, 30 | } 31 | 32 | impl Server { 33 | pub async fn new(listen_addr: A) -> Result { 34 | let listener = TcpListener::bind(listen_addr).await?; 35 | 36 | Ok(Self { 37 | listener, 38 | peers: Default::default(), 39 | count: 0, 40 | }) 41 | } 42 | 43 | fn next_id(&mut self) -> u64 { 44 | self.count += 1; 45 | self.count 46 | } 47 | 48 | pub async fn run(mut self) -> Result<()> { 49 | while let Ok((mut stream, _addr)) = self.listener.accept().await { 50 | let id = self.next_id(); 51 | let peers = self.peers.clone(); 52 | 53 | task::spawn(async move { 54 | let (tx, rx) = channel(10); 55 | let (r, w) = stream.split(); 56 | let h = PeerHandler { 57 | stream: w, 58 | peers, 59 | peer_id: "".to_string(), 60 | req_rx: rx, 61 | req_tx: tx, 62 | id, 63 | }; 64 | 65 | h.handle_stream(r).await; 66 | }); 67 | } 68 | 69 | Ok(()) 70 | } 71 | } 72 | 73 | #[derive(Clone)] 74 | struct PeerState { 75 | id: u64, 76 | last_ping: Instant, 77 | req_tx: Sender, 78 | addr: SocketAddr, 79 | } 80 | 81 | type PeerMap = Arc>>; 82 | 83 | struct PeerHandler<'a> { 84 | stream: WriteHalf<'a>, 85 | peers: PeerMap, 86 | peer_id: String, 87 | id: u64, 88 | req_tx: Sender, 89 | req_rx: Receiver, 90 | } 91 | 92 | impl<'a> PeerHandler<'a> { 93 | async fn handle_stream(mut self, r: ReadHalf<'a>) { 94 | let req_tx = self.req_tx.clone(); 95 | 96 | select! { 97 | _ = Self::read_reqs(r, req_tx) => {}, 98 | _ = self.handle_cmds()=> {}, 99 | } 100 | 101 | let mut peers = self.peers.lock().unwrap(); 102 | if let Some(p) = (*peers).get(&self.peer_id) { 103 | if p.id == self.id { 104 | peers.remove(&self.peer_id); 105 | } 106 | } 107 | 108 | if !self.peer_id.is_empty() { 109 | log::debug!("peer {} disconnect", self.peer_id); 110 | } 111 | } 112 | 113 | async fn read_reqs(mut r: ReadHalf<'a>, req_tx: Sender) -> Result<()> { 114 | loop { 115 | match timeout(Duration::from_secs(30), Self::read_req(&mut r)).await? { 116 | Ok(req) => req_tx 117 | .send(req) 118 | .await 119 | .map_err(|_| Error::new(Other, "mpsc channel closed")), 120 | _ => { 121 | let mut bye = Request::new(); 122 | bye.set_Bye(Bye::new()); 123 | let _ = req_tx.send(bye).await; 124 | 125 | Err(Error::new(Other, "timeout reading request")) 126 | } 127 | }?; 128 | } 129 | } 130 | 131 | async fn handle_cmds(&mut self) -> Result<()> { 132 | while let Some(req) = self.req_rx.recv().await { 133 | let src_id = req.id; 134 | match req.cmd { 135 | Some(ReqCmd::Ping(ping)) => self.handle_ping(src_id, ping).await?, 136 | Some(ReqCmd::Isync(isync)) => self.handle_isync(src_id, isync).await?, 137 | Some(ReqCmd::Fsync(fsync)) => self.handle_fsync(fsync).await?, 138 | Some(ReqCmd::Rsync(rsync)) => self.handle_rsync(src_id, rsync).await?, 139 | Some(ReqCmd::Bye(_)) => return Err(Error::new(Other, "received bye command")), 140 | _ => return Err(Error::new(Other, "unknown command received")), 141 | }; 142 | } 143 | 144 | Err(Error::new(Other, "cmd handler channel closed")) 145 | } 146 | 147 | async fn read_req(stream: &mut ReadHalf<'a>) -> Result { 148 | let mut buf = [0; 2]; 149 | stream.read_exact(&mut buf).await?; 150 | 151 | let size = u16::from_be_bytes(buf).into(); 152 | if size > 1500 { 153 | return Err(Error::new(Other, "invalid message size")); 154 | } 155 | let mut buf = vec![0; size]; 156 | stream.read_exact(&mut buf).await?; 157 | 158 | Request::parse_from_bytes(&buf).map_err(|_| Error::new(Other, "failed to parse request")) 159 | } 160 | 161 | async fn send_response(&mut self, cmd: RespCmd) -> Result<()> { 162 | let mut resp = Response::new(); 163 | resp.cmd = Some(cmd); 164 | 165 | let vec = resp.write_to_bytes().unwrap(); 166 | 167 | self.stream 168 | .write_all(&(vec.len() as u16).to_be_bytes()) 169 | .await?; 170 | self.stream.write_all(&vec).await?; 171 | Ok(()) 172 | } 173 | 174 | fn insert_peerstate(&mut self, id: String) { 175 | self.peer_id = id; 176 | let mut peers = self.peers.lock().unwrap(); 177 | 178 | if let Some(p) = peers.get(&self.peer_id) { 179 | if p.id != self.id { 180 | log::debug!("updating peer {}", self.peer_id); 181 | peers.remove(&self.peer_id); 182 | } 183 | } 184 | let p = peers 185 | .entry(self.peer_id.clone()) 186 | .or_insert_with(|| PeerState { 187 | id: self.id, 188 | req_tx: self.req_tx.clone(), 189 | last_ping: Instant::now(), 190 | addr: self.stream.as_ref().peer_addr().unwrap(), 191 | }); 192 | 193 | p.last_ping = Instant::now(); 194 | } 195 | 196 | async fn handle_ping(&mut self, src_id: String, _ping: Ping) -> Result<()> { 197 | log::trace!("handled ping from {}", src_id); 198 | 199 | self.insert_peerstate(src_id); 200 | 201 | self.send_response(RespCmd::Pong(Pong::new())).await 202 | } 203 | 204 | async fn handle_isync(&mut self, src_id: String, isync: Isync) -> Result<()> { 205 | let dst_id = isync.id; 206 | log::debug!("handling isync from {} to {}", src_id, dst_id); 207 | 208 | let mut rdr = Redirect::new(); 209 | rdr.id = dst_id.clone(); 210 | 211 | let peer_opt = self.peers.lock().unwrap().get(&dst_id).cloned(); 212 | if let Some(peer) = peer_opt { 213 | rdr.addr = peer.addr.to_string(); 214 | 215 | // Forward sync request 216 | let mut fsync = Fsync::new(); 217 | fsync.id = src_id.clone(); 218 | fsync.addr = self.stream.as_ref().peer_addr().unwrap().to_string(); 219 | let mut req = Request::new(); 220 | req.set_Fsync(fsync); 221 | 222 | let _ = peer.req_tx.send(req).await; 223 | 224 | // Wait for reply (rsync) 225 | self.insert_peerstate(src_id); 226 | Ok(()) 227 | } else { 228 | log::debug!("destination {} not found", dst_id); 229 | self.send_response(RespCmd::Redirect(rdr)).await 230 | } 231 | } 232 | 233 | async fn handle_fsync(&mut self, fsync: Fsync) -> Result<()> { 234 | log::debug!("handling fsync from {} to {}", fsync.id, self.peer_id); 235 | self.send_response(RespCmd::Fsync(fsync)).await 236 | } 237 | 238 | async fn handle_rsync(&mut self, src_id: String, rsync: Rsync) -> Result<()> { 239 | let dst_id = rsync.id.clone(); 240 | log::debug!("handling rsync from {} to {}", src_id, dst_id); 241 | 242 | if dst_id == self.peer_id { 243 | let peer_opt = self.peers.lock().unwrap().get(&src_id).cloned(); 244 | if let Some(peer) = peer_opt { 245 | let mut rdr = Redirect::new(); 246 | rdr.id = src_id; 247 | rdr.addr = peer.addr.to_string(); 248 | 249 | return self.send_response(RespCmd::Redirect(rdr)).await; 250 | } else { 251 | log::debug!("source {} not found", src_id); 252 | return Ok(()); 253 | } 254 | } 255 | let peer_opt = self.peers.lock().unwrap().get(&dst_id).cloned(); 256 | if let Some(peer) = peer_opt { 257 | let mut req = Request::new(); 258 | req.id = src_id; 259 | req.cmd = Some(ReqCmd::Rsync(rsync)); 260 | 261 | let _ = peer.req_tx.send(req).await; 262 | Ok(()) 263 | } else { 264 | log::debug!("destination {} not found", dst_id); 265 | Ok(()) 266 | } 267 | } 268 | } 269 | -------------------------------------------------------------------------------- /src/udp/client.rs: -------------------------------------------------------------------------------- 1 | use crate::proto::rndz::{ 2 | request::Cmd as ReqCmd, response::Cmd as RespCmd, Bye, Isync, Ping, Request, Response, Rsync, 3 | }; 4 | use log; 5 | use protobuf::Message; 6 | use socket2::{Domain, Protocol, Socket, Type}; 7 | use std::io::{Error, ErrorKind::Other, Result}; 8 | use std::mem::MaybeUninit; 9 | use std::net::{SocketAddr, ToSocketAddrs, UdpSocket}; 10 | use std::os::fd::{AsRawFd, RawFd}; 11 | use std::sync::{ 12 | atomic::{AtomicBool, Ordering::Relaxed}, 13 | Arc, RwLock, 14 | }; 15 | use std::thread::spawn; 16 | use std::time::{Duration, Instant}; 17 | 18 | pub trait SocketConfigure { 19 | fn config_socket(&self, sk: RawFd) -> Result<()>; 20 | } 21 | 22 | /// UDP socket builder 23 | /// 24 | /// Example 25 | /// ```no_run 26 | /// use rndz::udp::Client; 27 | /// 28 | /// let mut c1 = Client::new("rndz_server:1234", "c1", None).unwrap(); 29 | /// let s = c1.listen().unwrap(); 30 | /// let mut buf = [0u8, 10]; 31 | /// s.recv_from(&mut buf).unwrap(); 32 | /// ``` 33 | /// 34 | /// ```no_run 35 | /// use rndz::udp::Client; 36 | /// 37 | /// let mut c2 = Client::new("rndz_server:1234", "c2", None).unwrap(); 38 | /// let s = c2.connect("c1").unwrap(); 39 | /// s.send(b"hello").unwrap(); 40 | /// ``` 41 | pub struct Client { 42 | svr_sk: Option, 43 | sk_cfg: Option>, 44 | server_addr: SocketAddr, 45 | id: String, 46 | local_addr: SocketAddr, 47 | exit: Arc, 48 | last_pong: Arc>>, 49 | } 50 | 51 | impl Drop for Client { 52 | fn drop(&mut self) { 53 | self.exit.store(true, Relaxed); 54 | self.drop_server_sk(); 55 | } 56 | } 57 | 58 | impl Client { 59 | /// Set rendezvous server, peer identity, local bind address. 60 | /// If no local address set, choose according to server address type (IPv4 or IPv6). 61 | pub fn new( 62 | server_addr: &str, 63 | id: &str, 64 | local_addr: Option, 65 | sk_cfg: Option>, 66 | ) -> Result { 67 | let svr_sk = Self::connect_server(server_addr, local_addr, sk_cfg.as_deref())?; 68 | let local_addr = svr_sk.local_addr().unwrap().as_socket().unwrap(); 69 | 70 | Ok(Self { 71 | server_addr: svr_sk.peer_addr().unwrap().as_socket().unwrap(), 72 | sk_cfg, 73 | svr_sk: Some(svr_sk), 74 | id: id.into(), 75 | local_addr, 76 | exit: Default::default(), 77 | last_pong: Default::default(), 78 | }) 79 | } 80 | 81 | /// Get local address 82 | pub fn local_addr(&self) -> Option { 83 | Some(self.local_addr) 84 | } 85 | 86 | /// Get the last received pong from server 87 | pub fn last_pong(&self) -> Option { 88 | *self.last_pong.read().unwrap() 89 | } 90 | 91 | // Connect to server 92 | fn connect_server( 93 | server_addr: &str, 94 | local_addr: Option, 95 | sk_cfg: Option<&dyn SocketConfigure>, 96 | ) -> Result { 97 | let server_addr = server_addr 98 | .to_socket_addrs()? 99 | .next() 100 | .ok_or_else(|| Error::new(Other, "No address found"))?; 101 | 102 | let local_addr = match local_addr { 103 | Some(addr) => addr, 104 | None => match server_addr { 105 | SocketAddr::V4(_) => "0.0.0.0:0".parse().unwrap(), 106 | SocketAddr::V6(_) => "[::]:0".parse().unwrap(), 107 | }, 108 | }; 109 | 110 | let svr_sk = Self::create_socket(local_addr, sk_cfg)?; 111 | svr_sk.set_nonblocking(false)?; 112 | svr_sk.connect(&server_addr.into())?; 113 | 114 | Ok(svr_sk) 115 | } 116 | 117 | // Drop server socket 118 | fn drop_server_sk(&mut self) { 119 | if let Some(mut s) = self.svr_sk.take() { 120 | Self::send_cmd(&mut s, &self.id, ReqCmd::Bye(Bye::new()), self.server_addr); 121 | }; 122 | } 123 | 124 | // Create new socket 125 | fn create_socket(addr: SocketAddr, sk_cfg: Option<&dyn SocketConfigure>) -> Result { 126 | let domain = Domain::for_address(addr); 127 | let socket = Socket::new(domain, Type::DGRAM, Some(Protocol::UDP)).unwrap(); 128 | 129 | if let Some(cfg) = sk_cfg { 130 | cfg.config_socket(socket.as_raw_fd())?; 131 | } 132 | 133 | socket.set_reuse_address(true)?; 134 | socket.bind(&addr.into())?; 135 | 136 | Ok(socket) 137 | } 138 | 139 | // Create new request 140 | fn new_req(myid: &str) -> Request { 141 | let mut req = Request::new(); 142 | req.id = myid.into(); 143 | 144 | req 145 | } 146 | 147 | // Receive response from server 148 | fn recv_resp(&mut self) -> Result { 149 | let mut buf = unsafe { MaybeUninit::<[MaybeUninit; 1500]>::uninit().assume_init() }; //MaybeUninit::uninit_array 150 | let n = self.svr_sk.as_ref().unwrap().recv(&mut buf)?; 151 | let buf = unsafe { &*(&buf as *const _ as *const [u8; 1500]) }; //MaybeUninit::slice_assume_init_ref 152 | let resp = Response::parse_from_bytes(&buf[..n])?; 153 | Ok(resp) 154 | } 155 | 156 | /// Send rendezvous server a request to connect to target peer. 157 | /// 158 | /// Create a connected UDP socket with peer stored in peer_sk field, use `as_socket()` to get it. 159 | pub fn connect(&mut self, target_id: &str) -> Result { 160 | if self.svr_sk.is_none() { 161 | // This is a reconnect 162 | self.svr_sk = Some(Self::connect_server( 163 | &self.server_addr.to_string(), 164 | Some(self.local_addr), 165 | self.sk_cfg.as_deref(), 166 | )?); 167 | 168 | // From now on, there are two same port sockets, WINDOWS will confuse! 169 | // Windows can't work well with two same port sockets. 170 | 171 | // NOTE: DON'T reconnect on WINDOWS!!!! 172 | #[cfg(windows)] 173 | log::warn!("WARNING: reconnect not works on WINDOWS!!!"); 174 | } 175 | 176 | let mut isync = Isync::new(); 177 | isync.id = target_id.into(); 178 | 179 | let mut req = Self::new_req(&self.id); 180 | req.set_Isync(isync); 181 | 182 | let isync = req.write_to_bytes()?; 183 | 184 | self.svr_sk 185 | .as_ref() 186 | .unwrap() 187 | .set_read_timeout(Some(Duration::from_secs(10)))?; 188 | 189 | let mut peer_addr = None; 190 | for _ in 0..3 { 191 | self.svr_sk.as_ref().unwrap().send(isync.as_ref())?; 192 | 193 | if let Ok(resp) = self.recv_resp() { 194 | if resp.id != self.id { 195 | continue; 196 | } 197 | 198 | if let Some(RespCmd::Redirect(rdr)) = resp.cmd { 199 | if !rdr.addr.is_empty() { 200 | peer_addr = Some(rdr.addr); 201 | break; 202 | } else { 203 | return Err(Error::new(Other, "Target not found")); 204 | } 205 | } 206 | } 207 | } 208 | 209 | let peer_addr: SocketAddr = peer_addr 210 | .ok_or_else(|| Error::new(Other, "No response"))? 211 | .parse() 212 | .map_err(|_| { 213 | Error::new( 214 | Other, 215 | "Rendezvous server response contains invalid peer address", 216 | ) 217 | })?; 218 | 219 | // We don't need svr_sk anymore, to prevent interference with peer_sk on WINDOWS, we drop it. 220 | self.drop_server_sk(); 221 | 222 | let peer_sk = Self::create_socket(self.local_addr, self.sk_cfg.as_deref())?; 223 | peer_sk.connect(&peer_addr.into())?; 224 | 225 | Ok(peer_sk.into()) 226 | } 227 | 228 | /// Keep pinging rendezvous server, wait for peer connection request. 229 | /// 230 | /// When receiving `Fsync` request from server, attempt to send remote peer a packet. 231 | /// This will open the firewall and NAT rule for the peer. 232 | pub fn listen(&mut self) -> Result { 233 | #[cfg(windows)] 234 | log::warn!("WARNING: listen not works on WINDOWS!!!"); 235 | 236 | let mut svr_sk = self.svr_sk.as_ref().unwrap().try_clone().unwrap(); 237 | let myid = self.id.clone(); 238 | let server_addr = self.server_addr; 239 | 240 | let exit = self.exit.clone(); 241 | let last_pong = self.last_pong.clone(); 242 | 243 | spawn(move || { 244 | let mut req = Self::new_req(&myid); 245 | req.set_Ping(Ping::new()); 246 | let ping = req.write_to_bytes().unwrap(); 247 | 248 | let mut last_ping: Option = None; 249 | let keepalive_to = Duration::from_secs(10); 250 | 251 | svr_sk.set_read_timeout(Some(keepalive_to)).unwrap(); 252 | 253 | loop { 254 | if exit.load(Relaxed) { 255 | break; 256 | } 257 | 258 | if last_ping.is_none() || last_ping.as_ref().unwrap().elapsed() > keepalive_to { 259 | let _ = svr_sk.send(ping.as_ref()); 260 | last_ping = Some(Instant::now()) 261 | } 262 | 263 | let mut buf = 264 | unsafe { MaybeUninit::<[MaybeUninit; 1500]>::uninit().assume_init() }; //MaybeUninit::uninit_array 265 | let n = match svr_sk.recv(&mut buf) { 266 | Ok(n) => n, 267 | Err(_) => continue, 268 | }; 269 | 270 | let buf = unsafe { &*(&buf as *const _ as *const [u8; 1500]) }; //MaybeUninit::slice_assume_init_ref 271 | 272 | let resp = match Response::parse_from_bytes(&buf[..n]) { 273 | Ok(resp) => resp, 274 | Err(_) => continue, 275 | }; 276 | 277 | if resp.id != myid { 278 | continue; 279 | } 280 | 281 | match resp.cmd { 282 | Some(RespCmd::Pong(_)) => { 283 | *last_pong.write().unwrap() = Some(Instant::now()); 284 | } 285 | Some(RespCmd::Fsync(fsync)) => { 286 | log::debug!("fsync {}", fsync.id); 287 | 288 | Self::send_rsync(&mut svr_sk, &myid, &fsync.id, server_addr); 289 | 290 | match fsync.addr.parse() { 291 | Ok(addr) => Self::send_rsync(&mut svr_sk, &myid, &fsync.id, addr), 292 | _ => { 293 | log::debug!("Invalid fsync address"); 294 | continue; 295 | } 296 | }; 297 | } 298 | _ => {} 299 | }; 300 | } 301 | }); 302 | 303 | let peer_sk = Self::create_socket(self.local_addr, self.sk_cfg.as_deref())?; 304 | Ok(peer_sk.into()) 305 | } 306 | 307 | // Send rsync command 308 | fn send_rsync(socket: &mut Socket, myid: &str, target_id: &str, addr: SocketAddr) { 309 | let mut rsync = Rsync::new(); 310 | rsync.id = target_id.into(); 311 | 312 | Self::send_cmd(socket, myid, ReqCmd::Rsync(rsync), addr); 313 | } 314 | 315 | // Send command 316 | fn send_cmd(socket: &mut Socket, myid: &str, cmd: ReqCmd, addr: SocketAddr) { 317 | let mut req = Request::new(); 318 | req.id = myid.into(); 319 | req.cmd = Some(cmd); 320 | 321 | let _ = socket.send_to(req.write_to_bytes().unwrap().as_ref(), &addr.into()); 322 | } 323 | } 324 | -------------------------------------------------------------------------------- /src/udp/mod.rs: -------------------------------------------------------------------------------- 1 | //! UDP connection. 2 | //! 3 | //! Use `Client` to bind, connect socket. 4 | //! 5 | //! Use `Server` to create a rendezvous server. 6 | 7 | #[cfg(feature = "client")] 8 | mod client; 9 | #[cfg(feature = "client")] 10 | pub use client::Client; 11 | #[cfg(feature = "client")] 12 | pub use client::SocketConfigure; 13 | 14 | #[cfg(feature = "server")] 15 | mod server; 16 | #[cfg(feature = "server")] 17 | pub use server::Server; 18 | 19 | #[cfg(test)] 20 | mod tests { 21 | use socket2::{Domain, Protocol, Socket, Type}; 22 | use std::net::SocketAddr; 23 | 24 | #[test] 25 | fn test_server() { 26 | let local_addr: SocketAddr = "0.0.0.0:0".parse().unwrap(); 27 | let socket = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP)).unwrap(); 28 | socket.set_reuse_address(true).unwrap(); 29 | socket.bind(&local_addr.into()).unwrap(); 30 | let remote_addr: SocketAddr = "8.8.8.8:53".parse().unwrap(); 31 | socket.connect(&remote_addr.into()).unwrap(); 32 | 33 | let socket2 = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP)).unwrap(); 34 | socket2.set_reuse_address(true).unwrap(); 35 | socket2.bind(&socket.local_addr().unwrap()).unwrap(); 36 | let remote_addr2: SocketAddr = "1.1.1.1:53".parse().unwrap(); 37 | socket2.send_to(b"hello", &remote_addr2.into()).unwrap(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/udp/server.rs: -------------------------------------------------------------------------------- 1 | use log; 2 | use protobuf::Message; 3 | use std::collections::HashMap; 4 | use std::io::Result; 5 | use std::net::{SocketAddr, ToSocketAddrs, UdpSocket}; 6 | use std::time::{Duration, Instant}; 7 | 8 | use crate::proto::rndz::{ 9 | request::Cmd as ReqCmd, response::Cmd as RespCmd, Fsync, Isync, Ping, Pong, Redirect, Request, 10 | Response, Rsync, 11 | }; 12 | 13 | #[derive(Copy, Clone)] 14 | struct Client { 15 | addr: SocketAddr, 16 | last_ping: Instant, 17 | } 18 | 19 | impl Default for Client { 20 | fn default() -> Self { 21 | Client { 22 | addr: ([0, 0, 0, 0], 0).into(), 23 | last_ping: Instant::now(), 24 | } 25 | } 26 | } 27 | 28 | /// UDP rendezvous server 29 | /// 30 | /// Keeps track of all peers and forward connection requests. 31 | pub struct Server { 32 | socket: UdpSocket, 33 | clients: HashMap, 34 | next_gc: Instant, 35 | } 36 | 37 | impl Server { 38 | pub fn new(listen_addr: A) -> Result { 39 | let socket = UdpSocket::bind(listen_addr)?; 40 | 41 | Ok(Self { 42 | socket, 43 | clients: Default::default(), 44 | next_gc: Self::next_gc(), 45 | }) 46 | } 47 | 48 | pub fn run(mut self) -> Result<()> { 49 | let mut buf = [0; 1500]; 50 | 51 | self.socket 52 | .set_read_timeout(Some(Duration::from_secs(30)))?; 53 | 54 | loop { 55 | if let Ok((size, addr)) = self.socket.recv_from(&mut buf) { 56 | if let Ok(req) = Request::parse_from_bytes(&buf[..size]) { 57 | self.handle_request(req, addr); 58 | } 59 | } 60 | 61 | if Instant::now() > self.next_gc { 62 | self.gc(); 63 | } 64 | } 65 | } 66 | 67 | fn handle_request(&mut self, req: Request, addr: SocketAddr) { 68 | match req.cmd { 69 | Some(ReqCmd::Ping(ping)) => self.handle_ping(req.id, ping, addr), 70 | Some(ReqCmd::Isync(isync)) => self.handle_isync(req.id, isync, addr), 71 | Some(ReqCmd::Rsync(rsync)) => self.handle_rsync(req.id, rsync, addr), 72 | Some(ReqCmd::Bye(_)) => self.handle_bye(req.id), 73 | _ => { 74 | log::debug!("Unknown command {:?}", req) 75 | } 76 | }; 77 | } 78 | 79 | fn send_response(&mut self, cmd: RespCmd, id: String, addr: SocketAddr) { 80 | let mut resp = Response::new(); 81 | resp.id = id; 82 | resp.cmd = Some(cmd); 83 | 84 | let vec = resp.write_to_bytes().unwrap(); 85 | let _ = self.socket.send_to(vec.as_ref(), addr); 86 | } 87 | 88 | fn handle_ping(&mut self, id: String, _ping: Ping, addr: SocketAddr) { 89 | log::trace!("Ping from {}", id); 90 | 91 | let c = self.clients.entry(id.clone()).or_default(); 92 | c.last_ping = Instant::now(); 93 | c.addr = addr; 94 | 95 | self.send_response(RespCmd::Pong(Pong::new()), id, addr); 96 | } 97 | 98 | fn handle_isync(&mut self, id: String, isync: Isync, addr: SocketAddr) { 99 | let target_id = isync.id; 100 | log::debug!("Isync from {} to {}", id, target_id); 101 | 102 | if let Some(t) = self.clients.get(&target_id).copied() { 103 | let s = self.clients.entry(id.clone()).or_default(); 104 | s.last_ping = Instant::now(); 105 | s.addr = addr; 106 | 107 | let mut fsync = Fsync::new(); 108 | fsync.id = id; 109 | fsync.addr = addr.to_string(); 110 | self.send_response(RespCmd::Fsync(fsync), target_id.to_string(), t.addr); 111 | } else { 112 | log::debug!("Target ID {} not found", target_id); 113 | let mut rdr = Redirect::new(); 114 | rdr.id = target_id; 115 | self.send_response(RespCmd::Redirect(rdr), id, addr); 116 | } 117 | } 118 | 119 | fn handle_rsync(&mut self, id: String, rsync: Rsync, addr: SocketAddr) { 120 | let target_id = rsync.id; 121 | log::debug!("Rsync from {} to {}", id, target_id); 122 | 123 | if let Some(c) = self.clients.get(&target_id).copied() { 124 | let mut rdr = Redirect::new(); 125 | rdr.id = id; 126 | rdr.addr = addr.to_string(); 127 | self.send_response(RespCmd::Redirect(rdr), target_id.to_string(), c.addr); 128 | } else { 129 | log::debug!("Rsync could not find target {}", target_id); 130 | } 131 | } 132 | 133 | fn handle_bye(&mut self, id: String) { 134 | log::debug!("Bye from {}", id); 135 | self.clients.remove(&id); 136 | } 137 | 138 | fn next_gc() -> Instant { 139 | Instant::now() + Duration::from_secs(60) 140 | } 141 | 142 | fn gc(&mut self) { 143 | let expire = Instant::now() - Duration::from_secs(60); 144 | self.clients.retain(|id, c| { 145 | let not_expired = expire < c.last_ping; 146 | if !not_expired { 147 | log::debug!("Client {} expired", id); 148 | } 149 | not_expired 150 | }); 151 | 152 | self.next_gc = Self::next_gc(); 153 | } 154 | } 155 | --------------------------------------------------------------------------------