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 #pragma once
25 
26 #include <memory>
27 #include <yaml-cpp/yaml.h>
28 
29 #include "QUICFrame.h"
30 
31 namespace QLog
32 {
33 class QLogFrame
34 {
35 public:
QLogFrame(QUICFrameType type)36   QLogFrame(QUICFrameType type) : _type(type) {}
~QLogFrame()37   virtual ~QLogFrame() {}
38 
39   QUICFrameType
type()40   type() const
41   {
42     return this->_type;
43   }
44 
45   // encode frame into YAML stype
46   virtual void encode(YAML::Node &node) = 0;
47 
48 protected:
49   QUICFrameType _type = QUICFrameType::UNKNOWN;
50 };
51 
52 using QLogFrameUPtr = std::unique_ptr<QLogFrame>;
53 
54 //
55 // convert QUICFrame to QLogFrame
56 //
57 class QLogFrameFactory
58 {
59 public:
60   // create QLogFrame
61   static QLogFrameUPtr create(const QUICFrame *frame);
62 };
63 
64 namespace Frame
65 {
66   struct AckFrame : public QLogFrame {
AckFrameAckFrame67     AckFrame(const QUICAckFrame &frame) : QLogFrame(frame.type())
68     {
69       acked_range = frame.ranges();
70       ack_delay   = frame.ack_delay();
71       if (frame.ecn_section()) {
72         ect0 = frame.ecn_section()->ect0_count();
73         ect1 = frame.ecn_section()->ect1_count();
74         ce   = frame.ecn_section()->ecn_ce_count();
75       }
76     }
77 
78     void encode(YAML::Node &) override;
79 
80     std::set<QUICAckFrame::PacketNumberRange> acked_range;
81     uint64_t ect1      = 0;
82     uint64_t ect0      = 0;
83     uint64_t ce        = 0;
84     uint64_t ack_delay = 0;
85   };
86 
87   struct StreamFrame : public QLogFrame {
StreamFrameStreamFrame88     StreamFrame(const QUICStreamFrame &frame) : QLogFrame(frame.type())
89     {
90       stream_id = std::to_string(static_cast<uint64_t>(frame.stream_id()));
91       offset    = std::to_string(static_cast<uint64_t>(frame.offset()));
92       length    = frame.data_length();
93       fin       = frame.has_fin_flag();
94     }
95 
96     void encode(YAML::Node &) override;
97     std::string stream_id;
98 
99     // These two MUST always be set
100     // If not present in the Frame type, log their default values
101     std::string offset;
102     uint64_t length = 0;
103 
104     // this MAY be set any time, but MUST only be set if the value is "true"
105     // if absent, the value MUST be assumed to be "false"
106     bool fin = false;
107 
108     // FIXME raw
109   };
110 
111   struct PaddingFrame : public QLogFrame {
PaddingFramePaddingFrame112     PaddingFrame(const QUICPaddingFrame &frame) : QLogFrame(frame.type()) {}
113     void encode(YAML::Node &) override;
114   };
115 
116   struct PingFrame : public QLogFrame {
PingFramePingFrame117     PingFrame(const QUICPingFrame &frame) : QLogFrame(frame.type()) {}
118     void encode(YAML::Node &) override;
119   };
120 
121   struct RstStreamFrame : public QLogFrame {
RstStreamFrameRstStreamFrame122     RstStreamFrame(const QUICRstStreamFrame &frame) : QLogFrame(frame.type())
123     {
124       stream_id  = std::to_string(static_cast<uint64_t>(frame.stream_id()));
125       error_code = frame.error_code();
126       final_size = std::to_string(frame.final_offset());
127     }
128 
129     void encode(YAML::Node &) override;
130     std::string stream_id;
131     // FIXME ApplicationError
132     uint64_t error_code = 0;
133     std::string final_size;
134   };
135 
136   struct StopSendingFrame : public QLogFrame {
StopSendingFrameStopSendingFrame137     StopSendingFrame(const QUICStopSendingFrame &frame) : QLogFrame(frame.type())
138     {
139       stream_id  = std::to_string(static_cast<uint64_t>(frame.stream_id()));
140       error_code = frame.error_code();
141     }
142 
143     void encode(YAML::Node &) override;
144     std::string stream_id;
145     // FIXME ApplicationError
146     uint64_t error_code = 0;
147   };
148 
149   struct CryptoFrame : public QLogFrame {
CryptoFrameCryptoFrame150     CryptoFrame(const QUICCryptoFrame &frame) : QLogFrame(frame.type())
151     {
152       offset = std::to_string(static_cast<uint64_t>(frame.offset()));
153       length = frame.data_length();
154     }
155 
156     void encode(YAML::Node &) override;
157     std::string offset;
158     uint64_t length = 0;
159   };
160 
161   struct NewTokenFrame : public QLogFrame {
NewTokenFrameNewTokenFrame162     NewTokenFrame(const QUICNewTokenFrame &frame) : QLogFrame(frame.type())
163     {
164       token  = QUICBase::to_hex(frame.token(), frame.token_length());
165       length = frame.token_length();
166     }
167 
168     void encode(YAML::Node &) override;
169     std::string token;
170     uint64_t length = 0;
171   };
172 
173   struct MaxDataFrame : public QLogFrame {
MaxDataFrameMaxDataFrame174     MaxDataFrame(const QUICMaxDataFrame &frame) : QLogFrame(frame.type()), maximum(std::to_string(frame.maximum_data())) {}
175 
176     void encode(YAML::Node &) override;
177     std::string maximum;
178   };
179 
180   struct MaxStreamDataFrame : public QLogFrame {
MaxStreamDataFrameMaxStreamDataFrame181     MaxStreamDataFrame(const QUICMaxStreamDataFrame &frame) : QLogFrame(frame.type())
182     {
183       stream_id = std::to_string(static_cast<uint64_t>(frame.stream_id()));
184       maximum   = std::to_string(frame.maximum_stream_data());
185     }
186 
187     void encode(YAML::Node &) override;
188     std::string stream_id;
189     std::string maximum;
190   };
191 
192   struct MaxStreamsFrame : public QLogFrame {
MaxStreamsFrameMaxStreamsFrame193     MaxStreamsFrame(const QUICMaxStreamsFrame &frame) : QLogFrame(frame.type())
194     {
195       maximum = std::to_string(frame.maximum_streams());
196       // FIXME
197       stream_type = "bidirectional";
198     }
199 
200     void encode(YAML::Node &) override;
201     std::string stream_type;
202     std::string maximum;
203   };
204 
205   struct DataBlockedFrame : public QLogFrame {
DataBlockedFrameDataBlockedFrame206     DataBlockedFrame(const QUICDataBlockedFrame &frame) : QLogFrame(frame.type())
207     {
208       limit = std::to_string(static_cast<uint64_t>(frame.offset()));
209     }
210     void encode(YAML::Node &) override;
211     std::string limit;
212   };
213 
214   struct StreamDataBlockedFrame : public QLogFrame {
StreamDataBlockedFrameStreamDataBlockedFrame215     StreamDataBlockedFrame(const QUICStreamDataBlockedFrame &frame) : QLogFrame(frame.type())
216     {
217       limit     = std::to_string(static_cast<uint64_t>(frame.offset()));
218       stream_id = std::to_string(static_cast<uint64_t>(frame.stream_id()));
219     }
220 
221     void encode(YAML::Node &) override;
222     std::string stream_id, limit;
223   };
224 
225   struct StreamsBlockedFrame : public QLogFrame {
StreamsBlockedFrameStreamsBlockedFrame226     StreamsBlockedFrame(const QUICStreamIdBlockedFrame &frame) : QLogFrame(frame.type())
227     {
228       stream_type = "bidirectional";
229       stream_id   = std::to_string(static_cast<uint64_t>(frame.stream_id()));
230     }
231 
232     void encode(YAML::Node &) override;
233     std::string stream_id, stream_type;
234   };
235 
236   struct NewConnectionIDFrame : public QLogFrame {
NewConnectionIDFrameNewConnectionIDFrame237     NewConnectionIDFrame(const QUICNewConnectionIdFrame &frame)
238       : QLogFrame(frame.type()), sequence_number(std::to_string(frame.sequence()))
239     {
240       retire_prior_to       = std::to_string(frame.retire_prior_to());
241       connection_id         = frame.connection_id().hex();
242       stateless_reset_token = QUICBase::to_hex(frame.stateless_reset_token().buf(), QUICStatelessResetToken::LEN);
243       length                = frame.connection_id().length();
244     }
245 
246     void encode(YAML::Node &) override;
247     std::string sequence_number, retire_prior_to, connection_id, stateless_reset_token;
248     uint8_t length = 0;
249   };
250 
251   struct RetireConnectionIDFrame : public QLogFrame {
RetireConnectionIDFrameRetireConnectionIDFrame252     RetireConnectionIDFrame(const QUICRetireConnectionIdFrame &frame)
253       : QLogFrame(frame.type()), sequence_number(std::to_string(frame.seq_num()))
254     {
255     }
256     void encode(YAML::Node &) override;
257     std::string sequence_number;
258   };
259 
260   struct PathChallengeFrame : public QLogFrame {
PathChallengeFramePathChallengeFrame261     PathChallengeFrame(const QUICPathChallengeFrame &frame)
262       : QLogFrame(frame.type()), data(QUICBase::to_hex(frame.data(), QUICPathChallengeFrame::DATA_LEN))
263     {
264     }
265     void encode(YAML::Node &) override;
266     std::string data;
267   };
268 
269   struct PathResponseFrame : public QLogFrame {
PathResponseFramePathResponseFrame270     PathResponseFrame(const QUICPathResponseFrame &frame)
271       : QLogFrame(frame.type()), data(QUICBase::to_hex(frame.data(), QUICPathChallengeFrame::DATA_LEN))
272     {
273     }
274     void encode(YAML::Node &) override;
275     std::string data;
276   };
277 
278   struct ConnectionCloseFrame : public QLogFrame {
279     ConnectionCloseFrame(const QUICConnectionCloseFrame &frame, bool app = false)
280       : QLogFrame(frame.type()), error_space(app ? "application" : "transport")
281     {
282       error_code = frame.error_code();
283       // FIXME
284       raw_error_code = error_code;
285       reason         = frame.reason_phrase();
286     }
287 
288     void encode(YAML::Node &) override;
289     std::string error_space, reason, trigger_frame_type;
290     uint64_t error_code, raw_error_code;
291   };
292 
293   struct HandshakeDoneFrame : public QLogFrame {
HandshakeDoneFrameHandshakeDoneFrame294     HandshakeDoneFrame(const QUICHandshakeDoneFrame &frame) : QLogFrame(frame.type()){};
295     void encode(YAML::Node &) override;
296   };
297 
298   struct UnknownFrame : public QLogFrame {
UnknownFrameUnknownFrame299     UnknownFrame(const QUICUnknownFrame &frame) : QLogFrame(frame.type())
300     {
301       // FIXME
302       raw_frame_type = static_cast<uint8_t>(frame.type());
303     }
304 
305     void encode(YAML::Node &) override;
306     uint8_t raw_frame_type = 0;
307   };
308 } // namespace Frame
309 } // namespace QLog
310