Move SocketAddr normalization into Endpoint

This reduces the amount of conversion necessary.
This commit is contained in:
Benjamin Saunders
2018-12-30 11:44:10 -08:00
committed by Dirkjan Ochtman
parent 6f5dd2dc4d
commit 0abbff72a9
5 changed files with 55 additions and 54 deletions
+6 -6
View File
@@ -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]>,
+12 -6
View File
@@ -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);
+23 -9
View File
@@ -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
}
+8 -13
View File
@@ -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
View File
@@ -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,