xref: /trafficserver/iocore/net/quic/QUICStream.cc (revision 88909bcf)
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 "QUICStream.h"
25 
26 #include "QUICStreamManager.h"
27 
28 constexpr uint32_t MAX_STREAM_FRAME_OVERHEAD = 24;
29 
QUICStream(QUICConnectionInfoProvider * cinfo,QUICStreamId sid)30 QUICStream::QUICStream(QUICConnectionInfoProvider *cinfo, QUICStreamId sid) : _connection_info(cinfo), _id(sid) {}
31 
~QUICStream()32 QUICStream::~QUICStream() {}
33 
34 QUICStreamId
id() const35 QUICStream::id() const
36 {
37   return this->_id;
38 }
39 
40 QUICStreamDirection
direction() const41 QUICStream::direction() const
42 {
43   return QUICTypeUtil::detect_stream_direction(this->_id, this->_connection_info->direction());
44 }
45 
46 const QUICConnectionInfoProvider *
connection_info() const47 QUICStream::connection_info() const
48 {
49   return this->_connection_info;
50 }
51 
52 bool
is_bidirectional() const53 QUICStream::is_bidirectional() const
54 {
55   return ((this->_id & 0x03) < 0x02);
56 }
57 
58 QUICOffset
final_offset() const59 QUICStream::final_offset() const
60 {
61   // TODO Return final offset
62   return 0;
63 }
64 
65 QUICOffset
reordered_bytes() const66 QUICStream::reordered_bytes() const
67 {
68   return this->_reordered_bytes;
69 }
70 
71 QUICConnectionErrorUPtr
recv(const QUICStreamFrame & frame)72 QUICStream::recv(const QUICStreamFrame &frame)
73 {
74   return nullptr;
75 }
76 
77 QUICConnectionErrorUPtr
recv(const QUICMaxStreamDataFrame & frame)78 QUICStream::recv(const QUICMaxStreamDataFrame &frame)
79 {
80   return nullptr;
81 }
82 
83 QUICConnectionErrorUPtr
recv(const QUICStreamDataBlockedFrame & frame)84 QUICStream::recv(const QUICStreamDataBlockedFrame &frame)
85 {
86   return nullptr;
87 }
88 
89 QUICConnectionErrorUPtr
recv(const QUICStopSendingFrame & frame)90 QUICStream::recv(const QUICStopSendingFrame &frame)
91 {
92   return nullptr;
93 }
94 
95 QUICConnectionErrorUPtr
recv(const QUICRstStreamFrame & frame)96 QUICStream::recv(const QUICRstStreamFrame &frame)
97 {
98   return nullptr;
99 }
100 
101 QUICConnectionErrorUPtr
recv(const QUICCryptoFrame & frame)102 QUICStream::recv(const QUICCryptoFrame &frame)
103 {
104   return nullptr;
105 }
106 
107 void
_records_stream_frame(QUICEncryptionLevel level,const QUICStreamFrame & frame)108 QUICStream::_records_stream_frame(QUICEncryptionLevel level, const QUICStreamFrame &frame)
109 {
110   QUICFrameInformationUPtr info = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
111   info->type                    = frame.type();
112   info->level                   = level;
113   StreamFrameInfo *frame_info   = reinterpret_cast<StreamFrameInfo *>(info->data);
114   frame_info->stream_id         = frame.stream_id();
115   frame_info->offset            = frame.offset();
116   frame_info->has_fin           = frame.has_fin_flag();
117   frame_info->block             = frame.data();
118   this->_records_frame(frame.id(), std::move(info));
119 }
120 
121 void
_records_rst_stream_frame(QUICEncryptionLevel level,const QUICRstStreamFrame & frame)122 QUICStream::_records_rst_stream_frame(QUICEncryptionLevel level, const QUICRstStreamFrame &frame)
123 {
124   QUICFrameInformationUPtr info  = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
125   info->type                     = frame.type();
126   info->level                    = level;
127   RstStreamFrameInfo *frame_info = reinterpret_cast<RstStreamFrameInfo *>(info->data);
128   frame_info->error_code         = frame.error_code();
129   frame_info->final_offset       = frame.final_offset();
130   this->_records_frame(frame.id(), std::move(info));
131 }
132 
133 void
_records_stop_sending_frame(QUICEncryptionLevel level,const QUICStopSendingFrame & frame)134 QUICStream::_records_stop_sending_frame(QUICEncryptionLevel level, const QUICStopSendingFrame &frame)
135 {
136   QUICFrameInformationUPtr info    = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
137   info->type                       = frame.type();
138   info->level                      = level;
139   StopSendingFrameInfo *frame_info = reinterpret_cast<StopSendingFrameInfo *>(info->data);
140   frame_info->error_code           = frame.error_code();
141   this->_records_frame(frame.id(), std::move(info));
142 }
143 
144 void
_records_crypto_frame(QUICEncryptionLevel level,const QUICCryptoFrame & frame)145 QUICStream::_records_crypto_frame(QUICEncryptionLevel level, const QUICCryptoFrame &frame)
146 {
147   QUICFrameInformationUPtr info      = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
148   info->type                         = QUICFrameType::CRYPTO;
149   info->level                        = level;
150   CryptoFrameInfo *crypto_frame_info = reinterpret_cast<CryptoFrameInfo *>(info->data);
151   crypto_frame_info->offset          = frame.offset();
152   crypto_frame_info->block           = frame.data();
153   this->_records_frame(frame.id(), std::move(info));
154 }
155 
156 void
reset(QUICStreamErrorUPtr error)157 QUICStream::reset(QUICStreamErrorUPtr error)
158 {
159 }
160 
161 void
stop_sending(QUICStreamErrorUPtr error)162 QUICStream::stop_sending(QUICStreamErrorUPtr error)
163 {
164 }
165 
166 QUICOffset
largest_offset_received() const167 QUICStream::largest_offset_received() const
168 {
169   return 0;
170 }
171 
172 QUICOffset
largest_offset_sent() const173 QUICStream::largest_offset_sent() const
174 {
175   return 0;
176 }
177 
178 void
on_eos()179 QUICStream::on_eos()
180 {
181 }
182 
183 void
on_read()184 QUICStream::on_read()
185 {
186 }
187 
188 //
189 // QUICStreamVConnection
190 //
~QUICStreamVConnection()191 QUICStreamVConnection::~QUICStreamVConnection()
192 {
193   if (this->_read_event) {
194     this->_read_event->cancel();
195     this->_read_event = nullptr;
196   }
197 
198   if (this->_write_event) {
199     this->_write_event->cancel();
200     this->_write_event = nullptr;
201   }
202 }
203 
204 void
_write_to_read_vio(QUICOffset offset,const uint8_t * data,uint64_t data_length,bool fin)205 QUICStreamVConnection::_write_to_read_vio(QUICOffset offset, const uint8_t *data, uint64_t data_length, bool fin)
206 {
207   SCOPED_MUTEX_LOCK(lock, this->_read_vio.mutex, this_ethread());
208 
209   uint64_t bytes_added = this->_read_vio.buffer.writer()->write(data, data_length);
210 
211   // Until receive FIN flag, keep nbytes INT64_MAX
212   if (fin && bytes_added == data_length) {
213     this->_read_vio.nbytes = offset + data_length;
214   }
215 }
216 
217 /**
218  * Replace existing event only if the new event is different than the inprogress event
219  */
220 Event *
_send_tracked_event(Event * event,int send_event,VIO * vio)221 QUICStreamVConnection::_send_tracked_event(Event *event, int send_event, VIO *vio)
222 {
223   if (event != nullptr) {
224     if (event->callback_event != send_event) {
225       event->cancel();
226       event = nullptr;
227     }
228   }
229 
230   if (event == nullptr) {
231     event = this_ethread()->schedule_imm(this, send_event, vio);
232   }
233 
234   return event;
235 }
236 
237 /**
238  * @brief Signal event to this->_read_vio.cont
239  */
240 void
_signal_read_event()241 QUICStreamVConnection::_signal_read_event()
242 {
243   if (this->_read_vio.cont == nullptr || this->_read_vio.op == VIO::NONE) {
244     return;
245   }
246   MUTEX_TRY_LOCK(lock, this->_read_vio.mutex, this_ethread());
247 
248   int event = this->_read_vio.ntodo() ? VC_EVENT_READ_READY : VC_EVENT_READ_COMPLETE;
249 
250   if (lock.is_locked()) {
251     this->_read_vio.cont->handleEvent(event, &this->_read_vio);
252   } else {
253     this_ethread()->schedule_imm(this->_read_vio.cont, event, &this->_read_vio);
254   }
255 }
256 
257 /**
258  * @brief Signal event to this->_write_vio.cont
259  */
260 void
_signal_write_event()261 QUICStreamVConnection::_signal_write_event()
262 {
263   if (this->_write_vio.cont == nullptr || this->_write_vio.op == VIO::NONE) {
264     return;
265   }
266   MUTEX_TRY_LOCK(lock, this->_write_vio.mutex, this_ethread());
267 
268   int event = this->_write_vio.ntodo() ? VC_EVENT_WRITE_READY : VC_EVENT_WRITE_COMPLETE;
269 
270   if (lock.is_locked()) {
271     this->_write_vio.cont->handleEvent(event, &this->_write_vio);
272   } else {
273     this_ethread()->schedule_imm(this->_write_vio.cont, event, &this->_write_vio);
274   }
275 }
276 
277 /**
278  * @brief Signal event to this->_write_vio.cont
279  */
280 void
_signal_read_eos_event()281 QUICStreamVConnection::_signal_read_eos_event()
282 {
283   if (this->_read_vio.cont == nullptr || this->_read_vio.op == VIO::NONE) {
284     return;
285   }
286   MUTEX_TRY_LOCK(lock, this->_read_vio.mutex, this_ethread());
287 
288   int event = VC_EVENT_EOS;
289 
290   if (lock.is_locked()) {
291     this->_write_vio.cont->handleEvent(event, &this->_write_vio);
292   } else {
293     this_ethread()->schedule_imm(this->_read_vio.cont, event, &this->_read_vio);
294   }
295 }
296 
297 int64_t
_process_read_vio()298 QUICStreamVConnection::_process_read_vio()
299 {
300   if (this->_read_vio.cont == nullptr || this->_read_vio.op == VIO::NONE) {
301     return 0;
302   }
303 
304   // Pass through. Read operation is done by QUICStream::recv(const std::shared_ptr<const QUICStreamFrame> frame)
305   // TODO: 1. pop frame from _received_stream_frame_buffer
306   //       2. write data to _read_vio
307 
308   return 0;
309 }
310 
311 /**
312  * @brief Send STREAM DATA from _response_buffer
313  * @detail Call _signal_write_event() to indicate event upper layer
314  */
315 int64_t
_process_write_vio()316 QUICStreamVConnection::_process_write_vio()
317 {
318   if (this->_write_vio.cont == nullptr || this->_write_vio.op == VIO::NONE) {
319     return 0;
320   }
321 
322   return 0;
323 }
324