├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── question-or-other-issue.md ├── resources │ ├── img │ │ └── Connection Handshake.png │ └── mddoc │ │ ├── Raknet.md │ │ ├── protocol │ │ └── README.md │ │ └── reliability.md └── workflows │ └── ci.yml ├── .gitignore ├── Cargo.toml ├── LICENSE.md ├── README.md ├── coverage.py ├── examples ├── README.md ├── async-std │ ├── client │ │ ├── .cargo │ │ │ └── config.toml │ │ ├── Cargo.toml │ │ └── src │ │ │ └── main.rs │ └── server │ │ ├── .cargo │ │ └── config.toml │ │ ├── Cargo.toml │ │ └── src │ │ └── main.rs └── tokio │ ├── client │ ├── Cargo.toml │ └── src │ │ └── main.rs │ ├── proxy │ ├── Cargo.toml │ └── src │ │ └── main.rs │ └── server │ ├── .cargo │ └── config.toml │ ├── Cargo.toml │ └── src │ └── main.rs ├── resources ├── header.css └── header.html ├── rust-toolchain ├── src ├── client │ ├── discovery.rs │ ├── handshake.rs │ ├── mod.rs │ └── util.rs ├── connection │ ├── controller │ │ ├── mod.rs │ │ └── window.rs │ ├── mod.rs │ ├── queue │ │ ├── mod.rs │ │ ├── recv.rs │ │ └── send.rs │ └── state.rs ├── error │ ├── client.rs │ ├── connection.rs │ ├── mod.rs │ └── server.rs ├── lib.rs ├── notify │ ├── async_std.rs │ ├── mod.rs │ └── tokio.rs ├── protocol │ ├── ack.rs │ ├── frame.rs │ ├── magic.rs │ ├── mcpe │ │ ├── mod.rs │ │ └── motd.rs │ ├── mod.rs │ ├── packet │ │ ├── mod.rs │ │ ├── offline.rs │ │ └── online.rs │ └── reliability.rs ├── server │ ├── event.rs │ └── mod.rs └── util │ ├── debug.rs │ └── mod.rs └── tests └── fragment_queue.rs /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Submit an issue about undefined behaviour or abnormalities in the software. 4 | title: "[BUG]" 5 | labels: Bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Server versions (please complete the following information):** 27 | - commit: [6b7a6cf5110f6d90c246133430793a1ce4c1e1f0] 28 | - Version: 0.0.1-rc.1 29 | 30 | **Additional context** 31 | Add any other context about the problem here. 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question-or-other-issue.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question or Other Issue 3 | about: Submit an issue regarding the software, or a question you have that may affect 4 | others. 5 | title: "[QUESTION]" 6 | labels: Question 7 | assignees: '' 8 | 9 | --- 10 | 11 | **Issue / Question:** 12 | A concise description or question describing the issue. 13 | 14 | **Proposals / Details:** 15 | A list of possible proposals to fix the issue or resolve the question, or a description providing better context to the question. 16 | -------------------------------------------------------------------------------- /.github/resources/img/Connection Handshake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NetrexMC/RakNet/799a339d53928d33dd274a523fa8ae8e0c0dbf02/.github/resources/img/Connection Handshake.png -------------------------------------------------------------------------------- /.github/resources/mddoc/Raknet.md: -------------------------------------------------------------------------------- 1 | ## RakNet 2 | 3 | RakNet doesn't have a lot of resources on it's internal functionality, and to better understand it I've written these docs. 4 | 5 | RakNet is composed and derived of multiple parts, so for simplicity I've narrowed it down into the following parts: 6 | 7 | - [Protocol](./protocol/README.md) 8 | 9 | - [Connection Handshake](./protocol/handshake.md) 10 | 11 | - [Datagrams](./protocol/datagrams) 12 | 13 | - [Packet Reliability](./reliability.md) 14 | 15 | - [Congestion Control](./congestion.md) 16 | 17 | - [Plugins]() 18 | 19 | - [Server]() 20 | 21 | - [Client]() 22 | 23 | It's important to note that this documentation does conceptualize and take a different approach from the original RakNet implementation, however it does not deviate from the behavior of RakNet; rather providing a basis on how I believe it should be implemented. 24 | -------------------------------------------------------------------------------- /.github/resources/mddoc/protocol/README.md: -------------------------------------------------------------------------------- 1 | # RakNet Protocol 2 | -------------------------------------------------------------------------------- /.github/resources/mddoc/reliability.md: -------------------------------------------------------------------------------- 1 | # Reliability 2 | 3 | Reliability within RakNet specifies when a packet should arrive and how it should be treated. The term "Reliability" within RakNet generally refers to the following possible states of a packet: 4 | 5 | - **Unreliable**. The packet sent is not reliable and not important. Later packets will make up for it's loss. This is the same as a regular UDP packet with the added benefit that duplicates are discarded. 6 | 7 | - **UnreliableSequenced**. This packet is not necessarily important, if it arrives later than another packet, you should discard it. Otherwise you can treat it normally. *This reliability is generally not used* 8 | 9 | - **Reliable**. The packet should be acknow 10 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | test-formatting: 6 | name: Code style check 7 | runs-on: ubuntu-latest 8 | if: "!contains(github.event.head_commit.message, '-skip')" 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Run fmt test 12 | uses: actions-rs/cargo@v1.0.1 13 | with: 14 | command: fmt 15 | args: -- --check 16 | test-stable: 17 | name: Run tests on Stable 18 | runs-on: ubuntu-latest 19 | if: "contains(github.event.head_commit.message, '-stable')" 20 | steps: 21 | - uses: actions/checkout@v2 22 | - name: Setup stable toolchain 23 | uses: actions-rs/toolchain@v1.0.6 24 | with: 25 | toolchain: stable 26 | - name: Run test 27 | uses: actions-rs/cargo@v1.0.1 28 | with: 29 | command: test 30 | toolchain: stable 31 | test-beta: 32 | name: Run tests on Beta 33 | runs-on: ubuntu-latest 34 | if: "contains(github.event.head_commit.message, '-beta')" 35 | steps: 36 | - uses: actions/checkout@v2 37 | - name: Setup beta toolchain 38 | uses: actions-rs/toolchain@v1.0.6 39 | with: 40 | toolchain: beta 41 | - name: Run test 42 | uses: actions-rs/cargo@v1.0.1 43 | with: 44 | command: test 45 | toolchain: beta 46 | test-nightly: 47 | name: Run tests on Nightly 48 | runs-on: ubuntu-latest 49 | if: "!contains(github.event.head_commit.message, '-skip')" 50 | steps: 51 | - uses: actions/checkout@v2 52 | - name: Setup nightly toolchain 53 | uses: actions-rs/toolchain@v1.0.6 54 | with: 55 | toolchain: nightly 56 | - name: Run test 57 | uses: actions-rs/cargo@v1.0.1 58 | with: 59 | command: test 60 | toolchain: nightly 61 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | target 3 | 4 | # Ignore lock files 5 | Cargo.lock 6 | 7 | *.old/ 8 | *.profraw -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rak-rs" 3 | version = "0.3.3" 4 | authors = ["John Bergman "] 5 | edition = "2021" 6 | description = "A fully functional RakNet implementation in pure rust, asynchronously driven." 7 | license = "Apache-2.0" 8 | repository = "https://github.com/NetrexMC/RakNet" 9 | 10 | [package.metadata.docs.rs] 11 | rustdoc-args = ["--html-in-header", "./resources/header.html"] 12 | 13 | [features] 14 | default = [ "async_std" ] 15 | # default = ["async_tokio" ] 16 | mcpe = [] 17 | debug = [] 18 | debug_all = [] 19 | debug_buffers = [] 20 | async_std = [ "async-std" ] 21 | async_tokio = [ "tokio" ] 22 | 23 | [dependencies] 24 | rand = "0.8.3" 25 | binary-util = "0.3.4" 26 | tokio = { version = "1.28.2", features = ["full"], optional = true } 27 | byteorder = "1.4.3" 28 | futures = "0.3.19" 29 | futures-executor = "0.3.19" 30 | async-std = { version = "1.12.0", optional = true, features = [ "unstable" ] } 31 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 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 | 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | 100 | stating that You changed the files; and 101 | 102 | (c) You must retain, in the Source form of any Derivative Works 103 | 104 | that You distribute, all copyright, patent, trademark, and 105 | attribution notices from the Source form of the Work, 106 | excluding those notices that do not pertain to any part of 107 | the Derivative Works; and 108 | 109 | (d) If the Work includes a "NOTICE" text file as part of its 110 | 111 | distribution, then any Derivative Works that You distribute must 112 | include a readable copy of the attribution notices contained 113 | within such NOTICE file, excluding those notices that do not 114 | pertain to any part of the Derivative Works, in at least one 115 | of the following places: within a NOTICE text file distributed 116 | as part of the Derivative Works; within the Source form or 117 | documentation, if provided along with the Derivative Works; or, 118 | within a display generated by the Derivative Works, if and 119 | wherever such third-party notices normally appear. The contents 120 | of the NOTICE file are for informational purposes only and 121 | do not modify the License. You may add Your own attribution 122 | notices within Derivative Works that You distribute, alongside 123 | or as an addendum to the NOTICE text from the Work, provided 124 | that such additional attribution notices cannot be construed 125 | as modifying the License. 126 | 127 | You may add Your own copyright statement to Your modifications and 128 | may provide additional or different license terms and conditions 129 | for use, reproduction, or distribution of Your modifications, or 130 | for any such Derivative Works as a whole, provided Your use, 131 | reproduction, and distribution of the Work otherwise complies with 132 | the conditions stated in this License. 133 | 134 | 5. Submission of Contributions. Unless You explicitly state otherwise, 135 | any Contribution intentionally submitted for inclusion in the Work 136 | by You to the Licensor shall be under the terms and conditions of 137 | this License, without any additional terms or conditions. 138 | Notwithstanding the above, nothing herein shall supersede or modify 139 | the terms of any separate license agreement you may have executed 140 | with Licensor regarding such Contributions. 141 | 142 | 6. Trademarks. This License does not grant permission to use the trade 143 | names, trademarks, service marks, or product names of the Licensor, 144 | except as required for reasonable and customary use in describing the 145 | origin of the Work and reproducing the content of the NOTICE file. 146 | 147 | 7. Disclaimer of Warranty. Unless required by applicable law or 148 | agreed to in writing, Licensor provides the Work (and each 149 | Contributor provides its Contributions) on an "AS IS" BASIS, 150 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 151 | implied, including, without limitation, any warranties or conditions 152 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 153 | PARTICULAR PURPOSE. You are solely responsible for determining the 154 | appropriateness of using or redistributing the Work and assume any 155 | risks associated with Your exercise of permissions under this License. 156 | 157 | 8. Limitation of Liability. In no event and under no legal theory, 158 | whether in tort (including negligence), contract, or otherwise, 159 | unless required by applicable law (such as deliberate and grossly 160 | negligent acts) or agreed to in writing, shall any Contributor be 161 | liable to You for damages, including any direct, indirect, special, 162 | incidental, or consequential damages of any character arising as a 163 | result of this License or out of the use or inability to use the 164 | Work (including but not limited to damages for loss of goodwill, 165 | work stoppage, computer failure or malfunction, or any and all 166 | other commercial damages or losses), even if such Contributor 167 | has been advised of the possibility of such damages. 168 | 169 | 9. Accepting Warranty or Additional Liability. While redistributing 170 | the Work or Derivative Works thereof, You may choose to offer, 171 | and charge a fee for, acceptance of support, warranty, indemnity, 172 | or other liability obligations and/or rights consistent with this 173 | License. However, in accepting such obligations, You may act only 174 | on Your own behalf and on Your sole responsibility, not on behalf 175 | of any other Contributor, and only if You agree to indemnify, 176 | defend, and hold each Contributor harmless for any liability 177 | incurred by, or claims asserted against, such Contributor by reason 178 | of your accepting any such warranty or additional liability. 179 | 180 | END OF TERMS AND CONDITIONS 181 | 182 | Copyright 2021 Suruloon Studios 183 | 184 | Licensed under the Apache License, Version 2.0 (the "License"); 185 | you may not use this file except in compliance with the License. 186 | You may obtain a copy of the License at 187 | 188 | http://www.apache.org/licenses/LICENSE-2.0 189 | 190 | Unless required by applicable law or agreed to in writing, software 191 | distributed under the License is distributed on an "AS IS" BASIS, 192 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 193 | See the License for the specific language governing permissions and 194 | limitations under the License. 195 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rak-rs 2 | 3 | A fully functional RakNet implementation in pure rust, asynchronously driven. 4 | 5 | 6 | 7 | ## Getting Started 8 | 9 | RakNet (rak-rs) is available on [crates.io](https://crates.io/crates/rak-rs), to use it, add the following to your `Cargo.toml`: 10 | 11 | ```toml 12 | [dependencies] 13 | rak-rs = "0.3.3" 14 | ``` 15 | 16 | ## Features 17 | 18 | This RakNet implementation comes with 3 primary features, `async_std`, `async_tokio` and `mcpe`. However, by default, only `async_std` is enabled, and `mcpe` requires you to modify your `Cargo.toml`. 19 | 20 | If you wish to use these features, add them to your `Cargo.toml` as seen below: 21 | 22 | ```toml 23 | [dependencies] 24 | rak-rs = { version = "0.3.3", default-features = false, features = [ "async_tokio", "mcpe" ] } 25 | ``` 26 | 27 | 28 | 29 | rak-rs also provides the following modules: 30 | 31 | - [`rak_rs::client`](https://docs.rs/rak-rs/latest/rak-rs/client) - A client implementation of RakNet, allowing you to connect to a RakNet server. 32 | - [`rak_rs::connection`](https://docs.rs/rak-rs/latest/rak-rs/client) - A bare-bones implementation of a Raknet peer, this is mainly used for types. 33 | - [`rak_rs::error`](https://docs.rs/rak-rs/latest/rak-rs/error) - A module with errors that both the Client and Server can respond with. 34 | - [`rak_rs::protocol`](https://docs.rs/rak-rs/latest/rak-rs/protocol) - A lower level implementation of RakNet, responsible for encoding and decoding packets. 35 | - [`rak_rs::server`](https://docs.rs/rak-rs/latest/rak-rs/server) - The base server implementation of RakNet. 36 | - [`rak_rs::util`](https://docs.rs/rak-rs/latest/rak-rs/utils) - General utilities used within `rak-rs`. 37 | 38 | # Client 39 | 40 | The `client` module provides a way for you to interact with RakNet servers with code. 41 | 42 | **Example:** 43 | 44 | ```rust 45 | use rak_rs::client::{Client, DEFAULT_MTU}; 46 | use std::net::ToSocketAddrs; 47 | 48 | #[async_std::main] 49 | async fn main() { 50 | let version: u8 = 10; 51 | let mut client = Client::new(version, DEFAULT_MTU); 52 | 53 | client.connect("my_server.net:19132").await.unwrap(); 54 | 55 | // receive packets 56 | loop { 57 | let packet = client.recv().await.unwrap(); 58 | 59 | println!("Received a packet! {:?}", packet); 60 | 61 | client.send_ord(vec![254, 0, 1, 1], Some(1)); 62 | } 63 | } 64 | 65 | ``` 66 | 67 | # Server 68 | 69 | A RakNet server implementation in pure rust. 70 | 71 | **Example:** 72 | 73 | ```rust 74 | use rakrs::connection::Connection; 75 | use rakrs::Listener; 76 | use rakrs:: 77 | 78 | #[async_std::main] 79 | async fn main() { 80 | let mut server = Listener::bind("0.0.0.0:19132").await.unwrap(); 81 | server.start().await.unwrap(); 82 | 83 | loop { 84 | let conn = server.accept().await; 85 | async_std::task::spawn(handle(conn.unwrap())); 86 | } 87 | } 88 | 89 | async fn handle(mut conn: Connection) { 90 | loop { 91 | // keeping the connection alive 92 | if conn.is_closed() { 93 | println!("Connection closed!"); 94 | break; 95 | } 96 | if let Ok(pk) = conn.recv().await { 97 | println!("Got a connection packet {:?} ", pk); 98 | } 99 | } 100 | } 101 | ``` 102 | -------------------------------------------------------------------------------- /coverage.py: -------------------------------------------------------------------------------- 1 | import os 2 | os.system("CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' LLVM_PROFILE_FILE='cargo-test-%p-%m.profraw' cargo test") 3 | os.system("gcov . --binary-path ./target/debug/deps -s . -t html --branch --ignore-not-existing --ignore ../* --ignore /* --ignore xtask/* --ignore */src/tests/* -o coverage/html") -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | **async-std:** 4 | - [client](/examples/async-std/client) 5 | - [server](/examples/async-std/server) -------------------------------------------------------------------------------- /examples/async-std/client/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | rustflags = ["--cfg", "tokio_unstable"] -------------------------------------------------------------------------------- /examples/async-std/client/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "client" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | async-std = { version = "1.12.0", features = [ "unstable", "attributes" ] } 10 | binary-util = "0.3.4" 11 | rak-rs = { path = "../../../", features = [ "debug", "debug_all", "async-std", "mcpe"]} -------------------------------------------------------------------------------- /examples/async-std/client/src/main.rs: -------------------------------------------------------------------------------- 1 | use rak_rs::client::{Client, DEFAULT_MTU}; 2 | use std::{net::ToSocketAddrs, vec}; 3 | 4 | #[async_std::main] 5 | async fn main() { 6 | let mut client = Client::new(11, DEFAULT_MTU); 7 | let mut addr = "zeqa.net:19132".to_socket_addrs().unwrap(); 8 | 9 | if let Err(e) = Client::ping("zeqa.net:19132").await { 10 | println!("Failed to ping server: {}", e); 11 | } 12 | if let Err(e) = client.connect(addr.next().unwrap()).await { 13 | // here you could attempt to retry, but in this case, we'll just exit 14 | println!("Failed to connect to server: {}", e); 15 | return; 16 | } 17 | 18 | client.send_ord(&[254, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 ], 0).await.unwrap(); 19 | 20 | loop { 21 | let pk = client.recv().await.unwrap(); 22 | println!("Received packet: {:?}", pk); 23 | client.send_ord(&vec![ 254, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 ], 1).await.unwrap(); 24 | } 25 | } -------------------------------------------------------------------------------- /examples/async-std/server/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | rustflags = ["--cfg", "tokio_unstable"] -------------------------------------------------------------------------------- /examples/async-std/server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "raknet-server-async-std" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | async-std = { version = "1.12.0", features = [ "attributes" ] } 10 | console-subscriber = "0.1.8" 11 | rak-rs = { path = "../../../", features = [ "debug", "debug_all", "mcpe", "async_std" ], default-features = false } 12 | # rak-rs = { path = "../../../", features = [ "mcpe" ] } 13 | -------------------------------------------------------------------------------- /examples/async-std/server/src/main.rs: -------------------------------------------------------------------------------- 1 | use rak_rs::connection::Connection; 2 | use rak_rs::mcpe::motd::Gamemode; 3 | use rak_rs::Listener; 4 | 5 | #[async_std::main] 6 | async fn main() { 7 | // console_subscriber::init(); 8 | let mut server = Listener::bind("0.0.0.0:19133").await.unwrap(); 9 | server.motd.name = "RakNet Rust (async-std)!".to_string(); 10 | server.motd.gamemode = Gamemode::Survival; 11 | server.motd.player_count = 69420; 12 | server.motd.player_max = 69424; 13 | 14 | server.start().await.unwrap(); 15 | 16 | loop { 17 | let conn = server.accept().await; 18 | async_std::task::spawn(handle(conn.unwrap())); 19 | } 20 | } 21 | 22 | async fn handle(mut conn: Connection) { 23 | let mut f = std::sync::Arc::new(conn); 24 | loop { 25 | // keeping the connection alive 26 | if f.is_closed().await { 27 | println!("Connection closed!"); 28 | break; 29 | } 30 | 31 | if let Ok(pk) = std::sync::Arc::::get_mut(&mut f).unwrap().recv().await { 32 | println!("(RAKNET RECIEVE SIDE) Got a connection packet {:?} ", pk); 33 | f.send(&[254, 12, 143, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], true).await.unwrap(); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /examples/tokio/client/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "client" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | rak-rs = { path = "../../../", features = [ "async_tokio", "debug", "debug_all", "debug_buffers" ]} 10 | binary-util = "0.3.4" 11 | tokio = { version= "1.36.0", features = [ "full" ] } 12 | -------------------------------------------------------------------------------- /examples/tokio/client/src/main.rs: -------------------------------------------------------------------------------- 1 | use rak_rs::{ 2 | client::{Client, DEFAULT_MTU} 3 | }; 4 | 5 | #[tokio::main] 6 | async fn main() { 7 | let mut client = Client::new(11, DEFAULT_MTU) 8 | .with_timeout(20) 9 | .with_handshake_timeout(3); 10 | 11 | for _ in 0..3 { 12 | if let Err(e) = client.connect("zeqa.net:19132").await { 13 | println!("Failed to connect: {}, trying again...", e); 14 | } else { 15 | break; 16 | } 17 | } 18 | 19 | if !client.is_connected().await { 20 | println!("Failed to connect to server after 3 attempts. Exiting..."); 21 | return; 22 | } 23 | 24 | client 25 | .send_ord(&[254, 6, 193, 1, 0, 0, 2, 118], 0) 26 | .await 27 | .unwrap(); 28 | 29 | loop { 30 | let packet = client.recv().await.unwrap(); 31 | if packet[0] == 0xfe { 32 | println!("Received (Game): {:?}", packet); 33 | } else { 34 | println!("Received: {:?}", packet); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /examples/tokio/proxy/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "proxy" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | anyhow = "1.0.81" 8 | async-std = { version = "1.12.0", features = [ "attributes" ] } 9 | rak-rs = { path = "../../../", features = [ "mcpe", "async_tokio" ], default-features = false } 10 | tokio = "1.23.0" 11 | -------------------------------------------------------------------------------- /examples/tokio/proxy/src/main.rs: -------------------------------------------------------------------------------- 1 | use rak_rs::{Listener, Motd}; 2 | use rak_rs::client::{Client, DEFAULT_MTU}; 3 | 4 | 5 | #[tokio::main] 6 | async fn main() -> anyhow::Result<()> { 7 | let mut listener = Listener::bind("0.0.0.0:19132").await.unwrap(); 8 | 9 | // get address from process args 10 | let addr = match std::env::args().nth(1) { 11 | Some(a) => { 12 | a 13 | }, 14 | None => { 15 | println!("Usage: {}
", std::env::args().nth(0).unwrap()); 16 | return Ok(()); 17 | } 18 | }; 19 | 20 | println!("Starting proxy for {}", addr); 21 | 22 | // connect to server 23 | match Client::ping(addr.clone()).await { 24 | Err(e) => { 25 | println!("Could not identify remote: {}", e); 26 | return Ok(()); 27 | } 28 | Ok(pong) => { 29 | println!("Found server server: {:?}", pong.motd.write()); 30 | listener.motd = Motd::new(listener.id, "19132"); 31 | listener.motd.player_count = pong.motd.player_count; 32 | listener.motd.player_max = pong.motd.player_max; 33 | listener.motd.name = pong.motd.name; 34 | listener.motd.gamemode = pong.motd.gamemode; 35 | } 36 | } 37 | 38 | listener.start().await?; 39 | 40 | loop { 41 | let mut conn = listener.accept().await?; 42 | tokio::spawn(async move { 43 | // first we try to connect to the server with a new client 44 | let addr = std::env::args().nth(1).unwrap(); 45 | let mut client = Client::new(11, DEFAULT_MTU); 46 | if let Err(e) = client.connect(addr).await { 47 | println!("Could not connect to remote: {}", e); 48 | return; 49 | } 50 | 51 | // now we just forward patckets from the client to the server 52 | loop { 53 | tokio::select! { 54 | Ok(packet) = conn.recv() => { 55 | println!("S->C: {:?}", packet); 56 | if let Err(e) = client.send_ord(&packet[..], 0).await { 57 | println!("Could not send packet to remote: {}", e); 58 | return; 59 | } 60 | } 61 | Ok(packet) = client.recv() => { 62 | println!("C->S: {:?}", packet); 63 | if let Err(e) = conn.send(&packet[..], true).await { 64 | println!("Could not send packet to client: {}", e); 65 | return; 66 | } 67 | } 68 | } 69 | } 70 | 71 | }); 72 | } 73 | Ok(()) 74 | } -------------------------------------------------------------------------------- /examples/tokio/server/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | rustflags = ["--cfg", "tokio_unstable"] -------------------------------------------------------------------------------- /examples/tokio/server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "raknet-test" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | async-std = { version = "1.12.0", features = [ "attributes" ] } 10 | console-subscriber = "0.1.8" 11 | rak-rs = { path = "../../../", features = [ "debug", "debug_all", "mcpe", "async_tokio" ], default-features = false } 12 | tokio = "1.23.0" 13 | -------------------------------------------------------------------------------- /examples/tokio/server/src/main.rs: -------------------------------------------------------------------------------- 1 | use rak_rs::Listener; 2 | use rak_rs::Motd; 3 | use rak_rs::connection::Connection; 4 | use rak_rs::mcpe; 5 | use rak_rs::mcpe::motd::Gamemode; 6 | use rak_rs::server::event::ServerEvent; 7 | use rak_rs::server::event::ServerEventResponse; 8 | 9 | 10 | #[tokio::main] 11 | async fn main() { 12 | console_subscriber::init(); 13 | let mut server = Listener::bind("0.0.0.0:19132").await.unwrap(); 14 | server.motd.name = "RakNet Rust (tokio)!".to_string(); 15 | server.motd.gamemode = Gamemode::Survival; 16 | 17 | server.start().await.unwrap(); 18 | 19 | loop { 20 | let conn = server.accept().await; 21 | tokio::task::spawn(handle(conn.unwrap())); 22 | } 23 | } 24 | 25 | async fn handle(mut conn: Connection) { 26 | loop { 27 | // keeping the connection alive 28 | if conn.is_closed().await { 29 | println!("Connection closed!"); 30 | break; 31 | } 32 | if let Ok(pk) = conn.recv().await { 33 | println!("(RAKNET RECIEVE SIDE) Got a connection packet {:?} ", pk); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /resources/header.css: -------------------------------------------------------------------------------- 1 | 2 | .warning-2 { 3 | background: rgba(255,240,76,0.34) !important; 4 | padding: 0.75em; 5 | border-left: 2px solid #fce811; 6 | } 7 | 8 | .warning-2 code { 9 | background: rgba(211,201,88,0.64) !important; 10 | } 11 | 12 | .notice-2 { 13 | background: rgba(76, 240, 255, 0.629) !important; 14 | padding: 0.75em; 15 | border-left: 2px solid #4c96ff; 16 | } 17 | 18 | .notice-2 code { 19 | background: rgba(88, 211, 255, 0.64) !important; 20 | } -------------------------------------------------------------------------------- /resources/header.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /rust-toolchain: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly" 3 | components = [ "rustfmt" ] 4 | profile = "minimal" -------------------------------------------------------------------------------- /src/client/discovery.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | use std::sync::Mutex; 3 | use std::time::Duration; 4 | 5 | #[cfg(feature = "async_std")] 6 | use async_std::{ 7 | future::timeout, 8 | future::Future, 9 | net::UdpSocket, 10 | task::{self, Context, Poll, Waker}, 11 | }; 12 | 13 | use binary_util::interfaces::Reader; 14 | use binary_util::io::ByteReader; 15 | 16 | #[cfg(feature = "async_tokio")] 17 | use std::future::Future; 18 | #[cfg(feature = "async_tokio")] 19 | use std::task::{Context, Poll, Waker}; 20 | #[cfg(feature = "async_tokio")] 21 | use tokio::{ 22 | net::UdpSocket, 23 | task::{self}, 24 | time::timeout, 25 | }; 26 | 27 | use crate::match_ids; 28 | use crate::protocol::packet::offline::IncompatibleProtocolVersion; 29 | use crate::protocol::packet::offline::OpenConnectReply; 30 | use crate::protocol::packet::offline::OpenConnectRequest; 31 | use crate::rakrs_debug; 32 | 33 | use super::util::send_packet; 34 | 35 | macro_rules! update_state { 36 | ($done: expr, $shared_state: expr, $state: expr) => {{ 37 | let mut state = $shared_state.lock().unwrap(); 38 | state.status = $state; 39 | state.done = true; 40 | if let Some(waker) = state.waker.take() { 41 | waker.wake(); 42 | } 43 | return; 44 | }}; 45 | ($shared_state: expr, $state: expr) => {{ 46 | let mut state = $shared_state.lock().unwrap(); 47 | state.status = $state; 48 | if let Some(waker) = state.waker.take() { 49 | waker.wake(); 50 | } 51 | }}; 52 | } 53 | 54 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 55 | pub enum DiscoveryStatus { 56 | /// The discovery has been initiated. 57 | /// This only occurs when the discovery is first created. 58 | Initiated, 59 | /// The discovery has been completed. 60 | /// We know the MTU size. 61 | Discovered(u16), 62 | /// We failed to discover the MTU size. 63 | /// This is probably cause the server is offline. 64 | Failed, 65 | /// The discovery has been canceled because the client is on a different protocol version. 66 | IncompatibleVersion, 67 | /// We're still trying to find the MTU size. 68 | Undiscovered, 69 | } 70 | 71 | impl std::fmt::Display for DiscoveryStatus { 72 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 73 | write!( 74 | f, 75 | "{}", 76 | match self { 77 | DiscoveryStatus::Initiated => "Initiated", 78 | DiscoveryStatus::Discovered(_) => "Discovered", 79 | DiscoveryStatus::Failed => "Failed", 80 | DiscoveryStatus::IncompatibleVersion => "IncompatibleVersion", 81 | DiscoveryStatus::Undiscovered => "Undiscovered", 82 | } 83 | ) 84 | } 85 | } 86 | 87 | #[derive(Debug, Clone)] 88 | pub struct MtuDiscoveryMeta { 89 | pub id: i64, 90 | pub version: u8, 91 | pub mtu: u16, 92 | pub timeout: u16, 93 | } 94 | 95 | struct DiscoveryState { 96 | status: DiscoveryStatus, 97 | waker: Option, 98 | } 99 | 100 | pub struct MtuDiscovery { 101 | state: Arc>, 102 | } 103 | 104 | impl MtuDiscovery { 105 | pub fn new(socket: Arc, discovery_info: MtuDiscoveryMeta) -> Self { 106 | let state = Arc::new(Mutex::new(DiscoveryState { 107 | status: DiscoveryStatus::Initiated, 108 | waker: None, 109 | })); 110 | 111 | let shared_state = state.clone(); 112 | 113 | task::spawn(async move { 114 | // try to use the mtu provided by the user 115 | let valid_mtus: Vec = vec![discovery_info.mtu, 1506, 1492, 1400, 1200, 576]; 116 | // remove any mtu size that is larger than discovery_info.mtu 117 | // let valid_mtus: Vec = valid_mtus 118 | // .into_iter() 119 | // .filter(|mtu| *mtu <= discovery_info.mtu) 120 | // .collect(); 121 | for mtu in valid_mtus.iter() { 122 | // send a connection request 123 | let request = OpenConnectRequest { 124 | protocol: discovery_info.version, 125 | mtu_size: *mtu, 126 | }; 127 | 128 | if !send_packet(&socket, request.into()).await { 129 | rakrs_debug!( 130 | true, 131 | "[CLIENT] Failed sending OpenConnectRequest to server!" 132 | ); 133 | update_state!(shared_state, DiscoveryStatus::Undiscovered); 134 | // this is ok! we'll just try the next mtu 135 | continue; 136 | }; 137 | 138 | let reply = match_ids!( 139 | socket.clone(), 140 | discovery_info.timeout.into(), 141 | // Open connect Reply 142 | 0x06, 143 | // Incompatible protocol version 144 | 0x19 145 | ); 146 | 147 | if reply.is_none() { 148 | update_state!(shared_state, DiscoveryStatus::Undiscovered); 149 | // break; 150 | continue; 151 | } 152 | 153 | // this is being triggered, why not returning??? 154 | if let Ok(pk) = IncompatibleProtocolVersion::read(&mut ByteReader::from( 155 | &reply.clone().unwrap()[1..], 156 | )) { 157 | rakrs_debug!( 158 | true, 159 | "[CLIENT] Protocol mismatch. Server={}, Client={}", 160 | pk.protocol, 161 | discovery_info.version 162 | ); 163 | update_state!(shared_state, DiscoveryStatus::IncompatibleVersion); 164 | return; 165 | } 166 | 167 | let open_reply = 168 | OpenConnectReply::read(&mut ByteReader::from(&reply.unwrap()[1..])); 169 | 170 | if open_reply.is_err() { 171 | update_state!(shared_state, DiscoveryStatus::Failed); 172 | return; 173 | } 174 | 175 | if let Ok(response) = open_reply { 176 | rakrs_debug!( 177 | true, 178 | "[CLIENT] Received OpenConnectReply from server! mtu={}", 179 | response.mtu_size 180 | ); 181 | let mtu = response.mtu_size; 182 | update_state!(shared_state, DiscoveryStatus::Discovered(mtu)); 183 | return; 184 | } else { 185 | update_state!(shared_state, DiscoveryStatus::Undiscovered); 186 | } 187 | } 188 | 189 | update_state!(shared_state, DiscoveryStatus::Failed); 190 | }); 191 | 192 | Self { state } 193 | } 194 | } 195 | 196 | impl Future for MtuDiscovery { 197 | type Output = DiscoveryStatus; 198 | 199 | fn poll(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 200 | let mut state = self.state.lock().unwrap(); 201 | match state.status { 202 | DiscoveryStatus::Failed 203 | | DiscoveryStatus::IncompatibleVersion 204 | | DiscoveryStatus::Discovered(_) => Poll::Ready(state.status), 205 | _ => { 206 | state.waker = Some(cx.waker().clone()); 207 | Poll::Pending 208 | } 209 | } 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /src/client/handshake.rs: -------------------------------------------------------------------------------- 1 | use crate::client::discovery; 2 | use crate::client::discovery::DiscoveryStatus; 3 | use crate::client::discovery::MtuDiscovery; 4 | use crate::client::util::send_packet; 5 | use crate::connection::queue::send::SendQueue; 6 | use crate::connection::queue::RecvQueue; 7 | use crate::protocol::frame::FramePacket; 8 | use crate::protocol::packet::offline::{SessionInfoReply, SessionInfoRequest}; 9 | use crate::protocol::packet::online::ConnectedPong; 10 | use crate::protocol::packet::online::{ConnectionRequest, NewConnection, OnlinePacket}; 11 | use crate::protocol::reliability::Reliability; 12 | use crate::protocol::Magic; 13 | use crate::rakrs_debug; 14 | use crate::server::current_epoch; 15 | #[cfg(feature = "async_std")] 16 | use async_std::{ 17 | future::timeout, 18 | future::Future, 19 | net::UdpSocket, 20 | task::{self, Context, Poll, Waker}, 21 | }; 22 | use binary_util::interfaces::Reader; 23 | use binary_util::io::ByteReader; 24 | #[cfg(feature = "async_tokio")] 25 | use std::future::Future; 26 | use std::sync::Arc; 27 | use std::sync::Mutex; 28 | #[cfg(feature = "async_tokio")] 29 | use std::task::{Context, Poll, Waker}; 30 | use std::time::Duration; 31 | #[cfg(feature = "async_tokio")] 32 | use tokio::{ 33 | net::UdpSocket, 34 | task::{self}, 35 | time::timeout, 36 | }; 37 | 38 | #[macro_export] 39 | macro_rules! match_ids { 40 | ($socket: expr, $timeout: expr, $($ids: expr),*) => { 41 | { 42 | let mut recv_buf: [u8; 2048] = [0; 2048]; 43 | let mut tries: u8 = 0; 44 | let ids = vec![$($ids),*]; 45 | let mut pk: Option> = None; 46 | 47 | 'try_conn: loop { 48 | if (tries >= 5) { 49 | break; 50 | } 51 | 52 | let len: usize; 53 | let send_result = timeout( 54 | Duration::from_secs($timeout), 55 | $socket.recv(&mut recv_buf) 56 | ).await; 57 | 58 | if (send_result.is_err()) { 59 | rakrs_debug!(true, "[CLIENT] Failed to receive packet from server! Is it offline?"); 60 | break 'try_conn; 61 | } 62 | 63 | match send_result.unwrap() { 64 | Err(e) => { 65 | tries += 1; 66 | rakrs_debug!(true, "[CLIENT] Failed to receive packet from server! {}", e); 67 | continue; 68 | }, 69 | Ok(l) => len = l 70 | }; 71 | 72 | crate::rakrs_debug_buffers!(true, "[annon]\n {:?}", &recv_buf[..len]); 73 | 74 | // rakrs_debug!(true, "[CLIENT] Received packet from server: {:x?}", &recv_buf[..len]); 75 | 76 | if ids.contains(&recv_buf[0]) { 77 | pk = Some(recv_buf[..len].to_vec()); 78 | break 'try_conn; 79 | } 80 | } 81 | 82 | pk 83 | } 84 | }; 85 | } 86 | 87 | macro_rules! expect_reply { 88 | ($socket: expr, $reply: ty, $timeout: expr) => {{ 89 | let mut recv_buf: [u8; 2048] = [0; 2048]; 90 | let mut tries: u8 = 0; 91 | let mut pk: Option<$reply> = None; 92 | 93 | loop { 94 | if (tries >= 5) { 95 | break; 96 | } 97 | 98 | let len: usize; 99 | let send_result = 100 | timeout(Duration::from_secs($timeout), $socket.recv(&mut recv_buf)).await; 101 | 102 | if (send_result.is_err()) { 103 | rakrs_debug!( 104 | true, 105 | "[CLIENT] Failed to receive packet from server! Is it offline?" 106 | ); 107 | break; 108 | } 109 | 110 | match send_result.unwrap() { 111 | Err(_) => { 112 | tries += 1; 113 | continue; 114 | } 115 | Ok(l) => len = l, 116 | }; 117 | 118 | // rakrs_debug!(true, "[CLIENT] Received packet from server: {:x?}", &recv_buf[..len]); 119 | crate::rakrs_debug_buffers!(true, "[annon]\n {:?}", &recv_buf[..len]); 120 | 121 | let mut reader = ByteReader::from(&recv_buf[1..len]); 122 | if let Ok(packet) = <$reply>::read(&mut reader) { 123 | pk = Some(packet); 124 | break; 125 | } else { 126 | rakrs_debug!(true, "[CLIENT] Failed to parse packet!"); 127 | } 128 | } 129 | 130 | pk 131 | }}; 132 | } 133 | 134 | macro_rules! update_state { 135 | ($done: expr, $shared_state: expr, $state: expr) => {{ 136 | let mut state = $shared_state.lock().unwrap(); 137 | state.status = $state; 138 | state.done = true; 139 | if let Some(waker) = state.waker.take() { 140 | waker.wake(); 141 | } 142 | return; 143 | }}; 144 | ($shared_state: expr, $state: expr) => {{ 145 | let mut state = $shared_state.lock().unwrap(); 146 | state.status = $state; 147 | state.done = false; 148 | if let Some(waker) = state.waker.take() { 149 | waker.wake(); 150 | } 151 | }}; 152 | } 153 | 154 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 155 | pub enum HandshakeStatus { 156 | Created, 157 | Opening, 158 | SessionOpen, 159 | Failed, 160 | FailedMtuDiscovery, 161 | FailedNoSessionReply, 162 | IncompatibleVersion, 163 | Completed, 164 | } 165 | 166 | impl std::fmt::Display for HandshakeStatus { 167 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 168 | write!( 169 | f, 170 | "{}", 171 | match self { 172 | HandshakeStatus::Created => "Handshake created", 173 | HandshakeStatus::Opening => "Opening handshake", 174 | HandshakeStatus::SessionOpen => "Session open", 175 | HandshakeStatus::Failed => "Handshake failed", 176 | HandshakeStatus::FailedMtuDiscovery => "MTU discovery failed", 177 | HandshakeStatus::FailedNoSessionReply => "No session reply", 178 | HandshakeStatus::IncompatibleVersion => "Incompatible version", 179 | HandshakeStatus::Completed => "Handshake completed", 180 | } 181 | ) 182 | } 183 | } 184 | 185 | pub(crate) struct HandshakeState { 186 | status: HandshakeStatus, 187 | done: bool, 188 | waker: Option, 189 | } 190 | 191 | pub struct ClientHandshake { 192 | status: Arc>, 193 | } 194 | 195 | impl ClientHandshake { 196 | pub fn new( 197 | socket: Arc, 198 | id: i64, 199 | version: u8, 200 | mut mtu: u16, 201 | attempts: u8, 202 | timeout: u16, 203 | ) -> Self { 204 | let state = Arc::new(Mutex::new(HandshakeState { 205 | done: false, 206 | status: HandshakeStatus::Created, 207 | waker: None, 208 | })); 209 | 210 | let shared_state = state.clone(); 211 | 212 | task::spawn(async move { 213 | update_state!(shared_state, HandshakeStatus::Opening); 214 | 215 | rakrs_debug!(true, "[CLIENT] Sending OpenConnectRequest to server..."); 216 | 217 | match MtuDiscovery::new( 218 | socket.clone(), 219 | discovery::MtuDiscoveryMeta { 220 | id, 221 | version, 222 | mtu, 223 | timeout, 224 | }, 225 | ) 226 | .await 227 | { 228 | DiscoveryStatus::Discovered(m) => { 229 | rakrs_debug!(true, "[CLIENT] Discovered MTU size: {}", m); 230 | mtu = m; 231 | } 232 | DiscoveryStatus::IncompatibleVersion => { 233 | rakrs_debug!( 234 | true, 235 | "[CLIENT] Client is using incompatible protocol version." 236 | ); 237 | update_state!(true, shared_state, HandshakeStatus::IncompatibleVersion); 238 | } 239 | _ => { 240 | update_state!(true, shared_state, HandshakeStatus::FailedMtuDiscovery); 241 | } 242 | } 243 | 244 | let session_info = SessionInfoRequest { 245 | magic: Magic::new(), 246 | address: socket.peer_addr().unwrap(), 247 | mtu_size: mtu, 248 | client_id: id, 249 | }; 250 | 251 | rakrs_debug!(true, "[CLIENT] Sending SessionInfoRequest to server..."); 252 | 253 | update_state!(shared_state, HandshakeStatus::SessionOpen); 254 | 255 | if !send_packet(&socket, session_info.into()).await { 256 | rakrs_debug!( 257 | true, 258 | "[CLIENT] Failed to send SessionInfoRequest to server." 259 | ); 260 | update_state!(true, shared_state, HandshakeStatus::Failed); 261 | } 262 | 263 | let session_reply = expect_reply!(socket, SessionInfoReply, timeout.into()); 264 | 265 | if session_reply.is_none() { 266 | rakrs_debug!(true, "[CLIENT] Server did not reply with SessionInfoReply!"); 267 | update_state!(true, shared_state, HandshakeStatus::FailedNoSessionReply); 268 | } 269 | 270 | let session_reply = session_reply.unwrap(); 271 | 272 | if session_reply.mtu_size != mtu { 273 | rakrs_debug!( 274 | true, 275 | "[CLIENT] Server replied with incompatible MTU size! ({} != {})", 276 | session_reply.mtu_size, 277 | mtu 278 | ); 279 | update_state!(true, shared_state, HandshakeStatus::Failed); 280 | } 281 | 282 | rakrs_debug!(true, "[CLIENT] Received SessionInfoReply from server!"); 283 | 284 | // create a temporary sendq 285 | let mut send_q = SendQueue::new( 286 | mtu, 287 | timeout, 288 | attempts.clone().into(), 289 | socket.clone(), 290 | socket.peer_addr().unwrap(), 291 | ); 292 | let mut recv_q = RecvQueue::new(); 293 | 294 | if let Err(_) = Self::send_connection_request(&mut send_q, id).await { 295 | update_state!(true, shared_state, HandshakeStatus::Failed); 296 | } 297 | 298 | rakrs_debug!(true, "[CLIENT] Sent ConnectionRequest to server!"); 299 | 300 | let mut send_time = current_epoch() as i64; 301 | let mut tries = 0_u8; 302 | 303 | let mut buf: [u8; 2048] = [0; 2048]; 304 | 305 | loop { 306 | let len: usize; 307 | let rec = socket.recv_from(&mut buf).await; 308 | 309 | if (send_time + 2) <= current_epoch() as i64 { 310 | send_time = current_epoch() as i64; 311 | 312 | rakrs_debug!( 313 | true, 314 | "[CLIENT] Server did not reply with ConnectAccept, sending another..." 315 | ); 316 | 317 | if let Err(_) = Self::send_connection_request(&mut send_q, id).await { 318 | update_state!(true, shared_state, HandshakeStatus::Failed); 319 | } 320 | 321 | tries += 1; 322 | if tries >= 5 { 323 | update_state!(true, shared_state, HandshakeStatus::Failed); 324 | } 325 | } 326 | 327 | match rec { 328 | Err(_) => { 329 | continue; 330 | } 331 | Ok((l, _)) => len = l, 332 | }; 333 | 334 | let mut reader = ByteReader::from(&buf[..len]); 335 | 336 | // proccess frame packet 337 | match buf[0] { 338 | 0x80..=0x8d => { 339 | if let Ok(pk) = FramePacket::read(&mut reader) { 340 | if let Err(_) = recv_q.insert(pk) { 341 | continue; 342 | } 343 | 344 | let raw_packets = recv_q.flush(); 345 | 346 | for raw_pk in raw_packets { 347 | let mut pk = ByteReader::from(&raw_pk[..]); 348 | 349 | if let Ok(pk) = OnlinePacket::read(&mut pk) { 350 | match pk { 351 | OnlinePacket::ConnectedPing(pk) => { 352 | rakrs_debug!( 353 | true, 354 | "[CLIENT] Received ConnectedPing from server!" 355 | ); 356 | let response = ConnectedPong { 357 | ping_time: pk.time, 358 | pong_time: current_epoch() as i64, 359 | }; 360 | 361 | if let Err(_) = send_q 362 | .send_packet( 363 | response.into(), 364 | Reliability::Reliable, 365 | true, 366 | ) 367 | .await 368 | { 369 | rakrs_debug!( 370 | true, 371 | "[CLIENT] Failed to send pong packet!" 372 | ); 373 | } 374 | 375 | continue; 376 | } 377 | OnlinePacket::ConnectionAccept(pk) => { 378 | // send new incoming connection 379 | let new_incoming = NewConnection { 380 | server_address: socket.peer_addr().unwrap(), 381 | system_address: vec![ 382 | socket.peer_addr().unwrap(), 383 | socket.peer_addr().unwrap(), 384 | socket.peer_addr().unwrap(), 385 | socket.peer_addr().unwrap(), 386 | socket.peer_addr().unwrap(), 387 | socket.peer_addr().unwrap(), 388 | socket.peer_addr().unwrap(), 389 | socket.peer_addr().unwrap(), 390 | socket.peer_addr().unwrap(), 391 | socket.peer_addr().unwrap(), 392 | ], 393 | request_time: pk.request_time, 394 | timestamp: pk.timestamp, 395 | }; 396 | if let Err(_) = send_q 397 | .send_packet( 398 | new_incoming.into(), 399 | Reliability::Reliable, 400 | true, 401 | ) 402 | .await 403 | { 404 | update_state!( 405 | true, 406 | shared_state, 407 | HandshakeStatus::Failed 408 | ); 409 | } else { 410 | update_state!( 411 | true, 412 | shared_state, 413 | HandshakeStatus::Completed 414 | ); 415 | } 416 | } 417 | _ => { 418 | rakrs_debug!( 419 | true, 420 | "[CLIENT] Received unknown packet from server!" 421 | ); 422 | } 423 | } 424 | } 425 | } 426 | } 427 | } 428 | _ => {} 429 | } 430 | } 431 | }); 432 | 433 | Self { status: state } 434 | } 435 | 436 | pub(crate) async fn send_connection_request( 437 | send_q: &mut SendQueue, 438 | id: i64, 439 | ) -> std::io::Result<()> { 440 | let connect_request = ConnectionRequest { 441 | time: current_epoch() as i64, 442 | client_id: id, 443 | security: false, 444 | }; 445 | 446 | if let Err(_) = send_q 447 | .send_packet(connect_request.into(), Reliability::Reliable, true) 448 | .await 449 | { 450 | return Err(std::io::Error::new( 451 | std::io::ErrorKind::Other, 452 | "Failed to send ConnectionRequest!", 453 | )); 454 | } 455 | return Ok(()); 456 | } 457 | } 458 | 459 | impl Future for ClientHandshake { 460 | type Output = HandshakeStatus; 461 | 462 | fn poll(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { 463 | // see if we can finish 464 | let mut state = self.status.lock().unwrap(); 465 | 466 | if state.done { 467 | return Poll::Ready(state.status); 468 | } else { 469 | state.waker = Some(cx.waker().clone()); 470 | return Poll::Pending; 471 | } 472 | } 473 | } 474 | -------------------------------------------------------------------------------- /src/client/util.rs: -------------------------------------------------------------------------------- 1 | use crate::protocol::packet::RakPacket; 2 | use crate::{rakrs_debug, rakrs_debug_buffers}; 3 | #[cfg(feature = "async_std")] 4 | use async_std::net::UdpSocket; 5 | use binary_util::interfaces::Writer; 6 | use std::sync::Arc; 7 | #[cfg(feature = "async_tokio")] 8 | use tokio::net::UdpSocket; 9 | 10 | pub async fn send_packet(socket: &Arc, packet: RakPacket) -> bool { 11 | if let Ok(buf) = packet.write_to_bytes() { 12 | if let Err(e) = socket 13 | .send_to(buf.as_slice(), socket.peer_addr().unwrap()) 14 | .await 15 | { 16 | rakrs_debug!("[CLIENT] Failed sending payload to server! {}", e); 17 | return false; 18 | } else { 19 | rakrs_debug_buffers!(false, "[annon]\n{:?}", buf.as_slice()); 20 | return true; 21 | } 22 | } else { 23 | rakrs_debug!("[CLIENT] Failed writing payload to bytes!"); 24 | return false; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/connection/controller/mod.rs: -------------------------------------------------------------------------------- 1 | // TODO 2 | pub mod window; 3 | 4 | pub struct Controller { 5 | pub window: window::ReliableWindow, 6 | } 7 | -------------------------------------------------------------------------------- /src/connection/controller/window.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | use crate::server::current_epoch; 4 | 5 | #[derive(Debug, Clone)] 6 | pub struct ReliableWindow { 7 | // The current window start and end 8 | window: (u32, u32), 9 | // The current window size 10 | size: u32, 11 | // the current queue of packets by timestamp 12 | queue: HashMap, 13 | } 14 | 15 | impl ReliableWindow { 16 | pub fn new() -> Self { 17 | Self { 18 | window: (0, 2048), 19 | size: 2048, 20 | queue: HashMap::new(), 21 | } 22 | } 23 | 24 | pub fn insert(&mut self, index: u32) -> bool { 25 | // We already got this packet 26 | if index < self.window.0 || index > self.window.1 || self.queue.contains_key(&index) { 27 | return false; 28 | } 29 | 30 | self.queue.insert(index, current_epoch()); 31 | 32 | // we need to update the window to check if the is within it. 33 | if index == self.window.0 { 34 | self.adjust(); 35 | } 36 | 37 | return true; 38 | } 39 | 40 | /// Attempts to adjust the window size, removing all out of date packets 41 | /// from the queue. 42 | pub fn adjust(&mut self) { 43 | // remove all packets that are out of date, that we got before the window, 44 | // increasing the window start and end if we can. 45 | while self.queue.contains_key(&self.window.0) { 46 | self.queue.remove(&self.window.0); 47 | self.window.0 = self.window.0.wrapping_add(1); 48 | self.window.1 = self.window.1.wrapping_add(1); 49 | } 50 | 51 | // if the window is too small or too big, make sure it's the right size. 52 | // corresponding to self.size 53 | let curr_size = self.window.1.wrapping_sub(self.window.0); 54 | if curr_size < self.size { 55 | self.window.1 = self.window.0.wrapping_add(self.size); 56 | } else if curr_size > self.size { 57 | self.window.0 = self.window.1.wrapping_sub(self.size); 58 | } 59 | } 60 | 61 | /// Returns all the packets that are in the window. 62 | pub fn missing(&self) -> Vec { 63 | let mut missing = Vec::new(); 64 | 65 | for i in self.window.0..self.window.1 { 66 | if !self.queue.contains_key(&i) { 67 | missing.push(i); 68 | } 69 | } 70 | 71 | missing 72 | } 73 | 74 | pub fn range(&self) -> (u32, u32) { 75 | self.window 76 | } 77 | 78 | /// Forcefully clears packets that are not in the window. 79 | /// This is used when the window is too small to fit all the packets. 80 | pub fn clear_outdated(&mut self) { 81 | //todo actually clear packets that are out of date! 82 | self.queue 83 | .retain(|k, _| *k >= self.window.0 && *k <= self.window.1); 84 | } 85 | } 86 | 87 | pub struct Window { 88 | // last round trip time 89 | pub rtt: u32, 90 | } 91 | -------------------------------------------------------------------------------- /src/connection/queue/mod.rs: -------------------------------------------------------------------------------- 1 | pub(crate) mod recv; 2 | pub(crate) mod send; 3 | 4 | pub use self::recv::*; 5 | pub use self::send::*; 6 | 7 | use std::collections::BTreeMap; 8 | use std::collections::HashMap; 9 | 10 | use crate::protocol::frame::FragmentMeta; 11 | use crate::protocol::frame::Frame; 12 | use crate::protocol::reliability::Reliability; 13 | use crate::protocol::RAKNET_HEADER_FRAME_OVERHEAD; 14 | use crate::rakrs_debug; 15 | use crate::server::current_epoch; 16 | 17 | #[derive(Debug, Clone)] 18 | pub enum NetQueueError { 19 | /// The insertion failed for any given reason. 20 | InvalidInsertion, 21 | /// The insertion failed and the reason is known. 22 | InvalidInsertionKnown(String), 23 | /// The `Item` failed to be removed from the queue. 24 | ItemDeletionFail, 25 | /// The `Item` is invalid and can not be retrieved. 26 | InvalidItem, 27 | /// The queue is empty. 28 | EmptyQueue, 29 | /// The error is a custom error. 30 | Other(E), 31 | } 32 | 33 | pub trait NetQueue { 34 | /// The `Item` of the queue. 35 | // type Item = V; 36 | 37 | /// The "key" that each `Item` is stored under 38 | /// (used for removal) 39 | type KeyId; 40 | 41 | /// A custom error specifier for NetQueueError 42 | type Error; 43 | 44 | /// Inserts `Item` into the queue, given the conditions are fulfilled. 45 | fn insert(&mut self, item: Item) -> Result>; 46 | 47 | /// Remove an `Item` from the queue by providing an instance of `Self::KeyId` 48 | fn remove(&mut self, key: Self::KeyId) -> Result>; 49 | 50 | /// Retrieves an `Item` from the queue, by reference. 51 | fn get(&mut self, key: Self::KeyId) -> Result<&Item, NetQueueError>; 52 | 53 | /// Clears the entire queue. 54 | fn flush(&mut self) -> Result, NetQueueError>; 55 | } 56 | 57 | /// A recovery queue is used to store packets that need to be resent. 58 | /// This is used for sequenced and ordered packets. 59 | #[derive(Debug, Clone)] 60 | pub struct RecoveryQueue { 61 | /// The current queue of packets by timestamp 62 | /// (seq, (packet, timestamp)) 63 | // TODO use the timestamp for round trip time (RTT) 64 | queue: HashMap, 65 | } 66 | 67 | impl RecoveryQueue 68 | where 69 | Item: Clone, 70 | { 71 | pub fn new() -> Self { 72 | Self { 73 | queue: HashMap::new(), 74 | } 75 | } 76 | 77 | pub fn insert_id(&mut self, seq: u32, item: Item) { 78 | self.queue.insert(seq, (current_epoch(), item)); 79 | } 80 | 81 | pub fn get_all(&mut self) -> Vec<(u32, Item)> { 82 | self.queue 83 | .iter() 84 | .map(|(seq, (_, item))| (*seq, item.clone())) 85 | .collect::>() 86 | } 87 | 88 | pub fn flush_old(&mut self, threshold: u64) -> Vec { 89 | let old = self 90 | .queue 91 | .iter() 92 | .filter(|(_, (time, _))| (*time + threshold) < current_epoch()) 93 | .map(|(_, (_, item))| item.clone()) 94 | .collect::>(); 95 | self.queue 96 | .retain(|_, (time, _)| (*time + threshold) > current_epoch()); 97 | old 98 | } 99 | } 100 | 101 | impl NetQueue for RecoveryQueue { 102 | type KeyId = u32; 103 | type Error = (); 104 | 105 | fn insert(&mut self, item: Item) -> Result> { 106 | let index = self.queue.len() as u32; 107 | self.queue.insert(index, (current_epoch(), item)); 108 | Ok(index) 109 | } 110 | 111 | fn remove(&mut self, key: Self::KeyId) -> Result> { 112 | if let Some((_, item)) = self.queue.remove(&key) { 113 | Ok(item) 114 | } else { 115 | Err(NetQueueError::ItemDeletionFail) 116 | } 117 | } 118 | 119 | fn get(&mut self, key: Self::KeyId) -> Result<&Item, NetQueueError> { 120 | if let Some((_, item)) = self.queue.get(&key) { 121 | Ok(item) 122 | } else { 123 | Err(NetQueueError::ItemDeletionFail) 124 | } 125 | } 126 | 127 | fn flush(&mut self) -> Result, NetQueueError> { 128 | let mut items = Vec::new(); 129 | for (_, (_, item)) in self.queue.drain() { 130 | items.push(item); 131 | } 132 | Ok(items) 133 | } 134 | } 135 | 136 | /// An ordered queue is used to Index incoming packets over a channel 137 | /// within a reliable window time. 138 | /// 139 | /// Usage: 140 | /// ```ignore 141 | /// use rak_rs::connection::queue::OrderedQueue; 142 | /// let mut ord_qu: OrderedQueue> = OrderedQueue::new(); 143 | /// // Insert a packet with the id of "1" 144 | /// ord_qu.insert(1, vec![0, 1]); 145 | /// ord_qu.insert(5, vec![1, 0]); 146 | /// ord_qu.insert(3, vec![2, 0]); 147 | /// 148 | /// // Get the packets we still need. 149 | /// let needed: Vec = ord_qu.missing(); 150 | /// assert_eq!(needed, vec![0, 2, 4]); 151 | /// 152 | /// // We would in theory, request these packets, but we're going to insert them 153 | /// ord_qu.insert(4, vec![2, 0, 0, 1]); 154 | /// ord_qu.insert(2, vec![1, 0, 0, 2]); 155 | /// 156 | /// // Now let's return our packets in order. 157 | /// // Will return a vector of these packets in order by their "id". 158 | /// let ordered: Vec> = ord_qu.flush(); 159 | /// ``` 160 | #[derive(Debug, Clone)] 161 | pub struct OrderedQueue { 162 | /// The current ordered queue channels 163 | /// Channel, (Highest Index, Ord Index, Item) 164 | pub queue: BTreeMap, 165 | /// The window for this queue. 166 | pub window: (u32, u32), 167 | } 168 | 169 | impl OrderedQueue 170 | where 171 | Item: Clone + std::fmt::Debug, 172 | { 173 | pub fn new() -> Self { 174 | Self { 175 | queue: BTreeMap::new(), 176 | window: (0, 0), 177 | } 178 | } 179 | 180 | pub fn next(&mut self) -> u32 { 181 | self.window.0 = self.window.0.wrapping_add(1); 182 | return self.window.0; 183 | } 184 | 185 | pub fn insert(&mut self, index: u32, item: Item) -> bool { 186 | if index < self.window.0 { 187 | return false; 188 | } 189 | 190 | if self.queue.contains_key(&index) { 191 | return false; 192 | } 193 | 194 | if index >= self.window.1 { 195 | self.window.1 = index + 1; 196 | } 197 | 198 | self.queue.insert(index, item); 199 | true 200 | } 201 | 202 | pub fn insert_abs(&mut self, index: u32, item: Item) { 203 | if index >= self.window.1 { 204 | self.window.1 = index + 1; 205 | } 206 | 207 | self.queue.insert(index, item); 208 | } 209 | 210 | pub fn missing(&self) -> Vec { 211 | let mut missing = Vec::new(); 212 | for i in self.window.0..self.window.1 { 213 | if !self.queue.contains_key(&i) { 214 | missing.push(i); 215 | } 216 | } 217 | missing 218 | } 219 | 220 | /// Forcefully flushes the incoming queue resetting the highest window 221 | /// to the lowest window. 222 | /// 223 | /// THIS IS A PATCH FIX UNTIL I CAN FIGURE OUT WHY THE OTHER FLUSH IS BROKEN 224 | pub fn flush(&mut self) -> Vec { 225 | let mut items = Vec::new(); 226 | for i in self.window.0..self.window.1 { 227 | if let Some(item) = self.queue.remove(&i) { 228 | items.push(item); 229 | } 230 | } 231 | self.window.0 = self.window.1; 232 | items 233 | } 234 | 235 | /// Older, broken implementation, idk what is causing this to break 236 | /// after index 3 237 | /// The logic here is supposed to be, remove all indexes until the highest most up to date index. 238 | /// and retain older indexes until the order is correct. 239 | pub fn flush_old_impl(&mut self) -> Vec { 240 | let mut items = Vec::<(u32, Item)>::new(); 241 | 242 | let mut i = self.window.0; 243 | 244 | while self.queue.contains_key(&i) { 245 | rakrs_debug!("[!>] Removing: {}", &i); 246 | if let Some(item) = self.queue.remove(&i) { 247 | items.push((self.window.0, item)); 248 | i += 1; 249 | } else { 250 | break; 251 | } 252 | } 253 | 254 | self.window.0 = i; 255 | 256 | items.sort_by(|a, b| a.0.cmp(&b.0)); 257 | return items 258 | .iter() 259 | .map(|(_, item)| item.clone()) 260 | .collect::>(); 261 | } 262 | } 263 | 264 | /// A specialized structure for re-ordering fragments over the wire. 265 | /// You can use this structure to fragment frames as well. 266 | /// 267 | /// **NOTE:** This structure will NOT update a frame's reliable index! 268 | /// The sender is required to this! 269 | #[derive(Clone, Debug)] 270 | pub struct FragmentQueue { 271 | /// The current fragment id to use 272 | /// If for some reason this wraps back to 0, 273 | /// and the fragment queue is full, 0 is then cleared and reused. 274 | fragment_id: u16, 275 | 276 | /// The current Fragments 277 | /// Hashmap is by Fragment id, with the value being 278 | /// (`size`, Vec) 279 | fragments: HashMap)>, 280 | } 281 | 282 | impl FragmentQueue { 283 | pub fn new() -> Self { 284 | Self { 285 | fragment_id: 0, 286 | fragments: HashMap::new(), 287 | } 288 | } 289 | 290 | /// Inserts the frame into the fragment queue. 291 | /// Returns a result tuple of (`fragment_size`, `fragment_index`) 292 | pub fn insert(&mut self, fragment: Frame) -> Result<(u32, u32), FragmentQueueError> { 293 | if let Some(meta) = fragment.fragment_meta.clone() { 294 | if let Some((size, frames)) = self.fragments.get_mut(&meta.id) { 295 | // check if the frame index is out of bounds 296 | // todo: Check if == or >, I think it's > but I'm not sure. 297 | // todo: This is because the index starts at 0 and the size starts at 1. 298 | if meta.index >= *size { 299 | return Err(FragmentQueueError::FrameIndexOutOfBounds); 300 | } 301 | // the frame exists, and we have parts, check if we have this particular frame already. 302 | if let Some(_) = frames 303 | .iter() 304 | .find(|&f| f.fragment_meta.as_ref().unwrap().index == meta.index) 305 | { 306 | // We already have this frame! Do not replace it!! 307 | return Err(FragmentQueueError::FrameExists); 308 | } else { 309 | frames.push(fragment); 310 | return Ok((meta.size, meta.index)); 311 | } 312 | } else { 313 | // We don't already have this fragment index! 314 | let (size, mut frames) = (meta.size, Vec::::new()); 315 | frames.push(fragment); 316 | 317 | self.fragments.insert(meta.id, (size, frames)); 318 | return Ok((meta.size, meta.index)); 319 | } 320 | } 321 | 322 | return Err(FragmentQueueError::FrameNotFragmented); 323 | } 324 | 325 | /// Attempts to collect all fragments from a given fragment id. 326 | /// Will fail if not all fragments are specified. 327 | pub fn collect(&mut self, id: u16) -> Result, FragmentQueueError> { 328 | if let Some((size, frames)) = self.fragments.get_mut(&id) { 329 | if *size == frames.len() as u32 { 330 | // sort all frames by id, 331 | // because we now have all frames. 332 | frames.sort_by(|a, b| { 333 | a.fragment_meta 334 | .as_ref() 335 | .unwrap() 336 | .index 337 | .cmp(&b.fragment_meta.as_ref().unwrap().index) 338 | }); 339 | 340 | let mut buffer = Vec::::new(); 341 | 342 | for frame in frames.iter() { 343 | buffer.extend_from_slice(&frame.body); 344 | } 345 | 346 | self.fragments.remove(&id); 347 | return Ok(buffer); 348 | } 349 | return Err(FragmentQueueError::FragmentsMissing); 350 | } 351 | 352 | return Err(FragmentQueueError::FragmentInvalid); 353 | } 354 | 355 | /// This will split a given frame into a bunch of smaller frames within the specified 356 | /// restriction. 357 | pub fn split_insert(&mut self, buffer: &[u8], mtu: u16) -> Result { 358 | self.fragment_id += self.fragment_id.wrapping_add(1); 359 | 360 | let id = self.fragment_id; 361 | 362 | if self.fragments.contains_key(&id) { 363 | self.fragments.remove(&id); 364 | } 365 | 366 | if let Ok(frames) = Self::split(buffer, id, mtu) { 367 | self.fragments.insert(id, (frames.len() as u32, frames)); 368 | return Ok(id); 369 | } 370 | 371 | return Err(FragmentQueueError::DoesNotNeedSplit); 372 | } 373 | 374 | pub fn split(buffer: &[u8], id: u16, mtu: u16) -> Result, FragmentQueueError> { 375 | let max_mtu = mtu - RAKNET_HEADER_FRAME_OVERHEAD; 376 | 377 | if buffer.len() > max_mtu.into() { 378 | let splits = buffer 379 | .chunks(max_mtu.into()) 380 | .map(|c| c.to_vec()) 381 | .collect::>>(); 382 | let mut frames: Vec = Vec::new(); 383 | let mut index: u32 = 0; 384 | 385 | for buf in splits.iter() { 386 | let mut f = Frame::new(Reliability::ReliableOrd, Some(&buf[..])); 387 | f.fragment_meta = Some(FragmentMeta { 388 | index, 389 | size: splits.len() as u32, 390 | id, 391 | }); 392 | 393 | index += 1; 394 | 395 | frames.push(f); 396 | } 397 | 398 | return Ok(frames); 399 | } 400 | 401 | return Err(FragmentQueueError::DoesNotNeedSplit); 402 | } 403 | 404 | pub fn get(&self, id: &u16) -> Result<&(u32, Vec), FragmentQueueError> { 405 | if let Some(v) = self.fragments.get(id) { 406 | return Ok(v); 407 | } 408 | 409 | return Err(FragmentQueueError::FragmentInvalid); 410 | } 411 | 412 | pub fn get_mut(&mut self, id: &u16) -> Result<&mut (u32, Vec), FragmentQueueError> { 413 | if let Some(v) = self.fragments.get_mut(id) { 414 | return Ok(v); 415 | } 416 | 417 | return Err(FragmentQueueError::FragmentInvalid); 418 | } 419 | 420 | pub fn remove(&mut self, id: &u16) -> bool { 421 | self.fragments.remove(id).is_some() 422 | } 423 | 424 | /// This will hard clear the fragment queue, this should only be used if memory becomes an issue! 425 | pub fn clear(&mut self) { 426 | self.fragment_id = 0; 427 | self.fragments.clear(); 428 | } 429 | } 430 | 431 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] 432 | pub enum FragmentQueueError { 433 | FrameExists, 434 | FrameNotFragmented, 435 | DoesNotNeedSplit, 436 | FragmentInvalid, 437 | FragmentsMissing, 438 | FrameIndexOutOfBounds, 439 | } 440 | 441 | impl std::fmt::Display for FragmentQueueError { 442 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 443 | write!( 444 | f, 445 | "{}", 446 | match self { 447 | FragmentQueueError::FrameExists => "Frame already exists", 448 | FragmentQueueError::FrameNotFragmented => "Frame is not fragmented", 449 | FragmentQueueError::DoesNotNeedSplit => "Frame does not need to be split", 450 | FragmentQueueError::FragmentInvalid => "Fragment is invalid", 451 | FragmentQueueError::FragmentsMissing => "Fragments are missing", 452 | FragmentQueueError::FrameIndexOutOfBounds => "Frame index is out of bounds", 453 | } 454 | ) 455 | } 456 | } 457 | 458 | impl std::error::Error for FragmentQueueError {} 459 | -------------------------------------------------------------------------------- /src/connection/queue/recv.rs: -------------------------------------------------------------------------------- 1 | use std::collections::{HashMap, HashSet}; 2 | 3 | use crate::connection::controller::window::ReliableWindow; 4 | use crate::protocol::ack::{Ack, Ackable, Record, SingleRecord}; 5 | use crate::protocol::frame::{Frame, FramePacket}; 6 | use crate::protocol::reliability::Reliability; 7 | use crate::protocol::MAX_FRAGS; 8 | use crate::server::current_epoch; 9 | use crate::{rakrs_debug, rakrs_debug_buffers}; 10 | 11 | use super::{FragmentQueue, OrderedQueue}; 12 | 13 | #[derive(Debug, Clone)] 14 | pub enum RecvQueueError { 15 | OldSeq, 16 | } 17 | 18 | #[derive(Debug, Clone)] 19 | pub struct RecvQueue { 20 | frag_queue: FragmentQueue, 21 | pub(crate) window: ReliableWindow, 22 | pub(crate) reliable_window: ReliableWindow, 23 | order_channels: HashMap>>, 24 | /// Set of sequences that we've acknowledged. 25 | /// (seq, time) 26 | ack: HashSet<(u32, u64)>, 27 | nack: HashSet, 28 | ready: Vec>, 29 | } 30 | 31 | impl RecvQueue { 32 | pub fn new() -> Self { 33 | Self { 34 | frag_queue: FragmentQueue::new(), 35 | ack: HashSet::new(), 36 | nack: HashSet::new(), 37 | window: ReliableWindow::new(), 38 | reliable_window: ReliableWindow::new(), 39 | ready: Vec::new(), 40 | order_channels: HashMap::new(), 41 | } 42 | } 43 | 44 | pub fn insert(&mut self, packet: FramePacket) -> Result<(), RecvQueueError> { 45 | if !self.window.insert(packet.sequence) { 46 | return Err(RecvQueueError::OldSeq); 47 | } 48 | 49 | if self.window.range().0 < packet.sequence { 50 | for i in self.window.range().0..packet.sequence { 51 | self.nack.insert(i); 52 | } 53 | } 54 | 55 | self.ack.insert((packet.sequence, current_epoch())); 56 | 57 | for frame in packet.frames.iter() { 58 | self.handle_frame(frame); 59 | } 60 | 61 | return Ok(()); 62 | } 63 | 64 | pub fn flush(&mut self) -> Vec> { 65 | self.ready.drain(..).collect::>>() 66 | } 67 | 68 | pub fn ack_flush(&mut self) -> Vec { 69 | self.ack.drain().map(|(seq, _)| seq).collect() 70 | } 71 | 72 | pub fn nack_queue(&mut self) -> Vec { 73 | self.nack.iter().map(|x| *x).collect::>() 74 | } 75 | 76 | fn handle_frame(&mut self, frame: &Frame) { 77 | if let Some(reliable_index) = frame.reliable_index { 78 | if !self.reliable_window.insert(reliable_index) { 79 | return; 80 | } 81 | } 82 | 83 | if let Some(meta) = frame.fragment_meta.as_ref() { 84 | if meta.size > MAX_FRAGS { 85 | rakrs_debug!(true, "Fragment size is too large, rejected {}!", meta.size); 86 | return; 87 | } 88 | if let Err(_) = self.frag_queue.insert(frame.clone()) {} 89 | 90 | let res = self.frag_queue.collect(meta.id); 91 | if let Ok(data) = res { 92 | // reconstructed frame packet! 93 | self.ready.push(data); 94 | } else { 95 | rakrs_debug!( 96 | true, 97 | "Still Missing some fragments! {:?}", 98 | frame.fragment_meta.as_ref().unwrap() 99 | ); 100 | } 101 | return; 102 | } 103 | 104 | rakrs_debug_buffers!( 105 | true, 106 | "RecvQueue: {}\n{:?}\n", 107 | frame.body.len(), 108 | frame.body.clone() 109 | ); 110 | 111 | match frame.reliability { 112 | Reliability::Unreliable => { 113 | self.ready.push(frame.body.clone()); 114 | } 115 | Reliability::Reliable => { 116 | self.ready.push(frame.body.clone()); 117 | } 118 | Reliability::ReliableOrd => { 119 | let channel = frame.order_channel.unwrap(); 120 | let queue = self 121 | .order_channels 122 | .entry(channel) 123 | .or_insert(OrderedQueue::new()); 124 | 125 | if queue.insert(frame.order_index.unwrap(), frame.body.clone()) { 126 | for pk in queue.flush() { 127 | self.ready.push(pk); 128 | } 129 | } 130 | } 131 | _ => { 132 | self.ready.push(frame.body.clone()); 133 | } 134 | } 135 | } 136 | } 137 | 138 | impl Ackable for RecvQueue { 139 | type NackItem = (); 140 | 141 | fn ack(&mut self, ack: Ack) { 142 | if ack.is_nack() { 143 | rakrs_debug!(true, "Invalid ack: {:?}", ack.clone()); 144 | return; 145 | } 146 | 147 | rakrs_debug!(true, "Got ack item: {:?}", ack.clone()); 148 | 149 | // these packets are acknowledged, so we can remove them from the queue. 150 | for record in ack.records.iter() { 151 | match record { 152 | Record::Single(SingleRecord { sequence }) => { 153 | self.nack.remove(&sequence); 154 | } 155 | Record::Range(ranged) => { 156 | for i in ranged.start.0..ranged.end.0 { 157 | self.nack.remove(&i); 158 | } 159 | } 160 | } 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/connection/queue/send.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::net::SocketAddr; 3 | use std::sync::Arc; 4 | 5 | #[cfg(feature = "async_std")] 6 | use async_std::net::UdpSocket; 7 | 8 | use binary_util::interfaces::Writer; 9 | #[cfg(feature = "async_tokio")] 10 | use tokio::net::UdpSocket; 11 | 12 | use crate::protocol::ack::{Ack, Ackable, Record, SingleRecord}; 13 | use crate::protocol::frame::{Frame, FramePacket}; 14 | use crate::protocol::packet::RakPacket; 15 | use crate::protocol::reliability::Reliability; 16 | use crate::protocol::RAKNET_HEADER_FRAME_OVERHEAD; 17 | use crate::util::{to_address_token, SafeGenerator}; 18 | use crate::{rakrs_debug, rakrs_debug_buffers}; 19 | 20 | use super::{FragmentQueue, FragmentQueueError, NetQueue, RecoveryQueue}; 21 | 22 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] 23 | pub enum SendQueueError { 24 | /// The packet is too large to be sent. 25 | PacketTooLarge, 26 | /// Parsing Error 27 | ParseError, 28 | /// Fragmentation error 29 | FragmentError(FragmentQueueError), 30 | /// Send queue error 31 | SendError, 32 | } 33 | 34 | impl std::fmt::Display for SendQueueError { 35 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 36 | write!( 37 | f, 38 | "{}", 39 | match self { 40 | SendQueueError::PacketTooLarge => "Packet too large".to_string(), 41 | SendQueueError::ParseError => "Parse error".to_string(), 42 | SendQueueError::FragmentError(e) => format!("Fragment error: {}", e), 43 | SendQueueError::SendError => "Send error".to_string(), 44 | } 45 | ) 46 | } 47 | } 48 | 49 | impl std::error::Error for SendQueueError {} 50 | 51 | /// This queue is used to prioritize packets being sent out 52 | /// Packets that are old, are either dropped or requested again. 53 | /// You can define this behavior with the `timeout` property. 54 | #[derive(Debug, Clone)] 55 | pub struct SendQueue { 56 | mtu_size: u16, 57 | 58 | /// The amount of time that needs to pass for a packet to be 59 | /// dropped or requested again. 60 | _timeout: u16, 61 | 62 | /// The amount of times we should retry sending a packet before 63 | /// dropping it from the queue. This is currently set to `5`. 64 | _max_tries: u16, 65 | 66 | /// The current sequence number. This is incremented every time 67 | /// a packet is sent reliably. We can resend these if they are 68 | /// NAcked. 69 | send_seq: SafeGenerator, 70 | 71 | /// The current reliable index number. 72 | /// a packet is sent reliably an sequenced. 73 | reliable_seq: SafeGenerator, 74 | 75 | /// The current recovery queue. 76 | ack: RecoveryQueue, 77 | 78 | /// The fragment queue. 79 | fragment_queue: FragmentQueue, 80 | 81 | /// The ordered channels. 82 | /// (send_seq, reliable_seq) 83 | order_channels: HashMap, 84 | 85 | ready: Vec, 86 | 87 | socket: Arc, 88 | 89 | address: SocketAddr, 90 | } 91 | 92 | impl SendQueue { 93 | pub fn new( 94 | mtu_size: u16, 95 | _timeout: u16, 96 | _max_tries: u16, 97 | socket: Arc, 98 | address: SocketAddr, 99 | ) -> Self { 100 | Self { 101 | mtu_size, 102 | _timeout, 103 | _max_tries, 104 | send_seq: SafeGenerator::new(), 105 | reliable_seq: SafeGenerator::new(), 106 | ack: RecoveryQueue::new(), 107 | fragment_queue: FragmentQueue::new(), 108 | order_channels: HashMap::new(), 109 | ready: Vec::new(), 110 | socket, 111 | address, 112 | } 113 | } 114 | 115 | /// Send a packet based on its reliability. 116 | /// Note, reliability will be set to `Reliability::ReliableOrd` if 117 | /// the buffer is larger than max MTU. 118 | pub async fn insert( 119 | &mut self, 120 | packet: &[u8], 121 | reliability: Reliability, 122 | immediate: bool, 123 | channel: Option, 124 | ) -> Result<(), SendQueueError> { 125 | rakrs_debug!( 126 | true, 127 | "Inserting packet into send queue: {} bytes", 128 | packet.len() 129 | ); 130 | rakrs_debug!("Write is now processing packet"); 131 | let reliable = if packet.len() > (self.mtu_size + RAKNET_HEADER_FRAME_OVERHEAD) as usize { 132 | Reliability::ReliableOrd 133 | } else { 134 | reliability 135 | }; 136 | 137 | rakrs_debug!("Write is now processing packet: {:?}", reliable); 138 | 139 | match reliability { 140 | Reliability::Unreliable => { 141 | // we can just send this packet out immediately. 142 | let frame = Frame::new(Reliability::Unreliable, Some(packet)); 143 | self.send_frame(frame).await; 144 | return Ok(()); 145 | } 146 | Reliability::Reliable => { 147 | // we need to send this packet out reliably. 148 | let frame = Frame::new(Reliability::Reliable, Some(packet)); 149 | self.send_frame(frame).await; 150 | return Ok(()); 151 | } 152 | _ => {} 153 | }; 154 | 155 | // do another integrity check 156 | // this is to check to see if we really need to split this packet. 157 | if packet.len() > (self.mtu_size + RAKNET_HEADER_FRAME_OVERHEAD) as usize { 158 | // we need to split this packet! 159 | // pass the buffer to the fragment queue. 160 | let mut pk = FramePacket::new(); 161 | pk.sequence = self.send_seq.next(); 162 | pk.reliability = reliability; 163 | 164 | rakrs_debug!("Write is now splitting, too large: {:?}", reliability); 165 | 166 | let fragmented = self.fragment_queue.split_insert(&packet, self.mtu_size); 167 | 168 | if fragmented.is_ok() { 169 | let frag_id = fragmented.unwrap(); 170 | let (_, frames) = self.fragment_queue.get_mut(&frag_id).unwrap(); 171 | let (ord_seq, ord_index) = self 172 | .order_channels 173 | .entry(channel.unwrap_or(0)) 174 | .or_insert((0, 0)); 175 | 176 | for frame in frames.iter_mut() { 177 | frame.reliability = reliability; 178 | frame.sequence_index = Some(*ord_seq); 179 | frame.order_channel = Some(channel.unwrap_or(0)); 180 | frame.order_index = Some(*ord_index); 181 | 182 | if frame.reliability.is_reliable() { 183 | frame.reliable_index = Some(self.reliable_seq.next()); 184 | } 185 | } 186 | 187 | *ord_index = ord_index.wrapping_add(1); 188 | *ord_seq = ord_seq.wrapping_add(1); 189 | 190 | // Add this frame packet to the recovery queue. 191 | if let Ok(p) = pk.write_to_bytes() { 192 | rakrs_debug!("Write is sending stream: {:?}", reliability); 193 | 194 | self.send_stream(p.as_slice()).await; 195 | self.ack.insert_id(pk.sequence, pk); 196 | return Ok(()); 197 | } else { 198 | return Err(SendQueueError::SendError); 199 | } 200 | } else { 201 | // we couldn't send this frame! 202 | return Err(SendQueueError::FragmentError(fragmented.unwrap_err())); 203 | } 204 | } else { 205 | // we're not gonna send this frame out yet! 206 | // we need to wait for the next tick. 207 | let mut frame = Frame::new(reliable, Some(packet)); 208 | 209 | if frame.reliability.is_reliable() { 210 | frame.reliable_index = Some(self.reliable_seq.next()); 211 | } 212 | 213 | if frame.reliability.is_ordered() { 214 | let (_, ord_index) = self 215 | .order_channels 216 | .entry(channel.unwrap_or(0)) 217 | .or_insert((0, 0)); 218 | frame.order_index = Some(*ord_index); 219 | frame.sequence_index = Some(self.send_seq.get()); 220 | *ord_index = ord_index.wrapping_add(1); 221 | } else if frame.reliability.is_sequenced() { 222 | let (seq_index, ord_index) = self 223 | .order_channels 224 | .entry(channel.unwrap_or(0)) 225 | .or_insert((0, 0)); 226 | *seq_index = seq_index.wrapping_add(1); 227 | frame.order_index = Some(*ord_index); 228 | frame.sequence_index = Some(*seq_index); 229 | } 230 | 231 | if immediate { 232 | self.send_frame(frame).await; 233 | } else { 234 | self.ready.push(frame); 235 | } 236 | 237 | return Ok(()); 238 | } 239 | } 240 | 241 | /// A wrapper to send a single frame over the wire. 242 | /// While also reliabily tracking it. 243 | async fn send_frame(&mut self, mut frame: Frame) { 244 | let mut pk = FramePacket::new(); 245 | pk.sequence = self.send_seq.next(); 246 | pk.reliability = frame.reliability; 247 | 248 | if pk.reliability.is_reliable() { 249 | frame.reliable_index = Some(self.reliable_seq.next()); 250 | } 251 | 252 | pk.frames.push(frame); 253 | 254 | if pk.reliability.is_reliable() { 255 | // this seems redundant, but we need to insert the packet into the ACK queue 256 | self.ack.insert_id(self.reliable_seq.get(), pk.clone()); 257 | } 258 | 259 | if let Ok(buf) = pk.write_to_bytes() { 260 | rakrs_debug!("[!] Write sent the packet.. {:?}", buf.as_slice()); 261 | self.send_stream(buf.as_slice()).await; 262 | } else { 263 | rakrs_debug_buffers!(true, "SendQ: Failed to send frame: {:?}", pk); 264 | } 265 | } 266 | 267 | pub(crate) async fn send_stream(&mut self, packet: &[u8]) { 268 | rakrs_debug_buffers!(false, "SendQ: {}\n{:?}\n", packet.len(), packet); 269 | 270 | if let Err(e) = self.socket.send_to(packet, &self.address).await { 271 | // we couldn't sent the packet! 272 | rakrs_debug!( 273 | true, 274 | "[{}] Failed to send packet! {:?}", 275 | to_address_token(self.address), 276 | e 277 | ); 278 | } 279 | } 280 | 281 | pub async fn send_packet( 282 | &mut self, 283 | packet: RakPacket, 284 | reliability: Reliability, 285 | immediate: bool, 286 | ) -> Result<(), SendQueueError> { 287 | // parse the packet 288 | if let Ok(buf) = packet.write_to_bytes() { 289 | if let Err(e) = self 290 | .insert(buf.as_slice(), reliability, immediate, None) 291 | .await 292 | { 293 | rakrs_debug!( 294 | true, 295 | "[{}] Failed to insert packet into send queue: {:?}", 296 | to_address_token(self.address), 297 | e 298 | ); 299 | return Err(e); 300 | } 301 | return Ok(()); 302 | } else { 303 | return Err(SendQueueError::ParseError); 304 | } 305 | } 306 | 307 | pub async fn update(&mut self) { 308 | // send all the ready packets 309 | // TODO batch these packets together 310 | // TODO by lengths 311 | for frame in self.ready.drain(..).collect::>() { 312 | self.send_frame(frame).await; 313 | } 314 | 315 | // Flush ACK 316 | // check to see if we need to resend any packets. 317 | // TODO actually implement this 318 | let resend_queue = self.ack.flush().unwrap(); 319 | // let mut resend_queue = Vec::::new(); 320 | 321 | // for (seq, packet) in self.ack.get_all() { 322 | // if packet.resend_time < Instant::now() { 323 | // resend_queue.push(packet.clone()); 324 | // } 325 | // } 326 | 327 | for packet in resend_queue.iter() { 328 | if let Ok(buf) = packet.write_to_bytes() { 329 | self.send_stream(buf.as_slice()).await; 330 | } 331 | } 332 | } 333 | } 334 | 335 | impl Ackable for SendQueue { 336 | type NackItem = FramePacket; 337 | 338 | fn ack(&mut self, ack: Ack) { 339 | if ack.is_nack() { 340 | return; 341 | } 342 | 343 | // these packets are acknowledged, so we can remove them from the queue. 344 | for record in ack.records.iter() { 345 | match record { 346 | Record::Single(SingleRecord { sequence }) => { 347 | if let Ok(_) = self.ack.remove(sequence.0) {}; 348 | } 349 | Record::Range(ranged) => { 350 | for i in ranged.start.0..ranged.end.0 { 351 | if let Ok(_) = self.ack.remove(i) {}; 352 | } 353 | } 354 | } 355 | } 356 | } 357 | 358 | fn nack(&mut self, nack: Ack) -> Vec { 359 | if !nack.is_nack() { 360 | return Vec::new(); 361 | } 362 | 363 | let mut resend_queue = Vec::::new(); 364 | 365 | // we need to get the packets to resend. 366 | for record in nack.records.iter() { 367 | match record { 368 | Record::Single(single) => { 369 | if let Ok(packet) = self.ack.get(single.sequence.0) { 370 | resend_queue.push(packet.clone()); 371 | } 372 | } 373 | Record::Range(ranged) => { 374 | for i in ranged.start.0..ranged.end.0 { 375 | if let Ok(packet) = self.ack.get(i) { 376 | resend_queue.push(packet.clone()); 377 | } 378 | } 379 | } 380 | } 381 | } 382 | 383 | return resend_queue; 384 | } 385 | } 386 | -------------------------------------------------------------------------------- /src/connection/state.rs: -------------------------------------------------------------------------------- 1 | /// Connection States 2 | /// These are all possible states of a raknet session, and while accessible externally 3 | /// Please note that these are not states relied on within the original implementation of 4 | /// raknet, which preserve both "Unconnected" and "Connected" 5 | #[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] 6 | pub enum ConnectionState { 7 | /// The Session is not yet connected, but is actively trying to connect. 8 | /// Clients in this state are considered to be actively trying to connect. 9 | Connecting, 10 | 11 | /// The Session is connected and ready to send and receive packets. 12 | /// This is the state after a connection has been established. 13 | /// 14 | /// This state is applied once the `ConnectionHandshake` has been completed. 15 | Connected, 16 | 17 | /// The session is being timed out because it has not sent a packet in a while. 18 | /// The interval for this can be set in the Session Options. 19 | TimingOut, 20 | 21 | /// The session has been disconnected but is still in the process of cleaning up. 22 | /// This is the state after a disconnect has been requested, but the client still wants 23 | /// to send packets until its done. 24 | Disconnecting, 25 | 26 | /// The session has been disconnected and is ready to be removed. 27 | /// This is the state after a disconnect has been requested and the client has 28 | /// This is almost never used. 29 | Disconnected, 30 | 31 | /// The session is replying to the server but is not actually connected. This is 32 | /// the state where ping and pong packets are being sent. Similarly, this is 33 | /// the "Unconnected" state, hence "UnconnectedPing" 34 | Unidentified, 35 | 36 | /// The session has been identified and is ready to be connected. 37 | /// This is the state after a connection has been established. 38 | Identified, 39 | 40 | /// The session is not connected and is not trying to connect. 41 | /// During this state the session will be dropped. This state occurs when a client 42 | /// has completely stopped responding to packets or their socket is destroyed. 43 | /// This is not the same as the [`Disconnected`] state. 44 | /// 45 | /// [`Disconnected`]: crate::connection::state::ConnectionState::Disconnected 46 | Offline, 47 | } 48 | 49 | impl ConnectionState { 50 | /// Returns whether or not the Session is reliable. 51 | /// Reliable sessions are sessions that are not: 52 | /// - Offline 53 | /// - Disconnected 54 | /// - TimingOut 55 | pub fn is_reliable(&self) -> bool { 56 | match self { 57 | Self::Disconnected | Self::TimingOut | Self::Offline => false, 58 | _ => true, 59 | } 60 | } 61 | 62 | /// Returns whether or not the Session is available to recieve 63 | /// packets. Sessions in this state are: 64 | /// - Connected 65 | /// - Connecting 66 | /// - Unidentified 67 | /// - Disconnecting 68 | pub fn is_available(&self) -> bool { 69 | match self { 70 | Self::Connected | Self::Connecting | Self::Unidentified | Self::Disconnecting => true, 71 | _ => false, 72 | } 73 | } 74 | 75 | /// Returns whether or not the Session is in any "connected" state. 76 | /// Sessions in this state are: 77 | /// - Connected 78 | /// - Connecting 79 | pub fn is_connected(&self) -> bool { 80 | match self { 81 | Self::Connected | Self::Connecting => true, 82 | _ => false, 83 | } 84 | } 85 | } 86 | 87 | impl std::fmt::Display for ConnectionState { 88 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 89 | match self { 90 | Self::Connecting => write!(f, "Connecting"), 91 | Self::Connected => write!(f, "Connected"), 92 | Self::TimingOut => write!(f, "TimingOut"), 93 | Self::Disconnecting => write!(f, "Disconnecting"), 94 | Self::Disconnected => write!(f, "Disconnected"), 95 | Self::Unidentified => write!(f, "Unidentified"), 96 | Self::Identified => write!(f, "Identified"), 97 | Self::Offline => write!(f, "Offline"), 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/error/client.rs: -------------------------------------------------------------------------------- 1 | //! Client errors are errors that can occur when using the [`Client`](crate::client::Client) api. 2 | use crate::{client::handshake::HandshakeStatus, connection::queue::SendQueueError}; 3 | 4 | /// These are errors that can occur when using the [`Client`](crate::client::Client) api. 5 | /// These are returned for a variety of reasons, but is commonly used to indicate 6 | /// that something went wrong, and you should either clean up or retry. 7 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] 8 | pub enum ClientError { 9 | /// The client is already connected to the peer on this address. 10 | AddrBindErr, 11 | /// The client is already connected a peer. 12 | AlreadyOnline, 13 | /// The client is offline and can not send packets. 14 | NotListening, 15 | /// The client is unable to connect to the peer. 16 | Unavailable, 17 | /// The client is unable to connect to the peer because the peer is using a different protocol version. 18 | IncompatibleProtocolVersion, 19 | /// The client has been closed. 20 | Killed, 21 | /// The client has been closed, and can not be used again. 22 | Reset, 23 | /// The client is unable to connect to the peer because the peer is offline. 24 | ServerOffline, 25 | /// The client failed to process a packet you sent. 26 | SendQueueError(SendQueueError), 27 | /// The client errored during handshake. 28 | HandshakeError(HandshakeStatus), 29 | } 30 | 31 | impl std::fmt::Display for ClientError { 32 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 33 | write!( 34 | f, 35 | "{}", 36 | match self { 37 | ClientError::AddrBindErr => "Failed to bind to address", 38 | ClientError::AlreadyOnline => "Already online", 39 | ClientError::NotListening => "Not listening", 40 | ClientError::Unavailable => "Unavailable", 41 | ClientError::IncompatibleProtocolVersion => "Incompatible protocol version", 42 | ClientError::Killed => "Killed", 43 | ClientError::Reset => "Reset", 44 | ClientError::ServerOffline => "Server offline", 45 | ClientError::SendQueueError(e) => return e.fmt(f), 46 | ClientError::HandshakeError(e) => return e.fmt(f), 47 | } 48 | ) 49 | } 50 | } 51 | 52 | impl std::error::Error for ClientError {} 53 | -------------------------------------------------------------------------------- /src/error/connection.rs: -------------------------------------------------------------------------------- 1 | //! # Connection Error 2 | //! These error types are used when an error occurs within the [`Connection`]. 3 | //! 4 | //! [`Connection`]: crate::connection::Connection 5 | /// The error type for the [`Connection`]. 6 | /// These are lesser known errors that can occur within the connection. 7 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] 8 | pub enum ConnectionError { 9 | /// The connection has been closed. 10 | Closed, 11 | /// The connection has been closed by the peer. 12 | EventDispatchError, 13 | } 14 | 15 | impl std::fmt::Display for ConnectionError { 16 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 17 | write!( 18 | f, 19 | "{}", 20 | match self { 21 | ConnectionError::Closed => "Connection closed", 22 | ConnectionError::EventDispatchError => "Event dispatch error", 23 | } 24 | ) 25 | } 26 | } 27 | 28 | impl std::error::Error for ConnectionError {} 29 | -------------------------------------------------------------------------------- /src/error/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | pub mod connection; 3 | pub mod server; 4 | -------------------------------------------------------------------------------- /src/error/server.rs: -------------------------------------------------------------------------------- 1 | //! Server errors 2 | //! Server errors are errors that can occur when using the [`Listener`](crate::server::Listener) api. 3 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] 4 | pub enum ServerError { 5 | /// The server is unable to bind to the given address. 6 | AddrBindErr, 7 | /// The server is already online and can not be started again. 8 | AlreadyOnline, 9 | /// The server is offline and can not send packets. 10 | NotListening, 11 | /// The server has been closed. 12 | Killed, 13 | /// The server has been closed, and can not be used again. 14 | Reset, 15 | } 16 | 17 | impl std::fmt::Display for ServerError { 18 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 19 | write!( 20 | f, 21 | "{}", 22 | match self { 23 | ServerError::AddrBindErr => "Unable to bind to address", 24 | ServerError::AlreadyOnline => "Already online", 25 | ServerError::NotListening => "Not listening", 26 | ServerError::Killed => "Killed", 27 | ServerError::Reset => "Reset", 28 | } 29 | ) 30 | } 31 | } 32 | 33 | impl std::error::Error for ServerError {} 34 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # rak-rs 2 | //! 3 | //! A fully functional RakNet implementation in pure rust, asynchronously driven. 4 | //! 5 | //! ## Getting Started 6 | //! 7 | //! RakNet (rak-rs) is available on [crates.io](https://crates.io/crates/rak-rs), to use it, add the following to your `Cargo.toml`: 8 | //! 9 | //! ```toml 10 | //! [dependencies] 11 | //! rak-rs = "0.3.3" 12 | //! ``` 13 | //! 14 | //! ## Features 15 | //! 16 | //! This RakNet implementation comes with 3 primary features, `async_std`, `async_tokio` and `mcpe`. However, by default, only `async_std` is enabled, and `mcpe` requires you to modify your `Cargo.toml`. 17 | //! 18 | //! If you wish to use these features, add them to your `Cargo.toml` as seen below: 19 | //! 20 | //! ```toml 21 | //! [dependencies] 22 | //! rak-rs = { version = "0.3.3", default-features = false, features = [ "async_tokio", "mcpe" ] } 23 | //! ``` 24 | //! 25 | //! 26 | //! 27 | //! rak-rs also provides the following modules: 28 | //! 29 | //! - [`rak_rs::client`](crate::client) - A client implementation of RakNet, allowing you to connect to a RakNet server. 30 | //! - [`rak_rs::connection`](crate::connection) - A bare-bones implementation of a Raknet peer, this is mainly used for types. 31 | //! - [`rak_rs::error`](crate::error) - A module with errors that both the Client and Server can respond with. 32 | //! - [`rak_rs::protocol`](crate::protocol) - A lower level implementation of RakNet, responsible for encoding and decoding packets. 33 | //! - [`rak_rs::server`](crate::server) - The base server implementation of RakNet. 34 | //! - [`rak_rs::util`](crate::util) - General utilities used within `rak-rs`. 35 | //! 36 | //! # Client 37 | //! 38 | //! The `client` module provides a way for you to interact with RakNet servers with code. 39 | //! 40 | //! **Example:** 41 | //! 42 | //! ```ignore 43 | //! use rak_rs::client::{Client, DEFAULT_MTU}; 44 | //! use std::net::ToSocketAddrs; 45 | //! 46 | //! #[async_std::main] 47 | //! async fn main() { 48 | //! let version: u8 = 10; 49 | //! let mut client = Client::new(version, DEFAULT_MTU); 50 | //! 51 | //! client.connect("my_server.net:19132").await.unwrap(); 52 | //! 53 | //! // receive packets 54 | //! loop { 55 | //! let packet = client.recv().await.unwrap(); 56 | //! 57 | //! println!("Received a packet! {:?}", packet); 58 | //! 59 | //! client.send_ord(vec![254, 0, 1, 1], Some(1)); 60 | //! } 61 | //! } 62 | //! 63 | //! ``` 64 | //! 65 | //! # Server 66 | //! 67 | //! A RakNet server implementation in pure rust. 68 | //! 69 | //! **Example:** 70 | //! 71 | //! ```ignore 72 | //! use rakrs::connection::Connection; 73 | //! use rakrs::Listener; 74 | //! use rakrs:: 75 | //! 76 | //! #[async_std::main] 77 | //! async fn main() { 78 | //! let mut server = Listener::bind("0.0.0.0:19132").await.unwrap(); 79 | //! server.start().await.unwrap(); 80 | //! 81 | //! loop { 82 | //! let conn = server.accept().await; 83 | //! async_std::task::spawn(handle(conn.unwrap())); 84 | //! } 85 | //! } 86 | //! 87 | //! async fn handle(mut conn: Connection) { 88 | //! loop { 89 | //! // keeping the connection alive 90 | //! if conn.is_closed() { 91 | //! println!("Connection closed!"); 92 | //! break; 93 | //! } 94 | //! if let Ok(pk) = conn.recv().await { 95 | //! println!("Got a connection packet {:?} ", pk); 96 | //! } 97 | //! } 98 | //! } 99 | //! ``` 100 | /// A client implementation of RakNet, allowing you to connect to a RakNet server. 101 | pub mod client; 102 | /// The connection implementation of RakNet, allowing you to send and receive packets. 103 | /// This is barebones, and you should use the client or server implementations instead, this is mainly 104 | /// used internally. 105 | pub mod connection; 106 | /// The error implementation of RakNet, allowing you to handle errors. 107 | pub mod error; 108 | /// The packet implementation of RakNet. 109 | /// This is a lower level implementation responsible for serializing and deserializing packets. 110 | pub mod protocol; 111 | /// The server implementation of RakNet, allowing you to create a RakNet server. 112 | pub mod server; 113 | /// Utilties for RakNet, like epoch time. 114 | pub mod util; 115 | 116 | pub use protocol::mcpe::{self, motd::Motd}; 117 | pub use server::Listener; 118 | 119 | /// An internal module for notifying the connection of state updates. 120 | pub(crate) mod notify; 121 | -------------------------------------------------------------------------------- /src/notify/async_std.rs: -------------------------------------------------------------------------------- 1 | use async_std::channel::{Receiver, Sender}; 2 | 3 | /// Notify is a struct that wraps a buffer channel 4 | /// these channels are used to send messages to the main thread. 5 | #[derive(Clone)] 6 | pub struct Notify(pub Option>, pub Receiver<()>); 7 | 8 | impl Notify { 9 | /// Creates a new Notify struct. 10 | pub fn new() -> Self { 11 | let (send, recv) = async_std::channel::bounded(1); 12 | Self(Some(send), recv) 13 | } 14 | 15 | /// Sends a message to all listeners. 16 | pub async fn notify(&self) -> bool { 17 | if let Some(sender) = &self.0 { 18 | sender.close(); 19 | true 20 | } else { 21 | false 22 | } 23 | } 24 | 25 | /// Waits for a message from the main thread. 26 | pub async fn wait(&self) -> bool { 27 | if let Err(_) = self.1.recv().await { 28 | false 29 | } else { 30 | true 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/notify/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "async_std")] 2 | mod async_std; 3 | 4 | #[cfg(feature = "tokio")] 5 | mod tokio; 6 | 7 | #[cfg(feature = "async_std")] 8 | pub use self::async_std::Notify; 9 | 10 | #[cfg(feature = "tokio")] 11 | pub use self::tokio::Notify; 12 | -------------------------------------------------------------------------------- /src/notify/tokio.rs: -------------------------------------------------------------------------------- 1 | use tokio::sync::mpsc::{Receiver, Sender}; 2 | use tokio::sync::RwLock; 3 | 4 | /// Notify is a struct that wraps a buffer channel 5 | /// these channels are used to send messages to the main thread. 6 | pub struct Notify(RwLock>>, RwLock>>); 7 | 8 | impl Notify { 9 | /// Creates a new Notify struct. 10 | pub fn new() -> Self { 11 | let (send, recv) = tokio::sync::mpsc::channel(1); 12 | Self(RwLock::new(Some(send)), RwLock::new(Some(recv))) 13 | } 14 | 15 | /// Sends a message to all listeners. 16 | pub async fn notify(&self) -> bool { 17 | let mut sender = self.0.write().await; 18 | if let Some(_) = sender.take() { 19 | true 20 | } else { 21 | false 22 | } 23 | } 24 | 25 | /// Waits for a message from the main thread. 26 | pub async fn wait(&self) -> bool { 27 | let mut receiver = self.1.write().await; 28 | if let Some(receiver) = receiver.as_mut() { 29 | receiver.recv().await; 30 | true 31 | } else { 32 | false 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/protocol/ack.rs: -------------------------------------------------------------------------------- 1 | pub const ACK: u8 = 0xc0; 2 | pub const NACK: u8 = 0xa0; 3 | 4 | use std::ops::Range; 5 | 6 | use binary_util::{ 7 | interfaces::{Reader, Writer}, 8 | types::u24, 9 | BinaryIo, 10 | }; 11 | 12 | pub(crate) trait Ackable { 13 | type NackItem; 14 | 15 | /// When an ack packet is recieved. 16 | /// We should ack the queue 17 | fn ack(&mut self, _: Ack) {} 18 | 19 | /// When an NACK packet is recieved. 20 | /// We should nack the queue 21 | /// This should return the packets that need to be resent. 22 | fn nack(&mut self, _: Ack) -> Vec { 23 | todo!() 24 | } 25 | } 26 | 27 | /// An ack record. 28 | /// A record holds a single or range of acked packets. 29 | /// No real complexity other than that. 30 | #[derive(Debug, Clone, BinaryIo)] 31 | #[repr(u8)] 32 | pub enum Record { 33 | Single(SingleRecord) = 1, 34 | Range(RangeRecord) = 0, 35 | } 36 | 37 | #[derive(Debug, Clone)] 38 | pub struct SingleRecord { 39 | pub sequence: u24, 40 | } 41 | 42 | impl Reader for SingleRecord { 43 | fn read(buf: &mut binary_util::ByteReader) -> Result { 44 | Ok(SingleRecord { 45 | sequence: buf.read_u24_le()?.into(), 46 | }) 47 | } 48 | } 49 | 50 | impl Writer for SingleRecord { 51 | fn write(&self, buf: &mut binary_util::ByteWriter) -> Result<(), std::io::Error> { 52 | buf.write_u24_le(self.sequence)?; 53 | Ok(()) 54 | } 55 | } 56 | 57 | #[derive(Debug, Clone)] 58 | pub struct RangeRecord { 59 | pub start: u24, 60 | pub end: u24, 61 | } 62 | 63 | impl Reader for RangeRecord { 64 | fn read(buf: &mut binary_util::ByteReader) -> Result { 65 | Ok(RangeRecord { 66 | start: buf.read_u24_le()?.into(), 67 | end: buf.read_u24_le()?.into(), 68 | }) 69 | } 70 | } 71 | 72 | impl Writer for RangeRecord { 73 | fn write(&self, buf: &mut binary_util::ByteWriter) -> Result<(), std::io::Error> { 74 | buf.write_u24_le(self.start)?; 75 | buf.write_u24_le(self.end)?; 76 | Ok(()) 77 | } 78 | } 79 | 80 | #[allow(dead_code)] 81 | impl RangeRecord { 82 | /// Fixes the end of the range if it is lower than the start. 83 | pub fn fix(&mut self) { 84 | if self.end < self.start { 85 | std::mem::swap(&mut self.start, &mut self.end); 86 | } 87 | } 88 | } 89 | 90 | #[derive(Debug, Clone)] 91 | pub struct Ack { 92 | pub id: u8, 93 | pub count: u16, 94 | pub records: Vec, 95 | } 96 | 97 | impl Ack { 98 | pub fn new(count: u16, nack: bool, records: Vec) -> Self { 99 | Self { 100 | id: if nack { 0xa0 } else { 0xc0 }, 101 | count, 102 | records: records, 103 | } 104 | } 105 | 106 | pub fn is_nack(&self) -> bool { 107 | self.id == 0xa0 108 | } 109 | 110 | pub fn from_records(mut sequences: Vec, nack: bool) -> Self { 111 | // there at least one record 112 | if sequences.len() > 0 { 113 | // these sequences may not be in order. 114 | sequences.sort_unstable(); 115 | 116 | // however sometimes we need to create a range for each record if the numbers are in order 117 | // this is because the client will send a range if the numbers are in order 118 | let mut ack_records: Vec = Vec::new(); 119 | let mut current_range: Range = 0..0; 120 | 121 | for sequence in sequences.iter() { 122 | // now check if the current range is 0 123 | if current_range.start == 0 && current_range.end == 0 && *sequence != 0 { 124 | // if it is, set the start and end to the current sequence 125 | current_range.start = *sequence; 126 | current_range.end = *sequence; 127 | // skip the rest of the loop 128 | continue; 129 | } 130 | 131 | // first check if the difference is 1 132 | if *sequence == current_range.end + 1 { 133 | current_range.end = *sequence; 134 | // skip the rest of the loop 135 | continue; 136 | } else { 137 | // the difference is not 1, so we need to add the current range to the ack records 138 | // we also need to reset the current range 139 | // before we do this we need to verify the range start and end are not 0 140 | if current_range.start == current_range.end { 141 | // this is a single record 142 | ack_records.push(Record::Single(SingleRecord { 143 | sequence: current_range.start.into(), 144 | })); 145 | } else { 146 | // this is a range record 147 | ack_records.push(Record::Range(RangeRecord { 148 | start: current_range.start.into(), 149 | end: current_range.end.into(), 150 | })); 151 | } 152 | current_range.start = *sequence; 153 | current_range.end = *sequence; 154 | } 155 | } 156 | 157 | // verify last range is not equal to end 158 | if current_range.start == current_range.end { 159 | // this is a single record 160 | ack_records.push(Record::Single(SingleRecord { 161 | sequence: current_range.start.into(), 162 | })); 163 | } else { 164 | // this is a range record 165 | ack_records.push(Record::Range(RangeRecord { 166 | start: current_range.start.into(), 167 | end: current_range.end.into(), 168 | })); 169 | } 170 | 171 | Self::new(ack_records.len() as u16, nack, ack_records) 172 | } else { 173 | // There is only one record, we can just add it as a single record 174 | Self::new(0_u16, nack, Vec::new()) 175 | } 176 | } 177 | } 178 | 179 | impl Writer for Ack { 180 | fn write(&self, buf: &mut binary_util::ByteWriter) -> Result<(), std::io::Error> { 181 | buf.write_u8(self.id)?; 182 | buf.write_u16(self.count)?; 183 | for record in &self.records { 184 | buf.write(record.write_to_bytes()?.as_slice())?; 185 | } 186 | Ok(()) 187 | } 188 | } 189 | 190 | impl Reader for Ack { 191 | fn read(buf: &mut binary_util::ByteReader) -> Result { 192 | let id = buf.read_u8()?; 193 | let count = buf.read_u16()?; 194 | let mut records: Vec = Vec::new(); 195 | 196 | for _ in 0..count { 197 | let record = buf.read_type::()?; 198 | records.push(record); 199 | } 200 | 201 | Ok(Ack { id, count, records }) 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /src/protocol/frame.rs: -------------------------------------------------------------------------------- 1 | use binary_util::{ 2 | interfaces::{Reader, Writer}, 3 | BinaryIo, 4 | }; 5 | 6 | /// The information for the given fragment. 7 | /// This is used to determine how to reassemble the frame. 8 | #[derive(Debug, Clone, BinaryIo)] 9 | pub struct FragmentMeta { 10 | pub(crate) size: u32, 11 | pub(crate) id: u16, 12 | pub(crate) index: u32, 13 | } 14 | 15 | impl FragmentMeta { 16 | /// Creates a new fragment meta with the given size, id, and index. 17 | pub fn new(size: u32, id: u16, index: u32) -> Self { 18 | Self { size, id, index } 19 | } 20 | } 21 | 22 | use crate::rakrs_debug; 23 | 24 | use super::reliability::Reliability; 25 | 26 | /// Frames are a encapsulation of a packet or packets. 27 | /// They are used to send packets to the connection in a reliable way. 28 | #[derive(Debug, Clone)] 29 | pub struct FramePacket { 30 | pub sequence: u32, 31 | pub frames: Vec, 32 | pub reliability: Reliability, 33 | } 34 | 35 | impl FramePacket { 36 | /// Creates an empty frame packet. 37 | pub fn new() -> Self { 38 | Self { 39 | sequence: 0, 40 | frames: Vec::new(), 41 | reliability: Reliability::ReliableOrd, 42 | } 43 | } 44 | } 45 | 46 | impl Reader for FramePacket { 47 | fn read(buf: &mut binary_util::ByteReader) -> Result { 48 | // FRAME PACKET HEADER 49 | let id = buf.read_u8()?; 50 | match id { 51 | 0x80..=0x8d => {} 52 | _ => { 53 | return Err(std::io::Error::new( 54 | std::io::ErrorKind::InvalidData, 55 | "Invalid Frame Packet ID", 56 | )) 57 | } 58 | } 59 | let mut frames: Vec = Vec::new(); 60 | 61 | let sequence = buf.read_u24_le()?; 62 | 63 | loop { 64 | let frame_pos = buf.read_type::(); 65 | if let Ok(frame) = frame_pos { 66 | frames.push(frame); 67 | } else { 68 | break; 69 | } 70 | } 71 | 72 | Ok(FramePacket { 73 | sequence, 74 | frames, 75 | reliability: Reliability::ReliableOrd, 76 | }) 77 | } 78 | } 79 | 80 | impl Writer for FramePacket { 81 | fn write(&self, buf: &mut binary_util::ByteWriter) -> Result<(), std::io::Error> { 82 | buf.write_u8(0x84)?; 83 | buf.write_u24_le(self.sequence)?; 84 | 85 | for frame in &self.frames { 86 | buf.write(frame.write_to_bytes()?.as_slice())?; 87 | } 88 | 89 | Ok(()) 90 | } 91 | } 92 | 93 | /// An individual data frame, these are constructed from a payload. 94 | #[derive(Debug, Clone)] 95 | pub struct Frame { 96 | /// The flags for this frame, the first 3 bits are reserved for the reliability while the 4th 97 | /// bit is used to represent if this is a fragment. 98 | pub flags: u8, 99 | /// The length of the body of the frame. 100 | /// This is sized to 24 bits internally, so any number here must be within that range. 101 | pub size: u16, 102 | /// The Reliable index of the frame (if reliable) 103 | pub reliable_index: Option, 104 | /// The sequenced index of the frame (if sequenced) 105 | /// This is used to determine the position in frame list. 106 | pub sequence_index: Option, 107 | /// The order index of the frame (if ordered) 108 | /// This is used to determine the position in frame list, 109 | /// This is different from the sequence index in that it is 110 | /// used more to sequence packets in a specific manner. 111 | pub order_index: Option, 112 | /// The order channel of the frame (if ordered) 113 | /// This is used to store order information for the frame. 114 | pub order_channel: Option, 115 | /// The information for fragmentation (if the frame is split into parts) 116 | /// This is used to determine how to reassemble the frame. 117 | pub fragment_meta: Option, 118 | /// The reliability of this frame, this is essentially used to save frames and send them back if 119 | /// they are lost. Otherwise, the frame is sent unreliably. 120 | pub reliability: Reliability, 121 | /// The body of the frame, this is the payload of the frame. 122 | pub body: Vec, 123 | } 124 | 125 | impl Frame { 126 | /// Initializes a new empty frame that is Unreliable. 127 | /// This is usually used to inject data into. 128 | pub fn init() -> Self { 129 | Self { 130 | flags: 0, 131 | size: 0, 132 | reliable_index: None, 133 | sequence_index: None, 134 | order_index: None, 135 | order_channel: None, 136 | fragment_meta: None, 137 | reliability: Reliability::Unreliable, 138 | body: Vec::new(), 139 | } 140 | } 141 | 142 | /// Initializes a new frame with the given reliability. 143 | pub fn new(reliability: Reliability, body: Option<&[u8]>) -> Self { 144 | Self { 145 | flags: 0, 146 | size: if let Some(b) = body { 147 | b.len() as u16 148 | } else { 149 | 0 150 | }, 151 | reliable_index: None, 152 | sequence_index: None, 153 | order_index: None, 154 | order_channel: None, 155 | fragment_meta: None, 156 | reliability, 157 | body: body.unwrap_or(&[]).to_vec(), 158 | } 159 | } 160 | 161 | /// Whether or not the frame is fragmented. 162 | pub fn is_fragmented(&self) -> bool { 163 | self.fragment_meta.is_some() 164 | } 165 | 166 | /// Whether or not the frame is sequenced and reliable. 167 | pub fn is_sequenced(&self) -> bool { 168 | self.reliability.is_sequenced() 169 | } 170 | 171 | pub fn with_meta(mut self, meta: FragmentMeta) -> Self { 172 | self.fragment_meta = Some(meta); 173 | self 174 | } 175 | } 176 | 177 | impl Reader for Frame { 178 | fn read(buf: &mut binary_util::ByteReader) -> Result { 179 | let mut frame = Frame::init(); 180 | 181 | frame.flags = buf.read_u8()?; 182 | frame.reliability = Reliability::from_flags(frame.flags); 183 | 184 | let size = buf.read_u16(); 185 | 186 | if let Ok(size) = size { 187 | frame.size = size / 8; 188 | } 189 | 190 | if frame.reliability.is_reliable() { 191 | frame.reliable_index = Some(buf.read_u24_le()?); 192 | } 193 | 194 | if frame.reliability.is_sequenced() { 195 | frame.sequence_index = Some(buf.read_u24_le()?); 196 | } 197 | 198 | if frame.reliability.is_ordered() { 199 | frame.order_index = Some(buf.read_u24_le()?); 200 | frame.order_channel = Some(buf.read_u8()?); 201 | } 202 | 203 | if (frame.flags & 0x10) > 0 { 204 | frame.fragment_meta = Some(FragmentMeta::read(buf)?); 205 | } 206 | 207 | let mut body = vec![0; frame.size as usize]; 208 | 209 | // if let Ok(_) = buf.read(&mut body) { 210 | // frame.body = body.to_vec(); 211 | // println!("Frame body is: {:?}", frame.body); 212 | // } 213 | 214 | match buf.read(&mut body) { 215 | Ok(_) => { 216 | frame.body = body.to_vec(); 217 | // println!("Frame body is: {:?}", frame.body); 218 | } 219 | Err(e) => { 220 | rakrs_debug!(true, "[DECODE_ERR] Error reading frame body: {:?}", e); 221 | } 222 | } 223 | 224 | Ok(frame) 225 | } 226 | } 227 | 228 | impl Writer for Frame { 229 | fn write(&self, buf: &mut binary_util::ByteWriter) -> Result<(), std::io::Error> { 230 | let mut flags = self.reliability.to_flags(); 231 | 232 | // check whether or not this frame is fragmented, if it is, set the fragment flag 233 | if self.fragment_meta.is_some() { 234 | flags |= 0x10; 235 | } 236 | 237 | buf.write_u8(flags)?; 238 | buf.write_u16(self.size * 8)?; 239 | 240 | if self.reliability.is_reliable() { 241 | buf.write_u24_le(self.reliable_index.unwrap_or(0))?; 242 | } 243 | 244 | if self.reliability.is_sequenced() { 245 | buf.write_u24_le(self.sequence_index.unwrap_or(0))?; 246 | } 247 | 248 | if self.reliability.is_ordered() { 249 | buf.write_u24_le(self.order_index.unwrap_or(0))?; 250 | buf.write_u8(self.order_channel.unwrap_or(0))?; 251 | } 252 | 253 | if self.fragment_meta.is_some() { 254 | buf.write( 255 | self.fragment_meta 256 | .as_ref() 257 | .unwrap() 258 | .write_to_bytes()? 259 | .as_slice(), 260 | )?; 261 | } 262 | 263 | buf.write(&self.body)?; 264 | 265 | Ok(()) 266 | } 267 | } 268 | -------------------------------------------------------------------------------- /src/protocol/magic.rs: -------------------------------------------------------------------------------- 1 | use binary_util::interfaces::{Reader, Writer}; 2 | use binary_util::io::{ByteReader, ByteWriter}; 3 | 4 | /// A unique identifier recoginzing the client as offline. 5 | pub(crate) const MAGIC: [u8; 16] = [ 6 | 0x00, 0xff, 0xff, 0x0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfd, 0xfd, 0xfd, 0xfd, 0x12, 0x34, 0x56, 0x78, 7 | ]; 8 | 9 | /// The magic packet is sent to the server to identify the client as offline. 10 | /// This is a special raknet header that uniquely identifies the protocol as raknet. 11 | #[derive(Debug, Clone)] 12 | pub struct Magic; 13 | 14 | impl Magic { 15 | pub fn new() -> Self { 16 | Self {} 17 | } 18 | } 19 | 20 | impl Reader for Magic { 21 | fn read(buf: &mut ByteReader) -> Result { 22 | let mut magic = [0u8; 16]; 23 | buf.read(&mut magic)?; 24 | 25 | if magic != MAGIC { 26 | return Err(std::io::Error::new( 27 | std::io::ErrorKind::InvalidData, 28 | "Invalid magic", 29 | )); 30 | } 31 | 32 | Ok(Magic) 33 | } 34 | } 35 | 36 | impl Writer for Magic { 37 | fn write(&self, buf: &mut ByteWriter) -> Result<(), std::io::Error> { 38 | buf.write(&MAGIC)?; 39 | Ok(()) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/protocol/mcpe/mod.rs: -------------------------------------------------------------------------------- 1 | /// Minecraft has specific protocol for the `UnconnectedPong` packet. 2 | /// This data is attached to the Unconnect Pong packet and is used to 3 | /// display information about the server. 4 | pub mod motd; 5 | 6 | use binary_util::BinaryIo; 7 | 8 | use self::motd::Motd; 9 | 10 | use super::Magic; 11 | 12 | /// This is the MCPE specific implementation of the `UnconnectedPong` packet. 13 | /// The only difference here is the attached motd. 14 | #[derive(Debug, Clone, BinaryIo)] 15 | pub struct UnconnectedPong { 16 | pub timestamp: u64, 17 | pub server_id: u64, 18 | pub magic: Magic, 19 | pub motd: Motd, 20 | } 21 | -------------------------------------------------------------------------------- /src/protocol/mcpe/motd.rs: -------------------------------------------------------------------------------- 1 | use binary_util::interfaces::{Reader, Writer}; 2 | use binary_util::io::{ByteReader, ByteWriter}; 3 | use std::str::FromStr; 4 | 5 | #[repr(u8)] 6 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 7 | pub enum Gamemode { 8 | Survival = 0, 9 | Creative, 10 | Adventure, 11 | Spectator, 12 | } 13 | 14 | impl Gamemode { 15 | pub fn as_str(&self) -> &'static str { 16 | match self { 17 | Gamemode::Survival => "Survival", 18 | Gamemode::Creative => "Creative", 19 | Gamemode::Adventure => "Adventure", 20 | Gamemode::Spectator => "Spectator", 21 | } 22 | } 23 | } 24 | 25 | impl std::fmt::Display for Gamemode { 26 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 27 | let v = match *self { 28 | Gamemode::Survival => "0", 29 | Gamemode::Creative => "1", 30 | Gamemode::Adventure => "2", 31 | Gamemode::Spectator => "3", 32 | }; 33 | write!(f, "{}", v) 34 | } 35 | } 36 | 37 | impl FromStr for Gamemode { 38 | type Err = String; 39 | 40 | fn from_str(s: &str) -> Result { 41 | match s { 42 | "Survival" => Ok(Gamemode::Survival), 43 | "Creative" => Ok(Gamemode::Creative), 44 | "Adventure" => Ok(Gamemode::Adventure), 45 | "Spectator" => Ok(Gamemode::Spectator), 46 | _ => Err(format!("Invalid gamemode {}", s)), 47 | } 48 | } 49 | } 50 | 51 | /// Protocol wise, motd is just a string 52 | /// However we're using this struct to represent the motd 53 | #[derive(Debug, Clone)] 54 | pub struct Motd { 55 | /// The edition of the server (MCPE or MCEE) 56 | pub edition: String, 57 | /// The name of the server 58 | pub name: String, 59 | /// The second line of the server MOTD 60 | pub sub_name: String, 61 | /// The protocol version 62 | pub protocol: u16, 63 | /// The version of the server 64 | pub version: String, 65 | /// The number of players online 66 | pub player_count: u32, 67 | /// The maximum number of players 68 | pub player_max: u32, 69 | /// The gamemode of the server 70 | pub gamemode: Gamemode, 71 | /// The server's GUID 72 | pub server_guid: u64, 73 | /// The server's IPv4 port 74 | pub port: Option, 75 | /// The IPv6 port 76 | // TODO: Implement this 77 | pub ipv6_port: Option, 78 | /// Is Nintendo limited 79 | pub nintendo_limited: Option, 80 | } 81 | 82 | impl Motd { 83 | pub fn new>(server_guid: u64, port: S) -> Self { 84 | Self { 85 | edition: "MCPE".into(), 86 | name: "Netrex Server".into(), 87 | sub_name: "Netrex".into(), 88 | player_count: 10, 89 | player_max: 100, 90 | protocol: 448, 91 | gamemode: Gamemode::Survival, 92 | version: "1.18.0".into(), 93 | server_guid, 94 | port: Some(port.into()), 95 | ipv6_port: Some("19133".into()), 96 | nintendo_limited: Some(false), 97 | } 98 | } 99 | 100 | /// Takes the Motd and parses it into a valid MCPE 101 | /// MOTD buffer. 102 | pub fn write(&self) -> String { 103 | let mut props: Vec = vec![ 104 | self.edition.clone(), 105 | self.name.clone(), 106 | self.protocol.to_string(), 107 | self.version.clone(), 108 | self.player_count.to_string(), 109 | self.player_max.to_string(), 110 | self.server_guid.to_string(), 111 | self.sub_name.clone(), 112 | self.gamemode.as_str().to_string(), 113 | ]; 114 | 115 | if let Some(nintendo_limited) = self.nintendo_limited { 116 | if nintendo_limited { 117 | props.push("0".into()); 118 | } else { 119 | props.push("1".into()); 120 | } 121 | } 122 | 123 | if let Some(port) = &self.port { 124 | props.push(port.clone()); 125 | } 126 | 127 | if let Some(ipv6_port) = &self.ipv6_port { 128 | props.push(ipv6_port.clone()); 129 | } 130 | 131 | props.join(";").into() 132 | } 133 | } 134 | 135 | impl Reader for Motd { 136 | fn read(buf: &mut ByteReader) -> Result { 137 | let str_len = buf.read_u16()?; 138 | let mut str_buf = vec![0; str_len as usize]; 139 | 140 | buf.read(&mut str_buf)?; 141 | 142 | let motd = String::from_utf8(str_buf).unwrap(); 143 | let parts = motd 144 | .split(";") 145 | .map(|c| c.to_string()) 146 | .collect::>(); 147 | 148 | let edition = parts 149 | .get(0) 150 | .ok_or(std::io::Error::new( 151 | std::io::ErrorKind::InvalidData, 152 | "Invalid motd edition", 153 | ))? 154 | .clone(); 155 | 156 | let name = parts 157 | .get(1) 158 | .ok_or(std::io::Error::new( 159 | std::io::ErrorKind::InvalidData, 160 | "Invalid motd name", 161 | ))? 162 | .clone(); 163 | 164 | let protocol = parts 165 | .get(2) 166 | .ok_or(std::io::Error::new( 167 | std::io::ErrorKind::InvalidData, 168 | "Invalid motd protocol", 169 | ))? 170 | .clone(); 171 | 172 | let version = parts 173 | .get(3) 174 | .ok_or(std::io::Error::new( 175 | std::io::ErrorKind::InvalidData, 176 | "Invalid motd version", 177 | ))? 178 | .clone(); 179 | 180 | let player_count = parts 181 | .get(4) 182 | .ok_or(std::io::Error::new( 183 | std::io::ErrorKind::InvalidData, 184 | "Invalid motd player count", 185 | ))? 186 | .clone(); 187 | 188 | let player_max = parts 189 | .get(5) 190 | .ok_or(std::io::Error::new( 191 | std::io::ErrorKind::InvalidData, 192 | "Invalid motd player max", 193 | ))? 194 | .clone(); 195 | 196 | let server_guid = parts 197 | .get(6) 198 | .ok_or(std::io::Error::new( 199 | std::io::ErrorKind::InvalidData, 200 | "Invalid motd server guid", 201 | ))? 202 | .clone(); 203 | 204 | let sub_name = parts 205 | .get(7) 206 | .ok_or(std::io::Error::new( 207 | std::io::ErrorKind::InvalidData, 208 | "Invalid motd sub name", 209 | ))? 210 | .clone(); 211 | 212 | let gamemode = parts 213 | .get(8) 214 | .ok_or(std::io::Error::new( 215 | std::io::ErrorKind::InvalidData, 216 | "Invalid motd gamemode", 217 | ))? 218 | .clone(); 219 | 220 | // now optional fields 221 | let nintendo_limited = parts.get(9).map(|c| c.clone()); 222 | 223 | let port = parts.get(10).map(|c| c.clone()); 224 | 225 | let ipv6_port = parts.get(11).map(|c| c.clone()); 226 | 227 | Ok(Motd { 228 | edition, 229 | name, 230 | protocol: protocol.as_str().parse().unwrap(), 231 | version, 232 | player_count: player_count.parse().unwrap(), 233 | player_max: player_max.parse().unwrap(), 234 | server_guid: server_guid.parse().unwrap(), 235 | sub_name, 236 | gamemode: Gamemode::from_str(&gamemode).unwrap_or(Gamemode::Survival), 237 | nintendo_limited: nintendo_limited.map(|c| if c == "0" { true } else { false }), 238 | port, 239 | ipv6_port, 240 | }) 241 | } 242 | // fn read(buf: &mut ByteReader) -> Result { 243 | // let str_len = buf.read_u16()?; 244 | // let mut str_buf = vec![0; str_len as usize]; 245 | 246 | // buf.read(&mut str_buf)?; 247 | 248 | // let motd = String::from_utf8(str_buf).unwrap(); 249 | 250 | // let parts = motd 251 | // .split(";") 252 | // .map(|c| c.to_string()) 253 | // .collect::>(); 254 | 255 | // let edition = parts 256 | // .get(0) 257 | // .ok_or(std::io::Error::new( 258 | // std::io::ErrorKind::InvalidData, 259 | // "Invalid motd edition", 260 | // ))? 261 | // .clone(); 262 | 263 | // let name = parts 264 | // .get(1) 265 | // .ok_or(std::io::Error::new( 266 | // std::io::ErrorKind::InvalidData, 267 | // "Invalid motd name", 268 | // ))? 269 | // .clone(); 270 | 271 | // let protocol = parts 272 | // .get(2) 273 | // .ok_or(std::io::Error::new( 274 | // std::io::ErrorKind::InvalidData, 275 | // "Invalid motd protocol", 276 | // ))? 277 | // .clone(); 278 | 279 | // let version = parts 280 | // .get(3) 281 | // .ok_or(std::io::Error::new( 282 | // std::io::ErrorKind::InvalidData, 283 | // "Invalid motd version", 284 | // ))? 285 | // .clone(); 286 | 287 | // let player_count = parts 288 | // .get(4) 289 | // .ok_or(std::io::Error::new( 290 | // std::io::ErrorKind::InvalidData, 291 | // "Invalid motd player count", 292 | // ))? 293 | // .clone(); 294 | 295 | // let player_max = parts 296 | // .get(5) 297 | // .ok_or(std::io::Error::new( 298 | // std::io::ErrorKind::InvalidData, 299 | // "Invalid motd player max", 300 | // ))? 301 | // .clone(); 302 | 303 | // let server_guid = parts 304 | // .get(6) 305 | // .ok_or(std::io::Error::new( 306 | // std::io::ErrorKind::InvalidData, 307 | // "Invalid motd server guid", 308 | // ))? 309 | // .clone(); 310 | 311 | // let sub_name = parts 312 | // .get(7) 313 | // .ok_or(std::io::Error::new( 314 | // std::io::ErrorKind::InvalidData, 315 | // "Invalid motd sub name", 316 | // ))? 317 | // .clone(); 318 | 319 | // let gamemode = parts 320 | // .get(8) 321 | // .ok_or(std::io::Error::new( 322 | // std::io::ErrorKind::InvalidData, 323 | // "Invalid motd gamemode", 324 | // ))? 325 | // .clone(); 326 | 327 | // let nintendo_limited = parts 328 | // .get(9) 329 | // .ok_or(std::io::Error::new( 330 | // std::io::ErrorKind::InvalidData, 331 | // "Invalid motd nintendo limited", 332 | // ))? 333 | // .clone(); 334 | 335 | // let port = parts 336 | // .get(10) 337 | // .ok_or(std::io::Error::new( 338 | // std::io::ErrorKind::InvalidData, 339 | // "Invalid motd port", 340 | // ))? 341 | // .clone(); 342 | 343 | // let ipv6_port = parts 344 | // .get(11) 345 | // .ok_or(std::io::Error::new( 346 | // std::io::ErrorKind::InvalidData, 347 | // "Invalid motd ipv6 port", 348 | // ))? 349 | // .clone(); 350 | 351 | // Ok(Motd { 352 | // edition, 353 | // name, 354 | // protocol: protocol.as_str().parse().unwrap(), 355 | // version, 356 | // player_count: player_count.parse().unwrap(), 357 | // player_max: player_max.parse().unwrap(), 358 | // server_guid: server_guid.parse().unwrap(), 359 | // sub_name, 360 | // gamemode: Gamemode::from_str(&gamemode).unwrap_or(Gamemode::Survival), 361 | // nintendo_limited: if nintendo_limited == "0" { true } else { false }, 362 | // port, 363 | // ipv6_port, 364 | // }) 365 | // } 366 | } 367 | 368 | impl Writer for Motd { 369 | fn write(&self, buf: &mut ByteWriter) -> Result<(), std::io::Error> { 370 | let motd = self.write(); 371 | let motd_len = motd.len() as u16; 372 | buf.write_u16(motd_len)?; 373 | buf.write(motd.as_bytes())?; 374 | Ok(()) 375 | } 376 | } 377 | -------------------------------------------------------------------------------- /src/protocol/mod.rs: -------------------------------------------------------------------------------- 1 | //! Protocol implementation for RakNet. 2 | //! this module contains all of the necessary packets to communicate with RakNet servers. 3 | //! 4 | //! ## Example 5 | //! Please note this example is not a copy-paste example, but rather a snippet of code 6 | //! that shows how to use the [`protocol`] module. 7 | //! 8 | //! ```rust ignore 9 | //! use rakrs::protocol::packet::RakPacket; 10 | //! use binary_util::BinaryIo; 11 | //! 12 | //! fn decode_packet(packet: &[u8]) { 13 | //! let packet = RakPacket::read_from_slice(packet).unwrap(); 14 | //! 15 | //! match packet { 16 | //! RakPacket::Offline(packet) => match packet { 17 | //! OfflinePacket::UnconnectedPing(packet) => { 18 | //! println!("Received a ping packet! {:?}", packet); 19 | //! }, 20 | //! _ => {} 21 | //! }, 22 | //! _ => {} 23 | //! } 24 | //! }; 25 | //! ``` 26 | /// This is an internal module that contains the logic to implement the Ack system within 27 | /// RakNet. 28 | pub(crate) mod ack; 29 | /// This is an internal module that contains the logic to implement the frame system within 30 | /// RakNet. This is also called the "Datagram" or "Encapsulated" packet in different implementations. 31 | /// 32 | /// You can find the original implementation from RakNet [here](https://github.com/facebookarchive/RakNet/blob/1a169895a900c9fc4841c556e16514182b75faf8/Source/ReliabilityLayer.cpp#L110-L231) 33 | // pub(crate) mod frame; 34 | pub mod frame; 35 | /// This is the constant added to all offline packets to identify them as RakNet packets. 36 | pub(crate) mod magic; 37 | /// This module contains the MCPE specific packets that are used within RakNet, this is guarded 38 | /// under the `mcpe` feature. 39 | /// 40 | /// To enable this feature, add the following to your `Cargo.toml`: 41 | /// ```toml 42 | /// [dependencies] 43 | /// rak-rs = { version = "0.1.0", features = [ "mcpe" ] } 44 | /// ``` 45 | pub mod mcpe; 46 | pub mod packet; 47 | pub mod reliability; 48 | 49 | pub use magic::*; 50 | 51 | /// The maximum amount of fragments that can be sent within a single frame. 52 | /// This constant is used to prevent a client from sending too many fragments, 53 | /// or from bad actors from sending too many fragments. 54 | pub const MAX_FRAGS: u32 = 1024; 55 | /// The maximum amount of channels that can be used on a single connection. 56 | /// This is a raknet limitation, and is not configurable. 57 | pub const MAX_ORD_CHANS: u8 = 32; 58 | 59 | /// IP Header + UDP Header + RakNet Header + RakNet Frame Packet Header (MAX) 60 | pub const RAKNET_HEADER_FRAME_OVERHEAD: u16 = 20 + 8 + 8 + 4 + 20; 61 | /// IP Header + UDP Header + RakNet Header 62 | pub const RAKNET_HEADER_OVERHEAD: u16 = 20 + 8 + 8; 63 | 64 | /// The maximum possible amount of bytes that can be sent within a single frame. 65 | pub const MTU_MAX: u16 = 2400; 66 | /// The minimum possible amount of bytes that can be sent within a single frame. 67 | pub const MTU_MIN: u16 = 400; 68 | -------------------------------------------------------------------------------- /src/protocol/packet/mod.rs: -------------------------------------------------------------------------------- 1 | //! This module contains all the packets that are used by the RakNet protocol. 2 | //! This module is split into two submodules: 3 | //! - [`offline`]: Any packet that is not sent within a [`Frame`]. 4 | //! - [`online`]: Any packet considered to be online, which is sent within a [`Frame`]. 5 | //! 6 | //! [`offline`]: crate::protocol::packet::offline 7 | //! [`online`]: crate::protocol::packet::online 8 | // /// Handlers for both online & offline packets! 9 | // /// This is used by the connection struct to handle packets. 10 | // pub(crate) mod handler; 11 | 12 | pub mod offline; 13 | pub mod online; 14 | 15 | use binary_util::interfaces::{Reader, Writer}; 16 | 17 | use self::offline::OfflinePacket; 18 | use self::online::OnlinePacket; 19 | 20 | /// A wrapper or helper for both online and offline packets. 21 | /// This allows for a single type to be read with `Reader` and written with `Writer`, 22 | /// traits provided by `binary_util`. 23 | /// 24 | /// All packets sent are wrapped in this type, and can be unwrapped with the `get_offline` or `get_online` 25 | #[derive(Debug, Clone)] 26 | pub enum RakPacket { 27 | Offline(OfflinePacket), 28 | Online(OnlinePacket), 29 | } 30 | 31 | impl RakPacket { 32 | pub fn is_online(&self) -> bool { 33 | match self { 34 | RakPacket::Online(_) => true, 35 | _ => false, 36 | } 37 | } 38 | 39 | pub fn get_offline(&self) -> Option<&OfflinePacket> { 40 | match self { 41 | RakPacket::Offline(packet) => Some(packet), 42 | _ => None, 43 | } 44 | } 45 | 46 | pub fn get_online(&self) -> Option<&OnlinePacket> { 47 | match self { 48 | RakPacket::Online(packet) => Some(packet), 49 | _ => None, 50 | } 51 | } 52 | } 53 | 54 | impl Writer for RakPacket { 55 | fn write(&self, buf: &mut binary_util::io::ByteWriter) -> Result<(), std::io::Error> { 56 | match self { 57 | RakPacket::Offline(packet) => packet.write(buf), 58 | RakPacket::Online(packet) => packet.write(buf), 59 | } 60 | } 61 | } 62 | 63 | impl Reader for RakPacket { 64 | fn read(buf: &mut binary_util::ByteReader) -> Result { 65 | if let Ok(packet) = OfflinePacket::read(buf) { 66 | return Ok(RakPacket::Offline(packet)); 67 | } 68 | if let Ok(packet) = OnlinePacket::read(buf) { 69 | return Ok(RakPacket::Online(packet)); 70 | } 71 | 72 | Err(std::io::Error::new( 73 | std::io::ErrorKind::InvalidData, 74 | "Invalid packet", 75 | )) 76 | } 77 | } 78 | 79 | impl From for RakPacket { 80 | fn from(packet: OfflinePacket) -> Self { 81 | RakPacket::Offline(packet) 82 | } 83 | } 84 | 85 | impl From for RakPacket { 86 | fn from(packet: OnlinePacket) -> Self { 87 | RakPacket::Online(packet) 88 | } 89 | } 90 | 91 | impl From for OnlinePacket { 92 | fn from(packet: RakPacket) -> Self { 93 | match packet { 94 | RakPacket::Online(packet) => packet, 95 | _ => panic!("Invalid packet conversion"), 96 | } 97 | } 98 | } 99 | 100 | impl From for OfflinePacket { 101 | fn from(packet: RakPacket) -> Self { 102 | match packet { 103 | RakPacket::Offline(packet) => packet, 104 | _ => panic!("Invalid packet conversion"), 105 | } 106 | } 107 | } 108 | 109 | /// A utility macro that adds the implementation for any `OnlinePacket(Pk)` where 110 | /// `Pk` can be converted to `RakPacket`, `OnlinePacket` or `OfflinePacket` 111 | /// and vice versa. 112 | /// 113 | /// For example, we want unconnected pong to be unwrapped, we can do this without 114 | /// a match statement like this: 115 | /// ```rust ignore 116 | /// use raknet::packet::RakPacket; 117 | /// use raknet::packet::online::OnlinePacket; 118 | /// use raknet::packet::online::UnconnectedPing; 119 | /// let some_packet = RakPacket::from(&source)?; 120 | /// let connected_ping: UnconnectedPing = some_packet.into(); 121 | /// ``` 122 | /// 123 | /// This macro also allows for converting any `OnlinePacket(Pk)` to a `RakPacket`, where `Pk` can 124 | /// be directly converted into a packet. For example: 125 | /// ```rust ignore 126 | /// use raknet::packet::Packet; 127 | /// use raknet::packet::online::OnlinePacket; 128 | /// use raknet::packet::online::UnconnectedPong; 129 | /// 130 | /// let packet: Packet = UnconnectedPong { 131 | /// magic: Magic::new(), 132 | /// timestamp: SystemTime::now(), 133 | /// client_id: -129 134 | /// }.into(); 135 | /// ``` 136 | /// 137 | /// The macro can be expressed in the following way: 138 | /// ```rust ignore 139 | /// register_packets! { 140 | /// Online is OnlinePacket, 141 | /// UnconnectedPing, 142 | /// // etc... 143 | /// } 144 | /// ``` 145 | #[macro_export] 146 | macro_rules! register_packets { 147 | ($name: ident is $kind: ident, $($packet: ident),*) => { 148 | $( 149 | impl From<$packet> for $kind { 150 | fn from(packet: $packet) -> Self { 151 | $kind::$packet(packet) 152 | } 153 | } 154 | 155 | impl From<$packet> for RakPacket { 156 | fn from(packet: $packet) -> Self { 157 | $kind::$packet(packet).into() 158 | } 159 | } 160 | 161 | impl From<$kind> for $packet { 162 | fn from(packet: $kind) -> Self { 163 | match packet { 164 | $kind::$packet(packet) => packet.into(), 165 | _ => panic!("Invalid packet conversion"), 166 | } 167 | } 168 | } 169 | 170 | impl From for $packet { 171 | fn from(packet: RakPacket) -> Self { 172 | match packet { 173 | RakPacket::$name(packet) => packet.into(), 174 | _ => panic!("Invalid packet conversion"), 175 | } 176 | } 177 | } 178 | )* 179 | }; 180 | } 181 | -------------------------------------------------------------------------------- /src/protocol/packet/offline.rs: -------------------------------------------------------------------------------- 1 | //! Offline packets are packets that are sent before a connection is established. 2 | //! In rak-rs, these packets consist of: 3 | //! - [`UnconnectedPing`] 4 | //! - [`UnconnectedPong`] 5 | //! - [`OpenConnectRequest`] 6 | //! - [`OpenConnectReply`] 7 | //! - [`SessionInfoRequest`] 8 | //! - [`SessionInfoReply`] 9 | //! - [`IncompatibleProtocolVersion`] 10 | //! 11 | //! During this stage, the client and server are exchanging information about each other, such as 12 | //! the server id, the client id, the mtu size, etc, to prepare for the connection handshake. 13 | use std::net::SocketAddr; 14 | 15 | use super::RakPacket; 16 | #[cfg(feature = "mcpe")] 17 | pub use crate::protocol::mcpe::UnconnectedPong; 18 | use crate::protocol::Magic; 19 | use crate::protocol::RAKNET_HEADER_FRAME_OVERHEAD; 20 | use crate::register_packets; 21 | 22 | use binary_util::interfaces::{Reader, Writer}; 23 | use binary_util::io::{ByteReader, ByteWriter}; 24 | use binary_util::BinaryIo; 25 | 26 | /// This is an enum of all offline packets. 27 | /// 28 | /// You can use this to read and write offline packets, 29 | /// with the `binary_util` traits `Reader` and `Writer`. 30 | #[derive(Clone, Debug, BinaryIo)] 31 | #[repr(u8)] 32 | pub enum OfflinePacket { 33 | UnconnectedPing(UnconnectedPing) = 0x01, 34 | UnconnectedPong(UnconnectedPong) = 0x1c, 35 | OpenConnectRequest(OpenConnectRequest) = 0x05, 36 | OpenConnectReply(OpenConnectReply) = 0x06, 37 | SessionInfoRequest(SessionInfoRequest) = 0x07, 38 | SessionInfoReply(SessionInfoReply) = 0x08, 39 | IncompatibleProtocolVersion(IncompatibleProtocolVersion) = 0x19, 40 | } 41 | 42 | register_packets! { 43 | Offline is OfflinePacket, 44 | UnconnectedPing, 45 | UnconnectedPong, 46 | OpenConnectRequest, 47 | OpenConnectReply, 48 | SessionInfoRequest, 49 | SessionInfoReply, 50 | IncompatibleProtocolVersion 51 | } 52 | 53 | /// Send to the other peer expecting a [`UnconnectedPong`] packet, 54 | /// this is used to determine the latency between the client and the server, 55 | /// and to determine if the server is online. 56 | /// 57 | /// If the peer does not respond with a [`UnconnectedPong`] packet, the iniatior should 58 | /// expect that the server is offline. 59 | #[derive(Debug, Clone, BinaryIo)] 60 | pub struct UnconnectedPing { 61 | pub timestamp: u64, 62 | pub magic: Magic, 63 | pub client_id: i64, 64 | } 65 | 66 | /// Sent in response to a [`UnconnectedPing`] packet. 67 | /// This is used to determine the latency between the client and the server, and to determine 68 | /// that the peer is online. 69 | /// 70 | /// 93 | ///
94 | /// Note: 95 | ///

