xref: /trafficserver/iocore/net/quic/Mock.h (revision 4f8cb034)
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 "P_Net.h"
27 
28 #include "QUICApplication.h"
29 #include "QUICStreamManager.h"
30 #include "QUICLossDetector.h"
31 #include "QUICEvents.h"
32 
33 class MockQUICContext;
34 
35 using namespace std::literals;
36 std::string_view negotiated_application_name_sv = "h3-23"sv;
37 
38 class MockQUICLDConfig : public QUICLDConfig
39 {
40   uint32_t
packet_threshold() const41   packet_threshold() const
42   {
43     return 3;
44   }
45 
46   float
time_threshold() const47   time_threshold() const
48   {
49     return 1.25;
50   }
51 
52   ink_hrtime
granularity() const53   granularity() const
54   {
55     return HRTIME_MSECONDS(1);
56   }
57 
58   ink_hrtime
initial_rtt() const59   initial_rtt() const
60   {
61     return HRTIME_MSECONDS(100);
62   }
63 };
64 
65 class MockQUICCCConfig : public QUICCCConfig
66 {
67   uint32_t
max_datagram_size() const68   max_datagram_size() const
69   {
70     return 1200;
71   }
72 
73   uint32_t
initial_window() const74   initial_window() const
75   {
76     return 10;
77   }
78 
79   uint32_t
minimum_window() const80   minimum_window() const
81   {
82     return 2;
83   }
84 
85   float
loss_reduction_factor() const86   loss_reduction_factor() const
87   {
88     return 0.5;
89   }
90 
91   uint32_t
persistent_congestion_threshold() const92   persistent_congestion_threshold() const
93   {
94     return 2;
95   }
96 };
97 
98 class MockQUICConnectionInfoProvider : public QUICConnectionInfoProvider
99 {
100   QUICConnectionId
connection_id() const101   connection_id() const override
102   {
103     return {reinterpret_cast<const uint8_t *>("\x00"), 1};
104   }
105 
106   QUICConnectionId
peer_connection_id() const107   peer_connection_id() const override
108   {
109     return {reinterpret_cast<const uint8_t *>("\x00"), 1};
110   }
111 
112   QUICConnectionId
original_connection_id() const113   original_connection_id() const override
114   {
115     return {reinterpret_cast<const uint8_t *>("\x00"), 1};
116   }
117 
118   QUICConnectionId
first_connection_id() const119   first_connection_id() const override
120   {
121     return {reinterpret_cast<const uint8_t *>("\x00"), 1};
122   }
123 
124   const QUICFiveTuple
five_tuple() const125   five_tuple() const override
126   {
127     return QUICFiveTuple();
128   }
129 
130   std::string_view
cids() const131   cids() const override
132   {
133     using namespace std::literals;
134     return std::string_view("00000000-00000000"sv);
135   }
136 
137   uint32_t
pmtu() const138   pmtu() const override
139   {
140     return 1280;
141   }
142 
143   NetVConnectionContext_t
direction() const144   direction() const override
145   {
146     return NET_VCONNECTION_OUT;
147   }
148 
149   int
select_next_protocol(SSL * ssl,const unsigned char ** out,unsigned char * outlen,const unsigned char * in,unsigned inlen) const150   select_next_protocol(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in,
151                        unsigned inlen) const override
152   {
153     return SSL_TLSEXT_ERR_OK;
154   }
155 
156   bool
is_closed() const157   is_closed() const override
158   {
159     return false;
160   }
161 
162   std::string_view
negotiated_application_name() const163   negotiated_application_name() const override
164   {
165     return negotiated_application_name_sv;
166   }
167 };
168 
169 class MockQUICStreamManager : public QUICStreamManager
170 {
171 public:
MockQUICStreamManager(QUICConnectionInfoProvider * info)172   MockQUICStreamManager(QUICConnectionInfoProvider *info) : QUICStreamManager(info, nullptr, nullptr) {}
173 
174   // Override
175   virtual QUICConnectionErrorUPtr
handle_frame(QUICEncryptionLevel level,const QUICFrame & f)176   handle_frame(QUICEncryptionLevel level, const QUICFrame &f) override
177   {
178     ++_frameCount[static_cast<int>(f.type())];
179     ++_totalFrameCount;
180 
181     return nullptr;
182   }
183 
184   // for Test
185   int
getStreamFrameCount()186   getStreamFrameCount()
187   {
188     return _frameCount[static_cast<int>(QUICFrameType::STREAM)];
189   }
190 
191   int
getAckFrameCount()192   getAckFrameCount()
193   {
194     return _frameCount[static_cast<int>(QUICFrameType::ACK)];
195   }
196 
197   int
getPingFrameCount()198   getPingFrameCount()
199   {
200     return _frameCount[static_cast<int>(QUICFrameType::PING)];
201   }
202 
203   int
getTotalFrameCount()204   getTotalFrameCount()
205   {
206     return _totalFrameCount;
207   }
208 
209 private:
210   int _totalFrameCount = 0;
211   int _frameCount[256] = {0};
212 };
213 
214 class MockNetVConnection : public NetVConnection
215 {
216 public:
MockNetVConnection(NetVConnectionContext_t context=NET_VCONNECTION_OUT)217   MockNetVConnection(NetVConnectionContext_t context = NET_VCONNECTION_OUT) : NetVConnection() { netvc_context = context; }
218   VIO *
do_io_read(Continuation * c,int64_t nbytes,MIOBuffer * buf)219   do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf)
220   {
221     return nullptr;
222   };
223   VIO *
do_io_write(Continuation * c,int64_t nbytes,IOBufferReader * buf,bool owner=false)224   do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *buf, bool owner = false)
225   {
226     return nullptr;
227   };
do_io_close(int lerrno=-1)228   void do_io_close(int lerrno = -1){};
do_io_shutdown(ShutdownHowTo_t howto)229   void do_io_shutdown(ShutdownHowTo_t howto){};
reenable(VIO * vio)230   void reenable(VIO *vio){};
reenable_re(VIO * vio)231   void reenable_re(VIO *vio){};
set_active_timeout(ink_hrtime timeout_in)232   void set_active_timeout(ink_hrtime timeout_in){};
set_inactivity_timeout(ink_hrtime timeout_in)233   void set_inactivity_timeout(ink_hrtime timeout_in){};
cancel_active_timeout()234   void cancel_active_timeout(){};
cancel_inactivity_timeout()235   void cancel_inactivity_timeout(){};
add_to_keep_alive_queue()236   void add_to_keep_alive_queue(){};
remove_from_keep_alive_queue()237   void remove_from_keep_alive_queue(){};
238   bool
add_to_active_queue()239   add_to_active_queue()
240   {
241     return true;
242   };
243   ink_hrtime
get_active_timeout()244   get_active_timeout()
245   {
246     return 0;
247   }
248   ink_hrtime
get_inactivity_timeout()249   get_inactivity_timeout()
250   {
251     return 0;
252   }
253   void
apply_options()254   apply_options()
255   {
256   }
257   SOCKET
get_socket()258   get_socket() { return 0; }
259   int
set_tcp_init_cwnd(int init_cwnd)260   set_tcp_init_cwnd(int init_cwnd)
261   {
262     return 0;
263   }
264   int
set_tcp_congestion_control(int side)265   set_tcp_congestion_control(int side)
266   {
267     return 0;
268   }
set_local_addr()269   void set_local_addr(){};
set_remote_addr()270   void set_remote_addr(){};
271 
272   NetVConnectionContext_t
get_context() const273   get_context() const
274   {
275     return netvc_context;
276   }
277 };
278 
279 class MockQUICConnection : public QUICConnection
280 {
281 public:
MockQUICConnection(NetVConnectionContext_t context=NET_VCONNECTION_OUT)282   MockQUICConnection(NetVConnectionContext_t context = NET_VCONNECTION_OUT) : QUICConnection(), _direction(context)
283   {
284     this->_mutex = new_ProxyMutex();
285   };
286 
287   QUICConnectionId
connection_id() const288   connection_id() const override
289   {
290     return {reinterpret_cast<const uint8_t *>("\x00"), 1};
291   }
292 
293   QUICConnectionId
peer_connection_id() const294   peer_connection_id() const override
295   {
296     return {reinterpret_cast<const uint8_t *>("\x00"), 1};
297   }
298 
299   QUICConnectionId
original_connection_id() const300   original_connection_id() const override
301   {
302     return {reinterpret_cast<const uint8_t *>("\x00"), 1};
303   }
304 
305   QUICConnectionId
first_connection_id() const306   first_connection_id() const override
307   {
308     return {reinterpret_cast<const uint8_t *>("\x00"), 1};
309   }
310 
311   const QUICFiveTuple
five_tuple() const312   five_tuple() const override
313   {
314     return QUICFiveTuple();
315   }
316 
317   std::string_view
cids() const318   cids() const override
319   {
320     using namespace std::literals;
321     return std::string_view("00000000-00000000"sv);
322   }
323 
324   std::vector<QUICFrameType>
interests()325   interests() override
326   {
327     return {QUICFrameType::CONNECTION_CLOSE};
328   }
329 
330   QUICConnectionErrorUPtr
handle_frame(QUICEncryptionLevel level,const QUICFrame & f)331   handle_frame(QUICEncryptionLevel level, const QUICFrame &f) override
332   {
333     ++_frameCount[static_cast<int>(f.type())];
334     ++_totalFrameCount;
335 
336     return nullptr;
337   }
338 
339   uint32_t
pmtu() const340   pmtu() const override
341   {
342     return 1280;
343   }
344 
345   NetVConnectionContext_t
direction() const346   direction() const override
347   {
348     return _direction;
349   }
350 
351   void
close(QUICConnectionErrorUPtr error)352   close(QUICConnectionErrorUPtr error) override
353   {
354   }
355 
356   int
getTotalFrameCount()357   getTotalFrameCount()
358   {
359     return _totalFrameCount;
360   }
361 
362   QUICStreamManager *
stream_manager()363   stream_manager() override
364   {
365     return &_stream_manager;
366   }
367 
368   bool
is_closed() const369   is_closed() const override
370   {
371     return false;
372   }
373 
374   void
handle_received_packet(UDPPacket *)375   handle_received_packet(UDPPacket *) override
376   {
377   }
378 
379   void
ping()380   ping() override
381   {
382   }
383 
384   std::string_view
negotiated_application_name() const385   negotiated_application_name() const override
386   {
387     return negotiated_application_name_sv;
388   }
389 
390   int
select_next_protocol(SSL * ssl,const unsigned char ** out,unsigned char * outlen,const unsigned char * in,unsigned inlen) const391   select_next_protocol(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in,
392                        unsigned inlen) const override
393   {
394     return SSL_TLSEXT_ERR_OK;
395   }
396 
397   int _transmit_count   = 0;
398   int _retransmit_count = 0;
399   Ptr<ProxyMutex> _mutex;
400   int _totalFrameCount                  = 0;
401   int _frameCount[256]                  = {0};
402   MockQUICStreamManager _stream_manager = {this};
403 
404   QUICTransportParametersInEncryptedExtensions dummy_transport_parameters();
405   NetVConnectionContext_t _direction;
406 };
407 
408 class MockQUICCongestionController : public QUICCongestionController
409 {
410 public:
MockQUICCongestionController()411   MockQUICCongestionController() {}
412   // Override
413   virtual void
on_packets_lost(const std::map<QUICPacketNumber,QUICPacketInfo * > & packets)414   on_packets_lost(const std::map<QUICPacketNumber, QUICPacketInfo *> &packets) override
415   {
416     for (auto &p : packets) {
417       lost_packets.insert(p.first);
418     }
419   }
420 
421   virtual void
on_packet_sent(size_t bytes_sent)422   on_packet_sent(size_t bytes_sent) override
423   {
424   }
425   virtual void
on_packet_acked(const QUICPacketInfo & acked_packet)426   on_packet_acked(const QUICPacketInfo &acked_packet) override
427   {
428   }
429   virtual void
process_ecn(const QUICPacketInfo & acked_largest_packet,const QUICAckFrame::EcnSection * ecn_section)430   process_ecn(const QUICPacketInfo &acked_largest_packet, const QUICAckFrame::EcnSection *ecn_section) override
431   {
432   }
433   virtual void
add_extra_credit()434   add_extra_credit() override
435   {
436   }
437   virtual void
reset()438   reset() override
439   {
440   }
441   virtual uint32_t
credit() const442   credit() const override
443   {
444     return 0;
445   }
446 
447   // for Test
448   int
getStreamFrameCount()449   getStreamFrameCount()
450   {
451     return _frameCount[static_cast<int>(QUICFrameType::STREAM)];
452   }
453 
454   int
getAckFrameCount()455   getAckFrameCount()
456   {
457     return _frameCount[static_cast<int>(QUICFrameType::ACK)];
458   }
459 
460   int
getPingFrameCount()461   getPingFrameCount()
462   {
463     return _frameCount[static_cast<int>(QUICFrameType::PING)];
464   }
465 
466   int
getTotalFrameCount()467   getTotalFrameCount()
468   {
469     return _totalFrameCount;
470   }
471 
472   std::set<QUICPacketNumber> lost_packets;
473 
474 private:
475   int _totalFrameCount = 0;
476   int _frameCount[256] = {0};
477 };
478 
479 class MockQUICPacketProtectionKeyInfo : public QUICPacketProtectionKeyInfo
480 {
481 public:
482   const EVP_CIPHER *
get_cipher(QUICKeyPhase phase) const483   get_cipher(QUICKeyPhase phase) const override
484   {
485     return EVP_aes_128_gcm();
486   }
487 
488   size_t
get_tag_len(QUICKeyPhase phase) const489   get_tag_len(QUICKeyPhase phase) const override
490   {
491     return EVP_GCM_TLS_TAG_LEN;
492   }
493 
encryption_iv_len(QUICKeyPhase) const494   const size_t *encryption_iv_len(QUICKeyPhase) const override
495   {
496     static size_t dummy = 12;
497     return &dummy;
498   }
499 };
500 
501 class MockQUICContext : public QUICContext, public QUICLDContext, public QUICCCContext
502 {
503 public:
MockQUICContext()504   MockQUICContext()
505   {
506     _info      = std::make_unique<MockQUICConnectionInfoProvider>();
507     _key_info  = std::make_unique<MockQUICPacketProtectionKeyInfo>();
508     _ld_config = std::make_unique<MockQUICLDConfig>();
509     _cc_config = std::make_unique<MockQUICCCConfig>();
510   }
511 
512   virtual QUICConnectionInfoProvider *
connection_info() const513   connection_info() const override
514   {
515     return _info.get();
516   }
517   virtual QUICConfig::scoped_config
config() const518   config() const override
519   {
520     return _config;
521   }
522   virtual QUICRTTProvider *
rtt_provider() const523   rtt_provider() const override
524   {
525     return const_cast<QUICRTTMeasure *>(&_rtt_measure);
526   }
527 
528   virtual QUICPacketProtectionKeyInfo *
key_info() const529   key_info() const override
530   {
531     return _key_info.get();
532   }
533 
534   virtual QUICLDConfig &
ld_config() const535   ld_config() const override
536   {
537     return *_ld_config;
538   }
539 
540   virtual QUICCCConfig &
cc_config() const541   cc_config() const override
542   {
543     return *_cc_config;
544   }
545 
546 private:
547   QUICConfig::scoped_config _config;
548   QUICRTTMeasure _rtt_measure;
549   std::unique_ptr<QUICConnectionInfoProvider> _info;
550   std::unique_ptr<QUICPacketProtectionKeyInfo> _key_info;
551   std::unique_ptr<QUICLDConfig> _ld_config;
552   std::unique_ptr<QUICCCConfig> _cc_config;
553 };
554 
555 class MockQUICLossDetector : public QUICLossDetector
556 {
557 public:
MockQUICLossDetector(MockQUICContext & context)558   MockQUICLossDetector(MockQUICContext &context)
559     : QUICLossDetector(context, &_cc, &_rtt_measure, &this->_pinger, &this->_padder),
560       _padder(NetVConnectionContext_t::NET_VCONNECTION_UNSET)
561   {
562   }
rcv_frame(std::shared_ptr<const QUICFrame>)563   void rcv_frame(std::shared_ptr<const QUICFrame>) {}
564 
565   void
on_packet_sent(QUICPacketUPtr packet)566   on_packet_sent(QUICPacketUPtr packet)
567   {
568   }
569 
570 private:
571   QUICPinger _pinger;
572   QUICPadder _padder;
573   QUICRTTMeasure _rtt_measure;
574   MockQUICCongestionController _cc;
575 };
576 
577 class MockQUICApplication : public QUICApplication
578 {
579 public:
MockQUICApplication(QUICConnection * c)580   MockQUICApplication(QUICConnection *c) : QUICApplication(c) { SET_HANDLER(&MockQUICApplication::main_event_handler); }
581 
582   int
main_event_handler(int event,Event * data)583   main_event_handler(int event, Event *data)
584   {
585     if (event == 12345) {
586       QUICStreamIO *stream_io = static_cast<QUICStreamIO *>(data->cookie);
587       stream_io->write_reenable();
588     }
589     return EVENT_CONT;
590   }
591 
592   void
send(const uint8_t * data,size_t size,QUICStreamId stream_id)593   send(const uint8_t *data, size_t size, QUICStreamId stream_id)
594   {
595     QUICStreamIO *stream_io = this->_find_stream_io(stream_id);
596     stream_io->write(data, size);
597 
598     eventProcessor.schedule_imm(this, ET_CALL, 12345, stream_io);
599   }
600 };
601 
602 class MockQUICPacket : public QUICPacket
603 {
604 public:
605   const IpEndpoint &
from() const606   from() const override
607   {
608     return this->_from;
609   }
610 
611   const IpEndpoint &
to() const612   to() const override
613   {
614     return this->_to;
615   }
616 
617   void
set_to(const IpEndpoint ep)618   set_to(const IpEndpoint ep)
619   {
620     this->_to = ep;
621   }
622 
623   void
set_from(const IpEndpoint ep)624   set_from(const IpEndpoint ep)
625   {
626     this->_from = ep;
627   }
628 
629 private:
630   IpEndpoint _to;
631   IpEndpoint _from;
632 };
633 
634 class MockQUICHandshakeProtocol : public QUICHandshakeProtocol
635 {
636 public:
MockQUICHandshakeProtocol(QUICPacketProtectionKeyInfo & pp_key_info)637   MockQUICHandshakeProtocol(QUICPacketProtectionKeyInfo &pp_key_info) : QUICHandshakeProtocol(pp_key_info) {}
638 
639   int
handshake(QUICHandshakeMsgs * out,const QUICHandshakeMsgs * in)640   handshake(QUICHandshakeMsgs *out, const QUICHandshakeMsgs *in) override
641   {
642     return true;
643   }
644 
645   void
reset()646   reset() override
647   {
648   }
649 
650   bool
is_handshake_finished() const651   is_handshake_finished() const override
652   {
653     return true;
654   }
655 
656   bool
is_ready_to_derive() const657   is_ready_to_derive() const override
658   {
659     return true;
660   }
661 
662   int
initialize_key_materials(QUICConnectionId cid)663   initialize_key_materials(QUICConnectionId cid) override
664   {
665     return 0;
666   }
667 
668   const char *
negotiated_cipher_suite() const669   negotiated_cipher_suite() const override
670   {
671     return nullptr;
672   }
673 
674   void
negotiated_application_name(const uint8_t ** name,unsigned int * len) const675   negotiated_application_name(const uint8_t **name, unsigned int *len) const override
676   {
677     *name = reinterpret_cast<const uint8_t *>("h3");
678     *len  = 2;
679   }
680 
681   QUICEncryptionLevel
current_encryption_level() const682   current_encryption_level() const override
683   {
684     return QUICEncryptionLevel::INITIAL;
685   }
686 
687   void
abort_handshake()688   abort_handshake() override
689   {
690     return;
691   }
692 
693   std::shared_ptr<const QUICTransportParameters>
local_transport_parameters()694   local_transport_parameters() override
695   {
696     return nullptr;
697   }
698 
699   std::shared_ptr<const QUICTransportParameters>
remote_transport_parameters()700   remote_transport_parameters() override
701   {
702     return nullptr;
703   }
704 
705   void
set_local_transport_parameters(std::shared_ptr<const QUICTransportParameters> tp)706   set_local_transport_parameters(std::shared_ptr<const QUICTransportParameters> tp) override
707   {
708   }
709 
710   void
set_remote_transport_parameters(std::shared_ptr<const QUICTransportParameters> tp)711   set_remote_transport_parameters(std::shared_ptr<const QUICTransportParameters> tp) override
712   {
713   }
714 };
715 
716 class MockContinuation : public Continuation
717 {
718 public:
MockContinuation(Ptr<ProxyMutex> m)719   MockContinuation(Ptr<ProxyMutex> m) : Continuation(m) { SET_HANDLER(&MockContinuation::event_handler); }
720   int
event_handler(int event,Event * data)721   event_handler(int event, Event *data)
722   {
723     return EVENT_CONT;
724   }
725 };
726 
727 class MockQUICRTTProvider : public QUICRTTProvider
728 {
729   ink_hrtime
latest_rtt() const730   latest_rtt() const override
731   {
732     return HRTIME_MSECONDS(1);
733   }
734 
735   ink_hrtime
rttvar() const736   rttvar() const override
737   {
738     return HRTIME_MSECONDS(1);
739   }
740 
741   ink_hrtime
smoothed_rtt() const742   smoothed_rtt() const override
743   {
744     return HRTIME_MSECONDS(1);
745   }
746 
747   ink_hrtime
congestion_period(uint32_t threshold) const748   congestion_period(uint32_t threshold) const override
749   {
750     return HRTIME_MSECONDS(1);
751   }
752 };
753 
754 class MockQUICTransferProgressProvider : public QUICTransferProgressProvider
755 {
756 public:
757   bool
is_transfer_goal_set() const758   is_transfer_goal_set() const override
759   {
760     return false;
761   }
762 
763   bool
is_transfer_complete() const764   is_transfer_complete() const override
765   {
766     return this->_is_transfer_complete || this->_transfer_progress >= this->_transfer_goal;
767   }
768 
769   bool
is_cancelled() const770   is_cancelled() const override
771   {
772     return this->_is_reset_complete;
773   }
774 
775   uint64_t
transfer_progress() const776   transfer_progress() const override
777   {
778     return this->_transfer_progress;
779   }
780 
781   uint64_t
transfer_goal() const782   transfer_goal() const override
783   {
784     return this->_transfer_goal;
785   }
786 
787   void
set_transfer_complete(bool b)788   set_transfer_complete(bool b)
789   {
790     this->_is_transfer_complete = b;
791   }
792 
793   void
set_cancelled(bool b)794   set_cancelled(bool b)
795   {
796     this->_is_reset_complete = b;
797   }
798 
799   void
set_transfer_progress(uint64_t v)800   set_transfer_progress(uint64_t v)
801   {
802     this->_transfer_progress = v;
803   }
804 
805   void
set_transfer_goal(uint64_t v)806   set_transfer_goal(uint64_t v)
807   {
808     this->_transfer_goal = v;
809   }
810 
811 private:
812   bool _is_transfer_complete  = false;
813   bool _is_reset_complete     = false;
814   uint64_t _transfer_progress = 0;
815   uint64_t _transfer_goal     = UINT64_MAX;
816 };
817 
818 class MockQUICFrameGenerator : public QUICFrameGenerator
819 {
820 public:
821   bool
will_generate_frame(QUICEncryptionLevel level,size_t connection_credit,bool ack_eliciting,uint32_t seq_num)822   will_generate_frame(QUICEncryptionLevel level, size_t connection_credit, bool ack_eliciting, uint32_t seq_num) override
823   {
824     return true;
825   }
826 
827   QUICFrame *
generate_frame(uint8_t * buf,QUICEncryptionLevel level,uint64_t connection_credit,uint16_t maximum_frame_size,size_t current_packet_size,uint32_t seq_num)828   generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size,
829                  size_t current_packet_size, uint32_t seq_num) override
830   {
831     QUICFrame *frame              = QUICFrameFactory::create_ping_frame(buf, 0, this);
832     QUICFrameInformationUPtr info = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
833     this->_records_frame(0, std::move(info));
834     return frame;
835   }
836 
837   int lost_frame_count = 0;
838 
839 private:
840   void
_on_frame_lost(QUICFrameInformationUPtr & info)841   _on_frame_lost(QUICFrameInformationUPtr &info) override
842   {
843     lost_frame_count++;
844   }
845 };
846