├── .gitignore ├── Cargo.toml ├── LICENSE ├── README.md └── src ├── lib.rs ├── tachyon.rs └── tachyon ├── byte_buffer_pool.rs ├── channel.rs ├── connection.rs ├── connection_impl.rs ├── ffi.rs ├── fragmentation.rs ├── header.rs ├── int_buffer.rs ├── memory_block.rs ├── nack.rs ├── network_address.rs ├── pool.rs ├── pool_ffi.rs ├── pool_unreliable_sender.rs ├── receive_result.rs ├── receiver.rs ├── send_buffer_manager.rs ├── sequence.rs ├── sequence_buffer.rs ├── tachyon_socket.rs ├── tachyon_test.rs └── unreliable_sender.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tachyon-networking" 3 | version = "0.1.9" 4 | edition = "2021" 5 | authors = [ 6 | "Chris Ochs " 7 | ] 8 | 9 | description = "a Nack based reliable udp library for games and IPC" 10 | keywords = ["gamedev", "networking", "udp","ipc"] 11 | categories = ["game-engines", "network-programming"] 12 | 13 | readme = "README.md" 14 | license = "MIT" 15 | 16 | repository = "https://github.com/gamemachine/tachyon-networking" 17 | 18 | [lib] 19 | name="tachyon" 20 | crate-type = ["rlib", "cdylib"] 21 | 22 | 23 | [dependencies] 24 | libc = "0.2" 25 | rustc-hash = "1.1.0" 26 | socket2 = "0.4.2" 27 | varuint = "0.6" 28 | rand = "0.8.4" 29 | serial_test = "0.5.1" 30 | rayon = "1.5.1" 31 | crossbeam = "0.8.1" 32 | synchronoise = "1.0.0" 33 | 34 | [profile.test] 35 | opt-level = 3 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Chris Ochs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tachyon 2 | 3 | Tachyon is a performant and highly parallel reliable udp library that uses a nack based model. 4 | 5 | * Strongly reliable 6 | * Reliable fragmentation 7 | * Ordered and unordered channels 8 | * Identity management 9 | * Suitable for high throughput IPC as well as games. 10 | 11 | Tachyon was specifically designed for a verticaly scaled environment with many connected clients and high throughput local IPC. Parallelism for receives was necessary to be able to process the volume within a single frame. And larger receive windows were needed to handle the IPC volume while still retaining strong reliability. 12 | 13 | 14 | ## Reliablity 15 | Reliability models vary a lot because there aren't any perfect solutions and context tends to matter a lot. But a core technique that is used in a good number of them is [Glen Fiedler's approach](https://gafferongames.com/post/reliable_ordered_messages/) that encodes acks as bit flags. The most well known usage of it is to encode acks in every outgoing message. But that means if you send 33 messages per frame, you used up the entire window in a single frame. It's designed to be used with higher level message aggregation, sending say 1-4 packets per frame or so. 16 | 17 | The nack model can optimistically cover a much larger window in 33 slots using that same technique, because we are only covering missing packets. Tachyon extends this by chaining multiple 33 slot nack windows over a much larger receive window as needed, the default receive window being 512 slots. 18 | 19 | The receive window has a configurable max. It starts at the last in order sequence received, and runs to the last sequence received. Once per frame we walk this window back to front and create a nack messages for every 33 slots. And then pack those into a single varint encoded network packet and send it out. 20 | 21 | But that message itself could get dropped, introducing latency. So we also support taking those same nacks and insert them into outgoing messages in a round robin fashion. Up to ChannelConfig.nack_redundancy times per unique nack. The cost for redundancy is the outgoing message header size goes from 4 to 10 bytes. 22 | 23 | One thing to keep in mind is that the nack model needs a constant message flow in order to know what is missing. So if you have channels with only occasional messages, you should send a header + 1 sized message regularly. Tachyon should just add an internal message here that automatically sends on every channel if nothing else went out, but that's not in yet. 24 | 25 | We also have logic to expire messages that last too long in the send buffers. Like occasional large messages that have their own channel. The send buffer is 1024, double the size of the default receive window. 26 | 27 | 28 | ## Channels 29 | Sequencing is per channel. With every connected address (connection) having it's own set of channels. 30 | 31 | The system configures two channels automatically channel 1 being ordered and channel 2 unordered. And you can add more but they need to be added before bind/connect. Because they are per address, on the server side we lazily create channels as we see receives from new addresses. 32 | 33 | ## Fragmentation 34 | Fragments are individually reliable. Each one is sent as a separate sequenced message and tagged with a group id. When the other side gets all of the fragments in the group 35 | we re assemble the message and deliver it. So larger messages work fairly well, just not too large where you start chewing up too much of the receive window. 36 | 37 | ## Ordered vs Unordered 38 | Both ordered and unordered are reliable. 39 | 40 | Ordered messages are only delivered in order. 41 | Unordered are delivered as soon as they arrive. 42 | 43 | ## Connection management 44 | Tachyon connections mirror udp connections, the only identifying information is the ip address. 45 | 46 | And then we add an Identity abstraction that can be linked to a connection. An identity is an integer id and session id created by the application. You set an id/session pair on the server, and you tell the client what they are out of band say via https. If configured to use identities the client will automatically attempt to link it's identity after connect. If the client ip changes it needs to request to be linked again. The server when it links first removes any addresses previously linked. With identities enabled regular messages are blocked on both ends until identity is established. 47 | 48 | 49 | ## Concurrency 50 | Tachyon can be run highly parallel but uses no concurrency internally. By design nothing in Tachyon is thread safe. 51 | 52 | Parallelism is achieved by running multiple Tachyon's on different ports, and the Pool api exposes those as a single Tachyon more or less. Managing the internal mappings of connections and identities to ports for you. And then it runs the receives for those in parallel. 53 | 54 | Sending unreliable messages from multiple threads is supported through special unreliable senders (see below). 55 | 56 | Parallel receiving uses batching concurrency in it's flow. We use a concurrent queue of non concurrent queues to limit atomic operations to just a small handful per tachyon instance. 57 | 58 | ## Unreliable senders 59 | UnreliableSender and PoolUnreliableSender exist so you can send unreliable messages from multiple threads. They are intended to be used 60 | for sending a bunch of messages with one instance, and are a bit heavy to instantiate per message. You can create multiple of these using them in different threads, 61 | but you can't use one concurrently from multiple threads. 62 | 63 | ## Usage 64 | Not much in the way of documentation yet but there are a good number of unit tests. And ffi.rs encapsulates most of the api. tachyon_tests.rs has some stress testing unit tests. The api is designed primarily for ffi consumption, as I use it from a .NET server. 65 | 66 | update() has to be called once per frame. That is where nacks and resends in response to nacks received are sent. In addition to some housekeeping and fragment expiration. Sends are processed immediately. 67 | 68 | ### Pool usage 69 | The pool api has mostly the same send interface as Tachyon single usage. Mapping of connections and identities to servers is handled internally. So you just send to 70 | and address/identity and the pool maps that to the right server. 71 | 72 | There are 3 versions of the receive api currently. Two of them do heap allocations and a newer but more complex version 73 | that does not. That version writes out received messages into a single out buffer per tachyon, with individual messages prefixed with length, channel, and ip address. And then you read that out buffer using LengthPrefixed like a stream. This extra work is primarily to avoid memory fragmention from unnecessary allocations. 74 | 75 | 76 | 77 | 78 | ### Basic usage. 79 | 80 | The default send api is send_to_target that takes a SendTarget. If an identity id is set it will lookup the address using that. If not will use the address. 81 | Clients always send to a default NetworkAddress. This api is uniform for Tachyon and Pool. 82 | 83 | ``` 84 | let config = TachyonConfig::default(); 85 | let server = Tachyon::create(config); 86 | let client = Tachyon::create(config); 87 | 88 | let address = NetworkAddress { a: 127, b: 0, c: 0, d: 0, port: 8001}; 89 | server.bind(address); 90 | client.connect(address); 91 | 92 | let send_buffer: Vec = vec![0;1024]; 93 | let receive_buffer: Vec = vec![0;4096]; 94 | 95 | let target = SendTarget {address: NetworkAddress::default(), identity_id: 0}; 96 | client.send_to_target(1, target, &mut send_buffer, 32); 97 | let receive_result = server.receive_loop(&mut receive_buffer); 98 | if receive_result.length > 0 && receive_result.error == 0 { 99 | server.send_reliable(1, receive_result.address, &mut send_buffer, 32); 100 | } 101 | 102 | client.update(); 103 | server.update(); 104 | 105 | ``` 106 | 107 | 108 | ### Pool usage 109 | ``` 110 | let mut pool = Pool::create(); 111 | let config = TachyonConfig::default(); 112 | 113 | // create_server also binds the port 114 | pool.create_server(config, NetworkAddress::localhost(8001)); 115 | pool.create_server(config, NetworkAddress::localhost(8002)); 116 | pool.create_server(config, NetworkAddress::localhost(8003)); 117 | 118 | // using built in test client which removes some boilerplate 119 | let mut client1 = TachyonTestClient::create(NetworkAddress::localhost(8001)); 120 | let mut client2 = TachyonTestClient::create(NetworkAddress::localhost(8002)); 121 | let mut client3 = TachyonTestClient::create(NetworkAddress::localhost(8003)); 122 | client1.connect(); 123 | client2.connect(); 124 | client3.connect(); 125 | 126 | let count = 20000; 127 | let msg_len = 64; 128 | 129 | for _ in 0..count { 130 | client1.client_send_reliable(1, msg_len); 131 | client2.client_send_reliable(1, msg_len); 132 | client3.client_send_reliable(1, msg_len); 133 | } 134 | // non blocking receive 135 | let receiving = pool.receive(); 136 | 137 | // call this to finish/wait on the receive. 138 | let res = pool.finish_receive(); 139 | 140 | // or alternative call pool.receive_blocking() which doesn't need a finish_receive(). 141 | ``` 142 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | 2 | pub mod tachyon; 3 | -------------------------------------------------------------------------------- /src/tachyon.rs: -------------------------------------------------------------------------------- 1 | pub mod channel; 2 | pub mod connection; 3 | pub mod ffi; 4 | pub mod fragmentation; 5 | pub mod header; 6 | pub mod int_buffer; 7 | pub mod nack; 8 | pub mod network_address; 9 | pub mod pool; 10 | pub mod pool_ffi; 11 | pub mod receive_result; 12 | pub mod receiver; 13 | pub mod send_buffer_manager; 14 | pub mod sequence; 15 | pub mod sequence_buffer; 16 | pub mod tachyon_socket; 17 | pub mod unreliable_sender; 18 | pub mod byte_buffer_pool; 19 | pub mod pool_unreliable_sender; 20 | pub mod memory_block; 21 | 22 | mod connection_impl; 23 | 24 | // additional stress/scale testing 25 | #[cfg(test)] 26 | pub mod tachyon_test; 27 | 28 | use std::time::Duration; 29 | use std::time::Instant; 30 | 31 | use rustc_hash::FxHashMap; 32 | 33 | use self::channel::*; 34 | use self::connection::*; 35 | use self::connection_impl::ConnectionEventCallback; 36 | use self::connection_impl::IDENTITY_LINKED_EVENT; 37 | use self::connection_impl::IDENTITY_UNLINKED_EVENT; 38 | use self::connection_impl::LINK_IDENTITY_EVENT; 39 | use self::connection_impl::IdentityEventCallback; 40 | use self::connection_impl::UNLINK_IDENTITY_EVENT; 41 | use self::fragmentation::*; 42 | use self::header::*; 43 | use self::network_address::NetworkAddress; 44 | use self::pool::SendTarget; 45 | use self::receive_result::ReceiveResult; 46 | use self::receive_result::TachyonReceiveResult; 47 | use self::receive_result::RECEIVE_ERROR_CHANNEL; 48 | use self::receive_result::RECEIVE_ERROR_UNKNOWN; 49 | use self::tachyon_socket::*; 50 | use self::unreliable_sender::UnreliableSender; 51 | 52 | pub const SEND_ERROR_CHANNEL: u32 = 2; 53 | pub const SEND_ERROR_SOCKET: u32 = 1; 54 | pub const SEND_ERROR_FRAGMENT: u32 = 3; 55 | pub const SEND_ERROR_UNKNOWN: u32 = 4; 56 | pub const SEND_ERROR_LENGTH: u32 = 5; 57 | pub const SEND_ERROR_IDENTITY: u32 = 6; 58 | 59 | 60 | const SOCKET_RECEIVE_BUFFER_LEN: usize = 1024 * 1024; 61 | 62 | #[derive(Clone, Copy)] 63 | #[repr(C)] 64 | #[derive(Default, Debug)] 65 | pub struct TachyonStats { 66 | pub channel_stats: ChannelStats, 67 | pub packets_dropped: u64, 68 | pub unreliable_sent: u64, 69 | pub unreliable_received: u64, 70 | } 71 | 72 | impl std::fmt::Display for TachyonStats { 73 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 74 | write!( 75 | f, 76 | "channel_stats:{0} packets_dropped:{1} unreliable_sent:{2} unreliable_received:{3}\n", 77 | self.channel_stats, 78 | self.packets_dropped, 79 | self.unreliable_sent, 80 | self.unreliable_received 81 | ) 82 | } 83 | } 84 | 85 | #[derive(Default, Clone, Copy)] 86 | #[repr(C)] 87 | pub struct TachyonConfig { 88 | pub use_identity: u32, 89 | pub drop_packet_chance: u64, 90 | pub drop_reliable_only: u32 91 | } 92 | 93 | #[derive(Clone, Copy)] 94 | #[repr(C)] 95 | #[derive(Default)] 96 | pub struct TachyonSendResult { 97 | pub sent_len: u32, 98 | pub error: u32, 99 | pub header: Header, 100 | } 101 | 102 | pub struct Tachyon { 103 | pub id: u16, 104 | pub socket: TachyonSocket, 105 | pub socket_receive_buffer: Vec, 106 | pub unreliable_sender: Option, 107 | pub identities: FxHashMap, 108 | pub connections: FxHashMap, 109 | pub identity_to_address_map: FxHashMap, 110 | pub channels: FxHashMap<(NetworkAddress, u8), Channel>, 111 | pub channel_config: FxHashMap, 112 | pub config: TachyonConfig, 113 | pub nack_send_data: Vec, 114 | pub stats: TachyonStats, 115 | pub start_time: Instant, 116 | pub last_identity_link_request: Instant, 117 | pub identity: Identity, 118 | pub identity_event_callback: Option, 119 | pub connection_event_callback: Option 120 | } 121 | 122 | impl Tachyon { 123 | pub fn create(config: TachyonConfig) -> Self { 124 | return Tachyon::create_with_id(config, 0); 125 | } 126 | 127 | pub fn create_with_id(config: TachyonConfig, id: u16) -> Self { 128 | let socket = TachyonSocket::create(); 129 | 130 | let mut tachyon = Tachyon { 131 | id, 132 | identities: FxHashMap::default(), 133 | connections: FxHashMap::default(), 134 | identity_to_address_map: FxHashMap::default(), 135 | channels: FxHashMap::default(), 136 | channel_config: FxHashMap::default(), 137 | socket: socket, 138 | socket_receive_buffer: vec![0;SOCKET_RECEIVE_BUFFER_LEN], 139 | unreliable_sender: None, 140 | config, 141 | nack_send_data: vec![0; 4096], 142 | stats: TachyonStats::default(), 143 | start_time: Instant::now(), 144 | last_identity_link_request: Instant::now() - Duration::new(100, 0), 145 | identity: Identity::default(), 146 | identity_event_callback: None, 147 | connection_event_callback: None 148 | }; 149 | 150 | tachyon.channel_config.insert(1, ChannelConfig::default_ordered()); 151 | tachyon.channel_config.insert(2, ChannelConfig::default_unordered()); 152 | 153 | return tachyon; 154 | } 155 | 156 | 157 | pub fn time_since_start(&self) -> u64 { 158 | return Instant::now().duration_since(self.start_time).as_millis() as u64; 159 | } 160 | 161 | pub fn bind(&mut self, address: NetworkAddress) -> bool { 162 | match self.socket.bind_socket(address) { 163 | CreateConnectResult::Success => { 164 | self.unreliable_sender = self.create_unreliable_sender(); 165 | return true; 166 | } 167 | CreateConnectResult::Error => { 168 | return false; 169 | } 170 | } 171 | } 172 | 173 | pub fn connect(&mut self, address: NetworkAddress) -> bool { 174 | match self.socket.connect_socket(address) { 175 | CreateConnectResult::Success => { 176 | let local_address = NetworkAddress::default(); 177 | self.create_connection(local_address, Identity::default()); 178 | self.unreliable_sender = self.create_unreliable_sender(); 179 | return true; 180 | } 181 | CreateConnectResult::Error => { 182 | return false; 183 | } 184 | } 185 | } 186 | 187 | pub fn create_unreliable_sender(&self) -> Option { 188 | let socket = self.socket.clone_socket(); 189 | if !socket.is_some() { 190 | return None; 191 | } 192 | let sender = UnreliableSender::create(socket); 193 | return Some(sender); 194 | } 195 | 196 | pub fn get_channel(&mut self, address: NetworkAddress, channel_id: u8) -> Option<&mut Channel> { 197 | match self.channels.get_mut(&(address, channel_id)) { 198 | Some(channel) => { 199 | return Some(channel); 200 | } 201 | None => { 202 | return None; 203 | } 204 | } 205 | } 206 | 207 | fn create_configured_channels(&mut self, address: NetworkAddress) { 208 | for (channel_id,config) in &self.channel_config { 209 | match self.channels.get_mut(&(address, *channel_id)) { 210 | Some(_) => {} 211 | None => { 212 | let channel = Channel::create(*channel_id, address, *config); 213 | self.channels.insert((address, *channel_id), channel); 214 | } 215 | } 216 | } 217 | } 218 | 219 | pub fn get_channel_count(&mut self, address: NetworkAddress) -> u32 { 220 | let mut count = 0; 221 | for config in &self.channel_config { 222 | let channel_id = *config.0; 223 | if self.channels.contains_key(&(address, channel_id)) { 224 | count += 1; 225 | } 226 | } 227 | return count; 228 | } 229 | 230 | fn remove_configured_channels(&mut self, address: NetworkAddress) { 231 | for config in &self.channel_config { 232 | let channel_id = *config.0; 233 | self.channels.remove(&(address, channel_id)); 234 | } 235 | } 236 | 237 | pub fn configure_channel(&mut self, channel_id: u8, config: ChannelConfig) -> bool { 238 | if channel_id < 3 { 239 | return false; 240 | } 241 | self.channel_config.insert(channel_id, config); 242 | return true; 243 | } 244 | 245 | pub fn get_combined_stats(&mut self) -> TachyonStats { 246 | let mut channel_stats = ChannelStats::default(); 247 | for channel in self.channels.values_mut() { 248 | channel.update_stats(); 249 | channel_stats.add_from(&channel.stats); 250 | } 251 | let mut stats = self.stats.clone(); 252 | stats.channel_stats = channel_stats; 253 | return stats; 254 | } 255 | 256 | pub fn update(&mut self) { 257 | self.client_identity_update(); 258 | 259 | for channel in self.channels.values_mut() { 260 | channel.update(&self.socket); 261 | } 262 | } 263 | 264 | fn receive_published_channel_id(&mut self, receive_buffer: &mut [u8], address: NetworkAddress, channel_id: u8) -> u32 { 265 | match self.channels.get_mut(&(address, channel_id)) { 266 | Some(channel) => { 267 | let res = channel.receive_published(receive_buffer); 268 | return res.0; 269 | } 270 | None => { 271 | return 0; 272 | } 273 | } 274 | } 275 | 276 | fn receive_published_all_channels(&mut self, receive_buffer: &mut [u8]) -> TachyonReceiveResult { 277 | let mut result = TachyonReceiveResult::default(); 278 | 279 | for channel in self.channels.values_mut() { 280 | let res = channel.receive_published(receive_buffer); 281 | if res.0 > 0 { 282 | result.length = res.0; 283 | result.address = res.1; 284 | result.channel = channel.id as u16; 285 | return result; 286 | } 287 | } 288 | return result; 289 | } 290 | 291 | pub fn receive_loop(&mut self, receive_buffer: &mut [u8]) -> TachyonReceiveResult { 292 | let mut result = TachyonReceiveResult::default(); 293 | 294 | for _ in 0..100 { 295 | let receive_result = self.receive_from_socket(); 296 | match receive_result { 297 | ReceiveResult::Reliable { 298 | network_address: socket_addr, 299 | channel_id, 300 | } => { 301 | let published = self.receive_published_channel_id(receive_buffer, socket_addr, channel_id); 302 | if published > 0 { 303 | result.channel = channel_id as u16; 304 | result.length = published; 305 | result.address = socket_addr; 306 | return result; 307 | } 308 | } 309 | ReceiveResult::UnReliable { 310 | received_len, 311 | network_address: socket_addr, 312 | } => { 313 | receive_buffer[0..received_len-1].copy_from_slice(&self.socket_receive_buffer[1..received_len]); 314 | result.length = (received_len - 1) as u32; 315 | result.address = socket_addr; 316 | return result; 317 | } 318 | ReceiveResult::Empty => { 319 | break; 320 | } 321 | ReceiveResult::Retry => {} 322 | ReceiveResult::Error => { 323 | result.error = RECEIVE_ERROR_UNKNOWN; 324 | return result; 325 | } 326 | ReceiveResult::ChannelError => { 327 | result.error = RECEIVE_ERROR_CHANNEL; 328 | return result; 329 | } 330 | } 331 | } 332 | return self.receive_published_all_channels(receive_buffer); 333 | } 334 | 335 | 336 | fn receive_from_socket(&mut self) -> ReceiveResult { 337 | let address: NetworkAddress; 338 | let received_len: usize; 339 | let header: Header; 340 | 341 | let socket_result = self.socket.receive(&mut self.socket_receive_buffer,self.config.drop_packet_chance,self.config.drop_reliable_only == 1); 342 | match socket_result { 343 | SocketReceiveResult::Success {bytes_received, network_address} => { 344 | received_len = bytes_received; 345 | address = network_address; 346 | 347 | header = Header::read(&self.socket_receive_buffer); 348 | 349 | if self.socket.is_server { 350 | if self.config.use_identity == 1 { 351 | let connection_header: ConnectionHeader; 352 | 353 | if header.message_type == MESSAGE_TYPE_LINK_IDENTITY { 354 | connection_header = ConnectionHeader::read(&self.socket_receive_buffer); 355 | if self.try_link_identity(address, connection_header.id, connection_header.session_id) { 356 | self.fire_identity_event(LINK_IDENTITY_EVENT, address, connection_header.id, connection_header.session_id); 357 | } 358 | return ReceiveResult::Retry; 359 | } else if header.message_type == MESSAGE_TYPE_UNLINK_IDENTITY { 360 | connection_header = ConnectionHeader::read(&self.socket_receive_buffer); 361 | if self.try_unlink_identity(address, connection_header.id, connection_header.session_id) { 362 | self.fire_identity_event(UNLINK_IDENTITY_EVENT, address, connection_header.id, connection_header.session_id); 363 | } 364 | return ReceiveResult::Retry; 365 | } else { 366 | if !self.validate_and_update_linked_connection(address) { 367 | return ReceiveResult::Retry; 368 | } 369 | } 370 | } else { 371 | self.on_receive_connection_update(address); 372 | } 373 | } else { 374 | if self.config.use_identity == 1 { 375 | if header.message_type == MESSAGE_TYPE_IDENTITY_LINKED { 376 | self.identity.set_linked(1); 377 | self.fire_identity_event(IDENTITY_LINKED_EVENT, address, 0, 0); 378 | 379 | return ReceiveResult::Retry; 380 | } else if header.message_type == MESSAGE_TYPE_IDENTITY_UNLINKED { 381 | self.identity.set_linked(0); 382 | self.fire_identity_event(IDENTITY_UNLINKED_EVENT, address, 0, 0); 383 | return ReceiveResult::Retry; 384 | } 385 | 386 | if !self.identity.is_linked() { 387 | return ReceiveResult::Retry; 388 | } 389 | } 390 | } 391 | } 392 | SocketReceiveResult::Empty => { 393 | return ReceiveResult::Empty; 394 | } 395 | SocketReceiveResult::Error => { 396 | return ReceiveResult::Error; 397 | } 398 | SocketReceiveResult::Dropped => { 399 | self.stats.packets_dropped += 1; 400 | return ReceiveResult::Retry; 401 | } 402 | } 403 | 404 | if header.message_type == MESSAGE_TYPE_UNRELIABLE { 405 | self.stats.unreliable_received += 1; 406 | return ReceiveResult::UnReliable { 407 | received_len: received_len, 408 | network_address: address, 409 | }; 410 | } 411 | 412 | let channel = match self.channels.get_mut(&(address, header.channel)) { 413 | Some(c) => c, 414 | None => { 415 | return ReceiveResult::ChannelError; 416 | } 417 | }; 418 | 419 | channel.stats.bytes_received += received_len as u64; 420 | 421 | if header.message_type == MESSAGE_TYPE_NONE { 422 | channel.process_none_message(header.sequence, &mut self.socket_receive_buffer, received_len); 423 | return ReceiveResult::Retry; 424 | } 425 | 426 | if header.message_type == MESSAGE_TYPE_NACK { 427 | channel.process_nack_message(address, &mut self.socket_receive_buffer); 428 | return ReceiveResult::Retry; 429 | } 430 | 431 | if header.message_type == MESSAGE_TYPE_FRAGMENT { 432 | channel.process_fragment_message(header.sequence, &mut self.socket_receive_buffer, received_len); 433 | return ReceiveResult::Retry; 434 | } 435 | 436 | if header.message_type == MESSAGE_TYPE_RELIABLE || header.message_type == MESSAGE_TYPE_RELIABLE_WITH_NACK { 437 | 438 | if header.message_type == MESSAGE_TYPE_RELIABLE_WITH_NACK { 439 | channel.process_single_nack(address, &mut self.socket_receive_buffer); 440 | } 441 | 442 | if channel.receiver.receive_packet(header.sequence, &self.socket_receive_buffer, received_len) { 443 | channel.stats.received += 1; 444 | return ReceiveResult::Reliable { 445 | network_address: address, 446 | channel_id: channel.id, 447 | }; 448 | } else { 449 | return ReceiveResult::Retry; 450 | } 451 | } 452 | 453 | return ReceiveResult::Error; 454 | } 455 | 456 | pub fn send_to_target(&mut self, channel: u8, target: SendTarget, data: &mut [u8], length: usize) -> TachyonSendResult { 457 | let mut address = target.address; 458 | 459 | if target.identity_id > 0 { 460 | if let Some(addr) = self.identity_to_address_map.get(&target.identity_id) { 461 | address = *addr; 462 | } else { 463 | let mut result = TachyonSendResult::default(); 464 | result.error = SEND_ERROR_IDENTITY; 465 | return result; 466 | } 467 | } 468 | 469 | if channel > 0 { 470 | return self.send_reliable(channel,address, data, length as usize); 471 | } else { 472 | return self.send_unreliable(address, data, length as usize); 473 | } 474 | } 475 | 476 | pub fn send_unreliable(&mut self, address: NetworkAddress, data: &mut [u8], body_len: usize) -> TachyonSendResult { 477 | if !self.can_send() { 478 | let mut result = TachyonSendResult::default(); 479 | result.error = SEND_ERROR_IDENTITY; 480 | return result; 481 | } 482 | 483 | match &mut self.unreliable_sender { 484 | Some(sender) => { 485 | let result = sender.send(address, data, body_len); 486 | if result.error == 0 { 487 | self.stats.unreliable_sent += 1; 488 | } 489 | return result; 490 | } 491 | None => { 492 | let mut result = TachyonSendResult::default(); 493 | result.error = SEND_ERROR_UNKNOWN; 494 | return result; 495 | } 496 | } 497 | } 498 | 499 | pub fn send_reliable(&mut self, channel_id: u8, address: NetworkAddress, data: &mut [u8], body_len: usize) -> TachyonSendResult { 500 | let mut result = TachyonSendResult::default(); 501 | 502 | if !self.can_send() { 503 | result.error = SEND_ERROR_IDENTITY; 504 | return result; 505 | } 506 | 507 | if body_len == 0 { 508 | result.error = SEND_ERROR_LENGTH; 509 | return result; 510 | } 511 | 512 | if channel_id == 0 { 513 | result.error = SEND_ERROR_CHANNEL; 514 | return result; 515 | } 516 | 517 | if !self.socket.socket.is_some() { 518 | result.error = SEND_ERROR_SOCKET; 519 | return result; 520 | } 521 | 522 | let channel = match self.channels.get_mut(&(address, channel_id)) { 523 | Some(c) => c, 524 | None => { 525 | result.error = SEND_ERROR_CHANNEL; 526 | return result; 527 | } 528 | }; 529 | 530 | if Fragmentation::should_fragment(body_len) { 531 | let mut fragment_bytes_sent = 0; 532 | let frag_sequences = channel.frag.create_fragments(&mut channel.send_buffers, channel.id, data, body_len); 533 | if frag_sequences.len() == 0 { 534 | result.error = SEND_ERROR_FRAGMENT; 535 | return result; 536 | } 537 | 538 | for seq in frag_sequences { 539 | match channel.send_buffers.get_send_buffer(seq) { 540 | Some(fragment) => { 541 | let sent =self.socket.send_to(address, &fragment.byte_buffer.get(), fragment.byte_buffer.length); 542 | fragment_bytes_sent += sent; 543 | 544 | channel.stats.bytes_sent += sent as u64; 545 | channel.stats.fragments_sent += 1; 546 | } 547 | None => { 548 | result.error = SEND_ERROR_FRAGMENT; 549 | return result; 550 | } 551 | } 552 | } 553 | 554 | result.header.message_type = MESSAGE_TYPE_FRAGMENT; 555 | result.sent_len = fragment_bytes_sent as u32; 556 | 557 | channel.stats.sent += 1; 558 | 559 | return result; 560 | } 561 | 562 | 563 | result = channel.send_reliable(address, data, body_len, &self.socket); 564 | return result; 565 | } 566 | } 567 | 568 | #[cfg(test)] 569 | mod tests { 570 | 571 | use serial_test::serial; 572 | 573 | use crate::tachyon::tachyon_test::TachyonTest; 574 | 575 | use super::*; 576 | 577 | #[test] 578 | #[serial] 579 | fn test_connect_before_bind() { 580 | let address = NetworkAddress::test_address(); 581 | let mut buffer: Vec = vec![0;1024]; 582 | let config = TachyonConfig::default(); 583 | let mut server = Tachyon::create(config); 584 | let mut client = Tachyon::create(config); 585 | 586 | assert!(client.connect(address)); 587 | server.bind(address); 588 | 589 | let target = SendTarget {address: NetworkAddress::default(), identity_id: 0}; 590 | let sent = client.send_to_target(1, target, &mut buffer, 32); 591 | assert_eq!(0, sent.error); 592 | 593 | let res = server.receive_loop(&mut buffer); 594 | assert_eq!(32, res.length); 595 | } 596 | 597 | #[test] 598 | #[serial] 599 | fn test_server_receive_invalid_without_bind() { 600 | let mut buffer: Vec = vec![0;1024]; 601 | let config = TachyonConfig::default(); 602 | let mut server = Tachyon::create(config); 603 | let res = server.receive_loop(&mut buffer); 604 | assert_eq!(RECEIVE_ERROR_UNKNOWN, res.error); 605 | } 606 | 607 | #[test] 608 | #[serial] 609 | fn test_reliable() { 610 | // reliable messages just work with message bodies, headers are all internal 611 | 612 | let mut test = TachyonTest::default(); 613 | test.connect(); 614 | 615 | test.send_buffer[0] = 4; 616 | let sent = test.client_send_reliable(1, 2); 617 | // sent_len reports total including header. 618 | assert_eq!(2 + TACHYON_HEADER_SIZE, sent.sent_len as usize); 619 | 620 | let res = test.server_receive(); 621 | assert_eq!(2, res.length); 622 | assert_eq!(4, test.receive_buffer[0]); 623 | 624 | test.client_send_reliable(2, 33); 625 | let res = test.server_receive(); 626 | assert_eq!(33, res.length); 627 | 628 | // fragmented 629 | test.client_send_reliable(2, 3497); 630 | let res = test.server_receive(); 631 | assert_eq!(3497, res.length); 632 | } 633 | 634 | #[test] 635 | #[serial] 636 | fn test_unconfigured_channel_fails() { 637 | let mut test = TachyonTest::default(); 638 | let channel_config = ChannelConfig::default_ordered(); 639 | test.client.configure_channel(3, channel_config); 640 | test.connect(); 641 | 642 | let sent = test.client_send_reliable(3, 2); 643 | assert_eq!(2 + TACHYON_HEADER_SIZE, sent.sent_len as usize); 644 | assert_eq!(0, sent.error); 645 | 646 | let res = test.server_receive(); 647 | assert_eq!(0, res.length); 648 | assert_eq!(RECEIVE_ERROR_CHANNEL, res.error); 649 | } 650 | 651 | #[test] 652 | #[serial] 653 | fn test_configured_channel() { 654 | let mut test = TachyonTest::default(); 655 | let channel_config = ChannelConfig::default_ordered(); 656 | test.client.configure_channel(3, channel_config); 657 | test.server.configure_channel(3, channel_config); 658 | test.connect(); 659 | 660 | let sent = test.client_send_reliable(3, 2); 661 | assert_eq!(2 + TACHYON_HEADER_SIZE, sent.sent_len as usize); 662 | assert_eq!(0, sent.error); 663 | 664 | let res = test.server_receive(); 665 | assert_eq!(2, res.length); 666 | assert_eq!(0, res.error); 667 | } 668 | 669 | #[test] 670 | #[serial] 671 | fn test_unreliable() { 672 | let mut test = TachyonTest::default(); 673 | test.connect(); 674 | 675 | // unreliable messages need to be body length + 1; 676 | // send length error 677 | let send = test.client_send_unreliable(0); 678 | assert_eq!(SEND_ERROR_LENGTH, send.error); 679 | 680 | let res = test.server_receive(); 681 | assert_eq!(0, res.length); 682 | 683 | test.receive_buffer[0] = 1; 684 | test.send_buffer[0] = 3; 685 | test.send_buffer[1] = 4; 686 | test.send_buffer[2] = 5; 687 | test.send_buffer[3] = 6; 688 | let sent = test.client_send_unreliable(4); 689 | assert_eq!(0, sent.error); 690 | assert_eq!(5, sent.sent_len as usize); 691 | 692 | let res = test.server_receive(); 693 | assert_eq!(4, res.length); 694 | assert_eq!(3, test.receive_buffer[0]); 695 | assert_eq!(4, test.receive_buffer[1]); 696 | assert_eq!(5, test.receive_buffer[2]); 697 | assert_eq!(6, test.receive_buffer[3]); 698 | } 699 | } 700 | -------------------------------------------------------------------------------- /src/tachyon/byte_buffer_pool.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | 3 | pub const BYTE_BUFFER_SIZE_DEFAULT: usize = 1240; 4 | const POOL_SIZE_DEFAULT: usize = 512; 5 | 6 | 7 | pub struct ByteBuffer { 8 | data: Vec, 9 | pub length: usize, 10 | pub pooled: bool, 11 | pub version: u64 12 | } 13 | 14 | impl ByteBuffer { 15 | pub fn create(length: usize) -> Self { 16 | let byte_buffer = ByteBuffer { 17 | data: vec![0;length], 18 | length: length, 19 | pooled: false, 20 | version: 0 21 | }; 22 | return byte_buffer; 23 | } 24 | 25 | pub fn get(&self) -> &[u8] { 26 | return &self.data; 27 | } 28 | 29 | pub fn get_mut(&mut self) -> &mut [u8] { 30 | return &mut self.data; 31 | } 32 | } 33 | 34 | impl std::ops::Index for ByteBuffer 35 | where 36 | Idx: std::slice::SliceIndex<[u8]>, 37 | { 38 | type Output = Idx::Output; 39 | 40 | fn index(&self, index: Idx) -> &Self::Output { 41 | &self.data[index] 42 | } 43 | } 44 | 45 | impl std::ops::IndexMut for ByteBuffer 46 | where 47 | Idx: std::slice::SliceIndex<[u8]> 48 | { 49 | fn index_mut(&mut self, index: Idx) -> &mut Self::Output { 50 | &mut self.data[index] 51 | } 52 | } 53 | 54 | pub struct ByteBufferPool { 55 | pub buffer_size: usize, 56 | pool_size: usize, 57 | buffers: VecDeque, 58 | count: usize 59 | } 60 | 61 | impl ByteBufferPool { 62 | 63 | pub fn default() -> Self { 64 | let pool = ByteBufferPool::create(BYTE_BUFFER_SIZE_DEFAULT, POOL_SIZE_DEFAULT); 65 | return pool; 66 | } 67 | 68 | pub fn create(buffer_size: usize, max_buffers: usize) -> Self { 69 | let pool = ByteBufferPool { 70 | buffer_size, 71 | pool_size: max_buffers, 72 | buffers: VecDeque::new(), 73 | count: 0 74 | }; 75 | return pool; 76 | } 77 | 78 | pub fn len(&self) -> usize { 79 | return self.buffers.len(); 80 | } 81 | 82 | pub fn return_buffer(&mut self, mut byte_buffer: ByteBuffer) -> bool { 83 | if byte_buffer.length <= self.buffer_size { 84 | if self.count < self.pool_size { 85 | byte_buffer.version += 1; 86 | self.buffers.push_back(byte_buffer); 87 | self.count += 1; 88 | return true; 89 | } 90 | } 91 | return false; 92 | } 93 | 94 | pub fn get_buffer(&mut self, length: usize) -> ByteBuffer { 95 | if length > self.buffer_size { 96 | let buffer = ByteBuffer { 97 | data: vec![0; length], 98 | length: length, 99 | pooled: false, 100 | version: 0 101 | }; 102 | return buffer; 103 | } 104 | 105 | match self.buffers.pop_front() { 106 | Some(mut pooled) => { 107 | self.count -= 1; 108 | //pooled.data[0..length].fill(0); 109 | pooled.length = length; 110 | return pooled; 111 | }, 112 | None => { 113 | let data: Vec = vec![0; self.buffer_size]; 114 | let buffer = ByteBuffer { 115 | data, 116 | length: length, 117 | pooled: true, 118 | version: 0 119 | }; 120 | return buffer; 121 | }, 122 | } 123 | } 124 | } 125 | 126 | 127 | #[cfg(test)] 128 | mod tests { 129 | 130 | use crate::tachyon::byte_buffer_pool::{ByteBuffer, POOL_SIZE_DEFAULT, BYTE_BUFFER_SIZE_DEFAULT}; 131 | 132 | use super::ByteBufferPool; 133 | 134 | #[test] 135 | fn get_return_within_limits() { 136 | let mut pool = ByteBufferPool::default(); 137 | 138 | let buffer = pool.get_buffer(BYTE_BUFFER_SIZE_DEFAULT); 139 | assert!(pool.return_buffer(buffer)); 140 | assert_eq!(1, pool.len()); 141 | } 142 | 143 | #[test] 144 | fn get_allocates_over_max() { 145 | let mut pool = ByteBufferPool::default(); 146 | 147 | let buffer = pool.get_buffer(BYTE_BUFFER_SIZE_DEFAULT); 148 | pool.return_buffer(buffer); 149 | pool.get_buffer(BYTE_BUFFER_SIZE_DEFAULT + 1); 150 | assert_eq!(1, pool.len()); 151 | } 152 | 153 | #[test] 154 | fn will_not_return_over_max_buffer_size() { 155 | let mut pool = ByteBufferPool::default(); 156 | 157 | let buffer = pool.get_buffer(BYTE_BUFFER_SIZE_DEFAULT + 1); 158 | assert!(!pool.return_buffer(buffer)); 159 | assert_eq!(0, pool.len()); 160 | } 161 | 162 | #[test] 163 | fn will_not_return_if_full() { 164 | let mut pool = ByteBufferPool::default(); 165 | 166 | for _ in 0..POOL_SIZE_DEFAULT { 167 | let buffer = ByteBuffer::create(1024); 168 | assert!(pool.return_buffer(buffer)); 169 | } 170 | 171 | let buffer = ByteBuffer::create(1024); 172 | assert!(!pool.return_buffer(buffer)); 173 | } 174 | 175 | 176 | } 177 | -------------------------------------------------------------------------------- /src/tachyon/channel.rs: -------------------------------------------------------------------------------- 1 | 2 | use rustc_hash::{FxHashMap}; 3 | 4 | use super::{ 5 | fragmentation::Fragmentation, 6 | header::{ 7 | Header, MESSAGE_TYPE_FRAGMENT, MESSAGE_TYPE_NONE, MESSAGE_TYPE_NACK, 8 | TACHYON_FRAGMENTED_HEADER_SIZE, TACHYON_HEADER_SIZE, MESSAGE_TYPE_RELIABLE_WITH_NACK, MESSAGE_TYPE_RELIABLE, TACHYON_NACKED_HEADER_SIZE 9 | }, 10 | int_buffer::IntBuffer, 11 | nack::Nack, 12 | network_address::NetworkAddress, 13 | receiver::Receiver, 14 | send_buffer_manager::SendBufferManager, 15 | tachyon_socket::TachyonSocket, SEND_ERROR_UNKNOWN, TachyonSendResult 16 | }; 17 | 18 | pub static mut NONE_SEND_DATA: &'static mut [u8] = &mut [0; TACHYON_HEADER_SIZE]; 19 | const NACK_REDUNDANCY_DEFAULT: u32 = 1; 20 | pub const RECEIVE_WINDOW_SIZE_DEFAULT: u32 = 512; 21 | 22 | #[derive(Clone, Copy)] 23 | #[repr(C)] 24 | #[derive(Default, Debug)] 25 | pub struct ChannelStats { 26 | pub sent: u64, 27 | pub received: u64, 28 | pub bytes_sent: u64, 29 | pub bytes_received: u64, 30 | pub fragments_sent: u64, 31 | pub fragments_received: u64, 32 | pub fragments_assembled: u64, 33 | pub published: u64, 34 | pub published_consumed: u64, 35 | pub nacks_sent: u64, 36 | pub nacks_received: u64, 37 | pub resent: u64, 38 | pub nones_sent: u64, 39 | pub nones_received: u64, 40 | pub nones_accepted: u64, 41 | pub skipped_sequences: u64, 42 | } 43 | 44 | impl ChannelStats { 45 | pub fn add_from(&mut self, other: &ChannelStats) { 46 | self.sent += other.sent; 47 | self.received += other.received; 48 | self.bytes_sent += other.bytes_sent; 49 | self.bytes_received += other.bytes_received; 50 | self.fragments_sent += other.fragments_sent; 51 | self.fragments_received += other.fragments_received; 52 | self.fragments_assembled += other.fragments_assembled; 53 | self.published += other.published; 54 | self.published_consumed += other.published_consumed; 55 | self.nacks_sent += other.nacks_sent; 56 | self.nacks_received += other.nacks_received; 57 | self.resent += other.resent; 58 | self.nones_sent += other.nones_sent; 59 | self.nones_received += other.nones_received; 60 | self.nones_accepted += other.nones_accepted; 61 | self.skipped_sequences += other.skipped_sequences; 62 | } 63 | } 64 | 65 | impl std::fmt::Display for ChannelStats { 66 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 67 | write!( 68 | f, 69 | "sent:{} received:{},kb_sent:{} kb_received:{} 70 | fragments_sent:{} fragments_received:{} fragments_assembled:{}, 71 | published: {} published_consumed:{} nacks_sent:{} nacks_received:{} resent:{} 72 | nones_sent:{} nones_received:{} nones_accepted:{} skipped_sequences:{}\n\n", 73 | self.sent, 74 | self.received, 75 | self.bytes_sent / 1024, 76 | self.bytes_received / 1024, 77 | self.fragments_sent, 78 | self.fragments_received, 79 | self.fragments_assembled, 80 | self.published, 81 | self.published_consumed, 82 | self.nacks_sent, 83 | self.nacks_received, 84 | self.resent, 85 | self.nones_sent, 86 | self.nones_received, 87 | self.nones_accepted, 88 | self.skipped_sequences 89 | ) 90 | } 91 | } 92 | 93 | #[derive(Clone, Copy)] 94 | #[repr(C)] 95 | #[derive(Default)] 96 | pub struct ChannelConfig { 97 | pub receive_window_size: u32, 98 | pub nack_redundancy: u32, 99 | pub ordered: u32 100 | } 101 | 102 | impl ChannelConfig { 103 | 104 | pub fn default_ordered() -> Self { 105 | let config = ChannelConfig { 106 | ordered: 1, 107 | receive_window_size: RECEIVE_WINDOW_SIZE_DEFAULT, 108 | nack_redundancy: NACK_REDUNDANCY_DEFAULT 109 | }; 110 | return config; 111 | } 112 | 113 | pub fn default_unordered() -> Self { 114 | let config = ChannelConfig { 115 | ordered: 0, 116 | receive_window_size: RECEIVE_WINDOW_SIZE_DEFAULT, 117 | nack_redundancy: NACK_REDUNDANCY_DEFAULT 118 | }; 119 | return config; 120 | } 121 | 122 | pub fn is_ordered(&self) -> bool { 123 | return self.ordered == 1; 124 | } 125 | } 126 | 127 | pub struct Channel { 128 | pub id: u8, 129 | pub address: NetworkAddress, 130 | pub frag: Fragmentation, 131 | pub send_buffers: SendBufferManager, 132 | pub receiver: Receiver, 133 | pub stats: ChannelStats, 134 | nack_send_data: Vec, 135 | nacked_sequences: Vec, 136 | nacked_sequence_map: FxHashMap, 137 | pub resend_rewrite_buffer: Vec, 138 | pub nack_redundancy: u32 139 | } 140 | 141 | impl Channel { 142 | pub fn create(id: u8, address: NetworkAddress, config: ChannelConfig) -> Self { 143 | let channel = Channel { 144 | id, 145 | address, 146 | frag: Fragmentation::default(), 147 | send_buffers: SendBufferManager::default(), 148 | receiver: Receiver::create(config.is_ordered(), config.receive_window_size), 149 | stats: ChannelStats::default(), 150 | nack_send_data: vec![0; 512], 151 | nacked_sequences: Vec::new(), 152 | nacked_sequence_map: FxHashMap::default(), 153 | resend_rewrite_buffer: vec![0;2048], 154 | nack_redundancy: config.nack_redundancy 155 | }; 156 | return channel; 157 | } 158 | 159 | fn create_none(sequence: u16, channel_id: u8) { 160 | let mut header = Header::default(); 161 | header.message_type = MESSAGE_TYPE_NONE; 162 | header.sequence = sequence; 163 | header.channel = channel_id; 164 | header.write(unsafe { &mut NONE_SEND_DATA }); 165 | } 166 | 167 | pub fn is_ordered(&self) -> bool { 168 | return self.receiver.is_ordered; 169 | } 170 | 171 | pub fn update_stats(&mut self) { 172 | self.stats.skipped_sequences = self.receiver.skipped_sequences; 173 | } 174 | 175 | pub fn receive_published(&mut self, receive_buffer: &mut [u8]) -> (u32, NetworkAddress) { 176 | for _ in 0..1000 { 177 | let res = self.receive_published_internal(receive_buffer); 178 | if res.0 > 0 { 179 | return (res.0, res.1); 180 | } 181 | if !res.2 { 182 | break; 183 | } 184 | } 185 | 186 | return (0,self.address); 187 | } 188 | 189 | // returns message length, address, should retry (queue not empty) 190 | fn receive_published_internal(&mut self, receive_buffer: &mut [u8]) -> (u32, NetworkAddress, bool) { 191 | match self.receiver.take_published() { 192 | Some(byte_buffer) => { 193 | let buffer_len = byte_buffer.length; 194 | 195 | let mut reader = IntBuffer { index: 0 }; 196 | let message_type = reader.read_u8(&byte_buffer.get()); 197 | 198 | if message_type == MESSAGE_TYPE_NONE { 199 | self.receiver.return_buffer(byte_buffer); 200 | return (0, self.address, true); 201 | } 202 | 203 | if message_type == MESSAGE_TYPE_FRAGMENT { 204 | let header = Header::read_fragmented(&byte_buffer.get()); 205 | match self.frag.assemble(header) { 206 | Ok(res) => { 207 | let assembled_len = res.len(); 208 | receive_buffer[0..assembled_len].copy_from_slice(&res[..]); 209 | self.stats.received += 1; 210 | self.stats.fragments_assembled += header.fragment_count as u64; 211 | self.stats.published_consumed += 1; 212 | return (assembled_len as u32, self.address, true); 213 | } 214 | Err(_) => { 215 | self.receiver.return_buffer(byte_buffer); 216 | return (0, self.address, true); 217 | } 218 | } 219 | } 220 | 221 | let header_size: usize; 222 | if message_type == MESSAGE_TYPE_RELIABLE_WITH_NACK { 223 | header_size = TACHYON_NACKED_HEADER_SIZE; 224 | } else if message_type == MESSAGE_TYPE_RELIABLE { 225 | header_size = TACHYON_HEADER_SIZE; 226 | } else { 227 | // should not be possible 228 | return (0, self.address, true); 229 | } 230 | 231 | receive_buffer[0..buffer_len - header_size].copy_from_slice(&byte_buffer.get()[header_size..buffer_len]); 232 | self.receiver.return_buffer(byte_buffer); 233 | 234 | self.stats.published_consumed += 1; 235 | return ((buffer_len - header_size) as u32, self.address, true); 236 | } 237 | None => { 238 | return (0, self.address, false); 239 | } 240 | } 241 | 242 | } 243 | 244 | pub fn process_none_message(&mut self, sequence: u16, receive_buffer: &mut [u8], received_len: usize) { 245 | self.stats.nones_received += 1; 246 | if self.receiver.receive_packet(sequence, receive_buffer, received_len) 247 | { 248 | self.stats.nones_accepted += 1; 249 | } 250 | } 251 | 252 | pub fn process_fragment_message(&mut self, sequence: u16, receive_buffer: &mut [u8], received_len: usize) { 253 | let received_frag_res = self.frag.receive_fragment(receive_buffer, received_len); 254 | if received_frag_res.0 { 255 | if self.receiver.receive_packet(sequence,receive_buffer,TACHYON_FRAGMENTED_HEADER_SIZE) { 256 | self.stats.fragments_received += 1; 257 | } 258 | } 259 | } 260 | 261 | // separate nack message, varint encoded 262 | pub fn process_nack_message(&mut self, address: NetworkAddress, receive_buffer: &mut [u8]) { 263 | self.nacked_sequences.clear(); 264 | Nack::read_varint(&mut self.nacked_sequences, &receive_buffer[..],TACHYON_HEADER_SIZE); 265 | self.copy_nacked_to_map(address); 266 | } 267 | 268 | // nack that is in a reliable message 269 | pub fn process_single_nack(&mut self, address: NetworkAddress, receive_buffer: &mut [u8]) { 270 | self.nacked_sequences.clear(); 271 | Nack::read_single(&mut self.nacked_sequences, &receive_buffer[..],TACHYON_HEADER_SIZE); 272 | self.copy_nacked_to_map(address); 273 | } 274 | 275 | 276 | pub fn send_reliable(&mut self, address: NetworkAddress, data: &mut [u8], body_len: usize, socket: &TachyonSocket) -> TachyonSendResult { 277 | let mut result = TachyonSendResult::default(); 278 | 279 | // Optionally include nacks in outgoing messages, up to nack_redundancy times for each nack 280 | let mut nack_option: Option = None; 281 | let mut header_len = TACHYON_HEADER_SIZE; 282 | 283 | if self.nack_redundancy > 0 { 284 | if let Some(mut nack) = self.receiver.nack_queue.pop_front() { 285 | if nack.sent_count < self.nack_redundancy { 286 | nack.sent_count += 1; 287 | nack_option = Some(nack); 288 | header_len = TACHYON_NACKED_HEADER_SIZE; 289 | } 290 | self.receiver.nack_queue.push_back(nack); 291 | } 292 | } 293 | 294 | let send_buffer_len = body_len + header_len; 295 | 296 | match self.send_buffers.create_send_buffer(send_buffer_len) { 297 | Some(send_buffer) => { 298 | let sequence = send_buffer.sequence; 299 | send_buffer.byte_buffer.get_mut()[header_len..body_len + header_len].copy_from_slice(&data[0..body_len]); 300 | 301 | let mut header = Header::default(); 302 | header.channel = self.id; 303 | header.sequence = sequence; 304 | 305 | if let Some(nack) = nack_option { 306 | header.message_type = MESSAGE_TYPE_RELIABLE_WITH_NACK; 307 | header.start_sequence = nack.start_sequence; 308 | header.flags = nack.flags; 309 | 310 | self.stats.nacks_sent += nack.nacked_count as u64; 311 | } else { 312 | header.message_type = MESSAGE_TYPE_RELIABLE; 313 | } 314 | 315 | header.write(&mut send_buffer.byte_buffer.get_mut()); 316 | 317 | let sent_len = socket.send_to(address, &send_buffer.byte_buffer.get(), send_buffer_len); 318 | result.sent_len = sent_len as u32; 319 | result.header = header; 320 | 321 | self.stats.bytes_sent += sent_len as u64; 322 | self.stats.sent += 1; 323 | 324 | return result; 325 | } 326 | None => { 327 | result.error = SEND_ERROR_UNKNOWN; 328 | return result; 329 | } 330 | } 331 | } 332 | 333 | pub fn update(&mut self,socket: &TachyonSocket) { 334 | self.send_nacks(socket); 335 | self.resend_nacked(socket); 336 | 337 | // this takes way too long if there are a lot of frag groups, disabling until I find a better solution 338 | //self.frag.expire_groups(); 339 | 340 | self.receiver.publish(); 341 | } 342 | 343 | fn copy_nacked_to_map(&mut self, address: NetworkAddress) { 344 | for sequence in &self.nacked_sequences { 345 | self.nacked_sequence_map.insert(*sequence, address); 346 | } 347 | } 348 | 349 | 350 | // Resend messages for nacks sent to us. We accumulate these into a hashmap of unique sequence/address pairs 351 | // and then do the resends all at once when update() is run. 352 | fn resend_nacked(&mut self, socket: &TachyonSocket) { 353 | 354 | if self.nacked_sequence_map.len() == 0 { 355 | return; 356 | } 357 | 358 | for (sequence, address) in &self.nacked_sequence_map { 359 | self.stats.nacks_received += 1; 360 | match self.send_buffers.get_send_buffer(*sequence) { 361 | Some(send_buffer) => { 362 | 363 | let mut reader = IntBuffer { index: 0 }; 364 | 365 | let message_type = reader.read_u8(&send_buffer.byte_buffer.get()); 366 | 367 | // rewrite to MESSAGE_TYPE_RELIABLE. 368 | if message_type == MESSAGE_TYPE_RELIABLE_WITH_NACK { 369 | let send_len = Channel::rewrite_reliable_nack_to_reliable(&mut self.resend_rewrite_buffer,&send_buffer.byte_buffer.get()); 370 | 371 | socket.send_to(*address, &self.resend_rewrite_buffer, send_len); 372 | } else { 373 | socket.send_to(*address, &send_buffer.byte_buffer.get(), send_buffer.byte_buffer.length); 374 | } 375 | 376 | self.stats.resent += 1; 377 | } 378 | None => { 379 | Channel::create_none(*sequence, self.id); 380 | let _sent_len = socket.send_to(*address,unsafe { &NONE_SEND_DATA },TACHYON_HEADER_SIZE); 381 | self.stats.nones_sent += 1; 382 | } 383 | } 384 | } 385 | self.nacked_sequence_map.clear(); 386 | } 387 | 388 | // Send nacks for sequences we are missing 389 | fn send_nacks(&mut self, socket: &TachyonSocket) { 390 | 391 | let nack_count = self.receiver.create_nacks(); 392 | if self.receiver.nack_list.len() == 0 { 393 | return; 394 | } 395 | 396 | let mut header = Header::default(); 397 | header.message_type = MESSAGE_TYPE_NACK; 398 | header.channel = self.id; 399 | header.write(&mut self.nack_send_data); 400 | 401 | let position = Nack::write_varint(&self.receiver.nack_list, &mut self.nack_send_data, TACHYON_HEADER_SIZE as u64); 402 | socket.send_to(self.address, &self.nack_send_data, position as usize); 403 | 404 | self.stats.nacks_sent += nack_count as u64; 405 | } 406 | 407 | pub fn rewrite_reliable_nack_to_reliable(rewrite_buffer: &mut [u8], send_buffer: &[u8]) -> usize { 408 | let mut header = Header::read(send_buffer); 409 | let src_body = TACHYON_NACKED_HEADER_SIZE..send_buffer.len(); 410 | let src_body_len = src_body.len(); 411 | let dest = TACHYON_HEADER_SIZE..(TACHYON_HEADER_SIZE + src_body_len); 412 | rewrite_buffer[dest].copy_from_slice(&send_buffer[src_body]); 413 | 414 | header.message_type = MESSAGE_TYPE_RELIABLE; 415 | header.write(rewrite_buffer); 416 | 417 | return TACHYON_HEADER_SIZE + src_body_len; 418 | } 419 | } 420 | 421 | 422 | #[cfg(test)] 423 | mod tests { 424 | 425 | use crate::tachyon::{header::{Header, MESSAGE_TYPE_RELIABLE_WITH_NACK, MESSAGE_TYPE_RELIABLE}, network_address::NetworkAddress, channel::ChannelConfig}; 426 | 427 | use super::Channel; 428 | 429 | 430 | #[test] 431 | fn test_rewrite_nack_to_reliable() { 432 | 433 | let mut channel = Channel::create(1, NetworkAddress::default(), ChannelConfig::default_ordered()); 434 | let mut send_buffer: Vec = vec![0;1200]; 435 | let mut header = Header::default(); 436 | header.message_type = MESSAGE_TYPE_RELIABLE_WITH_NACK; 437 | header.channel = 13; 438 | header.sequence = 200; 439 | header.start_sequence = 12345; 440 | header.flags = 99; 441 | header.write(&mut send_buffer); 442 | send_buffer[10] = 3; 443 | send_buffer[1199] = 7; 444 | let send_len = Channel::rewrite_reliable_nack_to_reliable(&mut channel.resend_rewrite_buffer,&send_buffer); 445 | assert_eq!(1200 - 6, send_len); 446 | assert_eq!(3, channel.resend_rewrite_buffer[4]); 447 | assert_eq!(7, channel.resend_rewrite_buffer[1199 - 6]); 448 | 449 | let header = Header::read(&mut channel.resend_rewrite_buffer); 450 | assert_eq!(MESSAGE_TYPE_RELIABLE, header.message_type); 451 | assert_eq!(200, header.sequence); 452 | assert_eq!(13, header.channel); 453 | 454 | assert_eq!(0, header.start_sequence); 455 | assert_eq!(0, header.flags); 456 | 457 | } 458 | 459 | } 460 | 461 | -------------------------------------------------------------------------------- /src/tachyon/connection.rs: -------------------------------------------------------------------------------- 1 | use super::network_address::NetworkAddress; 2 | 3 | #[derive(Clone, Copy)] 4 | #[repr(C)] 5 | pub struct Connection { 6 | pub address: NetworkAddress, 7 | pub identity: Identity, 8 | pub tachyon_id: u16, 9 | pub received_at: u64, 10 | pub since_last_received: u64, 11 | } 12 | 13 | impl Connection { 14 | pub fn create(address: NetworkAddress, tachyon_id: u16) -> Self { 15 | let conn = Connection { 16 | identity: Identity::default(), 17 | address: address, 18 | tachyon_id, 19 | received_at: 0, 20 | since_last_received: 0, 21 | }; 22 | return conn; 23 | } 24 | } 25 | 26 | #[derive(Clone, Copy)] 27 | #[repr(C)] 28 | #[derive(Default)] 29 | pub struct Identity { 30 | pub id: u32, 31 | pub session_id: u32, 32 | pub linked: u32, 33 | } 34 | 35 | impl Identity { 36 | pub fn is_valid(&self) -> bool { 37 | return self.id > 0 && self.session_id > 0; 38 | } 39 | 40 | pub fn is_linked(&self) -> bool { 41 | return self.is_valid() && self.linked == 1; 42 | } 43 | 44 | pub fn set_linked(&mut self, linked: u32) { 45 | self.linked = linked; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/tachyon/connection_impl.rs: -------------------------------------------------------------------------------- 1 | use std::time::Instant; 2 | 3 | use super::connection::{Connection, Identity}; 4 | use super::header::{ 5 | ConnectionHeader, MESSAGE_TYPE_IDENTITY_LINKED, MESSAGE_TYPE_IDENTITY_UNLINKED, 6 | MESSAGE_TYPE_LINK_IDENTITY, MESSAGE_TYPE_UNLINK_IDENTITY, 7 | }; 8 | use super::network_address::NetworkAddress; 9 | use super::Tachyon; 10 | 11 | const IDENTITY_SEND_INTERVAL: u128 = 300; 12 | 13 | pub const CONNECTION_ADDED_EVENT: u8 = 1; 14 | pub const CONNECTION_REMOVED_EVENT: u8 = 2; 15 | 16 | pub const LINK_IDENTITY_EVENT: u8 = 1; 17 | pub const UNLINK_IDENTITY_EVENT: u8 = 2; 18 | pub const IDENTITY_LINKED_EVENT: u8 = 3; 19 | pub const IDENTITY_UNLINKED_EVENT: u8 = 4; 20 | 21 | pub type ConnectionEventCallback = unsafe extern "C" fn(action: u8, connection: Connection); 22 | pub type IdentityEventCallback = unsafe extern "C" fn(action: u8, connection: Connection); 23 | 24 | impl Tachyon { 25 | // setting identity removes any associated connection 26 | pub fn set_identity(&mut self, id: u32, session_id: u32) { 27 | self.remove_connection_by_identity(id); 28 | 29 | if session_id == 0 { 30 | self.identities.remove(&id); 31 | } else { 32 | self.identities.insert(id, session_id); 33 | } 34 | } 35 | 36 | pub fn create_connection(&mut self, address: NetworkAddress, identity: Identity) { 37 | let mut conn = Connection::create(address, self.id); 38 | conn.identity = identity; 39 | conn.received_at = self.time_since_start(); 40 | self.connections.insert(address, conn); 41 | self.create_configured_channels(address); 42 | self.fire_connection_event(CONNECTION_ADDED_EVENT, address); 43 | } 44 | 45 | fn remove_connection(&mut self, address: NetworkAddress) { 46 | self.connections.remove(&address); 47 | self.remove_configured_channels(address); 48 | self.fire_connection_event(CONNECTION_REMOVED_EVENT, address); 49 | } 50 | 51 | pub fn get_connection(&self, address: NetworkAddress) -> Option<&Connection> { 52 | return self.connections.get(&address); 53 | } 54 | 55 | pub fn get_connection_by_identity(&self, id: u32) -> Option<&Connection> { 56 | if let Some(address) = self.identity_to_address_map.get(&id) { 57 | return self.get_connection(*address); 58 | } 59 | return None; 60 | } 61 | 62 | pub fn get_connections(&mut self, max: i32) -> Vec { 63 | let mut list: Vec = Vec::new(); 64 | let result_count = std::cmp::min(self.connections.len(), max as usize); 65 | 66 | let mut count = 0; 67 | let since_start = self.time_since_start(); 68 | for conn in self.connections.values_mut() { 69 | conn.since_last_received = since_start - conn.received_at; 70 | list.push(*conn); 71 | count += 1; 72 | if count >= result_count { 73 | break; 74 | } 75 | } 76 | return list; 77 | } 78 | 79 | pub fn fire_identity_event(&self, event_id: u8, address: NetworkAddress, id: u32, session_id: u32) { 80 | if let Some(callback) = self.identity_event_callback { 81 | let mut conn = Connection::create(address, self.id); 82 | conn.identity = Identity {id, session_id, linked: 0 }; 83 | if event_id == IDENTITY_LINKED_EVENT { 84 | conn.identity.linked = 1; 85 | } 86 | unsafe { 87 | callback(event_id, conn); 88 | } 89 | } 90 | } 91 | 92 | pub fn fire_connection_event(&self, event_id: u8, address: NetworkAddress) { 93 | if let Some(callback) = self.connection_event_callback { 94 | let conn = Connection::create(address, self.id); 95 | unsafe { 96 | callback(event_id, conn); 97 | } 98 | } 99 | } 100 | 101 | // run when use_identity is not set 102 | pub fn on_receive_connection_update(&mut self, address: NetworkAddress) { 103 | let since_start = self.time_since_start(); 104 | if let Some(conn) = self.connections.get_mut(&address) { 105 | conn.received_at = since_start; 106 | } else { 107 | self.create_connection(address, Identity::default()); 108 | } 109 | } 110 | 111 | pub fn validate_and_update_linked_connection(&mut self, address: NetworkAddress) -> bool { 112 | let since_start = self.time_since_start(); 113 | if let Some(conn) = self.connections.get_mut(&address) { 114 | if conn.identity.id == 0 { 115 | return false; 116 | } 117 | conn.received_at = since_start; 118 | return true; 119 | } 120 | return false; 121 | } 122 | 123 | pub fn get_connection_identity(&self, address: NetworkAddress) -> Identity { 124 | if let Some(conn) = self.connections.get(&address) { 125 | return conn.identity; 126 | } else { 127 | return Identity::default(); 128 | } 129 | } 130 | 131 | 132 | 133 | pub fn remove_connection_by_identity(&mut self, id: u32) { 134 | let mut addresses: Vec = Vec::new(); 135 | 136 | for conn in self.connections.values_mut() { 137 | if conn.identity.id == id { 138 | addresses.push(conn.address); 139 | } 140 | } 141 | for addr in addresses { 142 | self.remove_connection(addr); 143 | } 144 | } 145 | 146 | 147 | 148 | pub fn try_link_identity(&mut self, address: NetworkAddress, id: u32, session_id: u32) -> bool { 149 | if let Some(current_session_id) = self.identities.get(&id) { 150 | if session_id != *current_session_id { 151 | return false; 152 | } 153 | 154 | let identity = self.get_connection_identity(address); 155 | if identity.id == id && identity.session_id == *current_session_id { 156 | return true; 157 | } 158 | 159 | self.remove_connection_by_identity(id); 160 | let identity = Identity { 161 | id: id, 162 | session_id: session_id, 163 | linked: 0, 164 | }; 165 | self.create_connection(address, identity); 166 | self.identity_to_address_map.insert(id, address); 167 | self.send_identity_linked(address); 168 | return true; 169 | } 170 | return false; 171 | } 172 | 173 | pub fn try_unlink_identity(&mut self, address: NetworkAddress, id: u32, session_id: u32) -> bool { 174 | if let Some(current_session_id) = self.identities.get(&id) { 175 | if session_id != *current_session_id { 176 | return false; 177 | } 178 | 179 | self.remove_connection_by_identity(id); 180 | self.identity_to_address_map.remove(&id); 181 | self.send_identity_unlinked(address); 182 | return true; 183 | } 184 | self.send_identity_unlinked(address); 185 | return false; 186 | } 187 | 188 | pub fn client_identity_update(&mut self) { 189 | if self.config.use_identity == 0 { 190 | return; 191 | } 192 | 193 | if self.socket.socket.is_none() { 194 | return; 195 | } 196 | 197 | if self.socket.is_server { 198 | return; 199 | } 200 | 201 | if !self.identity.is_valid() { 202 | return; 203 | } 204 | 205 | if self.identity.is_linked() { 206 | return; 207 | } 208 | 209 | let since_last = Instant::now() - self.last_identity_link_request; 210 | if since_last.as_millis() > IDENTITY_SEND_INTERVAL { 211 | self.last_identity_link_request = Instant::now(); 212 | self.send_link_identity(self.identity.id, self.identity.session_id); 213 | } 214 | } 215 | 216 | pub fn can_send(&self) -> bool { 217 | if self.socket.is_server { 218 | return true; 219 | } else { 220 | if self.config.use_identity == 1 { 221 | return self.identity.linked == 1; 222 | } else { 223 | return true; 224 | } 225 | } 226 | } 227 | 228 | pub fn send_link_identity(&self, id: u32, session_id: u32) { 229 | self.send_identity_message(MESSAGE_TYPE_LINK_IDENTITY, id, session_id, NetworkAddress::default()); 230 | } 231 | 232 | pub fn send_unlink_identity(&self, id: u32, session_id: u32) { 233 | self.send_identity_message(MESSAGE_TYPE_UNLINK_IDENTITY, id, session_id, NetworkAddress::default()); 234 | } 235 | 236 | pub fn send_identity_linked(&self, address: NetworkAddress) { 237 | self.send_identity_message(MESSAGE_TYPE_IDENTITY_LINKED, 0, 0, address); 238 | } 239 | 240 | pub fn send_identity_unlinked(&self, address: NetworkAddress) { 241 | self.send_identity_message(MESSAGE_TYPE_IDENTITY_UNLINKED, 0, 0, address); 242 | } 243 | 244 | fn send_identity_message(&self, message_type: u8, id: u32, session_id: u32, address: NetworkAddress) { 245 | let mut header = ConnectionHeader::default(); 246 | header.message_type = message_type; 247 | header.id = id; 248 | header.session_id = session_id; 249 | let mut send_buffer: Vec = vec![0; 12]; 250 | header.write(&mut send_buffer); 251 | self.socket.send_to(address, &send_buffer, send_buffer.len()); 252 | } 253 | } 254 | 255 | #[cfg(test)] 256 | mod tests { 257 | 258 | use serial_test::serial; 259 | 260 | use crate::tachyon::{ 261 | connection::Identity, network_address::NetworkAddress, tachyon_test::TachyonTest, Tachyon, 262 | TachyonConfig, 263 | }; 264 | 265 | #[test] 266 | fn test_connect() { 267 | let address = NetworkAddress::localhost(100); 268 | let changed_address = NetworkAddress::localhost(200); 269 | 270 | let config = TachyonConfig::default(); 271 | let mut server = Tachyon::create(config); 272 | server.set_identity(1, 10); 273 | 274 | assert!(!server.try_link_identity(address, 1, 11)); 275 | 276 | assert!(server.try_link_identity(address, 1, 10)); 277 | assert!(server.connections.contains_key(&address)); 278 | assert_eq!(2, server.get_channel_count(address)); 279 | 280 | // connect when connected is valid 281 | assert!(server.try_link_identity(address, 1, 10)); 282 | assert!(server.connections.contains_key(&address)); 283 | assert_eq!(2, server.get_channel_count(address)); 284 | 285 | // connect with new address wipes out old connection 286 | assert!(server.try_link_identity(changed_address, 1, 10)); 287 | assert!(server.connections.contains_key(&changed_address)); 288 | assert_eq!(2, server.get_channel_count(changed_address)); 289 | 290 | assert!(!server.connections.contains_key(&address)); 291 | assert_eq!(0, server.get_channel_count(address)); 292 | } 293 | 294 | #[test] 295 | fn test_disconnect() { 296 | let address = NetworkAddress::localhost(100); 297 | 298 | let config = TachyonConfig::default(); 299 | let mut server = Tachyon::create(config); 300 | server.set_identity(1, 10); 301 | server.try_link_identity(address, 1, 10); 302 | 303 | assert!(!server.try_unlink_identity(address, 1, 11)); 304 | 305 | assert!(server.try_unlink_identity(address, 1, 10)); 306 | assert!(!server.connections.contains_key(&address)); 307 | assert_eq!(0, server.get_channel_count(address)); 308 | } 309 | 310 | #[test] 311 | fn test_validate_and_update_connection() { 312 | let address = NetworkAddress::localhost(100); 313 | 314 | let config = TachyonConfig::default(); 315 | let mut server = Tachyon::create(config); 316 | server.set_identity(1, 10); 317 | 318 | assert!(!server.validate_and_update_linked_connection(address)); 319 | 320 | server.try_link_identity(address, 1, 10); 321 | assert!(server.validate_and_update_linked_connection(address)); 322 | } 323 | 324 | #[test] 325 | fn test_can_send() { 326 | 327 | let mut config = TachyonConfig::default(); 328 | config.use_identity = 1; 329 | let mut tach = Tachyon::create(config); 330 | tach.socket.is_server = true; 331 | assert!(tach.can_send()); 332 | 333 | tach.socket.is_server = false; 334 | assert!(!tach.can_send()); 335 | tach.identity.linked = 1; 336 | assert!(tach.can_send()); 337 | } 338 | 339 | #[test] 340 | #[serial] 341 | fn test_link_flow() { 342 | let mut test = TachyonTest::default(); 343 | test.client.config.use_identity = 1; 344 | test.client.identity = Identity { 345 | id: 1, 346 | session_id: 11, 347 | linked: 0, 348 | }; 349 | 350 | test.server.config.use_identity = 1; 351 | test.server.set_identity(1, 10); 352 | 353 | test.connect(); 354 | 355 | // linked 356 | test.server.set_identity(1, 11); 357 | test.client.update(); 358 | test.server_receive(); 359 | test.client_receive(); 360 | assert!(test.client.identity.is_linked()); 361 | 362 | // unlinked 363 | test.client 364 | .send_unlink_identity(test.client.identity.id, test.client.identity.session_id); 365 | test.server_receive(); 366 | test.client_receive(); 367 | assert!(!test.client.identity.is_linked()); 368 | } 369 | 370 | #[test] 371 | #[serial] 372 | fn test_link_fail_flow() { 373 | let mut test = TachyonTest::default(); 374 | test.client.config.use_identity = 1; 375 | test.client.identity = Identity { 376 | id: 1, 377 | session_id: 11, 378 | linked: 0, 379 | }; 380 | 381 | test.server.config.use_identity = 1; 382 | test.server.set_identity(1, 10); 383 | 384 | test.connect(); 385 | 386 | // link fails = bad session id 387 | test.client.update(); 388 | test.server_receive(); 389 | test.client_receive(); 390 | assert!(!test.client.identity.is_linked()); 391 | } 392 | } 393 | -------------------------------------------------------------------------------- /src/tachyon/ffi.rs: -------------------------------------------------------------------------------- 1 | 2 | use crate::tachyon::*; 3 | 4 | use super::pool::SendTarget; 5 | 6 | 7 | #[no_mangle] 8 | pub extern "C" fn register_callbacks(tachyon_ptr: *mut Tachyon, identity_event_callback: Option, 9 | connection_event_callback: Option) { 10 | let tachyon = unsafe { &mut *tachyon_ptr }; 11 | 12 | if identity_event_callback.is_some() { 13 | tachyon.identity_event_callback = identity_event_callback; 14 | } 15 | 16 | if connection_event_callback.is_some() { 17 | tachyon.connection_event_callback = connection_event_callback; 18 | } 19 | } 20 | 21 | #[no_mangle] 22 | pub extern "C" fn create_tachyon(config_ptr: *const TachyonConfig) -> *mut Tachyon { 23 | let config: TachyonConfig = unsafe { std::ptr::read(config_ptr as *const _) }; 24 | let tachyon = Tachyon::create(config); 25 | let b = Box::new(tachyon); 26 | return Box::into_raw(b); 27 | } 28 | 29 | #[no_mangle] 30 | pub extern "C" fn destroy_tachyon(tachyon: *mut Tachyon) { 31 | if !tachyon.is_null() { 32 | let _b = unsafe { Box::from_raw(tachyon) }; 33 | } 34 | } 35 | 36 | #[no_mangle] 37 | pub extern "C" fn bind_socket(tachyon_ptr: *mut Tachyon, naddress: *const NetworkAddress) -> i32 { 38 | let tachyon = unsafe { &mut *tachyon_ptr }; 39 | let address: NetworkAddress = unsafe { std::ptr::read(naddress as *const _) }; 40 | match tachyon.bind(address) { 41 | true => return 1, 42 | false => return -1, 43 | } 44 | } 45 | 46 | #[no_mangle] 47 | pub extern "C" fn connect_socket( 48 | tachyon_ptr: *mut Tachyon, 49 | naddress: *const NetworkAddress, 50 | ) -> i32 { 51 | let tachyon = unsafe { &mut *tachyon_ptr }; 52 | let address: NetworkAddress = unsafe { std::ptr::read(naddress as *const _) }; 53 | match tachyon.connect(address) { 54 | true => return 1, 55 | false => return -1, 56 | } 57 | } 58 | 59 | #[no_mangle] 60 | pub extern "C" fn configure_channel(tachyon_ptr: *mut Tachyon, channel_id: u8, config_ptr: *const ChannelConfig) -> i32 { 61 | let tachyon = unsafe { &mut *tachyon_ptr }; 62 | let channel_config = unsafe { &*config_ptr }; 63 | let res = tachyon.configure_channel(channel_id, *channel_config); 64 | if res { 65 | return 1; 66 | } else { 67 | return -1; 68 | } 69 | } 70 | 71 | pub fn copy_send_result(from: TachyonSendResult, to: *mut TachyonSendResult) { 72 | unsafe { 73 | (*to).sent_len = from.sent_len; 74 | (*to).error = from.error; 75 | (*to).header = from.header; 76 | } 77 | } 78 | 79 | #[no_mangle] 80 | pub extern "C" fn send_to_target(tachyon_ptr: *mut Tachyon, channel: u8, target_ptr: *const SendTarget, data: *mut u8, length: i32, ret: *mut TachyonSendResult) { 81 | let tachyon = unsafe { &mut *tachyon_ptr }; 82 | let target: SendTarget = unsafe { std::ptr::read(target_ptr as *const _) }; 83 | let slice = unsafe { std::slice::from_raw_parts_mut(data, length as usize) }; 84 | 85 | let result = tachyon.send_to_target(channel, target, slice, length as usize); 86 | copy_send_result(result, ret); 87 | } 88 | 89 | #[no_mangle] 90 | pub extern "C" fn receive(tachyon_ptr: *mut Tachyon, data: *mut u8, receive_buffer_len: u32, ret: *mut TachyonReceiveResult) { 91 | let tachyon = unsafe { &mut *tachyon_ptr }; 92 | let slice = unsafe { std::slice::from_raw_parts_mut(data, receive_buffer_len as usize) }; 93 | let result = tachyon.receive_loop(slice); 94 | 95 | unsafe { 96 | (*ret).channel = result.channel; 97 | (*ret).address = result.address; 98 | (*ret).length = result.length; 99 | (*ret).error = result.error; 100 | } 101 | } 102 | 103 | #[no_mangle] 104 | pub extern "C" fn tachyon_update(tachyon_ptr: *mut Tachyon) { 105 | let tachyon = unsafe { &mut *tachyon_ptr }; 106 | tachyon.update(); 107 | } 108 | 109 | #[no_mangle] 110 | pub extern "C" fn tachyon_get_connection(tachyon_ptr: *mut Tachyon, naddress: *const NetworkAddress, connection: *mut Connection) { 111 | let tachyon = unsafe { &mut *tachyon_ptr }; 112 | let address: NetworkAddress = unsafe { std::ptr::read(naddress as *const _) }; 113 | if let Some(conn) = tachyon.get_connection(address) { 114 | unsafe { 115 | (*connection) = *conn; 116 | } 117 | } 118 | } 119 | 120 | #[no_mangle] 121 | pub extern "C" fn tachyon_get_connection_by_identity(tachyon_ptr: *mut Tachyon, id: u32, connection: *mut Connection) { 122 | let tachyon = unsafe { &mut *tachyon_ptr }; 123 | if let Some(conn) = tachyon.get_connection_by_identity(id) { 124 | unsafe { 125 | (*connection) = *conn; 126 | } 127 | } 128 | } 129 | 130 | #[no_mangle] 131 | pub extern "C" fn tachyon_get_config(tachyon_ptr: *mut Tachyon, config: *mut TachyonConfig, identity: *mut Identity) { 132 | let tachyon = unsafe { &mut *tachyon_ptr }; 133 | unsafe { 134 | (*config) = tachyon.config; 135 | (*identity) = tachyon.identity; 136 | } 137 | } 138 | 139 | #[no_mangle] 140 | pub extern "C" fn set_identity(tachyon_ptr: *mut Tachyon, id: u32, session_id: u32, on_self: u32) { 141 | let tachyon = unsafe { &mut *tachyon_ptr }; 142 | if on_self == 1 { 143 | tachyon.identity.id = id; 144 | tachyon.identity.session_id = session_id; 145 | } else { 146 | tachyon.set_identity(id, session_id); 147 | } 148 | } 149 | 150 | #[no_mangle] 151 | pub extern "C" fn get_stats(tachyon_ptr: *mut Tachyon, stats: *mut TachyonStats) { 152 | let tachyon = unsafe { &mut *tachyon_ptr }; 153 | let combined = tachyon.get_combined_stats(); 154 | unsafe { 155 | (*stats).channel_stats = combined.channel_stats; 156 | (*stats).packets_dropped = combined.packets_dropped; 157 | (*stats).unreliable_sent = combined.unreliable_sent; 158 | (*stats).unreliable_received = combined.unreliable_received; 159 | } 160 | } 161 | 162 | 163 | #[no_mangle] 164 | pub extern "C" fn create_unreliable_sender(tachyon_ptr: *mut Tachyon) -> *mut UnreliableSender { 165 | let tachyon = unsafe { &mut *tachyon_ptr }; 166 | if let Some(sender) = tachyon.create_unreliable_sender() { 167 | let b = Box::new(sender); 168 | return Box::into_raw(b); 169 | } 170 | return std::ptr::null_mut(); 171 | } 172 | 173 | #[no_mangle] 174 | pub extern "C" fn destroy_unreliable_sender(sender_ptr: *mut UnreliableSender) { 175 | if !sender_ptr.is_null() { 176 | let _b = unsafe { Box::from_raw(sender_ptr) }; 177 | } 178 | } 179 | 180 | #[no_mangle] 181 | pub extern "C" fn unreliable_sender_send(sender_ptr: *mut UnreliableSender, naddress: *const NetworkAddress, data_ptr: *mut u8, length: i32, ret: *mut TachyonSendResult) { 182 | let sender = unsafe { &mut *sender_ptr }; 183 | let address: NetworkAddress = unsafe { std::ptr::read(naddress as *const _) }; 184 | let data = unsafe { std::slice::from_raw_parts_mut(data_ptr, length as usize) }; 185 | let result = sender.send(address, data, length as usize); 186 | copy_send_result(result, ret); 187 | } 188 | 189 | -------------------------------------------------------------------------------- /src/tachyon/fragmentation.rs: -------------------------------------------------------------------------------- 1 | use std::time::Instant; 2 | 3 | use super::header::*; 4 | use super::send_buffer_manager::*; 5 | use super::sequence::*; 6 | use rustc_hash::FxHashMap; 7 | 8 | const GROUP_EXPIRE: u128 = 5000; 9 | const FRAG_SIZE: usize = 1200; 10 | pub struct Fragmentation { 11 | pub next_group: u16, 12 | pub received: FxHashMap>>, 13 | pub received_at: FxHashMap, 14 | } 15 | 16 | impl Fragmentation { 17 | pub fn default() -> Self { 18 | let default = Fragmentation { 19 | next_group: 1, 20 | received: FxHashMap::default(), 21 | received_at: FxHashMap::default(), 22 | }; 23 | return default; 24 | } 25 | 26 | pub fn expire_groups(&mut self) { 27 | let mut expired: Vec = Vec::new(); 28 | for (group, time) in &self.received_at { 29 | if time.elapsed().as_millis() > GROUP_EXPIRE { 30 | self.received.remove(group); 31 | expired.push(*group); 32 | } 33 | } 34 | for group in expired { 35 | self.received_at.remove(&group); 36 | } 37 | } 38 | 39 | pub fn should_fragment(length: usize) -> bool { 40 | return length >= FRAG_SIZE; 41 | } 42 | 43 | fn get_next_group(&mut self) -> u16 { 44 | self.next_group += 1; 45 | if self.next_group >= std::u16::MAX - 1 { 46 | self.next_group = 1; 47 | } 48 | return self.next_group; 49 | } 50 | 51 | fn get_group_length(map: &FxHashMap>) -> usize { 52 | let mut length = 0; 53 | for (_, value) in map { 54 | length += value.len() - TACHYON_FRAGMENTED_HEADER_SIZE; 55 | } 56 | return length; 57 | } 58 | 59 | pub fn assemble(&mut self, header: Header) -> Result, ()> { 60 | let map = match self.received.get_mut(&header.fragment_group) { 61 | Some(v) => v, 62 | None => { 63 | return Err(()); 64 | } 65 | }; 66 | if map.len() != header.fragment_count as usize { 67 | return Err(()); 68 | } 69 | 70 | let body_length = Fragmentation::get_group_length(map); 71 | 72 | let mut buffer: Vec = vec![0; body_length]; 73 | let mut offset = 0; 74 | 75 | let mut seq = header.fragment_start_sequence; 76 | for _ in 0..header.fragment_count { 77 | match map.get_mut(&seq) { 78 | Some(fragment) => { 79 | let frag_body_len = fragment.len() - TACHYON_FRAGMENTED_HEADER_SIZE; 80 | let src = &fragment[TACHYON_FRAGMENTED_HEADER_SIZE..fragment.len()]; 81 | let dest = &mut buffer[offset..offset + frag_body_len]; 82 | dest.copy_from_slice(src); 83 | 84 | offset += frag_body_len; 85 | } 86 | None => { 87 | self.received.remove(&header.fragment_group); 88 | return Err(()); 89 | } 90 | } 91 | seq = Sequence::next_sequence(seq); 92 | } 93 | 94 | self.received.remove(&header.fragment_group); 95 | return Ok(buffer); 96 | } 97 | 98 | pub fn receive_fragment(&mut self, data: &[u8], length: usize) -> (bool, bool) { 99 | let header = Header::read_fragmented(data); 100 | if !self.received.contains_key(&header.fragment_group) { 101 | self.received.insert(header.fragment_group, FxHashMap::default()); 102 | self.received_at.insert(header.fragment_group, Instant::now()); 103 | } 104 | if let Some(map) = self.received.get_mut(&header.fragment_group) { 105 | let slice = &data[0..length as usize]; 106 | 107 | let mut fragment: Vec = vec![0; length]; 108 | fragment[..].copy_from_slice(slice); 109 | if !map.contains_key(&header.sequence) { 110 | map.insert(header.sequence, fragment); 111 | } 112 | 113 | return (true, map.len() == header.fragment_count as usize); 114 | } 115 | 116 | return (false, false); 117 | } 118 | 119 | pub fn create_fragments(&mut self, sender: &mut SendBufferManager, channel: u8, data: &[u8], length: usize) -> Vec { 120 | let slice = &data[0..length]; 121 | 122 | let chunks = slice.chunks(FRAG_SIZE as usize); 123 | let fragment_count = chunks.len() as u16; 124 | let mut fragments: Vec = Vec::new(); 125 | let group = self.get_next_group(); 126 | 127 | let mut start_sequence = 0; 128 | let mut index = 0; 129 | 130 | for chunk in chunks { 131 | let chunk_len = chunk.len(); 132 | let fragment_len = chunk_len + TACHYON_FRAGMENTED_HEADER_SIZE; 133 | 134 | match sender.create_send_buffer(fragment_len) { 135 | Some(send_buffer) => { 136 | let sequence = send_buffer.sequence; 137 | if index == 0 { 138 | start_sequence = sequence; 139 | } 140 | 141 | let fragment_header = Header::create_fragmented(sequence, channel, group, start_sequence, fragment_count); 142 | fragment_header.write_fragmented(&mut send_buffer.byte_buffer.get_mut()); 143 | 144 | send_buffer.byte_buffer.get_mut()[TACHYON_FRAGMENTED_HEADER_SIZE..chunk_len + TACHYON_FRAGMENTED_HEADER_SIZE].copy_from_slice(chunk); 145 | fragments.push(sequence); 146 | 147 | index += 1; 148 | } 149 | None => { 150 | fragments.clear(); 151 | return fragments; 152 | } 153 | } 154 | } 155 | 156 | return fragments; 157 | } 158 | } 159 | 160 | #[cfg(test)] 161 | mod tests { 162 | use std::time::Duration; 163 | 164 | use crate::tachyon::fragmentation::*; 165 | 166 | #[test] 167 | fn test_expire() { 168 | let mut frag = Fragmentation::default(); 169 | frag.received_at.insert(1, Instant::now()); 170 | frag.expire_groups(); 171 | assert!(frag.received_at.contains_key(&1)); 172 | assert_eq!(1, frag.received_at.len()); 173 | 174 | let now = Instant::now() - Duration::new(6, 0); 175 | frag.received_at.insert(2, now); 176 | frag.expire_groups(); 177 | assert!(!frag.received_at.contains_key(&2)); 178 | assert_eq!(1, frag.received_at.len()); 179 | } 180 | 181 | #[test] 182 | fn test_create() { 183 | let mut frag = Fragmentation::default(); 184 | let mut sender = SendBufferManager::default(); 185 | 186 | let data: Vec = vec![0; 1400]; 187 | assert_eq!(1400, data.len()); 188 | 189 | let result = frag.create_fragments(&mut sender, 1, &data[..], data.len()); 190 | assert_eq!(2, result.len()); 191 | let buffer = sender.get_send_buffer(result[0]).unwrap(); 192 | assert_eq!(1210, buffer.byte_buffer.length); 193 | let header = Header::read_fragmented(&buffer.byte_buffer.get()); 194 | assert_eq!(MESSAGE_TYPE_FRAGMENT, header.message_type); 195 | assert_eq!(1, header.sequence); 196 | assert_eq!(1, header.fragment_start_sequence); 197 | assert_eq!(2, header.fragment_count); 198 | 199 | let buffer = sender.get_send_buffer(result[1]).unwrap(); 200 | assert_eq!(210, buffer.byte_buffer.length); 201 | 202 | let header = Header::read_fragmented(&buffer.byte_buffer.get()); 203 | assert_eq!(MESSAGE_TYPE_FRAGMENT, header.message_type); 204 | assert_eq!(2, header.sequence); 205 | } 206 | 207 | #[test] 208 | fn test_receive() { 209 | let mut frag = Fragmentation::default(); 210 | let mut sender = SendBufferManager::default(); 211 | 212 | let data: Vec = vec![3; 2500]; 213 | let created = frag.create_fragments(&mut sender, 1, &data[..], data.len()); 214 | let send_buffer = sender.get_send_buffer(created[0]).unwrap(); 215 | let complete = frag.receive_fragment(&send_buffer.byte_buffer.get(), send_buffer.byte_buffer.length); 216 | assert!(!complete.1); 217 | 218 | let send_buffer = sender.get_send_buffer(created[1]).unwrap(); 219 | let complete = frag.receive_fragment(&send_buffer.byte_buffer.get(), send_buffer.byte_buffer.length); 220 | assert!(!complete.1); 221 | 222 | let send_buffer = sender.get_send_buffer(created[2]).unwrap(); 223 | let complete = frag.receive_fragment(&send_buffer.byte_buffer.get(), send_buffer.byte_buffer.length); 224 | assert!(complete.1); 225 | 226 | let header = Header::read_fragmented(&send_buffer.byte_buffer.get()); 227 | let assembled = frag.assemble(header); 228 | assert!(assembled.is_ok()); 229 | let assembled_data = assembled.unwrap(); 230 | assert_eq!(2500, assembled_data.len()); 231 | 232 | for i in 0..assembled_data.len() { 233 | assert_eq!(3, assembled_data[i]); 234 | } 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /src/tachyon/header.rs: -------------------------------------------------------------------------------- 1 | use super::int_buffer::IntBuffer; 2 | 3 | pub const MESSAGE_TYPE_UNRELIABLE: u8 = 0; 4 | pub const MESSAGE_TYPE_RELIABLE: u8 = 1; 5 | pub const MESSAGE_TYPE_FRAGMENT: u8 = 2; 6 | pub const MESSAGE_TYPE_NONE: u8 = 3; 7 | pub const MESSAGE_TYPE_NACK: u8 = 4; 8 | pub const MESSAGE_TYPE_RELIABLE_WITH_NACK: u8 = 5; 9 | 10 | pub const MESSAGE_TYPE_LINK_IDENTITY: u8 = 6; 11 | pub const MESSAGE_TYPE_UNLINK_IDENTITY: u8 = 7; 12 | 13 | pub const MESSAGE_TYPE_IDENTITY_LINKED: u8 = 8; 14 | pub const MESSAGE_TYPE_IDENTITY_UNLINKED: u8 = 9; 15 | 16 | pub const TACHYON_HEADER_SIZE: usize = 4; 17 | pub const TACHYON_NACKED_HEADER_SIZE: usize = 10; 18 | pub const TACHYON_FRAGMENTED_HEADER_SIZE: usize = 10; 19 | 20 | #[derive(Clone, Copy)] 21 | #[repr(C)] 22 | #[derive(Default)] 23 | pub struct ConnectionHeader { 24 | pub message_type: u8, 25 | pub id: u32, 26 | pub session_id: u32, 27 | } 28 | 29 | impl ConnectionHeader { 30 | pub fn read(buffer: &[u8]) -> Self { 31 | let mut header = ConnectionHeader::default(); 32 | let mut reader = IntBuffer { index: 0 }; 33 | 34 | header.message_type = reader.read_u8(buffer); 35 | header.id = reader.read_u32(buffer); 36 | header.session_id = reader.read_u32(buffer); 37 | 38 | return header; 39 | } 40 | 41 | pub fn write(&self, buffer: &mut [u8]) { 42 | let mut writer = IntBuffer { index: 0 }; 43 | 44 | writer.write_u8(self.message_type as u8, buffer); 45 | writer.write_u32(self.id, buffer); 46 | writer.write_u32(self.session_id, buffer); 47 | } 48 | } 49 | 50 | #[derive(Clone, Copy)] 51 | #[repr(C)] 52 | #[derive(Default)] 53 | pub struct Header { 54 | pub message_type: u8, 55 | pub channel: u8, 56 | pub sequence: u16, 57 | 58 | // fragment - optional 59 | pub fragment_group: u16, 60 | pub fragment_start_sequence: u16, 61 | pub fragment_count: u16, 62 | 63 | // nacked - optional 64 | pub start_sequence: u16, 65 | pub flags: u32 66 | } 67 | 68 | impl Header { 69 | 70 | pub fn write_unreliable(&self, buffer: &mut [u8]) { 71 | let mut writer = IntBuffer { index: 0 }; 72 | 73 | writer.write_u8(self.message_type as u8, buffer); 74 | } 75 | 76 | pub fn write_nacked(&self, buffer: &mut [u8]) { 77 | let mut writer = IntBuffer { index: 0 }; 78 | 79 | writer.write_u8(self.message_type, buffer); 80 | writer.write_u8(self.channel, buffer); 81 | writer.write_u16(self.sequence, buffer); 82 | 83 | writer.write_u16(self.start_sequence, buffer); 84 | writer.write_u32(self.flags, buffer); 85 | } 86 | 87 | pub fn write(&self, buffer: &mut [u8]) { 88 | let mut writer = IntBuffer { index: 0 }; 89 | 90 | writer.write_u8(self.message_type, buffer); 91 | writer.write_u8(self.channel, buffer); 92 | writer.write_u16(self.sequence, buffer); 93 | } 94 | 95 | pub fn read(buffer: &[u8]) -> Self { 96 | let mut header = Header::default(); 97 | let mut reader = IntBuffer { index: 0 }; 98 | 99 | header.message_type = reader.read_u8(buffer); 100 | header.channel = reader.read_u8(buffer); 101 | header.sequence = reader.read_u16(buffer); 102 | 103 | return header; 104 | } 105 | 106 | // fragmented 107 | pub fn write_fragmented(&self, buffer: &mut [u8]) { 108 | let mut writer = IntBuffer { index: 0 }; 109 | 110 | writer.write_u8(self.message_type, buffer); 111 | writer.write_u8(self.channel, buffer); 112 | writer.write_u16(self.sequence, buffer); 113 | 114 | writer.write_u16(self.fragment_group, buffer); 115 | writer.write_u16(self.fragment_start_sequence, buffer); 116 | writer.write_u16(self.fragment_count, buffer); 117 | } 118 | 119 | pub fn read_fragmented(buffer: &[u8]) -> Self { 120 | let mut header = Header::default(); 121 | let mut reader = IntBuffer { index: 0 }; 122 | 123 | header.message_type = reader.read_u8(buffer); 124 | header.channel = reader.read_u8(buffer); 125 | header.sequence = reader.read_u16(buffer); 126 | 127 | header.fragment_group = reader.read_u16(buffer); 128 | header.fragment_start_sequence = reader.read_u16(buffer); 129 | header.fragment_count = reader.read_u16(buffer); 130 | 131 | return header; 132 | } 133 | 134 | pub fn create_fragmented(sequence: u16, channel: u8, group: u16, start: u16, count: u16) -> Self { 135 | let mut header = Header::default(); 136 | header.message_type = MESSAGE_TYPE_FRAGMENT; 137 | header.sequence = sequence; 138 | header.channel = channel; 139 | 140 | header.fragment_group = group; 141 | header.fragment_start_sequence = start; 142 | header.fragment_count = count; 143 | return header; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/tachyon/int_buffer.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Range; 2 | 3 | use super::network_address::NetworkAddress; 4 | 5 | pub struct IntBuffer { 6 | pub index: usize, 7 | } 8 | 9 | impl IntBuffer { 10 | 11 | pub fn write_address(&mut self, address: NetworkAddress, data: &mut [u8]) { 12 | self.write_u16(address.a, data); 13 | self.write_u16(address.b, data); 14 | self.write_u16(address.c, data); 15 | self.write_u16(address.d, data); 16 | self.write_u32(address.port, data); 17 | } 18 | 19 | pub fn read_address(&mut self, data: &[u8]) -> NetworkAddress { 20 | let mut address = NetworkAddress::default(); 21 | address.a = self.read_u16(data); 22 | address.b = self.read_u16(data); 23 | address.c = self.read_u16(data); 24 | address.d = self.read_u16(data); 25 | address.port = self.read_u32(data); 26 | return address; 27 | } 28 | 29 | pub fn write_u32(&mut self, v: u32, data: &mut [u8]) { 30 | data[self.index] = v as u8; 31 | self.index += 1; 32 | data[self.index] = (v >> 8) as u8; 33 | self.index += 1; 34 | data[self.index] = (v >> 16) as u8; 35 | self.index += 1; 36 | data[self.index] = (v >> 24) as u8; 37 | self.index += 1; 38 | } 39 | 40 | pub fn read_u32(&mut self, data: &[u8]) -> u32 { 41 | let value = (data[self.index] as u32) 42 | | (data[self.index + 1] as u32) << 8 43 | | (data[self.index + 2] as u32) << 16 44 | | (data[self.index + 3] as u32) << 24; 45 | self.index += 4; 46 | return value; 47 | } 48 | 49 | pub fn write_u16(&mut self, v: u16, data: &mut [u8]) { 50 | data[self.index] = v as u8; 51 | self.index += 1; 52 | data[self.index] = (v >> 8) as u8; 53 | self.index += 1; 54 | } 55 | 56 | pub fn read_u16(&mut self, data: &[u8]) -> u16 { 57 | let value = (data[self.index] as u16) | (data[self.index + 1] as u16) << 8; 58 | self.index += 2; 59 | return value; 60 | } 61 | 62 | pub fn write_u8(&mut self, v: u8, data: &mut [u8]) { 63 | data[self.index] = v; 64 | self.index += 1; 65 | } 66 | 67 | pub fn read_u8(&mut self, data: &[u8]) -> u8 { 68 | let value = data[self.index]; 69 | self.index += 1; 70 | return value; 71 | } 72 | 73 | pub fn u4_to_u8(v1: u8, v2: u8) -> u8 { 74 | return v1 | v2 << 4; 75 | } 76 | 77 | pub fn u8_to_u4(byte: u8) -> (u8,u8) { 78 | return (byte & 0x0F, byte >> 4); 79 | } 80 | } 81 | 82 | pub struct LengthPrefixed { 83 | pub reader: IntBuffer, 84 | pub writer: IntBuffer 85 | } 86 | 87 | impl LengthPrefixed { 88 | pub fn default() -> Self { 89 | return LengthPrefixed { 90 | reader: IntBuffer {index: 0}, 91 | writer: IntBuffer {index: 0} 92 | } 93 | } 94 | 95 | pub fn write(&mut self, channel: u16, src_address: NetworkAddress, src: &[u8], dst: &mut [u8]) { 96 | self.writer.write_u32(src.len() as u32, dst); 97 | self.writer.write_u16(channel, dst); 98 | self.writer.write_address(src_address, dst); 99 | dst[self.writer.index..self.writer.index+src.len()].copy_from_slice(&src); 100 | self.writer.index += src.len(); 101 | } 102 | 103 | pub fn read(&mut self, data: &[u8]) -> (u16,NetworkAddress,Range) { 104 | let len = self.reader.read_u32(&data) as usize; 105 | let channel = self.reader.read_u16(&data); 106 | let address = self.reader.read_address(&data); 107 | let range = self.reader.index..self.reader.index+len; 108 | self.reader.index += len; 109 | return (channel, address,range); 110 | } 111 | } 112 | 113 | 114 | #[cfg(test)] 115 | mod tests { 116 | use crate::tachyon::int_buffer::IntBuffer; 117 | 118 | #[test] 119 | fn test_4bit() { 120 | let mut low = 3; 121 | let mut high = 15; 122 | let byte = IntBuffer::u4_to_u8(low, high); 123 | let res = IntBuffer::u8_to_u4(byte); 124 | low = res.0; 125 | high = res.1; 126 | 127 | println!("{0}", byte); 128 | println!("{0} {1}", low, high); 129 | } 130 | 131 | #[test] 132 | fn test_header_readwrite() { 133 | let mut bytes: Vec = vec![0; 128]; 134 | 135 | let mut buffer = IntBuffer { index: 0 }; 136 | buffer.write_u32(234, &mut bytes); 137 | buffer.write_u16(44, &mut bytes); 138 | buffer.write_u8(99, &mut bytes); 139 | buffer.write_u32(1, &mut bytes); 140 | buffer.index = 0; 141 | assert_eq!(234, buffer.read_u32(&bytes)); 142 | assert_eq!(44, buffer.read_u16(&bytes)); 143 | assert_eq!(99, buffer.read_u8(&bytes)); 144 | assert_eq!(1, buffer.read_u32(&bytes)); 145 | return; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/tachyon/memory_block.rs: -------------------------------------------------------------------------------- 1 | use std::alloc::{alloc_zeroed, Layout, dealloc}; 2 | 3 | 4 | #[repr(C)] 5 | pub struct MemoryBlock { 6 | pub memory: *mut u8, 7 | pub length: u32 8 | } 9 | 10 | impl MemoryBlock { 11 | 12 | pub fn allocate(length: u32) -> Option { 13 | match Layout::array::(length as usize) { 14 | Ok(layout) => { 15 | unsafe { 16 | let block = MemoryBlock { 17 | memory: alloc_zeroed(layout), 18 | length: length 19 | }; 20 | return Some(block); 21 | } 22 | }, 23 | Err(_) => { 24 | return None; 25 | }, 26 | } 27 | } 28 | 29 | pub fn free(block: MemoryBlock) -> i32 { 30 | if block.length == 0 { 31 | return -3; 32 | } 33 | 34 | match Layout::array::(block.length as usize) { 35 | Ok(layout) => { 36 | unsafe { 37 | dealloc(block.memory, layout); 38 | return 1; 39 | } 40 | }, 41 | Err(_) => { 42 | return -1; 43 | }, 44 | } 45 | } 46 | } 47 | 48 | #[no_mangle] 49 | pub extern "C" fn allocate_memory_block(length: u32, block_ptr: *mut MemoryBlock) -> i32 { 50 | match MemoryBlock::allocate(length) { 51 | Some(block) => { 52 | unsafe { 53 | (*block_ptr) = block; 54 | return 1; 55 | } 56 | }, 57 | None => { 58 | return -1; 59 | }, 60 | } 61 | } 62 | 63 | #[no_mangle] 64 | pub extern "C" fn free_memory_block(block_ptr: *mut MemoryBlock) -> i32 { 65 | if block_ptr.is_null() { 66 | return -2; 67 | } 68 | let block: MemoryBlock = unsafe { std::ptr::read(block_ptr as *mut _) }; 69 | return MemoryBlock::free(block); 70 | } -------------------------------------------------------------------------------- /src/tachyon/nack.rs: -------------------------------------------------------------------------------- 1 | use std::io::Cursor; 2 | 3 | use varuint::{ReadVarint, WriteVarint}; 4 | 5 | use super::{int_buffer::IntBuffer, sequence::Sequence}; 6 | 7 | #[derive(Clone, Copy)] 8 | #[repr(C)] 9 | #[derive(Default)] 10 | pub struct Nack { 11 | pub start_sequence: u16, 12 | pub flags: u32, 13 | pub nacked_count: u32, 14 | pub sent_count: u32 15 | } 16 | 17 | impl Nack { 18 | pub fn write(nacks: &[Nack], data: &mut [u8], position: u64) -> u64 { 19 | if nacks.len() == 0 { 20 | return 0; 21 | } 22 | let mut buffer = IntBuffer { 23 | index: position as usize, 24 | }; 25 | buffer.write_u8(nacks.len() as u8, data); 26 | for nack in nacks { 27 | buffer.write_u16(nack.start_sequence, data); 28 | buffer.write_u32(nack.flags, data); 29 | } 30 | return buffer.index as u64; 31 | } 32 | 33 | pub fn read_single(sequences: &mut Vec, data: &[u8], position: usize) { 34 | let mut buffer = IntBuffer { 35 | index: position 36 | }; 37 | 38 | let mut nack = Nack::default(); 39 | nack.start_sequence = buffer.read_u16(data); 40 | if nack.start_sequence == 0 { 41 | return; 42 | } 43 | 44 | nack.flags = buffer.read_u32(data); 45 | nack.get_nacked(sequences); 46 | } 47 | 48 | pub fn write_single(nack: &Nack, data: &mut [u8], position: usize) -> usize { 49 | let mut buffer = IntBuffer { 50 | index: position 51 | }; 52 | 53 | buffer.write_u16(nack.start_sequence, data); 54 | buffer.write_u32(nack.flags, data); 55 | return buffer.index; 56 | } 57 | 58 | pub fn write_varint(nacks: &[Nack], data: &mut [u8], position: u64) -> u64 { 59 | if nacks.len() == 0 { 60 | return 0; 61 | } 62 | 63 | let mut cursor = Cursor::new(data); 64 | cursor.set_position(position); 65 | let _ = cursor.write_varint(nacks.len() as u16).unwrap(); 66 | for nack in nacks { 67 | cursor.write_varint(nack.start_sequence).unwrap(); 68 | cursor.write_varint(nack.flags).unwrap(); 69 | } 70 | return cursor.position(); 71 | } 72 | 73 | pub fn read_varint(sequences: &mut Vec, data: &[u8], position: usize) { 74 | let mut cursor = Cursor::new(data); 75 | cursor.set_position(position as u64); 76 | 77 | let count = ReadVarint::::read_varint(&mut cursor).unwrap(); 78 | for _ in 0..count { 79 | let mut nack = Nack::default(); 80 | nack.start_sequence = ReadVarint::::read_varint(&mut cursor).unwrap(); 81 | nack.flags = ReadVarint::::read_varint(&mut cursor).unwrap(); 82 | nack.get_nacked(sequences); 83 | } 84 | } 85 | 86 | pub fn read(sequences: &mut Vec, data: &[u8], position: u64) { 87 | let mut buffer = IntBuffer { 88 | index: position as usize, 89 | }; 90 | let count = buffer.read_u8(data); 91 | for _ in 0..count { 92 | let mut nack = Nack::default(); 93 | nack.start_sequence = buffer.read_u16(data); 94 | nack.flags = buffer.read_u32(data); 95 | nack.get_nacked(sequences); 96 | } 97 | } 98 | 99 | 100 | pub fn get_nacked(&self, sequences: &mut Vec) { 101 | sequences.push(self.start_sequence); 102 | self.get_flagged(sequences); 103 | } 104 | 105 | pub fn get_flagged(&self, sequences: &mut Vec) { 106 | let mut seq = Sequence::previous_sequence(self.start_sequence); 107 | for i in 0i32..32 { 108 | if self.get_bits(i) { 109 | sequences.push(seq); 110 | } 111 | seq = Sequence::previous_sequence(seq); 112 | } 113 | } 114 | 115 | pub fn is_nacked(&self, sequence: u16) -> bool { 116 | if self.start_sequence == sequence { 117 | return true; 118 | } 119 | return self.is_flagged(sequence); 120 | } 121 | 122 | pub fn is_flagged(&self, sequence: u16) -> bool { 123 | let mut seq = Sequence::previous_sequence(self.start_sequence); 124 | for i in 0i32..32 { 125 | if seq == sequence { 126 | return self.get_bits(i); 127 | } 128 | seq = Sequence::previous_sequence(seq); 129 | } 130 | return false; 131 | } 132 | 133 | pub fn set_flagged(&mut self, sequence: u16) { 134 | let mut seq = Sequence::previous_sequence(self.start_sequence); 135 | for i in 0i32..32 { 136 | if seq == sequence { 137 | self.set_bits(i, true); 138 | return; 139 | } 140 | seq = Sequence::previous_sequence(seq); 141 | } 142 | } 143 | 144 | pub fn get_bits(&self, index: i32) -> bool { 145 | let mask = 1 << index; 146 | return (self.flags & mask) == mask; 147 | } 148 | 149 | pub fn set_bits(&mut self, index: i32, value: bool) { 150 | let mask = 1 << index; 151 | if value { 152 | self.flags |= mask; 153 | } else { 154 | self.flags &= !mask; 155 | } 156 | } 157 | } 158 | 159 | #[cfg(test)] 160 | mod tests { 161 | use crate::tachyon::sequence::Sequence; 162 | 163 | use super::Nack; 164 | 165 | #[test] 166 | fn test_flagged() { 167 | let mut nack = Nack::default(); 168 | nack.start_sequence = 33; 169 | nack.set_flagged(32); 170 | assert!(nack.is_flagged(32)); 171 | assert!(nack.get_bits(0)); 172 | 173 | nack.set_flagged(1); 174 | assert!(nack.get_bits(31)); 175 | assert!(nack.is_flagged(1)); 176 | 177 | nack.set_flagged(34); 178 | assert!(!nack.is_flagged(34)); 179 | } 180 | 181 | #[test] 182 | fn test_flagged_wrapped() { 183 | let mut nack = Nack::default(); 184 | nack.start_sequence = 0; 185 | nack.set_flagged(65534); 186 | assert!(nack.is_flagged(65534)); 187 | 188 | nack.set_flagged(65534 - 31); 189 | assert!(nack.is_flagged(65534 - 31)); 190 | 191 | nack.set_flagged(2); 192 | assert!(!nack.is_flagged(2)); 193 | } 194 | 195 | fn create_full_nack(start: u16) -> Nack { 196 | let mut nack = Nack::default(); 197 | nack.start_sequence = start; 198 | let mut seq = Sequence::previous_sequence(nack.start_sequence); 199 | for _ in 0..32 { 200 | nack.set_flagged(seq); 201 | seq = Sequence::previous_sequence(seq); 202 | } 203 | return nack; 204 | } 205 | 206 | #[test] 207 | fn test_get_nacked() { 208 | let mut nack = create_full_nack(1); 209 | 210 | let mut sequences: Vec = Vec::new(); 211 | nack.get_nacked(&mut sequences); 212 | assert_eq!(33, sequences.len()); 213 | 214 | nack.set_bits(4, false); 215 | nack.set_bits(31, false); 216 | 217 | let mut sequences: Vec = Vec::new(); 218 | nack.get_nacked(&mut sequences); 219 | assert_eq!(31, sequences.len()); 220 | } 221 | 222 | #[test] 223 | fn test_write_read() { 224 | let mut data: Vec = vec![0; 1024]; 225 | let mut sequences_out: Vec = Vec::new(); 226 | let mut nacks: Vec = Vec::new(); 227 | nacks.push(create_full_nack(1)); 228 | nacks.push(create_full_nack(34)); 229 | 230 | Nack::write_varint(&nacks, &mut data[..], 0); 231 | Nack::read_varint(&mut sequences_out, &data[..], 0); 232 | assert_eq!(66, sequences_out.len()); 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /src/tachyon/network_address.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | hash::{Hash, Hasher}, 3 | net::{IpAddr, Ipv4Addr, SocketAddr}, 4 | }; 5 | 6 | #[derive(Eq, Default, Clone, Copy)] 7 | #[repr(C)] 8 | pub struct NetworkAddress { 9 | pub a: u16, 10 | pub b: u16, 11 | pub c: u16, 12 | pub d: u16, 13 | pub port: u32, 14 | } 15 | 16 | impl std::fmt::Display for NetworkAddress { 17 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 18 | write!( 19 | f, 20 | "{0}.{1}.{2}.{3}:{4}\n", 21 | self.a, self.b, self.c, self.d, self.port 22 | ) 23 | } 24 | } 25 | 26 | impl Hash for NetworkAddress { 27 | fn hash(&self, hasher: &mut H) { 28 | let hash = NetworkAddress::get_hash(&self); 29 | hasher.write_u32(hash); 30 | hasher.finish(); 31 | } 32 | } 33 | 34 | impl PartialEq for NetworkAddress { 35 | fn eq(&self, other: &Self) -> bool { 36 | self.a == other.a 37 | && self.b == other.b 38 | && self.c == other.c 39 | && self.d == other.d 40 | && self.port == other.port 41 | } 42 | } 43 | 44 | impl NetworkAddress { 45 | pub fn test_address() -> Self { 46 | let address = NetworkAddress { 47 | a: 127, 48 | b: 0, 49 | c: 0, 50 | d: 1, 51 | port: 8265, 52 | }; 53 | return address; 54 | } 55 | 56 | pub fn broadcast(channel: u8) -> Self { 57 | NetworkAddress { 58 | a: 255, 59 | b: 255, 60 | c: 255, 61 | d: 255, 62 | port: channel as u32, 63 | } 64 | } 65 | 66 | pub fn localhost(port: u32) -> Self { 67 | let address = NetworkAddress { 68 | a: 127, 69 | b: 0, 70 | c: 0, 71 | d: 1, 72 | port: port, 73 | }; 74 | return address; 75 | } 76 | 77 | pub fn mock_client_address() -> Self { 78 | let address = NetworkAddress { 79 | a: 127, 80 | b: 0, 81 | c: 0, 82 | d: 1, 83 | port: 4598, 84 | }; 85 | return address; 86 | } 87 | 88 | pub fn from_socket_addr(address: SocketAddr) -> NetworkAddress { 89 | if let IpAddr::V4(ipv4) = address.ip() { 90 | let parts = ipv4.octets(); 91 | let result = NetworkAddress { 92 | a: parts[0] as u16, 93 | b: parts[1] as u16, 94 | c: parts[2] as u16, 95 | d: parts[3] as u16, 96 | port: address.port() as u32, 97 | }; 98 | return result; 99 | } else { 100 | return NetworkAddress::default(); 101 | } 102 | } 103 | 104 | pub fn to_socket_addr(&self) -> SocketAddr { 105 | let ip = Ipv4Addr::new(self.a as u8, self.b as u8, self.c as u8, self.d as u8); 106 | return SocketAddr::new(IpAddr::V4(ip), self.port as u16); 107 | } 108 | 109 | pub fn is_default(&self) -> bool { 110 | return NetworkAddress::default() == *self; 111 | } 112 | 113 | pub fn is_broadcast(&self) -> bool { 114 | self.a == 255 && self.b == 255 && self.c == 255 && self.d == 255 115 | } 116 | 117 | pub fn copy_from(&mut self, other: NetworkAddress) { 118 | self.a = other.a; 119 | self.b = other.b; 120 | self.c = other.c; 121 | self.d = other.d; 122 | self.port = other.port; 123 | } 124 | 125 | pub fn get_hash(&self) -> u32 { 126 | let mut hash: u32 = 17; 127 | hash = hash.wrapping_mul(23).wrapping_add(self.a as u32); 128 | hash = hash.wrapping_mul(23).wrapping_add(self.b as u32); 129 | hash = hash.wrapping_mul(23).wrapping_add(self.c as u32); 130 | hash = hash.wrapping_mul(23).wrapping_add(self.d as u32); 131 | hash = hash.wrapping_mul(23).wrapping_add(self.port as u32); 132 | 133 | /* hash = hash * 23 + self.a as u32; 134 | hash = hash * 23 + self.b as u32; 135 | hash = hash * 23 + self.c as u32; 136 | hash = hash * 23 + self.d as u32; 137 | hash = hash * 23 + self.port as u32; */ 138 | return hash; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/tachyon/pool.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | collections::VecDeque, 3 | sync::{Arc} 4 | }; 5 | 6 | use crossbeam::queue::ArrayQueue; 7 | use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator}; 8 | use rustc_hash::FxHashMap; 9 | use synchronoise::CountdownEvent; 10 | 11 | use super::{network_address::NetworkAddress, Tachyon, TachyonConfig, int_buffer::LengthPrefixed, connection::Connection, TachyonSendResult}; 12 | 13 | 14 | #[derive(Clone, Copy)] 15 | #[repr(C)] 16 | #[derive(Default)] 17 | pub struct SendTarget { 18 | pub identity_id: u32, 19 | pub address: NetworkAddress 20 | } 21 | 22 | #[derive(Default, Clone, Copy)] 23 | #[repr(C)] 24 | pub struct PoolServerRef { 25 | pub address: NetworkAddress, 26 | pub id: u16 27 | } 28 | 29 | #[derive(Default, Clone, Copy)] 30 | #[repr(C)] 31 | pub struct OutBufferCounts { 32 | pub bytes_written: u32, 33 | pub count: u32 34 | } 35 | 36 | pub struct OutBuffer { 37 | pub data: Vec, 38 | pub bytes_written: u32, 39 | pub count: u32 40 | } 41 | 42 | pub struct Pool { 43 | pub next_id: u16, 44 | pub max_servers: u8, 45 | pub receive_buffer_len: u32, 46 | pub servers: FxHashMap, 47 | pub receive_queue: Arc>>>, 48 | pub receive_buffers: Arc>>, 49 | pub out_buffers: Arc>, 50 | pub published: VecDeque>, 51 | pub servers_in_use: Arc>, 52 | pub counter: Option>, 53 | pub connections_by_identity: FxHashMap, 54 | pub connections_by_address: FxHashMap 55 | 56 | } 57 | 58 | impl Pool { 59 | pub fn create(max_servers: u8, receive_buffer_len: u32, out_buffer_len: u32) -> Self { 60 | 61 | let receive_buffers: ArrayQueue> = ArrayQueue::new(max_servers as usize); 62 | let out_buffers: ArrayQueue = ArrayQueue::new(max_servers as usize); 63 | let queue: ArrayQueue>> = ArrayQueue::new(max_servers as usize); 64 | 65 | for _ in 0..max_servers { 66 | queue.push(VecDeque::new()).unwrap_or(()); 67 | receive_buffers.push(vec![0; receive_buffer_len as usize]).unwrap_or(()); 68 | 69 | let buffer = OutBuffer { 70 | data: vec![0; out_buffer_len as usize], 71 | bytes_written: 0, 72 | count: 0 73 | }; 74 | out_buffers.push(buffer).unwrap_or(()); 75 | } 76 | 77 | let in_use: ArrayQueue = ArrayQueue::new(max_servers as usize); 78 | 79 | let pool = Pool { 80 | next_id: 0, 81 | max_servers, 82 | receive_buffer_len, 83 | servers: FxHashMap::default(), 84 | receive_queue: Arc::new(queue), 85 | receive_buffers: Arc::new(receive_buffers), 86 | out_buffers: Arc::new(out_buffers), 87 | published: VecDeque::new(), 88 | servers_in_use: Arc::new(in_use), 89 | counter: None, 90 | connections_by_identity: FxHashMap::default(), 91 | connections_by_address: FxHashMap::default() 92 | }; 93 | return pool; 94 | } 95 | 96 | pub fn create_server(&mut self, config: TachyonConfig, address: NetworkAddress, id: u16) -> bool { 97 | 98 | if self.servers.len() > self.max_servers.into() { 99 | return false; 100 | } 101 | if self.servers.contains_key(&id) { 102 | return false; 103 | } 104 | 105 | let mut tachyon = Tachyon::create(config); 106 | match tachyon.bind(address) { 107 | true => { 108 | tachyon.id = id; 109 | self.servers.insert(id, tachyon); 110 | 111 | return true; 112 | } 113 | false => { 114 | return false; 115 | } 116 | } 117 | } 118 | 119 | pub fn set_identity(&mut self, server_id: u16, id: u32, session_id: u32, on_self: u32) { 120 | if let Some(tachyon) = self.get_server(server_id) { 121 | if on_self == 1 { 122 | tachyon.identity.id = id; 123 | tachyon.identity.session_id = session_id; 124 | } else { 125 | tachyon.set_identity(id, session_id); 126 | } 127 | } 128 | } 129 | 130 | pub fn build_connection_maps(&mut self) { 131 | self.connections_by_address.clear(); 132 | self.connections_by_identity.clear(); 133 | 134 | for server in self.servers.values_mut() { 135 | for conn in server.connections.values() { 136 | self.connections_by_address.insert(conn.address, *conn); 137 | if conn.identity.id > 0 { 138 | self.connections_by_identity.insert(conn.identity.id, *conn); 139 | } 140 | } 141 | } 142 | } 143 | 144 | pub fn get_server_having_connection(&self, address: NetworkAddress) -> u16 { 145 | if let Some(conn) = self.connections_by_address.get(&address) { 146 | return conn.tachyon_id; 147 | } else { 148 | return 0; 149 | } 150 | } 151 | 152 | pub fn get_server_having_identity(&self, identity_id: u32) -> u16 { 153 | if let Some(conn) = self.connections_by_identity.get(&identity_id) { 154 | return conn.tachyon_id; 155 | } else { 156 | return 0; 157 | } 158 | } 159 | 160 | pub fn get_available_server(&self) -> Option { 161 | let mut best: Option = None; 162 | let mut low = 10000; 163 | for (_id,server) in &self.servers { 164 | let conn_count = server.connections.len(); 165 | if conn_count < low && server.socket.socket.is_some() { 166 | low = conn_count; 167 | best = Some(PoolServerRef {address: server.socket.address, id: server.id}); 168 | } 169 | } 170 | 171 | return best; 172 | } 173 | 174 | pub fn get_server(&mut self, id: u16) -> Option<&mut Tachyon> { 175 | return self.servers.get_mut(&id); 176 | } 177 | 178 | pub fn send_to_target(&mut self,channel_id: u8, target: SendTarget, data: &mut [u8], length: i32) -> TachyonSendResult { 179 | if target.identity_id > 0 { 180 | return self.send_to_identity(channel_id,target.identity_id, data, length); 181 | } else { 182 | return self.send_to_address(channel_id,target.address, data, length); 183 | } 184 | } 185 | 186 | fn send_to_identity(&mut self, channel_id: u8, id: u32, data: &mut [u8], length: i32) -> TachyonSendResult { 187 | if let Some(conn) = self.connections_by_identity.get(&id) { 188 | if let Some(server) = self.servers.get_mut(&conn.tachyon_id) { 189 | if channel_id == 0 { 190 | return server.send_unreliable(conn.address, data, length as usize); 191 | } else { 192 | return server.send_reliable(channel_id,conn.address, data, length as usize); 193 | } 194 | } 195 | } 196 | return TachyonSendResult::default(); 197 | } 198 | 199 | fn send_to_address(&mut self,channel_id: u8, address: NetworkAddress, data: &mut [u8], length: i32) -> TachyonSendResult { 200 | if let Some(conn) = self.connections_by_address.get(&address) { 201 | if let Some(sender) = self.servers.get_mut(&conn.tachyon_id) { 202 | if channel_id == 0 { 203 | return sender.send_unreliable(address, data, length as usize); 204 | } else { 205 | return sender.send_reliable(channel_id, address, data, length as usize); 206 | } 207 | } 208 | } 209 | return TachyonSendResult::default(); 210 | } 211 | 212 | pub fn take_published(&mut self) -> Option> { 213 | return self.published.pop_front(); 214 | } 215 | 216 | fn move_received_to_published(&mut self) -> i32 { 217 | let mut count = 0; 218 | for _ in 0..self.receive_queue.len() { 219 | if let Some(mut receive_queue) = self.receive_queue.pop() { 220 | for value in receive_queue.drain(..) { 221 | self.published.push_back(value); 222 | count += 1; 223 | } 224 | self.receive_queue.push(receive_queue).unwrap_or_default(); 225 | } 226 | } 227 | return count; 228 | } 229 | 230 | fn receive_server(server: &mut Tachyon, receive_queue: &mut VecDeque>, receive_buffer: &mut Vec) { 231 | for _ in 0..100000 { 232 | let res = server.receive_loop(receive_buffer); 233 | if res.length == 0 || res.error > 0 { 234 | break; 235 | } else { 236 | let mut message: Vec = vec![0; res.length as usize]; 237 | message.copy_from_slice(&receive_buffer[0..res.length as usize]); 238 | receive_queue.push_back(message); 239 | 240 | } 241 | } 242 | } 243 | 244 | // receive and finish_receive go together, this heap allocates and puts messages into a queue 245 | pub fn receive(&mut self) -> bool { 246 | let server_count = self.servers.len(); 247 | if server_count == 0 { 248 | return false; 249 | } 250 | 251 | let counter = Arc::new(CountdownEvent::new(server_count)); 252 | 253 | let in_use = self.servers_in_use.clone(); 254 | for s in self.servers.drain() { 255 | let server = s.1; 256 | in_use.push(server).unwrap_or(()); 257 | } 258 | 259 | for _ in 0..server_count { 260 | let in_use = self.servers_in_use.clone(); 261 | let receive_queue_clone = self.receive_queue.clone(); 262 | let receive_buffers_clone = self.receive_buffers.clone(); 263 | let signal = counter.clone(); 264 | 265 | rayon::spawn(move || { 266 | match in_use.pop() { 267 | Some(mut server) => { 268 | if let Some(mut receive_queue) = receive_queue_clone.pop() { 269 | if let Some(mut receive_buffer) = receive_buffers_clone.pop() { 270 | Pool::receive_server(&mut server, &mut receive_queue, &mut receive_buffer); 271 | receive_buffers_clone.push(receive_buffer).unwrap_or_default(); 272 | } 273 | receive_queue_clone.push(receive_queue).unwrap_or_default(); 274 | } 275 | in_use.push(server).unwrap_or(()); 276 | } 277 | None => {} 278 | } 279 | signal.decrement().unwrap(); 280 | }); 281 | } 282 | self.counter = Some(counter); 283 | return true; 284 | } 285 | 286 | pub fn finish_receive(&mut self) -> (u32, i32) { 287 | let mut server_count = 0; 288 | let mut message_count = 0; 289 | 290 | match &self.counter { 291 | Some(counter) => { 292 | counter.wait(); 293 | message_count += self.move_received_to_published(); 294 | 295 | for _ in 0..self.servers_in_use.len() { 296 | if let Some(server) = self.servers_in_use.pop() { 297 | self.servers.insert(server.id, server); 298 | server_count += 1; 299 | } 300 | } 301 | self.counter = None; 302 | } 303 | None => {} 304 | } 305 | return (server_count, message_count); 306 | } 307 | 308 | // receive blocking, also heap allocates into the queue 309 | pub fn receive_blocking(&mut self) { 310 | self.servers.par_iter_mut().for_each(|(_key, server)| { 311 | let receive_queue_clone = self.receive_queue.clone(); 312 | let receive_buffers_clone = self.receive_buffers.clone(); 313 | 314 | if let Some(mut receive_queue) = receive_queue_clone.pop() { 315 | if let Some(mut receive_buffer) = receive_buffers_clone.pop() { 316 | Pool::receive_server(server, &mut receive_queue, &mut receive_buffer); 317 | receive_buffers_clone.push(receive_buffer).unwrap_or_default(); 318 | } 319 | receive_queue_clone.push(receive_queue).unwrap_or_default(); 320 | } 321 | }); 322 | self.move_received_to_published(); 323 | } 324 | 325 | 326 | // blocking receive with more complex api. messages are copied to a single out buffer with length and ip address prefixed. 327 | pub fn receive_blocking_out_buffer(&mut self) { 328 | self.servers.par_iter_mut().for_each(|(_key, server)| { 329 | let receive_buffers_clone = self.receive_buffers.clone(); 330 | let out_buffers_clone = self.out_buffers.clone(); 331 | 332 | if let Some(mut out_buffer) = out_buffers_clone.pop() { 333 | out_buffer.bytes_written = 0; 334 | out_buffer.count = 0; 335 | 336 | if let Some(mut receive_buffer) = receive_buffers_clone.pop() { 337 | Pool::receive_server_into_out_buffer(server, &mut out_buffer, &mut receive_buffer); 338 | receive_buffers_clone.push(receive_buffer).unwrap_or_default(); 339 | } 340 | out_buffers_clone.push(out_buffer).unwrap_or_default(); 341 | } 342 | }); 343 | } 344 | 345 | fn receive_server_into_out_buffer(server: &mut Tachyon, out_buffer: &mut OutBuffer, receive_buffer: &mut Vec) { 346 | let mut writer = LengthPrefixed::default(); 347 | for _ in 0..100000 { 348 | let res = server.receive_loop(receive_buffer); 349 | if res.length == 0 || res.error > 0 { 350 | out_buffer.bytes_written = writer.writer.index as u32; 351 | break; 352 | } else { 353 | writer.write(res.channel,res.address,&receive_buffer[0..res.length as usize], &mut out_buffer.data); 354 | out_buffer.count += 1; 355 | } 356 | } 357 | } 358 | 359 | pub fn get_next_out_buffer(&mut self, receive_buffer: &mut [u8]) -> OutBufferCounts { 360 | let mut result = OutBufferCounts::default(); 361 | 362 | for _ in 0..self.out_buffers.len() { 363 | if let Some(mut out_buffer) = self.out_buffers.pop() { 364 | if out_buffer.count == 0 { 365 | self.out_buffers.push(out_buffer).unwrap_or_default(); 366 | continue; 367 | } 368 | 369 | receive_buffer[0..out_buffer.bytes_written as usize].copy_from_slice(&out_buffer.data[0..out_buffer.bytes_written as usize]); 370 | 371 | result.count = out_buffer.count; 372 | result.bytes_written = out_buffer.bytes_written; 373 | 374 | out_buffer.bytes_written = 0; 375 | out_buffer.count = 0; 376 | 377 | self.out_buffers.push(out_buffer).unwrap_or_default(); 378 | 379 | return result; 380 | } 381 | } 382 | return result; 383 | } 384 | 385 | } 386 | 387 | #[cfg(test)] 388 | mod tests { 389 | use serial_test::serial; 390 | 391 | use crate::tachyon::{ 392 | network_address::NetworkAddress, 393 | tachyon_test::{TachyonTestClient}, 394 | TachyonConfig, int_buffer::{IntBuffer, LengthPrefixed} 395 | }; 396 | use std::{ 397 | time::Instant, 398 | }; 399 | 400 | use super::Pool; 401 | 402 | #[test] 403 | #[serial] 404 | fn test_blocking_receive() { 405 | let mut pool = Pool::create(40, 1024 * 1024, 1024 * 1024 * 4); 406 | let config = TachyonConfig::default(); 407 | pool.create_server(config, NetworkAddress::localhost(8001),1); 408 | pool.create_server(config, NetworkAddress::localhost(8002),2); 409 | pool.create_server(config, NetworkAddress::localhost(8003),3); 410 | 411 | let mut id = 4; 412 | for i in 0..20 { 413 | pool.create_server(config, NetworkAddress::localhost(8004 + i), id); 414 | id += 1; 415 | } 416 | 417 | let mut client1 = TachyonTestClient::create(NetworkAddress::localhost(8001)); 418 | let mut client2 = TachyonTestClient::create(NetworkAddress::localhost(8002)); 419 | let mut client3 = TachyonTestClient::create(NetworkAddress::localhost(8003)); 420 | client1.connect(); 421 | client2.connect(); 422 | client3.connect(); 423 | 424 | let count: usize = 2000; 425 | let msg_len = 64; 426 | let msg_value = 234873; 427 | 428 | for _ in 0..count { 429 | let mut writer = IntBuffer {index: 0}; 430 | writer.write_u32(msg_value, &mut client1.send_buffer); 431 | client1.client_send_reliable(1, msg_len); 432 | 433 | let mut writer = IntBuffer {index: 0}; 434 | writer.write_u32(msg_value, &mut client2.send_buffer); 435 | client2.client_send_reliable(1, msg_len); 436 | 437 | let mut writer = IntBuffer {index: 0}; 438 | writer.write_u32(msg_value, &mut client3.send_buffer); 439 | client3.client_send_reliable(1, msg_len); 440 | } 441 | 442 | let now = Instant::now(); 443 | pool.receive_blocking_out_buffer(); 444 | 445 | let elapsed = now.elapsed(); 446 | println!("Elapsed: {:.2?}", elapsed); 447 | 448 | // should have 3 out buffers to read 449 | let mut receive_buffer: Vec = vec![0;1024 * 1024 * 4]; 450 | let res = pool.get_next_out_buffer(&mut receive_buffer); 451 | println!("bytes_written:{0} count:{1}", res.bytes_written, res.count); 452 | 453 | 454 | 455 | // length + channel + address + body 456 | let bytes_written = count * msg_len + count * 4 + count * 14; 457 | assert_eq!(res.bytes_written, bytes_written as u32); 458 | assert_eq!(count, res.count as usize); 459 | 460 | let mut reader = LengthPrefixed::default(); 461 | for _ in 0..res.count { 462 | let (_channel,_address,range) = reader.read(&receive_buffer); 463 | let len = range.end - range.start; 464 | //println!("len:{0} address:{1}", len, address); 465 | 466 | assert_eq!(msg_len, len as usize); 467 | let slice = &receive_buffer[range]; 468 | 469 | let mut value_reader = IntBuffer {index: 0}; 470 | let value = value_reader.read_u32(slice); 471 | assert_eq!(msg_value, value); 472 | } 473 | 474 | let res = pool.get_next_out_buffer(&mut receive_buffer); 475 | assert_eq!(res.bytes_written, bytes_written as u32); 476 | assert_eq!(count, res.count as usize); 477 | 478 | let res = pool.get_next_out_buffer(&mut receive_buffer); 479 | assert_eq!(res.bytes_written, bytes_written as u32); 480 | assert_eq!(count, res.count as usize); 481 | 482 | let res = pool.get_next_out_buffer(&mut receive_buffer); 483 | assert_eq!(res.bytes_written, 0); 484 | assert_eq!(0, res.count as usize); 485 | 486 | // servers and arrays returned 487 | assert_eq!(pool.max_servers as usize, pool.out_buffers.len()); 488 | assert_eq!(23, pool.servers.len()); 489 | 490 | } 491 | 492 | #[test] 493 | #[serial] 494 | fn test_receive() { 495 | let mut pool = Pool::create(4, 1024 * 1024, 1024 * 1024 * 4); 496 | let config = TachyonConfig::default(); 497 | pool.create_server(config, NetworkAddress::localhost(8001),1); 498 | pool.create_server(config, NetworkAddress::localhost(8002),2); 499 | pool.create_server(config, NetworkAddress::localhost(8003),3); 500 | 501 | let mut client1 = TachyonTestClient::create(NetworkAddress::localhost(8001)); 502 | let mut client2 = TachyonTestClient::create(NetworkAddress::localhost(8002)); 503 | let mut client3 = TachyonTestClient::create(NetworkAddress::localhost(8003)); 504 | client1.connect(); 505 | client2.connect(); 506 | client3.connect(); 507 | 508 | let count = 200; 509 | let msg_len = 64; 510 | let msg_value = 234873; 511 | for _ in 0..count { 512 | let mut writer = IntBuffer {index: 0}; 513 | writer.write_u32(msg_value, &mut client1.send_buffer); 514 | client1.client_send_reliable(1, msg_len); 515 | 516 | let mut writer = IntBuffer {index: 0}; 517 | writer.write_u32(msg_value, &mut client2.send_buffer); 518 | client2.client_send_reliable(1, msg_len); 519 | 520 | let mut writer = IntBuffer {index: 0}; 521 | writer.write_u32(msg_value, &mut client3.send_buffer); 522 | client3.client_send_reliable(1, msg_len); 523 | } 524 | 525 | let now = Instant::now(); 526 | let receiving = pool.receive(); 527 | assert!(receiving); 528 | 529 | // should return false, all servers moved 530 | let receiving = pool.receive(); 531 | assert!(!receiving); 532 | 533 | let res = pool.finish_receive(); 534 | assert_eq!(3, res.0); 535 | assert_eq!(count * 3, res.1); 536 | assert_eq!(count * 3, pool.published.len() as i32); 537 | 538 | // nothing to finish 539 | let res = pool.finish_receive(); 540 | assert_eq!(0, res.0); 541 | assert_eq!(0, res.1); 542 | 543 | let elapsed = now.elapsed(); 544 | println!("Elapsed: {:.2?}", elapsed); 545 | 546 | } 547 | 548 | 549 | } 550 | -------------------------------------------------------------------------------- /src/tachyon/pool_ffi.rs: -------------------------------------------------------------------------------- 1 | 2 | use crate::tachyon::*; 3 | use super::{pool::{Pool, PoolServerRef, OutBufferCounts, SendTarget}, ffi::copy_send_result}; 4 | 5 | #[no_mangle] 6 | pub extern "C" fn pool_create(max_servers: u8, receive_buffer_len: u32, out_buffer_len: u32) -> *mut Pool { 7 | let pool = Pool::create(max_servers, receive_buffer_len, out_buffer_len); 8 | let b = Box::new(pool); 9 | return Box::into_raw(b); 10 | } 11 | 12 | #[no_mangle] 13 | pub extern "C" fn pool_destroy(pool: *mut Pool) { 14 | if !pool.is_null() { 15 | let _b = unsafe { Box::from_raw(pool) }; 16 | } 17 | } 18 | 19 | #[no_mangle] 20 | pub extern "C" fn pool_create_server(pool_ptr: *mut Pool, config_ptr: *const TachyonConfig, naddress: *const NetworkAddress, id: u16) -> i32 { 21 | let pool = unsafe { &mut *pool_ptr }; 22 | let config: TachyonConfig = unsafe { std::ptr::read(config_ptr as *const _) }; 23 | let address: NetworkAddress = unsafe { std::ptr::read(naddress as *const _) }; 24 | match pool.create_server(config, address, id) { 25 | true => {return 1;}, 26 | false => { return -1;}, 27 | } 28 | } 29 | 30 | 31 | #[no_mangle] 32 | pub extern "C" fn pool_configure_channel(pool_ptr: *mut Pool, server_id: u16, channel_id: u8, config_ptr: *const ChannelConfig) -> i32 { 33 | let pool = unsafe { &mut *pool_ptr }; 34 | if let Some(tachyon) = pool.get_server(server_id) { 35 | let channel_config = unsafe { &*config_ptr }; 36 | let res = tachyon.configure_channel(channel_id, *channel_config); 37 | if res { 38 | return 1; 39 | } else { 40 | return -1; 41 | } 42 | } 43 | return -1; 44 | } 45 | 46 | #[no_mangle] 47 | pub extern "C" fn pool_get_available(pool_ptr: *mut Pool, pool_ref_ptr: *mut PoolServerRef) -> i32 { 48 | let pool = unsafe { &mut *pool_ptr }; 49 | 50 | match pool.get_available_server() { 51 | Some(pool_ref) => { 52 | unsafe { 53 | (*pool_ref_ptr) = pool_ref; 54 | } 55 | return 1; 56 | } 57 | None => return -1, 58 | } 59 | } 60 | 61 | #[no_mangle] 62 | pub extern "C" fn pool_get_server_having_connection(pool_ptr: *mut Pool, naddress: *const NetworkAddress) -> u16 { 63 | let pool = unsafe { &mut *pool_ptr }; 64 | let address: NetworkAddress = unsafe { std::ptr::read(naddress as *const _) }; 65 | return pool.get_server_having_connection(address); 66 | } 67 | 68 | #[no_mangle] 69 | pub extern "C" fn pool_get_server_having_identity(pool_ptr: *mut Pool, id: u32) -> u16 { 70 | let pool = unsafe { &mut *pool_ptr }; 71 | 72 | return pool.get_server_having_identity(id); 73 | } 74 | 75 | #[no_mangle] 76 | pub extern "C" fn pool_set_identity(pool_ptr: *mut Pool, server_id: u16, id: u32, session_id: u32, on_self: u32) { 77 | let pool = unsafe { &mut *pool_ptr }; 78 | pool.set_identity(server_id, id, session_id, on_self); 79 | } 80 | 81 | #[no_mangle] 82 | pub extern "C" fn pool_update_servers(pool_ptr: *mut Pool) { 83 | let pool = unsafe { &mut *pool_ptr }; 84 | for server in pool.servers.values_mut() { 85 | server.update(); 86 | } 87 | pool.build_connection_maps(); 88 | } 89 | 90 | #[no_mangle] 91 | pub extern "C" fn pool_register_callbacks(pool_ptr: *mut Pool, identity_event_callback: Option, 92 | connection_event_callback: Option) { 93 | 94 | let pool = unsafe { &mut *pool_ptr }; 95 | for server in pool.servers.values_mut() { 96 | if identity_event_callback.is_some() { 97 | server.identity_event_callback = identity_event_callback; 98 | } 99 | 100 | if connection_event_callback.is_some() { 101 | server.connection_event_callback = connection_event_callback; 102 | } 103 | } 104 | } 105 | 106 | #[no_mangle] 107 | pub extern "C" fn pool_receive_blocking(pool_ptr: *mut Pool) { 108 | let pool = unsafe { &mut *pool_ptr }; 109 | pool.receive_blocking_out_buffer(); 110 | } 111 | 112 | #[no_mangle] 113 | pub extern "C" fn pool_get_next_out_buffer(pool_ptr: *mut Pool, receive_buffer_ptr: *mut u8, result: *mut OutBufferCounts) { 114 | let pool = unsafe { &mut *pool_ptr }; 115 | let slice = unsafe { std::slice::from_raw_parts_mut(receive_buffer_ptr, pool.receive_buffer_len as usize) }; 116 | let res = pool.get_next_out_buffer(slice); 117 | unsafe { 118 | (*result) = res; 119 | } 120 | } 121 | 122 | #[no_mangle] 123 | pub extern "C" fn pool_receive(pool_ptr: *mut Pool) -> i32 { 124 | let pool = unsafe { &mut *pool_ptr }; 125 | if pool.receive() { 126 | return 1; 127 | } else { 128 | return -1; 129 | } 130 | } 131 | 132 | #[no_mangle] 133 | pub extern "C" fn pool_finish_receive(pool_ptr: *mut Pool) -> i32 { 134 | let pool = unsafe { &mut *pool_ptr }; 135 | let result = pool.finish_receive(); 136 | return result.1; 137 | } 138 | 139 | #[no_mangle] 140 | pub extern "C" fn pool_send_to(pool_ptr: *mut Pool, channel: u8, target_ptr: *const SendTarget, data: *mut u8, length: i32, ret: *mut TachyonSendResult) { 141 | let pool = unsafe { &mut *pool_ptr }; 142 | 143 | let target: SendTarget = unsafe { std::ptr::read(target_ptr as *const _) }; 144 | let slice = unsafe { std::slice::from_raw_parts_mut(data, length as usize) }; 145 | 146 | let result = pool.send_to_target(channel, target, slice, length); 147 | copy_send_result(result, ret); 148 | } 149 | 150 | 151 | -------------------------------------------------------------------------------- /src/tachyon/pool_unreliable_sender.rs: -------------------------------------------------------------------------------- 1 | use rustc_hash::FxHashMap; 2 | 3 | use super::{ 4 | pool::{Pool, SendTarget}, TachyonSendResult, network_address::NetworkAddress, connection::Connection, unreliable_sender::UnreliableSender, ffi::copy_send_result 5 | }; 6 | 7 | pub struct PoolUnreliableSender { 8 | pub identity_to_conn_map: FxHashMap, 9 | pub address_to_conn_map: FxHashMap, 10 | pub senders: FxHashMap 11 | } 12 | 13 | impl PoolUnreliableSender { 14 | pub fn create() -> Self { 15 | PoolUnreliableSender { 16 | identity_to_conn_map: FxHashMap::default(), 17 | address_to_conn_map: FxHashMap::default(), 18 | senders: FxHashMap::default() 19 | } 20 | } 21 | 22 | pub fn send_to_target(&mut self, target: SendTarget, data: &mut [u8], length: i32) -> TachyonSendResult { 23 | if target.identity_id > 0 { 24 | return self.send_to_identity(target.identity_id, data, length); 25 | } else { 26 | return self.send_to_address(target.address, data, length); 27 | } 28 | } 29 | 30 | fn send_to_identity(&mut self, id: u32, data: &mut [u8], length: i32) -> TachyonSendResult { 31 | if let Some(conn) = self.identity_to_conn_map.get(&id) { 32 | if let Some(sender) = self.senders.get_mut(&conn.tachyon_id) { 33 | return sender.send(conn.address, data, length as usize); 34 | } 35 | } 36 | return TachyonSendResult::default(); 37 | } 38 | 39 | fn send_to_address(&mut self, address: NetworkAddress, data: &mut [u8], length: i32) -> TachyonSendResult { 40 | if let Some(conn) = self.address_to_conn_map.get(&address) { 41 | if let Some(sender) = self.senders.get_mut(&conn.tachyon_id) { 42 | return sender.send(address, data, length as usize); 43 | } 44 | } 45 | return TachyonSendResult::default(); 46 | } 47 | 48 | pub fn build(&mut self, pool: &mut Pool) { 49 | self.address_to_conn_map.clear(); 50 | self.identity_to_conn_map.clear(); 51 | self.senders.clear(); 52 | 53 | for server in pool.servers.values() { 54 | if !self.senders.contains_key(&server.id) { 55 | if let Some(sender) = server.create_unreliable_sender() { 56 | self.senders.insert(server.id, sender); 57 | } 58 | } 59 | for conn in server.connections.values() { 60 | self.address_to_conn_map.insert(conn.address, *conn); 61 | if conn.identity.id > 0 { 62 | self.identity_to_conn_map.insert(conn.identity.id, *conn); 63 | } 64 | } 65 | } 66 | } 67 | } 68 | 69 | #[no_mangle] 70 | pub extern "C" fn pool_unreliable_sender_create(pool_ptr: *mut Pool) -> *mut PoolUnreliableSender { 71 | let pool = unsafe { &mut *pool_ptr }; 72 | let mut sender = PoolUnreliableSender::create(); 73 | sender.build(pool); 74 | 75 | let b = Box::new(sender); 76 | return Box::into_raw(b); 77 | } 78 | 79 | #[no_mangle] 80 | pub extern "C" fn pool_unreliable_sender_destroy(pool: *mut PoolUnreliableSender) { 81 | if !pool.is_null() { 82 | let _b = unsafe { Box::from_raw(pool) }; 83 | } 84 | } 85 | 86 | #[no_mangle] 87 | pub extern "C" fn pool_unreliable_sender_build(pool_ptr: *mut Pool, sender_ptr: *mut PoolUnreliableSender) { 88 | let pool = unsafe { &mut *pool_ptr }; 89 | let sender = unsafe { &mut *sender_ptr }; 90 | sender.build(pool) 91 | } 92 | 93 | #[no_mangle] 94 | pub extern "C" fn pool_unreliable_sender_send(sender_ptr: *mut PoolUnreliableSender, target_ptr: *const SendTarget, data_ptr: *mut u8, length: i32, ret: *mut TachyonSendResult) { 95 | let sender = unsafe { &mut *sender_ptr }; 96 | let target: SendTarget = unsafe { std::ptr::read(target_ptr as *const _) }; 97 | let data = unsafe { std::slice::from_raw_parts_mut(data_ptr, length as usize) }; 98 | 99 | let result = sender.send_to_target(target, data, length); 100 | copy_send_result(result, ret); 101 | } 102 | -------------------------------------------------------------------------------- /src/tachyon/receive_result.rs: -------------------------------------------------------------------------------- 1 | use super::network_address::NetworkAddress; 2 | 3 | pub const RECEIVE_ERROR_UNKNOWN: u32 = 1; 4 | pub const RECEIVE_ERROR_CHANNEL: u32 = 2; 5 | 6 | pub enum ReceiveResult { 7 | Reliable { 8 | network_address: NetworkAddress, 9 | channel_id: u8, 10 | }, 11 | Error, 12 | Empty, 13 | Retry, 14 | ChannelError, 15 | UnReliable { 16 | received_len: usize, 17 | network_address: NetworkAddress, 18 | }, 19 | } 20 | 21 | #[repr(C)] 22 | #[derive(Default)] 23 | #[derive(Clone, Copy)] 24 | pub struct TachyonReceiveResult { 25 | pub channel: u16, 26 | pub address: NetworkAddress, 27 | pub length: u32, 28 | pub error: u32, 29 | } 30 | 31 | impl TachyonReceiveResult { 32 | pub fn default() -> Self { 33 | let result = TachyonReceiveResult { 34 | channel: 0, 35 | address: NetworkAddress::default(), 36 | length: 0, 37 | error: 0, 38 | }; 39 | return result; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/tachyon/receiver.rs: -------------------------------------------------------------------------------- 1 | 2 | use std::collections::VecDeque; 3 | 4 | use super::{nack::Nack, sequence::*, sequence_buffer::SequenceBuffer, channel::RECEIVE_WINDOW_SIZE_DEFAULT, byte_buffer_pool::{ByteBuffer, ByteBufferPool}}; 5 | 6 | const RECEIVE_BUFFER_SIZE: u16 = 1024; 7 | 8 | 9 | pub struct Receiver { 10 | pub is_ordered: bool, 11 | pub receive_window_size: u32, 12 | pub last_sequence: u16, 13 | pub current_sequence: u16, 14 | pub buffered: SequenceBuffer, 15 | pub published: VecDeque, 16 | pub received: SequenceBuffer, 17 | pub resend_list: Vec, 18 | pub nack_list: Vec, 19 | pub nack_queue: VecDeque, 20 | pub skipped_sequences: u64, 21 | pub buffer_pool: ByteBufferPool 22 | } 23 | 24 | impl Receiver { 25 | pub fn create(is_ordered: bool, receive_window_size: u32) -> Self { 26 | let mut buffered: SequenceBuffer = SequenceBuffer { 27 | values: Vec::new(), 28 | partition_by: RECEIVE_BUFFER_SIZE, 29 | }; 30 | for i in 0..RECEIVE_BUFFER_SIZE { 31 | buffered.values.insert(i as usize, None); 32 | } 33 | 34 | let received: SequenceBuffer = SequenceBuffer { 35 | values: vec![None; RECEIVE_BUFFER_SIZE as usize], 36 | partition_by: RECEIVE_BUFFER_SIZE, 37 | }; 38 | 39 | let receiver = Receiver { 40 | is_ordered, 41 | receive_window_size, 42 | last_sequence: 0, 43 | current_sequence: 0, 44 | buffered, 45 | published: VecDeque::new(), 46 | received, 47 | resend_list: Vec::new(), 48 | nack_list: Vec::new(), 49 | skipped_sequences: 0, 50 | nack_queue: VecDeque::new(), 51 | buffer_pool: ByteBufferPool::default() 52 | }; 53 | 54 | return receiver; 55 | } 56 | 57 | pub fn default(is_ordered: bool) -> Self { 58 | return Receiver::create(is_ordered, RECEIVE_WINDOW_SIZE_DEFAULT); 59 | } 60 | 61 | pub fn calculate_current_in_window(current: u16, last: u16) -> u16 { 62 | if current == last { 63 | return current; 64 | } 65 | 66 | let mut start: i32 = (last as i32 - RECEIVE_WINDOW_SIZE_DEFAULT as i32) as i32; 67 | if start < 0 { 68 | start = std::u16::MAX as i32 + start; 69 | } 70 | 71 | if Sequence::is_greater_then(start as u16, current) { 72 | return start as u16; 73 | } else { 74 | return current; 75 | } 76 | } 77 | pub fn should_increment_current(current: u16, last: u16, receive_window_size: u32) -> bool { 78 | if current == last { 79 | return false; 80 | } 81 | 82 | let mut start: i32 = (last as i32 - receive_window_size as i32) as i32; 83 | if start < 0 { 84 | start = std::u16::MAX as i32 + start; 85 | } 86 | 87 | if Sequence::is_greater_then(start as u16, current) { 88 | return true; 89 | } else { 90 | return false; 91 | } 92 | } 93 | 94 | pub fn return_buffer(&mut self, byte_buffer: ByteBuffer) { 95 | self.buffer_pool.return_buffer(byte_buffer); 96 | } 97 | 98 | pub fn take_published(&mut self) -> Option { 99 | return self.published.pop_front(); 100 | } 101 | 102 | fn is_buffered(&self, sequence: u16) -> bool { 103 | return self.buffered.is_some(sequence); 104 | } 105 | 106 | pub fn is_received(&self, sequence: u16) -> bool { 107 | return self.received.is_some(sequence); 108 | } 109 | 110 | fn set_received(&mut self, sequence: u16) { 111 | self.received.insert(sequence, true); 112 | } 113 | 114 | fn set_buffered(&mut self, sequence: u16, data: &[u8], length: usize) { 115 | let mut byte_buffer = self.buffer_pool.get_buffer(length); 116 | byte_buffer.get_mut()[0..length].copy_from_slice(&data[0..length]); 117 | self.buffered.insert(sequence, byte_buffer); 118 | } 119 | 120 | // Note: we use current sequence increments to mark previous as not received. 121 | // This forces current to only ever increment by 1. Ie we can't just adjust our window forward 122 | // in big steps for example or we would leave a bunch of entries < current still marked as received. 123 | 124 | pub fn receive_packet(&mut self, sequence: u16, data: &[u8], length: usize) -> bool { 125 | // if the difference between current/last is greater then the window, increment current. 126 | if Receiver::should_increment_current(self.current_sequence, self.last_sequence, self.receive_window_size) { 127 | self.received.take(self.current_sequence); 128 | self.current_sequence = Sequence::next_sequence(self.current_sequence); 129 | self.skipped_sequences += 1; 130 | } 131 | 132 | if !Sequence::is_greater_then(sequence, self.current_sequence) { 133 | return false; 134 | } 135 | 136 | if Sequence::is_greater_then(sequence, self.last_sequence) { 137 | self.last_sequence = sequence; 138 | } 139 | 140 | let next = Sequence::next_sequence(self.current_sequence); 141 | if sequence == next { 142 | let last_sequence = self.current_sequence; 143 | self.current_sequence = sequence; 144 | self.received.remove(last_sequence); 145 | } 146 | 147 | // resends can be higher then current and already received. 148 | if self.is_received(sequence) { 149 | return false; 150 | } else { 151 | self.set_buffered(sequence, data, length); 152 | self.set_received(sequence); 153 | } 154 | 155 | self.publish(); 156 | 157 | return true; 158 | } 159 | 160 | pub fn publish(&mut self) { 161 | // walk from current to last and move buffered into published 162 | // increment current sequence until we hit a missing sequence. 163 | // on missing, ordered channel breaks out it's done. 164 | // unordered channel keep moving buffered to published 165 | 166 | let start = self.current_sequence; 167 | let end = Sequence::next_sequence(self.last_sequence); 168 | let mut step_sequence = true; 169 | let mut seq = start; 170 | 171 | for _ in 0..self.receive_window_size { 172 | if self.is_received(seq) { 173 | if self.current_sequence == seq { 174 | self.received.remove(seq); 175 | } else if step_sequence && Sequence::is_greater_then(seq, self.current_sequence) { 176 | self.current_sequence = seq; 177 | self.received.remove(seq); 178 | } 179 | 180 | if self.is_buffered(seq) { 181 | match self.buffered.take(seq) { 182 | Some(byte_buffer) => { 183 | self.published.push_back(byte_buffer); 184 | } 185 | None => {} 186 | } 187 | } 188 | } else { 189 | if self.is_ordered { 190 | break; 191 | } else { 192 | step_sequence = false; 193 | } 194 | } 195 | seq = Sequence::next_sequence(seq); 196 | if seq == end { 197 | break; 198 | } 199 | } 200 | } 201 | 202 | pub fn set_resend_list(&mut self) { 203 | self.resend_list.clear(); 204 | 205 | if self.current_sequence == self.last_sequence { 206 | return; 207 | } 208 | 209 | let start = Sequence::previous_sequence(self.last_sequence); 210 | let end = self.current_sequence; 211 | 212 | let mut seq = start; 213 | 214 | for _ in 0..self.receive_window_size { 215 | if !self.is_received(seq) { 216 | self.resend_list.push(seq); 217 | } 218 | 219 | seq = Sequence::previous_sequence(seq); 220 | if seq == end { 221 | break; 222 | } 223 | } 224 | } 225 | 226 | pub fn create_nacks(&mut self) -> u32 { 227 | self.nack_list.clear(); 228 | self.nack_queue.clear(); 229 | 230 | let mut nacked_count = 0; 231 | let mut seq = Sequence::previous_sequence(self.last_sequence); 232 | if Sequence::is_equal_to_or_less_than(seq, self.current_sequence) { 233 | return nacked_count; 234 | } 235 | 236 | let count = self.receive_window_size / 32; 237 | 238 | for _ in 0..count { 239 | 240 | if Sequence::is_equal_to_or_less_than(seq, self.current_sequence) { 241 | return nacked_count; 242 | } 243 | 244 | if self.is_received(seq) { 245 | seq = Sequence::previous_sequence(seq); 246 | if Sequence::is_equal_to_or_less_than(seq, self.current_sequence) { 247 | return nacked_count; 248 | } 249 | continue; 250 | } 251 | 252 | let mut current = Nack::default(); 253 | current.start_sequence = seq; 254 | nacked_count += 1; 255 | current.nacked_count = nacked_count; 256 | 257 | for i in 0..32 { 258 | seq = Sequence::previous_sequence(seq); 259 | 260 | if Sequence::is_equal_to_or_less_than(seq, self.current_sequence) { 261 | self.nack_list.push(current); 262 | self.nack_queue.push_back(current); 263 | return nacked_count; 264 | } 265 | 266 | if !self.is_received(seq) { 267 | current.set_bits(i, true); 268 | nacked_count += 1; 269 | current.nacked_count = nacked_count; 270 | } 271 | } 272 | self.nack_list.push(current); 273 | self.nack_queue.push_back(current); 274 | 275 | seq = Sequence::previous_sequence(seq); 276 | 277 | } 278 | return nacked_count; 279 | } 280 | 281 | } 282 | 283 | #[cfg(test)] 284 | mod tests { 285 | 286 | use crate::tachyon::{receiver::*}; 287 | 288 | pub fn is_nacked(receiver: &Receiver, sequence: u16) -> bool { 289 | for nack in &receiver.nack_list { 290 | if nack.is_nacked(sequence) { 291 | return true; 292 | } 293 | } 294 | return false; 295 | } 296 | 297 | fn assert_nack(receiver: &mut Receiver, sequence: u16) { 298 | if receiver.is_received(sequence) || sequence >= receiver.last_sequence || sequence <= receiver.current_sequence { 299 | if is_nacked(receiver, sequence) { 300 | panic!("{0} is nacked", sequence); 301 | } else { 302 | //println!("{0} not nacked", sequence); 303 | } 304 | } else { 305 | if !is_nacked(receiver,sequence) { 306 | panic!("{0} not nacked", sequence); 307 | } else { 308 | //println!("{0} nacked", sequence); 309 | } 310 | } 311 | } 312 | 313 | #[test] 314 | fn test_all_nacked() { 315 | let mut channel = Receiver::default(true); 316 | channel.current_sequence = 0; 317 | channel.last_sequence = 512; 318 | 319 | 320 | let nack_count = channel.create_nacks(); 321 | assert_eq!(16, channel.nack_list.len()); 322 | assert_eq!(511, nack_count); 323 | 324 | for i in 0..512 { 325 | assert_nack(&mut channel, i); 326 | } 327 | } 328 | 329 | #[test] 330 | fn test_some_nacked() { 331 | let mut channel = Receiver::default(true); 332 | channel.current_sequence = 0; 333 | channel.last_sequence = 64; 334 | 335 | channel.set_received(63); 336 | channel.set_received(63 - 32); 337 | channel.set_received(63 - 33); 338 | channel.set_received(1); 339 | let nacked_count = channel.create_nacks(); 340 | 341 | assert_eq!(2, channel.nack_list.len()); 342 | assert_eq!(63 - 4, nacked_count); 343 | 344 | for i in 0..66 { 345 | assert_nack(&mut channel,i); 346 | 347 | } 348 | } 349 | 350 | #[test] 351 | fn test_skipped() { 352 | let mut channel = Receiver::default(true); 353 | let data: Vec = vec![0; 1024]; 354 | channel.current_sequence = 0; 355 | channel.last_sequence = 512 + 10; 356 | 357 | // should skip and take received 358 | channel.set_received(0); 359 | assert!(!channel.receive_packet(1, &data[..], 32)); 360 | assert!(!channel.is_received(0)); 361 | assert_eq!(1, channel.current_sequence); 362 | 363 | assert!(!channel.receive_packet(1, &data[..], 32)); 364 | assert_eq!(2, channel.current_sequence); 365 | } 366 | 367 | #[test] 368 | fn test_reset_receive_window() { 369 | assert_eq!(65530, Receiver::calculate_current_in_window(65530, 100)); 370 | assert_eq!(0, Receiver::calculate_current_in_window(0, 512)); 371 | assert_eq!(10, Receiver::calculate_current_in_window(0, 512 + 10)); 372 | assert_eq!(1, Receiver::calculate_current_in_window(0, 513)); 373 | assert_eq!(0, Receiver::calculate_current_in_window(65533, 512)); 374 | } 375 | 376 | #[test] 377 | fn wrapping_in_order() { 378 | let mut channel = Receiver::default(true); 379 | channel.current_sequence = 65533; 380 | let data: Vec = vec![0; 1024]; 381 | 382 | let receive_result = channel.receive_packet(65534, &data[..], 32); 383 | assert!(receive_result); 384 | 385 | assert_eq!(65534, channel.current_sequence); 386 | assert_eq!(1, channel.published.len()); 387 | 388 | let receive_result = channel.receive_packet(0, &data[..], 32); 389 | assert!(receive_result); 390 | assert_eq!(0, channel.current_sequence); 391 | assert_eq!(0, channel.last_sequence); 392 | assert!((channel.take_published().is_some())); 393 | 394 | let receive_result = channel.receive_packet(1, &data[..], 32); 395 | assert!(receive_result); 396 | assert_eq!(1, channel.current_sequence); 397 | assert!((channel.take_published().is_some())); 398 | 399 | let receive_result = channel.receive_packet(2, &data[..], 32); 400 | assert!(receive_result); 401 | assert_eq!(2, channel.last_sequence); 402 | assert_eq!(2, channel.current_sequence); 403 | assert!((channel.take_published().is_some())); 404 | } 405 | 406 | #[test] 407 | fn wrapping_out_of_order() { 408 | let mut channel = Receiver::default(true); 409 | channel.current_sequence = 65533; 410 | let data: Vec = vec![0; 1024]; 411 | let receive_result = channel.receive_packet(65534, &data[..], 32); 412 | assert!(receive_result); 413 | assert_eq!(65534, channel.current_sequence); 414 | let receive_result = channel.receive_packet(2, &data[..], 32); 415 | assert!(receive_result); 416 | assert_eq!(65534, channel.current_sequence); 417 | assert_eq!(2, channel.last_sequence); 418 | let receive_result = channel.receive_packet(1, &data[..], 32); 419 | assert!(receive_result); 420 | assert_eq!(65534, channel.current_sequence); 421 | 422 | let receive_result = channel.receive_packet(0, &data[..], 32); 423 | assert!(receive_result); 424 | assert_eq!(2, channel.last_sequence); 425 | assert_eq!(2, channel.current_sequence); 426 | } 427 | 428 | 429 | #[test] 430 | fn full_wrap() { 431 | let mut channel = Receiver::default(true); 432 | let data: Vec = vec![0; 1024]; 433 | 434 | let mut sequence = 1; 435 | for _ in 1..200000 { 436 | let _receive_result = channel.receive_packet(sequence, &data[..], 32); 437 | if channel.current_sequence != sequence { 438 | print!( 439 | "{0} {1} {2}\n", 440 | sequence, channel.current_sequence, channel.last_sequence 441 | ); 442 | panic!(); 443 | } 444 | assert!(channel.take_published().is_some()); 445 | 446 | sequence = Sequence::next_sequence(sequence); 447 | } 448 | } 449 | 450 | #[test] 451 | fn publish_consume_publish() { 452 | let mut channel = Receiver::default(true); 453 | let data: Vec = vec![0; 1024]; 454 | let _receive_result = channel.receive_packet(1, &data[..], 32); 455 | let _receive_result = channel.receive_packet(2, &data[..], 32); 456 | assert!((channel.take_published().is_some())); 457 | assert!((channel.take_published().is_some())); 458 | assert!((channel.take_published().is_none())); 459 | 460 | let _receive_result = channel.receive_packet(4, &data[..], 32); 461 | let _receive_result = channel.receive_packet(3, &data[..], 32); 462 | assert!((channel.take_published().is_some())); 463 | assert!((channel.take_published().is_some())); 464 | assert!((channel.take_published().is_none())); 465 | 466 | let _receive_result = channel.receive_packet(5, &data[..], 32); 467 | assert!((channel.take_published().is_some())); 468 | assert!((channel.take_published().is_none())); 469 | 470 | assert_eq!(0, channel.published.len()); 471 | } 472 | 473 | #[test] 474 | fn receive_older_fails() { 475 | let mut channel = Receiver::default(true); 476 | let data: Vec = vec![0; 1024]; 477 | let receive_result = channel.receive_packet(1, &data[..], 32); 478 | assert!(receive_result); 479 | let receive_result = channel.receive_packet(1, &data[..], 32); 480 | assert!(!receive_result); 481 | let receive_result = channel.receive_packet(0, &data[..], 32); 482 | assert!(!receive_result); 483 | } 484 | 485 | #[test] 486 | #[allow(dead_code)] 487 | fn ordered_flow_test() { 488 | let mut channel = Receiver::default(true); 489 | let data: Vec = vec![0; 1024]; 490 | let receive_result = channel.receive_packet(1, &data[..], 32); 491 | assert!(receive_result); 492 | assert_eq!(1, channel.published.len()); 493 | 494 | let receive_result = channel.receive_packet(5, &data[..], 32); 495 | assert!(receive_result); 496 | assert_eq!(1, channel.published.len()); 497 | assert_eq!(1, channel.current_sequence); 498 | assert_eq!(5, channel.last_sequence); 499 | 500 | 501 | let receive_result = channel.receive_packet(3, &data[..], 32); 502 | assert!(receive_result); 503 | assert_eq!(1, channel.current_sequence); 504 | 505 | let _receive_result = channel.receive_packet(2, &data[..], 32); 506 | assert_eq!(3, channel.current_sequence); 507 | assert_eq!(3, channel.published.len()); 508 | 509 | let _receive_result = channel.receive_packet(4, &data[..], 32); 510 | assert_eq!(5, channel.current_sequence); 511 | assert_eq!(5, channel.last_sequence); 512 | 513 | 514 | assert_eq!(5, channel.published.len()); 515 | 516 | assert!(channel.take_published().is_some()); 517 | assert!(channel.take_published().is_some()); 518 | assert!(channel.take_published().is_some()); 519 | assert!(channel.take_published().is_some()); 520 | assert!(channel.take_published().is_some()); 521 | 522 | assert!(channel.take_published().is_none()); 523 | assert_eq!(0, channel.published.len()); 524 | } 525 | 526 | #[test] 527 | #[allow(dead_code)] 528 | fn unordered_flow_test() { 529 | let mut channel = Receiver::default(false); 530 | let data: Vec = vec![0; 1024]; 531 | let _receive_result = channel.receive_packet(1, &data[..], 32); 532 | assert_eq!(1, channel.published.len()); 533 | let _receive_result = channel.receive_packet(5, &data[..], 32); 534 | assert_eq!(2, channel.published.len()); 535 | assert_eq!(1, channel.current_sequence); 536 | assert_eq!(5, channel.last_sequence); 537 | 538 | 539 | let _receive_result = channel.receive_packet(3, &data[..], 32); 540 | assert_eq!(1, channel.current_sequence); 541 | 542 | 543 | let _receive_result = channel.receive_packet(2, &data[..], 32); 544 | assert_eq!(3, channel.current_sequence); 545 | assert_eq!(4, channel.published.len()); 546 | 547 | 548 | let _receive_result = channel.receive_packet(4, &data[..], 32); 549 | assert_eq!(5, channel.current_sequence); 550 | assert_eq!(5, channel.last_sequence); 551 | 552 | assert_eq!(5, channel.published.len()); 553 | 554 | assert!(channel.take_published().is_some()); 555 | assert!(channel.take_published().is_some()); 556 | assert!(channel.take_published().is_some()); 557 | assert!(channel.take_published().is_some()); 558 | assert!(channel.take_published().is_some()); 559 | 560 | assert!(channel.take_published().is_none()); 561 | assert_eq!(0, channel.published.len()); 562 | } 563 | } 564 | -------------------------------------------------------------------------------- /src/tachyon/send_buffer_manager.rs: -------------------------------------------------------------------------------- 1 | use std::time::Instant; 2 | 3 | use super::{sequence::Sequence, sequence_buffer::SequenceBuffer, byte_buffer_pool::{ByteBuffer, ByteBufferPool, BYTE_BUFFER_SIZE_DEFAULT}}; 4 | 5 | const SEND_BUFFER_SIZE: u16 = 1024; 6 | const EXPIRE: u128 = 5000; 7 | 8 | pub struct SendBuffer { 9 | pub sequence: u16, 10 | pub byte_buffer: ByteBuffer, 11 | pub created_at: Instant, 12 | } 13 | pub struct SendBufferManager { 14 | pub current_sequence: u16, 15 | pub buffers: SequenceBuffer, 16 | pub buffer_pool: ByteBufferPool 17 | } 18 | 19 | impl SendBufferManager { 20 | pub fn default() -> Self { 21 | let mut buffers: SequenceBuffer = SequenceBuffer { 22 | values: Vec::new(), 23 | partition_by: SEND_BUFFER_SIZE, 24 | }; 25 | for _ in 0..SEND_BUFFER_SIZE { 26 | buffers.values.push(None); 27 | } 28 | 29 | let sender = SendBufferManager { 30 | current_sequence: 0, 31 | buffers, 32 | buffer_pool: ByteBufferPool::create(BYTE_BUFFER_SIZE_DEFAULT,SEND_BUFFER_SIZE as usize) 33 | }; 34 | return sender; 35 | } 36 | 37 | pub fn get_send_buffer(&mut self, sequence: u16) -> Option<&mut SendBuffer> { 38 | match self.buffers.get_mut(sequence) { 39 | Some(send_buffer) => { 40 | return Some(send_buffer); 41 | } 42 | None => { 43 | return None; 44 | } 45 | } 46 | } 47 | 48 | pub fn expire(&mut self) { 49 | let mut expired: Vec = Vec::new(); 50 | 51 | for value in &self.buffers.values { 52 | if let Some(buffer) = value { 53 | if buffer.created_at.elapsed().as_millis() > EXPIRE { 54 | expired.push(buffer.sequence); 55 | } 56 | } 57 | } 58 | for sequence in expired { 59 | self.buffers.remove(sequence); 60 | } 61 | } 62 | 63 | pub fn create_send_buffer_old(&mut self, length: usize) -> Option<&mut SendBuffer> { 64 | 65 | self.current_sequence = Sequence::next_sequence(self.current_sequence); 66 | 67 | let byte_buffer = ByteBuffer::create(length); 68 | 69 | let buffer = SendBuffer { 70 | sequence: self.current_sequence, 71 | byte_buffer, 72 | created_at: Instant::now(), 73 | }; 74 | 75 | self.buffers.insert(self.current_sequence, buffer); 76 | 77 | match self.buffers.get_mut(self.current_sequence) { 78 | Some(buffer) => { 79 | return Some(buffer); 80 | } 81 | None => { 82 | return None; 83 | } 84 | } 85 | } 86 | 87 | pub fn create_send_buffer(&mut self, length: usize) -> Option<&mut SendBuffer> { 88 | self.current_sequence = Sequence::next_sequence(self.current_sequence); 89 | 90 | if let Some(mut send_buffer) = self.buffers.take(self.current_sequence) { 91 | if send_buffer.byte_buffer.pooled && length <= self.buffer_pool.buffer_size { 92 | send_buffer.byte_buffer.length = length; 93 | } else { 94 | self.buffer_pool.return_buffer(send_buffer.byte_buffer); 95 | send_buffer.byte_buffer = self.buffer_pool.get_buffer(length); 96 | } 97 | send_buffer.sequence = self.current_sequence; 98 | send_buffer.created_at = Instant::now(); 99 | return self.buffers.insert(self.current_sequence, send_buffer); 100 | } 101 | 102 | let byte_buffer = self.buffer_pool.get_buffer(length); 103 | let send_buffer = SendBuffer { 104 | sequence: self.current_sequence, 105 | byte_buffer, 106 | created_at: Instant::now(), 107 | }; 108 | return self.buffers.insert(self.current_sequence, send_buffer); 109 | 110 | } 111 | } 112 | 113 | #[cfg(test)] 114 | mod tests { 115 | use std::time::{Duration, Instant}; 116 | 117 | 118 | use crate::tachyon::byte_buffer_pool::BYTE_BUFFER_SIZE_DEFAULT; 119 | 120 | use super::SendBufferManager; 121 | 122 | #[test] 123 | fn test_create_buffer() { 124 | let mut manager = SendBufferManager::default(); 125 | let buffer = manager.create_send_buffer(BYTE_BUFFER_SIZE_DEFAULT).unwrap(); 126 | assert!(buffer.byte_buffer.pooled); 127 | 128 | let buffer = manager.create_send_buffer(BYTE_BUFFER_SIZE_DEFAULT + 1).unwrap(); 129 | assert!(!buffer.byte_buffer.pooled); 130 | } 131 | 132 | #[test] 133 | fn test_reused_buffer() { 134 | let mut manager = SendBufferManager::default(); 135 | manager.current_sequence = 10; 136 | let buffer = manager.create_send_buffer(BYTE_BUFFER_SIZE_DEFAULT).unwrap(); 137 | assert_eq!(11, buffer.sequence); 138 | assert_eq!(0, buffer.byte_buffer.version); 139 | 140 | // should get back same byte buffer with same version and new length 141 | manager.current_sequence = 10; 142 | let buffer = manager.create_send_buffer(BYTE_BUFFER_SIZE_DEFAULT - 1).unwrap(); 143 | assert_eq!(11, buffer.sequence); 144 | assert_eq!(0, buffer.byte_buffer.version); 145 | assert!(buffer.byte_buffer.pooled); 146 | assert_eq!(BYTE_BUFFER_SIZE_DEFAULT - 1, buffer.byte_buffer.length); 147 | 148 | // should get new byte buffer 149 | manager.current_sequence = 10; 150 | let buffer = manager.create_send_buffer(BYTE_BUFFER_SIZE_DEFAULT + 10).unwrap(); 151 | assert_eq!(11, buffer.sequence); 152 | assert_eq!(0, buffer.byte_buffer.version); 153 | assert!(!buffer.byte_buffer.pooled); 154 | assert_eq!(BYTE_BUFFER_SIZE_DEFAULT + 10, buffer.byte_buffer.length); 155 | } 156 | 157 | #[test] 158 | fn test_expire() { 159 | let mut buffers = SendBufferManager::default(); 160 | let buffer = buffers.create_send_buffer(32); 161 | let buffer = buffer.unwrap(); 162 | let sequence = buffer.sequence; 163 | let now = Instant::now() - Duration::new(6, 0); 164 | buffer.created_at = now; 165 | 166 | assert!(buffers.buffers.is_some(sequence)); 167 | buffers.expire(); 168 | assert!(!buffers.buffers.is_some(sequence)); 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /src/tachyon/sequence.rs: -------------------------------------------------------------------------------- 1 | pub struct Sequence {} 2 | 3 | impl Sequence { 4 | pub fn is_greater_then(s1: u16, s2: u16) -> bool { 5 | return ((s1 > s2) && (s1 - s2 <= 32768)) || ((s1 < s2) && (s2 - s1 > 32768)); 6 | } 7 | 8 | pub fn is_less_than(s1: u16, s2: u16) -> bool { 9 | return Sequence::is_greater_then(s2, s1); 10 | } 11 | 12 | pub fn is_equal_to_or_less_than(s1: u16, s2: u16) -> bool { 13 | if s1 == s2 { 14 | return true; 15 | } 16 | return Sequence::is_greater_then(s2, s1); 17 | } 18 | 19 | pub fn next_sequence(sequence: u16) -> u16 { 20 | if sequence >= std::u16::MAX - 1 { 21 | return 0; 22 | } else { 23 | return sequence + 1; 24 | } 25 | } 26 | 27 | pub fn previous_sequence(sequence: u16) -> u16 { 28 | if sequence == 0 { 29 | return std::u16::MAX - 1; 30 | } else { 31 | return sequence - 1; 32 | } 33 | } 34 | } 35 | 36 | #[cfg(test)] 37 | mod tests { 38 | use crate::tachyon::sequence::Sequence; 39 | 40 | #[test] 41 | fn test_basic() { 42 | assert_eq!(65534, Sequence::next_sequence(65533)); 43 | assert_eq!(0, Sequence::next_sequence(65534)); 44 | assert_eq!(1, Sequence::next_sequence(0)); 45 | 46 | assert_eq!(65533, Sequence::previous_sequence(65534)); 47 | assert_eq!(65534, Sequence::previous_sequence(0)); 48 | assert_eq!(0, Sequence::previous_sequence(1)); 49 | 50 | assert!(Sequence::is_greater_then(0, 65534)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/tachyon/sequence_buffer.rs: -------------------------------------------------------------------------------- 1 | pub struct SequenceBuffer { 2 | pub values: Vec>, 3 | pub partition_by: u16, 4 | } 5 | 6 | impl SequenceBuffer { 7 | pub fn sequence_to_index(&self, sequence: u16) -> usize { 8 | return (sequence % self.partition_by) as usize; 9 | } 10 | 11 | pub fn insert(&mut self, sequence: u16, value: T) -> Option<&mut T> { 12 | let index = self.sequence_to_index(sequence); 13 | self.values[index] = Some(value); 14 | return self.values[index].as_mut(); 15 | } 16 | 17 | pub fn remove(&mut self, sequence: u16) { 18 | let index = self.sequence_to_index(sequence); 19 | self.values[index] = None; 20 | } 21 | 22 | pub fn remove_at_index(&mut self, index: usize) { 23 | self.values[index] = None; 24 | } 25 | 26 | pub fn is_some(&self, sequence: u16) -> bool { 27 | let index = self.sequence_to_index(sequence); 28 | return self.values[index].is_some(); 29 | } 30 | 31 | pub fn take(&mut self, sequence: u16) -> Option { 32 | let index = self.sequence_to_index(sequence); 33 | return self.values[index].take(); 34 | } 35 | 36 | pub fn get(&self, sequence: u16) -> Option<&T> { 37 | let index = self.sequence_to_index(sequence); 38 | match self.values.get(index) { 39 | Some(value) => { 40 | let value_ref = value.as_ref(); 41 | return value_ref; 42 | } 43 | None => { 44 | return None; 45 | } 46 | } 47 | } 48 | 49 | pub fn get_at_index(&self, index: usize) -> Option<&T> { 50 | match self.values.get(index) { 51 | Some(value) => { 52 | let value_ref = value.as_ref(); 53 | return value_ref; 54 | } 55 | None => { 56 | return None; 57 | } 58 | } 59 | } 60 | 61 | pub fn get_mut(&mut self, sequence: u16) -> Option<&mut T> { 62 | let index = self.sequence_to_index(sequence); 63 | match self.values.get_mut(index) { 64 | Some(value) => { 65 | let value_ref = value.as_mut(); 66 | return value_ref; 67 | } 68 | None => { 69 | return None; 70 | } 71 | } 72 | } 73 | } 74 | 75 | #[cfg(test)] 76 | mod tests { 77 | use crate::tachyon::sequence_buffer::SequenceBuffer; 78 | 79 | #[test] 80 | fn basic_test() { 81 | let data: Vec = vec![0; 32]; 82 | let mut buffer: SequenceBuffer> = SequenceBuffer { 83 | values: vec![None; 1024], 84 | partition_by: 1024, 85 | }; 86 | 87 | buffer.insert(1, data); 88 | let option = buffer.get(1); 89 | assert!(option.is_some()); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/tachyon/tachyon_socket.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | io, 3 | net::{Ipv4Addr, SocketAddrV4, UdpSocket}, 4 | }; 5 | 6 | use rand::{prelude::StdRng, Rng, SeedableRng}; 7 | use socket2::{Domain, Socket, Type}; 8 | 9 | use super::{ 10 | header::{MESSAGE_TYPE_RELIABLE}, 11 | int_buffer::IntBuffer, 12 | network_address::NetworkAddress 13 | }; 14 | 15 | pub enum CreateConnectResult { 16 | Success, 17 | Error, 18 | } 19 | 20 | pub enum SocketReceiveResult { 21 | Success { 22 | bytes_received: usize, 23 | network_address: NetworkAddress, 24 | }, 25 | Empty, 26 | Error, 27 | Dropped, 28 | } 29 | pub struct TachyonSocket { 30 | pub address: NetworkAddress, 31 | pub is_server: bool, 32 | pub socket: Option, 33 | pub rng: StdRng 34 | } 35 | 36 | impl TachyonSocket { 37 | pub fn create() -> Self { 38 | let socket = TachyonSocket { 39 | address: NetworkAddress::default(), 40 | is_server: false, 41 | socket: None, 42 | rng: SeedableRng::seed_from_u64(32634) 43 | }; 44 | return socket; 45 | } 46 | 47 | pub fn clone_socket(&self) -> Option { 48 | match &self.socket { 49 | Some(sock) => { 50 | return Some(sock.try_clone().unwrap()); 51 | } 52 | None => return None, 53 | } 54 | } 55 | 56 | pub fn bind_socket(&mut self, naddress: NetworkAddress) -> CreateConnectResult { 57 | if self.socket.is_some() { 58 | return CreateConnectResult::Error; 59 | } 60 | 61 | let address = naddress.to_socket_addr(); 62 | self.address = naddress; 63 | 64 | let socket = Socket::new(Domain::IPV4, Type::DGRAM, None).unwrap(); 65 | match socket.bind(&address.into()) { 66 | Ok(()) => { 67 | socket.set_recv_buffer_size(8192 * 256).unwrap(); 68 | socket.set_nonblocking(true).unwrap(); 69 | self.socket = Some(socket.into()); 70 | self.is_server = true; 71 | 72 | return CreateConnectResult::Success; 73 | } 74 | Err(_) => { 75 | return CreateConnectResult::Error; 76 | } 77 | } 78 | } 79 | 80 | pub fn connect_socket(&mut self, naddress: NetworkAddress) -> CreateConnectResult { 81 | if self.socket.is_some() { 82 | return CreateConnectResult::Error; 83 | } 84 | 85 | self.address = NetworkAddress::default(); 86 | let sock_addr = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0); 87 | let socket = Socket::new(Domain::IPV4, Type::DGRAM, None).unwrap(); 88 | 89 | match socket.bind(&sock_addr.into()) { 90 | Ok(()) => { 91 | socket.set_recv_buffer_size(8192 * 256).unwrap(); 92 | socket.set_nonblocking(true).unwrap(); 93 | let address = naddress.to_socket_addr(); 94 | let udp_socket: UdpSocket = socket.into(); 95 | 96 | match udp_socket.connect(&address) { 97 | Ok(()) => { 98 | self.socket = Some(udp_socket); 99 | return CreateConnectResult::Success; 100 | } 101 | Err(_) => { 102 | return CreateConnectResult::Error; 103 | } 104 | } 105 | } 106 | Err(_) => { 107 | return CreateConnectResult::Error; 108 | } 109 | } 110 | } 111 | 112 | fn should_drop(&mut self, data: &mut [u8], drop_chance: u64, drop_reliable_only: bool) -> bool { 113 | if drop_chance > 0 { 114 | let r = self.rng.gen_range(1..100); 115 | if r <= drop_chance { 116 | let mut can_drop = true; 117 | if drop_reliable_only { 118 | let mut reader = IntBuffer { index: 0 }; 119 | let message_type = reader.read_u8(data); 120 | if message_type != MESSAGE_TYPE_RELIABLE { 121 | can_drop = false; 122 | } 123 | } 124 | 125 | if can_drop { 126 | return true; 127 | } 128 | } 129 | } 130 | return false; 131 | } 132 | 133 | pub fn receive(&mut self, data: &mut [u8], drop_chance: u64, drop_reliable_only: bool) -> SocketReceiveResult { 134 | let socket = match &self.socket { 135 | Some(v) => v, 136 | None => { 137 | return SocketReceiveResult::Error; 138 | } 139 | }; 140 | 141 | if self.is_server { 142 | match socket.recv_from(data) { 143 | Ok((bytes_received, src_addr)) => { 144 | if self.should_drop(data, drop_chance, drop_reliable_only) { 145 | return SocketReceiveResult::Dropped; 146 | } 147 | let address = NetworkAddress::from_socket_addr(src_addr); 148 | return SocketReceiveResult::Success { 149 | bytes_received, 150 | network_address: address, 151 | }; 152 | } 153 | Err(_) => { 154 | return SocketReceiveResult::Empty; 155 | } 156 | } 157 | } else { 158 | match socket.recv(data) { 159 | Ok(size) => { 160 | if self.should_drop(data, drop_chance, drop_reliable_only) { 161 | return SocketReceiveResult::Dropped; 162 | } 163 | return SocketReceiveResult::Success { 164 | bytes_received: size, 165 | network_address: NetworkAddress::default(), 166 | }; 167 | } 168 | Err(_) => { 169 | return SocketReceiveResult::Empty; 170 | } 171 | } 172 | } 173 | } 174 | 175 | pub fn send_to(&self, address: NetworkAddress, data: &[u8], length: usize) -> usize { 176 | match &self.socket { 177 | Some(socket) => { 178 | let slice = &data[0..length]; 179 | let socket_result: io::Result; 180 | 181 | if address.port == 0 { 182 | socket_result = socket.send(slice); 183 | } else { 184 | socket_result = socket.send_to(slice, address.to_socket_addr()); 185 | } 186 | 187 | match socket_result { 188 | Ok(size) => { 189 | return size; 190 | } 191 | Err(_) => { 192 | return 0; 193 | } 194 | } 195 | } 196 | None => { 197 | return 0; 198 | } 199 | } 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /src/tachyon/tachyon_test.rs: -------------------------------------------------------------------------------- 1 | use core::time; 2 | use std::thread; 3 | use std::time::Instant; 4 | 5 | use serial_test::serial; 6 | 7 | use crate::tachyon::header::*; 8 | use crate::tachyon::receiver::*; 9 | use crate::tachyon::*; 10 | 11 | pub struct TachyonTestClient { 12 | pub client_address: NetworkAddress, 13 | pub client: Tachyon, 14 | pub address: NetworkAddress, 15 | pub config: TachyonConfig, 16 | pub receive_buffer: Vec, 17 | pub send_buffer: Vec, 18 | } 19 | 20 | impl TachyonTestClient { 21 | pub fn create(address: NetworkAddress) -> Self { 22 | let config = TachyonConfig::default(); 23 | let client = Tachyon::create(config); 24 | let default = TachyonTestClient { 25 | client_address: NetworkAddress::default(), 26 | address: address, 27 | config: config, 28 | client: client, 29 | receive_buffer: vec![0; 4096], 30 | send_buffer: vec![0; 4096], 31 | }; 32 | return default; 33 | } 34 | 35 | pub fn connect(&mut self) { 36 | assert!(self.client.connect(self.address), "connect failed"); 37 | } 38 | 39 | pub fn client_send_reliable(&mut self, channel_id: u8, length: usize) -> TachyonSendResult { 40 | let target = SendTarget {address: self.client_address, identity_id: 0}; 41 | return self.client.send_to_target(channel_id, target,&mut self.send_buffer, length); 42 | } 43 | 44 | pub fn client_send_unreliable(&mut self, length: usize) -> TachyonSendResult { 45 | let target = SendTarget {address: self.client_address, identity_id: 0}; 46 | return self.client.send_to_target(0,target, &mut self.send_buffer, length); 47 | } 48 | 49 | pub fn client_receive(&mut self) -> TachyonReceiveResult { 50 | return self.client.receive_loop(&mut self.receive_buffer); 51 | } 52 | } 53 | 54 | pub struct TachyonTest { 55 | pub client_address: NetworkAddress, 56 | pub client: Tachyon, 57 | pub server: Tachyon, 58 | pub address: NetworkAddress, 59 | pub config: TachyonConfig, 60 | pub receive_buffer: Vec, 61 | pub send_buffer: Vec, 62 | } 63 | 64 | impl TachyonTest { 65 | pub fn default() -> Self { 66 | let address = NetworkAddress::test_address(); 67 | return TachyonTest::create(address); 68 | } 69 | 70 | pub fn create(address: NetworkAddress) -> Self { 71 | let config = TachyonConfig::default(); 72 | let server = Tachyon::create(config); 73 | let client = Tachyon::create(config); 74 | 75 | let default = TachyonTest { 76 | client_address: NetworkAddress::default(), 77 | address: address, 78 | config: config, 79 | client: client, 80 | server: server, 81 | receive_buffer: vec![0; 4096], 82 | send_buffer: vec![0; 4096], 83 | }; 84 | return default; 85 | } 86 | 87 | pub fn connect(&mut self) { 88 | assert!(self.server.bind(self.address), "bind failed"); 89 | assert!(self.client.connect(self.address), "connect failed"); 90 | } 91 | 92 | pub fn remote_client(&mut self) -> NetworkAddress { 93 | let list = self.server.get_connections(100); 94 | if list.len() > 0 { 95 | return list[0].address; 96 | } else { 97 | return NetworkAddress::default(); 98 | } 99 | } 100 | 101 | pub fn server_send_reliable(&mut self, channel_id: u8, length: usize) -> TachyonSendResult { 102 | let address = self.remote_client(); 103 | if address.is_default() { 104 | return TachyonSendResult::default(); 105 | } 106 | let target = SendTarget {address: address, identity_id: 0}; 107 | return self.server.send_to_target(channel_id, target, &mut self.send_buffer, length); 108 | } 109 | 110 | pub fn server_send_unreliable(&mut self, length: usize) -> TachyonSendResult { 111 | let address = self.remote_client(); 112 | if address.is_default() { 113 | return TachyonSendResult::default(); 114 | } 115 | let target = SendTarget {address: address, identity_id: 0}; 116 | return self.server.send_to_target(0,target, &mut self.send_buffer, length); 117 | } 118 | 119 | pub fn client_send_reliable(&mut self, channel_id: u8, length: usize) -> TachyonSendResult { 120 | let target = SendTarget {address: self.client_address, identity_id: 0}; 121 | return self.client.send_to_target(channel_id, target,&mut self.send_buffer,length); 122 | } 123 | 124 | pub fn client_send_unreliable(&mut self, length: usize) -> TachyonSendResult { 125 | let target = SendTarget {address: self.client_address, identity_id: 0}; 126 | return self.client.send_to_target(0,target, &mut self.send_buffer, length); 127 | } 128 | 129 | pub fn server_receive(&mut self) -> TachyonReceiveResult { 130 | return self.server.receive_loop(&mut self.receive_buffer); 131 | } 132 | 133 | pub fn client_receive(&mut self) -> TachyonReceiveResult { 134 | return self.client.receive_loop(&mut self.receive_buffer); 135 | } 136 | } 137 | 138 | pub fn show_channel_debug(channel: &mut Receiver) { 139 | print!( 140 | "current:{0} last:{1}\n", 141 | channel.current_sequence, channel.last_sequence 142 | ); 143 | channel.set_resend_list(); 144 | for seq in &channel.resend_list { 145 | print!("not received:{0} \n", seq); 146 | } 147 | } 148 | 149 | fn send_receive(update: bool,send: bool,channel_id: u8, message_type: u8, client: &mut Tachyon, server: &mut Tachyon, send_buffer: &mut [u8], receive_buffer: &mut [u8], 150 | send_message_size: usize, client_remote: &mut NetworkAddress) { 151 | let client_address = NetworkAddress::default(); 152 | //let mut client_remote = NetworkAddress::default(); 153 | 154 | if send { 155 | for _ in 0..4 { 156 | let send_result: TachyonSendResult; 157 | let target = SendTarget {address: client_address, identity_id: 0}; 158 | if message_type == MESSAGE_TYPE_RELIABLE { 159 | send_result = client.send_to_target(channel_id, target, send_buffer, send_message_size); 160 | } else { 161 | send_result = client.send_to_target(0,target, send_buffer, send_message_size); 162 | } 163 | assert_eq!(0, send_result.error); 164 | assert!(send_result.sent_len > 0); 165 | } 166 | 167 | } 168 | 169 | let receive_result = server.receive_loop(receive_buffer); 170 | assert_eq!(0, receive_result.error); 171 | 172 | if send { 173 | if receive_result.length > 0 { 174 | assert!(receive_result.address.port > 0); 175 | client_remote.copy_from(receive_result.address); 176 | if client_remote.port > 0 { 177 | let target = SendTarget {address: *client_remote, identity_id: 0}; 178 | if message_type == MESSAGE_TYPE_RELIABLE { 179 | server.send_to_target(channel_id,target,send_buffer,send_message_size); 180 | } else { 181 | server.send_to_target(0,target, send_buffer, send_message_size); 182 | } 183 | } 184 | } 185 | } 186 | 187 | for _ in 0..100 { 188 | let receive_result = server.receive_loop(receive_buffer); 189 | if receive_result.length == 0 { 190 | break; 191 | } 192 | } 193 | 194 | for _ in 0..100 { 195 | let receive_result = client.receive_loop(receive_buffer); 196 | if receive_result.length == 0 { 197 | break; 198 | } 199 | } 200 | 201 | if update { 202 | client.update(); 203 | server.update(); 204 | } 205 | } 206 | 207 | 208 | #[test] 209 | #[serial] 210 | fn general_stress() { 211 | let address = NetworkAddress::test_address(); 212 | let client_address = NetworkAddress::default(); 213 | 214 | let sleep_in_loop = false; 215 | let buffer_size = 64 * 1024; 216 | let drop_reliable_only = 0; 217 | let client_drop_chance = 0; 218 | let server_drop_chance = 0; 219 | let loop_count = 2000; // inner loop sends 4 messages 220 | let channel_id = 1; 221 | let message_type = MESSAGE_TYPE_RELIABLE; 222 | //let message_type = MESSAGE_TYPE_UNRELIABLE; 223 | let send_message_size = 384; 224 | 225 | let mut send_buffer: Vec = vec![0; buffer_size]; 226 | let mut receive_buffer: Vec = vec![0; buffer_size]; 227 | 228 | let mut config = TachyonConfig::default(); 229 | config.drop_packet_chance = server_drop_chance; 230 | config.drop_reliable_only = drop_reliable_only; 231 | 232 | let mut server = Tachyon::create(config); 233 | server.bind(address); 234 | 235 | let mut config = TachyonConfig::default(); 236 | config.drop_packet_chance = client_drop_chance; 237 | config.drop_reliable_only = drop_reliable_only; 238 | let mut client = Tachyon::create(config); 239 | client.connect(address); 240 | 241 | let mut client_remote = NetworkAddress::default(); 242 | for _ in 0..loop_count { 243 | 244 | if sleep_in_loop { 245 | thread::sleep(time::Duration::from_millis(10)); 246 | send_receive(true,true,channel_id, message_type, &mut client, &mut server, &mut send_buffer, &mut receive_buffer, send_message_size, &mut client_remote); 247 | } else { 248 | send_receive(true,true,channel_id, message_type, &mut client, &mut server, &mut send_buffer, &mut receive_buffer, send_message_size, &mut client_remote); 249 | } 250 | 251 | 252 | 253 | } 254 | 255 | for _ in 0..200 { 256 | send_receive(true,false,channel_id,message_type,&mut client,&mut server, &mut send_buffer, &mut receive_buffer, send_message_size, &mut client_remote); 257 | } 258 | 259 | let channel = client.get_channel(client_address, channel_id).unwrap(); 260 | channel.receiver.publish(); 261 | channel.receiver.set_resend_list(); 262 | channel.update_stats(); 263 | print!( 264 | "CLIENT {0} current_seq:{1} last_seq:{2}, missing:{3}\n", 265 | channel.stats, 266 | channel.receiver.current_sequence, 267 | channel.receiver.last_sequence, 268 | channel.receiver.resend_list.len() 269 | ); 270 | 271 | match server.get_channel(client_remote, channel_id) { 272 | Some(channel) => { 273 | channel.receiver.publish(); 274 | channel.receiver.set_resend_list(); 275 | channel.update_stats(); 276 | print!( 277 | "SERVER {0} current_seq:{1} last_seq:{2} missing:{3}\n", 278 | channel.stats, 279 | channel.receiver.current_sequence, 280 | channel.receiver.last_sequence, 281 | channel.receiver.resend_list.len() 282 | ); 283 | } 284 | None => {} 285 | } 286 | 287 | print!( 288 | "Dropped client:{0} server:{1}\n\n", 289 | client.stats.packets_dropped, server.stats.packets_dropped 290 | ); 291 | 292 | print!( 293 | "Unreliable client sent:{0} received:{1}\n\n", 294 | client.stats.unreliable_sent, client.stats.unreliable_received 295 | ); 296 | print!( 297 | "Unreliable server sent:{0} received:{1}\n\n", 298 | server.stats.unreliable_sent, server.stats.unreliable_received 299 | ); 300 | 301 | match server.get_channel(client_remote, channel_id) { 302 | Some(channel) => { 303 | show_channel_debug(&mut channel.receiver); 304 | } 305 | None => {} 306 | } 307 | } 308 | 309 | #[test] 310 | #[serial] 311 | fn many_clients() { 312 | let address = NetworkAddress::test_address(); 313 | 314 | let client_count = 200; 315 | let loop_count = 4; 316 | let channel_id = 1; 317 | let message_type = MESSAGE_TYPE_RELIABLE; 318 | //let message_type = MESSAGE_TYPE_UNRELIABLE; 319 | 320 | let msize = 384; 321 | let mut send_buffer: Vec = vec![0; 1024]; 322 | let mut receive_buffer: Vec = vec![0; 4096]; 323 | 324 | let mut config = TachyonConfig::default(); 325 | config.drop_packet_chance = 0; 326 | 327 | let mut server = Tachyon::create(config); 328 | server.bind(address); 329 | 330 | let mut clients: Vec = Vec::new(); 331 | 332 | for _ in 0..client_count { 333 | let mut client = Tachyon::create(config); 334 | client.connect(address); 335 | clients.push(client); 336 | } 337 | 338 | for mut client in &mut clients { 339 | let mut client_remote = NetworkAddress::default(); 340 | for _ in 0..loop_count { 341 | send_receive(false,true,channel_id, message_type, &mut client, &mut server,&mut send_buffer, &mut receive_buffer,msize, &mut client_remote); 342 | } 343 | } 344 | 345 | let now = Instant::now(); 346 | 347 | for _ in 0..10000 { 348 | let _receive_result = server.receive_loop(&mut receive_buffer); 349 | if _receive_result.length == 0 || _receive_result.error > 0 { 350 | break; 351 | } 352 | } 353 | 354 | for _ in 0..100 { 355 | server.update(); 356 | } 357 | let elapsed = now.elapsed(); 358 | println!("Elapsed: {:.2?}", elapsed); 359 | print!("Server CombinedStats:{0}\n", server.get_combined_stats()); 360 | } 361 | -------------------------------------------------------------------------------- /src/tachyon/unreliable_sender.rs: -------------------------------------------------------------------------------- 1 | use std::{io, net::UdpSocket}; 2 | 3 | use super::{ 4 | header::{Header, MESSAGE_TYPE_UNRELIABLE}, 5 | network_address::NetworkAddress, 6 | TachyonSendResult, SEND_ERROR_CHANNEL, SEND_ERROR_LENGTH, 7 | }; 8 | 9 | const UNRELIABLE_BUFFER_LEN: usize = 1024 * 16; 10 | 11 | // this is created with a cloned UdpSocket which can then be used from another thread. 12 | pub struct UnreliableSender { 13 | pub socket: Option, 14 | pub send_buffer: Vec 15 | } 16 | 17 | impl UnreliableSender { 18 | 19 | pub fn create(socket: Option) -> Self { 20 | UnreliableSender { 21 | socket, 22 | send_buffer: vec![0;UNRELIABLE_BUFFER_LEN] 23 | } 24 | } 25 | 26 | pub fn send(&mut self, address: NetworkAddress, data: &mut [u8], body_len: usize) -> TachyonSendResult { 27 | let mut result = TachyonSendResult::default(); 28 | 29 | if body_len < 1 { 30 | result.error = SEND_ERROR_LENGTH; 31 | return result; 32 | } 33 | 34 | if !self.socket.is_some() { 35 | result.error = SEND_ERROR_CHANNEL; 36 | return result; 37 | } 38 | 39 | // copy to send buffer at +1 offset for message_type 40 | self.send_buffer[1..body_len+1].copy_from_slice(&data[0..body_len]); 41 | let length = body_len + 1; 42 | 43 | let mut header = Header::default(); 44 | header.message_type = MESSAGE_TYPE_UNRELIABLE; 45 | header.write_unreliable(&mut self.send_buffer); 46 | 47 | let sent_len = self.send_to(address, length); 48 | result.sent_len = sent_len as u32; 49 | result.header = header; 50 | 51 | return result; 52 | } 53 | 54 | fn send_to(&self, address: NetworkAddress, length: usize) -> usize { 55 | match &self.socket { 56 | Some(socket) => { 57 | let slice = &self.send_buffer[0..length]; 58 | let socket_result: io::Result; 59 | 60 | if address.port == 0 { 61 | socket_result = socket.send(slice); 62 | } else { 63 | socket_result = socket.send_to(slice, address.to_socket_addr()); 64 | } 65 | 66 | match socket_result { 67 | Ok(size) => { 68 | return size; 69 | } 70 | Err(_) => { 71 | return 0; 72 | } 73 | } 74 | } 75 | None => { 76 | return 0; 77 | } 78 | } 79 | } 80 | } 81 | --------------------------------------------------------------------------------