mirror of
https://github.com/n0-computer/noq.git
synced 2026-09-25 04:35:17 +00:00
Implement basic support for close frames
This commit is contained in:
+7
-1
@@ -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
@@ -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]);
|
||||
|
||||
|
||||
@@ -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 = "")]
|
||||
|
||||
Reference in New Issue
Block a user