@@ -22,6 +22,7 @@ use s2n_quic_core::{
2222} ;
2323use std:: {
2424 fmt,
25+ hash:: { BuildHasherDefault , Hasher } ,
2526 net:: { Ipv4Addr , SocketAddr } ,
2627 sync:: {
2728 atomic:: { AtomicBool , AtomicU64 , AtomicUsize , Ordering } ,
@@ -51,6 +52,24 @@ pub struct Map {
5152 pub ( super ) state : Arc < State > ,
5253}
5354
55+ #[ derive( Default ) ]
56+ pub ( super ) struct NoopIdHasher ( Option < u64 > ) ;
57+
58+ impl Hasher for NoopIdHasher {
59+ fn finish ( & self ) -> u64 {
60+ self . 0 . unwrap ( )
61+ }
62+
63+ fn write ( & mut self , _bytes : & [ u8 ] ) {
64+ unimplemented ! ( )
65+ }
66+
67+ fn write_u64 ( & mut self , x : u64 ) {
68+ debug_assert ! ( self . 0 . is_none( ) ) ;
69+ self . 0 = Some ( x) ;
70+ }
71+ }
72+
5473// # Managing memory consumption
5574//
5675// For regular rotation with live peers, we retain at most two secrets: one derived from the most
@@ -93,7 +112,7 @@ pub(super) struct State {
93112 pub ( super ) requested_handshakes : flurry:: HashSet < SocketAddr > ,
94113
95114 // All known entries.
96- pub ( super ) ids : fixed_map:: Map < Id , Arc < Entry > > ,
115+ pub ( super ) ids : fixed_map:: Map < Id , Arc < Entry > , BuildHasherDefault < NoopIdHasher > > ,
97116
98117 pub ( super ) signer : stateless_reset:: Signer ,
99118
@@ -232,7 +251,7 @@ impl State {
232251}
233252
234253impl Map {
235- pub fn new ( signer : stateless_reset:: Signer ) -> Self {
254+ pub fn new ( signer : stateless_reset:: Signer , capacity : usize ) -> Self {
236255 // FIXME: Avoid unwrap and the whole socket.
237256 //
238257 // We only ever send on this socket - but we really should be sending on the same
@@ -244,11 +263,11 @@ impl Map {
244263 control_socket. set_nonblocking ( true ) . unwrap ( ) ;
245264 let state = State {
246265 // This is around 500MB with current entry size.
247- max_capacity : 500_000 ,
266+ max_capacity : capacity ,
248267 // FIXME: Allow configuring the rehandshake_period.
249268 rehandshake_period : Duration :: from_secs ( 3600 * 24 ) ,
250- peers : fixed_map:: Map :: with_capacity ( 500_000 , Default :: default ( ) ) ,
251- ids : fixed_map:: Map :: with_capacity ( 500_000 , Default :: default ( ) ) ,
269+ peers : fixed_map:: Map :: with_capacity ( capacity , Default :: default ( ) ) ,
270+ ids : fixed_map:: Map :: with_capacity ( capacity , Default :: default ( ) ) ,
252271 requested_handshakes : Default :: default ( ) ,
253272 cleaner : Cleaner :: new ( ) ,
254273 signer,
@@ -301,6 +320,19 @@ impl Map {
301320 Some ( ( sealer, credentials, state. parameters . clone ( ) ) )
302321 }
303322
323+ /// Retrieve a sealer by path secret ID.
324+ ///
325+ /// Generally callers should prefer to use one of the `pair` APIs; this is primarily useful for
326+ /// "response" datagrams which want to be bound to the exact same shared secret.
327+ ///
328+ /// Note that unlike by-IP lookup this should typically not be done significantly after the
329+ /// original secret was used for decryption.
330+ pub fn seal_once_id ( & self , id : Id ) -> Option < ( seal:: Once , Credentials , ApplicationParams ) > {
331+ let state = self . state . ids . get_by_key ( & id) ?;
332+ let ( sealer, credentials) = state. uni_sealer ( ) ;
333+ Some ( ( sealer, credentials, state. parameters . clone ( ) ) )
334+ }
335+
304336 pub fn open_once (
305337 & self ,
306338 credentials : & Credentials ,
@@ -485,7 +517,7 @@ impl Map {
485517 pub fn for_test_with_peers (
486518 peers : Vec < ( schedule:: Ciphersuite , dc:: Version , SocketAddr ) > ,
487519 ) -> ( Self , Vec < Id > ) {
488- let provider = Self :: new ( stateless_reset:: Signer :: random ( ) ) ;
520+ let provider = Self :: new ( stateless_reset:: Signer :: random ( ) , peers . len ( ) * 3 ) ;
489521 let mut secret = [ 0 ; 32 ] ;
490522 aws_lc_rs:: rand:: fill ( & mut secret) . unwrap ( ) ;
491523 let mut stateless_reset = [ 0 ; control:: TAG_LEN ] ;
0 commit comments