Implement basic support for close frames

This commit is contained in:
Dirkjan Ochtman
2018-05-07 13:55:35 +02:00
parent 7c1026b507
commit 02a37af854
3 changed files with 76 additions and 4 deletions
+7 -1
View File
@@ -6,7 +6,7 @@ use std::ops::{Deref, DerefMut};
use super::{QuicError, QuicResult};
use codec::BufLen;
use crypto::{PacketKey, Secret};
use frame::{Ack, AckFrame, Frame, PaddingFrame, PathFrame, StreamFrame};
use frame::{Ack, AckFrame, CloseFrame, Frame, PaddingFrame, PathFrame, StreamFrame};
use packet::{Header, LongType, Packet, ShortType};
use tls;
use types::{ConnectionId, DRAFT_11, Side, GENERATED_CID_LENGTH};
@@ -203,6 +203,12 @@ where
Frame::PathChallenge(PathFrame(token)) => {
payload.push(Frame::PathResponse(PathFrame(token.clone())));
}
Frame::ApplicationClose(CloseFrame { code, ref reason }) => {
return Err(QuicError::ApplicationClose(code, reason.clone()));
}
Frame::ConnectionClose(CloseFrame { code, ref reason }) => {
return Err(QuicError::ConnectionClose(code, reason.clone()));
}
Frame::Ack(_) | Frame::Padding(_) | Frame::PathResponse(_) | Frame::Stream(_) => {}
}
}
+65 -3
View File
@@ -1,10 +1,14 @@
use bytes::{Buf, BufMut};
use bytes::{BigEndian, Buf, BufMut};
use codec::{BufLen, Codec, VarLen};
use std::str;
#[derive(Debug, PartialEq)]
pub enum Frame {
Ack(AckFrame),
ApplicationClose(CloseFrame),
ConnectionClose(CloseFrame),
Padding(PaddingFrame),
PathChallenge(PathFrame),
PathResponse(PathFrame),
@@ -15,6 +19,8 @@ impl BufLen for Frame {
fn buf_len(&self) -> usize {
match *self {
Frame::Ack(ref f) => f.buf_len(),
Frame::ApplicationClose(ref f) => 1 + f.buf_len(),
Frame::ConnectionClose(ref f) => 1 + f.buf_len(),
Frame::Padding(ref f) => f.buf_len(),
Frame::PathChallenge(ref f) => 1 + f.buf_len(),
Frame::PathResponse(ref f) => 1 + f.buf_len(),
@@ -27,6 +33,14 @@ impl Codec for Frame {
fn encode<T: BufMut>(&self, buf: &mut T) {
match *self {
Frame::Ack(ref f) => f.encode(buf),
Frame::ApplicationClose(ref f) => {
buf.put_u8(0x03);
f.encode(buf)
}
Frame::ConnectionClose(ref f) => {
buf.put_u8(0x02);
f.encode(buf)
}
Frame::Padding(ref f) => f.encode(buf),
Frame::PathChallenge(ref f) => {
buf.put_u8(0x0e);
@@ -43,9 +57,23 @@ impl Codec for Frame {
fn decode<T: Buf>(buf: &mut T) -> Self {
match buf.bytes()[0] {
v if v >= 0x10 => Frame::Stream(StreamFrame::decode(buf)),
0x02 => Frame::ConnectionClose({
buf.get_u8();
CloseFrame::decode(buf)
}),
0x03 => Frame::ApplicationClose({
buf.get_u8();
CloseFrame::decode(buf)
}),
0x0d => Frame::Ack(AckFrame::decode(buf)),
0x0e => Frame::PathChallenge(PathFrame::decode(buf)),
0x0f => Frame::PathResponse(PathFrame::decode(buf)),
0x0e => Frame::PathChallenge({
buf.get_u8();
PathFrame::decode(buf)
}),
0x0f => Frame::PathResponse({
buf.get_u8();
PathFrame::decode(buf)
}),
0 => Frame::Padding(PaddingFrame::decode(buf)),
v => panic!("unimplemented decoding for frame type {}", v),
}
@@ -182,6 +210,40 @@ impl Ack {
}
}
#[derive(Debug, PartialEq)]
pub struct CloseFrame {
pub(crate) code: u16,
pub(crate) reason: String,
}
impl BufLen for CloseFrame {
fn buf_len(&self) -> usize {
2 + VarLen(self.reason.len() as u64).buf_len() + self.reason.len()
}
}
impl Codec for CloseFrame {
fn encode<T: BufMut>(&self, buf: &mut T) {
buf.put_u16::<BigEndian>(self.code);
VarLen(self.reason.len() as u64).encode(buf);
buf.put_slice(self.reason.as_bytes());
}
fn decode<T: Buf>(buf: &mut T) -> Self {
let code = buf.get_u16::<BigEndian>();
let len = VarLen::decode(buf).0 as usize;
let reason = {
let bytes = buf.bytes();
str::from_utf8(&bytes[..len]).unwrap()
}.to_string();
buf.advance(len);
CloseFrame {
code,
reason,
}
}
}
#[derive(Debug, PartialEq)]
pub struct PathFrame(pub [u8; 8]);
+4
View File
@@ -33,6 +33,10 @@ pub enum QuicError {
AddrParse(#[cause] std::net::AddrParseError),
#[fail(display = "needed slice of size {}, found {}", _0, _1)]
AllocationError(usize, usize),
#[fail(display = "application close ({}): '{}'", _0, _1)]
ApplicationClose(u16, String),
#[fail(display = "connection close ({}): '{}'", _0, _1)]
ConnectionClose(u16, String),
#[fail(display = "")]
DecryptError,
#[fail(display = "")]