├── .gitignore ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md └── src ├── client.rs ├── codec.rs ├── conn_state.rs ├── crypto.rs ├── frame.rs ├── handshake.rs ├── http ├── client.rs ├── frame.rs └── mod.rs ├── lib.rs ├── nquic.rs ├── packet.rs ├── parameters.rs ├── server.rs ├── streams.rs └── types.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | /*.key 5 | /*.crt 6 | /*.pem 7 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ninn" 3 | version = "0.1.0" 4 | authors = ["Mathias Hall-Andersen ", "Dirkjan Ochtman "] 5 | description = "Futures-based nQUIC implementation" 6 | keywords = ["quic", "tokio"] 7 | categories = ["network-programming"] 8 | repository = "https://github.com/rot256/ninn" 9 | license = "MIT/Apache-2.0" 10 | 11 | [dependencies] 12 | bytes = "0.4.7" 13 | failure = "0.1" 14 | failure_derive = "0.1" 15 | futures = "0.1" 16 | hex = "0.3.2" 17 | log = "0.4" 18 | tokio = "0.1" 19 | tokio-core = "*" 20 | rand = "=0.5.0-pre.2" 21 | ring = "0.13.0-alpha" 22 | webpki = "0.18.0-alpha" 23 | webpki-roots = "0.14" 24 | lazy_static = "*" 25 | 26 | [dependencies.rustls] 27 | git = "https://github.com/ctz/rustls" 28 | branch = "jbp-tls13-draft-28" 29 | features = ["quic"] 30 | 31 | [dependencies.snow] 32 | git = "https://github.com/rot256/snow" 33 | branch = "master" 34 | 35 | [dev-dependencies] 36 | env_logger = "0.5" 37 | untrusted = "0.6" 38 | hex = "*" 39 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Dirkjan Ochtman 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ninn 2 | 3 | This is a work-in-progress implementation of the nQUIC draft, based on Quinn. 4 | -------------------------------------------------------------------------------- /src/client.rs: -------------------------------------------------------------------------------- 1 | use futures::{task, Async, Future, Poll}; 2 | 3 | use super::{QuicError, QuicResult}; 4 | use conn_state::ConnectionState; 5 | use parameters::ClientTransportParameters; 6 | use streams::Streams; 7 | use handshake; 8 | 9 | use std::net::{SocketAddr, ToSocketAddrs}; 10 | use std::time::Duration; 11 | use tokio::net::UdpSocket; 12 | use tokio::prelude::future::Select; 13 | use tokio_core::reactor; 14 | 15 | pub struct Client { 16 | conn_state: ConnectionState, 17 | socket: UdpSocket, 18 | buf: Vec, 19 | } 20 | 21 | impl Client { 22 | pub fn connect(server: &str, port: u16, server_static: [u8; 32], client_static: Option<[u8; 32]>) 23 | -> QuicResult 24 | { 25 | ConnectFuture::new( 26 | Self::new(server, port, server_static, client_static)? 27 | ) 28 | } 29 | 30 | pub(crate) fn new(server: &str, port: u16, server_static: [u8; 32], client_static: Option<[u8; 32]>) -> QuicResult { 31 | let handshake = handshake::client_session( 32 | server_static, 33 | client_static, 34 | ClientTransportParameters::default().clone()); 35 | Self::with_state(server, port, ConnectionState::new(handshake, None)) 36 | } 37 | 38 | pub(crate) fn with_state( 39 | server: &str, 40 | port: u16, 41 | conn_state: ConnectionState, 42 | ) -> QuicResult { 43 | let addr = (server, port).to_socket_addrs()?.next().ok_or_else(|| { 44 | QuicError::General(format!("no address found for '{}:{}'", server, port)) 45 | })?; 46 | 47 | let local = match addr { 48 | SocketAddr::V4(_) => SocketAddr::from(([0, 0, 0, 0], 0)), 49 | SocketAddr::V6(_) => SocketAddr::from(([0, 0, 0, 0, 0, 0, 0, 0], 0)), 50 | }; 51 | 52 | let socket = UdpSocket::bind(&local)?; 53 | socket.connect(&addr)?; 54 | Ok(Self { 55 | conn_state, 56 | socket, 57 | buf: vec![0u8; 65536], 58 | }) 59 | } 60 | 61 | fn poll_send(&mut self) -> Poll<(), QuicError> { 62 | if let Some(buf) = self.conn_state.queued()? { 63 | let len = try_ready!(self.socket.poll_send(&buf)); 64 | debug_assert_eq!(len, buf.len()); 65 | } 66 | self.conn_state.pop_queue(); 67 | Ok(Async::Ready(())) 68 | } 69 | } 70 | 71 | impl Future for Client { 72 | type Item = (); 73 | type Error = QuicError; 74 | fn poll(&mut self) -> Poll { 75 | self.conn_state.streams.set_task(task::current()); 76 | loop { 77 | match self.poll_send() { 78 | Ok(Async::Ready(())) | Ok(Async::NotReady) => {} 79 | e @ Err(_) => try_ready!(e), 80 | } 81 | let len = try_ready!(self.socket.poll_recv(&mut self.buf)); 82 | match self.conn_state.handle(&mut self.buf[..len]) { 83 | Ok(_) => (), 84 | Err(err) => { 85 | debug!("error, failed to handle message {:?}", err); 86 | () 87 | } 88 | } 89 | } 90 | } 91 | } 92 | 93 | #[must_use = "futures do nothing unless polled"] 94 | pub struct ConnectFuture { 95 | client : Option, 96 | timeout : reactor::Timeout, 97 | } 98 | 99 | impl ConnectFuture { 100 | fn new(mut client: Client) -> QuicResult { 101 | let core = reactor::Core::new().unwrap(); 102 | let handle = core.handle(); 103 | Ok(ConnectFuture { 104 | client : Some(client), 105 | timeout : reactor::Timeout::new( 106 | Duration::from_millis(1000), &handle 107 | ).unwrap(), 108 | }) 109 | } 110 | } 111 | 112 | impl Future for ConnectFuture { 113 | type Item = (Client, Streams); 114 | type Error = QuicError; 115 | fn poll(&mut self) -> Poll { 116 | 117 | // poll timeout 118 | 119 | match self.timeout.poll() { 120 | Err(_) => return Err(QuicError::Timeout), 121 | Ok(Async::Ready(_)) => return Err(QuicError::Timeout), 122 | _ => (), 123 | }; 124 | 125 | // poll for connection progression 126 | 127 | let done = if let Some(ref mut client) = self.client { 128 | match client.poll() { 129 | Err(e) => { 130 | return Err(e); 131 | } 132 | _ => !client.conn_state.is_handshaking(), 133 | } 134 | } else { 135 | panic!("invalid state for ConnectFuture"); 136 | }; 137 | 138 | if done { 139 | match self.client.take() { 140 | Some(client) => { 141 | let streams = client.conn_state.streams.clone(); 142 | Ok(Async::Ready((client, streams))) 143 | } 144 | _ => panic!("invalid future state"), 145 | } 146 | } else { 147 | Ok(Async::NotReady) 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/codec.rs: -------------------------------------------------------------------------------- 1 | use super::{QuicError, QuicResult}; 2 | use bytes::{Buf, BufMut}; 3 | 4 | pub struct VarLen(pub u64); 5 | 6 | impl BufLen for VarLen { 7 | fn buf_len(&self) -> usize { 8 | match self.0 { 9 | v if v <= 63 => 1, 10 | v if v <= 16_383 => 2, 11 | v if v <= 1_073_741_823 => 4, 12 | v if v <= 4_611_686_018_427_387_903 => 8, 13 | v => panic!("too large for variable-length encoding: {}", v), 14 | } 15 | } 16 | } 17 | 18 | impl Codec for VarLen { 19 | fn encode(&self, buf: &mut T) { 20 | match self.buf_len() { 21 | 1 => buf.put_u8(self.0 as u8), 22 | 2 => buf.put_u16_be(self.0 as u16 | 16384), 23 | 4 => buf.put_u32_be(self.0 as u32 | 2_147_483_648), 24 | 8 => buf.put_u64_be(self.0 | 13_835_058_055_282_163_712), 25 | _ => panic!("impossible variable-length encoding"), 26 | } 27 | } 28 | 29 | fn decode(buf: &mut T) -> QuicResult { 30 | let first = buf.get_u8(); 31 | let be_val = first & 0x3f; 32 | let val = match first >> 6 { 33 | 0 => u64::from(be_val), 34 | 1 => u64::from(be_val) << 8 | u64::from(buf.get_u8()), 35 | 2 => { 36 | u64::from(be_val) << 24 | u64::from(buf.get_u8()) << 16 37 | | u64::from(buf.get_u16_be()) 38 | } 39 | 3 => { 40 | u64::from(be_val) << 56 | u64::from(buf.get_u8()) << 48 41 | | u64::from(buf.get_u16_be()) << 32 42 | | u64::from(buf.get_u32_be()) 43 | } 44 | v => { 45 | return Err(QuicError::DecodeError(format!( 46 | "impossible variable length encoding: {}", 47 | v 48 | ))) 49 | } 50 | }; 51 | Ok(VarLen(val)) 52 | } 53 | } 54 | 55 | pub trait BufLen { 56 | fn buf_len(&self) -> usize; 57 | } 58 | 59 | impl BufLen for Option 60 | where 61 | T: BufLen, 62 | { 63 | fn buf_len(&self) -> usize { 64 | match self { 65 | Some(v) => v.buf_len(), 66 | None => 0, 67 | } 68 | } 69 | } 70 | 71 | impl BufLen for Vec 72 | where 73 | T: BufLen, 74 | { 75 | fn buf_len(&self) -> usize { 76 | self.iter().map(|i| i.buf_len()).sum() 77 | } 78 | } 79 | 80 | pub trait Codec: Sized { 81 | // TODO q on add sized 82 | fn encode(&self, buf: &mut T); 83 | fn decode(buf: &mut T) -> QuicResult; 84 | } 85 | 86 | #[cfg(test)] 87 | mod tests { 88 | use super::{Codec, VarLen}; 89 | use std::io::Cursor; 90 | #[test] 91 | fn test_var_len_encoding_8() { 92 | let num = 151_288_809_941_952_652; 93 | let bytes = b"\xc2\x19\x7c\x5e\xff\x14\xe8\x8c"; 94 | 95 | let mut buf = Vec::new(); 96 | VarLen(num).encode(&mut buf); 97 | assert_eq!(bytes[..], *buf); 98 | 99 | let mut read = Cursor::new(bytes); 100 | assert_eq!(VarLen::decode(&mut read).expect("Invalid VarLen").0, num); 101 | } 102 | #[test] 103 | fn test_var_len_encoding_4() { 104 | let num = 494_878_333; 105 | let bytes = b"\x9d\x7f\x3e\x7d"; 106 | 107 | let mut buf = Vec::new(); 108 | VarLen(num).encode(&mut buf); 109 | assert_eq!(bytes[..], *buf); 110 | 111 | let mut read = Cursor::new(bytes); 112 | assert_eq!(VarLen::decode(&mut read).expect("Invalid VarLen").0, num); 113 | } 114 | #[test] 115 | fn test_var_len_encoding_2() { 116 | let num = 15_293; 117 | let bytes = b"\x7b\xbd"; 118 | 119 | let mut buf = Vec::new(); 120 | VarLen(num).encode(&mut buf); 121 | assert_eq!(bytes[..], *buf); 122 | 123 | let mut read = Cursor::new(bytes); 124 | assert_eq!(VarLen::decode(&mut read).expect("Invalid VarLen").0, num); 125 | } 126 | #[test] 127 | fn test_var_len_encoding_1_short() { 128 | let num = 37; 129 | let bytes = b"\x25"; 130 | 131 | let mut buf = Vec::new(); 132 | VarLen(num).encode(&mut buf); 133 | assert_eq!(bytes[..], *buf); 134 | 135 | let mut read = Cursor::new(bytes); 136 | assert_eq!(VarLen::decode(&mut read).expect("Invalid VarLen").0, num); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/conn_state.rs: -------------------------------------------------------------------------------- 1 | use bytes::Buf; 2 | 3 | use rand::{thread_rng, Rng}; 4 | 5 | use std::collections::VecDeque; 6 | use std::io::Cursor; 7 | use std::mem; 8 | 9 | use hex; 10 | 11 | use super::{QuicError, QuicResult, QUIC_VERSION}; 12 | use codec::Codec; 13 | use crypto::Secret; 14 | use frame::{Ack, AckFrame, CloseFrame, Frame, PaddingFrame, PathFrame, CryptoFrame}; 15 | use packet::{Header, LongType, PartialDecode, ShortType}; 16 | use parameters::TransportParameters; 17 | use streams::Streams; 18 | use handshake; 19 | use types::{ConnectionId, Side, GENERATED_CID_LENGTH}; 20 | 21 | pub struct ConnectionState { 22 | side: Side, 23 | state: State, 24 | local: PeerData, 25 | remote: PeerData, 26 | dst_pn: u32, 27 | src_pn: u32, 28 | secret: Secret, 29 | prev_secret: Option, 30 | pub streams: Streams, 31 | queue: VecDeque>, 32 | control: VecDeque, 33 | handshake: T, 34 | pmtu: usize, 35 | } 36 | 37 | fn recover_packet_number(current : u32, pn : u32, t : ShortType) -> u32 { 38 | let mask = match t { 39 | ShortType::One => 0xffff_ff00, 40 | ShortType::Two => 0xffff_0000, 41 | ShortType::Four => 0x0000_0000, 42 | }; 43 | 44 | let new = (current & mask) | pn; 45 | let off = (mask & 0xffff_ffff) + 1; 46 | return if new < current { 47 | new + off 48 | } else { 49 | new 50 | } 51 | } 52 | 53 | impl ConnectionState 54 | where 55 | T: handshake::Session + handshake::QuicSide, 56 | { 57 | pub fn new(handshake: T, secret: Option) -> Self { 58 | let mut rng = thread_rng(); 59 | let dst_cid = rng.gen(); 60 | let side = handshake.side(); 61 | 62 | let secret = if side == Side::Client { 63 | debug_assert!(secret.is_none()); 64 | Secret::Handshake(dst_cid) 65 | } else if let Some(secret) = secret { 66 | secret 67 | } else { 68 | panic!("need secret for client conn_state"); 69 | }; 70 | 71 | let local = PeerData::new(rng.gen()); 72 | let (num_recv_bidi, num_recv_uni) = ( 73 | u64::from(local.params.max_streams_bidi), 74 | u64::from(local.params.max_stream_id_uni), 75 | ); 76 | let (max_recv_bidi, max_recv_uni) = if side == Side::Client { 77 | (1 + 4 * num_recv_bidi, 3 + 4 * num_recv_uni) 78 | } else { 79 | (4 * num_recv_bidi, 1 + 4 * num_recv_uni) 80 | }; 81 | 82 | let mut streams = Streams::new(side); 83 | streams.update_max_id(max_recv_bidi); 84 | streams.update_max_id(max_recv_uni); 85 | 86 | ConnectionState { 87 | handshake, 88 | side, 89 | state: State::Start, 90 | remote: PeerData::new(dst_cid), 91 | local, 92 | src_pn: rng.gen(), 93 | dst_pn: 0, 94 | secret, 95 | prev_secret: None, 96 | streams, 97 | queue: VecDeque::new(), 98 | control: VecDeque::new(), 99 | pmtu: IPV6_MIN_MTU, 100 | } 101 | } 102 | 103 | pub fn is_handshaking(&self) -> bool { 104 | match self.state { 105 | State::Connected => false, 106 | _ => true, 107 | } 108 | } 109 | 110 | pub fn queued(&mut self) -> QuicResult>> { 111 | self.queue_packet()?; 112 | Ok(self.queue.front()) 113 | } 114 | 115 | pub fn pop_queue(&mut self) { 116 | self.queue.pop_front(); 117 | } 118 | 119 | pub fn pick_unused_cid(&mut self, is_used: F) -> ConnectionId 120 | where 121 | F: Fn(ConnectionId) -> bool, 122 | { 123 | while is_used(self.local.cid) { 124 | self.local.cid = thread_rng().gen(); 125 | } 126 | self.local.cid 127 | } 128 | 129 | pub(crate) fn set_secret(&mut self, secret: Secret) { 130 | let old = mem::replace(&mut self.secret, secret); 131 | self.prev_secret = Some(old); 132 | } 133 | 134 | #[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))] 135 | pub fn queue_packet(&mut self) -> QuicResult<()> { 136 | 137 | let (dst_cid, src_cid) = (self.remote.cid, self.local.cid); 138 | debug_assert_eq!(src_cid.len, GENERATED_CID_LENGTH); 139 | let number = self.src_pn; 140 | self.src_pn += 1; 141 | 142 | 143 | let (ptype, new_state) = match self.state { 144 | State::Connected => (None, self.state), 145 | State::Handshaking => (Some(LongType::Handshake), self.state), 146 | State::InitialSent => (Some(LongType::Handshake), State::Handshaking), 147 | State::Start => if self.side == Side::Client { 148 | (Some(LongType::Initial), State::InitialSent) 149 | } else { 150 | (Some(LongType::Handshake), State::Handshaking) 151 | } 152 | State::ConfirmHandshake => (Some(LongType::Handshake), State::ConfirmHandshake), 153 | }; 154 | 155 | 156 | let header_len = match ptype { 157 | Some(_) => (12 + (dst_cid.len + src_cid.len) as usize), 158 | None => (3 + dst_cid.len as usize), 159 | }; 160 | 161 | let secret = if let Some(LongType::Handshake) = ptype { 162 | if let Some(ref secret @ Secret::Handshake(_)) = self.prev_secret { 163 | secret 164 | } else { 165 | &self.secret 166 | } 167 | } else { 168 | &self.secret 169 | }; 170 | 171 | println!("debug : queue packet"); 172 | println!("debug : src_pn = {}", self.src_pn); 173 | println!("debug : type = {:?}", ptype); 174 | println!("debug : secret = {:?}", secret); 175 | 176 | let key = secret.build_key(self.side); 177 | let tag_len = key.algorithm().tag_len(); 178 | 179 | let mut buf = vec![0u8; self.pmtu]; 180 | let payload_len = { 181 | let mut write = Cursor::new(&mut buf[header_len..self.pmtu - tag_len]); 182 | while let Some(frame) = self.control.pop_front() { 183 | println!("debug : control frame"); 184 | println!("debug : {:?}", frame); 185 | frame.encode(&mut write); 186 | } 187 | self.streams.poll_send(&mut write); 188 | 189 | let mut payload_len = write.position() as usize; 190 | let initial_min_size = 1200 - header_len - tag_len; 191 | if ptype == Some(LongType::Initial) && payload_len < initial_min_size { 192 | Frame::Padding(PaddingFrame(initial_min_size - payload_len)).encode(&mut write); 193 | payload_len = initial_min_size; 194 | } 195 | payload_len 196 | }; 197 | 198 | if payload_len == 0 { 199 | return Ok(()); 200 | } 201 | 202 | let header = match ptype { 203 | Some(ltype) => Header::Long { 204 | ptype: ltype, 205 | version: QUIC_VERSION, 206 | dst_cid, 207 | src_cid, 208 | len: (payload_len + tag_len) as u64, 209 | number, 210 | }, 211 | None => Header::Short { 212 | key_phase: false, 213 | ptype: ShortType::Two, 214 | dst_cid, 215 | number, 216 | }, 217 | }; 218 | 219 | println!("{:?}", header); 220 | 221 | { 222 | let mut write = Cursor::new(&mut buf[..header_len]); 223 | header.encode(&mut write); 224 | } 225 | 226 | let out_len = { 227 | let (header_buf, mut payload) = buf.split_at_mut(header_len); 228 | let mut in_out = &mut payload[..payload_len + tag_len]; 229 | key.encrypt(number, &header_buf, in_out, tag_len)? 230 | }; 231 | 232 | buf.truncate(header_len + out_len); 233 | self.queue.push_back(buf); 234 | self.state = new_state; 235 | Ok(()) 236 | } 237 | 238 | pub(crate) fn handle(&mut self, buf: &mut [u8]) -> QuicResult<()> { 239 | println!("debug : handle packet:"); 240 | println!("debug : buf = {}", hex::encode(&buf)); 241 | let pdecode = PartialDecode::new(buf)?; 242 | self.handle_partial(pdecode) 243 | } 244 | 245 | pub(crate) fn handle_partial(&mut self, partial: PartialDecode) -> QuicResult<()> { 246 | let PartialDecode { 247 | header, 248 | header_len, 249 | buf, 250 | } = partial; 251 | 252 | let key = { 253 | let secret = &self.secret; 254 | println!("debug : key = {:?}", &secret); 255 | secret.build_key(self.side.other()) 256 | }; 257 | 258 | println!("debug : state = {:?}", &self.state); 259 | println!("debug : header = {:?}", header); 260 | 261 | let payload = match header { 262 | Header::Long { number, .. } | Header::Short { number, .. } => { 263 | let (header_buf, payload_buf) = buf.split_at_mut(header_len); 264 | 265 | let number = match header { 266 | Header::Short { ptype, .. } => 267 | recover_packet_number(self.dst_pn, number, ptype), 268 | _ => number, 269 | }; 270 | 271 | let decrypted = key.decrypt(number, &header_buf, payload_buf)?; 272 | 273 | self.dst_pn = number; 274 | 275 | // implicit confirmation 276 | 277 | match self.state { 278 | State::ConfirmHandshake => { 279 | println!("debug : connection confirmed"); 280 | self.state = State::Connected; 281 | } 282 | _ => (), 283 | } 284 | 285 | let mut read = Cursor::new(decrypted); 286 | let mut payload = Vec::new(); 287 | while read.has_remaining() { 288 | let frame = Frame::decode(&mut read)?; 289 | payload.push(frame); 290 | } 291 | payload 292 | } 293 | Header::Negotiation { .. } => vec![], 294 | }; 295 | 296 | self.handle_packet(header, payload) 297 | } 298 | 299 | #[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))] 300 | fn handle_packet(&mut self, header: Header, payload: Vec) -> QuicResult<()> { 301 | let (dst_cid, number) = match header { 302 | Header::Long { 303 | dst_cid, 304 | src_cid, 305 | number, 306 | .. 307 | } => match self.state { 308 | State::Start | State::InitialSent => { 309 | self.remote.cid = src_cid; 310 | (dst_cid, number) 311 | } 312 | _ => (dst_cid, number), 313 | }, 314 | Header::Short { 315 | dst_cid, number, .. 316 | } => if let State::Connected = self.state { 317 | (dst_cid, number) 318 | } else { 319 | return Err(QuicError::General(format!( 320 | "{:?} received short header in {:?} state", 321 | self.side, self.state 322 | ))); 323 | }, 324 | Header::Negotiation { .. } => { 325 | return Err(QuicError::General( 326 | "negotiation packet not handled by connections".into(), 327 | )); 328 | } 329 | }; 330 | 331 | if self.state != State::Start && dst_cid != self.local.cid { 332 | return Err(QuicError::General(format!( 333 | "invalid destination CID {:?} received (expected {:?} in state {:?})", 334 | dst_cid, self.local.cid, self.state 335 | ))); 336 | } 337 | 338 | let mut prologue = false; 339 | let mut send_ack = false; 340 | for frame in &payload { 341 | println!("debug : decoded frame:"); 342 | println!("debug : {:?}", frame); 343 | println!("debug : {:?}", header.ptype()); 344 | match frame { 345 | Frame::Crypto(f) => { 346 | match header.ptype() { 347 | Some(LongType::Initial) => 348 | { 349 | if self.side == Side::Client { 350 | return Err(QuicError::General(format!( 351 | "client received initial message" 352 | ))); 353 | }; 354 | 355 | if prologue { 356 | self.handle_handshake_message(&f.payload)?; 357 | } else { 358 | println!("debug : set prologue"); 359 | self.handshake.set_prologue(&f.payload)?; 360 | prologue = true; 361 | }; 362 | } 363 | Some(LongType::Handshake) => 364 | self.handle_handshake_message(&f.payload)?, 365 | _ => (), 366 | }; 367 | } 368 | Frame::Stream(f) => { 369 | assert!(self.state == State::Connected); 370 | send_ack = true; 371 | self.streams.received(f)?; 372 | } 373 | Frame::PathChallenge(PathFrame(token)) => { 374 | send_ack = true; 375 | self.control 376 | .push_back(Frame::PathResponse(PathFrame(*token))); 377 | } 378 | Frame::ApplicationClose(CloseFrame { code, reason }) => { 379 | return Err(QuicError::ApplicationClose(*code, reason.clone())); 380 | } 381 | Frame::ConnectionClose(CloseFrame { code, reason }) => { 382 | return Err(QuicError::ConnectionClose(*code, reason.clone())); 383 | } 384 | Frame::PathResponse(_) | Frame::Ping | Frame::StreamIdBlocked(_) => { 385 | send_ack = true; 386 | } 387 | Frame::Ack(_) | Frame::Padding(_) => {} 388 | } 389 | } 390 | 391 | if send_ack { 392 | self.control.push_back(Frame::Ack(AckFrame { 393 | largest: number, 394 | ack_delay: 0, 395 | blocks: vec![Ack::Ack(0)], 396 | })); 397 | } 398 | 399 | Ok(()) 400 | } 401 | 402 | fn handle_handshake_message(&mut self, msg : &[u8]) -> QuicResult<()> { 403 | 404 | println!("debug : handle handshake message:"); 405 | println!("debug : length = {}", msg.len()); 406 | println!("debug : msg = {}", hex::encode(msg)); 407 | 408 | let (new_msg, new_secret) = self.handshake.process_handshake_message(msg)?; 409 | 410 | // process new key material 411 | 412 | if let Some(secret) = new_secret { 413 | 414 | /* TODO 415 | mem::replace(&mut self.remote.params, params); 416 | */ 417 | 418 | let (num_send_bidi, num_send_uni) = ( 419 | u64::from(self.remote.params.max_streams_bidi), 420 | u64::from(self.remote.params.max_stream_id_uni), 421 | ); 422 | 423 | let (max_send_bidi, max_send_uni) = if self.side == Side::Server { 424 | (1 + 4 * num_send_bidi, 3 + 4 * num_send_uni) 425 | } else { 426 | (4 * num_send_bidi, 1 + 4 * num_send_uni) 427 | }; 428 | self.streams.update_max_id(max_send_bidi); 429 | self.streams.update_max_id(max_send_uni); 430 | 431 | // update secret 432 | 433 | self.set_secret(secret); 434 | 435 | // update state 436 | 437 | match self.side { 438 | Side::Client => { 439 | self.state = State::Connected; 440 | self.control.push_back(Frame::Padding(PaddingFrame(1))); // TODO : less hacky 441 | }, 442 | Side::Server => { 443 | self.state = State::ConfirmHandshake; 444 | } 445 | }; 446 | } 447 | 448 | // send new message 449 | 450 | if let Some(msg) = new_msg { 451 | assert!(self.is_handshaking()); 452 | println!("debug : send handshake message"); 453 | println!("debug : msg = {} ", hex::encode(&msg)); 454 | self.control.push_back(Frame::Crypto(CryptoFrame { 455 | offset : 0, 456 | length : msg.len() as u64, 457 | payload : msg, 458 | })); 459 | } 460 | 461 | Ok(()) 462 | } 463 | } 464 | 465 | impl ConnectionState { 466 | pub(crate) fn initial(&mut self, prologue : &[u8]) -> QuicResult<()> { 467 | println!("debug : create initial handshake packet"); 468 | 469 | let msg = self.handshake.create_handshake_request(prologue)?; 470 | 471 | // push prologue frame 472 | 473 | self.control.push_back(Frame::Crypto(CryptoFrame{ 474 | offset : 0, 475 | length : prologue.len() as u64, 476 | payload : prologue.to_owned(), 477 | })); 478 | 479 | // push crypto frame 480 | 481 | debug_assert!(msg.len() < (1 << 16)); 482 | self.control.push_back(Frame::Crypto(CryptoFrame{ 483 | offset : 0, 484 | length : msg.len() as u64, 485 | payload : msg, 486 | })); 487 | 488 | Ok(()) 489 | } 490 | } 491 | 492 | pub struct PeerData { 493 | pub cid: ConnectionId, 494 | pub params: TransportParameters, 495 | } 496 | 497 | impl PeerData { 498 | pub fn new(cid: ConnectionId) -> Self { 499 | PeerData { 500 | cid, 501 | params: TransportParameters::default(), 502 | } 503 | } 504 | } 505 | 506 | #[derive(Clone, Copy, Debug, PartialEq)] 507 | enum State { 508 | Start, 509 | InitialSent, 510 | Handshaking, 511 | ConfirmHandshake, 512 | Connected, 513 | } 514 | 515 | const IPV6_MIN_MTU: usize = 1232; 516 | -------------------------------------------------------------------------------- /src/crypto.rs: -------------------------------------------------------------------------------- 1 | use bytes::{Buf, BufMut}; 2 | 3 | use std::fmt; 4 | use std::io::Cursor; 5 | 6 | use ring::aead::{self, OpeningKey, SealingKey}; 7 | use ring::{digest, hkdf}; 8 | 9 | pub use ring::aead::AES_256_GCM; 10 | pub use ring::digest::SHA256; 11 | pub use ring::hmac::SigningKey; 12 | 13 | use super::{QuicError, QuicResult}; 14 | use types::{ConnectionId, Side}; 15 | 16 | pub enum Secret { 17 | Handshake(ConnectionId), 18 | For1Rtt( 19 | &'static aead::Algorithm, 20 | &'static digest::Algorithm, 21 | Vec, 22 | Vec, 23 | ), 24 | } 25 | 26 | impl Secret { 27 | pub fn tag_len(&self) -> usize { 28 | match self { 29 | Secret::Handshake(_) => AES_256_GCM.tag_len(), 30 | Secret::For1Rtt(aead_alg, _, _, _) => aead_alg.tag_len(), 31 | } 32 | } 33 | 34 | pub fn build_key(&self, side: Side) -> PacketKey { 35 | match self { 36 | Secret::Handshake(cid) => { 37 | let label = if side == Side::Client { 38 | b"client hs" 39 | } else { 40 | b"server hs" 41 | }; 42 | PacketKey::new( 43 | &AES_256_GCM, 44 | &SHA256, 45 | &expanded_handshake_secret(*cid, label), 46 | ) 47 | } 48 | Secret::For1Rtt(aead_alg, hash_alg, ref client_secret, ref server_secret) => { 49 | PacketKey::new( 50 | aead_alg, 51 | hash_alg, 52 | match side { 53 | Side::Client => client_secret, 54 | Side::Server => server_secret, 55 | }, 56 | ) 57 | } 58 | } 59 | } 60 | } 61 | 62 | impl fmt::Debug for Secret { 63 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 64 | match self { 65 | Secret::Handshake(cid) => write!(f, "Handshake({:?})", cid), 66 | Secret::For1Rtt(_, _, _, _) => write!(f, "For1Rtt()"), 67 | } 68 | } 69 | } 70 | 71 | pub struct PacketKey { 72 | alg: &'static aead::Algorithm, 73 | data: Vec, 74 | split: usize, 75 | } 76 | 77 | impl PacketKey { 78 | pub fn new( 79 | aead_alg: &'static aead::Algorithm, 80 | hash_alg: &'static digest::Algorithm, 81 | secret: &[u8], 82 | ) -> Self { 83 | let mut res = Self { 84 | alg: aead_alg, 85 | data: vec![0; aead_alg.key_len() + aead_alg.nonce_len()], 86 | split: aead_alg.key_len(), 87 | }; 88 | let secret_key = SigningKey::new(hash_alg, secret); 89 | qhkdf_expand(&secret_key, b"key", &mut res.data[..res.split]); 90 | qhkdf_expand(&secret_key, b"iv", &mut res.data[res.split..]); 91 | res 92 | } 93 | 94 | pub fn algorithm(&self) -> &aead::Algorithm { 95 | self.alg 96 | } 97 | 98 | pub fn write_nonce(&self, number: u32, out: &mut [u8]) { 99 | debug_assert_eq!(out.len(), self.alg.nonce_len()); 100 | let out = { 101 | let mut write = Cursor::new(out); 102 | write.put_u32_be(0); 103 | write.put_u64_be(u64::from(number)); 104 | debug_assert_eq!(write.remaining(), 0); 105 | write.into_inner() 106 | }; 107 | let iv = &self.data[self.split..]; 108 | for i in 0..self.alg.nonce_len() { 109 | out[i] ^= iv[i]; 110 | } 111 | } 112 | 113 | pub fn encrypt( 114 | &self, 115 | number: u32, 116 | ad: &[u8], 117 | in_out: &mut [u8], 118 | out_suffix_capacity: usize, 119 | ) -> QuicResult { 120 | let key = SealingKey::new(self.alg, &self.data[..self.split]) 121 | .map_err(|_| QuicError::EncryptError)?; 122 | let mut nonce_buf = [0u8; aead::MAX_TAG_LEN]; 123 | let nonce = &mut nonce_buf[..self.alg.nonce_len()]; 124 | self.write_nonce(number, nonce); 125 | aead::seal_in_place(&key, &*nonce, ad, in_out, out_suffix_capacity) 126 | .map_err(|_| QuicError::EncryptError) 127 | } 128 | 129 | pub fn decrypt<'a>( 130 | &self, 131 | number: u32, 132 | ad: &[u8], 133 | input: &'a mut [u8], 134 | ) -> QuicResult<&'a mut [u8]> { 135 | let key = OpeningKey::new(self.alg, &self.data[..self.split]) 136 | .map_err(|_| QuicError::DecryptError)?; 137 | let mut nonce_buf = [0u8; aead::MAX_TAG_LEN]; 138 | let nonce = &mut nonce_buf[..self.alg.nonce_len()]; 139 | self.write_nonce(number, nonce); 140 | aead::open_in_place(&key, &*nonce, ad, 0, input).map_err(|_| QuicError::DecryptError) 141 | } 142 | } 143 | 144 | pub fn expanded_handshake_secret(conn_id: ConnectionId, label: &[u8]) -> Vec { 145 | let prk = handshake_secret(conn_id); 146 | let mut out = vec![0u8; SHA256.output_len]; 147 | qhkdf_expand(&prk, label, &mut out); 148 | out 149 | } 150 | 151 | pub fn qhkdf_expand(key: &SigningKey, label: &[u8], out: &mut [u8]) { 152 | let mut info = Vec::with_capacity(2 + 1 + 5 + out.len()); 153 | info.put_u16_be(out.len() as u16); 154 | info.put_u8(5 + (label.len() as u8)); 155 | info.extend_from_slice(b"QUIC "); 156 | info.extend_from_slice(&label); 157 | hkdf::expand(key, &info, out); 158 | } 159 | 160 | fn handshake_secret(conn_id: ConnectionId) -> SigningKey { 161 | let key = SigningKey::new(&SHA256, HANDSHAKE_SALT); 162 | let mut buf = Vec::with_capacity(8); 163 | buf.put_slice(&conn_id); 164 | hkdf::extract(&key, &buf) 165 | } 166 | 167 | const HANDSHAKE_SALT: &[u8; 20] = 168 | b"\x9c\x10\x8f\x98\x52\x0a\x5c\x5c\x32\x96\x8e\x95\x0e\x8a\x2c\x5f\xe0\x6d\x6c\x38"; 169 | 170 | #[cfg(test)] 171 | mod tests { 172 | use types::ConnectionId; 173 | 174 | #[test] 175 | fn test_handshake_client() { 176 | let hs_cid = ConnectionId { 177 | len: 8, 178 | bytes: [ 179 | 0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180 | ], 181 | }; 182 | let client_handshake_secret = super::expanded_handshake_secret(hs_cid, b"client hs"); 183 | let expected = b"\x83\x55\xf2\x1a\x3d\x8f\x83\xec\xb3\xd0\xf9\x71\x08\xd3\xf9\x5e\ 184 | \x0f\x65\xb4\xd8\xae\x88\xa0\x61\x1e\xe4\x9d\xb0\xb5\x23\x59\x1d"; 185 | assert_eq!(&client_handshake_secret, expected); 186 | let input = super::PacketKey::new( 187 | &super::AES_256_GCM, 188 | &super::SHA256, 189 | &client_handshake_secret, 190 | ); 191 | assert_eq!( 192 | &input.data[..input.split], 193 | b"\x3a\xd0\x54\x2c\x4a\x85\x84\x74\x00\x63\x04\x9e\x3b\x3c\xaa\xb2" 194 | ); 195 | assert_eq!( 196 | &input.data[input.split..], 197 | b"\xd1\xfd\x26\x05\x42\x75\x3a\xba\x38\x58\x9b\xad" 198 | ); 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /src/frame.rs: -------------------------------------------------------------------------------- 1 | use bytes::{Buf, BufMut}; 2 | 3 | use codec::{BufLen, Codec, VarLen}; 4 | 5 | use std::str; 6 | 7 | use super::{QuicError, QuicResult}; 8 | 9 | const CRYPTO_FRAME_ID : u8 = 0x18; // see draft-13 10 | 11 | #[derive(Debug, PartialEq)] 12 | pub enum Frame { 13 | Ack(AckFrame), 14 | ApplicationClose(CloseFrame), 15 | ConnectionClose(CloseFrame), 16 | Padding(PaddingFrame), 17 | PathChallenge(PathFrame), 18 | PathResponse(PathFrame), 19 | Ping, 20 | Stream(StreamFrame), 21 | StreamIdBlocked(StreamIdBlockedFrame), 22 | Crypto(CryptoFrame), 23 | } 24 | 25 | impl BufLen for Frame { 26 | fn buf_len(&self) -> usize { 27 | match self { 28 | Frame::Ack(f) => f.buf_len(), 29 | Frame::Crypto(f) => 1 + f.buf_len(), 30 | Frame::ApplicationClose(f) => 1 + f.buf_len(), 31 | Frame::ConnectionClose(f) => 1 + f.buf_len(), 32 | Frame::Padding(f) => f.buf_len(), 33 | Frame::PathChallenge(f) => 1 + f.buf_len(), 34 | Frame::PathResponse(f) => 1 + f.buf_len(), 35 | Frame::Ping => 1, 36 | Frame::Stream(f) => f.buf_len(), 37 | Frame::StreamIdBlocked(f) => 1 + f.buf_len(), 38 | } 39 | } 40 | } 41 | 42 | impl Codec for Frame { 43 | fn encode(&self, buf: &mut T) { 44 | match self { 45 | Frame::Ack(f) => f.encode(buf), 46 | Frame::ApplicationClose(f) => { 47 | buf.put_u8(0x03); 48 | f.encode(buf) 49 | } 50 | Frame::ConnectionClose(f) => { 51 | buf.put_u8(0x02); 52 | f.encode(buf) 53 | } 54 | Frame::Padding(f) => f.encode(buf), 55 | Frame::PathChallenge(f) => { 56 | buf.put_u8(0x0e); 57 | f.encode(buf) 58 | } 59 | Frame::PathResponse(f) => { 60 | buf.put_u8(0x0f); 61 | f.encode(buf) 62 | } 63 | Frame::Ping => buf.put_u8(0x07), 64 | Frame::Stream(f) => f.encode(buf), 65 | Frame::StreamIdBlocked(f) => { 66 | buf.put_u8(0x0a); 67 | f.encode(buf) 68 | } 69 | Frame::Crypto(f) => { 70 | buf.put_u8(CRYPTO_FRAME_ID); 71 | f.encode(buf) 72 | } 73 | } 74 | } 75 | 76 | fn decode(buf: &mut T) -> QuicResult { 77 | Ok(match buf.bytes()[0] { 78 | v if v >= 0x10 && v < 0x18 79 | => Frame::Stream(StreamFrame::decode(buf)?), 80 | 0x02 => Frame::ConnectionClose({ 81 | buf.get_u8(); 82 | CloseFrame::decode(buf)? 83 | }), 84 | 0x03 => Frame::ApplicationClose({ 85 | buf.get_u8(); 86 | CloseFrame::decode(buf)? 87 | }), 88 | 0x07 => { 89 | buf.get_u8(); 90 | Frame::Ping 91 | } 92 | 0x0a => Frame::StreamIdBlocked({ 93 | buf.get_u8(); 94 | StreamIdBlockedFrame::decode(buf)? 95 | }), 96 | CRYPTO_FRAME_ID => Frame::Crypto({ 97 | buf.get_u8(); 98 | CryptoFrame::decode(buf)? 99 | }), 100 | 0x0d => Frame::Ack(AckFrame::decode(buf)?), 101 | 0x0e => Frame::PathChallenge({ 102 | buf.get_u8(); 103 | PathFrame::decode(buf)? 104 | }), 105 | 0x0f => Frame::PathResponse({ 106 | buf.get_u8(); 107 | PathFrame::decode(buf)? 108 | }), 109 | 0 => Frame::Padding(PaddingFrame::decode(buf)?), 110 | v => { 111 | return Err(QuicError::DecodeError(format!( 112 | "unimplemented decoding for frame type {}", 113 | v 114 | ))) 115 | } 116 | }) 117 | } 118 | } 119 | 120 | #[derive(Debug, PartialEq)] 121 | pub struct StreamFrame { 122 | pub id: u64, 123 | pub fin: bool, 124 | pub offset: u64, 125 | pub len: Option, 126 | pub data: Vec, 127 | } 128 | 129 | impl BufLen for StreamFrame { 130 | fn buf_len(&self) -> usize { 131 | 1 + VarLen(self.id).buf_len() + if self.offset > 0 { 132 | VarLen(self.offset).buf_len() 133 | } else { 134 | 0 135 | } + self.len.map(VarLen).buf_len() + self.data.len() 136 | } 137 | } 138 | 139 | impl Codec for StreamFrame { 140 | fn encode(&self, buf: &mut T) { 141 | let has_offset = if self.offset > 0 { 0x04 } else { 0 }; 142 | let has_len = if self.len.is_some() { 0x02 } else { 0 }; 143 | let is_fin = if self.fin { 0x01 } else { 0 }; 144 | buf.put_u8(0x10 | has_offset | has_len | is_fin); 145 | VarLen(self.id).encode(buf); 146 | if self.offset > 0 { 147 | VarLen(self.offset).encode(buf); 148 | } 149 | if let Some(len) = self.len { 150 | VarLen(len).encode(buf); 151 | } 152 | buf.put_slice(&self.data); 153 | } 154 | 155 | fn decode(buf: &mut T) -> QuicResult { 156 | let first = buf.get_u8(); 157 | let id = VarLen::decode(buf)?.0; 158 | let offset = if first & 0x04 > 0 { 159 | VarLen::decode(buf)?.0 160 | } else { 161 | 0 162 | }; 163 | 164 | let rem = buf.remaining() as u64; 165 | let (len, consume) = match first & 0x02 { 166 | 0 => (None, rem), 167 | _ => { 168 | let len = VarLen::decode(buf)?.0; 169 | if len > rem { 170 | return Err( 171 | QuicError::DecodeError("length too great".to_string()) 172 | ); 173 | } 174 | (Some(len), len) 175 | } 176 | }; 177 | 178 | let mut data = vec![0u8; consume as usize]; 179 | buf.copy_to_slice(&mut data); 180 | 181 | Ok(StreamFrame { 182 | id, 183 | fin: first & 0x01 > 0, 184 | offset, 185 | len, 186 | data, 187 | }) 188 | } 189 | } 190 | 191 | #[derive(Debug, PartialEq)] 192 | pub struct CryptoFrame { 193 | pub offset : u64, 194 | pub length : u64, 195 | pub payload : Vec, 196 | } 197 | 198 | impl BufLen for CryptoFrame { 199 | fn buf_len(&self) -> usize { 200 | 1 + 201 | VarLen(self.offset).buf_len() + 202 | VarLen(self.length).buf_len() + 203 | self.payload.len() 204 | } 205 | } 206 | 207 | impl Codec for CryptoFrame { 208 | /* Flags: 209 | * has_offset : The offset should always be zero, hence can be omitted entirely 210 | */ 211 | fn encode(&self, buf: &mut T) { 212 | buf.put_u8(CRYPTO_FRAME_ID); 213 | VarLen(self.offset).encode(buf); 214 | VarLen(self.length).encode(buf); 215 | buf.put_slice(&self.payload); 216 | } 217 | 218 | fn decode(buf: &mut T) -> QuicResult { 219 | if buf.get_u8() != CRYPTO_FRAME_ID { 220 | return Err(QuicError::DecodeError("invalid frame id".to_string())); 221 | } 222 | 223 | let offset = VarLen::decode(buf)?.0; 224 | let length = VarLen::decode(buf)?.0; 225 | 226 | if length > buf.remaining() as u64 { 227 | return Err(QuicError::DecodeError("length is too great".to_string())); 228 | } 229 | 230 | // copy payload into frame 231 | 232 | let mut payload = vec![0u8; length as usize]; 233 | buf.copy_to_slice(&mut payload); 234 | Ok(CryptoFrame {offset, length, payload}) 235 | } 236 | } 237 | 238 | #[derive(Debug, PartialEq)] 239 | pub struct AckFrame { 240 | pub largest: u32, 241 | pub ack_delay: u64, 242 | pub blocks: Vec, 243 | } 244 | 245 | impl BufLen for AckFrame { 246 | fn buf_len(&self) -> usize { 247 | 1 + VarLen(u64::from(self.largest)).buf_len() + VarLen(self.ack_delay).buf_len() 248 | + VarLen((self.blocks.len() - 1) as u64).buf_len() 249 | + self.blocks 250 | .iter() 251 | .map(|v| VarLen(v.value()).buf_len()) 252 | .sum::() 253 | } 254 | } 255 | 256 | impl Codec for AckFrame { 257 | fn encode(&self, buf: &mut T) { 258 | buf.put_u8(0x0d); 259 | VarLen(u64::from(self.largest)).encode(buf); 260 | VarLen(self.ack_delay).encode(buf); 261 | VarLen((self.blocks.len() - 1) as u64).encode(buf); 262 | for ack in &self.blocks { 263 | VarLen(ack.value()).encode(buf); 264 | } 265 | } 266 | 267 | fn decode(buf: &mut T) -> QuicResult { 268 | let _ = buf.get_u8(); 269 | let largest = VarLen::decode(buf)?.0 as u32; 270 | let ack_delay = VarLen::decode(buf)?.0; 271 | let count = VarLen::decode(buf)?.0; 272 | debug_assert_eq!(count % 2, 0); 273 | 274 | let mut blocks = vec![]; 275 | for i in 0..count + 1 { 276 | blocks.push(if i % 2 == 0 { 277 | Ack::Ack(VarLen::decode(buf)?.0) 278 | } else { 279 | Ack::Gap(VarLen::decode(buf)?.0) 280 | }); 281 | } 282 | 283 | Ok(AckFrame { 284 | largest, 285 | ack_delay, 286 | blocks, 287 | }) 288 | } 289 | } 290 | 291 | #[derive(Debug, PartialEq)] 292 | pub enum Ack { 293 | Ack(u64), 294 | Gap(u64), 295 | } 296 | 297 | impl Ack { 298 | fn value(&self) -> u64 { 299 | match *self { 300 | Ack::Ack(v) => v, 301 | Ack::Gap(v) => v, 302 | } 303 | } 304 | } 305 | 306 | #[derive(Debug, PartialEq)] 307 | pub struct CloseFrame { 308 | pub(crate) code: u16, 309 | pub(crate) reason: String, 310 | } 311 | 312 | impl BufLen for CloseFrame { 313 | fn buf_len(&self) -> usize { 314 | 2 + VarLen(self.reason.len() as u64).buf_len() + self.reason.len() 315 | } 316 | } 317 | 318 | impl Codec for CloseFrame { 319 | fn encode(&self, buf: &mut T) { 320 | buf.put_u16_be(self.code); 321 | VarLen(self.reason.len() as u64).encode(buf); 322 | buf.put_slice(self.reason.as_bytes()); 323 | } 324 | 325 | fn decode(buf: &mut T) -> QuicResult { 326 | let code = buf.get_u16_be(); 327 | let len = VarLen::decode(buf)?.0 as usize; 328 | let reason = { 329 | let bytes = buf.bytes(); 330 | str::from_utf8(&bytes[..len]).unwrap() 331 | }.to_string(); 332 | buf.advance(len); 333 | Ok(CloseFrame { code, reason }) 334 | } 335 | } 336 | 337 | #[derive(Debug, PartialEq)] 338 | pub struct PathFrame(pub [u8; 8]); 339 | 340 | impl BufLen for PathFrame { 341 | fn buf_len(&self) -> usize { 342 | 8 343 | } 344 | } 345 | 346 | impl Codec for PathFrame { 347 | fn encode(&self, buf: &mut T) { 348 | buf.put_slice(&self.0); 349 | } 350 | 351 | fn decode(buf: &mut T) -> QuicResult { 352 | let mut bytes = [0; 8]; 353 | buf.copy_to_slice(&mut bytes); 354 | Ok(PathFrame(bytes)) 355 | } 356 | } 357 | 358 | #[derive(Debug, PartialEq)] 359 | pub struct StreamIdBlockedFrame(pub u64); 360 | 361 | impl BufLen for StreamIdBlockedFrame { 362 | fn buf_len(&self) -> usize { 363 | VarLen(self.0).buf_len() 364 | } 365 | } 366 | 367 | impl Codec for StreamIdBlockedFrame { 368 | fn encode(&self, buf: &mut T) { 369 | VarLen(self.0).encode(buf) 370 | } 371 | 372 | fn decode(buf: &mut T) -> QuicResult { 373 | Ok(StreamIdBlockedFrame(VarLen::decode(buf)?.0)) 374 | } 375 | } 376 | 377 | #[derive(Debug, PartialEq)] 378 | pub struct PaddingFrame(pub usize); 379 | 380 | impl BufLen for PaddingFrame { 381 | fn buf_len(&self) -> usize { 382 | self.0 383 | } 384 | } 385 | 386 | impl Codec for PaddingFrame { 387 | fn encode(&self, buf: &mut T) { 388 | let padding = vec![0; self.0]; 389 | buf.put_slice(&padding); 390 | } 391 | 392 | fn decode(buf: &mut T) -> QuicResult { 393 | let size = buf.bytes().iter().take_while(|b| **b == 0).count(); 394 | buf.advance(size); 395 | Ok(PaddingFrame(size)) 396 | } 397 | } 398 | 399 | #[cfg(test)] 400 | mod tests { 401 | use bytes::Buf; 402 | use codec::{BufLen, Codec}; 403 | use std::io::Cursor; 404 | 405 | #[test] 406 | fn test_padding_roundtrip() { 407 | let bytes = b"\x00\x00\x00\x00\x01"; 408 | let frame = { 409 | let mut read = Cursor::new(&bytes); 410 | let frame = super::Frame::decode(&mut read).unwrap(); 411 | assert_eq!(read.bytes(), b"\x01"); 412 | frame 413 | }; 414 | assert_eq!(frame, super::Frame::Padding(super::PaddingFrame(4))); 415 | 416 | let mut buf = vec![0u8; 16]; 417 | frame.encode(&mut buf); 418 | assert_eq!(&bytes[..4], &buf[..4]); 419 | } 420 | 421 | #[test] 422 | fn test_ack_roundtrip() { 423 | let obj = super::Frame::Ack(super::AckFrame { 424 | largest: 485971334, 425 | ack_delay: 0, 426 | blocks: vec![super::Ack::Ack(0)], 427 | }); 428 | let bytes = b"\x0d\x9c\xf7\x55\x86\x00\x00\x00"; 429 | assert_eq!(obj.buf_len(), bytes.len()); 430 | 431 | let mut buf = Vec::with_capacity(64); 432 | obj.encode(&mut buf); 433 | assert_eq!(&buf, bytes); 434 | 435 | let mut read = Cursor::new(bytes); 436 | let decoded = super::Frame::decode(&mut read).unwrap(); 437 | assert_eq!(decoded, obj); 438 | } 439 | 440 | #[test] 441 | fn test_crypto_round_trip() { 442 | let payload = b"\x0d\x9c\xf7\x55\x86\x00\x00\x00"; 443 | let obj = super::Frame::Crypto(super::CryptoFrame { 444 | len : payload.len() as u16, 445 | payload : payload.to_vec(), 446 | }); 447 | let bytes = b"\x0b\x00\x08\x0d\x9c\xf7\x55\x86\x00\x00\x00"; 448 | assert_eq!(obj.buf_len(), bytes.len()); 449 | 450 | let mut buf = Vec::with_capacity(64); 451 | obj.encode(&mut buf); 452 | println!("{:?}", buf); 453 | assert_eq!(buf.len(), obj.buf_len()); 454 | 455 | 456 | let mut read = Cursor::new(bytes); 457 | let decoded = super::Frame::decode(&mut read).unwrap(); 458 | assert_eq!(decoded, obj); 459 | } 460 | } 461 | -------------------------------------------------------------------------------- /src/handshake.rs: -------------------------------------------------------------------------------- 1 | use crypto::Secret; 2 | use parameters::{ClientTransportParameters, ServerTransportParameters, TransportParameters}; 3 | use types::Side; 4 | use super::{QuicError, QuicResult}; 5 | use codec::Codec; 6 | use std::str; 7 | use std::io::Cursor; 8 | 9 | use super::QUIC_VERSION; 10 | 11 | use hex; 12 | 13 | use ring::aead::AES_256_GCM; 14 | use ring::digest::SHA256; 15 | 16 | use snow; 17 | use snow::NoiseBuilder; 18 | use snow::params::NoiseParams; 19 | 20 | lazy_static! { 21 | static ref PARAMS: NoiseParams = "Noise_IK_25519_AESGCM_SHA256".parse().unwrap(); 22 | } 23 | 24 | const STATIC_DUMMY_SECRET : [u8; 32] = [ 25 | 0xe0, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 26 | 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 27 | 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 28 | 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 29 | ]; 30 | 31 | pub struct ClientSession { 32 | static_key : [u8; 32], // client secret 33 | remote_key : [u8; 32], // server public 34 | session : Option, // noise snow session 35 | params_remote : Option, // authenticated remote transport parameters 36 | params_local : ClientTransportParameters, // transport parameters 37 | } 38 | 39 | pub struct ServerSession { 40 | static_key : [u8; 32], // server secret 41 | session : Option, // noise snow session 42 | params_remote : Option, // authenticated remote transport parameters 43 | params_local : ServerTransportParameters, // transport parameters 44 | auth_check : fn([u8; 32]) -> bool // application specific auth. check 45 | } 46 | 47 | pub trait Session { 48 | fn process_handshake_message(&mut self, &[u8]) -> QuicResult; 49 | fn set_prologue(&mut self, prologue : &[u8]) -> QuicResult<()>; 50 | fn get_transport_parameters(&self) -> Option; 51 | } 52 | 53 | fn no_auth(pk : [u8; 32]) -> bool { 54 | println!("debug : client identity : {}", hex::encode(&pk)); 55 | true 56 | } 57 | 58 | pub fn client_session( 59 | remote_key : [u8; 32], 60 | static_key : Option<[u8; 32]>, 61 | params : ClientTransportParameters, 62 | ) -> ClientSession { 63 | ClientSession { 64 | static_key: static_key.unwrap_or(STATIC_DUMMY_SECRET), 65 | params_remote: None, 66 | params_local: params, 67 | remote_key, 68 | session: None 69 | } 70 | } 71 | 72 | pub fn server_session( 73 | static_key : [u8; 32], 74 | params : ServerTransportParameters, 75 | ) -> ServerSession { 76 | ServerSession { 77 | static_key: static_key, 78 | params_remote: None, 79 | params_local: params, 80 | session: None, 81 | auth_check: no_auth, 82 | } 83 | } 84 | 85 | impl Session for ClientSession { 86 | fn set_prologue(&mut self, _prologue : &[u8]) -> QuicResult<()> { 87 | Err(QuicError::General("setting prologue on client".to_owned())) 88 | } 89 | 90 | fn get_transport_parameters(&self) -> Option { 91 | match &self.params_remote { 92 | Some(p) => Some(p.parameters.clone()), 93 | None => None, 94 | } 95 | } 96 | 97 | fn process_handshake_message(&mut self, msg: &[u8]) -> QuicResult { 98 | let session = self.session.as_mut().unwrap(); 99 | let mut payload = vec![0u8; 65535]; 100 | match session.read_message(msg, &mut payload) { 101 | Ok(n) => { 102 | // parse server transport parameters 103 | 104 | self.params_remote = Some({ 105 | let mut read = Cursor::new(&payload[..n]); 106 | ServerTransportParameters::decode(&mut read)? 107 | }); 108 | 109 | assert!(session.is_initiator()); 110 | assert!(session.is_handshake_finished()); 111 | 112 | // export key material 113 | 114 | let (k1, k2) = session.export().unwrap(); 115 | let secret = Secret::For1Rtt(&AES_256_GCM, &SHA256, k1.to_vec(), k2.to_vec()); 116 | 117 | println!("debug : params_remote = {:?}", &self.params_remote); 118 | println!("debug : exporting key material from Noise:"); 119 | println!("debug : i->r : {}", hex::encode(k1)); 120 | println!("debug : i<-r : {}", hex::encode(k2)); 121 | 122 | Ok((None, Some(secret))) 123 | }, 124 | Err(_) => Err(QuicError::General("failed to decrypt noise".to_owned())) 125 | } 126 | } 127 | } 128 | 129 | impl ClientSession { 130 | pub fn create_handshake_request(&mut self, prologue : &[u8]) -> QuicResult> { 131 | 132 | // sanity check 133 | 134 | if let Some(_) = self.session { 135 | panic!("Multiple calls to create_handshake_request"); 136 | } 137 | 138 | // build Noise session 139 | 140 | self.session = Some({ 141 | let builder = NoiseBuilder::new(PARAMS.clone()); 142 | builder 143 | .prologue(prologue) 144 | .local_private_key(&self.static_key) 145 | .remote_public_key(&self.remote_key) 146 | .build_initiator().unwrap() 147 | }); 148 | 149 | // serialize parameters 150 | 151 | let session = self.session.as_mut().unwrap(); 152 | let mut payload = Vec::new(); 153 | self.params_local.encode(&mut payload); 154 | 155 | let mut msg = vec![0u8; 65535]; 156 | let len = session.write_message(&payload, &mut msg).unwrap(); 157 | 158 | Ok(msg[..len].to_owned()) 159 | } 160 | } 161 | 162 | impl Session for ServerSession { 163 | fn set_prologue(&mut self, prologue : &[u8]) -> QuicResult<()> { 164 | match self.session { 165 | Some(_) => 166 | Err(QuicError::General("setting prologue after processing handshake request".to_owned())), 167 | None => { 168 | self.session = Some({ 169 | let builder = NoiseBuilder::new(PARAMS.clone()); 170 | builder 171 | .local_private_key(&self.static_key) 172 | .prologue(prologue) 173 | .build_responder().unwrap() 174 | }); 175 | Ok(()) 176 | } 177 | } 178 | } 179 | 180 | fn get_transport_parameters(&self) -> Option { 181 | match &self.params_remote { 182 | Some(p) => Some(p.parameters.clone()), 183 | None => None, 184 | } 185 | } 186 | 187 | fn process_handshake_message(&mut self, msg: &[u8]) -> QuicResult { 188 | 189 | println!("debug : process handshake message"); 190 | 191 | let session = self.session.as_mut().unwrap(); 192 | let mut payload = vec![0u8; 65535]; 193 | match session.read_message(msg, &mut payload) { 194 | Ok(n) => { 195 | 196 | // parse client transport parameters 197 | 198 | let parameters = { 199 | let mut read = Cursor::new(&payload[..n]); 200 | ClientTransportParameters::decode(&mut read)? 201 | }; 202 | self.params_remote = Some(parameters.clone()); 203 | println!("debug : client parameters {:?}", ¶meters); 204 | 205 | // validate initial_version (this is the only supported version) 206 | 207 | if parameters.initial_version != QUIC_VERSION { 208 | return Err( 209 | QuicError::General("failed to decrypt noise".to_owned()) 210 | ); 211 | }; 212 | 213 | // validate client identity 214 | 215 | let auth_ok = match session.get_remote_static() { 216 | None => false, 217 | Some(key) => { 218 | let mut pk = [0u8; 32]; 219 | pk[..].clone_from_slice(key); 220 | (self.auth_check)(pk) 221 | } 222 | }; 223 | 224 | if !auth_ok { 225 | return Err( 226 | QuicError::General("client idenity rejected".to_owned()) 227 | ); 228 | } 229 | 230 | // create handshake response 231 | 232 | let resp = { 233 | let mut payload = Vec::new(); 234 | let mut msg = vec![0u8; 65535]; 235 | self.params_local.encode(&mut payload); 236 | let len = session.write_message(&payload, &mut msg).unwrap(); 237 | assert!(session.is_handshake_finished()); 238 | msg[..len].to_owned() 239 | }; 240 | 241 | // export transport keys 242 | 243 | println!("debug : exporting key material from Noise:"); 244 | 245 | assert!(!session.is_initiator()); 246 | assert!(session.is_handshake_finished()); 247 | 248 | let (k1, k2) = session.export().unwrap(); 249 | let secret = Secret::For1Rtt( 250 | &AES_256_GCM, 251 | &SHA256, 252 | k1.to_vec(), 253 | k2.to_vec() 254 | ); 255 | 256 | println!("debug : i->r : {}", hex::encode(k1)); 257 | println!("debug : i<-r : {}", hex::encode(k2)); 258 | 259 | Ok((Some(resp), Some(secret))) 260 | }, 261 | Err(_) => Err(QuicError::General("failed to decrypt noise".to_owned())) 262 | } 263 | } 264 | } 265 | 266 | pub trait QuicSide { 267 | fn side(&self) -> Side; 268 | } 269 | 270 | impl QuicSide for ClientSession { 271 | fn side(&self) -> Side { 272 | Side::Client 273 | } 274 | } 275 | 276 | impl QuicSide for ServerSession { 277 | fn side(&self) -> Side { 278 | Side::Server 279 | } 280 | } 281 | 282 | type HandshakeResult = (Option>, Option); 283 | 284 | fn to_vec(val: &T) -> Vec { 285 | let mut bytes = Vec::new(); 286 | val.encode(&mut bytes); 287 | bytes 288 | } 289 | 290 | const ALPN_PROTOCOL: &str = "hq-11"; 291 | -------------------------------------------------------------------------------- /src/http/client.rs: -------------------------------------------------------------------------------- 1 | use futures::future::Future; 2 | 3 | use streams::Streams; 4 | use QuicError; 5 | 6 | pub fn start(streams: Streams) -> impl Future { 7 | println!("REQUEST STREAM 2"); 8 | streams.request_stream(2) 9 | } 10 | -------------------------------------------------------------------------------- /src/http/frame.rs: -------------------------------------------------------------------------------- 1 | use bytes::{Buf, BufMut}; 2 | 3 | use codec::{BufLen, Codec, VarLen}; 4 | use {QuicError, QuicResult}; 5 | 6 | // On the wire: 7 | // len: VarLen 8 | // ptype: u8 9 | // flags: u8 10 | // payload: [u8] 11 | #[derive(Debug, PartialEq)] 12 | enum HttpFrame { 13 | Settings(SettingsFrame), 14 | } 15 | 16 | impl Codec for HttpFrame { 17 | fn encode(&self, buf: &mut T) { 18 | match self { 19 | HttpFrame::Settings(f) => { 20 | f.len().encode(buf); 21 | buf.put_u8(0x4); 22 | f.encode(buf); 23 | } 24 | } 25 | } 26 | 27 | fn decode(buf: &mut T) -> QuicResult { 28 | let len = VarLen::decode(buf)?.0 as usize; 29 | match buf.get_u8() { 30 | 0x4 => Ok(HttpFrame::Settings(SettingsFrame::decode( 31 | &mut buf.take(1 + len), 32 | )?)), 33 | v => Err(QuicError::DecodeError(format!( 34 | "unsupported HTTP frame type {}", 35 | v 36 | ))), 37 | } 38 | } 39 | } 40 | 41 | #[derive(Debug, PartialEq)] 42 | struct SettingsFrame(Settings); 43 | 44 | impl Codec for SettingsFrame { 45 | fn encode(&self, buf: &mut T) { 46 | buf.put_u8(0); 47 | buf.put_u16_be(0x1); 48 | let encoded = VarLen(u64::from(self.0.header_table_size)); 49 | let encoded_len = encoded.buf_len(); 50 | debug_assert!(encoded_len < 64); 51 | VarLen(encoded_len as u64).encode(buf); 52 | encoded.encode(buf); 53 | 54 | buf.put_u16_be(0x6); 55 | let encoded = VarLen(u64::from(self.0.max_header_list_size)); 56 | let encoded_len = encoded.buf_len(); 57 | debug_assert!(encoded_len < 64); 58 | VarLen(encoded_len as u64).encode(buf); 59 | encoded.encode(buf); 60 | } 61 | 62 | fn decode(buf: &mut T) -> QuicResult { 63 | if buf.get_u8() != 0 { 64 | return Err(QuicError::DecodeError("unsupported flags".into())); 65 | } 66 | let mut settings = Settings::default(); 67 | while buf.has_remaining() { 68 | let tag = buf.get_u16_be(); 69 | if tag != 0x1 && tag != 0x6 { 70 | return Err(QuicError::DecodeError("unsupported tag".into())); 71 | } 72 | VarLen::decode(buf)?; 73 | let val = VarLen::decode(buf)?; 74 | if tag == 0x1 { 75 | settings.header_table_size = val.0 as u32; 76 | } else if tag == 0x6 { 77 | settings.max_header_list_size = val.0 as u32; 78 | } 79 | } 80 | Ok(SettingsFrame(settings)) 81 | } 82 | } 83 | 84 | impl FrameHeader for SettingsFrame { 85 | fn len(&self) -> VarLen { 86 | VarLen( 87 | (6 + VarLen(u64::from(self.0.header_table_size)).buf_len() 88 | + VarLen(u64::from(self.0.max_header_list_size)).buf_len()) as u64, 89 | ) 90 | } 91 | fn flags(&self) -> u8 { 92 | 0 93 | } 94 | fn ftype(&self) -> u8 { 95 | 0x4 96 | } 97 | } 98 | 99 | impl BufLen for T 100 | where 101 | T: FrameHeader, 102 | { 103 | fn buf_len(&self) -> usize { 104 | let len = self.len(); 105 | 2 + VarLen(len.0).buf_len() + (len.0 as usize) 106 | } 107 | } 108 | 109 | pub trait FrameHeader { 110 | fn len(&self) -> VarLen; 111 | fn flags(&self) -> u8; 112 | fn ftype(&self) -> u8; 113 | fn encode_header(&self, buf: &mut T) { 114 | self.len().encode(buf); 115 | buf.put_u8(self.ftype()); 116 | buf.put_u8(self.flags()); 117 | } 118 | } 119 | 120 | #[derive(Debug, PartialEq)] 121 | pub struct Settings { 122 | header_table_size: u32, 123 | max_header_list_size: u32, 124 | } 125 | 126 | impl Default for Settings { 127 | fn default() -> Settings { 128 | Settings { 129 | header_table_size: 65536, 130 | max_header_list_size: 65536, 131 | } 132 | } 133 | } 134 | 135 | #[cfg(test)] 136 | mod tests { 137 | use codec::Codec; 138 | use std::io::Cursor; 139 | 140 | #[test] 141 | fn test_settings_frame() { 142 | let settings = super::Settings { 143 | header_table_size: 131072, 144 | max_header_list_size: 65536, 145 | }; 146 | 147 | let frame = super::HttpFrame::Settings(super::SettingsFrame(settings)); 148 | let mut buf = Vec::new(); 149 | frame.encode(&mut buf); 150 | assert_eq!( 151 | &buf, 152 | &[14, 4, 0, 0, 1, 4, 128, 2, 0, 0, 0, 6, 4, 128, 1, 0, 0] 153 | ); 154 | 155 | let mut read = Cursor::new(&buf); 156 | let decoded = super::HttpFrame::decode(&mut read).unwrap(); 157 | assert_eq!(decoded, frame); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/http/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod client; 2 | mod frame; 3 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate bytes; 2 | extern crate failure; 3 | #[macro_use] 4 | extern crate failure_derive; 5 | #[macro_use] 6 | extern crate futures; 7 | #[macro_use] 8 | extern crate log; 9 | #[macro_use] 10 | extern crate lazy_static; 11 | extern crate hex; 12 | extern crate rand; 13 | extern crate ring; 14 | extern crate snow; 15 | extern crate rustls; 16 | extern crate tokio; 17 | extern crate tokio_core; 18 | extern crate webpki; 19 | extern crate webpki_roots; 20 | 21 | pub use client::Client; 22 | pub use server::Server; 23 | 24 | mod client; 25 | mod codec; 26 | mod conn_state; 27 | mod crypto; 28 | mod frame; 29 | mod nquic; 30 | pub mod http; 31 | mod packet; 32 | mod parameters; 33 | mod server; 34 | pub mod streams; 35 | pub mod handshake; 36 | mod types; 37 | 38 | #[derive(Debug, Fail)] 39 | pub enum QuicError { 40 | #[fail(display = "{}", _0)] 41 | AddrParse(#[cause] std::net::AddrParseError), 42 | #[fail(display = "needed slice of size {}, found {}", _0, _1)] 43 | AllocationError(usize, usize), 44 | #[fail(display = "application close ({}): '{}'", _0, _1)] 45 | ApplicationClose(u16, String), 46 | #[fail(display = "connection close ({}): '{}'", _0, _1)] 47 | ConnectionClose(u16, String), 48 | #[fail(display = "")] 49 | DecryptError, 50 | #[fail(display = "")] 51 | EncryptError, 52 | #[fail(display = "{}", _0)] 53 | General(String), 54 | #[fail(display = "{}", _0)] 55 | InvalidDnsName(String), 56 | #[fail(display = "{}", _0)] 57 | Io(#[cause] std::io::Error), 58 | #[fail(display = "{}", _0)] 59 | Tls(#[cause] rustls::TLSError), 60 | #[fail(display = "{}", _0)] 61 | DecodeError(String), 62 | #[fail(display = "")] 63 | Timeout, 64 | } 65 | 66 | impl From for QuicError { 67 | fn from(e: std::io::Error) -> QuicError { 68 | QuicError::Io(e) 69 | } 70 | } 71 | 72 | impl From for QuicError { 73 | fn from(e: std::net::AddrParseError) -> QuicError { 74 | QuicError::AddrParse(e) 75 | } 76 | } 77 | 78 | impl From for QuicError { 79 | fn from(e: rustls::TLSError) -> QuicError { 80 | QuicError::Tls(e) 81 | } 82 | } 83 | 84 | pub type QuicResult = std::result::Result; 85 | 86 | pub const QUIC_VERSION: u32 = 0xff00_000b; 87 | -------------------------------------------------------------------------------- /src/nquic.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rot256/ninn/d00d0059959e285675828f0aad2e006e99cf5abb/src/nquic.rs -------------------------------------------------------------------------------- /src/packet.rs: -------------------------------------------------------------------------------- 1 | use bytes::{Buf, BufMut}; 2 | 3 | use super::QuicResult; 4 | use codec::{BufLen, Codec, VarLen}; 5 | use types::{ConnectionId, GENERATED_CID_LENGTH}; 6 | 7 | use rand::{thread_rng, Rng}; 8 | 9 | use std::io::Cursor; 10 | 11 | pub struct PartialDecode<'a> { 12 | pub header: Header, 13 | pub header_len: usize, 14 | pub buf: &'a mut [u8], 15 | } 16 | 17 | impl<'a> PartialDecode<'a> { 18 | pub fn new(buf: &'a mut [u8]) -> QuicResult { 19 | let (header, header_len) = { 20 | let mut read = Cursor::new(&buf); 21 | let header = Header::decode(&mut read)?; 22 | (header, read.position() as usize) 23 | }; 24 | Ok(Self { 25 | header, 26 | header_len, 27 | buf, 28 | }) 29 | } 30 | 31 | pub fn dst_cid(&self) -> ConnectionId { 32 | self.header.dst_cid() 33 | } 34 | } 35 | 36 | #[derive(Debug, PartialEq)] 37 | pub enum Header { 38 | Long { 39 | ptype: LongType, 40 | version: u32, 41 | dst_cid: ConnectionId, 42 | src_cid: ConnectionId, 43 | len: u64, 44 | number: u32, 45 | }, 46 | Short { 47 | key_phase: bool, 48 | ptype: ShortType, 49 | dst_cid: ConnectionId, 50 | number: u32, 51 | }, 52 | Negotiation { 53 | dst_cid: ConnectionId, 54 | src_cid: ConnectionId, 55 | supported_versions: Vec, 56 | }, 57 | } 58 | 59 | impl Header { 60 | pub fn ptype(&self) -> Option { 61 | match *self { 62 | Header::Long { ptype, .. } => Some(ptype), 63 | Header::Short { .. } => None, 64 | Header::Negotiation { .. } => None, 65 | } 66 | } 67 | 68 | fn dst_cid(&self) -> ConnectionId { 69 | match *self { 70 | Header::Long { dst_cid, .. } => dst_cid, 71 | Header::Short { dst_cid, .. } => dst_cid, 72 | Header::Negotiation { dst_cid, .. } => dst_cid, 73 | } 74 | } 75 | } 76 | 77 | impl BufLen for Header { 78 | fn buf_len(&self) -> usize { 79 | match self { 80 | Header::Long { 81 | dst_cid, src_cid, .. 82 | } => 12 + (dst_cid.len as usize + src_cid.len as usize), 83 | Header::Short { ptype, dst_cid, .. } => 1 + (dst_cid.len as usize) + ptype.buf_len(), 84 | Header::Negotiation { 85 | dst_cid, 86 | src_cid, 87 | supported_versions, 88 | } => 6 + (dst_cid.len as usize + src_cid.len as usize) + 4 * supported_versions.len(), 89 | } 90 | } 91 | } 92 | 93 | impl Codec for Header { 94 | fn encode(&self, buf: &mut T) { 95 | match *self { 96 | Header::Long { 97 | ptype, 98 | version, 99 | dst_cid, 100 | src_cid, 101 | len, 102 | number, 103 | } => { 104 | buf.put_u8(128 | ptype.to_byte()); 105 | buf.put_u32_be(version); 106 | buf.put_u8((dst_cid.cil() << 4) | src_cid.cil()); 107 | buf.put_slice(&dst_cid); 108 | buf.put_slice(&src_cid); 109 | debug_assert!(len < 16383); 110 | buf.put_u16_be((len | 16384) as u16); 111 | buf.put_u32_be(number); 112 | } 113 | Header::Short { 114 | key_phase, 115 | ptype, 116 | dst_cid, 117 | number, 118 | } => { 119 | let key_phase_bit = if key_phase { 0x40 } else { 0 }; 120 | buf.put_u8(key_phase_bit | 0x20 | 0x10 | ptype.to_byte()); 121 | buf.put_slice(&dst_cid); 122 | match ptype { 123 | ShortType::One => buf.put_u8(number as u8), 124 | ShortType::Two => buf.put_u16_be(number as u16), 125 | ShortType::Four => buf.put_u32_be(number as u32), 126 | }; 127 | } 128 | Header::Negotiation { 129 | dst_cid, 130 | src_cid, 131 | ref supported_versions, 132 | } => { 133 | buf.put_u8(thread_rng().gen::() | 128); 134 | buf.put_u32_be(0); 135 | buf.put_u8((dst_cid.cil() << 4) | src_cid.cil()); 136 | buf.put_slice(&dst_cid); 137 | buf.put_slice(&src_cid); 138 | for v in supported_versions { 139 | buf.put_u32_be(*v); 140 | } 141 | } 142 | } 143 | } 144 | 145 | fn decode(buf: &mut T) -> QuicResult { 146 | let first = buf.get_u8(); 147 | if first & 128 == 128 { 148 | let version = buf.get_u32_be(); 149 | let cils = buf.get_u8(); 150 | 151 | let (dst_cid, src_cid, used) = { 152 | let (mut dcil, mut scil) = ((cils >> 4) as usize, (cils & 15) as usize); 153 | if dcil > 0 { 154 | dcil += 3; 155 | } 156 | if scil > 0 { 157 | scil += 3; 158 | } 159 | 160 | let bytes = buf.bytes(); 161 | let dst_cid = ConnectionId::new(&bytes[..dcil]); 162 | let src_cid = ConnectionId::new(&bytes[dcil..dcil + scil]); 163 | (dst_cid, src_cid, dcil + scil) 164 | }; 165 | 166 | buf.advance(used); 167 | if version == 0 { 168 | let mut supported_versions = vec![]; 169 | while buf.has_remaining() { 170 | supported_versions.push(buf.get_u32_be()); 171 | } 172 | Ok(Header::Negotiation { 173 | dst_cid, 174 | src_cid, 175 | supported_versions, 176 | }) 177 | } else { 178 | Ok(Header::Long { 179 | ptype: LongType::from_byte(first ^ 128), 180 | version, 181 | dst_cid, 182 | src_cid, 183 | len: VarLen::decode(buf)?.0, 184 | number: buf.get_u32_be(), 185 | }) 186 | } 187 | } else { 188 | let key_phase = first & 0x40 == 0x40; 189 | let dst_cid = { 190 | let bytes = buf.bytes(); 191 | ConnectionId::new(&bytes[..GENERATED_CID_LENGTH as usize]) 192 | }; 193 | buf.advance(GENERATED_CID_LENGTH as usize); 194 | 195 | let ptype = ShortType::from_byte(first & 3); 196 | let number = match ptype { 197 | ShortType::One => u32::from(buf.get_u8()), 198 | ShortType::Two => u32::from(buf.get_u16_be()), 199 | ShortType::Four => buf.get_u32_be(), 200 | }; 201 | 202 | Ok(Header::Short { 203 | key_phase, 204 | ptype, 205 | dst_cid, 206 | number, 207 | }) 208 | } 209 | } 210 | } 211 | 212 | #[derive(Clone, Debug, PartialEq)] 213 | pub enum LongType { 214 | Initial = 0x7f, 215 | Retry = 0x7e, 216 | Handshake = 0x7d, 217 | Protected = 0x7c, 218 | } 219 | 220 | impl Copy for LongType {} 221 | 222 | impl LongType { 223 | pub fn to_byte(&self) -> u8 { 224 | use self::LongType::*; 225 | match self { 226 | Initial => 0x7f, 227 | Retry => 0x7e, 228 | Handshake => 0x7d, 229 | Protected => 0x7c, 230 | } 231 | } 232 | pub fn from_byte(v: u8) -> Self { 233 | use self::LongType::*; 234 | match v { 235 | 0x7f => Initial, 236 | 0x7e => Retry, 237 | 0x7d => Handshake, 238 | 0x7c => Protected, 239 | _ => panic!("invalid long packet type {}", v), 240 | } 241 | } 242 | } 243 | 244 | #[derive(Clone, Debug, PartialEq)] 245 | pub enum ShortType { 246 | One = 0x0, 247 | Two = 0x1, 248 | Four = 0x2, 249 | } 250 | 251 | impl Copy for ShortType {} 252 | 253 | impl BufLen for ShortType { 254 | fn buf_len(&self) -> usize { 255 | use self::ShortType::*; 256 | match self { 257 | One => 1, 258 | Two => 2, 259 | Four => 4, 260 | } 261 | } 262 | } 263 | 264 | impl ShortType { 265 | pub fn to_byte(&self) -> u8 { 266 | use self::ShortType::*; 267 | match self { 268 | One => 0, 269 | Two => 1, 270 | Four => 2, 271 | } 272 | } 273 | pub fn from_byte(v: u8) -> Self { 274 | use self::ShortType::*; 275 | match v { 276 | 0 => One, 277 | 1 => Two, 278 | 2 => Four, 279 | _ => panic!("invalid short packet type {}", v), 280 | } 281 | } 282 | } 283 | 284 | 285 | #[cfg(test)] 286 | mod tests { 287 | use hex; 288 | use codec::Codec; 289 | use types::ConnectionId; 290 | use std::io::Cursor; 291 | 292 | #[test] 293 | fn test_short_roundtrip() { 294 | let con : [u8; 8] = [ 295 | 0x38, 0xa7, 0xe6, 0x55, 296 | 0xbf, 0x62, 0xf5, 0xf7 297 | ]; 298 | let header = super::Header::Short { 299 | key_phase: false, 300 | ptype: super::ShortType::Two, 301 | dst_cid: ConnectionId::new(&con), 302 | number: 3152957029, 303 | }; 304 | 305 | let mut bytes = Vec::with_capacity(64); 306 | header.encode(&mut bytes); 307 | 308 | println!("encoded : {}", hex::encode(&bytes)); 309 | 310 | let mut read = Cursor::new(bytes); 311 | let decoded = super::Header::decode(&mut read).unwrap(); 312 | 313 | assert_eq!(decoded, header); 314 | } 315 | } 316 | -------------------------------------------------------------------------------- /src/parameters.rs: -------------------------------------------------------------------------------- 1 | use bytes::{Buf, BufMut}; 2 | 3 | use super::{QuicResult, QUIC_VERSION}; 4 | use codec::Codec; 5 | 6 | #[derive(Clone, Debug, PartialEq)] 7 | pub struct ClientTransportParameters { 8 | pub initial_version: u32, 9 | pub parameters: TransportParameters, 10 | } 11 | 12 | impl Default for ClientTransportParameters { 13 | fn default() -> Self { 14 | Self { 15 | initial_version: QUIC_VERSION, 16 | parameters: TransportParameters::default(), 17 | } 18 | } 19 | } 20 | 21 | impl Codec for ClientTransportParameters { 22 | fn encode(&self, buf: &mut T) { 23 | buf.put_u32_be(self.initial_version); 24 | self.parameters.encode(buf); 25 | } 26 | 27 | fn decode(buf: &mut T) -> QuicResult { 28 | Ok(ClientTransportParameters { 29 | initial_version: buf.get_u32_be(), 30 | parameters: TransportParameters::decode(buf)?, 31 | }) 32 | } 33 | } 34 | 35 | #[derive(Clone, Debug, PartialEq)] 36 | pub struct ServerTransportParameters { 37 | pub negotiated_version: u32, 38 | pub supported_versions: Vec, 39 | pub parameters: TransportParameters, 40 | } 41 | 42 | impl Default for ServerTransportParameters { 43 | fn default() -> Self { 44 | Self { 45 | negotiated_version: QUIC_VERSION, 46 | supported_versions: vec![QUIC_VERSION], 47 | parameters: TransportParameters::default(), 48 | } 49 | } 50 | } 51 | 52 | impl Codec for ServerTransportParameters { 53 | fn encode(&self, buf: &mut T) { 54 | buf.put_u32_be(self.negotiated_version); 55 | buf.put_u8((4 * self.supported_versions.len()) as u8); 56 | for v in &self.supported_versions { 57 | buf.put_u32_be(*v); 58 | } 59 | self.parameters.encode(buf); 60 | } 61 | 62 | fn decode(buf: &mut T) -> QuicResult { 63 | Ok(ServerTransportParameters { 64 | negotiated_version: buf.get_u32_be(), 65 | supported_versions: { 66 | let mut supported_versions = vec![]; 67 | let supported_bytes = buf.get_u8() as usize; 68 | let mut sub = buf.take(supported_bytes); 69 | while sub.has_remaining() { 70 | supported_versions.push(sub.get_u32_be()); 71 | } 72 | supported_versions 73 | }, 74 | parameters: TransportParameters::decode(buf)?, 75 | }) 76 | } 77 | } 78 | 79 | impl Codec for TransportParameters { 80 | fn encode(&self, buf: &mut T) { 81 | let mut tmp = vec![]; 82 | let mut val = vec![]; 83 | 84 | tmp.put_u16_be(0); 85 | val.put_u32_be(self.max_stream_data); 86 | tmp.put_u16_be(val.len() as u16); 87 | tmp.append(&mut val); 88 | val.truncate(0); 89 | 90 | tmp.put_u16_be(1); 91 | val.put_u32_be(self.max_data); 92 | tmp.put_u16_be(val.len() as u16); 93 | tmp.append(&mut val); 94 | val.truncate(0); 95 | 96 | tmp.put_u16_be(3); 97 | val.put_u16_be(self.idle_timeout); 98 | tmp.put_u16_be(val.len() as u16); 99 | tmp.append(&mut val); 100 | val.truncate(0); 101 | 102 | if self.max_streams_bidi > 0 { 103 | tmp.put_u16_be(2); 104 | val.put_u16_be(self.max_streams_bidi); 105 | tmp.put_u16_be(val.len() as u16); 106 | tmp.append(&mut val); 107 | val.truncate(0); 108 | } 109 | 110 | if self.max_packet_size != 65527 { 111 | tmp.put_u16_be(5); 112 | val.put_u16_be(self.max_packet_size); 113 | tmp.put_u16_be(val.len() as u16); 114 | tmp.append(&mut val); 115 | val.truncate(0); 116 | } 117 | 118 | if self.ack_delay_exponent != 3 { 119 | tmp.put_u16_be(7); 120 | val.put_u8(self.ack_delay_exponent); 121 | tmp.put_u16_be(val.len() as u16); 122 | tmp.append(&mut val); 123 | val.truncate(0); 124 | } 125 | 126 | if self.max_stream_id_uni > 0 { 127 | tmp.put_u16_be(8); 128 | val.put_u16_be(self.max_stream_id_uni); 129 | tmp.put_u16_be(val.len() as u16); 130 | tmp.append(&mut val); 131 | val.truncate(0); 132 | } 133 | 134 | if let Some(token) = self.stateless_reset_token { 135 | tmp.put_u16_be(6); 136 | tmp.put_u16_be(16); 137 | tmp.extend_from_slice(&token); 138 | } 139 | 140 | buf.put_u16_be(tmp.len() as u16); 141 | buf.put_slice(&tmp); 142 | } 143 | 144 | fn decode(buf: &mut T) -> QuicResult { 145 | let mut params = TransportParameters::default(); 146 | let num = buf.get_u16_be(); 147 | let mut sub = buf.take(num as usize); 148 | while sub.has_remaining() { 149 | let tag = sub.get_u16_be(); 150 | let size = sub.get_u16_be(); 151 | match tag { 152 | 0 => { 153 | debug_assert_eq!(size, 4); 154 | params.max_stream_data = sub.get_u32_be(); 155 | } 156 | 1 => { 157 | debug_assert_eq!(size, 4); 158 | params.max_data = sub.get_u32_be(); 159 | } 160 | 2 => { 161 | debug_assert_eq!(size, 2); 162 | params.max_streams_bidi = sub.get_u16_be(); 163 | } 164 | 3 => { 165 | debug_assert_eq!(size, 2); 166 | params.idle_timeout = sub.get_u16_be(); 167 | } 168 | 5 => { 169 | debug_assert_eq!(size, 2); 170 | params.max_packet_size = sub.get_u16_be(); 171 | } 172 | 6 => { 173 | debug_assert_eq!(size, 16); 174 | let mut token = [0; 16]; 175 | sub.copy_to_slice(&mut token); 176 | params.stateless_reset_token = Some(token); 177 | } 178 | 7 => { 179 | debug_assert_eq!(size, 1); 180 | params.ack_delay_exponent = sub.get_u8(); 181 | } 182 | 8 => { 183 | debug_assert_eq!(size, 2); 184 | params.max_stream_id_uni = sub.get_u16_be(); 185 | } 186 | _ => { 187 | sub.advance(usize::from(size)); 188 | } 189 | } 190 | } 191 | Ok(params) 192 | } 193 | } 194 | 195 | #[derive(Clone, Debug, PartialEq)] 196 | pub struct TransportParameters { 197 | pub max_stream_data: u32, // 0x00 198 | pub max_data: u32, // 0x01 199 | pub max_streams_bidi: u16, // 0x02 200 | pub idle_timeout: u16, // 0x03 201 | pub max_packet_size: u16, // 0x05 202 | pub stateless_reset_token: Option<[u8; 16]>, // 0x06 203 | pub ack_delay_exponent: u8, // 0x07 204 | pub max_stream_id_uni: u16, // 0x08 205 | } 206 | 207 | impl Default for TransportParameters { 208 | fn default() -> Self { 209 | Self { 210 | max_stream_data: 131_072, 211 | max_data: 1_048_576, 212 | max_streams_bidi: 4, 213 | idle_timeout: 300, 214 | max_packet_size: 65_527, 215 | stateless_reset_token: None, 216 | ack_delay_exponent: 3, 217 | max_stream_id_uni: 20, 218 | } 219 | } 220 | } 221 | 222 | #[cfg(test)] 223 | mod tests { 224 | use super::TransportParameters; 225 | use super::{ClientTransportParameters, Codec, ServerTransportParameters}; 226 | use std::fmt::Debug; 227 | use std::io::Cursor; 228 | 229 | fn round_trip(t: T) { 230 | let buf = { 231 | let mut ret = Vec::new(); 232 | t.encode(&mut ret); 233 | ret 234 | }; 235 | let mut read = Cursor::new(&buf); 236 | assert_eq!(t, T::decode(&mut read).unwrap()); 237 | } 238 | 239 | #[test] 240 | fn test_client_transport_parameters() { 241 | round_trip(ClientTransportParameters { 242 | initial_version: 1, 243 | parameters: TransportParameters { 244 | max_stream_data: 0, 245 | max_data: 1234, 246 | idle_timeout: 26, 247 | ..Default::default() 248 | }, 249 | }); 250 | } 251 | 252 | #[test] 253 | fn test_server_transport_parameters() { 254 | round_trip(ServerTransportParameters { 255 | negotiated_version: 1, 256 | supported_versions: vec![1, 2, 3], 257 | parameters: TransportParameters { 258 | stateless_reset_token: Some([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]), 259 | ..Default::default() 260 | }, 261 | }); 262 | } 263 | 264 | #[test] 265 | fn test_ignores_unknown_transport_parameter_ids() { 266 | #[cfg_attr(rustfmt, rustfmt_skip)] 267 | let bytes = [0u8, 130, 268 | 0, 0, 0, 4, 0, 0, 64, 0, 269 | 0, 1, 0, 4, 0, 0, 128, 0, 270 | 0, 2, 0, 2, 0, 1, 271 | 0, 8, 0, 2, 0, 1, 272 | 0, 3, 0, 2, 0, 10, 273 | 255, 0, 0, 2, 255, 0, 274 | 255, 1, 0, 2, 255, 1, 275 | 255, 2, 0, 2, 255, 2, 276 | 255, 3, 0, 2, 255, 3, 277 | 255, 4, 0, 2, 255, 4, 278 | 255, 5, 0, 2, 255, 5, 279 | 255, 6, 0, 2, 255, 6, 280 | 255, 7, 0, 2, 255, 7, 281 | 255, 8, 0, 2, 255, 8, 282 | 255, 9, 0, 2, 255, 9, 283 | 255, 10, 0, 2, 255, 10, 284 | 255, 11, 0, 2, 255, 11, 285 | 255, 12, 0, 2, 255, 12, 286 | 255, 13, 0, 2, 255, 13, 287 | 255, 14, 0, 2, 255, 14, 288 | 255, 15, 0, 2, 255, 15]; 289 | let tp = TransportParameters::decode(&mut Cursor::new(bytes.as_ref())).unwrap(); 290 | assert_eq!( 291 | tp, 292 | TransportParameters { 293 | max_stream_data: 16384, 294 | max_data: 32768, 295 | max_streams_bidi: 1, 296 | idle_timeout: 10, 297 | max_packet_size: 65527, 298 | stateless_reset_token: None, 299 | ack_delay_exponent: 3, 300 | max_stream_id_uni: 1, 301 | } 302 | ); 303 | } 304 | } 305 | -------------------------------------------------------------------------------- /src/server.rs: -------------------------------------------------------------------------------- 1 | use futures::sync::mpsc::{self, Receiver, Sender}; 2 | use futures::{Async, AsyncSink, Future, Poll, Sink, Stream}; 3 | 4 | use super::{QuicError, QuicResult}; 5 | use conn_state::ConnectionState; 6 | use crypto::Secret; 7 | use packet::{LongType, PartialDecode}; 8 | use parameters::ServerTransportParameters; 9 | use handshake; 10 | use types::ConnectionId; 11 | 12 | use std::collections::{hash_map::Entry, HashMap}; 13 | use std::net::{SocketAddr, ToSocketAddrs}; 14 | 15 | use tokio::{self, net::UdpSocket}; 16 | 17 | pub struct Server { 18 | socket: UdpSocket, 19 | in_buf: Vec, 20 | connections: HashMap>>, 21 | send_queue: PacketChannel, 22 | key: [u8; 32], 23 | } 24 | 25 | impl Server { 26 | pub fn new(ip: &str, port: u16, key: [u8; 32]) -> QuicResult { 27 | let addr = (ip, port) 28 | .to_socket_addrs()? 29 | .next() 30 | .ok_or_else(|| QuicError::General("no address found for host".into()))?; 31 | Ok(Server { 32 | socket: UdpSocket::bind(&addr)?, 33 | in_buf: vec![0u8; 65536], 34 | connections: HashMap::new(), 35 | send_queue: mpsc::channel(5), 36 | key, 37 | }) 38 | } 39 | 40 | fn received(&mut self, addr: SocketAddr, len: usize) -> QuicResult<()> { 41 | let connections = &mut self.connections; 42 | let packet = &mut self.in_buf[..len]; 43 | 44 | let (dst_cid, ptype) = { 45 | let partial = PartialDecode::new(packet)?; 46 | println!("debug : incoming packet: {:?} {:?}", addr, partial.header); 47 | (partial.dst_cid(), partial.header.ptype()) 48 | }; 49 | 50 | let cid = if ptype == Some(LongType::Initial) { 51 | let mut state = ConnectionState::new( 52 | handshake::server_session(self.key, ServerTransportParameters::default().clone()), 53 | Some(Secret::Handshake(dst_cid)), 54 | ); 55 | 56 | let cid = state.pick_unused_cid(|cid| connections.contains_key(&cid)); 57 | let (recv_tx, recv_rx) = mpsc::channel(5); 58 | tokio::spawn( 59 | Connection::new(addr, state, self.send_queue.0.clone(), recv_rx).map_err(|e| { 60 | error!("error spawning connection: {:?}", e); 61 | }), 62 | ); 63 | connections.insert(cid, recv_tx); 64 | cid 65 | } else { 66 | dst_cid 67 | }; 68 | 69 | match connections.entry(cid) { 70 | Entry::Occupied(mut inner) => { 71 | let mut sink = inner.get_mut(); 72 | forward_packet(sink, packet.to_vec())?; 73 | } 74 | Entry::Vacant(_) => println!("debug : connection ID {:?} unknown", cid), 75 | } 76 | 77 | Ok(()) 78 | } 79 | 80 | fn poll_next(&mut self) -> Option<(SocketAddr, Vec)> { 81 | match self.send_queue.1.poll() { 82 | Ok(Async::Ready(msg)) => msg, 83 | Ok(Async::NotReady) => None, 84 | Err(e) => { 85 | error!("error polling send queue: {:?}", e); 86 | None 87 | } 88 | } 89 | } 90 | } 91 | 92 | impl Future for Server { 93 | type Item = (); 94 | type Error = (); 95 | 96 | fn poll(&mut self) -> Poll { 97 | let mut waiting; 98 | loop { 99 | waiting = true; 100 | match self.socket.poll_recv_from(&mut self.in_buf) { 101 | Ok(Async::Ready((len, addr))) => { 102 | waiting = false; 103 | if let Err(e) = self.received(addr, len) { 104 | error!("error while handling received packet: {:?}", e); 105 | } 106 | } 107 | Ok(Async::NotReady) => {} 108 | Err(e) => error!("Server RECV ERROR: {:?}", e), 109 | } 110 | 111 | if let Some((addr, msg)) = self.poll_next() { 112 | waiting = false; 113 | match self.socket.poll_send_to(&msg, &addr) { 114 | Ok(Async::Ready(_)) => {} 115 | Ok(Async::NotReady) => {} 116 | Err(e) => error!("Server poll_send_to ERROR {:?}", e), 117 | } 118 | } 119 | 120 | if waiting { 121 | break; 122 | } 123 | } 124 | Ok(Async::NotReady) 125 | } 126 | } 127 | 128 | fn forward_packet(sink: &mut Sender>, msg: Vec) -> QuicResult<()> { 129 | match sink.start_send(msg) { 130 | Ok(AsyncSink::Ready) => {} 131 | Ok(AsyncSink::NotReady(msg)) => error!("discarding message: {:?}", msg), 132 | Err(e) => { 133 | return Err(QuicError::General(format!( 134 | "error while starting channel send: {:?}", 135 | e 136 | ))); 137 | } 138 | } 139 | match sink.poll_complete() { 140 | Ok(Async::Ready(())) => {} 141 | Ok(Async::NotReady) => {} 142 | Err(e) => { 143 | return Err(QuicError::General(format!( 144 | "error while polling channel complete: {:?}", 145 | e 146 | ))); 147 | } 148 | } 149 | Ok(()) 150 | } 151 | 152 | struct Connection { 153 | addr: SocketAddr, 154 | state: ConnectionState, 155 | send: Sender<(SocketAddr, Vec)>, 156 | recv: Receiver>, 157 | } 158 | 159 | impl Connection { 160 | fn new( 161 | addr: SocketAddr, 162 | state: ConnectionState, 163 | send: Sender<(SocketAddr, Vec)>, 164 | recv: Receiver>, 165 | ) -> Self { 166 | Self { 167 | addr, 168 | state, 169 | send, 170 | recv, 171 | } 172 | } 173 | } 174 | 175 | impl Future for Connection { 176 | type Item = (); 177 | type Error = (); 178 | fn poll(&mut self) -> Poll<(), ()> { 179 | loop { 180 | let mut received = false; 181 | match self.recv.poll() { 182 | Ok(Async::Ready(Some(ref mut msg))) => { 183 | self.state.handle(msg).unwrap(); 184 | received = true; 185 | } 186 | Ok(Async::Ready(None)) => {} 187 | Ok(Async::NotReady) => {} 188 | Err(e) => error!("error from server: {:?}", e), 189 | } 190 | 191 | let mut sent = false; 192 | match self.state.queued() { 193 | Ok(Some(msg)) => match self.send.start_send((self.addr, msg.clone())) { 194 | Ok(AsyncSink::Ready) => { 195 | sent = true; 196 | } 197 | Ok(AsyncSink::NotReady(msg)) => { 198 | error!("start send not ready: {:?}", msg); 199 | } 200 | Err(e) => error!("error sending: {:?}", e), 201 | }, 202 | Ok(None) => {} 203 | Err(e) => error!("error from connection state: {:?}", e), 204 | } 205 | if sent { 206 | self.state.pop_queue(); 207 | } 208 | 209 | let flushed = false; 210 | match self.send.poll_complete() { 211 | Ok(Async::Ready(())) => {} 212 | Ok(Async::NotReady) => {} 213 | Err(e) => error!("error from flushing sender: {:?}", e), 214 | } 215 | 216 | if !(received || sent || flushed) { 217 | break; 218 | } 219 | } 220 | Ok(Async::NotReady) 221 | } 222 | } 223 | 224 | type PacketChannel = ( 225 | Sender<(SocketAddr, Vec)>, 226 | Receiver<(SocketAddr, Vec)>, 227 | ); 228 | -------------------------------------------------------------------------------- /src/streams.rs: -------------------------------------------------------------------------------- 1 | use bytes::BufMut; 2 | 3 | use futures::future::{self, Future}; 4 | use futures::sync::oneshot; 5 | use futures::task; 6 | 7 | use std::collections::{HashMap, VecDeque}; 8 | use std::iter; 9 | use std::sync::{Arc, Mutex}; 10 | 11 | use super::{QuicError, QuicResult}; 12 | use codec::{BufLen, Codec}; 13 | use frame::{Frame, StreamFrame, StreamIdBlockedFrame}; 14 | use types::Side; 15 | 16 | #[derive(Clone)] 17 | pub struct Streams { 18 | inner: Arc>, 19 | } 20 | 21 | impl Streams { 22 | pub fn new(side: Side) -> Self { 23 | let mut open = [ 24 | OpenStreams::new(), 25 | OpenStreams::new(), 26 | OpenStreams::new(), 27 | OpenStreams::new(), 28 | ]; 29 | 30 | open[0].next = Some(0); 31 | 32 | Self { 33 | inner: Arc::new(Mutex::new(Inner { 34 | side, 35 | task: None, 36 | streams: HashMap::new(), 37 | open, 38 | control: VecDeque::new(), 39 | send_queue: VecDeque::new(), 40 | })), 41 | } 42 | } 43 | 44 | pub fn set_task(&mut self, task: task::Task) { 45 | let mut me = self.inner.lock().unwrap(); 46 | me.task = Some(task); 47 | } 48 | 49 | pub fn poll_send(&mut self, payload: &mut T) { 50 | let mut me = self.inner.lock().unwrap(); 51 | while let Some(frame) = me.control.pop_front() { 52 | frame.encode(payload); 53 | } 54 | 55 | while let Some((id, start, mut end)) = me.send_queue.pop_front() { 56 | if payload.remaining_mut() < 16 { 57 | me.send_queue.push_front((id, start, end)); 58 | break; 59 | } 60 | 61 | let mut frame = StreamFrame { 62 | id, 63 | fin: false, 64 | offset: start as u64, 65 | len: Some((end - start) as u64), 66 | data: Vec::new(), 67 | }; 68 | 69 | let len = end - start; 70 | if len > payload.remaining_mut() { 71 | let pivot = start + payload.remaining_mut() - frame.buf_len(); 72 | me.send_queue.push_front((id, pivot, end)); 73 | end = pivot; 74 | frame.len = Some((end - start) as u64); 75 | } 76 | 77 | let mut stream = &me.streams[&id]; 78 | let offset = stream.send_offset; 79 | let (start, mut end) = (start - offset, end - offset); 80 | let slices = stream.queued.as_slices(); 81 | 82 | if start < slices.0.len() && end <= slices.0.len() { 83 | frame.data.extend(&slices.0[start..end]); 84 | } else if start < slices.0.len() { 85 | frame.data.extend(&slices.0[start..]); 86 | end -= slices.0.len(); 87 | frame.data.extend(&slices.1[..end]); 88 | } else { 89 | let (start, end) = (start - slices.0.len(), end - slices.0.len()); 90 | frame.data.extend(&slices.1[start..end]); 91 | } 92 | 93 | debug_assert_eq!(frame.len, Some((end - start) as u64)); 94 | let frame = Frame::Stream(frame); 95 | frame.encode(payload); 96 | } 97 | 98 | println!("debug : streams poll_send"); 99 | } 100 | 101 | pub fn get_stream(&self, id: u64) -> Option { 102 | let me = self.inner.lock().unwrap(); 103 | if me.streams.contains_key(&id) { 104 | Some(StreamRef { 105 | inner: self.inner.clone(), 106 | id, 107 | }) 108 | } else { 109 | None 110 | } 111 | } 112 | 113 | pub fn init_send(&self, dir: Dir) -> QuicResult { 114 | let mut me = self.inner.lock().unwrap(); 115 | let stype = (me.side.to_bit() + dir.to_bit()) as usize; 116 | let next = me.open[stype].next; 117 | 118 | if let Some(id) = next { 119 | me.open[stype].next = if id + 4 < me.open[stype].max { 120 | Some(id + 4) 121 | } else { 122 | None 123 | }; 124 | } 125 | 126 | next.map(|id| { 127 | me.streams.insert(id, Stream::new()); 128 | StreamRef { 129 | inner: self.inner.clone(), 130 | id, 131 | } 132 | }).ok_or_else(|| { 133 | QuicError::General(format!( 134 | "{:?} not allowed to send on stream {:?} [init send]", 135 | me.side, next 136 | )) 137 | }) 138 | } 139 | 140 | pub fn update_max_id(&mut self, id: u64) { 141 | let mut me = self.inner.lock().unwrap(); 142 | me.open[(id % 4) as usize].max = id; 143 | } 144 | 145 | pub fn received(&mut self, frame: &StreamFrame) -> QuicResult<()> { 146 | let mut me = self.inner.lock().unwrap(); 147 | let id = frame.id; 148 | if Dir::from_id(id) == Dir::Uni && Side::from_id(id) == me.side { 149 | return Err(QuicError::General(format!( 150 | "{:?} not allowed to receive on stream {:?} [direction]", 151 | me.side, id 152 | ))); 153 | } 154 | 155 | if !me.streams.contains_key(&id) { 156 | let stype = (id % 4) as usize; 157 | if let Some(id) = me.open[stype].next { 158 | me.open[stype].next = if id + 4 <= me.open[stype].max { 159 | Some(id + 4) 160 | } else { 161 | None 162 | }; 163 | } else { 164 | return Err(QuicError::General(format!( 165 | "{:?} not allowed to receive on stream {:?} [limited]", 166 | me.side, id 167 | ))); 168 | } 169 | } 170 | 171 | let stream = me.streams.entry(id).or_insert_with(Stream::new); 172 | let offset = frame.offset as usize; 173 | let expected = stream.recv_offset + stream.received.len(); 174 | if offset == expected { 175 | stream.received.extend(&frame.data); 176 | } else if offset > expected { 177 | stream 178 | .received 179 | .extend(iter::repeat(0).take(offset - expected)); 180 | stream.received.extend(&frame.data); 181 | } else { 182 | return Err(QuicError::General(format!( 183 | "unhandled receive: {:?} {:?} {:?}", 184 | frame.offset, frame.len, expected 185 | ))); 186 | } 187 | 188 | Ok(()) 189 | } 190 | 191 | pub fn request_stream(self, id: u64) -> Box> { 192 | let consumer = { 193 | let mut me = self.inner.lock().unwrap(); 194 | let consumer = { 195 | let open = me.open.get_mut((id % 4) as usize).unwrap(); 196 | if id > open.max { 197 | let (p, c) = oneshot::channel::(); 198 | open.updates.push(p); 199 | Some(c) 200 | } else { 201 | None 202 | } 203 | }; 204 | if consumer.is_some() { 205 | me.control 206 | .push_back(Frame::StreamIdBlocked(StreamIdBlockedFrame(id))); 207 | if let Some(ref mut task) = me.task { 208 | task.notify(); 209 | } 210 | } 211 | consumer 212 | }; 213 | 214 | match consumer { 215 | Some(c) => Box::new( 216 | c.map(|_| self) 217 | .map_err(|_| QuicError::General("StreamIdBlocked future canceled".into())), 218 | ), 219 | None => Box::new(future::ok(self)), 220 | } 221 | } 222 | } 223 | 224 | pub struct StreamRef { 225 | inner: Arc>, 226 | pub id: u64, 227 | } 228 | 229 | impl StreamRef { 230 | pub fn send(&self, buf: &[u8]) -> QuicResult<()> { 231 | if buf.is_empty() { 232 | return Ok(()); 233 | } 234 | 235 | let mut me = self.inner.lock().unwrap(); 236 | if Dir::from_id(self.id) == Dir::Uni && Side::from_id(self.id) != me.side { 237 | return Err(QuicError::General(format!( 238 | "{:?} not allowed to send on stream {:?} [send]", 239 | me.side, self.id 240 | ))); 241 | } 242 | 243 | let (start, end) = { 244 | let stream = me.streams.get_mut(&self.id).unwrap(); 245 | let start = stream.send_offset + stream.queued.len(); 246 | stream.queued.extend(buf); 247 | (start, start + buf.len()) 248 | }; 249 | 250 | me.send_queue.push_back((self.id, start, end)); 251 | Ok(()) 252 | } 253 | 254 | pub fn received(&self) -> QuicResult> { 255 | let mut me = self.inner.lock().unwrap(); 256 | if Dir::from_id(self.id) == Dir::Uni && Side::from_id(self.id) == me.side { 257 | return Err(QuicError::General(format!( 258 | "{:?} not allowed to receive on stream {:?}", 259 | me.side, self.id 260 | ))); 261 | } 262 | let stream = me.streams.get_mut(&self.id).unwrap(); 263 | let vec = stream.received.drain(..).collect::>(); 264 | stream.recv_offset += vec.len(); 265 | Ok(vec) 266 | } 267 | } 268 | 269 | struct Inner { 270 | side: Side, 271 | task: Option, 272 | streams: HashMap, 273 | open: [OpenStreams; 4], 274 | control: VecDeque, 275 | send_queue: VecDeque<(u64, usize, usize)>, 276 | } 277 | 278 | #[derive(Default)] 279 | struct Stream { 280 | send_offset: usize, 281 | recv_offset: usize, 282 | queued: VecDeque, 283 | received: VecDeque, 284 | } 285 | 286 | impl Stream { 287 | fn new() -> Self { 288 | Self { 289 | ..Default::default() 290 | } 291 | } 292 | } 293 | 294 | #[derive(Debug)] 295 | struct OpenStreams { 296 | next: Option, 297 | max: u64, 298 | updates: Vec>, 299 | } 300 | 301 | impl OpenStreams { 302 | fn new() -> Self { 303 | Self { 304 | next: None, 305 | max: 0, 306 | updates: Vec::new(), 307 | } 308 | } 309 | } 310 | 311 | #[derive(Clone, Copy, Debug, PartialEq)] 312 | pub enum Dir { 313 | Bidi, 314 | Uni, 315 | } 316 | 317 | impl Dir { 318 | fn from_id(id: u64) -> Self { 319 | if id & 2 == 2 { 320 | Dir::Uni 321 | } else { 322 | Dir::Bidi 323 | } 324 | } 325 | 326 | fn to_bit(&self) -> u64 { 327 | match self { 328 | Dir::Bidi => 0, 329 | Dir::Uni => 2, 330 | } 331 | } 332 | } 333 | -------------------------------------------------------------------------------- /src/types.rs: -------------------------------------------------------------------------------- 1 | use rand::{self, Rng}; 2 | 3 | use std::fmt; 4 | use std::ops::Deref; 5 | 6 | #[derive(Clone, Eq, Hash, PartialEq)] 7 | pub struct ConnectionId { 8 | pub len: u8, 9 | pub bytes: [u8; 18], 10 | } 11 | 12 | impl Copy for ConnectionId {} 13 | 14 | impl ConnectionId { 15 | pub fn new(bytes: &[u8]) -> Self { 16 | debug_assert!(bytes.is_empty() || (bytes.len() > 3 && bytes.len() < 19)); 17 | let mut res = Self { 18 | len: bytes.len() as u8, 19 | bytes: [0; 18], 20 | }; 21 | (&mut res.bytes[..bytes.len()]).clone_from_slice(bytes); 22 | res 23 | } 24 | 25 | pub fn cil(&self) -> u8 { 26 | if self.len > 0 { 27 | self.len - 3 28 | } else { 29 | self.len 30 | } 31 | } 32 | } 33 | 34 | impl fmt::Debug for ConnectionId { 35 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 36 | write!(f, "0x")?; 37 | for b in (&self.bytes[..self.len as usize]).iter() { 38 | write!(f, "{:02x}", b)?; 39 | } 40 | Ok(()) 41 | } 42 | } 43 | 44 | impl Deref for ConnectionId { 45 | type Target = [u8]; 46 | fn deref(&self) -> &[u8] { 47 | &self.bytes[..self.len as usize] 48 | } 49 | } 50 | 51 | impl rand::distributions::Distribution for rand::distributions::Standard { 52 | fn sample(&self, rng: &mut R) -> ConnectionId { 53 | let mut res = ConnectionId { 54 | len: GENERATED_CID_LENGTH, 55 | bytes: [0; 18], 56 | }; 57 | rng.fill_bytes(&mut res.bytes[..res.len as usize]); 58 | res 59 | } 60 | } 61 | 62 | #[derive(Clone, Debug, PartialEq)] 63 | pub enum Side { 64 | Client, 65 | Server, 66 | } 67 | 68 | impl Side { 69 | pub fn other(&self) -> Side { 70 | match self { 71 | Side::Client => Side::Server, 72 | Side::Server => Side::Client, 73 | } 74 | } 75 | 76 | pub fn from_id(id: u64) -> Self { 77 | if id & 1 == 1 { 78 | Side::Server 79 | } else { 80 | Side::Client 81 | } 82 | } 83 | 84 | pub fn to_bit(&self) -> u64 { 85 | match self { 86 | Side::Client => 0, 87 | Side::Server => 1, 88 | } 89 | } 90 | } 91 | 92 | impl Copy for Side {} 93 | 94 | pub const GENERATED_CID_LENGTH: u8 = 8; 95 | --------------------------------------------------------------------------------