96 | /// If the client is a Minecraft: Bedrock Edition client, this packet is not sent 97 | /// and the 98 | /// 101 | /// UnconnectedPong 102 | /// 103 | /// from the mcpe module is sent instead. 104 | ///

105 | ///
106 | /// 107 | /// [`UnconnectedPong`]: crate::protocol::packet::offline::UnconnectedPong 108 | #[cfg(not(feature = "mcpe"))] 109 | #[derive(Debug, Clone, BinaryIo)] 110 | pub struct UnconnectedPong { 111 | pub timestamp: u64, 112 | pub server_id: u64, 113 | pub magic: Magic, 114 | } 115 | 116 | /// This packet is the equivelant of the `OpenConnectRequest` packet in RakNet. 117 | /// 118 | /// This packet is sent by the peer to a server to request a connection. 119 | /// It contains information about the client, such as the protocol version, and the mtu size. 120 | /// The peer should expect a [`OpenConnectReply`] packet in response to this packet, if the 121 | /// server accepts the connection. Otherwise, the peer should expect a [`IncompatibleProtocolVersion`] 122 | /// packet to be sent to indicate that the server does not support the protocol version. 123 | /// 124 | /// 147 | ///
148 | /// Note: 149 | ///

150 | /// Internally this packet is padded by the given 151 | /// mtu_size in the packet. This is done by appending null bytes 152 | /// to the current buffer of the packet which is calculated by adding the difference 153 | /// between the mtu_size and the current length. 154 | ///

