diff options
author | open-trade <[email protected]> | 2020-03-06 17:18:22 +0800 |
---|---|---|
committer | open-trade <[email protected]> | 2020-03-06 17:18:22 +0800 |
commit | 1695b5e3574b578aae0d75189e4395c631ca3b8a (patch) | |
tree | 95023624e8963efb1ab41b5baee91161e6baaf7a /src | |
parent | d188a5f5ea0b6498eecd6a9c8239cb2d55341f81 (diff) | |
download | rustdesk-server-1695b5e3574b578aae0d75189e4395c631ca3b8a.tar.gz rustdesk-server-1695b5e3574b578aae0d75189e4395c631ca3b8a.zip |
prototype...
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 5 | ||||
-rw-r--r-- | src/main.rs | 15 | ||||
-rw-r--r-- | src/protos/message.rs | 301 | ||||
-rw-r--r-- | src/rendezvous_server.rs | 93 |
4 files changed, 411 insertions, 3 deletions
diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..6cb9769 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,5 @@ +mod rendezvous_server; +pub use rendezvous_server::*; +#[path = "./protos/message.rs"] +mod message_proto; +pub use message_proto::*;
\ No newline at end of file diff --git a/src/main.rs b/src/main.rs index e7a11a9..d1aad28 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,12 @@ -fn main() { - println!("Hello, world!"); -} +// https://tools.ietf.org/rfc/rfc5128.txt +// https://blog.csdn.net/bytxl/article/details/44344855 + +use hbbs::*; +use std::error::Error; + +#[tokio::main] +async fn main() -> Result<(), Box<dyn Error>> { + env_logger::init(); + RendezvousServer::start("0.0.0.0:21116").await?; + Ok(()) +}
\ No newline at end of file diff --git a/src/protos/message.rs b/src/protos/message.rs new file mode 100644 index 0000000..a40385f --- /dev/null +++ b/src/protos/message.rs @@ -0,0 +1,301 @@ +// This file is generated by rust-protobuf 2.10.2. Do not edit +// @generated + +// https://github.com/rust-lang/rust-clippy/issues/702 +#![allow(unknown_lints)] +#![allow(clippy::all)] + +#![cfg_attr(rustfmt, rustfmt_skip)] + +#![allow(box_pointers)] +#![allow(dead_code)] +#![allow(missing_docs)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(trivial_casts)] +#![allow(unsafe_code)] +#![allow(unused_imports)] +#![allow(unused_results)] +//! Generated file from `message.proto` + +use protobuf::Message as Message_imported_for_functions; +use protobuf::ProtobufEnum as ProtobufEnum_imported_for_functions; + +/// Generated files are compatible only with the same version +/// of protobuf runtime. +// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_10_2; + +#[derive(PartialEq,Clone,Default)] +pub struct Message { + // message fields + pub addr: ::std::string::String, + // message oneof groups + pub union: ::std::option::Option<Message_oneof_union>, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a Message { + fn default() -> &'a Message { + <Message as ::protobuf::Message>::default_instance() + } +} + +#[derive(Clone,PartialEq,Debug)] +pub enum Message_oneof_union { + socket_addr(::std::vec::Vec<u8>), +} + +impl Message { + pub fn new() -> Message { + ::std::default::Default::default() + } + + // string addr = 1; + + + pub fn get_addr(&self) -> &str { + &self.addr + } + pub fn clear_addr(&mut self) { + self.addr.clear(); + } + + // Param is passed by value, moved + pub fn set_addr(&mut self, v: ::std::string::String) { + self.addr = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_addr(&mut self) -> &mut ::std::string::String { + &mut self.addr + } + + // Take field + pub fn take_addr(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.addr, ::std::string::String::new()) + } + + // bytes socket_addr = 6; + + + pub fn get_socket_addr(&self) -> &[u8] { + match self.union { + ::std::option::Option::Some(Message_oneof_union::socket_addr(ref v)) => v, + _ => &[], + } + } + pub fn clear_socket_addr(&mut self) { + self.union = ::std::option::Option::None; + } + + pub fn has_socket_addr(&self) -> bool { + match self.union { + ::std::option::Option::Some(Message_oneof_union::socket_addr(..)) => true, + _ => false, + } + } + + // Param is passed by value, moved + pub fn set_socket_addr(&mut self, v: ::std::vec::Vec<u8>) { + self.union = ::std::option::Option::Some(Message_oneof_union::socket_addr(v)) + } + + // Mutable pointer to the field. + pub fn mut_socket_addr(&mut self) -> &mut ::std::vec::Vec<u8> { + if let ::std::option::Option::Some(Message_oneof_union::socket_addr(_)) = self.union { + } else { + self.union = ::std::option::Option::Some(Message_oneof_union::socket_addr(::std::vec::Vec::new())); + } + match self.union { + ::std::option::Option::Some(Message_oneof_union::socket_addr(ref mut v)) => v, + _ => panic!(), + } + } + + // Take field + pub fn take_socket_addr(&mut self) -> ::std::vec::Vec<u8> { + if self.has_socket_addr() { + match self.union.take() { + ::std::option::Option::Some(Message_oneof_union::socket_addr(v)) => v, + _ => panic!(), + } + } else { + ::std::vec::Vec::new() + } + } +} + +impl ::protobuf::Message for Message { + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.addr)?; + }, + 6 => { + if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + self.union = ::std::option::Option::Some(Message_oneof_union::socket_addr(is.read_bytes()?)); + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if !self.addr.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.addr); + } + if let ::std::option::Option::Some(ref v) = self.union { + match v { + &Message_oneof_union::socket_addr(ref v) => { + my_size += ::protobuf::rt::bytes_size(6, &v); + }, + }; + } + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { + if !self.addr.is_empty() { + os.write_string(1, &self.addr)?; + } + if let ::std::option::Option::Some(ref v) = self.union { + match v { + &Message_oneof_union::socket_addr(ref v) => { + os.write_bytes(6, v)?; + }, + }; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &dyn (::std::any::Any) { + self as &dyn (::std::any::Any) + } + fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) { + self as &mut dyn (::std::any::Any) + } + fn into_any(self: Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> Message { + Message::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, + }; + unsafe { + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "addr", + |m: &Message| { &m.addr }, + |m: &mut Message| { &mut m.addr }, + )); + fields.push(::protobuf::reflect::accessor::make_singular_bytes_accessor::<_>( + "socket_addr", + Message::has_socket_addr, + Message::get_socket_addr, + )); + ::protobuf::reflect::MessageDescriptor::new::<Message>( + "Message", + fields, + file_descriptor_proto() + ) + }) + } + } + + fn default_instance() -> &'static Message { + static mut instance: ::protobuf::lazy::Lazy<Message> = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const Message, + }; + unsafe { + instance.get(Message::new) + } + } +} + +impl ::protobuf::Clear for Message { + fn clear(&mut self) { + self.addr.clear(); + self.union = ::std::option::Option::None; + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for Message { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for Message { + fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { + ::protobuf::reflect::ProtobufValueRef::Message(self) + } +} + +static file_descriptor_proto_data: &'static [u8] = b"\ + \n\rmessage.proto\x12\x03hbb\"=\n\x07Message\x12\x0e\n\x04addr\x18\x01\ + \x20\x01(\tB\0\x12\x17\n\x0bsocket_addr\x18\x06\x20\x01(\x0cH\0B\0B\x07\ + \n\x05union:\0B\0b\x06proto3\ +"; + +static mut file_descriptor_proto_lazy: ::protobuf::lazy::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::lazy::Lazy { + lock: ::protobuf::lazy::ONCE_INIT, + ptr: 0 as *const ::protobuf::descriptor::FileDescriptorProto, +}; + +fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto { + ::protobuf::parse_from_bytes(file_descriptor_proto_data).unwrap() +} + +pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto { + unsafe { + file_descriptor_proto_lazy.get(|| { + parse_descriptor_proto() + }) + } +} diff --git a/src/rendezvous_server.rs b/src/rendezvous_server.rs new file mode 100644 index 0000000..1b5d3d8 --- /dev/null +++ b/src/rendezvous_server.rs @@ -0,0 +1,93 @@ +use super::message_proto::Message; +use bytes::Bytes; +use futures::{FutureExt, SinkExt}; +use protobuf::{parse_from_bytes, Message as _}; +use std::{ + collections::HashMap, + error::Error, + net::{Ipv4Addr, SocketAddr, SocketAddrV4}, + time::{SystemTime, UNIX_EPOCH}, +}; +use tokio::net::UdpSocket; +use tokio::stream::StreamExt; +use tokio_util::{codec::BytesCodec, udp::UdpFramed}; + +/// Certain router and firewalls scan the packet and if they +/// find an IP address belonging to their pool that they use to do the NAT mapping/translation, so here we mangle the ip address + +pub struct V4AddrMangle(Vec<u8>); + +impl V4AddrMangle { + pub fn encode(addr: SocketAddrV4) -> Self { + let tm = (SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_micros() as u32) as u128; + let ip = u32::from_ne_bytes(addr.ip().octets()) as u128; + let port = addr.port() as u128; + let v = ((ip + tm) << 49) | (tm << 17) | (port + (tm & 0xFFFF)); + let bytes = v.to_ne_bytes(); + let mut n_padding = 0; + for i in bytes.iter().rev() { + if i == &0u8 { + n_padding += 1; + } else { + break; + } + } + Self(bytes[..(16 - n_padding)].to_vec()) + } + + pub fn decode(&self) -> SocketAddrV4 { + let mut padded = [0u8; 16]; + padded[..self.0.len()].copy_from_slice(&self.0); + let number = u128::from_ne_bytes(padded); + let tm = (number >> 17) & (u32::max_value() as u128); + let ip = (((number >> 49) - tm) as u32).to_ne_bytes(); + let port = (number & 0xFFFFFF) - (tm & 0xFFFF); + SocketAddrV4::new(Ipv4Addr::new(ip[0], ip[1], ip[2], ip[3]), port as u16) + } +} + +pub struct Peer { + socket_addr: SocketAddr, +} + +type PeerMap = HashMap<String, Peer>; + +pub struct RendezvousServer { + peer_map: PeerMap, +} + +impl RendezvousServer { + pub async fn start(addr: &str) -> Result<Self, Box<dyn Error>> { + let socket = UdpSocket::bind(addr).await?; + let mut socket = UdpFramed::new(socket, BytesCodec::new()); + + let rs = Self { + peer_map: PeerMap::new(), + }; + while let Some(Ok((bytes, addr))) = socket.next().await { + if let SocketAddr::V4(addr_v4) = addr { + if let Ok(msg_in) = parse_from_bytes::<Message>(&bytes) { + let msg_out = Message::new(); + socket + .send((Bytes::from(msg_out.write_to_bytes().unwrap()), addr)) + .await?; + } + } + } + Ok(rs) + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_mangle() { + let addr = SocketAddrV4::new(Ipv4Addr::new(192, 168, 16, 32), 21116); + assert_eq!(addr, V4AddrMangle::encode(addr).decode()); + println!("{:?}", V4AddrMangle::encode(addr).0); + } +} |