Bug 1596069 - Update neqo to version 0.1.6 r=agrover
authorDragana Damjanovic <dd.mozilla@gmail.com>
Sun, 17 Nov 2019 03:30:04 +0000
changeset 502331 69773bf582aaf07359f93e043c45728bb2224b31
parent 502330 c4a8c476bbe5a63a86298d6b13858740f3261d80
child 502332 b10aec041377e78814a6e6073cdead9e817bef00
push id114172
push userdluca@mozilla.com
push dateTue, 19 Nov 2019 11:31:10 +0000
treeherdermozilla-inbound@b5c5ba07d3db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersagrover
bugs1596069
milestone72.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1596069 - Update neqo to version 0.1.6 r=agrover Differential Revision: https://phabricator.services.mozilla.com/D53327
.cargo/config.in
Cargo.lock
netwerk/socket/neqo_glue/Cargo.toml
third_party/rust/neqo-common/.cargo-checksum.json
third_party/rust/neqo-common/Cargo.toml
third_party/rust/neqo-common/src/log.rs
third_party/rust/neqo-common/tests/log.rs
third_party/rust/neqo-crypto/.cargo-checksum.json
third_party/rust/neqo-crypto/Cargo.toml
third_party/rust/neqo-crypto/build.rs
third_party/rust/neqo-crypto/src/agent.rs
third_party/rust/neqo-crypto/src/agentio.rs
third_party/rust/neqo-crypto/src/err.rs
third_party/rust/neqo-http3/.cargo-checksum.json
third_party/rust/neqo-http3/Cargo.toml
third_party/rust/neqo-http3/src/connection.rs
third_party/rust/neqo-http3/src/connection_client.rs
third_party/rust/neqo-http3/src/connection_server.rs
third_party/rust/neqo-http3/src/control_stream_local.rs
third_party/rust/neqo-http3/src/control_stream_remote.rs
third_party/rust/neqo-http3/src/hframe.rs
third_party/rust/neqo-http3/src/lib.rs
third_party/rust/neqo-http3/src/server.rs
third_party/rust/neqo-http3/src/server_connection_events.rs
third_party/rust/neqo-http3/src/server_events.rs
third_party/rust/neqo-http3/src/stream_type_reader.rs
third_party/rust/neqo-http3/src/transaction_client.rs
third_party/rust/neqo-http3/src/transaction_server.rs
third_party/rust/neqo-http3/tests/httpconn.rs
third_party/rust/neqo-qpack/.cargo-checksum.json
third_party/rust/neqo-qpack/Cargo.toml
third_party/rust/neqo-qpack/src/decoder.rs
third_party/rust/neqo-qpack/src/encoder.rs
third_party/rust/neqo-transport/.cargo-checksum.json
third_party/rust/neqo-transport/Cargo.toml
third_party/rust/neqo-transport/src/connection.rs
third_party/rust/neqo-transport/src/crypto.rs
third_party/rust/neqo-transport/src/dump.rs
third_party/rust/neqo-transport/src/flow_mgr.rs
third_party/rust/neqo-transport/src/frame.rs
third_party/rust/neqo-transport/src/recovery.rs
third_party/rust/neqo-transport/src/recv_stream.rs
third_party/rust/neqo-transport/src/send_stream.rs
third_party/rust/neqo-transport/src/server.rs
third_party/rust/neqo-transport/src/tracking.rs
--- a/.cargo/config.in
+++ b/.cargo/config.in
@@ -10,17 +10,17 @@ replace-with = "vendored-sources"
 [source."https://github.com/mozilla/rkv"]
 git = "https://github.com/mozilla/rkv"
 replace-with = "vendored-sources"
 rev = "6a866fdad2ca880df9b87fcbc9921abac1e91914"
 
 [source."https://github.com/mozilla/neqo"]
 git = "https://github.com/mozilla/neqo"
 replace-with = "vendored-sources"
