├── .gitignore ├── .travis.yml ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── appveyor.yml ├── examples ├── client.rs └── server.rs └── src ├── client.rs ├── lib.rs ├── server.rs ├── shared ├── binary_rate_limiter.rs ├── config.rs ├── connection.rs ├── message_queue.rs ├── mod.rs ├── noop_packet_modifier.rs ├── stats.rs ├── ticker.rs └── udp_socket.rs ├── test ├── client.rs ├── connection.rs ├── message_queue.rs ├── mock_socket.rs ├── mod.rs └── server.rs └── traits ├── mod.rs ├── packet_modifier.rs ├── rate_limiter.rs └── socket.rs /.gitignore: -------------------------------------------------------------------------------- 1 | doc 2 | target 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: rust 3 | 4 | addons: 5 | apt: 6 | packages: 7 | - libcurl4-openssl-dev 8 | - libelf-dev 9 | - libdw-dev 10 | - binutils-dev # optional: only required for the --verify flag of coveralls 11 | 12 | rust: 13 | - stable 14 | - beta 15 | 16 | matrix: 17 | allow_failure: 18 | - rust: nightly 19 | 20 | include: 21 | - rust: nightly 22 | 23 | # load travis-cargo 24 | before_script: 25 | - | 26 | pip install 'travis-cargo<0.2' --user && 27 | export PATH=$HOME/.local/bin:$PATH 28 | 29 | # the main build 30 | script: 31 | - | 32 | travis-cargo build && 33 | travis-cargo test && 34 | travis-cargo bench && 35 | travis-cargo --only stable doc 36 | 37 | after_success: 38 | # upload the documentation from the build with stable (automatically only actually 39 | # runs on the master branch, not individual PRs) 40 | - travis-cargo --only stable doc-upload 41 | # measure code coverage and upload to coveralls.io (the verify 42 | # argument mitigates kcov crashes due to malformed debuginfo, at the 43 | # cost of some speed ) 44 | - travis-cargo coveralls --no-sudo --verify 45 | - ./kcov/build/src/kcov --verify --coveralls-id=$TRAVIS_JOB_ID --exclude-pattern=/.cargo,./test,/usr/lib target/kcov target/debug/cobalt-* 46 | 47 | env: 48 | global: 49 | # override the default `--features unstable` used for the nightly branch (optional) 50 | - TRAVIS_CARGO_NIGHTLY_FEATURE=lint 51 | # encrypted github token for doc upload (see `GH_TOKEN` link above) 52 | - secure: djlxUOb/Am51vc3z7RewDLAm631Xe1Qxip1Y2ZZuSRyPmr3Bmitk9VAFa0N7twA9VplvCs2Qjq4ChW7JRdgd7zngSDzagmI/RKhcq5hp0+ZS2gimTe56Y19wGB8PLB/mK4+7EdBK8HmBO00/2zoNrnN9tmxID5iHhWyu/VDhbs11ND+Mxwu1zy5Aw3U/YHfAJwxFD/alIRW4SA+3WSgOJ3liJMR4dxUxTonHbKXTyJzPiPeS6djUSMrNDfvyNzDPYoM4aRHNb/EZTQ65oYp7wy4Iesni1r+wTrOgfsuuMXg7xbEEKmbLPoEyIeCm3JBV0j7j+I1fZF3MoiI4CSEa7ZNrT4GHHv+C1LXVjAPGCwMmCp0GJ0ZG4DlcNeAFJhwN32k6vKV8agQwImdMP85TAq/lKBKGEA4tFGMqoZ/sodazSIfPbW9aVFvpiT98MBlrjzUvzjIBJtSNtpsyNpuAT9rvrtue5mIVPOPu/ziCwZ5xl8SijzQgkaRKjBtmd3NLNakzHfZz3t6fUHnBNLWKCp9SOSSkjj0owgy3LIGyfbKhX6UAy9ROjbsGeIXgDskeyPi1bvZdTyu1R1fe18ZoKyUuNmld5wb3CyzSX6d9SakI05Wsptyt2TQkIA7uCercsZ0YvTgX4TwmSznAMVkiu67GFDsKTQf+HXouzVk1MvM= 53 | 54 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cobalt" 3 | version = "0.22.0" 4 | authors = ["Ivo Wetzel "] 5 | description="Low level, UDP based networking library." 6 | documentation = "https://bonsaiden.github.io/cobalt-rs/doc/cobalt" 7 | repository = "https://github.com/BonsaiDen/cobalt-rs.git" 8 | readme = "README.md" 9 | keywords = [ "virtual", "udp", "connection", "message", "queue"] 10 | categories = ["network-programming"] 11 | license = "MIT/Apache-2.0" 12 | 13 | [dependencies] 14 | rand = "0.3.14" 15 | clippy = { version = "*", optional = true } 16 | 17 | [features] 18 | lint = ["clippy"] 19 | 20 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-2016 Ivo Wetzel 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cobalt [![Build Status](https://img.shields.io/travis/BonsaiDen/cobalt-rs/master.svg?style=flat-square)](https://travis-ci.org/BonsaiDen/cobalt-rs) [![Build status](https://img.shields.io/appveyor/ci/BonsaiDen/cobalt-rs/master.svg?style=flat-square)](https://ci.appveyor.com/project/BonsaiDen/cobalt-rs) [![Crates.io](https://img.shields.io/crates/v/cobalt.svg?style=flat-square)](https://crates.io/crates/cobalt) [![License](https://img.shields.io/crates/l/cobalt.svg?style=flat-square)]() [![Coverage Status](https://coveralls.io/repos/github/BonsaiDen/cobalt-rs/badge.svg?branch=master)](https://coveralls.io/github/BonsaiDen/cobalt-rs?branch=master) 2 | 3 | A [rust](https://rust-lang.org/) based networking library providing [virtual 4 | connections over UDP](http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/) 5 | with an included message layer supporting both unreliable messaging and reliable 6 | messages with optional in-order delivery. 7 | 8 | - [Documentation](https://bonsaiden.github.io/cobalt-rs/cobalt/index.html) for the latest master build. 9 | 10 | 11 | ## Usage 12 | 13 | Add this to your `Cargo.toml`: 14 | 15 | ```toml 16 | [dependencies] 17 | cobalt = "0.22.0" 18 | ``` 19 | 20 | and this to your crate root: 21 | 22 | ```rust 23 | extern crate cobalt; 24 | ``` 25 | 26 | For usage examples please refer to the documentation of the libraries server 27 | and client abstractions. 28 | 29 | ## License 30 | 31 | Licensed under either of 32 | * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 33 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) 34 | at your option. 35 | 36 | 37 | ### Contribution 38 | 39 | Unless you explicitly state otherwise, any contribution intentionally submitted 40 | for inclusion in the work by you shall be dual licensed as above, without any 41 | additional terms or conditions. 42 | 43 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | RUST_TEST_THREADS: 1 3 | matrix: 4 | - TARGET: x86_64-pc-windows-msvc 5 | VERSION: nightly 6 | - TARGET: i686-pc-windows-msvc 7 | VERSION: nightly 8 | - TARGET: i686-pc-windows-gnu 9 | VERSION: nightly 10 | 11 | install: 12 | - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-${env:VERSION}-${env:TARGET}.exe" 13 | - rust-%VERSION%-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" 14 | - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin 15 | - SET PATH=%PATH%;C:\MinGW\bin 16 | - rustc -V 17 | - cargo -V 18 | 19 | build: false 20 | test_script: 21 | - cargo test --verbose -- --nocapture 22 | 23 | -------------------------------------------------------------------------------- /examples/client.rs: -------------------------------------------------------------------------------- 1 | // Crates --------------------------------------------------------------------- 2 | extern crate cobalt; 3 | 4 | 5 | // Dependencies --------------------------------------------------------------- 6 | use cobalt::{ 7 | BinaryRateLimiter, Config, NoopPacketModifier, MessageKind, UdpSocket, 8 | Client, ClientEvent 9 | }; 10 | 11 | fn main() { 12 | 13 | // Create a new client that communicates over a udp socket 14 | let mut client = Client::< 15 | UdpSocket, 16 | BinaryRateLimiter, 17 | NoopPacketModifier 18 | 19 | >::new(Config::default()); 20 | 21 | // Make the client connect to port `1234` on `localhost` 22 | println!("[Client] Connecting..."); 23 | client.connect("127.0.0.1:1234").expect("Failed to bind to socket."); 24 | 25 | 'main: loop { 26 | 27 | // Accept incoming connections and fetch their events 28 | while let Ok(event) = client.receive() { 29 | // Handle events (e.g. Connection, Messages, etc.) 30 | match event { 31 | ClientEvent::Connection => { 32 | let conn = client.connection().unwrap(); 33 | println!( 34 | "[Client] Connection established ({}, {}ms rtt).", 35 | conn.peer_addr(), 36 | conn.rtt() 37 | ); 38 | 39 | }, 40 | ClientEvent::Message(message) => { 41 | let conn = client.connection().unwrap(); 42 | println!( 43 | "[Client] Message from server ({}, {}ms rtt): {:?}", 44 | conn.peer_addr(), 45 | conn.rtt(), 46 | message 47 | ); 48 | 49 | }, 50 | ClientEvent::ConnectionClosed(_) | ClientEvent::ConnectionLost(_) => { 51 | let conn = client.connection().unwrap(); 52 | println!( 53 | "[Client] ({}, {}ms rtt) disconnected.", 54 | conn.peer_addr(), 55 | conn.rtt() 56 | ); 57 | break 'main; 58 | }, 59 | _ => {} 60 | } 61 | } 62 | 63 | // Send a message to all connected clients 64 | if let Ok(conn) = client.connection() { 65 | conn.send(MessageKind::Instant, b"Hello from Client".to_vec()); 66 | } 67 | 68 | // Send all outgoing messages. 69 | // 70 | // Also auto delay the current thread to achieve the configured tick rate. 71 | client.send(true).is_ok(); 72 | 73 | } 74 | 75 | println!("[Client] Disconnecting..."); 76 | 77 | // Shutdown the server (freeing its socket and closing all its connections) 78 | client.disconnect().ok(); 79 | 80 | } 81 | 82 | 83 | -------------------------------------------------------------------------------- /examples/server.rs: -------------------------------------------------------------------------------- 1 | // Crates --------------------------------------------------------------------- 2 | extern crate cobalt; 3 | 4 | 5 | // Dependencies --------------------------------------------------------------- 6 | use cobalt::{ 7 | BinaryRateLimiter, Config, NoopPacketModifier, MessageKind, UdpSocket, 8 | Server, ServerEvent 9 | }; 10 | 11 | fn main() { 12 | 13 | // Create a new server that communicates over a udp socket 14 | let mut server = Server::< 15 | UdpSocket, 16 | BinaryRateLimiter, 17 | NoopPacketModifier 18 | 19 | >::new(Config::default()); 20 | 21 | // Make the server listen on port `1234` on all interfaces. 22 | println!("[Server] Listening..."); 23 | server.listen("0.0.0.0:1234").expect("Failed to bind to socket."); 24 | 25 | 'main: loop { 26 | 27 | // Accept incoming connections and fetch their events 28 | while let Ok(event) = server.accept_receive() { 29 | // Handle events (e.g. Connection, Messages, etc.) 30 | match event { 31 | ServerEvent::Connection(id) => { 32 | let conn = server.connection(&id).unwrap(); 33 | println!( 34 | "[Server] Client {} ({}, {}ms rtt) connected.", 35 | id.0, 36 | conn.peer_addr(), 37 | conn.rtt() 38 | ); 39 | 40 | }, 41 | ServerEvent::Message(id, message) => { 42 | let conn = server.connection(&id).unwrap(); 43 | println!( 44 | "[Server] Message from client {} ({}, {}ms rtt): {:?}", 45 | id.0, 46 | conn.peer_addr(), 47 | conn.rtt(), 48 | message 49 | ); 50 | 51 | }, 52 | ServerEvent::ConnectionClosed(id, _) | ServerEvent::ConnectionLost(id, _) => { 53 | let conn = server.connection(&id).unwrap(); 54 | println!( 55 | "[Server] Client {} ({}, {}ms rtt) disconnected.", 56 | id.0, 57 | conn.peer_addr(), 58 | conn.rtt() 59 | ); 60 | break 'main; 61 | }, 62 | _ => {} 63 | } 64 | } 65 | 66 | // Send a message to all connected clients 67 | for (_, conn) in server.connections() { 68 | conn.send(MessageKind::Instant, b"Hello from Server".to_vec()); 69 | } 70 | 71 | // Send all outgoing messages. 72 | // 73 | // Also auto delay the current thread to achieve the configured tick rate. 74 | server.send(true).is_ok(); 75 | 76 | } 77 | 78 | println!("[Server] Shutting down..."); 79 | 80 | // Shutdown the server (freeing its socket and closing all its connections) 81 | server.shutdown().ok(); 82 | 83 | } 84 | 85 | -------------------------------------------------------------------------------- /src/client.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2017 Ivo Wetzel 2 | 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | 10 | // STD Dependencies ----------------------------------------------------------- 11 | use std::io::{Error, ErrorKind}; 12 | use std::net::{SocketAddr, ToSocketAddrs}; 13 | use std::sync::mpsc::TryRecvError; 14 | use std::collections::VecDeque; 15 | 16 | 17 | // Internal Dependencies ------------------------------------------------------ 18 | use shared::stats::{Stats, StatsCollector}; 19 | use shared::ticker::Ticker; 20 | use super::{ 21 | Config, 22 | Connection, ConnectionEvent, 23 | RateLimiter, PacketModifier, Socket 24 | }; 25 | 26 | 27 | /// Enum of client related network events. 28 | #[derive(Debug, PartialEq)] 29 | pub enum ClientEvent { 30 | 31 | /// Emitted once a connection to a server has been established. 32 | Connection, 33 | 34 | /// Emitted when a initial connection attempt to a server failed. 35 | ConnectionFailed, 36 | 37 | /// Emitted when a existing connection to a server is lost. 38 | /// 39 | /// The contained boolean indicates whether the connection was lost due to 40 | /// an isse the remote end, if the value is `false` instead, then a local 41 | /// issue caused the connection to be lost. 42 | ConnectionLost(bool), 43 | 44 | /// Emitted when a connection is closed programmatically. 45 | /// 46 | /// The contained boolean indicates whether the connection was closed by the 47 | /// remote end, if the value is `false` instead, then the connection was 48 | /// closed locally. 49 | ConnectionClosed(bool), 50 | 51 | /// Emitted for each message received from a server. 52 | Message(Vec), 53 | 54 | /// Emitted for each packet which was not confirmed by a server 55 | /// within the specified limits. 56 | PacketLost(Vec), 57 | 58 | /// Emitted each time the connection's congestion state changes. 59 | ConnectionCongestionStateChanged(bool) 60 | 61 | } 62 | 63 | /// Implementation of a low latency socket client. 64 | /// 65 | /// # Basic Usage 66 | /// 67 | /// ``` 68 | /// use cobalt::{ 69 | /// BinaryRateLimiter, Client, Config, NoopPacketModifier, MessageKind, UdpSocket 70 | /// }; 71 | /// 72 | /// // Create a new client that communicates over a udp socket 73 | /// let mut client = Client::::new(Config::default()); 74 | /// 75 | /// // Initiate a connection to the server 76 | /// client.connect("127.0.0.1:1234").expect("Failed to bind to socket"); 77 | /// 78 | /// // loop { 79 | /// 80 | /// // Fetch connection events 81 | /// while let Ok(event) = client.receive() { 82 | /// // Handle events (e.g. Connection, Messages, etc.) 83 | /// } 84 | /// 85 | /// // Schedule a message to the send to the server 86 | /// if let Ok(connection) = client.connection() { 87 | /// connection.send(MessageKind::Instant, b"Ping".to_vec()); 88 | /// } 89 | /// 90 | /// // Send all outgoing messages. 91 | /// // 92 | /// // Also auto delay the current thread to achieve the configured tick rate. 93 | /// client.send(true); 94 | /// 95 | /// // } 96 | /// 97 | /// // Disconnect the client, closing its connection and unbinding its socket 98 | /// client.disconnect(); 99 | /// ``` 100 | #[derive(Debug)] 101 | pub struct Client { 102 | config: Config, 103 | socket: Option, 104 | connection: Option>, 105 | ticker: Ticker, 106 | peer_address: Option, 107 | local_address: Option, 108 | events: VecDeque, 109 | should_receive: bool, 110 | stats_collector: StatsCollector, 111 | stats: Stats 112 | } 113 | 114 | impl Client { 115 | 116 | /// Creates a new client with the given configuration. 117 | pub fn new(config: Config) -> Client { 118 | Client { 119 | config: config, 120 | socket: None, 121 | connection: None, 122 | ticker: Ticker::new(config), 123 | peer_address: None, 124 | local_address: None, 125 | events: VecDeque::new(), 126 | should_receive: false, 127 | stats_collector: StatsCollector::new(config), 128 | stats: Stats { 129 | bytes_sent: 0, 130 | bytes_received: 0 131 | } 132 | } 133 | } 134 | 135 | /// Returns the number of bytes sent over the last second. 136 | pub fn bytes_sent(&self) -> u32 { 137 | self.stats.bytes_sent 138 | } 139 | 140 | /// Returns the number of bytes received over the last second. 141 | pub fn bytes_received(&self) -> u32 { 142 | self.stats.bytes_received 143 | } 144 | 145 | /// Returns the address of the server the client is currently connected to. 146 | pub fn peer_addr(&self) -> Result { 147 | self.peer_address.ok_or_else(|| Error::new(ErrorKind::AddrNotAvailable, "")) 148 | } 149 | 150 | /// Returns the local address that the client is sending from. 151 | pub fn local_addr(&self) -> Result { 152 | self.local_address.ok_or_else(|| Error::new(ErrorKind::AddrNotAvailable, "")) 153 | } 154 | 155 | /// Returns a mutable reference to underlying connection to the server. 156 | pub fn connection(&mut self) -> Result<&mut Connection, Error> { 157 | if let Some(connection) = self.connection.as_mut() { 158 | Ok(connection) 159 | 160 | } else { 161 | Err(Error::new(ErrorKind::NotConnected, "")) 162 | } 163 | } 164 | 165 | /// Returns a mutable reference to the client's underlying socket. 166 | pub fn socket(&mut self) -> Result<&mut S, Error> { 167 | if let Some(socket) = self.socket.as_mut() { 168 | Ok(socket) 169 | 170 | } else { 171 | Err(Error::new(ErrorKind::NotConnected, "")) 172 | } 173 | } 174 | 175 | /// Returns the client's current configuration. 176 | pub fn config(&self) -> Config { 177 | self.config 178 | } 179 | 180 | /// Overrides the client's current configuration. 181 | pub fn set_config(&mut self, config: Config) { 182 | 183 | self.config = config; 184 | self.ticker.set_config(config); 185 | self.stats_collector.set_config(config); 186 | 187 | if let Some(connection) = self.connection.as_mut() { 188 | connection.set_config(config); 189 | } 190 | 191 | } 192 | 193 | /// Establishes a connection with the server at the specified address. 194 | pub fn connect(&mut self, addr: A) -> Result<(), Error> { 195 | 196 | if self.socket.is_none() { 197 | 198 | let socket = try!(S::new( 199 | "0.0.0.0:0", 200 | self.config.packet_max_size 201 | )); 202 | 203 | let peer_addr = try!(addr.to_socket_addrs()).nth(0).unwrap(); 204 | let local_addr = try!(socket.local_addr()); 205 | 206 | self.socket = Some(socket); 207 | self.peer_address = Some(peer_addr); 208 | self.local_address = Some(local_addr); 209 | 210 | self.connection = Some(Connection::new( 211 | self.config, 212 | local_addr, 213 | peer_addr, 214 | R::new(self.config), 215 | M::new(self.config) 216 | )); 217 | 218 | self.should_receive = true; 219 | 220 | Ok(()) 221 | 222 | } else { 223 | Err(Error::new(ErrorKind::AlreadyExists, "")) 224 | } 225 | 226 | } 227 | 228 | /// Receives the next incoming message from the client's underlying 229 | /// connection. 230 | pub fn receive(&mut self) -> Result { 231 | 232 | if self.socket.is_none() { 233 | Err(TryRecvError::Disconnected) 234 | 235 | } else { 236 | 237 | if self.should_receive { 238 | 239 | self.ticker.begin_tick(); 240 | 241 | let peer_address = self.peer_address.unwrap(); 242 | 243 | // Receive all incoming UDP packets to our local address 244 | let mut bytes_received = 0; 245 | while let Ok((addr, packet)) = self.socket.as_mut().unwrap().try_recv() { 246 | if addr == peer_address { 247 | bytes_received += packet.len(); 248 | self.connection.as_mut().unwrap().receive_packet(packet); 249 | } 250 | } 251 | 252 | self.stats_collector.set_bytes_received(bytes_received as u32); 253 | 254 | // Map connection events 255 | for e in self.connection.as_mut().unwrap().events() { 256 | self.events.push_back(match e { 257 | ConnectionEvent::Connected => ClientEvent::Connection, 258 | ConnectionEvent::FailedToConnect => ClientEvent::ConnectionFailed, 259 | ConnectionEvent::Lost(by_remote) => ClientEvent::ConnectionLost(by_remote), 260 | ConnectionEvent::Closed(by_remote) => ClientEvent::ConnectionClosed(by_remote), 261 | ConnectionEvent::Message(payload) => ClientEvent::Message(payload), 262 | ConnectionEvent::CongestionStateChanged(c) => ClientEvent::ConnectionCongestionStateChanged(c), 263 | ConnectionEvent::PacketLost(payload) => ClientEvent::PacketLost(payload) 264 | }); 265 | } 266 | 267 | self.should_receive = false; 268 | 269 | } 270 | 271 | if let Some(event) = self.events.pop_front() { 272 | Ok(event) 273 | 274 | } else { 275 | Err(TryRecvError::Empty) 276 | } 277 | 278 | } 279 | 280 | } 281 | 282 | /// Sends all queued messages over the client's underlying connection. 283 | /// 284 | /// If `auto_tick` is specified as `true` this method will block the 285 | /// current thread for the amount of time which is required to limit the 286 | /// number of calls per second (when called inside a loop) to the client's 287 | /// configured `send_rate`. 288 | pub fn send(&mut self, auto_tick: bool) -> Result<(), Error> { 289 | if self.socket.is_some() { 290 | 291 | let peer_address = self.peer_address.unwrap(); 292 | let bytes_sent = self.connection.as_mut().unwrap().send_packet( 293 | self.socket.as_mut().unwrap(), 294 | &peer_address 295 | ); 296 | 297 | self.stats_collector.set_bytes_sent(bytes_sent); 298 | self.stats_collector.tick(); 299 | self.stats = self.stats_collector.average(); 300 | 301 | self.should_receive = true; 302 | 303 | if auto_tick { 304 | self.ticker.end_tick(); 305 | } 306 | 307 | Ok(()) 308 | 309 | } else { 310 | Err(Error::new(ErrorKind::NotConnected, "")) 311 | } 312 | } 313 | 314 | /// Resets the client, clearing all pending events and dropping any 315 | /// connection to the server, returning it into the `Connecting` 316 | /// state. 317 | /// 318 | /// This can be used to re-try a connection attempt if a previous one has 319 | /// failed. 320 | pub fn reset(&mut self) -> Result<(), Error> { 321 | if self.socket.is_some() { 322 | self.connection.as_mut().unwrap().reset(); 323 | self.stats_collector.reset(); 324 | self.stats.reset(); 325 | self.events.clear(); 326 | self.ticker.reset(); 327 | Ok(()) 328 | 329 | } else { 330 | Err(Error::new(ErrorKind::NotConnected, "")) 331 | } 332 | } 333 | 334 | /// Drops the client's connection to the server, freeing the socket and 335 | /// clearing any state. 336 | pub fn disconnect(&mut self) -> Result<(), Error> { 337 | if self.socket.is_some() { 338 | self.reset().ok(); 339 | self.should_receive = false; 340 | self.peer_address = None; 341 | self.local_address = None; 342 | self.connection = None; 343 | self.socket = None; 344 | Ok(()) 345 | 346 | } else { 347 | Err(Error::new(ErrorKind::NotConnected, "")) 348 | } 349 | } 350 | 351 | } 352 | 353 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2017 Ivo Wetzel 2 | 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | //! **cobalt** is low level a networking library which implements [virtual 10 | //! connections over UDP](http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/) 11 | //! supporting both unreliable messaging and reliable messages with optional 12 | //! in-order delivery. 13 | //! 14 | //! It is designed for use with real-time, low latency situations, for example 15 | //! action oriented multiplayer games. 16 | //! 17 | //! The library provides the underlying architecture required for handling and 18 | //! maintaining virtual connections over UDP sockets and takes care of sending 19 | //! raw messages over the established client-server connections with minimal 20 | //! overhead. 21 | #![cfg_attr(feature="clippy", feature(plugin))] 22 | #![cfg_attr(feature="clippy", plugin(clippy))] 23 | #![deny( 24 | missing_docs, 25 | missing_debug_implementations, missing_copy_implementations, 26 | trivial_casts, trivial_numeric_casts, 27 | unsafe_code, 28 | unused_import_braces, unused_qualifications 29 | )] 30 | mod shared; 31 | mod traits; 32 | mod client; 33 | mod server; 34 | 35 | 36 | // Exports -------------------------------------------------------------------- 37 | pub use shared::{ 38 | BinaryRateLimiter, 39 | Config, 40 | Connection, 41 | ConnectionID, 42 | ConnectionMap, 43 | ConnectionState, 44 | ConnectionEvent, 45 | MessageKind, 46 | NoopPacketModifier, 47 | UdpSocket 48 | }; 49 | pub use traits::*; 50 | pub use client::*; 51 | pub use server::*; 52 | 53 | #[cfg(test)] 54 | mod test; 55 | 56 | -------------------------------------------------------------------------------- /src/server.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2017 Ivo Wetzel 2 | 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | 10 | // STD Dependencies ----------------------------------------------------------- 11 | use std::io::{Error, ErrorKind}; 12 | use std::net::{SocketAddr, ToSocketAddrs}; 13 | use std::sync::mpsc::TryRecvError; 14 | use std::collections::{HashMap, VecDeque}; 15 | 16 | 17 | // Internal Dependencies ------------------------------------------------------ 18 | use shared::stats::{Stats, StatsCollector}; 19 | use shared::ticker::Ticker; 20 | use super::{ 21 | Config, 22 | ConnectionID, Connection, ConnectionEvent, 23 | RateLimiter, PacketModifier, Socket 24 | }; 25 | 26 | 27 | /// Enum of server network events. 28 | #[derive(Debug, PartialEq)] 29 | pub enum ServerEvent { 30 | 31 | /// Event emitted once a new client connection has been established. 32 | Connection(ConnectionID), 33 | 34 | /// Event emitted when a existing client connection is lost. 35 | /// 36 | /// The contained boolean indicates whether the connection was lost due to 37 | /// an isse the remote end, if the value is `false` instead, then a local 38 | /// issue caused the connection to be lost. 39 | ConnectionLost(ConnectionID, bool), 40 | 41 | /// Event emitted when a client connection is closed programmatically. 42 | /// 43 | /// The contained boolean indicates whether the connection was closed by the 44 | /// remote end, if the value is `false` instead, then the connection was 45 | /// closed locally. 46 | ConnectionClosed(ConnectionID, bool), 47 | 48 | /// Event emitted for each message received from a client connection. 49 | Message(ConnectionID, Vec), 50 | 51 | /// Event emitted each time a client's connection congestion state changes. 52 | ConnectionCongestionStateChanged(ConnectionID, bool), 53 | 54 | /// Event emitted each time a client connection packet is lost. 55 | PacketLost(ConnectionID, Vec) 56 | 57 | } 58 | 59 | 60 | /// Implementation of a multi-client low latency socket server. 61 | /// 62 | /// # Basic Usage 63 | /// 64 | /// ``` 65 | /// use cobalt::{ 66 | /// BinaryRateLimiter, Server, Config, NoopPacketModifier, MessageKind, UdpSocket 67 | /// }; 68 | /// 69 | /// // Create a new server that communicates over a udp socket 70 | /// let mut server = Server::::new(Config::default()); 71 | /// 72 | /// // Make the server listen on port `1234` on all interfaces. 73 | /// server.listen("0.0.0.0:1234").expect("Failed to bind to socket."); 74 | /// 75 | /// // loop { 76 | /// 77 | /// // Accept incoming connections and fetch their events 78 | /// while let Ok(event) = server.accept_receive() { 79 | /// // Handle events (e.g. Connection, Messages, etc.) 80 | /// } 81 | /// 82 | /// // Send a message to all connected clients 83 | /// for (_, conn) in server.connections() { 84 | /// conn.send(MessageKind::Instant, b"Ping".to_vec()); 85 | /// } 86 | /// 87 | /// // Send all outgoing messages. 88 | /// // 89 | /// // Also auto delay the current thread to achieve the configured tick rate. 90 | /// server.send(true); 91 | /// 92 | /// // } 93 | /// 94 | /// // Shutdown the server (freeing its socket and closing all its connections) 95 | /// server.shutdown(); 96 | /// ``` 97 | /// 98 | #[derive(Debug)] 99 | pub struct Server { 100 | config: Config, 101 | socket: Option, 102 | connections: HashMap>, 103 | addresses: HashMap, 104 | dropped: Vec, 105 | ticker: Ticker, 106 | local_address: Option, 107 | events: VecDeque, 108 | should_receive: bool, 109 | stats_collector: StatsCollector, 110 | stats: Stats 111 | } 112 | 113 | impl Server { 114 | 115 | /// Creates a new server with the given configuration. 116 | pub fn new(config: Config) -> Server { 117 | Server { 118 | config: config, 119 | socket: None, 120 | connections: HashMap::new(), 121 | addresses: HashMap::new(), 122 | dropped: Vec::new(), 123 | ticker: Ticker::new(config), 124 | local_address: None, 125 | events: VecDeque::new(), 126 | should_receive: false, 127 | stats_collector: StatsCollector::new(config), 128 | stats: Stats { 129 | bytes_sent: 0, 130 | bytes_received: 0 131 | } 132 | } 133 | } 134 | 135 | /// Returns the number of bytes sent over the last second. 136 | pub fn bytes_sent(&self) -> u32 { 137 | self.stats.bytes_sent 138 | } 139 | 140 | /// Returns the number of bytes received over the last second. 141 | pub fn bytes_received(&self) -> u32 { 142 | self.stats.bytes_received 143 | } 144 | 145 | /// Returns the local address that the client is sending from. 146 | pub fn local_addr(&self) -> Result { 147 | self.local_address.ok_or_else(|| Error::new(ErrorKind::AddrNotAvailable, "")) 148 | } 149 | 150 | /// Returns a mutable reference to the specified client connection. 151 | pub fn connection(&mut self, id: &ConnectionID) -> Result<&mut Connection, Error> { 152 | if self.socket.is_some() { 153 | if let Some(conn) = self.connections.get_mut(id) { 154 | Ok(conn) 155 | 156 | } else { 157 | Err(Error::new(ErrorKind::NotFound, "")) 158 | } 159 | 160 | } else { 161 | Err(Error::new(ErrorKind::NotConnected, "")) 162 | } 163 | } 164 | 165 | /// Returns a mutable reference to the servers client connections. 166 | pub fn connections(&mut self) -> &mut HashMap> { 167 | &mut self.connections 168 | } 169 | 170 | /// Returns a mutable reference to the server's underlying socket. 171 | pub fn socket(&mut self) -> Result<&mut S, Error> { 172 | if let Some(socket) = self.socket.as_mut() { 173 | Ok(socket) 174 | 175 | } else { 176 | Err(Error::new(ErrorKind::NotConnected, "")) 177 | } 178 | } 179 | 180 | /// Returns the server's current configuration. 181 | pub fn config(&self) -> Config { 182 | self.config 183 | } 184 | 185 | /// Overrides the server's current configuration. 186 | pub fn set_config(&mut self, config: Config) { 187 | 188 | self.config = config; 189 | self.ticker.set_config(config); 190 | self.stats_collector.set_config(config); 191 | 192 | for conn in self.connections.values_mut() { 193 | conn.set_config(config); 194 | } 195 | 196 | } 197 | 198 | /// Binds the server to listen the specified address. 199 | pub fn listen(&mut self, addr: A) -> Result<(), Error> { 200 | 201 | if self.socket.is_none() { 202 | 203 | let local_addr = try!(addr.to_socket_addrs()).nth(0).unwrap(); 204 | let socket = try!(S::new( 205 | local_addr, 206 | self.config.packet_max_size 207 | )); 208 | 209 | self.socket = Some(socket); 210 | self.local_address = Some(local_addr); 211 | self.should_receive = true; 212 | 213 | Ok(()) 214 | 215 | } else { 216 | Err(Error::new(ErrorKind::AlreadyExists, "")) 217 | } 218 | 219 | } 220 | 221 | /// Accepts new incoming client connections from the server's underlying 222 | /// server and receives and returns messages from them. 223 | pub fn accept_receive(&mut self) -> Result { 224 | 225 | if self.socket.is_none() { 226 | Err(TryRecvError::Disconnected) 227 | 228 | } else { 229 | 230 | if self.should_receive { 231 | 232 | self.ticker.begin_tick(); 233 | 234 | // Receive all incoming UDP packets to our local address 235 | let mut bytes_received = 0; 236 | while let Ok((addr, packet)) = self.socket.as_mut().unwrap().try_recv() { 237 | 238 | // Try to extract the connection id from the packet 239 | if let Some(id) = Connection::::id_from_packet(&self.config, &packet) { 240 | bytes_received += self.receive_connection_packet(id, addr, packet); 241 | } 242 | 243 | } 244 | 245 | self.stats_collector.set_bytes_received(bytes_received as u32); 246 | self.should_receive = false; 247 | 248 | } 249 | 250 | if let Some(event) = self.events.pop_front() { 251 | Ok(event) 252 | 253 | } else { 254 | Err(TryRecvError::Empty) 255 | } 256 | 257 | } 258 | 259 | } 260 | 261 | /// Sends all queued messages to the server's underlying client connections. 262 | /// 263 | /// If `auto_tick` is specified as `true` this method will block the 264 | /// current thread for the amount of time which is required to limit the 265 | /// number of calls per second (when called inside a loop) to the server's 266 | /// configured `send_rate`. 267 | pub fn send(&mut self, auto_tick: bool) -> Result<(), Error> { 268 | if self.socket.is_some() { 269 | 270 | // Remove any dropped connections and their address mappings 271 | for id in self.dropped.drain(0..) { 272 | self.connections.remove(&id).unwrap().reset(); 273 | self.addresses.remove(&id); 274 | } 275 | 276 | // Create outgoing packets for all connections 277 | let mut bytes_sent = 0; 278 | for (id, connection) in &mut self.connections { 279 | 280 | // Resolve the last known remote address for this 281 | // connection and send the data 282 | let addr = &self.addresses[id]; 283 | 284 | // Then invoke the connection to send a outgoing packet 285 | bytes_sent += connection.send_packet( 286 | self.socket.as_mut().unwrap(), 287 | addr 288 | ); 289 | 290 | // Collect all lost / closed connections 291 | if !connection.open() { 292 | // Map any remaining connection events 293 | map_connection_events(&mut self.events, connection); 294 | self.dropped.push(*id); 295 | } 296 | 297 | } 298 | 299 | self.stats_collector.set_bytes_sent(bytes_sent); 300 | self.stats_collector.tick(); 301 | self.stats = self.stats_collector.average(); 302 | 303 | self.should_receive = true; 304 | 305 | if auto_tick { 306 | self.ticker.end_tick(); 307 | } 308 | 309 | Ok(()) 310 | 311 | } else { 312 | Err(Error::new(ErrorKind::NotConnected, "")) 313 | } 314 | } 315 | 316 | /// Shuts down all of the server's client connections, clearing any state 317 | /// and freeing the server's socket. 318 | pub fn shutdown(&mut self) -> Result<(), Error> { 319 | if self.socket.is_some() { 320 | self.should_receive = false; 321 | self.stats_collector.reset(); 322 | self.stats.reset(); 323 | self.events.clear(); 324 | self.connections.clear(); 325 | self.addresses.clear(); 326 | self.dropped.clear(); 327 | self.ticker.reset(); 328 | self.local_address = None; 329 | self.socket = None; 330 | Ok(()) 331 | 332 | } else { 333 | Err(Error::new(ErrorKind::NotConnected, "")) 334 | } 335 | } 336 | 337 | // Internal --------------------------------------------------------------- 338 | fn receive_connection_packet( 339 | &mut self, 340 | id: ConnectionID, 341 | addr: SocketAddr, 342 | packet: Vec 343 | 344 | ) -> usize { 345 | 346 | let packet_length = packet.len(); 347 | 348 | // Get existing connection 349 | if self.connections.contains_key(&id) { 350 | 351 | let connection = self.connections.get_mut(&id).unwrap(); 352 | 353 | // Check if the packet was actually consumed by the connection. 354 | // 355 | // If it was, see if the address we received the packet from differs 356 | // from the last known address of the connection. 357 | // 358 | // If it does, we re-map the connections address to the new one, 359 | // effectively tracking the clients sending / receiving port. 360 | // 361 | // This is done so that when the clients NAT decides to switch the 362 | // port the connection doesn't end up sending packets into the void. 363 | if connection.receive_packet(packet) && addr != connection.peer_addr() { 364 | connection.set_peer_addr(addr); 365 | self.addresses.remove(&id); 366 | self.addresses.insert(id, addr); 367 | } 368 | 369 | // Map any connection events 370 | map_connection_events(&mut self.events, connection); 371 | 372 | packet_length 373 | 374 | // Or insert new one 375 | } else { 376 | 377 | let mut conn = Connection::new( 378 | self.config, 379 | self.local_address.unwrap(), 380 | addr, 381 | R::new(self.config), 382 | M::new(self.config) 383 | ); 384 | 385 | conn.set_id(id); 386 | 387 | self.connections.insert(id, conn); 388 | self.addresses.insert(id, addr); 389 | 390 | // Receive first packet 391 | let connection = self.connections.get_mut(&id).unwrap(); 392 | 393 | if connection.receive_packet(packet) { 394 | 395 | // Map any connection events 396 | map_connection_events(&mut self.events, connection); 397 | 398 | } 399 | 400 | packet_length 401 | 402 | } 403 | 404 | } 405 | 406 | } 407 | 408 | // Helpers -------------------------------------------------------------------- 409 | fn map_connection_events( 410 | server_events: &mut VecDeque, 411 | connection: &mut Connection 412 | ) { 413 | let id = connection.id(); 414 | for event in connection.events() { 415 | server_events.push_back(match event { 416 | ConnectionEvent::Connected => ServerEvent::Connection(id), 417 | ConnectionEvent::Lost(by_remote) => ServerEvent::ConnectionLost(id, by_remote), 418 | ConnectionEvent::FailedToConnect => unreachable!(), 419 | ConnectionEvent::Closed(by_remote) => ServerEvent::ConnectionClosed(id, by_remote), 420 | ConnectionEvent::Message(payload) => ServerEvent::Message(id, payload), 421 | ConnectionEvent::CongestionStateChanged(c) => ServerEvent::ConnectionCongestionStateChanged(id, c), 422 | ConnectionEvent::PacketLost(payload) => ServerEvent::PacketLost(id, payload) 423 | }) 424 | } 425 | } 426 | 427 | -------------------------------------------------------------------------------- /src/shared/binary_rate_limiter.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2017 Ivo Wetzel 2 | 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | 10 | // STD Dependencies ----------------------------------------------------------- 11 | use std::cmp; 12 | use std::time::{Duration, Instant}; 13 | 14 | 15 | // Internal Dependencies ------------------------------------------------------ 16 | use ::{Config, RateLimiter}; 17 | 18 | /// Minimum time before switching back into good mode in milliseconds. 19 | const MIN_GOOD_MODE_TIME_DELAY: u64 = 1000; 20 | 21 | /// Maximum time before switching back into good mode in milliseconds. 22 | const MAX_GOOD_MODE_TIME_DELAY: u64 = 60000; 23 | 24 | #[derive(Debug, PartialEq)] 25 | enum Mode { 26 | Good, 27 | Bad 28 | } 29 | 30 | /// Implementation of a binary state rate limiter for congestion avoidance. 31 | /// 32 | /// It is based on the example design from the following article: 33 | /// http://gafferongames.com/networking-for-game-programmers/reliability-and-flow-control/ 34 | #[derive(Debug)] 35 | pub struct BinaryRateLimiter { 36 | tick: u32, 37 | max_tick: u32, 38 | mode: Mode, 39 | rtt_threshold: u32, 40 | last_bad_time: Instant, 41 | last_good_time: Instant, 42 | good_time_duration: u64, 43 | delay_until_good_mode: u64 44 | } 45 | 46 | impl RateLimiter for BinaryRateLimiter { 47 | 48 | fn new(config: Config) -> BinaryRateLimiter { 49 | 50 | let rate = config.send_rate as f32; 51 | 52 | BinaryRateLimiter { 53 | tick: 0, 54 | // Calculate about a third of normal send rate 55 | max_tick: (rate / (33.0 / (100.0 / rate))) as u32, 56 | mode: Mode::Good, 57 | rtt_threshold: 250, 58 | last_bad_time: Instant::now(), 59 | last_good_time: Instant::now(), 60 | good_time_duration: 0, 61 | delay_until_good_mode: MIN_GOOD_MODE_TIME_DELAY 62 | } 63 | 64 | } 65 | 66 | fn update(&mut self, rtt: u32, _: f32) { 67 | 68 | // Check current network conditions 69 | let conditions = if rtt <= self.rtt_threshold { 70 | // Keep track of the time we are in good mode 71 | self.good_time_duration += time_since(&self.last_good_time); 72 | self.last_good_time = Instant::now(); 73 | Mode::Good 74 | 75 | } else { 76 | // Remember the last time we were in bad mode 77 | self.last_bad_time = Instant::now(); 78 | self.good_time_duration = 0; 79 | Mode::Bad 80 | }; 81 | 82 | match self.mode { 83 | 84 | Mode::Good => match conditions { 85 | 86 | // If we are currently in good mode, and conditions become bad, 87 | // immediately drop to bad mode 88 | Mode::Bad => { 89 | 90 | self.mode = Mode::Bad; 91 | 92 | // To avoid rapid toggling between good and bad mode, if we 93 | // drop from good mode to bad in under 10 seconds 94 | if time_since(&self.last_bad_time) < 10000 { 95 | 96 | // We double the amount of time before bad mode goes 97 | // back to good. 98 | self.delay_until_good_mode *= 2; 99 | 100 | // We also clamp this at a maximum 101 | self.delay_until_good_mode = cmp::min( 102 | self.delay_until_good_mode, 103 | MAX_GOOD_MODE_TIME_DELAY 104 | ); 105 | 106 | } 107 | 108 | }, 109 | 110 | Mode::Good => { 111 | 112 | // To avoid punishing good connections when they have short 113 | // periods of bad behavior, for each 10 seconds the 114 | // connection is in good mode, we halve the time before bad 115 | // mode goes back to good. 116 | if self.good_time_duration >= 10000 { 117 | self.good_time_duration -= 10000; 118 | 119 | // We also clamp this at a minimum 120 | self.delay_until_good_mode = cmp::max( 121 | self.delay_until_good_mode, 122 | MIN_GOOD_MODE_TIME_DELAY 123 | ); 124 | 125 | } 126 | 127 | } 128 | 129 | }, 130 | 131 | Mode::Bad => { 132 | 133 | // If you are in bad mode, and conditions have been good for a 134 | // specific length of time return to good mode 135 | if time_since(&self.last_bad_time) > self.delay_until_good_mode { 136 | self.mode = Mode::Good; 137 | } 138 | 139 | } 140 | 141 | } 142 | 143 | // Tick wrapper for send rate reduction, max_tick is calculated to be 144 | // about a third of the configured send_rate 145 | self.tick += 1; 146 | if self.tick == self.max_tick { 147 | self.tick = 0; 148 | } 149 | 150 | } 151 | 152 | fn congested(&self) -> bool { 153 | self.mode == Mode::Bad 154 | } 155 | 156 | fn should_send(&self ) -> bool { 157 | // Send all packets when in good mode and about only a third when in 158 | // bad mode 159 | !self.congested() || self.tick == 0 160 | } 161 | 162 | fn reset(&mut self) { 163 | self.tick = 0; 164 | self.mode = Mode::Good; 165 | self.last_bad_time = Instant::now();; 166 | self.last_good_time = Instant::now(); 167 | self.good_time_duration = 0; 168 | self.delay_until_good_mode = MIN_GOOD_MODE_TIME_DELAY; 169 | } 170 | 171 | } 172 | 173 | fn time_since(i: &Instant) -> u64 { 174 | millis_from_duration(i.elapsed()) 175 | } 176 | 177 | fn millis_from_duration(d: Duration) -> u64 { 178 | d.as_secs() * 1000 + (d.subsec_nanos() as u64 / 1000000) 179 | } 180 | 181 | #[cfg(test)] 182 | mod test { 183 | 184 | use std::thread; 185 | use std::time::Duration; 186 | 187 | use ::{Config, RateLimiter}; 188 | use super::BinaryRateLimiter; 189 | 190 | #[test] 191 | fn test_modes() { 192 | 193 | let mut rl = BinaryRateLimiter::new(Config::default()); 194 | 195 | // Default to good mode 196 | assert_eq!(rl.congested(), false); 197 | assert_eq!(rl.should_send(), true); 198 | 199 | // Update with values that continue good mode 200 | rl.update(51, 0.0); 201 | assert_eq!(rl.congested(), false); 202 | assert_eq!(rl.should_send(), true); 203 | 204 | rl.update(151, 0.0); 205 | assert_eq!(rl.congested(), false); 206 | assert_eq!(rl.should_send(), true); 207 | 208 | rl.update(250, 0.0); 209 | assert_eq!(rl.congested(), false); 210 | assert_eq!(rl.should_send(), true); 211 | 212 | // Update with values that will trigger bad mode 213 | rl.update(251, 0.0); 214 | 215 | // Should now be in bad mode 216 | assert_eq!(rl.congested(), true); 217 | 218 | // Should not send for the next two update calls 219 | assert_eq!(rl.should_send(), false); 220 | rl.update(251, 0.0); 221 | assert_eq!(rl.should_send(), false); 222 | rl.update(251, 0.0); 223 | 224 | // Every third tick should send while in bad mode 225 | assert_eq!(rl.should_send(), true); 226 | 227 | // Sleep until the limiter will transition back into good mode 228 | thread::sleep(Duration::from_millis(2100)); 229 | rl.update(12, 0.0); 230 | assert_eq!(rl.congested(), false); 231 | assert_eq!(rl.should_send(), true); 232 | 233 | } 234 | 235 | #[test] 236 | fn test_reset() { 237 | 238 | let mut rl = BinaryRateLimiter::new(Config::default()); 239 | 240 | // Default to good mode 241 | assert_eq!(rl.congested(), false); 242 | assert_eq!(rl.should_send(), true); 243 | 244 | // Update with values that will trigger bad mode 245 | rl.update(251, 0.0); 246 | assert_eq!(rl.congested(), true); 247 | assert_eq!(rl.should_send(), false); 248 | 249 | // Reset should put the limiter back into good mode 250 | rl.reset(); 251 | assert_eq!(rl.congested(), false); 252 | assert_eq!(rl.should_send(), true); 253 | 254 | } 255 | 256 | } 257 | 258 | -------------------------------------------------------------------------------- /src/shared/config.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2017 Ivo Wetzel 2 | 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | 10 | // STD Dependencies ----------------------------------------------------------- 11 | use std::time::Duration; 12 | 13 | 14 | /// Structure defining connection and message configuration options. 15 | #[derive(Copy, Clone, Debug, PartialEq)] 16 | pub struct Config { 17 | 18 | /// Number of packets send per second. Default is `30`. 19 | pub send_rate: u64, 20 | 21 | /// Maximum bytes that can be received / send in one packet. Default 22 | /// `1400`. 23 | pub packet_max_size: usize, 24 | 25 | /// 32-Bit Protocol ID used to identify UDP related packets. Default is 26 | /// `[1, 2, 3, 4]`. 27 | pub protocol_header: [u8; 4], 28 | 29 | /// Maximum roundtrip-time in milliseconds before a packet is considered 30 | /// lost. Default is `1000`. 31 | pub packet_drop_threshold: Duration, 32 | 33 | /// Maximum time in milliseconds until the first packet must be received 34 | /// before a connection attempt fails. Default is `100`. 35 | pub connection_init_threshold: Duration, 36 | 37 | /// Maximum time in milliseconds between any two packets before the 38 | /// connection gets dropped. Default is `1000`. 39 | pub connection_drop_threshold: Duration, 40 | 41 | /// Maximum time in milliseconds to wait for remote confirmation after 42 | /// programmatically closing a connection. Default is `150`. 43 | pub connection_closing_threshold: Duration, 44 | 45 | /// The percent of available packet bytes to use when serializing 46 | /// `MessageKind::Instant` into a packet via a `MessageQueue`. 47 | pub message_quota_instant: f32, 48 | 49 | /// The percent of available packet bytes to use when serializing 50 | /// `MessageKind::Reliable` into a packet via a `MessageQueue`. 51 | pub message_quota_reliable: f32, 52 | 53 | /// The percent of available packet bytes to use when serializing 54 | /// `MessageKind::Ordered` into a packet via a `MessageQueue`. 55 | pub message_quota_ordered: f32, 56 | 57 | /// Whether to keep track of ticks which exceed their maximum running time 58 | /// and speed up successive ticks in order to keep the desired target 59 | /// `send_rate` stable. 60 | /// 61 | /// Each tick has a limit of the number of milliseconds in can take before 62 | /// the `send_rate` drops below the specified ticks per second 63 | /// target (`1000 / send_rate` milliseconds). Ticks which fall below this 64 | /// threshold will normally sleep for the remaining amount of time. 65 | /// 66 | /// Ticks which exceed this threshold will normally cause the `send_rate` 67 | /// to drop below the target; however, with `tick_overflow_recovery` 68 | /// enabled any tick which falls below the threshold will give up some of 69 | /// its remaining sleep time in order to allow the `send_rate` to catch up 70 | /// again. 71 | /// 72 | /// How much of each tick's sleep time is used for speedup purposes is 73 | /// determined by the value of `tick_overflow_recovery`. 74 | /// 75 | /// Default is `true`. 76 | pub tick_overflow_recovery: bool, 77 | 78 | /// Determines how much of each tick's sleep time may be used to reduce the 79 | /// current tick overflow time in order to smooth out the `send_rate`. 80 | /// 81 | /// Values must be in the range of `0.0` to `1.0` where `0.25` would be a 82 | /// quarter of the tick's sleep time. 83 | /// 84 | /// Example: For a `send_rate` of `30` with a maximum sleep time of `33.33` 85 | /// milliseconds, a `tick_overflow_recovery_rate` value of `0.5` would 86 | /// allow up to `16.66` milliseconds of sleep to be skipped. 87 | /// 88 | /// Values smaller than `0.0` or bigger than `1.0` will have no effect. 89 | /// 90 | /// Default is `1.0`. 91 | pub tick_overflow_recovery_rate: f32 92 | 93 | } 94 | 95 | impl Default for Config { 96 | 97 | fn default() -> Config { 98 | Config { 99 | send_rate: 30, 100 | protocol_header: [1, 2, 3, 4], 101 | packet_max_size: 1400, 102 | packet_drop_threshold: Duration::from_millis(1000), 103 | connection_init_threshold: Duration::from_millis(100), 104 | connection_drop_threshold: Duration::from_millis(1000), 105 | connection_closing_threshold: Duration::from_millis(150), 106 | message_quota_instant: 60.0, 107 | message_quota_reliable: 20.0, 108 | message_quota_ordered: 20.0, 109 | tick_overflow_recovery: true, 110 | tick_overflow_recovery_rate: 1.0 111 | } 112 | } 113 | 114 | } 115 | 116 | -------------------------------------------------------------------------------- /src/shared/connection.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2017 Ivo Wetzel 2 | 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | extern crate rand; 9 | 10 | 11 | // STD Dependencies ----------------------------------------------------------- 12 | use std::cmp; 13 | use std::vec::Drain; 14 | use std::net::SocketAddr; 15 | use std::time::{Duration, Instant}; 16 | use std::collections::{HashMap, VecDeque}; 17 | 18 | 19 | // Internal Dependencies ------------------------------------------------------ 20 | use super::message_queue::MessageQueue; 21 | use ::{Config, MessageKind, PacketModifier, RateLimiter, Socket}; 22 | 23 | /// Maximum number of acknowledgement bits available in the packet header. 24 | const MAX_ACK_BITS: u32 = 32; 25 | 26 | /// Maximum packet sequence number before wrap around happens. 27 | const MAX_SEQ_NUMBER: u32 = 256; 28 | 29 | /// Number of bytes used by a packet header. 30 | const PACKET_HEADER_SIZE: usize = 14; 31 | 32 | /// Special packet data used to notify of programmtic connection closure. 33 | const CLOSURE_PACKET_DATA: [u8; 6] = [ 34 | 0, 128, // Most distant sequence numbers 35 | 85, 85, 85, 85 // ack bitfield with every second bit set 36 | ]; 37 | 38 | /// Enum indicating the state of a `SentPacketAck`. 39 | #[derive(Debug, PartialEq)] 40 | enum PacketState { 41 | Unknown, 42 | Acked, 43 | Lost 44 | } 45 | 46 | /// Structure used for packet acknowledgment of sent packets. 47 | #[derive(Debug)] 48 | struct SentPacketAck { 49 | seq: u32, 50 | time: Instant, 51 | state: PacketState, 52 | packet: Option> 53 | } 54 | 55 | /// Enum indicating the state of a connection. 56 | #[derive(Debug, Copy, Clone, PartialEq)] 57 | pub enum ConnectionState { 58 | 59 | /// The connection has been opened but has yet to receive the first 60 | /// incoming packet. 61 | Connecting, 62 | 63 | /// The remote has responded and at least one incoming packet has been 64 | /// received. 65 | Connected, 66 | 67 | /// The remote did not respond with the first packet within the maximum 68 | /// configured time frame for establishing a connection. 69 | FailedToConnect, 70 | 71 | /// The remote did not send any packets within the maximum configured time 72 | /// frame between any two packets. 73 | Lost, 74 | 75 | /// The connection is about to be closed. 76 | Closing, 77 | 78 | /// The connection has been closed programmatically. 79 | Closed 80 | 81 | } 82 | 83 | /// Enum of connection related network events. 84 | #[derive(Debug, PartialEq)] 85 | pub enum ConnectionEvent { 86 | 87 | /// Emitted once a the connection has been established. 88 | Connected, 89 | 90 | /// Emitted when a connection attempt failed. 91 | FailedToConnect, 92 | 93 | /// Emitted when the already established connection is lost. 94 | Lost(bool), 95 | 96 | /// Emitted when the already established connection is closed 97 | /// programmatically. 98 | Closed(bool), 99 | 100 | /// Emitted for each message that is received over the connection. 101 | Message(Vec), 102 | 103 | /// Event emitted for each packet which was not confirmed by the remote end 104 | /// of the connection within the specified limits. 105 | PacketLost(Vec), 106 | 107 | /// Emitted each time the connection's congestion state changes. 108 | CongestionStateChanged(bool) 109 | } 110 | 111 | 112 | /// Representation of a random ID for connection identification purposes. 113 | /// 114 | /// Used to uniquely\* identify the reliable connections. The ID is send with 115 | /// every packet and allows to support multiple connections behind NAT. It also 116 | /// reduces the chance of connection drop attacks it also and helps with cases 117 | /// where NAT re-assigns local UDP ports which would cause purely address based 118 | /// packet identification mechanisms to break down. 119 | /// 120 | /// > \* Since the ID is random integer, there is of course a always a chance 121 | /// > for two connections to end up with the same ID, in that case - due to 122 | /// conflicting ack sequences and message data - both connections will get 123 | /// dropped shortly. 124 | #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, Ord, PartialOrd)] 125 | pub struct ConnectionID(pub u32); 126 | 127 | 128 | /// Type alias for connection mappings. 129 | pub type ConnectionMap = HashMap>; 130 | 131 | /// Implementation of a reliable, virtual socket connection. 132 | #[derive(Debug)] 133 | pub struct Connection { 134 | 135 | /// The connection's configuration 136 | config: Config, 137 | 138 | /// Random Connection ID 139 | random_id: ConnectionID, 140 | 141 | /// State of the connection 142 | state: ConnectionState, 143 | 144 | /// The socket address of the local end of the connection 145 | local_address: SocketAddr, 146 | 147 | /// The socket address of the remote end of the connection 148 | peer_address: SocketAddr, 149 | 150 | /// The most recent received remote sequence number 151 | remote_seq_number: u32, 152 | 153 | /// The current, local sequence number 154 | local_seq_number: u32, 155 | 156 | /// Exponentially smoothed moving average of the roundtrip time 157 | smoothed_rtt: f32, 158 | 159 | /// Last time a packet was received 160 | last_receive_time: Instant, 161 | 162 | /// Last time a packet was successully sent over the local network interface 163 | last_send_time: Instant, 164 | 165 | /// Queue of recently received packets used for ack bitfield construction 166 | recv_ack_queue: VecDeque, 167 | 168 | /// Queue of recently send packets pending acknowledgment 169 | sent_ack_queue: Vec, 170 | 171 | /// Number of all packets sent over the connection 172 | sent_packets: u32, 173 | 174 | /// Number of all packets received over the connection 175 | recv_packets: u32, 176 | 177 | /// Number of all packets sent which were acknowledged 178 | lost_packets: u32, 179 | 180 | /// Number of all packets sent which were lost 181 | acked_packets: u32, 182 | 183 | /// The internal message queue of the connection 184 | message_queue: MessageQueue, 185 | 186 | /// The rate limiter used to handle and avoid network congestion 187 | rate_limiter: R, 188 | 189 | /// The packet modifier used for payload modification 190 | packet_modifier: M, 191 | 192 | /// List of accumulated connection events 193 | events: Vec 194 | 195 | } 196 | 197 | impl Connection { 198 | 199 | /// Creates a new Virtual Connection over the given `SocketAddr`. 200 | /// 201 | /// # Examples 202 | /// 203 | /// ``` 204 | /// use std::net::SocketAddr; 205 | /// use cobalt::{ 206 | /// BinaryRateLimiter, 207 | /// Connection, ConnectionState, Config, 208 | /// NoopPacketModifier, PacketModifier, RateLimiter 209 | /// }; 210 | /// 211 | /// let config = Config::default(); 212 | /// let local_address: SocketAddr = "127.0.0.1:0".parse().unwrap(); 213 | /// let peer_address: SocketAddr = "255.0.0.1:0".parse().unwrap(); 214 | /// let limiter = BinaryRateLimiter::new(config); 215 | /// let modifier = NoopPacketModifier::new(config); 216 | /// let conn = Connection::new(config, local_address, peer_address, limiter, modifier); 217 | /// 218 | /// assert!(conn.state() == ConnectionState::Connecting); 219 | /// assert_eq!(conn.open(), true); 220 | /// ``` 221 | pub fn new( 222 | config: Config, 223 | local_addr: SocketAddr, 224 | peer_addr: SocketAddr, 225 | rate_limiter: R, 226 | packet_modifier: M 227 | 228 | ) -> Connection { 229 | Connection { 230 | config: config, 231 | random_id: ConnectionID(rand::random()), 232 | state: ConnectionState::Connecting, 233 | local_address: local_addr, 234 | peer_address: peer_addr, 235 | local_seq_number: 0, 236 | remote_seq_number: 0, 237 | smoothed_rtt: 0.0, 238 | last_receive_time: Instant::now(), 239 | last_send_time: Instant::now(), 240 | recv_ack_queue: VecDeque::new(), 241 | sent_ack_queue: Vec::new(), 242 | sent_packets: 0, 243 | recv_packets: 0, 244 | acked_packets: 0, 245 | lost_packets: 0, 246 | message_queue: MessageQueue::new(config), 247 | rate_limiter: rate_limiter, 248 | packet_modifier: packet_modifier, 249 | events: Vec::new() 250 | } 251 | } 252 | 253 | /// Extracts a `ConnectionID` from packet with a valid protocol header. 254 | /// 255 | /// # Examples 256 | /// 257 | /// ``` 258 | /// use cobalt::{ 259 | /// BinaryRateLimiter, 260 | /// Connection, ConnectionID, Config, 261 | /// NoopPacketModifier 262 | /// }; 263 | /// 264 | /// let config = Config { 265 | /// protocol_header: [11, 22, 33, 44], 266 | /// ..Config::default() 267 | /// }; 268 | /// 269 | /// let packet = [ 270 | /// 11, 22, 33, 44, 271 | /// 1, 2, 3, 4, 272 | /// 0, 273 | /// 0, 274 | /// 0, 0, 0, 0 275 | /// ]; 276 | /// 277 | /// let conn_id = Connection::::id_from_packet(&config, &packet); 278 | /// 279 | /// assert!(conn_id == Some(ConnectionID(16909060))); 280 | /// ``` 281 | pub fn id_from_packet(config: &Config, packet: &[u8]) -> Option { 282 | if packet.len() >= 8 && &packet[0..4] == &config.protocol_header { 283 | Some(ConnectionID( 284 | (packet[4] as u32) << 24 | (packet[5] as u32) << 16 | 285 | (packet[6] as u32) << 8 | packet[7] as u32 286 | )) 287 | 288 | } else { 289 | None 290 | } 291 | } 292 | 293 | /// Returns whether the connection is currently accepting any incoming 294 | /// packets. 295 | pub fn open(&self) -> bool { 296 | match self.state { 297 | ConnectionState::Closing | 298 | ConnectionState::Connecting | 299 | ConnectionState::Connected => true, 300 | _ => false 301 | } 302 | } 303 | 304 | /// Returns whether the connection is currently congested and should be 305 | /// sending less packets per second in order to resolve the congestion. 306 | pub fn congested(&self) -> bool { 307 | self.rate_limiter.congested() 308 | } 309 | 310 | /// Returns the id of the connection. 311 | pub fn id(&self) -> ConnectionID { 312 | self.random_id 313 | } 314 | 315 | /// Overrides the id of the connection. 316 | pub fn set_id(&mut self, id: ConnectionID) { 317 | self.random_id = id; 318 | } 319 | 320 | /// Returns the current state of the connection. 321 | pub fn state(&self) -> ConnectionState { 322 | self.state 323 | } 324 | 325 | /// Returns the average roundtrip time for the connection. 326 | pub fn rtt(&self) -> u32 { 327 | self.smoothed_rtt.ceil() as u32 328 | } 329 | 330 | /// Returns the percent of packets that were sent and never acknowledged 331 | /// over the total number of packets that have been send across the 332 | /// connection. 333 | pub fn packet_loss(&self) -> f32 { 334 | 100.0 / cmp::max(self.sent_packets, 1) as f32 * self.lost_packets as f32 335 | } 336 | 337 | /// Returns the socket address for the local end of this connection. 338 | pub fn local_addr(&self) -> SocketAddr { 339 | self.local_address 340 | } 341 | 342 | /// Returns the socket address for the remote end of this connection. 343 | pub fn peer_addr(&self) -> SocketAddr { 344 | self.peer_address 345 | } 346 | 347 | /// Sets the socket address of the remote peer of this connection. 348 | pub fn set_peer_addr(&mut self, peer_addr: SocketAddr) { 349 | self.peer_address = peer_addr; 350 | } 351 | 352 | /// Overrides the connection's existing configuration. 353 | pub fn set_config(&mut self, config: Config) { 354 | self.config = config; 355 | self.message_queue.set_config(config); 356 | } 357 | 358 | /// Sends a message of the specified `kind` along with its `payload` over 359 | /// the connection. 360 | /// 361 | /// How exactly the message is send and whether it is guaranteed to be 362 | /// delivered eventually is determined by its `MessageKind`. 363 | pub fn send(&mut self, kind: MessageKind, payload: Vec) { 364 | self.message_queue.send(kind, payload); 365 | } 366 | 367 | /// Returns a drain iterator over all queued events from this connection. 368 | pub fn events(&mut self) -> Drain { 369 | 370 | // We only fetch messages from the queue "on demand" they will otherwise 371 | // get dismissed once send_packet is called. 372 | for message in self.message_queue.received() { 373 | self.events.push(ConnectionEvent::Message(message)); 374 | } 375 | 376 | self.events.drain(0..) 377 | 378 | } 379 | 380 | /// Receives a incoming UDP packet. 381 | pub fn receive_packet(&mut self, packet: Vec) -> bool { 382 | 383 | // Ignore any packets shorter then the header length 384 | if packet.len() < PACKET_HEADER_SIZE { 385 | return false; 386 | } 387 | 388 | // Update connection state 389 | if !self.update_receive_state(&packet) { 390 | return false; 391 | } 392 | 393 | // Update time used for disconnect detection 394 | self.last_receive_time = Instant::now(); 395 | 396 | // Read remote sequence number 397 | self.remote_seq_number = packet[8] as u32; 398 | 399 | // Get latest acknowledge sequence number 400 | let ack_seq_number = packet[9] as u32; 401 | 402 | // Get acknowledgement bitfield 403 | let bitfield = (packet[10] as u32) << 24 404 | | (packet[11] as u32) << 16 405 | | (packet[12] as u32) << 8 406 | | packet[13] as u32; 407 | 408 | // Check recently send packets for their acknowledgment 409 | for i in 0..self.sent_ack_queue.len() { 410 | 411 | if let Some(lost_packet) = { 412 | 413 | let ack = &mut self.sent_ack_queue[i]; 414 | 415 | // Calculate the roundtrip time from acknowledged packets 416 | if seq_was_acked(ack.seq, ack_seq_number, bitfield) { 417 | 418 | let tick_delay = Duration::from_millis( 419 | 1000 / self.config.send_rate 420 | ); 421 | 422 | self.acked_packets = self.acked_packets.wrapping_add(1); 423 | self.smoothed_rtt = moving_average( 424 | self.smoothed_rtt, 425 | (cmp::max(self.last_receive_time - ack.time, tick_delay) - tick_delay) 426 | ); 427 | 428 | ack.state = PacketState::Acked; 429 | 430 | None 431 | 432 | // Extract data from lost packets 433 | } else if self.last_receive_time - ack.time 434 | > self.config.packet_drop_threshold { 435 | 436 | self.lost_packets = self.lost_packets.wrapping_add(1); 437 | ack.state = PacketState::Lost; 438 | ack.packet.take() 439 | 440 | // Keep all pending packets 441 | } else { 442 | None 443 | } 444 | 445 | } { 446 | 447 | // Push messages from lost packets into the queue 448 | self.message_queue.lost_packet(&lost_packet[PACKET_HEADER_SIZE..]); 449 | 450 | // Packet lost notification 451 | self.events.push(ConnectionEvent::PacketLost( 452 | lost_packet[PACKET_HEADER_SIZE..].to_vec() 453 | )); 454 | 455 | } 456 | 457 | } 458 | 459 | // Push packet data into message queue 460 | if let Some(payload) = self.packet_modifier.incoming( 461 | &packet[PACKET_HEADER_SIZE..] 462 | ) { 463 | self.message_queue.receive_packet(&payload[..]); 464 | 465 | } else { 466 | self.message_queue.receive_packet(&packet[PACKET_HEADER_SIZE..]); 467 | } 468 | 469 | // Remove all acknowledged and lost packets from the sent ack queue 470 | self.sent_ack_queue.retain(|p| p.state == PacketState::Unknown); 471 | 472 | // Insert packet into receive acknowledgment queue 473 | self.recv_ack_queue.push_front(self.remote_seq_number); 474 | 475 | // Don't keep more entries than we can actually acknowledge per packet 476 | if self.recv_ack_queue.len() > MAX_ACK_BITS as usize { 477 | self.recv_ack_queue.pop_back(); 478 | } 479 | 480 | // Update packet statistics 481 | self.recv_packets = self.recv_packets.wrapping_add(1); 482 | 483 | true 484 | 485 | } 486 | 487 | /// Send a new outgoing UDP packet. 488 | pub fn send_packet( 489 | &mut self, 490 | socket: &mut S, 491 | addr: &SocketAddr 492 | 493 | ) -> u32 { 494 | 495 | // Update connection state 496 | if !self.update_send_state() { 497 | return 0; 498 | } 499 | 500 | let congested = self.rate_limiter.congested(); 501 | let rtt = self.rtt(); 502 | let packet_loss = self.packet_loss(); 503 | 504 | // Update congestion state 505 | self.rate_limiter.update(rtt, packet_loss); 506 | 507 | // Check if the state changed and invoke handler 508 | if congested != self.rate_limiter.congested() { 509 | self.events.push(ConnectionEvent::CongestionStateChanged(!congested)); 510 | } 511 | 512 | // Check if we should be sending packets, if not skip this packet 513 | if !self.rate_limiter.should_send() { 514 | return 0; 515 | } 516 | 517 | // Take write buffer out and insert a fresh, empty one in its place 518 | let mut packet = Vec::::with_capacity(PACKET_HEADER_SIZE); 519 | 520 | // Set packet protocol header 521 | packet.push(self.config.protocol_header[0]); 522 | packet.push(self.config.protocol_header[1]); 523 | packet.push(self.config.protocol_header[2]); 524 | packet.push(self.config.protocol_header[3]); 525 | 526 | // Set connection ID 527 | packet.push((self.random_id.0 >> 24) as u8); 528 | packet.push((self.random_id.0 >> 16) as u8); 529 | packet.push((self.random_id.0 >> 8) as u8); 530 | packet.push(self.random_id.0 as u8); 531 | 532 | // Send closing packets if required 533 | if self.state == ConnectionState::Closing { 534 | packet.extend_from_slice(&CLOSURE_PACKET_DATA); 535 | 536 | } else { 537 | 538 | // Set local sequence number 539 | packet.push(self.local_seq_number as u8); 540 | 541 | // Set packet ack number 542 | packet.push(self.remote_seq_number as u8); 543 | 544 | // Construct ack bitfield from most recently received packets 545 | let mut bitfield: u32 = 0; 546 | for seq in &self.recv_ack_queue { 547 | 548 | // Ignore the remote sequence as it already gets set in the header 549 | if *seq != self.remote_seq_number { 550 | 551 | // Calculate bitfield index 552 | let bit = seq_bit_index(*seq, self.remote_seq_number); 553 | 554 | // Set ack bit 555 | if bit < MAX_ACK_BITS { 556 | bitfield |= (1 << bit) as u32; 557 | } 558 | 559 | } 560 | 561 | } 562 | 563 | // Set ack bitfield 564 | packet.push((bitfield >> 24) as u8); 565 | packet.push((bitfield >> 16) as u8); 566 | packet.push((bitfield >> 8) as u8); 567 | packet.push(bitfield as u8); 568 | 569 | // Write messages from queue into the packet 570 | self.message_queue.send_packet( 571 | &mut packet, self.config.packet_max_size - PACKET_HEADER_SIZE 572 | ); 573 | 574 | } 575 | 576 | // Construct outgoing packet 577 | let packet = if let Some(mut payload) = self.packet_modifier.outgoing( 578 | &packet[PACKET_HEADER_SIZE..] 579 | ) { 580 | 581 | // Combine existing header with modified packet payload 582 | let mut packet = packet[..PACKET_HEADER_SIZE].to_vec(); 583 | packet.append(&mut payload); 584 | packet 585 | 586 | } else { 587 | packet 588 | }; 589 | 590 | // Send packet over socket 591 | let bytes_sent = match socket.send_to(&packet[..], *addr) { 592 | Ok(_) => { 593 | self.last_send_time = Instant::now(); 594 | packet.len() 595 | }, 596 | Err(_) => 0 597 | }; 598 | 599 | // Insert packet into send acknowledgment queue (but avoid dupes) 600 | if self.send_ack_required(self.local_seq_number) { 601 | self.sent_ack_queue.push(SentPacketAck { 602 | seq: self.local_seq_number, 603 | time: Instant::now(), 604 | state: PacketState::Unknown, 605 | packet: Some(packet) 606 | }); 607 | } 608 | 609 | // Increase local sequence number and wrap around 610 | self.local_seq_number += 1; 611 | 612 | if self.local_seq_number == MAX_SEQ_NUMBER { 613 | self.local_seq_number = 0; 614 | } 615 | 616 | // Update packet statistics 617 | self.sent_packets = self.sent_packets.wrapping_add(1); 618 | 619 | // Dismiss any pending, received messages 620 | self.message_queue.dismiss(); 621 | 622 | // Return number of bytes sent over the socket 623 | bytes_sent as u32 624 | 625 | } 626 | 627 | /// Resets the connection for re-use with another address. 628 | pub fn reset(&mut self) { 629 | self.state = ConnectionState::Connecting; 630 | self.local_seq_number = 0; 631 | self.remote_seq_number = 0; 632 | self.smoothed_rtt = 0.0; 633 | self.last_receive_time = Instant::now(); 634 | self.last_send_time = Instant::now(); 635 | self.recv_ack_queue.clear(); 636 | self.sent_ack_queue.clear(); 637 | self.sent_packets = 0; 638 | self.recv_packets = 0; 639 | self.acked_packets = 0; 640 | self.lost_packets = 0; 641 | self.message_queue.reset(); 642 | self.rate_limiter.reset(); 643 | } 644 | 645 | /// Closes the connection, no further packets will be received or send. 646 | pub fn close(&mut self) { 647 | self.state = ConnectionState::Closing; 648 | } 649 | 650 | 651 | // Internal State Handling ------------------------------------------------ 652 | 653 | fn update_receive_state(&mut self, packet: &[u8]) -> bool { 654 | 655 | // Ignore any packets which do not match the desired protocol header 656 | &packet[0..4] == &self.config.protocol_header && match self.state { 657 | 658 | ConnectionState::Lost | 659 | ConnectionState::Closed | 660 | ConnectionState::FailedToConnect => false, 661 | 662 | ConnectionState::Closing => true, 663 | 664 | ConnectionState::Connecting => { 665 | 666 | // Once we receive the first valid packet we consider the 667 | // connection as established 668 | self.state = ConnectionState::Connected; 669 | 670 | // Reset Packet Loss upon connection 671 | self.lost_packets = 0; 672 | 673 | self.events.push(ConnectionEvent::Connected); 674 | 675 | true 676 | 677 | }, 678 | 679 | ConnectionState::Connected => { 680 | 681 | // Check for closure packet from remote 682 | if &packet[8..14] == &CLOSURE_PACKET_DATA { 683 | self.state = ConnectionState::Closed; 684 | self.events.push(ConnectionEvent::Closed(true)); 685 | false 686 | 687 | } else { 688 | // Check if the packet sequence number is more recent, 689 | // otherwise drop it as a duplicate 690 | seq_is_more_recent( 691 | packet[8] as u32, self.remote_seq_number 692 | ) 693 | } 694 | 695 | } 696 | 697 | } 698 | 699 | } 700 | 701 | fn update_send_state(&mut self) -> bool { 702 | 703 | // Calculate time since last received packet 704 | let inactive_receive_time = self.last_receive_time.elapsed(); 705 | 706 | // Calculate time since last sent packet 707 | let inactive_send_time = self.last_send_time.elapsed(); 708 | 709 | match self.state { 710 | 711 | ConnectionState::Lost | 712 | ConnectionState::Closed | 713 | ConnectionState::FailedToConnect => false, 714 | 715 | ConnectionState::Connecting => { 716 | 717 | // Quickly detect initial connection failures 718 | if inactive_receive_time > self.config.connection_init_threshold { 719 | self.state = ConnectionState::FailedToConnect; 720 | self.events.push(ConnectionEvent::FailedToConnect); 721 | false 722 | 723 | } else { 724 | true 725 | } 726 | 727 | }, 728 | 729 | ConnectionState::Connected => { 730 | 731 | // Detect remote connection failures (remote went away etc.) 732 | if inactive_receive_time > self.config.connection_drop_threshold { 733 | self.state = ConnectionState::Lost; 734 | self.events.push(ConnectionEvent::Lost(true)); 735 | false 736 | 737 | // Detect local connection failures (network interface no longer exists etc.) 738 | } else if inactive_send_time > self.config.connection_drop_threshold { 739 | self.state = ConnectionState::Lost; 740 | self.events.push(ConnectionEvent::Lost(false)); 741 | false 742 | 743 | } else { 744 | true 745 | } 746 | 747 | }, 748 | 749 | ConnectionState::Closing => { 750 | 751 | // Detect connection closure 752 | if inactive_receive_time > self.config.connection_closing_threshold { 753 | self.state = ConnectionState::Closed; 754 | self.events.push(ConnectionEvent::Closed(false)); 755 | false 756 | 757 | } else { 758 | true 759 | } 760 | 761 | } 762 | 763 | } 764 | 765 | } 766 | 767 | // Internal Helpers ------------------------------------------------------- 768 | fn send_ack_required(&self, seq: u32) -> bool { 769 | !self.sent_ack_queue.iter().any(|p| p.seq == seq) 770 | } 771 | 772 | } 773 | 774 | 775 | // Static Helpers ------------------------------------------------------------- 776 | fn moving_average(a: f32, b: Duration) -> f32 { 777 | let b = (b.as_secs() as f32) * 1000.0 + (b.subsec_nanos() / 1000000) as f32; 778 | (a - (a - b) * 0.10).max(0.0) 779 | } 780 | 781 | fn seq_bit_index(seq: u32, ack: u32) -> u32 { 782 | if seq > ack { 783 | ack + (MAX_SEQ_NUMBER - 1 - seq) 784 | 785 | } else { 786 | ack - 1 - seq 787 | } 788 | } 789 | 790 | fn seq_is_more_recent(a: u32, b: u32) -> bool { 791 | (a > b) && (a - b <= MAX_SEQ_NUMBER / 2) || 792 | (b > a) && (b - a > MAX_SEQ_NUMBER / 2) 793 | } 794 | 795 | fn seq_was_acked(seq: u32, ack: u32, bitfield: u32) -> bool { 796 | if seq == ack { 797 | true 798 | 799 | } else { 800 | let bit = seq_bit_index(seq, ack); 801 | bit < MAX_ACK_BITS && (bitfield & (1 << bit)) != 0 802 | } 803 | } 804 | 805 | -------------------------------------------------------------------------------- /src/shared/message_queue.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2017 Ivo Wetzel 2 | 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | // STD Dependencies ----------------------------------------------------------- 10 | use std::cmp; 11 | use std::collections::{BinaryHeap, HashSet, VecDeque}; 12 | 13 | 14 | // Internal Dependencies ------------------------------------------------------ 15 | use ::Config; 16 | 17 | /// Maximum message ordering id before wrap around happens. 18 | const MAX_ORDER_ID: u16 = 4096; 19 | 20 | /// Number of bytes used in a single message header. 21 | const MESSAGE_HEADER_BYTES: usize = 4; 22 | 23 | /// Enum for specification of a message handling algorithm. 24 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] 25 | pub enum MessageKind { 26 | /// Message that is going be send exactly once and ignored in case its 27 | /// containing packet is lost. No guarantees are made as for the order in 28 | /// which a message of this kind is going to be received by a remote queue. 29 | Instant = 0, 30 | 31 | /// Message that is going to be re-send in case its containing packet is 32 | /// lost. No guarantees are made as for the order in which a message of 33 | /// this kind is going to be received by a remote queue. 34 | Reliable = 1, 35 | 36 | /// Message that is going to be re-send in case its containing packet is 37 | /// lost and is also guaranteed to arrive in-order, meaning that if you send 38 | /// two `Ordered` messages and the second arrives first in the remote queue 39 | /// , the remote queue will buffer the second message until the first one 40 | /// arrives and then make both of them available to the application at 41 | /// once. 42 | Ordered = 2 43 | } 44 | 45 | /// Structure for handling messages inside a `MessageQueue` with support for 46 | /// insertion into a binary min heap for order checking on received messages. 47 | #[derive(Debug, Eq, PartialEq)] 48 | struct Message { 49 | kind: MessageKind, 50 | order: u16, 51 | size: u16, 52 | data: Vec 53 | } 54 | 55 | impl Ord for Message { 56 | // Explicitly implement the trait so the queue becomes a min-heap 57 | // instead of a max-heap. 58 | fn cmp(&self, other: &Self) -> cmp::Ordering { 59 | other.order.cmp(&self.order) 60 | } 61 | } 62 | 63 | impl PartialOrd for Message { 64 | fn partial_cmp(&self, other: &Self) -> Option { 65 | Some(self.cmp(other)) 66 | } 67 | } 68 | 69 | /// Consuming iterator over the received messages of a `MessageQueue`. 70 | #[derive(Debug)] 71 | pub struct MessageIterator<'a> { 72 | messages: &'a mut VecDeque 73 | } 74 | 75 | impl<'a> Iterator for MessageIterator<'a> { 76 | 77 | type Item = Vec; 78 | 79 | fn next(&mut self) -> Option { 80 | match self.messages.pop_front() { 81 | Some(m) => Some(m.data), 82 | None => None 83 | } 84 | } 85 | 86 | } 87 | 88 | /// Implementation of a queue that manages the sending and receiving of both 89 | /// reliable and unreliable message types and also supports optional in order 90 | /// transmission. 91 | #[derive(Debug)] 92 | pub struct MessageQueue { 93 | 94 | /// The queue's configuration 95 | config: Config, 96 | 97 | /// The local order id which gets attached to all messages send as kind 98 | /// `MessageKind::Ordered` 99 | local_order_id: u16, 100 | 101 | /// The remote order id that is expected for the next incoming message of 102 | /// kind `MessageKind::Ordered` 103 | remote_order_id: u16, 104 | 105 | /// Queue of outgoing messages of the kind `MessageKind::Instant` 106 | i_queue: VecDeque, 107 | 108 | /// Queue of outgoing messages of the kind `MessageKind::Reliable` 109 | r_queue: VecDeque, 110 | 111 | /// Queue of outgoing messages of the kind `MessageKind::Ordered` 112 | o_queue: VecDeque, 113 | 114 | /// Ordered queue of incoming messages 115 | recv_queue: VecDeque, 116 | 117 | /// Binary Min-Heap to manage incomging, out of order messages 118 | o_recv_heap: BinaryHeap, 119 | 120 | /// Set for avoiding duplication of out of order messages 121 | o_recv_set: HashSet 122 | 123 | } 124 | 125 | impl MessageQueue { 126 | 127 | /// Creates a new queue for sending and receiving messages. 128 | pub fn new(config: Config) -> MessageQueue { 129 | MessageQueue { 130 | config: config, 131 | local_order_id: 0, 132 | remote_order_id: 0, 133 | i_queue: VecDeque::new(), 134 | r_queue: VecDeque::new(), 135 | o_queue: VecDeque::new(), 136 | recv_queue: VecDeque::new(), 137 | o_recv_heap: BinaryHeap::new(), 138 | o_recv_set: HashSet::new() 139 | } 140 | } 141 | 142 | /// Overrides the queue's existing configuration. 143 | pub fn set_config(&mut self, config: Config) { 144 | self.config = config; 145 | } 146 | 147 | /// Returns a consuming iterator over all received messages in the queue. 148 | pub fn received(&mut self) -> MessageIterator { 149 | MessageIterator { messages: &mut self.recv_queue } 150 | } 151 | 152 | /// Clears the queue of received messages, dismissing any messages which 153 | /// have not been fetched via `MessageQueue::received()`. 154 | pub fn dismiss(&mut self) { 155 | self.recv_queue.clear(); 156 | } 157 | 158 | /// Pushes a message of the specified `kind` along with its `data` into the 159 | /// queue. The message will eventually get serialized via 160 | /// `MessageQueue::send_packet()`. 161 | pub fn send(&mut self, kind: MessageKind, data: Vec) { 162 | 163 | let message = Message { 164 | kind: kind, 165 | order: self.local_order_id, 166 | size: data.len() as u16, 167 | data: data 168 | }; 169 | 170 | match kind { 171 | MessageKind::Instant => self.i_queue.push_back(message), 172 | MessageKind::Reliable => self.r_queue.push_back(message), 173 | MessageKind::Ordered => { 174 | 175 | self.o_queue.push_back(message); 176 | self.local_order_id += 1; 177 | 178 | if self.local_order_id == MAX_ORDER_ID { 179 | self.local_order_id = 0; 180 | } 181 | 182 | } 183 | } 184 | 185 | } 186 | 187 | /// Serializes a number of internally queued messages into the 188 | /// `available` space within the `packet`. 189 | /// 190 | /// The used algorithm first tries to fill the available space with the 191 | /// desired quotas for each `MessageKind` as defined in the queues 192 | /// configuration. 193 | /// 194 | /// Afterwards the remaining available space is filled by alternating 195 | /// between the different message kinds until there is finally no more 196 | /// space left to insert any further messages into the packet. 197 | /// 198 | /// For example, if we have `512` bytes available inside the packer and we 199 | /// specify that 60% of the packet data should be filled with 200 | /// `MessageKind::Instant` messages, then we will try to fill the 201 | /// buffer with at most `307` bytes of instant messages, at first. 202 | /// 203 | /// Then, after the other quotas have been taken into account, we'll try to 204 | /// fit more instant messages into the remaining available space within the 205 | /// packet. 206 | pub fn send_packet(&mut self, packet: &mut Vec, available: usize) { 207 | 208 | // First we are trying to fill the packet by using the set quotas 209 | let mut written = 0; 210 | write_messages( 211 | &mut self.i_queue, packet, 212 | (available as f32 / 100.0 * self.config.message_quota_instant) as usize, 213 | &mut written 214 | ); 215 | 216 | write_messages( 217 | &mut self.r_queue, packet, 218 | (available as f32 / 100.0 * self.config.message_quota_reliable) as usize, 219 | &mut written 220 | ); 221 | 222 | write_messages( 223 | &mut self.o_queue, packet, 224 | (available as f32 / 100.0 * self.config.message_quota_ordered) as usize, 225 | &mut written 226 | ); 227 | 228 | // After that, we try to fill the remaining packet space by trying to 229 | // add one message of each kind until no more messages can be fit in 230 | let mut more = true; 231 | while more { 232 | more = false; 233 | more |= write_message(&mut self.i_queue, packet, available, &mut written); 234 | more |= write_message(&mut self.r_queue, packet, available, &mut written); 235 | more |= write_message(&mut self.o_queue, packet, available, &mut written); 236 | } 237 | 238 | } 239 | 240 | /// Parses the contents of a packet into messages, appending all valid 241 | /// messages into the internal receive queue. 242 | pub fn receive_packet(&mut self, packet: &[u8]) { 243 | for m in messages_from_packet(packet) { 244 | match m.kind { 245 | MessageKind::Instant | MessageKind::Reliable => { 246 | self.recv_queue.push_back(m); 247 | }, 248 | MessageKind::Ordered => self.receive_ordered_message(m) 249 | } 250 | } 251 | } 252 | 253 | /// Parses the contents of a lost packet into messages, dropping all 254 | /// messages of the type `MessageKind::Instant` and prepending all 255 | /// remaining valid messages into the internal send queues for 256 | /// re-transmission. 257 | pub fn lost_packet(&mut self, packet: &[u8]) { 258 | for m in messages_from_packet(packet) { 259 | match m.kind { 260 | MessageKind::Instant => { 261 | // ignore lost instant messages 262 | }, 263 | MessageKind::Reliable => self.r_queue.push_front(m), 264 | MessageKind::Ordered => self.o_queue.push_front(m) 265 | } 266 | } 267 | } 268 | 269 | /// Resets the queue, clearing all its internal structures and order ids. 270 | pub fn reset(&mut self) { 271 | self.local_order_id = 0; 272 | self.remote_order_id = 0; 273 | self.i_queue.clear(); 274 | self.r_queue.clear(); 275 | self.o_queue.clear(); 276 | self.recv_queue.clear(); 277 | self.o_recv_heap.clear(); 278 | self.o_recv_set.clear(); 279 | } 280 | 281 | // Internal Message Handling ---------------------------------------------- 282 | 283 | fn receive_ordered_message(&mut self, m: Message) { 284 | 285 | // Check if the order ID matches the currently expected on 286 | if m.order == self.remote_order_id { 287 | 288 | // Received the message in order 289 | self.recv_queue.push_back(m); 290 | 291 | self.remote_order_id += 1; 292 | if self.remote_order_id == MAX_ORDER_ID { 293 | self.remote_order_id = 0; 294 | } 295 | 296 | // Now check our heap for further messages we have received 297 | // out of order and check if they are next in the expected 298 | // order 299 | let mut matches = true; 300 | while matches { 301 | 302 | // Check if the order id of the minimal item in the heap 303 | // matches the expected next remote order id 304 | matches = if let Some(msg) = self.o_recv_heap.peek() { 305 | msg.order == self.remote_order_id 306 | 307 | } else { 308 | false 309 | }; 310 | 311 | // We found another message, matching the next expected order id 312 | if matches { 313 | 314 | // Unset duplication marker 315 | self.o_recv_set.remove(&self.remote_order_id); 316 | 317 | // Remove it from the heap and push it into the recv queue 318 | let msg = self.o_recv_heap.pop().unwrap(); 319 | self.recv_queue.push_back(msg); 320 | 321 | self.remote_order_id += 1; 322 | if self.remote_order_id == MAX_ORDER_ID { 323 | self.remote_order_id = 0; 324 | } 325 | 326 | } 327 | 328 | } 329 | 330 | // Otherwise check if the message order is more recent and if not, we 331 | // simply drop it. If it IS more recent, then we have received a future 332 | // message out of order. 333 | // 334 | // Also, before we insert the message into the min-heap, we check 335 | // that there's no other message with the same order id in the heap 336 | // already. Duplicates would require additional peek / pop later on 337 | // when removing messages from the heap, so we resort to a Set here. 338 | } else if order_is_more_recent(m.order, self.remote_order_id) && !self.o_recv_set.contains(&m.order) { 339 | self.o_recv_set.insert(m.order); 340 | self.o_recv_heap.push(m); 341 | } 342 | 343 | } 344 | 345 | } 346 | 347 | // Static Helpers ------------------------------------------------------------- 348 | fn order_is_more_recent(a: u16, b: u16) -> bool { 349 | (a > b) && (a - b <= MAX_ORDER_ID / 2) 350 | || (b > a) && (b - a > MAX_ORDER_ID / 2) 351 | } 352 | 353 | fn messages_from_packet(packet: &[u8]) -> Vec { 354 | 355 | let available = packet.len(); 356 | let mut index = 0; 357 | let mut messages = Vec::new(); 358 | 359 | // Consume as long as message headers can be present 360 | while index < available && available - index >= MESSAGE_HEADER_BYTES { 361 | 362 | // Upper 4 bits of kind are bits 9..11 of order 363 | let order_high = ((packet[index] & 0xF0) as u16) << 4; 364 | let order_low = packet[index + 1] as u16; 365 | 366 | // Byte 2 is the size 367 | let size_high = (packet[index + 2] as u16) << 8; 368 | let size = size_high | packet[index + 3] as u16; 369 | 370 | // Lower 4 bits of byte 0 are the MessageKind 371 | let kind = match packet[index] & 0x0F { 372 | 0 => Some(MessageKind::Instant), 373 | 1 => Some(MessageKind::Reliable), 374 | 2 => Some(MessageKind::Ordered), 375 | _ => None 376 | }; 377 | 378 | // Ignore any unknown message kind 379 | if let Some(kind) = kind { 380 | messages.push(Message { 381 | kind: kind, 382 | order: order_high | order_low, 383 | size: size, 384 | data: packet[ 385 | index + MESSAGE_HEADER_BYTES..cmp::min( 386 | index + MESSAGE_HEADER_BYTES + size as usize, 387 | available 388 | ) 389 | ].to_vec() 390 | 391 | }); 392 | } 393 | 394 | index += size as usize + MESSAGE_HEADER_BYTES; 395 | 396 | } 397 | 398 | messages 399 | 400 | } 401 | 402 | fn write_messages( 403 | queue: &mut VecDeque, 404 | packet: &mut Vec, 405 | available: usize, 406 | written: &mut usize 407 | ) { 408 | let mut used = 0; 409 | while write_message(queue, packet, available, &mut used) {} 410 | *written += used; 411 | } 412 | 413 | fn write_message( 414 | queue: &mut VecDeque, 415 | packet: &mut Vec, 416 | available: usize, 417 | written: &mut usize 418 | 419 | ) -> bool { 420 | 421 | if queue.is_empty() { 422 | false 423 | 424 | } else { 425 | 426 | let required = { 427 | (queue.front().unwrap().size as usize) + MESSAGE_HEADER_BYTES 428 | }; 429 | 430 | // If adding this message would exceed the available bytes, exit 431 | if required > available - *written { 432 | false 433 | 434 | // Remove and serialize the message into the packet 435 | } else { 436 | let message = queue.pop_front().unwrap(); 437 | packet.push( 438 | ((message.order & 0x0F00) >> 4) as u8 | (message.kind as u8) 439 | ); 440 | packet.push(message.order as u8); 441 | packet.push((message.size >> 8) as u8); 442 | packet.push(message.size as u8); 443 | packet.extend_from_slice(&message.data[..]); 444 | *written += required; 445 | true 446 | } 447 | 448 | } 449 | 450 | } 451 | 452 | -------------------------------------------------------------------------------- /src/shared/mod.rs: -------------------------------------------------------------------------------- 1 | // Modules -------------------------------------------------------------------- 2 | mod binary_rate_limiter; 3 | mod config; 4 | mod connection; 5 | pub mod message_queue; 6 | mod noop_packet_modifier; 7 | mod udp_socket; 8 | pub mod stats; 9 | pub mod ticker; 10 | 11 | 12 | // Re-Exports ----------------------------------------------------------------- 13 | pub use self::binary_rate_limiter::BinaryRateLimiter; 14 | pub use self::config::Config; 15 | pub use self::connection::{ 16 | Connection, 17 | ConnectionID, 18 | ConnectionMap, 19 | ConnectionState, 20 | ConnectionEvent 21 | }; 22 | pub use self::message_queue::MessageKind; 23 | pub use self::noop_packet_modifier::NoopPacketModifier; 24 | pub use self::udp_socket::UdpSocket; 25 | 26 | -------------------------------------------------------------------------------- /src/shared/noop_packet_modifier.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2017 Ivo Wetzel 2 | 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | 10 | // Internal Dependencies ------------------------------------------------------ 11 | use ::{Config, PacketModifier}; 12 | 13 | 14 | /// Implementation of a packet modifier which does nothing. 15 | #[derive(Debug, Copy, Clone)] 16 | pub struct NoopPacketModifier; 17 | 18 | impl PacketModifier for NoopPacketModifier { 19 | 20 | fn new(_: Config) -> NoopPacketModifier { 21 | NoopPacketModifier 22 | } 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /src/shared/stats.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2017 Ivo Wetzel 2 | 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | 10 | // Internal Dependencies ------------------------------------------------------ 11 | use ::Config; 12 | 13 | /// A structure containing stats data average of the course of one second. 14 | #[derive(Debug, PartialEq, Copy, Clone)] 15 | pub struct Stats { 16 | 17 | /// Average number of bytes received over the last second. 18 | pub bytes_sent: u32, 19 | 20 | /// Average number of bytes received over the last second. 21 | pub bytes_received: u32 22 | 23 | } 24 | 25 | impl Stats { 26 | pub fn reset(&mut self) { 27 | self.bytes_sent = 0; 28 | self.bytes_received = 0; 29 | } 30 | } 31 | 32 | impl Default for Stats { 33 | fn default() -> Stats { 34 | Stats { 35 | bytes_sent: 0, 36 | bytes_received: 0 37 | } 38 | } 39 | } 40 | 41 | /// Structure to keep track of per second average stats of a Client or Server. 42 | /// 43 | /// Uses a list of buckets and caluclates the average each time a new value is 44 | /// pushed into the bucket list `O(1)`. 45 | #[derive(Debug)] 46 | pub struct StatsCollector { 47 | 48 | /// Internal tick value 49 | tick: u64, 50 | 51 | /// The collectors's configuration 52 | config: Config, 53 | 54 | /// Internal stat buckets for O(1) average calculation 55 | buckets: Vec, 56 | 57 | /// Internal stat average for the current tick 58 | averages: Stats 59 | 60 | } 61 | 62 | impl StatsCollector { 63 | 64 | /// Creates a new stats object which averages incoming data over the given 65 | /// number of ticks per second. 66 | pub fn new(config: Config) -> StatsCollector { 67 | StatsCollector { 68 | tick: 0, 69 | config: config, 70 | buckets: (0..config.send_rate + 1).map(|_| { 71 | Stats::default() 72 | 73 | }).collect::>(), 74 | averages: Stats::default() 75 | } 76 | } 77 | 78 | /// Overrides the collector's existing configuration. 79 | pub fn set_config(&mut self, config: Config) { 80 | self.config = config; 81 | self.buckets = (0..config.send_rate + 1).map(|_| { 82 | Stats::default() 83 | 84 | }).collect::>() 85 | } 86 | 87 | /// Sets the number of bytes sent for the current tick. 88 | pub fn set_bytes_sent(&mut self, bytes: u32) { 89 | let old_index = (self.tick as i32 + 1) % (self.config.send_rate + 1) as i32; 90 | let old_bytes = self.buckets[old_index as usize].bytes_sent; 91 | self.averages.bytes_sent = (self.averages.bytes_sent - old_bytes) + bytes; 92 | self.buckets[self.tick as usize].bytes_sent = bytes; 93 | } 94 | 95 | /// Sets the number of bytes received for the current tick. 96 | pub fn set_bytes_received(&mut self, bytes: u32) { 97 | let old_index = (self.tick as i32 + 1) % (self.config.send_rate + 1) as i32; 98 | let old_bytes = self.buckets[old_index as usize].bytes_received; 99 | self.averages.bytes_received = (self.averages.bytes_received - old_bytes) + bytes; 100 | self.buckets[self.tick as usize].bytes_received = bytes; 101 | } 102 | 103 | /// Steps the internal tick value used for average calculation. 104 | pub fn tick(&mut self) { 105 | self.tick = (self.tick + 1) % (self.config.send_rate + 1); 106 | } 107 | 108 | /// Returns the calculated averages from the last tick. 109 | pub fn average(&self) -> Stats { 110 | self.averages 111 | } 112 | 113 | /// Resets the internal data used for average calculation, but does not 114 | /// reset the last calculated averages. 115 | pub fn reset(&mut self) { 116 | self.averages.bytes_sent = 0; 117 | self.averages.bytes_received = 0; 118 | for d in &mut self.buckets { 119 | d.reset(); 120 | } 121 | } 122 | 123 | } 124 | 125 | -------------------------------------------------------------------------------- /src/shared/ticker.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2017 Ivo Wetzel 2 | 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | // STD Dependencies ----------------------------------------------------------- 10 | use std::cmp; 11 | use std::thread; 12 | use std::time::{Duration, Instant}; 13 | 14 | 15 | // Internal Dependencies ------------------------------------------------------ 16 | use ::shared::config::Config; 17 | 18 | 19 | // Tick Rate Limiting --------------------------------------------------------- 20 | #[derive(Debug)] 21 | pub struct Ticker { 22 | tick_start: Instant, 23 | tick_overflow: u64, 24 | tick_overflow_recovery: bool, 25 | tick_overflow_recovery_rate: f32, 26 | tick_delay: u64 27 | } 28 | 29 | impl Ticker { 30 | 31 | pub fn new(config: Config) -> Ticker { 32 | Ticker { 33 | tick_start: Instant::now(), 34 | tick_overflow: 0, 35 | tick_overflow_recovery: config.tick_overflow_recovery, 36 | tick_overflow_recovery_rate: config.tick_overflow_recovery_rate, 37 | tick_delay: 1000000000 / config.send_rate 38 | } 39 | } 40 | 41 | pub fn set_config(&mut self, config: Config) { 42 | self.tick_overflow_recovery = config.tick_overflow_recovery; 43 | self.tick_overflow_recovery_rate = config.tick_overflow_recovery_rate; 44 | self.tick_delay = 1000000000 / config.send_rate 45 | } 46 | 47 | pub fn begin_tick(&mut self) { 48 | self.tick_start = Instant::now(); 49 | } 50 | 51 | pub fn reset(&mut self) { 52 | self.tick_start = Instant::now(); 53 | self.tick_overflow = 0; 54 | } 55 | 56 | pub fn end_tick(&mut self) { 57 | 58 | // Actual time taken by the tick 59 | let time_taken = nanos_from_duration(self.tick_start.elapsed()); 60 | 61 | // Required delay reduction to keep tick rate 62 | let mut reduction = cmp::min(time_taken, self.tick_delay); 63 | 64 | if self.tick_overflow_recovery { 65 | 66 | // Keep track of how much additional time the current tick required 67 | self.tick_overflow += time_taken - reduction; 68 | 69 | // Try to reduce the existing overflow by reducing the reduction time 70 | // for the current frame. 71 | let max_correction = (self.tick_delay - reduction) as i64; 72 | let correction = cmp::min( 73 | (max_correction as f32 * self.tick_overflow_recovery_rate) as i64, 74 | max_correction 75 | ); 76 | 77 | // This way we'll achieve a speed up effect in an effort to keep the 78 | // desired tick rate stable over a longer period of time 79 | let reduced_overflow = cmp::max(0, self.tick_overflow as i64 - correction) as u64; 80 | 81 | // Adjust the reduction amount to speed up 82 | reduction += self.tick_overflow - reduced_overflow; 83 | 84 | // Update remaining overflow 85 | self.tick_overflow = reduced_overflow; 86 | 87 | } 88 | 89 | thread::sleep(Duration::new(0, (self.tick_delay - reduction) as u32)); 90 | 91 | } 92 | 93 | } 94 | 95 | // Helpers --------------------------------------------------------------------- 96 | fn nanos_from_duration(d: Duration) -> u64 { 97 | d.as_secs() * 1000 * 1000000 + d.subsec_nanos() as u64 98 | } 99 | 100 | -------------------------------------------------------------------------------- /src/shared/udp_socket.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2017 Ivo Wetzel 2 | 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | 10 | // STD Dependencies ----------------------------------------------------------- 11 | use std::net; 12 | use std::fmt; 13 | use std::iter; 14 | use std::io::Error; 15 | use std::sync::mpsc::TryRecvError; 16 | 17 | 18 | // Internal Dependencies ------------------------------------------------------ 19 | use ::Socket; 20 | 21 | /// Non-blocking abstraction over a UDP socket. 22 | pub struct UdpSocket { 23 | socket: net::UdpSocket, 24 | buffer: Vec 25 | } 26 | 27 | impl Socket for UdpSocket { 28 | 29 | /// Tries to create a new UDP socket by binding to the specified address. 30 | fn new( 31 | address: T, max_packet_size: usize 32 | 33 | ) -> Result { 34 | 35 | // Create the send socket 36 | let socket = try!(net::UdpSocket::bind(address)); 37 | 38 | // Switch into non-blocking mode 39 | try!(socket.set_nonblocking(true)); 40 | 41 | // Allocate receival buffer 42 | let buffer: Vec = iter::repeat(0).take(max_packet_size).collect(); 43 | 44 | Ok(UdpSocket { 45 | socket: socket, 46 | buffer: buffer 47 | }) 48 | 49 | } 50 | 51 | /// Attempts to return a incoming packet on this socket without blocking. 52 | fn try_recv(&mut self) -> Result<(net::SocketAddr, Vec), TryRecvError> { 53 | 54 | if let Ok((len, src)) = self.socket.recv_from(&mut self.buffer) { 55 | Ok((src, self.buffer[..len].to_vec())) 56 | 57 | } else { 58 | Err(TryRecvError::Empty) 59 | } 60 | } 61 | 62 | /// Send data on the socket to the given address. On success, returns the 63 | /// number of bytes written. 64 | fn send_to( 65 | &mut self, data: &[u8], addr: net::SocketAddr) 66 | 67 | -> Result { 68 | self.socket.send_to(data, addr) 69 | } 70 | 71 | /// Returns the socket address of the underlying `net::UdpSocket`. 72 | fn local_addr(&self) -> Result { 73 | self.socket.local_addr() 74 | } 75 | 76 | } 77 | 78 | impl fmt::Debug for UdpSocket { 79 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 80 | write!(f, "UdpSocket({:?})", self.socket) 81 | } 82 | } 83 | 84 | -------------------------------------------------------------------------------- /src/test/client.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2017 Ivo Wetzel 2 | 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | // STD Dependencies ----------------------------------------------------------- 10 | use std::thread; 11 | use std::time::{Duration, Instant}; 12 | use std::io::ErrorKind; 13 | use std::sync::mpsc::TryRecvError; 14 | 15 | 16 | // Internal Dependencies ------------------------------------------------------ 17 | use super::MockSocket; 18 | use ::{ 19 | BinaryRateLimiter, Client, ClientEvent, Config, MessageKind, 20 | NoopPacketModifier 21 | }; 22 | 23 | 24 | // Macros --------------------------------------------------------------------- 25 | macro_rules! assert_millis_since { 26 | ($start:expr, $target:expr, $difference:expr) => { 27 | { 28 | let duration = $start.elapsed(); 29 | let millis = (duration.subsec_nanos() / 1000000) as u64; 30 | 31 | let actual = (duration.as_secs() * 1000 + millis) as i64; 32 | let min = $target - $difference; 33 | let max = $target + $difference; 34 | if actual < min || actual > max { 35 | panic!(format!("Value {} not in range {} - {}", actual, min, max)); 36 | } 37 | } 38 | } 39 | } 40 | 41 | 42 | // Tests ---------------------------------------------------------------------- 43 | #[test] 44 | fn test_client_configuration() { 45 | 46 | let config = Config { 47 | send_rate: 30, 48 | .. Config::default() 49 | }; 50 | 51 | let mut client = Client::::new(config); 52 | assert_eq!(client.config(), config); 53 | 54 | let config = Config { 55 | send_rate: 60, 56 | .. Config::default() 57 | }; 58 | 59 | client.set_config(config); 60 | assert_eq!(client.config(), config); 61 | 62 | } 63 | 64 | #[test] 65 | fn test_client_internals() { 66 | 67 | let mut client = Client::::new(Config { 68 | send_rate: 30, 69 | .. Config::default() 70 | }); 71 | 72 | assert_eq!(client.socket().unwrap_err().kind(), ErrorKind::NotConnected); 73 | 74 | } 75 | 76 | #[test] 77 | fn test_client_disconnected() { 78 | 79 | let mut client = Client::::new(Config { 80 | send_rate: 30, 81 | .. Config::default() 82 | }); 83 | 84 | assert_eq!(client.bytes_sent(), 0); 85 | assert_eq!(client.bytes_received(), 0); 86 | 87 | assert_eq!(client.peer_addr().unwrap_err().kind(), ErrorKind::AddrNotAvailable); 88 | assert_eq!(client.local_addr().unwrap_err().kind(), ErrorKind::AddrNotAvailable); 89 | assert_eq!(client.connection().unwrap_err().kind(), ErrorKind::NotConnected); 90 | 91 | assert_eq!(client.receive(), Err(TryRecvError::Disconnected)); 92 | assert_eq!(client.send(false).unwrap_err().kind(), ErrorKind::NotConnected); 93 | assert_eq!(client.reset().unwrap_err().kind(), ErrorKind::NotConnected); 94 | assert_eq!(client.disconnect().unwrap_err().kind(), ErrorKind::NotConnected); 95 | 96 | } 97 | 98 | #[test] 99 | fn test_client_connect_reset_close() { 100 | 101 | let mut client = Client::::new(Config::default()); 102 | 103 | assert!(client.connect("255.1.1.1:5678").is_ok()); 104 | 105 | assert_eq!(client.connect("255.1.1.1:5678").unwrap_err().kind(), ErrorKind::AlreadyExists); 106 | assert!(client.socket().is_ok()); 107 | 108 | assert!(client.reset().is_ok()); 109 | assert!(client.socket().is_ok()); 110 | 111 | assert!(client.disconnect().is_ok()); 112 | assert_eq!(client.socket().unwrap_err().kind(), ErrorKind::NotConnected); 113 | 114 | assert_eq!(client.disconnect().unwrap_err().kind(), ErrorKind::NotConnected); 115 | assert_eq!(client.reset().unwrap_err().kind(), ErrorKind::NotConnected); 116 | 117 | } 118 | 119 | #[test] 120 | fn test_client_without_connection() { 121 | 122 | let mut client = Client::::new(Config::default()); 123 | 124 | assert!(client.connect("255.1.1.1:5678").is_ok()); 125 | 126 | assert_eq!(client.receive(), Err(TryRecvError::Empty)); 127 | 128 | assert!(client.send(false).is_ok()); 129 | 130 | assert!(client.disconnect().is_ok()); 131 | 132 | } 133 | 134 | #[test] 135 | fn test_client_flush_without_delay() { 136 | 137 | let mut client = Client::::new(Config::default()); 138 | client.connect("255.1.1.1:5678").ok(); 139 | 140 | let start = Instant::now(); 141 | for _ in 0..5 { 142 | client.receive().ok(); 143 | client.send(false).ok(); 144 | } 145 | assert_millis_since!(start, 0, 16); 146 | 147 | } 148 | 149 | #[test] 150 | fn test_client_connection_failure() { 151 | 152 | let mut client = client_init(Config { 153 | connection_init_threshold: Duration::from_millis(100), 154 | .. Config::default() 155 | }); 156 | 157 | // Let the connection attempt time out 158 | thread::sleep(Duration::from_millis(200)); 159 | 160 | let events = client_events(&mut client); 161 | assert_eq!(events, vec![ClientEvent::ConnectionFailed]); 162 | 163 | client.send(false).ok(); 164 | client.send(false).ok(); 165 | 166 | // We expect no additional packets to be send once the connection failed 167 | client.socket().unwrap().assert_sent_none(); 168 | 169 | } 170 | 171 | #[test] 172 | fn test_client_connection_success() { 173 | 174 | let mut client = client_init(Config { 175 | .. Config::default() 176 | }); 177 | 178 | // Mock the receival of the first server packet which acknowledges the client 179 | let id = client.connection().unwrap().id().0; 180 | client.socket().unwrap().mock_receive(vec![ 181 | ("255.1.1.1:5678", vec![ 182 | 1, 2, 3, 4, 183 | (id >> 24) as u8, 184 | (id >> 16) as u8, 185 | (id >> 8) as u8, 186 | id as u8, 187 | 0, 188 | 0, 189 | 0, 0, 0, 0 190 | ]) 191 | ]); 192 | 193 | assert_eq!(client_events(&mut client), vec![ClientEvent::Connection]); 194 | assert_eq!(client.bytes_sent(), 28); 195 | assert_eq!(client.bytes_received(), 0); 196 | 197 | // Send again to update states 198 | client.send(true).ok(); 199 | 200 | assert_eq!(client.bytes_sent(), 42); 201 | assert_eq!(client.bytes_received(), 14); 202 | 203 | } 204 | 205 | #[test] 206 | fn test_client_reset_events() { 207 | 208 | let mut client = client_init(Config { 209 | .. Config::default() 210 | }); 211 | 212 | let id = client.connection().unwrap().id().0; 213 | client.socket().unwrap().mock_receive(vec![ 214 | ("255.1.1.1:5678", vec![ 215 | 1, 2, 3, 4, 216 | (id >> 24) as u8, 217 | (id >> 16) as u8, 218 | (id >> 8) as u8, 219 | id as u8, 220 | 0, 221 | 0, 222 | 0, 0, 0, 0 223 | ]) 224 | ]); 225 | 226 | // Fetch events from the connection 227 | client.receive().ok(); 228 | client.send(false).ok(); 229 | 230 | // Reset events 231 | client.reset().ok(); 232 | assert_eq!(client_events(&mut client), vec![]); 233 | 234 | client.socket().unwrap().mock_receive(vec![ 235 | ("255.1.1.1:5678", vec![ 236 | 1, 2, 3, 4, 237 | (id >> 24) as u8, 238 | (id >> 16) as u8, 239 | (id >> 8) as u8, 240 | id as u8, 241 | 0, 242 | 0, 243 | 0, 0, 0, 0 244 | ]) 245 | ]); 246 | 247 | // Fetch events from the connection 248 | client.receive().ok(); 249 | client.send(false).ok(); 250 | 251 | // Disconnect and clear events 252 | client.disconnect().ok(); 253 | 254 | // Re-connect to make events accesible again 255 | client.connect("255.1.1.1:5678").ok(); 256 | 257 | assert_eq!(client_events(&mut client), vec![]); 258 | 259 | } 260 | 261 | #[test] 262 | fn test_client_connection_ignore_non_peer() { 263 | 264 | let mut client = client_init(Config { 265 | connection_init_threshold: Duration::from_millis(100), 266 | .. Config::default() 267 | }); 268 | 269 | // We expect the client to ignore any packets from peers other than the 270 | // server it is connected to 271 | let id = client.connection().unwrap().id().0; 272 | client.socket().unwrap().mock_receive(vec![ 273 | ("255.1.1.1:5679", vec![ 274 | 1, 2, 3, 4, 275 | (id >> 24) as u8, 276 | (id >> 16) as u8, 277 | (id >> 8) as u8, 278 | id as u8, 279 | 0, 280 | 0, 281 | 0, 0, 0, 0 282 | ]) 283 | ]); 284 | 285 | assert_eq!(client_events(&mut client), vec![]); 286 | 287 | } 288 | 289 | #[test] 290 | fn test_client_connection_loss_and_reconnect() { 291 | 292 | let mut client = client_init(Config { 293 | connection_drop_threshold: Duration::from_millis(100), 294 | .. Config::default() 295 | }); 296 | 297 | // Mock the receival of the first server packet which acknowledges the client 298 | let id = client.connection().unwrap().id().0; 299 | client.socket().unwrap().mock_receive(vec![ 300 | ("255.1.1.1:5678", vec![ 301 | 1, 2, 3, 4, 302 | (id >> 24) as u8, 303 | (id >> 16) as u8, 304 | (id >> 8) as u8, 305 | id as u8, 306 | 0, 307 | 0, 308 | 0, 0, 0, 0 309 | ]) 310 | ]); 311 | 312 | assert_eq!(client_events(&mut client), vec![ClientEvent::Connection]); 313 | assert_eq!(client.bytes_sent(), 28); 314 | assert_eq!(client.bytes_received(), 0); 315 | 316 | // Let the connection time out 317 | thread::sleep(Duration::from_millis(200)); 318 | 319 | // Expect one last packet 320 | assert_eq!(client.socket().unwrap().sent_count(), 1); 321 | 322 | assert_eq!(client_events(&mut client), vec![ClientEvent::ConnectionLost(true)]); 323 | 324 | client.send(false).ok(); 325 | client.send(false).ok(); 326 | 327 | // We expect no additional packets to be send once the connection failed 328 | client.socket().unwrap().assert_sent_none(); 329 | 330 | // Reset the client connection 331 | client.reset().ok(); 332 | 333 | // Stats should have been reset 334 | assert_eq!(client.bytes_sent(), 0); 335 | assert_eq!(client.bytes_received(), 0); 336 | 337 | // Mock the receival of the first server packet which acknowledges the client 338 | let id = client.connection().unwrap().id().0; 339 | client.socket().unwrap().mock_receive(vec![ 340 | ("255.1.1.1:5678", vec![ 341 | 1, 2, 3, 4, 342 | (id >> 24) as u8, 343 | (id >> 16) as u8, 344 | (id >> 8) as u8, 345 | id as u8, 346 | 0, 347 | 0, 348 | 0, 0, 0, 0 349 | ]) 350 | ]); 351 | 352 | assert_eq!(client_events(&mut client), vec![ClientEvent::Connection]); 353 | 354 | // Expect one last packet 355 | assert_eq!(client.socket().unwrap().sent_count(), 1); 356 | assert_eq!(client.bytes_sent(), 14); 357 | assert_eq!(client.bytes_received(), 0); 358 | 359 | } 360 | 361 | #[test] 362 | fn test_client_send() { 363 | 364 | let mut client = client_init(Config { 365 | connection_drop_threshold: Duration::from_millis(100), 366 | .. Config::default() 367 | }); 368 | 369 | assert_eq!(client.bytes_sent(), 14); 370 | 371 | // Mock the receival of the first server packet which acknowledges the client 372 | let id = client.connection().unwrap().id().0; 373 | client.socket().unwrap().mock_receive(vec![ 374 | ("255.1.1.1:5678", vec![ 375 | 1, 2, 3, 4, 376 | (id >> 24) as u8, 377 | (id >> 16) as u8, 378 | (id >> 8) as u8, 379 | id as u8, 380 | 0, 381 | 0, 382 | 0, 0, 0, 0 383 | ]) 384 | ]); 385 | 386 | assert_eq!(client_events(&mut client), vec![ClientEvent::Connection]); 387 | 388 | // States should not be updated before the next send() call 389 | assert_eq!(client.bytes_sent(), 28); 390 | assert_eq!(client.bytes_received(), 0); 391 | client.send(false).ok(); 392 | 393 | assert_eq!(client.bytes_sent(), 42); 394 | assert_eq!(client.bytes_received(), 14); 395 | 396 | // Verify initial connection packets 397 | client.socket().unwrap().assert_sent(vec![ 398 | ("255.1.1.1:5678", [ 399 | 1, 2, 3, 4, 400 | 9, 8, 7, 6, 401 | 1, 402 | 0, 403 | 0, 0, 0, 0 404 | 405 | ].to_vec()), 406 | ("255.1.1.1:5678", [ 407 | 1, 2, 3, 4, 408 | 9, 8, 7, 6, 409 | 2, 410 | 0, 411 | 0, 0, 0, 0 412 | 413 | ].to_vec()) 414 | ]); 415 | 416 | // Send messages to server 417 | client.connection().unwrap().send(MessageKind::Instant, b"Foo".to_vec()); 418 | client.connection().unwrap().send(MessageKind::Reliable, b"Bar".to_vec()); 419 | 420 | // Packets should not be send before the next send() call 421 | client.socket().unwrap().assert_sent_none(); 422 | 423 | client.send(false).ok(); 424 | client.socket().unwrap().assert_sent(vec![ 425 | ("255.1.1.1:5678", [ 426 | 1, 2, 3, 4, 427 | 9, 8, 7, 6, 428 | 3, 429 | 0, 430 | 0, 0, 0, 0, 431 | 0, 0, 0, 3, 70, 111, 111, 432 | 1, 0, 0, 3, 66, 97, 114 433 | 434 | ].to_vec()) 435 | ]); 436 | 437 | assert_eq!(client.bytes_sent(), 70); 438 | 439 | } 440 | 441 | #[test] 442 | fn test_client_receive() { 443 | 444 | let mut client = client_init(Config { 445 | connection_drop_threshold: Duration::from_millis(100), 446 | .. Config::default() 447 | }); 448 | 449 | let id = client.connection().unwrap().id().0; 450 | client.socket().unwrap().mock_receive(vec![ 451 | ("255.1.1.1:5678", vec![ 452 | 1, 2, 3, 4, 453 | (id >> 24) as u8, 454 | (id >> 16) as u8, 455 | (id >> 8) as u8, 456 | id as u8, 457 | 0, 458 | 0, 459 | 0, 0, 0, 0, 460 | 1, 0, 0, 3, 70, 111, 111, 461 | 0, 0, 0, 3, 66, 97, 114 462 | ]) 463 | ]); 464 | 465 | assert_eq!(client_events(&mut client), vec![ 466 | ClientEvent::Connection, 467 | ClientEvent::Message(b"Foo".to_vec()), 468 | ClientEvent::Message(b"Bar".to_vec()) 469 | ]); 470 | 471 | // Stats should not be updated before next send() call 472 | assert_eq!(client.bytes_received(), 0); 473 | 474 | client.send(false).ok(); 475 | assert_eq!(client.bytes_received(), 28); 476 | 477 | // Ignore duplicates 478 | client.socket().unwrap().mock_receive(vec![ 479 | ("255.1.1.1:5678", vec![ 480 | 1, 2, 3, 4, 481 | (id >> 24) as u8, 482 | (id >> 16) as u8, 483 | (id >> 8) as u8, 484 | id as u8, 485 | 0, 486 | 0, 487 | 0, 0, 0, 0, 488 | 1, 0, 0, 3, 70, 111, 111, 489 | 0, 0, 0, 3, 66, 97, 114 490 | ]) 491 | ]); 492 | 493 | client.socket().unwrap().mock_receive(vec![ 494 | ("255.1.1.1:5678", vec![ 495 | 1, 2, 3, 4, 496 | (id >> 24) as u8, 497 | (id >> 16) as u8, 498 | (id >> 8) as u8, 499 | id as u8, 500 | 1, 501 | 0, 502 | 0, 0, 0, 0, 503 | 0, 0, 0, 3, 66, 97, 122 504 | ]) 505 | ]); 506 | 507 | assert_eq!(client_events(&mut client), vec![ 508 | ClientEvent::Message(b"Baz".to_vec()) 509 | ]); 510 | 511 | } 512 | 513 | #[test] 514 | fn test_client_close_by_remote() { 515 | 516 | let mut client = client_init(Config::default()); 517 | let id = client.connection().unwrap().id().0; 518 | client.socket().unwrap().mock_receive(vec![ 519 | ("255.1.1.1:5678", vec![ 520 | 1, 2, 3, 4, 521 | (id >> 24) as u8, 522 | (id >> 16) as u8, 523 | (id >> 8) as u8, 524 | id as u8, 525 | 0, 526 | 0, 527 | 0, 0, 0, 0 528 | ]) 529 | ]); 530 | 531 | assert_eq!(client_events(&mut client), vec![ 532 | ClientEvent::Connection 533 | ]); 534 | 535 | // Receive closure packet 536 | client.socket().unwrap().mock_receive(vec![ 537 | ("255.1.1.1:5678", vec![ 538 | 1, 2, 3, 4, 539 | (id >> 24) as u8, 540 | (id >> 16) as u8, 541 | (id >> 8) as u8, 542 | id as u8, 543 | 0, 128, // Most distant sequence numbers 544 | 85, 85, 85, 85 // ack bitfield with every second bit set 545 | ]) 546 | ]); 547 | 548 | // Expect closure by remote 549 | assert_eq!(client_events(&mut client), vec![ 550 | ClientEvent::ConnectionClosed(true) 551 | ]); 552 | 553 | } 554 | 555 | #[test] 556 | fn test_client_close_by_local() { 557 | 558 | let mut client = client_init(Config::default()); 559 | let id = client.connection().unwrap().id().0; 560 | client.socket().unwrap().mock_receive(vec![ 561 | ("255.1.1.1:5678", vec![ 562 | 1, 2, 3, 4, 563 | (id >> 24) as u8, 564 | (id >> 16) as u8, 565 | (id >> 8) as u8, 566 | id as u8, 567 | 0, 568 | 0, 569 | 0, 0, 0, 0 570 | ]) 571 | ]); 572 | 573 | assert_eq!(client_events(&mut client), vec![ 574 | ClientEvent::Connection 575 | ]); 576 | 577 | client.socket().unwrap().assert_sent(vec![ 578 | ("255.1.1.1:5678", [ 579 | 1, 2, 3, 4, 580 | (id >> 24) as u8, 581 | (id >> 16) as u8, 582 | (id >> 8) as u8, 583 | id as u8, 584 | 1, 585 | 0, 586 | 0, 0, 0, 0 587 | 588 | ].to_vec()) 589 | ]); 590 | 591 | // Close connection 592 | client.connection().unwrap().close(); 593 | 594 | // Expect closure packet to be sent 595 | client.send(false).ok(); 596 | client.socket().unwrap().assert_sent(vec![ 597 | ("255.1.1.1:5678", [ 598 | 1, 2, 3, 4, 599 | (id >> 24) as u8, 600 | (id >> 16) as u8, 601 | (id >> 8) as u8, 602 | id as u8, 603 | 0, 604 | 128, 605 | 85, 85, 85, 85 606 | 607 | ].to_vec()) 608 | ]); 609 | 610 | // Expect connection to be dropped after closing threshold 611 | thread::sleep(Duration::from_millis(165)); 612 | assert_eq!(client_events(&mut client), vec![ 613 | ClientEvent::ConnectionClosed(false) 614 | ]); 615 | 616 | } 617 | 618 | #[test] 619 | #[cfg(target_os = "linux")] 620 | fn test_client_flush_auto_delay() { 621 | 622 | let mut client = Client::::new(Config::default()); 623 | client.connect("255.1.1.1:5678").ok(); 624 | 625 | let start = Instant::now(); 626 | for _ in 0..5 { 627 | client.receive().ok(); 628 | client.send(true).ok(); 629 | } 630 | assert_millis_since!(start, 167, 33); 631 | 632 | } 633 | 634 | #[test] 635 | #[cfg(target_os = "linux")] 636 | fn test_client_auto_delay_with_load() { 637 | 638 | let mut client = Client::::new(Config::default()); 639 | client.connect("255.1.1.1:5678").ok(); 640 | 641 | // Without load 642 | let start = Instant::now(); 643 | for _ in 0..10 { 644 | client.receive().ok(); 645 | client.send(true).ok(); 646 | } 647 | 648 | assert_millis_since!(start, 330, 16); 649 | 650 | // With load 651 | let start = Instant::now(); 652 | for _ in 0..10 { 653 | client.receive().ok(); 654 | thread::sleep(Duration::from_millis(10)); 655 | client.send(true).ok(); 656 | } 657 | 658 | assert_millis_since!(start, 330, 16); 659 | 660 | // With more load 661 | let start = Instant::now(); 662 | for _ in 0..10 { 663 | client.receive().ok(); 664 | thread::sleep(Duration::from_millis(20)); 665 | client.send(true).ok(); 666 | } 667 | 668 | assert_millis_since!(start, 330, 16); 669 | 670 | } 671 | 672 | // TODO test congestion state changes 673 | // TODO test packet lost events 674 | 675 | 676 | // Helpers -------------------------------------------------------------------- 677 | fn client_init(config: Config) -> Client { 678 | 679 | let mut client = Client::::new(config); 680 | client.connect("255.1.1.1:5678").ok(); 681 | 682 | // Verify initial connection packet 683 | let id = client.connection().unwrap().id().0; 684 | client.send(false).ok(); 685 | client.socket().unwrap().assert_sent(vec![ 686 | ("255.1.1.1:5678", [ 687 | 1, 2, 3, 4, 688 | (id >> 24) as u8, 689 | (id >> 16) as u8, 690 | (id >> 8) as u8, 691 | id as u8, 692 | 0, 693 | 0, 694 | 0, 0, 0, 0 695 | 696 | ].to_vec()) 697 | ]); 698 | 699 | client 700 | 701 | } 702 | 703 | fn client_events(client: &mut Client) -> Vec { 704 | client.send(false).ok(); 705 | let mut events = Vec::new(); 706 | while let Ok(event) = client.receive() { 707 | events.push(event); 708 | } 709 | events 710 | } 711 | 712 | -------------------------------------------------------------------------------- /src/test/message_queue.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2017 Ivo Wetzel 2 | 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | // Internal Dependencies ------------------------------------------------------ 10 | use ::Config; 11 | use ::shared::message_queue::{MessageKind, MessageQueue}; 12 | 13 | 14 | // Tests ---------------------------------------------------------------------- 15 | #[test] 16 | fn test_debug_fmt() { 17 | 18 | let mut q = MessageQueue::new(Config::default()); 19 | q.send(MessageKind::Instant, b"Hello World".to_vec()); 20 | 21 | // Check debug fmt support 22 | assert_ne!(format!("{:?}", q), ""); 23 | 24 | } 25 | 26 | #[test] 27 | fn test_send_write() { 28 | 29 | let mut q = MessageQueue::new(Config::default()); 30 | 31 | // Filled from quota 32 | q.send(MessageKind::Instant, b"Hello World".to_vec()); 33 | q.send(MessageKind::Instant, b"Hello World".to_vec()); 34 | 35 | // Added by filling buffer 36 | q.send(MessageKind::Instant, b"Hello World".to_vec()); 37 | 38 | // Put into packet 2 39 | q.send(MessageKind::Instant, b"Hello World2".to_vec()); 40 | q.send(MessageKind::Instant, b"Hello World2".to_vec()); 41 | 42 | // Filled from quota 43 | q.send(MessageKind::Reliable, b"Foo".to_vec()); 44 | 45 | // Put into packet 2 by quota 46 | q.send(MessageKind::Reliable, b"Foo2".to_vec()); 47 | 48 | // Put into packet 2 by filling buffer 49 | q.send(MessageKind::Reliable, b"Foo More".to_vec()); 50 | 51 | // Filled from quota 52 | q.send(MessageKind::Ordered, b"Bar".to_vec()); 53 | 54 | // Put into packet 2 by quota 55 | q.send(MessageKind::Ordered, b"Bar2".to_vec()); 56 | 57 | // Put into packet 3 58 | q.send(MessageKind::Ordered, b"Bar More".to_vec()); 59 | q.send(MessageKind::Ordered, b"Bar Even More".to_vec()); 60 | 61 | // Check Packet 1 62 | let mut buffer = Vec::new(); 63 | q.send_packet(&mut buffer, 60); 64 | 65 | assert_eq!(buffer, [ 66 | // Hello World 67 | 0, 0, 0, 11, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 68 | // Hello World 69 | 0, 0, 0, 11, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 70 | // Foo 71 | 1, 0, 0, 3, 70, 111, 111, 72 | // Bar 73 | 2, 0, 0, 3, 66, 97, 114, 74 | // Hello World 75 | 0, 0, 0, 11, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100 76 | 77 | ].to_vec()); 78 | 79 | // Check Packet 2 80 | let mut buffer = Vec::new(); 81 | q.send_packet(&mut buffer, 64); 82 | 83 | assert_eq!(buffer, [ 84 | // Hello World2 85 | 0, 0, 0, 12, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 50, 86 | // Hello World2 87 | 0, 0, 0, 12, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 50, 88 | // Foo2 89 | 1, 0, 0, 4, 70, 111, 111, 50, 90 | // Bar2 91 | 2, 1, 0, 4, 66, 97, 114, 50, 92 | // Foo More 93 | 1, 0, 0, 8, 70, 111, 111, 32, 77, 111, 114, 101 94 | 95 | ].to_vec()); 96 | 97 | // Check Packet 3 98 | let mut buffer = Vec::new(); 99 | q.send_packet(&mut buffer, 64); 100 | 101 | assert_eq!(buffer, [ 102 | // Bar More 103 | 2, 2, 0, 8, 66, 97, 114, 32, 77, 111, 114, 101, 104 | 105 | // Bar Even More 106 | 2, 3, 0, 13, 66, 97, 114, 32, 69, 118, 101, 110, 32, 77, 111, 114, 101 107 | ].to_vec()); 108 | 109 | } 110 | 111 | #[test] 112 | fn test_send_write_long() { 113 | 114 | let msg = b"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do \ 115 | eiusmod tempor incididunt ut labore et dolore magna aliqua. \ 116 | Ut enim ad minim veniam, quis nostrud exercitation ullamco \ 117 | laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure \ 118 | dolor in reprehenderit in voluptate velit esse cillum dolore eu \ 119 | fugiat nulla pariatur. Excepteur sint occaecat cupidatat non \ 120 | proident, sunt in culpa qui officia deserunt mollit anim id est \ 121 | laborum"; 122 | 123 | let mut q = MessageQueue::new(Config::default()); 124 | q.send(MessageKind::Instant, msg.to_vec()); 125 | 126 | let mut buffer = Vec::new(); 127 | q.send_packet(&mut buffer, 1400); 128 | 129 | assert_eq!(buffer, [ 130 | 0, 0, 1, 188, 76, 111, 114, 101, 109, 32, 105, 112, 115, 117, 109, 131 | 32, 100, 111, 108, 111, 114, 32, 115, 105, 116, 32, 97, 109, 101, 132 | 116, 44, 32, 99, 111, 110, 115, 101, 99, 116, 101, 116, 117, 114, 133 | 32, 97, 100, 105, 112, 105, 115, 99, 105, 110, 103, 32, 101, 108, 134 | 105, 116, 44, 32, 115, 101, 100, 32, 100, 111, 32, 101, 105, 117, 135 | 115, 109, 111, 100, 32, 116, 101, 109, 112, 111, 114, 32, 105, 110, 136 | 99, 105, 100, 105, 100, 117, 110, 116, 32, 117, 116, 32, 108, 97, 137 | 98, 111, 114, 101, 32, 101, 116, 32, 100, 111, 108, 111, 114, 101, 138 | 32, 109, 97, 103, 110, 97, 32, 97, 108, 105, 113, 117, 97, 46, 32, 139 | 85, 116, 32, 101, 110, 105, 109, 32, 97, 100, 32, 109, 105, 110, 140 | 105, 109, 32, 118, 101, 110, 105, 97, 109, 44, 32, 113, 117, 105, 141 | 115, 32, 110, 111, 115, 116, 114, 117, 100, 32, 101, 120, 101, 114, 142 | 99, 105, 116, 97, 116, 105, 111, 110, 32, 117, 108, 108, 97, 109, 143 | 99, 111, 32, 108, 97, 98, 111, 114, 105, 115, 32, 110, 105, 115, 144 | 105, 32, 117, 116, 32, 97, 108, 105, 113, 117, 105, 112, 32, 101, 145 | 120, 32, 101, 97, 32, 99, 111, 109, 109, 111, 100, 111, 32, 99, 146 | 111, 110, 115, 101, 113, 117, 97, 116, 46, 32, 68, 117, 105, 115, 147 | 32, 97, 117, 116, 101, 32, 105, 114, 117, 114, 101, 32, 100, 111, 148 | 108, 111, 114, 32, 105, 110, 32, 114, 101, 112, 114, 101, 104, 101, 149 | 110, 100, 101, 114, 105, 116, 32, 105, 110, 32, 118, 111, 108, 117, 150 | 112, 116, 97, 116, 101, 32, 118, 101, 108, 105, 116, 32, 101, 115, 151 | 115, 101, 32, 99, 105, 108, 108, 117, 109, 32, 100, 111, 108, 111, 152 | 114, 101, 32, 101, 117, 32, 102, 117, 103, 105, 97, 116, 32, 110, 153 | 117, 108, 108, 97, 32, 112, 97, 114, 105, 97, 116, 117, 114, 46, 154 | 32, 69, 120, 99, 101, 112, 116, 101, 117, 114, 32, 115, 105, 110, 155 | 116, 32, 111, 99, 99, 97, 101, 99, 97, 116, 32, 99, 117, 112, 105, 156 | 100, 97, 116, 97, 116, 32, 110, 111, 110, 32, 112, 114, 111, 105, 157 | 100, 101, 110, 116, 44, 32, 115, 117, 110, 116, 32, 105, 110, 32, 158 | 99, 117, 108, 112, 97, 32, 113, 117, 105, 32, 111, 102, 102, 105, 159 | 99, 105, 97, 32, 100, 101, 115, 101, 114, 117, 110, 116, 32, 109, 160 | 111, 108, 108, 105, 116, 32, 97, 110, 105, 109, 32, 105, 100, 32, 161 | 101, 115, 116, 32, 108, 97, 98, 111, 114, 117, 109 162 | ].to_vec()); 163 | 164 | } 165 | 166 | #[test] 167 | fn test_packet_lost_write() { 168 | 169 | let mut q = MessageQueue::new(Config::default()); 170 | 171 | q.lost_packet(&[ 172 | // Hello World2 173 | 0, 0, 0, 12, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 50, 174 | // Hello World2 175 | 0, 0, 0, 12, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 50, 176 | // Foo2 177 | 1, 0, 0, 4, 70, 111, 111, 50, 178 | // Bar2 179 | 2, 1, 0, 4, 66, 97, 114, 50, 180 | // Foo More 181 | 1, 0, 0, 8, 70, 111, 111, 32, 77, 111, 114, 101 182 | ]); 183 | 184 | // Send some more messages 185 | q.send(MessageKind::Instant, b"Hello World".to_vec()); 186 | q.send(MessageKind::Reliable, b"Foo5".to_vec()); 187 | q.send(MessageKind::Ordered, b"Bar3".to_vec()); 188 | 189 | let mut buffer = Vec::new(); 190 | q.send_packet(&mut buffer, 64); 191 | assert_eq!(buffer, [ 192 | 193 | // Hello World 194 | 0, 0, 0, 11, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 195 | 196 | // Foo More 197 | 1, 0, 0, 8, 70, 111, 111, 32, 77, 111, 114, 101, 198 | 199 | // Bar2 200 | 2, 1, 0, 4, 66, 97, 114, 50, 201 | 202 | // Foo2 203 | 1, 0, 0, 4, 70, 111, 111, 50, 204 | 205 | // Bar3 206 | 2, 0, 0, 4, 66, 97, 114, 51, 207 | 208 | // Foo5 209 | 1, 0, 0, 4, 70, 111, 111, 53 210 | 211 | ].to_vec()); 212 | 213 | } 214 | 215 | #[test] 216 | fn test_receive_read() { 217 | 218 | let mut q = MessageQueue::new(Config::default()); 219 | let packet = [ 220 | // Hello World 221 | 0, 0, 0, 11, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 222 | // Hello World 223 | 0, 0, 0, 11, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 224 | // Foo 225 | 1, 0, 0, 3, 70, 111, 111, 226 | // Bar 227 | 2, 0, 0, 3, 66, 97, 114, 228 | // Hello World 229 | 0, 0, 0, 11, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100 230 | ].to_vec(); 231 | 232 | q.receive_packet(&packet[..]); 233 | 234 | assert_eq!(messages(&mut q), [ 235 | b"Hello World".to_vec(), 236 | b"Hello World".to_vec(), 237 | b"Foo".to_vec(), 238 | b"Bar".to_vec(), 239 | b"Hello World".to_vec() 240 | ]); 241 | 242 | } 243 | 244 | #[test] 245 | fn test_receive_read_long() { 246 | 247 | let mut q = MessageQueue::new(Config::default()); 248 | let packet = [ 249 | 0, 0, 1, 188, 76, 111, 114, 101, 109, 32, 105, 112, 115, 117, 109, 250 | 32, 100, 111, 108, 111, 114, 32, 115, 105, 116, 32, 97, 109, 101, 251 | 116, 44, 32, 99, 111, 110, 115, 101, 99, 116, 101, 116, 117, 114, 252 | 32, 97, 100, 105, 112, 105, 115, 99, 105, 110, 103, 32, 101, 108, 253 | 105, 116, 44, 32, 115, 101, 100, 32, 100, 111, 32, 101, 105, 117, 254 | 115, 109, 111, 100, 32, 116, 101, 109, 112, 111, 114, 32, 105, 110, 255 | 99, 105, 100, 105, 100, 117, 110, 116, 32, 117, 116, 32, 108, 97, 256 | 98, 111, 114, 101, 32, 101, 116, 32, 100, 111, 108, 111, 114, 101, 257 | 32, 109, 97, 103, 110, 97, 32, 97, 108, 105, 113, 117, 97, 46, 32, 258 | 85, 116, 32, 101, 110, 105, 109, 32, 97, 100, 32, 109, 105, 110, 259 | 105, 109, 32, 118, 101, 110, 105, 97, 109, 44, 32, 113, 117, 105, 260 | 115, 32, 110, 111, 115, 116, 114, 117, 100, 32, 101, 120, 101, 114, 261 | 99, 105, 116, 97, 116, 105, 111, 110, 32, 117, 108, 108, 97, 109, 262 | 99, 111, 32, 108, 97, 98, 111, 114, 105, 115, 32, 110, 105, 115, 263 | 105, 32, 117, 116, 32, 97, 108, 105, 113, 117, 105, 112, 32, 101, 264 | 120, 32, 101, 97, 32, 99, 111, 109, 109, 111, 100, 111, 32, 99, 265 | 111, 110, 115, 101, 113, 117, 97, 116, 46, 32, 68, 117, 105, 115, 266 | 32, 97, 117, 116, 101, 32, 105, 114, 117, 114, 101, 32, 100, 111, 267 | 108, 111, 114, 32, 105, 110, 32, 114, 101, 112, 114, 101, 104, 101, 268 | 110, 100, 101, 114, 105, 116, 32, 105, 110, 32, 118, 111, 108, 117, 269 | 112, 116, 97, 116, 101, 32, 118, 101, 108, 105, 116, 32, 101, 115, 270 | 115, 101, 32, 99, 105, 108, 108, 117, 109, 32, 100, 111, 108, 111, 271 | 114, 101, 32, 101, 117, 32, 102, 117, 103, 105, 97, 116, 32, 110, 272 | 117, 108, 108, 97, 32, 112, 97, 114, 105, 97, 116, 117, 114, 46, 273 | 32, 69, 120, 99, 101, 112, 116, 101, 117, 114, 32, 115, 105, 110, 274 | 116, 32, 111, 99, 99, 97, 101, 99, 97, 116, 32, 99, 117, 112, 105, 275 | 100, 97, 116, 97, 116, 32, 110, 111, 110, 32, 112, 114, 111, 105, 276 | 100, 101, 110, 116, 44, 32, 115, 117, 110, 116, 32, 105, 110, 32, 277 | 99, 117, 108, 112, 97, 32, 113, 117, 105, 32, 111, 102, 102, 105, 278 | 99, 105, 97, 32, 100, 101, 115, 101, 114, 117, 110, 116, 32, 109, 279 | 111, 108, 108, 105, 116, 32, 97, 110, 105, 109, 32, 105, 100, 32, 280 | 101, 115, 116, 32, 108, 97, 98, 111, 114, 117, 109 281 | ].to_vec(); 282 | 283 | q.receive_packet(&packet[..]); 284 | 285 | let msg = b"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do \ 286 | eiusmod tempor incididunt ut labore et dolore magna aliqua. \ 287 | Ut enim ad minim veniam, quis nostrud exercitation ullamco \ 288 | laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure \ 289 | dolor in reprehenderit in voluptate velit esse cillum dolore eu \ 290 | fugiat nulla pariatur. Excepteur sint occaecat cupidatat non \ 291 | proident, sunt in culpa qui officia deserunt mollit anim id est \ 292 | laborum"; 293 | 294 | assert_eq!(messages(&mut q), [ 295 | msg.to_vec(), 296 | ]); 297 | 298 | } 299 | 300 | #[test] 301 | fn test_receive_read_out_of_order() { 302 | 303 | let mut q = MessageQueue::new(Config::default()); 304 | 305 | // Receive one out of order(#1) "World" message 306 | q.receive_packet(&[ 307 | 2, 1, 0, 5, 87, 111, 114, 108, 100 308 | ]); 309 | 310 | // We expect no message yet 311 | assert!(messages(&mut q).is_empty()); 312 | 313 | // Receive one out of order(#3) "order!" message 314 | q.receive_packet(&[ 315 | 2, 3, 0, 6, 111, 114, 100, 101, 114, 33 316 | ]); 317 | 318 | // We still expect no message yet 319 | assert!(messages(&mut q).is_empty()); 320 | 321 | // Receive the actual first "Hello" message 322 | q.receive_packet(&[ 323 | 2, 0, 0, 5, 72, 101, 108, 108, 111 324 | ]); 325 | 326 | // We now expect both "Hello" and "World" 327 | assert_eq!(messages(&mut q), [b"Hello", b"World"]); 328 | 329 | // Receive the order(#2) "out of" message 330 | q.receive_packet(&[ 331 | 2, 2, 0, 6, 111, 117, 116, 32, 111, 102 332 | ]); 333 | 334 | // We now expect both "out of" and "order!" 335 | assert_eq!(messages(&mut q), [b"out of", b"order!"]); 336 | } 337 | 338 | #[test] 339 | fn test_receive_empty() { 340 | 341 | let mut q = MessageQueue::new(Config::default()); 342 | 343 | // Receive 2 empty messages 344 | q.receive_packet(&[ 345 | 0, 0, 0, 0, 346 | 0, 0, 0, 0 347 | ]); 348 | 349 | assert_eq!(messages(&mut q), [b"", b""]); 350 | 351 | } 352 | 353 | #[test] 354 | fn test_receive_invalid() { 355 | 356 | let mut q = MessageQueue::new(Config::default()); 357 | 358 | // Receive a message with a invalid kind 359 | q.receive_packet(&[ 360 | 255, 0, 0, 0 361 | ]); 362 | 363 | assert!(messages(&mut q).is_empty()); 364 | 365 | // Receive a message with incomplete header 366 | q.receive_packet(&[ 367 | 0, 0 368 | ]); 369 | 370 | q.receive_packet(&[ 371 | 0, 0, 0 372 | ]); 373 | 374 | // Receive a message with incomplete data 375 | q.receive_packet(&[ 376 | 0, 0, 0, 15, 72, 101, 108, 108, 111 // 15 bytes but only 5 in buffer 377 | ]); 378 | 379 | assert_eq!(messages(&mut q), [b"Hello"]); 380 | 381 | } 382 | 383 | #[test] 384 | fn test_receive_ordered_decoding_wrap_around() { 385 | 386 | let mut q = MessageQueue::new(Config::default()); 387 | for i in 0..4096 { 388 | 389 | q.receive_packet(&[ 390 | 2 | ((i & 0x0F00) >> 4) as u8, (i as u8), 0, 2, (i >> 8) as u8, i as u8 391 | ]); 392 | 393 | assert_eq!(messages(&mut q), [[(i >> 8) as u8, i as u8]]); 394 | 395 | } 396 | 397 | // Should now expect order=0 again 398 | q.receive_packet(&[ 399 | 2, 0, 0, 2, 0, 0 400 | ]); 401 | assert_eq!(messages(&mut q), [[0, 0]]); 402 | 403 | } 404 | 405 | #[test] 406 | fn test_receive_ordered_encoding_wrap_around() { 407 | 408 | let mut q = MessageQueue::new(Config::default()); 409 | for i in 0..4096 { 410 | 411 | q.send(MessageKind::Ordered, [(i >> 8) as u8, i as u8].to_vec()); 412 | 413 | let mut buffer = Vec::new(); 414 | q.send_packet(&mut buffer, 64); 415 | assert_eq!(buffer, [ 416 | 2 | ((i & 0x0F00) >> 4) as u8, (i as u8), 0, 2, (i >> 8) as u8, i as u8].to_vec() 417 | ); 418 | 419 | } 420 | 421 | // Should now write order=0 again 422 | q.send(MessageKind::Ordered, [0, 0].to_vec()); 423 | 424 | let mut buffer = Vec::new(); 425 | q.send_packet(&mut buffer, 64); 426 | assert_eq!(buffer, [2, 0, 0, 2, 0, 0].to_vec()); 427 | 428 | } 429 | 430 | #[test] 431 | fn test_reset() { 432 | 433 | let mut q = MessageQueue::new(Config::default()); 434 | q.send(MessageKind::Instant, b"Hello World".to_vec()); 435 | q.send(MessageKind::Instant, b"Hello World".to_vec()); 436 | q.send(MessageKind::Reliable, b"Hello World".to_vec()); 437 | q.send(MessageKind::Ordered, b"Hello World".to_vec()); 438 | q.send(MessageKind::Ordered, b"Hello World".to_vec()); 439 | 440 | // Reset all queues and order ids 441 | q.reset(); 442 | 443 | // Check that nothing gets serialized 444 | let mut buffer = Vec::new(); 445 | q.send_packet(&mut buffer, 64); 446 | assert_eq!(buffer, [].to_vec()); 447 | 448 | // Check that local_order_id has been reset 449 | q.send(MessageKind::Ordered, b"".to_vec()); 450 | q.send_packet(&mut buffer, 64); 451 | assert_eq!(buffer, [2, 0, 0, 0].to_vec()); 452 | } 453 | 454 | #[test] 455 | fn test_in_order_duplicates() { 456 | 457 | let mut q = MessageQueue::new(Config::default()); 458 | 459 | q.receive_packet(&[ 460 | 2, 0, 0, 1, 53, // Expected #1 461 | 2, 1, 0, 1, 54, // Expected #2 462 | 2, 1, 0, 1, 55, 463 | 2, 1, 0, 1, 56, 464 | 2, 2, 0, 1, 57, // Expected #3 465 | 2, 2, 0, 1, 58, 466 | 2, 3, 0, 1, 59 // Expected #4 467 | ]); 468 | 469 | assert_eq!(messages(&mut q), [[53], [54], [57], [59]]); 470 | 471 | } 472 | 473 | #[test] 474 | fn test_out_of_order_duplicates() { 475 | 476 | let mut q = MessageQueue::new(Config::default()); 477 | 478 | q.receive_packet(&[ 479 | 2, 0, 0, 1, 53, // Expected #1 480 | 2, 2, 0, 1, 54, // Expected #3 481 | 2, 2, 0, 1, 55, 482 | 2, 2, 0, 1, 56, 483 | 2, 1, 0, 1, 57, // Expected #2 484 | 2, 4, 0, 1, 58, // Expected #5 485 | 2, 3, 0, 1, 59 // Expected #4 486 | ]); 487 | 488 | assert_eq!(messages(&mut q), [[53], [57], [54], [59], [58]]); 489 | 490 | } 491 | 492 | // Helpers -------------------------------------------------------------------- 493 | fn messages(q: &mut MessageQueue) -> Vec> { 494 | let mut messages = Vec::new(); 495 | for m in q.received() { 496 | messages.push(m); 497 | } 498 | messages 499 | } 500 | 501 | -------------------------------------------------------------------------------- /src/test/mock_socket.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2017 Ivo Wetzel 2 | 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | // STD Dependencies ----------------------------------------------------------- 10 | use std::cmp; 11 | use std::io::{Error, ErrorKind}; 12 | use std::net::{SocketAddr, ToSocketAddrs}; 13 | use std::collections::VecDeque; 14 | use std::sync::mpsc::TryRecvError; 15 | 16 | 17 | // Internal Dependencies ------------------------------------------------------ 18 | use super::super::Socket; 19 | 20 | 21 | // Mock Packet Data Abstraction ----------------------------------------------- 22 | #[derive(Debug, Clone, Eq, PartialEq)] 23 | pub struct MockPacket(SocketAddr, Vec); 24 | 25 | impl Ord for MockPacket { 26 | 27 | fn cmp(&self, other: &Self) -> cmp::Ordering { 28 | self.0.port().cmp(&other.0.port()) 29 | } 30 | } 31 | 32 | impl PartialOrd for MockPacket { 33 | fn partial_cmp(&self, other: &Self) -> Option { 34 | Some(self.cmp(other)) 35 | } 36 | } 37 | 38 | 39 | // Client / Server Socket Abstraction ----------------------------------------- 40 | #[derive(Debug)] 41 | pub struct MockSocket { 42 | local_addr: SocketAddr, 43 | sent_index: usize, 44 | pub incoming: VecDeque, 45 | pub outgoing: Vec, 46 | fail_sends: bool 47 | } 48 | 49 | impl Socket for MockSocket { 50 | 51 | fn new(addr: T, _: usize) -> Result { 52 | Ok(MockSocket { 53 | local_addr: to_socket_addr(addr), 54 | sent_index: 0, 55 | incoming: VecDeque::new(), 56 | outgoing: Vec::new(), 57 | fail_sends: false 58 | }) 59 | } 60 | 61 | fn try_recv(&mut self) -> Result<(SocketAddr, Vec), TryRecvError> { 62 | if let Some(packet) = self.incoming.pop_front() { 63 | Ok((packet.0, packet.1)) 64 | 65 | } else { 66 | Err(TryRecvError::Empty) 67 | } 68 | } 69 | 70 | fn send_to( 71 | &mut self, 72 | data: &[u8], 73 | addr: SocketAddr 74 | 75 | ) -> Result { 76 | if !self.fail_sends { 77 | self.outgoing.push(MockPacket(addr, data.to_vec())); 78 | Ok(data.len()) 79 | 80 | } else { 81 | Err(Error::new(ErrorKind::Other, "")) 82 | } 83 | } 84 | 85 | fn local_addr(&self) -> Result { 86 | Ok(self.local_addr) 87 | } 88 | 89 | } 90 | 91 | impl MockSocket { 92 | 93 | pub fn fail_further_sends(&mut self) { 94 | self.fail_sends = true; 95 | } 96 | 97 | pub fn mock_receive(&mut self, packets: Vec<(T, Vec)>) { 98 | for p in packets { 99 | self.incoming.push_back(MockPacket(to_socket_addr(p.0), p.1)); 100 | } 101 | } 102 | 103 | pub fn sent(&mut self) -> Vec { 104 | 105 | let packets: Vec = self.outgoing.iter().skip(self.sent_index).cloned().collect(); 106 | 107 | self.sent_index += packets.len(); 108 | packets 109 | 110 | } 111 | 112 | pub fn assert_sent_none(&mut self) { 113 | let sent = self.sent(); 114 | if !sent.is_empty() { 115 | panic!(format!("Expected no more packet(s) to be sent, but {} additional ones.", sent.len())); 116 | } 117 | } 118 | 119 | pub fn sent_count(&mut self) -> usize { 120 | self.sent().len() 121 | } 122 | 123 | pub fn assert_sent(&mut self, expected: Vec<(T, Vec)>) { 124 | self.assert_sent_sorted(expected, false); 125 | } 126 | 127 | fn assert_sent_sorted(&mut self, expected: Vec<(T, Vec)>, sort_by_addr: bool) { 128 | 129 | // In some cases we need a reliable assert order so we sort the sent 130 | // packets by their address 131 | let sent = if sort_by_addr { 132 | let mut sent = self.sent(); 133 | sent.sort(); 134 | sent 135 | 136 | } else { 137 | self.sent() 138 | }; 139 | 140 | // Totals 141 | let expected_total = expected.len(); 142 | let sent_total = sent.len(); 143 | let min_total = cmp::min(expected_total, sent_total); 144 | 145 | for (i, (expected, sent)) in expected.into_iter().zip(sent.into_iter()).enumerate() { 146 | 147 | // Compare addresses 148 | let sent_addr = to_socket_addr(sent.0); 149 | let expected_addr = to_socket_addr(expected.0); 150 | if sent_addr != expected_addr { 151 | panic!(format!( 152 | "{}) Packet destination address ({:?}) does not match expected one: {:?}.", 153 | i, sent_addr, expected_addr 154 | )); 155 | } 156 | 157 | // Verify packet data. We specifically ignore the connection ID here 158 | // since it is random and cannot be accessed by the mocks 159 | if sent.1[0..4] != expected.1[0..4] { 160 | panic!(format!( 161 | "{}) Packet protocol header of sent packet ({:?}) does not match expected one: {:?}.", 162 | i, sent.1[0..4].to_vec(), expected.1[0..4].to_vec() 163 | )); 164 | } 165 | 166 | if sent.1[8..] != expected.1[8..] { 167 | panic!(format!( 168 | "{}) Packet body data of sent packet ({:?}) does not match expected one: {:?}.", 169 | i, sent.1[8..].to_vec(), expected.1[8..].to_vec() 170 | )); 171 | } 172 | 173 | } 174 | 175 | if expected_total > min_total { 176 | panic!(format!("Expected at least {} packet(s) to be sent, but only got a total of {}.", expected_total, sent_total)); 177 | 178 | } else if sent_total > min_total { 179 | panic!(format!("Expected no more than {} packet(s) to be sent, but got a total of {}.", expected_total, sent_total)); 180 | } 181 | 182 | } 183 | 184 | } 185 | 186 | 187 | // Helpers -------------------------------------------------------------------- 188 | fn to_socket_addr(address: T) -> SocketAddr { 189 | address.to_socket_addrs().unwrap().nth(0).unwrap() 190 | } 191 | 192 | -------------------------------------------------------------------------------- /src/test/mod.rs: -------------------------------------------------------------------------------- 1 | // Modules -------------------------------------------------------------------- 2 | mod client; 3 | mod connection; 4 | mod message_queue; 5 | mod mock_socket; 6 | mod server; 7 | 8 | 9 | // Re-Exports ----------------------------------------------------------------- 10 | pub use self::mock_socket::MockSocket; 11 | 12 | -------------------------------------------------------------------------------- /src/test/server.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2017 Ivo Wetzel 2 | 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | // STD Dependencies ----------------------------------------------------------- 10 | use std::thread; 11 | use std::time::{Duration, Instant}; 12 | use std::io::ErrorKind; 13 | use std::sync::mpsc::TryRecvError; 14 | 15 | 16 | // Internal Dependencies ------------------------------------------------------ 17 | use super::MockSocket; 18 | use ::{ 19 | BinaryRateLimiter, ConnectionID, Config, MessageKind, NoopPacketModifier, 20 | Server, ServerEvent 21 | }; 22 | 23 | 24 | // Macros --------------------------------------------------------------------- 25 | macro_rules! assert_millis_since { 26 | ($start:expr, $target:expr, $difference:expr) => { 27 | { 28 | let duration = $start.elapsed(); 29 | let millis = (duration.subsec_nanos() / 1000000) as u64; 30 | 31 | let actual = (duration.as_secs() * 1000 + millis) as i64; 32 | let min = $target - $difference; 33 | let max = $target + $difference; 34 | if actual < min || actual > max { 35 | panic!(format!("Value {} not in range {} - {}", actual, min, max)); 36 | } 37 | } 38 | } 39 | } 40 | 41 | 42 | // Tests ---------------------------------------------------------------------- 43 | #[test] 44 | fn test_server_configuration() { 45 | 46 | let config = Config { 47 | send_rate: 30, 48 | .. Config::default() 49 | }; 50 | 51 | let mut server = Server::::new(config); 52 | assert_eq!(server.config(), config); 53 | 54 | let config = Config { 55 | send_rate: 60, 56 | .. Config::default() 57 | }; 58 | 59 | server.set_config(config); 60 | assert_eq!(server.config(), config); 61 | 62 | } 63 | 64 | #[test] 65 | fn test_server_internals() { 66 | 67 | let mut server = Server::::new(Config { 68 | send_rate: 30, 69 | .. Config::default() 70 | }); 71 | 72 | assert_eq!(server.socket().unwrap_err().kind(), ErrorKind::NotConnected); 73 | 74 | } 75 | 76 | #[test] 77 | fn test_server_disconnected() { 78 | 79 | let conn_id = ConnectionID(0); 80 | 81 | let mut server = Server::::new(Config { 82 | send_rate: 30, 83 | .. Config::default() 84 | }); 85 | 86 | assert_eq!(server.bytes_sent(), 0); 87 | assert_eq!(server.bytes_received(), 0); 88 | 89 | assert_eq!(server.local_addr().unwrap_err().kind(), ErrorKind::AddrNotAvailable); 90 | assert_eq!(server.connection(&conn_id).unwrap_err().kind(), ErrorKind::NotConnected); 91 | assert_eq!(server.connections().len(), 0); 92 | 93 | assert_eq!(server.accept_receive(), Err(TryRecvError::Disconnected)); 94 | assert_eq!(server.send(false).unwrap_err().kind(), ErrorKind::NotConnected); 95 | assert_eq!(server.shutdown().unwrap_err().kind(), ErrorKind::NotConnected); 96 | 97 | } 98 | 99 | #[test] 100 | fn test_server_listen_shutdown() { 101 | 102 | let mut server = Server::::new(Config::default()); 103 | 104 | assert!(server.listen("127.0.0.1:1234").is_ok()); 105 | 106 | assert_eq!(server.listen("127.0.0.1:1234").unwrap_err().kind(), ErrorKind::AlreadyExists); 107 | assert!(server.socket().is_ok()); 108 | 109 | assert!(server.shutdown().is_ok()); 110 | assert_eq!(server.socket().unwrap_err().kind(), ErrorKind::NotConnected); 111 | 112 | assert_eq!(server.shutdown().unwrap_err().kind(), ErrorKind::NotConnected); 113 | 114 | } 115 | 116 | #[test] 117 | fn test_server_flow_without_connections() { 118 | 119 | let mut server = Server::::new(Config::default()); 120 | 121 | assert!(server.listen("127.0.0.1:1234").is_ok()); 122 | 123 | assert_eq!(server.accept_receive(), Err(TryRecvError::Empty)); 124 | 125 | assert!(server.send(false).is_ok()); 126 | 127 | assert!(server.shutdown().is_ok()); 128 | 129 | } 130 | 131 | #[test] 132 | fn test_server_flush_without_delay() { 133 | 134 | let mut server = Server::::new(Config::default()); 135 | server.listen("127.0.0.1:1234").ok(); 136 | 137 | let start = Instant::now(); 138 | for _ in 0..5 { 139 | server.accept_receive().ok(); 140 | server.send(false).ok(); 141 | } 142 | assert_millis_since!(start, 0, 16); 143 | 144 | } 145 | 146 | #[test] 147 | fn test_server_connection() { 148 | 149 | let mut server = Server::::new(Config::default()); 150 | server.listen("127.0.0.1:1234").ok(); 151 | 152 | // Accept a incoming connection 153 | server.socket().unwrap().mock_receive(vec![ 154 | ("255.1.1.1:1000", vec![ 155 | 1, 2, 3, 4, 156 | 9, 8, 7, 6, 157 | 0, 158 | 0, 159 | 0, 0, 0, 0 160 | ]) 161 | ]); 162 | 163 | assert_eq!(server_events(&mut server), vec![ 164 | ServerEvent::Connection(ConnectionID(151521030)) 165 | ]); 166 | 167 | assert_eq!(server.connections().keys().collect::>(), vec![&ConnectionID(151521030)]); 168 | 169 | // Accept another incoming connection 170 | server.socket().unwrap().mock_receive(vec![ 171 | ("255.1.1.1:2000", vec![ 172 | 1, 2, 3, 4, 173 | 4, 0, 0, 1, 174 | 0, 175 | 0, 176 | 0, 0, 0, 0 177 | ]) 178 | ]); 179 | 180 | assert_eq!(server_events(&mut server), vec![ 181 | ServerEvent::Connection(ConnectionID(67108865)) 182 | ]); 183 | 184 | { 185 | let mut keys = server.connections().keys().collect::>(); 186 | keys.sort(); 187 | assert_eq!(keys, vec![ 188 | &ConnectionID(67108865), 189 | &ConnectionID(151521030) 190 | ]); 191 | } 192 | 193 | // Switch the first connection to another peer address 194 | server.socket().unwrap().mock_receive(vec![ 195 | ("255.1.1.2:1003", vec![ 196 | 1, 2, 3, 4, 197 | 9, 8, 7, 6, 198 | 0, 199 | 0, 200 | 0, 0, 0, 0 201 | ]) 202 | ]); 203 | 204 | // Shutdown and drop all connections 205 | server.shutdown().ok(); 206 | 207 | assert_eq!(server_events(&mut server), vec![]); 208 | 209 | // All connections should have been removed 210 | assert!(server.connections().keys().collect::>().is_empty()); 211 | assert!(server.connection(&ConnectionID(151521030)).is_err()); 212 | assert!(server.connection(&ConnectionID(67108865)).is_err()); 213 | 214 | } 215 | 216 | #[test] 217 | fn test_server_connection_address_remap() { 218 | 219 | let mut server = Server::::new(Config::default()); 220 | server.listen("127.0.0.1:1234").ok(); 221 | 222 | // Accept a incoming connection 223 | server.socket().unwrap().mock_receive(vec![ 224 | ("255.1.1.1:1000", vec![ 225 | 1, 2, 3, 4, 226 | 9, 8, 7, 6, 227 | 0, 228 | 0, 229 | 0, 0, 0, 0 230 | ]) 231 | ]); 232 | 233 | assert_eq!(server_events(&mut server), vec![ 234 | ServerEvent::Connection(ConnectionID(151521030)) 235 | ]); 236 | 237 | // Test send to initial address 238 | server.send(false).ok(); 239 | server.socket().unwrap().assert_sent(vec![ 240 | ("255.1.1.1:1000", [ 241 | 1, 2, 3, 4, 242 | 9, 8, 7, 6, 243 | 0, 244 | 0, 245 | 0, 0, 0, 0 246 | 247 | ].to_vec()) 248 | ]); 249 | 250 | // Receive from same connection id but different address 251 | server.socket().unwrap().mock_receive(vec![ 252 | ("255.1.1.4:2000", vec![ 253 | 1, 2, 3, 4, 254 | 9, 8, 7, 6, 255 | 1, 256 | 0, 257 | 0, 0, 0, 0 258 | ]) 259 | ]); 260 | 261 | // Trigger receival and address re-map 262 | server.accept_receive().ok(); 263 | 264 | // Check send to new address 265 | server.send(false).ok(); 266 | server.socket().unwrap().assert_sent(vec![ 267 | ("255.1.1.4:2000", [ 268 | 1, 2, 3, 4, 269 | 9, 8, 7, 6, 270 | 1, 271 | 1, 272 | 0, 0, 0, 1 273 | 274 | ].to_vec()) 275 | ]); 276 | 277 | // Re-map should not happen for packets with older sequence numbers 278 | server.socket().unwrap().mock_receive(vec![ 279 | ("255.1.1.8:4000", vec![ 280 | 1, 2, 3, 4, 281 | 9, 8, 7, 6, 282 | 0, 283 | 0, 284 | 0, 0, 0, 0 285 | ]) 286 | ]); 287 | 288 | server.accept_receive().ok(); 289 | server.send(false).ok(); 290 | 291 | // Verify send to first re-mapped address 292 | server.socket().unwrap().assert_sent(vec![ 293 | ("255.1.1.4:2000", [ 294 | 1, 2, 3, 4, 295 | 9, 8, 7, 6, 296 | 2, 297 | 1, 298 | 0, 0, 0, 1 299 | 300 | ].to_vec()) 301 | ]); 302 | 303 | assert_eq!(server_events(&mut server), vec![ 304 | // There should be no connection event here since the connection id 305 | // got remapped to the new peer address 306 | ]); 307 | 308 | } 309 | 310 | #[test] 311 | fn test_server_reset_events() { 312 | 313 | let mut server = Server::::new(Config::default()); 314 | server.listen("127.0.0.1:1234").ok(); 315 | 316 | // Accept a incoming connection 317 | server.socket().unwrap().mock_receive(vec![ 318 | ("255.1.1.1:1000", vec![ 319 | 1, 2, 3, 4, 320 | 9, 8, 7, 6, 321 | 0, 322 | 0, 323 | 0, 0, 0, 0 324 | ]) 325 | ]); 326 | 327 | // Fetch events from the connections 328 | server.accept_receive().ok(); 329 | server.send(false).ok(); 330 | 331 | // Shutdown should clear events 332 | server.shutdown().ok(); 333 | 334 | // Re-bind and make events accesible again 335 | server.listen("127.0.0.1:1234").ok(); 336 | assert!(server_events(&mut server).is_empty()); 337 | 338 | } 339 | 340 | #[test] 341 | fn test_server_send() { 342 | 343 | let mut server = Server::::new(Config::default()); 344 | server.listen("127.0.0.1:1234").ok(); 345 | 346 | // Accept a incoming connection 347 | server.socket().unwrap().mock_receive(vec![ 348 | ("255.1.1.1:1000", vec![ 349 | 1, 2, 3, 4, 350 | 9, 8, 7, 6, 351 | 0, 352 | 0, 353 | 0, 0, 0, 0 354 | ]) 355 | ]); 356 | 357 | assert_eq!(server_events(&mut server), vec![ 358 | ServerEvent::Connection(ConnectionID(151521030)) 359 | ]); 360 | 361 | assert!(server.connection(&ConnectionID(1)).is_err()); 362 | 363 | // Send via connection handle 364 | server.connection(&ConnectionID(151521030)).unwrap().send(MessageKind::Instant, b"Foo".to_vec()); 365 | server.connection(&ConnectionID(151521030)).unwrap().send(MessageKind::Instant, b"Bar".to_vec()); 366 | 367 | // Check connections map entries 368 | assert_eq!(server.connections().keys().collect::>(), vec![&ConnectionID(151521030)]); 369 | 370 | // Stats should not be updated before send is called 371 | assert_eq!(server.bytes_sent(), 0); 372 | assert_eq!(server.bytes_received(), 0); 373 | 374 | // No messages should be send before send is called 375 | server.socket().unwrap().assert_sent_none(); 376 | 377 | // Both messages should be send after the send call 378 | server.send(false).ok(); 379 | server.socket().unwrap().assert_sent(vec![("255.1.1.1:1000", [ 380 | 1, 2, 3, 4, 381 | 9, 8, 7, 6, 382 | 0, 383 | 0, 384 | 0, 0, 0, 0, 385 | 0, 0, 0, 3, 70, 111, 111, 386 | 0, 0, 0, 3, 66, 97, 114 387 | 388 | ].to_vec())]); 389 | 390 | // Stats should be updated after send call 391 | assert_eq!(server.bytes_sent(), 28); 392 | assert_eq!(server.bytes_received(), 14); 393 | 394 | // Switch connection to new address 395 | server.socket().unwrap().mock_receive(vec![ 396 | ("255.1.1.2:1001", vec![ 397 | 1, 2, 3, 4, 398 | 9, 8, 7, 6, 399 | 1, 400 | 0, 401 | 0, 0, 0, 0 402 | ]) 403 | ]); 404 | 405 | server.accept_receive().ok(); 406 | 407 | // Send to new address 408 | server.connection(&ConnectionID(151521030)).unwrap().send(MessageKind::Instant, b"Baz".to_vec()); 409 | 410 | // Check connections map entries 411 | assert_eq!(server.connections().keys().collect::>(), vec![&ConnectionID(151521030)]); 412 | 413 | // Message should be send to the new address of the connection 414 | server.send(false).ok(); 415 | server.socket().unwrap().assert_sent(vec![ 416 | ("255.1.1.2:1001", [ 417 | 1, 2, 3, 4, 418 | 9, 8, 7, 6, 419 | 1, 420 | 1, 421 | 0, 0, 0, 1, 422 | 0, 0, 0, 3, 66, 97, 122 423 | 424 | ].to_vec()) 425 | ]); 426 | 427 | assert_eq!(server.bytes_sent(), 49); 428 | assert_eq!(server.bytes_received(), 28); 429 | 430 | // Shutdown and reset stats 431 | server.shutdown().ok(); 432 | assert_eq!(server.bytes_sent(), 0); 433 | assert_eq!(server.bytes_received(), 0); 434 | 435 | } 436 | 437 | #[test] 438 | fn test_server_receive() { 439 | 440 | let mut server = Server::::new(Config::default()); 441 | server.listen("127.0.0.1:1234").ok(); 442 | 443 | // Accept incoming connections 444 | server.socket().unwrap().mock_receive(vec![ 445 | ("255.1.1.1:1000", vec![ 446 | 1, 2, 3, 4, 447 | 9, 8, 7, 6, 448 | 0, 449 | 0, 450 | 0, 0, 0, 0, 451 | 0, 0, 0, 3, 66, 97, 122 452 | ]), 453 | ("255.1.1.2:2000", vec![ 454 | 1, 2, 3, 4, 455 | 5, 5, 1, 1, 456 | 0, 457 | 0, 458 | 0, 0, 0, 0, 459 | 1, 0, 0, 3, 70, 111, 111 460 | ]) 461 | ]); 462 | 463 | server.socket().unwrap().mock_receive(vec![ 464 | ("255.1.1.1:1000", vec![ 465 | 1, 2, 3, 4, 466 | 9, 8, 7, 6, 467 | 0, 468 | 0, 469 | 0, 0, 0, 0, 470 | 0, 0, 0, 3, 66, 97, 122 471 | ]), 472 | ("255.1.1.2:2000", vec![ 473 | 1, 2, 3, 4, 474 | 5, 5, 1, 1, 475 | 0, 476 | 0, 477 | 0, 0, 0, 0, 478 | 1, 0, 0, 3, 70, 111, 111 479 | ]) 480 | ]); 481 | 482 | assert_eq!(server_events(&mut server), vec![ 483 | ServerEvent::Connection(ConnectionID(151521030)), 484 | ServerEvent::Message(ConnectionID(151521030), b"Baz".to_vec()), 485 | ServerEvent::Connection(ConnectionID(84214017)), 486 | ServerEvent::Message(ConnectionID(84214017), b"Foo".to_vec()) 487 | ]); 488 | 489 | // Should ignore duplicates 490 | server.socket().unwrap().mock_receive(vec![ 491 | ("255.1.1.1:1000", vec![ 492 | 1, 2, 3, 4, 493 | 9, 8, 7, 6, 494 | 0, 495 | 0, 496 | 0, 0, 0, 0, 497 | 0, 0, 0, 3, 66, 97, 122 498 | ]), 499 | ("255.1.1.2:2000", vec![ 500 | 1, 2, 3, 4, 501 | 5, 5, 1, 1, 502 | 0, 503 | 0, 504 | 0, 0, 0, 0, 505 | 1, 0, 0, 3, 70, 111, 111 506 | ]) 507 | ]); 508 | 509 | assert!(server_events(&mut server).is_empty()); 510 | 511 | // Receive additional messages 512 | server.socket().unwrap().mock_receive(vec![ 513 | ("255.1.1.1:1000", vec![ 514 | 1, 2, 3, 4, 515 | 9, 8, 7, 6, 516 | 1, 517 | 0, 518 | 0, 0, 0, 0, 519 | 1, 0, 0, 3, 70, 111, 111 520 | ]), 521 | ("255.1.1.2:2000", vec![ 522 | 1, 2, 3, 4, 523 | 5, 5, 1, 1, 524 | 1, 525 | 0, 526 | 0, 0, 0, 0, 527 | 0, 0, 0, 3, 66, 97, 122 528 | ]) 529 | ]); 530 | 531 | assert_eq!(server_events(&mut server), vec![ 532 | ServerEvent::Message(ConnectionID(151521030), b"Foo".to_vec()), 533 | ServerEvent::Message(ConnectionID(84214017), b"Baz".to_vec()) 534 | ]); 535 | 536 | } 537 | 538 | #[test] 539 | fn test_server_connection_close() { 540 | 541 | let mut server = Server::::new(Config::default()); 542 | server.listen("127.0.0.1:1234").ok(); 543 | 544 | // Accept incoming connections 545 | server.socket().unwrap().mock_receive(vec![ 546 | ("255.1.1.1:1000", vec![ 547 | 1, 2, 3, 4, 548 | 9, 8, 7, 6, 549 | 0, 550 | 0, 551 | 0, 0, 0, 0 552 | ]), 553 | ("255.1.1.2:2000", vec![ 554 | 1, 2, 3, 4, 555 | 5, 5, 1, 1, 556 | 0, 557 | 0, 558 | 0, 0, 0, 0 559 | ]) 560 | ]); 561 | 562 | server.socket().unwrap().mock_receive(vec![ 563 | ("255.1.1.1:1000", vec![ 564 | 1, 2, 3, 4, 565 | 9, 8, 7, 6, 566 | 0, 567 | 0, 568 | 0, 0, 0, 0, 569 | 0, 0, 0, 3, 66, 97, 122 570 | ]), 571 | ("255.1.1.2:2000", vec![ 572 | 1, 2, 3, 4, 573 | 5, 5, 1, 1, 574 | 0, 575 | 0, 576 | 0, 0, 0, 0, 577 | 1, 0, 0, 3, 70, 111, 111 578 | ]) 579 | ]); 580 | 581 | assert_eq!(server_events(&mut server), vec![ 582 | ServerEvent::Connection(ConnectionID(151521030)), 583 | ServerEvent::Connection(ConnectionID(84214017)), 584 | ]); 585 | 586 | // Receive closure packet 587 | server.socket().unwrap().mock_receive(vec![ 588 | ("255.1.1.1:1000", vec![ 589 | 1, 2, 3, 4, 590 | 9, 8, 7, 6, 591 | 0, 128, // Most distant sequence numbers 592 | 85, 85, 85, 85 // ack bitfield with every second bit set 593 | ]) 594 | ]); 595 | 596 | // Expect closure by remote 597 | assert_eq!(server_events(&mut server), vec![ 598 | ServerEvent::ConnectionClosed(ConnectionID(151521030), true) 599 | ]); 600 | 601 | // Connection should still exist after next send() call 602 | server.send(false).ok(); 603 | assert!(server.connection(&ConnectionID(151521030)).is_ok()); 604 | 605 | // But should be gone after second to next send() call 606 | server.send(false).ok(); 607 | assert!(server.connection(&ConnectionID(151521030)).is_err()); 608 | 609 | // Close via connection handle 610 | server.connection(&ConnectionID(84214017)).unwrap().close(); 611 | 612 | // Connection should still be there during closing threshold 613 | assert_eq!(server_events(&mut server), vec![]); 614 | 615 | // Expect connection to be dropped after closing threshold 616 | thread::sleep(Duration::from_millis(165)); 617 | assert_eq!(server_events(&mut server), vec![ 618 | ServerEvent::ConnectionClosed(ConnectionID(84214017), false) 619 | ]); 620 | 621 | } 622 | 623 | #[test] 624 | fn test_server_connection_loss() { 625 | 626 | let mut server = Server::::new(Config { 627 | connection_drop_threshold: Duration::from_millis(100), 628 | .. Config::default() 629 | }); 630 | server.listen("127.0.0.1:1234").ok(); 631 | 632 | // Accept a incoming connection 633 | server.socket().unwrap().mock_receive(vec![ 634 | ("255.1.1.1:1000", vec![ 635 | 1, 2, 3, 4, 636 | 9, 8, 7, 6, 637 | 0, 638 | 0, 639 | 0, 0, 0, 0 640 | ]) 641 | ]); 642 | 643 | assert_eq!(server_events(&mut server), vec![ 644 | ServerEvent::Connection(ConnectionID(151521030)) 645 | ]); 646 | 647 | assert!(server.connection(&ConnectionID(151521030)).is_ok()); 648 | assert_eq!(server.connections().keys().collect::>(), vec![&ConnectionID(151521030)]); 649 | 650 | // Let the connection attempt time out 651 | thread::sleep(Duration::from_millis(200)); 652 | 653 | let events = server_events(&mut server); 654 | 655 | // Connection should still be there when fetching the events 656 | assert_eq!(events, vec![ServerEvent::ConnectionLost(ConnectionID(151521030), true)]); 657 | assert!(server.connection(&ConnectionID(151521030)).is_ok()); 658 | assert_eq!(server.connections().len(), 1); 659 | 660 | 661 | // But connection be gone after next send() call 662 | server.send(false).ok(); 663 | assert!(server.connection(&ConnectionID(151521030)).is_err()); 664 | assert_eq!(server.connections().len(), 0); 665 | 666 | // We expect no additional packets to be send once the connection was lost 667 | server.socket().unwrap().assert_sent_none(); 668 | 669 | } 670 | 671 | #[test] 672 | #[cfg(target_os = "linux")] 673 | fn test_server_flush_auto_delay() { 674 | 675 | let mut server = Server::::new(Config::default()); 676 | server.listen("127.0.0.1:1234").ok(); 677 | 678 | let start = Instant::now(); 679 | for _ in 0..5 { 680 | server.accept_receive().ok(); 681 | server.send(true).ok(); 682 | } 683 | assert_millis_since!(start, 167, 33); 684 | 685 | } 686 | 687 | #[test] 688 | #[cfg(target_os = "linux")] 689 | fn test_server_auto_delay_with_load() { 690 | 691 | let mut server = Server::::new(Config::default()); 692 | server.listen("127.0.0.1:1234").ok(); 693 | 694 | // Without load 695 | let start = Instant::now(); 696 | for _ in 0..10 { 697 | server.accept_receive().ok(); 698 | server.send(true).ok(); 699 | } 700 | 701 | assert_millis_since!(start, 330, 16); 702 | 703 | // With load 704 | let start = Instant::now(); 705 | for _ in 0..10 { 706 | server.accept_receive().ok(); 707 | thread::sleep(Duration::from_millis(10)); 708 | server.send(true).ok(); 709 | } 710 | 711 | assert_millis_since!(start, 330, 16); 712 | 713 | // With more load 714 | let start = Instant::now(); 715 | for _ in 0..10 { 716 | server.accept_receive().ok(); 717 | thread::sleep(Duration::from_millis(20)); 718 | server.send(true).ok(); 719 | } 720 | 721 | assert_millis_since!(start, 330, 16); 722 | 723 | } 724 | 725 | // TODO test congestion state changes 726 | // TODO test packet lost events 727 | 728 | 729 | // Helpers -------------------------------------------------------------------- 730 | fn server_events(server: &mut Server) -> Vec { 731 | server.send(false).ok(); 732 | let mut events = Vec::new(); 733 | while let Ok(event) = server.accept_receive() { 734 | events.push(event); 735 | } 736 | events 737 | } 738 | 739 | -------------------------------------------------------------------------------- /src/traits/mod.rs: -------------------------------------------------------------------------------- 1 | // Modules -------------------------------------------------------------------- 2 | mod packet_modifier; 3 | mod rate_limiter; 4 | mod socket; 5 | 6 | 7 | // Re-Exports ----------------------------------------------------------------- 8 | pub use self::packet_modifier::PacketModifier; 9 | pub use self::rate_limiter::RateLimiter; 10 | pub use self::socket::Socket; 11 | 12 | -------------------------------------------------------------------------------- /src/traits/packet_modifier.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2017 Ivo Wetzel 2 | 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | // STD Dependencies ----------------------------------------------------------- 10 | use std::fmt; 11 | 12 | 13 | // Internal Dependencies ------------------------------------------------------ 14 | use super::super::Config; 15 | 16 | 17 | /// Trait describing optional per-packet payload modification logic. 18 | pub trait PacketModifier { 19 | 20 | /// Method that constructs a new packet modifier using the provided configuration. 21 | fn new(Config) -> Self where Self: Sized; 22 | 23 | /// Method that is called for payload modification before a packet is send 24 | /// over a connection's underlying socket. 25 | /// 26 | /// The default implementation does not actually perform any kind of 27 | /// modification and leaves the payload to be send untouched. 28 | fn outgoing(&mut self, _: &[u8]) -> Option> { 29 | None 30 | } 31 | 32 | /// Method that is called for payload modification purposes after a packet 33 | /// is received over a connection's underlying socket. 34 | /// 35 | /// The default implementation does not actually perform any kind of 36 | /// modification and returns leaves received payload untouched. 37 | fn incoming(&mut self, _: &[u8]) -> Option> { 38 | None 39 | } 40 | 41 | } 42 | 43 | impl fmt::Debug for PacketModifier { 44 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 45 | write!(f, "PacketModifier") 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /src/traits/rate_limiter.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2017 Ivo Wetzel 2 | 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | // STD Dependencies ----------------------------------------------------------- 10 | use std::fmt; 11 | 12 | 13 | // Internal Dependencies ------------------------------------------------------ 14 | use super::super::Config; 15 | 16 | 17 | /// Trait describing a network congestion avoidance algorithm. 18 | pub trait RateLimiter { 19 | 20 | /// Method that constructs a new rate limiter using the provided configuration. 21 | fn new(Config) -> Self where Self: Sized; 22 | 23 | /// Method implementing a congestion avoidance algorithm based on round 24 | /// trip time and packet loss. 25 | fn update(&mut self, rtt: u32, packet_loss: f32); 26 | 27 | /// Method that should return `true` in case the connection is currently 28 | /// considered congested and should reduce the number of packets it sends 29 | /// per second. 30 | fn congested(&self) -> bool; 31 | 32 | /// Method that returns whether a connection should be currently sending 33 | /// packets or not. 34 | fn should_send(&self) -> bool; 35 | 36 | /// Method that resets any internal state of the rate limiter. 37 | fn reset(&mut self); 38 | 39 | } 40 | 41 | impl fmt::Debug for RateLimiter { 42 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 43 | write!(f, "RateLimiter") 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /src/traits/socket.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2016 Ivo Wetzel 2 | 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | // STD Dependencies ----------------------------------------------------------- 10 | use std::net; 11 | use std::fmt; 12 | use std::io::Error; 13 | use std::sync::mpsc::TryRecvError; 14 | 15 | /// Trait describing a non-blocking low latency socket. 16 | pub trait Socket: fmt::Debug { 17 | 18 | /// Method that tries to bind a new socket at the specified address. 19 | fn new(T, usize) -> Result where Self: Sized; 20 | 21 | /// Method that attempts to return a incoming packet on this socket without 22 | /// blocking. 23 | fn try_recv(&mut self) -> Result<(net::SocketAddr, Vec), TryRecvError>; 24 | 25 | /// Method sending data on the socket to the given address. On success, 26 | /// returns the number of bytes written. 27 | fn send_to( 28 | &mut self, data: &[u8], addr: net::SocketAddr) 29 | 30 | -> Result; 31 | 32 | /// Method returning the address of the actual, underlying socket. 33 | fn local_addr(&self) -> Result; 34 | 35 | } 36 | 37 | --------------------------------------------------------------------------------