Skip to content

Commit

Permalink
limit custom settings
Browse files Browse the repository at this point in the history
  • Loading branch information
devsnek committed Dec 20, 2024
1 parent 1bdda76 commit d8058d2
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 6 deletions.
16 changes: 16 additions & 0 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ use crate::{FlowControl, PingPong, RecvStream, SendStream};

use bytes::{Buf, Bytes};
use http::{uri, HeaderMap, Method, Request, Response, Version};
use std::collections::BTreeSet;
use std::fmt;
use std::future::Future;
use std::pin::Pin;
Expand Down Expand Up @@ -343,6 +344,9 @@ pub struct Builder {
///
/// When this gets exceeded, we issue GOAWAYs.
local_max_error_reset_streams: Option<usize>,

/// Custom settings IDs to be tracked from the remote
allowed_custom_settings: BTreeSet<u16>,
}

#[derive(Debug)]
Expand Down Expand Up @@ -673,6 +677,7 @@ impl Builder {
settings: Default::default(),
stream_id: 1.into(),
local_max_error_reset_streams: Some(proto::DEFAULT_LOCAL_RESET_COUNT_MAX),
allowed_custom_settings: BTreeSet::new(),
}
}

Expand Down Expand Up @@ -879,6 +884,16 @@ impl Builder {
self
}

/// By default, unknown settings recieved from the remote will be ignored.
///
/// See [Section 6.5] in the HTTP/2 spec for more details.
///
/// [Section 6.5]: https://httpwg.org/specs/rfc7540.html#rfc.section.6.5
pub fn allow_custom_setting(&mut self, id: u16) -> &mut Self {
self.allowed_custom_settings.insert(id);
self
}

/// Sets the initial maximum of locally initiated (send) streams.
///
/// The initial settings will be overwritten by the remote peer when
Expand Down Expand Up @@ -1355,6 +1370,7 @@ where
remote_reset_stream_max: builder.pending_accept_reset_stream_max,
local_error_reset_streams_max: builder.local_max_error_reset_streams,
settings: builder.settings.clone(),
allowed_custom_settings: builder.allowed_custom_settings,
},
);
let send_request = SendRequest {
Expand Down
4 changes: 2 additions & 2 deletions src/frame/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ impl Settings {
}
}

pub fn custom_settings(&self) -> &BTreeMap<u16, u32> {
&self.custom
pub fn custom_setting(&self, id: u16) -> Option<u32> {
self.custom.get(&id).copied()
}

pub fn load(head: Head, payload: &[u8]) -> Result<Settings, Error> {
Expand Down
3 changes: 3 additions & 0 deletions src/proto/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::proto::*;

use bytes::Bytes;
use futures_core::Stream;
use std::collections::BTreeSet;
use std::io;
use std::marker::PhantomData;
use std::pin::Pin;
Expand Down Expand Up @@ -83,6 +84,7 @@ pub(crate) struct Config {
pub remote_reset_stream_max: usize,
pub local_error_reset_streams_max: Option<usize>,
pub settings: frame::Settings,
pub allowed_custom_settings: BTreeSet<u16>,
}

#[derive(Debug)]
Expand Down Expand Up @@ -123,6 +125,7 @@ where
.max_concurrent_streams()
.map(|max| max as usize),
local_max_error_reset_streams: config.local_error_reset_streams_max,
allowed_custom_settings: config.allowed_custom_settings.clone(),
}
}
let streams = Streams::new(streams_config(&config));
Expand Down
4 changes: 4 additions & 0 deletions src/proto/streams/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use crate::frame::{StreamId, StreamIdOverflow};
use crate::proto::*;

use bytes::Bytes;
use std::collections::BTreeSet;
use std::time::Duration;

#[derive(Debug)]
Expand Down Expand Up @@ -72,4 +73,7 @@ pub struct Config {
///
/// When this gets exceeded, we issue GOAWAYs.
pub local_max_error_reset_streams: Option<usize>,

/// Custom settings IDs to be tracked from the remote
pub allowed_custom_settings: BTreeSet<u16>,
}
12 changes: 9 additions & 3 deletions src/proto/streams/send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use bytes::Buf;
use tokio::io::AsyncWrite;

use std::cmp::Ordering;
use std::collections::BTreeMap;
use std::collections::{BTreeMap, BTreeSet};
use std::io;
use std::task::{Context, Poll, Waker};

Expand Down Expand Up @@ -42,6 +42,7 @@ pub(super) struct Send {

/// Custom settings
custom_settings: BTreeMap<u16, u32>,
allowed_custom_settings: BTreeSet<u16>,
}

/// A value to detect which public API has called `poll_reset`.
Expand All @@ -62,6 +63,7 @@ impl Send {
is_push_enabled: true,
is_extended_connect_protocol_enabled: false,
custom_settings: BTreeMap::new(),
allowed_custom_settings: config.allowed_custom_settings.clone(),
}
}

Expand Down Expand Up @@ -439,7 +441,11 @@ impl Send {
if let Some(val) = settings.is_extended_connect_protocol_enabled() {
self.is_extended_connect_protocol_enabled = val;
}
self.custom_settings.extend(settings.custom_settings());
for id in &self.allowed_custom_settings {
if let Some(val) = settings.custom_setting(*id) {
self.custom_settings.insert(*id, val);
}
}

// Applies an update to the remote endpoint's initial window size.
//
Expand Down Expand Up @@ -590,6 +596,6 @@ impl Send {
}

pub(crate) fn custom_setting(&self, id: u16) -> Option<u32> {
self.custom_settings.get(&id).map(|v| *v)
self.custom_settings.get(&id).copied()
}
}
17 changes: 16 additions & 1 deletion src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ use crate::{FlowControl, PingPong, RecvStream, SendStream};

use bytes::{Buf, Bytes};
use http::{HeaderMap, Method, Request, Response};
use std::collections::BTreeSet;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
Expand Down Expand Up @@ -258,6 +259,9 @@ pub struct Builder {
///
/// When this gets exceeded, we issue GOAWAYs.
local_max_error_reset_streams: Option<usize>,

/// Custom settings IDs to be tracked from the remote
allowed_custom_settings: BTreeSet<u16>,
}

/// Send a response back to the client
Expand Down Expand Up @@ -675,8 +679,8 @@ impl Builder {
settings: Settings::default(),
initial_target_connection_window_size: None,
max_send_buffer_size: proto::DEFAULT_MAX_SEND_BUFFER_SIZE,

local_max_error_reset_streams: Some(proto::DEFAULT_LOCAL_RESET_COUNT_MAX),
allowed_custom_settings: BTreeSet::new(),
}
}

Expand Down Expand Up @@ -1058,6 +1062,16 @@ impl Builder {
self
}

/// By default, unknown settings recieved from the remote will be ignored.
///
/// See [Section 6.5] in the HTTP/2 spec for more details.
///
/// [Section 6.5]: https://httpwg.org/specs/rfc7540.html#rfc.section.6.5
pub fn allow_custom_setting(&mut self, id: u16) -> &mut Self {
self.allowed_custom_settings.insert(id);
self
}

/// Creates a new configured HTTP/2 server backed by `io`.
///
/// It is expected that `io` already be in an appropriate state to commence
Expand Down Expand Up @@ -1420,6 +1434,7 @@ where
.builder
.local_max_error_reset_streams,
settings: self.builder.settings.clone(),
allowed_custom_settings: self.builder.allowed_custom_settings.clone(),
},
);

Expand Down

0 comments on commit d8058d2

Please sign in to comment.