1use super::*;
28
29use smallvec::smallvec;
30
31use crate::recovery::Sent;
32
33const NO_PQ_CURVES: &str = "X25519:P-256:P-384";
40
41pub fn config_no_pq(version: u32) -> Result<Config> {
50 let mut config = Config::new(version)?;
51 config.set_curves_list(NO_PQ_CURVES)?;
52 Ok(config)
53}
54
55pub struct Pipe<F = DefaultBufFactory>
56where
57 F: BufFactory,
58{
59 pub client: Connection<F>,
60 pub server: Connection<F>,
61}
62
63impl Pipe {
64 pub fn default_config(cc_algorithm_name: &str) -> Result<Config> {
65 let mut config = Config::new(PROTOCOL_VERSION)?;
66 assert_eq!(config.set_cc_algorithm_name(cc_algorithm_name), Ok(()));
67 config.load_cert_chain_from_pem_file("examples/cert.crt")?;
68 config.load_priv_key_from_pem_file("examples/cert.key")?;
69 config.set_application_protos(&[b"proto1", b"proto2"])?;
70 config.set_initial_max_data(30);
71 config.set_initial_max_stream_data_bidi_local(15);
72 config.set_initial_max_stream_data_bidi_remote(15);
73 config.set_initial_max_stream_data_uni(10);
74 config.set_initial_max_streams_bidi(3);
75 config.set_initial_max_streams_uni(3);
76 config.set_max_idle_timeout(180_000);
77 config.verify_peer(false);
78 config.set_ack_delay_exponent(8);
79 Ok(config)
80 }
81
82 pub fn default_config_no_pq(cc_algorithm_name: &str) -> Result<Config> {
85 let mut config = Self::default_config(cc_algorithm_name)?;
86 config.set_curves_list(NO_PQ_CURVES)?;
87 Ok(config)
88 }
89
90 #[cfg(feature = "boringssl-boring-crate")]
91 pub fn default_tls_ctx_builder() -> boring::ssl::SslContextBuilder {
92 let mut ctx_builder =
93 boring::ssl::SslContextBuilder::new(boring::ssl::SslMethod::tls())
94 .unwrap();
95 ctx_builder
96 .set_certificate_chain_file("examples/cert.crt")
97 .unwrap();
98 ctx_builder
99 .set_private_key_file(
100 "examples/cert.key",
101 boring::ssl::SslFiletype::PEM,
102 )
103 .unwrap();
104
105 ctx_builder
106 }
107
108 pub fn client_addr() -> SocketAddr {
109 "127.0.0.1:1234".parse().unwrap()
110 }
111
112 pub fn server_addr() -> SocketAddr {
113 "127.0.0.1:4321".parse().unwrap()
114 }
115
116 pub fn new(cc_algorithm_name: &str) -> Result<Pipe> {
117 let mut config = Self::default_config(cc_algorithm_name)?;
118 Pipe::with_config(&mut config)
119 }
120
121 pub fn with_config(config: &mut Config) -> Result<Pipe> {
122 Pipe::<DefaultBufFactory>::with_config_and_buf(config)
123 }
124
125 pub fn with_config_and_scid_lengths(
126 config: &mut Config, client_scid_len: usize, server_scid_len: usize,
127 ) -> Result<Pipe> {
128 Pipe::<DefaultBufFactory>::with_config_and_scid_lengths_and_buf(
129 config,
130 client_scid_len,
131 server_scid_len,
132 )
133 }
134
135 pub fn with_client_config(client_config: &mut Config) -> Result<Pipe> {
136 Pipe::<DefaultBufFactory>::with_client_config_and_buf(client_config)
137 }
138
139 pub fn with_server_config(server_config: &mut Config) -> Result<Pipe> {
140 Pipe::<DefaultBufFactory>::with_server_config_and_buf(server_config)
141 }
142
143 pub fn with_client_and_server_config(
144 client_config: &mut Config, server_config: &mut Config,
145 ) -> Result<Pipe> {
146 Pipe::<DefaultBufFactory>::with_client_and_server_config_and_buf(
147 client_config,
148 server_config,
149 )
150 }
151}
152
153impl<F: BufFactory> Pipe<F> {
154 pub fn new_with_buf(cc_algorithm_name: &str) -> Result<Pipe<F>> {
155 let mut config = Pipe::default_config(cc_algorithm_name)?;
156 Pipe::with_config_and_buf(&mut config)
157 }
158
159 pub fn with_config_and_buf(config: &mut Config) -> Result<Pipe<F>> {
160 let mut client_scid = [0; 16];
161 rand::rand_bytes(&mut client_scid[..]);
162 let client_scid = ConnectionId::from_ref(&client_scid);
163 let client_addr = Pipe::client_addr();
164
165 let mut server_scid = [0; 16];
166 rand::rand_bytes(&mut server_scid[..]);
167 let server_scid = ConnectionId::from_ref(&server_scid);
168 let server_addr = Pipe::server_addr();
169
170 Ok(Pipe {
171 client: connect_with_buffer_factory(
172 Some("quic.tech"),
173 &client_scid,
174 client_addr,
175 server_addr,
176 config,
177 )?,
178 server: accept_with_buf_factory(
179 &server_scid,
180 None,
181 server_addr,
182 client_addr,
183 config,
184 )?,
185 })
186 }
187
188 pub fn with_config_and_scid_lengths_and_buf(
189 config: &mut Config, client_scid_len: usize, server_scid_len: usize,
190 ) -> Result<Pipe<F>> {
191 let mut client_scid = vec![0; client_scid_len];
192 rand::rand_bytes(&mut client_scid[..]);
193 let client_scid = ConnectionId::from_ref(&client_scid);
194 let client_addr = Pipe::client_addr();
195
196 let mut server_scid = vec![0; server_scid_len];
197 rand::rand_bytes(&mut server_scid[..]);
198 let server_scid = ConnectionId::from_ref(&server_scid);
199 let server_addr = Pipe::server_addr();
200
201 Ok(Pipe {
202 client: connect_with_buffer_factory(
203 Some("quic.tech"),
204 &client_scid,
205 client_addr,
206 server_addr,
207 config,
208 )?,
209 server: accept_with_buf_factory(
210 &server_scid,
211 None,
212 server_addr,
213 client_addr,
214 config,
215 )?,
216 })
217 }
218
219 pub fn with_client_config_and_buf(
220 client_config: &mut Config,
221 ) -> Result<Pipe<F>> {
222 let mut client_scid = [0; 16];
223 rand::rand_bytes(&mut client_scid[..]);
224 let client_scid = ConnectionId::from_ref(&client_scid);
225 let client_addr = Pipe::client_addr();
226
227 let mut server_scid = [0; 16];
228 rand::rand_bytes(&mut server_scid[..]);
229 let server_scid = ConnectionId::from_ref(&server_scid);
230 let server_addr = Pipe::server_addr();
231
232 let mut config = Config::new(PROTOCOL_VERSION)?;
233 config.load_cert_chain_from_pem_file("examples/cert.crt")?;
234 config.load_priv_key_from_pem_file("examples/cert.key")?;
235 config.set_application_protos(&[b"proto1", b"proto2"])?;
236 config.set_initial_max_data(30);
237 config.set_initial_max_stream_data_bidi_local(15);
238 config.set_initial_max_stream_data_bidi_remote(15);
239 config.set_initial_max_streams_bidi(3);
240 config.set_initial_max_streams_uni(3);
241 config.set_ack_delay_exponent(8);
242
243 Ok(Pipe {
244 client: connect_with_buffer_factory(
245 Some("quic.tech"),
246 &client_scid,
247 client_addr,
248 server_addr,
249 client_config,
250 )?,
251 server: accept_with_buf_factory(
252 &server_scid,
253 None,
254 server_addr,
255 client_addr,
256 &mut config,
257 )?,
258 })
259 }
260
261 pub fn with_server_config_and_buf(
262 server_config: &mut Config,
263 ) -> Result<Pipe<F>> {
264 let mut client_scid = [0; 16];
265 rand::rand_bytes(&mut client_scid[..]);
266 let client_scid = ConnectionId::from_ref(&client_scid);
267 let client_addr = Pipe::client_addr();
268
269 let mut server_scid = [0; 16];
270 rand::rand_bytes(&mut server_scid[..]);
271 let server_scid = ConnectionId::from_ref(&server_scid);
272 let server_addr = Pipe::server_addr();
273
274 let mut config = Config::new(PROTOCOL_VERSION)?;
275 config.set_application_protos(&[b"proto1", b"proto2"])?;
276 config.set_initial_max_data(30);
277 config.set_initial_max_stream_data_bidi_local(15);
278 config.set_initial_max_stream_data_bidi_remote(15);
279 config.set_initial_max_streams_bidi(3);
280 config.set_initial_max_streams_uni(3);
281 config.set_ack_delay_exponent(8);
282
283 Ok(Pipe {
284 client: connect_with_buffer_factory(
285 Some("quic.tech"),
286 &client_scid,
287 client_addr,
288 server_addr,
289 &mut config,
290 )?,
291 server: accept_with_buf_factory(
292 &server_scid,
293 None,
294 server_addr,
295 client_addr,
296 server_config,
297 )?,
298 })
299 }
300
301 pub fn with_client_and_server_config_and_buf(
302 client_config: &mut Config, server_config: &mut Config,
303 ) -> Result<Pipe<F>> {
304 let mut client_scid = [0; 16];
305 rand::rand_bytes(&mut client_scid[..]);
306 let client_scid = ConnectionId::from_ref(&client_scid);
307 let client_addr = Pipe::client_addr();
308
309 let mut server_scid = [0; 16];
310 rand::rand_bytes(&mut server_scid[..]);
311 let server_scid = ConnectionId::from_ref(&server_scid);
312 let server_addr = Pipe::server_addr();
313
314 Ok(Pipe {
315 client: connect_with_buffer_factory(
316 Some("quic.tech"),
317 &client_scid,
318 client_addr,
319 server_addr,
320 client_config,
321 )?,
322 server: accept_with_buf_factory(
323 &server_scid,
324 None,
325 server_addr,
326 client_addr,
327 server_config,
328 )?,
329 })
330 }
331
332 pub fn handshake(&mut self) -> Result<()> {
333 while !self.client.is_established() || !self.server.is_established() {
334 let flight = emit_flight(&mut self.client)?;
335 process_flight(&mut self.server, flight)?;
336
337 let flight = emit_flight(&mut self.server)?;
338 process_flight(&mut self.client, flight)?;
339 }
340
341 Ok(())
342 }
343
344 pub fn advance(&mut self) -> Result<()> {
345 let mut client_done = false;
346 let mut server_done = false;
347
348 while !client_done || !server_done {
349 match emit_flight(&mut self.client) {
350 Ok(flight) => process_flight(&mut self.server, flight)?,
351
352 Err(Error::Done) => client_done = true,
353
354 Err(e) => return Err(e),
355 };
356
357 match emit_flight(&mut self.server) {
358 Ok(flight) => process_flight(&mut self.client, flight)?,
359
360 Err(Error::Done) => server_done = true,
361
362 Err(e) => return Err(e),
363 };
364 }
365
366 Ok(())
367 }
368
369 pub fn client_recv(&mut self, buf: &mut [u8]) -> Result<usize> {
370 let server_path = &self.server.paths.get_active().unwrap();
371 let info = RecvInfo {
372 to: server_path.peer_addr(),
373 from: server_path.local_addr(),
374 };
375
376 self.client.recv(buf, info)
377 }
378
379 pub fn server_recv(&mut self, buf: &mut [u8]) -> Result<usize> {
380 let client_path = &self.client.paths.get_active().unwrap();
381 let info = RecvInfo {
382 to: client_path.peer_addr(),
383 from: client_path.local_addr(),
384 };
385
386 self.server.recv(buf, info)
387 }
388
389 pub fn send_pkt_to_server(
390 &mut self, pkt_type: Type, frames: &[frame::Frame], buf: &mut [u8],
391 ) -> Result<usize> {
392 let written = encode_pkt(&mut self.client, pkt_type, frames, buf)?;
393 recv_send(&mut self.server, buf, written)
394 }
395
396 pub fn client_update_key(&mut self) -> Result<()> {
397 let crypto_ctx = &mut self.client.crypto_ctx[packet::Epoch::Application];
398
399 let open_next = crypto_ctx
400 .crypto_open
401 .as_ref()
402 .unwrap()
403 .derive_next_packet_key()
404 .unwrap();
405
406 let seal_next = crypto_ctx
407 .crypto_seal
408 .as_ref()
409 .unwrap()
410 .derive_next_packet_key()?;
411
412 let open_prev = crypto_ctx.crypto_open.replace(open_next);
413 crypto_ctx.crypto_seal.replace(seal_next);
414
415 crypto_ctx.key_update = Some(packet::KeyUpdate {
416 crypto_open: open_prev.unwrap(),
417 pn_on_update: self.client.next_pkt_num,
418 update_acked: true,
419 timer: Instant::now(),
420 });
421
422 self.client.key_phase = !self.client.key_phase;
423
424 Ok(())
425 }
426}
427
428pub fn recv_send<F: BufFactory>(
429 conn: &mut Connection<F>, buf: &mut [u8], len: usize,
430) -> Result<usize> {
431 let active_path = conn.paths.get_active()?;
432 let info = RecvInfo {
433 to: active_path.local_addr(),
434 from: active_path.peer_addr(),
435 };
436
437 conn.recv(&mut buf[..len], info)?;
438
439 let mut off = 0;
440
441 match conn.send(&mut buf[off..]) {
442 Ok((write, _)) => off += write,
443
444 Err(Error::Done) => (),
445
446 Err(e) => return Err(e),
447 }
448
449 Ok(off)
450}
451
452pub fn process_flight<F: BufFactory>(
453 conn: &mut Connection<F>, flight: Vec<(Vec<u8>, SendInfo)>,
454) -> Result<()> {
455 for (mut pkt, si) in flight {
456 let info = RecvInfo {
457 to: si.to,
458 from: si.from,
459 };
460
461 conn.recv(&mut pkt, info)?;
462 }
463
464 Ok(())
465}
466
467pub fn emit_flight_with_max_buffer<F: BufFactory>(
468 conn: &mut Connection<F>, out_size: usize, from: Option<SocketAddr>,
469 to: Option<SocketAddr>,
470) -> Result<Vec<(Vec<u8>, SendInfo)>> {
471 let mut flight = Vec::new();
472
473 loop {
474 let mut out = vec![0u8; out_size];
475
476 let info = match conn.send_on_path(&mut out, from, to) {
477 Ok((written, info)) => {
478 out.truncate(written);
479 info
480 },
481
482 Err(Error::Done) => break,
483
484 Err(e) => return Err(e),
485 };
486
487 flight.push((out, info));
488 }
489
490 if flight.is_empty() {
491 return Err(Error::Done);
492 }
493
494 Ok(flight)
495}
496
497pub fn emit_flight_on_path<F: BufFactory>(
498 conn: &mut Connection<F>, from: Option<SocketAddr>, to: Option<SocketAddr>,
499) -> Result<Vec<(Vec<u8>, SendInfo)>> {
500 emit_flight_with_max_buffer(conn, 65535, from, to)
501}
502
503pub fn emit_flight<F: BufFactory>(
504 conn: &mut Connection<F>,
505) -> Result<Vec<(Vec<u8>, SendInfo)>> {
506 emit_flight_on_path(conn, None, None)
507}
508
509pub fn encode_pkt<F: BufFactory>(
510 conn: &mut Connection<F>, pkt_type: Type, frames: &[frame::Frame],
511 buf: &mut [u8],
512) -> Result<usize> {
513 let mut b = octets::OctetsMut::with_slice(buf);
514
515 let epoch = pkt_type.to_epoch()?;
516
517 let crypto_ctx = &mut conn.crypto_ctx[epoch];
518
519 let pn = conn.next_pkt_num;
520 let pn_len = 4;
521
522 let send_path = conn.paths.get_active()?;
523 let active_dcid_seq = send_path
524 .active_dcid_seq
525 .as_ref()
526 .ok_or(Error::InvalidState)?;
527 let active_scid_seq = send_path
528 .active_scid_seq
529 .as_ref()
530 .ok_or(Error::InvalidState)?;
531
532 let hdr = Header {
533 ty: pkt_type,
534 version: conn.version,
535 dcid: ConnectionId::from_ref(
536 conn.ids.get_dcid(*active_dcid_seq)?.cid.as_ref(),
537 ),
538 scid: ConnectionId::from_ref(
539 conn.ids.get_scid(*active_scid_seq)?.cid.as_ref(),
540 ),
541 pkt_num: pn,
542 pkt_num_len: pn_len,
543 token: conn.token.clone(),
544 versions: None,
545 key_phase: conn.key_phase,
546 };
547
548 hdr.to_bytes(&mut b)?;
549
550 let payload_len = frames.iter().fold(0, |acc, x| acc + x.wire_len());
551
552 if pkt_type != Type::Short {
553 let len = pn_len + payload_len + crypto_ctx.crypto_overhead().unwrap();
554 b.put_varint(len as u64)?;
555 }
556
557 b.put_u32(pn as u32)?;
560
561 let payload_offset = b.off();
562
563 for frame in frames {
564 frame.to_bytes(&mut b)?;
565 }
566
567 let aead = match crypto_ctx.crypto_seal {
568 Some(ref mut v) => v,
569 None => return Err(Error::InvalidState),
570 };
571
572 let written = packet::encrypt_pkt(
573 &mut b,
574 pn,
575 pn_len,
576 payload_len,
577 payload_offset,
578 None,
579 aead,
580 )?;
581
582 conn.next_pkt_num += 1;
583
584 Ok(written)
585}
586
587pub fn decode_pkt<F: BufFactory>(
588 conn: &mut Connection<F>, buf: &mut [u8],
589) -> Result<Vec<frame::Frame>> {
590 let mut b = octets::OctetsMut::with_slice(buf);
591
592 let mut hdr = Header::from_bytes(&mut b, conn.source_id().len()).unwrap();
593
594 let epoch = hdr.ty.to_epoch()?;
595
596 let aead = conn.crypto_ctx[epoch].crypto_open.as_ref().unwrap();
597
598 let payload_len = b.cap();
599
600 packet::decrypt_hdr(&mut b, &mut hdr, aead).unwrap();
601
602 let pn = packet::decode_pkt_num(
603 conn.pkt_num_spaces[epoch].largest_rx_pkt_num,
604 hdr.pkt_num,
605 hdr.pkt_num_len,
606 );
607
608 let mut payload =
609 packet::decrypt_pkt(&mut b, pn, hdr.pkt_num_len, payload_len, aead)
610 .unwrap();
611
612 let mut frames = Vec::new();
613
614 while payload.cap() > 0 {
615 let frame = frame::Frame::from_bytes(&mut payload, hdr.ty)?;
616 frames.push(frame);
617 }
618
619 Ok(frames)
620}
621
622pub fn create_cid_and_reset_token(
623 cid_len: usize,
624) -> (ConnectionId<'static>, u128) {
625 let mut cid = vec![0; cid_len];
626 rand::rand_bytes(&mut cid[..]);
627 let cid = ConnectionId::from(cid);
628
629 let mut reset_token = [0; 16];
630 rand::rand_bytes(&mut reset_token);
631 let reset_token = u128::from_be_bytes(reset_token);
632
633 (cid, reset_token)
634}
635
636pub fn helper_packet_sent(pkt_num: u64, now: Instant, size: usize) -> Sent {
637 Sent {
638 pkt_num,
639 frames: smallvec![],
640 time_sent: now,
641 time_acked: None,
642 time_lost: None,
643 size,
644 ack_eliciting: true,
645 in_flight: true,
646 delivered: 0,
647 delivered_time: now,
648 first_sent_time: now,
649 is_app_limited: false,
650 tx_in_flight: 0,
651 lost: 0,
652 has_data: true,
653 is_pmtud_probe: false,
654 }
655}
656
657pub fn stream_recv_discard<F: BufFactory>(
659 conn: &mut Connection<F>, discard: bool, stream_id: u64,
660) -> Result<(usize, bool)> {
661 let mut buf = [0; 65535];
662 if discard {
663 conn.stream_discard(stream_id, 65535)
664 } else {
665 conn.stream_recv(stream_id, &mut buf)
666 }
667}
668
669#[cfg(test)]
677pub fn trigger_ack_based_loss<F: BufFactory>(
678 sender: &mut Connection<F>, receiver: &mut Connection<F>,
679) {
680 let mut buf = [0; 65535];
681
682 let pkt_thresh = sender
684 .paths
685 .get_active()
686 .unwrap()
687 .recovery
688 .pkt_thresh()
689 .unwrap();
690
691 for _ in 0..pkt_thresh {
692 sender.send_ack_eliciting().unwrap();
693 let (len, _) = sender.send(&mut buf).unwrap();
694
695 let info = RecvInfo {
696 to: receiver.paths.get_active().unwrap().local_addr(),
697 from: receiver.paths.get_active().unwrap().peer_addr(),
698 };
699 receiver.recv(&mut buf[..len], info).unwrap();
700 }
701
702 let (ack_len, _) = receiver.send(&mut buf).unwrap();
704
705 let info = RecvInfo {
707 to: sender.paths.get_active().unwrap().local_addr(),
708 from: sender.paths.get_active().unwrap().peer_addr(),
709 };
710 sender.recv(&mut buf[..ack_len], info).unwrap();
711}