1 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
4 // option. This file may not be copied, modified, or distributed
5 // except according to those terms.
6
7 #![allow(unused_assignments)]
8
9 use neqo_common::{event::Provider, Datagram};
10 use neqo_crypto::{AuthenticationStatus, ResumptionToken};
11 use neqo_http3::{
12 Header, Http3Client, Http3ClientEvent, Http3OrWebTransportStream, Http3Parameters, Http3Server,
13 Http3ServerEvent, Http3State, Priority,
14 };
15 use neqo_transport::{ConnectionParameters, StreamType};
16 use std::mem;
17 use test_fixture::*;
18
19 const RESPONSE_DATA: &[u8] = &[0x61, 0x62, 0x63];
20
receive_request(server: &mut Http3Server) -> Option<Http3OrWebTransportStream>21 fn receive_request(server: &mut Http3Server) -> Option<Http3OrWebTransportStream> {
22 while let Some(event) = server.next_event() {
23 if let Http3ServerEvent::Headers {
24 stream,
25 headers,
26 fin,
27 } = event
28 {
29 assert_eq!(
30 &headers,
31 &[
32 Header::new(":method", "GET"),
33 Header::new(":scheme", "https"),
34 Header::new(":authority", "something.com"),
35 Header::new(":path", "/")
36 ]
37 );
38 assert!(fin);
39
40 return Some(stream);
41 }
42 }
43 None
44 }
45
set_response(request: &mut Http3OrWebTransportStream)46 fn set_response(request: &mut Http3OrWebTransportStream) {
47 request
48 .send_headers(&[
49 Header::new(":status", "200"),
50 Header::new("content-length", "3"),
51 ])
52 .unwrap();
53 request.send_data(RESPONSE_DATA).unwrap();
54 request.stream_close_send().unwrap();
55 }
56
process_server_events(server: &mut Http3Server)57 fn process_server_events(server: &mut Http3Server) {
58 let mut request = receive_request(server).unwrap();
59 set_response(&mut request);
60 }
61
process_client_events(conn: &mut Http3Client)62 fn process_client_events(conn: &mut Http3Client) {
63 let mut response_header_found = false;
64 let mut response_data_found = false;
65 while let Some(event) = conn.next_event() {
66 match event {
67 Http3ClientEvent::HeaderReady { headers, fin, .. } => {
68 assert_eq!(
69 &headers,
70 &[
71 Header::new(":status", "200"),
72 Header::new("content-length", "3"),
73 ]
74 );
75 assert!(!fin);
76 response_header_found = true;
77 }
78 Http3ClientEvent::DataReadable { stream_id } => {
79 let mut buf = [0u8; 100];
80 let (amount, fin) = conn.read_data(now(), stream_id, &mut buf).unwrap();
81 assert!(fin);
82 assert_eq!(amount, RESPONSE_DATA.len());
83 assert_eq!(&buf[..RESPONSE_DATA.len()], RESPONSE_DATA);
84 response_data_found = true;
85 }
86 _ => {}
87 }
88 }
89 assert!(response_header_found);
90 assert!(response_data_found);
91 }
92
connect_peers(hconn_c: &mut Http3Client, hconn_s: &mut Http3Server) -> Option<Datagram>93 fn connect_peers(hconn_c: &mut Http3Client, hconn_s: &mut Http3Server) -> Option<Datagram> {
94 assert_eq!(hconn_c.state(), Http3State::Initializing);
95 let out = hconn_c.process(None, now()); // Initial
96 let out = hconn_s.process(out.dgram(), now()); // Initial + Handshake
97 let out = hconn_c.process(out.dgram(), now()); // ACK
98 mem::drop(hconn_s.process(out.dgram(), now())); //consume ACK
99 let authentication_needed = |e| matches!(e, Http3ClientEvent::AuthenticationNeeded);
100 assert!(hconn_c.events().any(authentication_needed));
101 hconn_c.authenticated(AuthenticationStatus::Ok, now());
102 let out = hconn_c.process(None, now()); // Handshake
103 assert_eq!(hconn_c.state(), Http3State::Connected);
104 let out = hconn_s.process(out.dgram(), now()); // Handshake
105 let out = hconn_c.process(out.dgram(), now());
106 let out = hconn_s.process(out.dgram(), now());
107 // assert!(hconn_s.settings_received);
108 let out = hconn_c.process(out.dgram(), now());
109 // assert!(hconn_c.settings_received);
110
111 out.dgram()
112 }
113
connect() -> (Http3Client, Http3Server, Option<Datagram>)114 fn connect() -> (Http3Client, Http3Server, Option<Datagram>) {
115 let mut hconn_c = default_http3_client();
116 let mut hconn_s = default_http3_server();
117
118 let out = connect_peers(&mut hconn_c, &mut hconn_s);
119 (hconn_c, hconn_s, out)
120 }
121
exchange_packets(client: &mut Http3Client, server: &mut Http3Server, out_ex: Option<Datagram>)122 fn exchange_packets(client: &mut Http3Client, server: &mut Http3Server, out_ex: Option<Datagram>) {
123 let mut out = out_ex;
124 loop {
125 out = client.process(out, now()).dgram();
126 out = server.process(out, now()).dgram();
127 if out.is_none() {
128 break;
129 }
130 }
131 }
132
133 #[test]
test_connect()134 fn test_connect() {
135 let (_hconn_c, _hconn_s, _d) = connect();
136 }
137
138 #[test]
test_fetch()139 fn test_fetch() {
140 let (mut hconn_c, mut hconn_s, dgram) = connect();
141
142 eprintln!("-----client");
143 let req = hconn_c
144 .fetch(
145 now(),
146 "GET",
147 &("https", "something.com", "/"),
148 &[],
149 Priority::default(),
150 )
151 .unwrap();
152 assert_eq!(req, 0);
153 hconn_c.stream_close_send(req).unwrap();
154 let out = hconn_c.process(dgram, now());
155 eprintln!("-----server");
156 let out = hconn_s.process(out.dgram(), now());
157 mem::drop(hconn_c.process(out.dgram(), now()));
158 process_server_events(&mut hconn_s);
159 let out = hconn_s.process(None, now());
160
161 eprintln!("-----client");
162 mem::drop(hconn_c.process(out.dgram(), now()));
163 let out = hconn_s.process(None, now());
164 mem::drop(hconn_c.process(out.dgram(), now()));
165 process_client_events(&mut hconn_c);
166 }
167
168 #[test]
test_103_response()169 fn test_103_response() {
170 let (mut hconn_c, mut hconn_s, dgram) = connect();
171
172 let req = hconn_c
173 .fetch(
174 now(),
175 "GET",
176 &("https", "something.com", "/"),
177 &[],
178 Priority::default(),
179 )
180 .unwrap();
181 assert_eq!(req, 0);
182 hconn_c.stream_close_send(req).unwrap();
183 let out = hconn_c.process(dgram, now());
184
185 let out = hconn_s.process(out.dgram(), now());
186 mem::drop(hconn_c.process(out.dgram(), now()));
187 let mut request = receive_request(&mut hconn_s).unwrap();
188
189 let info_headers = [
190 Header::new(":status", "103"),
191 Header::new("link", "</style.css>; rel=preload; as=style"),
192 ];
193 // Send 103
194 request.send_headers(&info_headers).unwrap();
195 let out = hconn_s.process(None, now());
196
197 mem::drop(hconn_c.process(out.dgram(), now()));
198
199 let info_headers_event = |e| {
200 matches!(e, Http3ClientEvent::HeaderReady { headers,
201 interim,
202 fin, .. } if !fin && interim && headers.as_ref() == info_headers)
203 };
204 assert!(hconn_c.events().any(info_headers_event));
205
206 set_response(&mut request);
207 let out = hconn_s.process(None, now());
208 mem::drop(hconn_c.process(out.dgram(), now()));
209 process_client_events(&mut hconn_c)
210 }
211
212 #[test]
test_data_writable_events()213 fn test_data_writable_events() {
214 const STREAM_LIMIT: u64 = 5000;
215 const DATA_AMOUNT: usize = 10000;
216
217 let mut hconn_c = http3_client_with_params(Http3Parameters::default().connection_parameters(
218 ConnectionParameters::default().max_stream_data(StreamType::BiDi, false, STREAM_LIMIT),
219 ));
220 let mut hconn_s = default_http3_server();
221
222 mem::drop(connect_peers(&mut hconn_c, &mut hconn_s));
223
224 // Create a request.
225 let req = hconn_c
226 .fetch(
227 now(),
228 "GET",
229 &("https", "something.com", "/"),
230 &[],
231 Priority::default(),
232 )
233 .unwrap();
234 hconn_c.stream_close_send(req).unwrap();
235 exchange_packets(&mut hconn_c, &mut hconn_s, None);
236
237 let mut request = receive_request(&mut hconn_s).unwrap();
238
239 request
240 .send_headers(&[
241 Header::new(":status", "200"),
242 Header::new("content-length", DATA_AMOUNT.to_string()),
243 ])
244 .unwrap();
245
246 // Send a lot of data
247 let buf = &[1; DATA_AMOUNT];
248 let mut sent = request.send_data(buf).unwrap();
249 assert!(sent < DATA_AMOUNT);
250
251 // Exchange packets and read the data on the client side.
252 exchange_packets(&mut hconn_c, &mut hconn_s, None);
253 let stream_id = request.stream_id();
254 let mut recv_buf = [0_u8; DATA_AMOUNT];
255 let (mut recvd, _) = hconn_c.read_data(now(), stream_id, &mut recv_buf).unwrap();
256 assert_eq!(sent, recvd);
257 exchange_packets(&mut hconn_c, &mut hconn_s, None);
258
259 let data_writable = |e| {
260 matches!(
261 e,
262 Http3ServerEvent::DataWritable {
263 stream
264 } if stream.stream_id() == stream_id
265 )
266 };
267 // Make sure we have a DataWritable event.
268 assert!(hconn_s.events().any(data_writable));
269 // Data can be sent again.
270 let s = request.send_data(&buf[sent..]).unwrap();
271 assert!(s > 0);
272 sent += s;
273
274 // Exchange packets and read the data on the client side.
275 exchange_packets(&mut hconn_c, &mut hconn_s, None);
276 let (r, _) = hconn_c
277 .read_data(now(), stream_id, &mut recv_buf[recvd..])
278 .unwrap();
279 recvd += r;
280 exchange_packets(&mut hconn_c, &mut hconn_s, None);
281 assert_eq!(sent, recvd);
282
283 // One more DataWritable event.
284 assert!(hconn_s.events().any(data_writable));
285 // Send more data.
286 let s = request.send_data(&buf[sent..]).unwrap();
287 assert!(s > 0);
288 sent += s;
289 assert_eq!(sent, DATA_AMOUNT);
290
291 exchange_packets(&mut hconn_c, &mut hconn_s, None);
292 let (r, _) = hconn_c
293 .read_data(now(), stream_id, &mut recv_buf[recvd..])
294 .unwrap();
295 recvd += r;
296
297 // Make sure all data is received by the client.
298 assert_eq!(recvd, DATA_AMOUNT);
299 assert_eq!(&recv_buf, buf);
300 }
301
get_token(client: &mut Http3Client) -> ResumptionToken302 fn get_token(client: &mut Http3Client) -> ResumptionToken {
303 assert_eq!(client.state(), Http3State::Connected);
304 client
305 .events()
306 .find_map(|e| {
307 if let Http3ClientEvent::ResumptionToken(token) = e {
308 Some(token)
309 } else {
310 None
311 }
312 })
313 .unwrap()
314 }
315
316 #[test]
zerortt()317 fn zerortt() {
318 let (mut hconn_c, _, dgram) = connect();
319 let token = get_token(&mut hconn_c);
320
321 // Create a new connection with a resumption token.
322 let mut hconn_c = default_http3_client();
323 hconn_c
324 .enable_resumption(now(), &token)
325 .expect("Set resumption token.");
326 let mut hconn_s = default_http3_server();
327
328 // Create a request.
329 let req = hconn_c
330 .fetch(
331 now(),
332 "GET",
333 &("https", "something.com", "/"),
334 &[],
335 Priority::default(),
336 )
337 .unwrap();
338 hconn_c.stream_close_send(req).unwrap();
339
340 let out = hconn_c.process(dgram, now());
341 let out = hconn_s.process(out.dgram(), now());
342
343 let mut request_stream = None;
344 let mut zerortt_state_change = false;
345 while let Some(event) = hconn_s.next_event() {
346 match event {
347 Http3ServerEvent::Headers {
348 stream,
349 headers,
350 fin,
351 } => {
352 assert_eq!(
353 &headers,
354 &[
355 Header::new(":method", "GET"),
356 Header::new(":scheme", "https"),
357 Header::new(":authority", "something.com"),
358 Header::new(":path", "/")
359 ]
360 );
361 assert!(fin);
362
363 request_stream = Some(stream);
364 }
365 Http3ServerEvent::StateChange { state, .. } => {
366 assert_eq!(state, Http3State::ZeroRtt);
367 zerortt_state_change = true;
368 }
369 _ => {}
370 }
371 }
372 assert!(zerortt_state_change);
373 let mut request_stream = request_stream.unwrap();
374
375 // Send a response
376 set_response(&mut request_stream);
377
378 // Receive the response
379 exchange_packets(&mut hconn_c, &mut hconn_s, out.dgram());
380 process_client_events(&mut hconn_c);
381 }
382