155 | ///
156 | #[derive(Debug, Clone)] 157 | pub struct OpenConnectRequest { 158 | pub protocol: u8, // 9 159 | pub mtu_size: u16, // 500 160 | } 161 | 162 | impl Reader for OpenConnectRequest { 163 | fn read(buf: &mut ByteReader) -> Result { 164 | let len = buf.as_slice().len(); 165 | buf.read_type::()?; 166 | Ok(OpenConnectRequest { 167 | protocol: buf.read_u8()?, 168 | mtu_size: (len + RAKNET_HEADER_FRAME_OVERHEAD as usize) as u16, 169 | }) 170 | } 171 | } 172 | 173 | impl Writer for OpenConnectRequest { 174 | fn write(&self, buf: &mut ByteWriter) -> Result<(), std::io::Error> { 175 | buf.write_type::(&Magic::new())?; 176 | buf.write_u8(self.protocol)?; 177 | // padding 178 | // remove 28 bytes from the mtu size 179 | let mtu_size = self.mtu_size - RAKNET_HEADER_FRAME_OVERHEAD as u16; 180 | for _ in 0..mtu_size { 181 | buf.write_u8(0)?; 182 | } 183 | Ok(()) 184 | } 185 | } 186 | 187 | // Open Connection Reply 188 | /// This packet is sent in response to a [`OpenConnectRequest`] packet, and confirms 189 | /// the information sent by the peer in the [`OpenConnectRequest`] packet. 190 | /// 191 | /// This packet is the equivalent of the `Open Connect Reply 1` within the original RakNet implementation. 192 | /// 193 | /// If the server chooses to deny the connection, it should send a [`IncompatibleProtocolVersion`] 194 | /// or ignore the packet. 195 | #[derive(Debug, Clone, BinaryIo)] 196 | pub struct OpenConnectReply { 197 | pub magic: Magic, 198 | pub server_id: u64, 199 | pub security: bool, 200 | pub mtu_size: u16, 201 | } 202 | 203 | /// This packet is sent after receiving a [`OpenConnectReply`] packet, and confirms 204 | /// that the peer wishes to proceed with the connection. The information within this packet 205 | /// is primarily used to get the external address of the peer. 206 | /// 207 | /// This packet is the equivalent of the `Open Connect Request 2` within the original RakNet implementation. 208 | #[derive(Debug, Clone, BinaryIo)] 209 | pub struct SessionInfoRequest { 210 | pub magic: Magic, 211 | /// The socket address of the peer you are sending 212 | /// this packet to. 213 | pub address: SocketAddr, 214 | /// The mtu size of the peer you are sending this packet to. 215 | pub mtu_size: u16, 216 | /// Your internal client id. 217 | pub client_id: i64, 218 | } 219 | 220 | /// This packet is sent in response to a [`SessionInfoRequest`] packet, and confirms 221 | /// all the information sent by the peer in the [`SessionInfoRequest`] packet. This packet 222 | /// also specifies the external address of the peer, as well as whether or not 223 | /// encryption at the RakNet level is enabled on the server. 224 | /// 225 | /// This packet is the equivalent of the `Open Connect Reply 2` within the original RakNet implementation. 226 | #[derive(Debug, Clone, BinaryIo)] 227 | pub struct SessionInfoReply { 228 | pub magic: Magic, 229 | pub server_id: u64, 230 | pub client_address: SocketAddr, 231 | pub mtu_size: u16, 232 | pub security: bool, 233 | } 234 | 235 | /// This packet is sent by the server to indicate that the server does not support the 236 | /// protocol version of the client. 237 | #[derive(Debug, Clone, BinaryIo)] 238 | pub struct IncompatibleProtocolVersion { 239 | pub protocol: u8, 240 | pub magic: Magic, 241 | pub server_id: u64, 242 | } 243 | -------------------------------------------------------------------------------- /src/protocol/packet/online.rs: -------------------------------------------------------------------------------- 1 | //! Online packets are packets that are sent when the client is connected to the server 2 | //! and are used to keep the connection alive, and to send game packets to the server. 3 | //! 4 | //! The following module provides the following packets: 5 | //! - [`ConnectedPing`] 6 | //! - [`ConnectedPong`] 7 | //! - [`LostConnection`] 8 | //! - [`ConnectionRequest`] 9 | //! - [`ConnectionAccept`] 10 | //! - [`NewConnection`] 11 | //! - [`Disconnect`] 12 | //! 13 | //! During this stage, the client and server are exchanging information about each other, 14 | //! to initialize the connection within raknet, and completing the connection handshake. 15 | use std::net::SocketAddr; 16 | 17 | use super::RakPacket; 18 | use crate::register_packets; 19 | 20 | use binary_util::interfaces::{Reader, Writer}; 21 | use binary_util::io::{ByteReader, ByteWriter}; 22 | use binary_util::BinaryIo; 23 | 24 | /// An enum of all Online packets. 25 | /// 26 | /// You can use this to read and write online packets, 27 | /// with the `binary_util` traits `Reader` and `Writer`. 28 | #[derive(BinaryIo, Clone, Debug)] 29 | #[repr(u8)] 30 | pub enum OnlinePacket { 31 | ConnectedPing(ConnectedPing) = 0x00, 32 | ConnectedPong(ConnectedPong) = 0x03, 33 | LostConnection(LostConnection) = 0x04, 34 | ConnectionRequest(ConnectionRequest) = 0x09, 35 | ConnectionAccept(ConnectionAccept) = 0x10, 36 | NewConnection(NewConnection) = 0x13, 37 | Disconnect(Disconnect) = 0x15, 38 | } 39 | 40 | register_packets! { 41 | Online is OnlinePacket, 42 | ConnectedPing, 43 | ConnectedPong, 44 | LostConnection, 45 | ConnectionRequest, 46 | ConnectionAccept, 47 | NewConnection, 48 | Disconnect 49 | } 50 | 51 | /// This packet is sent by either the client or the server to the other peer. 52 | /// The other peer should respond with a [`ConnectedPong`] packet. In general 53 | /// you should be sending this packet every 5 seconds to keep the connection alive. 54 | ///
55 | ///
56 | /// If you do not continue to send this packet, the connection will be closed after 57 | /// the other peer does not receive a [`ConnectedPong`] packet for the configured timeout option. 58 | #[derive(Clone, Debug, BinaryIo)] 59 | pub struct ConnectedPing { 60 | /// The time you sent the packet to the peer. 61 | pub time: i64, 62 | } 63 | 64 | /// Sent in response to a [`ConnectedPing`] packet. 65 | /// 66 | /// This packet is sent by the other peer in response to a [`ConnectedPing`] packet as 67 | /// an acknowledgement that the connection is still alive. It contains the time of the 68 | /// round trip from the time that the initiator sent the [`ConnectedPing`] packet. 69 | #[derive(Clone, Debug, BinaryIo)] 70 | pub struct ConnectedPong { 71 | /// The time that the peer sent the [`ConnectedPing`] packet. 72 | pub ping_time: i64, 73 | /// The time that you sent the [`ConnectedPong`] packet to the peer. 74 | pub pong_time: i64, 75 | } 76 | 77 | /// A connection Request Request, this contains information about the client. Like it's 78 | /// current time and the client id. 79 | #[derive(Clone, Debug, BinaryIo)] 80 | pub struct ConnectionRequest { 81 | pub client_id: i64, 82 | pub time: i64, 83 | pub security: bool, 84 | } 85 | 86 | /// A connection Accept packet, this is sent by the server to the client. 87 | /// This is sent by the server and contains information about the server. 88 | #[derive(Clone, Debug)] 89 | pub struct ConnectionAccept { 90 | /// The address of the client connecting (locally?). 91 | pub client_address: SocketAddr, 92 | /// The system index of the server. 93 | pub system_index: i16, 94 | /// The internal id's of the server or alternative IP's of the server. 95 | /// These are addresses the client will use if it can't connect to the server. 96 | /// (Not sure why this is useful) 97 | pub internal_ids: Vec, 98 | /// The time of the timestamp the client sent with `ConnectionRequest`. 99 | pub request_time: i64, 100 | /// The time on the server. 101 | pub timestamp: i64, 102 | } 103 | 104 | impl Reader for ConnectionAccept { 105 | fn read(buf: &mut ByteReader) -> std::io::Result { 106 | let client_address = buf.read_type::()?; 107 | 108 | // read the system index, this is 109 | let system_index = buf.read_i16()?; 110 | let mut internal_ids = Vec::::new(); 111 | 112 | for _ in 0..20 { 113 | // we only have the request time and timestamp left... 114 | if buf.as_slice().len() <= 16 { 115 | break; 116 | } 117 | internal_ids.push(buf.read_type::()?); 118 | } 119 | 120 | let request_time = buf.read_i64()?; 121 | let timestamp = buf.read_i64()?; 122 | 123 | Ok(Self { 124 | client_address, 125 | system_index, 126 | internal_ids, 127 | request_time, 128 | timestamp, 129 | }) 130 | } 131 | } 132 | 133 | impl Writer for ConnectionAccept { 134 | fn write(&self, buf: &mut ByteWriter) -> std::io::Result<()> { 135 | buf.write_type::(&self.client_address)?; 136 | buf.write_i16(self.system_index)?; 137 | 138 | if self.internal_ids.len() > 20 { 139 | return Err(std::io::Error::new( 140 | std::io::ErrorKind::InvalidInput, 141 | "Too many internal id's", 142 | )); 143 | } 144 | 145 | for internal_id in &self.internal_ids { 146 | buf.write_type::(internal_id)?; 147 | } 148 | 149 | buf.write_i64(self.request_time)?; 150 | buf.write_i64(self.timestamp)?; 151 | 152 | Ok(()) 153 | } 154 | } 155 | 156 | /// Going to be completely Honest here, I have no idea what this is used for right now, 157 | /// even after reading the source code. 158 | #[derive(Clone, Debug)] 159 | pub struct NewConnection { 160 | /// The external IP Address of the server. 161 | pub server_address: SocketAddr, 162 | /// The internal IP Address of the server. 163 | pub system_address: Vec, 164 | /// The time of the timestamp the client sent with `ConnectionRequest`. 165 | pub request_time: i64, 166 | /// The time on the server. 167 | pub timestamp: i64, 168 | } 169 | 170 | impl Reader for NewConnection { 171 | fn read(buf: &mut ByteReader) -> std::io::Result { 172 | let server_address = buf.read_type::()?; 173 | 174 | let mut system_address = Vec::::new(); 175 | 176 | for _ in 0..20 { 177 | // we only have the request time and timestamp left... 178 | if buf.as_slice().len() < 16 { 179 | break; 180 | } 181 | system_address.push(buf.read_type::()?); 182 | } 183 | 184 | let request_time = buf.read_i64()?; 185 | let timestamp = buf.read_i64()?; 186 | 187 | Ok(Self { 188 | server_address, 189 | system_address, 190 | request_time, 191 | timestamp, 192 | }) 193 | } 194 | } 195 | 196 | impl Writer for NewConnection { 197 | fn write(&self, buf: &mut ByteWriter) -> std::io::Result<()> { 198 | buf.write_type::(&self.server_address)?; 199 | 200 | if self.system_address.len() > 20 { 201 | return Err(std::io::Error::new( 202 | std::io::ErrorKind::InvalidInput, 203 | "Too many internal id's", 204 | )); 205 | } 206 | 207 | for system_address in &self.system_address { 208 | buf.write_type::(system_address)?; 209 | } 210 | 211 | buf.write_i64(self.request_time)?; 212 | buf.write_i64(self.timestamp)?; 213 | 214 | Ok(()) 215 | } 216 | } 217 | 218 | /// A disconnect notification. Tells the client to disconnect. 219 | #[derive(Clone, Debug, BinaryIo)] 220 | pub struct Disconnect {} 221 | 222 | /// A connection lost notification. 223 | /// This is sent by the client when it loses connection to the server. 224 | #[derive(Clone, Debug, BinaryIo)] 225 | pub struct LostConnection {} 226 | -------------------------------------------------------------------------------- /src/protocol/reliability.rs: -------------------------------------------------------------------------------- 1 | //! Reliability types for packets. 2 | //! Each packet sent on the RakNet protocol has a reliability type, which determines how the packet should be handled. 3 | //! 4 | //! ## Unreliable 5 | //! Unreliable packets are sent without any guarantee that they will be received by the other peer. 6 | //! In other words, the packet is sent and forgotten about, with no expectation of a response. 7 | //! This is the fastest reliability type, as it does not require any acks to be sent 8 | //! back to the sender. Generally used for packets that are not important, such as 9 | //! [`UnconnectedPing`] and [`UnconnectedPong`]. 10 | //! 11 | //! ## Sequenced 12 | //! Sequenced packets are sent with a sequence index in each frame (datagram) that is sent. 13 | //! This is a number that is incremented after each packet. This allows us to implement a sliding window 14 | //! ([`ReliableWindow`]), which 15 | //! will discard any packets that are way too old or way too new. 16 | //! 17 | //! ## Ordered 18 | //! Ordered packets are sent with an order index in each frame, as well as an order channel. 19 | //! RakNet will use this information to order the packets in a specific way. 20 | //! 21 | //! The `order_channel` is used to determine which channel the packet should be sent on, in other words, 22 | //! this is a unique channel chosen by the sender to send the packet on, and the receiver will use this 23 | //! channel to re-order the packets in the correct order when they are sent. 24 | //! 25 | //! The `order_index` is used to determine the position of the packet in the order channel, this is 26 | //! incremented after each packet is sent, similar to the sequence index, without the sliding window. 27 | //! 28 | //! ## Reliable 29 | //! Reliable packets are sent with an ack system, meaning that the receiver will send an ack back to the 30 | //! sender, which the sender expects to recieve. 31 | //! 32 | //! If the sender does not receive the ack, it will resend the packet until it receives the ack, or until 33 | //! the connection is closed. 34 | //! 35 | //! [`UnconnectedPing`]: crate::protocol::packet::offline::UnconnectedPing 36 | //! [`UnconnectedPong`]: crate::protocol::packet::offline::UnconnectedPong 37 | //! [`ReliableWindow`]: crate::connection::controller::window::ReliableWindow 38 | //! 39 | /// The [RakNet Reliabilty] of a packet. 40 | /// 41 | /// This is a bit flag encoded within each [`Frame`] that determines how the packet should be handled. 42 | /// As of writing the following reliability types are supported: 43 | /// - [`Unreliable`] 44 | /// - [`UnreliableSeq`] 45 | /// - [`Reliable`] 46 | /// - [`ReliableOrd`] 47 | /// - [`ReliableSeq`] 48 | /// 49 | /// [RakNet Reliabilty]: https://github.com/facebookarchive/RakNet/blob/1a169895a900c9fc4841c556e16514182b75faf8/Source/PacketPriority.h#L46-L85 50 | /// [`Frame`]: crate::protocol::frame::Frame 51 | /// [`Unreliable`]: crate::protocol::reliability::Reliability::Unreliable 52 | /// [`UnreliableSeq`]: crate::protocol::reliability::Reliability::UnreliableSeq 53 | /// [`Reliable`]: crate::protocol::reliability::Reliability::Reliable 54 | /// [`ReliableOrd`]: crate::protocol::reliability::Reliability::ReliableOrd 55 | /// [`ReliableSeq`]: crate::protocol::reliability::Reliability::ReliableSeq 56 | #[derive(Clone, Debug, Copy)] 57 | #[repr(u8)] 58 | pub enum Reliability { 59 | /// Unreliable (with no ack) 60 | Unreliable = 0, 61 | /// Unreliable with a sequence 62 | UnreliableSeq, 63 | /// Reliable 64 | Reliable, 65 | ReliableOrd, 66 | /// Reliably sequenced **AND** ordered 67 | ReliableSeq, 68 | /// never used over the wire 69 | UnreliableAck, 70 | /// never used over the wire 71 | ReliableAck, 72 | /// never used over the wire 73 | ReliableOrdAck, 74 | } 75 | 76 | impl Reliability { 77 | /// Creates a new [`Reliability`] from the given flags. 78 | /// This is used internally to decode the reliability from the given 79 | /// bit flags. 80 | /// 81 | /// [`Reliability`]: crate::protocol::reliability::Reliability 82 | pub fn from_flags(flags: u8) -> Self { 83 | match (flags & 224) >> 5 { 84 | 0 => Reliability::Unreliable, 85 | 1 => Reliability::UnreliableSeq, 86 | 2 => Reliability::Reliable, 87 | 3 => Reliability::ReliableOrd, 88 | 4 => Reliability::ReliableSeq, 89 | 5 => Reliability::UnreliableAck, 90 | 6 => Reliability::ReliableAck, 91 | 7 => Reliability::ReliableOrdAck, 92 | // we shouldn't error, but we'll just return unreliable 93 | _ => Reliability::Unreliable, 94 | } 95 | } 96 | 97 | /// Converts the [`Reliability`] into a bit flag. 98 | /// This is useful for encoding the reliability into a packet. 99 | pub fn to_flags(&self) -> u8 { 100 | match self { 101 | Reliability::Unreliable => 0 << 5, 102 | Reliability::UnreliableSeq => 1 << 5, 103 | Reliability::Reliable => 2 << 5, 104 | Reliability::ReliableOrd => 3 << 5, 105 | Reliability::ReliableSeq => 4 << 5, 106 | Reliability::UnreliableAck => 5 << 5, 107 | Reliability::ReliableAck => 6 << 5, 108 | Reliability::ReliableOrdAck => 7 << 5, 109 | } 110 | } 111 | 112 | /// This method checks whether the reliability is ordered, meaning that the packets 113 | /// are either: 114 | /// - [`ReliableOrd`] 115 | /// - [`ReliableOrdAck`] 116 | /// - [`UnreliableSeq`] 117 | /// 118 | /// [`ReliableOrd`]: crate::protocol::reliability::Reliability::ReliableOrd 119 | /// [`ReliableOrdAck`]: crate::protocol::reliability::Reliability::ReliableOrdAck 120 | /// [`UnreliableSeq`]: crate::protocol::reliability::Reliability::UnreliableSeq 121 | pub fn is_ordered(&self) -> bool { 122 | match self { 123 | Self::UnreliableSeq | Self::ReliableOrd | Self::ReliableOrdAck => true, 124 | _ => false, 125 | } 126 | } 127 | 128 | /// Verifies whether or not the reliabilty is reliable, meaning that the packets 129 | /// are either: 130 | /// - [`Reliable`] 131 | /// - [`ReliableOrd`] 132 | /// - [`ReliableSeq`] 133 | /// - [`ReliableAck`] 134 | /// 135 | /// Other reliabilities are not reliable, and will return `false`. 136 | /// 137 | /// [`Reliable`]: crate::protocol::reliability::Reliability::Reliable 138 | /// [`ReliableOrd`]: crate::protocol::reliability::Reliability::ReliableOrd 139 | /// [`ReliableSeq`]: crate::protocol::reliability::Reliability::ReliableSeq 140 | /// [`ReliableAck`]: crate::protocol::reliability::Reliability::ReliableAck 141 | pub fn is_reliable(&self) -> bool { 142 | match self { 143 | Self::Reliable | Self::ReliableOrd | Self::ReliableSeq | Self::ReliableOrdAck => true, 144 | _ => false, 145 | } 146 | } 147 | 148 | /// Verifies whether or not the reliabilty is unreliable, meaning that the packets 149 | /// are either: 150 | /// - [`Unreliable`] 151 | /// - [`UnreliableSeq`] 152 | /// - [`UnreliableAck`] 153 | /// 154 | /// Other reliabilities are not unreliable, and will return `false`. 155 | /// 156 | /// [`Unreliable`]: crate::protocol::reliability::Reliability::Unreliable 157 | /// [`UnreliableSeq`]: crate::protocol::reliability::Reliability::UnreliableSeq 158 | /// [`UnreliableAck`]: crate::protocol::reliability::Reliability::UnreliableAck 159 | pub fn is_unreliable(&self) -> bool { 160 | match self { 161 | Self::Unreliable | Self::UnreliableSeq | Self::UnreliableAck => true, 162 | _ => false, 163 | } 164 | } 165 | 166 | /// Verifies whether or not the reliabilty is sequenced, meaning that the packets 167 | /// are either: 168 | /// - [`UnreliableSeq`] 169 | /// - [`ReliableSeq`] 170 | /// 171 | /// Other reliabilities are not sequenced, and will return `false`. 172 | /// 173 | /// ## What is a sequenced packet? 174 | /// A sequenced packet is a packet with an index that is incremented after each packet. 175 | /// RakNet uses this internally to discard packets that are sent out of sequence, accepting 176 | /// only the latest packet. 177 | /// 178 | /// [`UnreliableSeq`]: crate::protocol::reliability::Reliability::UnreliableSeq 179 | /// [`ReliableSeq`]: crate::protocol::reliability::Reliability::ReliableSeq 180 | pub fn is_sequenced(&self) -> bool { 181 | match self { 182 | Self::UnreliableSeq | Self::ReliableSeq => true, 183 | _ => false, 184 | } 185 | } 186 | 187 | /// Verifies whether or not the reliabilty is sequenced or ordered. This function 188 | /// is a combination of [`Reliability::is_sequenced`] and [`Reliability::is_ordered`], 189 | /// combined into one signature. 190 | /// 191 | /// [`Reliability::is_sequenced`]: crate::protocol::reliability::Reliability::is_sequenced 192 | /// [`Reliability::is_ordered`]: crate::protocol::reliability::Reliability::is_ordered 193 | pub fn is_sequenced_or_ordered(&self) -> bool { 194 | match self { 195 | Self::UnreliableSeq | Self::ReliableSeq | Self::ReliableOrd | Self::ReliableOrdAck => { 196 | true 197 | } 198 | _ => false, 199 | } 200 | } 201 | 202 | /// Verifies that the reliability is an ack ([`Ack`]). 203 | /// This is primarily used internally to determine whether or not to send an ack. 204 | /// 205 | /// [`Ack`]: crate::protocol::ack::Ack 206 | pub fn is_ack(&self) -> bool { 207 | match self { 208 | Self::UnreliableAck | Self::ReliableAck | Self::ReliableOrdAck => true, 209 | _ => false, 210 | } 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /src/server/event.rs: -------------------------------------------------------------------------------- 1 | use std::net::SocketAddr; 2 | 3 | use crate::{connection::state::ConnectionState, protocol::mcpe::motd::Motd}; 4 | 5 | #[derive(Debug, Clone)] 6 | pub enum ServerEvent { 7 | /// A request to refresh the MOTD, 8 | /// the second value in this tuple represents 9 | /// the `Motd` that will be used if the event is 10 | /// disregarded. 11 | RefreshMotdRequest(SocketAddr, Motd), 12 | /// Requests the client to update their mtu size. 13 | /// This event is dispatched before the client fully connects 14 | /// allowing you to control the MtuSize. 15 | SetMtuSize(u16), 16 | /// Disconnect the client immediately 17 | /// Sent to the client to immediately disconnect the client. 18 | /// If you ignore this, the connection will be dropped automatically 19 | /// however this event is fired to allow graceful handling of a disconnect 20 | DisconnectImmediately, 21 | /// A request from the listener to update a connection's state. 22 | /// This is done during handshake or if the connection is timed out. 23 | UpdateConnectionState(ConnectionState), 24 | } 25 | 26 | #[derive(Debug, Clone)] 27 | pub enum ServerEventResponse { 28 | /// The response to a `RefreshMotdRequest`. 29 | RefreshMotd(Motd), 30 | /// A generic response that acknowledges the event was recieved, but 31 | /// no actions were taken. 32 | /// 33 | /// VALID FOR ALL EVENTS 34 | Acknowledged, 35 | } 36 | -------------------------------------------------------------------------------- /src/server/mod.rs: -------------------------------------------------------------------------------- 1 | //! This is the server implementation of RakNet, allowing you to create a RakNet server. 2 | //! 3 | //! This module provides a [`Listener`] struct, which is responsible for listening to connections, 4 | //! and dispatching them to a handler, as well as some other utilities. 5 | //! 6 | //! [`Listener`]: struct.Listener.html 7 | #[allow(unused)] 8 | /// Server events module. Handles things like updating the MOTD 9 | /// for certain connections. This is a notifier channel. 10 | pub mod event; 11 | 12 | use std::collections::HashMap; 13 | use std::net::ToSocketAddrs; 14 | use std::{net::SocketAddr, sync::Arc}; 15 | 16 | #[cfg(feature = "async_std")] 17 | use async_std::{ 18 | channel::{bounded, Receiver, Sender}, 19 | net::UdpSocket, 20 | sync::Mutex, 21 | task::{self}, 22 | }; 23 | #[cfg(feature = "async_std")] 24 | use futures::{select, FutureExt}; 25 | 26 | use binary_util::interfaces::{Reader, Writer}; 27 | use binary_util::ByteReader; 28 | 29 | #[cfg(feature = "async_tokio")] 30 | use tokio::{ 31 | net::UdpSocket, 32 | select, 33 | sync::mpsc::channel as bounded, 34 | sync::mpsc::{Receiver, Sender}, 35 | sync::Mutex, 36 | task::{self}, 37 | }; 38 | 39 | use crate::connection::{ConnMeta, Connection}; 40 | use crate::error::server::ServerError; 41 | use crate::notify::Notify; 42 | use crate::protocol::mcpe::motd::Motd; 43 | use crate::protocol::packet::offline::{ 44 | IncompatibleProtocolVersion, OfflinePacket, OpenConnectReply, SessionInfoReply, UnconnectedPong, 45 | }; 46 | use crate::protocol::packet::RakPacket; 47 | use crate::protocol::Magic; 48 | use crate::rakrs_debug; 49 | use crate::util::to_address_token; 50 | 51 | pub(crate) type Session = (ConnMeta, Sender>); 52 | 53 | /// This is a helper enum that allows you to pass in a `SocketAddr` or a `&str` to the `Listener::bind` function. 54 | /// This is useful for when you want to bind to a specific address, but you don't want to parse it yourself. 55 | /// 56 | /// This Trait will successfully parse the following: 57 | /// - `SocketAddr::new("127.0.0.1:19132")` 58 | /// - `"127.0.0.1:19132"` 59 | /// - `String::from("127.0.0.1:19132")` 60 | pub enum PossiblySocketAddr<'a> { 61 | SocketAddr(SocketAddr), 62 | Str(&'a str), 63 | String(String), 64 | ActuallyNot, 65 | } 66 | 67 | impl PossiblySocketAddr<'_> { 68 | pub fn to_socket_addr(self) -> Option { 69 | match self { 70 | PossiblySocketAddr::SocketAddr(addr) => Some(addr), 71 | PossiblySocketAddr::Str(addr) => { 72 | // we need to parse it 73 | Some(addr.parse::().unwrap()) 74 | } 75 | PossiblySocketAddr::String(addr) => { 76 | if let Ok(addr) = addr.parse::() { 77 | Some(addr.clone()) 78 | } else { 79 | // try to parse it as a socket addr then a string 80 | if let Ok(mut addr) = addr.to_socket_addrs() { 81 | if let Some(v) = addr.next() { 82 | Some(v) 83 | } else { 84 | None 85 | } 86 | } else { 87 | None 88 | } 89 | } 90 | } 91 | _ => None, 92 | } 93 | } 94 | } 95 | 96 | impl From<&str> for PossiblySocketAddr<'_> { 97 | fn from(s: &str) -> Self { 98 | PossiblySocketAddr::String(s.to_string()) 99 | } 100 | } 101 | 102 | impl From for PossiblySocketAddr<'_> { 103 | fn from(s: String) -> Self { 104 | PossiblySocketAddr::String(s) 105 | } 106 | } 107 | 108 | impl From for PossiblySocketAddr<'_> { 109 | fn from(s: SocketAddr) -> Self { 110 | PossiblySocketAddr::SocketAddr(s) 111 | } 112 | } 113 | 114 | impl std::fmt::Display for PossiblySocketAddr<'_> { 115 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 116 | match self { 117 | PossiblySocketAddr::SocketAddr(addr) => write!(f, "{}", addr), 118 | PossiblySocketAddr::Str(addr) => write!(f, "{}", addr), 119 | PossiblySocketAddr::String(addr) => write!(f, "{}", addr), 120 | PossiblySocketAddr::ActuallyNot => write!(f, "Not a valid address!"), 121 | } 122 | } 123 | } 124 | 125 | /// The main server struct, this is responsible for listening to connections, and dispatching them to a handler. 126 | /// > If you are having problems with debugging, you can use the rak-rs debug feature, which will print out 127 | /// > all packets that are sent and recieved. 128 | /// 129 | /// 152 | /// 153 | ///
154 | /// Notice: 155 | ///

