├── .gitignore ├── shell.nix ├── quicr ├── Cargo.toml ├── examples │ ├── client.rs │ ├── interop.rs │ └── server.rs └── src │ └── lib.rs ├── Cargo.toml ├── LICENSE-MIT ├── README.md ├── src ├── memory_stream.rs ├── coding.rs ├── varint.rs ├── hkdf.rs ├── transport_error.rs ├── lib.rs ├── transport_parameters.rs ├── range_set.rs ├── stream.rs └── frame.rs ├── examples └── connect.rs ├── LICENSE-APACHE └── tests └── tests.rs /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /target/ 3 | **/*.rs.bk 4 | Cargo.lock 5 | -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | with import ((import {}).pkgs.fetchFromGitHub { 2 | owner = "NixOS"; 3 | repo = "nixpkgs-channels"; 4 | rev = "0a7e258012b60cbe530a756f09a4f2516786d370"; 5 | sha256 = "1qcnxkqkw7bffyc17mqifcwjfqwbvn0vs0xgxnjvh9w0ssl2s036"; 6 | }) { }; 7 | stdenv.mkDerivation { 8 | name = "quicr"; 9 | buildInputs = with pkgs; [ rustChannels.stable.rust pkgconfig openssl_1_1 ]; 10 | shellHook = '' 11 | export CARGO_INCREMENTAL=1 12 | export RUST_BACKTRACE=1 13 | ''; 14 | } 15 | -------------------------------------------------------------------------------- /quicr/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "quicr" 3 | version = "0.4.1" 4 | authors = ["Benjamin Saunders "] 5 | license = "MIT/Apache-2.0" 6 | repository = "https://github.com/Ralith/quicr" 7 | description = "Moved to quinn (was: QUIC transport protocol implementation for Tokio)" 8 | readme = "../README.md" 9 | documentation = "https://ralith.github.io/quicr/quicr/" 10 | keywords = ["quic"] 11 | categories = [ "network-programming", "asynchronous" ] 12 | 13 | [badges] 14 | maintenance = { status = "deprecated" } 15 | 16 | [dependencies] 17 | quicr-core = { path = "..", version = "0.4.0" } 18 | tokio-reactor = "0.1.1" 19 | tokio-udp = "0.1" 20 | tokio-io = "0.1" 21 | tokio-timer = "0.2.1" 22 | slog = "2.1" 23 | futures = "0.1.21" 24 | fnv = "1.0.6" 25 | openssl = "0.10.10" 26 | failure = "0.1" 27 | bytes = "0.4.7" 28 | rand = "0.4" 29 | 30 | [dev-dependencies] 31 | tokio = "0.1.6" 32 | slog-term = "2" 33 | url = "1.7" 34 | structopt = "0.2.7" 35 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "quicr-core" 3 | version = "0.4.1" 4 | authors = ["Benjamin Saunders "] 5 | license = "MIT/Apache-2.0" 6 | repository = "https://github.com/Ralith/quicr" 7 | description = "Moved to quinn-proto (was: State machine for the QUIC transport protocol)" 8 | keywords = ["quic"] 9 | categories = [ "network-programming", "asynchronous" ] 10 | 11 | [badges] 12 | maintenance = { status = "deprecated" } 13 | 14 | [dependencies] 15 | rand = "0.4" 16 | slab = "0.4" 17 | bytes = "0.4.7" 18 | byteorder = "1.1" 19 | failure = "0.1" 20 | digest = "0.7" 21 | blake2 = "0.7" 22 | constant_time_eq = "0.1" 23 | lazy_static = "1" 24 | slog = { version = "2.2", features = ["max_level_trace", "release_max_level_debug"] } 25 | arrayvec = "0.4.7" 26 | fnv = "1.0.6" 27 | openssl = "0.10.10" 28 | 29 | [dev-dependencies] 30 | slog-term = "2" 31 | assert_matches = "1.1" 32 | hex-literal = "0.1.1" 33 | 34 | [workspace] 35 | members = ["quicr"] 36 | 37 | [profile.release] 38 | debug = true 39 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 The quicr Developers 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Moved 2 | 3 | This project has moved to, and merged with, [quinn](https://github.com/djc/quinn). 4 | 5 | # quicr 6 | 7 | quicr is an implementation of the [QUIC](https://en.wikipedia.org/wiki/QUIC) network protocol [undergoing 8 | standardization by the IETF](https://quicwg.github.io/). It is currently suitable for experimental use. The 9 | implementation is split up into the state machine crate `quicr-core` which performs no IO internally and can be tested 10 | deterministically, and a high-level tokio-compatible API in `quicr`. See `quicr/examples/` for usage. 11 | 12 | [![Crates.io](https://img.shields.io/crates/v/quicr.svg)](https://crates.io/crates/quicr) 13 | [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE-MIT) 14 | [![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE-APACHE) 15 | 16 | [API Docs](https://ralith.github.io/quicr/quicr/) 17 | 18 | ## Features 19 | 20 | - Simultaneous client/server operation 21 | - Ordered and unordered reads for improved performance 22 | 23 | ## Status 24 | 25 | - [x] QUIC draft 11 with TLS 1.3 draft 28 26 | - [x] Cryptographic handshake 27 | - [x] Stream data w/ flow control and congestion control 28 | - [x] Connection close 29 | - [x] Stateless retry 30 | - [ ] Migration 31 | - [x] 0-RTT data 32 | - [x] Session resumption 33 | 34 | ## Building 35 | 36 | Because TLS1.3 is a new standard, OpenSSL 1.1.1 (or later) is required for quicr to build. 37 | -------------------------------------------------------------------------------- /src/memory_stream.rs: -------------------------------------------------------------------------------- 1 | use std::io::{self, Read, Write, Result}; 2 | use std::ops::Deref; 3 | 4 | use stream; 5 | 6 | #[derive(Debug)] 7 | pub struct MemoryStream { 8 | incoming: stream::Assembler, 9 | outgoing: Vec, 10 | } 11 | 12 | impl MemoryStream { 13 | pub fn new() -> Self { Self { 14 | incoming: stream::Assembler::new(), 15 | outgoing: Vec::new(), 16 | }} 17 | 18 | pub fn insert(&mut self, offset: u64, data: &[u8]) { 19 | self.incoming.insert(offset, data); 20 | } 21 | 22 | pub fn take_outgoing(&mut self) -> Outgoing { Outgoing(&mut self.outgoing) } 23 | 24 | pub fn read_blocked(&self) -> bool { self.incoming.blocked() } 25 | pub fn read_offset(&self) -> u64 { self.incoming.offset() } 26 | 27 | pub fn reset_read(&mut self) { self.incoming = stream::Assembler::new(); } 28 | } 29 | 30 | impl Read for MemoryStream { 31 | fn read(&mut self, buf: &mut [u8]) -> Result { 32 | let n = self.incoming.read(buf); 33 | if n == 0 { 34 | return Err(io::Error::new(io::ErrorKind::WouldBlock, "no data available")); 35 | } 36 | Ok(n) 37 | } 38 | } 39 | 40 | impl Write for MemoryStream { 41 | fn write(&mut self, buf: &[u8]) -> Result { 42 | self.outgoing.write(buf) 43 | } 44 | 45 | fn flush(&mut self) -> Result<()> { Ok(()) } 46 | } 47 | 48 | pub struct Outgoing<'a>(&'a mut Vec); 49 | 50 | impl<'a> Drop for Outgoing<'a> { 51 | fn drop(&mut self) { 52 | self.0.clear(); 53 | } 54 | } 55 | 56 | impl<'a> Deref for Outgoing<'a> { 57 | type Target = [u8]; 58 | fn deref(&self) -> &[u8] { &self.0 } 59 | } 60 | 61 | impl<'a> AsRef<[u8]> for Outgoing<'a> { 62 | fn as_ref(&self) -> &[u8] { &self.0 } 63 | } 64 | -------------------------------------------------------------------------------- /src/coding.rs: -------------------------------------------------------------------------------- 1 | use bytes::{Buf, BufMut}; 2 | 3 | use varint; 4 | 5 | #[derive(Fail, Debug, Copy, Clone, Eq, PartialEq)] 6 | #[fail(display = "unexpected end of buffer")] 7 | pub struct UnexpectedEnd; 8 | 9 | pub type Result = ::std::result::Result; 10 | 11 | pub trait Value: Sized { 12 | fn decode(buf: &mut B) -> Result; 13 | fn encode(&self, buf: &mut B); 14 | } 15 | 16 | impl Value for u8 { 17 | fn decode(buf: &mut B) -> Result { 18 | if buf.remaining() < 1 { return Err(UnexpectedEnd); } 19 | Ok(buf.get_u8()) 20 | } 21 | fn encode(&self, buf: &mut B) { buf.put_u8(*self); } 22 | } 23 | 24 | impl Value for u16 { 25 | fn decode(buf: &mut B) -> Result { 26 | if buf.remaining() < 2 { return Err(UnexpectedEnd); } 27 | Ok(buf.get_u16_be()) 28 | } 29 | fn encode(&self, buf: &mut B) { buf.put_u16_be(*self); } 30 | } 31 | 32 | impl Value for u32 { 33 | fn decode(buf: &mut B) -> Result { 34 | if buf.remaining() < 4 { return Err(UnexpectedEnd); } 35 | Ok(buf.get_u32_be()) 36 | } 37 | fn encode(&self, buf: &mut B) { buf.put_u32_be(*self); } 38 | } 39 | 40 | impl Value for u64 { 41 | fn decode(buf: &mut B) -> Result { 42 | if buf.remaining() < 8 { return Err(UnexpectedEnd); } 43 | Ok(buf.get_u64_be()) 44 | } 45 | fn encode(&self, buf: &mut B) { buf.put_u64_be(*self); } 46 | } 47 | 48 | pub trait BufExt { 49 | fn get(&mut self) -> Result; 50 | fn get_var(&mut self) -> Result; 51 | } 52 | 53 | impl BufExt for T { 54 | fn get(&mut self) -> Result { 55 | U::decode(self) 56 | } 57 | 58 | fn get_var(&mut self) -> Result { 59 | varint::read(self).ok_or(UnexpectedEnd) 60 | } 61 | } 62 | 63 | pub trait BufMutExt { 64 | fn write(&mut self, x: T); 65 | fn write_var(&mut self, x: u64); 66 | } 67 | 68 | impl BufMutExt for T { 69 | fn write(&mut self, x: U) { 70 | x.encode(self); 71 | } 72 | 73 | fn write_var(&mut self, x: u64) { 74 | varint::write(x, self).unwrap() 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/varint.rs: -------------------------------------------------------------------------------- 1 | use bytes::{Buf, BufMut}; 2 | 3 | use byteorder::{ByteOrder, BigEndian}; 4 | 5 | pub fn size(x: u64) -> Option { 6 | if x < 2u64.pow(6) { 7 | Some(1) 8 | } else if x < 2u64.pow(14) { 9 | Some(2) 10 | } else if x < 2u64.pow(30) { 11 | Some(4) 12 | } else if x < 2u64.pow(62) { 13 | Some(8) 14 | } else { 15 | None 16 | } 17 | } 18 | 19 | pub fn read(r: &mut R) -> Option { 20 | if !r.has_remaining() { return None; } 21 | let mut buf = [0; 8]; 22 | buf[0] = r.get_u8(); 23 | let tag = buf[0] >> 6; 24 | buf[0] &= 0b00111111; 25 | Some(match tag { 26 | 0b00 => buf[0] as u64, 27 | 0b01 => { 28 | if r.remaining() < 1 { return None; } 29 | r.copy_to_slice(&mut buf[1..2]); 30 | BigEndian::read_u16(&buf) as u64 31 | } 32 | 0b10 => { 33 | if r.remaining() < 3 { return None; } 34 | r.copy_to_slice(&mut buf[1..4]); 35 | BigEndian::read_u32(&buf) as u64 36 | } 37 | 0b11 => { 38 | if r.remaining() < 7 { return None; } 39 | r.copy_to_slice(&mut buf[1..8]); 40 | BigEndian::read_u64(&buf) as u64 41 | } 42 | _ => unreachable!(), 43 | }) 44 | } 45 | 46 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Fail)] 47 | pub enum WriteError { 48 | #[fail(display = "insufficient space to encode value")] 49 | InsufficientSpace, 50 | #[fail(display = "value too large for varint encoding")] 51 | OversizedValue, 52 | } 53 | 54 | pub fn write(x: u64, w: &mut W) -> Result<(), WriteError> { 55 | if x < 2u64.pow(6) { 56 | if w.remaining_mut() < 1 { return Err(WriteError::InsufficientSpace); } 57 | w.put_u8(x as u8); 58 | } else if x < 2u64.pow(14) { 59 | if w.remaining_mut() < 2 { return Err(WriteError::InsufficientSpace); } 60 | w.put_u16_be(0b01 << 14 | x as u16); 61 | } else if x < 2u64.pow(30) { 62 | if w.remaining_mut() < 4 { return Err(WriteError::InsufficientSpace); } 63 | w.put_u32_be(0b10 << 30 | x as u32); 64 | } else if x < 2u64.pow(62) { 65 | if w.remaining_mut() < 8 { return Err(WriteError::InsufficientSpace); } 66 | w.put_u64_be(0b11 << 62 | x); 67 | } else { 68 | return Err(WriteError::OversizedValue); 69 | } 70 | Ok(()) 71 | } 72 | -------------------------------------------------------------------------------- /src/hkdf.rs: -------------------------------------------------------------------------------- 1 | use openssl::hash::MessageDigest; 2 | use openssl::sign::Signer; 3 | use openssl::pkey::PKey; 4 | 5 | use bytes::BufMut; 6 | 7 | pub fn extract(algo: MessageDigest, salt: &[u8], ikm: &[u8]) -> Box<[u8]> { 8 | let key = PKey::hmac(salt).unwrap(); 9 | let mut signer = Signer::new(algo, &key).unwrap(); 10 | signer.update(ikm).unwrap(); 11 | signer.sign_to_vec().unwrap().into() 12 | } 13 | 14 | fn expand(algo: MessageDigest, prk: &[u8], info: &[u8], length: usize) -> Box<[u8]> { 15 | let size = algo.size(); 16 | let prk = PKey::hmac(prk).unwrap(); 17 | let mut t = Vec::new(); 18 | let mut okm = Vec::new(); 19 | okm.reserve_exact(length); 20 | if length > 255 * size { panic!("length too large"); } 21 | for i in 1.. { 22 | let mut signer = Signer::new(algo, &prk).unwrap(); 23 | signer.update(&t).unwrap(); 24 | t.resize(size, 0); 25 | signer.update(info).unwrap(); 26 | signer.update(&[i as u8]).unwrap(); 27 | let n = signer.sign(&mut t).unwrap(); 28 | debug_assert_eq!(n, size); 29 | let remaining = length - okm.len(); 30 | if remaining > size { 31 | okm.extend_from_slice(&t); 32 | } else { 33 | okm.extend_from_slice(&t[0..remaining]); 34 | return okm.into(); 35 | } 36 | } 37 | unreachable!() 38 | } 39 | 40 | pub fn qexpand(algo: MessageDigest, prk: &[u8], label: &[u8], length: u16) -> Box<[u8]> { 41 | const PREFIX: &[u8] = b"QUIC "; 42 | assert!(label.len() < u8::max_value() as usize - PREFIX.len()); 43 | let mut info = Vec::new(); 44 | info.put_u16_be(length); 45 | info.put_u8(PREFIX.len() as u8 + label.len() as u8); 46 | info.put_slice(PREFIX); 47 | info.put_slice(label); 48 | expand(algo, prk, &info, length as usize) 49 | } 50 | 51 | #[cfg(test)] 52 | mod test { 53 | use super::*; 54 | 55 | #[test] 56 | fn case1() { 57 | let algo = MessageDigest::sha256(); 58 | const IKM: [u8; 22] = hex!("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"); 59 | const SALT: [u8; 13] = hex!("000102030405060708090a0b0c"); 60 | const INFO: [u8; 10] = hex!("f0f1f2f3f4f5f6f7f8f9"); 61 | const L: usize = 42; 62 | let prk = extract(algo, &SALT, &IKM); 63 | assert_eq!(&prk[..], &hex!("077709362c2e32df0ddc3f0dc47bba63 90b6c73bb50f9c3122ec844ad7c2b3e5")[..]); 64 | let okm = expand(algo, &prk, &INFO, L); 65 | assert_eq!(okm.len(), L); 66 | assert_eq!(&okm[..], &hex!("3cb25f25faacd57a90434f64d0362f2a 2d2d0a90cf1a5a4c5db02d56ecc4c5bf 34007208d5b887185865")[..]); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/transport_error.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | 3 | use bytes::{Buf, BufMut}; 4 | 5 | use frame; 6 | use coding::{self, BufExt, BufMutExt}; 7 | 8 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] 9 | pub struct Error(u16); 10 | 11 | impl Error { 12 | pub fn frame(ty: frame::Type) -> Self { Error(0x100 | u8::from(ty) as u16) } 13 | } 14 | 15 | impl coding::Value for Error { 16 | fn decode(buf: &mut B) -> coding::Result { Ok(Error(buf.get::()?)) } 17 | fn encode(&self, buf: &mut B) { buf.write::(self.0) } 18 | } 19 | 20 | impl From for u16 { fn from(x: Error) -> u16 { x.0 } } 21 | 22 | macro_rules! errors { 23 | {$($name:ident($val:expr) $desc:expr;)*} => { 24 | impl Error { 25 | $(#[doc = $desc] pub const $name: Self = Error($val);)* 26 | } 27 | impl fmt::Display for Error { 28 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 29 | if self.0 >= 0x100 && self.0 <= 0x1ff { 30 | return write!(f, "invalid {} frame", frame::Type::from(self.0 as u8)); 31 | } 32 | let x = match self.0 { 33 | $($val => $desc,)* 34 | _ => "unknown error" 35 | }; 36 | f.write_str(x) 37 | } 38 | } 39 | } 40 | } 41 | 42 | errors!{ 43 | NO_ERROR(0x0) "the connection is being closed abruptly in the absence of any error"; 44 | INTERNAL_ERROR(0x1) "the endpoint encountered an internal error and cannot continue with the connection"; 45 | SERVER_BUSY(0x2) "the server is currently busy and does not accept any new connections"; 46 | FLOW_CONTROL_ERROR(0x3) "an endpoint received more data than it permitted in its advertised data limits"; 47 | STREAM_ID_ERROR(0x4) "an endpoint received a frame for a stream identifier that exceeded its advertised maximum stream ID"; 48 | STREAM_STATE_ERROR(0x5) "an endpoint received a frame for a stream that was not in a state that permitted that frame"; 49 | FINAL_OFFSET_ERROR(0x6) "an endpoint received a STREAM frame containing data that exceeded the previously established final offset, or a RST_STREAM frame containing a final offset that was lower than the maximum offset of data that was already received, or a RST_STREAM frame containing a different final offset to the one already established"; 50 | FRAME_FORMAT_ERROR(0x7) "an endpoint received a frame that was badly formatted. For instance, an empty STREAM frame that omitted the FIN flag, or an ACK frame that has more acknowledgment ranges than the remainder of the packet could carry"; 51 | TRANSPORT_PARAMETER_ERROR(0x8) "an endpoint received transport parameters that were badly formatted, included an invalid value, was absent even though it is mandatory, was present though it is forbidden, or is otherwise in error"; 52 | VERSION_NEGOTIATION_ERROR(0x9) "an endpoint received transport parameters that contained version negotiation parameters that disagreed with the version negotiation that it performed, constituting a potential version downgrade attack"; 53 | PROTOCOL_VIOLATION(0xA) "an endpoint detected an error with protocol compliance that was not covered by more specific error codes"; 54 | UNSOLICITED_PATH_RESPONSE(0xB) "an endpoint received a PATH_RESPONSE frame that did not correspond to any PATH_CHALLENGE frame that it previously sent"; 55 | 56 | TLS_HANDSHAKE_FAILED(0x201) "the TLS handshake failed"; 57 | TLS_FATAL_ALERT_GENERATED(0x202) "a TLS fatal alert was sent, causing the TLS connection to end prematurely"; 58 | TLS_FATAL_ALERT_RECEIVED(0x203) "a TLS fatal alert was received, causing the TLS connection to end prematurely"; 59 | } 60 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate bytes; 2 | extern crate byteorder; 3 | extern crate rand; 4 | extern crate openssl; 5 | extern crate slab; 6 | #[macro_use] 7 | extern crate failure; 8 | extern crate digest; 9 | extern crate blake2; 10 | extern crate constant_time_eq; 11 | #[macro_use] 12 | extern crate lazy_static; 13 | #[macro_use] 14 | extern crate slog; 15 | #[cfg(test)] 16 | #[macro_use] 17 | extern crate assert_matches; 18 | #[cfg(test)] 19 | #[macro_use] 20 | extern crate hex_literal; 21 | extern crate arrayvec; 22 | extern crate fnv; 23 | 24 | use std::fmt; 25 | 26 | mod varint; 27 | mod memory_stream; 28 | mod transport_parameters; 29 | mod coding; 30 | mod hkdf; 31 | mod range_set; 32 | mod stream; 33 | 34 | mod frame; 35 | use frame::Frame; 36 | pub use frame::{ApplicationClose, ConnectionClose}; 37 | 38 | mod endpoint; 39 | pub use endpoint::{Endpoint, Config, CertConfig, ListenKeys, ConnectionHandle, Event, Io, Timer, ConnectionError, ReadError, WriteError, ConnectError, 40 | ConnectionId, EndpointError, ClientConfig}; 41 | 42 | mod transport_error; 43 | pub use transport_error::Error as TransportError; 44 | 45 | 46 | /// The QUIC protocol version implemented 47 | pub const VERSION: u32 = 0xff00000B; 48 | 49 | /// Whether an endpoint was the initiator of a connection 50 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] 51 | pub enum Side { 52 | /// The initiator of a connection 53 | Client = 0, 54 | /// The acceptor of a connection 55 | Server = 1, 56 | } 57 | 58 | impl ::std::ops::Not for Side { 59 | type Output = Side; 60 | fn not(self) -> Side { match self { Side::Client => Side::Server, Side::Server => Side::Client } } 61 | } 62 | 63 | impl slog::Value for Side { 64 | fn serialize(&self, _: &slog::Record, key: slog::Key, serializer: &mut slog::Serializer) -> slog::Result { 65 | serializer.emit_arguments(key, &format_args!("{:?}", self)) 66 | } 67 | } 68 | 69 | /// Whether a stream communicates data in both directions or only from the initiator 70 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] 71 | pub enum Directionality { 72 | /// Data flows in both directions 73 | Bi = 0, 74 | /// Data flows only from the stream's initiator 75 | Uni = 1, 76 | } 77 | 78 | /// Identifier for a stream within a particular connection 79 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] 80 | pub struct StreamId(pub(crate) u64); 81 | 82 | impl fmt::Display for StreamId { 83 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 84 | let initiator = match self.initiator() { Side::Client => "client", Side::Server => "server" }; 85 | let directionality = match self.directionality() { Directionality::Uni => "uni", Directionality::Bi => "bi" }; 86 | write!(f, "{} {}directional stream {}", initiator, directionality, self.index()) 87 | } 88 | } 89 | 90 | impl slog::Value for StreamId { 91 | fn serialize(&self, _: &slog::Record, key: slog::Key, serializer: &mut slog::Serializer) -> slog::Result { 92 | serializer.emit_arguments(key, &format_args!("{:?}", self)) 93 | } 94 | } 95 | 96 | impl StreamId { 97 | pub(crate) fn new(initiator: Side, directionality: Directionality, index: u64) -> Self { 98 | StreamId(index << 2 | (directionality as u64) << 1 | initiator as u64) 99 | } 100 | /// Which side of a connection initiated the stream 101 | pub fn initiator(&self) -> Side { if self.0 & 0x1 == 0 { Side::Client } else { Side::Server } } 102 | /// Which directions data flows in 103 | pub fn directionality(&self) -> Directionality { if self.0 & 0x2 == 0 { Directionality::Bi } else { Directionality::Uni } } 104 | /// Distinguishes streams of the same initiator and directionality 105 | pub fn index(&self) -> u64 { self.0 >> 2 } 106 | } 107 | 108 | impl coding::Value for StreamId { 109 | fn decode(buf: &mut B) -> coding::Result { 110 | varint::read(buf).map(StreamId).ok_or(coding::UnexpectedEnd) 111 | } 112 | fn encode(&self, buf: &mut B) { 113 | varint::write(self.0, buf).unwrap() 114 | } 115 | } 116 | 117 | // 118 | // Useful internal constants 119 | // 120 | 121 | const RESET_TOKEN_SIZE: usize = 16; 122 | const MAX_CID_SIZE: usize = 18; 123 | const MIN_CID_SIZE: usize = 4; 124 | -------------------------------------------------------------------------------- /quicr/examples/client.rs: -------------------------------------------------------------------------------- 1 | extern crate tokio; 2 | extern crate quicr; 3 | #[macro_use] 4 | extern crate failure; 5 | #[macro_use] 6 | extern crate slog; 7 | extern crate slog_term; 8 | extern crate futures; 9 | extern crate url; 10 | #[macro_use] 11 | extern crate structopt; 12 | 13 | use std::net::ToSocketAddrs; 14 | use std::io::{self, Write}; 15 | use std::time::{Instant, Duration}; 16 | use std::path::PathBuf; 17 | use std::fs; 18 | 19 | use futures::{Future, Stream}; 20 | use tokio::runtime::current_thread::Runtime; 21 | use tokio::executor::current_thread; 22 | use url::Url; 23 | use structopt::StructOpt; 24 | 25 | use slog::{Logger, Drain}; 26 | use failure::Error; 27 | 28 | type Result = std::result::Result; 29 | 30 | #[derive(StructOpt, Debug)] 31 | #[structopt(name = "client")] 32 | struct Opt { 33 | /// file to log TLS keys to for debugging 34 | #[structopt(parse(from_os_str), long = "keylog")] 35 | keylog: Option, 36 | 37 | url: Url, 38 | 39 | /// whether to accept invalid (e.g. self-signed) TLS certificates 40 | #[structopt(long = "accept-insecure-certs")] 41 | accept_insecure_certs: bool, 42 | 43 | /// file to read/write session tickets to 44 | #[structopt(long = "session-cache", parse(from_os_str))] 45 | session_cache: Option, 46 | } 47 | 48 | fn main() { 49 | let opt = Opt::from_args(); 50 | let code = { 51 | let decorator = slog_term::PlainSyncDecorator::new(std::io::stderr()); 52 | let drain = slog_term::FullFormat::new(decorator).use_original_order().build().fuse(); 53 | if let Err(e) = run(Logger::root(drain, o!()), opt) { 54 | eprintln!("ERROR: {}", e); 55 | 1 56 | } else { 0 } 57 | }; 58 | ::std::process::exit(code); 59 | } 60 | 61 | fn run(log: Logger, mut options: Opt) -> Result<()> { 62 | let url = options.url; 63 | let remote = url.with_default_port(|_| Ok(4433))?.to_socket_addrs()?.next().ok_or(format_err!("couldn't resolve to an address"))?; 64 | 65 | let mut runtime = Runtime::new()?; 66 | 67 | let config = quicr::Config { 68 | protocols: vec![b"hq-11"[..].into()], 69 | keylog: options.keylog, 70 | ..quicr::Config::default() 71 | }; 72 | 73 | let ticket; 74 | if let Some(path) = options.session_cache.take() { 75 | ticket = match fs::read(&path) { 76 | Ok(x) => Some(x), 77 | Err(ref e) if e.kind() == io::ErrorKind::NotFound => None, 78 | Err(e) => { return Err(e.into()); } 79 | }; 80 | } else { 81 | ticket = None; 82 | } 83 | 84 | let mut builder = quicr::Endpoint::new(); 85 | builder.logger(log.clone()) 86 | .config(config); 87 | let (endpoint, driver, _) = builder.bind("[::]:0")?; 88 | runtime.spawn(driver.map_err(|e| eprintln!("IO error: {}", e))); 89 | 90 | let request = format!("GET {}\r\n", url.path()); 91 | let start = Instant::now(); 92 | let mut session_path = options.session_cache.take(); 93 | runtime.block_on( 94 | endpoint.connect(&remote, 95 | quicr::ClientConfig { 96 | server_name: Some(url.host_str().ok_or(format_err!("URL missing host"))?), 97 | accept_insecure_certs: options.accept_insecure_certs, 98 | session_ticket: ticket.as_ref().map(|x| &x[..]), 99 | ..quicr::ClientConfig::default() 100 | })? 101 | .map_err(|e| format_err!("failed to connect: {}", e)) 102 | .and_then(move |conn| { 103 | eprintln!("connected at {}", duration_secs(&start.elapsed())); 104 | if let Some(path) = session_path.take() { 105 | current_thread::spawn(conn.session_tickets.map_err(|_| ()).for_each(move |data| { 106 | if let Err(e) = fs::write(&path, &data) { 107 | error!(log, "failed to write session: {error}", error=e.to_string()); 108 | } else { 109 | info!(log, "wrote {bytes}B session", bytes=data.len()); 110 | } 111 | Ok(()) 112 | })); 113 | } 114 | let conn = conn.connection; 115 | let stream = conn.open_bi(); 116 | stream.map_err(|e| format_err!("failed to open stream: {}", e)) 117 | .and_then(move |stream| { 118 | eprintln!("stream opened at {}", duration_secs(&start.elapsed())); 119 | tokio::io::write_all(stream, request.as_bytes().to_owned()).map_err(|e| format_err!("failed to send request: {}", e)) 120 | }) 121 | .and_then(|(stream, _)| tokio::io::shutdown(stream).map_err(|e| format_err!("failed to shutdown stream: {}", e))) 122 | .and_then(move |stream| { 123 | let response_start = Instant::now(); 124 | eprintln!("request sent at {}", duration_secs(&(response_start - start))); 125 | quicr::read_to_end(stream, usize::max_value()).map_err(|e| format_err!("failed to read response: {}", e)) 126 | .map(move |x| (x, response_start)) 127 | }) 128 | .and_then(move |((_, data), response_start)| { 129 | let seconds = duration_secs(&response_start.elapsed()); 130 | eprintln!("response received in {} - {} KiB/s", seconds, data.len() as f32 / (seconds * 1024.0)); 131 | io::stdout().write_all(&data).unwrap(); 132 | io::stdout().flush().unwrap(); 133 | conn.close(0, b"done").map_err(|_| unreachable!()) 134 | }) 135 | .map(|()| eprintln!("drained")) 136 | }) 137 | )?; 138 | 139 | Ok(()) 140 | } 141 | 142 | fn duration_secs(x: &Duration) -> f32 { x.as_secs() as f32 + x.subsec_nanos() as f32 * 1e-9 } 143 | -------------------------------------------------------------------------------- /quicr/examples/interop.rs: -------------------------------------------------------------------------------- 1 | extern crate tokio; 2 | extern crate quicr; 3 | #[macro_use] 4 | extern crate failure; 5 | #[macro_use] 6 | extern crate slog; 7 | extern crate slog_term; 8 | extern crate futures; 9 | #[macro_use] 10 | extern crate structopt; 11 | 12 | use std::net::ToSocketAddrs; 13 | use std::path::PathBuf; 14 | 15 | use futures::{Future, Stream}; 16 | use tokio::runtime::current_thread::Runtime; 17 | use structopt::StructOpt; 18 | 19 | use slog::{Logger, Drain}; 20 | use failure::Error; 21 | 22 | type Result = std::result::Result; 23 | 24 | #[derive(StructOpt, Debug)] 25 | #[structopt(name = "interop")] 26 | struct Opt { 27 | host: String, 28 | #[structopt(default_value = "4433")] 29 | port: u16, 30 | retry_port: Option, 31 | 32 | /// file to log TLS keys to for debugging 33 | #[structopt(parse(from_os_str), long = "keylog")] 34 | keylog: Option, 35 | } 36 | 37 | fn main() { 38 | let opt = Opt::from_args(); 39 | let code = { 40 | let decorator = slog_term::PlainSyncDecorator::new(std::io::stderr()); 41 | let drain = slog_term::FullFormat::new(decorator).use_original_order().build().fuse(); 42 | if let Err(e) = run(Logger::root(drain, o!()), opt) { 43 | eprintln!("ERROR: {}", e); 44 | 1 45 | } else { 0 } 46 | }; 47 | ::std::process::exit(code); 48 | } 49 | 50 | fn run(log: Logger, options: Opt) -> Result<()> { 51 | let remote = format!("{}:{}", options.host, options.port).to_socket_addrs()?.next().ok_or(format_err!("couldn't resolve to an address"))?; 52 | 53 | let mut runtime = Runtime::new()?; 54 | 55 | let config = quicr::Config { 56 | protocols: vec![b"hq-11"[..].into()], 57 | keylog: options.keylog, 58 | ..quicr::Config::default() 59 | }; 60 | 61 | let mut builder = quicr::Endpoint::new(); 62 | builder.logger(log.clone()) 63 | .config(config); 64 | let (endpoint, driver, _) = builder.bind("[::]:0")?; 65 | runtime.spawn(driver.map_err(|e| eprintln!("IO error: {}", e))); 66 | 67 | let mut handshake = false; 68 | let mut stream_data = false; 69 | let mut close = false; 70 | let mut ticket = None; 71 | let result = runtime.block_on( 72 | endpoint.connect(&remote, 73 | quicr::ClientConfig { 74 | server_name: Some(&options.host), 75 | accept_insecure_certs: true, 76 | ..quicr::ClientConfig::default() 77 | })? 78 | .map_err(|e| format_err!("failed to connect: {}", e)) 79 | .and_then(|conn| { 80 | println!("connected"); 81 | handshake = true; 82 | let tickets = conn.session_tickets; 83 | let conn = conn.connection; 84 | let stream = conn.open_bi(); 85 | stream.map_err(|e| format_err!("failed to open stream: {}", e)) 86 | .and_then(move |stream| get(stream)) 87 | .and_then(|data| { 88 | println!("read {} bytes, closing", data.len()); 89 | stream_data = true; 90 | conn.close(0, b"done").map_err(|_| unreachable!()) 91 | }) 92 | .map(|()| { close = true; }) 93 | .and_then(|()| tickets.into_future().map_err(|(e, _)| e.into()) 94 | .map(|(x, _)| if let Some(x) = x { ticket = Some(x); })) 95 | }) 96 | ); 97 | if let Err(e) = result { 98 | println!("failure: {}", e); 99 | } 100 | 101 | let mut retry = false; 102 | if let Some(port) = options.retry_port { 103 | println!("connecting to retry port"); 104 | let remote = format!("{}:{}", options.host, port).to_socket_addrs()?.next().ok_or(format_err!("couldn't resolve to an address"))?; 105 | let result = runtime.block_on(endpoint.connect(&remote, 106 | quicr::ClientConfig { 107 | server_name: Some(&options.host), 108 | accept_insecure_certs: true, 109 | ..quicr::ClientConfig::default() 110 | })? 111 | .and_then(|conn| { 112 | retry = true; 113 | conn.connection.close(0, b"done").map_err(|_| unreachable!()) 114 | })); 115 | if let Err(e) = result { 116 | println!("failure: {}", e); 117 | } 118 | } 119 | 120 | let mut resumption = false; 121 | if let Some(ticket) = ticket { 122 | println!("attempting 0-RTT"); 123 | let (conn, established) = endpoint.connect_zero_rtt( 124 | &remote, 125 | quicr::ClientConfig { 126 | server_name: Some(&options.host), 127 | accept_insecure_certs: true, 128 | session_ticket: Some(&ticket), 129 | ..quicr::ClientConfig::default() 130 | })?; 131 | let conn = conn.connection; 132 | let request = conn.open_bi() 133 | .map_err(|e| format_err!("failed to open stream: {}", e)) 134 | .and_then(|stream| get(stream)) 135 | .and_then(|data| { 136 | println!("read {} bytes, closing", data.len()); 137 | resumption = conn.session_resumed(); 138 | conn.close(0, b"done").map_err(|_| unreachable!()) 139 | }); 140 | let result = runtime.block_on(established.map_err(|e| format_err!("failed to connect: {}", e)).join(request)); 141 | if let Err(e) = result { 142 | println!("failure: {}", e); 143 | } 144 | } 145 | 146 | if handshake { 147 | print!("VH"); 148 | } 149 | if stream_data { 150 | print!("D"); 151 | } 152 | if close { 153 | print!("C"); 154 | } 155 | if resumption { 156 | print!("R"); 157 | } 158 | if retry { 159 | print!("S"); 160 | } 161 | 162 | println!(""); 163 | 164 | Ok(()) 165 | } 166 | 167 | fn get(stream: quicr::Stream) -> impl Future, Error=Error> { 168 | tokio::io::write_all(stream, b"GET /index.html\r\n".to_owned()).map_err(|e| format_err!("failed to send request: {}", e)) 169 | .and_then(|(stream, _)| tokio::io::shutdown(stream).map_err(|e| format_err!("failed to shutdown stream: {}", e))) 170 | .and_then(move |stream| { 171 | quicr::read_to_end(stream, usize::max_value()).map_err(|e| format_err!("failed to read response: {}", e)) 172 | }) 173 | .map(|(_, data)| data) 174 | } 175 | -------------------------------------------------------------------------------- /examples/connect.rs: -------------------------------------------------------------------------------- 1 | extern crate quicr_core as quicr; 2 | extern crate rand; 3 | #[macro_use] 4 | extern crate failure; 5 | #[macro_use] 6 | extern crate slog; 7 | extern crate slog_term; 8 | 9 | use std::net::{UdpSocket, SocketAddr, SocketAddrV6, ToSocketAddrs}; 10 | use std::time::{Instant, Duration}; 11 | use std::io::{self, Write}; 12 | use std::str; 13 | 14 | use failure::Error; 15 | use quicr::{Endpoint, Config, Io, Timer, Event, Directionality, ReadError, ClientConfig}; 16 | use slog::{Logger, Drain}; 17 | 18 | fn main() { 19 | let code = { 20 | let decorator = slog_term::PlainSyncDecorator::new(std::io::stderr()); 21 | let drain = slog_term::FullFormat::new(decorator).use_original_order().build().fuse(); 22 | if let Err(e) = run(Logger::root(drain, o!())) { 23 | eprintln!("ERROR: {}", e); 24 | 1 25 | } else { 0 } 26 | }; 27 | ::std::process::exit(code); 28 | } 29 | 30 | fn normalize(x: SocketAddr) -> SocketAddrV6 { 31 | match x { 32 | SocketAddr::V6(x) => x, 33 | SocketAddr::V4(x) => SocketAddrV6::new(x.ip().to_ipv6_mapped(), x.port(), 0, 0), 34 | } 35 | } 36 | 37 | type Result = ::std::result::Result; 38 | 39 | fn run(log: Logger) -> Result<()> { 40 | let remote = ::std::env::args().nth(1).ok_or(format_err!("missing address argument"))?; 41 | let mut ctx = Context::new(log, remote)?; 42 | ctx.run()?; 43 | Ok(()) 44 | } 45 | 46 | struct Context { 47 | log: Logger, 48 | socket: UdpSocket, 49 | client: Endpoint, 50 | remote_host: String, 51 | remote: SocketAddrV6, 52 | loss_timer: Option, 53 | close_timer: Option, 54 | idle_timer: Option, 55 | } 56 | 57 | impl Context { 58 | fn new(log: Logger, mut remote_host: String) -> Result { 59 | let socket = UdpSocket::bind("[::]:0")?; 60 | let remote = normalize(remote_host.to_socket_addrs()?.next().ok_or(format_err!("couldn't resolve to an address"))?); 61 | if let Some(x) = remote_host.rfind(':') { remote_host.truncate(x); } 62 | let config = Config { 63 | protocols: vec![b"hq-11"[..].into()], 64 | //receive_window: 256, 65 | //stream_receive_window: 256, 66 | ..Config::default() 67 | }; 68 | Ok(Self { 69 | socket, 70 | client: Endpoint::new(log.clone(), config, None, None)?, 71 | log, remote_host, remote, 72 | loss_timer: None, 73 | close_timer: None, 74 | idle_timer: None, 75 | }) 76 | } 77 | 78 | fn run(&mut self) -> Result<()> { 79 | let epoch = Instant::now(); 80 | let c = self.client.connect(self.remote, ClientConfig { server_name: Some(&self.remote_host), ..ClientConfig::default() })?; 81 | let mut time = 0; 82 | let mut buf = Vec::new(); 83 | let mut sent = 0; 84 | let mut recvd = 0; 85 | loop { 86 | while let Some((connection, e)) = self.client.poll() { match e { 87 | Event::Connected { protocol, .. } => { 88 | info!(self.log, "connected, submitting request"; "protocol" => %protocol.as_ref().map_or("none", |x| str::from_utf8(x).unwrap())); 89 | let s = self.client.open(c, Directionality::Bi).ok_or(format_err!("no streams available"))?; 90 | self.client.write(c, s, b"GET /index.html\r\n"[..].into()).unwrap(); 91 | self.client.finish(c, s); 92 | } 93 | Event::ConnectionLost { reason, .. } => { 94 | self.client.close(time, c, 0, b""[..].into()); 95 | bail!("connection lost: {}", reason); 96 | } 97 | Event::StreamReadable { stream, .. } => { 98 | assert_eq!(c, connection); 99 | loop { match self.client.read_unordered(connection, stream) { 100 | Ok((data, offset)) => { 101 | let len = buf.len().max(offset as usize + data.len()); 102 | buf.resize(len, 0); 103 | buf[offset as usize..offset as usize+data.len()].copy_from_slice(&data); 104 | } 105 | Err(ReadError::Finished) => { 106 | info!(self.log, "done, closing"); 107 | io::stdout().write_all(&buf)?; 108 | io::stdout().flush()?; 109 | self.client.close(time, c, 0, b"finished"[..].into()); 110 | break; 111 | } 112 | Err(ReadError::Blocked) => { break; } 113 | Err(e) => { 114 | error!(self.log, "read error"; "error" => %e); 115 | self.client.close(time, c, 1, b"unexpected error"[..].into()); 116 | } 117 | }} 118 | } 119 | _ => {} 120 | }} 121 | while let Some(io) = self.client.poll_io(time) { match io { 122 | Io::Transmit { destination, packet } => { sent += 1; self.socket.send_to(&packet, destination)?; } 123 | Io::TimerStart { timer: Timer::LossDetection, time, .. } => { self.loss_timer = Some(time); } 124 | Io::TimerStart { timer: Timer::Close, time, .. } => { self.close_timer = Some(time); } 125 | Io::TimerStart { timer: Timer::Idle, time, .. } => { self.idle_timer = Some(time); } 126 | Io::TimerStop { timer: Timer::LossDetection, .. } => { self.loss_timer = None; } 127 | Io::TimerStop { timer: Timer::Close, .. } => { self.close_timer = None; } 128 | Io::TimerStop { timer: Timer::Idle, .. } => { unreachable!() } 129 | }} 130 | let mut buf = [0; 2048]; 131 | let (timeout, timer) = (self.loss_timer.unwrap_or(u64::max_value()), Timer::LossDetection) 132 | .min((self.close_timer.unwrap_or(u64::max_value()), Timer::Close)) 133 | .min((self.idle_timer.unwrap_or(u64::max_value()), Timer::Idle)); 134 | if timeout != u64::max_value() { 135 | trace!(self.log, "setting timeout"; "type" => ?timer, "time" => time); 136 | let dt = timeout - time; 137 | let seconds = dt / (1000 * 1000); 138 | self.socket.set_read_timeout(Some(Duration::new(seconds, (dt - (seconds * 1000 * 1000)) as u32 * 1000)))?; 139 | } else { 140 | self.socket.set_read_timeout(None)?; 141 | } 142 | let r = self.socket.recv_from(&mut buf); 143 | let dt = Instant::now() - epoch; 144 | time = dt.subsec_nanos() as u64 / 1000 + dt.as_secs() * 1000 * 1000; 145 | match r { 146 | Ok((n, addr)) => { 147 | recvd += 1; 148 | self.client.handle(time, normalize(addr), (&buf[0..n]).into()); 149 | } 150 | Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { 151 | trace!(self.log, "timeout"; "type" => ?timer); 152 | self.client.timeout(time, c, timer); 153 | match timer { 154 | Timer::LossDetection => self.loss_timer = None, 155 | Timer::Idle => self.idle_timer = None, 156 | Timer::Close => { 157 | self.close_timer = None; 158 | info!(self.log, "done"; "sent packets" => sent, "received packets" => recvd); 159 | return Ok(()); 160 | } 161 | } 162 | } 163 | Err(e) => { return Err(e.into()); } 164 | } 165 | } 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /quicr/examples/server.rs: -------------------------------------------------------------------------------- 1 | extern crate tokio; 2 | extern crate quicr; 3 | #[macro_use] 4 | extern crate failure; 5 | #[macro_use] 6 | extern crate slog; 7 | extern crate slog_term; 8 | extern crate futures; 9 | #[macro_use] 10 | extern crate structopt; 11 | 12 | use std::fs; 13 | use std::fmt; 14 | use std::path::{self, Path, PathBuf}; 15 | use std::str; 16 | use std::rc::Rc; 17 | use std::ascii; 18 | use std::net::SocketAddr; 19 | 20 | use futures::{Future, Stream}; 21 | use tokio::executor::current_thread; 22 | use tokio::runtime::current_thread::Runtime; 23 | use failure::{ResultExt, Fail}; 24 | use structopt::StructOpt; 25 | 26 | use slog::{Logger, Drain}; 27 | use failure::Error; 28 | 29 | type Result = std::result::Result; 30 | 31 | pub struct PrettyErr<'a>(&'a Fail); 32 | impl<'a> fmt::Display for PrettyErr<'a> { 33 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 34 | fmt::Display::fmt(&self.0, f)?; 35 | let mut x: &Fail = self.0; 36 | while let Some(cause) = x.cause() { 37 | f.write_str(": ")?; 38 | fmt::Display::fmt(&cause, f)?; 39 | x = cause; 40 | } 41 | Ok(()) 42 | } 43 | } 44 | 45 | pub trait ErrorExt { 46 | fn pretty(&self) -> PrettyErr; 47 | } 48 | 49 | impl ErrorExt for Error { 50 | fn pretty(&self) -> PrettyErr { PrettyErr(self.cause()) } 51 | } 52 | 53 | #[derive(StructOpt, Debug)] 54 | #[structopt(name = "server")] 55 | struct Opt { 56 | /// file to log TLS keys to for debugging 57 | #[structopt(parse(from_os_str), long = "keylog")] 58 | keylog: Option, 59 | /// directory to serve files from 60 | #[structopt(parse(from_os_str))] 61 | root: PathBuf, 62 | /// TLS private key in PEM format 63 | #[structopt(parse(from_os_str), short = "k", long = "key", requires = "cert")] 64 | key: Option, 65 | /// TLS certificate in PEM format 66 | #[structopt(parse(from_os_str), short = "c", long = "cert", requires = "key")] 67 | cert: Option, 68 | /// Enable stateless retries 69 | #[structopt(long = "stateless-retry")] 70 | stateless_retry: bool, 71 | /// Address to listen on 72 | #[structopt(long = "listen", default_value = "[::]:4433")] 73 | listen: SocketAddr, 74 | } 75 | 76 | fn main() { 77 | let opt = Opt::from_args(); 78 | let code = { 79 | let decorator = slog_term::PlainSyncDecorator::new(std::io::stderr()); 80 | let drain = slog_term::FullFormat::new(decorator).use_original_order().build().fuse(); 81 | if let Err(e) = run(Logger::root(drain, o!()), opt) { 82 | eprintln!("ERROR: {}", e.pretty()); 83 | 1 84 | } else { 0 } 85 | }; 86 | ::std::process::exit(code); 87 | } 88 | 89 | fn run(log: Logger, options: Opt) -> Result<()> { 90 | let root = Rc::new(options.root); 91 | if !root.exists() { bail!("root path does not exist"); } 92 | 93 | let mut runtime = Runtime::new()?; 94 | 95 | let mut builder = quicr::Endpoint::new(); 96 | builder.logger(log.clone()) 97 | .config(quicr::Config { 98 | protocols: vec![b"hq-11"[..].into()], 99 | max_remote_bi_streams: 64, 100 | keylog: options.keylog, 101 | use_stateless_retry: options.stateless_retry, 102 | ..quicr::Config::default() 103 | }) 104 | .listen(); 105 | 106 | if let Some(key_path) = options.key { 107 | let key = fs::read(&key_path).context("failed to read private key")?;; 108 | builder.private_key_pem(&key).context("failed to load private key")?; 109 | 110 | let cert_path = options.cert.unwrap(); // Ensured present by option parsing 111 | let cert = fs::read(&cert_path).context("failed to read certificate")?; 112 | builder.certificate_pem(&cert).context("failed to load certificate")?; 113 | } else { 114 | builder.generate_insecure_certificate().context("failed to generate certificate")?; 115 | } 116 | 117 | let (_, driver, incoming) = builder.bind(options.listen)?; 118 | 119 | runtime.spawn(incoming.for_each(move |conn| { handle_connection(&root, &log, conn); Ok(()) })); 120 | runtime.block_on(driver)?; 121 | 122 | Ok(()) 123 | } 124 | 125 | fn handle_connection(root: &PathBuf, log: &Logger, conn: quicr::NewConnection) { 126 | let quicr::NewConnection { incoming, connection } = conn; 127 | let log = log.new(o!("local_id" => format!("{}", connection.local_id()))); 128 | info!(log, "got connection"; 129 | "remote_id" => %connection.remote_id(), 130 | "address" => %connection.remote_address(), 131 | "protocol" => connection.protocol().map_or_else(|| "".into(), |x| String::from_utf8_lossy(&x).into_owned())); 132 | let log2 = log.clone(); 133 | let root = root.clone(); 134 | 135 | // Each stream initiated by the client constitutes a new request. 136 | current_thread::spawn( 137 | incoming 138 | .map_err(move |e| info!(log2, "connection terminated"; "reason" => %e)) 139 | .for_each(move |stream| { handle_request(&root, &log, stream); Ok(()) }) 140 | ); 141 | } 142 | 143 | fn handle_request(root: &PathBuf, log: &Logger, stream: quicr::NewStream) { 144 | let stream = match stream { 145 | quicr::NewStream::Bi(stream) => stream, 146 | quicr::NewStream::Uni(_) => unreachable!(), // config.max_remote_uni_streams is defaulted to 0 147 | }; 148 | let root = root.clone(); 149 | let log = log.clone(); 150 | let log2 = log.clone(); 151 | let log3 = log.clone(); 152 | 153 | current_thread::spawn( 154 | quicr::read_to_end(stream, 64 * 1024) // Read the request, which must be at most 64KiB 155 | .map_err(|e| format_err!("failed reading request: {}", e)) 156 | .and_then(move |(stream, req)| { 157 | let mut escaped = String::new(); 158 | for &x in &req[..] { 159 | let part = ascii::escape_default(x).collect::>(); 160 | escaped.push_str(str::from_utf8(&part).unwrap()); 161 | } 162 | info!(log, "got request"; "content" => escaped); 163 | // Execute the request 164 | let resp = process_get(&root, &req).unwrap_or_else(move |e| { 165 | error!(log, "failed to process request"; "reason" => %e.pretty()); 166 | format!("failed to process request: {}\n", e.pretty()).into_bytes().into() 167 | }); 168 | // Write the response 169 | tokio::io::write_all(stream, resp).map_err(|e| format_err!("failed to send response: {}", e)) 170 | }) 171 | // Gracefully terminate the stream 172 | .and_then(|(stream, _)| tokio::io::shutdown(stream).map_err(|e| format_err!("failed to shutdown stream: {}", e))) 173 | .map(move |_| info!(log3, "request complete")) 174 | .map_err(move |e| error!(log2, "request failed"; "reason" => %e.pretty())) 175 | ) 176 | } 177 | 178 | fn process_get(root: &Path, x: &[u8]) -> Result> { 179 | if x.len() < 4 || &x[0..4] != b"GET " { bail!("missing GET"); } 180 | if x[4..].len() < 2 || &x[x.len()-2..] != b"\r\n" { bail!("missing \\r\\n"); } 181 | let path = str::from_utf8(&x[4..x.len()-2]).context("path is malformed UTF-8")?; 182 | let path = Path::new(&path); 183 | let mut real_path = PathBuf::from(root); 184 | let mut components = path.components(); 185 | match components.next() { 186 | Some(path::Component::RootDir) => {} 187 | _ => { bail!("path must be absolute"); } 188 | } 189 | for c in components { 190 | match c { 191 | path::Component::Normal(x) => { real_path.push(x); } 192 | x => { bail!("illegal component in path: {:?}", x); } 193 | } 194 | } 195 | let data = fs::read(&real_path).context("failed reading file")?; 196 | Ok(data.into()) 197 | } 198 | -------------------------------------------------------------------------------- /src/transport_parameters.rs: -------------------------------------------------------------------------------- 1 | use bytes::{Buf, BufMut}; 2 | 3 | use coding::{BufExt, BufMutExt}; 4 | use {VERSION, Side}; 5 | 6 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] 7 | pub struct TransportParameters { 8 | pub initial_max_stream_data: u32, 9 | pub initial_max_data: u32, 10 | pub idle_timeout: u16, 11 | pub stateless_reset_token: Option<[u8; 16]>, 12 | pub initial_max_streams_bidi: u16, 13 | pub initial_max_streams_uni: u16, 14 | pub max_packet_size: Option, 15 | pub ack_delay_exponent: u8, 16 | } 17 | 18 | const DEFAULT_ACK_DELAY_EXPONENT: u8 = 3; 19 | 20 | impl Default for TransportParameters { 21 | fn default() -> Self { Self { 22 | // TODO: Sanity check all 23 | initial_max_stream_data: 64 * 1024, 24 | initial_max_data: 64 * 1024, 25 | idle_timeout: 10, 26 | stateless_reset_token: None, 27 | initial_max_streams_bidi: 0, 28 | initial_max_streams_uni: 0, 29 | max_packet_size: None, 30 | ack_delay_exponent: DEFAULT_ACK_DELAY_EXPONENT, 31 | }} 32 | } 33 | 34 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Fail)] 35 | pub enum Error { 36 | #[fail(display = "version negotiation was tampered with")] 37 | VersionNegotiation, 38 | #[fail(display = "parameter had illegal value")] 39 | IllegalValue, 40 | #[fail(display = "parameters were malformed")] 41 | Malformed, 42 | } 43 | 44 | impl TransportParameters { 45 | pub fn write(&self, side: Side, w: &mut W) { 46 | if side == Side::Server { 47 | w.write::(VERSION); // Negotiated version 48 | w.write::(8); // Bytes of supported versions 49 | w.write::(0x0a1a2a3a); // Reserved version 50 | w.write::(VERSION); // Real supported version 51 | } else { 52 | w.write::(VERSION); // Initially requested version 53 | } 54 | 55 | let mut buf = Vec::with_capacity(22); 56 | 57 | buf.write::(0x0000); 58 | buf.write::(4); 59 | buf.write::(self.initial_max_stream_data); 60 | 61 | buf.write::(0x0001); 62 | buf.write::(4); 63 | buf.write::(self.initial_max_data); 64 | 65 | buf.write::(0x0003); 66 | buf.write::(2); 67 | buf.write::(self.idle_timeout); 68 | 69 | if let Some(ref x) = self.stateless_reset_token { 70 | buf.write::(0x0006); 71 | buf.write::(16); 72 | buf.put_slice(x); 73 | } 74 | 75 | if self.initial_max_streams_bidi != 0 { 76 | buf.write::(0x0002); 77 | buf.write::(2); 78 | buf.write::(self.initial_max_streams_bidi); 79 | } 80 | 81 | if self.initial_max_streams_uni != 0 { 82 | buf.write::(0x0008); 83 | buf.write::(2); 84 | buf.write::(self.initial_max_streams_uni); 85 | } 86 | 87 | if let Some(x) = self.max_packet_size { 88 | buf.write::(0x0005); 89 | buf.write::(2); 90 | buf.write::(x); 91 | } 92 | 93 | if self.ack_delay_exponent != DEFAULT_ACK_DELAY_EXPONENT { 94 | buf.write::(0x0007); 95 | buf.write::(1); 96 | buf.write::(self.ack_delay_exponent); 97 | } 98 | 99 | w.write::(buf.len() as u16); 100 | w.put_slice(&buf); 101 | } 102 | 103 | pub fn read(side: Side, r: &mut R) -> Result { 104 | if side == Side::Server { 105 | if r.remaining() < 26 { return Err(Error::Malformed); } 106 | // We only support one version, so there is no validation to do here. 107 | r.get::().unwrap(); 108 | } else { 109 | if r.remaining() < 31 { return Err(Error::Malformed); } 110 | let negotiated = r.get::().unwrap(); 111 | if negotiated != VERSION { return Err(Error::VersionNegotiation); } 112 | let supported_bytes = r.get::().unwrap(); 113 | if supported_bytes < 4 || supported_bytes > 252 || supported_bytes % 4 != 0 { 114 | return Err(Error::Malformed); 115 | } 116 | let mut found = false; 117 | for _ in 0..(supported_bytes / 4) { 118 | found |= r.get::().unwrap() == negotiated; 119 | } 120 | if !found { return Err(Error::VersionNegotiation); } 121 | } 122 | 123 | let mut initial_max_stream_data = false; 124 | let mut initial_max_data = false; 125 | let mut idle_timeout = false; 126 | let mut initial_max_streams_bidi = false; 127 | let mut initial_max_streams_uni = false; 128 | let mut ack_delay_exponent = false; 129 | let mut params = Self::default(); 130 | let params_len = r.get::().unwrap(); 131 | if params_len as usize != r.remaining() { return Err(Error::Malformed); } 132 | while r.has_remaining() { 133 | if r.remaining() < 4 { return Err(Error::Malformed); } 134 | let id = r.get::().unwrap(); 135 | let len = r.get::().unwrap(); 136 | if r.remaining() < len as usize { return Err(Error::Malformed); } 137 | match id { 138 | 0x0000 => { 139 | if len != 4 || initial_max_stream_data { return Err(Error::Malformed); } 140 | params.initial_max_stream_data = r.get::().unwrap(); 141 | initial_max_stream_data = true; 142 | } 143 | 0x0001 => { 144 | if len != 4 || initial_max_data { return Err(Error::Malformed); } 145 | params.initial_max_data = r.get::().unwrap(); 146 | initial_max_data = true; 147 | } 148 | 0x0003 => { 149 | if len != 2 || idle_timeout { return Err(Error::Malformed); } 150 | params.idle_timeout = r.get::().unwrap(); 151 | idle_timeout = true; 152 | } 153 | 0x0006 => { 154 | if len != 16 || params.stateless_reset_token.is_some() { return Err(Error::Malformed); } 155 | let mut tok = [0; 16]; 156 | r.copy_to_slice(&mut tok); 157 | params.stateless_reset_token = Some(tok); 158 | } 159 | 0x0002 => { 160 | if len != 2 || initial_max_streams_bidi { return Err(Error::Malformed); } 161 | params.initial_max_streams_bidi = r.get::().unwrap(); 162 | initial_max_streams_bidi = true; 163 | } 164 | 0x0008 => { 165 | if len != 2 || initial_max_streams_uni { return Err(Error::Malformed); } 166 | params.initial_max_streams_uni = r.get::().unwrap(); 167 | initial_max_streams_uni = true; 168 | } 169 | 0x0005 => { 170 | if len != 2 || params.max_packet_size.is_some() { return Err(Error::Malformed); } 171 | params.max_packet_size = Some(r.get::().unwrap()); 172 | } 173 | 0x0007 => { 174 | if len != 1 || ack_delay_exponent { return Err(Error::Malformed); } 175 | params.ack_delay_exponent = r.get::().unwrap(); 176 | ack_delay_exponent = true; 177 | if params.ack_delay_exponent > 20 { return Err(Error::IllegalValue); } 178 | } 179 | _ => r.advance(len as usize), 180 | } 181 | } 182 | 183 | if initial_max_stream_data && initial_max_data && idle_timeout { 184 | Ok(params) 185 | } else { 186 | Err(Error::IllegalValue) 187 | } 188 | } 189 | } 190 | 191 | #[cfg(test)] 192 | mod test { 193 | use super::*; 194 | use bytes::IntoBuf; 195 | 196 | #[test] 197 | fn coding() { 198 | let mut buf = Vec::new(); 199 | let params = TransportParameters { 200 | initial_max_streams_bidi: 16, 201 | initial_max_streams_uni: 16, 202 | ack_delay_exponent: 2, 203 | max_packet_size: Some(1200), 204 | ..TransportParameters::default() 205 | }; 206 | params.write(Side::Client, &mut buf); 207 | assert_eq!(TransportParameters::read(Side::Server, &mut buf.into_buf()).unwrap(), params); 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /src/range_set.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BTreeMap; 2 | use std::collections::Bound::{Included, Excluded}; 3 | use std::collections::btree_map; 4 | use std::ops::Range; 5 | use std::cmp; 6 | 7 | /// A set of u64 values optimized for long runs and random insert/delete/contains 8 | #[derive(Debug, Clone)] 9 | pub struct RangeSet(BTreeMap); 10 | 11 | impl RangeSet { 12 | pub fn new() -> Self { RangeSet(BTreeMap::new()) } 13 | 14 | pub fn contains(&self, x: u64) -> bool { 15 | self.pred(x).map_or(false, |(_, end)| end > x) 16 | } 17 | 18 | pub fn insert_one(&mut self, x: u64) -> bool { 19 | if let Some((start, end)) = self.pred(x) { 20 | if end > x { 21 | // Wholly contained 22 | return false; 23 | } else if end == x { 24 | // Extend existing 25 | self.0.remove(&start); 26 | let mut new_end = x+1; 27 | if let Some((next_start, next_end)) = self.succ(x) { 28 | if next_start == new_end { 29 | self.0.remove(&next_start); 30 | new_end = next_end; 31 | } 32 | } 33 | self.0.insert(start, new_end); 34 | return true; 35 | } 36 | } 37 | let mut new_end = x+1; 38 | if let Some((next_start, next_end)) = self.succ(x) { 39 | if next_start == new_end { 40 | self.0.remove(&next_start); 41 | new_end = next_end; 42 | } 43 | } 44 | self.0.insert(x, new_end); 45 | true 46 | } 47 | 48 | pub fn insert(&mut self, mut x: Range) -> bool { 49 | if let Some((start, end)) = self.pred(x.start) { 50 | if end >= x.end { 51 | // Wholly contained 52 | return false; 53 | } else if end >= x.start { 54 | // Overlaps with pred 55 | self.0.remove(&start); 56 | while let Some((next_start, next_end)) = self.succ(x.start) { 57 | if next_start > x.end { break; } 58 | // ..and succ 59 | self.0.remove(&next_start); 60 | x.end = cmp::max(next_end, x.end); 61 | } 62 | self.0.insert(start, x.end); 63 | return true; 64 | } 65 | } 66 | while let Some((next_start, next_end)) = self.succ(x.start) { 67 | if next_start > x.end { break; } 68 | // Overlaps with succ 69 | self.0.remove(&next_start); 70 | x.end = cmp::max(next_end, x.end); 71 | } 72 | self.0.insert(x.start, x.end); 73 | true 74 | } 75 | 76 | fn pred(&self, x: u64) -> Option<(u64, u64)> { 77 | self.0.range((Included(0), Included(x))).rev().next().map(|(&x, &y)| (x, y)) 78 | } 79 | 80 | fn succ(&self, x: u64) -> Option<(u64, u64)> { 81 | self.0.range((Excluded(x), Included(u64::max_value()))).next().map(|(&x, &y)| (x, y)) 82 | } 83 | 84 | pub fn remove(&mut self, x: Range) -> bool { 85 | let before = if let Some((start, end)) = self.pred(x.start) { 86 | if end > x.start { 87 | self.0.remove(&start); 88 | if start < x.start { 89 | self.0.insert(start, x.start); 90 | } 91 | if end > x.end { 92 | self.0.insert(x.end, end); 93 | } 94 | // Short-circuit if we cannot possibly overlap with another range 95 | if end >= x.end { return true; } 96 | true 97 | } else { false } 98 | } else { false }; 99 | let mut after = false;; 100 | while let Some((start, end)) = self.succ(x.start) { 101 | if start >= x.end { break; } 102 | after = true; 103 | self.0.remove(&start); 104 | if end > x.end { 105 | self.0.insert(x.end, end); 106 | break; 107 | } 108 | }; 109 | before || after 110 | } 111 | 112 | pub fn add(&mut self, other: &RangeSet) { 113 | for (&start, &end) in &other.0 { 114 | self.insert(start..end); 115 | } 116 | } 117 | 118 | pub fn subtract(&mut self, other: &RangeSet) { 119 | for (&start, &end) in &other.0 { 120 | self.remove(start..end); 121 | } 122 | } 123 | 124 | pub fn is_empty(&self) -> bool { self.0.is_empty() } 125 | 126 | pub fn min(&self) -> Option { self.iter().next().map(|x| x.start) } 127 | pub fn max(&self) -> Option { self.iter().rev().next().map(|x| x.end-1) } 128 | 129 | pub fn len(&self) -> usize { self.0.len() } 130 | pub fn iter(&self) -> Iter { Iter(self.0.iter()) } 131 | pub fn elts(&self) -> EltIter { EltIter { inner: self.0.iter(), next: 0, end: 0 } } 132 | 133 | pub fn pop_min(&mut self) -> Option> { 134 | let (&start, &end) = self.0.iter().next()?; 135 | self.0.remove(&start); 136 | Some(start..end) 137 | } 138 | } 139 | 140 | pub struct Iter<'a>(btree_map::Iter<'a, u64, u64>); 141 | 142 | impl<'a> Iterator for Iter<'a> { 143 | type Item = Range; 144 | fn next(&mut self) -> Option> { 145 | let (&start, &end) = self.0.next()?; 146 | Some(start..end) 147 | } 148 | } 149 | 150 | impl<'a> DoubleEndedIterator for Iter<'a> { 151 | fn next_back(&mut self) -> Option> { 152 | let (&start, &end) = self.0.next_back()?; 153 | Some(start..end) 154 | } 155 | } 156 | 157 | impl<'a> IntoIterator for &'a RangeSet { 158 | type Item = Range; 159 | type IntoIter = Iter<'a>; 160 | fn into_iter(self) -> Iter<'a> { self.iter() } 161 | } 162 | 163 | pub struct EltIter<'a> { 164 | inner: btree_map::Iter<'a, u64, u64>, 165 | next: u64, 166 | end: u64, 167 | } 168 | 169 | impl<'a> Iterator for EltIter<'a> { 170 | type Item = u64; 171 | fn next(&mut self) -> Option { 172 | if self.next == self.end { 173 | let (&start, &end) = self.inner.next()?; 174 | self.next = start; 175 | self.end = end; 176 | } 177 | let x = self.next; 178 | self.next += 1; 179 | Some(x) 180 | } 181 | } 182 | 183 | impl<'a> DoubleEndedIterator for EltIter<'a> { 184 | fn next_back(&mut self) -> Option { 185 | if self.next == self.end { 186 | let (&start, &end) = self.inner.next_back()?; 187 | self.next = start; 188 | self.end = end; 189 | } 190 | self.end -= 1; 191 | Some(self.end) 192 | } 193 | } 194 | 195 | #[cfg(test)] 196 | mod tests { 197 | use super::*; 198 | 199 | #[test] 200 | fn merge_and_split() { 201 | let mut set = RangeSet::new(); 202 | assert!(set.insert(0..2)); 203 | assert!(set.insert(2..4)); 204 | assert!(!set.insert(1..3)); 205 | assert_eq!(set.len(), 1); 206 | assert_eq!(&set.elts().collect::>()[..], [0, 1, 2, 3]); 207 | assert!(!set.contains(4)); 208 | assert!(set.remove(2..3)); 209 | assert_eq!(set.len(), 2); 210 | assert!(!set.contains(2)); 211 | assert_eq!(&set.elts().collect::>()[..], [0, 1, 3]); 212 | } 213 | 214 | #[test] 215 | fn double_merge_exact() { 216 | let mut set = RangeSet::new(); 217 | assert!(set.insert(0..2)); 218 | assert!(set.insert(4..6)); 219 | assert_eq!(set.len(), 2); 220 | assert!(set.insert(2..4)); 221 | assert_eq!(set.len(), 1); 222 | assert_eq!(&set.elts().collect::>()[..], [0, 1, 2, 3, 4, 5]); 223 | } 224 | 225 | #[test] 226 | fn single_merge_low() { 227 | let mut set = RangeSet::new(); 228 | assert!(set.insert(0..2)); 229 | assert!(set.insert(4..6)); 230 | assert_eq!(set.len(), 2); 231 | assert!(set.insert(2..3)); 232 | assert_eq!(set.len(), 2); 233 | assert_eq!(&set.elts().collect::>()[..], [0, 1, 2, 4, 5]); 234 | } 235 | 236 | #[test] 237 | fn single_merge_high() { 238 | let mut set = RangeSet::new(); 239 | assert!(set.insert(0..2)); 240 | assert!(set.insert(4..6)); 241 | assert_eq!(set.len(), 2); 242 | assert!(set.insert(3..4)); 243 | assert_eq!(set.len(), 2); 244 | assert_eq!(&set.elts().collect::>()[..], [0, 1, 3, 4, 5]); 245 | } 246 | 247 | #[test] 248 | fn double_merge_wide() { 249 | let mut set = RangeSet::new(); 250 | assert!(set.insert(0..2)); 251 | assert!(set.insert(4..6)); 252 | assert_eq!(set.len(), 2); 253 | assert!(set.insert(1..5)); 254 | assert_eq!(set.len(), 1); 255 | assert_eq!(&set.elts().collect::>()[..], [0, 1, 2, 3, 4, 5]); 256 | } 257 | 258 | #[test] 259 | fn double_remove() { 260 | let mut set = RangeSet::new(); 261 | assert!(set.insert(0..2)); 262 | assert!(set.insert(4..6)); 263 | assert!(set.remove(1..5)); 264 | assert_eq!(set.len(), 2); 265 | assert_eq!(&set.elts().collect::>()[..], [0, 5]); 266 | } 267 | 268 | #[test] 269 | fn insert_multiple() { 270 | let mut set = RangeSet::new(); 271 | assert!(set.insert(0..1)); 272 | assert!(set.insert(2..3)); 273 | assert!(set.insert(4..5)); 274 | assert!(set.insert(0..5)); 275 | assert_eq!(set.len(), 1); 276 | } 277 | 278 | #[test] 279 | fn remove_multiple() { 280 | let mut set = RangeSet::new(); 281 | assert!(set.insert(0..1)); 282 | assert!(set.insert(2..3)); 283 | assert!(set.insert(4..5)); 284 | assert!(set.remove(0..5)); 285 | assert!(set.is_empty()); 286 | } 287 | } 288 | -------------------------------------------------------------------------------- /src/stream.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | 3 | use bytes::Bytes; 4 | 5 | use range_set::RangeSet; 6 | 7 | #[derive(Debug)] 8 | pub enum Stream { 9 | Send(Send), 10 | Recv(Recv), 11 | Both(Send, Recv), 12 | } 13 | 14 | impl Stream { 15 | pub fn new_bi(window: u64) -> Self { Stream::Both(Send::new(), Recv::new(window)) } 16 | 17 | pub fn send(&self) -> Option<&Send> { 18 | match *self { 19 | Stream::Send(ref x) => Some(x), 20 | Stream::Both(ref x, _) => Some(x), 21 | _ => None 22 | } 23 | } 24 | 25 | pub fn recv(&self) -> Option<&Recv> { 26 | match *self { 27 | Stream::Recv(ref x) => Some(x), 28 | Stream::Both(_, ref x) => Some(x), 29 | _ => None 30 | } 31 | } 32 | 33 | pub fn send_mut(&mut self) -> Option<&mut Send> { 34 | match *self { 35 | Stream::Send(ref mut x) => Some(x), 36 | Stream::Both(ref mut x, _) => Some(x), 37 | _ => None 38 | } 39 | } 40 | 41 | pub fn recv_mut(&mut self) -> Option<&mut Recv> { 42 | match *self { 43 | Stream::Recv(ref mut x) => Some(x), 44 | Stream::Both(_, ref mut x) => Some(x), 45 | _ => None 46 | } 47 | } 48 | 49 | /// Safe to free 50 | pub fn is_closed(&self) -> bool { 51 | self.send().map_or(true, |x| x.is_closed()) 52 | && self.recv().map_or(true, |x| x.is_closed()) 53 | } 54 | } 55 | 56 | impl From for Stream { fn from(x: Send) -> Stream { Stream::Send(x) } } 57 | impl From for Stream { fn from(x: Recv) -> Stream { Stream::Recv(x) } } 58 | 59 | #[derive(Debug)] 60 | pub struct Send { 61 | pub offset: u64, 62 | pub max_data: u64, 63 | pub state: SendState, 64 | /// Number of bytes sent but unacked 65 | pub bytes_in_flight: u64, 66 | } 67 | 68 | impl Send { 69 | pub fn new() -> Self { Self { 70 | offset: 0, 71 | max_data: 0, 72 | state: SendState::Ready, 73 | bytes_in_flight: 0, 74 | }} 75 | 76 | /// All data acknowledged and STOP_SENDING error code, if any, processed by application 77 | pub fn is_closed(&self) -> bool { 78 | use self::SendState::*; 79 | match self.state { 80 | DataRecvd | ResetRecvd { stop_reason: None } => true, 81 | _ => false, 82 | } 83 | } 84 | } 85 | 86 | #[derive(Debug)] 87 | pub struct Recv { 88 | pub state: RecvState, 89 | pub recvd: RangeSet, 90 | pub buffered: VecDeque<(Bytes, u64)>, 91 | /// Upper limit dictated by the peer 92 | pub max_data: u64, 93 | /// Whether any unordered reads have been performed, making this stream unusable for ordered reads 94 | pub unordered: bool, 95 | pub assembler: Assembler, 96 | /// Whether the application is aware of this stream yet 97 | pub fresh: bool, 98 | } 99 | 100 | impl Recv { 101 | pub fn new(max_data: u64) -> Self { Self { 102 | state: RecvState::Recv { size: None }, 103 | recvd: RangeSet::new(), 104 | buffered: VecDeque::new(), 105 | max_data, 106 | unordered: false, 107 | assembler: Assembler::new(), 108 | fresh: true, 109 | }} 110 | 111 | /// No more data expected from peer 112 | pub fn is_finished(&self) -> bool { 113 | match self.state { 114 | RecvState::Recv { .. } => false, 115 | _ => true, 116 | } 117 | } 118 | 119 | /// All data read by application 120 | pub fn is_closed(&self) -> bool { 121 | self.state == self::RecvState::Closed 122 | } 123 | 124 | pub fn buffer(&mut self, data: Bytes, offset: u64) { 125 | // TODO: Dedup 126 | self.buffered.push_back((data, offset)); 127 | } 128 | 129 | /// Offset after the largest byte received 130 | pub fn limit(&self) -> u64 { self.recvd.max().map_or(0, |x| x+1) } 131 | 132 | pub fn final_offset(&self) -> Option { 133 | match self.state { 134 | RecvState::Recv { size } => size, 135 | RecvState::ResetRecvd { size, .. } => Some(size), 136 | RecvState::DataRecvd { size } => Some(size), 137 | _ => None, 138 | } 139 | } 140 | } 141 | 142 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] 143 | pub enum SendState { 144 | Ready, DataSent, ResetSent { stop_reason: Option }, DataRecvd, ResetRecvd { stop_reason: Option }, 145 | } 146 | 147 | impl SendState { 148 | pub fn was_reset(&self) -> bool { 149 | use self::SendState::*; 150 | match *self { 151 | ResetSent { .. } | ResetRecvd { .. } => true, 152 | _ => false, 153 | } 154 | } 155 | } 156 | 157 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] 158 | pub enum RecvState { 159 | Recv { size: Option }, 160 | DataRecvd { size: u64 }, ResetRecvd { size: u64, error_code: u16 }, 161 | Closed, 162 | } 163 | 164 | /// Helper to assemble unordered stream frames into an ordered stream 165 | #[derive(Debug)] 166 | pub struct Assembler { 167 | offset: u64, 168 | data: VecDeque, 169 | /// bitmap of data bytes; 0 = written, 1 = not 170 | written: VecDeque, 171 | /// number of bits of written to skip; always < 8 172 | written_offset: u8, 173 | } 174 | 175 | impl Assembler { 176 | pub fn new() -> Self { Self { 177 | offset: 0, 178 | data: VecDeque::new(), 179 | written: VecDeque::new(), 180 | written_offset: 0, 181 | }} 182 | 183 | /// Whether `peek` will return at least one nonempty slice 184 | pub fn blocked(&self) -> bool { 185 | let mask = !0 >> self.written_offset; 186 | self.written.front().map_or(true, |x| x & mask == mask) 187 | } 188 | 189 | pub fn offset(&self) -> u64 { self.offset } 190 | 191 | /// Leading written bytes 192 | fn prefix_len(&self) -> usize { 193 | for i in 0..self.written.len() { 194 | let x = self.written[i]; 195 | if x == 0 || (i == 0 && x << self.written_offset == 0) { continue; } 196 | return (i * 8 + x.leading_zeros() as usize) - self.written_offset as usize; 197 | } 198 | self.written.len() 199 | } 200 | 201 | pub fn read(&mut self, buf: &mut [u8]) -> usize { 202 | let n; 203 | { 204 | let (a, b) = self.data.as_slices(); 205 | let available = self.prefix_len(); 206 | let a_len = a.len().min(available); 207 | let (a, b) = (&a[0..a_len], &b[0..(available - a_len)]); 208 | let a_n = a.len().min(buf.len()); 209 | buf[0..a_n].copy_from_slice(&a[0..a_n]); 210 | let b_n = b.len().min(buf.len().saturating_sub(a.len())); 211 | buf[a_n..(a_n+b_n)].copy_from_slice(&b[0..b_n]); 212 | n = a_n + b_n; 213 | } 214 | 215 | self.offset += n as u64; 216 | self.data.drain(0..n); 217 | let q = n / 8; 218 | let r = n % 8; 219 | let carry = (self.written_offset as usize + r) / 8; 220 | self.written.drain(0..(q + carry)); 221 | self.written_offset = (self.written_offset as usize + r - carry * 8) as u8; 222 | 223 | n 224 | } 225 | 226 | #[cfg(test)] 227 | fn next(&mut self) -> Option> { 228 | let mut buf = Vec::new(); 229 | buf.resize(self.prefix_len(), 0); 230 | self.read(&mut buf); 231 | if !buf.is_empty() { Some(buf.into()) } else { None } 232 | } 233 | 234 | pub fn insert(&mut self, mut offset: u64, mut data: &[u8]) { 235 | if let Some(advance) = self.offset.checked_sub(offset) { 236 | if advance >= data.len() as u64 { return; } 237 | data = &data[advance as usize..]; 238 | offset += advance; 239 | } 240 | let start = (offset - self.offset) as usize; 241 | let end = start + data.len(); 242 | if end > self.data.len() { 243 | self.data.resize(end, 0); 244 | // 1 extra to leave room for written_extra 245 | self.written.resize(end/8 + (end % 8 != 0) as usize + 1, !0); 246 | } 247 | for i in 0..data.len() { 248 | let position = start + i; 249 | self.data[position] = data[i]; 250 | let bit = self.written_offset as usize + position; 251 | self.written[bit / 8] &= !(1 << (7 - bit % 8)); 252 | } 253 | } 254 | } 255 | 256 | #[cfg(test)] 257 | mod test { 258 | use super::*; 259 | 260 | #[test] 261 | fn assemble_ordered() { 262 | let mut x = Assembler::new(); 263 | assert_matches!(x.next(), None); 264 | x.insert(0, (&b"123"[..]).into()); 265 | assert_matches!(x.next(), Some(ref y) if &y[..] == b"123"); 266 | x.insert(3, (&b"456"[..]).into()); 267 | assert_matches!(x.next(), Some(ref y) if &y[..] == b"456"); 268 | x.insert(6, (&b"789"[..]).into()); 269 | x.insert(9, (&b"10"[..]).into()); 270 | assert_matches!(x.next(), Some(ref y) if &y[..] == b"78910"); 271 | assert_matches!(x.next(), None); 272 | } 273 | 274 | #[test] 275 | fn assemble_unordered() { 276 | let mut x = Assembler::new(); 277 | x.insert(3, (&b"456"[..]).into()); 278 | assert_matches!(x.next(), None); 279 | x.insert(0, (&b"123"[..]).into()); 280 | assert_matches!(x.next(), Some(ref y) if &y[..] == b"123456"); 281 | assert_matches!(x.next(), None); 282 | } 283 | 284 | #[test] 285 | fn assemble_duplicate() { 286 | let mut x = Assembler::new(); 287 | x.insert(0, (&b"123"[..]).into()); 288 | x.insert(0, (&b"123"[..]).into()); 289 | assert_matches!(x.next(), Some(ref y) if &y[..] == b"123"); 290 | assert_matches!(x.next(), None); 291 | } 292 | 293 | #[test] 294 | fn assemble_contained() { 295 | let mut x = Assembler::new(); 296 | x.insert(0, (&b"12345"[..]).into()); 297 | x.insert(1, (&b"234"[..]).into()); 298 | assert_matches!(x.next(), Some(ref y) if &y[..] == b"12345"); 299 | assert_matches!(x.next(), None); 300 | } 301 | 302 | #[test] 303 | fn assemble_contains() { 304 | let mut x = Assembler::new(); 305 | x.insert(1, (&b"234"[..]).into()); 306 | x.insert(0, (&b"12345"[..]).into()); 307 | assert_matches!(x.next(), Some(ref y) if &y[..] == b"12345"); 308 | assert_matches!(x.next(), None); 309 | } 310 | 311 | #[test] 312 | fn assemble_overlapping() { 313 | let mut x = Assembler::new(); 314 | x.insert(0, (&b"123"[..]).into()); 315 | x.insert(1, (&b"234"[..]).into()); 316 | assert_matches!(x.next(), Some(ref y) if &y[..] == b"1234"); 317 | assert_matches!(x.next(), None); 318 | } 319 | 320 | #[test] 321 | fn assemble_complex() { 322 | let mut x = Assembler::new(); 323 | x.insert(0, (&b"1"[..]).into()); 324 | x.insert(2, (&b"3"[..]).into()); 325 | x.insert(4, (&b"5"[..]).into()); 326 | x.insert(0, (&b"123456"[..]).into()); 327 | assert_matches!(x.next(), Some(ref y) if &y[..] == b"123456"); 328 | assert_matches!(x.next(), None); 329 | } 330 | 331 | #[test] 332 | fn assemble_old() { 333 | let mut x = Assembler::new(); 334 | x.insert(0, b"1234"); 335 | assert_matches!(x.next(), Some(ref y) if &y[..] == b"1234"); 336 | x.insert(0, b"1234"); 337 | assert_matches!(x.next(), None); 338 | } 339 | } 340 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/frame.rs: -------------------------------------------------------------------------------- 1 | use std::{mem, fmt, io}; 2 | use std::ops::Range; 3 | 4 | use bytes::{Bytes, Buf, BufMut}; 5 | 6 | use {varint, TransportError, StreamId, ConnectionId, MIN_CID_SIZE, MAX_CID_SIZE, RESET_TOKEN_SIZE}; 7 | use range_set::RangeSet; 8 | use coding::{self, BufExt, BufMutExt, UnexpectedEnd}; 9 | 10 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] 11 | pub struct Type(u8); 12 | 13 | impl From for Type { fn from(x: u8) -> Self { Type(x) } } 14 | impl From for u8 { fn from(x: Type) -> Self { x.0 } } 15 | 16 | impl Type { 17 | fn stream(&self) -> Option { 18 | if self.0 >= 0x10 && self.0 <= 0x17 { Some(StreamInfo(self.0)) } else { None } 19 | } 20 | } 21 | 22 | impl coding::Value for Type { 23 | fn decode(buf: &mut B) -> coding::Result { 24 | Ok(Type(buf.get()?)) 25 | } 26 | fn encode(&self, buf: &mut B) { 27 | self.0.encode(buf); 28 | } 29 | } 30 | 31 | macro_rules! frame_types { 32 | {$($name:ident = $val:expr,)*} => { 33 | impl Type { 34 | $(pub const $name: Type = Type($val);)* 35 | } 36 | 37 | impl fmt::Display for Type { 38 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 39 | match self.0 { 40 | $($val => f.write_str(stringify!($name)),)* 41 | x if x >= 0x10 && x <= 0x17 => f.write_str("STREAM"), 42 | _ => write!(f, "", self.0), 43 | } 44 | } 45 | } 46 | } 47 | } 48 | 49 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] 50 | struct StreamInfo(u8); 51 | 52 | impl StreamInfo { 53 | fn fin(&self) -> bool { self.0 & 0x01 != 0 } 54 | fn len(&self) -> bool { self.0 & 0x02 != 0 } 55 | fn off(&self) -> bool { self.0 & 0x04 != 0 } 56 | } 57 | 58 | frame_types!{ 59 | PADDING = 0x00, 60 | RST_STREAM = 0x01, 61 | CONNECTION_CLOSE = 0x02, 62 | APPLICATION_CLOSE = 0x03, 63 | MAX_DATA = 0x04, 64 | MAX_STREAM_DATA = 0x05, 65 | MAX_STREAM_ID = 0x06, 66 | PING = 0x07, 67 | BLOCKED = 0x08, 68 | STREAM_BLOCKED = 0x09, 69 | STREAM_ID_BLOCKED = 0x0a, 70 | NEW_CONNECTION_ID = 0x0b, 71 | STOP_SENDING = 0x0c, 72 | ACK = 0x0d, 73 | PATH_CHALLENGE = 0x0e, 74 | PATH_RESPONSE = 0x0f, 75 | } 76 | 77 | #[derive(Debug)] 78 | pub enum Frame { 79 | Padding, 80 | RstStream(RstStream), 81 | ConnectionClose(ConnectionClose), 82 | ApplicationClose(ApplicationClose), 83 | MaxData(u64), 84 | MaxStreamData { 85 | id: StreamId, 86 | offset: u64, 87 | }, 88 | MaxStreamId(StreamId), 89 | Ping, 90 | Blocked { 91 | offset: u64, 92 | }, 93 | StreamBlocked { 94 | id: StreamId, 95 | offset: u64, 96 | }, 97 | StreamIdBlocked { 98 | id: StreamId, 99 | }, 100 | StopSending { 101 | id: StreamId, 102 | error_code: u16, 103 | }, 104 | Ack(Ack), 105 | Stream(Stream), 106 | PathChallenge(u64), 107 | PathResponse(u64), 108 | NewConnectionId { 109 | sequence: u64, 110 | id: ConnectionId, 111 | reset_token: [u8; 16], 112 | }, 113 | Invalid(Type), 114 | } 115 | 116 | impl Frame { 117 | pub fn ty(&self) -> Type { 118 | use self::Frame::*; 119 | match *self { 120 | Padding => Type::PADDING, 121 | RstStream(_) => Type::RST_STREAM, 122 | ConnectionClose(_) => Type::CONNECTION_CLOSE, 123 | ApplicationClose(_) => Type::APPLICATION_CLOSE, 124 | MaxData(_) => Type::MAX_DATA, 125 | MaxStreamData { .. } => Type::MAX_STREAM_DATA, 126 | MaxStreamId(_) => Type::MAX_STREAM_ID, 127 | Ping => Type::PING, 128 | Blocked { .. } => Type::BLOCKED, 129 | StreamBlocked { .. } => Type::STREAM_BLOCKED, 130 | StreamIdBlocked { .. } => Type::STREAM_ID_BLOCKED, 131 | StopSending { .. } => Type::STOP_SENDING, 132 | Ack(_) => Type::ACK, 133 | Stream(ref x) => { 134 | let mut ty = 0x10; 135 | if x.fin { ty |= 0x01; } 136 | if x.offset != 0 { ty |= 0x04; } 137 | Type(ty) 138 | } 139 | PathChallenge(_) => Type::PATH_CHALLENGE, 140 | PathResponse(_) => Type::PATH_RESPONSE, 141 | NewConnectionId { .. } => Type::NEW_CONNECTION_ID, 142 | Invalid(ty) => ty, 143 | } 144 | } 145 | } 146 | 147 | #[derive(Debug, Clone)] 148 | pub struct ConnectionClose { 149 | pub error_code: TransportError, 150 | pub reason: T, 151 | } 152 | 153 | impl fmt::Display for ConnectionClose 154 | where T: AsRef<[u8]> 155 | { 156 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 157 | self.error_code.fmt(f)?; 158 | if !self.reason.as_ref().is_empty() { 159 | f.write_str(": ")?; 160 | f.write_str(&String::from_utf8_lossy(self.reason.as_ref()))?; 161 | } 162 | Ok(()) 163 | } 164 | } 165 | 166 | impl From for ConnectionClose { 167 | fn from(x: TransportError) -> Self { ConnectionClose { error_code: x, reason: Bytes::new() } } 168 | } 169 | 170 | impl ConnectionClose 171 | where T: AsRef<[u8]> 172 | { 173 | pub fn encode(&self, out: &mut W, max_len: u16) { 174 | out.write(Type::CONNECTION_CLOSE); 175 | out.write(self.error_code); 176 | let max_len = max_len as usize - 3 - varint::size(self.reason.as_ref().len() as u64).unwrap(); 177 | let actual_len = self.reason.as_ref().len().min(max_len); 178 | varint::write(actual_len as u64, out).unwrap(); 179 | out.put_slice(&self.reason.as_ref()[0..actual_len]); 180 | } 181 | } 182 | 183 | #[derive(Debug, Clone)] 184 | pub struct ApplicationClose { 185 | pub error_code: u16, 186 | pub reason: T, 187 | } 188 | 189 | impl fmt::Display for ApplicationClose 190 | where T: AsRef<[u8]> 191 | { 192 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 193 | if !self.reason.as_ref().is_empty() { 194 | f.write_str(&String::from_utf8_lossy(self.reason.as_ref()))?; 195 | f.write_str(" (code ")?; 196 | self.error_code.fmt(f)?; 197 | f.write_str(")")?; 198 | } else { 199 | self.error_code.fmt(f)?; 200 | } 201 | Ok(()) 202 | } 203 | } 204 | 205 | impl ApplicationClose 206 | where T: AsRef<[u8]> 207 | { 208 | pub fn encode(&self, out: &mut W, max_len: u16) { 209 | out.write(Type::APPLICATION_CLOSE); 210 | out.write(self.error_code); 211 | let max_len = max_len as usize - 3 - varint::size(self.reason.as_ref().len() as u64).unwrap(); 212 | let actual_len = self.reason.as_ref().len().min(max_len); 213 | varint::write(actual_len as u64, out).unwrap(); 214 | out.put_slice(&self.reason.as_ref()[0..actual_len]); 215 | } 216 | } 217 | 218 | #[derive(Debug, Clone, Eq, PartialEq)] 219 | pub struct Ack { 220 | pub largest: u64, 221 | pub delay: u64, 222 | pub additional: Bytes, 223 | } 224 | 225 | impl<'a> IntoIterator for &'a Ack { 226 | type Item = Range; 227 | type IntoIter = AckIter<'a>; 228 | 229 | fn into_iter(self) -> AckIter<'a> { 230 | AckIter::new(self.largest, &self.additional[..]) 231 | } 232 | } 233 | 234 | impl Ack { 235 | pub fn encode(delay: u64, ranges: &RangeSet, buf: &mut W) { 236 | let mut rest = ranges.iter().rev(); 237 | let first = rest.next().unwrap(); 238 | let largest = first.end - 1; 239 | let first_size = first.end - first.start; 240 | buf.write(Type::ACK); 241 | varint::write(largest, buf).unwrap(); 242 | varint::write(delay, buf).unwrap(); 243 | varint::write(ranges.len() as u64 - 1, buf).unwrap(); 244 | varint::write(first_size-1, buf).unwrap(); 245 | let mut prev = first.start; 246 | for block in rest { 247 | let size = block.end - block.start; 248 | varint::write(prev - block.end - 1, buf).unwrap(); 249 | varint::write(size - 1, buf).unwrap(); 250 | prev = block.start; 251 | } 252 | } 253 | 254 | pub fn iter(&self) -> AckIter { self.into_iter() } 255 | } 256 | 257 | #[derive(Debug, Clone)] 258 | pub struct Stream { 259 | pub id: StreamId, 260 | pub offset: u64, 261 | pub fin: bool, 262 | pub data: T, 263 | } 264 | 265 | impl Stream 266 | where T: AsRef<[u8]> 267 | { 268 | pub fn encode(&self, length: bool, out: &mut W) { 269 | let mut ty = 0x10; 270 | if self.offset != 0 { ty |= 0x04; } 271 | if length { ty |= 0x02; } 272 | if self.fin { ty |= 0x01; } 273 | out.put_u8(ty); 274 | varint::write(self.id.0, out).unwrap(); 275 | if self.offset != 0 { varint::write(self.offset, out).unwrap(); } 276 | if length { varint::write(self.data.as_ref().len() as u64, out).unwrap(); } 277 | out.put_slice(self.data.as_ref()); 278 | } 279 | } 280 | 281 | pub struct Iter { 282 | // TODO: ditch io::Cursor after bytes 0.5 283 | bytes: io::Cursor, 284 | last_ty: Option, 285 | } 286 | 287 | enum IterErr { 288 | UnexpectedEnd, 289 | InvalidFrameId, 290 | Malformed, 291 | } 292 | 293 | impl From for IterErr { fn from(_: UnexpectedEnd) -> Self { IterErr::UnexpectedEnd } } 294 | 295 | impl Iter { 296 | pub fn new(payload: Bytes) -> Self { Iter { bytes: io::Cursor::new(payload), last_ty: None } } 297 | 298 | fn take_len(&mut self) -> Result { 299 | let len = self.bytes.get_var()?; 300 | if len > self.bytes.remaining() as u64 { return Err(UnexpectedEnd); } 301 | let start = self.bytes.position() as usize; 302 | self.bytes.advance(len as usize); 303 | Ok(self.bytes.get_ref().slice(start, start + len as usize)) 304 | } 305 | 306 | fn try_next(&mut self) -> Result { 307 | let ty = self.bytes.get::()?; 308 | self.last_ty = Some(ty); 309 | Ok(match ty { 310 | Type::PADDING => Frame::Padding, 311 | Type::RST_STREAM => Frame::RstStream(RstStream { 312 | id: self.bytes.get()?, 313 | error_code: self.bytes.get()?, 314 | final_offset: self.bytes.get_var()?, 315 | }), 316 | Type::CONNECTION_CLOSE => Frame::ConnectionClose(ConnectionClose { 317 | error_code: self.bytes.get()?, 318 | reason: self.take_len()?, 319 | }), 320 | Type::APPLICATION_CLOSE => Frame::ApplicationClose(ApplicationClose { 321 | error_code: self.bytes.get()?, 322 | reason: self.take_len()?, 323 | }), 324 | Type::MAX_DATA => Frame::MaxData(self.bytes.get_var()?), 325 | Type::MAX_STREAM_DATA => Frame::MaxStreamData { 326 | id: self.bytes.get()?, 327 | offset: self.bytes.get_var()?, 328 | }, 329 | Type::MAX_STREAM_ID => Frame::MaxStreamId(self.bytes.get()?), 330 | Type::PING => Frame::Ping, 331 | Type::BLOCKED => Frame::Blocked { 332 | offset: self.bytes.get_var()?, 333 | }, 334 | Type::STREAM_BLOCKED => Frame::StreamBlocked { 335 | id: self.bytes.get()?, 336 | offset: self.bytes.get_var()?, 337 | }, 338 | Type::STREAM_ID_BLOCKED => Frame::StreamIdBlocked { 339 | id: self.bytes.get()?, 340 | }, 341 | Type::STOP_SENDING => Frame::StopSending { 342 | id: self.bytes.get()?, 343 | error_code: self.bytes.get()?, 344 | }, 345 | Type::ACK => { 346 | let largest = self.bytes.get_var()?; 347 | let delay = self.bytes.get_var()?; 348 | let extra_blocks = self.bytes.get_var()? as usize; 349 | let start = self.bytes.position() as usize; 350 | let len = scan_ack_blocks(&self.bytes.bytes()[..], largest, extra_blocks).ok_or(UnexpectedEnd)?; 351 | self.bytes.advance(len); 352 | Frame::Ack(Ack { 353 | delay, largest, 354 | additional: self.bytes.get_ref().slice(start, start + len), 355 | }) 356 | } 357 | Type::PATH_CHALLENGE => Frame::PathChallenge(self.bytes.get()?), 358 | Type::PATH_RESPONSE => Frame::PathResponse(self.bytes.get()?), 359 | Type::NEW_CONNECTION_ID => { 360 | let sequence = self.bytes.get_var()?; 361 | let length = self.bytes.get::()? as usize; 362 | if length < MIN_CID_SIZE || length > MAX_CID_SIZE { return Err(IterErr::Malformed); } 363 | if length > self.bytes.remaining() { return Err(IterErr::UnexpectedEnd); } 364 | let mut stage = [0; MAX_CID_SIZE]; 365 | self.bytes.copy_to_slice(&mut stage[0..length]); 366 | let id = ConnectionId::new(stage, length); 367 | if self.bytes.remaining() < 16 { return Err(IterErr::UnexpectedEnd); } 368 | let mut reset_token = [0; RESET_TOKEN_SIZE]; 369 | self.bytes.copy_to_slice(&mut reset_token); 370 | Frame::NewConnectionId { 371 | sequence, id, reset_token 372 | } 373 | } 374 | _ => match ty.stream() { 375 | Some(s) => Frame::Stream(Stream { 376 | id: self.bytes.get()?, 377 | offset: if s.off() { self.bytes.get_var()? } else { 0 }, 378 | fin: s.fin(), 379 | data: if s.len() { self.take_len()? } else { 380 | let mut x = mem::replace(self.bytes.get_mut(), Bytes::new()); 381 | x.advance(self.bytes.position() as usize); 382 | self.bytes.set_position(0); 383 | x 384 | } 385 | }), 386 | None => { return Err(IterErr::InvalidFrameId); } 387 | } 388 | }) 389 | } 390 | } 391 | 392 | impl Iterator for Iter { 393 | type Item = Frame; 394 | fn next(&mut self) -> Option { 395 | if !self.bytes.has_remaining() { return None; } 396 | match self.try_next() { 397 | Ok(x) => Some(x), 398 | Err(_) => { 399 | // Corrupt frame, skip it and everything that follows 400 | self.bytes = io::Cursor::new(Bytes::new()); 401 | Some(Frame::Invalid(self.last_ty.unwrap())) 402 | } 403 | } 404 | } 405 | } 406 | 407 | fn scan_ack_blocks(packet: &[u8], largest: u64, n: usize) -> Option { 408 | let mut buf = io::Cursor::new(packet); 409 | let first_block = varint::read(&mut buf)?; 410 | let mut smallest = largest.checked_sub(first_block)?; 411 | for _ in 0..n { 412 | let gap = varint::read(&mut buf)?; 413 | smallest = smallest.checked_sub(gap + 2)?; 414 | let block = varint::read(&mut buf)?; 415 | smallest = smallest.checked_sub(block)?; 416 | } 417 | Some(buf.position() as usize) 418 | } 419 | 420 | #[derive(Debug, Clone)] 421 | pub struct AckIter<'a> { 422 | largest: u64, 423 | data: io::Cursor<&'a [u8]>, 424 | } 425 | 426 | impl<'a> AckIter<'a> { 427 | fn new(largest: u64, payload: &'a [u8]) -> Self { 428 | let data = io::Cursor::new(payload); 429 | Self { largest, data } 430 | } 431 | } 432 | 433 | impl<'a> Iterator for AckIter<'a> { 434 | type Item = Range; 435 | fn next(&mut self) -> Option> { 436 | if !self.data.has_remaining() { return None; } 437 | let block = varint::read(&mut self.data).unwrap(); 438 | let largest = self.largest; 439 | if let Some(gap) = varint::read(&mut self.data) { 440 | self.largest -= block + gap + 2; 441 | } 442 | Some(largest - block .. largest + 1) 443 | } 444 | } 445 | 446 | #[derive(Debug, Copy, Clone)] 447 | pub struct RstStream { 448 | pub id: StreamId, 449 | pub error_code: u16, 450 | pub final_offset: u64, 451 | } 452 | 453 | impl RstStream { 454 | pub fn encode(&self, out: &mut W) { 455 | out.write(Type::RST_STREAM); 456 | varint::write(self.id.0, out).unwrap(); 457 | out.write(self.error_code); 458 | varint::write(self.final_offset, out).unwrap(); 459 | } 460 | } 461 | 462 | #[cfg(test)] 463 | mod test { 464 | use super::*; 465 | 466 | #[test] 467 | fn ack_coding() { 468 | const PACKETS: &[u64] = &[1, 2, 3, 5, 10, 11, 14]; 469 | let mut ranges = RangeSet::new(); 470 | for &packet in PACKETS { ranges.insert(packet..packet+1); } 471 | let mut buf = Vec::new(); 472 | Ack::encode(42, &ranges, &mut buf); 473 | let frames = Iter::new(Bytes::from(buf)).collect::>(); 474 | match frames[0] { 475 | Frame::Ack(ref ack) => { 476 | let mut packets = ack.iter().flat_map(|x| x).collect::>(); 477 | packets.sort_unstable(); 478 | assert_eq!(&packets[..], PACKETS); 479 | } 480 | ref x => { panic!("incorrect frame {:?}", x) } 481 | } 482 | } 483 | } 484 | -------------------------------------------------------------------------------- /tests/tests.rs: -------------------------------------------------------------------------------- 1 | extern crate quicr_core as quicr; 2 | extern crate openssl; 3 | extern crate rand; 4 | #[macro_use] 5 | extern crate slog; 6 | #[macro_use] 7 | extern crate assert_matches; 8 | #[macro_use] 9 | extern crate lazy_static; 10 | extern crate bytes; 11 | #[macro_use] 12 | extern crate hex_literal; 13 | extern crate byteorder; 14 | 15 | use std::net::SocketAddrV6; 16 | use std::{fmt, str}; 17 | use std::io::{self, Write}; 18 | use std::collections::VecDeque; 19 | 20 | use openssl::pkey::{PKey, Private}; 21 | use openssl::rsa::Rsa; 22 | use openssl::x509::X509; 23 | use openssl::asn1::Asn1Time; 24 | use slog::{Logger, Drain, KV}; 25 | use byteorder::{ByteOrder, BigEndian}; 26 | 27 | use quicr::*; 28 | 29 | struct TestDrain; 30 | 31 | impl Drain for TestDrain { 32 | type Ok = (); 33 | type Err = io::Error; 34 | fn log(&self, record: &slog::Record, values: &slog::OwnedKVList) -> Result<(), io::Error> { 35 | let mut vals = Vec::new(); 36 | values.serialize(&record, &mut TestSerializer(&mut vals))?; 37 | record.kv().serialize(&record, &mut TestSerializer(&mut vals))?; 38 | println!("{} {}{}", record.level(), record.msg(), str::from_utf8(&vals).unwrap()); 39 | Ok(()) 40 | } 41 | } 42 | 43 | struct TestSerializer<'a, W: 'a>(&'a mut W); 44 | impl<'a, W> slog::Serializer for TestSerializer<'a, W> 45 | where W: Write + 'a 46 | { 47 | fn emit_arguments(&mut self, key: slog::Key, val: &fmt::Arguments) -> slog::Result { 48 | write!(self.0, ", {}: {}", key, val).unwrap(); 49 | Ok(()) 50 | } 51 | } 52 | 53 | fn logger() -> Logger { 54 | Logger::root(TestDrain.fuse(), o!()) 55 | } 56 | 57 | lazy_static! { 58 | static ref KEY: PKey = PKey::from_rsa(Rsa::generate(2048).unwrap()).unwrap(); 59 | static ref CERT: X509 = { 60 | let mut cert = X509::builder().unwrap(); 61 | cert.set_pubkey(&KEY).unwrap(); 62 | cert.set_not_before(&Asn1Time::days_from_now(0).unwrap()).unwrap(); 63 | cert.set_not_after(&Asn1Time::days_from_now(u32::max_value()).unwrap()).unwrap(); 64 | cert.sign(&KEY, openssl::hash::MessageDigest::sha256()).unwrap(); 65 | cert.build() 66 | }; 67 | static ref LISTEN_KEYS: ListenKeys = ListenKeys::new(&mut rand::thread_rng()); 68 | } 69 | 70 | struct Pair { 71 | log: Logger, 72 | server: TestEndpoint, 73 | client: TestEndpoint, 74 | time: u64, 75 | // One-way 76 | latency: u64, 77 | } 78 | 79 | impl Default for Pair { 80 | fn default() -> Self { 81 | Pair::new(Config { max_remote_uni_streams: 32, max_remote_bi_streams: 32, ..Config::default() }, 82 | Config::default()) 83 | } 84 | } 85 | 86 | impl Pair { 87 | fn new(server_config: Config, client_config: Config) -> Self { 88 | let log = logger(); 89 | let server_addr = "[::1]:42".parse().unwrap(); 90 | let server = Endpoint::new( 91 | log.new(o!("side" => "Server")), 92 | server_config, 93 | Some(CertConfig { 94 | private_key: &KEY, 95 | cert: &CERT, 96 | }), 97 | Some(*LISTEN_KEYS)).unwrap(); 98 | let client_addr = "[::2]:7890".parse().unwrap(); 99 | let client = Endpoint::new(log.new(o!("side" => "Client")), client_config, None, None).unwrap(); 100 | 101 | Self { 102 | log, 103 | server: TestEndpoint::new(Side::Server, server, server_addr), 104 | client: TestEndpoint::new(Side::Client, client, client_addr), 105 | time: 0, 106 | latency: 0, 107 | } 108 | } 109 | 110 | /// Returns whether the connection is not idle 111 | fn step(&mut self) -> bool { 112 | self.drive_client(); 113 | self.drive_server(); 114 | let client_t = self.client.next_wakeup(); 115 | let server_t = self.server.next_wakeup(); 116 | if client_t == self.client.idle && server_t == self.server.idle { return false; } 117 | if client_t < server_t { 118 | if client_t != self.time { 119 | self.time = self.time.max(client_t); 120 | trace!(self.log, "advancing to {time} for client", time=self.time); 121 | } 122 | } else { 123 | if server_t != self.time { 124 | self.time = self.time.max(server_t); 125 | trace!(self.log, "advancing to {time} for server", time=self.time); 126 | } 127 | } 128 | true 129 | } 130 | 131 | /// Advance time until both connections are idle 132 | fn drive(&mut self) { while self.step() {} } 133 | 134 | fn drive_client(&mut self) { 135 | trace!(self.log, "client running"); 136 | self.client.drive(&self.log, self.time, self.server.addr); 137 | for packet in self.client.outbound.drain(..) { 138 | self.server.inbound.push_back((self.time + self.latency, packet)); 139 | } 140 | } 141 | 142 | fn drive_server(&mut self) { 143 | trace!(self.log, "server running"); 144 | self.server.drive(&self.log, self.time, self.client.addr); 145 | for packet in self.server.outbound.drain(..) { 146 | self.client.inbound.push_back((self.time + self.latency, packet)); 147 | } 148 | } 149 | 150 | fn connect(&mut self) -> (ConnectionHandle, ConnectionHandle) { 151 | info!(self.log, "connecting"); 152 | let client_conn = self.client.connect(self.server.addr, ClientConfig { 153 | accept_insecure_certs: true, 154 | ..ClientConfig::default() 155 | }).unwrap(); 156 | self.drive(); 157 | let server_conn = if let Some(c) = self.server.accept() { c } else { panic!("server didn't connect"); }; 158 | assert_matches!(self.client.poll(), Some((conn, Event::Connected { .. })) if conn == client_conn); 159 | (client_conn, server_conn) 160 | } 161 | } 162 | 163 | struct TestEndpoint { 164 | side: Side, 165 | endpoint: Endpoint, 166 | addr: SocketAddrV6, 167 | idle: u64, 168 | loss: u64, 169 | close: u64, 170 | conn: Option, 171 | outbound: VecDeque>, 172 | inbound: VecDeque<(u64, Box<[u8]>)>, 173 | } 174 | 175 | impl TestEndpoint { 176 | fn new(side: Side, endpoint: Endpoint, addr: SocketAddrV6) -> Self { Self { 177 | side, endpoint, addr, 178 | idle: u64::max_value(), 179 | loss: u64::max_value(), 180 | close: u64::max_value(), 181 | conn: None, 182 | outbound: VecDeque::new(), 183 | inbound: VecDeque::new(), 184 | }} 185 | 186 | fn drive(&mut self, log: &Logger, now: u64, remote: SocketAddrV6) { 187 | if let Some(conn) = self.conn { 188 | if self.loss <= now { 189 | trace!(log, "{side:?} {timer:?} timeout", side=self.side, timer=Timer::LossDetection); 190 | self.loss = u64::max_value(); 191 | self.endpoint.timeout(now, conn, Timer::LossDetection); 192 | } 193 | if self.idle <= now { 194 | trace!(log, "{side:?} {timer:?} timeout", side=self.side, timer=Timer::Idle); 195 | self.idle = u64::max_value(); 196 | self.endpoint.timeout(now, conn, Timer::Idle); 197 | } 198 | if self.close <= now { 199 | trace!(log, "{side:?} {timer:?} timeout", side=self.side, timer=Timer::Close); 200 | self.close = u64::max_value(); 201 | self.endpoint.timeout(now, conn, Timer::Close); 202 | } 203 | } 204 | while self.inbound.front().map_or(false, |x| x.0 <= now) { 205 | self.endpoint.handle(now, remote, Vec::from(self.inbound.pop_front().unwrap().1).into()); 206 | } 207 | while let Some(x) = self.endpoint.poll_io(now) { match x { 208 | Io::Transmit { packet, .. } => { 209 | self.outbound.push_back(packet); 210 | } 211 | Io::TimerStart { timer, time, connection } => { 212 | self.conn = Some(connection); 213 | trace!(log, "{side:?} {timer:?} start: {dt}", side=self.side, timer=timer, dt=(time - now)); 214 | match timer { 215 | Timer::LossDetection => { self.loss = time; } 216 | Timer::Idle => { self.idle = time; } 217 | Timer::Close => { self.close = time; } 218 | } 219 | } 220 | Io::TimerStop { timer, .. } => { 221 | trace!(log, "{side:?} {timer:?} stop", side=self.side, timer=timer); 222 | match timer { 223 | Timer::LossDetection => { self.loss = u64::max_value(); } 224 | Timer::Idle => { self.idle = u64::max_value(); } 225 | Timer::Close => { self.close = u64::max_value(); } 226 | } 227 | } 228 | }} 229 | } 230 | 231 | fn next_wakeup(&self) -> u64 { 232 | self.idle.min(self.loss).min(self.close).min(self.inbound.front().map_or(u64::max_value(), |x| x.0)) 233 | } 234 | } 235 | 236 | impl ::std::ops::Deref for TestEndpoint { 237 | type Target = Endpoint; 238 | fn deref(&self) -> &Endpoint { &self.endpoint } 239 | } 240 | 241 | impl ::std::ops::DerefMut for TestEndpoint { 242 | fn deref_mut(&mut self) -> &mut Endpoint { &mut self.endpoint } 243 | } 244 | 245 | #[test] 246 | fn version_negotiate() { 247 | let log = logger(); 248 | let client_addr = "[::2]:7890".parse().unwrap(); 249 | let mut server = Endpoint::new( 250 | log.new(o!("peer" => "server")), 251 | Config::default(), 252 | Some(CertConfig { 253 | private_key: &KEY, 254 | cert: &CERT, 255 | }), 256 | Some(*LISTEN_KEYS)).unwrap(); 257 | server.handle(0, client_addr, 258 | // Long-header packet with reserved version number 259 | hex!("80 0a1a2a3a 260 | 11 00000000 00000000 261 | 00")[..].into()); 262 | let io = server.poll_io(0); 263 | assert_matches!(io, Some(Io::Transmit { .. })); 264 | if let Some(Io::Transmit { packet, .. }) = io { 265 | assert!(packet[0] | 0x80 != 0); 266 | assert!(&packet[1..14] == hex!("00000000 11 00000000 00000000")); 267 | assert!(packet[14..].chunks(4).any(|x| BigEndian::read_u32(x) == VERSION)); 268 | } 269 | assert_matches!(server.poll_io(0), None); 270 | assert_matches!(server.poll(), None); 271 | } 272 | 273 | #[test] 274 | fn lifecycle() { 275 | let mut pair = Pair::default(); 276 | let (client_conn, _) = pair.connect(); 277 | assert_matches!(pair.client.poll(), Some((conn, Event::NewSessionTicket { .. })) if conn == client_conn); 278 | 279 | const REASON: &[u8] = b"whee"; 280 | info!(pair.log, "closing"); 281 | pair.client.close(pair.time, client_conn, 42, REASON.into()); 282 | pair.drive(); 283 | assert_matches!(pair.server.poll(), 284 | Some((_, Event::ConnectionLost { reason: ConnectionError::ApplicationClosed { 285 | reason: ApplicationClose { error_code: 42, ref reason } 286 | }})) if reason == REASON); 287 | assert_matches!(pair.client.poll(), Some((conn, Event::NewSessionTicket { .. })) if conn == client_conn); 288 | assert_matches!(pair.client.poll(), Some((conn, Event::ConnectionDrained)) if conn == client_conn); 289 | } 290 | 291 | #[test] 292 | fn stateless_retry() { 293 | let mut pair = Pair::new(Config { use_stateless_retry: true, ..Config::default() }, Config::default()); 294 | pair.connect(); 295 | } 296 | 297 | #[test] 298 | fn stateless_reset() { 299 | let mut pair = Pair::default(); 300 | let (client_conn, _) = pair.connect(); 301 | assert_matches!(pair.client.poll(), Some((conn, Event::NewSessionTicket { .. })) if conn == client_conn); 302 | pair.server.endpoint = Endpoint::new( 303 | pair.log.new(o!("peer" => "server")), 304 | Config::default(), 305 | Some(CertConfig { 306 | private_key: &KEY, 307 | cert: &CERT, 308 | }), 309 | Some(*LISTEN_KEYS)).unwrap(); 310 | pair.client.ping(client_conn); 311 | info!(pair.log, "resetting"); 312 | pair.drive(); 313 | assert_matches!(pair.client.poll(), Some((conn, Event::NewSessionTicket { .. })) if conn == client_conn); 314 | assert_matches!(pair.client.poll(), Some((conn, Event::ConnectionLost { reason: ConnectionError::Reset })) if conn == client_conn); 315 | } 316 | 317 | #[test] 318 | fn finish_stream() { 319 | let mut pair = Pair::default(); 320 | let (client_conn, server_conn) = pair.connect(); 321 | 322 | let s = pair.client.open(client_conn, Directionality::Uni).unwrap(); 323 | 324 | const MSG: &[u8] = b"hello"; 325 | pair.client.write(client_conn, s, MSG).unwrap(); 326 | pair.client.finish(client_conn, s); 327 | pair.drive(); 328 | 329 | assert_matches!(pair.client.poll(), Some((conn, Event::NewSessionTicket { .. })) if conn == client_conn); 330 | assert_matches!(pair.client.poll(), Some((conn, Event::NewSessionTicket { .. })) if conn == client_conn); 331 | assert_matches!(pair.client.poll(), Some((conn, Event::StreamFinished { stream })) if conn == client_conn && stream == s); 332 | assert_matches!(pair.client.poll(), None); 333 | assert_matches!(pair.server.poll(), Some((conn, Event::StreamReadable { stream, fresh: true })) if conn == server_conn && stream == s); 334 | assert_matches!(pair.server.poll(), None); 335 | assert_matches!(pair.server.read_unordered(server_conn, s), Ok((ref data, 0)) if data == MSG); 336 | assert_matches!(pair.server.read_unordered(server_conn, s), Err(ReadError::Finished)); 337 | } 338 | 339 | #[test] 340 | fn reset_stream() { 341 | let mut pair = Pair::default(); 342 | let (client_conn, server_conn) = pair.connect(); 343 | assert_matches!(pair.client.poll(), Some((conn, Event::NewSessionTicket { .. })) if conn == client_conn); 344 | 345 | let s = pair.client.open(client_conn, Directionality::Uni).unwrap(); 346 | 347 | const MSG: &[u8] = b"hello"; 348 | pair.client.write(client_conn, s, MSG).unwrap(); 349 | pair.drive(); 350 | 351 | info!(pair.log, "resetting stream"); 352 | const ERROR: u16 = 42; 353 | pair.client.reset(client_conn, s, ERROR); 354 | pair.drive(); 355 | 356 | assert_matches!(pair.server.poll(), Some((conn, Event::StreamReadable { stream, fresh: true })) if conn == server_conn && stream == s); 357 | assert_matches!(pair.server.poll(), None); 358 | assert_matches!(pair.server.read_unordered(server_conn, s), Ok((ref data, 0)) if data == MSG); 359 | assert_matches!(pair.server.read_unordered(server_conn, s), Err(ReadError::Reset { error_code: ERROR })); 360 | assert_matches!(pair.client.poll(), Some((conn, Event::NewSessionTicket { .. })) if conn == client_conn); 361 | assert_matches!(pair.client.poll(), None); 362 | } 363 | 364 | #[test] 365 | fn stop_stream() { 366 | let mut pair = Pair::default(); 367 | let (client_conn, server_conn) = pair.connect(); 368 | 369 | let s = pair.client.open(client_conn, Directionality::Uni).unwrap(); 370 | const MSG: &[u8] = b"hello"; 371 | pair.client.write(client_conn, s, MSG).unwrap(); 372 | pair.drive(); 373 | 374 | info!(pair.log, "stopping stream"); 375 | const ERROR: u16 = 42; 376 | pair.server.stop_sending(server_conn, s, ERROR); 377 | pair.drive(); 378 | 379 | assert_matches!(pair.server.poll(), Some((conn, Event::StreamReadable { stream, fresh: true })) if conn == server_conn && stream == s); 380 | assert_matches!(pair.server.poll(), None); 381 | assert_matches!(pair.server.read_unordered(server_conn, s), Ok((ref data, 0)) if data == MSG); 382 | assert_matches!(pair.server.read_unordered(server_conn, s), Err(ReadError::Reset { error_code: 0 })); 383 | 384 | assert_matches!(pair.client.write(client_conn, s, b"foo"), Err(WriteError::Stopped { error_code: ERROR })); 385 | } 386 | 387 | #[test] 388 | fn reject_self_signed_cert() { 389 | let mut pair = Pair::new(Config::default(), Config::default()); 390 | info!(pair.log, "connecting"); 391 | let client_conn = pair.client.connect(pair.server.addr, ClientConfig::default()).unwrap(); 392 | pair.drive(); 393 | assert_matches!(pair.client.poll(), 394 | Some((conn, Event::ConnectionLost { reason: ConnectionError::TransportError { 395 | error_code: TransportError::TLS_HANDSHAKE_FAILED 396 | }})) if conn == client_conn); 397 | } 398 | 399 | #[test] 400 | fn congestion() { 401 | let mut pair = Pair::default(); 402 | let (client_conn, _) = pair.connect(); 403 | 404 | let initial_congestion_state = pair.client.get_congestion_state(client_conn); 405 | let s = pair.client.open(client_conn, Directionality::Uni).unwrap(); 406 | loop { 407 | match pair.client.write(client_conn, s, &[42; 1024]) { 408 | Ok(n) => { assert!(n <= 1024); pair.drive_client(); } 409 | Err(WriteError::Blocked) => { break; } 410 | Err(e) => { panic!("unexpected write error: {}", e); } 411 | } 412 | } 413 | pair.drive(); 414 | assert!(pair.client.get_congestion_state(client_conn) >= initial_congestion_state); 415 | pair.client.write(client_conn, s, &[42; 1024]).unwrap(); 416 | } 417 | 418 | #[test] 419 | fn high_latency_handshake() { 420 | let mut pair = Pair::default(); 421 | pair.latency = 200 * 1000; 422 | let client_conn = pair.client.connect(pair.server.addr, ClientConfig { accept_insecure_certs: true, ..ClientConfig::default() }).unwrap(); 423 | pair.drive(); 424 | let server_conn = if let Some(c) = pair.server.accept() { c } else { panic!("server didn't connect"); }; 425 | assert_matches!(pair.client.poll(), Some((conn, Event::Connected { .. })) if conn == client_conn); 426 | assert_eq!(pair.client.get_bytes_in_flight(client_conn), 0); 427 | assert_eq!(pair.server.get_bytes_in_flight(server_conn), 0); 428 | } 429 | 430 | #[test] 431 | fn zero_rtt() { 432 | let mut pair = Pair::default(); 433 | let (c, _) = pair.connect(); 434 | let ticket = match pair.client.poll() { 435 | Some((conn, Event::NewSessionTicket { ref ticket })) if conn == c => ticket.clone(), 436 | e => panic!("unexpected poll result: {:?}", e), 437 | }; 438 | info!(pair.log, "closing"; "ticket size" => ticket.len()); 439 | pair.client.close(pair.time, c, 42, (&[][..]).into()); 440 | pair.drive(); 441 | info!(pair.log, "resuming"); 442 | let cc = pair.client.connect(pair.server.addr, 443 | ClientConfig { 444 | accept_insecure_certs: true, 445 | session_ticket: Some(&ticket), 446 | ..ClientConfig::default() 447 | }).unwrap(); 448 | let s = pair.client.open(cc, Directionality::Uni).unwrap(); 449 | const MSG: &[u8] = b"Hello, 0-RTT!"; 450 | pair.client.write(cc, s, MSG).unwrap(); 451 | pair.drive(); 452 | assert!(pair.client.get_session_resumed(c)); 453 | let sc = if let Some(c) = pair.server.accept() { c } else { panic!("server didn't connect"); }; 454 | assert_matches!(pair.server.read_unordered(sc, s), Ok((ref data, 0)) if data == MSG); 455 | } 456 | -------------------------------------------------------------------------------- /quicr/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! QUIC transport protocol support for Tokio 2 | //! 3 | //! [QUIC](https://en.wikipedia.org/wiki/QUIC) is a modern transport protocol addressing shortcomings of TCP, such as 4 | //! head-of-line blocking, poor security, slow handshakes, and inefficient congestion control. This crate provides a 5 | //! portable userspace implementation. 6 | //! 7 | //! The entry point of this crate is the [`Endpoint`](struct.Endpoint.html). 8 | //! 9 | //! The futures and streams defined in this crate are not `Send` because they necessarily share state with eachother. As 10 | //! a result, they must be spawned on a single-threaded tokio runtime. 11 | //! 12 | //! ``` 13 | //! # extern crate tokio; 14 | //! # extern crate quicr; 15 | //! # extern crate futures; 16 | //! # use futures::Future; 17 | //! # fn main() { 18 | //! let mut runtime = tokio::runtime::current_thread::Runtime::new().unwrap(); 19 | //! let mut builder = quicr::Endpoint::new(); 20 | //! // 21 | //! let (endpoint, driver, _) = builder.bind("[::]:0").unwrap(); 22 | //! runtime.spawn(driver.map_err(|e| panic!("IO error: {}", e))); 23 | //! // ... 24 | //! # } 25 | //! ``` 26 | //! # About QUIC 27 | //! 28 | //! A QUIC connection is an association between two endpoints. The endpoint which initiates the connection is termed the 29 | //! client, and the endpoint which accepts it is termed the server. A single endpoint may function as both client and 30 | //! server for different connections, for example in a peer-to-peer application. To communicate application data, each 31 | //! endpoint may open streams up to a limit dictated by its peer. Typically, that limit is increased as old streams are 32 | //! finished. 33 | //! 34 | //! Streams may be unidirectional or bidirectional, and are cheap to create and disposable. For example, a traditionally 35 | //! datagram-oriented application could use a new stream for every message it wants to send, no longer needing to worry 36 | //! about MTUs. Bidirectional streams behave much like a traditional TCP connection, and are useful for sending messages 37 | //! that have an immediate response, such as an HTTP request. Stream data is delivered reliably, and there is no 38 | //! ordering enforced between data on different streams. 39 | //! 40 | //! By avoiding head-of-line blocking and providing unified congestion control across all streams of a connection, QUIC 41 | //! is able to provide higher throughput and lower latency than one or multiple TCP connections between the same two 42 | //! hosts, while providing more useful behavior than raw UDP sockets. 43 | //! 44 | //! QUIC uses encryption and identity verification built directly on TLS 1.3. Just as with a TLS server, it is useful 45 | //! for a QUIC server to be identified by a certificate signed by a trusted authority. If this is infeasible--for 46 | //! example, if servers are short-lived or not associated with a domain name--then as with TLS, self-signed certificates 47 | //! can be used to provide encryption alone. 48 | #![warn(missing_docs)] 49 | 50 | extern crate quicr_core as quicr; 51 | extern crate tokio_reactor; 52 | extern crate tokio_udp; 53 | extern crate tokio_io; 54 | extern crate tokio_timer; 55 | #[macro_use] 56 | extern crate slog; 57 | extern crate futures; 58 | extern crate fnv; 59 | extern crate openssl; 60 | #[macro_use] 61 | extern crate failure; 62 | extern crate bytes; 63 | extern crate rand; 64 | 65 | use std::{io, mem}; 66 | use std::net::{SocketAddr, SocketAddrV6, ToSocketAddrs}; 67 | use std::rc::Rc; 68 | use std::cell::RefCell; 69 | use std::collections::{VecDeque, hash_map}; 70 | use std::time::{Instant, Duration}; 71 | use std::borrow::Cow; 72 | 73 | use tokio_udp::UdpSocket; 74 | use tokio_io::{AsyncRead, AsyncWrite}; 75 | use tokio_timer::Delay; 76 | use slog::Logger; 77 | use futures::{Future, Poll, Async}; 78 | use futures::Stream as FuturesStream; 79 | use futures::unsync::{oneshot, mpsc}; 80 | use futures::task::{self, Task}; 81 | use futures::stream::FuturesUnordered; 82 | use fnv::FnvHashMap; 83 | use openssl::ssl; 84 | use openssl::pkey::{PKey, Private}; 85 | use openssl::rsa::Rsa; 86 | use openssl::x509::X509; 87 | use openssl::asn1::Asn1Time; 88 | use bytes::Bytes; 89 | 90 | use quicr::{Directionality, StreamId, ConnectionHandle, Side, CertConfig}; 91 | 92 | pub use quicr::{Config, ClientConfig, ConnectionError, ConnectionId, ListenKeys, ConnectError}; 93 | 94 | /// Errors that can occur during the construction of an `Endpoint`. 95 | #[derive(Debug, Fail)] 96 | pub enum Error { 97 | /// An error during setup of the underlying UDP socket. 98 | #[fail(display = "failed to set up UDP socket: {}", _0)] 99 | Socket(io::Error), 100 | /// An error configuring TLS. 101 | #[fail(display = "failed to set up TLS: {}", _0)] 102 | Tls(ssl::Error), 103 | /// An error opening a file for logging TLS keys. 104 | #[fail(display = "failed open keylog file: {}", _0)] 105 | Keylog(io::Error), 106 | /// A supplied protocol identifier was too long 107 | #[fail(display = "protocol ID longer than 255 bytes")] 108 | ProtocolTooLong(Box<[u8]>), 109 | } 110 | 111 | impl From for Error { 112 | fn from(x: quicr::EndpointError) -> Self { 113 | use quicr::EndpointError::*; 114 | match x { 115 | Tls(x) => Error::Tls(x), 116 | Keylog(x) => Error::Keylog(x), 117 | ProtocolTooLong(x) => Error::ProtocolTooLong(x), 118 | } 119 | } 120 | } 121 | 122 | struct EndpointInner { 123 | log: Logger, 124 | socket: UdpSocket, 125 | inner: quicr::Endpoint, 126 | outgoing: VecDeque<(SocketAddrV6, Box<[u8]>)>, 127 | epoch: Instant, 128 | pending: FnvHashMap, 129 | // TODO: Replace this with something custom that avoids using oneshots to cancel 130 | timers: FuturesUnordered, 131 | incoming: mpsc::UnboundedSender, 132 | driver: Option, 133 | } 134 | 135 | impl EndpointInner { 136 | /// Wake up a blocked `Driver` task to process I/O 137 | fn notify(&self) { self.driver.as_ref().map(|x| x.notify()); } 138 | } 139 | 140 | struct Pending { 141 | blocked_writers: FnvHashMap, 142 | blocked_readers: FnvHashMap, 143 | connecting: Option>>, 144 | uni_opening: VecDeque>>, 145 | bi_opening: VecDeque>>, 146 | cancel_loss_detect: Option>, 147 | cancel_idle: Option>, 148 | incoming_streams: VecDeque, 149 | incoming_streams_reader: Option, 150 | finishing: FnvHashMap>>, 151 | error: Option, 152 | draining: Option>, 153 | drained: bool, 154 | incoming_session_tickets: VecDeque>, 155 | incoming_session_tickets_reader: Option, 156 | } 157 | 158 | impl Pending { 159 | fn new(connecting: Option>>) -> Self { Self { 160 | blocked_writers: FnvHashMap::default(), 161 | blocked_readers: FnvHashMap::default(), 162 | connecting, 163 | uni_opening: VecDeque::new(), 164 | bi_opening: VecDeque::new(), 165 | cancel_loss_detect: None, 166 | cancel_idle: None, 167 | incoming_streams: VecDeque::new(), 168 | incoming_streams_reader: None, 169 | finishing: FnvHashMap::default(), 170 | error: None, 171 | draining: None, 172 | drained: false, 173 | incoming_session_tickets: VecDeque::new(), 174 | incoming_session_tickets_reader: None, 175 | }} 176 | 177 | fn fail(&mut self, reason: ConnectionError) { 178 | self.error = Some(reason.clone()); 179 | for (_, writer) in self.blocked_writers.drain() { 180 | writer.notify() 181 | } 182 | for (_, reader) in self.blocked_readers.drain() { 183 | reader.notify() 184 | } 185 | if let Some(c) = self.connecting.take() { 186 | let _ = c.send(Some(reason.clone())); 187 | } 188 | for x in self.uni_opening.drain(..) { 189 | let _ = x.send(Err(reason.clone())); 190 | } 191 | for x in self.bi_opening.drain(..) { 192 | let _ = x.send(Err(reason.clone())); 193 | } 194 | if let Some(x) = self.incoming_streams_reader.take() { 195 | x.notify(); 196 | } 197 | for (_, x) in self.finishing.drain() { 198 | let _ = x.send(Some(reason.clone())); 199 | } 200 | if let Some(x) = self.incoming_session_tickets_reader.take() { 201 | x.notify(); 202 | } 203 | } 204 | } 205 | 206 | /// A QUIC endpoint. 207 | /// 208 | /// An endpoint corresponds to a single UDP socket, may host many connections, and may act as both client and server for 209 | /// different connections. 210 | pub struct Endpoint(Rc>); 211 | 212 | /// A future that drives IO on an endpoint. 213 | pub struct Driver(Rc>); 214 | 215 | /// Stream of incoming connections. 216 | pub type Incoming = mpsc::UnboundedReceiver; 217 | 218 | /// A helper for constructing an `Endpoint`. 219 | pub struct EndpointBuilder<'a> { 220 | reactor: Option<&'a tokio_reactor::Handle>, 221 | logger: Logger, 222 | listen: Option, 223 | config: Config, 224 | private_key: Option>, 225 | cert: Option, 226 | } 227 | 228 | #[allow(missing_docs)] 229 | impl<'a> EndpointBuilder<'a> { 230 | pub fn reactor(&mut self, handle: &'a tokio_reactor::Handle) -> &mut Self { self.reactor = Some(handle); self } 231 | pub fn logger(&mut self, logger: Logger) -> &mut Self { self.logger = logger; self } 232 | pub fn config(&mut self, config: Config) -> &mut Self { self.config = config; self } 233 | 234 | /// Prefer `listen_with_keys`. 235 | pub fn listen(&mut self) -> &mut Self { self.listen = Some(ListenKeys::new(&mut rand::thread_rng())); self } 236 | 237 | /// Use with persistent `keys` instead of `listen` to allow graceful reset of clients when the server restarts. 238 | pub fn listen_with_keys(&mut self, keys: ListenKeys) -> &mut Self { self.listen = Some(keys); self } 239 | 240 | pub fn private_key_pem(&mut self, key: &[u8]) -> Result<&mut Self, ssl::Error> { 241 | self.private_key = Some(PKey::::private_key_from_pem(key)?); 242 | Ok(self) 243 | } 244 | pub fn certificate_pem(&mut self, cert: &[u8]) -> Result<&mut Self, ssl::Error> { 245 | self.cert = Some(X509::from_pem(&cert)?); 246 | Ok(self) 247 | } 248 | pub fn private_key_der(&mut self, key: &[u8]) -> Result<&mut Self, ssl::Error> { 249 | self.private_key = Some(PKey::::private_key_from_der(key)?); 250 | Ok(self) 251 | } 252 | pub fn certificate_der(&mut self, cert: &[u8]) -> Result<&mut Self, ssl::Error> { 253 | self.cert = Some(X509::from_der(&cert)?); 254 | Ok(self) 255 | } 256 | 257 | /// Generate a key pair and self-signed TLS certificate. 258 | /// 259 | /// Peers will be unable to verify this endpoint's identity. Useful to host a server with a minimum of set-up when 260 | /// preventing man-in-the-middle attacks is not important. 261 | pub fn generate_insecure_certificate(&mut self) -> Result<&mut Self, ssl::Error> { 262 | let key = PKey::from_rsa(Rsa::generate(2048)?)?; 263 | let mut cert = X509::builder()?; 264 | cert.set_pubkey(&key)?; 265 | let now = Asn1Time::days_from_now(0)?; 266 | cert.set_not_before(&now)?; 267 | let forever = Asn1Time::days_from_now(u32::max_value())?; 268 | cert.set_not_after(&forever)?; 269 | cert.sign(&key, openssl::hash::MessageDigest::sha256())?; 270 | self.cert = Some(cert.build()); 271 | self.private_key = Some(key); 272 | Ok(self) 273 | } 274 | 275 | pub fn from_socket(self, socket: std::net::UdpSocket) -> Result<(Endpoint, Driver, Incoming), Error> { 276 | let cert = self.cert; 277 | let cert_config = self.private_key.as_ref().and_then(|private_key| cert.as_ref().map(|cert| CertConfig { private_key, cert })); 278 | let reactor = if let Some(x) = self.reactor { Cow::Borrowed(x) } else { Cow::Owned(tokio_reactor::Handle::current()) }; 279 | let socket = UdpSocket::from_std(socket, &reactor).map_err(Error::Socket)?; 280 | let (send, recv) = mpsc::unbounded(); 281 | let rc = Rc::new(RefCell::new(EndpointInner { 282 | log: self.logger.clone(), 283 | socket: socket, 284 | inner: quicr::Endpoint::new(self.logger, self.config, cert_config, self.listen)?, 285 | outgoing: VecDeque::new(), 286 | epoch: Instant::now(), 287 | pending: FnvHashMap::default(), 288 | timers: FuturesUnordered::new(), 289 | incoming: send, 290 | driver: None, 291 | })); 292 | Ok((Endpoint(rc.clone()), Driver(rc), recv)) 293 | } 294 | 295 | pub fn bind(self, addr: T) -> Result<(Endpoint, Driver, Incoming), Error> { 296 | let socket = std::net::UdpSocket::bind(addr).map_err(Error::Socket)?; 297 | self.from_socket(socket) 298 | } 299 | } 300 | 301 | impl<'a> Default for EndpointBuilder<'a> { 302 | fn default() -> Self { Endpoint::new() } 303 | } 304 | 305 | impl Endpoint { 306 | /// Begin constructing an `Endpoint` 307 | pub fn new<'a>() -> EndpointBuilder<'a> { EndpointBuilder { 308 | reactor: None, 309 | logger: Logger::root(slog::Discard, o!()), 310 | listen: None, 311 | config: Config::default(), 312 | cert: None, 313 | private_key: None, 314 | }} 315 | 316 | /// Connect to a remote endpoint. 317 | /// 318 | /// May fail immediately due to configuration errors, or in the future if the connection could not be established. 319 | pub fn connect(&self, addr: &SocketAddr, config: ClientConfig) 320 | -> Result, ConnectError> 321 | { 322 | let (fut, conn) = self.connect_inner(addr, config)?; 323 | Ok(fut.map_err(|_| unreachable!()) 324 | .and_then(move |err| if let Some(err) = err { Err(err) } else { 325 | Ok(NewClientConnection::new(Rc::new(conn))) 326 | })) 327 | } 328 | 329 | /// Connect to a remote endpoint, with support for transmitting data before the connection is established 330 | /// 331 | /// Returns a connection that may be used for sending immediately, and a future that will complete when the 332 | /// connection is established. 333 | /// 334 | /// Data transmitted this way may be replayed by an attacker until the session ticket expires. Never send non-idempotent 335 | /// commands as 0-RTT data. 336 | /// 337 | /// Servers may reject 0-RTT data, in which case anything sent will be retransmitted after the connection is 338 | /// established. 339 | /// 340 | /// # Panics 341 | /// - If `config.session_ticket` is `None`. A session ticket is necessary for 0-RTT to be possible. 342 | pub fn connect_zero_rtt(&self, addr: &SocketAddr, config: ClientConfig) 343 | -> Result<(NewClientConnection, impl Future), ConnectError> 344 | { 345 | assert!(config.session_ticket.is_some(), "a session ticket must be supplied for zero-rtt transmits to be possible"); 346 | let (fut, conn) = self.connect_inner(addr, config)?; 347 | let conn = NewClientConnection::new(Rc::new(conn)); 348 | Ok((conn, fut.map_err(|_| unreachable!()).and_then(move |err| err.map_or(Ok(()), Err) ))) 349 | } 350 | 351 | fn connect_inner(&self, addr: &SocketAddr, config: ClientConfig) 352 | -> Result<(impl Future, Error=futures::Canceled>, ConnectionInner), ConnectError> 353 | { 354 | let (send, recv) = oneshot::channel(); 355 | let handle = { 356 | let mut endpoint = self.0.borrow_mut(); 357 | let handle = endpoint.inner.connect(normalize(*addr), config)?; 358 | endpoint.pending.insert(handle, Pending::new(Some(send))); 359 | handle 360 | }; 361 | let conn = ConnectionInner { 362 | endpoint: Endpoint(self.0.clone()), 363 | conn: handle, 364 | side: Side::Client, 365 | }; 366 | Ok((recv, conn)) 367 | } 368 | } 369 | 370 | /// A connection initiated by a remote client. 371 | pub struct NewConnection { 372 | /// The connection itself. 373 | pub connection: Connection, 374 | /// The stream of QUIC streams initiated by the client. 375 | pub incoming: IncomingStreams, 376 | } 377 | 378 | impl NewConnection { 379 | fn new(endpoint: Endpoint, handle: quicr::ConnectionHandle) -> Self { 380 | let conn = Rc::new(ConnectionInner { 381 | endpoint: Endpoint(endpoint.0.clone()), 382 | conn: handle, 383 | side: Side::Server, 384 | }); 385 | NewConnection { 386 | connection: Connection(conn.clone()), 387 | incoming: IncomingStreams(conn), 388 | } 389 | } 390 | } 391 | 392 | /// A connection initiated locally. 393 | pub struct NewClientConnection { 394 | /// The connection itself. 395 | pub connection: Connection, 396 | /// The stream of QUIC streams initiated by the client. 397 | pub incoming: IncomingStreams, 398 | /// The stream of session tickets provided by the server. 399 | pub session_tickets: IncomingSessionTickets, 400 | } 401 | 402 | impl NewClientConnection { 403 | fn new(conn: Rc) -> Self { 404 | Self { 405 | connection: Connection(conn.clone()), 406 | incoming: IncomingStreams(conn.clone()), 407 | session_tickets: IncomingSessionTickets(conn), 408 | } 409 | } 410 | } 411 | 412 | impl Future for Driver { 413 | type Item = (); 414 | type Error = io::Error; 415 | fn poll(&mut self) -> Poll { 416 | let mut buf = [0; 64 * 1024]; 417 | let endpoint = &mut *self.0.borrow_mut(); 418 | if endpoint.driver.is_none() { endpoint.driver = Some(task::current()); } 419 | let now = micros_from(endpoint.epoch.elapsed()); 420 | loop { 421 | loop { 422 | match endpoint.socket.poll_recv_from(&mut buf) { 423 | Ok(Async::Ready((n, addr))) => { 424 | endpoint.inner.handle(now, normalize(addr), (&buf[0..n]).into()); 425 | } 426 | Ok(Async::NotReady) => { break; } 427 | // Ignore ECONNRESET as it's undefined in QUIC and may be injected by an attacker 428 | Err(ref e) if e.kind() == io::ErrorKind::ConnectionReset => { continue; } 429 | Err(e) => { return Err(e); } 430 | } 431 | } 432 | while let Some((connection, event)) = endpoint.inner.poll() { 433 | use quicr::Event::*; 434 | match event { 435 | Connected { .. } => { 436 | let _ = endpoint.pending.get_mut(&connection).unwrap().connecting.take() 437 | .expect("got Connected event for unknown connection") 438 | .send(None); 439 | } 440 | ConnectionLost { reason } => { 441 | // HACK HACK HACK: Handshake currently emits ConnectionLost, which means we might not know about 442 | // this connection yet. This should probably be made more consistent. 443 | if let Some(x) = endpoint.pending.get_mut(&connection) { 444 | x.fail(reason); 445 | } 446 | } 447 | ConnectionDrained => { 448 | if let Some(x) = endpoint.pending.get_mut(&connection).and_then(|p| { p.drained = true; p.draining.take() }) { 449 | let _ = x.send(()); 450 | } 451 | } 452 | StreamWritable { stream } => { 453 | if let Some(writer) = endpoint.pending.get_mut(&connection).unwrap().blocked_writers.remove(&stream) { 454 | writer.notify(); 455 | } 456 | } 457 | StreamReadable { stream, fresh } => { 458 | let pending = endpoint.pending.get_mut(&connection).unwrap(); 459 | if let Some(reader) = pending.blocked_readers.remove(&stream) { 460 | reader.notify(); 461 | } 462 | if fresh { 463 | pending.incoming_streams.push_back(stream); 464 | if let Some(x) = pending.incoming_streams_reader.take() { x.notify(); } 465 | } 466 | } 467 | StreamAvailable { directionality } => { 468 | let pending = endpoint.pending.get_mut(&connection).unwrap(); 469 | let queue = match directionality { 470 | Directionality::Uni => &mut pending.uni_opening, 471 | Directionality::Bi => &mut pending.bi_opening, 472 | }; 473 | while let Some(ch) = queue.pop_front() { 474 | if let Some(id) = endpoint.inner.open(connection, directionality) { 475 | let _ = ch.send(Ok(id)); 476 | } else { 477 | queue.push_front(ch); 478 | break; 479 | } 480 | } 481 | } 482 | StreamFinished { stream } => { 483 | let _ = endpoint.pending.get_mut(&connection).unwrap() 484 | .finishing.remove(&stream).unwrap().send(None); 485 | } 486 | NewSessionTicket { ticket } => { 487 | let pending = endpoint.pending.get_mut(&connection).unwrap(); 488 | const SESSION_TICKET_BUFFER_SIZE: usize = 16; 489 | if pending.incoming_session_tickets.len() >= SESSION_TICKET_BUFFER_SIZE { 490 | pending.incoming_session_tickets.pop_front(); 491 | } 492 | pending.incoming_session_tickets.push_back(ticket); 493 | if let Some(x) = pending.incoming_session_tickets_reader.take() { 494 | x.notify(); 495 | } 496 | } 497 | } 498 | } 499 | let mut blocked = false; 500 | while !endpoint.outgoing.is_empty() { 501 | { 502 | let front = endpoint.outgoing.front().unwrap(); 503 | match endpoint.socket.poll_send_to(&front.1, &front.0.into()) { 504 | Ok(Async::Ready(_)) => {} 505 | Ok(Async::NotReady) => { blocked = true; break; } 506 | Err(ref e) if e.kind() == io::ErrorKind::PermissionDenied => { blocked = true; break; } 507 | Err(e) => { return Err(e); } 508 | } 509 | } 510 | endpoint.outgoing.pop_front(); 511 | } 512 | while let Some(io) = endpoint.inner.poll_io(now) { 513 | use quicr::Io::*; 514 | match io { 515 | Transmit { destination, packet } => { 516 | if !blocked { 517 | match endpoint.socket.poll_send_to(&packet, &destination.into()) { 518 | Ok(Async::Ready(_)) => {} 519 | Ok(Async::NotReady) => { blocked = true; } 520 | Err(ref e) if e.kind() == io::ErrorKind::PermissionDenied => { blocked = true; } 521 | Err(e) => { return Err(e); } 522 | } 523 | } 524 | if blocked { 525 | endpoint.outgoing.push_front((destination, packet)); 526 | } 527 | } 528 | TimerStart { connection, timer: timer@quicr::Timer::Close, time } => { 529 | let instant = endpoint.epoch + duration_micros(time); 530 | endpoint.timers.push(Timer { 531 | conn: connection, 532 | ty: timer, 533 | delay: Delay::new(instant), 534 | cancel: None, 535 | }); 536 | } 537 | TimerStart { connection, timer, time } => { 538 | // Loss detection and idle timers start before the connection is established 539 | let pending = endpoint.pending.entry(connection).or_insert_with(|| Pending::new(None)); 540 | use quicr::Timer::*; 541 | let mut cancel = match timer { 542 | LossDetection => &mut pending.cancel_loss_detect, 543 | Idle => &mut pending.cancel_idle, 544 | Close => unreachable!() 545 | }; 546 | let instant = endpoint.epoch + duration_micros(time); 547 | if let Some(cancel) = cancel.take() { 548 | let _ = cancel.send(()); 549 | } 550 | let (send, recv) = oneshot::channel(); 551 | *cancel = Some(send); 552 | trace!(endpoint.log, "timer start"; "timer" => ?timer, "time" => ?duration_micros(time)); 553 | endpoint.timers.push(Timer { 554 | conn: connection, 555 | ty: timer, 556 | delay: Delay::new(instant), 557 | cancel: Some(recv), 558 | }); 559 | } 560 | TimerStop { connection, timer } => { 561 | trace!(endpoint.log, "timer stop"; "timer" => ?timer); 562 | // If a connection was lost, we already canceled its loss/idle timers. 563 | if let Some(pending) = endpoint.pending.get_mut(&connection) { 564 | use quicr::Timer::*; 565 | match timer { 566 | LossDetection => { pending.cancel_loss_detect.take().map(|x| { let _ = x.send(()); }); } 567 | Idle => { pending.cancel_idle.take().map(|x| x.send(())); } 568 | Close => {} // Arises from stateless reset 569 | } 570 | } 571 | } 572 | } 573 | } 574 | while let Some(x) = endpoint.inner.accept() { 575 | let _ = endpoint.incoming.unbounded_send(NewConnection::new(Endpoint(self.0.clone()), x)); 576 | } 577 | let mut fired = false; 578 | loop { 579 | match endpoint.timers.poll() { 580 | Ok(Async::Ready(Some(Some((conn, timer))))) => { 581 | trace!(endpoint.log, "timeout"; "timer" => ?timer); 582 | endpoint.inner.timeout(now, conn, timer); 583 | fired = true; 584 | } 585 | Ok(Async::Ready(Some(None))) => {} 586 | Ok(Async::Ready(None)) | Ok(Async::NotReady) => { break; } 587 | Err(()) => unreachable!() 588 | } 589 | } 590 | if !fired { break; } 591 | } 592 | Ok(Async::NotReady) 593 | } 594 | } 595 | 596 | fn duration_micros(x: u64) -> Duration { Duration::new(x / (1000 * 1000), (x % (1000 * 1000)) as u32 * 1000) } 597 | fn micros_from(x: Duration) -> u64 { x.as_secs() * 1000 * 1000 + (x.subsec_nanos() / 1000) as u64 } 598 | 599 | fn normalize(x: SocketAddr) -> SocketAddrV6 { 600 | match x { 601 | SocketAddr::V6(x) => x, 602 | SocketAddr::V4(x) => SocketAddrV6::new(x.ip().to_ipv6_mapped(), x.port(), 0, 0), 603 | } 604 | } 605 | 606 | struct ConnectionInner { 607 | endpoint: Endpoint, 608 | conn: ConnectionHandle, 609 | side: Side, 610 | } 611 | 612 | /// A QUIC connection. 613 | /// 614 | /// If a `Connection` is dropped without being explicitly closed, it will be automatically closed with an `error_code` 615 | /// of 0 and an empty `reason`. 616 | pub struct Connection(Rc); 617 | 618 | impl Connection { 619 | /// Initite a new outgoing unidirectional stream. 620 | pub fn open_uni(&self) -> impl Future { 621 | let (send, recv) = oneshot::channel(); 622 | { 623 | let mut endpoint = self.0.endpoint.0.borrow_mut(); 624 | if let Some(x) = endpoint.inner.open(self.0.conn, Directionality::Uni) { 625 | let _ = send.send(Ok(x)); 626 | } else { 627 | let pending = endpoint.pending.get_mut(&self.0.conn).unwrap(); 628 | pending.uni_opening.push_back(send); 629 | // We don't notify the driver here because there's no way to ask the peer for more streams 630 | } 631 | } 632 | let conn = self.0.clone(); 633 | recv.map_err(|_| unreachable!()) 634 | .and_then(|result| result) 635 | .map(move |stream| SendStream(Stream::new(conn, stream))) 636 | } 637 | 638 | /// Initiate a new outgoing bidirectional stream. 639 | pub fn open_bi(&self) -> impl Future { 640 | let (send, recv) = oneshot::channel(); 641 | { 642 | let mut endpoint = self.0.endpoint.0.borrow_mut(); 643 | if let Some(x) = endpoint.inner.open(self.0.conn, Directionality::Bi) { 644 | let _ = send.send(Ok(x)); 645 | } else { 646 | let pending = endpoint.pending.get_mut(&self.0.conn).unwrap(); 647 | pending.bi_opening.push_back(send); 648 | // We don't notify the driver here because there's no way to ask the peer for more streams 649 | } 650 | } 651 | let conn = self.0.clone(); 652 | recv.map_err(|_| unreachable!()) 653 | .and_then(|result| result) 654 | .map(move |stream| { 655 | Stream::new(conn.clone(), stream) 656 | }) 657 | } 658 | 659 | /// Close the connection immediately. 660 | /// 661 | /// This does not ensure delivery of outstanding data. It is the application's responsibility to call this only when 662 | /// all important communications have been completed. 663 | /// 664 | /// `error_code` and `reason` are not interpreted, and are provided directly to the peer. 665 | /// 666 | /// `reason` will be truncated to fit in a single packet with overhead; to be certain it is preserved in full, it 667 | /// should be kept under 1KiB. 668 | // FIXME: Infallible 669 | pub fn close(self, error_code: u16, reason: &[u8]) -> impl Future { 670 | let (send, recv) = oneshot::channel(); 671 | { 672 | let endpoint = &mut *self.0.endpoint.0.borrow_mut(); 673 | endpoint.inner.close(micros_from(endpoint.epoch.elapsed()), self.0.conn, error_code, reason.into()); 674 | let pending = endpoint.pending.get_mut(&self.0.conn).unwrap(); 675 | pending.draining = Some(send); 676 | } 677 | recv.then(move |_| { let _ = self; Ok(()) }) 678 | } 679 | 680 | /// The peer's UDP address. 681 | pub fn remote_address(&self) -> SocketAddr { 682 | (*self.0.endpoint.0.borrow().inner.get_remote_address(self.0.conn)).into() 683 | } 684 | 685 | /// The `ConnectionId` used for `conn` locally. 686 | pub fn local_id(&self) -> ConnectionId { 687 | self.0.endpoint.0.borrow().inner.get_local_id(self.0.conn).clone() 688 | } 689 | /// The `ConnectionId` used for `conn` by the peer. 690 | pub fn remote_id(&self) -> ConnectionId { 691 | self.0.endpoint.0.borrow().inner.get_remote_id(self.0.conn).clone() 692 | } 693 | 694 | /// The negotiated application protocol 695 | pub fn protocol(&self) -> Option> { 696 | self.0.endpoint.0.borrow().inner.get_protocol(self.0.conn).map(|x| x.into()) 697 | } 698 | 699 | /// Whether the cryptographic session was resumed 700 | pub fn session_resumed(&self) -> bool { 701 | self.0.endpoint.0.borrow().inner.get_session_resumed(self.0.conn) 702 | } 703 | } 704 | 705 | impl Drop for ConnectionInner { 706 | fn drop(&mut self) { 707 | let endpoint = &mut *self.endpoint.0.borrow_mut(); 708 | if let hash_map::Entry::Occupied(pending) = endpoint.pending.entry(self.conn) { 709 | if pending.get().draining.is_none() && !pending.get().drained { 710 | endpoint.inner.close(micros_from(endpoint.epoch.elapsed()), self.conn, 0, (&[][..]).into()); 711 | endpoint.driver.as_ref().map(|x| x.notify()); 712 | } 713 | pending.remove_entry(); 714 | } else { unreachable!() } 715 | } 716 | } 717 | 718 | /// Trait of readable streams 719 | pub trait Read { 720 | /// Read a segment of data from any offset in the stream. 721 | /// 722 | /// Returns a segment of data and their offset in the stream. Segments may be received in any order and may overlap. 723 | /// 724 | /// Using this function reduces latency improves throughput by avoiding head-of-line blocking within the stream, and 725 | /// reduces computational overhead by allowing data to be passed on without any intermediate buffering. Prefer it 726 | /// whenever possible. 727 | fn poll_read_unordered(&mut self) -> Poll<(Bytes, u64), ReadError>; 728 | 729 | /// Read data contiguously from the stream. 730 | /// 731 | /// Incurs latency, throughput, and computational overhead and is not necessary for most applications. Prefer 732 | /// `poll_read_unordered` whenever possible. 733 | /// 734 | /// # Panics 735 | /// - If called after `poll_read_unordered` was called on the same stream. 736 | /// This is forbidden because an unordered read could consume a segment of data from a location other than the start 737 | /// of the receive buffer, making it impossible for future ordered reads to proceed. 738 | fn poll_read(&mut self, buf: &mut [u8]) -> Poll; 739 | 740 | /// Abandon receiving data on this stream. 741 | /// 742 | /// The peer is notified and will reset this stream in response. 743 | fn stop(&mut self, error_code: u16); 744 | } 745 | 746 | /// Trait of writable streams 747 | pub trait Write { 748 | /// Write some bytes to the stream. 749 | fn poll_write(&mut self, buf: &[u8]) -> Poll; 750 | 751 | /// Indicate that no more data will be written. 752 | /// 753 | /// Completes when the peer has acknowledged all sent data. 754 | fn poll_finish(&mut self) -> Poll<(), ConnectionError>; 755 | 756 | /// Abandon transmitting data on this stream. 757 | /// 758 | /// No new data may be transmitted, and no previously transmitted data will be retransmitted if lost. 759 | fn reset(&mut self, error_code: u16); 760 | } 761 | 762 | /// A stream that supports both sending and receiving data 763 | pub struct Stream { 764 | conn: Rc, 765 | stream: StreamId, 766 | 767 | // Send only 768 | finishing: Option>>, 769 | finished: bool, 770 | 771 | // Recv only 772 | // Whether data reception is complete (due to receiving finish or reset or sending stop) 773 | recvd: bool, 774 | } 775 | 776 | impl Stream { 777 | fn new(conn: Rc, stream: StreamId) -> Self { Self { 778 | conn, stream, 779 | finishing: None, 780 | finished: false, 781 | recvd: false, 782 | }} 783 | } 784 | 785 | impl Write for Stream { 786 | fn poll_write(&mut self, buf: &[u8]) -> Poll { 787 | let mut endpoint = self.conn.endpoint.0.borrow_mut(); 788 | use quicr::WriteError::*; 789 | let n = match endpoint.inner.write(self.conn.conn, self.stream, buf) { 790 | Ok(n) => n, 791 | Err(Blocked) => { 792 | let pending = endpoint.pending.get_mut(&self.conn.conn).unwrap(); 793 | if let Some(ref x) = pending.error { return Err(WriteError::ConnectionClosed(x.clone())); } 794 | pending.blocked_writers.insert(self.stream, task::current()); 795 | return Ok(Async::NotReady); 796 | } 797 | Err(Stopped { error_code }) => { 798 | return Err(WriteError::Stopped { error_code }); 799 | } 800 | }; 801 | endpoint.notify(); 802 | Ok(Async::Ready(n)) 803 | } 804 | 805 | fn poll_finish(&mut self) -> Poll<(), ConnectionError> { 806 | let mut endpoint = self.conn.endpoint.0.borrow_mut(); 807 | if self.finishing.is_none() { 808 | endpoint.inner.finish(self.conn.conn, self.stream); 809 | let (send, recv) = oneshot::channel(); 810 | self.finishing = Some(recv); 811 | endpoint.pending.get_mut(&self.conn.conn).unwrap().finishing.insert(self.stream, send); 812 | endpoint.notify(); 813 | } 814 | let r = self.finishing.as_mut().unwrap().poll().unwrap(); 815 | match r { 816 | Async::Ready(None) => { 817 | self.finished = true; 818 | Ok(Async::Ready(())) 819 | } 820 | Async::Ready(Some(e)) => Err(e), 821 | Async::NotReady => Ok(Async::NotReady), 822 | } 823 | } 824 | 825 | fn reset(&mut self, error_code: u16) { 826 | let endpoint = &mut *self.conn.endpoint.0.borrow_mut(); 827 | endpoint.inner.reset(self.conn.conn, self.stream, error_code); 828 | endpoint.notify(); 829 | } 830 | } 831 | 832 | impl Read for Stream { 833 | fn poll_read_unordered(&mut self) -> Poll<(Bytes, u64), ReadError> { 834 | let endpoint = &mut *self.conn.endpoint.0.borrow_mut(); 835 | use quicr::ReadError::*; 836 | let pending = endpoint.pending.get_mut(&self.conn.conn).unwrap(); 837 | match endpoint.inner.read_unordered(self.conn.conn, self.stream) { 838 | Ok((bytes, offset)) => Ok(Async::Ready((bytes, offset))), 839 | Err(Blocked) => { 840 | if let Some(ref x) = pending.error { return Err(ReadError::ConnectionClosed(x.clone())); } 841 | pending.blocked_readers.insert(self.stream, task::current()); 842 | Ok(Async::NotReady) 843 | } 844 | Err(Reset { error_code }) => { 845 | self.recvd = true; 846 | Err(ReadError::Reset { error_code }) 847 | } 848 | Err(Finished) => { 849 | self.recvd = true; 850 | Err(ReadError::Finished) 851 | } 852 | } 853 | } 854 | 855 | fn poll_read(&mut self, buf: &mut [u8]) -> Poll { 856 | let endpoint = &mut *self.conn.endpoint.0.borrow_mut(); 857 | use quicr::ReadError::*; 858 | let pending = endpoint.pending.get_mut(&self.conn.conn).unwrap(); 859 | match endpoint.inner.read(self.conn.conn, self.stream, buf) { 860 | Ok(n) => Ok(Async::Ready(n)), 861 | Err(Blocked) => { 862 | if let Some(ref x) = pending.error { return Err(ReadError::ConnectionClosed(x.clone())); } 863 | pending.blocked_readers.insert(self.stream, task::current()); 864 | Ok(Async::NotReady) 865 | } 866 | Err(Reset { error_code }) => { 867 | self.recvd = true; 868 | Err(ReadError::Reset { error_code }) 869 | } 870 | Err(Finished) => { 871 | self.recvd = true; 872 | Err(ReadError::Finished) 873 | } 874 | } 875 | } 876 | 877 | fn stop(&mut self, error_code: u16) { 878 | let endpoint = &mut *self.conn.endpoint.0.borrow_mut(); 879 | endpoint.inner.stop_sending(self.conn.conn, self.stream, error_code); 880 | endpoint.notify(); 881 | self.recvd = true; 882 | } 883 | } 884 | 885 | impl io::Write for Stream { 886 | fn write(&mut self, buf: &[u8]) -> io::Result { 887 | match Write::poll_write(self, buf) { 888 | Ok(Async::Ready(n)) => Ok(n), 889 | Ok(Async::NotReady) => Err(io::Error::new(io::ErrorKind::WouldBlock, "stream blocked")), 890 | Err(WriteError::Stopped { error_code }) => 891 | Err(io::Error::new(io::ErrorKind::ConnectionReset, format!("stream stopped by peer: error {}", error_code))), 892 | Err(WriteError::ConnectionClosed(e)) => Err(io::Error::new(io::ErrorKind::ConnectionAborted, format!("connection closed: {}", e))), 893 | } 894 | } 895 | 896 | fn flush(&mut self) -> io::Result<()> { Ok(()) } 897 | } 898 | 899 | impl AsyncWrite for Stream { 900 | fn shutdown(&mut self) -> Poll<(), io::Error> { 901 | self.poll_finish().map_err(|e| io::Error::new(io::ErrorKind::ConnectionAborted, format!("connection closed: {}", e))) 902 | } 903 | } 904 | 905 | impl Drop for Stream { 906 | fn drop(&mut self) { 907 | let endpoint = &mut *self.conn.endpoint.0.borrow_mut(); 908 | let ours = self.stream.initiator() == self.conn.side; 909 | let (send, recv) = match self.stream.directionality() { 910 | Directionality::Bi => (true, true), 911 | Directionality::Uni => (ours, !ours), 912 | }; 913 | if send && !self.finished { 914 | endpoint.inner.reset(self.conn.conn, self.stream, 0); 915 | } 916 | if recv && !self.recvd { 917 | endpoint.inner.stop_sending(self.conn.conn, self.stream, 0); 918 | } 919 | endpoint.notify(); 920 | } 921 | } 922 | 923 | /// Errors that arise from writing to a stream 924 | #[derive(Debug, Fail, Clone)] 925 | pub enum WriteError { 926 | /// The peer is no longer accepting data on this stream. 927 | #[fail(display = "sending stopped by peer: error {}", error_code)] 928 | Stopped { 929 | /// The error code supplied by the peer. 930 | error_code: u16 931 | }, 932 | /// The connection was closed. 933 | #[fail(display = "connection closed: {}", _0)] 934 | ConnectionClosed(ConnectionError), 935 | } 936 | 937 | impl io::Read for Stream { 938 | fn read(&mut self, buf: &mut [u8]) -> io::Result { 939 | use ReadError::*; 940 | match Read::poll_read(self, buf) { 941 | Ok(Async::Ready(n)) => Ok(n), 942 | Err(Finished) => Ok(0), 943 | Ok(Async::NotReady) => Err(io::Error::new(io::ErrorKind::WouldBlock, "stream blocked")), 944 | Err(Reset { error_code }) => Err(io::Error::new(io::ErrorKind::ConnectionAborted, format!("stream reset by peer: error {}", error_code))), 945 | Err(ConnectionClosed(e)) => Err(io::Error::new(io::ErrorKind::ConnectionAborted, format!("connection closed: {}", e))), 946 | } 947 | } 948 | } 949 | 950 | impl AsyncRead for Stream { 951 | unsafe fn prepare_uninitialized_buffer(&self, _: &mut [u8]) -> bool { false } 952 | } 953 | 954 | /// A stream that can only be used to send data 955 | pub struct SendStream(Stream); 956 | 957 | impl Write for SendStream { 958 | fn poll_write(&mut self, buf: &[u8]) -> Poll { Write::poll_write(&mut self.0, buf) } 959 | fn poll_finish(&mut self) -> Poll<(), ConnectionError> { self.0.poll_finish() } 960 | fn reset(&mut self, error_code: u16) { self.0.reset(error_code); } 961 | } 962 | 963 | impl io::Write for SendStream { 964 | fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) } 965 | fn flush(&mut self) -> io::Result<()> { Ok(()) } 966 | } 967 | 968 | impl AsyncWrite for SendStream { 969 | fn shutdown(&mut self) -> Poll<(), io::Error> { self.0.shutdown() } 970 | } 971 | 972 | /// A stream that can only be used to receive data 973 | pub struct RecvStream(Stream); 974 | 975 | impl Read for RecvStream { 976 | fn poll_read_unordered(&mut self) -> Poll<(Bytes, u64), ReadError> { self.0.poll_read_unordered() } 977 | fn poll_read(&mut self, buf: &mut [u8]) -> Poll { Read::poll_read(&mut self.0, buf) } 978 | fn stop(&mut self, error_code: u16) { self.0.stop(error_code) } 979 | } 980 | 981 | impl io::Read for RecvStream { 982 | fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) } 983 | } 984 | 985 | impl AsyncRead for RecvStream { 986 | unsafe fn prepare_uninitialized_buffer(&self, _: &mut [u8]) -> bool { false } 987 | } 988 | 989 | /// Errors that arise from reading from a stream. 990 | #[derive(Debug, Fail, Clone)] 991 | pub enum ReadError { 992 | /// The peer abandoned transmitting data on this stream. 993 | #[fail(display = "stream reset by peer: error {}", error_code)] 994 | Reset { 995 | /// The error code supplied by the peer. 996 | error_code: u16 997 | }, 998 | /// The data on this stream has been fully delivered and no more will be transmitted. 999 | #[fail(display = "the stream has been completely received")] 1000 | Finished, 1001 | /// The connection was closed. 1002 | #[fail(display = "connection closed: {}", _0)] 1003 | ConnectionClosed(ConnectionError), 1004 | } 1005 | 1006 | struct Timer { 1007 | conn: ConnectionHandle, 1008 | ty: quicr::Timer, 1009 | delay: Delay, 1010 | cancel: Option>, 1011 | } 1012 | 1013 | impl Future for Timer { 1014 | type Item = Option<(ConnectionHandle, quicr::Timer)>; 1015 | type Error = (); // FIXME 1016 | fn poll(&mut self) -> Poll { 1017 | if let Some(ref mut cancel) = self.cancel { 1018 | if let Ok(Async::NotReady) = cancel.poll() {} 1019 | else { 1020 | return Ok(Async::Ready(None)); 1021 | } 1022 | } 1023 | match self.delay.poll() { 1024 | Err(e) => panic!("unexpected timer error: {}", e), 1025 | Ok(Async::NotReady) => Ok(Async::NotReady), 1026 | Ok(Async::Ready(())) => Ok(Async::Ready(Some((self.conn, self.ty)))), 1027 | } 1028 | } 1029 | } 1030 | 1031 | /// A stream of QUIC streams initiated by a remote peer. 1032 | pub struct IncomingStreams(Rc); 1033 | 1034 | /// A stream initiated by a remote peer. 1035 | pub enum NewStream { 1036 | /// A unidirectional stream. 1037 | Uni(RecvStream), 1038 | /// A bidirectional stream. 1039 | Bi(Stream), 1040 | } 1041 | 1042 | impl FuturesStream for IncomingStreams { 1043 | type Item = NewStream; 1044 | type Error = ConnectionError; 1045 | fn poll(&mut self) -> Poll, Self::Error> { 1046 | let mut endpoint = self.0.endpoint.0.borrow_mut(); 1047 | let pending = endpoint.pending.get_mut(&self.0.conn).unwrap(); 1048 | if let Some(x) = pending.incoming_streams.pop_front() { 1049 | let stream = Stream::new(self.0.clone(), x); 1050 | let stream = if x.directionality() == Directionality::Uni { 1051 | NewStream::Uni(RecvStream(stream)) 1052 | } else { 1053 | NewStream::Bi(stream) 1054 | }; 1055 | return Ok(Async::Ready(Some(stream))); 1056 | } 1057 | if let Some(ref x) = pending.error { 1058 | Err(x.clone()) 1059 | } else { 1060 | pending.incoming_streams_reader = Some(task::current()); 1061 | Ok(Async::NotReady) 1062 | } 1063 | } 1064 | } 1065 | 1066 | /// A stream of session tickets supplied by the server. 1067 | pub struct IncomingSessionTickets(Rc); 1068 | 1069 | impl FuturesStream for IncomingSessionTickets { 1070 | type Item = Box<[u8]>; 1071 | type Error = ConnectionError; 1072 | fn poll(&mut self) -> Poll, Self::Error> { 1073 | let mut endpoint = self.0.endpoint.0.borrow_mut(); 1074 | let pending = endpoint.pending.get_mut(&self.0.conn).unwrap(); 1075 | if let Some(x) = pending.incoming_session_tickets.pop_front() { 1076 | return Ok(Async::Ready(Some(x))); 1077 | } 1078 | if let Some(ref x) = pending.error { 1079 | Err(x.clone()) 1080 | } else if pending.drained { 1081 | return Ok(Async::Ready(None)); 1082 | } else { 1083 | pending.incoming_session_tickets_reader = Some(task::current()); 1084 | Ok(Async::NotReady) 1085 | } 1086 | } 1087 | } 1088 | 1089 | /// Uses unordered reads to be more efficient than using `AsyncRead` would allow 1090 | pub fn read_to_end(stream: T, size_limit: usize) -> ReadToEnd { 1091 | ReadToEnd { stream: Some(stream), size_limit, buffer: Vec::new() } 1092 | } 1093 | 1094 | /// Future produced by `read_to_end` 1095 | pub struct ReadToEnd { 1096 | stream: Option, 1097 | buffer: Vec, 1098 | size_limit: usize, 1099 | } 1100 | 1101 | impl Future for ReadToEnd { 1102 | type Item = (T, Box<[u8]>); 1103 | type Error = ReadError; 1104 | fn poll(&mut self) -> Poll { 1105 | loop { 1106 | match self.stream.as_mut().unwrap().poll_read_unordered() { 1107 | Ok(Async::Ready((data, offset))) => { 1108 | let len = self.buffer.len().max(offset as usize + data.len()); 1109 | if len > self.size_limit { return Err(ReadError::Finished); } 1110 | self.buffer.resize(len, 0); 1111 | self.buffer[offset as usize..offset as usize+data.len()].copy_from_slice(&data); 1112 | } 1113 | Ok(Async::NotReady) => { return Ok(Async::NotReady); } 1114 | Err(ReadError::Finished) => { 1115 | return Ok(Async::Ready((self.stream.take().unwrap(), mem::replace(&mut self.buffer, Vec::new()).into()))); 1116 | } 1117 | Err(e) => { return Err(e); } 1118 | } 1119 | } 1120 | } 1121 | } 1122 | --------------------------------------------------------------------------------