mirror of
https://github.com/n0-computer/noq.git
synced 2026-09-18 09:15:37 +00:00
Move SocketAddr normalization into Endpoint
This reduces the amount of conversion necessary.
This commit is contained in:
committed by
Dirkjan Ochtman
parent
6f5dd2dc4d
commit
0abbff72a9
@@ -1,5 +1,5 @@
|
||||
use std::collections::{hash_map, BTreeMap, HashMap, VecDeque};
|
||||
use std::net::SocketAddrV6;
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
use std::{cmp, io, mem};
|
||||
|
||||
@@ -37,7 +37,7 @@ pub struct Connection {
|
||||
loc_cids: HashMap<u64, ConnectionId>,
|
||||
rem_cid: ConnectionId,
|
||||
rem_cid_seq: u64,
|
||||
remote: SocketAddrV6,
|
||||
remote: SocketAddr,
|
||||
state: State,
|
||||
side: Side,
|
||||
mtu: u16,
|
||||
@@ -131,7 +131,7 @@ impl Connection {
|
||||
init_cid: ConnectionId,
|
||||
loc_cid: ConnectionId,
|
||||
rem_cid: ConnectionId,
|
||||
remote: SocketAddrV6,
|
||||
remote: SocketAddr,
|
||||
client_config: Option<ClientConfig>,
|
||||
tls: TlsSession,
|
||||
) -> Self {
|
||||
@@ -875,7 +875,7 @@ impl Connection {
|
||||
pub fn handle_decode(
|
||||
&mut self,
|
||||
now: u64,
|
||||
remote: SocketAddrV6,
|
||||
remote: SocketAddr,
|
||||
ecn: Option<EcnCodepoint>,
|
||||
partial_decode: PartialDecode,
|
||||
) -> Option<BytesMut> {
|
||||
@@ -2361,7 +2361,7 @@ impl Connection {
|
||||
self.rem_cid
|
||||
}
|
||||
|
||||
pub fn remote(&self) -> SocketAddrV6 {
|
||||
pub fn remote(&self) -> SocketAddr {
|
||||
self.remote
|
||||
}
|
||||
|
||||
@@ -2794,7 +2794,7 @@ const MAX_ACK_BLOCKS: usize = 64;
|
||||
#[derive(Debug)]
|
||||
pub enum Io {
|
||||
Transmit {
|
||||
destination: SocketAddrV6,
|
||||
destination: SocketAddr,
|
||||
/// Explicit congestion notification bits to set on the packet
|
||||
ecn: Option<EcnCodepoint>,
|
||||
packet: Box<[u8]>,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::net::SocketAddrV6;
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
@@ -429,7 +429,7 @@ impl TokenKey {
|
||||
|
||||
pub(crate) fn generate(
|
||||
&self,
|
||||
address: &SocketAddrV6,
|
||||
address: &SocketAddr,
|
||||
dst_cid: &ConnectionId,
|
||||
issued: SystemTime,
|
||||
) -> Vec<u8> {
|
||||
@@ -443,7 +443,10 @@ impl TokenKey {
|
||||
.unwrap_or(0),
|
||||
);
|
||||
let signature_pos = buf.len();
|
||||
buf.put_slice(&address.ip().octets());
|
||||
match address.ip() {
|
||||
IpAddr::V4(x) => buf.put_slice(&x.octets()),
|
||||
IpAddr::V6(x) => buf.put_slice(&x.octets()),
|
||||
}
|
||||
buf.write(address.port());
|
||||
let signature = hmac::sign(&self.inner, &buf);
|
||||
// No reason to actually encode the IP in the token, since we always have the remote addr for an incoming packet.
|
||||
@@ -454,7 +457,7 @@ impl TokenKey {
|
||||
|
||||
pub(crate) fn check(
|
||||
&self,
|
||||
address: &SocketAddrV6,
|
||||
address: &SocketAddr,
|
||||
data: &[u8],
|
||||
) -> Option<(ConnectionId, SystemTime)> {
|
||||
let mut reader = io::Cursor::new(data);
|
||||
@@ -471,7 +474,10 @@ impl TokenKey {
|
||||
|
||||
let mut buf = Vec::new();
|
||||
buf.put_slice(&data[0..signature_start]);
|
||||
buf.put_slice(&address.ip().octets());
|
||||
match address.ip() {
|
||||
IpAddr::V4(x) => buf.put_slice(&x.octets()),
|
||||
IpAddr::V6(x) => buf.put_slice(&x.octets()),
|
||||
}
|
||||
buf.write(address.port());
|
||||
|
||||
hmac::verify_with_own_key(&self.inner, &buf, &data[signature_start..]).ok()?;
|
||||
@@ -576,7 +582,7 @@ mod test {
|
||||
let mut key = [0; TokenKey::SIZE];
|
||||
rand::thread_rng().fill_bytes(&mut key);
|
||||
let key = TokenKey::new(&key);
|
||||
let addr = SocketAddrV6::new(Ipv6Addr::LOCALHOST, 4433, 0, 0);
|
||||
let addr = SocketAddr::new(Ipv6Addr::LOCALHOST.into(), 4433);
|
||||
let dst_cid = ConnectionId::random(&mut rand::thread_rng(), MAX_CID_SIZE);
|
||||
let issued = UNIX_EPOCH + Duration::new(42, 0); // Fractional seconds would be lost
|
||||
let token = key.generate(&addr, &dst_cid, issued);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::cmp;
|
||||
use std::collections::VecDeque;
|
||||
use std::net::SocketAddrV6;
|
||||
use std::net::{SocketAddr, SocketAddrV4};
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
@@ -39,7 +39,7 @@ pub struct Endpoint {
|
||||
incoming: VecDeque<ConnectionHandle>,
|
||||
connection_ids_initial: FnvHashMap<ConnectionId, ConnectionHandle>,
|
||||
connection_ids: FnvHashMap<ConnectionId, ConnectionHandle>,
|
||||
connection_remotes: FnvHashMap<SocketAddrV6, ConnectionHandle>,
|
||||
connection_remotes: FnvHashMap<SocketAddr, ConnectionHandle>,
|
||||
pub(crate) connections: Slab<Connection>,
|
||||
config: Arc<Config>,
|
||||
server_config: Option<ServerConfig>,
|
||||
@@ -138,10 +138,11 @@ impl Endpoint {
|
||||
pub fn handle(
|
||||
&mut self,
|
||||
now: u64,
|
||||
remote: SocketAddrV6,
|
||||
remote: SocketAddr,
|
||||
ecn: Option<EcnCodepoint>,
|
||||
mut data: BytesMut,
|
||||
) {
|
||||
let remote = normalize(remote);
|
||||
let datagram_len = data.len();
|
||||
while !data.is_empty() {
|
||||
match PartialDecode::new(data, self.config.local_cid_len) {
|
||||
@@ -210,7 +211,7 @@ impl Endpoint {
|
||||
fn handle_decode(
|
||||
&mut self,
|
||||
now: u64,
|
||||
remote: SocketAddrV6,
|
||||
remote: SocketAddr,
|
||||
ecn: Option<EcnCodepoint>,
|
||||
partial_decode: PartialDecode,
|
||||
datagram_len: usize,
|
||||
@@ -308,7 +309,7 @@ impl Endpoint {
|
||||
fn stateless_reset(
|
||||
&mut self,
|
||||
inciting_dgram_len: usize,
|
||||
remote: SocketAddrV6,
|
||||
remote: SocketAddr,
|
||||
dst_cid: &ConnectionId,
|
||||
) {
|
||||
/// Minimum amount of padding for the stateless reset to look like a short-header packet
|
||||
@@ -347,10 +348,11 @@ impl Endpoint {
|
||||
/// Initiate a connection
|
||||
pub fn connect(
|
||||
&mut self,
|
||||
remote: SocketAddrV6,
|
||||
remote: SocketAddr,
|
||||
config: &Arc<crypto::ClientConfig>,
|
||||
server_name: &str,
|
||||
) -> Result<ConnectionHandle, ConnectError> {
|
||||
let remote = normalize(remote);
|
||||
let remote_id = ConnectionId::random(&mut self.rng, MAX_CID_SIZE);
|
||||
trace!(self.log, "initial dcid"; "value" => %remote_id);
|
||||
let conn = self.add_connection(
|
||||
@@ -380,7 +382,7 @@ impl Endpoint {
|
||||
&mut self,
|
||||
initial_id: ConnectionId,
|
||||
remote_id: ConnectionId,
|
||||
remote: SocketAddrV6,
|
||||
remote: SocketAddr,
|
||||
opts: ConnectionOpts,
|
||||
) -> Result<ConnectionHandle, ConnectError> {
|
||||
let local_id = self.new_cid();
|
||||
@@ -431,7 +433,7 @@ impl Endpoint {
|
||||
fn handle_initial(
|
||||
&mut self,
|
||||
now: u64,
|
||||
remote: SocketAddrV6,
|
||||
remote: SocketAddr,
|
||||
ecn: Option<EcnCodepoint>,
|
||||
mut packet: Packet,
|
||||
crypto: &Crypto,
|
||||
@@ -927,7 +929,7 @@ impl From<ConnectionError> for Event {
|
||||
#[derive(Debug)]
|
||||
pub enum Io {
|
||||
Transmit {
|
||||
destination: SocketAddrV6,
|
||||
destination: SocketAddr,
|
||||
/// Explicit congestion notification bits to set on the packet
|
||||
ecn: Option<EcnCodepoint>,
|
||||
packet: Box<[u8]>,
|
||||
@@ -973,3 +975,15 @@ enum ConnectionOpts {
|
||||
Client(ClientConfig),
|
||||
Server { orig_dst_cid: Option<ConnectionId> },
|
||||
}
|
||||
|
||||
/// Convert IPv4-mapped IPv6 SocketAddrs into normal IPv4 addrs for consistent hashing/comparison
|
||||
fn normalize(x: SocketAddr) -> SocketAddr {
|
||||
if let SocketAddr::V6(x) = x {
|
||||
if let Some(ip) = x.ip().to_ipv4() {
|
||||
if x.ip().segments()[5] == 0xFFFF {
|
||||
return SocketAddr::V4(SocketAddrV4::new(ip, x.port()));
|
||||
}
|
||||
}
|
||||
}
|
||||
x
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::collections::VecDeque;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::net::{Ipv6Addr, SocketAddrV6, UdpSocket};
|
||||
use std::net::{Ipv6Addr, SocketAddr, UdpSocket};
|
||||
use std::ops::RangeFrom;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Duration;
|
||||
@@ -132,18 +132,13 @@ impl Pair {
|
||||
.unwrap();
|
||||
let client = Endpoint::new(log.new(o!("side" => "Client")), client_config, None).unwrap();
|
||||
|
||||
let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
|
||||
let server_addr = SocketAddrV6::new(
|
||||
localhost,
|
||||
let server_addr = SocketAddr::new(
|
||||
Ipv6Addr::LOCALHOST.into(),
|
||||
SERVER_PORTS.lock().unwrap().next().unwrap(),
|
||||
0,
|
||||
0,
|
||||
);
|
||||
let client_addr = SocketAddrV6::new(
|
||||
localhost,
|
||||
let client_addr = SocketAddr::new(
|
||||
Ipv6Addr::LOCALHOST.into(),
|
||||
CLIENT_PORTS.lock().unwrap().next().unwrap(),
|
||||
0,
|
||||
0,
|
||||
);
|
||||
Self {
|
||||
log,
|
||||
@@ -245,7 +240,7 @@ impl Pair {
|
||||
struct TestEndpoint {
|
||||
side: Side,
|
||||
endpoint: Endpoint,
|
||||
addr: SocketAddrV6,
|
||||
addr: SocketAddr,
|
||||
socket: Option<UdpSocket>,
|
||||
timers: [u64; 4],
|
||||
conn: Option<ConnectionHandle>,
|
||||
@@ -255,7 +250,7 @@ struct TestEndpoint {
|
||||
}
|
||||
|
||||
impl TestEndpoint {
|
||||
fn new(side: Side, endpoint: Endpoint, addr: SocketAddrV6) -> Self {
|
||||
fn new(side: Side, endpoint: Endpoint, addr: SocketAddr) -> Self {
|
||||
let socket = if env::var_os("SSLKEYLOGFILE").is_some() {
|
||||
let socket = UdpSocket::bind(addr).expect("failed to bind UDP socket");
|
||||
socket
|
||||
@@ -278,7 +273,7 @@ impl TestEndpoint {
|
||||
}
|
||||
}
|
||||
|
||||
fn drive(&mut self, log: &Logger, now: u64, remote: SocketAddrV6) {
|
||||
fn drive(&mut self, log: &Logger, now: u64, remote: SocketAddr) {
|
||||
if let Some(ref socket) = self.socket {
|
||||
loop {
|
||||
let mut buf = [0; 8192];
|
||||
|
||||
+6
-20
@@ -58,7 +58,7 @@ mod udp;
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{hash_map, VecDeque};
|
||||
use std::net::{SocketAddr, SocketAddrV6, ToSocketAddrs};
|
||||
use std::net::{SocketAddr, ToSocketAddrs};
|
||||
use std::rc::Rc;
|
||||
use std::str;
|
||||
use std::sync::Arc;
|
||||
@@ -119,7 +119,7 @@ struct EndpointInner {
|
||||
log: Logger,
|
||||
socket: UdpSocket,
|
||||
inner: quinn::Endpoint,
|
||||
outgoing: VecDeque<(SocketAddrV6, Option<quinn::EcnCodepoint>, Box<[u8]>)>,
|
||||
outgoing: VecDeque<(SocketAddr, Option<quinn::EcnCodepoint>, Box<[u8]>)>,
|
||||
epoch: Instant,
|
||||
pending: FnvHashMap<ConnectionHandle, Pending>,
|
||||
// TODO: Replace this with something custom that avoids using oneshots to cancel
|
||||
@@ -591,9 +591,7 @@ impl Endpoint {
|
||||
let (send, recv) = oneshot::channel();
|
||||
let handle = {
|
||||
let mut endpoint = self.inner.borrow_mut();
|
||||
let handle = endpoint
|
||||
.inner
|
||||
.connect(normalize(*addr), config, server_name)?;
|
||||
let handle = endpoint.inner.connect(*addr, config, server_name)?;
|
||||
endpoint.pending.insert(handle, Pending::new(Some(send)));
|
||||
handle
|
||||
};
|
||||
@@ -662,9 +660,7 @@ impl Future for Driver {
|
||||
loop {
|
||||
match endpoint.socket.poll_recv(&mut buf) {
|
||||
Ok(Async::Ready((n, addr, ecn))) => {
|
||||
endpoint
|
||||
.inner
|
||||
.handle(now, normalize(addr), ecn, (&buf[0..n]).into());
|
||||
endpoint.inner.handle(now, addr, ecn, (&buf[0..n]).into());
|
||||
}
|
||||
Ok(Async::NotReady) => {
|
||||
break;
|
||||
@@ -763,10 +759,7 @@ impl Future for Driver {
|
||||
while !endpoint.outgoing.is_empty() {
|
||||
{
|
||||
let (destination, ecn, packet) = endpoint.outgoing.front().unwrap();
|
||||
match endpoint
|
||||
.socket
|
||||
.poll_send(&(*destination).into(), *ecn, packet)
|
||||
{
|
||||
match endpoint.socket.poll_send(destination, *ecn, packet) {
|
||||
Ok(Async::Ready(_)) => {}
|
||||
Ok(Async::NotReady) => {
|
||||
blocked = true;
|
||||
@@ -792,7 +785,7 @@ impl Future for Driver {
|
||||
ecn,
|
||||
} => {
|
||||
if !blocked {
|
||||
match endpoint.socket.poll_send(&destination.into(), ecn, &packet) {
|
||||
match endpoint.socket.poll_send(&destination, ecn, &packet) {
|
||||
Ok(Async::Ready(_)) => {}
|
||||
Ok(Async::NotReady) => {
|
||||
blocked = true;
|
||||
@@ -933,13 +926,6 @@ fn micros_from(x: Duration) -> u64 {
|
||||
x.as_secs() * 1000 * 1000 + x.subsec_micros() as u64
|
||||
}
|
||||
|
||||
fn normalize(x: SocketAddr) -> SocketAddrV6 {
|
||||
match x {
|
||||
SocketAddr::V6(x) => x,
|
||||
SocketAddr::V4(x) => SocketAddrV6::new(x.ip().to_ipv6_mapped(), x.port(), 0, 0),
|
||||
}
|
||||
}
|
||||
|
||||
struct ConnectionInner {
|
||||
endpoint: Rc<RefCell<EndpointInner>>,
|
||||
conn: ConnectionHandle,
|
||||
|
||||
Reference in New Issue
Block a user