156 | /// Currently, the Listener does not support encryption, plugins, or any feature to allow you to 157 | /// hijack the RakNet connection sequence. Currently rak_rs is a pure, bare-bones RakNet implementation.

158 | /// There is currently an open issue 159 | /// to add support for plugins but this is not a priority, instead you should use the Connection struct 160 | /// to handle your own packets with the recv method. 161 | ///

162 | ///
163 | /// 164 | /// ## A generic example 165 | /// ```rust ignore 166 | /// use rak_rs::server::Listener; 167 | /// 168 | /// #[async_std::main] 169 | /// async fn main() { 170 | /// // Bind the server to the specified address, but do not start it. 171 | /// let mut server = Listener::bind("0.0.0.0:19132").await.unwrap(); 172 | /// 173 | /// // Begins listening to connections 174 | /// server.start().await.unwrap(); 175 | /// 176 | /// // Start recieving connections 177 | /// loop { 178 | /// let conn = server.accept().await; 179 | /// async_std::task::spawn(handle(conn.unwrap())); 180 | /// } 181 | /// } 182 | /// 183 | /// // This is a function that handles the connection, this is where you would handle the connection. 184 | /// async fn handle(mut conn: Connection) { 185 | /// loop { 186 | /// // this is used to cleanup the connection 187 | /// if conn.get_state().await.is_closed() { 188 | /// println!("Connection closed!"); 189 | /// break; 190 | /// } 191 | /// 192 | /// if let Ok(pk) = conn.recv().await { 193 | /// println!("Got a connection packet {:?} ", pk); 194 | /// } 195 | /// } 196 | /// } 197 | /// ``` 198 | /// 199 | /// ## Accepting other protocols 200 | /// This struct allows support for other raknet protocols, however this is not recommended, because occasionally 201 | /// the protocol may change and the Listener may not be updated to support it. This was mainly added for MCPE. 202 | /// 203 | /// ```rust ignore 204 | /// use rak_rs::server::Listener; 205 | /// 206 | /// #[async_std::main] 207 | /// async fn main() { 208 | /// let mut server = Listener::bind("0.0.0.0:19132").await.unwrap(); 209 | /// server.versions = &[10, 11]; 210 | /// server.start().await.unwrap(); 211 | /// 212 | /// loop { 213 | /// // .. same loop as above 214 | /// } 215 | /// } 216 | /// ``` 217 | pub struct Listener { 218 | /// If mcpe is true, this is the default MOTD, this is 219 | /// the default MOTD to send to the client. You can change this later by setting 220 | /// a motd in the `Conn` struct. 221 | pub motd: Motd, 222 | /// A server Id, passed in unconnected pong. 223 | pub id: u64, 224 | /// Supported versions 225 | pub versions: &'static [u8], 226 | /// Whether or not the server is being served. 227 | serving: bool, 228 | /// The current socket. 229 | sock: Option>, 230 | /// A Hashmap off all current connections along with a sending channel 231 | /// and some meta data like the time of connection, and the requested MTU_Size 232 | connections: Arc>>, 233 | /// The recieve communication channel, This is used to dispatch connections between a handle 234 | /// It allows you to use the syntax sugar for `Listener::accept()`. 235 | recv_comm: Receiver, 236 | send_comm: Sender, 237 | // TODO, fix this! 238 | // send_evnt: Sender<(ServerEvent, oneshot::Sender)>, 239 | // pub recv_evnt: Arc)>>>, 240 | // TODO 241 | /// A Notifier (sephamore) that will wait until all notified listeners 242 | /// are completed, and finish closing. 243 | closed: Arc, 244 | // This is a notifier that acknowledges all connections have been removed from the server successfully. 245 | // This is important to prevent memory leaks if the process is continously running. 246 | // cleanup: Arc, 247 | } 248 | 249 | impl Listener { 250 | /// Binds a new listener to the specified address provided, this will error if the address is invalid or already in use. 251 | /// This will not start the listener, you must call [`Listener::start`] to start listening to connections. 252 | /// 253 | /// ## Example 254 | /// ```ignore 255 | /// use rak_rs::server::Listener; 256 | /// 257 | /// async fn start() { 258 | /// let mut server = Listener::bind("").await.unwrap(); 259 | /// } 260 | /// ``` 261 | /// 262 | /// [`PossiblySocketAddr`]: enum.PossiblySocketAddr.html 263 | /// [`Listener::start`]: struct.Listener.html#method.start 264 | pub async fn bind Into>>( 265 | address: I, 266 | ) -> Result { 267 | let a: PossiblySocketAddr = address.into(); 268 | let address_r: Option = a.to_socket_addr(); 269 | if address_r.is_none() { 270 | rakrs_debug!("Invalid binding value"); 271 | return Err(ServerError::AddrBindErr); 272 | } 273 | 274 | let address = address_r.unwrap(); 275 | 276 | let sock = match UdpSocket::bind(address).await { 277 | Ok(s) => s, 278 | Err(_) => return Err(ServerError::AddrBindErr), 279 | }; 280 | 281 | rakrs_debug!(true, "listener: Bound to {}", address); 282 | 283 | let server_id: u64 = rand::random(); 284 | let motd = Motd::new(server_id, format!("{}", address.port())); 285 | 286 | // This channel is a Communication channel for when `Connection` structs are initialized. 287 | let (send_comm, recv_comm) = bounded::(10); 288 | // This channel is responsible for handling and dispatching events between clients. 289 | // Oneshot will garauntee this event is intended for the client whom requested the event. 290 | // TODO: Fix with new event system 291 | // let (send_evnt, recv_evnt) = 292 | // mpsc::channel::<(ServerEvent, oneshot::Sender)>(10); 293 | 294 | let listener = Self { 295 | sock: Some(Arc::new(sock)), 296 | id: server_id, 297 | versions: &[10, 11], 298 | motd, 299 | send_comm, 300 | recv_comm, 301 | // send_evnt, 302 | // recv_evnt: Arc::new(Mutex::new(recv_evnt)), 303 | serving: false, 304 | connections: Arc::new(Mutex::new(HashMap::new())), 305 | // closer: Arc::new(Semaphore::new(0)), 306 | closed: Arc::new(Notify::new()), 307 | // cleanup: Arc::new(Notify::new()), 308 | // cleanup: Arc::new(Condvar::new()), 309 | }; 310 | 311 | return Ok(listener); 312 | } 313 | 314 | /// This method is required to be called before the server can begin listening to connections. 315 | /// However, you must call [`Listener::bind`] before you can call this method, as that method 316 | /// is responsible for creating the socket and initializing the server. 317 | /// 318 | /// ## Example 319 | /// ```ignore 320 | /// use rak_rs::server::Listener; 321 | /// async fn start() { 322 | /// let mut server = Listener::bind("0.0.0.0:19132").await.unwrap(); 323 | /// 324 | /// // let's begin to listen to connections 325 | /// server.start().await; 326 | /// } 327 | /// ``` 328 | /// 329 | /// [`Listener::bind`]: struct.Listener.html#method.bind 330 | pub async fn start(&mut self) -> Result<(), ServerError> { 331 | if self.serving { 332 | return Err(ServerError::AlreadyOnline); 333 | } 334 | 335 | let socket = self.sock.as_ref().unwrap().clone(); 336 | let send_comm = self.send_comm.clone(); 337 | // let send_evt = self.send_evnt.clone(); 338 | let server_id = self.id.clone(); 339 | #[cfg(feature = "mcpe")] 340 | let default_motd = self.motd.clone(); 341 | let connections = self.connections.clone(); 342 | let closer = self.closed.clone(); 343 | let connections2 = self.connections.clone(); 344 | let closer2 = self.closed.clone(); 345 | let versions = self.versions; 346 | 347 | self.serving = true; 348 | 349 | #[cfg(feature = "async_std")] 350 | let (cs, client_close_recv) = bounded::(10); 351 | #[cfg(feature = "async_tokio")] 352 | let (cs, mut client_close_recv) = bounded::(10); 353 | let client_close_send = Arc::new(cs); 354 | 355 | task::spawn(async move { 356 | // We allocate here to prevent constant allocation of this array 357 | let mut buf: [u8; 2048] = [0; 2048]; 358 | #[cfg(feature = "mcpe")] 359 | let motd_default = default_motd.clone(); 360 | loop { 361 | let length: usize; 362 | let origin: SocketAddr; 363 | 364 | macro_rules! recv_body { 365 | ($recv: ident) => { 366 | match $recv { 367 | Ok((l, o)) => { 368 | length = l; 369 | origin = o; 370 | } 371 | Err(e) => { 372 | match e.kind() { 373 | std::io::ErrorKind::ConnectionReset => { 374 | continue; 375 | }, 376 | _ => { 377 | rakrs_debug!(true, "[SERVER-SOCKET] Failed to recieve packet! {}", e); 378 | continue; 379 | } 380 | } 381 | } 382 | } 383 | 384 | // Do a quick check to see if this a valid raknet packet, otherwise we're going to handle it normally 385 | if let Ok(pk) = OfflinePacket::read(&mut ByteReader::from(&buf[..length])) { 386 | // Offline packets are not buffered to the user. 387 | // The reason for this is because we don't wish for the user to be able to disrupt 388 | // raknet protocol, and handshaking. 389 | match pk { 390 | OfflinePacket::UnconnectedPing(_) => { 391 | // let (resp_tx, resp_rx) = 392 | // oneshot::channel::(); 393 | #[cfg(feature = "mcpe")] 394 | let motd: Motd = motd_default.clone(); 395 | 396 | // if let Err(e) = send_evt.try_send(( 397 | // ServerEvent::RefreshMotdRequest(origin, motd.clone()), 398 | // // resp_tx, 399 | // )) 400 | // { 401 | // match e { 402 | // TrySendError::Full(_) => { 403 | // rakrs_debug!(true, "[{}] Event dispatcher is full! Dropping request.", to_address_token(origin)); 404 | // } 405 | // TrySendError::Closed(_) => { 406 | // rakrs_debug!(true, "[{}] Event dispatcher is closed! Dropping request.", to_address_token(origin)); 407 | // } 408 | // } 409 | // } 410 | 411 | // if let Ok(res) = resp_rx.await { 412 | // // get the motd from the server event otherwise use defaults. 413 | // // if let Ok(res) = res { 414 | // match res { 415 | // ServerEventResponse::RefreshMotd(m) => { 416 | // motd = m; 417 | // } 418 | // _ => { 419 | // rakrs_debug!(true, "[{}] Response to ServerEvent::RefreshMotdRequest is invalid!", to_address_token(origin)); 420 | // } 421 | // } 422 | // // }; 423 | // } 424 | 425 | // unconnected pong signature is different if MCPE is specified. 426 | let resp = UnconnectedPong { 427 | timestamp: current_epoch(), 428 | server_id, 429 | magic: Magic::new(), 430 | #[cfg(feature = "mcpe")] 431 | motd, 432 | }; 433 | 434 | send_packet_to_socket(&socket, resp.into(), origin).await; 435 | continue; 436 | } 437 | OfflinePacket::OpenConnectRequest(mut pk) => { 438 | // TODO make a constant for this 439 | if !versions.contains(&pk.protocol) { 440 | let resp = IncompatibleProtocolVersion { 441 | protocol: pk.protocol, 442 | magic: Magic::new(), 443 | server_id, 444 | }; 445 | 446 | rakrs_debug!("[{}] Sent ({}) which is invalid RakNet protocol. Version is incompatible with server.", pk.protocol, to_address_token(*&origin)); 447 | 448 | send_packet_to_socket(&socket, resp.into(), origin).await; 449 | continue; 450 | } 451 | 452 | rakrs_debug!( 453 | true, 454 | "[{}] Client requested Mtu Size: {}", 455 | to_address_token(*&origin), 456 | pk.mtu_size 457 | ); 458 | 459 | if pk.mtu_size > 2048 { 460 | rakrs_debug!( 461 | true, 462 | "[{}] Client requested Mtu Size: {} which is larger than the maximum allowed size of 2048", 463 | to_address_token(*&origin), 464 | pk.mtu_size 465 | ); 466 | pk.mtu_size = 2048; 467 | } 468 | 469 | let resp = OpenConnectReply { 470 | server_id, 471 | // TODO allow encryption 472 | security: false, 473 | magic: Magic::new(), 474 | // TODO make this configurable, this is sent to the client to change 475 | // it's mtu size, right now we're using what the client prefers. 476 | // however in some cases this may not be the preferred use case, for instance 477 | // on servers with larger worlds, you may want a larger mtu size, or if 478 | // your limited on network bandwith 479 | mtu_size: pk.mtu_size, 480 | }; 481 | send_packet_to_socket(&socket, resp.into(), origin).await; 482 | continue; 483 | } 484 | OfflinePacket::SessionInfoRequest(pk) => { 485 | let resp = SessionInfoReply { 486 | server_id, 487 | client_address: origin, 488 | magic: Magic::new(), 489 | mtu_size: pk.mtu_size, 490 | security: false, 491 | }; 492 | 493 | // This is a valid packet, let's check if a session exists, if not, we should create it. 494 | // Event if the connection is only in offline mode. 495 | let mut sessions = connections.lock().await; 496 | 497 | if !sessions.contains_key(&origin) { 498 | rakrs_debug!(true, "Creating new session for {}", origin); 499 | let meta = ConnMeta::new(0); 500 | let (net_send, net_recv) = bounded::>(10); 501 | let connection = 502 | Connection::new(origin, &socket, net_recv, client_close_send.clone(), pk.mtu_size).await; 503 | rakrs_debug!(true, "Created Session for {}", origin); 504 | 505 | // Add the connection to the available connections list. 506 | // we're using the name "sessions" here to differeniate 507 | // for some reason the reciever likes to be dropped, so we're saving it here. 508 | sessions.insert(origin, (meta, net_send)); 509 | 510 | // notify the connection communicator 511 | if let Err(err) = send_comm.send(connection).await { 512 | let connection = err.0; 513 | // there was an error, and we should terminate this connection immediately. 514 | rakrs_debug!("[{}] Error while communicating with internal connection channel! Connection withdrawn.", to_address_token(connection.address)); 515 | sessions.remove(&origin); 516 | continue; 517 | } 518 | } 519 | 520 | // update the sessions mtuSize, this is referred to internally, we also will send this event to the client 521 | // event channel. However we are not expecting a response. 522 | 523 | sessions.get_mut(&origin).unwrap().0.mtu_size = pk.mtu_size; 524 | rakrs_debug!( 525 | true, 526 | "[{}] Updated mtu size to {}", 527 | to_address_token(origin), 528 | pk.mtu_size 529 | ); 530 | 531 | // let (resp_tx, resp_rx) = oneshot::channel::(); 532 | 533 | // if let Err(_) = timeout(Duration::from_millis(5), resp_rx).await { 534 | // rakrs_debug!( 535 | // "[{}] Failed to update mtu size with the client!", 536 | // to_address_token(origin) 537 | // ); 538 | // } 539 | 540 | // if let Err(_) = send_evt.send((ServerEvent::SetMtuSize(pk.mtu_size), resp_tx)) 541 | // .await 542 | // { 543 | // rakrs_debug!( 544 | // "[{}] Failed to update mtu size with the client!", 545 | // to_address_token(origin) 546 | // ); 547 | // } 548 | 549 | send_packet_to_socket(&socket, resp.into(), origin).await; 550 | continue; 551 | } 552 | _ => { 553 | rakrs_debug!( 554 | "[{}] Received invalid packet!", 555 | to_address_token(*&origin) 556 | ); 557 | } 558 | } 559 | } 560 | 561 | // Packet may be valid, but we'll let the connection decide this 562 | let mut sessions = connections.lock().await; 563 | if sessions.contains_key(&origin) { 564 | if let Err(_) = sessions[&origin].1.send(buf[..length].to_vec()).await { 565 | rakrs_debug!(true, "[{}] Failed when handling recieved packet! Could not pass over to internal connection, the channel might be closed! (Removed the connection)", to_address_token(*&origin)); 566 | sessions.remove(&origin); 567 | } 568 | } 569 | drop(sessions); 570 | }; 571 | } 572 | 573 | #[cfg(feature = "async_std")] 574 | select! { 575 | _ = closer.wait().fuse() => { 576 | rakrs_debug!(true, "[SERVER] [NETWORK] Server has recieved the shutdown notification!"); 577 | break; 578 | } 579 | recv = socket.recv_from(&mut buf).fuse() => { 580 | recv_body!(recv); 581 | } 582 | } 583 | 584 | #[cfg(feature = "async_tokio")] 585 | select! { 586 | _ = closer.wait() => { 587 | rakrs_debug!(true, "[SERVER] [NETWORK] Server has recieved the shutdown notification!"); 588 | break; 589 | } 590 | recv = socket.recv_from(&mut buf) => { 591 | recv_body!(recv); 592 | } 593 | } 594 | } 595 | }); 596 | 597 | task::spawn(async move { 598 | // here we loop and recv from the client_close_recv channel 599 | // and remove the connection from the hashmap 600 | loop { 601 | #[cfg(feature = "async_std")] 602 | select! { 603 | _ = closer2.wait().fuse() => { 604 | rakrs_debug!(true, "[SERVER] [Cleanup] Server has recieved the shutdown notification!"); 605 | break; 606 | } 607 | addr = client_close_recv.recv().fuse() => { 608 | if let Ok(addr) = addr { 609 | rakrs_debug!(true, "[SERVER] [Cleanup] Removing connection for {}", to_address_token(addr)); 610 | let mut c = connections2.lock().await; 611 | c.remove(&addr); 612 | drop(c); 613 | } 614 | } 615 | } 616 | 617 | #[cfg(feature = "async_tokio")] 618 | select! { 619 | _ = closer2.wait() => { 620 | rakrs_debug!(true, "[SERVER] [Cleanup] Server has recieved the shutdown notification!"); 621 | break; 622 | } 623 | addr = client_close_recv.recv() => { 624 | if let Some(addr) = addr { 625 | rakrs_debug!(true, "[SERVER] [Cleanup] Removing connection for {}", to_address_token(addr)); 626 | let mut c = connections2.lock().await; 627 | c.remove(&addr); 628 | drop(c); 629 | } 630 | } 631 | } 632 | } 633 | }); 634 | 635 | return Ok(()); 636 | } 637 | 638 | // pub async fn recv_event(&self) -> Result<(ServerEvent, oneshot::Sender), ServerError> { 639 | // if !self.serving { 640 | // Err(ServerError::NotListening) 641 | // } else { 642 | // let mut recvr = self.recv_evnt.lock().await; 643 | // tokio::select! { 644 | // receiver = recvr.recv() => { 645 | // match receiver { 646 | // Some(c) => Ok(c), 647 | // None => Err(ServerError::Killed) 648 | // } 649 | // }, 650 | // _ = self.closer.acquire() => { 651 | // Err(ServerError::Killed) 652 | // } 653 | // } 654 | // } 655 | // } 656 | 657 | /// This method is used to accept a connection, this will block until a connection is available. 658 | /// You can only call this method once both [`Listener::bind`] AND [`Listener::start`] have. This function 659 | /// is used to recieve and accept connections. Alternatively, you can refuse a connection 660 | /// by dropping it when you accept it. 661 | /// 662 | /// [`Listener::bind`]: struct.Listener.html#method.bind 663 | /// [`Listener::start`]: struct.Listener.html#method.start 664 | /// 665 | ///
666 | /// Warning: 667 | ///

