1 /** @file
2  *
3  *  A brief file description
4  *
5  *  @section license License
6  *
7  *  Licensed to the Apache Software Foundation (ASF) under one
8  *  or more contributor license agreements.  See the NOTICE file
9  *  distributed with this work for additional information
10  *  regarding copyright ownership.  The ASF licenses this file
11  *  to you under the Apache License, Version 2.0 (the
12  *  "License"); you may not use this file except in compliance
13  *  with the License.  You may obtain a copy of the License at
14  *
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  *
17  *  Unless required by applicable law or agreed to in writing, software
18  *  distributed under the License is distributed on an "AS IS" BASIS,
19  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  *  See the License for the specific language governing permissions and
21  *  limitations under the License.
22  */
23 
24 #include "QUICStreamState.h"
25 #include "tscore/ink_assert.h"
26 
27 // ---------QUICReceiveStreamState -----------
28 
29 bool
is_allowed_to_send(const QUICFrame & frame) const30 QUICReceiveStreamStateMachine::is_allowed_to_send(const QUICFrame &frame) const
31 {
32   return this->is_allowed_to_send(frame.type());
33 }
34 
35 bool
is_allowed_to_send(QUICFrameType type) const36 QUICReceiveStreamStateMachine::is_allowed_to_send(QUICFrameType type) const
37 {
38   if (type != QUICFrameType::STOP_SENDING && type != QUICFrameType::MAX_STREAM_DATA) {
39     return false;
40   }
41 
42   QUICReceiveStreamState state = this->get();
43   // The receiver only sends MAX_STREAM_DATA in the “Recv” state.
44   if (type == QUICFrameType::MAX_STREAM_DATA && state == QUICReceiveStreamState::Recv) {
45     return true;
46   }
47 
48   // A receiver can send STOP_SENDING in any state where it has not received a RESET_STREAM frame; that is states other than “Reset
49   // Recvd” or “Reset Read”.
50   if (type == QUICFrameType::STOP_SENDING && state != QUICReceiveStreamState::ResetRecvd &&
51       state != QUICReceiveStreamState::ResetRead) {
52     return true;
53   }
54 
55   return false;
56 }
57 
58 bool
is_allowed_to_receive(const QUICFrame & frame) const59 QUICReceiveStreamStateMachine::is_allowed_to_receive(const QUICFrame &frame) const
60 {
61   return this->is_allowed_to_receive(frame.type());
62 }
63 
64 bool
is_allowed_to_receive(QUICFrameType type) const65 QUICReceiveStreamStateMachine::is_allowed_to_receive(QUICFrameType type) const
66 {
67   // always allow receive these frames.
68   if (type == QUICFrameType::STREAM || type == QUICFrameType::STREAM_DATA_BLOCKED || type == QUICFrameType::RESET_STREAM) {
69     return true;
70   }
71 
72   return false;
73 }
74 
75 void
update_with_sending_frame(const QUICFrame & frame)76 QUICReceiveStreamStateMachine::update_with_sending_frame(const QUICFrame &frame)
77 {
78 }
79 
80 void
update_with_receiving_frame(const QUICFrame & frame)81 QUICReceiveStreamStateMachine::update_with_receiving_frame(const QUICFrame &frame)
82 {
83   // The receiving part of a stream initiated by a peer (types 1 and 3 for a client, or 0 and 2 for a server) is created when the
84   // first STREAM, STREAM_DATA_BLOCKED, or RESET_STREAM is received for that stream.
85   QUICReceiveStreamState state = this->get();
86   QUICFrameType type           = frame.type();
87 
88   if (state == QUICReceiveStreamState::Init &&
89       (type == QUICFrameType::STREAM || type == QUICFrameType::STREAM_DATA_BLOCKED || type == QUICFrameType::RESET_STREAM)) {
90     this->_set_state(QUICReceiveStreamState::Recv);
91   }
92 
93   switch (this->get()) {
94   case QUICReceiveStreamState::Recv:
95     if (type == QUICFrameType::STREAM) {
96       if (static_cast<const QUICStreamFrame &>(frame).has_fin_flag()) {
97         this->_set_state(QUICReceiveStreamState::SizeKnown);
98         if (this->_in_progress->is_transfer_complete()) {
99           this->_set_state(QUICReceiveStreamState::DataRecvd);
100         }
101       }
102     } else if (type == QUICFrameType::RESET_STREAM) {
103       this->_set_state(QUICReceiveStreamState::ResetRecvd);
104     }
105     break;
106   case QUICReceiveStreamState::SizeKnown:
107     if (type == QUICFrameType::STREAM && this->_in_progress->is_transfer_complete()) {
108       this->_set_state(QUICReceiveStreamState::DataRecvd);
109     } else if (type == QUICFrameType::RESET_STREAM) {
110       this->_set_state(QUICReceiveStreamState::ResetRecvd);
111     }
112     break;
113   case QUICReceiveStreamState::DataRecvd:
114     if (type == QUICFrameType::STREAM && this->_in_progress->is_transfer_complete()) {
115       this->_set_state(QUICReceiveStreamState::ResetRecvd);
116     }
117     break;
118   case QUICReceiveStreamState::Init:
119   case QUICReceiveStreamState::ResetRecvd:
120   case QUICReceiveStreamState::DataRead:
121   case QUICReceiveStreamState::ResetRead:
122     break;
123   default:
124     ink_assert(!"Unknown state");
125     break;
126   }
127 }
128 
129 void
update_on_read()130 QUICReceiveStreamStateMachine::update_on_read()
131 {
132   if (this->_in_progress->is_transfer_complete()) {
133     this->_set_state(QUICReceiveStreamState::DataRead);
134   }
135 }
136 
137 void
update_on_eos()138 QUICReceiveStreamStateMachine::update_on_eos()
139 {
140   this->_set_state(QUICReceiveStreamState::ResetRead);
141 }
142 
143 void
update(const QUICSendStreamState state)144 QUICReceiveStreamStateMachine::update(const QUICSendStreamState state)
145 {
146   // The receiving part of a stream enters the “Recv” state when the sending part of a bidirectional stream initiated by the
147   // endpoint (type 0 for a client, type 1 for a server) enters the “Ready” state.
148   switch (this->get()) {
149   case QUICReceiveStreamState::Init:
150     if (state == QUICSendStreamState::Ready) {
151       this->_set_state(QUICReceiveStreamState::Recv);
152     }
153     break;
154   default:
155     break;
156   }
157 }
158 
159 // ---------- QUICSendStreamState -------------
160 
161 bool
is_allowed_to_send(const QUICFrame & frame) const162 QUICSendStreamStateMachine::is_allowed_to_send(const QUICFrame &frame) const
163 {
164   return this->is_allowed_to_send(frame.type());
165 }
166 
167 bool
is_allowed_to_send(QUICFrameType type) const168 QUICSendStreamStateMachine::is_allowed_to_send(QUICFrameType type) const
169 {
170   if (type != QUICFrameType::STREAM && type != QUICFrameType::STREAM_DATA_BLOCKED && type != QUICFrameType::RESET_STREAM) {
171     return false;
172   }
173 
174   switch (this->get()) {
175   case QUICSendStreamState::Ready:
176     if (type == QUICFrameType::STREAM || type == QUICFrameType::STREAM_DATA_BLOCKED || type == QUICFrameType::RESET_STREAM) {
177       return true;
178     }
179     break;
180   case QUICSendStreamState::Send:
181     if (type == QUICFrameType::STREAM || type == QUICFrameType::STREAM_DATA_BLOCKED || type == QUICFrameType::RESET_STREAM) {
182       return true;
183     }
184     break;
185   case QUICSendStreamState::DataSent:
186     if (type == QUICFrameType::RESET_STREAM) {
187       return true;
188     }
189     break;
190   // A sender MUST NOT send any of these frames from a terminal state (“Data Recvd” or “Reset Recvd”).
191   case QUICSendStreamState::DataRecvd:
192   case QUICSendStreamState::ResetRecvd:
193     break;
194   // A sender MUST NOT send STREAM or STREAM_DATA_BLOCKED after sending a RESET_STREAM; that is, in the terminal states and in the
195   // “Reset Sent” state.
196   case QUICSendStreamState::ResetSent:
197     if (type == QUICFrameType::RESET_STREAM) {
198       return true;
199     }
200     break;
201   default:
202     ink_assert("This shouuldn't be happen");
203     break;
204   }
205 
206   return false;
207 }
208 
209 bool
is_allowed_to_receive(const QUICFrame & frame) const210 QUICSendStreamStateMachine::is_allowed_to_receive(const QUICFrame &frame) const
211 {
212   return this->is_allowed_to_receive(frame.type());
213 }
214 
215 bool
is_allowed_to_receive(QUICFrameType type) const216 QUICSendStreamStateMachine::is_allowed_to_receive(QUICFrameType type) const
217 {
218   if (type != QUICFrameType::STOP_SENDING && type != QUICFrameType::MAX_STREAM_DATA) {
219     return false;
220   }
221 
222   // A sender could receive either of these two frames(MAX_STREAM_DATA and STOP_SENDING) in any state as a result of delayed
223   // delivery of packets.
224   // PS: Because we need to reply a RESET_STREAM frame. STOP_SENDING frame is accpeted in all states. But we
225   // don't need to do anything for MAX_STREAM_DATA frame when we are in terminal state.
226   if (type == QUICFrameType::STOP_SENDING) {
227     return true;
228   }
229 
230   switch (this->get()) {
231   case QUICSendStreamState::Ready:
232   case QUICSendStreamState::Send:
233     if (type == QUICFrameType::MAX_STREAM_DATA) {
234       return true;
235     }
236     break;
237   // "MAX_STREAM_DATA frames might be received until the peer receives the final stream offset. The endpoint can safely ignore
238   // any MAX_STREAM_DATA frames it receives from its peer for a stream in this state."
239   case QUICSendStreamState::DataSent:
240   case QUICSendStreamState::ResetSent:
241   case QUICSendStreamState::DataRecvd:
242   case QUICSendStreamState::ResetRecvd:
243     if (type == QUICFrameType::MAX_STREAM_DATA) {
244       return true;
245     }
246     break;
247   default:
248     break;
249   }
250 
251   return false;
252 }
253 
254 void
update_with_sending_frame(const QUICFrame & frame)255 QUICSendStreamStateMachine::update_with_sending_frame(const QUICFrame &frame)
256 {
257   QUICSendStreamState state = this->get();
258   QUICFrameType type        = frame.type();
259   if (state == QUICSendStreamState::Ready &&
260       (type == QUICFrameType::STREAM || type == QUICFrameType::STREAM_DATA_BLOCKED || type == QUICFrameType::RESET_STREAM)) {
261     this->_set_state(QUICSendStreamState::Send);
262   }
263 
264   switch (this->get()) {
265   case QUICSendStreamState::Send:
266     if (type == QUICFrameType::STREAM) {
267       if (static_cast<const QUICStreamFrame &>(frame).has_fin_flag()) {
268         this->_set_state(QUICSendStreamState::DataSent);
269       }
270     } else if (type == QUICFrameType::RESET_STREAM) {
271       this->_set_state(QUICSendStreamState::ResetSent);
272     }
273     break;
274   case QUICSendStreamState::DataSent:
275     if (type == QUICFrameType::RESET_STREAM) {
276       this->_set_state(QUICSendStreamState::ResetSent);
277     }
278     break;
279   case QUICSendStreamState::Init:
280   case QUICSendStreamState::Ready:
281   case QUICSendStreamState::DataRecvd:
282   case QUICSendStreamState::ResetSent:
283   case QUICSendStreamState::ResetRecvd:
284     break;
285   default:
286     ink_assert(!"Unknown state");
287     break;
288   }
289 }
290 
291 void
update_with_receiving_frame(const QUICFrame & frame)292 QUICSendStreamStateMachine::update_with_receiving_frame(const QUICFrame &frame)
293 {
294 }
295 
296 void
update_on_ack()297 QUICSendStreamStateMachine::update_on_ack()
298 {
299   if (this->_out_progress->is_transfer_complete()) {
300     this->_set_state(QUICSendStreamState::DataRecvd);
301   } else if (this->_out_progress->is_cancelled()) {
302     this->_set_state(QUICSendStreamState::ResetRecvd);
303   }
304 }
305 
306 void
update(const QUICReceiveStreamState state)307 QUICSendStreamStateMachine::update(const QUICReceiveStreamState state)
308 {
309   // The sending part of a bidirectional stream initiated by a peer (type 0 for a server, type 1 for a client) enters the “Ready”
310   // state then immediately transitions to the “Send” state if the receiving part enters the “Recv” state (Section 3.2).
311   switch (this->get()) {
312   case QUICSendStreamState::Ready:
313     if (state == QUICReceiveStreamState::Recv) {
314       this->_set_state(QUICSendStreamState::Send);
315     }
316     break;
317   default:
318     break;
319   }
320 }
321 
322 // ---------QUICBidirectionalStreamState -----------
323 
324 QUICBidirectionalStreamState
get() const325 QUICBidirectionalStreamStateMachine::get() const
326 {
327   QUICSendStreamState s_state    = this->_send_stream_state.get();
328   QUICReceiveStreamState r_state = this->_recv_stream_state.get();
329 
330   if (s_state == QUICSendStreamState::Ready || r_state == QUICReceiveStreamState::Init) {
331     return QUICBidirectionalStreamState::Idle;
332   } else if (s_state == QUICSendStreamState::Ready || s_state == QUICSendStreamState::Send ||
333              s_state == QUICSendStreamState::DataSent) {
334     if (r_state == QUICReceiveStreamState::Recv || r_state == QUICReceiveStreamState::SizeKnown) {
335       return QUICBidirectionalStreamState::Open;
336     } else if (r_state == QUICReceiveStreamState::DataRecvd || r_state == QUICReceiveStreamState::DataRead) {
337       return QUICBidirectionalStreamState::HC_R;
338     } else if (r_state == QUICReceiveStreamState::ResetRecvd || r_state == QUICReceiveStreamState::ResetRead) {
339       return QUICBidirectionalStreamState::HC_R;
340     } else {
341       ink_assert(false);
342       return QUICBidirectionalStreamState::Invalid;
343     }
344   } else if (s_state == QUICSendStreamState::DataRecvd) {
345     if (r_state == QUICReceiveStreamState::Recv || r_state == QUICReceiveStreamState::SizeKnown) {
346       return QUICBidirectionalStreamState::HC_L;
347     } else if (r_state == QUICReceiveStreamState::DataRecvd || r_state == QUICReceiveStreamState::DataRead) {
348       return QUICBidirectionalStreamState::Closed;
349     } else if (r_state == QUICReceiveStreamState::ResetRecvd || r_state == QUICReceiveStreamState::ResetRead) {
350       return QUICBidirectionalStreamState::Closed;
351     } else {
352       ink_assert(false);
353       return QUICBidirectionalStreamState::Invalid;
354     }
355   } else if (s_state == QUICSendStreamState::ResetSent || s_state == QUICSendStreamState::ResetRecvd) {
356     if (r_state == QUICReceiveStreamState::Recv || r_state == QUICReceiveStreamState::SizeKnown) {
357       return QUICBidirectionalStreamState::HC_L;
358     } else if (r_state == QUICReceiveStreamState::DataRecvd || r_state == QUICReceiveStreamState::DataRead) {
359       return QUICBidirectionalStreamState::Closed;
360     } else if (r_state == QUICReceiveStreamState::ResetRecvd || r_state == QUICReceiveStreamState::ResetRead) {
361       return QUICBidirectionalStreamState::Closed;
362     } else {
363       ink_assert(false);
364       return QUICBidirectionalStreamState::Invalid;
365     }
366   } else {
367     ink_assert(false);
368     return QUICBidirectionalStreamState::Invalid;
369   }
370 }
371 
372 void
update_with_sending_frame(const QUICFrame & frame)373 QUICBidirectionalStreamStateMachine::update_with_sending_frame(const QUICFrame &frame)
374 {
375   // The receiving part of a stream enters the “Recv” state when the sending part of a bidirectional stream initiated by the
376   // endpoint (type 0 for a client, type 1 for a server) enters the “Ready” state.
377   this->_send_stream_state.update_with_sending_frame(frame);
378   // PS: It should not happen because we initialize the send side and read side together. And the SendState has the default state
379   // "Ready". But to obey the specs, we do this as follow.
380   if (this->_send_stream_state.get() == QUICSendStreamState::Ready &&
381       this->_recv_stream_state.get() == QUICReceiveStreamState::Init) {
382     this->_recv_stream_state.update(this->_send_stream_state.get());
383   }
384 }
385 
386 void
update_with_receiving_frame(const QUICFrame & frame)387 QUICBidirectionalStreamStateMachine::update_with_receiving_frame(const QUICFrame &frame)
388 {
389   // The sending part of a bidirectional stream initiated by a peer (type 0 for a server, type 1 for a client) enters the “Ready”
390   // state then immediately transitions to the “Send” state if the receiving part enters the “Recv” state (Section 3.2).
391   this->_recv_stream_state.update_with_receiving_frame(frame);
392   if (this->_send_stream_state.get() == QUICSendStreamState::Ready &&
393       this->_recv_stream_state.get() == QUICReceiveStreamState::Recv) {
394     this->_send_stream_state.update(this->_recv_stream_state.get());
395   }
396 }
397 
398 void
update_on_ack()399 QUICBidirectionalStreamStateMachine::update_on_ack()
400 {
401   this->_send_stream_state.update_on_ack();
402 }
403 
404 void
update_on_read()405 QUICBidirectionalStreamStateMachine::update_on_read()
406 {
407   this->_recv_stream_state.update_on_read();
408 }
409 
410 void
update_on_eos()411 QUICBidirectionalStreamStateMachine::update_on_eos()
412 {
413   this->_recv_stream_state.update_on_eos();
414 }
415 
416 bool
is_allowed_to_send(const QUICFrame & frame) const417 QUICBidirectionalStreamStateMachine::is_allowed_to_send(const QUICFrame &frame) const
418 {
419   return this->is_allowed_to_send(frame.type());
420 }
421 
422 bool
is_allowed_to_send(QUICFrameType type) const423 QUICBidirectionalStreamStateMachine::is_allowed_to_send(QUICFrameType type) const
424 {
425   return this->_send_stream_state.is_allowed_to_send(type) || this->_recv_stream_state.is_allowed_to_send(type);
426 }
427 
428 bool
is_allowed_to_receive(const QUICFrame & frame) const429 QUICBidirectionalStreamStateMachine::is_allowed_to_receive(const QUICFrame &frame) const
430 {
431   return this->is_allowed_to_receive(frame.type());
432 }
433 
434 bool
is_allowed_to_receive(QUICFrameType type) const435 QUICBidirectionalStreamStateMachine::is_allowed_to_receive(QUICFrameType type) const
436 {
437   return this->_send_stream_state.is_allowed_to_receive(type) || this->_recv_stream_state.is_allowed_to_receive(type);
438 }
439