-rev = "a17c1e83"
+tag = "v0.1.6"
 
 [source."https://github.com/kvark/spirv_cross"]
 branch = "wgpu"
 git = "https://github.com/kvark/spirv_cross"
 replace-with = "vendored-sources"
 
 [source."https://github.com/kvark/rust-objc-exception"]
 branch = "cc"
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2296,86 +2296,86 @@ dependencies = [
 
 [[package]]
 name = "murmurhash3"
 version = "0.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "neqo-common"
-version = "0.1.4"
-source = "git+https://github.com/mozilla/neqo?rev=a17c1e83#a17c1e83bb44ed923eb16a4c675ffe569b3a08f3"
+version = "0.1.6"
+source = "git+https://github.com/mozilla/neqo?tag=v0.1.6#c110c2e09a36707934271d95a4bf5f44d6753dd5"
 dependencies = [
  "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "neqo-crypto"
-version = "0.1.4"
-source = "git+https://github.com/mozilla/neqo?rev=a17c1e83#a17c1e83bb44ed923eb16a4c675ffe569b3a08f3"
+version = "0.1.6"
+source = "git+https://github.com/mozilla/neqo?tag=v0.1.6#c110c2e09a36707934271d95a4bf5f44d6753dd5"
 dependencies = [
  "bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "neqo-common 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
+ "neqo-common 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
  "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "neqo-http3"
-version = "0.1.4"
-source = "git+https://github.com/mozilla/neqo?rev=a17c1e83#a17c1e83bb44ed923eb16a4c675ffe569b3a08f3"
+version = "0.1.6"
+source = "git+https://github.com/mozilla/neqo?tag=v0.1.6#c110c2e09a36707934271d95a4bf5f44d6753dd5"
 dependencies = [
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "neqo-common 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
- "neqo-crypto 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
- "neqo-qpack 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
- "neqo-transport 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
+ "neqo-common 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
+ "neqo-crypto 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
+ "neqo-qpack 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
+ "neqo-transport 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
  "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "neqo-qpack"
-version = "0.1.4"
-source = "git+https://github.com/mozilla/neqo?rev=a17c1e83#a17c1e83bb44ed923eb16a4c675ffe569b3a08f3"
+version = "0.1.6"
+source = "git+https://github.com/mozilla/neqo?tag=v0.1.6#c110c2e09a36707934271d95a4bf5f44d6753dd5"
 dependencies = [
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "neqo-common 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
- "neqo-crypto 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
- "neqo-transport 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
+ "neqo-common 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
+ "neqo-crypto 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
+ "neqo-transport 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
 ]
 
 [[package]]
 name = "neqo-transport"
-version = "0.1.4"
-source = "git+https://github.com/mozilla/neqo?rev=a17c1e83#a17c1e83bb44ed923eb16a4c675ffe569b3a08f3"
+version = "0.1.6"
+source = "git+https://github.com/mozilla/neqo?tag=v0.1.6#c110c2e09a36707934271d95a4bf5f44d6753dd5"
 dependencies = [
  "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "neqo-common 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
- "neqo-crypto 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
+ "neqo-common 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
+ "neqo-crypto 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
  "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "slice-deque 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "neqo_glue"
 version = "0.1.0"
 dependencies = [
- "neqo-common 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
- "neqo-crypto 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
- "neqo-http3 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
- "neqo-transport 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)",
+ "neqo-common 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
+ "neqo-crypto 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
+ "neqo-http3 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
+ "neqo-transport 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)",
  "nserror 0.1.0",
  "nsstring 0.1.0",
  "thin-vec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "xpcom 0.1.0",
 ]
 
 [[package]]
 name = "net2"
@@ -3165,17 +3165,17 @@ name = "rust_cascade"
 version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "bit_reverse 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "murmurhash3 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-demangle"
 version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -4670,21 +4670,21 @@ dependencies = [
 "checksum mio-named-pipes 0.1.6 (git+https://github.com/alexcrichton/mio-named-pipes)" = "<none>"
 "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125"
 "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
 "checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226"
 "checksum moz_cbor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20c82a57087fd5990d7122dbff1607c3b20c3d2958e9d9ad9765aab415e2c91c"
 "checksum mp4parse_fallible 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6626c2aef76eb8f984eef02e475883d3fe9112e114720446c5810fc5f045cd30"
 "checksum msdos_time 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aad9dfe950c057b1bfe9c1f2aa51583a8468ef2a5baba2ebbe06d775efeb7729"
 "checksum murmurhash3 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a2983372caf4480544083767bf2d27defafe32af49ab4df3a0b7fc90793a3664"
-"checksum neqo-common 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)" = "<none>"
-"checksum neqo-crypto 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)" = "<none>"
-"checksum neqo-http3 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)" = "<none>"
-"checksum neqo-qpack 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)" = "<none>"
-"checksum neqo-transport 0.1.4 (git+https://github.com/mozilla/neqo?rev=a17c1e83)" = "<none>"
+"checksum neqo-common 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)" = "<none>"
+"checksum neqo-crypto 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)" = "<none>"
+"checksum neqo-http3 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)" = "<none>"
+"checksum neqo-qpack 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)" = "<none>"
+"checksum neqo-transport 0.1.6 (git+https://github.com/mozilla/neqo?tag=v0.1.6)" = "<none>"
 "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
 "checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"
 "checksum nix 0.13.1 (git+https://github.com/shravanrn/nix/?branch=r0.13.1)" = "<none>"
 "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
 "checksum nom 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9c349f68f25f596b9f44cf0e7c69752a5c633b0550c3ff849518bfba0233774a"
 "checksum num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1"
 "checksum num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "eafd0b45c5537c3ba526f79d3e75120036502bebacbb3f3220914067ce39dbf2"
 "checksum num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c8b15b261814f992e33760b1fca9fe8b693d8a65299f20c9901688636cfb746"
--- a/netwerk/socket/neqo_glue/Cargo.toml
+++ b/netwerk/socket/neqo_glue/Cargo.toml
@@ -3,21 +3,21 @@ name = "neqo_glue"
 version = "0.1.0"
 authors = ["Dragana Damjanovic <dd.mozilla@gmail.com>"]
 edition = "2018"
 
 [lib]
 name = "neqo_glue"
 
 [dependencies]
-neqo-http3 = { rev = "a17c1e83", git = "https://github.com/mozilla/neqo" }
-neqo-transport = { rev = "a17c1e83", git = "https://github.com/mozilla/neqo" }
-neqo-common = { rev = "a17c1e83", git = "https://github.com/mozilla/neqo" }
+neqo-http3 = { tag = "v0.1.6", git = "https://github.com/mozilla/neqo" }
+neqo-transport = { tag = "v0.1.6", git = "https://github.com/mozilla/neqo" }
+neqo-common = { tag = "v0.1.6", git = "https://github.com/mozilla/neqo" }
 nserror = { path = "../../../xpcom/rust/nserror" }
 nsstring = { path = "../../../xpcom/rust/nsstring" }
 xpcom = { path = "../../../xpcom/rust/xpcom" }
 thin-vec = { version = "0.1.0", features = ["gecko-ffi"] }
 
 [dependencies.neqo-crypto]
-rev = "a17c1e83"
+tag = "v0.1.6"
 git = "https://github.com/mozilla/neqo"
 default-features = false
 features = ["gecko"]
--- a/third_party/rust/neqo-common/.cargo-checksum.json
+++ b/third_party/rust/neqo-common/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"6791b2f6143d31a8b2511e995a1ca902e0827f8cefdd966a477ad11068602e80","src/codec.rs":"6c619c42d1293297fd1e1763213033a82723bfa97938f5dd9fde6745f965940e","src/datagram.rs":"47d69797b66108cec997375818cb43ba9575b89f8730277047c6889de09b12aa","src/incrdecoder.rs":"4d55c9d992a4c409e4b4e37a8c04d3741d2ba260f46d5385cb3eff5121db03de","src/lib.rs":"7204f3eb32908563ffd50e615534326509be781cb5afd111f3bccdd6cf04249c","src/log.rs":"68a0a30344edcfad6c222eed62f5810fb9aa896fea7ec782b6ca2b2fc9a0bd4b","src/once.rs":"ad0d1ac0233dda75e294b5ccab65caceaec66d277659e22b1236aceea0c53ede","src/timer.rs":"13fb2ad4ef435d57895c61c291aca82a261c93c0f2cae2634929fb6ca5fdac85","tests/log.rs":"79e01eeef039d1abb17aadb2212256ad064c53e6d72bbebe254230119a623510"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"0132063e21304df128d64381c01694c31d7775c1f3d72f169ea9d4547d7024cf","src/codec.rs":"6c619c42d1293297fd1e1763213033a82723bfa97938f5dd9fde6745f965940e","src/datagram.rs":"47d69797b66108cec997375818cb43ba9575b89f8730277047c6889de09b12aa","src/incrdecoder.rs":"4d55c9d992a4c409e4b4e37a8c04d3741d2ba260f46d5385cb3eff5121db03de","src/lib.rs":"7204f3eb32908563ffd50e615534326509be781cb5afd111f3bccdd6cf04249c","src/log.rs":"943e4e332400d94805d60f965d1d0ae7aad180f6d5b50936d0bd9e085bbc1502","src/once.rs":"ad0d1ac0233dda75e294b5ccab65caceaec66d277659e22b1236aceea0c53ede","src/timer.rs":"13fb2ad4ef435d57895c61c291aca82a261c93c0f2cae2634929fb6ca5fdac85","tests/log.rs":"1c7ae6cb43047877fff27f3d01abc8ac456ea0907e88473d0179215342391d5d"},"package":null}
\ No newline at end of file
--- a/third_party/rust/neqo-common/Cargo.toml
+++ b/third_party/rust/neqo-common/Cargo.toml
@@ -1,11 +1,11 @@
 [package]
 name = "neqo-common"
-version = "0.1.4"
+version = "0.1.6"
 authors = ["Bobby Holley <bobbyholley@gmail.com>"]
 edition = "2018"
 license = "MIT/Apache-2.0"
 
 [dependencies]
 num-traits = "0.2"
 log = "0.4.0"
 env_logger = "0.6.1"
--- a/third_party/rust/neqo-common/src/log.rs
+++ b/third_party/rust/neqo-common/src/log.rs
@@ -42,35 +42,30 @@ macro_rules! qlog {
     ($lvl:expr, $ctx:expr, $($arg:tt)*) => ( {
         ::neqo_common::log::init();
         ::log::log!($lvl, "[{}] {}", $ctx, format!($($arg)*));
     } )
 }
 #[macro_export]
 macro_rules! qerror {
     ([$ctx:expr], $($arg:tt)*) => (::neqo_common::qlog!(::log::Level::Error, $ctx, $($arg)*););
-    ([$ctx:expr] $($arg:tt)*) => (::neqo_common::qlog!(::log::Level::Error, $ctx, $($arg)*););
     ($($arg:tt)*) => ( { ::neqo_common::log::init(); ::log::log!(::log::Level::Error, $($arg)*); } );
 }
 #[macro_export]
 macro_rules! qwarn {
     ([$ctx:expr], $($arg:tt)*) => (::neqo_common::qlog!(::log::Level::Warn, $ctx, $($arg)*););
-    ([$ctx:expr] $($arg:tt)*) => (::neqo_common::qlog!(::log::Level::Warn, $ctx, $($arg)*););
     ($($arg:tt)*) => ( { ::neqo_common::log::init(); ::log::log!(::log::Level::Warn, $($arg)*); } );
 }
 #[macro_export]
 macro_rules! qinfo {
     ([$ctx:expr], $($arg:tt)*) => (::neqo_common::qlog!(::log::Level::Info, $ctx, $($arg)*););
-    ([$ctx:expr] $($arg:tt)*) => (::neqo_common::qlog!(::log::Level::Info, $ctx, $($arg)*););
     ($($arg:tt)*) => ( { ::neqo_common::log::init(); ::log::log!(::log::Level::Info, $($arg)*); } );
 }
 #[macro_export]
 macro_rules! qdebug {
     ([$ctx:expr], $($arg:tt)*) => (::neqo_common::qlog!(::log::Level::Debug, $ctx, $($arg)*););
-    ([$ctx:expr] $($arg:tt)*) => (::neqo_common::qlog!(::log::Level::Debug, $ctx, $($arg)*););
     ($($arg:tt)*) => ( { ::neqo_common::log::init(); ::log::log!(::log::Level::Debug, $($arg)*); } );
 }
 #[macro_export]
 macro_rules! qtrace {
     ([$ctx:expr], $($arg:tt)*) => (::neqo_common::qlog!(::log::Level::Trace, $ctx, $($arg)*););
-    ([$ctx:expr] $($arg:tt)*) => (::neqo_common::qlog!(::log::Level::Trace, $ctx, $($arg)*););
     ($($arg:tt)*) => ( { ::neqo_common::log::init(); ::log::log!(::log::Level::Trace, $($arg)*); } );
 }
--- a/third_party/rust/neqo-common/tests/log.rs
+++ b/third_party/rust/neqo-common/tests/log.rs
@@ -26,21 +26,21 @@ fn args() {
     qinfo!("info {} {:?}", num, obj);
     qdebug!("debug {} {:?}", num, obj);
     qtrace!("trace {} {:?}", num, obj);
 }
 
 #[test]
 fn context() {
     let context = "context";
-    qerror!([context] "error");
-    qwarn!([context] "warn");
-    qinfo!([context] "info");
-    qdebug!([context] "debug");
-    qtrace!([context] "trace");
+    qerror!([context], "error");
+    qwarn!([context], "warn");
+    qinfo!([context], "info");
+    qdebug!([context], "debug");
+    qtrace!([context], "trace");
 }
 
 #[test]
 fn context_comma() {
     let obj = vec![1, 2, 3];
     let context = "context";
     qerror!([context], "error {:?}", obj);
     qwarn!([context], "warn {:?}", obj);
--- a/third_party/rust/neqo-crypto/.cargo-checksum.json
+++ b/third_party/rust/neqo-crypto/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"d7afc57115b1915c379e45550e58e5b09245db87affd7a55b8b733a852a542a0","TODO":"ac0f1c2ebcca03f5b3c0cc56c5aedbb030a4b511e438bc07a57361c789f91e9f","bindings/bindings.toml":"0f305bda9513e7fb4b521df79912ad5ba21784377b84f4b531895619e561f356","bindings/mozpkix.hpp":"77072c8bb0f6eb6bfe8cbadc111dcd92e0c79936d13f2e501aae1e5d289a6675","bindings/nspr_err.h":"2d5205d017b536c2d838bcf9bc4ec79f96dd50e7bb9b73892328781f1ee6629d","bindings/nspr_error.h":"e41c03c77b8c22046f8618832c9569fbcc7b26d8b9bbc35eea7168f35e346889","bindings/nspr_io.h":"085b289849ef0e77f88512a27b4d9bdc28252bd4d39c6a17303204e46ef45f72","bindings/nspr_time.h":"2e637fd338a5cf0fd3fb0070a47f474a34c2a7f4447f31b6875f5a9928d0a261","bindings/nss_ciphers.h":"95ec6344a607558b3c5ba8510f463b6295f3a2fb3f538a01410531045a5f62d1","bindings/nss_init.h":"ef49045063782fb612aff459172cc6a89340f15005808608ade5320ca9974310","bindings/nss_p11.h":"0b81e64fe6db49b2ecff94edd850be111ef99ec11220e88ceb1c67be90143a78","bindings/nss_secerr.h":"713e8368bdae5159af7893cfa517dabfe5103cede051dee9c9557c850a2defc6","bindings/nss_ssl.h":"af222fb957b989e392e762fa2125c82608a0053aff4fb97e556691646c88c335","bindings/nss_sslerr.h":"24b97f092183d8486f774cdaef5030d0249221c78343570d83a4ee5b594210ae","bindings/nss_sslopt.h":"b7807eb7abdad14db6ad7bc51048a46b065a0ea65a4508c95a12ce90e59d1eea","build.rs":"ebb685e47de005413d8e24370ba22576b45b0273aaf0a5116af96dcdc48d32c0","src/aead.rs":"bfbd4b72354fb7103ff31a2a600dd457e10fdc14ad670a5de1f5bb0f9b6e1504","src/agent.rs":"b8f59b2f1d3432db0b810383c2ae6d17a79b89819b90da50eecc3370cae77398","src/agentio.rs":"615a805e0f27970755daa5bfe864b2e9b3b09309dfa4178b85f38a13ae6f7131","src/auth.rs":"846a4954186f0bcabc4084214ae216819215f3bccc33cc08d93abb9c5fefb7f2","src/cert.rs":"fd3fd2bbb38754bdcee3898549feae412943c9f719032531c1ad6e61783b5394","src/constants.rs":"75dec8e3c74326f492a115a0e7a487daba32eba30bcbd64d2223333b3caa4008","src/err.rs":"81d5c9b75457d4367607d0a456c276fa037c0f66a1c8df40af58ff42426c9890","src/exp.rs":"61586662407359c1ecb8ed4987bc3c702f26ba2e203a091a51b6d6363cbd510f","src/ext.rs":"f3cc5bfdd96d46affff43653258d91eb447251f83da19b37dd415129052413e3","src/hkdf.rs":"6d44f63493f0c558a23339f88fe766f8afdb0bda3dc11a79e8a99d3c8d0b6acb","src/hp.rs":"854ce7b9d44892fbb01ac4078b84266771a9254cebfea5b94e7f4b4a7fb1b946","src/lib.rs":"6c3540b4e54510f6a298f04093f44f6d957f30f475214fd3ec9e39fa4d98e386","src/p11.rs":"89df482ae683646add0f46333991f31fe996fdce67859a1ff37c090a4166ce6e","src/prio.rs":"0e213056f6bf0c797c2cfe13c6d14dbb64a64b1218fff21cbf36fb3309b852f9","src/replay.rs":"01eae2accfefbc26719fcccd4bcb8c1ea6400ab96fbb696ecdb8f32164f931a2","src/result.rs":"d76c7bc5e99c80a5a124909ab586cdb91d894856e52f5146430da43584a6d6c1","src/secrets.rs":"e929b69927d93b4bde3bd490c0ed9a4e1e4c5a047492259ab1dae7fbad885c22","src/selfencrypt.rs":"9bffad6af2f186f606bd7305a8528d76e66471a71f7103c7498b90507fb031e1","src/ssl.rs":"4c7c850777a1b4b7b66ad765e24a25780e64f24da08175b5cc722a840d35f693","src/time.rs":"4dffa6f4ac9cfc8db240c370fb04a7d7241c80793ecf6acda2d41d0bc94b0236","tests/aead.rs":"bedf985ba0b95a9c6db6a84f870d15062d821f3b24cb3cb9dfa89445be795d50","tests/agent.rs":"8b9ca3c182cf065b7668fd9c7e5885b1cde8bb1d0ea3afbb5fb7a3186d7a9d2e","tests/ext.rs":"b1d2f9d68d18e24df5f246e4ad6f80a0a0d98f824094a9fa447a580b02486d90","tests/handshake.rs":"2752bd6c575e7d28db2bce8484aa08ba08846f30aa0bb9aa07153d1763dab830","tests/hkdf.rs":"83300020a18d5485a1adcd3b806aed64fd008072589875112145f401340f3602","tests/hp.rs":"83f453a792ef17eb51a20b2764407c28a60620f5d3b917c8e237a121b32988df","tests/init.rs":"abb08d3d5d9610d62dc94535230ed4f52743d90b7059224b152caa8cf7cf43d7","tests/selfencrypt.rs":"365bc96be63d2e970bab7cf0134a59526513e1c1c3b854c34fa44fc8ed8c10d3"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"f238c080977551a9301b25aa52362b19dae1ad1fdeda2b3f47d21752e13e37bf","TODO":"ac0f1c2ebcca03f5b3c0cc56c5aedbb030a4b511e438bc07a57361c789f91e9f","bindings/bindings.toml":"0f305bda9513e7fb4b521df79912ad5ba21784377b84f4b531895619e561f356","bindings/mozpkix.hpp":"77072c8bb0f6eb6bfe8cbadc111dcd92e0c79936d13f2e501aae1e5d289a6675","bindings/nspr_err.h":"2d5205d017b536c2d838bcf9bc4ec79f96dd50e7bb9b73892328781f1ee6629d","bindings/nspr_error.h":"e41c03c77b8c22046f8618832c9569fbcc7b26d8b9bbc35eea7168f35e346889","bindings/nspr_io.h":"085b289849ef0e77f88512a27b4d9bdc28252bd4d39c6a17303204e46ef45f72","bindings/nspr_time.h":"2e637fd338a5cf0fd3fb0070a47f474a34c2a7f4447f31b6875f5a9928d0a261","bindings/nss_ciphers.h":"95ec6344a607558b3c5ba8510f463b6295f3a2fb3f538a01410531045a5f62d1","bindings/nss_init.h":"ef49045063782fb612aff459172cc6a89340f15005808608ade5320ca9974310","bindings/nss_p11.h":"0b81e64fe6db49b2ecff94edd850be111ef99ec11220e88ceb1c67be90143a78","bindings/nss_secerr.h":"713e8368bdae5159af7893cfa517dabfe5103cede051dee9c9557c850a2defc6","bindings/nss_ssl.h":"af222fb957b989e392e762fa2125c82608a0053aff4fb97e556691646c88c335","bindings/nss_sslerr.h":"24b97f092183d8486f774cdaef5030d0249221c78343570d83a4ee5b594210ae","bindings/nss_sslopt.h":"b7807eb7abdad14db6ad7bc51048a46b065a0ea65a4508c95a12ce90e59d1eea","build.rs":"0a4eaffefed2e190286a0de3eb69cd860ed4aea215d58a7135331b1850a5f82d","src/aead.rs":"bfbd4b72354fb7103ff31a2a600dd457e10fdc14ad670a5de1f5bb0f9b6e1504","src/agent.rs":"2539f4d1c471457208af0597c61a30e7abb1295d1442e6ed8fbbd83811c3dff6","src/agentio.rs":"25b87af28366d32671770900bed3bf093b141cc92c5193be71e4f748eea2a313","src/auth.rs":"846a4954186f0bcabc4084214ae216819215f3bccc33cc08d93abb9c5fefb7f2","src/cert.rs":"fd3fd2bbb38754bdcee3898549feae412943c9f719032531c1ad6e61783b5394","src/constants.rs":"75dec8e3c74326f492a115a0e7a487daba32eba30bcbd64d2223333b3caa4008","src/err.rs":"d2ee7e2e024acb8894fe0a9e028e6627dad19368808df1d52d321f1b8a159dca","src/exp.rs":"61586662407359c1ecb8ed4987bc3c702f26ba2e203a091a51b6d6363cbd510f","src/ext.rs":"f3cc5bfdd96d46affff43653258d91eb447251f83da19b37dd415129052413e3","src/hkdf.rs":"6d44f63493f0c558a23339f88fe766f8afdb0bda3dc11a79e8a99d3c8d0b6acb","src/hp.rs":"854ce7b9d44892fbb01ac4078b84266771a9254cebfea5b94e7f4b4a7fb1b946","src/lib.rs":"6c3540b4e54510f6a298f04093f44f6d957f30f475214fd3ec9e39fa4d98e386","src/p11.rs":"89df482ae683646add0f46333991f31fe996fdce67859a1ff37c090a4166ce6e","src/prio.rs":"0e213056f6bf0c797c2cfe13c6d14dbb64a64b1218fff21cbf36fb3309b852f9","src/replay.rs":"01eae2accfefbc26719fcccd4bcb8c1ea6400ab96fbb696ecdb8f32164f931a2","src/result.rs":"d76c7bc5e99c80a5a124909ab586cdb91d894856e52f5146430da43584a6d6c1","src/secrets.rs":"e929b69927d93b4bde3bd490c0ed9a4e1e4c5a047492259ab1dae7fbad885c22","src/selfencrypt.rs":"9bffad6af2f186f606bd7305a8528d76e66471a71f7103c7498b90507fb031e1","src/ssl.rs":"4c7c850777a1b4b7b66ad765e24a25780e64f24da08175b5cc722a840d35f693","src/time.rs":"4dffa6f4ac9cfc8db240c370fb04a7d7241c80793ecf6acda2d41d0bc94b0236","tests/aead.rs":"bedf985ba0b95a9c6db6a84f870d15062d821f3b24cb3cb9dfa89445be795d50","tests/agent.rs":"8b9ca3c182cf065b7668fd9c7e5885b1cde8bb1d0ea3afbb5fb7a3186d7a9d2e","tests/ext.rs":"b1d2f9d68d18e24df5f246e4ad6f80a0a0d98f824094a9fa447a580b02486d90","tests/handshake.rs":"2752bd6c575e7d28db2bce8484aa08ba08846f30aa0bb9aa07153d1763dab830","tests/hkdf.rs":"83300020a18d5485a1adcd3b806aed64fd008072589875112145f401340f3602","tests/hp.rs":"83f453a792ef17eb51a20b2764407c28a60620f5d3b917c8e237a121b32988df","tests/init.rs":"abb08d3d5d9610d62dc94535230ed4f52743d90b7059224b152caa8cf7cf43d7","tests/selfencrypt.rs":"365bc96be63d2e970bab7cf0134a59526513e1c1c3b854c34fa44fc8ed8c10d3"},"package":null}
\ No newline at end of file
--- a/third_party/rust/neqo-crypto/Cargo.toml
+++ b/third_party/rust/neqo-crypto/Cargo.toml
@@ -1,11 +1,11 @@
 [package]
 name = "neqo-crypto"
-version = "0.1.4"
+version = "0.1.6"
 authors = ["Martin Thomson <mt@lowentropy.net>"]
 edition = "2018"
 build = "build.rs"
 license = "MIT/Apache-2.0"
 
 [dependencies]
 neqo-common = { path = "../neqo-common" }
 log = "0.4.0"
--- a/third_party/rust/neqo-crypto/build.rs
+++ b/third_party/rust/neqo-crypto/build.rs
@@ -226,17 +226,19 @@ fn get_includes(nsstarget: &Path, nssdis
 fn build_bindings(base: &str, bindings: &Bindings, flags: &[String], gecko: bool) {
     let suffix = if bindings.cplusplus { ".hpp" } else { ".h" };
     let header_path = PathBuf::from(BINDINGS_DIR).join(String::from(base) + suffix);
     let header = header_path.to_str().unwrap();
     let out = PathBuf::from(env::var("OUT_DIR").unwrap()).join(String::from(base) + ".rs");
 
     println!("cargo:rerun-if-changed={}", header);
 
-    let mut builder = Builder::default().header(header).generate_comments(false);
+    let mut builder = Builder::default().header(header);
+    builder = builder.generate_comments(false);
+    builder = builder.derive_debug(false); // https://github.com/rust-lang/rust-bindgen/issues/372
 
     builder = builder.clang_arg("-v");
 
     if !gecko {
         builder = builder.clang_arg("-DNO_NSPR_10_SUPPORT");
         if env::consts::OS == "windows" {
             builder = builder.clang_arg("-DWIN");
         } else if env::consts::OS == "macos" {
--- a/third_party/rust/neqo-crypto/src/agent.rs
+++ b/third_party/rust/neqo-crypto/src/agent.rs
@@ -70,17 +70,17 @@ fn get_alpn(fd: *mut ssl::PRFileDesc, pr
             chosen.truncate(chosen_len as usize);
             Some(match String::from_utf8(chosen) {
                 Ok(a) => a,
                 _ => return Err(Error::InternalError),
             })
         }
         _ => None,
     };
-    qinfo!([format!("{:p}", fd)] "got ALPN {:?}", alpn);
+    qinfo!([format!("{:p}", fd)], "got ALPN {:?}", alpn);
     Ok(alpn)
 }
 
 pub struct SecretAgentPreInfo {
     info: ssl::SSLPreliminaryChannelInfo,
     alpn: Option<String>,
 }
 
@@ -285,17 +285,21 @@ impl SecretAgent {
         let alert = alert.as_ref().unwrap();
         if alert.level == 2 {
             // Fatal alerts demand attention.
             let p = arg as *mut Option<Alert>;
             let st = p.as_mut().unwrap();
             if st.is_none() {
                 *st = Some(alert.description);
             } else {
-                qwarn!([format!("{:p}", fd)] "duplicate alert {}", alert.description);
+                qwarn!(
+                    [format!("{:p}", fd)],
+                    "duplicate alert {}",
+                    alert.description
+                );
             }
         }
     }
 
     // TODO(mt) move to time.rs.
     unsafe extern "C" fn time_func(arg: *mut c_void) -> PRTime {
         let p = arg as *mut PRTime as *const PRTime;
         *p.as_ref().unwrap()
@@ -505,17 +509,17 @@ impl SecretAgent {
     pub fn authenticated(&mut self, status: AuthenticationStatus) {
         assert_eq!(self.state, HandshakeState::AuthenticationPending);
         *self.auth_required = false;
         self.state = HandshakeState::Authenticated(status.into());
     }
 
     fn capture_error<T>(&mut self, res: Res<T>) -> Res<T> {
         if let Err(e) = &res {
-            qwarn!([self] "error: {:?}", e);
+            qwarn!([self], "error: {:?}", e);
             self.state = HandshakeState::Failed(e.clone());
         }
         res
     }
 
     fn update_state(&mut self, res: Res<()>) -> Res<()> {
         self.state = if is_blocked(&res) {
             if *self.auth_required {
@@ -523,17 +527,17 @@ impl SecretAgent {
             } else {
                 HandshakeState::InProgress
             }
         } else {
             self.capture_error(res)?;
             let info = self.capture_error(SecretAgentInfo::new(self.fd))?;
             HandshakeState::Complete(info)
         };
-        qinfo!([self] "state -> {:?}", self.state);
+        qinfo!([self], "state -> {:?}", self.state);
         Ok(())
     }
 
     // Drive the TLS handshake, taking bytes from @input and putting
     // any bytes necessary into @output.
     // This takes the current time as @now.
     // On success a tuple of a HandshakeState and usize indicate whether the handshake
     // is complete and how many bytes were written to @output, respectively.
@@ -577,19 +581,19 @@ impl SecretAgent {
         if self.no_eoed {
             let mut read_epoch: u16 = 0;
             unsafe { ssl::SSL_GetCurrentEpoch(self.fd, &mut read_epoch, null_mut()) }?;
             if read_epoch == 1 {
                 // It's waiting for EndOfEarlyData, so feed one in.
                 // Note that this is the test that ensures that we only do this for the server.
                 let eoed = Record::new(1, 22, END_OF_EARLY_DATA);
                 self.capture_error(eoed.write(self.fd))?;
+                self.no_eoed = false;
             }
         }
-        self.no_eoed = false;
         Ok(())
     }
 
     // Drive the TLS handshake, but get the raw content of records, not
     // protected records as bytes. This function is incompatible with
     // handshake(); use either this or handshake() exclusively.
     //
     // Ideally, this only includes records from the current epoch.
@@ -597,17 +601,17 @@ impl SecretAgent {
     pub fn handshake_raw(&mut self, now: Instant, input: Option<Record>) -> Res<RecordList> {
         *self.now = Time::from(now).try_into()?;
         let mut records = self.setup_raw()?;
 
         // Fire off any authentication we might need to complete.
         if let HandshakeState::Authenticated(ref err) = self.state {
             let result =
                 secstatus_to_res(unsafe { ssl::SSL_AuthCertificateComplete(self.fd, *err) });
-            qdebug!([self] "SSL_AuthCertificateComplete: {:?}", result);
+            qdebug!([self], "SSL_AuthCertificateComplete: {:?}", result);
             // This should return SECSuccess, so don't use update_state().
             self.capture_error(result)?;
         }
 
         // Feed in any records.
         if let Some(rec) = input {
             if rec.epoch == 2 {
                 self.inject_eoed()?;
@@ -674,17 +678,17 @@ impl Client {
         token: *const u8,
         len: c_uint,
         arg: *mut c_void,
     ) -> ssl::SECStatus {
         let resumption_ptr = arg as *mut Option<Vec<u8>>;
         let resumption = resumption_ptr.as_mut().unwrap();
         let mut v = Vec::with_capacity(len as usize);
         v.extend_from_slice(std::slice::from_raw_parts(token, len as usize));
-        qdebug!([format!("{:p}", fd)] "Got resumption token");
+        qdebug!([format!("{:p}", fd)], "Got resumption token");
         *resumption = Some(v);
         ssl::SECSuccess
     }
 
     fn ready(&mut self) -> Res<()> {
         unsafe {
             ssl::SSL_SetResumptionTokenCallback(
                 self.fd,
--- a/third_party/rust/neqo-crypto/src/agentio.rs
+++ b/third_party/rust/neqo-crypto/src/agentio.rs
@@ -172,26 +172,26 @@ impl AgentIoInput {
     fn read_input(&mut self, buf: *mut u8, count: usize) -> Res<usize> {
         let amount = min(self.available, count);
         if amount == 0 {
             unsafe { PR_SetError(nspr::PR_WOULD_BLOCK_ERROR, 0) };
             return Err(Error::NoDataAvailable);
         }
 
         let src = unsafe { std::slice::from_raw_parts(self.input, amount) };
-        qtrace!([self] "read {}", hex(src));
+        qtrace!([self], "read {}", hex(src));
         let dst = unsafe { std::slice::from_raw_parts_mut(buf, amount) };
         dst.copy_from_slice(&src);
         self.input = self.input.wrapping_add(amount);
         self.available -= amount;
         Ok(amount)
     }
 
     fn reset(&mut self) {
-        qtrace!([self] "reset");
+        qtrace!([self], "reset");
         self.input = null();
         self.available = 0;
     }
 }
 
 impl ::std::fmt::Display for AgentIoInput {
     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
         write!(f, "AgentIoInput {:p}", self.input)
@@ -227,22 +227,22 @@ impl AgentIo {
     pub fn wrap<'a: 'c, 'b: 'c, 'c>(&'a mut self, input: &'b [u8]) -> AgentIoInputContext<'c> {
         assert_eq!(self.output.len(), 0);
         self.input.wrap(input)
     }
 
     // Stage output from TLS into the output buffer.
     fn save_output(&mut self, buf: *const u8, count: usize) {
         let slice = unsafe { std::slice::from_raw_parts(buf, count) };
-        qtrace!([self] "save output {}", hex(slice));
+        qtrace!([self], "save output {}", hex(slice));
         self.output.extend_from_slice(slice);
     }
 
     pub fn take_output(&mut self) -> Vec<u8> {
-        qtrace!([self] "take output");
+        qtrace!([self], "take output");
         mem::replace(&mut self.output, Vec::new())
     }
 }
 
 impl ::std::fmt::Display for AgentIo {
     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
         write!(f, "AgentIo")
     }
--- a/third_party/rust/neqo-crypto/src/err.rs
+++ b/third_party/rust/neqo-crypto/src/err.rs
@@ -183,10 +183,9 @@ mod tests {
             Error::NssError { name, code, desc } => {
                 assert_eq!(name, "PR_WOULD_BLOCK_ERROR");
                 assert_eq!(code, -5998);
                 assert_eq!(desc, "The operation would have blocked");
             }
             _ => panic!("bad error type"),
         }
     }
-
 }
--- a/third_party/rust/neqo-http3/.cargo-checksum.json
+++ b/third_party/rust/neqo-http3/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"bde1a1af255191ae9785b8f438fe72addc291496e4fa7d140437de5828aa6d8c","src/client_events.rs":"c7022955c4c7c1257204948a0a2a88ccd895dfdb64b62ff76e56bc989d066277","src/connection.rs":"5a3003fad10db9c92ae5c4728e6944e3fc3433555cd210300908f4bf55eabe4f","src/connection_client.rs":"96395301b0b82aa09f3684b6f8571cab9261a1590565ad67209b71b40f610d81","src/connection_server.rs":"ec6c6182f4522b2c8bddbd441790bc8f07f122c35292dc227779c7a7574d8a43","src/control_stream_local.rs":"8b685d5236ea59914ca91f6bd9613586ede581ca400e54e8f429f9e51580774b","src/control_stream_remote.rs":"94ba2cdeeb1e76e7bab7ed19ef02b9516fb4c13f496a4c8066f92230c62cf083","src/hframe.rs":"15dce78028666c12dbc99e252f3db8e87659da9260fc7bf0d2d182cb9e6d3081","src/lib.rs":"8b5607f7dee014e11771ea05b4ed52fcd1eafe146ee8ebee75da742921867b57","src/server_events.rs":"374b40c645443eae19a0a039f74e3f5353b1a6373c7a3089e9f270db9609596e","src/stream_type_reader.rs":"e96f55f9e1df4e894d4d93250a79a4a46db1669d8c17353b94525db0a75c774e","src/transaction_client.rs":"d2664b0eb6505c6de9ec86d5c422d30576c42896e6bbbf5c907a9fd7e01caecd","src/transaction_server.rs":"9c1eb5a7cc81269a063fa891aeae0fc93bf773f23ead8a177452ea2dc425ff09","tests/httpconn.rs":"7a78d258bb940c88b3b935e4e3c76c103fb4d400ddfad14107b17a15759eb3e9"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"2c3a091954d90040b9d2bc7df2e2e2e2457da21186d69d4fe30fcf4cf3888a66","src/client_events.rs":"c7022955c4c7c1257204948a0a2a88ccd895dfdb64b62ff76e56bc989d066277","src/connection.rs":"30a79c660e6945fd193ab0eb27bf22014c4d246a5ee361aad5a5586e3c03b39f","src/connection_client.rs":"362f4774003c5c3b51eda02e9975943de15d3f244178c208407c62115942e867","src/control_stream_local.rs":"319f8277fc4765b31a4a094bfd663e681d71831532925b0043bae5da96202e64","src/control_stream_remote.rs":"1b96316d6eecc582436382517fcffdb2bb4f9d73194301bc3e2e253d3322e95e","src/hframe.rs":"6e65670cfe5944e88a0631e39d077c8e9d225fde650c978405816f1b2028c9a1","src/lib.rs":"908cb880d6b68c35085b768b67e866d1db0d3212d3bd0e6a76daf0d670b79d1c","src/server.rs":"4819dcfe998f036501b4900ce489c03cc3e24c45ca8825354daff826f7157316","src/server_connection_events.rs":"6ae07ca2c54a8b733a2e4cdd5594838f530224e7bb8233ecd9d7ad0838842bf2","src/server_events.rs":"e0a19bfc88b91d0584c1ec08da3005aae192471cbc37809a977dd6098f4e7dcc","src/stream_type_reader.rs":"be1ea1f553292b5447f0d6d89bdfa73732189db236ce34b4067cda0276229540","src/transaction_client.rs":"2e4a2ca83bdc6583697ab5b6e8c2767b4fd46fd4215f4fe9cf79891ad5523bd6","src/transaction_server.rs":"98ba7522fb20936e056cce2bbd1098ee94e748a58e7b4609772c87c349b12d85","tests/httpconn.rs":"7955f6ac4406b5d770e0fb10258aff529a1c01020374dfc5f85d8608abb68f6f"},"package":null}
\ No newline at end of file
--- a/third_party/rust/neqo-http3/Cargo.toml
+++ b/third_party/rust/neqo-http3/Cargo.toml
@@ -1,11 +1,11 @@
 [package]
 name = "neqo-http3"
-version = "0.1.4"
+version = "0.1.6"
 authors = ["draganadamjanovic"]
 edition = "2018"
 license = "MIT/Apache-2.0"
 
 [dependencies]
 neqo-common = { path = "./../neqo-common" }
 neqo-crypto = { path = "./../neqo-crypto" }
 neqo-transport = { path = "./../neqo-transport" }
--- a/third_party/rust/neqo-http3/src/connection.rs
+++ b/third_party/rust/neqo-http3/src/connection.rs
@@ -3,34 +3,27 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
 use crate::client_events::Http3ClientEvents;
 use crate::control_stream_local::{ControlStreamLocal, HTTP3_UNI_STREAM_TYPE_CONTROL};
 use crate::control_stream_remote::ControlStreamRemote;
 use crate::hframe::{HFrame, HSettingType};
-use crate::server_events::Http3ServerEvents;
+use crate::server_connection_events::Http3ServerConnEvents;
 use crate::stream_type_reader::NewStreamTypeReader;
 use crate::transaction_client::TransactionClient;
 use crate::transaction_server::TransactionServer;
-use neqo_common::{matches, qdebug, qerror, qinfo, qtrace, qwarn, Datagram};
-use neqo_crypto::AntiReplay;
+use neqo_common::{matches, qdebug, qerror, qinfo, qtrace, qwarn};
 use neqo_qpack::decoder::{QPackDecoder, QPACK_UNI_STREAM_TYPE_DECODER};
 use neqo_qpack::encoder::{QPackEncoder, QPACK_UNI_STREAM_TYPE_ENCODER};
-use neqo_transport::{
-    AppError, CloseError, Connection, ConnectionEvent, ConnectionIdManager, Output, Role, State,
-    StreamType,
-};
-use std::cell::RefCell;
+use neqo_transport::{AppError, CloseError, Connection, ConnectionEvent, State, StreamType};
 use std::collections::{BTreeSet, HashMap};
 use std::fmt::Debug;
 use std::mem;
-use std::net::SocketAddr;
-use std::rc::Rc;
 use std::time::Instant;
 
 use crate::{Error, Res};
 
 const HTTP3_UNI_STREAM_TYPE_PUSH: u64 = 0x1;
 
 const MAX_HEADER_LIST_SIZE_DEFAULT: u64 = u64::max_value();
 
@@ -90,19 +83,19 @@ pub trait Http3Handler<E: Http3Events, T
 pub enum Http3State {
     Initializing,
     Connected,
     GoingAway,
     Closing(CloseError),
     Closed(CloseError),
 }
 
+#[derive(Debug)]
 pub struct Http3Connection<E: Http3Events, T: Http3Transaction, H: Http3Handler<E, T>> {
     pub state: Http3State,
-    pub conn: Connection,
     max_header_list_size: u64,
     control_stream_local: ControlStreamLocal,
     control_stream_remote: ControlStreamRemote,
     new_streams: HashMap<u64, NewStreamTypeReader>,
     pub qpack_encoder: QPackEncoder,
     pub qpack_decoder: QPackDecoder,
     settings_received: bool,
     streams_have_data_to_send: BTreeSet<u64>,
@@ -110,263 +103,185 @@ pub struct Http3Connection<E: Http3Event
     pub transactions: HashMap<u64, T>,
     handler: H,
 }
 
 impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>> ::std::fmt::Display
     for Http3Connection<E, T, H>
 {
     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
-        write!(f, "Http3 connection {:?}", self.role())
+        write!(f, "Http3 connection")
     }
 }
 
 impl<E: Http3Events + Default, T: Http3Transaction, H: Http3Handler<E, T>>
     Http3Connection<E, T, H>
 {
-    pub fn new_client(
-        server_name: &str,
-        protocols: &[impl AsRef<str>],
-        cid_manager: Rc<RefCell<dyn ConnectionIdManager>>,
-        local_addr: SocketAddr,
-        remote_addr: SocketAddr,
-        max_table_size: u32,
-        max_blocked_streams: u16,
-    ) -> Res<Self> {
+    pub fn new(max_table_size: u32, max_blocked_streams: u16) -> Self {
         if max_table_size > (1 << 30) - 1 {
             panic!("Wrong max_table_size");
         }
-        let conn =
-            Connection::new_client(server_name, protocols, cid_manager, local_addr, remote_addr)?;
-        Http3Connection::new_client_with_conn(conn, max_table_size, max_blocked_streams)
-    }
-
-    pub fn new_client_with_conn(
-        c: Connection,
-        max_table_size: u32,
-        max_blocked_streams: u16,
-    ) -> Res<Self> {
-        if max_table_size > (1 << 30) - 1 {
-            panic!("Wrong max_table_size");
-        }
-        Ok(Http3Connection {
+        Http3Connection {
             state: Http3State::Initializing,
-            conn: c,
             max_header_list_size: MAX_HEADER_LIST_SIZE_DEFAULT,
             control_stream_local: ControlStreamLocal::default(),
             control_stream_remote: ControlStreamRemote::new(),
             new_streams: HashMap::new(),
             qpack_encoder: QPackEncoder::new(true),
             qpack_decoder: QPackDecoder::new(max_table_size, max_blocked_streams),
             settings_received: false,
             streams_have_data_to_send: BTreeSet::new(),
             events: E::default(),
             transactions: HashMap::new(),
             handler: H::new(),
-        })
+        }
     }
 
-    pub fn new_server(
-        certs: &[impl AsRef<str>],
-        protocols: &[impl AsRef<str>],
-        anti_replay: &AntiReplay,
-        cid_manager: Rc<RefCell<dyn ConnectionIdManager>>,
-        max_table_size: u32,
-        max_blocked_streams: u16,
-    ) -> Res<Self> {
-        if max_table_size > (1 << 30) - 1 {
-            panic!("Wrong max_table_size");
-        }
-        Ok(Http3Connection {
-            state: Http3State::Initializing,
-            conn: Connection::new_server(certs, protocols, anti_replay, cid_manager)?,
-            max_header_list_size: MAX_HEADER_LIST_SIZE_DEFAULT,
-            control_stream_local: ControlStreamLocal::default(),
-            control_stream_remote: ControlStreamRemote::new(),
-            new_streams: HashMap::new(),
-            qpack_encoder: QPackEncoder::new(true),
-            qpack_decoder: QPackDecoder::new(max_table_size, max_blocked_streams),
-            settings_received: false,
-            streams_have_data_to_send: BTreeSet::new(),
-            events: E::default(),
-            transactions: HashMap::new(),
-            handler: H::new(),
-        })
-    }
+    fn initialize_http3_connection(&mut self, conn: &mut Connection) -> Res<()> {
+        qinfo!([self], "Initialize the http3 connection.");
+        self.control_stream_local.create(conn)?;
 
-    fn initialize_http3_connection(&mut self) -> Res<()> {
-        qinfo!([self] "Initialize the http3 connection.");
-        self.control_stream_local.create(&mut self.conn)?;
         self.send_settings();
-        self.create_qpack_streams()?;
+        self.create_qpack_streams(conn)?;
         Ok(())
     }
 
     fn send_settings(&mut self) {
-        qdebug!([self] "Send settings.");
+        qdebug!([self], "Send settings.");
         self.control_stream_local.queue_frame(HFrame::Settings {
             settings: vec![
                 (
                     HSettingType::MaxTableSize,
                     self.qpack_decoder.get_max_table_size().into(),
                 ),
                 (
                     HSettingType::BlockedStreams,
                     self.qpack_decoder.get_blocked_streams().into(),
                 ),
             ],
         });
     }
 
-    fn create_qpack_streams(&mut self) -> Res<()> {
-        qdebug!([self] "create_qpack_streams.");
+    fn create_qpack_streams(&mut self, conn: &mut Connection) -> Res<()> {
+        qdebug!([self], "create_qpack_streams.");
         self.qpack_encoder
-            .add_send_stream(self.conn.stream_create(StreamType::UniDi)?);
+            .add_send_stream(conn.stream_create(StreamType::UniDi)?);
         self.qpack_decoder
-            .add_send_stream(self.conn.stream_create(StreamType::UniDi)?);
+            .add_send_stream(conn.stream_create(StreamType::UniDi)?);
         Ok(())
     }
 
     // This function takes the provided result and check for an error.
     // An error results in closing the connection.
-    fn check_result<ERR>(&mut self, now: Instant, res: Res<ERR>) -> bool {
+    fn check_result<ERR>(&mut self, conn: &mut Connection, now: Instant, res: Res<ERR>) -> bool {
         match &res {
             Err(e) => {
-                qinfo!([self] "Connection error: {}.", e);
-                self.close(now, e.code(), &format!("{}", e));
+                qinfo!([self], "Connection error: {}.", e);
+                self.close(conn, now, e.code(), &format!("{}", e));
+                self.events
+                    .connection_state_change(Http3State::Closing(CloseError::Application(
+                        e.code(),
+                    )));
                 true
             }
             _ => false,
         }
     }
 
-    pub fn role(&self) -> Role {
-        self.conn.role()
-    }
-
-    pub fn process(&mut self, dgram: Option<Datagram>, now: Instant) -> Output {
-        qtrace!([self] "Process.");
-        if let Some(d) = dgram {
-            self.process_input(d, now);
-        }
-        self.process_http3(now);
-        self.process_output(now)
-    }
-
-    pub fn process_input(&mut self, dgram: Datagram, now: Instant) {
-        qtrace!([self] "Process input.");
-        self.conn.process_input(dgram, now);
-    }
-
-    pub fn process_timer(&mut self, now: Instant) {
-        qtrace!([self] "Process timer.");
-        self.conn.process_timer(now);
-    }
-
-    pub fn conn(&mut self) -> &mut Connection {
-        &mut self.conn
-    }
-
-    pub fn process_http3(&mut self, now: Instant) {
-        qtrace!([self] "Process http3 internal.");
+    pub fn process_http3(&mut self, conn: &mut Connection, now: Instant) {
+        qtrace!([self], "Process http3 internal.");
         match self.state {
             Http3State::Connected | Http3State::GoingAway => {
-                let res = self.check_connection_events();
-                if self.check_result(now, res) {
+                let res = self.check_connection_events(conn);
+                if self.check_result(conn, now, res) {
                     return;
                 }
-                let res = self.process_sending();
-                self.check_result(now, res);
+                let res = self.process_sending(conn);
+                self.check_result(conn, now, res);
             }
             Http3State::Closed { .. } => {}
             _ => {
-                let res = self.check_connection_events();
-                let _ = self.check_result(now, res);
+                let res = self.check_connection_events(conn);
+                let _ = self.check_result(conn, now, res);
             }
         }
     }
 
-    pub fn process_output(&mut self, now: Instant) -> Output {
-        qtrace!([self] "Process output.");
-        self.conn.process_output(now)
-    }
-
-    pub fn stream_stop_sending(&mut self, stream_id: u64, app_error: AppError) -> Res<()> {
-        self.conn.stream_stop_sending(stream_id, app_error)?;
-        Ok(())
-    }
-
     pub fn insert_streams_have_data_to_send(&mut self, stream_id: u64) {
         self.streams_have_data_to_send.insert(stream_id);
     }
 
-    fn process_sending(&mut self) -> Res<()> {
+    pub fn has_data_to_send(&self) -> bool {
+        !self.streams_have_data_to_send.is_empty()
+    }
+
+    fn process_sending(&mut self, conn: &mut Connection) -> Res<()> {
         // check if control stream has data to send.
-        self.control_stream_local.send(&mut self.conn)?;
+        self.control_stream_local.send(conn)?;
 
         let to_send = mem::replace(&mut self.streams_have_data_to_send, BTreeSet::new());
         for stream_id in to_send {
             if let Some(t) = &mut self.transactions.get_mut(&stream_id) {
-                t.send(&mut self.conn, &mut self.qpack_encoder)?;
+                t.send(conn, &mut self.qpack_encoder)?;
                 if t.has_data_to_send() {
                     self.streams_have_data_to_send.insert(stream_id);
                 }
             }
         }
-        self.qpack_decoder.send(&mut self.conn)?;
-        self.qpack_encoder.send(&mut self.conn)?;
+        self.qpack_decoder.send(conn)?;
+        self.qpack_encoder.send(conn)?;
         Ok(())
     }
 
     // If this return an error the connection must be closed.
-    fn check_connection_events(&mut self) -> Res<()> {
-        qtrace!([self] "Check connection events.");
-        while let Some(e) = self.conn.next_event() {
-            qdebug!([self] "check_connection_events - event {:?}.", e);
+    fn check_connection_events(&mut self, conn: &mut Connection) -> Res<()> {
+        qtrace!([self], "Check connection events.");
+        while let Some(e) = conn.next_event() {
+            qdebug!([self], "check_connection_events - event {:?}.", e);
             match e {
                 ConnectionEvent::NewStream {
                     stream_id,
                     stream_type,
-                } => self.handle_new_stream(stream_id, stream_type)?,
+                } => self.handle_new_stream(conn, stream_id, stream_type)?,
                 ConnectionEvent::SendStreamWritable { stream_id } => {
                     self.handler.handle_send_stream_writable(
                         &mut self.transactions,
                         &mut self.events,
                         stream_id,
                     )?
                 }
                 ConnectionEvent::RecvStreamReadable { stream_id } => {
-                    self.handle_stream_readable(stream_id)?
+                    self.handle_stream_readable(conn, stream_id)?
                 }
                 ConnectionEvent::RecvStreamReset {
                     stream_id,
                     app_error,
-                } => self.handle_stream_reset(stream_id, app_error)?,
+                } => self.handle_stream_reset(conn, stream_id, app_error)?,
                 ConnectionEvent::SendStreamStopSending {
                     stream_id,
                     app_error,
                 } => self.handler.handle_stream_stop_sending(
                     &mut self.transactions,
                     &mut self.events,
-                    &mut self.conn,
+                    conn,
                     stream_id,
                     app_error,
                 )?,
                 ConnectionEvent::SendStreamComplete { stream_id } => {
                     self.handle_stream_complete(stream_id)?
                 }
                 ConnectionEvent::SendStreamCreatable { stream_type } => self
                     .handler
                     .handle_stream_creatable(&mut self.events, stream_type)?,
                 ConnectionEvent::AuthenticationNeeded => self
                     .handler
                     .handle_authentication_needed(&mut self.events)?,
                 ConnectionEvent::StateChange(state) => {
                     match state {
-                        State::Connected => self.handle_connection_connected()?,
+                        State::Connected => self.handle_connection_connected(conn)?,
                         State::Closing { error, .. } => {
                             self.handle_connection_closing(error.clone().into())?
                         }
                         State::Closed(error) => {
                             self.handle_connection_closed(error.clone().into())?
                         }
                         _ => {}
                     };
@@ -375,153 +290,165 @@ impl<E: Http3Events + Default, T: Http3T
                     // TODO(mt) work out what to do here.
                     // Everything will have to be redone: SETTINGS, qpack streams, and requests.
                 }
             }
         }
         Ok(())
     }
 
-    fn handle_new_stream(&mut self, stream_id: u64, stream_type: StreamType) -> Res<()> {
-        qinfo!([self] "A new stream: {:?} {}.", stream_type, stream_id);
+    fn handle_new_stream(
+        &mut self,
+        conn: &mut Connection,
+        stream_id: u64,
+        stream_type: StreamType,
+    ) -> Res<()> {
+        qinfo!([self], "A new stream: {:?} {}.", stream_type, stream_id);
         assert!(self.state_active());
         match stream_type {
             StreamType::BiDi => self.handler.handle_new_bidi_stream(
                 &mut self.transactions,
                 &mut self.events,
                 stream_id,
             ),
             StreamType::UniDi => {
                 let stream_type;
                 let fin;
                 {
                     let ns = &mut self
                         .new_streams
                         .entry(stream_id)
                         .or_insert_with(NewStreamTypeReader::new);
-                    stream_type = ns.get_type(&mut self.conn, stream_id);
+                    stream_type = ns.get_type(conn, stream_id);
                     fin = ns.fin();
                 }
 
                 if fin {
                     self.new_streams.remove(&stream_id);
                     Ok(())
                 } else if let Some(t) = stream_type {
-                    self.decode_new_stream(t, stream_id)?;
+                    self.decode_new_stream(conn, t, stream_id)?;
                     self.new_streams.remove(&stream_id);
                     Ok(())
                 } else {
                     Ok(())
                 }
             }
         }
     }
 
-    fn handle_stream_readable(&mut self, stream_id: u64) -> Res<()> {
-        qtrace!([self] "Readable stream {}.", stream_id);
+    fn handle_stream_readable(&mut self, conn: &mut Connection, stream_id: u64) -> Res<()> {
+        qtrace!([self], "Readable stream {}.", stream_id);
 
         assert!(self.state_active());
 
         let label = if ::log::log_enabled!(::log::Level::Debug) {
             format!("{}", self)
         } else {
             String::new()
         };
         let mut unblocked_streams: Vec<u64> = Vec::new();
 
-        if self.handle_read_stream(stream_id)? {
-            qdebug!([label] "Request/response stream {} read.", stream_id);
+        if self.handle_read_stream(conn, stream_id)? {
+            qdebug!([label], "Request/response stream {} read.", stream_id);
         } else if self
             .control_stream_remote
-            .receive_if_this_stream(&mut self.conn, stream_id)?
+            .receive_if_this_stream(conn, stream_id)?
         {
             qdebug!(
-                [self]
+                [self],
                 "The remote control stream ({}) is readable.",
                 stream_id
             );
             while self.control_stream_remote.frame_reader_done()
                 || self.control_stream_remote.recvd_fin()
             {
                 self.handle_control_frame()?;
                 self.control_stream_remote
-                    .receive_if_this_stream(&mut self.conn, stream_id)?;
+                    .receive_if_this_stream(conn, stream_id)?;
             }
-        } else if self
-            .qpack_encoder
-            .recv_if_encoder_stream(&mut self.conn, stream_id)?
-        {
+        } else if self.qpack_encoder.recv_if_encoder_stream(conn, stream_id)? {
             qdebug!(
-                [self]
+                [self],
                 "The qpack encoder stream ({}) is readable.",
                 stream_id
             );
         } else if self.qpack_decoder.is_recv_stream(stream_id) {
             qdebug!(
-                [self]
+                [self],
                 "The qpack decoder stream ({}) is readable.",
                 stream_id
             );
-            unblocked_streams = self.qpack_decoder.receive(&mut self.conn, stream_id)?;
+            unblocked_streams = self.qpack_decoder.receive(conn, stream_id)?;
         } else if let Some(ns) = self.new_streams.get_mut(&stream_id) {
-            let stream_type = ns.get_type(&mut self.conn, stream_id);
+            let stream_type = ns.get_type(conn, stream_id);
             let fin = ns.fin();
             if fin {
                 self.new_streams.remove(&stream_id);
             }
             if let Some(t) = stream_type {
-                self.decode_new_stream(t, stream_id)?;
+                self.decode_new_stream(conn, t, stream_id)?;
                 self.new_streams.remove(&stream_id);
             }
         } else {
             // For a new stream we receive NewStream event and a
             // RecvStreamReadable event.
             // In most cases we decode a new stream already on the NewStream
             // event and remove it from self.new_streams.
             // Therefore, while processing RecvStreamReadable there will be no
             // entry for the stream in self.new_streams.
             qdebug!("Unknown stream.");
         }
 
         for stream_id in unblocked_streams {
-            qinfo!([self] "Stream {} is unblocked", stream_id);
-            self.handle_read_stream(stream_id)?;
+            qinfo!([self], "Stream {} is unblocked", stream_id);
+            self.handle_read_stream(conn, stream_id)?;
         }
         Ok(())
     }
 
-    fn handle_stream_reset(&mut self, stream_id: u64, app_err: AppError) -> Res<()> {
-        qinfo!([self] "Handle a stream reset stream_id={} app_err={}", stream_id, app_err);
+    fn handle_stream_reset(
+        &mut self,
+        conn: &mut Connection,
+        stream_id: u64,
+        app_err: AppError,
+    ) -> Res<()> {
+        qinfo!(
+            [self],
+            "Handle a stream reset stream_id={} app_err={}",
+            stream_id,
+            app_err
+        );
 
         assert!(self.state_active());
 
         if let Some(t) = self.transactions.get_mut(&stream_id) {
             // Post the reset event.
             self.events.reset(stream_id, app_err);
             // Close both sides of the transaction_client.
             t.reset_receiving_side();
             t.stop_sending();
             // close sending side of the transport stream as well. The server may have done
             // it se well, but just to be sure.
-            let _ = self.conn.stream_reset_send(stream_id, app_err);
+            let _ = conn.stream_reset_send(stream_id, app_err);
             // remove the stream
             self.transactions.remove(&stream_id);
         }
         Ok(())
     }
 
     fn handle_stream_complete(&mut self, _stream_id: u64) -> Res<()> {
         Ok(())
     }
 
-    fn handle_connection_connected(&mut self) -> Res<()> {
+    fn handle_connection_connected(&mut self, conn: &mut Connection) -> Res<()> {
         assert_eq!(self.state, Http3State::Initializing);
         self.events.connection_state_change(Http3State::Connected);
         self.state = Http3State::Connected;
-        self.initialize_http3_connection()
+        self.initialize_http3_connection(conn)
     }
 
     fn handle_connection_closing(&mut self, error_code: CloseError) -> Res<()> {
         assert!(self.state_active() || self.state_closing());
         self.events
             .connection_state_change(Http3State::Closing(error_code));
         self.state = Http3State::Closing(error_code);
         Ok(())
@@ -529,133 +456,147 @@ impl<E: Http3Events + Default, T: Http3T
 
     fn handle_connection_closed(&mut self, error_code: CloseError) -> Res<()> {
         self.events
             .connection_state_change(Http3State::Closed(error_code));
         self.state = Http3State::Closed(error_code);
         Ok(())
     }
 
-    fn handle_read_stream(&mut self, stream_id: u64) -> Res<bool> {
+    fn handle_read_stream(&mut self, conn: &mut Connection, stream_id: u64) -> Res<bool> {
         let label = if ::log::log_enabled!(::log::Level::Debug) {
             format!("{}", self)
         } else {
             String::new()
         };
 
         assert!(self.state_active());
 
         if let Some(transaction) = &mut self.transactions.get_mut(&stream_id) {
-            qinfo!([label] "Request/response stream {} is readable.", stream_id);
-            match transaction.receive(&mut self.conn, &mut self.qpack_decoder) {
+            qinfo!(
+                [label],
+                "Request/response stream {} is readable.",
+                stream_id
+            );
+            match transaction.receive(conn, &mut self.qpack_decoder) {
                 Err(e) => {
-                    qerror!([label] "Error {} ocurred", e);
+                    qerror!([label], "Error {} ocurred", e);
                     return Err(e);
                 }
                 Ok(()) => {
                     if transaction.done() {
                         self.transactions.remove(&stream_id);
                     }
                 }
             }
             Ok(true)
         } else {
             Ok(false)
         }
     }
 
-    fn decode_new_stream(&mut self, stream_type: u64, stream_id: u64) -> Res<()> {
+    fn decode_new_stream(
+        &mut self,
+        conn: &mut Connection,
+        stream_type: u64,
+        stream_id: u64,
+    ) -> Res<()> {
         match stream_type {
             HTTP3_UNI_STREAM_TYPE_CONTROL => {
                 self.control_stream_remote.add_remote_stream(stream_id)?;
                 Ok(())
             }
 
             HTTP3_UNI_STREAM_TYPE_PUSH => {
-                qinfo!([self] "A new push stream {}.", stream_id);
+                qinfo!([self], "A new push stream {}.", stream_id);
                 self.handler.handle_new_push_stream()
             }
             QPACK_UNI_STREAM_TYPE_ENCODER => {
-                qinfo!([self] "A new remote qpack encoder stream {}", stream_id);
+                qinfo!([self], "A new remote qpack encoder stream {}", stream_id);
                 self.qpack_decoder
                     .add_recv_stream(stream_id)
                     .map_err(|_| Error::HttpStreamCreationError)
             }
             QPACK_UNI_STREAM_TYPE_DECODER => {
-                qinfo!([self] "A new remote qpack decoder stream {}", stream_id);
+                qinfo!([self], "A new remote qpack decoder stream {}", stream_id);
                 self.qpack_encoder
                     .add_recv_stream(stream_id)
                     .map_err(|_| Error::HttpStreamCreationError)
             }
             // TODO reserved stream types
             _ => {
-                self.conn
-                    .stream_stop_sending(stream_id, Error::HttpStreamCreationError.code())?;
+                conn.stream_stop_sending(stream_id, Error::HttpStreamCreationError.code())?;
                 Ok(())
             }
         }
     }
 
-    pub fn close(&mut self, now: Instant, error: AppError, msg: &str) {
-        qinfo!([self] "Close connection error {:?} msg={}.", error, msg);
-        assert!(self.state_active());
-        self.state = Http3State::Closing(CloseError::Application(error));
-        if !self.transactions.is_empty() && (error == 0) {
-            qwarn!("close() called when streams still active");
+    pub fn close(&mut self, conn: &mut Connection, now: Instant, error: AppError, msg: &str) {
+        qinfo!([self], "Close connection error {:?} msg={}.", error, msg);
+        if !matches!(self.state, Http3State::Closing(_) | Http3State::Closed(_)) {
+            self.state = Http3State::Closing(CloseError::Application(error));
+            if !self.transactions.is_empty() && (error == 0) {
+                qwarn!("close() called when streams still active");
+            }
+            self.transactions.clear();
+            conn.close(now, error, msg);
         }
-        self.transactions.clear();
-        self.conn.close(now, error, msg);
     }
 
-    pub fn stream_reset(&mut self, stream_id: u64, error: AppError) -> Res<()> {
-        qinfo!([self] "Reset stream {} error={}.", stream_id, error);
+    pub fn stream_reset(
+        &mut self,
+        conn: &mut Connection,
+        stream_id: u64,
+        error: AppError,
+    ) -> Res<()> {
+        qinfo!([self], "Reset stream {} error={}.", stream_id, error);
         assert!(self.state_active());
         let mut transaction = self
             .transactions
             .remove(&stream_id)
             .ok_or(Error::InvalidStreamId)?;
         transaction.stop_sending();
         // Stream maybe already be closed and we may get an error here, but we do not care.
-        let _ = self.conn.stream_reset_send(stream_id, error);
+        let _ = conn.stream_reset_send(stream_id, error);
         transaction.reset_receiving_side();
         // Stream maybe already be closed and we may get an error here, but we do not care.
-        self.conn.stream_stop_sending(stream_id, error)?;
+        conn.stream_stop_sending(stream_id, error)?;
         self.events.remove_events_for_stream_id(stream_id);
         Ok(())
     }
 
-    pub fn stream_close_send(&mut self, stream_id: u64) -> Res<()> {
-        qinfo!([self] "Close sending side for stream {}.", stream_id);
+    pub fn stream_close_send(&mut self, conn: &mut Connection, stream_id: u64) -> Res<()> {
+        qinfo!([self], "Close sending side for stream {}.", stream_id);
         assert!(self.state_active());
         let transaction = self
             .transactions
             .get_mut(&stream_id)
             .ok_or(Error::InvalidStreamId)?;
-        transaction.close_send(&mut self.conn)?;
+        transaction.close_send(conn)?;
         if transaction.done() {
             self.transactions.remove(&stream_id);
         }
         Ok(())
     }
 
     fn handle_control_frame(&mut self) -> Res<()> {
         if self.control_stream_remote.recvd_fin() {
             return Err(Error::HttpClosedCriticalStream);
         }
         if self.control_stream_remote.frame_reader_done() {
             let f = self.control_stream_remote.get_frame()?;
-            qinfo!([self] "Handle a control frame {:?}", f);
+            qinfo!([self], "Handle a control frame {:?}", f);
             if let HFrame::Settings { .. } = f {
                 if self.settings_received {
-                    qerror!([self] "SETTINGS frame already received");
+                    qerror!([self], "SETTINGS frame already received");
                     return Err(Error::HttpFrameUnexpected);
                 }
                 self.settings_received = true;
             } else if !self.settings_received {
-                qerror!([self] "SETTINGS frame not received");
+                qerror!([self], "SETTINGS frame not received");
                 return Err(Error::HttpMissingSettings);
             }
             return match f {
                 HFrame::Settings { settings } => {
                     self.handle_settings(&settings)?;
                     Ok(())
                 }
                 HFrame::CancelPush { .. } => Err(Error::HttpFrameUnexpected),
@@ -668,37 +609,34 @@ impl<E: Http3Events + Default, T: Http3T
                 HFrame::MaxPushId { push_id } => self.handler.handle_max_push_id(push_id),
                 _ => Err(Error::HttpFrameUnexpected),
             };
         }
         Ok(())
     }
 
     fn handle_settings(&mut self, s: &[(HSettingType, u64)]) -> Res<()> {
-        qinfo!([self] "Handle SETTINGS frame.");
+        qinfo!([self], "Handle SETTINGS frame.");
         for (t, v) in s {
-            qinfo!([self] " {:?} = {:?}", t, v);
+            qinfo!([self], " {:?} = {:?}", t, v);
             match t {
                 HSettingType::MaxHeaderListSize => {
                     self.max_header_list_size = *v;
                 }
                 HSettingType::MaxTableSize => self.qpack_encoder.set_max_capacity(*v)?,
                 HSettingType::BlockedStreams => self.qpack_encoder.set_max_blocked_streams(*v)?,
 
                 _ => {}
             }
         }
         Ok(())
     }
 
     fn state_active(&self) -> bool {
-        match self.state {
-            Http3State::Connected | Http3State::GoingAway => true,
-            _ => false,
-        }
+        matches!(self.state, Http3State::Connected | Http3State::GoingAway)
     }
 
     fn state_closing(&self) -> bool {
         matches!(self.state, Http3State::Closing(_))
     }
 
     pub fn state(&self) -> Http3State {
         self.state.clone()
@@ -726,17 +664,17 @@ impl Http3Handler<Http3ClientEvents, Tra
         stream_type: StreamType,
     ) -> Res<()> {
         events.new_requests_creatable(stream_type);
         Ok(())
     }
 
     fn handle_new_push_stream(&mut self) -> Res<()> {
         // TODO implement PUSH
-        qerror!([self] "PUSH is not implemented!");
+        qerror!([self], "PUSH is not implemented!");
         Err(Error::HttpIdError)
     }
 
     fn handle_new_bidi_stream(
         &mut self,
         _transactions: &mut HashMap<u64, TransactionClient>,
         _events: &mut Http3ClientEvents,
         _stream_id: u64,
@@ -746,17 +684,17 @@ impl Http3Handler<Http3ClientEvents, Tra
     }
 
     fn handle_send_stream_writable(
         &mut self,
         transactions: &mut HashMap<u64, TransactionClient>,
         events: &mut Http3ClientEvents,
         stream_id: u64,
     ) -> Res<()> {
-        qtrace!([self] "Writable stream {}.", stream_id);
+        qtrace!([self], "Writable stream {}.", stream_id);
 
         if let Some(t) = transactions.get_mut(&stream_id) {
             if t.is_state_sending_data() {
                 events.data_writable(stream_id);
             }
         }
         Ok(())
     }
@@ -764,17 +702,22 @@ impl Http3Handler<Http3ClientEvents, Tra
     fn handle_stream_stop_sending(
         &mut self,
         transactions: &mut HashMap<u64, TransactionClient>,
         events: &mut Http3ClientEvents,
         conn: &mut Connection,
         stop_stream_id: u64,
         app_err: AppError,
     ) -> Res<()> {
-        qinfo!([self] "Handle stream_stop_sending stream_id={} app_err={}", stop_stream_id, app_err);
+        qinfo!(
+            [self],
+            "Handle stream_stop_sending stream_id={} app_err={}",
+            stop_stream_id,
+            app_err
+        );
 
         if let Some(t) = transactions.get_mut(&stop_stream_id) {
             // close sending side.
             t.stop_sending();
 
             // If error is Error::EarlyResponse we will post StopSending event,
             // otherwise post reset.
             if app_err == Error::HttpEarlyResponse.code() && !t.is_sending_closed() {
@@ -797,17 +740,17 @@ impl Http3Handler<Http3ClientEvents, Tra
 
     fn handle_goaway(
         &mut self,
         transactions: &mut HashMap<u64, TransactionClient>,
         events: &mut Http3ClientEvents,
         state: &mut Http3State,
         goaway_stream_id: u64,
     ) -> Res<()> {
-        qinfo!([self] "handle_goaway");
+        qinfo!([self], "handle_goaway");
         // Issue reset events for streams >= goaway stream id
         for id in transactions
             .iter()
             .filter(|(id, _)| **id >= goaway_stream_id)
             .map(|(id, _)| *id)
         {
             events.reset(id, Error::HttpRequestRejected.code())
         }
@@ -818,101 +761,101 @@ impl Http3Handler<Http3ClientEvents, Tra
 
         if *state == Http3State::Connected {
             *state = Http3State::GoingAway;
         }
         Ok(())
     }
 
     fn handle_max_push_id(&mut self, stream_id: u64) -> Res<()> {
-        qerror!([self] "handle_max_push_id={}.", stream_id);
+        qerror!([self], "handle_max_push_id={}.", stream_id);
         Err(Error::HttpFrameUnexpected)
     }
 
     fn handle_authentication_needed(&self, events: &mut Http3ClientEvents) -> Res<()> {
         events.authentication_needed();
         Ok(())
     }
 }
 
 impl ::std::fmt::Display for Http3ClientHandler {
     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
         write!(f, "Http3 connection client")
     }
 }
 
-#[derive(Default)]
+#[derive(Default, Debug)]
 pub struct Http3ServerHandler {}
 
-impl Http3Handler<Http3ServerEvents, TransactionServer> for Http3ServerHandler {
+impl Http3Handler<Http3ServerConnEvents, TransactionServer> for Http3ServerHandler {
     fn new() -> Self {
         Http3ServerHandler::default()
     }
 
     fn handle_stream_creatable(
         &mut self,
-        _events: &mut Http3ServerEvents,
+        _events: &mut Http3ServerConnEvents,
         _stream_type: StreamType,
     ) -> Res<()> {
         Ok(())
     }
 
     fn handle_new_push_stream(&mut self) -> Res<()> {
-        qerror!([self] "Error: server receives a push stream!");
+        qerror!([self], "Error: server receives a push stream!");
         Err(Error::HttpStreamCreationError)
     }
 
     fn handle_new_bidi_stream(
         &mut self,
         transactions: &mut HashMap<u64, TransactionServer>,
-        events: &mut Http3ServerEvents,
+        events: &mut Http3ServerConnEvents,
         stream_id: u64,
     ) -> Res<()> {
         transactions.insert(stream_id, TransactionServer::new(stream_id, events.clone()));
         Ok(())
     }
 
     fn handle_send_stream_writable(
         &mut self,
         _transactions: &mut HashMap<u64, TransactionServer>,
-        _events: &mut Http3ServerEvents,
+        _events: &mut Http3ServerConnEvents,
         _stream_id: u64,
     ) -> Res<()> {
         Ok(())
     }
 
     fn handle_goaway(
         &mut self,
         _transactions: &mut HashMap<u64, TransactionServer>,
-        _events: &mut Http3ServerEvents,
+        _events: &mut Http3ServerConnEvents,
         _state: &mut Http3State,
         _goaway_stream_id: u64,
     ) -> Res<()> {
-        qerror!([self] "handle_goaway");
+        qerror!([self], "handle_goaway");
         Err(Error::HttpFrameUnexpected)
     }
 
     fn handle_stream_stop_sending(
         &mut self,
         _transactions: &mut HashMap<u64, TransactionServer>,
-        _events: &mut Http3ServerEvents,
+        _events: &mut Http3ServerConnEvents,
         _conn: &mut Connection,
         _stop_stream_id: u64,
         _app_err: AppError,
     ) -> Res<()> {
         Ok(())
     }
 
     fn handle_max_push_id(&mut self, stream_id: u64) -> Res<()> {
-        qinfo!([self] "handle_max_push_id={}.", stream_id);
+        qinfo!([self], "handle_max_push_id={}.", stream_id);
         // TODO
         Ok(())
     }
 
-    fn handle_authentication_needed(&self, _events: &mut Http3ServerEvents) -> Res<()> {
+    fn handle_authentication_needed(&self, _events: &mut Http3ServerConnEvents) -> Res<()> {
         Err(Error::HttpInternalError)
     }
 }
 
 impl ::std::fmt::Display for Http3ServerHandler {
     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
         write!(f, "Http3 connection server")
     }
--- a/third_party/rust/neqo-http3/src/connection_client.rs
+++ b/third_party/rust/neqo-http3/src/connection_client.rs
@@ -15,141 +15,145 @@ use neqo_transport::{AppError, Connectio
 use std::cell::RefCell;
 use std::net::SocketAddr;
 use std::rc::Rc;
 use std::time::Instant;
 
 use crate::{Error, Res};
 
 pub struct Http3Client {
+    conn: Connection,
     base_handler: Http3Connection<Http3ClientEvents, TransactionClient, Http3ClientHandler>,
 }
 
 impl ::std::fmt::Display for Http3Client {
     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
-        write!(f, "Http3 connection {:?}", self.role())
+        write!(f, "Http3 client")
     }
 }
 
 impl Http3Client {
     pub fn new(
         server_name: &str,
         protocols: &[impl AsRef<str>],
         cid_manager: Rc<RefCell<dyn ConnectionIdManager>>,
         local_addr: SocketAddr,
         remote_addr: SocketAddr,
         max_table_size: u32,
         max_blocked_streams: u16,
     ) -> Res<Http3Client> {
         Ok(Http3Client {
-            base_handler: Http3Connection::new_client(
+            conn: Connection::new_client(
                 server_name,
                 protocols,
                 cid_manager,
                 local_addr,
                 remote_addr,
-                max_table_size,
-                max_blocked_streams,
             )?,
+            base_handler: Http3Connection::new(max_table_size, max_blocked_streams),
         })
     }
 
     pub fn new_with_conn(
         c: Connection,
         max_table_size: u32,
         max_blocked_streams: u16,
     ) -> Res<Http3Client> {
         Ok(Http3Client {
-            base_handler: Http3Connection::new_client_with_conn(
-                c,
-                max_table_size,
-                max_blocked_streams,
-            )?,
+            conn: c,
+            base_handler: Http3Connection::new(max_table_size, max_blocked_streams),
         })
     }
 
     pub fn role(&self) -> Role {
-        self.base_handler.role()
+        self.conn.role()
     }
 
     pub fn state(&self) -> Http3State {
         self.base_handler.state()
     }
 
     pub fn tls_info(&self) -> Option<&SecretAgentInfo> {
-        self.base_handler.conn.tls_info()
+        self.conn.tls_info()
     }
 
     /// Get the peer's certificate.
     pub fn peer_certificate(&self) -> Option<CertificateInfo> {
-        self.base_handler.conn.peer_certificate()
+        self.conn.peer_certificate()
     }
 
     pub fn authenticated(&mut self, status: AuthenticationStatus, now: Instant) {
-        self.base_handler.conn.authenticated(status, now);
+        self.conn.authenticated(status, now);
     }
 
     pub fn close(&mut self, now: Instant, error: AppError, msg: &str) {
-        qinfo!([self] "Close the connection error={} msg={}.", error, msg);
-        self.base_handler.close(now, error, msg);
+        qinfo!([self], "Close the connection error={} msg={}.", error, msg);
+        self.base_handler.close(&mut self.conn, now, error, msg);
     }
 
     pub fn fetch(
         &mut self,
         method: &str,
         scheme: &str,
         host: &str,
         path: &str,
         headers: &[Header],
     ) -> Res<u64> {
         qinfo!(
-            [self]
+            [self],
             "Fetch method={}, scheme={}, host={}, path={}",
             method,
             scheme,
             host,
             path
         );
-        let id = self.base_handler.conn().stream_create(StreamType::BiDi)?;
+        let id = self.conn.stream_create(StreamType::BiDi)?;
         self.base_handler.add_transaction(
             id,
             TransactionClient::new(
                 id,
                 method,
                 scheme,
                 host,
                 path,
                 headers,
                 self.base_handler.events.clone(),
             ),
         );
         Ok(id)
     }
 
     pub fn stream_reset(&mut self, stream_id: u64, error: AppError) -> Res<()> {
-        qinfo!([self] "reset_stream {} error={}.", stream_id, error);
-        self.base_handler.stream_reset(stream_id, error)
+        qinfo!([self], "reset_stream {} error={}.", stream_id, error);
+        self.base_handler
+            .stream_reset(&mut self.conn, stream_id, error)
     }
 
     pub fn stream_close_send(&mut self, stream_id: u64) -> Res<()> {
-        qinfo!([self] "Close senidng side stream={}.", stream_id);
-        self.base_handler.stream_close_send(stream_id)
+        qinfo!([self], "Close senidng side stream={}.", stream_id);
+        self.base_handler
+            .stream_close_send(&mut self.conn, stream_id)
     }
 
     pub fn send_request_body(&mut self, stream_id: u64, buf: &[u8]) -> Res<usize> {
-        qinfo!([self] "send_request_body from stream {} sending {} bytes.", stream_id, buf.len());
+        qinfo!(
+            [self],
+            "send_request_body from stream {} sending {} bytes.",
+            stream_id,
+            buf.len()
+        );
         self.base_handler
             .transactions
             .get_mut(&stream_id)
             .ok_or(Error::InvalidStreamId)?
-            .send_request_body(&mut self.base_handler.conn, buf)
+            .send_request_body(&mut self.conn, buf)
     }
 
     pub fn read_response_headers(&mut self, stream_id: u64) -> Res<(Vec<Header>, bool)> {
-        qinfo!([self] "read_response_headers from stream {}.", stream_id);
+        qinfo!([self], "read_response_headers from stream {}.", stream_id);
         let transaction = self
             .base_handler
             .transactions
             .get_mut(&stream_id)
             .ok_or(Error::InvalidStreamId)?;
         match transaction.read_response_headers() {
             Ok((headers, fin)) => {
                 if transaction.done() {
@@ -162,37 +166,34 @@ impl Http3Client {
     }
 
     pub fn read_response_data(
         &mut self,
         now: Instant,
         stream_id: u64,
         buf: &mut [u8],
     ) -> Res<(usize, bool)> {
-        qinfo!([self] "read_data from stream {}.", stream_id);
+        qinfo!([self], "read_data from stream {}.", stream_id);
         let transaction = self
             .base_handler
             .transactions
             .get_mut(&stream_id)
             .ok_or(Error::InvalidStreamId)?;
 
-        match transaction.read_response_data(&mut self.base_handler.conn, buf) {
+        match transaction.read_response_data(&mut self.conn, buf) {
             Ok((amount, fin)) => {
                 if fin {
                     self.base_handler.transactions.remove(&stream_id);
                 } else if amount > 0 {
                     // Directly call receive instead of adding to
                     // streams_are_readable here. This allows the app to
                     // pick up subsequent already-received data frames in
                     // the stream even if no new packets arrive to cause
                     // process_http3() to run.
-                    transaction.receive(
-                        &mut self.base_handler.conn,
-                        &mut self.base_handler.qpack_decoder,
-                    )?;
+                    transaction.receive(&mut self.conn, &mut self.base_handler.qpack_decoder)?;
                 }
                 Ok((amount, fin))
             }
             Err(e) => {
                 if e == Error::HttpFrameError {
                     self.close(now, e.code(), "");
                 }
                 Err(e)
@@ -214,43 +215,47 @@ impl Http3Client {
     /// Get events that indicate state changes on the connection. This method
     /// correctly handles cases where handling one event can obsolete
     /// previously-queued events, or cause new events to be generated.
     pub fn next_event(&mut self) -> Option<Http3ClientEvent> {
         self.base_handler.events.next_event()
     }
 
     pub fn process(&mut self, dgram: Option<Datagram>, now: Instant) -> Output {
-        qtrace!([self] "Process.");
-        self.base_handler.process(dgram, now)
+        qtrace!([self], "Process.");
+        if let Some(d) = dgram {
+            self.process_input(d, now);
+        }
+        self.process_http3(now);
+        self.process_output(now)
     }
 
     pub fn process_input(&mut self, dgram: Datagram, now: Instant) {
-        qtrace!([self] "Process input.");
-        self.base_handler.process_input(dgram, now);
+        qtrace!([self], "Process input.");
+        self.conn.process_input(dgram, now);
     }
 
     pub fn process_timer(&mut self, now: Instant) {
-        qtrace!([self] "Process timer.");
-        self.base_handler.process_timer(now);
+        qtrace!([self], "Process timer.");
+        self.conn.process_timer(now);
     }
 
     pub fn conn(&mut self) -> &mut Connection {
-        &mut self.base_handler.conn
+        &mut self.conn
     }
 
     pub fn process_http3(&mut self, now: Instant) {
-        qtrace!([self] "Process http3 internal.");
+        qtrace!([self], "Process http3 internal.");
 
-        self.base_handler.process_http3(now);
+        self.base_handler.process_http3(&mut self.conn, now);
     }
 
     pub fn process_output(&mut self, now: Instant) -> Output {
-        qtrace!([self] "Process output.");
-        self.base_handler.process_output(now)
+        qtrace!([self], "Process output.");
+        self.conn.process_output(now)
     }
 }
 
 #[cfg(test)]
 mod tests {
     use super::*;
     use crate::hframe::HFrame;
     use neqo_common::{matches, Encoder};
deleted file mode 100644
--- a/third_party/rust/neqo-http3/src/connection_server.rs
+++ /dev/null
@@ -1,737 +0,0 @@
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use crate::connection::{Http3Connection, Http3ServerHandler, Http3State};
-use crate::server_events::{Http3ServerEvent, Http3ServerEvents};
-use crate::transaction_server::TransactionServer;
-use crate::{Error, Header, Res};
-use neqo_common::{qdebug, qinfo, qtrace, Datagram};
-use neqo_crypto::AntiReplay;
-use neqo_transport::{AppError, Connection, ConnectionIdManager, Output, Role};
-use std::cell::RefCell;
-use std::rc::Rc;
-use std::time::Instant;
-
-pub struct Http3Server {
-    base_handler: Http3Connection<Http3ServerEvents, TransactionServer, Http3ServerHandler>,
-}
-
-impl ::std::fmt::Display for Http3Server {
-    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
-        write!(f, "Http3 connection {:?}", self.role())
-    }
-}
-
-impl Http3Server {
-    pub fn new(
-        certs: &[impl AsRef<str>],
-        protocols: &[impl AsRef<str>],
-        anti_replay: &AntiReplay,
-        cid_manager: Rc<RefCell<dyn ConnectionIdManager>>,
-        max_table_size: u32,
-        max_blocked_streams: u16,
-    ) -> Res<Http3Server> {
-        Ok(Http3Server {
-            base_handler: Http3Connection::new_server(
-                certs,
-                protocols,
-                anti_replay,
-                cid_manager,
-                max_table_size,
-                max_blocked_streams,
-            )?,
-        })
-    }
-
-    fn role(&self) -> Role {
-        self.base_handler.role()
-    }
-
-    pub fn process(&mut self, dgram: Option<Datagram>, now: Instant) -> Output {
-        qtrace!([self] "Process.");
-        self.base_handler.process(dgram, now)
-    }
-
-    pub fn process_input(&mut self, dgram: Datagram, now: Instant) {
-        qtrace!([self] "Process input.");
-        self.base_handler.process_input(dgram, now);
-    }
-
-    pub fn process_timer(&mut self, now: Instant) {
-        qtrace!([self] "Process timer.");
-        self.base_handler.process_timer(now);
-    }
-
-    pub fn conn(&mut self) -> &mut Connection {
-        &mut self.base_handler.conn
-    }
-
-    pub fn process_http3(&mut self, now: Instant) {
-        qtrace!([self] "Process http3 internal.");
-        self.base_handler.process_http3(now);
-    }
-
-    pub fn process_output(&mut self, now: Instant) -> Output {
-        qtrace!([self] "Process output.");
-        self.base_handler.process_output(now)
-    }
-
-    pub fn close(&mut self, now: Instant, error: AppError, msg: &str) {
-        qinfo!([self] "Close connection.");
-        self.base_handler.close(now, error, msg);
-    }
-
-    pub fn state(&self) -> Http3State {
-        self.base_handler.state.clone()
-    }
-
-    /// Get all current events. Best used just in debug/testing code, use
-    /// next_event() instead.
-    pub fn events(&mut self) -> impl Iterator<Item = Http3ServerEvent> {
-        self.base_handler.events.events()
-    }
-
-    /// Return true if there are outstanding events.
-    pub fn has_events(&self) -> bool {
-        self.base_handler.events.has_events()
-    }
-
-    /// Get events that indicate state changes on the connection. This method
-    /// correctly handles cases where handling one event can obsolete
-    /// previously-queued events, or cause new events to be generated.
-    pub fn next_event(&mut self) -> Option<Http3ServerEvent> {
-        self.base_handler.events.next_event()
-    }
-
-    pub fn set_response(&mut self, stream_id: u64, headers: &[Header], data: Vec<u8>) -> Res<()> {
-        qinfo!([self] "Set new respons for stream {}.", stream_id);
-        self.base_handler
-            .transactions
-            .get_mut(&stream_id)
-            .ok_or(Error::InvalidStreamId)?
-            .set_response(headers, data, &mut self.base_handler.qpack_encoder);
-        self.base_handler
-            .insert_streams_have_data_to_send(stream_id);
-        Ok(())
-    }
-
-    pub fn stream_stop_sending(&mut self, stream_id: u64, app_error: AppError) -> Res<()> {
-        qdebug!([self] "stop sending stream_id:{} error:{}.", stream_id, app_error);
-        self.base_handler.stream_stop_sending(stream_id, app_error)
-    }
-
-    pub fn stream_reset(&mut self, stream_id: u64, app_error: AppError) -> Res<()> {
-        qdebug!([self] "reset stream_id:{} error:{}.", stream_id, app_error);
-        self.base_handler.stream_reset(stream_id, app_error)
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use neqo_common::matches;
-    use neqo_crypto::AuthenticationStatus;
-    use neqo_qpack::encoder::QPackEncoder;
-    use neqo_transport::{
-        CloseError, ConnectionEvent, FixedConnectionIdManager, State, StreamType,
-    };
-    use test_fixture::*;
-
-    /// Create a http3 server with default configuration.
-    pub fn default_http3_server() -> Http3Server {
-        fixture_init();
-        Http3Server::new(
-            DEFAULT_KEYS,
-            DEFAULT_ALPN,
-            &anti_replay(),
-            Rc::new(RefCell::new(FixedConnectionIdManager::new(5))),
-            100,
-            100,
-        )
-        .expect("create a default server")
-    }
-
-    fn assert_closed(hconn: &Http3Server, expected: Error) {
-        match hconn.state() {
-            Http3State::Closing(err) | Http3State::Closed(err) => {
-                assert_eq!(err, CloseError::Application(expected.code()))
-            }
-            _ => panic!("Wrong state {:?}", hconn.state()),
-        };
-    }
-
-    // Start a client/server and check setting frame.
-    #[allow(clippy::cognitive_complexity)]
-    fn connect_and_receive_settings() -> (Http3Server, Connection) {
-        // Create a server and connect it to a client.
-        // We will have a http3 server on one side and a neqo_transport
-        // connection on the other side so that we can check what the http3
-        // side sends and also to simulate an incorrectly behaving http3
-        // client.
-
-        fixture_init();
-        let mut hconn = default_http3_server();
-        let mut neqo_trans_conn = default_client();
-
-        assert_eq!(hconn.state(), Http3State::Initializing);
-        let out = neqo_trans_conn.process(None, now());
-        let out = hconn.process(out.dgram(), now());
-        let out = neqo_trans_conn.process(out.dgram(), now());
-        let _ = hconn.process(out.dgram(), now());
-        let authentication_needed = |e| matches!(e, ConnectionEvent::AuthenticationNeeded);
-        assert!(neqo_trans_conn.events().any(authentication_needed));
-        neqo_trans_conn.authenticated(AuthenticationStatus::Ok, now());
-        let out = neqo_trans_conn.process(None, now());
-        let out = hconn.process(out.dgram(), now());
-        assert_eq!(hconn.state(), Http3State::Connected);
-        neqo_trans_conn.process(out.dgram(), now());
-
-        let mut connected = false;
-        while let Some(e) = neqo_trans_conn.next_event() {
-            match e {
-                ConnectionEvent::NewStream {
-                    stream_id,
-                    stream_type,
-                } => {
-                    assert!((stream_id == 3) || (stream_id == 7) || (stream_id == 11));
-                    assert_eq!(stream_type, StreamType::UniDi);
-                }
-                ConnectionEvent::RecvStreamReadable { stream_id } => {
-                    if stream_id == 2 || stream_id == 3 {
-                        // the control stream
-                        let mut buf = [0u8; 100];
-                        let (amount, fin) =
-                            neqo_trans_conn.stream_recv(stream_id, &mut buf).unwrap();
-                        assert_eq!(fin, false);
-                        const CONTROL_STREAM_DATA: &[u8] =
-                            &[0x0, 0x4, 0x6, 0x1, 0x40, 0x64, 0x7, 0x40, 0x64];
-                        assert_eq!(amount, CONTROL_STREAM_DATA.len());
-                        assert_eq!(&buf[..9], CONTROL_STREAM_DATA);
-                    } else if stream_id == 6 || stream_id == 7 {
-                        let mut buf = [0u8; 100];
-                        let (amount, fin) =
-                            neqo_trans_conn.stream_recv(stream_id, &mut buf).unwrap();
-                        assert_eq!(fin, false);
-                        assert_eq!(amount, 1);
-                        assert_eq!(buf[..1], [0x2]);
-                    } else if stream_id == 10 || stream_id == 11 {
-                        let mut buf = [0u8; 100];
-                        let (amount, fin) =
-                            neqo_trans_conn.stream_recv(stream_id, &mut buf).unwrap();
-                        assert_eq!(fin, false);
-                        assert_eq!(amount, 1);
-                        assert_eq!(buf[..1], [0x3]);
-                    } else {
-                        panic!("unexpected event");
-                    }
-                }
-                ConnectionEvent::SendStreamWritable { stream_id } => {
-                    assert!((stream_id == 2) || (stream_id == 6) || (stream_id == 10));
-                }
-                ConnectionEvent::StateChange(State::Connected) => connected = true,
-                ConnectionEvent::StateChange(_) => (),
-                _ => panic!("unexpected event"),
-            }
-        }
-        assert!(connected);
-        (hconn, neqo_trans_conn)
-    }
-
-    // Test http3 connection inintialization.
-    // The server will open the control and qpack streams and send SETTINGS frame.
-    #[test]
-    fn test_server_connect() {
-        let _ = connect_and_receive_settings();
-    }
-
-    struct PeerConnection {
-        conn: Connection,
-        control_stream_id: u64,
-    }
-
-    // Connect transport, send and receive settings.
-    fn connect() -> (Http3Server, PeerConnection) {
-        let (mut hconn, mut neqo_trans_conn) = connect_and_receive_settings();
-        let control_stream = neqo_trans_conn.stream_create(StreamType::UniDi).unwrap();
-        let mut sent = neqo_trans_conn.stream_send(
-            control_stream,
-            &[0x0, 0x4, 0x6, 0x1, 0x40, 0x64, 0x7, 0x40, 0x64],
-        );
-        assert_eq!(sent, Ok(9));
-        let mut encoder = QPackEncoder::new(true);
-        encoder.add_send_stream(neqo_trans_conn.stream_create(StreamType::UniDi).unwrap());
-        encoder.send(&mut neqo_trans_conn).unwrap();
-        let decoder_stream = neqo_trans_conn.stream_create(StreamType::UniDi).unwrap();
-        sent = neqo_trans_conn.stream_send(decoder_stream, &[0x3]);
-        assert_eq!(sent, Ok(1));
-        let out = neqo_trans_conn.process(None, now());
-        hconn.process(out.dgram(), now());
-
-        // assert no error occured.
-        assert_eq!(hconn.state(), Http3State::Connected);
-        (
-            hconn,
-            PeerConnection {
-                conn: neqo_trans_conn,
-                control_stream_id: control_stream,
-            },
-        )
-    }
-
-    // Server: Test receiving a new control stream and a SETTINGS frame.
-    #[test]
-    fn test_server_receive_control_frame() {
-        let _ = connect();
-    }
-
-    // Server: Test that the connection will be closed if control stream
-    // has been closed.
-    #[test]
-    fn test_server_close_control_stream() {
-        let (mut hconn, mut peer_conn) = connect();
-        peer_conn
-            .conn
-            .stream_close_send(peer_conn.control_stream_id)
-            .unwrap();
-        let out = peer_conn.conn.process(None, now());
-        hconn.process(out.dgram(), now());
-        assert_closed(&hconn, Error::HttpClosedCriticalStream);
-    }
-
-    // Server: test missing SETTINGS frame
-    // (the first frame sent is a MAX_PUSH_ID frame).
-    #[test]
-    fn test_server_missing_settings() {
-        let (mut hconn, mut neqo_trans_conn) = connect_and_receive_settings();
-        // Create client control stream.
-        let control_stream = neqo_trans_conn.stream_create(StreamType::UniDi).unwrap();
-        // Send a MAX_PUSH_ID frame instead.
-        let sent = neqo_trans_conn.stream_send(control_stream, &[0x0, 0xd, 0x1, 0xf]);
-        assert_eq!(sent, Ok(4));
-        let out = neqo_trans_conn.process(None, now());
-        hconn.process(out.dgram(), now());
-        assert_closed(&hconn, Error::HttpMissingSettings);
-    }
-
-    // Server: receiving SETTINGS frame twice causes connection close
-    // with error HTTP_UNEXPECTED_FRAME.
-    #[test]
-    fn test_server_receive_settings_twice() {
-        let (mut hconn, mut peer_conn) = connect();
-        // send the second SETTINGS frame.
-        let sent = peer_conn.conn.stream_send(
-            peer_conn.control_stream_id,
-            &[0x4, 0x6, 0x1, 0x40, 0x64, 0x7, 0x40, 0x64],
-        );
-        assert_eq!(sent, Ok(8));
-        let out = peer_conn.conn.process(None, now());
-        hconn.process(out.dgram(), now());
-        assert_closed(&hconn, Error::HttpFrameUnexpected);
-    }
-
-    fn test_wrong_frame_on_control_stream(v: &[u8]) {
-        let (mut hconn, mut peer_conn) = connect();
-
-        // receive a frame that is not allowed on the control stream.
-        let _ = peer_conn.conn.stream_send(peer_conn.control_stream_id, v);
-
-        let out = peer_conn.conn.process(None, now());
-        hconn.process(out.dgram(), now());
-
-        assert_closed(&hconn, Error::HttpFrameUnexpected);
-    }
-
-    // send DATA frame on a cortrol stream
-    #[test]
-    fn test_server_data_frame_on_control_stream() {
-        test_wrong_frame_on_control_stream(&[0x0, 0x2, 0x1, 0x2]);
-    }
-
-    // send HEADERS frame on a cortrol stream
-    #[test]
-    fn test_server_headers_frame_on_control_stream() {
-        test_wrong_frame_on_control_stream(&[0x1, 0x2, 0x1, 0x2]);
-    }
-
-    // send PUSH_PROMISE frame on a cortrol stream
-    #[test]
-    fn test_server_push_promise_frame_on_control_stream() {
-        test_wrong_frame_on_control_stream(&[0x5, 0x2, 0x1, 0x2]);
-    }
-
-    // send DUPLICATE_PUSH frame on a cortrol stream
-    #[test]
-    fn test_server_duplicate_push_frame_on_control_stream() {
-        test_wrong_frame_on_control_stream(&[0xe, 0x2, 0x1, 0x2]);
-    }
-
-    // Server: receive unkonwn stream type
-    // also test getting stream id that does not fit into a single byte.
-    #[test]
-    fn test_server_received_unknown_stream() {
-        let (mut hconn, mut peer_conn) = connect();
-
-        // create a stream with unknown type.
-        let new_stream_id = peer_conn.conn.stream_create(StreamType::UniDi).unwrap();
-        let _ = peer_conn
-            .conn
-            .stream_send(new_stream_id, &[0x41, 0x19, 0x4, 0x4, 0x6, 0x0, 0x8, 0x0]);
-        let out = peer_conn.conn.process(None, now());
-        let out = hconn.process(out.dgram(), now());
-        peer_conn.conn.process(out.dgram(), now());
-
-        // check for stop-sending with Error::HttpStreamCreationError.
-        let mut stop_sending_event_found = false;
-        while let Some(e) = peer_conn.conn.next_event() {
-            if let ConnectionEvent::SendStreamStopSending {
-                stream_id,
-                app_error,
-            } = e
-            {
-                stop_sending_event_found = true;
-                assert_eq!(stream_id, new_stream_id);
-                assert_eq!(app_error, Error::HttpStreamCreationError.code());
-            }
-        }
-        assert!(stop_sending_event_found);
-        assert_eq!(hconn.state(), Http3State::Connected);
-    }
-
-    // Server: receiving a push stream on a server should cause WrongStreamDirection
-    #[test]
-    fn test_server_received_push_stream() {
-        let (mut hconn, mut peer_conn) = connect();
-
-        // create a push stream.
-        let push_stream_id = peer_conn.conn.stream_create(StreamType::UniDi).unwrap();
-        let _ = peer_conn.conn.stream_send(push_stream_id, &[0x1]);
-        let out = peer_conn.conn.process(None, now());
-        let out = hconn.process(out.dgram(), now());
-        peer_conn.conn.process(out.dgram(), now());
-        assert_closed(&hconn, Error::HttpStreamCreationError);
-    }
-
-    //// Test reading of a slowly streamed frame. bytes are received one by one
-    #[test]
-    fn test_server_frame_reading() {
-        let (mut hconn, mut peer_conn) = connect_and_receive_settings();
-
-        // create a control stream.
-        let control_stream = peer_conn.stream_create(StreamType::UniDi).unwrap();
-
-        // send the stream type
-        let mut sent = peer_conn.stream_send(control_stream, &[0x0]);
-        assert_eq!(sent, Ok(1));
-        let out = peer_conn.process(None, now());
-        hconn.process(out.dgram(), now());
-
-        // start sending SETTINGS frame
-        sent = peer_conn.stream_send(control_stream, &[0x4]);
-        assert_eq!(sent, Ok(1));
-        let out = peer_conn.process(None, now());
-        hconn.process(out.dgram(), now());
-
-        sent = peer_conn.stream_send(control_stream, &[0x4]);
-        assert_eq!(sent, Ok(1));
-        let out = peer_conn.process(None, now());
-        hconn.process(out.dgram(), now());
-
-        sent = peer_conn.stream_send(control_stream, &[0x6]);
-        assert_eq!(sent, Ok(1));
-        let out = peer_conn.process(None, now());
-        hconn.process(out.dgram(), now());
-
-        sent = peer_conn.stream_send(control_stream, &[0x0]);
-        assert_eq!(sent, Ok(1));
-        let out = peer_conn.process(None, now());
-        hconn.process(out.dgram(), now());
-
-        sent = peer_conn.stream_send(control_stream, &[0x8]);
-        assert_eq!(sent, Ok(1));
-        let out = peer_conn.process(None, now());
-        hconn.process(out.dgram(), now());
-
-        sent = peer_conn.stream_send(control_stream, &[0x0]);
-        assert_eq!(sent, Ok(1));
-        let out = peer_conn.process(None, now());
-        hconn.process(out.dgram(), now());
-
-        assert_eq!(hconn.state(), Http3State::Connected);
-
-        // Now test PushPromise
-        sent = peer_conn.stream_send(control_stream, &[0x5]);
-        assert_eq!(sent, Ok(1));
-        let out = peer_conn.process(None, now());
-        hconn.process(out.dgram(), now());
-
-        sent = peer_conn.stream_send(control_stream, &[0x5]);
-        assert_eq!(sent, Ok(1));
-        let out = peer_conn.process(None, now());
-        hconn.process(out.dgram(), now());
-
-        sent = peer_conn.stream_send(control_stream, &[0x4]);
-        assert_eq!(sent, Ok(1));
-        let out = peer_conn.process(None, now());
-        hconn.process(out.dgram(), now());
-
-        // PUSH_PROMISE on a control stream will cause an error
-        assert_closed(&hconn, Error::HttpFrameUnexpected);
-    }
-
-    // Test reading of a slowly streamed frame. bytes are received one by one
-    fn test_incomplet_frame(res: &[u8]) {
-        let (mut hconn, mut peer_conn) = connect_and_receive_settings();
-
-        // send an incomplete reequest.
-        let stream_id = peer_conn.stream_create(StreamType::BiDi).unwrap();
-        peer_conn.stream_send(stream_id, res).unwrap();
-        peer_conn.stream_close_send(stream_id).unwrap();
-
-        let out = peer_conn.process(None, now());
-        hconn.process(out.dgram(), now());
-
-        assert_closed(&hconn, Error::HttpFrameError);
-    }
-
-    const REQUEST_WITH_BODY: &[u8] = &[
-        // headers
-        0x01, 0x10, 0x00, 0x00, 0xd1, 0xd7, 0x50, 0x89, 0x41, 0xe9, 0x2a, 0x67, 0x35, 0x53, 0x2e,
-        0x43, 0xd3, 0xc1, // the first data frame.
-        0x0, 0x3, 0x61, 0x62, 0x63, // the second data frame.
-        0x0, 0x3, 0x64, 0x65, 0x66,
-    ];
-
-    // Incomplete DATA frame
-    #[test]
-    fn test_server_incomplet_data_frame() {
-        test_incomplet_frame(&REQUEST_WITH_BODY[..22]);
-    }
-
-    // Incomplete HEADERS frame
-    #[test]
-    fn test_server_incomplet_headers_frame() {
-        test_incomplet_frame(&REQUEST_WITH_BODY[..10]);
-    }
-
-    #[test]
-    fn test_server_incomplet_unknown_frame() {
-        test_incomplet_frame(&[0x21]);
-    }
-
-    #[test]
-    fn test_server_request_with_body() {
-        let (mut hconn, mut peer_conn) = connect();
-
-        let stream_id = peer_conn.conn.stream_create(StreamType::BiDi).unwrap();
-        peer_conn
-            .conn
-            .stream_send(stream_id, REQUEST_WITH_BODY)
-            .unwrap();
-        peer_conn.conn.stream_close_send(stream_id).unwrap();
-
-        let out = peer_conn.conn.process(None, now());
-        hconn.process(out.dgram(), now());
-
-        // Check connection event. There should be 1 Header and 2 data events.
-        let mut headers_frames = 0;
-        let mut data_frames = 0;
-        while let Some(event) = hconn.next_event() {
-            match event {
-                Http3ServerEvent::Headers { headers, fin, .. } => {
-                    assert_eq!(
-                        headers,
-                        vec![
-                            (String::from(":method"), String::from("GET")),
-                            (String::from(":scheme"), String::from("https")),
-                            (String::from(":authority"), String::from("something.com")),
-                            (String::from(":path"), String::from("/"))
-                        ]
-                    );
-                    assert_eq!(fin, false);
-                    headers_frames += 1;
-                }
-                Http3ServerEvent::Data {
-                    stream_id,
-                    data,
-                    fin,
-                } => {
-                    if data_frames == 0 {
-                        assert_eq!(data, &REQUEST_WITH_BODY[20..23]);
-                    } else {
-                        assert_eq!(data, &REQUEST_WITH_BODY[25..]);
-                        assert_eq!(fin, true);
-                        hconn
-                            .set_response(
-                                stream_id,
-                                &[
-                                    (String::from(":status"), String::from("200")),
-                                    (String::from("content-length"), String::from("3")),
-                                ],
-                                vec![0x67, 0x68, 0x69],
-                            )
-                            .unwrap();
-                    }
-                    data_frames += 1;
-                }
-                _ => {}
-            }
-        }
-        assert_eq!(headers_frames, 1);
-        assert_eq!(data_frames, 2);
-    }
-
-    #[test]
-    fn test_server_request_with_body_send_stop_sending() {
-        let (mut hconn, mut peer_conn) = connect();
-
-        let stream_id = peer_conn.conn.stream_create(StreamType::BiDi).unwrap();
-        // Send only request headers for now.
-        peer_conn
-            .conn
-            .stream_send(stream_id, &REQUEST_WITH_BODY[..20])
-            .unwrap();
-
-        let out = peer_conn.conn.process(None, now());
-        hconn.process(out.dgram(), now());
-
-        // Check connection event. There should be 1 Header and no data events.
-        let mut headers_frames = 0;
-        while let Some(event) = hconn.next_event() {
-            match event {
-                Http3ServerEvent::Headers {
-                    stream_id,
-                    headers,
-                    fin,
-                } => {
-                    assert_eq!(
-                        headers,
-                        vec![
-                            (String::from(":method"), String::from("GET")),
-                            (String::from(":scheme"), String::from("https")),
-                            (String::from(":authority"), String::from("something.com")),
-                            (String::from(":path"), String::from("/"))
-                        ]
-                    );
-                    assert_eq!(fin, false);
-                    headers_frames += 1;
-                    hconn
-                        .stream_stop_sending(stream_id, Error::HttpEarlyResponse.code())
-                        .unwrap();
-                    hconn
-                        .set_response(
-                            stream_id,
-                            &[
-                                (String::from(":status"), String::from("200")),
-                                (String::from("content-length"), String::from("3")),
-                            ],
-                            vec![0x67, 0x68, 0x69],
-                        )
-                        .unwrap();
-                }
-                Http3ServerEvent::Data { .. } => {
-                    panic!("We should not have a Data event");
-                }
-                _ => {}
-            }
-        }
-        let out = hconn.process(None, now());
-
-        // Send data.
-        peer_conn
-            .conn
-            .stream_send(stream_id, &REQUEST_WITH_BODY[20..])
-            .unwrap();
-        peer_conn.conn.stream_close_send(stream_id).unwrap();
-
-        let out = peer_conn.conn.process(out.dgram(), now());
-        hconn.process(out.dgram(), now());
-
-        while let Some(event) = hconn.next_event() {
-            match event {
-                Http3ServerEvent::Headers { .. } => {
-                    panic!("We should not have a Data event");
-                }
-                Http3ServerEvent::Data { .. } => {
-                    panic!("We should not have a Data event");
-                }
-                _ => {}
-            }
-        }
-        assert_eq!(headers_frames, 1);
-    }
-
-    #[test]
-    fn test_server_request_with_body_server_reset() {
-        let (mut hconn, mut peer_conn) = connect();
-
-        let request_stream_id = peer_conn.conn.stream_create(StreamType::BiDi).unwrap();
-        // Send only request headers for now.
-        peer_conn
-            .conn
-            .stream_send(request_stream_id, &REQUEST_WITH_BODY[..20])
-            .unwrap();
-
-        let out = peer_conn.conn.process(None, now());
-        hconn.process(out.dgram(), now());
-
-        // Check connection event. There should be 1 Header and no data events.
-        // The server will reset the stream.
-        let mut headers_frames = 0;
-        while let Some(event) = hconn.next_event() {
-            match event {
-                Http3ServerEvent::Headers {
-                    stream_id,
-                    headers,
-                    fin,
-                } => {
-                    assert_eq!(request_stream_id, stream_id);
-                    assert_eq!(
-                        headers,
-                        vec![
-                            (String::from(":method"), String::from("GET")),
-                            (String::from(":scheme"), String::from("https")),
-                            (String::from(":authority"), String::from("something.com")),
-                            (String::from(":path"), String::from("/"))
-                        ]
-                    );
-                    assert_eq!(fin, false);
-                    headers_frames += 1;
-                    hconn
-                        .stream_reset(stream_id, Error::HttpRequestRejected.code())
-                        .unwrap();
-                }
-                Http3ServerEvent::Data { .. } => {
-                    panic!("We should not have a Data event");
-                }
-                _ => {}
-            }
-        }
-        let out = hconn.process(None, now());
-
-        let out = peer_conn.conn.process(out.dgram(), now());
-        hconn.process(out.dgram(), now());
-
-        // Check that STOP_SENDING and REET has been received.
-        let mut reset = 0;
-        let mut stop_sending = 0;
-        while let Some(event) = peer_conn.conn.next_event() {
-            match event {
-                ConnectionEvent::RecvStreamReset { stream_id, .. } => {
-                    assert_eq!(request_stream_id, stream_id);
-                    reset += 1;
-                }
-                ConnectionEvent::SendStreamStopSending { stream_id, .. } => {
-                    assert_eq!(request_stream_id, stream_id);
-                    stop_sending += 1;
-                }
-                _ => {}
-            }
-        }
-        assert_eq!(headers_frames, 1);
-        assert_eq!(reset, 1);
-        assert_eq!(stop_sending, 1);
-    }
-}
--- a/third_party/rust/neqo-http3/src/control_stream_local.rs
+++ b/third_party/rust/neqo-http3/src/control_stream_local.rs
@@ -29,30 +29,30 @@ impl ControlStreamLocal {
         let mut enc = Encoder::default();
         f.encode(&mut enc);
         self.buf.append(&mut enc.into());
     }
 
     pub fn send(&mut self, conn: &mut Connection) -> Res<()> {
         if let Some(stream_id) = self.stream_id {
             if !self.buf.is_empty() {
-                qtrace!([self] "sending data.");
+                qtrace!([self], "sending data.");
                 let sent = conn.stream_send(stream_id, &self.buf[..])?;
                 if sent == self.buf.len() {
                     self.buf.clear();
                 } else {
                     let b = self.buf.split_off(sent);
                     self.buf = b;
                 }
             }
         }
         Ok(())
     }
 
     pub fn create(&mut self, conn: &mut Connection) -> Res<()> {
-        qtrace!([self] "Create a control stream.");
+        qtrace!([self], "Create a control stream.");
         self.stream_id = Some(conn.stream_create(StreamType::UniDi)?);
         let mut enc = Encoder::default();
         enc.encode_varint(HTTP3_UNI_STREAM_TYPE_CONTROL as u64);
         self.buf.append(&mut enc.into());
         Ok(())
     }
 }
--- a/third_party/rust/neqo-http3/src/control_stream_remote.rs
+++ b/third_party/rust/neqo-http3/src/control_stream_remote.rs
@@ -28,29 +28,29 @@ impl ControlStreamRemote {
         ControlStreamRemote {
             stream_id: None,
             frame_reader: HFrameReader::new(),
             fin: false,
         }
     }
 
     pub fn add_remote_stream(&mut self, stream_id: u64) -> Res<()> {
-        qinfo!([self] "A new control stream {}.", stream_id);
+        qinfo!([self], "A new control stream {}.", stream_id);
         if self.stream_id.is_some() {
-            qdebug!([self] "A control stream already exists");
+            qdebug!([self], "A control stream already exists");
             return Err(Error::HttpStreamCreationError);
         }
         self.stream_id = Some(stream_id);
         Ok(())
     }
 
     pub fn receive_if_this_stream(&mut self, conn: &mut Connection, stream_id: u64) -> Res<bool> {
         if let Some(id) = self.stream_id {
             if id == stream_id {
-                qdebug!([self] "Receiving data.");
+                qdebug!([self], "Receiving data.");
                 self.fin = self.frame_reader.receive(conn, stream_id)?;
                 return Ok(true);
             }
         }
         Ok(false)
     }
 
     pub fn recvd_fin(&self) -> bool {
--- a/third_party/rust/neqo-http3/src/hframe.rs
+++ b/third_party/rust/neqo-http3/src/hframe.rs
@@ -208,56 +208,71 @@ impl HFrameReader {
     // returns true if quic stream was closed.
     pub fn receive(&mut self, conn: &mut Connection, stream_id: u64) -> Res<bool> {
         loop {
             let to_read = std::cmp::min(self.decoder.min_remaining(), 4096);
             let mut buf = vec![0; to_read];
             let fin;
             let mut input = match conn.stream_recv(stream_id, &mut buf[..]) {
                 Ok((0, true)) => {
-                    qtrace!([conn] "HFrameReader::receive: stream has been closed");
+                    qtrace!([conn], "HFrameReader::receive: stream has been closed");
                     break match self.state {
                         HFrameReaderState::BeforeFrame => Ok(true),
                         _ => Err(Error::HttpFrameError),
                     };
                 }
                 Ok((0, false)) => break Ok(false),
                 Ok((amount, f)) => {
-                    qtrace!([conn] "HFrameReader::receive: reading {} byte, fin={}", amount, f);
+                    qtrace!(
+                        [conn],
+                        "HFrameReader::receive: reading {} byte, fin={}",
+                        amount,
+                        f
+                    );
                     fin = f;
                     Decoder::from(&buf[..amount])
                 }
                 Err(e) => {
-                    qdebug!([conn] "HFrameReader::receive: error reading data from stream {}: {:?}", stream_id, e);
+                    qdebug!(
+                        [conn],
+                        "HFrameReader::receive: error reading data from stream {}: {:?}",
+                        stream_id,
+                        e
+                    );
                     break Err(e.into());
                 }
             };
 
             // TODO(mt) this amount_read thing is terrible.
             let mut amount_read = input.remaining();
             let progress = self.decoder.consume(&mut input);
             amount_read -= input.remaining();
             match self.state {
                 HFrameReaderState::BeforeFrame | HFrameReaderState::GetType => match progress {
                     IncrementalDecoderResult::Uint(v) => {
-                        qtrace!([conn] "HFrameReader::receive: read frame type {}", v);
+                        qtrace!([conn], "HFrameReader::receive: read frame type {}", v);
                         self.hframe_type = v;
                         self.decoder = IncrementalDecoder::decode_varint();
                         self.state = HFrameReaderState::GetLength;
                     }
                     IncrementalDecoderResult::InProgress => {
                         self.state = HFrameReaderState::GetType;
                     }
                     _ => panic!("We must be in one of the states above"),
                 },
 
                 HFrameReaderState::GetLength => {
                     match progress {
                         IncrementalDecoderResult::Uint(len) => {
-                            qtrace!([conn] "HFrameReader::receive: frame type {} length {}", self.hframe_type, len);
+                            qtrace!(
+                                [conn],
+                                "HFrameReader::receive: frame type {} length {}",
+                                self.hframe_type,
+                                len
+                            );
                             self.hframe_len = len;
                             self.state = match self.hframe_type {
                                 // DATA and HEADERS payload are left on the quic stream and picked up separately
                                 H3_FRAME_TYPE_DATA | H3_FRAME_TYPE_HEADERS => {
                                     HFrameReaderState::Done
                                 }
                                 // For push frame we only decode the first varint. Headers blocks will be picked up separately.
                                 H3_FRAME_TYPE_PUSH_PROMISE => {
@@ -305,17 +320,22 @@ impl HFrameReader {
                         }
                         IncrementalDecoderResult::InProgress => {}
                         _ => panic!("We must be in one of the states above"),
                     };
                 }
                 HFrameReaderState::GetData => {
                     match progress {
                         IncrementalDecoderResult::Buffer(data) => {
-                            qtrace!([conn] "received frame {}: {}", self.hframe_type, hex(&data[..]));
+                            qtrace!(
+                                [conn],
+                                "received frame {}: {}",
+                                self.hframe_type,
+                                hex(&data[..])
+                            );
                             self.payload = data;
                             self.state = HFrameReaderState::Done;
                         }
                         IncrementalDecoderResult::InProgress => {}
                         _ => panic!("We must be in one of the states above"),
                     };
                 }
                 HFrameReaderState::UnknownFrameDischargeData => {
--- a/third_party/rust/neqo-http3/src/lib.rs
+++ b/third_party/rust/neqo-http3/src/lib.rs
@@ -4,34 +4,36 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
 #![deny(warnings)]
 
 mod client_events;
 mod connection;
 pub mod connection_client;
-pub mod connection_server;
 mod control_stream_local;
 mod control_stream_remote;
 pub mod hframe;
+pub mod server;
+mod server_connection_events;
 mod server_events;
 mod stream_type_reader;
 mod transaction_client;
 pub mod transaction_server;
+//pub mod server;
 
 use neqo_qpack;
 use neqo_transport;
 pub use neqo_transport::Output;
 
 pub use client_events::Http3ClientEvent;
 pub use connection::Http3State;
 pub use connection_client::Http3Client;
-pub use connection_server::Http3Server;
 pub use neqo_qpack::Header;
+pub use server::Http3Server;
 pub use server_events::Http3ServerEvent;
 pub use transaction_server::TransactionServer;
 
 type Res<T> = Result<T, Error>;
 
 #[derive(Clone, Debug, PartialEq)]
 pub enum Error {
     HttpNoError,
new file mode 100644
--- /dev/null
+++ b/third_party/rust/neqo-http3/src/server.rs
@@ -0,0 +1,781 @@
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::connection::Http3State;
+use crate::server_connection_events::Http3ServerConnEvent;
+use crate::server_events::{
+    ClientRequestStream, Http3Handler, Http3ServerEvent, Http3ServerEvents,
+};
+use crate::Res;
+use neqo_common::{qtrace, Datagram};
+use neqo_crypto::AntiReplay;
+use neqo_transport::server::{ActiveConnectionRef, Server};
+use neqo_transport::{ConnectionIdManager, Output};
+use std::cell::RefCell;
+use std::collections::HashMap;
+use std::rc::Rc;
+use std::time::Instant;
+
+type HandlerRef = Rc<RefCell<Http3Handler>>;
+
+pub struct Http3Server {
+    server: Server,
+    max_table_size: u32,
+    max_blocked_streams: u16,
+    connections: HashMap<ActiveConnectionRef, HandlerRef>,
+    events: Http3ServerEvents,
+}
+
+impl ::std::fmt::Display for Http3Server {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+        write!(f, "Http3 server ")
+    }
+}
+
+impl Http3Server {
+    pub fn new(
+        now: Instant,
+        certs: &[impl AsRef<str>],
+        protocols: &[impl AsRef<str>],
+        anti_replay: AntiReplay,
+        cid_manager: Rc<RefCell<dyn ConnectionIdManager>>,
+        max_table_size: u32,
+        max_blocked_streams: u16,
+    ) -> Res<Http3Server> {
+        Ok(Http3Server {
+            server: Server::new(now, certs, protocols, anti_replay, cid_manager)?,
+            max_table_size,
+            max_blocked_streams,
+            connections: HashMap::new(),
+            events: Http3ServerEvents::default(),
+        })
+    }
+
+    pub fn process(&mut self, dgram: Option<Datagram>, now: Instant) -> Output {
+        qtrace!([self], "Process.");
+        let out = self.server.process(dgram, now);
+        self.process_http3(now);
+        // If we do not that a dgram already try again after process_http3.
+        match out {
+            Output::Datagram(d) => {
+                qtrace!([self], "Send packet: {:?}", d);
+                Output::Datagram(d)
+            }
+            _ => self.server.process(None, now),
+        }
+    }
+
+    pub fn process_http3(&mut self, now: Instant) {
+        qtrace!([self], "Process http3 internal.");
+        let mut active_conns = self.server.active_connections();
+
+        // We need to find connections that needs to be process on http3 level.
+        let mut http3_active: Vec<ActiveConnectionRef> = self
+            .connections
+            .iter()
+            .filter(|(conn, handler)| {
+                handler.borrow().should_be_processed() && !active_conns.contains(&conn)
+            })
+            .map(|(conn, _)| conn)
+            .cloned()
+            .collect();
+        // For http_active connection we need to put them in neqo-transport's server
+        // waiting queue.
+        http3_active
+            .iter()
+            .for_each(|conn| self.server.add_to_waiting(conn.clone()));
+        active_conns.append(&mut http3_active);
+        active_conns.dedup();
+        let max_table_size = self.max_table_size;
+        let max_blocked_streams = self.max_blocked_streams;
+        for mut conn in active_conns {
+            let handler = self.connections.entry(conn.clone()).or_insert_with(|| {
+                Rc::new(RefCell::new(Http3Handler::new(
+                    max_table_size,
+                    max_blocked_streams,
+                )))
+            });
+
+            handler
+                .borrow_mut()
+                .process_http3(&mut conn.borrow_mut(), now);
+            let mut remove = false;
+            while let Some(e) = handler.borrow_mut().next_event() {
+                match e {
+                    Http3ServerConnEvent::Headers {
+                        stream_id,
+                        headers,
+                        fin,
+                    } => self.events.headers(
+                        ClientRequestStream::new(conn.clone(), handler.clone(), stream_id),
+                        headers,
+                        fin,
+                    ),
+                    Http3ServerConnEvent::Data {
+                        stream_id,
+                        data,
+                        fin,
+                    } => self.events.data(
+                        ClientRequestStream::new(conn.clone(), handler.clone(), stream_id),
+                        data,
+                        fin,
+                    ),
+                    Http3ServerConnEvent::StateChange(state) => {
+                        self.events
+                            .connection_state_change(conn.clone(), state.clone());
+                        if let Http3State::Closed { .. } = state {
+                            remove = true;
+                        }
+                    }
+                    _ => {}
+                }
+            }
+            if remove {
+                self.connections.remove(&conn.clone());
+            }
+        }
+    }
+
+    /// Get all current events. Best used just in debug/testing code, use
+    /// next_event() instead.
+    pub fn events(&mut self) -> impl Iterator<Item = Http3ServerEvent> {
+        self.events.events()
+    }
+
+    /// Return true if there are outstanding events.
+    pub fn has_events(&self) -> bool {
+        self.events.has_events()
+    }
+
+    /// Get events that indicate state changes on the connection. This method
+    /// correctly handles cases where handling one event can obsolete
+    /// previously-queued events, or cause new events to be generated.
+    pub fn next_event(&mut self) -> Option<Http3ServerEvent> {
+        self.events.next_event()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::Error;
+    use neqo_common::matches;
+    use neqo_crypto::AuthenticationStatus;
+    use neqo_qpack::encoder::QPackEncoder;
+    use neqo_transport::{
+        CloseError, Connection, ConnectionEvent, FixedConnectionIdManager, State, StreamType,
+    };
+    use test_fixture::*;
+
+    /// Create a http3 server with default configuration.
+    pub fn default_http3_server() -> Http3Server {
+        fixture_init();
+        Http3Server::new(
+            now(),
+            DEFAULT_KEYS,
+            DEFAULT_ALPN,
+            anti_replay(),
+            Rc::new(RefCell::new(FixedConnectionIdManager::new(5))),
+            100,
+            100,
+        )
+        .expect("create a default server")
+    }
+
+    fn assert_closed(hconn: &mut Http3Server, expected: Error) {
+        let err = CloseError::Application(expected.code());
+        let closed = |e| {
+            matches!(e,
+            Http3ServerEvent::StateChange{ state: Http3State::Closing(e), .. }
+            | Http3ServerEvent::StateChange{ state: Http3State::Closed(e), .. }
+              if e == err)
+        };
+        assert!(hconn.events().any(closed));
+    }
+
+    fn assert_connected(hconn: &mut Http3Server) {
+        let connected =
+            |e| matches!(e, Http3ServerEvent::StateChange{ state: Http3State::Connected, ..} );
+        assert!(hconn.events().any(connected));
+    }
+
+    fn assert_not_closed(hconn: &mut Http3Server) {
+        let closed = |e| {
+            matches!(e,
+            Http3ServerEvent::StateChange{ state: Http3State::Closing(..), .. })
+        };
+        assert!(!hconn.events().any(closed));
+    }
+
+    // Start a client/server and check setting frame.
+    #[allow(clippy::cognitive_complexity)]
+    fn connect_and_receive_settings() -> (Http3Server, Connection) {
+        // Create a server and connect it to a client.
+        // We will have a http3 server on one side and a neqo_transport
+        // connection on the other side so that we can check what the http3
+        // side sends and also to simulate an incorrectly behaving http3
+        // client.
+
+        fixture_init();
+        let mut hconn = default_http3_server();
+        let mut neqo_trans_conn = default_client();
+
+        let out = neqo_trans_conn.process(None, now());
+        let out = hconn.process(out.dgram(), now());
+        let out = neqo_trans_conn.process(out.dgram(), now());
+        let _ = hconn.process(out.dgram(), now());
+        let authentication_needed = |e| matches!(e, ConnectionEvent::AuthenticationNeeded);
+        assert!(neqo_trans_conn.events().any(authentication_needed));
+        neqo_trans_conn.authenticated(AuthenticationStatus::Ok, now());
+        let out = neqo_trans_conn.process(None, now());
+        let out = hconn.process(out.dgram(), now());
+        assert_connected(&mut hconn);
+        neqo_trans_conn.process(out.dgram(), now());
+
+        let mut connected = false;
+        while let Some(e) = neqo_trans_conn.next_event() {
+            match e {
+                ConnectionEvent::NewStream {
+                    stream_id,
+                    stream_type,
+                } => {
+                    assert!((stream_id == 3) || (stream_id == 7) || (stream_id == 11));
+                    assert_eq!(stream_type, StreamType::UniDi);
+                }
+                ConnectionEvent::RecvStreamReadable { stream_id } => {
+                    if stream_id == 2 || stream_id == 3 {
+                        // the control stream
+                        let mut buf = [0u8; 100];
+                        let (amount, fin) =
+                            neqo_trans_conn.stream_recv(stream_id, &mut buf).unwrap();
+                        assert_eq!(fin, false);
+                        const CONTROL_STREAM_DATA: &[u8] =
+                            &[0x0, 0x4, 0x6, 0x1, 0x40, 0x64, 0x7, 0x40, 0x64];
+                        assert_eq!(amount, CONTROL_STREAM_DATA.len());
+                        assert_eq!(&buf[..9], CONTROL_STREAM_DATA);
+                    } else if stream_id == 6 || stream_id == 7 {
+                        let mut buf = [0u8; 100];
+                        let (amount, fin) =
+                            neqo_trans_conn.stream_recv(stream_id, &mut buf).unwrap();
+                        assert_eq!(fin, false);
+                        assert_eq!(amount, 1);
+                        assert_eq!(buf[..1], [0x2]);
+                    } else if stream_id == 10 || stream_id == 11 {
+                        let mut buf = [0u8; 100];
+                        let (amount, fin) =
+                            neqo_trans_conn.stream_recv(stream_id, &mut buf).unwrap();
+                        assert_eq!(fin, false);
+                        assert_eq!(amount, 1);
+                        assert_eq!(buf[..1], [0x3]);
+                    } else {
+                        panic!("unexpected event");
+                    }
+                }
+                ConnectionEvent::SendStreamWritable { stream_id } => {
+                    assert!((stream_id == 2) || (stream_id == 6) || (stream_id == 10));
+                }
+                ConnectionEvent::StateChange(State::Connected) => connected = true,
+                ConnectionEvent::StateChange(_) => (),
+                _ => panic!("unexpected event"),
+            }
+        }
+        assert!(connected);
+        (hconn, neqo_trans_conn)
+    }
+
+    // Test http3 connection inintialization.
+    // The server will open the control and qpack streams and send SETTINGS frame.
+    #[test]
+    fn test_server_connect() {
+        let _ = connect_and_receive_settings();
+    }
+
+    struct PeerConnection {
+        conn: Connection,
+        control_stream_id: u64,
+    }
+
+    // Connect transport, send and receive settings.
+    fn connect() -> (Http3Server, PeerConnection) {
+        let (mut hconn, mut neqo_trans_conn) = connect_and_receive_settings();
+        let control_stream = neqo_trans_conn.stream_create(StreamType::UniDi).unwrap();
+        let mut sent = neqo_trans_conn.stream_send(
+            control_stream,
+            &[0x0, 0x4, 0x6, 0x1, 0x40, 0x64, 0x7, 0x40, 0x64],
+        );
+        assert_eq!(sent, Ok(9));
+        let mut encoder = QPackEncoder::new(true);
+        encoder.add_send_stream(neqo_trans_conn.stream_create(StreamType::UniDi).unwrap());
+        encoder.send(&mut neqo_trans_conn).unwrap();
+        let decoder_stream = neqo_trans_conn.stream_create(StreamType::UniDi).unwrap();
+        sent = neqo_trans_conn.stream_send(decoder_stream, &[0x3]);
+        assert_eq!(sent, Ok(1));
+        let out = neqo_trans_conn.process(None, now());
+        hconn.process(out.dgram(), now());
+
+        // assert no error occured.
+        assert_not_closed(&mut hconn);
+        (
+            hconn,
+            PeerConnection {
+                conn: neqo_trans_conn,
+                control_stream_id: control_stream,
+            },
+        )
+    }
+
+    // Server: Test receiving a new control stream and a SETTINGS frame.
+    #[test]
+    fn test_server_receive_control_frame() {
+        let _ = connect();
+    }
+
+    // Server: Test that the connection will be closed if control stream
+    // has been closed.
+    #[test]
+    fn test_server_close_control_stream() {
+        let (mut hconn, mut peer_conn) = connect();
+        peer_conn
+            .conn
+            .stream_close_send(peer_conn.control_stream_id)
+            .unwrap();
+        let out = peer_conn.conn.process(None, now());
+        hconn.process(out.dgram(), now());
+        assert_closed(&mut hconn, Error::HttpClosedCriticalStream);
+    }
+
+    // Server: test missing SETTINGS frame
+    // (the first frame sent is a MAX_PUSH_ID frame).
+    #[test]
+    fn test_server_missing_settings() {
+        let (mut hconn, mut neqo_trans_conn) = connect_and_receive_settings();
+        // Create client control stream.
+        let control_stream = neqo_trans_conn.stream_create(StreamType::UniDi).unwrap();
+        // Send a MAX_PUSH_ID frame instead.
+        let sent = neqo_trans_conn.stream_send(control_stream, &[0x0, 0xd, 0x1, 0xf]);
+        assert_eq!(sent, Ok(4));
+        let out = neqo_trans_conn.process(None, now());
+        hconn.process(out.dgram(), now());
+        assert_closed(&mut hconn, Error::HttpMissingSettings);
+    }
+
+    // Server: receiving SETTINGS frame twice causes connection close
+    // with error HTTP_UNEXPECTED_FRAME.
+    #[test]
+    fn test_server_receive_settings_twice() {
+        let (mut hconn, mut peer_conn) = connect();
+        // send the second SETTINGS frame.
+        let sent = peer_conn.conn.stream_send(
+            peer_conn.control_stream_id,
+            &[0x4, 0x6, 0x1, 0x40, 0x64, 0x7, 0x40, 0x64],
+        );
+        assert_eq!(sent, Ok(8));
+        let out = peer_conn.conn.process(None, now());
+        hconn.process(out.dgram(), now());
+        assert_closed(&mut hconn, Error::HttpFrameUnexpected);
+    }
+
+    fn test_wrong_frame_on_control_stream(v: &[u8]) {
+        let (mut hconn, mut peer_conn) = connect();
+
+        // receive a frame that is not allowed on the control stream.
+        let _ = peer_conn.conn.stream_send(peer_conn.control_stream_id, v);
+
+        let out = peer_conn.conn.process(None, now());
+        hconn.process(out.dgram(), now());
+        assert_closed(&mut hconn, Error::HttpFrameUnexpected);
+    }
+
+    // send DATA frame on a cortrol stream
+    #[test]
+    fn test_server_data_frame_on_control_stream() {
+        test_wrong_frame_on_control_stream(&[0x0, 0x2, 0x1, 0x2]);
+    }
+
+    // send HEADERS frame on a cortrol stream
+    #[test]
+    fn test_server_headers_frame_on_control_stream() {
+        test_wrong_frame_on_control_stream(&[0x1, 0x2, 0x1, 0x2]);
+    }
+
+    // send PUSH_PROMISE frame on a cortrol stream
+    #[test]
+    fn test_server_push_promise_frame_on_control_stream() {
+        test_wrong_frame_on_control_stream(&[0x5, 0x2, 0x1, 0x2]);
+    }
+
+    // send DUPLICATE_PUSH frame on a cortrol stream
+    #[test]
+    fn test_server_duplicate_push_frame_on_control_stream() {
+        test_wrong_frame_on_control_stream(&[0xe, 0x2, 0x1, 0x2]);
+    }
+
+    // Server: receive unkonwn stream type
+    // also test getting stream id that does not fit into a single byte.
+    #[test]
+    fn test_server_received_unknown_stream() {
+        let (mut hconn, mut peer_conn) = connect();
+
+        // create a stream with unknown type.
+        let new_stream_id = peer_conn.conn.stream_create(StreamType::UniDi).unwrap();
+        let _ = peer_conn
+            .conn
+            .stream_send(new_stream_id, &[0x41, 0x19, 0x4, 0x4, 0x6, 0x0, 0x8, 0x0]);
+        let out = peer_conn.conn.process(None, now());
+        let out = hconn.process(out.dgram(), now());
+        peer_conn.conn.process(out.dgram(), now());
+        let out = hconn.process(None, now());
+        peer_conn.conn.process(out.dgram(), now());
+
+        // check for stop-sending with Error::HttpStreamCreationError.
+        let mut stop_sending_event_found = false;
+        while let Some(e) = peer_conn.conn.next_event() {
+            if let ConnectionEvent::SendStreamStopSending {
+                stream_id,
+                app_error,
+            } = e
+            {
+                stop_sending_event_found = true;
+                assert_eq!(stream_id, new_stream_id);
+                assert_eq!(app_error, Error::HttpStreamCreationError.code());
+            }
+        }
+        assert!(stop_sending_event_found);
+        assert_not_closed(&mut hconn);
+    }
+
+    // Server: receiving a push stream on a server should cause WrongStreamDirection
+    #[test]
+    fn test_server_received_push_stream() {
+        let (mut hconn, mut peer_conn) = connect();
+
+        // create a push stream.
+        let push_stream_id = peer_conn.conn.stream_create(StreamType::UniDi).unwrap();
+        let _ = peer_conn.conn.stream_send(push_stream_id, &[0x1]);
+        let out = peer_conn.conn.process(None, now());
+        let out = hconn.process(out.dgram(), now());
+        peer_conn.conn.process(out.dgram(), now());
+        assert_closed(&mut hconn, Error::HttpStreamCreationError);
+    }
+
+    //// Test reading of a slowly streamed frame. bytes are received one by one
+    #[test]
+    fn test_server_frame_reading() {
+        let (mut hconn, mut peer_conn) = connect_and_receive_settings();
+
+        // create a control stream.
+        let control_stream = peer_conn.stream_create(StreamType::UniDi).unwrap();
+
+        // send the stream type
+        let mut sent = peer_conn.stream_send(control_stream, &[0x0]);
+        assert_eq!(sent, Ok(1));
+        let out = peer_conn.process(None, now());
+        hconn.process(out.dgram(), now());
+
+        // start sending SETTINGS frame
+        sent = peer_conn.stream_send(control_stream, &[0x4]);
+        assert_eq!(sent, Ok(1));
+        let out = peer_conn.process(None, now());
+        hconn.process(out.dgram(), now());
+
+        sent = peer_conn.stream_send(control_stream, &[0x4]);
+        assert_eq!(sent, Ok(1));
+        let out = peer_conn.process(None, now());
+        hconn.process(out.dgram(), now());
+
+        sent = peer_conn.stream_send(control_stream, &[0x6]);
+        assert_eq!(sent, Ok(1));
+        let out = peer_conn.process(None, now());
+        hconn.process(out.dgram(), now());
+
+        sent = peer_conn.stream_send(control_stream, &[0x0]);
+        assert_eq!(sent, Ok(1));
+        let out = peer_conn.process(None, now());
+        hconn.process(out.dgram(), now());
+
+        sent = peer_conn.stream_send(control_stream, &[0x8]);
+        assert_eq!(sent, Ok(1));
+        let out = peer_conn.process(None, now());
+        hconn.process(out.dgram(), now());
+
+        sent = peer_conn.stream_send(control_stream, &[0x0]);
+        assert_eq!(sent, Ok(1));
+        let out = peer_conn.process(None, now());
+        hconn.process(out.dgram(), now());
+
+        assert_not_closed(&mut hconn);
+
+        // Now test PushPromise
+        sent = peer_conn.stream_send(control_stream, &[0x5]);
+        assert_eq!(sent, Ok(1));
+        let out = peer_conn.process(None, now());
+        hconn.process(out.dgram(), now());
+
+        sent = peer_conn.stream_send(control_stream, &[0x5]);
+        assert_eq!(sent, Ok(1));
+        let out = peer_conn.process(None, now());
+        hconn.process(out.dgram(), now());
+
+        sent = peer_conn.stream_send(control_stream, &[0x4]);
+        assert_eq!(sent, Ok(1));
+        let out = peer_conn.process(None, now());
+        hconn.process(out.dgram(), now());
+
+        // PUSH_PROMISE on a control stream will cause an error
+        assert_closed(&mut hconn, Error::HttpFrameUnexpected);
+    }
+
+    // Test reading of a slowly streamed frame. bytes are received one by one
+    fn test_incomplet_frame(res: &[u8]) {
+        let (mut hconn, mut peer_conn) = connect_and_receive_settings();
+
+        // send an incomplete reequest.
+        let stream_id = peer_conn.stream_create(StreamType::BiDi).unwrap();
+        peer_conn.stream_send(stream_id, res).unwrap();
+        peer_conn.stream_close_send(stream_id).unwrap();
+
+        let out = peer_conn.process(None, now());
+        hconn.process(out.dgram(), now());
+
+        assert_closed(&mut hconn, Error::HttpFrameError);
+    }
+
+    const REQUEST_WITH_BODY: &[u8] = &[
+        // headers
+        0x01, 0x10, 0x00, 0x00, 0xd1, 0xd7, 0x50, 0x89, 0x41, 0xe9, 0x2a, 0x67, 0x35, 0x53, 0x2e,
+        0x43, 0xd3, 0xc1, // the first data frame.
+        0x0, 0x3, 0x61, 0x62, 0x63, // the second data frame.
+        0x0, 0x3, 0x64, 0x65, 0x66,
+    ];
+
+    // Incomplete DATA frame
+    #[test]
+    fn test_server_incomplet_data_frame() {
+        test_incomplet_frame(&REQUEST_WITH_BODY[..22]);
+    }
+
+    // Incomplete HEADERS frame
+    #[test]
+    fn test_server_incomplet_headers_frame() {
+        test_incomplet_frame(&REQUEST_WITH_BODY[..10]);
+    }
+
+    #[test]
+    fn test_server_incomplet_unknown_frame() {
+        test_incomplet_frame(&[0x21]);
+    }
+
+    #[test]
+    fn test_server_request_with_body() {
+        let (mut hconn, mut peer_conn) = connect();
+
+        let stream_id = peer_conn.conn.stream_create(StreamType::BiDi).unwrap();
+        peer_conn
+            .conn
+            .stream_send(stream_id, REQUEST_WITH_BODY)
+            .unwrap();
+        peer_conn.conn.stream_close_send(stream_id).unwrap();
+
+        let out = peer_conn.conn.process(None, now());
+        hconn.process(out.dgram(), now());
+
+        // Check connection event. There should be 1 Header and 2 data events.
+        let mut headers_frames = 0;
+        let mut data_frames = 0;
+        while let Some(event) = hconn.next_event() {
+            match event {
+                Http3ServerEvent::Headers { headers, fin, .. } => {
+                    assert_eq!(
+                        headers,
+                        vec![
+                            (String::from(":method"), String::from("GET")),
+                            (String::from(":scheme"), String::from("https")),
+                            (String::from(":authority"), String::from("something.com")),
+                            (String::from(":path"), String::from("/"))
+                        ]
+                    );
+                    assert_eq!(fin, false);
+                    headers_frames += 1;
+                }
+                Http3ServerEvent::Data {
+                    mut request,
+                    data,
+                    fin,
+                } => {
+                    if data_frames == 0 {
+                        assert_eq!(data, &REQUEST_WITH_BODY[20..23]);
+                    } else {
+                        assert_eq!(data, &REQUEST_WITH_BODY[25..]);
+                        assert_eq!(fin, true);
+                        request
+                            .set_response(
+                                &[
+                                    (String::from(":status"), String::from("200")),
+                                    (String::from("content-length"), String::from("3")),
+                                ],
+                                vec![0x67, 0x68, 0x69],
+                            )
+                            .unwrap();
+                    }
+                    data_frames += 1;
+                }
+                _ => {}
+            }
+        }
+        assert_eq!(headers_frames, 1);
+        assert_eq!(data_frames, 2);
+    }
+
+    #[test]
+    fn test_server_request_with_body_send_stop_sending() {
+        let (mut hconn, mut peer_conn) = connect();
+
+        let stream_id = peer_conn.conn.stream_create(StreamType::BiDi).unwrap();
+        // Send only request headers for now.
+        peer_conn
+            .conn
+            .stream_send(stream_id, &REQUEST_WITH_BODY[..20])
+            .unwrap();
+
+        let out = peer_conn.conn.process(None, now());
+        hconn.process(out.dgram(), now());
+
+        // Check connection event. There should be 1 Header and no data events.
+        let mut headers_frames = 0;
+        while let Some(event) = hconn.next_event() {
+            match event {
+                Http3ServerEvent::Headers {
+                    mut request,
+                    headers,
+                    fin,
+                } => {
+                    assert_eq!(
+                        headers,
+                        vec![
+                            (String::from(":method"), String::from("GET")),
+                            (String::from(":scheme"), String::from("https")),
+                            (String::from(":authority"), String::from("something.com")),
+                            (String::from(":path"), String::from("/"))
+                        ]
+                    );
+                    assert_eq!(fin, false);
+                    headers_frames += 1;
+                    request
+                        .stream_stop_sending(Error::HttpEarlyResponse.code())
+                        .unwrap();
+                    request
+                        .set_response(
+                            &[
+                                (String::from(":status"), String::from("200")),
+                                (String::from("content-length"), String::from("3")),
+                            ],
+                            vec![0x67, 0x68, 0x69],
+                        )
+                        .unwrap();
+                }
+                Http3ServerEvent::Data { .. } => {
+                    panic!("We should not have a Data event");
+                }
+                _ => {}
+            }
+        }
+        let out = hconn.process(None, now());
+
+        // Send data.
+        peer_conn
+            .conn
+            .stream_send(stream_id, &REQUEST_WITH_BODY[20..])
+            .unwrap();
+        peer_conn.conn.stream_close_send(stream_id).unwrap();
+
+        let out = peer_conn.conn.process(out.dgram(), now());
+        hconn.process(out.dgram(), now());
+
+        while let Some(event) = hconn.next_event() {
+            match event {
+                Http3ServerEvent::Headers { .. } => {
+                    panic!("We should not have a Data event");
+                }
+                Http3ServerEvent::Data { .. } => {
+                    panic!("We should not have a Data event");
+                }
+                _ => {}
+            }
+        }
+        assert_eq!(headers_frames, 1);
+    }
+
+    #[test]
+    fn test_server_request_with_body_server_reset() {
+        let (mut hconn, mut peer_conn) = connect();
+
+        let request_stream_id = peer_conn.conn.stream_create(StreamType::BiDi).unwrap();
+        // Send only request headers for now.
+        peer_conn
+            .conn
+            .stream_send(request_stream_id, &REQUEST_WITH_BODY[..20])
+            .unwrap();
+
+        let out = peer_conn.conn.process(None, now());
+        hconn.process(out.dgram(), now());
+
+        // Check connection event. There should be 1 Header and no data events.
+        // The server will reset the stream.
+        let mut headers_frames = 0;
+        while let Some(event) = hconn.next_event() {
+            match event {
+                Http3ServerEvent::Headers {
+                    mut request,
+                    headers,
+                    fin,
+                } => {
+                    assert_eq!(
+                        headers,
+                        vec![
+                            (String::from(":method"), String::from("GET")),
+                            (String::from(":scheme"), String::from("https")),
+                            (String::from(":authority"), String::from("something.com")),
+                            (String::from(":path"), String::from("/"))
+                        ]
+                    );
+                    assert_eq!(fin, false);
+                    headers_frames += 1;
+                    request
+                        .stream_reset(Error::HttpRequestRejected.code())
+                        .unwrap();
+                }
+                Http3ServerEvent::Data { .. } => {
+                    panic!("We should not have a Data event");
+                }
+                _ => {}
+            }
+        }
+        let out = hconn.process(None, now());
+
+        let out = peer_conn.conn.process(out.dgram(), now());
+        hconn.process(out.dgram(), now());
+
+        // Check that STOP_SENDING and REET has been received.
+        let mut reset = 0;
+        let mut stop_sending = 0;
+        while let Some(event) = peer_conn.conn.next_event() {
+            match event {
+                ConnectionEvent::RecvStreamReset { stream_id, .. } => {
+                    assert_eq!(request_stream_id, stream_id);
+                    reset += 1;
+                }
+                ConnectionEvent::SendStreamStopSending { stream_id, .. } => {
+                    assert_eq!(request_stream_id, stream_id);
+                    stop_sending += 1;
+                }
+                _ => {}
+            }
+        }
+        assert_eq!(headers_frames, 1);
+        assert_eq!(reset, 1);
+        assert_eq!(stop_sending, 1);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/neqo-http3/src/server_connection_events.rs
@@ -0,0 +1,97 @@
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use crate::connection::{Http3Events, Http3State};
+use crate::Header;
+use neqo_common::matches;
+use neqo_transport::AppError;
+
+use std::cell::RefCell;
+use std::collections::VecDeque;
+use std::rc::Rc;
+
+#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)]
+pub enum Http3ServerConnEvent {
+    /// Headers are ready.
+    Headers {
+        stream_id: u64,
+        headers: Vec<Header>,
+        fin: bool,
+    },
+    /// Request data is ready.
+    Data {
+        stream_id: u64,
+        data: Vec<u8>,
+        fin: bool,
+    },
+    /// Peer reset the stream.
+    Reset { stream_id: u64, error: AppError },
+    /// Connection state change.
+    StateChange(Http3State),
+}
+
+#[derive(Debug, Default, Clone)]
+pub struct Http3ServerConnEvents {
+    events: Rc<RefCell<VecDeque<Http3ServerConnEvent>>>,
+}
+
+impl Http3ServerConnEvents {
+    fn insert(&self, event: Http3ServerConnEvent) {
+        self.events.borrow_mut().push_back(event);
+    }
+
+    fn remove<F>(&self, f: F)
+    where
+        F: Fn(&Http3ServerConnEvent) -> bool,
+    {
+        self.events.borrow_mut().retain(|evt| !f(evt))
+    }
+
+    pub fn events(&self) -> impl Iterator<Item = Http3ServerConnEvent> {
+        self.events.replace(VecDeque::new()).into_iter()
+    }
+
+    pub fn has_events(&self) -> bool {
+        !self.events.borrow().is_empty()
+    }
+
+    pub fn next_event(&self) -> Option<Http3ServerConnEvent> {
+        self.events.borrow_mut().pop_front()
+    }
+
+    pub fn headers(&self, stream_id: u64, headers: Vec<Header>, fin: bool) {
+        self.insert(Http3ServerConnEvent::Headers {
+            stream_id,
+            headers,
+            fin,
+        });
+    }
+
+    pub fn data(&self, stream_id: u64, data: Vec<u8>, fin: bool) {
+        self.insert(Http3ServerConnEvent::Data {
+            stream_id,
+            data,
+            fin,
+        });
+    }
+}
+
+impl Http3Events for Http3ServerConnEvents {
+    fn reset(&self, stream_id: u64, error: AppError) {
+        self.insert(Http3ServerConnEvent::Reset { stream_id, error });
+    }
+
+    fn connection_state_change(&self, state: Http3State) {
+        self.insert(Http3ServerConnEvent::StateChange(state));
+    }
+
+    fn remove_events_for_stream_id(&self, stream_id: u64) {
+        self.remove(|evt| {
+            matches!(evt,
+                Http3ServerConnEvent::Reset { stream_id: x, .. } if *x == stream_id)
+        });
+    }
+}
--- a/third_party/rust/neqo-http3/src/server_events.rs
+++ b/third_party/rust/neqo-http3/src/server_events.rs
@@ -1,97 +1,184 @@
 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use crate::connection::{Http3Events, Http3State};
-use crate::Header;
-use neqo_common::matches;
-use neqo_transport::AppError;
+use crate::connection::{Http3Connection, Http3ServerHandler, Http3State};
+use crate::server_connection_events::{Http3ServerConnEvent, Http3ServerConnEvents};
+use crate::transaction_server::TransactionServer;
+use crate::{Error, Header, Res};
+use neqo_common::{qdebug, qinfo};
+use neqo_transport::server::ActiveConnectionRef;
+use neqo_transport::{AppError, Connection};
 
 use std::cell::RefCell;
 use std::collections::VecDeque;
 use std::rc::Rc;
+use std::time::Instant;
 
-#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)]
+pub type Http3ServerConnection =
+    Http3Connection<Http3ServerConnEvents, TransactionServer, Http3ServerHandler>;
+
+#[derive(Debug)]
+pub struct Http3Handler {
+    handler: Http3ServerConnection,
+}
+
+impl Http3Handler {
+    pub fn new(max_table_size: u32, max_blocked_streams: u16) -> Self {
+        Http3Handler {
+            handler: Http3Connection::new(max_table_size, max_blocked_streams),
+        }
+    }
+    pub fn set_response(&mut self, stream_id: u64, headers: &[Header], data: Vec<u8>) -> Res<()> {
+        self.handler
+            .transactions
+            .get_mut(&stream_id)
+            .ok_or(Error::InvalidStreamId)?
+            .set_response(headers, data, &mut self.handler.qpack_encoder);
+        self.handler.insert_streams_have_data_to_send(stream_id);
+        Ok(())
+    }
+
+    pub fn stream_reset(
+        &mut self,
+        conn: &mut Connection,
+        stream_id: u64,
+        app_error: AppError,
+    ) -> Res<()> {
+        self.handler.stream_reset(conn, stream_id, app_error)
+    }
+
+    pub fn process_http3(&mut self, conn: &mut Connection, now: Instant) {
+        self.handler.process_http3(conn, now);
+    }
+
+    pub fn next_event(&mut self) -> Option<Http3ServerConnEvent> {
+        self.handler.events.next_event()
+    }
+
+    pub fn should_be_processed(&self) -> bool {
+        self.handler.has_data_to_send() | self.handler.events.has_events()
+    }
+}
+
+#[derive(Debug, Clone)]
+pub struct ClientRequestStream {
+    conn: ActiveConnectionRef,
+    handler: Rc<RefCell<Http3Handler>>,
+    stream_id: u64,
+}
+
+impl ::std::fmt::Display for ClientRequestStream {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+        let conn: &Connection = &self.conn.borrow();
+        write!(
+            f,
+            "Http3 server conn={:?} stream_id={}",
+            conn, self.stream_id
+        )
+    }
+}
+
+impl ClientRequestStream {
+    pub fn new(
+        conn: ActiveConnectionRef,
+        handler: Rc<RefCell<Http3Handler>>,
+        stream_id: u64,
+    ) -> Self {
+        ClientRequestStream {
+            conn,
+            handler,
+            stream_id,
+        }
+    }
+    pub fn set_response(&mut self, headers: &[Header], data: Vec<u8>) -> Res<()> {
+        qinfo!([self], "Set new response.");
+        self.handler
+            .borrow_mut()
+            .set_response(self.stream_id, headers, data)
+    }
+
+    pub fn stream_stop_sending(&mut self, app_error: AppError) -> Res<()> {
+        qdebug!(
+            [self],
+            "stop sending stream_id:{} error:{}.",
+            self.stream_id,
+            app_error
+        );
+        self.conn
+            .borrow_mut()
+            .stream_stop_sending(self.stream_id, app_error)?;
+        Ok(())
+    }
+
+    pub fn stream_reset(&mut self, app_error: AppError) -> Res<()> {
+        qdebug!([self], "reset error:{}.", app_error);
+        self.handler.borrow_mut().stream_reset(
+            &mut self.conn.borrow_mut(),
+            self.stream_id,
+            app_error,
+        )
+    }
+}
+
+#[derive(Debug, Clone)]
 pub enum Http3ServerEvent {
     /// Headers are ready.
     Headers {
-        stream_id: u64,
+        request: ClientRequestStream,
         headers: Vec<Header>,
         fin: bool,
     },
     /// Request data is ready.
     Data {
-        stream_id: u64,
+        request: ClientRequestStream,
         data: Vec<u8>,
         fin: bool,
     },
-    /// Peer reset the stream.
-    Reset { stream_id: u64, error: AppError },
-    /// Connection state change.
-    StateChange(Http3State),
+    /// When individual connection change state. It is only used for tests.
+    StateChange {
+        conn: ActiveConnectionRef,
+        state: Http3State,
+    },
 }
 
 #[derive(Debug, Default, Clone)]
 pub struct Http3ServerEvents {
     events: Rc<RefCell<VecDeque<Http3ServerEvent>>>,
 }
 
 impl Http3ServerEvents {
     fn insert(&self, event: Http3ServerEvent) {
         self.events.borrow_mut().push_back(event);
     }
 
-    fn remove<F>(&self, f: F)
-    where
-        F: Fn(&Http3ServerEvent) -> bool,
-    {
-        self.events.borrow_mut().retain(|evt| !f(evt))
-    }
-
     pub fn events(&self) -> impl Iterator<Item = Http3ServerEvent> {
         self.events.replace(VecDeque::new()).into_iter()
     }
 
     pub fn has_events(&self) -> bool {
         !self.events.borrow().is_empty()
     }
 
     pub fn next_event(&self) -> Option<Http3ServerEvent> {
         self.events.borrow_mut().pop_front()
     }
 
-    pub fn headers(&self, stream_id: u64, headers: Vec<Header>, fin: bool) {
+    pub fn headers(&self, request: ClientRequestStream, headers: Vec<Header>, fin: bool) {
         self.insert(Http3ServerEvent::Headers {
-            stream_id,
+            request,
             headers,
             fin,
         });
     }
 
-    pub fn data(&self, stream_id: u64, data: Vec<u8>, fin: bool) {
-        self.insert(Http3ServerEvent::Data {
-            stream_id,
-            data,
-            fin,
-        });
+    pub fn connection_state_change(&self, conn: ActiveConnectionRef, state: Http3State) {
+        self.insert(Http3ServerEvent::StateChange { conn, state });
+    }
+
+    pub fn data(&self, request: ClientRequestStream, data: Vec<u8>, fin: bool) {
+        self.insert(Http3ServerEvent::Data { request, data, fin });
     }
 }
-
-impl Http3Events for Http3ServerEvents {
-    fn reset(&self, stream_id: u64, error: AppError) {
-        self.insert(Http3ServerEvent::Reset { stream_id, error });
-    }
-
-    fn connection_state_change(&self, state: Http3State) {
-        self.insert(Http3ServerEvent::StateChange(state));
-    }
-
-    fn remove_events_for_stream_id(&self, stream_id: u64) {
-        self.remove(|evt| {
-            matches!(evt,
-                Http3ServerEvent::Reset { stream_id: x, .. } if *x == stream_id)
-        });
-    }
-}
--- a/third_party/rust/neqo-http3/src/stream_type_reader.rs
+++ b/third_party/rust/neqo-http3/src/stream_type_reader.rs
@@ -41,17 +41,22 @@ impl NewStreamTypeReader {
                         }
                         IncrementalDecoderResult::InProgress => {}
                         _ => {
                             return None;
                         }
                     }
                 }
                 Err(e) => {
-                    qdebug!([conn] "Error reading stream type for stream {}: {:?}", stream_id, e);
+                    qdebug!(
+                        [conn],
+                        "Error reading stream type for stream {}: {:?}",
+                        stream_id,
+                        e
+                    );
                     self.fin = true;
                     return None;
                 }
             }
         }
     }
 
     pub fn fin(&self) -> bool {
--- a/third_party/rust/neqo-http3/src/transaction_client.rs
+++ b/third_party/rust/neqo-http3/src/transaction_client.rs
@@ -53,17 +53,17 @@ impl Request {
         r
     }
 
     pub fn ensure_encoded(&mut self, encoder: &mut QPackEncoder, stream_id: u64) {
         if self.buf.is_some() {
             return;
         }
 
-        qinfo!([self] "Encoding headers for {}/{}", self.host, self.path);
+        qinfo!([self], "Encoding headers for {}/{}", self.host, self.path);
         let encoded_headers = encoder.encode_header_block(&self.headers, stream_id);
         let f = HFrame::Headers {
             len: encoded_headers.len() as u64,
         };
         let mut d = Encoder::default();
         f.encode(&mut d);
         d.encode(&encoded_headers[..]);
         self.buf = Some(d.into());
@@ -78,20 +78,20 @@ impl Request {
         let label = if ::log::log_enabled!(::log::Level::Debug) {
             format!("{}", self)
         } else {
             String::new()
         };
         self.ensure_encoded(encoder, stream_id);
         if let Some(buf) = &mut self.buf {
             let sent = conn.stream_send(stream_id, &buf)?;
-            qinfo!([label] "{} bytes sent", sent);
+            qinfo!([label], "{} bytes sent", sent);
 
             if sent == buf.len() {
-                qinfo!([label] "done sending request");
+                qinfo!([label], "done sending request");
                 Ok(true)
             } else {
                 let b = buf.split_off(sent);
                 self.buf = Some(b);
                 Ok(false)
             }
         } else {
             panic!("We must have buffer in this state")
@@ -191,17 +191,22 @@ impl TransactionClient {
             stream_id,
             response_headers_state: ResponseHeadersState::NoHeaders,
             frame_reader: HFrameReader::new(),
             conn_events,
         }
     }
 
     pub fn send_request_body(&mut self, conn: &mut Connection, buf: &[u8]) -> Res<usize> {
-        qinfo!([self] "send_request_body: send_state={:?} len={}", self.send_state, buf.len());
+        qinfo!(
+            [self],
+            "send_request_body: send_state={:?} len={}",
+            self.send_state,
+            buf.len()
+        );
         match self.send_state {
             TransactionSendState::SendingHeaders { .. } => Ok(0),
             TransactionSendState::SendingData => {
                 let available = conn.stream_avail_send_space(self.stream_id)? as usize;
                 if available <= 2 {
                     return Ok(0);
                 }
                 let to_send;
@@ -213,17 +218,22 @@ impl TransactionClient {
                     to_send = min(min(buf.len(), available - 3), MAX_DATA_HEADER_SIZE_3);
                 } else if available <= MAX_DATA_HEADER_SIZE_5 {
                     // 1073741823 + 9
                     to_send = min(min(buf.len(), available - 5), MAX_DATA_HEADER_SIZE_5_LIMIT);
                 } else {
                     to_send = min(buf.len(), available - 9);
                 }
 
-                qinfo!([self] "send_request_body: available={} to_send={}.", available, to_send);
+                qinfo!(
+                    [self],
+                    "send_request_body: available={} to_send={}.",
+                    available,
+                    to_send
+                );
 
                 let data_frame = HFrame::Data {
                     len: to_send as u64,
                 };
                 let mut enc = Encoder::default();
                 data_frame.encode(&mut enc);
                 match conn.stream_send(self.stream_id, &enc) {
                     Ok(sent) => {
@@ -236,17 +246,22 @@ impl TransactionClient {
                     Err(e) => Err(Error::TransportError(e)),
                 }
             }
             TransactionSendState::Closed => Err(Error::AlreadyClosed),
         }
     }
 
     fn handle_frame_in_state_waiting_for_headers(&mut self, frame: HFrame, fin: bool) -> Res<()> {
-        qinfo!([self] "A new frame has been received: {:?}; state={:?}", frame, self.recv_state);
+        qinfo!(
+            [self],
+            "A new frame has been received: {:?}; state={:?}",
+            frame,
+            self.recv_state
+        );
         match frame {
             HFrame::Headers { len } => self.handle_headers_frame(len, fin),
             HFrame::PushPromise { .. } => Err(Error::HttpIdError),
             _ => Err(Error::HttpFrameUnexpected),
         }
     }
 
     fn handle_headers_frame(&mut self, len: u64, fin: bool) -> Res<()> {
@@ -260,17 +275,22 @@ impl TransactionClient {
                 buf: vec![0; len as usize],
                 offset: 0,
             };
             Ok(())
         }
     }
 
     fn handle_frame_in_state_waiting_for_data(&mut self, frame: HFrame, fin: bool) -> Res<()> {
-        qinfo!([self] "A new frame has been received: {:?}; state={:?}", frame, self.recv_state);
+        qinfo!(
+            [self],
+            "A new frame has been received: {:?}; state={:?}",
+            frame,
+            self.recv_state
+        );
         match frame {
             HFrame::Data { len } => self.handle_data_frame(len, fin),
             HFrame::PushPromise { .. } => Err(Error::HttpIdError),
             HFrame::Headers { .. } => {
                 // TODO implement trailers!
                 Err(Error::HttpFrameUnexpected)
             }
             _ => Err(Error::HttpFrameUnexpected),
@@ -297,44 +317,48 @@ impl TransactionClient {
         self.conn_events.header_ready(self.stream_id);
         self.recv_state = TransactionRecvState::WaitingForData;
         Ok(())
     }
 
     fn set_state_to_close_pending(&mut self) {
         // Stream has received fin. Depending on headers state set header_ready
         // or data_readable event so that app can pick up the fin.
-        qdebug!([self] "set_state_to_close_pending:  response_headers_state={:?}", self.response_headers_state);
+        qdebug!(
+            [self],
+            "set_state_to_close_pending:  response_headers_state={:?}",
+            self.response_headers_state
+        );
         match self.response_headers_state {
             ResponseHeadersState::NoHeaders => {
                 self.conn_events.header_ready(self.stream_id);
                 self.response_headers_state = ResponseHeadersState::Ready(None);
             }
             // In Ready state we are already waiting for app to pick up headers
             // it can also pick up fin, so we do not need a new event.
             ResponseHeadersState::Ready(..) => {}
             ResponseHeadersState::Read => self.conn_events.data_readable(self.stream_id),
         }
         self.recv_state = TransactionRecvState::ClosePending;
     }
 
     fn recv_frame_header(&mut self, conn: &mut Connection) -> Res<Option<(HFrame, bool)>> {
-        qtrace!([self] "receiving frame header");
+        qtrace!([self], "receiving frame header");
         let fin = self.frame_reader.receive(conn, self.stream_id)?;
         if !self.frame_reader.done() {
             if fin {
                 //we have received stream fin while waiting for a frame.
                 // !self.frame_reader.done() means that we do not have a new
                 // frame at all. Set state to ClosePending and waith for app
                 // to pick up fin.
                 self.set_state_to_close_pending();
             }
             Ok(None)
         } else {
-            qdebug!([self] "A new frame has been received.");
+            qdebug!([self], "A new frame has been received.");
             Ok(Some((self.frame_reader.get_frame()?, fin)))
         }
     }
 
     fn read_headers_frame_body(
         &mut self,
         conn: &mut Connection,
         decoder: &mut QPackDecoder,
@@ -345,28 +369,31 @@ impl TransactionClient {
             String::new()
         };
         if let TransactionRecvState::ReadingHeaders {
             ref mut buf,
             ref mut offset,
         } = self.recv_state
         {
             let (amount, fin) = conn.stream_recv(self.stream_id, &mut buf[*offset..])?;
-            qdebug!([label] "read_headers: read {} bytes fin={}.", amount, fin);
+            qdebug!([label], "read_headers: read {} bytes fin={}.", amount, fin);
             *offset += amount as usize;
             if *offset < buf.len() {
                 if fin {
                     // Malformated frame
                     return Err(Error::HttpFrameError);
                 }
                 return Ok(true);
             }
 
             // we have read the headers, try decoding them.
-            qinfo!([label] "read_headers: read all headers, try decoding them.");
+            qinfo!(
+                [label],
+                "read_headers: read all headers, try decoding them."
+            );
             match decoder.decode_header_block(buf, self.stream_id)? {
                 Some(headers) => {
                     self.add_headers(Some(headers))?;
                     if fin {
                         self.set_state_to_close_pending();
                     }
                     Ok(fin)
                 }
@@ -464,35 +491,40 @@ impl Http3Transaction for TransactionCli
             ref mut request,
             fin,
         } = self.send_state
         {
             if request.send(conn, encoder, self.stream_id)? {
                 if fin {
                     conn.stream_close_send(self.stream_id)?;
                     self.send_state = TransactionSendState::Closed;
-                    qinfo!([label] "done sending request");
+                    qinfo!([label], "done sending request");
                 } else {
                     self.send_state = TransactionSendState::SendingData;
                     self.conn_events.data_writable(self.stream_id);
-                    qinfo!([label] "change to state SendingData");
+                    qinfo!([label], "change to state SendingData");
                 }
             }
         }
         Ok(())
     }
 
     fn receive(&mut self, conn: &mut Connection, decoder: &mut QPackDecoder) -> Res<()> {
         let label = if ::log::log_enabled!(::log::Level::Debug) {
             format!("{}", self)
         } else {
             String::new()
         };
         loop {
-            qdebug!([label] "send_state={:?} recv_state={:?}.", self.send_state, self.recv_state);
+            qdebug!(
+                [label],
+                "send_state={:?} recv_state={:?}.",
+                self.send_state,
+                self.recv_state
+            );
             match self.recv_state {
                 TransactionRecvState::WaitingForResponseHeaders => {
                     match self.recv_frame_header(conn)? {
                         None => break Ok(()),
                         Some((f, fin)) => {
                             self.handle_frame_in_state_waiting_for_headers(f, fin)?;
                             if fin {
                                 self.set_state_to_close_pending();
@@ -511,17 +543,17 @@ impl Http3Transaction for TransactionCli
                         Some(headers) => {
                             self.add_headers(Some(headers))?;
                             if fin {
                                 self.set_state_to_close_pending();
                                 break Ok(());
                             }
                         }
                         None => {
-                            qinfo!([self] "decoding header is blocked.");
+                            qinfo!([self], "decoding header is blocked.");
                             break Ok(());
                         }
                     }
                 }
                 TransactionRecvState::WaitingForData => {
                     match self.recv_frame_header(conn)? {
                         None => break Ok(()),
                         Some((f, fin)) => {
--- a/third_party/rust/neqo-http3/src/transaction_server.rs
+++ b/third_party/rust/neqo-http3/src/transaction_server.rs
@@ -1,20 +1,20 @@
 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
 use crate::connection::Http3Transaction;
 use crate::hframe::{HFrame, HFrameReader};
-use crate::server_events::Http3ServerEvents;
+use crate::server_connection_events::Http3ServerConnEvents;
 use crate::Header;
 use crate::{Error, Res};
-use neqo_common::{qdebug, qinfo, qtrace, Encoder};
+use neqo_common::{matches, qdebug, qinfo, qtrace, Encoder};
 use neqo_qpack::decoder::QPackDecoder;
 use neqo_qpack::encoder::QPackEncoder;
 use neqo_transport::Connection;
 use std::mem;
 
 #[derive(PartialEq, Debug)]
 enum TransactionRecvState {
     WaitingForHeaders,
@@ -33,59 +33,59 @@ enum TransactionSendState {
 }
 
 #[derive(Debug)]
 pub struct TransactionServer {
     recv_state: TransactionRecvState,
     send_state: TransactionSendState,
     stream_id: u64,
     frame_reader: HFrameReader,
-    conn_events: Http3ServerEvents,
+    conn_events: Http3ServerConnEvents,
 }
 
 impl TransactionServer {
-    pub fn new(stream_id: u64, conn_events: Http3ServerEvents) -> TransactionServer {
+    pub fn new(stream_id: u64, conn_events: Http3ServerConnEvents) -> TransactionServer {
         qinfo!("Create a request stream_id={}", stream_id);
         TransactionServer {
             recv_state: TransactionRecvState::WaitingForHeaders,
             send_state: TransactionSendState::Initial,
             stream_id,
             frame_reader: HFrameReader::new(),
             conn_events,
         }
     }
 
     pub fn set_response(&mut self, headers: &[Header], data: Vec<u8>, encoder: &mut QPackEncoder) {
-        qdebug!([self] "Encoding headers");
+        qdebug!([self], "Encoding headers");
         let encoded_headers = encoder.encode_header_block(&headers, self.stream_id);
         let hframe = HFrame::Headers {
             len: encoded_headers.len() as u64,
         };
         let mut d = Encoder::default();
         hframe.encode(&mut d);
         d.encode(&encoded_headers);
         if !data.is_empty() {
-            qdebug!([self] "Encoding data");
+            qdebug!([self], "Encoding data");
             let d_frame = HFrame::Data {
                 len: data.len() as u64,
             };
             d_frame.encode(&mut d);
             d.encode(&data);
         }
 
         self.send_state = TransactionSendState::SendingResponse { buf: d.into() };
     }
 
     fn recv_frame_header(&mut self, conn: &mut Connection) -> Res<(Option<HFrame>, bool)> {
-        qtrace!([self] "receiving frame header");
+        qtrace!([self], "receiving frame header");
         let fin = self.frame_reader.receive(conn, self.stream_id)?;
         if !self.frame_reader.done() {
             Ok((None, fin))
         } else {
-            qinfo!([self] "A new frame has been received.");
+            qinfo!([self], "A new frame has been received.");
             Ok((Some(self.frame_reader.get_frame()?), fin))
         }
     }
 
     fn read_headers_frame_body(
         &mut self,
         conn: &mut Connection,
         decoder: &mut QPackDecoder,
@@ -96,28 +96,31 @@ impl TransactionServer {
             String::new()
         };
         if let TransactionRecvState::ReadingHeaders {
             ref mut buf,
             ref mut offset,
         } = self.recv_state
         {
             let (amount, fin) = conn.stream_recv(self.stream_id, &mut buf[*offset..])?;
-            qdebug!([label] "read_headers: read {} bytes fin={}.", amount, fin);
+            qdebug!([label], "read_headers: read {} bytes fin={}.", amount, fin);
             *offset += amount as usize;
             if *offset < buf.len() {
                 if fin {
                     // Malformed frame
                     return Err(Error::HttpFrameError);
                 }
                 return Ok(true);
             }
 
             // we have read the headers, try decoding them.
-            qinfo!([label] "read_headers: read all headers, try decoding them.");
+            qinfo!(
+                [label],
+                "read_headers: read all headers, try decoding them."
+            );
             match decoder.decode_header_block(buf, self.stream_id)? {
                 Some(headers) => {
                     self.conn_events.headers(self.stream_id, headers, fin);
                     if fin {
                         self.recv_state = TransactionRecvState::Closed;
                     } else {
                         self.recv_state = TransactionRecvState::WaitingForData;
                     }
@@ -132,49 +135,49 @@ impl TransactionServer {
                 }
             }
         } else {
             panic!("This is only called when recv_state is ReadingHeaders.");
         }
     }
 
     fn handle_frame_in_state_waiting_for_headers(&mut self, frame: HFrame, fin: bool) -> Res<()> {
-        qdebug!([self] "A new frame has been received: {:?}", frame);
+        qdebug!([self], "A new frame has been received: {:?}", frame);
         match frame {
             HFrame::Headers { len } => self.handle_headers_frame(len, fin),
             _ => Err(Error::HttpFrameUnexpected),
         }
     }
 
     fn handle_frame_in_state_waiting_for_data(&mut self, frame: HFrame, fin: bool) -> Res<()> {
-        qdebug!([self] "A new frame has been received: {:?}", frame);
+        qdebug!([self], "A new frame has been received: {:?}", frame);
         match frame {
             HFrame::Data { len } => self.handle_data_frame(len, fin),
             _ => Err(Error::HttpFrameUnexpected),
         }
     }
 
     fn handle_headers_frame(&mut self, len: u64, fin: bool) -> Res<()> {
-        qinfo!([self] "A new header frame len={} fin={}", len, fin);
+        qinfo!([self], "A new header frame len={} fin={}", len, fin);
         if len == 0 {
             self.conn_events.headers(self.stream_id, Vec::new(), fin);
         } else {
             if fin {
                 return Err(Error::HttpFrameError);
             }
             self.recv_state = TransactionRecvState::ReadingHeaders {
                 buf: vec![0; len as usize],
                 offset: 0,
             };
         }
         Ok(())
     }
 
     fn handle_data_frame(&mut self, len: u64, fin: bool) -> Res<()> {
-        qinfo!([self] "A new data frame len={} fin={}", len, fin);
+        qinfo!([self], "A new data frame len={} fin={}", len, fin);
         if len > 0 {
             if fin {
                 return Err(Error::HttpFrameError);
             }
             self.recv_state = TransactionRecvState::ReadingData {
                 remaining_data_len: len as usize,
             };
         } else if fin {
@@ -188,29 +191,29 @@ impl TransactionServer {
 impl ::std::fmt::Display for TransactionServer {
     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
         write!(f, "TransactionServer {}", self.stream_id)
     }
 }
 
 impl Http3Transaction for TransactionServer {
     fn send(&mut self, conn: &mut Connection, _encoder: &mut QPackEncoder) -> Res<()> {
-        qtrace!([self] "Sending response.");
+        qtrace!([self], "Sending response.");
         let label = if ::log::log_enabled!(::log::Level::Debug) {
             format!("{}", self)
         } else {
             String::new()
         };
         if let TransactionSendState::SendingResponse { ref mut buf } = self.send_state {
             let sent = conn.stream_send(self.stream_id, &buf[..])?;
-            qinfo!([label] "{} bytes sent", sent);
+            qinfo!([label], "{} bytes sent", sent);
             if sent == buf.len() {
                 conn.stream_close_send(self.stream_id)?;
                 self.send_state = TransactionSendState::Closed;
-                qinfo!([label] "done sending request");
+                qinfo!([label], "done sending request");
             } else {
                 let mut b = buf.split_off(sent);
                 mem::swap(buf, &mut b);
             }
         }
 
         Ok(())
     }
@@ -218,17 +221,21 @@ impl Http3Transaction for TransactionSer
     fn receive(&mut self, conn: &mut Connection, decoder: &mut QPackDecoder) -> Res<()> {
         let label = if ::log::log_enabled!(::log::Level::Debug) {
             format!("{}", self)
         } else {
             String::new()
         };
 
         loop {
-            qtrace!([label] "[recv_state={:?}] receiving data.", self.recv_state);
+            qtrace!(
+                [label],
+                "[recv_state={:?}] receiving data.",
+                self.recv_state
+            );
             match self.recv_state {
                 TransactionRecvState::WaitingForHeaders => {
                     let (f, fin) = self.recv_frame_header(conn)?;
                     match f {
                         None => {
                             if fin {
                                 self.conn_events.headers(self.stream_id, Vec::new(), true);
                                 self.recv_state = TransactionRecvState::Closed;
@@ -253,17 +260,17 @@ impl Http3Transaction for TransactionSer
                     match decoder.decode_header_block(buf, self.stream_id)? {
                         Some(headers) => {
                             self.conn_events.headers(self.stream_id, headers, fin);
                             if fin {
                                 return Ok(());
                             }
                         }
                         None => {
-                            qinfo!([self] "decoding header is blocked.");
+                            qinfo!([self], "decoding header is blocked.");
                             return Ok(());
                         }
                     }
                 }
                 TransactionRecvState::WaitingForData => {
                     let (f, fin) = self.recv_frame_header(conn)?;
                     match f {
                         None => {
@@ -318,21 +325,17 @@ impl Http3Transaction for TransactionSer
                 TransactionRecvState::Closed => {
                     panic!("Stream readable after being closed!");
                 }
             };
         }
     }
 
     fn has_data_to_send(&self) -> bool {
-        if let TransactionSendState::SendingResponse { .. } = self.send_state {
-            true
-        } else {
-            false
-        }
+        matches!(self.send_state, TransactionSendState::SendingResponse { .. })
     }
 
     fn is_state_sending_data(&self) -> bool {
         self.has_data_to_send()
     }
 
     fn reset_receiving_side(&mut self) {}
 
--- a/third_party/rust/neqo-http3/tests/httpconn.rs
+++ b/third_party/rust/neqo-http3/tests/httpconn.rs
@@ -8,44 +8,44 @@
 
 use neqo_common::{matches, Datagram};
 use neqo_crypto::AuthenticationStatus;
 use neqo_http3::{Http3Client, Http3ClientEvent, Http3Server, Http3ServerEvent, Http3State};
 use test_fixture::*;
 
 const RESPONSE_DATA: &[u8] = &[0x61, 0x62, 0x63];
 
-fn process_server_events(conn: &mut Http3Server) {
+fn process_server_events(server: &mut Http3Server) {
     let mut request_found = false;
-    while let Some(event) = conn.next_event() {
+    while let Some(event) = server.next_event() {
         if let Http3ServerEvent::Headers {
-            stream_id,
+            mut request,
             headers,
             fin,
         } = event
         {
             assert_eq!(
                 headers,
                 vec![
                     (String::from(":method"), String::from("GET")),
                     (String::from(":scheme"), String::from("https")),
                     (String::from(":authority"), String::from("something.com")),
                     (String::from(":path"), String::from("/"))
                 ]
             );
             assert_eq!(fin, true);
-            conn.set_response(
-                stream_id,
-                &[
-                    (String::from(":status"), String::from("200")),
-                    (String::from("content-length"), String::from("3")),
-                ],
-                RESPONSE_DATA.to_vec(),
-            )
-            .unwrap();
+            request
+                .set_response(
+                    &[
+                        (String::from(":status"), String::from("200")),
+                        (String::from("content-length"), String::from("3")),
+                    ],
+                    RESPONSE_DATA.to_vec(),
+                )
+                .unwrap();
             request_found = true;
         }
     }
     assert_eq!(request_found, true);
 }
 
 fn process_client_events(conn: &mut Http3Client) {
     let mut response_header_found = false;
@@ -81,28 +81,26 @@ fn process_client_events(conn: &mut Http
     assert_eq!(response_data_found, true)
 }
 
 fn connect() -> (Http3Client, Http3Server, Option<Datagram>) {
     let mut hconn_c = default_http3_client();
     let mut hconn_s = default_http3_server();
 
     assert_eq!(hconn_c.state(), Http3State::Initializing);
-    assert_eq!(hconn_s.state(), Http3State::Initializing);
     let out = hconn_c.process(None, now()); // Initial
     let out = hconn_s.process(out.dgram(), now()); // Initial + Handshake
     let out = hconn_c.process(out.dgram(), now()); // ACK
     let _ = hconn_s.process(out.dgram(), now()); //consume ACK
     let authentication_needed = |e| matches!(e, Http3ClientEvent::AuthenticationNeeded);
     assert!(hconn_c.events().any(authentication_needed));
     hconn_c.authenticated(AuthenticationStatus::Ok, now());
     let out = hconn_c.process(None, now()); // Handshake
     assert_eq!(hconn_c.state(), Http3State::Connected);
     let out = hconn_s.process(out.dgram(), now()); // Handshake
-    assert_eq!(hconn_s.state(), Http3State::Connected);
     let out = hconn_c.process(out.dgram(), now());
     let out = hconn_s.process(out.dgram(), now());
     // assert_eq!(hconn_s.settings_received, true);
     let out = hconn_c.process(out.dgram(), now());
     // assert_eq!(hconn_c.settings_received, true);
 
     (hconn_c, hconn_s, out.dgram())
 }
@@ -126,10 +124,12 @@ fn test_fetch() {
     eprintln!("-----server");
     let out = hconn_s.process(out.dgram(), now());
     let _ = hconn_c.process(out.dgram(), now());
     process_server_events(&mut hconn_s);
     let out = hconn_s.process(None, now());
 
     eprintln!("-----client");
     let _ = hconn_c.process(out.dgram(), now());
+    let out = hconn_s.process(None, now());
+    let _ = hconn_c.process(out.dgram(), now());
     process_client_events(&mut hconn_c);
 }
--- a/third_party/rust/neqo-qpack/.cargo-checksum.json
+++ b/third_party/rust/neqo-qpack/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"1b0641ab11933da85b807fc64e9b9c19d49a53602359e8b51722d80ac3774a63","src/decoder.rs":"bbbeae34f8d1d42d51fd344a4d558aec1ddaa3c3bb41b0428796c316c160a778","src/encoder.rs":"854864b93d63b127659c5ed85822fe9452eb5f40a362cb2a19dc8273a7c2e81e","src/huffman.rs":"720eedace45205098a0b2210c876906ce15b7be469a799e75e70baafac8adee8","src/huffman_decode_helper.rs":"e4734353591770dfe9a9047b0be5d9068150433e9cea8cad029444b42b0afa39","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"b223e4a709a9cc144d36777d2bcf78d81780bdbc09e9f2f09c7bffa110a098da","src/qpack_helper.rs":"200ab8bcb60728e3bcacf25b7006fa54b544458bfee5e66e09fa472a614347fc","src/qpack_send_buf.rs":"471e3b0af9f8783aa1bfe11a1959bf5694e62bc2d8e1cf783c933af81e3f3cf9","src/static_table.rs":"fda9d5c6f38f94b0bf92d3afdf8432dce6e27e189736596e16727090c77b78ec","src/table.rs":"f4f09692bf6ec863b0f066c88837d99f59a1fc4a8ca61bee4ed76d45a77c3cc4"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"96d0220db0a96108e39ca9d277a4979bd387e4d9d6ac92da7bbd590a86b2fa12","src/decoder.rs":"18f08a510d8a63012146eb0bb063218bf691a720624f521a29dc8cc3b1e52237","src/encoder.rs":"78da509611b5869d320795c42bef944b6499c0f207c73818c1908f1a1cf001fc","src/huffman.rs":"720eedace45205098a0b2210c876906ce15b7be469a799e75e70baafac8adee8","src/huffman_decode_helper.rs":"e4734353591770dfe9a9047b0be5d9068150433e9cea8cad029444b42b0afa39","src/huffman_table.rs":"06fea766a6276ac56c7ee0326faed800a742c15fda1f33bf2513e6cc6a5e6d27","src/lib.rs":"b223e4a709a9cc144d36777d2bcf78d81780bdbc09e9f2f09c7bffa110a098da","src/qpack_helper.rs":"200ab8bcb60728e3bcacf25b7006fa54b544458bfee5e66e09fa472a614347fc","src/qpack_send_buf.rs":"471e3b0af9f8783aa1bfe11a1959bf5694e62bc2d8e1cf783c933af81e3f3cf9","src/static_table.rs":"fda9d5c6f38f94b0bf92d3afdf8432dce6e27e189736596e16727090c77b78ec","src/table.rs":"f4f09692bf6ec863b0f066c88837d99f59a1fc4a8ca61bee4ed76d45a77c3cc4"},"package":null}
\ No newline at end of file
--- a/third_party/rust/neqo-qpack/Cargo.toml
+++ b/third_party/rust/neqo-qpack/Cargo.toml
@@ -1,11 +1,11 @@
 [package]
 name = "neqo-qpack"
-version = "0.1.4"
+version = "0.1.6"
 authors = ["Dragana Damjanovic <dragana.damjano@gmail.com>"]
 edition = "2018"
 license = "MIT/Apache-2.0"
 
 [dependencies]
 neqo-common = { path = "./../neqo-common" }
 neqo-transport = { path = "./../neqo-transport" }
 neqo-crypto = { path = "./../neqo-crypto" }
--- a/third_party/rust/neqo-qpack/src/decoder.rs
+++ b/third_party/rust/neqo-qpack/src/decoder.rs
@@ -128,17 +128,17 @@ impl QPackDecoder {
         self.blocked_streams.retain(|(_, req)| *req > base);
         Ok(r)
     }
 
     #[allow(clippy::cognitive_complexity)]
     #[allow(clippy::useless_let_if_seq)]
     fn read_instructions(&mut self, conn: &mut Connection, stream_id: u64) -> Res<()> {
         let label = self.to_string();
-        qdebug!([self] "reading instructions");
+        qdebug!([self], "reading instructions");
         loop {
             match self.state {
                 QPackDecoderState::ReadInstruction => {
                     let mut b = [0; 1];
                     match conn.stream_recv(stream_id, &mut b) {
                         Err(_) => break Err(Error::DecoderStreamError),
                         Ok((amount, fin)) => {
                             if fin {
@@ -204,17 +204,17 @@ impl QPackDecoder {
                     } else if (b[0] & 0x20) == 0 {
                         // Duplicate
                         let mut v: u64 = 0;
                         let mut cnt: u8 = 0;
                         let done = read_prefixed_encoded_int_with_connection_wrap(
                             conn, stream_id, &mut v, &mut cnt, 3, b[0], true,
                         )?;
                         if done {
-                            qdebug!([label] "received instruction - duplicate index={}", v);
+                            qdebug!([label], "received instruction - duplicate index={}", v);
                             self.table.duplicate(v)?;
                             self.total_num_of_inserts += 1;
                             self.increment += 1;
                             self.state = QPackDecoderState::ReadInstruction;
                         } else {
                             self.state = QPackDecoderState::Duplicate { index: v, cnt };
                             // wait for more data
                             break Ok(());
@@ -305,17 +305,17 @@ impl QPackDecoder {
                             if value.len() == *offset {
                                 // We are done reading instruction, insert the new entry.
                                 let mut value_to_insert: Vec<u8> = Vec::new();
                                 if *value_is_huffman {
                                     value_to_insert = Huffman::default().decode(value)?;
                                 } else {
                                     mem::swap(&mut value_to_insert, value);
                                 }
-                                qdebug!([label] "received instruction - insert with name ref index={} static={} value={:x?}", name_index, name_static_table, value_to_insert);
+                                qdebug!([label], "received instruction - insert with name ref index={} static={} value={:x?}", name_index, name_static_table, value_to_insert);
                                 self.table.insert_with_name_ref(
                                     *name_static_table,
                                     *name_index,
                                     value_to_insert,
                                 )?;
                                 self.total_num_of_inserts += 1;
                                 self.increment += 1;
                                 self.state = QPackDecoderState::ReadInstruction;
@@ -425,17 +425,17 @@ impl QPackDecoder {
                                     mem::swap(&mut name_to_insert, name);
                                 }
                                 let mut value_to_insert: Vec<u8> = Vec::new();
                                 if *value_is_huffman {
                                     value_to_insert = Huffman::default().decode(value)?;
                                 } else {
                                     mem::swap(&mut value_to_insert, value);
                                 }
-                                qdebug!([label] "received instruction - insert with name literal name={:x?} value={:x?}", name_to_insert, value_to_insert);
+                                qdebug!([label], "received instruction - insert with name literal name={:x?} value={:x?}", name_to_insert, value_to_insert);
                                 self.table.insert(name_to_insert, value_to_insert)?;
                                 self.total_num_of_inserts += 1;
                                 self.increment += 1;
                                 self.state = QPackDecoderState::ReadInstruction;
                             } else {
                                 // waiting for more data
                                 break Ok(());
                             }
@@ -445,17 +445,17 @@ impl QPackDecoder {
                 QPackDecoderState::Duplicate {
                     ref mut index,
                     ref mut cnt,
                 } => {
                     let done = read_prefixed_encoded_int_with_connection_wrap(
                         conn, stream_id, index, cnt, 0, 0x0, false,
                     )?;
                     if done {
-                        qdebug!([label] "received instruction - duplicate index={}", index);
+                        qdebug!([label], "received instruction - duplicate index={}", index);
                         self.table.duplicate(*index)?;
                         self.total_num_of_inserts += 1;
                         self.increment += 1;
                         self.state = QPackDecoderState::ReadInstruction;
                     } else {
                         // waiting for more data
                         break Ok(());
                     }
@@ -476,17 +476,17 @@ impl QPackDecoder {
                         break Ok(());
                     }
                 }
             }
         }
     }
 
     pub fn set_capacity(&mut self, cap: u64) -> Res<()> {
-        qdebug!([self] "received instruction capacity cap={}", cap);
+        qdebug!([self], "received instruction capacity cap={}", cap);
         if cap > u64::from(self.max_table_size) {
             return Err(Error::EncoderStreamError);
         }
         self.table.set_capacity(cap);
         Ok(())
     }
 
     fn header_ack(&mut self, stream_id: u64) {
@@ -507,41 +507,41 @@ impl QPackDecoder {
             self.increment = 0;
         }
         if self.send_buf.len() == 0 {
             Ok(())
         } else if let Some(stream_id) = self.local_stream_id {
             match conn.stream_send(stream_id, &self.send_buf[..]) {
                 Err(_) => Err(Error::DecoderStreamError),
                 Ok(r) => {
-                    qdebug!([self] "{} bytes sent.", r);
+                    qdebug!([self], "{} bytes sent.", r);
                     self.send_buf.read(r as usize);
                     Ok(())
                 }
             }
         } else {
             Ok(())
         }
     }
 
     // this function returns None if the stream is blocked waiting for table insertions.
     pub fn decode_header_block(&mut self, buf: &[u8], stream_id: u64) -> Res<Option<Vec<Header>>> {
-        qdebug!([self] "decode header block.");
+        qdebug!([self], "decode header block.");
         let mut reader = BufWrapper { buf, offset: 0 };
 
         let (req_inserts, base) = self.read_base(&mut reader)?;
         qdebug!(
-            [self]
+            [self],
             "requested inserts count is {} and base is {}",
             req_inserts,
             base
         );
         if self.table.base() < req_inserts {
             qdebug!(
-                [self]
+                [self],
                 "stream is blocked stream_id={} requested inserts count={}",
                 stream_id,
                 req_inserts
             );
             self.blocked_streams.push((stream_id, req_inserts));
             if self.blocked_streams.len() > self.max_blocked_streams as usize {
                 return Err(Error::DecompressionFailed);
             }
@@ -550,17 +550,17 @@ impl QPackDecoder {
         let mut h: Vec<Header> = Vec::new();
 
         loop {
             if reader.done() {
                 // Send header_ack
                 if req_inserts != 0 {
                     self.header_ack(stream_id);
                 }
-                qdebug!([self] "done decoding header block.");
+                qdebug!([self], "done decoding header block.");
                 break Ok(Some(h));
             }
 
             let b = reader.peek()?;
             if b & 0x80 != 0 {
                 h.push(self.read_indexed(&mut reader, base)?);
             } else if b & 0x40 != 0 {
                 h.push(self.read_literal_with_name_ref(&mut reader, base)?);
@@ -589,41 +589,41 @@ impl QPackDecoder {
             req_insert_cnt - base_delta - 1
         };
         Ok((req_insert_cnt, base))
     }
 
     fn read_indexed(&self, buf: &mut BufWrapper, base: u64) -> Res<Header> {
         let static_table = buf.peek()? & 0x40 != 0;
         let index = read_prefixed_encoded_int_slice(buf, 2)?;
-        qdebug!([self] "decoder indexed {} static={}.", index, static_table);
+        qdebug!([self], "decoder indexed {} static={}.", index, static_table);
         if static_table {
             match self.table.get_static(index) {
                 Ok(entry) => Ok((to_string(entry.name())?, to_string(entry.value())?)),
                 Err(_) => Err(Error::DecompressionFailed),
             }
         } else if let Ok(entry) = self.table.get_dynamic(index, base, false) {
             Ok((to_string(entry.name())?, to_string(entry.value())?))
         } else {
             Err(Error::DecompressionFailed)
         }
     }
 
     fn read_post_base_index(&self, buf: &mut BufWrapper, base: u64) -> Res<Header> {
         let index = read_prefixed_encoded_int_slice(buf, 4)?;
-        qdebug!([self] "decode post-based {}.", index);
+        qdebug!([self], "decode post-based {}.", index);
         if let Ok(entry) = self.table.get_dynamic(index, base, true) {
             Ok((to_string(entry.name())?, to_string(entry.value())?))
         } else {
             Err(Error::DecompressionFailed)
         }
     }
 
     fn read_literal_with_name_ref(&self, buf: &mut BufWrapper, base: u64) -> Res<Header> {
-        qdebug!([self] "read literal with name reference.");
+        qdebug!([self], "read literal with name reference.");
         // ignore n bit.
         let static_table = buf.peek()? & 0x10 != 0;
         let index = read_prefixed_encoded_int_slice(buf, 4)?;
 
         let name: Vec<u8>;
         if static_table {
             if let Ok(entry) = self.table.get_static(index) {
                 name = entry.name().to_vec();
@@ -640,27 +640,27 @@ impl QPackDecoder {
         let value_len = read_prefixed_encoded_int_slice(buf, 1)? as usize;
 
         let value = if value_is_huffman {
             Huffman::default().decode(buf.slice(value_len)?)?
         } else {
             buf.slice(value_len)?.to_vec()
         };
         qdebug!(
-            [self]
+            [self],
             "name index={} static={} value={:x?}.",
             index,
             static_table,
             value
         );
         Ok((to_string(&name)?, to_string(&value)?))
     }
 
     fn read_literal_with_post_base_name_ref(&self, buf: &mut BufWrapper, base: u64) -> Res<Header> {
-        qdebug!([self] "decoder literal with post-based index.");
+        qdebug!([self], "decoder literal with post-based index.");
         // ignore n bit.
         let index = read_prefixed_encoded_int_slice(buf, 5)?;
         let name: Vec<u8>;
         if let Ok(entry) = self.table.get_dynamic(index, base, true) {
             name = entry.name().to_vec();
         } else {
             return Err(Error::DecompressionFailed);
         }
@@ -669,22 +669,22 @@ impl QPackDecoder {
         let value_len = read_prefixed_encoded_int_slice(buf, 1)? as usize;
 
         let value = if value_is_huffman {
             Huffman::default().decode(buf.slice(value_len)?)?
         } else {
             buf.slice(value_len)?.to_vec()
         };
 
-        qdebug!([self] "name={:x?} value={:x?}.", name, value);
+        qdebug!([self], "name={:x?} value={:x?}.", name, value);
         Ok((to_string(&name)?, to_string(&value)?))
     }
 
     fn read_literal_with_name_literal(&self, buf: &mut BufWrapper) -> Res<Header> {
-        qdebug!([self] "decode literal with name literal.");
+        qdebug!([self], "decode literal with name literal.");
         // ignore n bit.
 
         let name_is_huffman = buf.peek()? & 0x08 != 0;
         let name_len = read_prefixed_encoded_int_slice(buf, 5)? as usize;
 
         let name = if name_is_huffman {
             Huffman::default().decode(buf.slice(name_len)?)?
         } else {
@@ -695,17 +695,17 @@ impl QPackDecoder {
         let value_len = read_prefixed_encoded_int_slice(buf, 1)? as usize;
 
         let value = if value_is_huffman {
             Huffman::default().decode(buf.slice(value_len)?)?
         } else {
             buf.slice(value_len)?.to_vec()
         };
 
-        qdebug!([self] "name={:x?} value={:x?}.", name, value);
+        qdebug!([self], "name={:x?} value={:x?}.", name, value);
         Ok((to_string(&name)?, to_string(&value)?))
     }
 
     fn calc_req_insert_cnt(&self, encoded: u64) -> Res<u64> {
         if encoded == 0 {
             Ok(0)
         } else if self.max_entries == 0 {
             Err(Error::DecompressionFailed)
--- a/third_party/rust/neqo-qpack/src/encoder.rs
+++ b/third_party/rust/neqo-qpack/src/encoder.rs
@@ -67,28 +67,28 @@ impl QPackEncoder {
         }
     }
 
     pub fn set_max_capacity(&mut self, cap: u64) -> Res<()> {
         if cap > (1 << 30) - 1 {
             // TODO dragana check wat is the correct error.
             return Err(Error::EncoderStreamError);
         }
-        qdebug!([self] "Set max capacity to {}.", cap);
+        qdebug!([self], "Set max capacity to {}.", cap);
         self.max_entries = (cap as f64 / 32.0).floor() as u64;
         // we also set our table to the max allowed. TODO we may not want to use max allowed.
         self.change_capacity(cap);
         Ok(())
     }
 
     pub fn set_max_blocked_streams(&mut self, blocked_streams: u64) -> Res<()> {
         if blocked_streams > (1 << 16) - 1 {
             return Err(Error::EncoderStreamError);
         }
-        qdebug!([self] "Set max blocked streams to {}.", blocked_streams);
+        qdebug!([self], "Set max blocked streams to {}.", blocked_streams);
         self.max_blocked_streams = blocked_streams as u16;
         Ok(())
     }
 
     pub fn recv_if_encoder_stream(&mut self, conn: &mut Connection, stream_id: u64) -> Res<bool> {
         match self.remote_stream_id {
             Some(id) => {
                 if id == stream_id {
@@ -98,17 +98,17 @@ impl QPackEncoder {
                     Ok(false)
                 }
             }
             None => Ok(false),
         }
     }
 
     fn read_instructions(&mut self, conn: &mut Connection, stream_id: u64) -> Res<()> {
-        qdebug!([self] "read a new instraction");
+        qdebug!([self], "read a new instraction");
         loop {
             match self.instruction_reader_current_inst {
                 None => {
                     // get new instruction
                     let mut b = [0];
                     match conn.stream_recv(stream_id, &mut b) {
                         Err(_) => break Err(Error::EncoderStreamError),
                         Ok((amount, fin)) => {
@@ -169,17 +169,17 @@ impl QPackEncoder {
                     }
                 }
             }
         }
     }
 
     fn call_instruction(&mut self) {
         if let Some(inst) = &self.instruction_reader_current_inst {
-            qdebug!([self] "call intruction {:?}", inst);
+            qdebug!([self], "call intruction {:?}", inst);
             match inst {
                 DecoderInstructions::InsertCountIncrement => {
                     self.table.increment_acked(self.instruction_reader_value);
                     let inserts = self.table.get_acked_inserts_cnt();
                     self.blocked_streams.retain(|req| *req <= inserts);
                 }
                 DecoderInstructions::HeaderAck => {
                     self.table.header_ack(self.instruction_reader_value)
@@ -198,17 +198,17 @@ impl QPackEncoder {
 
     pub fn insert_with_name_ref(
         &mut self,
         name_static_table: bool,
         name_index: u64,
         value: Vec<u8>,
     ) -> Res<()> {
         qdebug!(
-            [self]
+            [self],
             "insert with name reference {} from {} value={:x?}.",
             name_index,
             if name_static_table {
                 "static table"
             } else {
                 "dynamic table"
             },
             value
@@ -221,60 +221,60 @@ impl QPackEncoder {
         let instr = 0x80 | (if name_static_table { 0x40 } else { 0x00 });
         self.send_buf
             .encode_prefixed_encoded_int(instr, 2, name_index);
         encode_literal(self.use_huffman, &mut self.send_buf, 0x0, 0, entry.value());
         Ok(())
     }
 
     pub fn insert_with_name_literal(&mut self, name: Vec<u8>, value: Vec<u8>) -> Res<()> {
-        qdebug!([self] "insert name {:x?}, value={:x?}.", name, value);
+        qdebug!([self], "insert name {:x?}, value={:x?}.", name, value);
         // try to insert a new entry
         self.table.insert(name, value)?;
 
         let entry = self.table.get_last_added_entry().unwrap();
         // encode instruction.
         encode_literal(self.use_huffman, &mut self.send_buf, 0x40, 2, entry.name());
         encode_literal(self.use_huffman, &mut self.send_buf, 0x0, 0, entry.value());
 
         Ok(())
     }
 
     pub fn duplicate(&mut self, index: u64) -> Res<()> {
-        qdebug!([self] "duplicate entry {}.", index);
+        qdebug!([self], "duplicate entry {}.", index);
         self.table.duplicate(index)?;
         self.send_buf.encode_prefixed_encoded_int(0x00, 3, index);
         Ok(())
     }
 
     pub fn change_capacity(&mut self, cap: u64) {
-        qdebug!([self] "change capacity: {}", cap);
+        qdebug!([self], "change capacity: {}", cap);
         self.table.set_capacity(cap);
         self.send_buf.encode_prefixed_encoded_int(0x20, 3, cap);
     }
 
     pub fn send(&mut self, conn: &mut Connection) -> Res<()> {
         if self.send_buf.is_empty() {
             Ok(())
         } else if let Some(stream_id) = self.local_stream_id {
             match conn.stream_send(stream_id, &self.send_buf[..]) {
                 Err(_) => Err(Error::EncoderStreamError),
                 Ok(r) => {
-                    qdebug!([self] "{} bytes sent.", r);
+                    qdebug!([self], "{} bytes sent.", r);
                     self.send_buf.read(r as usize);
                     Ok(())
                 }
             }
         } else {
             Ok(())
         }
     }
 
     pub fn encode_header_block(&mut self, h: &[Header], stream_id: u64) -> QPData {
-        qdebug!([self] "encoding headers.");
+        qdebug!([self], "encoding headers.");
         let mut encoded_h = QPData::default();
         let base = self.table.base();
         let mut req_insert_cnt = 0;
         self.encode_header_block_prefix(&mut encoded_h, false, 0, base, true);
         for iter in h.iter() {
             let name = iter.0.clone().into_bytes();
             let value = iter.1.clone().into_bytes();
             qtrace!("encoding {:x?} {:x?}.", name, value);
@@ -285,27 +285,27 @@ impl QPackEncoder {
             let mut is_dynamic = false;
             let acked_inserts_cnt = self.table.get_acked_inserts_cnt(); // we need to read it here because of borrowing problem.
             let can_be_blocked = self.blocked_streams.len() < self.max_blocked_streams as usize;
             {
                 let label = self.to_string();
                 // this is done in this way because otherwise it is complaining about mut borrow. TODO: look if we can do this better
                 let (e_s, e_d, found_value) = self.table.lookup(&name, &value);
                 if let Some(entry) = e_s {
-                    qtrace!([label] "found a static entry, value-match={}", found_value);
+                    qtrace!([label], "found a static entry, value-match={}", found_value);
                     can_use = true;
                     index = entry.index();
                     value_as_well = found_value;
                 }
                 if !can_use {
                     if let Some(entry) = e_d {
                         index = entry.index();
                         can_use = index < acked_inserts_cnt || can_be_blocked;
                         qtrace!(
-                            [label]
+                            [label],
                             "found a dynamic entry - can_use={} value-match={},",
                             can_use,
                             found_value
                         );
                         if can_use {
                             value_as_well = found_value;
                             is_dynamic = true;
                             entry.add_ref(stream_id, 1);
@@ -380,17 +380,17 @@ impl QPackEncoder {
         &self,
         buf: &mut QPData,
         fix: bool,
         req_insert_cnt: u64,
         delta: u64,
         positive: bool,
     ) {
         qdebug!(
-            [self]
+            [self],
             "encode header block prefix req_insert_cnt={} delta={} (fix={}).",
             req_insert_cnt,
             delta,
             fix
         );
         let enc_insert_cnt = if req_insert_cnt != 0 {
             (req_insert_cnt % (2 * self.max_entries)) + 1
         } else {
@@ -430,59 +430,59 @@ impl QPackEncoder {
                     req_insert_cnt - base - 1,
                     false,
                 );
             }
         }
     }
 
     fn encode_indexed(&self, buf: &mut QPData, is_static: bool, index: u64) {
-        qdebug!([self] "encode index {} (static={}).", index, is_static);
+        qdebug!([self], "encode index {} (static={}).", index, is_static);
         let prefix = if is_static { 0xc0 } else { 0x80 };
         buf.encode_prefixed_encoded_int(prefix, 2, index);
     }
 
     fn encode_literal_with_name_ref(
         &self,
         buf: &mut QPData,
         is_static: bool,
         index: u64,
         value: &[u8],
     ) {
         qdebug!(
-            [self]
+            [self],
             "encode literal with name ref - index={}, static={}, value={:x?}",
             index,
             is_static,
             value
         );
         let prefix = if is_static { 0x50 } else { 0x40 };
         buf.encode_prefixed_encoded_int(prefix, 4, index);
         encode_literal(self.use_huffman, buf, 0x0, 0, value);
     }
 
     fn encode_post_base_index(&self, buf: &mut QPData, index: u64) {
-        qdebug!([self] "encode post base index {}.", index);
+        qdebug!([self], "encode post base index {}.", index);
         buf.encode_prefixed_encoded_int(0x10, 4, index);
     }
 
     fn encode_literal_with_post_based_name_ref(&self, buf: &mut QPData, index: u64, value: &[u8]) {
         qdebug!(
-            [self]
+            [self],
             "encode literal with post base index - index={}, value={:x?}.",
             index,
             value
         );
         buf.encode_prefixed_encoded_int(0x00, 5, index);
         encode_literal(self.use_huffman, buf, 0x0, 0, value);
     }
 
     fn encode_literal_with_name_literal(&self, buf: &mut QPData, name: &[u8], value: &[u8]) {
         qdebug!(
-            [self]
+            [self],
             "encode literal with name literal - name={:x?}, value={:x?}.",
             name,
             value
         );
         encode_literal(self.use_huffman, buf, 0x20, 4, name);
         encode_literal(self.use_huffman, buf, 0x0, 0, value);
     }
 
--- a/third_party/rust/neqo-transport/.cargo-checksum.json
+++ b/third_party/rust/neqo-transport/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"82faeea7483f4181d323f7e6889d336606c52dd52d9e7cb900b9e51e6f3e3a83","TODO":"d759cb804b32fa9d96ea8d3574a3c4073da9fe6a0b02b708a0e22cce5a5b4a0f","src/connection.rs":"ced6150694f2bfda6f7ff1799087a52dabe07155401919fe84cbb3cdbf5ef307","src/crypto.rs":"2eccba8925d74b199f524686c70de3c6715fab95af7654e0657e58cfd338b640","src/dump.rs":"d3c327d303c1257094687f750b3d468eedf945b06166484bee75dc4cab7ca001","src/events.rs":"07b1fa18efc538b96736ebfedba929b4854dffd460e1250ae02dc79cc86bb310","src/flow_mgr.rs":"9ced2d8f9a8747a960795c80aad384bde7a9a25ed4ac3ebf4ea0ebf1133d8e7a","src/frame.rs":"97fc6b83a71e51106d5f947ca9855892bae657d50c7f3aa55e18c67c1bf71359","src/lib.rs":"784bc483e981c92a9f2301ed67cee62654405c6bdb854dadb1f2464b8e3ac5a5","src/packet.rs":"7fa31e596082d577397853b2043b4e0ac534218a7fdc6cfc52eeba1224948970","src/recovery.rs":"5fea4291a54ef6693ed7d2022b6e0574f94224421015714e090e38132b1f7cff","src/recv_stream.rs":"f092be0c94655938461d69cdbb146200681341145f15c57817873c64bc25c538","src/send_stream.rs":"f778f0904d1a944c934198af9138dc872912c45662338ae8562093f648735b3e","src/server.rs":"a3b44025a9ee5f1071ca75f5ae8f8e7e5070ae7b9c053737d1e090e7855907c1","src/stats.rs":"dca5afcb6252f3f32f494513f76964cffb945afd6d18b8669dea98a7aeed1689","src/stream_id.rs":"b3158cf2c6072da79bf6e77a31f71f2f3b970429221142a9ff1dd6cd07df2442","src/tparams.rs":"d35e2ec14958de74c315710bce80d8a72262f2437ddd1121fe28e752a1b4244d","src/tracking.rs":"9ce66170fa240db42a8c596f70846cc8e62925c30be6e622bc40b1a8f1ec73f2","tests/conn_vectors.rs":"5c381c8f1e0d126cb675bea302d1d118ea2ae988ec9c1536db2b18552074d845","tests/connection.rs":"195f52a876b9bd92f4368f301c98169a36438b5c9c1bb9ebaab146c7f8e0bb24","tests/server.rs":"8126ee12424487ee723d062169295e20858b041284a66c019173d39a7eaaa066"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"aa4e0d0fe520b00cca715828f066d6827c039f5127b1db9a3514318b53f36c51","TODO":"d759cb804b32fa9d96ea8d3574a3c4073da9fe6a0b02b708a0e22cce5a5b4a0f","src/connection.rs":"1994a978b6e6a970bb4d6870d0b932c92067f1288b81a871b6bdb7933c212211","src/crypto.rs":"dca8ce0a92f2ae12d87fcaa903cfd69048d6867eadd0eaf71670d000a23343de","src/dump.rs":"e4058d89acf50c3dea7e9f067e6fa1d8abfe0a65a77acf187f5012b53ed2568d","src/events.rs":"07b1fa18efc538b96736ebfedba929b4854dffd460e1250ae02dc79cc86bb310","src/flow_mgr.rs":"acd567f932be71ac4d342308369dd1620f6498fdb1c9a35a7325725702575c41","src/frame.rs":"17b85f48d20752dabaa2cd529ee65294ab0d37c4498134bb844958c9d901f2b0","src/lib.rs":"784bc483e981c92a9f2301ed67cee62654405c6bdb854dadb1f2464b8e3ac5a5","src/packet.rs":"7fa31e596082d577397853b2043b4e0ac534218a7fdc6cfc52eeba1224948970","src/recovery.rs":"f7bfbc605a03ba5c60a403fecbf843129d2868cb77e6378aa17c7c27c3dc6003","src/recv_stream.rs":"e3f8339aa8152587ec093ed426618a37a3b836fac56417fdf7822270bb5e87de","src/send_stream.rs":"69ee5867aa66a6d838dfc16e79b75d6fa9e0074d54229ccfc2e770f9f7deba57","src/server.rs":"d391a1d585bb1e45d025cdd1adb25f986128302178926b71e17dce8105346dda","src/stats.rs":"dca5afcb6252f3f32f494513f76964cffb945afd6d18b8669dea98a7aeed1689","src/stream_id.rs":"b3158cf2c6072da79bf6e77a31f71f2f3b970429221142a9ff1dd6cd07df2442","src/tparams.rs":"d35e2ec14958de74c315710bce80d8a72262f2437ddd1121fe28e752a1b4244d","src/tracking.rs":"49d2ca42ade8c2f9d119a0b96c25106a657f5e15022a1a19ddababb097944aea","tests/conn_vectors.rs":"5c381c8f1e0d126cb675bea302d1d118ea2ae988ec9c1536db2b18552074d845","tests/connection.rs":"195f52a876b9bd92f4368f301c98169a36438b5c9c1bb9ebaab146c7f8e0bb24","tests/server.rs":"8126ee12424487ee723d062169295e20858b041284a66c019173d39a7eaaa066"},"package":null}
\ No newline at end of file
--- a/third_party/rust/neqo-transport/Cargo.toml
+++ b/third_party/rust/neqo-transport/Cargo.toml
@@ -1,11 +1,11 @@
 [package]
 name = "neqo-transport"
-version = "0.1.4"
+version = "0.1.6"
 authors = ["EKR <ekr@rtfm.com>"]
 edition = "2018"
 license = "MIT/Apache-2.0"
 
 [dependencies]
 neqo-crypto = { path = "../neqo-crypto" }
 neqo-common = { path = "../neqo-common" }
 derive_more = "0.13"
--- a/third_party/rust/neqo-transport/src/connection.rs
+++ b/third_party/rust/neqo-transport/src/connection.rs
@@ -1,37 +1,35 @@
 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
 // The class implementing a QUIC connection.
 
-#![allow(dead_code)]
 use std::cell::RefCell;
 use std::cmp::{max, Ordering};
 use std::collections::HashMap;
 use std::convert::TryInto;
 use std::fmt::{self, Debug};
-use std::mem;
 use std::net::SocketAddr;
 use std::rc::Rc;
 use std::time::{Duration, Instant};
 
 use smallvec::SmallVec;
 
 use neqo_common::{hex, matches, qdebug, qerror, qinfo, qtrace, qwarn, Datagram, Decoder, Encoder};
 use neqo_crypto::agent::CertificateInfo;
 use neqo_crypto::{
-    Agent, AntiReplay, AuthenticationStatus, Client, Epoch, HandshakeState, Record, RecordList,
+    Agent, AntiReplay, AuthenticationStatus, Client, Epoch, HandshakeState, Record,
     SecretAgentInfo, Server,
 };
 
-use crate::crypto::Crypto;
+use crate::crypto::{Crypto, CryptoState};
 use crate::dump::*;
 use crate::events::{ConnectionEvent, ConnectionEvents};
 use crate::flow_mgr::FlowMgr;
 use crate::frame::{decode_frame, AckRange, Frame, FrameType, StreamType, TxMode};
 use crate::packet::{
     decode_packet_hdr, decrypt_packet, encode_packet, ConnectionId, ConnectionIdDecoder, PacketHdr,
     PacketNumberDecoder, PacketType,
 };
@@ -150,16 +148,24 @@ impl Path {
             local_cids: Vec::new(),
             remote_cid,
         }
     }
 
     pub fn received_on(&self, d: &Datagram) -> bool {
         self.local == d.destination() && self.remote == d.source()
     }
+
+    fn mtu(&self) -> usize {
+        if self.local.is_ipv4() {
+            1252
+        } else {
+            1232 // IPv6
+        }
+    }
 }
 
 #[derive(Clone, Debug, PartialEq)]
 /// Type returned from process() and `process_output()`. Users are required to
 /// call these repeatedly until `Callback` or `None` is returned.
 pub enum Output {
     /// Connection requires no action.
     None,
@@ -344,17 +350,17 @@ impl Connection {
             protocols,
             Some(Path {
                 local: local_addr,
                 remote: remote_addr,
                 local_cids,
                 remote_cid: dcid.clone(),
             }),
         );
-        c.crypto.states[0] = Some(c.crypto.create_initial_state(Role::Client, &dcid));
+        c.crypto.create_initial_state(Role::Client, &dcid);
         Ok(c)
     }
 
     /// Create a new QUIC connection with Server role.
     pub fn new_server(
         certs: &[impl AsRef<str>],
         protocols: &[impl AsRef<str>],
         anti_replay: &AntiReplay,
@@ -432,24 +438,16 @@ impl Connection {
         }
     }
 
     /// Set a local transport parameter, possibly overriding a default value.
     pub fn set_local_tparam(&self, key: u16, value: TransportParameter) {
         self.tps.borrow_mut().local.set(key, value)
     }
 
-    fn pmtu(&self) -> usize {
-        match &self.path {
-            Some(path) if path.local.is_ipv4() => 1252,
-            Some(_) => 1232, // IPv6
-            None => 1280,
-        }
-    }
-
     /// Set the connection ID that was originally chosen by the client.
     pub(crate) fn original_connection_id(&mut self, odcid: &ConnectionId) {
         assert_eq!(self.role, Role::Server);
         self.tps
             .borrow_mut()
             .local
             .set_bytes(tp_const::ORIGINAL_CONNECTION_ID, odcid.to_vec());
     }
@@ -490,31 +488,31 @@ impl Connection {
     }
 
     /// Enable resumption, using a token previously provided.
     /// This can only be called once and only on the client.
     /// After calling the function, it should be possible to attempt 0-RTT
     /// if the token supports that.
     pub fn set_resumption_token(&mut self, now: Instant, token: &[u8]) -> Res<()> {
         if self.state != State::Init {
-            qerror!([self] "set token in state {:?}", self.state);
+            qerror!([self], "set token in state {:?}", self.state);
             return Err(Error::ConnectionState);
         }
-        qinfo!([self] "resumption token {}", hex(token));
+        qinfo!([self], "resumption token {}", hex(token));
         let mut dec = Decoder::from(token);
         let tp_slice = match dec.decode_vvec() {
             Some(v) => v,
             _ => return Err(Error::InvalidResumptionToken),
         };
-        qtrace!([self] "  transport parameters {}", hex(&tp_slice));
+        qtrace!([self], "  transport parameters {}", hex(&tp_slice));
         let mut dec_tp = Decoder::from(tp_slice);
         let tp = TransportParameters::decode(&mut dec_tp)?;
 
         let tok = dec.decode_remainder();
-        qtrace!([self] "  TLS token {}", hex(&tok));
+        qtrace!([self], "  TLS token {}", hex(&tok));
         match self.crypto.tls {
             Agent::Client(ref mut c) => c.set_resumption_token(&tok)?,
             Agent::Server(_) => return Err(Error::WrongRole),
         }
 
         self.tps.borrow_mut().remote_0rtt = Some(tp);
         self.set_initial_limits();
         // Start up TLS, which has the effect of setting up all the necessary
@@ -528,18 +526,18 @@ impl Connection {
         match self.crypto.tls {
             Agent::Server(ref mut s) => {
                 let mut enc = Encoder::default();
                 enc.encode_vvec_with(|mut enc_inner| {
                     tps.borrow().local.encode(&mut enc_inner);
                 });
                 enc.encode(extra);
                 let records = s.send_ticket(now, &enc)?;
-                qinfo!([self] "send session ticket {}", hex(&enc));
-                self.buffer_crypto_records(records);
+                qinfo!([self], "send session ticket {}", hex(&enc));
+                self.crypto.buffer_records(records);
                 Ok(())
             }
             Agent::Client(_) => Err(Error::WrongRole),
         }
     }
 
     pub fn tls_info(&self) -> Option<&SecretAgentInfo> {
         self.crypto.tls.info()
@@ -576,17 +574,17 @@ impl Connection {
     // properly if that call fails.
     fn capture_error<T>(&mut self, now: Instant, frame_type: FrameType, res: Res<T>) -> Res<T> {
         if let Err(v) = &res {
             #[cfg(debug_assertions)]
             let msg = format!("{:?}", v);
             #[cfg(not(debug_assertions))]
             let msg = String::from("");
             if let State::Closed(err) | State::Closing { error: err, .. } = &self.state {
-                qwarn!([self] "Closing again after error {:?}", err);
+                qwarn!([self], "Closing again after error {:?}", err);
             } else {
                 self.set_state(State::Closing {
                     error: ConnectionError::Transport(v.clone()),
                     frame_type,
                     msg,
                     timeout: self.get_closing_period_time(now),
                 });
             }
@@ -621,17 +619,17 @@ impl Connection {
     pub fn process_input(&mut self, dgram: Datagram, now: Instant) {
         let res = self.input(dgram, now);
         self.absorb_error(now, res);
         self.cleanup_streams();
     }
 
     /// Get the time that we next need to be called back, relative to `now`.
     fn next_delay(&mut self, now: Instant) -> Duration {
-        self.loss_recovery_state = self.loss_recovery.get_timer(&self.state);
+        self.loss_recovery_state = self.loss_recovery.get_timer();
 
         let mut delays = SmallVec::<[_; 4]>::new();
 
         if let Some(lr_time) = self.loss_recovery_state.callback_time() {
             delays.push(lr_time);
         }
 
         if let Some(ack_time) = self.acks.ack_time() {
@@ -700,77 +698,85 @@ impl Connection {
     }
 
     fn is_valid_initial(&self, hdr: &PacketHdr) -> bool {
         if let PacketType::Initial(token) = &hdr.tipe {
             // Server checks the token, so if we have one,
             // assume that the DCID is OK.
             if hdr.dcid.len() < 8 {
                 if token.is_empty() {
-                    qinfo!([self] "Drop Initial with short DCID");
+                    qinfo!([self], "Drop Initial with short DCID");
                     false
                 } else {
-                    qinfo!([self] "Initial received with token, assuming OK");
+                    qinfo!([self], "Initial received with token, assuming OK");
                     true
                 }
             } else {
                 // This is the normal path. Don't log.
                 true
             }
         } else {
-            qdebug!([self] "Dropping non-Initial packet");
+            qdebug!([self], "Dropping non-Initial packet");
             false
         }
     }
 
     fn handle_retry(&mut self, scid: &ConnectionId, odcid: &ConnectionId, token: &[u8]) -> Res<()> {
-        qdebug!([self] "received Retry");
+        qdebug!([self], "received Retry");
         if self.retry_info.is_some() {
-            qinfo!([self] "Dropping extra Retry");
+            qinfo!([self], "Dropping extra Retry");
             return Ok(());
         }
         if token.is_empty() {
-            qinfo!([self] "Dropping Retry without a token");
+            qinfo!([self], "Dropping Retry without a token");
             return Ok(());
         }
         match self.path.iter_mut().find(|p| p.remote_cid == *odcid) {
             None => {
-                qinfo!([self] "Ignoring Retry with mismatched ODCID");
+                qinfo!([self], "Ignoring Retry with mismatched ODCID");
                 return Ok(());
             }
             Some(path) => {
                 path.remote_cid = scid.clone();
             }
         }
-        qinfo!([self] "Valid Retry received, restarting with provided token");
+        qinfo!(
+            [self],
+            "Valid Retry received, restarting with provided token"
+        );
         self.retry_info = Some(RetryInfo {
             token: token.to_vec(),
             odcid: odcid.clone(),
         });
         let lost_packets = self.loss_recovery.retry();
         self.handle_lost_packets(lost_packets);
 
         // Switching crypto state here might not happen eventually.
         // https://github.com/quicwg/base-drafts/issues/2823
-        self.crypto.states[0] = Some(self.crypto.create_initial_state(self.role, scid));
+        self.crypto.create_initial_state(self.role, scid);
         Ok(())
     }
 
     fn input(&mut self, d: Datagram, now: Instant) -> Res<()> {
         let mut slc = &d[..];
 
-        qinfo!([self] "input {}", hex( &**d));
+        qinfo!([self], "input {}", hex(&**d));
 
         // Handle each packet in the datagram
         while !slc.is_empty() {
             let res = decode_packet_hdr(self.cid_manager.borrow().as_decoder(), slc);
             let mut hdr = match res {
                 Ok(h) => h,
                 Err(e) => {
-                    qinfo!([self] "Received indecipherable packet header {} {}", hex(slc), e);
+                    qinfo!(
+                        [self],
+                        "Received indecipherable packet header {} {}",
+                        hex(slc),
+                        e
+                    );
                     return Ok(()); // Drop the remainder of the datagram.
                 }
             };
             self.stats.packets_rx += 1;
             match (&hdr.tipe, &self.state, &self.role) {
                 (PacketType::VN(_), State::WaitInitial, Role::Client) => {
                     self.set_state(State::Closed(ConnectionError::Transport(
                         Error::VersionNegotiation,
@@ -795,100 +801,106 @@ impl Connection {
                         self.version,
                     );
                     return Ok(());
                 }
             }
 
             match self.state {
                 State::Init => {
-                    qinfo!([self] "Received message while in Init state");
+                    qinfo!([self], "Received message while in Init state");
                     return Ok(());
                 }
                 State::WaitInitial => {
-                    qinfo!([self] "Received packet in WaitInitial");
+                    qinfo!([self], "Received packet in WaitInitial");
                     if self.role == Role::Server {
                         if !self.is_valid_initial(&hdr) {
                             return Ok(());
                         }
-                        self.crypto.states[0] =
-                            Some(self.crypto.create_initial_state(self.role, &hdr.dcid));
+                        self.crypto.create_initial_state(self.role, &hdr.dcid);
                     }
                 }
                 State::Handshaking | State::Connected => {
                     if !self.is_valid_cid(&hdr.dcid) {
-                        qinfo!([self] "Ignoring packet with CID {:?}", hdr.dcid);
+                        qinfo!([self], "Ignoring packet with CID {:?}", hdr.dcid);
                         return Ok(());
                     }
                 }
                 State::Closing { .. } => {
                     // Don't bother processing the packet. Instead ask to get a
                     // new close frame.
                     self.flow_mgr.borrow_mut().set_need_close_frame(true);
                     return Ok(());
                 }
                 State::Closed(..) => {
                     // Do nothing.
                     return Ok(());
                 }
             }
 
-            qdebug!([self] "Received unverified packet {:?}", hdr);
+            qdebug!([self], "Received unverified packet {:?}", hdr);
 
             let body = self.decrypt_body(&mut hdr, slc);
             slc = &slc[hdr.hdr_len + hdr.body_len()..];
             if let Some(body) = body {
                 // TODO(ekr@rtfm.com): Have the server blow away the initial
                 // crypto state if this fails? Otherwise, we will get a panic
                 // on the assert for doesn't exist.
                 // OK, we have a valid packet.
                 self.idle_timeout.on_packet_received(now);
-                dump_packet(self, "<- RX", &hdr, &body);
+                dump_packet(self, "-> RX", &hdr, &body);
                 if self.process_packet(&hdr, body, now)? {
                     continue;
                 }
                 self.start_handshake(hdr, &d)?;
                 self.process_migrations(&d)?;
             }
         }
         Ok(())
     }
 
     fn decrypt_body(&mut self, mut hdr: &mut PacketHdr, slc: &[u8]) -> Option<Vec<u8>> {
         // Decryption failure, or not having keys is not fatal.
         // If the state isn't available, or we can't decrypt the packet, drop
         // the rest of the datagram on the floor, but don't generate an error.
         let largest_acknowledged = self
             .loss_recovery
-            .largest_acknowledged(PNSpace::from(hdr.epoch));
+            .largest_acknowledged_pn(PNSpace::from(hdr.epoch));
+        if (self.state == State::Handshaking) && (hdr.epoch == 3) {
+            // Server has keys for epoch 3 but it is still in state Handshaking -> discharge packet.
+            debug_assert_eq!(self.role(), Role::Server);
+            return None;
+        }
         match self.crypto.obtain_crypto_state(self.role, hdr.epoch) {
-            Ok(cs) => match cs.rx.as_ref() {
-                Some(rx) => {
-                    let pn_decoder = PacketNumberDecoder::new(largest_acknowledged);
-                    decrypt_packet(rx, pn_decoder, &mut hdr, slc).ok()
-                }
-                _ => None,
-            },
+            Ok(CryptoState { rx: Some(rx), .. }) => {
+                let pn_decoder = PacketNumberDecoder::new(largest_acknowledged);
+                decrypt_packet(rx, pn_decoder, &mut hdr, slc).ok()
+            }
             _ => None,
         }
     }
 
     /// Ok(true) if the packet is a duplicate
     fn process_packet(&mut self, hdr: &PacketHdr, body: Vec<u8>, now: Instant) -> Res<bool> {
         // TODO(ekr@rtfm.com): Have the server blow away the initial
         // crypto state if this fails? Otherwise, we will get a panic
         // on the assert for doesn't exist.
         // OK, we have a valid packet.
 
         // TODO(ekr@rtfm.com): Filter for valid for this epoch.
 
         let ack_eliciting = self.input_packet(hdr.epoch, Decoder::from(&body[..]), now)?;
         let space = PNSpace::from(hdr.epoch);
         if self.acks[space].is_duplicate(hdr.pn) {
-            qdebug!([self] "Received duplicate packet epoch={} pn={}", hdr.epoch, hdr.pn);
+            qdebug!(
+                [self],
+                "Received duplicate packet epoch={} pn={}",
+                hdr.epoch,
+                hdr.pn
+            );
             self.stats.dups_rx += 1;
             Ok(true)
         } else {
             self.acks[space].set_received(now, hdr.pn, ack_eliciting);
             Ok(false)
         }
     }
 
@@ -911,17 +923,21 @@ impl Connection {
             // SecretAgentPreinfo::early_data() always returns false for a server,
             // but a non-zero maximum tells us if we are accepting 0-RTT.
             self.zero_rtt_state = if self.crypto.tls.preinfo()?.max_early_data() > 0 {
                 ZeroRttState::Accepted
             } else {
                 ZeroRttState::Rejected
             };
         } else {
-            qdebug!([self] "Changing to use Server CID={}", hdr.scid.as_ref().unwrap());
+            qdebug!(
+                [self],
+                "Changing to use Server CID={}",
+                hdr.scid.as_ref().unwrap()
+            );
             let p = self
                 .path
                 .iter_mut()
                 .find(|p| p.received_on(&d))
                 .expect("should have a path for sending Initial");
             p.remote_cid = hdr.scid.unwrap();
         }
         self.set_state(State::Handshaking);
@@ -934,91 +950,88 @@ impl Connection {
         } else {
             // Right now, we don't support any form of migration.
             // So generate an error if a packet is received on a new path.
             Err(Error::InvalidMigration)
         }
     }
 
     // Return whether the packet had ack-eliciting frames.
-    fn input_packet(&mut self, epoch: Epoch, mut d: Decoder, now: Instant) -> Res<(bool)> {
+    fn input_packet(&mut self, epoch: Epoch, mut d: Decoder, now: Instant) -> Res<bool> {
         let mut ack_eliciting = false;
 
         // Handle each frame in the packet
         while d.remaining() > 0 {
             let f = decode_frame(&mut d)?;
             ack_eliciting |= f.ack_eliciting();
             let t = f.get_type();
             let res = self.input_frame(epoch, f, now);
             self.capture_error(now, t, res)?;
         }
 
         Ok(ack_eliciting)
     }
 
     fn output(&mut self, now: Instant) -> Option<Datagram> {
         let mut out = None;
-        // Can't call a method on self while iterating over self.paths
-        let paths = mem::replace(&mut self.path, Default::default());
-        for p in &paths {
-            match self.output_path(&p, now) {
-                Ok(Some(dgram)) => {
-                    out = Some(dgram);
-                    break;
+        if self.path.is_some() {
+            match self.output_pkt_for_path(now) {
+                Ok(res) => {
+                    out = res;
                 }
                 Err(e) => {
                     if !matches!(self.state, State::Closing{..}) {
                         // An error here causes us to transition to closing.
                         self.absorb_error(now, Err(e));
                         // Rerun to give a chance to send a CONNECTION_CLOSE.
-                        out = match self.output_path(&p, now) {
+                        out = match self.output_pkt_for_path(now) {
                             Ok(x) => x,
                             Err(e) => {
-                                qwarn!([self] "two output_path errors in a row: {:?}", e);
+                                qwarn!([self], "two output_path errors in a row: {:?}", e);
                                 None
                             }
                         };
-                        break;
                     }
                 }
-                _ => (),
             };
         }
-        self.path = paths;
         out
     }
 
+    #[allow(clippy::cognitive_complexity)]
     /// Build a datagram, possibly from multiple packets (for different PN
     /// spaces) and each containing 1+ frames.
-    fn output_path(&mut self, path: &Path, now: Instant) -> Res<Option<Datagram>> {
+    fn output_pkt_for_path(&mut self, now: Instant) -> Res<Option<Datagram>> {
         let mut out_bytes = Vec::new();
         let mut needs_padding = false;
+        let path = self
+            .path
+            .take()
+            .expect("we know we have a path because calling fn checked");
 
         // Frames for different epochs must go in different packets, but then these
         // packets can go in a single datagram
         for epoch in 0..NUM_EPOCHS {
             let space = PNSpace::from(epoch);
             let mut encoder = Encoder::default();
             let mut tokens = Vec::new();
 
-            // Try to make our own crypo state and if we can't, skip this epoch.
-            match self.crypto.obtain_crypto_state(self.role, epoch) {
-                Ok(cs) => {
-                    if cs.tx.is_none() {
-                        continue;
-                    }
-                }
-                _ => continue,
+            // Ensure we have tx crypto state for this epoch, or skip it.
+            if !matches!(
+                self.crypto.obtain_crypto_state(self.role, epoch),
+                Ok(CryptoState { tx: Some(_), .. })
+            ) {
+                continue;
             }
 
             let mut ack_eliciting = false;
             match &self.state {
                 State::Init | State::WaitInitial | State::Handshaking | State::Connected => {
                     loop {
-                        let remaining = self.pmtu() - out_bytes.len() - encoder.len();
+                        let remaining = path.mtu() - out_bytes.len() - encoder.len();
 
                         // Check sources in turn for available frames
                         if let Some((frame, token)) = self
                             .acks
                             .get_frame(now, epoch)
                             .or_else(|| self.crypto.get_frame(epoch, TxMode::Normal, remaining))
                             .or_else(|| self.flow_mgr.borrow_mut().get_frame(epoch, remaining))
                             .or_else(|| {
@@ -1026,18 +1039,17 @@ impl Connection {
                                     .get_frame(epoch, TxMode::Normal, remaining)
                             })
                         {
                             ack_eliciting |= frame.ack_eliciting();
                             frame.marshal(&mut encoder);
                             if let Some(t) = token {
                                 tokens.push(t);
                             }
-                            assert!(encoder.len() <= self.pmtu());
-                            if out_bytes.len() + encoder.len() == self.pmtu() {
+                            if out_bytes.len() + encoder.len() == path.mtu() {
                                 // No more space for frames.
                                 break;
                             }
                         } else {
                             // No more frames to send.
                             break;
                         }
                     }
@@ -1064,17 +1076,17 @@ impl Connection {
                 }
                 State::Closed { .. } => unimplemented!(),
             }
 
             if encoder.len() == 0 {
                 continue;
             }
 
-            qdebug!([self] "Need to send a packet");
+            qdebug!([self], "Need to send a packet");
             match epoch {
                 // Packets containing Initial packets need padding.
                 0 => needs_padding = true,
                 1 => (),
                 // ...unless they include higher epochs.
                 _ => needs_padding = false,
             }
             let hdr = PacketHdr::new(
@@ -1113,39 +1125,42 @@ impl Connection {
             let cs = self
                 .crypto
                 .obtain_crypto_state(self.role, hdr.epoch)
                 .unwrap();
             let tx = cs.tx.as_ref().unwrap();
             let mut packet = encode_packet(tx, &hdr, &encoder);
             dump_packet(self, "TX ->", &hdr, &encoder);
             out_bytes.append(&mut packet);
-            if out_bytes.len() >= self.pmtu() {
+            if out_bytes.len() >= path.mtu() {
                 break;
             }
         }
 
         if out_bytes.is_empty() {
+            self.path = Some(path);
             return Ok(None);
         }
 
         // Pad Initial packets sent by the client to 1200 bytes.
         if self.role == Role::Client && needs_padding {
-            qdebug!([self] "pad Initial to 1200");
+            qdebug!([self], "pad Initial to 1200");
             out_bytes.resize(1200, 0);
         }
-        Ok(Some(Datagram::new(path.local, path.remote, out_bytes)))
+        let dgram = Some(Datagram::new(path.local, path.remote, out_bytes));
+        self.path = Some(path);
+        Ok(dgram)
     }
 
     fn client_start(&mut self, now: Instant) -> Res<()> {
-        qinfo!([self] "client_start");
+        qinfo!([self], "client_start");
         self.handshake(now, 0, None)?;
         self.set_state(State::WaitInitial);
         if self.crypto.tls.preinfo()?.early_data() {
-            qdebug!([self] "Enabling 0-RTT");
+            qdebug!([self], "Enabling 0-RTT");
             self.zero_rtt_state = ZeroRttState::Enabled;
         }
         Ok(())
     }
 
     fn get_closing_period_time(&self, now: Instant) -> Instant {
         // Spec says close time should be at least PTO times 3.
         now + (self.loss_recovery.pto() * 3)
@@ -1156,25 +1171,16 @@ impl Connection {
         self.set_state(State::Closing {
             error: ConnectionError::Application(error),
             frame_type: 0,
             msg: msg.into(),
             timeout: self.get_closing_period_time(now),
         });
     }
 
-    /// Buffer crypto records for sending.
-    fn buffer_crypto_records(&mut self, records: RecordList) {
-        for r in records {
-            assert_eq!(r.ct, 22);
-            qdebug!([self] "Adding CRYPTO data {:?}", r);
-            self.crypto.streams[r.epoch as usize].tx.send(&r.data);
-        }
-    }
-
     fn set_initial_limits(&mut self) {
         let tps = self.tps.borrow();
         let remote = tps.remote();
         self.indexes.remote_max_stream_bidi =
             StreamIndex::new(remote.get_integer(tp_const::INITIAL_MAX_STREAMS_BIDI));
         self.indexes.remote_max_stream_uni =
             StreamIndex::new(remote.get_integer(tp_const::INITIAL_MAX_STREAMS_UNI));
         self.flow_mgr
@@ -1197,47 +1203,46 @@ impl Connection {
             }
         } else {
             Ok(())
         }
     }
 
     fn handshake(&mut self, now: Instant, epoch: u16, data: Option<&[u8]>) -> Res<()> {
         qdebug!("Handshake epoch={} data={:0x?}", epoch, data);
-        let mut rec: Option<Record> = None;
 
-        if let Some(d) = data {
-            qdebug!([self] "Handshake received {:0x?} ", d);
-            rec = Some(Record {
-                ct: 22, // TODO(ekr@rtfm.com): Symbolic constants for CT. This is handshake.
-                epoch,
-                data: d.to_vec(),
-            });
-        }
+        let rec = data
+            .map(|d| {
+                qdebug!([self], "Handshake received {:0x?} ", d);
+                Some(Record {
+                    ct: 22, // TODO(ekr@rtfm.com): Symbolic constants for CT. This is handshake.
+                    epoch,
+                    data: d.to_vec(),
+                })
+            })
+            .unwrap_or(None);
 
-        let m = self.crypto.tls.handshake_raw(now, rec);
-        if *self.crypto.tls.state() == HandshakeState::AuthenticationPending {
-            self.events.authentication_needed();
-        }
-
-        match m {
+        match self.crypto.tls.handshake_raw(now, rec) {
             Err(e) => {
-                qwarn!([self] "Handshake failed");
+                qwarn!([self], "Handshake failed");
                 return Err(match self.crypto.tls.alert() {
                     Some(a) => Error::CryptoAlert(*a),
                     _ => Error::CryptoError(e),
                 });
             }
-            Ok(msgs) => self.buffer_crypto_records(msgs),
+            Ok(msgs) => self.crypto.buffer_records(msgs),
         }
-        if self.crypto.tls.state().connected() {
-            qinfo!([self] "TLS handshake completed");
+
+        if *self.crypto.tls.state() == HandshakeState::AuthenticationPending {
+            self.events.authentication_needed();
+        } else if matches!(self.crypto.tls.state(), HandshakeState::Complete(_)) {
+            qinfo!([self], "TLS handshake completed");
 
             if self.crypto.tls.info().map(SecretAgentInfo::alpn).is_none() {
-                qwarn!([self] "No ALPN. Closing connection.");
+                qwarn!([self], "No ALPN. Closing connection.");
                 // 120 = no_application_protocol
                 return Err(Error::CryptoAlert(120));
             }
 
             self.validate_odcid()?;
             self.set_state(State::Connected);
             self.set_initial_limits();
         }
@@ -1258,16 +1263,19 @@ impl Connection {
                     // uses up all the conn credit. Not our fault.
                     self.events.send_stream_writable(*id)
                 }
             }
         }
     }
 
     fn input_frame(&mut self, epoch: Epoch, frame: Frame, now: Instant) -> Res<()> {
+        if !frame.is_allowed(epoch) {
+            return Err(Error::ProtocolViolation);
+        }
         match frame {
             Frame::Padding => {
                 // Ignore
             }
             Frame::Ping => {
                 // Ack elicited with no further handling needed
             }
             Frame::Ack {
@@ -1302,17 +1310,17 @@ impl Connection {
                 self.events
                     .send_stream_stop_sending(stream_id.into(), application_error_code);
                 if let (Some(ss), _) = self.obtain_stream(stream_id.into())? {
                     ss.reset(application_error_code);
                 }
             }
             Frame::Crypto { offset, data } => {
                 qdebug!(
-                    [self]
+                    [self],
                     "Crypto frame on epoch={} offset={}, data={:0x?}",
                     epoch,
                     offset,
                     &data
                 );
                 let rx = &mut self.crypto.streams[epoch as usize].rx;
                 rx.inbound_frame(offset, data)?;
                 if rx.data_ready() {
@@ -1323,16 +1331,17 @@ impl Connection {
                 }
             }
             Frame::NewToken { token } => self.token = Some(token),
             Frame::Stream {
                 fin,
                 stream_id,
                 offset,
                 data,
+                ..
             } => {
                 if let (_, Some(rs)) = self.obtain_stream(stream_id.into())? {
                     rs.inbound_stream_frame(fin, offset, data)?;
                 }
             }
             Frame::MaxData { maximum_data } => self.handle_max_data(maximum_data),
             Frame::MaxStreamData {
                 stream_id,
@@ -1353,17 +1362,21 @@ impl Connection {
 
                 if maximum_streams > *remote_max {
                     *remote_max = maximum_streams;
                     self.events.send_stream_creatable(stream_type);
                 }
             }
             Frame::DataBlocked { data_limit } => {
                 // Should never happen since we set data limit to 2^62-1
-                qwarn!([self] "Received DataBlocked with data limit {}", data_limit);
+                qwarn!(
+                    [self],
+                    "Received DataBlocked with data limit {}",
+                    data_limit
+                );
             }
             Frame::StreamDataBlocked { stream_id, .. } => {
                 // TODO(agrover@mozilla.com): how should we be using
                 // currently-unused stream_data_limit?
 
                 let stream_id: StreamId = stream_id.into();
 
                 // Terminate connection with STREAM_STATE_ERROR if send-only
@@ -1397,29 +1410,31 @@ impl Connection {
             }
             Frame::RetireConnectionId { sequence_number } => {
                 self.connection_ids.remove(&sequence_number);
             }
             Frame::PathChallenge { data } => self.flow_mgr.borrow_mut().path_response(data),
             Frame::PathResponse { .. } => {
                 // Should never see this, we don't support migration atm and
                 // do not send path challenges
-                qwarn!([self] "Received Path Response");
+                qwarn!([self], "Received Path Response");
             }
             Frame::ConnectionClose {
                 error_code,
                 frame_type,
                 reason_phrase,
             } => {
                 let reason_phrase = String::from_utf8_lossy(&reason_phrase);
-                qinfo!([self]
-                       "ConnectionClose received. Error code: {:?} frame type {:x} reason {}",
-                       error_code,
-                       frame_type,
-                       reason_phrase);
+                qinfo!(
+                    [self],
+                    "ConnectionClose received. Error code: {:?} frame type {:x} reason {}",
+                    error_code,
+                    frame_type,
+                    reason_phrase
+                );
                 self.set_state(State::Closed(error_code.into()));
             }
         };
 
         Ok(())
     }
 
     fn handle_lost_packets<I>(&mut self, lost_packets: I)
@@ -1429,17 +1444,17 @@ impl Connection {
         for lost in lost_packets {
             for token in lost.tokens {
                 qtrace!([self], "Lost: {:?}", token);
                 match token {
                     RecoveryToken::Ack(_) => {}
                     RecoveryToken::Stream(st) => self.send_streams.lost(&st),
                     RecoveryToken::Crypto(ct) => self.crypto.lost(ct),
                     RecoveryToken::Flow(ft) => self.flow_mgr.borrow_mut().lost(
-                        ft,
+                        &ft,
                         &mut self.send_streams,
                         &mut self.recv_streams,
                         &mut self.indexes,
                     ),
                 }
             }
         }
     }
@@ -1449,17 +1464,17 @@ impl Connection {
         epoch: Epoch,
         largest_acknowledged: u64,
         ack_delay: u64,
         first_ack_range: u64,
         ack_ranges: Vec<AckRange>,
         now: Instant,
     ) -> Res<()> {
         qinfo!(
-            [self]
+            [self],
             "Rx ACK epoch={}, largest_acked={}, first_ack_range={}, ranges={:?}",
             epoch,
             largest_acknowledged,
             first_ack_range,
             ack_ranges
         );
 
         let acked_ranges =
@@ -1498,32 +1513,32 @@ impl Connection {
         // have a congestion controller.
         for dropped in self.loss_recovery.drop_0rtt() {
             for token in dropped.tokens {
                 match token {
                     RecoveryToken::Ack(_) => {}
                     RecoveryToken::Stream(st) => self.send_streams.lost(&st),
                     RecoveryToken::Crypto(ct) => self.crypto.lost(ct),
                     RecoveryToken::Flow(ft) => self.flow_mgr.borrow_mut().lost(
-                        ft,
+                        &ft,
                         &mut self.send_streams,
                         &mut self.recv_streams,
                         &mut self.indexes,
                     ),
                 }
             }
         }
         self.send_streams.clear();
         self.recv_streams.clear();
         self.events.client_0rtt_rejected();
     }
 
     fn set_state(&mut self, state: State) {
         if state > self.state {
-            qinfo!([self] "State change from {:?} -> {:?}", self.state, state);
+            qinfo!([self], "State change from {:?} -> {:?}", self.state, state);
             self.state = state.clone();
             match &self.state {
                 State::Connected => {
                     if self.role == Role::Server {
                         // Remove the randomized client CID from the list of acceptable CIDs.
                         assert_eq!(1, self.valid_cids.len());
                         self.valid_cids.clear();
                     } else {
@@ -1610,30 +1625,36 @@ impl Connection {
             } else {
                 &mut self.indexes.local_next_stream_uni
             };
             let stream_idx: StreamIndex = stream_id.into();
 
             if stream_idx >= *next_stream_idx {
                 let recv_initial_max_stream_data = if stream_id.is_bidi() {
                     if stream_idx > self.indexes.local_max_stream_bidi {
-                        qwarn!([self] "remote bidi stream create blocked, next={:?} max={:?}",
-                               stream_idx,
-                               self.indexes.local_max_stream_bidi);
+                        qwarn!(
+                            [self],
+                            "remote bidi stream create blocked, next={:?} max={:?}",
+                            stream_idx,
+                            self.indexes.local_max_stream_bidi
+                        );
                         return Err(Error::StreamLimitError);
                     }
                     self.tps
                         .borrow()
                         .local
                         .get_integer(tp_const::INITIAL_MAX_STREAM_DATA_BIDI_REMOTE)
                 } else {
                     if stream_idx > self.indexes.local_max_stream_uni {
-                        qwarn!([self] "remote uni stream create blocked, next={:?} max={:?}",
-                               stream_idx,
-                               self.indexes.local_max_stream_uni);
+                        qwarn!(
+                            [self],
+                            "remote uni stream create blocked, next={:?} max={:?}",
+                            stream_idx,
+                            self.indexes.local_max_stream_uni
+                        );
                         return Err(Error::StreamLimitError);
                     }
                     self.tps
                         .borrow()
                         .local
                         .get_integer(tp_const::INITIAL_MAX_STREAM_DATA_UNI)
                 };
 
@@ -1705,19 +1726,22 @@ impl Connection {
         }
 
         Ok(match st {
             StreamType::UniDi => {
                 if self.indexes.remote_next_stream_uni >= self.indexes.remote_max_stream_uni {
                     self.flow_mgr
                         .borrow_mut()
                         .streams_blocked(self.indexes.remote_max_stream_uni, StreamType::UniDi);
-                    qwarn!([self] "local uni stream create blocked, next={:?} max={:?}",
-                           self.indexes.remote_next_stream_uni,
-                           self.indexes.remote_max_stream_uni);
+                    qwarn!(
+                        [self],
+                        "local uni stream create blocked, next={:?} max={:?}",
+                        self.indexes.remote_next_stream_uni,
+                        self.indexes.remote_max_stream_uni
+                    );
                     return Err(Error::StreamLimitError);
                 }
                 let new_id = self
                     .indexes
                     .remote_next_stream_uni
                     .to_stream_id(StreamType::UniDi, self.role);
                 self.indexes.remote_next_stream_uni += 1;
                 let initial_max_stream_data = self
@@ -1737,19 +1761,22 @@ impl Connection {
                 );
                 new_id.as_u64()
             }
             StreamType::BiDi => {
                 if self.indexes.remote_next_stream_bidi >= self.indexes.remote_max_stream_bidi {
                     self.flow_mgr
                         .borrow_mut()
                         .streams_blocked(self.indexes.remote_max_stream_bidi, StreamType::BiDi);
-                    qwarn!([self] "local bidi stream create blocked, next={:?} max={:?}",
-                           self.indexes.remote_next_stream_bidi,
-                           self.indexes.remote_max_stream_bidi);
+                    qwarn!(
+                        [self],
+                        "local bidi stream create blocked, next={:?} max={:?}",
+                        self.indexes.remote_next_stream_bidi,
+                        self.indexes.remote_max_stream_bidi
+                    );
                     return Err(Error::StreamLimitError);
                 }
                 let new_id = self
                     .indexes
                     .remote_next_stream_bidi
                     .to_stream_id(StreamType::BiDi, self.role);
                 self.indexes.remote_next_stream_bidi += 1;
                 let send_initial_max_stream_data = self
@@ -1851,17 +1878,17 @@ impl Connection {
     /// Get events that indicate state changes on the connection. This method
     /// correctly handles cases where handling one event can obsolete
     /// previously-queued events, or cause new events to be generated.
     pub fn next_event(&mut self) -> Option<ConnectionEvent> {
         self.events.next_event()
     }
 
     fn check_loss_detection_timeout(&mut self, now: Instant) {
-        qdebug!([self] "check_loss_timeouts");
+        qdebug!([self], "check_loss_timeouts");
 
         if matches!(self.loss_recovery_state.mode(), LossRecoveryMode::None) {
             // LR not the active timer
             return;
         }
 
         if self.loss_recovery_state.callback_time() > Some(now) {
             // LR timer, but hasn't expired.
@@ -1882,28 +1909,28 @@ impl Connection {
                 qinfo!("lost packets: {}", packets.len());
                 for lost in packets {
                     for token in lost.tokens {
                         match token {
                             RecoveryToken::Ack(_) => {} // Do nothing
                             RecoveryToken::Stream(st) => self.send_streams.lost(&st),
                             RecoveryToken::Crypto(ct) => self.crypto.lost(ct),
                             RecoveryToken::Flow(ft) => self.flow_mgr.borrow_mut().lost(
-                                ft,
+                                &ft,
                                 &mut self.send_streams,
                                 &mut self.recv_streams,
                                 &mut self.indexes,
                             ),
                         }
                     }
                 }
             }
             LossRecoveryMode::PTO => {
                 qinfo!(
-                    [self]
+                    [self],
                     "check_loss_detection_timeout -send_one_or_two_packets"
                 );
                 self.loss_recovery.increment_pto_count();
                 // TODO
                 // if (has unacknowledged crypto data):
                 //   RetransmitUnackedCryptoData()
                 // else if (endpoint is client without 1-RTT keys):
                 //   // Client sends an anti-deadlock packet: Initial is padded
@@ -1925,16 +1952,17 @@ impl ::std::fmt::Display for Connection 
         write!(f, "{:?} {:p}", self.role, self as *const Connection)
     }
 }
 
 #[cfg(test)]
 mod tests {
     use super::*;
     use crate::frame::StreamType;
+    use std::mem;
     use test_fixture::{self, assertions, fixture_init, loopback, now};
 
     // This is fabulous: because test_fixture uses the public API for Connection,
     // it gets a different type to the ones that are referenced via super::*.
     // Thus, this code can't use default_client() and default_server() from
     // test_fixture because they produce different types.
     //
     // These are a direct copy of those functions.
@@ -2810,9 +2838,47 @@ mod tests {
 
         // The client gets the STOP_SENDING frame.
         client.process(out.dgram(), now());
         assert_eq!(
             Err(Error::InvalidStreamId),
             client.stream_send(stream_id, &[0x00])
         );
     }
+
+    #[test]
+    fn test_client_fin_reorder() {
+        let mut client = default_client();
+        let mut server = default_server();
+
+        // Send ClientHello.
+        let client_hs = client.process(None, now());
+        assert!(client_hs.as_dgram_ref().is_some());
+
+        let server_hs = server.process(client_hs.dgram(), now());
+        assert!(server_hs.as_dgram_ref().is_some()); // ServerHello, etc...
+
+        let client_ack = client.process(server_hs.dgram(), now());
+        assert!(client_ack.as_dgram_ref().is_some());
+
+        let server_out = server.process(client_ack.dgram(), now());
+        assert!(server_out.as_dgram_ref().is_none());
+
+        assert!(maybe_authenticate(&mut client));
+        assert_eq!(*client.state(), State::Connected);
+
+        let client_fin = client.process(None, now());
+        assert!(client_fin.as_dgram_ref().is_some());
+
+        let client_stream_id = client.stream_create(StreamType::UniDi).unwrap();
+        client.stream_send(client_stream_id, &[1, 2, 3]).unwrap();
+        let client_stream_data = client.process(None, now());
+        assert!(client_stream_data.as_dgram_ref().is_some());
+
+        // Now stream data gets before client_fin
+        let server_out = server.process(client_stream_data.dgram(), now());
+        assert!(server_out.as_dgram_ref().is_none()); // the packet will be discarded
+
+        assert_eq!(*server.state(), State::Handshaking);
+        let server_out = server.process(client_fin.dgram(), now());
+        assert!(server_out.as_dgram_ref().is_some());
+    }
 }
--- a/third_party/rust/neqo-transport/src/crypto.rs
+++ b/third_party/rust/neqo-transport/src/crypto.rs
@@ -1,28 +1,27 @@
 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
 use std::cell::RefCell;
-use std::cmp::min;
 use std::rc::Rc;
 
 use neqo_common::{hex, qdebug, qinfo, qtrace};
 use neqo_crypto::aead::Aead;
 use neqo_crypto::hp::HpKey;
 use neqo_crypto::{
-    hkdf, Agent, AntiReplay, Cipher, Epoch, SymKey, TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384,
-    TLS_VERSION_1_3,
+    hkdf, Agent, AntiReplay, Cipher, Epoch, RecordList, SymKey, TLS_AES_128_GCM_SHA256,
+    TLS_AES_256_GCM_SHA384, TLS_VERSION_1_3,
 };
 
 use crate::connection::Role;
-use crate::frame::{crypto_frame_hdr_len, Frame, TxMode};
+use crate::frame::{Frame, TxMode};
 use crate::packet::{CryptoCtx, PacketNumber};
 use crate::recovery::RecoveryToken;
 use crate::recv_stream::RxStreamOrderer;
 use crate::send_stream::TxBuffer;
 use crate::tparams::{TpZeroRttChecker, TransportParametersHandler};
 use crate::{Error, Res};
 
 const MAX_AUTH_TAG: usize = 32;
@@ -57,58 +56,67 @@ impl Crypto {
         Ok(Crypto {
             tls: agent,
             streams: Default::default(),
             states: Default::default(),
         })
     }
 
     // Create the initial crypto state.
-    pub fn create_initial_state(&mut self, role: Role, dcid: &[u8]) -> CryptoState {
+    pub fn create_initial_state(&mut self, role: Role, dcid: &[u8]) {
         const CLIENT_INITIAL_LABEL: &str = "client in";
         const SERVER_INITIAL_LABEL: &str = "server in";
 
         qinfo!(
-            [self]
+            [self],
             "Creating initial cipher state role={:?} dcid={}",
             role,
             hex(dcid)
         );
 
         let (write_label, read_label) = match role {
             Role::Client => (CLIENT_INITIAL_LABEL, SERVER_INITIAL_LABEL),
             Role::Server => (SERVER_INITIAL_LABEL, CLIENT_INITIAL_LABEL),
         };
 
-        CryptoState {
+        self.states[0] = Some(CryptoState {
             epoch: 0,
             tx: CryptoDxState::new_initial(CryptoDxDirection::Write, write_label, dcid),
             rx: CryptoDxState::new_initial(CryptoDxDirection::Read, read_label, dcid),
+        });
+    }
+
+    /// Buffer crypto records for sending.
+    pub fn buffer_records(&mut self, records: RecordList) {
+        for r in records {
+            assert_eq!(r.ct, 22);
+            qdebug!([self], "Adding CRYPTO data {:?}", r);
+            self.streams[r.epoch as usize].tx.send(&r.data);
         }
     }
 
     // Get a crypto state, making it if necessary, otherwise return an error.
     pub fn obtain_crypto_state(&mut self, role: Role, epoch: Epoch) -> Res<&mut CryptoState> {
         #[cfg(debug_assertions)]
         let label = format!("{}", self);
         #[cfg(not(debug_assertions))]
         let label = "";
 
         let cs = &mut self.states[epoch as usize];
         if cs.is_none() {
-            qtrace!([label] "Build crypto state for epoch {}", epoch);
+            qtrace!([label], "Build crypto state for epoch {}", epoch);
             assert!(epoch != 0); // This state is made directly.
 
             let cipher = match (epoch, self.tls.info()) {
                 (1, _) => self.tls.preinfo()?.early_data_cipher(),
                 (_, None) => self.tls.preinfo()?.cipher_suite(),
                 (_, Some(info)) => Some(info.cipher_suite()),
             };
             if cipher.is_none() {
-                qdebug!([label] "cipher info not available yet");
+                qdebug!([label], "cipher info not available yet");
                 return Err(Error::KeysNotFound);
             }
             let cipher = cipher.unwrap();
 
             let rx = self
                 .tls
                 .read_secret(epoch)
                 .map(|rs| CryptoDxState::new(CryptoDxDirection::Read, epoch, rs, cipher));
@@ -118,17 +126,17 @@ impl Crypto {
                 .map(|ws| CryptoDxState::new(CryptoDxDirection::Write, epoch, ws, cipher));
 
             // Validate the key setup.
             match (&rx, &tx, role, epoch) {
                 (None, Some(_), Role::Client, 1)
                 | (Some(_), None, Role::Server, 1)
                 | (Some(_), Some(_), _, _) => {}
                 (None, None, _, _) => {
-                    qdebug!([label] "Keying material not available for epoch {}", epoch);
+                    qdebug!([label], "Keying material not available for epoch {}", epoch);
                     return Err(Error::KeysNotFound);
                 }
                 _ => panic!("bad configuration of keys"),
             }
 
             *cs = Some(CryptoState { epoch, rx, tx });
         }
 
@@ -162,22 +170,17 @@ impl Crypto {
     pub fn get_frame(
         &mut self,
         epoch: u16,
         mode: TxMode,
         remaining: usize,
     ) -> Option<(Frame, Option<RecoveryToken>)> {
         let tx_stream = &mut self.streams[epoch as usize].tx;
         if let Some((offset, data)) = tx_stream.next_bytes(mode) {
-            let frame_hdr_len = crypto_frame_hdr_len(offset, remaining);
-            let length = min(data.len(), remaining - frame_hdr_len);
-            let frame = Frame::Crypto {
-                offset,
-                data: data[..length].to_vec(),
-            };
+            let (frame, length) = Frame::new_crypto(offset, data, remaining);
             tx_stream.mark_as_sent(offset, length);
 
             qdebug!(
                 "Emitting crypto frame epoch={}, offset={}, len={}",
                 epoch,
                 offset,
                 length
             );
@@ -271,41 +274,41 @@ impl CryptoCtx for CryptoDxState {
     fn compute_mask(&self, sample: &[u8]) -> Res<Vec<u8>> {
         let mask = self.hpkey.mask(sample)?;
         qdebug!("HP sample={} mask={}", hex(sample), hex(&mask));
         Ok(mask)
     }
 
     fn aead_decrypt(&self, pn: PacketNumber, hdr: &[u8], body: &[u8]) -> Res<Vec<u8>> {
         qinfo!(
-            [self]
+            [self],
             "aead_decrypt pn={} hdr={} body={}",
             pn,
             hex(hdr),
             hex(body)
         );
         let mut out = vec![0; body.len()];
         let res = self.aead.decrypt(pn, hdr, body, &mut out)?;
         Ok(res.to_vec())
     }
 
     fn aead_encrypt(&self, pn: PacketNumber, hdr: &[u8], body: &[u8]) -> Res<Vec<u8>> {
         qdebug!(
-            [self]
+            [self],
             "aead_encrypt pn={} hdr={} body={}",
             pn,
             hex(hdr),
             hex(body)
         );
 
         let size = body.len() + MAX_AUTH_TAG;
         let mut out = vec![0; size];
         let res = self.aead.encrypt(pn, hdr, body, &mut out)?;
 
-        qdebug!([self] "aead_encrypt ct={}", hex(res),);
+        qdebug!([self], "aead_encrypt ct={}", hex(res),);
 
         Ok(res.to_vec())
     }
 }
 
 impl std::fmt::Display for CryptoDxState {
     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
         write!(f, "epoch {} {:?}", self.epoch, self.direction)
--- a/third_party/rust/neqo-transport/src/dump.rs
+++ b/third_party/rust/neqo-transport/src/dump.rs
@@ -23,10 +23,10 @@ pub fn dump_packet(conn: &Connection, di
                 s.push_str(" [broken]...");
                 break;
             }
         };
         if let Some(x) = f.dump() {
             s.push_str(&format!("\n  {} {}", dir, &x));
         }
     }
-    qdebug!([conn] "pn={} type={:?}{}", hdr.pn, hdr.tipe, s);
+    qdebug!([conn], "pn={} type={:?}{}", hdr.pn, hdr.tipe, s);
 }
--- a/third_party/rust/neqo-transport/src/flow_mgr.rs
+++ b/third_party/rust/neqo-transport/src/flow_mgr.rs
@@ -46,20 +46,26 @@ impl FlowMgr {
         self.max_data - self.used_data
     }
 
     pub fn conn_increase_credit_used(&mut self, amount: u64) {
         self.used_data += amount;
         assert!(self.used_data <= self.max_data)
     }
 
+    // Dummy DataBlocked frame for discriminant use below
+
     /// Returns whether max credit was actually increased.
     pub fn conn_increase_max_credit(&mut self, new: u64) -> bool {
         if new > self.max_data {
             self.max_data = new;
+
+            const DB_FRAME: Frame = Frame::DataBlocked { data_limit: 0 };
+            self.from_conn.remove(&mem::discriminant(&DB_FRAME));
+
             true
         } else {
             false
         }
     }
 
     // -- frames scoped on connection --
 
@@ -70,16 +76,21 @@ impl FlowMgr {
         self.from_conn.insert(mem::discriminant(&frame), frame);
     }
 
     pub fn path_response(&mut self, data: [u8; 8]) {
         let frame = Frame::PathResponse { data };
         self.from_conn.insert(mem::discriminant(&frame), frame);
     }
 
+    pub fn max_data(&mut self, maximum_data: u64) {
+        let frame = Frame::MaxData { maximum_data };
+        self.from_conn.insert(mem::discriminant(&frame), frame);
+    }
+
     // -- frames scoped on stream --
 
     /// Indicate to receiving remote the stream is reset
     pub fn stream_reset(
         &mut self,
         stream_id: StreamId,
         application_error_code: AppError,
         final_size: u64,
@@ -200,22 +211,22 @@ impl FlowMgr {
             }
 
             send_streams.reset_acked(stream_id.into());
         }
     }
 
     pub(crate) fn lost(
         &mut self,
-        token: FlowControlRecoveryToken,
+        token: &FlowControlRecoveryToken,
         send_streams: &mut SendStreams,
         recv_streams: &mut RecvStreams,
         indexes: &mut StreamIndexes,
     ) {
-        match token {
+        match *token {
             // Always resend ResetStream if lost
             Frame::ResetStream {
                 stream_id,
                 application_error_code,
                 final_size,
             } => {
                 qinfo!(
                     "Reset lost stream={} err={} final_size={}",
--- a/third_party/rust/neqo-transport/src/frame.rs
+++ b/third_party/rust/neqo-transport/src/frame.rs
@@ -1,22 +1,26 @@
 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
 // Directly relating to QUIC frames.
 
-use neqo_common::{qdebug, Decoder, Encoder};
+use neqo_common::{matches, qdebug, Decoder, Encoder};
+use neqo_crypto::Epoch;
 
 use crate::stream_id::StreamIndex;
 use crate::{AppError, TransportError};
 use crate::{ConnectionError, Error, Res};
 
+use std::cmp::min;
+use std::convert::TryFrom;
+
 #[allow(clippy::module_name_repetitions)]
 pub type FrameType = u64;
 
 const FRAME_TYPE_PADDING: FrameType = 0x0;
 const FRAME_TYPE_PING: FrameType = 0x1;
 const FRAME_TYPE_ACK: FrameType = 0x2;
 const FRAME_TYPE_ACK_ECN: FrameType = 0x3;
 const FRAME_TYPE_RST_STREAM: FrameType = 0x4;
@@ -137,16 +141,17 @@ pub enum Frame {
     NewToken {
         token: Vec<u8>,
     },
     Stream {
         fin: bool,
         stream_id: u64,
         offset: u64,
         data: Vec<u8>,
+        fill: bool,
     },
     MaxData {
         maximum_data: u64,
     },
     MaxStreamData {
         stream_id: u64,
         maximum_stream_data: u64,
     },
@@ -192,25 +197,29 @@ impl Frame {
         match self {
             Frame::Padding => FRAME_TYPE_PADDING,
             Frame::Ping => FRAME_TYPE_PING,
             Frame::Ack { .. } => FRAME_TYPE_ACK, // We don't do ACK ECN.
             Frame::ResetStream { .. } => FRAME_TYPE_RST_STREAM,
             Frame::StopSending { .. } => FRAME_TYPE_STOP_SENDING,
             Frame::Crypto { .. } => FRAME_TYPE_CRYPTO,
             Frame::NewToken { .. } => FRAME_TYPE_NEW_TOKEN,
-            Frame::Stream { fin, offset, .. } => {
+            Frame::Stream {
+                fin, offset, fill, ..
+            } => {
                 let mut t = FRAME_TYPE_STREAM;
                 if *fin {
                     t |= STREAM_FRAME_BIT_FIN;
                 }
                 if *offset > 0 {
                     t |= STREAM_FRAME_BIT_OFF;
                 }
-                t |= STREAM_FRAME_BIT_LEN;
+                if !*fill {
+                    t |= STREAM_FRAME_BIT_LEN;
+                }
                 t
             }
             Frame::MaxData { .. } => FRAME_TYPE_MAX_DATA,
             Frame::MaxStreamData { .. } => FRAME_TYPE_MAX_STREAM_DATA,
             Frame::MaxStreams { stream_type, .. } => {
                 FRAME_TYPE_MAX_STREAMS_BIDI + stream_type.frame_type_bit()
             }
             Frame::DataBlocked { .. } => FRAME_TYPE_DATA_BLOCKED,
@@ -223,16 +232,78 @@ impl Frame {
             Frame::PathChallenge { .. } => FRAME_TYPE_PATH_CHALLENGE,
             Frame::PathResponse { .. } => FRAME_TYPE_PATH_RESPONSE,
             Frame::ConnectionClose { error_code, .. } => {
                 FRAME_TYPE_CONNECTION_CLOSE_TRANSPORT + error_code.frame_type_bit()
             }
         }
     }
 
+    /// Create a CRYPTO frame that fits the available space and its length.
+    pub fn new_crypto(offset: u64, data: &[u8], space: usize) -> (Frame, usize) {
+        // Subtract the frame type and offset from available space.
+        let mut remaining = space - 1 - Encoder::varint_len(offset);
+        // Then subtract space for the length field.
+        let data_len = min(remaining - 1, data.len());
+        remaining -= Encoder::varint_len(u64::try_from(data_len).unwrap());
+        remaining = min(data.len(), remaining);
+        (
+            Frame::Crypto {
+                offset,
+                data: data[..remaining].to_vec(),
+            },
+            remaining,
+        )
+    }
+
+    /// Create a STREAM frame that fits the available space.
+    /// Return a tuple of a frame and the amount of data it carries.
+    pub fn new_stream(
+        stream_id: u64,
+        offset: u64,
+        data: &[u8],
+        fin: bool,
+        space: usize,
+    ) -> (Frame, usize) {
+        let mut remaining = space - 1 - Encoder::varint_len(stream_id);
+        if offset > 0 {
+            remaining -= Encoder::varint_len(offset);
+        }
+        let (fin, fill) = if data.len() > remaining {
+            // More data than fits, fill the packet and negate |fin|.
+            (false, true)
+        } else if data.len() == remaining {
+            // Exact fit, fill the packet, keep |fin|.
+            (fin, true)
+        } else {
+            // Too small, so include a length.
+            let data_len = min(remaining - 1, data.len());
+            remaining -= Encoder::varint_len(u64::try_from(data_len).unwrap());
+            remaining = min(data.len(), remaining);
+            // In case the added length causes this to spill over, check |fin| again.
+            (fin && remaining == data.len(), false)
+        };
+        qdebug!(
+            "Frame::new_stream fill {} fin {} data {}",
+            fill,
+            fin,
+            remaining
+        );
+        (
+            Frame::Stream {
+                stream_id,
+                offset,
+                data: data[..remaining].to_vec(),
+                fin,
+                fill,
+            },
+            remaining,
+        )
+    }
+
     pub fn marshal(&self, enc: &mut Encoder) {
         enc.encode_varint(self.get_type());
 
         match self {
             Frame::Padding | Frame::Ping => (),
             Frame::Ack {
                 largest_acknowledged,
                 ack_delay,
@@ -270,23 +341,28 @@ impl Frame {
             }
             Frame::NewToken { token } => {
                 enc.encode_vvec(token);
             }
             Frame::Stream {
                 stream_id,
                 offset,
                 data,
+                fill,
                 ..
             } => {
                 enc.encode_varint(*stream_id);
                 if *offset > 0 {
                     enc.encode_varint(*offset);
                 }
-                enc.encode_vvec(&data);
+                if *fill {
+                    enc.encode(&data);
+                } else {
+                    enc.encode_vvec(&data);
+                }
             }
             Frame::MaxData { maximum_data } => {
                 enc.encode_varint(*maximum_data);
             }
             Frame::MaxStreamData {
                 stream_id,
                 maximum_stream_data,
             } => {
@@ -340,20 +416,17 @@ impl Frame {
                 enc.encode_varint(error_code.code());
                 enc.encode_varint(*frame_type);
                 enc.encode_vvec(reason_phrase);
             }
         }
     }
 
     pub fn ack_eliciting(&self) -> bool {
-        match self {
-            Frame::Ack { .. } | Frame::Padding => false,
-            _ => true,
-        }
+        !matches!(self, Frame::Ack { .. } | Frame::Padding | Frame::ConnectionClose { .. })
     }
 
     /// Converts AckRanges as encoded in a ACK frame (see -transport
     /// 19.3.1) into ranges of acked packets (end, start), inclusive of
     /// start and end values.
     pub fn decode_ack_frame(
         largest_acked: u64,
         first_ack_range: u64,
@@ -399,36 +472,45 @@ impl Frame {
             Frame::Crypto { offset, data } => Some(format!(
                 "Crypto {{ offset: {}, len: {} }}",
                 offset,
                 data.len()
             )),
             Frame::Stream {
                 stream_id,
                 offset,
+                fill,
                 data,
                 fin,
             } => Some(format!(
-                "Stream {{ stream_id: {}, offset: {}, len: {} fin: {} }}",
+                "Stream {{ stream_id: {}, offset: {}, len: {}{} fin: {} }}",
                 stream_id,
                 offset,
+                if *fill { ">>" } else { "" },
                 data.len(),
                 fin,
             )),
             Frame::Padding => None,
             _ => Some(format!("{:?}", self)),
         }
     }
-}
 
-/// Calculate the crypto frame header size so we know how much data we can fit
-pub fn crypto_frame_hdr_len(offset: u64, remaining: usize) -> usize {
-    let mut hdr_len = 1; // for frame type
-    hdr_len += Encoder::varint_len(offset);
-    hdr_len + Encoder::varint_len(remaining as u64)
+    pub fn is_allowed(&self, epoch: Epoch) -> bool {
+        qdebug!("is_allowed {:?} {}", self, epoch);
+        if matches!(self, Frame::Padding | Frame::Ping) {
+            true
+        } else if matches!(self, Frame::Crypto {..} | Frame::Ack {..} | Frame::ConnectionClose { error_code: CloseError::Transport(_), .. })
+        {
+            epoch != 1
+        } else if matches!(self, Frame::NewToken {..} | Frame::ConnectionClose {..}) {
+            epoch >= 3
+        } else {
+            epoch == 1 || epoch >= 3 // Application data
+        }
+    }
 }
 
 #[allow(clippy::module_name_repetitions)]
 pub fn decode_frame(dec: &mut Decoder) -> Res<Frame> {
     macro_rules! d {
         ($d:expr) => {
             match $d {
                 Some(v) => v,
@@ -503,28 +585,30 @@ pub fn decode_frame(dec: &mut Decoder) -
         FRAME_TYPE_STREAM..=FRAME_TYPE_STREAM_MAX => {
             let s = dv!(dec);
             let o = if t & STREAM_FRAME_BIT_OFF == 0 {
                 0
             } else {
                 dv!(dec)
             };
             qdebug!("STREAM {}", t);
-            let data = if (t & STREAM_FRAME_BIT_LEN) == 0 {
+            let fill = (t & STREAM_FRAME_BIT_LEN) == 0;
+            let data = if fill {
                 qdebug!("STREAM frame extends to the end of the packet");
                 dec.decode_remainder()
             } else {
                 qdebug!("STREAM frame has a length");
                 d!(dec.decode_vvec())
             };
             Ok(Frame::Stream {
                 fin: (t & STREAM_FRAME_BIT_FIN) != 0,
                 stream_id: s,
                 offset: o,
                 data: data.to_vec(), // TODO(mt) unnecessary copy.
+                fill,
             })
         }
         FRAME_TYPE_MAX_DATA => Ok(Frame::MaxData {
             maximum_data: dv!(dec),
         }),
         FRAME_TYPE_MAX_STREAM_DATA => Ok(Frame::MaxStreamData {
             stream_id: dv!(dec),
             maximum_stream_data: dv!(dec),
@@ -586,17 +670,16 @@ pub fn decode_frame(dec: &mut Decoder) -
         }
         _ => Err(Error::UnknownFrameType),
     }
 }
 
 #[derive(Debug, PartialEq, Clone, Copy)]
 pub enum TxMode {
     Normal,
-    #[allow(dead_code)]
     Pto,
 }
 
 #[cfg(test)]
 mod tests {
     use super::*;
     use neqo_common::hex;
 
@@ -684,40 +767,45 @@ mod tests {
         };
 
         enc_dec(&f, "0703123456");
     }
 
     #[test]
     fn test_stream() {
         // First, just set the length bit.
-        let mut f = Frame::Stream {
+        let f = Frame::Stream {
             fin: false,
             stream_id: 5,
             offset: 0,
             data: vec![1, 2, 3],
+            fill: false,
         };
 
         enc_dec(&f, "0a0503010203");
 
-        // Now verify that we can parse without the length
-        // bit, because we never generate this.
-        let enc = Encoder::from_hex("0805010203");
-        let mut dec = enc.as_decoder();
-        let f2 = decode_frame(&mut dec).unwrap();
-        assert_eq!(f, f2);
-
         // Now with offset != 0 and FIN
-        f = Frame::Stream {
+        let f = Frame::Stream {
             fin: true,
             stream_id: 5,
             offset: 1,
             data: vec![1, 2, 3],
+            fill: false,
         };
         enc_dec(&f, "0f050103010203");
+
+        // Now to fill the packet.
+        let f = Frame::Stream {
+            fin: true,
+            stream_id: 5,
+            offset: 0,
+            data: vec![1, 2, 3],
+            fill: true,
+        };
+        enc_dec(&f, "0905010203");
     }
 
     #[test]
     fn test_max_data() {
         let f = Frame::MaxData {
             maximum_data: 0x1234,
         };
 
--- a/third_party/rust/neqo-transport/src/recovery.rs
+++ b/third_party/rust/neqo-transport/src/recovery.rs
@@ -14,17 +14,16 @@ use std::time::{Duration, Instant};
 use smallvec::SmallVec;
 
 use neqo_common::{qdebug, qinfo};
 
 use crate::crypto::CryptoRecoveryToken;
 use crate::flow_mgr::FlowControlRecoveryToken;
 use crate::send_stream::StreamRecoveryToken;
 use crate::tracking::{AckToken, PNSpace};
-use crate::State;
 
 const GRANULARITY: Duration = Duration::from_millis(20);
 // Defined in -recovery 6.2 as 500ms but using lower value until we have RTT
 // caching. See https://github.com/mozilla/neqo/issues/79
 const INITIAL_RTT: Duration = Duration::from_millis(100);
 
 const PACKET_THRESHOLD: u64 = 3;
 
@@ -239,17 +238,17 @@ impl LossRecovery {
         self.spaces[pn_space].tx_pn += 1;
         val
     }
 
     pub fn increment_pto_count(&mut self) {
         self.pto_count += 1;
     }
 
-    pub fn largest_acknowledged(&self, pn_space: PNSpace) -> Option<u64> {
+    pub fn largest_acknowledged_pn(&self, pn_space: PNSpace) -> Option<u64> {
         self.spaces[pn_space].largest_acked
     }
 
     pub fn pto(&self) -> Duration {
         self.rtt_vals.pto()
     }
 
     pub fn drop_0rtt(&mut self) -> impl Iterator<Item = SentPacket> {
@@ -259,17 +258,17 @@ impl LossRecovery {
     pub fn on_packet_sent(
         &mut self,
         pn_space: PNSpace,
         packet_number: u64,
         ack_eliciting: bool,
         tokens: Vec<RecoveryToken>,
         now: Instant,
     ) {
-        qdebug!([self] "packet {:?}-{} sent.", pn_space, packet_number);
+        qdebug!([self], "packet {:?}-{} sent.", pn_space, packet_number);
         self.spaces[pn_space].sent_packets.insert(
             packet_number,
             SentPacket {
                 time_sent: now,
                 ack_eliciting,
                 tokens,
                 time_declared_lost: None,
             },
@@ -285,18 +284,22 @@ impl LossRecovery {
     pub fn on_ack_received(
         &mut self,
         pn_space: PNSpace,
         largest_acked: u64,
         acked_ranges: Vec<(u64, u64)>,
         ack_delay: Duration,
         now: Instant,
     ) -> (Vec<SentPacket>, Vec<SentPacket>) {
-        qdebug!([self] "ack received for {:?} - largest_acked={}.",
-                pn_space, largest_acked);
+        qdebug!(
+            [self],
+            "ack received for {:?} - largest_acked={}.",
+            pn_space,
+            largest_acked
+        );
 
         let (acked_packets, any_ack_eliciting) = self.spaces[pn_space].remove_acked(acked_ranges);
         if acked_packets.is_empty() {
             // No new information.
             return (Vec::new(), Vec::new());
         }
 
         // Track largest PN acked per space
@@ -349,19 +352,22 @@ impl LossRecovery {
 
     /// Detect packets whose contents may need to be retransmitted.
     pub fn detect_lost_packets(&mut self, pn_space: PNSpace, now: Instant) -> Vec<SentPacket> {
         self.enable_timed_loss_detection = false;
         let loss_delay = self.loss_delay();
 
         // Packets sent before this time are deemed lost.
         let lost_deadline = now - loss_delay;
-        qdebug!([self]
+        qdebug!(
+            [self],
             "detect lost packets = now {:?} loss delay {:?} lost_deadline {:?}",
-            now, loss_delay, lost_deadline
+            now,
+            loss_delay,
+            lost_deadline
         );
 
         let packet_space = &mut self.spaces[pn_space];
 
         // Lost for retrans/CC purposes
         let mut lost_pns = SmallVec::<[_; 8]>::new();
 
         // Lost for we-can-actually-forget-about-it purposes
@@ -431,36 +437,33 @@ impl LossRecovery {
                 .expect("PN must be in sent_packets")
                 .clone();
             lost_packets.push(lost_packet);
         }
 
         lost_packets
     }
 
-    pub fn get_timer(&mut self, conn_state: &State) -> LossRecoveryState {
-        qdebug!([self] "get_loss_detection_timer.");
+    pub fn get_timer(&mut self) -> LossRecoveryState {
+        qdebug!([self], "get_loss_detection_timer.");
 
         let has_ack_eliciting_out = self
             .spaces
             .iter()
             .flat_map(|spc| spc.sent_packets.values())
             .any(|sp| sp.ack_eliciting);
 
-        qdebug!(
-            [self]
-            "has_ack_eliciting_out={}",
-            has_ack_eliciting_out,
-        );
+        qdebug!([self], "has_ack_eliciting_out={}", has_ack_eliciting_out,);
 
-        if !has_ack_eliciting_out && *conn_state == State::Connected {
+        if !has_ack_eliciting_out {
             return LossRecoveryState::new(LossRecoveryMode::None, None);
         }
 
-        qinfo!([self]
+        qinfo!(
+            [self],
             "sent packets {} {} {}",
             self.spaces[PNSpace::Initial].sent_packets.len(),
             self.spaces[PNSpace::Handshake].sent_packets.len(),
             self.spaces[PNSpace::ApplicationData].sent_packets.len()
         );
 
         // QUIC only has one timer, but it does double duty because it falls
         // back to other uses if first use is not needed: first the loss
@@ -473,17 +476,22 @@ impl LossRecovery {
             let timeout = self.rtt_vals.pto() * 2_u32.pow(self.pto_count);
             (
                 LossRecoveryMode::PTO,
                 self.time_of_last_sent_ack_eliciting_packet
                     .map(|i| i + timeout),
             )
         };
 
-        qdebug!([self] "loss_detection_timer mode={:?} timer={:?}", mode, maybe_timer);
+        qdebug!(
+            [self],
+            "loss_detection_timer mode={:?} timer={:?}",
+            mode,
+            maybe_timer
+        );
         LossRecoveryState::new(mode, maybe_timer)
     }
 
     /// Find when the earliest sent packet should be considered lost.
     pub fn get_earliest_loss_time(&self) -> Option<(PNSpace, Instant)> {
         if !self.enable_timed_loss_detection {
             return None;
         }
@@ -738,17 +746,17 @@ mod tests {
             ACK_DELAY,
             pn_time(2) + INITIAL_RTT,
         );
         assert!(lost.is_empty());
         let pn1_sent_time = pn_time(1);
         assert_sent_times(&lr, None, None, Some(pn1_sent_time));
 
         // After time elapses, pn 1 is marked lost.
-        let lr_state = lr.get_timer(&State::Connected);
+        let lr_state = lr.get_timer();
         let pn1_lost_time = pn1_sent_time + (INITIAL_RTT * 9 / 8);
         assert_eq!(lr_state.callback_time, Some(pn1_lost_time));
         match lr_state.mode {
             LossRecoveryMode::LostPackets => {
                 let packets = lr.detect_lost_packets(PNSpace::ApplicationData, pn1_lost_time);
 
                 assert_eq!(packets.len(), 1)
             }
--- a/third_party/rust/neqo-transport/src/recv_stream.rs
+++ b/third_party/rust/neqo-transport/src/recv_stream.rs
@@ -16,17 +16,17 @@ use std::ops::Bound::{Included, Unbounde
 use std::rc::Rc;
 
 use smallvec::SmallVec;
 
 use crate::events::ConnectionEvents;
 use crate::flow_mgr::FlowMgr;
 use crate::stream_id::StreamId;
 use crate::{AppError, Error, Res};
-use neqo_common::qtrace;
+use neqo_common::{matches, qtrace};
 
 pub const RX_STREAM_DATA_WINDOW: u64 = 0xFFFF; // 64 KiB
 
 pub(crate) type RecvStreams = BTreeMap<StreamId, RecvStream>;
 
 /// Holds data not yet read by application. Orders and dedupes data ranges
 /// from incoming STREAM frames.
 #[derive(Debug, Default, PartialEq)]
@@ -459,28 +459,25 @@ impl RecvStream {
                         .borrow_mut()
                         .max_stream_data(self.stream_id, maybe_new_max)
                 }
             }
         }
     }
 
     pub fn is_terminal(&self) -> bool {
-        match self.state {
-            RecvStreamState::ResetRecvd | RecvStreamState::DataRead => true,
-            _ => false,
-        }
+        matches!(
+            self.state,
+            RecvStreamState::ResetRecvd | RecvStreamState::DataRead
+        )
     }
 
     // App got all data but did not get the fin signal.
     fn needs_to_inform_app_about_fin(&self) -> bool {
-        match self.state {
-            RecvStreamState::DataRecvd { .. } => true,
-            _ => false,
-        }
+        matches!(self.state, RecvStreamState::DataRecvd { .. })
     }
 
     fn data_ready(&self) -> bool {
         self.state
             .recv_buf()
             .map_or(false, RxStreamOrderer::data_ready)
     }
 
@@ -746,10 +743,9 @@ mod tests {
         assert_eq!(rx_ord.buffered(), 15);
         assert_eq!(rx_ord.retired(), 2);
         // an old frame
         rx_ord.inbound_frame(0, vec![4; 2]).unwrap();
         assert_eq!(rx_ord.bytes_ready(), 9);
         assert_eq!(rx_ord.buffered(), 15);
         assert_eq!(rx_ord.retired(), 2);
     }
-
 }
--- a/third_party/rust/neqo-transport/src/send_stream.rs
+++ b/third_party/rust/neqo-transport/src/send_stream.rs
@@ -11,17 +11,17 @@ use std::cmp::{max, min};
 use std::collections::{hash_map::IterMut, BTreeMap, HashMap};
 use std::convert::{TryFrom, TryInto};
 use std::mem;
 use std::rc::Rc;
 
 use slice_deque::SliceDeque;
 use smallvec::SmallVec;
 
-use neqo_common::{matches, qerror, qinfo, qtrace, qwarn, Encoder};
+use neqo_common::{matches, qdebug, qerror, qinfo, qtrace, qwarn};
 
 use crate::events::ConnectionEvents;
 use crate::flow_mgr::FlowMgr;
 use crate::frame::{Frame, TxMode};
 use crate::recovery::RecoveryToken;
 use crate::stream_id::StreamId;
 use crate::{AppError, Error, Res};
 
@@ -294,30 +294,41 @@ impl TxBuffer {
         let can_buffer = min(TxBuffer::BUFFER_SIZE - self.buffered(), buf.len());
         if can_buffer > 0 {
             self.send_buf.extend(&buf[..can_buffer]);
             assert!(self.send_buf.len() <= TxBuffer::BUFFER_SIZE);
         }
         can_buffer
     }
 
-    pub fn next_bytes(&self, _mode: TxMode) -> Option<(u64, &[u8])> {
-        let (start, maybe_len) = self.ranges.first_unmarked_range();
+    pub fn next_bytes(&self, mode: TxMode) -> Option<(u64, &[u8])> {
+        match mode {
+            TxMode::Normal => {
+                let (start, maybe_len) = self.ranges.first_unmarked_range();
 
-        if start == self.retired + u64::try_from(self.buffered()).unwrap() {
-            return None;
-        }
+                if start == self.retired + u64::try_from(self.buffered()).unwrap() {
+                    return None;
+                }
 
-        let buff_off = usize::try_from(start - self.retired).unwrap();
-        match maybe_len {
-            Some(len) => Some((
-                start,
-                &self.send_buf[buff_off..buff_off + usize::try_from(len).unwrap()],
-            )),
-            None => Some((start, &self.send_buf[buff_off..])),
+                let buff_off = usize::try_from(start - self.retired).unwrap();
+                match maybe_len {
+                    Some(len) => Some((
+                        start,
+                        &self.send_buf[buff_off..buff_off + usize::try_from(len).unwrap()],
+                    )),
+                    None => Some((start, &self.send_buf[buff_off..])),
+                }
+            }
+            TxMode::Pto => {
+                if self.buffered() == 0 {
+                    None
+                } else {
+                    Some((self.retired, &self.send_buf))
+                }
+            }
         }
     }
 
     pub fn mark_as_sent(&mut self, offset: u64, len: usize) {
         self.ranges.mark_range(offset, len, RangeState::Sent)
     }
 
     pub fn mark_as_acked(&mut self, offset: u64, len: usize) {
@@ -601,20 +612,17 @@ impl SendStream {
                 qtrace!("Reset acked while in {} state?", self.state.name())
             }
             SendStreamState::ResetSent => self.state.transition(SendStreamState::ResetRecvd),
             SendStreamState::ResetRecvd => qtrace!("already in ResetRecvd state"),
         };
     }
 
     pub fn is_terminal(&self) -> bool {
-        match self.state {
-            SendStreamState::DataRecvd { .. } | SendStreamState::ResetRecvd => true,
-            _ => false,
-        }
+        matches!(self.state, SendStreamState::DataRecvd { .. } | SendStreamState::ResetRecvd)
     }
 
     pub fn send(&mut self, buf: &[u8]) -> Res<usize> {
         if buf.is_empty() {
             qerror!("zero-length send on stream {}", self.stream_id.as_u64());
             return Err(Error::InvalidInput);
         }
 
@@ -754,40 +762,32 @@ impl SendStreams {
         mode: TxMode,
         remaining: usize,
     ) -> Option<(Frame, Option<RecoveryToken>)> {
         if epoch != 3 && epoch != 1 {
             return None;
         }
 
         for (stream_id, stream) in self {
-            let fin = stream.final_size();
+            let complete = stream.final_size().is_some();
             if let Some((offset, data)) = stream.next_bytes(mode) {
-                qtrace!(
-                    "Stream {} sending bytes {}-{}, epoch {}, mode {:?}, remaining {}",
+                let (frame, length) =
+                    Frame::new_stream(stream_id.as_u64(), offset, data, complete, remaining);
+                qdebug!(
+                    "Stream {} sending bytes {}-{}, epoch {}, mode {:?}",
                     stream_id.as_u64(),
                     offset,
-                    offset + data.len() as u64,
+                    offset + length as u64,
                     epoch,
                     mode,
-                    remaining
                 );
-                let frame_hdr_len = stream_frame_hdr_len(*stream_id, offset, remaining);
-                let length = min(data.len(), remaining - frame_hdr_len);
-                let fin = match fin {
-                    None => false,
-                    Some(fin) => fin == offset + length as u64,
-                };
-                let frame = Frame::Stream {
-                    fin,
-                    stream_id: stream_id.as_u64(),
-                    offset,
-                    data: data[..length].to_vec(),
-                };
+                let fin = complete && length == data.len();
+                debug_assert!(!fin || matches!(frame, Frame::Stream{fin: true, .. }));
                 stream.mark_as_sent(offset, length, fin);
+
                 return Some((
                     frame,
                     Some(RecoveryToken::Stream(StreamRecoveryToken {
                         id: *stream_id,
                         offset,
                         length,
                         fin,
                     })),
@@ -802,28 +802,16 @@ impl<'a> IntoIterator for &'a mut SendSt
     type Item = (&'a StreamId, &'a mut SendStream);
     type IntoIter = IterMut<'a, StreamId, SendStream>;
 
     fn into_iter(self) -> IterMut<'a, StreamId, SendStream> {
         self.0.iter_mut()
     }
 }
 
-/// Calculate the frame header size so we know how much data we can fit
-fn stream_frame_hdr_len(stream_id: StreamId, offset: u64, remaining: usize) -> usize {
-    let mut hdr_len = 1; // for frame type
-    hdr_len += Encoder::varint_len(stream_id.as_u64());
-    if offset > 0 {
-        hdr_len += Encoder::varint_len(offset);
-    }
-
-    // We always include a length field.
-    hdr_len + Encoder::varint_len(remaining as u64)
-}
-
 #[derive(Debug, Clone)]
 pub struct StreamRecoveryToken {
     pub(crate) id: StreamId,
     offset: u64,
     length: usize,
     fin: bool,
 }
 
@@ -877,16 +865,25 @@ mod tests {
         rt.mark_range(5, 5, RangeState::Acked);
         rt.mark_range(10, 5, RangeState::Sent);
 
         // Should unmark sent but not acked range
         rt.unmark_range(7, 6);
 
         let res = rt.first_unmarked_range();
         assert_eq!(res, (0, Some(5)));
+        assert_eq!(
+            rt.used.iter().nth(0).unwrap(),
+            (&5, &(5, RangeState::Acked))
+        );
+        assert_eq!(
+            rt.used.iter().nth(1).unwrap(),
+            (&13, &(2, RangeState::Sent))
+        );
+        assert!(rt.used.iter().nth(2).is_none());
         rt.mark_range(0, 5, RangeState::Sent);
 
         let res = rt.first_unmarked_range();
         assert_eq!(res, (10, Some(3)));
         rt.mark_range(10, 3, RangeState::Sent);
 
         let res = rt.first_unmarked_range();
         assert_eq!(res, (15, None));
--- a/third_party/rust/neqo-transport/src/server.rs
+++ b/third_party/rust/neqo-transport/src/server.rs
@@ -43,17 +43,17 @@ const MIN_INITIAL_PACKET_SIZE: usize = 1
 const TIMER_GRANULARITY: Duration = Duration::from_millis(10);
 const TIMER_CAPACITY: usize = 16384;
 
 type StateRef = Rc<RefCell<ServerConnectionState>>;
 type CidMgr = Rc<RefCell<dyn ConnectionIdManager>>;
 type ConnectionTableRef = Rc<RefCell<HashMap<ConnectionId, StateRef>>>;
 
 #[derive(Debug)]
-struct ServerConnectionState {
+pub struct ServerConnectionState {
     c: Connection,
     last_timer: Instant,
 }
 
 impl Deref for ServerConnectionState {
     type Target = Connection;
     fn deref(&self) -> &Self::Target {
         &self.c
@@ -259,38 +259,38 @@ impl Server {
     }
 
     fn process_connection(
         &mut self,
         c: StateRef,
         dgram: Option<Datagram>,
         now: Instant,
     ) -> Option<Datagram> {
-        qtrace!([self] "Process connection {:?}", c);
+        qtrace!([self], "Process connection {:?}", c);
         let out = c.borrow_mut().process(dgram, now);
         match out {
             Output::Datagram(_) => {
-                qtrace!([self] "Sending packet, added to waiting connections");
+                qtrace!([self], "Sending packet, added to waiting connections");
                 self.waiting.push_back(c.clone());
             }
             Output::Callback(delay) => {
                 let next = now + delay;
                 if next != c.borrow().last_timer {
-                    qtrace!([self] "Change timer to {:?}", next);
+                    qtrace!([self], "Change timer to {:?}", next);
                     self.remove_timer(&c);
                     c.borrow_mut().last_timer = next;
                     self.timers.add(next, c.clone());
                 }
             }
             _ => {
                 self.remove_timer(&c);
             }
         }
         if c.borrow().has_events() {
-            qtrace!([self] "Connection active: {:?}", c);
+            qtrace!([self], "Connection active: {:?}", c);
             self.active.insert(ActiveConnectionRef { c: c.clone() });
         }
         if matches!(c.borrow().state(), State::Closed(_)) {
             self.connections
                 .borrow_mut()
                 .retain(|_, v| !Rc::ptr_eq(v, &c));
         }
         out.dgram()
@@ -310,17 +310,17 @@ impl Server {
         dgram: Datagram,
         now: Instant,
     ) -> Option<Datagram> {
         match self.retry.validate(&hdr, dgram.source(), now) {
             RetryTokenResult::Invalid => None,
             RetryTokenResult::Pass => self.accept_connection(None, dgram, now),
             RetryTokenResult::Valid(dcid) => self.accept_connection(Some(dcid), dgram, now),
             RetryTokenResult::Validate => {
-                qinfo!([self] "Send retry for {:?}", hdr.dcid);
+                qinfo!([self], "Send retry for {:?}", hdr.dcid);
 
                 let res = self.retry.generate_token(&hdr.dcid, dgram.source(), now);
                 let token = if let Ok(t) = res {
                     t
                 } else {
                     qerror!([self], "unable to generate token, dropping packet");
                     return None;
                 };
@@ -343,17 +343,17 @@ impl Server {
     }
 
     fn accept_connection(
         &mut self,
         odcid: Option<ConnectionId>,
         dgram: Datagram,
         now: Instant,
     ) -> Option<Datagram> {
-        qinfo!([self] "Accept connection");
+        qinfo!([self], "Accept connection");
         // The internal connection ID manager that we use is not used directly.
         // Instead, wrap it so that we can save connection IDs.
         let cid_mgr = Rc::new(RefCell::new(ServerConnectionIdManager {
             c: None,
             cid_manager: self.cid_manager.clone(),
             connections: self.connections.clone(),
         }));
         let sconn = Connection::new_server(
@@ -365,68 +365,68 @@ impl Server {
         if let Ok(mut c) = sconn {
             if let Some(odcid) = odcid {
                 c.original_connection_id(&odcid);
             }
             let c = Rc::new(RefCell::new(ServerConnectionState { c, last_timer: now }));
             cid_mgr.borrow_mut().c = Some(c.clone());
             self.process_connection(c, Some(dgram), now)
         } else {
-            qwarn!([self] "Unable to create connection");
+            qwarn!([self], "Unable to create connection");
             None
         }
     }
 
     fn process_input(&mut self, dgram: Datagram, now: Instant) -> Option<Datagram> {
         qtrace!("Process datagram: {}", hex(&dgram[..]));
 
         // This is only looking at the first packet header in the datagram.
         // All packets in the datagram are routed to the same connection.
         let res = decode_packet_hdr(self.cid_manager.borrow().as_decoder(), &dgram[..]);
         let hdr = match res {
             Ok(h) => h,
             _ => {
-                qtrace!([self] "Discarding {:?}", dgram);
+                qtrace!([self], "Discarding {:?}", dgram);
                 return None;
             }
         };
 
         // Finding an existing connection. Should be the most common case.
         if let Some(c) = self.connection(&hdr.dcid) {
             return self.process_connection(c, Some(dgram), now);
         }
 
         if hdr.tipe == PacketType::Short {
             // TODO send a stateless reset here.
-            qtrace!([self] "Short header packet for an unknown connection");
+            qtrace!([self], "Short header packet for an unknown connection");
             return None;
         }
 
         if dgram.len() < MIN_INITIAL_PACKET_SIZE {
-            qtrace!([self] "Bogus packet: too short");
+            qtrace!([self], "Bogus packet: too short");
             return None;
         }
 
         if hdr.version != Some(self.version) {
             return Some(self.create_vn(&hdr, dgram));
         }
 
         self.handle_initial(hdr, dgram, now)
     }
 
     /// Iterate through the pending connections looking for any that might want
     /// to send a datagram.  Stop at the first one that does.
     fn process_next_output(&mut self, now: Instant) -> Option<Datagram> {
-        qtrace!([self] "No packet to send, look at waiting connections");
+        qtrace!([self], "No packet to send, look at waiting connections");
         while let Some(c) = self.waiting.pop_front() {
             if let Some(d) = self.process_connection(c, None, now) {
                 return Some(d);
             }
         }
-        qtrace!([self] "No packet to send still, run timers");
+        qtrace!([self], "No packet to send still, run timers");
         while let Some(c) = self.timers.take_next(now) {
             if let Some(d) = self.process_connection(c, None, now) {
                 return Some(d);
             }
         }
         None
     }
 
@@ -442,68 +442,77 @@ impl Server {
         let out = if let Some(d) = dgram {
             self.process_input(d, now)
         } else {
             None
         };
         let out = out.or_else(|| self.process_next_output(now));
         match out {
             Some(d) => {
-                qtrace!([self] "Send packet: {:?}", d);
+                qtrace!([self], "Send packet: {:?}", d);
                 Output::Datagram(d)
             }
             _ => match self.next_time(now) {
                 Some(delay) => {
-                    qtrace!([self] "Wait: {:?}", delay);
+                    qtrace!([self], "Wait: {:?}", delay);
                     Output::Callback(delay)
                 }
                 _ => {
-                    qtrace!([self] "Go dormant");
+                    qtrace!([self], "Go dormant");
                     Output::None
                 }
             },
         }
     }
 
     /// This lists the connections that have received new events
     /// as a result of calling `process()`.
     pub fn active_connections(&mut self) -> Vec<ActiveConnectionRef> {
         mem::replace(&mut self.active, Default::default())
             .into_iter()
             .collect()
     }
+
+    pub fn add_to_waiting(&mut self, c: ActiveConnectionRef) {
+        self.waiting.push_back(c.connection());
+    }
 }
 
 #[derive(Clone, Debug)]
 pub struct ActiveConnectionRef {
     c: StateRef,
 }
 
 impl ActiveConnectionRef {
     pub fn borrow<'a>(&'a self) -> impl Deref<Target = Connection> + 'a {
         std::cell::Ref::map(self.c.borrow(), |c| &c.c)
     }
 
     pub fn borrow_mut<'a>(&'a mut self) -> impl DerefMut<Target = Connection> + 'a {
         std::cell::RefMut::map(self.c.borrow_mut(), |c| &mut c.c)
     }
+
+    pub fn connection(&self) -> StateRef {
+        self.c.clone()
+    }
 }
 
 impl std::hash::Hash for ActiveConnectionRef {
     fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
         let ptr: *const _ = self.c.as_ref();
         ptr.hash(state)
     }
 }
 
 impl PartialEq for ActiveConnectionRef {
     fn eq(&self, other: &Self) -> bool {
         Rc::ptr_eq(&self.c, &other.c)
     }
 }
+
 impl Eq for ActiveConnectionRef {}
 
 struct ServerConnectionIdManager {
     c: Option<StateRef>,
     connections: ConnectionTableRef,
     cid_manager: CidMgr,
 }
 
--- a/third_party/rust/neqo-transport/src/tracking.rs
+++ b/third_party/rust/neqo-transport/src/tracking.rs
@@ -79,46 +79,46 @@ impl PacketRange {
         (pn >= self.smallest) && (pn <= self.largest)
     }
 
     /// Maybe add a packet number to the range.  Returns true if it was added.
     pub fn add(&mut self, pn: u64) -> bool {
         assert!(!self.contains(pn));
         // Only insert if this is adjacent the current range.
         if (self.largest + 1) == pn {
-            qtrace!([self] "Adding largest {}", pn);
+            qtrace!([self], "Adding largest {}", pn);
             self.largest += 1;
             self.ack_needed = true;
             true
         } else if self.smallest == (pn + 1) {
-            qtrace!([self] "Adding smallest {}", pn);
+            qtrace!([self], "Adding smallest {}", pn);
             self.smallest -= 1;
             self.ack_needed = true;
             true
         } else {
             false
         }
     }
 
     /// Maybe merge a lower-numbered range into this.
     pub fn merge_smaller(&mut self, other: &Self) {
-        qinfo!([self] "Merging {}", other);
+        qinfo!([self], "Merging {}", other);
         // This only works if they are immediately adjacent.
         assert_eq!(self.smallest - 1, other.largest);
 
         self.smallest = other.smallest;
         self.ack_needed = self.ack_needed || other.ack_needed;
     }
 
     /// When a packet containing the range `other` is acknowledged,
     /// clear the ack_needed attribute on this.
     /// Requires that other is equal to this, or a larger range.
     pub fn acknowledged(&mut self, other: &Self) {
         if (other.smallest <= self.smallest) && (other.largest >= self.largest) {
-            qinfo!([self] "Acknowledged");
+            qinfo!([self], "Acknowledged");
             self.ack_needed = false;
         }
     }
 }
 
 impl ::std::fmt::Display for PacketRange {
     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
         write!(f, "{}->{}", self.largest, self.smallest)
@@ -196,39 +196,44 @@ impl RecvdPackets {
             }
         }
         self.ranges.push_back(PacketRange::new(pn));
         self.ranges.len() - 1
     }
 
     /// Add the packet to the tracked set.
     pub fn set_received(&mut self, now: Instant, pn: u64, ack_eliciting: bool) {
+        let next_in_order_pn = self.ranges.get(0).map(|pr| pr.largest + 1).unwrap_or(0);
+        qdebug!("next in order pn: {}", next_in_order_pn);
         let i = self.add(pn);
 
         // The new addition was the largest, so update the time we use for calculating ACK delay.
         if i == 0 && pn == self.ranges[0].largest {
             self.largest_pn_time = Some(now);
         }
 
         // Limit the number of ranges that are tracked to MAX_TRACKED_RANGES.
         if self.ranges.len() > MAX_TRACKED_RANGES {
             let oldest = self.ranges.pop_back().unwrap();
             if oldest.ack_needed {
-                qwarn!([self] "Dropping unacknowledged ACK range: {}", oldest);
+                qwarn!([self], "Dropping unacknowledged ACK range: {}", oldest);
             // TODO(mt) Record some statistics about this so we can tune MAX_TRACKED_RANGES.
             } else {
-                qdebug!([self] "Drop ACK range: {}", oldest);
+                qdebug!([self], "Drop ACK range: {}", oldest);
             }
             self.min_tracked = oldest.largest + 1;
         }
 
         if ack_eliciting {
-            // On the first ack-eliciting packet since sending an ACK, set a delay.
-            // On the second, remove that delay.
-            if self.ack_time.is_none() && self.space == PNSpace::ApplicationData {
+            // Send ACK right away if out-of-order
+            // On the first in-order ack-eliciting packet since sending an ACK,
+            // set a delay. On the second, remove that delay.
+            if pn != next_in_order_pn {
+                self.ack_time = Some(now);
+            } else if self.ack_time.is_none() && self.space == PNSpace::ApplicationData {
                 self.ack_time = Some(now + ACK_DELAY);
             } else {
                 self.ack_time = Some(now);
             }
         }
     }
 
     /// Check if the packet is a duplicate.
@@ -503,16 +508,34 @@ mod tests {
             // Any packet will be acknowledged straight away.
             rp.set_received(now(), 0, true);
             assert_eq!(Some(now()), rp.ack_time());
             assert!(rp.ack_now(now()));
         }
     }
 
     #[test]
+    fn ooo_no_ack_delay() {
+        for space in &[
+            PNSpace::Initial,
+            PNSpace::Handshake,
+            PNSpace::ApplicationData,
+        ] {
+            let mut rp = RecvdPackets::new(*space);
+            assert!(rp.ack_time().is_none());
+            assert!(!rp.ack_now(now()));
+
+            // Any OoO packet will be acknowledged straight away.
+            rp.set_received(now(), 3, true);
+            assert_eq!(Some(now()), rp.ack_time());
+            assert!(rp.ack_now(now()));
+        }
+    }
+
+    #[test]
     fn aggregate_ack_time() {
         let mut tracker = AckTracker::default();
         // This packet won't trigger an ACK.
         tracker[PNSpace::Handshake].set_received(now(), 0, false);
         assert_eq!(None, tracker.ack_time());
 
         // This should be delayed.
         tracker[PNSpace::ApplicationData].set_received(now(), 0, true);