668 | /// This method will block until a connection is available, this is not recommended to be used 669 | /// in the main thread, instead you should use a task or future to handle connections. 670 | ///

671 | ///
672 | /// 673 | /// ## Example 674 | /// ```rust ignore 675 | /// use rak_rs::server::Listener; 676 | /// use rak_rs::Connection; 677 | /// 678 | /// #[async_std::main] 679 | /// async fn main() { 680 | /// let mut server = Listener::bind("0.0.0.0:19132").await.unwrap(); 681 | /// server.start().await.unwrap(); 682 | /// 683 | /// loop { 684 | /// let conn = server.accept().await; 685 | /// async_std::task::spawn(handle(conn.unwrap())); 686 | /// } 687 | /// } 688 | /// 689 | /// async fn handle(mut conn: Connection) { 690 | /// loop { 691 | /// let packet = conn.recv().await; 692 | /// println!("Received a packet! {:?}", packet); 693 | /// } 694 | /// } 695 | /// ``` 696 | pub async fn accept(&mut self) -> Result { 697 | if !self.serving { 698 | Err(ServerError::NotListening) 699 | } else { 700 | let receiver = self.recv_comm.recv().await; 701 | return match receiver { 702 | #[cfg(feature = "async_std")] 703 | Ok(c) => Ok(c), 704 | #[cfg(feature = "async_std")] 705 | Err(_) => Err(ServerError::Killed), 706 | #[cfg(feature = "async_tokio")] 707 | Some(c) => Ok(c), 708 | #[cfg(feature = "async_tokio")] 709 | None => Err(ServerError::Killed), 710 | }; 711 | } 712 | } 713 | 714 | /// Stops the Listener, effectively closing the socket and stopping the server. 715 | /// This will also close all connections, and prevent any new connections from being accepted, 716 | /// until [`Listener::start`] is called again. 717 | /// 718 | /// [`Listener::start`]: struct.Listener.html#method.start 719 | pub async fn stop(&mut self) -> Result<(), ServerError> { 720 | self.closed.notify().await; 721 | // self.cleanup.notified().await; 722 | 723 | self.sock = None; 724 | self.serving = false; 725 | 726 | Ok(()) 727 | } 728 | } 729 | 730 | impl Drop for Listener { 731 | fn drop(&mut self) { 732 | if self.serving { 733 | futures_executor::block_on(self.stop()).unwrap(); 734 | } 735 | } 736 | } 737 | 738 | async fn send_packet_to_socket(socket: &Arc, packet: RakPacket, origin: SocketAddr) { 739 | if let Err(e) = socket 740 | .send_to(&mut packet.write_to_bytes().unwrap().as_slice(), origin) 741 | .await 742 | { 743 | rakrs_debug!( 744 | "[{}] Failed sending payload to socket! {}", 745 | to_address_token(origin), 746 | e 747 | ); 748 | } 749 | } 750 | 751 | pub(crate) fn current_epoch() -> u64 { 752 | std::time::SystemTime::now() 753 | .duration_since(std::time::UNIX_EPOCH) 754 | .unwrap() 755 | .as_secs() as u64 756 | } 757 | -------------------------------------------------------------------------------- /src/util/debug.rs: -------------------------------------------------------------------------------- 1 | /// A wrapper for println that is enabled only with the features `debug`, `debug_all`, or `debug_features`. 2 | /// - `debug` - Enables generic logging, purposeful for debugging things going wrong with your implementation 3 | /// - `debug_all` - Enables logging of all components, IE, connection, packets, etc. 4 | /// - `debug_buffers` - Enables logging of all buffers sent and received. 5 | #[macro_export] 6 | macro_rules! rakrs_debug { 7 | ($heavy: ident, $($t: tt)*) => { 8 | if cfg!(feature="debug") && cfg!(feature="debug_all") { 9 | println!("[rakrs] DBG! {}", format!($($t)*)); 10 | } 11 | }; 12 | ($($t: tt)*) => { 13 | if cfg!(feature="debug") { 14 | println!("[rakrs] DBG! {}", format!($($t)*)); 15 | } 16 | }; 17 | } 18 | 19 | #[macro_export] 20 | macro_rules! rakrs_debug_buffers { 21 | ($server: literal, $($t: tt)*) => { 22 | if cfg!(feature="debug_buffers") { 23 | let x = if $server == true { "S -> C" } else { "C -> S" }; 24 | println!("[rakrs] DBG [{}]: {}", x, format!($($t)*)); 25 | } 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /src/util/mod.rs: -------------------------------------------------------------------------------- 1 | #![allow(deprecated)] 2 | #[cfg(feature = "async_std")] 3 | use async_std::task::sleep as async_sleep; 4 | use std::net::{SocketAddr, ToSocketAddrs}; 5 | use std::{collections::HashMap, time::SystemTime}; 6 | #[cfg(feature = "async_tokio")] 7 | use tokio::time::sleep as async_sleep; 8 | 9 | pub(crate) mod debug; 10 | 11 | #[derive(Debug, Clone)] 12 | pub struct SafeGenerator { 13 | pub(crate) sequence: T, 14 | } 15 | 16 | impl SafeGenerator 17 | where 18 | T: Default, 19 | { 20 | pub fn new() -> Self { 21 | Self { 22 | sequence: T::default(), 23 | } 24 | } 25 | } 26 | 27 | macro_rules! impl_gen { 28 | ($n: ty) => { 29 | impl SafeGenerator<$n> { 30 | pub fn next(&mut self) -> $n { 31 | self.sequence = self.sequence.wrapping_add(1); 32 | return self.sequence; 33 | } 34 | 35 | pub fn get(&self) -> $n { 36 | self.sequence 37 | } 38 | } 39 | }; 40 | } 41 | 42 | impl_gen!(u8); 43 | impl_gen!(u16); 44 | impl_gen!(u32); 45 | impl_gen!(u64); 46 | impl_gen!(u128); 47 | impl_gen!(usize); 48 | 49 | /// This is a fancy wrapper over a HashMap that serves as 50 | /// a time oriented cache, where you can optionally clean up 51 | /// old and un-used values. Key serves as a `packet_id` in 52 | /// rakrs, but this could be used else-where. 53 | /// 54 | /// 88 | /// 89 | ///
90 | /// Warning: 91 | ///

