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 use super::super::Connection;
8 use super::{
9     connect, default_client, default_server, exchange_ticket, new_server,
10     CountingConnectionIdGenerator,
11 };
12 use crate::events::ConnectionEvent;
13 use crate::{ConnectionParameters, Error, StreamType};
14 
15 use neqo_common::event::Provider;
16 use neqo_crypto::{AllowZeroRtt, AntiReplay};
17 use std::cell::RefCell;
18 use std::rc::Rc;
19 use test_fixture::{self, assertions, now};
20 
21 #[test]
zero_rtt_negotiate()22 fn zero_rtt_negotiate() {
23     // Note that the two servers in this test will get different anti-replay filters.
24     // That's OK because we aren't testing anti-replay.
25     let mut client = default_client();
26     let mut server = default_server();
27     connect(&mut client, &mut server);
28 
29     let token = exchange_ticket(&mut client, &mut server, now());
30     let mut client = default_client();
31     client
32         .enable_resumption(now(), token)
33         .expect("should set token");
34     let mut server = default_server();
35     connect(&mut client, &mut server);
36     assert!(client.tls_info().unwrap().early_data_accepted());
37     assert!(server.tls_info().unwrap().early_data_accepted());
38 }
39 
40 #[test]
zero_rtt_send_recv()41 fn zero_rtt_send_recv() {
42     let mut client = default_client();
43     let mut server = default_server();
44     connect(&mut client, &mut server);
45 
46     let token = exchange_ticket(&mut client, &mut server, now());
47     let mut client = default_client();
48     client
49         .enable_resumption(now(), token)
50         .expect("should set token");
51     let mut server = default_server();
52 
53     // Send ClientHello.
54     let client_hs = client.process(None, now());
55     assert!(client_hs.as_dgram_ref().is_some());
56 
57     // Now send a 0-RTT packet.
58     let client_stream_id = client.stream_create(StreamType::UniDi).unwrap();
59     client.stream_send(client_stream_id, &[1, 2, 3]).unwrap();
60     let client_0rtt = client.process(None, now());
61     assert!(client_0rtt.as_dgram_ref().is_some());
62     // 0-RTT packets on their own shouldn't be padded to 1200.
63     assert!(client_0rtt.as_dgram_ref().unwrap().len() < 1200);
64 
65     let server_hs = server.process(client_hs.dgram(), now());
66     assert!(server_hs.as_dgram_ref().is_some()); // ServerHello, etc...
67 
68     let all_frames = server.stats().frame_tx.all;
69     let ack_frames = server.stats().frame_tx.ack;
70     let server_process_0rtt = server.process(client_0rtt.dgram(), now());
71     assert!(server_process_0rtt.as_dgram_ref().is_some());
72     assert_eq!(server.stats().frame_tx.all, all_frames + 1);
73     assert_eq!(server.stats().frame_tx.ack, ack_frames + 1);
74 
75     let server_stream_id = server
76         .events()
77         .find_map(|evt| match evt {
78             ConnectionEvent::NewStream { stream_id, .. } => Some(stream_id),
79             _ => None,
80         })
81         .expect("should have received a new stream event");
82     assert_eq!(client_stream_id, server_stream_id.as_u64());
83 }
84 
85 #[test]
zero_rtt_send_coalesce()86 fn zero_rtt_send_coalesce() {
87     let mut client = default_client();
88     let mut server = default_server();
89     connect(&mut client, &mut server);
90 
91     let token = exchange_ticket(&mut client, &mut server, now());
92     let mut client = default_client();
93     client
94         .enable_resumption(now(), token)
95         .expect("should set token");
96     let mut server = default_server();
97 
98     // Write 0-RTT before generating any packets.
99     // This should result in a datagram that coalesces Initial and 0-RTT.
100     let client_stream_id = client.stream_create(StreamType::UniDi).unwrap();
101     client.stream_send(client_stream_id, &[1, 2, 3]).unwrap();
102     let client_0rtt = client.process(None, now());
103     assert!(client_0rtt.as_dgram_ref().is_some());
104 
105     assertions::assert_coalesced_0rtt(&client_0rtt.as_dgram_ref().unwrap()[..]);
106 
107     let server_hs = server.process(client_0rtt.dgram(), now());
108     assert!(server_hs.as_dgram_ref().is_some()); // Should produce ServerHello etc...
109 
110     let server_stream_id = server
111         .events()
112         .find_map(|evt| match evt {
113             ConnectionEvent::NewStream { stream_id } => Some(stream_id),
114             _ => None,
115         })
116         .expect("should have received a new stream event");
117     assert_eq!(client_stream_id, server_stream_id.as_u64());
118 }
119 
120 #[test]
zero_rtt_before_resumption_token()121 fn zero_rtt_before_resumption_token() {
122     let mut client = default_client();
123     assert!(client.stream_create(StreamType::BiDi).is_err());
124 }
125 
126 #[test]
zero_rtt_send_reject()127 fn zero_rtt_send_reject() {
128     const MESSAGE: &[u8] = &[1, 2, 3];
129 
130     let mut client = default_client();
131     let mut server = default_server();
132     connect(&mut client, &mut server);
133 
134     let token = exchange_ticket(&mut client, &mut server, now());
135     let mut client = default_client();
136     client
137         .enable_resumption(now(), token)
138         .expect("should set token");
139     let mut server = Connection::new_server(
140         test_fixture::DEFAULT_KEYS,
141         test_fixture::DEFAULT_ALPN,
142         Rc::new(RefCell::new(CountingConnectionIdGenerator::default())),
143         ConnectionParameters::default(),
144     )
145     .unwrap();
146     // Using a freshly initialized anti-replay context
147     // should result in the server rejecting 0-RTT.
148     let ar =
149         AntiReplay::new(now(), test_fixture::ANTI_REPLAY_WINDOW, 1, 3).expect("setup anti-replay");
150     server
151         .server_enable_0rtt(&ar, AllowZeroRtt {})
152         .expect("enable 0-RTT");
153 
154     // Send ClientHello.
155     let client_hs = client.process(None, now());
156     assert!(client_hs.as_dgram_ref().is_some());
157 
158     // Write some data on the client.
159     let stream_id = client.stream_create(StreamType::UniDi).unwrap();
160     client.stream_send(stream_id, MESSAGE).unwrap();
161     let client_0rtt = client.process(None, now());
162     assert!(client_0rtt.as_dgram_ref().is_some());
163 
164     let server_hs = server.process(client_hs.dgram(), now());
165     assert!(server_hs.as_dgram_ref().is_some()); // Should produce ServerHello etc...
166     let server_ignored = server.process(client_0rtt.dgram(), now());
167     assert!(server_ignored.as_dgram_ref().is_none());
168 
169     // The server shouldn't receive that 0-RTT data.
170     let recvd_stream_evt = |e| matches!(e, ConnectionEvent::NewStream { .. });
171     assert!(!server.events().any(recvd_stream_evt));
172 
173     // Client should get a rejection.
174     let client_fin = client.process(server_hs.dgram(), now());
175     let recvd_0rtt_reject = |e| e == ConnectionEvent::ZeroRttRejected;
176     assert!(client.events().any(recvd_0rtt_reject));
177 
178     // Server consume client_fin
179     let server_ack = server.process(client_fin.dgram(), now());
180     assert!(server_ack.as_dgram_ref().is_some());
181     let client_out = client.process(server_ack.dgram(), now());
182     assert!(client_out.as_dgram_ref().is_none());
183 
184     // ...and the client stream should be gone.
185     let res = client.stream_send(stream_id, MESSAGE);
186     assert!(res.is_err());
187     assert_eq!(res.unwrap_err(), Error::InvalidStreamId);
188 
189     // Open a new stream and send data. StreamId should start with 0.
190     let stream_id_after_reject = client.stream_create(StreamType::UniDi).unwrap();
191     assert_eq!(stream_id, stream_id_after_reject);
192     client.stream_send(stream_id_after_reject, MESSAGE).unwrap();
193     let client_after_reject = client.process(None, now()).dgram();
194     assert!(client_after_reject.is_some());
195 
196     // The server should receive new stream
197     server.process_input(client_after_reject.unwrap(), now());
198     assert!(server.events().any(recvd_stream_evt));
199 }
200 
201 #[test]
zero_rtt_update_flow_control()202 fn zero_rtt_update_flow_control() {
203     const LOW: u64 = 3;
204     const HIGH: u64 = 10;
205     #[allow(clippy::cast_possible_truncation)]
206     const MESSAGE: &[u8] = &[0; HIGH as usize];
207 
208     let mut client = default_client();
209     let mut server = new_server(
210         ConnectionParameters::default()
211             .max_stream_data(StreamType::UniDi, true, LOW)
212             .max_stream_data(StreamType::BiDi, true, LOW),
213     );
214     connect(&mut client, &mut server);
215 
216     let token = exchange_ticket(&mut client, &mut server, now());
217     let mut client = default_client();
218     client
219         .enable_resumption(now(), token)
220         .expect("should set token");
221     let mut server = new_server(
222         ConnectionParameters::default()
223             .max_stream_data(StreamType::UniDi, true, HIGH)
224             .max_stream_data(StreamType::BiDi, true, HIGH),
225     );
226 
227     // Stream limits should be low for 0-RTT.
228     let client_hs = client.process(None, now()).dgram();
229     let uni_stream = client.stream_create(StreamType::UniDi).unwrap();
230     assert!(!client.stream_send_atomic(uni_stream, MESSAGE).unwrap());
231     let bidi_stream = client.stream_create(StreamType::BiDi).unwrap();
232     assert!(!client.stream_send_atomic(bidi_stream, MESSAGE).unwrap());
233 
234     // Now get the server transport parameters.
235     let server_hs = server.process(client_hs, now()).dgram();
236     client.process_input(server_hs.unwrap(), now());
237 
238     // The streams should report a writeable event.
239     let mut uni_stream_event = false;
240     let mut bidi_stream_event = false;
241     for e in client.events() {
242         if let ConnectionEvent::SendStreamWritable { stream_id } = e {
243             if stream_id.is_uni() {
244                 uni_stream_event = true;
245             } else {
246                 bidi_stream_event = true;
247             }
248         }
249     }
250     assert!(uni_stream_event);
251     assert!(bidi_stream_event);
252     // But no MAX_STREAM_DATA frame was received.
253     assert_eq!(client.stats().frame_rx.max_stream_data, 0);
254 
255     // And the new limit applies.
256     assert!(client.stream_send_atomic(uni_stream, MESSAGE).unwrap());
257     assert!(client.stream_send_atomic(bidi_stream, MESSAGE).unwrap());
258 }
259