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 "catch.hpp"
25 
26 #include "QUICFrameRetransmitter.h"
27 
28 constexpr static uint8_t data[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x01, 0x02, 0x03, 0x04, 0x05,
29                                    0x06, 0x07, 0x08, 0x09, 0x10, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10};
30 
31 TEST_CASE("QUICFrameRetransmitter ignore frame which can not be retranmistted", "[quic]")
32 {
33   QUICFrameRetransmitter retransmitter;
34   QUICFrameInformationUPtr info = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
35   info->type                    = QUICFrameType::PING;
36   info->level                   = QUICEncryptionLevel::NONE;
37 
38   retransmitter.save_frame_info(std::move(info));
39   uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE];
40   CHECK(retransmitter.create_retransmitted_frame(frame_buf, QUICEncryptionLevel::INITIAL, UINT16_MAX) == nullptr);
41 }
42 
43 // TEST_CASE("QUICFrameRetransmitter ignore frame which can not be split", "[quic]")
44 // {
45 //   QUICFrameRetransmitter retransmitter;
46 //   QUICFrameInformationUPtr info = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
47 //   info->type                    = QUICFrameType::STOP_SENDING;
48 //   info->level                   = QUICEncryptionLevel::NONE;
49 //
50 //   retransmitter.save_frame_info(info);
51 //   CHECK(retransmitter.create_retransmitted_frame(QUICEncryptionLevel::INITIAL, 0) == nullptr);
52 // }
53 
54 TEST_CASE("QUICFrameRetransmitter ignore frame which has wrong level", "[quic]")
55 {
56   QUICFrameRetransmitter retransmitter;
57   QUICFrameInformationUPtr info = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
58   info->type                    = QUICFrameType::STREAM;
59   info->level                   = QUICEncryptionLevel::HANDSHAKE;
60 
61   retransmitter.save_frame_info(std::move(info));
62   uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE];
63   CHECK(retransmitter.create_retransmitted_frame(frame_buf, QUICEncryptionLevel::INITIAL, UINT16_MAX) == nullptr);
64 }
65 
66 TEST_CASE("QUICFrameRetransmitter successfully create retransmitted frame", "[quic]")
67 {
68   QUICFrameRetransmitter retransmitter;
69   QUICFrameInformationUPtr info = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
70   info->type                    = QUICFrameType::STREAM;
71   info->level                   = QUICEncryptionLevel::INITIAL;
72 
73   Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
74   block->alloc();
75   memcpy(block->start(), data, sizeof(data));
76   block->fill(sizeof(data));
77 
78   StreamFrameInfo *frame_info = reinterpret_cast<StreamFrameInfo *>(info->data);
79   frame_info->stream_id       = 0x12345;
80   frame_info->offset          = 0x67890;
81   frame_info->block           = block;
82 
83   retransmitter.save_frame_info(std::move(info));
84 
85   uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE];
86   auto frame = retransmitter.create_retransmitted_frame(frame_buf, QUICEncryptionLevel::INITIAL, UINT16_MAX);
87   CHECK(frame != nullptr);
88   CHECK(frame->type() == QUICFrameType::STREAM);
89 }
90 
91 TEST_CASE("QUICFrameRetransmitter successfully create stream frame", "[quic]")
92 {
93   QUICFrameRetransmitter retransmitter;
94   QUICFrameInformationUPtr info = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
95   info->type                    = QUICFrameType::STREAM;
96   info->level                   = QUICEncryptionLevel::INITIAL;
97 
98   Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
99   block->alloc();
100   memcpy(block->start(), data, sizeof(data));
101   block->fill(sizeof(data));
102 
103   StreamFrameInfo *frame_info = reinterpret_cast<StreamFrameInfo *>(info->data);
104   frame_info->stream_id       = 0x12345;
105   frame_info->offset          = 0x67890;
106   frame_info->block           = block;
107 
108   CHECK(block->refcount() == 2);
109   retransmitter.save_frame_info(std::move(info));
110   CHECK(block->refcount() == 2); // block's refcount doesn't change
111 
112   uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE];
113   auto frame = retransmitter.create_retransmitted_frame(frame_buf, QUICEncryptionLevel::INITIAL, UINT16_MAX);
114   CHECK(frame != nullptr);
115   CHECK(frame->type() == QUICFrameType::STREAM);
116   auto stream_frame = static_cast<QUICStreamFrame *>(frame);
117   CHECK(stream_frame->stream_id() == 0x12345);
118   CHECK(stream_frame->offset() == 0x67890);
119   CHECK(stream_frame->data_length() == sizeof(data));
120   CHECK(memcmp(stream_frame->data()->start(), data, sizeof(data)) == 0);
121   std::destroy_at(frame);
122   frame = nullptr;
123   // Becasue the info has been released, the refcount should be 1 (var block).
124   CHECK(block->refcount() == 1);
125 }
126 
127 TEST_CASE("QUICFrameRetransmitter successfully split stream frame", "[quic]")
128 {
129   QUICFrameRetransmitter retransmitter;
130   QUICFrameInformationUPtr info = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
131   info->type                    = QUICFrameType::STREAM;
132   info->level                   = QUICEncryptionLevel::INITIAL;
133 
134   Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
135   block->alloc();
136   memcpy(block->start(), data, sizeof(data));
137   block->fill(sizeof(data));
138 
139   StreamFrameInfo *frame_info = reinterpret_cast<StreamFrameInfo *>(info->data);
140   frame_info->stream_id       = 0x12345;
141   frame_info->offset          = 0x67890;
142   frame_info->block           = block;
143   CHECK(block->refcount() == 2);
144 
145   retransmitter.save_frame_info(std::move(info));
146 
147   uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE];
148   auto frame = retransmitter.create_retransmitted_frame(frame_buf, QUICEncryptionLevel::INITIAL, 25);
149   CHECK(frame != nullptr);
150   CHECK(frame->type() == QUICFrameType::STREAM);
151   auto stream_frame = static_cast<QUICStreamFrame *>(frame);
152   CHECK(stream_frame->stream_id() == 0x12345);
153   CHECK(stream_frame->offset() == 0x67890);
154   CHECK(stream_frame->size() <= 25);
155 
156   auto size = stream_frame->data_length();
157   CHECK(memcmp(stream_frame->data()->start(), data, stream_frame->data_length()) == 0);
158   // one for var block, one for the left data which saved in retransmitter
159   CHECK(block->data->refcount() == 2);
160   // one for var block, one for the left data which saved in retransmitter, one for var frame
161   CHECK(block->refcount() == 2);
162   std::destroy_at(frame);
163   frame = nullptr;
164   // one for var block, one for var info
165   CHECK(block->refcount() == 2);
166   CHECK(block->data->refcount() == 1);
167 
168   frame = retransmitter.create_retransmitted_frame(frame_buf, QUICEncryptionLevel::INITIAL, UINT16_MAX);
169   CHECK(frame != nullptr);
170   CHECK(frame->type() == QUICFrameType::STREAM);
171   stream_frame = static_cast<QUICStreamFrame *>(frame);
172   CHECK(stream_frame->stream_id() == 0x12345);
173   CHECK(stream_frame->offset() == 0x67890 + size);
174   CHECK(stream_frame->data_length() == sizeof(data) - size);
175   CHECK(memcmp(stream_frame->data()->start(), data + size, stream_frame->data_length()) == 0);
176   CHECK(block->refcount() == 1); // one for var block
177 
178   std::destroy_at(frame);
179   frame = nullptr;
180   CHECK(block->refcount() == 1);
181   CHECK(block->data->refcount() == 1);
182 }
183 
184 TEST_CASE("QUICFrameRetransmitter successfully split crypto frame", "[quic]")
185 {
186   QUICFrameRetransmitter retransmitter;
187   QUICFrameInformationUPtr info = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
188   info->type                    = QUICFrameType::CRYPTO;
189   info->level                   = QUICEncryptionLevel::INITIAL;
190 
191   Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
192   block->alloc();
193   memcpy(block->start(), data, sizeof(data));
194   block->fill(sizeof(data));
195 
196   CryptoFrameInfo *frame_info = reinterpret_cast<CryptoFrameInfo *>(info->data);
197   frame_info->offset          = 0x67890;
198   frame_info->block           = block;
199   CHECK(block->refcount() == 2);
200 
201   retransmitter.save_frame_info(std::move(info));
202 
203   uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE];
204   auto frame = retransmitter.create_retransmitted_frame(frame_buf, QUICEncryptionLevel::INITIAL, 25);
205   CHECK(frame != nullptr);
206   CHECK(frame->type() == QUICFrameType::CRYPTO);
207   auto crypto_frame = static_cast<QUICCryptoFrame *>(frame);
208   CHECK(crypto_frame->offset() == 0x67890);
209   CHECK(crypto_frame->size() <= 25);
210 
211   auto size = crypto_frame->data_length();
212   CHECK(memcmp(crypto_frame->data()->start(), data, crypto_frame->data_length()) == 0);
213   // one for var block, one for the left data which saved in retransmitter
214   CHECK(block->data->refcount() == 2);
215   // one for var block, one for the left data which saved in retransmitter, one for var frame
216   CHECK(block->refcount() == 2);
217   std::destroy_at(frame);
218   frame = nullptr;
219   // one for var block, one for var info
220   CHECK(block->refcount() == 2);
221   CHECK(block->data->refcount() == 1);
222 
223   frame = retransmitter.create_retransmitted_frame(frame_buf, QUICEncryptionLevel::INITIAL, UINT16_MAX);
224   CHECK(frame != nullptr);
225   CHECK(frame->type() == QUICFrameType::CRYPTO);
226   crypto_frame = static_cast<QUICCryptoFrame *>(frame);
227   CHECK(crypto_frame->offset() == 0x67890 + size);
228   CHECK(crypto_frame->data_length() == sizeof(data) - size);
229   CHECK(memcmp(crypto_frame->data()->start(), data + size, crypto_frame->data_length()) == 0);
230   CHECK(block->refcount() == 1); // one for var block
231 
232   std::destroy_at(frame);
233   frame = nullptr;
234   CHECK(block->refcount() == 1);
235   CHECK(block->data->refcount() == 1);
236 }
237 
238 TEST_CASE("QUICFrameRetransmitter successfully split stream frame with fin flag", "[quic]")
239 {
240   QUICFrameRetransmitter retransmitter;
241   QUICFrameInformationUPtr info = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
242   info->type                    = QUICFrameType::STREAM;
243   info->level                   = QUICEncryptionLevel::INITIAL;
244 
245   Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
246   block->alloc();
247   memcpy(block->start(), data, sizeof(data));
248   block->fill(sizeof(data));
249 
250   StreamFrameInfo *frame_info = reinterpret_cast<StreamFrameInfo *>(info->data);
251   frame_info->stream_id       = 0x12345;
252   frame_info->offset          = 0x67890;
253   frame_info->block           = block;
254   frame_info->has_fin         = true;
255   CHECK(block->refcount() == 2);
256 
257   retransmitter.save_frame_info(std::move(info));
258 
259   uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE];
260   auto frame = retransmitter.create_retransmitted_frame(frame_buf, QUICEncryptionLevel::INITIAL, 25);
261   CHECK(frame != nullptr);
262   CHECK(frame->type() == QUICFrameType::STREAM);
263   auto stream_frame = static_cast<QUICStreamFrame *>(frame);
264   CHECK(stream_frame->stream_id() == 0x12345);
265   CHECK(stream_frame->offset() == 0x67890);
266   CHECK(stream_frame->size() <= 25);
267   CHECK(stream_frame->has_fin_flag() == false);
268 
269   auto size = stream_frame->data_length();
270   CHECK(memcmp(stream_frame->data()->start(), data, stream_frame->data_length()) == 0);
271   // one for var block, one for the left data which saved in retransmitter
272   CHECK(block->data->refcount() == 2);
273   // one for var block, one for the left data which saved in retransmitter, one for var frame
274   CHECK(block->refcount() == 2);
275   std::destroy_at(frame);
276   frame = nullptr;
277   // one for var block, one for var info
278   CHECK(block->refcount() == 2);
279   CHECK(block->data->refcount() == 1);
280 
281   frame = retransmitter.create_retransmitted_frame(frame_buf, QUICEncryptionLevel::INITIAL, UINT16_MAX);
282   CHECK(frame != nullptr);
283   CHECK(frame->type() == QUICFrameType::STREAM);
284   stream_frame = static_cast<QUICStreamFrame *>(frame);
285   CHECK(stream_frame->stream_id() == 0x12345);
286   CHECK(stream_frame->offset() == 0x67890 + size);
287   CHECK(stream_frame->data_length() == sizeof(data) - size);
288   CHECK(memcmp(stream_frame->data()->start(), data + size, stream_frame->data_length()) == 0);
289   CHECK(block->refcount() == 1); // one for var block
290   CHECK(stream_frame->has_fin_flag() == true);
291 
292   std::destroy_at(frame);
293   frame = nullptr;
294   CHECK(block->refcount() == 1);
295   CHECK(block->data->refcount() == 1);
296 }
297