92 | /// This struct will be removed in 0.2.0 in favor of RecoveryQueue. 93 | ///

94 | ///
95 | /// 96 | /// 97 | /// Usage example: 98 | /// ```rust 99 | /// use rak_rs::util::CacheStore; 100 | /// 101 | /// let mut myStore: CacheStore> = CacheStore::new(); 102 | /// let myPacket = (0 as u8, vec![0, 0, 0, 1]); 103 | /// myStore.add(myPacket.0, myPacket.1); 104 | /// // Wait a few seconds 105 | /// myStore.flush(); 106 | /// ``` 107 | #[derive(Debug, Clone)] 108 | #[deprecated( 109 | since = "0.0.1", 110 | note = "This is deprecated in favor of `RecoveryQueue`" 111 | )] 112 | pub struct CacheStore { 113 | pub(crate) store: HashMap)>, 114 | } 115 | 116 | impl CacheStore 117 | where 118 | K: std::hash::Hash + std::cmp::Eq, 119 | V: ?Sized + Clone, 120 | { 121 | pub fn new() -> Self { 122 | Self { 123 | store: HashMap::new(), 124 | } 125 | } 126 | 127 | pub fn add(&mut self, sequence: K, buffer: V) { 128 | let ent = self 129 | .store 130 | .entry(sequence) 131 | .or_insert((SystemTime::now(), Vec::new())); 132 | ent.1.push(buffer); 133 | } 134 | 135 | pub fn add_bulk(&mut self, sequence: K, buffers: Vec) { 136 | let ent = self 137 | .store 138 | .entry(sequence) 139 | .or_insert((SystemTime::now(), Vec::new())); 140 | ent.1.extend(buffers); 141 | } 142 | 143 | // clear old packets from the cache and return them 144 | pub fn flush(&mut self) -> Vec<(K, SystemTime, Vec)> { 145 | let mut flushed = Vec::new(); 146 | for (sequence, (time, frames)) in self.store.drain() { 147 | flushed.push((sequence, time, frames)); 148 | } 149 | return flushed; 150 | } 151 | 152 | pub fn flush_key(&mut self, key: K) -> Option<(SystemTime, Vec)> { 153 | self.store.remove(&key) 154 | } 155 | 156 | pub fn has(&self, key: &K) -> bool { 157 | self.store.contains_key(key) 158 | } 159 | } 160 | 161 | pub fn to_address_token(remote: SocketAddr) -> String { 162 | let mut address = remote.ip().to_string(); 163 | address.push_str(":"); 164 | address.push_str(remote.port().to_string().as_str()); 165 | return address; 166 | } 167 | 168 | pub fn from_address_token(remote: String) -> SocketAddr { 169 | let mut parsed = remote 170 | .to_socket_addrs() 171 | .expect("Could not parse remote address."); 172 | SocketAddr::from(parsed.next().unwrap()) 173 | } 174 | 175 | pub async fn sleep(duration: std::time::Duration) { 176 | async_sleep(duration).await; 177 | } 178 | -------------------------------------------------------------------------------- /tests/fragment_queue.rs: -------------------------------------------------------------------------------- 1 | use rak_rs::{ 2 | connection::queue::FragmentQueue, 3 | protocol::{ 4 | frame::{FragmentMeta, Frame}, 5 | reliability::Reliability, 6 | }, 7 | }; 8 | 9 | // Fixes issue: https://github.com/NetrexMC/RakNet/issues/55 10 | #[test] 11 | fn test_proper_reordering() { 12 | let mut queue = FragmentQueue::new(); 13 | 14 | const SLICE_ONE: &[u8] = &[1, 2, 3, 4, 5]; 15 | const SLICE_TWO: &[u8] = &[6, 7, 8, 9, 10]; 16 | const SLICE_THREE: &[u8] = &[11, 12, 13, 14, 15]; 17 | 18 | // push slice 2 first, then slice 1, then slice 3 19 | queue 20 | .insert( 21 | Frame::new(Reliability::ReliableOrd, Some(SLICE_TWO)) 22 | .with_meta(FragmentMeta::new(3, 11, 1)), 23 | ) 24 | .unwrap(); 25 | 26 | queue 27 | .insert( 28 | Frame::new(Reliability::ReliableOrd, Some(SLICE_ONE)) 29 | .with_meta(FragmentMeta::new(3, 11, 0)), 30 | ) 31 | .unwrap(); 32 | 33 | queue 34 | .insert( 35 | Frame::new(Reliability::ReliableOrd, Some(SLICE_THREE)) 36 | .with_meta(FragmentMeta::new(3, 11, 2)), 37 | ) 38 | .unwrap(); 39 | 40 | // collect the fragments 41 | let res = queue.collect(11); 42 | 43 | assert_eq!( 44 | res.unwrap(), 45 | vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] 46 | ); 47 | } 48 | --------------------------------------------------------------------------------