1use std::sync::Arc;
2
3use bytes::{Buf, Bytes, BytesMut};
4
5use crate::draft13::endpoint::{Endpoint, EndpointError};
6use crate::draft13::event::{ClientEvent, Direction, FetchObject, StreamKind, SubgroupObject};
7use crate::draft13::observer::ConnectionObserver;
8use crate::transport::quic::QuicTransport;
9use crate::transport::{RecvStream, SendStream, Transport, TransportError};
10use moqtap_codec::dispatch::{
11 AnyControlMessage, AnyDatagramHeader, AnyFetchHeader, AnySubgroupHeader,
12};
13use moqtap_codec::draft13::data_stream::{FetchObjectHeader, ObjectHeader};
14use moqtap_codec::draft13::message::ControlMessage;
15use moqtap_codec::error::CodecError;
16use moqtap_codec::types::*;
17use moqtap_codec::varint::VarInt;
18use moqtap_codec::version::DraftVersion;
19
20pub const MOQT_ALPN: &[u8] = b"moq-00";
22
23#[derive(Debug, thiserror::Error)]
25pub enum ConnectionError {
26 #[error("endpoint error: {0}")]
28 Endpoint(#[from] EndpointError),
29 #[error("codec error: {0}")]
31 Codec(#[from] CodecError),
32 #[error("transport error: {0}")]
34 Transport(#[from] TransportError),
35 #[error("varint error: {0}")]
37 VarInt(#[from] moqtap_codec::varint::VarIntError),
38 #[error("control stream not open")]
40 NoControlStream,
41 #[error("unexpected end of stream")]
43 UnexpectedEnd,
44 #[error("stream finished")]
46 StreamFinished,
47 #[error("invalid server address: {0}")]
49 InvalidAddress(String),
50 #[error("TLS config error: {0}")]
52 TlsConfig(String),
53}
54
55#[derive(Debug, Clone)]
57pub enum TransportType {
58 Quic,
60 WebTransport {
62 url: String,
64 },
65}
66
67pub struct ClientConfig {
69 pub additional_versions: Vec<DraftVersion>,
72 pub transport: TransportType,
74 pub skip_cert_verification: bool,
76 pub ca_certs: Vec<Vec<u8>>,
78 pub setup_parameters: Vec<moqtap_codec::kvp::KeyValuePair>,
80}
81
82impl ClientConfig {
83 pub fn supported_versions(&self) -> Vec<VarInt> {
86 let mut versions = vec![DraftVersion::Draft13.version_varint()];
87 for v in &self.additional_versions {
88 let varint = v.version_varint();
89 if !versions.contains(&varint) {
90 versions.push(varint);
91 }
92 }
93 versions
94 }
95
96 pub fn alpn(&self) -> Vec<Vec<u8>> {
98 match &self.transport {
99 TransportType::Quic => vec![DraftVersion::Draft13.quic_alpn().to_vec()],
100 TransportType::WebTransport { .. } => vec![b"h3".to_vec()],
101 }
102 }
103}
104
105pub struct FramedSendStream {
107 inner: SendStream,
108}
109
110impl FramedSendStream {
111 pub fn new(inner: SendStream) -> Self {
113 Self { inner }
114 }
115
116 pub fn stream_id(&self) -> u64 {
118 self.inner.stream_id()
119 }
120
121 pub async fn write_control(
124 &mut self,
125 msg: &AnyControlMessage,
126 ) -> Result<Vec<u8>, ConnectionError> {
127 let mut buf = Vec::new();
128 msg.encode(&mut buf)?;
129 self.inner.write_all(&buf).await?;
130 Ok(buf)
131 }
132
133 pub async fn write_subgroup_header(
135 &mut self,
136 header: &AnySubgroupHeader,
137 ) -> Result<(), ConnectionError> {
138 let mut buf = Vec::new();
139 header.encode(&mut buf);
140 self.inner.write_all(&buf).await?;
141 Ok(())
142 }
143
144 pub async fn write_fetch_header(
146 &mut self,
147 header: &AnyFetchHeader,
148 ) -> Result<(), ConnectionError> {
149 let mut buf = Vec::new();
150 header.encode(&mut buf);
151 self.inner.write_all(&buf).await?;
152 Ok(())
153 }
154
155 pub async fn write_subgroup_object(
159 &mut self,
160 object: &SubgroupObject,
161 ) -> Result<(), ConnectionError> {
162 let mut buf = Vec::new();
163 object.header.encode(&mut buf);
164 buf.extend_from_slice(&object.payload);
165 self.inner.write_all(&buf).await?;
166 Ok(())
167 }
168
169 pub async fn write_fetch_object(
171 &mut self,
172 object: &FetchObject,
173 ) -> Result<(), ConnectionError> {
174 let mut buf = Vec::new();
175 object.header.encode(&mut buf);
176 buf.extend_from_slice(&object.payload);
177 self.inner.write_all(&buf).await?;
178 Ok(())
179 }
180
181 pub async fn finish(&mut self) -> Result<(), ConnectionError> {
183 self.inner.finish()?;
184 Ok(())
185 }
186}
187
188pub struct FramedRecvStream {
190 inner: RecvStream,
191 buf: BytesMut,
192}
193
194impl FramedRecvStream {
195 pub fn new(inner: RecvStream) -> Self {
197 Self { inner, buf: BytesMut::with_capacity(4096) }
198 }
199
200 pub fn stream_id(&self) -> u64 {
202 self.inner.stream_id()
203 }
204
205 async fn fill(&mut self) -> Result<bool, ConnectionError> {
207 let mut tmp = [0u8; 4096];
208 match self.inner.read(&mut tmp).await {
209 Ok(Some(n)) => {
210 self.buf.extend_from_slice(&tmp[..n]);
211 Ok(true)
212 }
213 Ok(None) => Ok(false),
214 Err(e) => Err(ConnectionError::Transport(e)),
215 }
216 }
217
218 async fn ensure(&mut self, n: usize) -> Result<(), ConnectionError> {
220 while self.buf.len() < n {
221 if !self.fill().await? {
222 return Err(ConnectionError::UnexpectedEnd);
223 }
224 }
225 Ok(())
226 }
227
228 pub async fn read_control(
234 &mut self,
235 capture_raw: bool,
236 ) -> Result<(AnyControlMessage, Option<Vec<u8>>), ConnectionError> {
237 self.ensure(1).await?;
239 let type_len = varint_len(self.buf[0]);
240 self.ensure(type_len).await?;
241
242 let mut cursor = &self.buf[..type_len];
243 let _type_id = VarInt::decode(&mut cursor)?;
244
245 let len_field_size = 2;
247 self.ensure(type_len + len_field_size).await?;
248 let payload_len = u16::from_be_bytes([self.buf[type_len], self.buf[type_len + 1]]) as usize;
249
250 let total = type_len + len_field_size + payload_len;
252 self.ensure(total).await?;
253
254 let raw = capture_raw.then(|| self.buf[..total].to_vec());
256
257 let mut frame = &self.buf[..total];
259 let msg = AnyControlMessage::decode(DraftVersion::Draft13, &mut frame)?;
260 self.buf.advance(total);
261 Ok((msg, raw))
262 }
263
264 pub async fn read_subgroup_header(&mut self) -> Result<AnySubgroupHeader, ConnectionError> {
266 self.ensure(1).await?;
267 loop {
268 let mut cursor = &self.buf[..];
269 match AnySubgroupHeader::decode(DraftVersion::Draft13, &mut cursor) {
270 Ok(header) => {
271 let consumed = self.buf.len() - cursor.remaining();
272 self.buf.advance(consumed);
273 return Ok(header);
274 }
275 Err(CodecError::UnexpectedEnd) => {
276 if !self.fill().await? {
277 return Err(ConnectionError::UnexpectedEnd);
278 }
279 }
280 Err(e) => return Err(ConnectionError::Codec(e)),
281 }
282 }
283 }
284
285 pub async fn read_fetch_header(&mut self) -> Result<AnyFetchHeader, ConnectionError> {
287 self.ensure(1).await?;
288 loop {
289 let mut cursor = &self.buf[..];
290 match AnyFetchHeader::decode(DraftVersion::Draft13, &mut cursor) {
291 Ok(header) => {
292 let consumed = self.buf.len() - cursor.remaining();
293 self.buf.advance(consumed);
294 return Ok(header);
295 }
296 Err(CodecError::UnexpectedEnd) => {
297 if !self.fill().await? {
298 return Err(ConnectionError::UnexpectedEnd);
299 }
300 }
301 Err(e) => return Err(ConnectionError::Codec(e)),
302 }
303 }
304 }
305
306 pub async fn read_subgroup_object(&mut self) -> Result<SubgroupObject, ConnectionError> {
310 loop {
311 let mut cursor = &self.buf[..];
312 match ObjectHeader::decode(&mut cursor) {
313 Ok(header) => {
314 let header_consumed = self.buf.len() - cursor.remaining();
315 let payload_len = header.payload_length.into_inner() as usize;
316 let total = header_consumed + payload_len;
317 if self.buf.len() < total {
318 if !self.fill().await? {
319 return Err(ConnectionError::UnexpectedEnd);
320 }
321 continue;
322 }
323 let payload = self.buf[header_consumed..total].to_vec();
324 self.buf.advance(total);
325 return Ok(SubgroupObject { header, payload });
326 }
327 Err(CodecError::UnexpectedEnd) => {
328 if !self.fill().await? {
329 return Err(ConnectionError::UnexpectedEnd);
330 }
331 }
332 Err(e) => return Err(ConnectionError::Codec(e)),
333 }
334 }
335 }
336
337 pub async fn read_fetch_object(&mut self) -> Result<FetchObject, ConnectionError> {
339 loop {
340 let mut cursor = &self.buf[..];
341 match FetchObjectHeader::decode(&mut cursor) {
342 Ok(header) => {
343 let header_consumed = self.buf.len() - cursor.remaining();
344 let payload_len = header.payload_length.into_inner() as usize;
345 let total = header_consumed + payload_len;
346 if self.buf.len() < total {
347 if !self.fill().await? {
348 return Err(ConnectionError::UnexpectedEnd);
349 }
350 continue;
351 }
352 let payload = self.buf[header_consumed..total].to_vec();
353 self.buf.advance(total);
354 return Ok(FetchObject { header, payload });
355 }
356 Err(CodecError::UnexpectedEnd) => {
357 if !self.fill().await? {
358 return Err(ConnectionError::UnexpectedEnd);
359 }
360 }
361 Err(e) => return Err(ConnectionError::Codec(e)),
362 }
363 }
364 }
365}
366
367pub struct Connection {
369 transport: Transport,
370 endpoint: Endpoint,
371 control_send: Option<FramedSendStream>,
372 control_recv: Option<FramedRecvStream>,
373 observer: Option<Box<dyn ConnectionObserver>>,
374}
375
376impl Connection {
377 pub async fn connect(addr: &str, config: ClientConfig) -> Result<Self, ConnectionError> {
379 let transport = match &config.transport {
380 TransportType::Quic => Self::connect_quic(addr, &config).await?,
381 TransportType::WebTransport { url } => {
382 let url = url.clone();
383 Self::connect_webtransport(&url, &config).await?
384 }
385 };
386
387 let (send, recv) = transport.open_bi().await?;
389 let mut control_send = FramedSendStream::new(send);
390 let mut control_recv = FramedRecvStream::new(recv);
391
392 let mut endpoint = Endpoint::new();
394 endpoint.connect()?;
395 let setup_msg = endpoint
396 .send_client_setup(config.supported_versions(), config.setup_parameters.clone())?;
397 let any_setup = AnyControlMessage::Draft13(setup_msg);
398 let _raw_setup = control_send.write_control(&any_setup).await?;
399
400 let (server_setup, _raw_server_setup) = control_recv.read_control(false).await?;
401 match &server_setup {
402 AnyControlMessage::Draft13(ControlMessage::ServerSetup(ref ss)) => {
403 endpoint.receive_server_setup(ss)?;
404 }
405 _ => {
406 return Err(ConnectionError::Endpoint(EndpointError::NotActive));
407 }
408 }
409
410 let conn = Self {
411 transport,
412 endpoint,
413 control_send: Some(control_send),
414 control_recv: Some(control_recv),
415 observer: None,
416 };
417
418 if let Some(v) = conn.endpoint.negotiated_version() {
419 conn.emit(ClientEvent::SetupComplete { negotiated_version: v.into_inner() });
420 }
421
422 Ok(conn)
423 }
424
425 async fn connect_quic(addr: &str, config: &ClientConfig) -> Result<Transport, ConnectionError> {
427 let server_addr = addr.parse().map_err(|e: std::net::AddrParseError| {
428 ConnectionError::InvalidAddress(e.to_string())
429 })?;
430
431 let mut tls_config = if config.skip_cert_verification {
432 rustls::ClientConfig::builder()
433 .dangerous()
434 .with_custom_certificate_verifier(Arc::new(SkipVerification))
435 .with_no_client_auth()
436 } else {
437 let mut roots = rustls::RootCertStore::empty();
438 roots.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
439 for der in &config.ca_certs {
440 roots
441 .add(rustls::pki_types::CertificateDer::from(der.clone()))
442 .map_err(|e| ConnectionError::TlsConfig(format!("bad CA cert: {e}")))?;
443 }
444 rustls::ClientConfig::builder().with_root_certificates(roots).with_no_client_auth()
445 };
446
447 tls_config.alpn_protocols = config.alpn();
448
449 let quic_config: quinn::crypto::rustls::QuicClientConfig =
450 tls_config.try_into().map_err(|e| ConnectionError::TlsConfig(format!("{e}")))?;
451 let client_config = quinn::ClientConfig::new(Arc::new(quic_config));
452
453 let mut quinn_endpoint = quinn::Endpoint::client("0.0.0.0:0".parse().unwrap())
454 .map_err(|e| ConnectionError::InvalidAddress(e.to_string()))?;
455 quinn_endpoint.set_default_client_config(client_config);
456
457 let server_name = addr.split(':').next().unwrap_or("localhost").to_string();
458
459 let quic = quinn_endpoint
460 .connect(server_addr, &server_name)
461 .map_err(TransportError::from)?
462 .await
463 .map_err(TransportError::from)?;
464
465 Ok(Transport::Quic(QuicTransport::new(quic)))
466 }
467
468 #[cfg(feature = "webtransport")]
470 async fn connect_webtransport(
471 url: &str,
472 config: &ClientConfig,
473 ) -> Result<Transport, ConnectionError> {
474 use crate::transport::webtransport::WebTransportTransport;
475
476 let wt_config = if config.skip_cert_verification {
477 wtransport::ClientConfig::builder()
478 .with_bind_default()
479 .with_no_cert_validation()
480 .build()
481 } else {
482 wtransport::ClientConfig::builder().with_bind_default().with_native_certs().build()
483 };
484
485 let endpoint = wtransport::Endpoint::client(wt_config)
486 .map_err(|e| ConnectionError::Transport(TransportError::Connect(e.to_string())))?;
487
488 let connection = endpoint
489 .connect(url)
490 .await
491 .map_err(|e| ConnectionError::Transport(TransportError::Connect(e.to_string())))?;
492
493 Ok(Transport::WebTransport(WebTransportTransport::new(connection)))
494 }
495
496 #[cfg(not(feature = "webtransport"))]
498 async fn connect_webtransport(
499 _url: &str,
500 _config: &ClientConfig,
501 ) -> Result<Transport, ConnectionError> {
502 Err(ConnectionError::Transport(TransportError::Connect(
503 "webtransport feature not enabled".into(),
504 )))
505 }
506
507 pub fn set_observer(&mut self, observer: Box<dyn ConnectionObserver>) {
511 self.observer = Some(observer);
512 }
513
514 pub fn clear_observer(&mut self) {
516 self.observer = None;
517 }
518
519 fn emit(&self, event: ClientEvent) {
521 if let Some(ref obs) = self.observer {
522 obs.on_event_owned(event);
523 }
524 }
525
526 pub async fn send_control(&mut self, msg: &ControlMessage) -> Result<(), ConnectionError> {
530 let any = AnyControlMessage::Draft13(msg.clone());
531 let send = self.control_send.as_mut().ok_or(ConnectionError::NoControlStream)?;
532 let raw = send.write_control(&any).await?;
533 self.emit(ClientEvent::ControlMessage {
534 direction: Direction::Send,
535 message: any,
536 raw: Some(raw),
537 });
538 Ok(())
539 }
540
541 pub async fn recv_control(&mut self) -> Result<ControlMessage, ConnectionError> {
543 let recv = self.control_recv.as_mut().ok_or(ConnectionError::NoControlStream)?;
544 let capture_raw = self.observer.is_some();
545 let (any, raw) = recv.read_control(capture_raw).await?;
546 if capture_raw {
547 self.emit(ClientEvent::ControlMessage {
548 direction: Direction::Receive,
549 message: any.clone(),
550 raw,
551 });
552 }
553 match any {
554 AnyControlMessage::Draft13(msg) => Ok(msg),
555 _ => Err(ConnectionError::Codec(CodecError::UnknownMessageType(0))),
556 }
557 }
558
559 pub async fn recv_and_dispatch(&mut self) -> Result<ControlMessage, ConnectionError> {
562 let msg = self.recv_control().await?;
563 self.endpoint.receive_message(msg.clone())?;
564
565 if let ControlMessage::GoAway(ref ga) = msg {
566 self.emit(ClientEvent::Draining { new_session_uri: ga.new_session_uri.clone() });
567 }
568
569 Ok(msg)
570 }
571
572 pub async fn subscribe(
580 &mut self,
581 track_namespace: TrackNamespace,
582 track_name: Vec<u8>,
583 subscriber_priority: u8,
584 group_order: VarInt,
585 filter_type: VarInt,
586 ) -> Result<VarInt, ConnectionError> {
587 let (req_id, msg) = self.endpoint.subscribe(
588 track_namespace,
589 track_name,
590 subscriber_priority,
591 group_order,
592 filter_type,
593 )?;
594 self.send_control(&msg).await?;
595 Ok(req_id)
596 }
597
598 pub async fn unsubscribe(&mut self, request_id: VarInt) -> Result<(), ConnectionError> {
600 let msg = self.endpoint.unsubscribe(request_id)?;
601 self.send_control(&msg).await
602 }
603
604 #[allow(clippy::too_many_arguments)]
608 pub async fn fetch(
609 &mut self,
610 track_namespace: TrackNamespace,
611 track_name: Vec<u8>,
612 subscriber_priority: u8,
613 group_order: VarInt,
614 start_group: VarInt,
615 start_object: VarInt,
616 end_group: VarInt,
617 end_object: VarInt,
618 ) -> Result<VarInt, ConnectionError> {
619 let (req_id, msg) = self.endpoint.fetch(
620 track_namespace,
621 track_name,
622 subscriber_priority,
623 group_order,
624 start_group,
625 start_object,
626 end_group,
627 end_object,
628 )?;
629 self.send_control(&msg).await?;
630 Ok(req_id)
631 }
632
633 pub async fn fetch_cancel(&mut self, request_id: VarInt) -> Result<(), ConnectionError> {
635 let msg = self.endpoint.fetch_cancel(request_id)?;
636 self.send_control(&msg).await
637 }
638
639 pub async fn subscribe_namespace(
643 &mut self,
644 track_namespace_prefix: TrackNamespace,
645 ) -> Result<VarInt, ConnectionError> {
646 let (req_id, msg) = self.endpoint.subscribe_namespace(track_namespace_prefix)?;
647 self.send_control(&msg).await?;
648 Ok(req_id)
649 }
650
651 pub async fn announce(
653 &mut self,
654 track_namespace: TrackNamespace,
655 ) -> Result<VarInt, ConnectionError> {
656 let (req_id, msg) = self.endpoint.announce(track_namespace)?;
657 self.send_control(&msg).await?;
658 Ok(req_id)
659 }
660
661 pub async fn unannounce(
663 &mut self,
664 track_namespace: TrackNamespace,
665 ) -> Result<(), ConnectionError> {
666 let msg = self.endpoint.unannounce(track_namespace)?;
667 self.send_control(&msg).await
668 }
669
670 #[allow(clippy::too_many_arguments)]
675 pub async fn track_status_request(
676 &mut self,
677 track_namespace: TrackNamespace,
678 track_name: Vec<u8>,
679 subscriber_priority: u8,
680 group_order: VarInt,
681 forward: VarInt,
682 filter_type: VarInt,
683 ) -> Result<VarInt, ConnectionError> {
684 let (req_id, msg) = self.endpoint.track_status_request(
685 track_namespace,
686 track_name,
687 subscriber_priority,
688 group_order,
689 forward,
690 filter_type,
691 )?;
692 self.send_control(&msg).await?;
693 Ok(req_id)
694 }
695
696 pub async fn open_subgroup_stream(
700 &self,
701 header: &AnySubgroupHeader,
702 ) -> Result<FramedSendStream, ConnectionError> {
703 let send = self.transport.open_uni().await?;
704 let mut framed = FramedSendStream::new(send);
705 let sid = framed.stream_id();
706 framed.write_subgroup_header(header).await?;
707 self.emit(ClientEvent::StreamOpened {
708 direction: Direction::Send,
709 stream_kind: StreamKind::Subgroup,
710 stream_id: sid,
711 });
712 self.emit(ClientEvent::DataStreamHeader {
713 stream_id: sid,
714 direction: Direction::Send,
715 header: header.clone(),
716 });
717 Ok(framed)
718 }
719
720 pub async fn accept_subgroup_stream(
723 &self,
724 ) -> Result<(AnySubgroupHeader, FramedRecvStream), ConnectionError> {
725 let recv = self.transport.accept_uni().await?;
726 let mut framed = FramedRecvStream::new(recv);
727 let sid = framed.stream_id();
728 let header = framed.read_subgroup_header().await?;
729 self.emit(ClientEvent::StreamOpened {
730 direction: Direction::Receive,
731 stream_kind: StreamKind::Subgroup,
732 stream_id: sid,
733 });
734 self.emit(ClientEvent::DataStreamHeader {
735 stream_id: sid,
736 direction: Direction::Receive,
737 header: header.clone(),
738 });
739 Ok((header, framed))
740 }
741
742 pub fn send_datagram(
744 &self,
745 header: &AnyDatagramHeader,
746 payload: &[u8],
747 ) -> Result<(), ConnectionError> {
748 let mut buf = Vec::new();
749 header.encode(&mut buf);
750 buf.extend_from_slice(payload);
751 self.emit(ClientEvent::DatagramReceived {
752 direction: Direction::Send,
753 header: header.clone(),
754 payload_len: payload.len(),
755 });
756 self.transport.send_datagram(bytes::Bytes::from(buf))?;
757 Ok(())
758 }
759
760 pub async fn recv_datagram(&self) -> Result<(AnyDatagramHeader, Bytes), ConnectionError> {
762 let data = self.transport.recv_datagram().await?;
763 let mut cursor = &data[..];
764 let header = AnyDatagramHeader::decode(DraftVersion::Draft13, &mut cursor)?;
765 let consumed = data.len() - cursor.len();
766 let payload = data.slice(consumed..);
767 self.emit(ClientEvent::DatagramReceived {
768 direction: Direction::Receive,
769 header: header.clone(),
770 payload_len: payload.len(),
771 });
772 Ok((header, payload))
773 }
774
775 pub fn endpoint(&self) -> &Endpoint {
779 &self.endpoint
780 }
781
782 pub fn endpoint_mut(&mut self) -> &mut Endpoint {
784 &mut self.endpoint
785 }
786
787 pub fn negotiated_version(&self) -> Option<VarInt> {
789 self.endpoint.negotiated_version()
790 }
791
792 pub fn close(&self, code: u32, reason: &[u8]) {
794 self.emit(ClientEvent::Closed { code, reason: reason.to_vec() });
795 self.transport.close(code, reason);
796 }
797}
798
799fn varint_len(first_byte: u8) -> usize {
801 1 << (first_byte >> 6)
802}
803
804#[derive(Debug)]
806struct SkipVerification;
807
808impl rustls::client::danger::ServerCertVerifier for SkipVerification {
809 fn verify_server_cert(
810 &self,
811 _end_entity: &rustls::pki_types::CertificateDer<'_>,
812 _intermediates: &[rustls::pki_types::CertificateDer<'_>],
813 _server_name: &rustls::pki_types::ServerName<'_>,
814 _ocsp_response: &[u8],
815 _now: rustls::pki_types::UnixTime,
816 ) -> Result<rustls::client::danger::ServerCertVerified, rustls::Error> {
817 Ok(rustls::client::danger::ServerCertVerified::assertion())
818 }
819
820 fn verify_tls12_signature(
821 &self,
822 _message: &[u8],
823 _cert: &rustls::pki_types::CertificateDer<'_>,
824 _dcs: &rustls::DigitallySignedStruct,
825 ) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
826 Ok(rustls::client::danger::HandshakeSignatureValid::assertion())
827 }
828
829 fn verify_tls13_signature(
830 &self,
831 _message: &[u8],
832 _cert: &rustls::pki_types::CertificateDer<'_>,
833 _dcs: &rustls::DigitallySignedStruct,
834 ) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
835 Ok(rustls::client::danger::HandshakeSignatureValid::assertion())
836 }
837
838 fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
839 vec![
840 rustls::SignatureScheme::ECDSA_NISTP256_SHA256,
841 rustls::SignatureScheme::ECDSA_NISTP384_SHA384,
842 rustls::SignatureScheme::ED25519,
843 rustls::SignatureScheme::RSA_PSS_SHA256,
844 rustls::SignatureScheme::RSA_PSS_SHA384,
845 rustls::SignatureScheme::RSA_PSS_SHA512,
846 ]
847 }
848}
849
850#[cfg(test)]
851mod tests {
852 use super::*;
853
854 #[test]
855 fn client_config_supported_versions_default() {
856 let config = ClientConfig {
857 additional_versions: Vec::new(),
858 transport: TransportType::Quic,
859 skip_cert_verification: false,
860 ca_certs: Vec::new(),
861 setup_parameters: Vec::new(),
862 };
863 let versions = config.supported_versions();
864 assert_eq!(versions.len(), 1);
865 assert_eq!(versions[0].into_inner(), 0xff000000 + 13);
866 }
867
868 #[test]
869 fn client_config_alpn_quic() {
870 let config = ClientConfig {
871 additional_versions: Vec::new(),
872 transport: TransportType::Quic,
873 skip_cert_verification: false,
874 ca_certs: Vec::new(),
875 setup_parameters: Vec::new(),
876 };
877 assert_eq!(config.alpn(), vec![DraftVersion::Draft13.quic_alpn().to_vec()]);
878 }
879
880 #[test]
881 fn moqt_alpn_value() {
882 assert_eq!(MOQT_ALPN, b"moq-00");
883 }
884}