1use log::trace;
42use std::sync::Arc;
43
44use crate::backend::Handshaker;
45use backend::{
46 client,
47 manager::{self, Manager},
48 server,
49 timer::Timer,
50};
51use config::{MAX_DATAGRAM_SIZE, STREAM_BUFFER_SIZE};
52use connection::{QuicConnection, ToClient, ToServer};
53use error::Result;
54use quiche::ConnectionId;
55use rand::Rng;
56use ring::rand::SystemRandom;
57use tokio::{
58 net::{ToSocketAddrs, UdpSocket},
59 sync::mpsc::{self, UnboundedReceiver},
60 task::JoinHandle,
61};
62
63mod backend;
64pub mod config;
65pub mod connection;
66mod crypto;
67pub mod error;
68pub mod stream;
69
70#[derive(Debug)]
71pub(crate) enum Message {
72 Data {
73 stream_id: u64,
74 bytes: Vec<u8>,
75 fin: bool,
76 },
77 Close(u64),
78}
79
80pub struct QuicListener {
88 io: Arc<UdpSocket>,
89 #[allow(unused)]
90 handle: JoinHandle<Result<()>>,
91 connection_recv: UnboundedReceiver<manager::Client>,
92}
93
94impl QuicListener {
95 #[cfg(not(feature = "key-gen"))]
96 pub async fn bind<A: ToSocketAddrs>(
97 addr: A,
98 key_pem: &str,
99 cert_pem: &str,
100 secret: Vec<u8>,
101 ) -> Result<Self> {
102 let mut config = config::default();
103 config.load_priv_key_from_pem_file(key_pem).unwrap();
104 config.load_cert_chain_from_pem_file(cert_pem).unwrap();
105 Self::bind_with_config(addr, config, secret).await
106 }
107
108 #[cfg(feature = "key-gen")]
109 pub async fn bind<A: ToSocketAddrs>(addr: A) -> Result<Self> {
110 use ring::rand::Random;
111 let rng = SystemRandom::new();
112 let random: Random<[u8; 16]> = ring::rand::generate(&rng).unwrap();
113 Self::bind_with_config(addr, config::default(), random.expose().to_vec()).await
114 }
115
116 pub async fn bind_with_config<A: ToSocketAddrs>(
117 addr: A,
118 config: quiche::Config,
119 secret: Vec<u8>,
120 ) -> Result<Self> {
121 trace!("Bind listener [{secret:?}]");
122 let io = Arc::new(UdpSocket::bind(addr).await?);
123 let rng = SystemRandom::new();
124 let (tx, connection_recv) = mpsc::unbounded_channel();
125 let manager = Manager::new(
126 io.clone(),
127 ring::hmac::Key::generate(ring::hmac::HMAC_SHA256, &rng).unwrap(),
128 secret,
129 config,
130 tx,
131 );
132 let handle = tokio::spawn(manager);
133 Ok(Self {
134 io,
135 handle,
136 connection_recv,
137 })
138 }
139
140 pub async fn accept(&mut self) -> Result<QuicConnection<ToClient>> {
142 let manager::Client { connection, recv } = self.connection_recv.recv().await.unwrap();
143
144 let mut inner = server::Inner {
145 io: self.io.clone(),
146 connection,
147 data_recv: recv,
148 send_flush: false,
149 send_end: 0,
150 send_pos: 0,
151 recv_buf: vec![0; STREAM_BUFFER_SIZE],
152 send_buf: vec![0; MAX_DATAGRAM_SIZE],
153 timer: Timer::Unset,
154 last_address: None,
155 };
156 trace!(
157 "Accepted connection trace-id: {:?}, server-name: {:?}",
158 inner.connection.trace_id(),
159 inner.connection.server_name()
160 );
161 Handshaker(&mut inner).await?;
162 trace!(
163 "Handshake complete trace-id: {:?}, server-name: {:?}",
164 inner.connection.trace_id(),
165 inner.connection.server_name()
166 );
167 Ok(QuicConnection::<ToClient>::new(inner))
168 }
169}
170
171pub struct QuicSocket {
179 io: Arc<UdpSocket>,
180 config: quiche::Config,
181}
182
183impl QuicSocket {
184 #[cfg(not(feature = "key-gen"))]
185 pub async fn bind<A: ToSocketAddrs>(addr: A, key_pem: &str, cert_pem: &str) -> Result<Self> {
187 let mut config = config::default();
188 config.load_priv_key_from_pem_file(key_pem).unwrap();
189 config.load_cert_chain_from_pem_file(cert_pem).unwrap();
190 Self::bind_with_config(addr, config).await
191 }
192
193 #[cfg(feature = "key-gen")]
194 pub async fn bind<A: ToSocketAddrs>(addr: A) -> Result<Self> {
196 Self::bind_with_config(addr, config::default()).await
197 }
198
199 pub async fn bind_with_config<A: ToSocketAddrs>(
201 addr: A,
202 config: quiche::Config,
203 ) -> Result<Self> {
204 Ok(Self {
205 io: Arc::new(UdpSocket::bind(addr).await?),
206 config,
207 })
208 }
209
210 pub async fn connect<A: ToSocketAddrs>(
215 &mut self,
216 server_name: Option<&str>,
217 addr: A,
218 ) -> Result<QuicConnection<ToServer>> {
219 self.io.connect(addr).await?;
220 let mut scid = vec![0; 16];
221 rand::thread_rng().fill(&mut *scid);
222 let scid: ConnectionId = scid.into();
223 let connection = quiche::connect(
224 server_name,
225 &scid,
226 self.io.local_addr()?,
227 self.io.peer_addr()?,
228 &mut self.config,
229 )
230 .unwrap();
231
232 let mut inner = client::Inner {
233 io: self.io.clone(),
234 connection,
235 send_flush: false,
236 send_end: 0,
237 send_pos: 0,
238 recv_buf: vec![0; STREAM_BUFFER_SIZE],
239 send_buf: vec![0; MAX_DATAGRAM_SIZE],
240 timer: Timer::Unset,
241 };
242
243 Handshaker(&mut inner).await?;
244
245 Ok(QuicConnection::<ToServer>::new(inner))
246 }
247}