From b452b06c00cd7225e7ca67d277f7513ce77afd64 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 29 May 2018 09:12:35 +0200 Subject: [PATCH] Implement support for header-only negotiation packets --- src/conn_state.rs | 5 ++++ src/packet.rs | 62 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/src/conn_state.rs b/src/conn_state.rs index c6ffb7c89..0883fff03 100644 --- a/src/conn_state.rs +++ b/src/conn_state.rs @@ -208,6 +208,11 @@ where self.state ))); }, + Header::Negotiation { .. } => { + return Err(QuicError::General(format!( + "negotiation packet not handled by connections" + ))); + } }; if self.state != State::Start && dst_cid != self.local.cid { diff --git a/src/packet.rs b/src/packet.rs index 8f2fbc978..a505369e3 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -6,6 +6,8 @@ use crypto::PacketKey; use frame::Frame; use types::{ConnectionId, GENERATED_CID_LENGTH}; +use rand::{thread_rng, Rng}; + use std::io::Cursor; #[derive(Debug, PartialEq)] @@ -44,6 +46,7 @@ impl Packet { let mut in_out = &mut payload[..msg_len - header_len + tag_len]; key.encrypt(number, &header_buf, in_out, tag_len)? } + Header::Negotiation { .. } => header_len, }; if let Header::Long { len, .. } = self.header { @@ -97,6 +100,7 @@ impl<'a> PartialDecode<'a> { } payload } + Header::Negotiation { .. } => vec![], }; Ok(Packet { header, payload }) @@ -125,6 +129,11 @@ pub enum Header { dst_cid: ConnectionId, number: u32, }, + Negotiation { + dst_cid: ConnectionId, + src_cid: ConnectionId, + supported_versions: Vec, + }, } impl Header { @@ -132,6 +141,7 @@ impl Header { match *self { Header::Long { ptype, .. } => Some(ptype), Header::Short { .. } => None, + Header::Negotiation { .. } => None, } } @@ -139,20 +149,26 @@ impl Header { match *self { Header::Long { dst_cid, .. } => dst_cid, Header::Short { dst_cid, .. } => dst_cid, + Header::Negotiation { dst_cid, .. } => dst_cid, } } } impl BufLen for Header { fn buf_len(&self) -> usize { - match *self { + match self { Header::Long { dst_cid, src_cid, len, .. - } => 10 + (dst_cid.len as usize + src_cid.len as usize) + VarLen(len).buf_len(), + } => 10 + (dst_cid.len as usize + src_cid.len as usize) + VarLen(*len).buf_len(), Header::Short { ptype, dst_cid, .. } => 1 + (dst_cid.len as usize) + ptype.buf_len(), + Header::Negotiation { + dst_cid, + src_cid, + supported_versions, + } => 6 + (dst_cid.len as usize + src_cid.len as usize) + 4 * supported_versions.len(), } } } @@ -192,6 +208,20 @@ impl Codec for Header { ShortType::Four => buf.put_u32_be(number), } } + Header::Negotiation { + dst_cid, + src_cid, + ref supported_versions, + } => { + buf.put_u8(thread_rng().gen::() | 128); + buf.put_u32_be(0); + buf.put_u8((dst_cid.cil() << 4) | src_cid.cil()); + buf.put_slice(&dst_cid); + buf.put_slice(&src_cid); + for v in supported_versions { + buf.put_u32_be(*v); + } + } } } @@ -217,14 +247,26 @@ impl Codec for Header { }; buf.advance(used); - Ok(Header::Long { - ptype: LongType::from_byte(first ^ 128), - version, - dst_cid, - src_cid, - len: VarLen::decode(buf)?.0, - number: buf.get_u32_be(), - }) + if version == 0 { + let mut supported_versions = vec![]; + while buf.has_remaining() { + supported_versions.push(buf.get_u32_be()); + } + Ok(Header::Negotiation { + dst_cid, + src_cid, + supported_versions, + }) + } else { + Ok(Header::Long { + ptype: LongType::from_byte(first ^ 128), + version, + dst_cid, + src_cid, + len: VarLen::decode(buf)?.0, + number: buf.get_u32_be(), + }) + } } else { let key_phase = first & 0x40 == 0x40; let dst_cid = {