Skip to content

Commit

Permalink
preferred address
Browse files Browse the repository at this point in the history
  • Loading branch information
devsnek committed Apr 10, 2024
1 parent cc0d2e9 commit e59c381
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 23 deletions.
23 changes: 22 additions & 1 deletion quinn-proto/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
use std::{fmt, num::TryFromIntError, sync::Arc, time::Duration};
use std::{
fmt,
net::{SocketAddrV4, SocketAddrV6},
num::TryFromIntError,
sync::Arc,
time::Duration,
};

use thiserror::Error;

Expand Down Expand Up @@ -985,3 +991,18 @@ impl fmt::Debug for IdleTimeout {
self.0.fmt(f)
}
}

#[derive(Clone, Debug)]
pub struct AcceptConfig {
pub preferred_address_v4: Option<SocketAddrV4>,
pub preferred_address_v6: Option<SocketAddrV6>,
}

impl Default for AcceptConfig {
fn default() -> Self {
Self {
preferred_address_v4: None,
preferred_address_v6: None,
}
}
}
21 changes: 15 additions & 6 deletions quinn-proto/src/connection/cid_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,30 @@ pub(super) struct CidState {
}

impl CidState {
pub(crate) fn new(cid_len: usize, cid_lifetime: Option<Duration>, now: Instant) -> Self {
pub(crate) fn new(
cid_len: usize,
cid_lifetime: Option<Duration>,
now: Instant,
issued: u64,
) -> Self {
let mut active_seq = FxHashSet::default();
// Add sequence number of CID used in handshaking into tracking set
active_seq.insert(0);
// Add sequence number of CIDs used in handshaking into tracking set
for seq in 0..issued {
active_seq.insert(seq);
}
let mut this = Self {
retire_timestamp: VecDeque::new(),
issued: 1, // One CID is already supplied during handshaking
issued,
active_seq,
prev_retire_seq: 0,
retire_seq: 0,
cid_len,
cid_lifetime,
};
// Track lifetime of cid used in handshaking
this.track_lifetime(0, now);
// Track lifetime of CIDs used in handshaking
for seq in 0..issued {
this.track_lifetime(seq, now);
}
this
}

Expand Down
8 changes: 7 additions & 1 deletion quinn-proto/src/connection/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ impl Connection {
init_cid: ConnectionId,
loc_cid: ConnectionId,
rem_cid: ConnectionId,
pref_addr_cid: Option<ConnectionId>,
remote: SocketAddr,
local_ip: Option<IpAddr>,
crypto: Box<dyn crypto::Session>,
Expand Down Expand Up @@ -275,7 +276,12 @@ impl Connection {
crypto,
handshake_cid: loc_cid,
rem_handshake_cid: rem_cid,
local_cid_state: CidState::new(cid_gen.cid_len(), cid_gen.cid_lifetime(), now),
local_cid_state: CidState::new(
cid_gen.cid_len(),
cid_gen.cid_lifetime(),
now,
if pref_addr_cid.is_some() { 2 } else { 1 },
),
path: PathData::new(
remote,
config.initial_rtt,
Expand Down
40 changes: 35 additions & 5 deletions quinn-proto/src/endpoint.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{
collections::{hash_map, HashMap},
convert::TryFrom,
fmt, iter,
fmt,
net::{IpAddr, SocketAddr},
ops::{Index, IndexMut},
sync::Arc,
Expand All @@ -18,7 +18,7 @@ use tracing::{debug, error, trace, warn};
use crate::{
cid_generator::{ConnectionIdGenerator, RandomConnectionIdGenerator},
coding::BufMutExt,
config::{ClientConfig, EndpointConfig, ServerConfig},
config::{AcceptConfig, ClientConfig, EndpointConfig, ServerConfig},
connection::{Connection, ConnectionError},
crypto::{self, Keys, UnsupportedVersion},
frame,
Expand All @@ -30,7 +30,7 @@ use crate::{
ConnectionEvent, ConnectionEventInner, ConnectionId, EcnCodepoint, EndpointEvent,
EndpointEventInner, IssuedCid,
},
transport_parameters::TransportParameters,
transport_parameters::{PreferredAddress, TransportParameters},
ResetToken, RetryToken, Side, Transmit, TransportConfig, TransportError, INITIAL_MTU,
MAX_CID_SIZE, MIN_INITIAL_SIZE, RESET_TOKEN_SIZE,
};
Expand Down Expand Up @@ -390,6 +390,7 @@ impl Endpoint {
remote_id,
loc_cid,
remote_id,
None,
FourTuple {
remote,
local_ip: None,
Expand Down Expand Up @@ -506,6 +507,7 @@ impl Endpoint {
mut incoming: Incoming,
now: Instant,
buf: &mut BytesMut,
accept_config: AcceptConfig,
) -> Result<(ConnectionHandle, Connection), AcceptError> {
let packet_number = incoming.packet.header.number.expand(0);
let InitialHeader {
Expand Down Expand Up @@ -562,6 +564,19 @@ impl Endpoint {
params.stateless_reset_token = Some(ResetToken::new(&*self.config.reset_key, &loc_cid));
params.original_dst_cid = Some(incoming.orig_dst_cid);
params.retry_src_cid = incoming.retry_src_cid;
let mut pref_addr_cid = None;
if accept_config.preferred_address_v4.is_some()
|| accept_config.preferred_address_v6.is_some()
{
let cid = self.new_cid(ch);
pref_addr_cid = Some(cid);
params.preferred_address = Some(PreferredAddress {
address_v4: accept_config.preferred_address_v4,
address_v6: accept_config.preferred_address_v6,
connection_id: cid,
stateless_reset_token: ResetToken::new(&*self.config.reset_key, &cid),
});
}

let tls = server_config.crypto.clone().start_session(version, &params);
let transport_config = server_config.transport.clone();
Expand All @@ -571,6 +586,7 @@ impl Endpoint {
dst_cid,
loc_cid,
src_cid,
pref_addr_cid,
incoming.addresses,
now,
tls,
Expand Down Expand Up @@ -718,6 +734,7 @@ impl Endpoint {
init_cid: ConnectionId,
loc_cid: ConnectionId,
rem_cid: ConnectionId,
pref_addr_cid: Option<ConnectionId>,
addresses: FourTuple,
now: Instant,
tls: Box<dyn crypto::Session>,
Expand All @@ -734,6 +751,7 @@ impl Endpoint {
init_cid,
loc_cid,
rem_cid,
pref_addr_cid,
addresses.remote,
addresses.local_ip,
tls,
Expand All @@ -745,10 +763,22 @@ impl Endpoint {
path_validated,
);

let mut cids_issued = 0;
let mut loc_cids = FxHashMap::default();

loc_cids.insert(cids_issued, loc_cid);

if let Some(cid) = pref_addr_cid {
// Spec: preferred address cid must have a sequence of 1.
cids_issued += 1;
debug_assert_eq!(cids_issued, 1);
loc_cids.insert(cids_issued, cid);
}

let id = self.connections.insert(ConnectionMeta {
init_cid,
cids_issued: 0,
loc_cids: iter::once((0, loc_cid)).collect(),
cids_issued,
loc_cids,
addresses,
reset_token: None,
});
Expand Down
4 changes: 2 additions & 2 deletions quinn-proto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ pub use crate::connection::{

mod config;
pub use config::{
AckFrequencyConfig, ClientConfig, ConfigError, EndpointConfig, IdleTimeout, MtuDiscoveryConfig,
ServerConfig, TransportConfig,
AcceptConfig, AckFrequencyConfig, ClientConfig, ConfigError, EndpointConfig, IdleTimeout,
MtuDiscoveryConfig, ServerConfig, TransportConfig,
};

pub mod crypto;
Expand Down
5 changes: 4 additions & 1 deletion quinn-proto/src/tests/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,10 @@ impl TestEndpoint {
now: Instant,
) -> Result<ConnectionHandle, ConnectionError> {
let mut buf = BytesMut::new();
match self.endpoint.accept(incoming, now, &mut buf) {
match self
.endpoint
.accept(incoming, now, &mut buf, Default::default())
{
Ok((ch, conn)) => {
self.connections.insert(ch, conn);
self.accepted = Some(Ok(ch));
Expand Down
2 changes: 1 addition & 1 deletion quinn-proto/src/transport_parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ mod test {
max_udp_payload_size: 1200u32.into(),
preferred_address: Some(PreferredAddress {
address_v4: Some(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 42)),
address_v6: None,
address_v6: Some(SocketAddrV6::new(Ipv6Addr::LOCALHOST, 24, 0, 0)),
connection_id: ConnectionId::new(&[0x42]),
stateless_reset_token: [0xab; RESET_TOKEN_SIZE].into(),
}),
Expand Down
12 changes: 8 additions & 4 deletions quinn/src/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ use crate::runtime::{default_runtime, AsyncUdpSocket, Runtime};
use bytes::{Bytes, BytesMut};
use pin_project_lite::pin_project;
use proto::{
self as proto, ClientConfig, ConnectError, ConnectionError, ConnectionHandle, DatagramEvent,
ServerConfig,
self as proto, AcceptConfig, ClientConfig, ConnectError, ConnectionError, ConnectionHandle,
DatagramEvent, ServerConfig,
};
use rustc_hash::FxHashMap;
use tokio::sync::{futures::Notified, mpsc, Notify};
Expand Down Expand Up @@ -359,12 +359,16 @@ pub(crate) struct EndpointInner {
}

impl EndpointInner {
pub(crate) fn accept(&self, incoming: proto::Incoming) -> Result<Connecting, ConnectionError> {
pub(crate) fn accept(
&self,
incoming: proto::Incoming,
config: AcceptConfig,
) -> Result<Connecting, ConnectionError> {
let mut state = self.state.lock().unwrap();
let mut response_buffer = BytesMut::new();
match state
.inner
.accept(incoming, Instant::now(), &mut response_buffer)
.accept(incoming, Instant::now(), &mut response_buffer, config)
{
Ok((handle, conn)) => {
let socket = state.socket.clone();
Expand Down
4 changes: 2 additions & 2 deletions quinn/src/incoming.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{
task::{Context, Poll},
};

use proto::ConnectionError;
use proto::{AcceptConfig, ConnectionError};
use thiserror::Error;

use crate::{
Expand All @@ -25,7 +25,7 @@ impl Incoming {
/// Attempt to accept this incoming connection (an error may still occur)
pub fn accept(mut self) -> Result<Connecting, ConnectionError> {
let state = self.0.take().unwrap();
state.endpoint.accept(state.inner)
state.endpoint.accept(state.inner, AcceptConfig::default())
}

/// Reject this incoming connection attempt
Expand Down

0 comments on commit e59c381

Please sign in to comment.