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 #include <climits>
24 #include <string>
25 
26 #include "tscore/ink_config.h"
27 #include "records/I_RecHttp.h"
28 #include "tscore/Diags.h"
29 
30 #include "P_Net.h"
31 #include "InkAPIInternal.h" // Added to include the quic_hook definitions
32 #include "Log.h"
33 
34 #include "P_SSLNextProtocolSet.h"
35 #include "QUICMultiCertConfigLoader.h"
36 #include "QUICTLS.h"
37 
38 #include "QUICStats.h"
39 #include "QUICGlobals.h"
40 #include "QUICDebugNames.h"
41 #include "QUICEvents.h"
42 #include "QUICConfig.h"
43 #include "QUICIntUtil.h"
44 
45 using namespace std::literals;
46 static constexpr std::string_view QUIC_DEBUG_TAG = "quic_net"sv;
47 
48 #define QUICConDebug(fmt, ...) Debug(QUIC_DEBUG_TAG.data(), "[%s] " fmt, this->cids().data(), ##__VA_ARGS__)
49 
50 #define QUICConVDebug(fmt, ...) Debug("v_quic_net", "[%s] " fmt, this->cids().data(), ##__VA_ARGS__)
51 #define QUICConVVVDebug(fmt, ...) Debug("vvv_quic_net", "[%s] " fmt, this->cids().data(), ##__VA_ARGS__)
52 
53 #define QUICFCDebug(fmt, ...) Debug("quic_flow_ctrl", "[%s] " fmt, this->cids().data(), ##__VA_ARGS__)
54 
55 #define QUICError(fmt, ...)                                           \
56   Debug("quic_net", "[%s] " fmt, this->cids().data(), ##__VA_ARGS__); \
57   Error("quic_net [%s] " fmt, this->cids().data(), ##__VA_ARGS__)
58 
59 static constexpr uint32_t IPV4_HEADER_SIZE            = 20;
60 static constexpr uint32_t IPV6_HEADER_SIZE            = 40;
61 static constexpr uint32_t UDP_HEADER_SIZE             = 8;
62 static constexpr uint32_t MAX_PACKET_OVERHEAD         = 62; ///< Max long header len without length of token field of Initial packet
63 static constexpr uint32_t MINIMUM_INITIAL_PACKET_SIZE = 1200;
64 static constexpr ink_hrtime WRITE_READY_INTERVAL      = HRTIME_MSECONDS(2);
65 static constexpr uint32_t PACKET_PER_EVENT            = 256;
66 static constexpr uint32_t MAX_CONSECUTIVE_STREAMS     = 8; ///< Interrupt sending STREAM frames to send ACK frame
67 // static constexpr uint32_t MIN_PKT_PAYLOAD_LEN         = 3; ///< Minimum payload length for sampling for header protection
68 
69 static constexpr uint32_t STATE_CLOSING_MAX_SEND_PKT_NUM  = 8; ///< Max number of sending packets which contain a closing frame.
70 static constexpr uint32_t STATE_CLOSING_MAX_RECV_PKT_WIND = 1 << STATE_CLOSING_MAX_SEND_PKT_NUM;
71 
72 ClassAllocator<QUICNetVConnection> quicNetVCAllocator("quicNetVCAllocator");
73 
74 class QUICTPConfigQCP : public QUICTPConfig
75 {
76 public:
QUICTPConfigQCP(const QUICConfigParams * params,NetVConnectionContext_t ctx)77   QUICTPConfigQCP(const QUICConfigParams *params, NetVConnectionContext_t ctx) : _params(params), _ctx(ctx) {}
78 
79   uint32_t
no_activity_timeout() const80   no_activity_timeout() const override
81   {
82     if (this->_ctx == NET_VCONNECTION_IN) {
83       return this->_params->no_activity_timeout_in();
84     } else {
85       return this->_params->no_activity_timeout_out();
86     }
87   }
88 
89   const IpEndpoint *
preferred_address_ipv4() const90   preferred_address_ipv4() const override
91   {
92     return this->_params->preferred_address_ipv4();
93   }
94 
95   const IpEndpoint *
preferred_address_ipv6() const96   preferred_address_ipv6() const override
97   {
98     return this->_params->preferred_address_ipv6();
99   }
100 
101   uint32_t
initial_max_data() const102   initial_max_data() const override
103   {
104     if (this->_ctx == NET_VCONNECTION_IN) {
105       return this->_params->initial_max_data_in();
106     } else {
107       return this->_params->initial_max_data_out();
108     }
109   }
110 
111   uint32_t
initial_max_stream_data_bidi_local() const112   initial_max_stream_data_bidi_local() const override
113   {
114     if (this->_ctx == NET_VCONNECTION_IN) {
115       return this->_params->initial_max_stream_data_bidi_local_in();
116     } else {
117       return this->_params->initial_max_stream_data_bidi_local_out();
118     }
119   }
120 
121   uint32_t
initial_max_stream_data_bidi_remote() const122   initial_max_stream_data_bidi_remote() const override
123   {
124     if (this->_ctx == NET_VCONNECTION_IN) {
125       return this->_params->initial_max_stream_data_bidi_remote_in();
126     } else {
127       return this->_params->initial_max_stream_data_bidi_remote_out();
128     }
129   }
130 
131   uint32_t
initial_max_stream_data_uni() const132   initial_max_stream_data_uni() const override
133   {
134     if (this->_ctx == NET_VCONNECTION_IN) {
135       return this->_params->initial_max_stream_data_uni_in();
136     } else {
137       return this->_params->initial_max_stream_data_uni_out();
138     }
139   }
140 
141   uint64_t
initial_max_streams_bidi() const142   initial_max_streams_bidi() const override
143   {
144     if (this->_ctx == NET_VCONNECTION_IN) {
145       return this->_params->initial_max_streams_bidi_in();
146     } else {
147       return this->_params->initial_max_streams_bidi_out();
148     }
149   }
150 
151   uint64_t
initial_max_streams_uni() const152   initial_max_streams_uni() const override
153   {
154     if (this->_ctx == NET_VCONNECTION_IN) {
155       return this->_params->initial_max_streams_uni_in();
156     } else {
157       return this->_params->initial_max_streams_uni_out();
158     }
159   }
160 
161   uint8_t
ack_delay_exponent() const162   ack_delay_exponent() const override
163   {
164     if (this->_ctx == NET_VCONNECTION_IN) {
165       return this->_params->ack_delay_exponent_in();
166     } else {
167       return this->_params->ack_delay_exponent_out();
168     }
169   }
170 
171   uint8_t
max_ack_delay() const172   max_ack_delay() const override
173   {
174     if (this->_ctx == NET_VCONNECTION_IN) {
175       return this->_params->max_ack_delay_in();
176     } else {
177       return this->_params->max_ack_delay_out();
178     }
179   }
180 
181   uint8_t
active_cid_limit() const182   active_cid_limit() const override
183   {
184     if (this->_ctx == NET_VCONNECTION_IN) {
185       return this->_params->active_cid_limit_in();
186     } else {
187       return this->_params->active_cid_limit_out();
188     }
189   }
190 
191 private:
192   const QUICConfigParams *_params;
193   NetVConnectionContext_t _ctx;
194 };
195 
QUICNetVConnection()196 QUICNetVConnection::QUICNetVConnection() : _packet_factory(this->_pp_key_info), _ph_protector(this->_pp_key_info) {}
197 
~QUICNetVConnection()198 QUICNetVConnection::~QUICNetVConnection()
199 {
200   this->_unschedule_ack_manager_periodic();
201   this->_unschedule_packet_write_ready();
202   this->_unschedule_closing_timeout();
203   this->_unschedule_closed_event();
204 }
205 
206 // XXX This might be called on ET_UDP thread
207 // Initialize QUICNetVC for out going connection (NET_VCONNECTION_OUT)
208 void
init(QUICConnectionId peer_cid,QUICConnectionId original_cid,UDPConnection * udp_con,QUICPacketHandler * packet_handler)209 QUICNetVConnection::init(QUICConnectionId peer_cid, QUICConnectionId original_cid, UDPConnection *udp_con,
210                          QUICPacketHandler *packet_handler)
211 {
212   SET_HANDLER((NetVConnHandler)&QUICNetVConnection::startEvent);
213   this->_udp_con                     = udp_con;
214   this->_packet_handler              = packet_handler;
215   this->_peer_quic_connection_id     = peer_cid;
216   this->_original_quic_connection_id = original_cid;
217   this->_quic_connection_id.randomize();
218 
219   this->_update_cids();
220 
221   if (is_debug_tag_set(QUIC_DEBUG_TAG.data())) {
222     char dcid_hex_str[QUICConnectionId::MAX_HEX_STR_LENGTH];
223     char scid_hex_str[QUICConnectionId::MAX_HEX_STR_LENGTH];
224     this->_peer_quic_connection_id.hex(dcid_hex_str, QUICConnectionId::MAX_HEX_STR_LENGTH);
225     this->_quic_connection_id.hex(scid_hex_str, QUICConnectionId::MAX_HEX_STR_LENGTH);
226 
227     QUICConDebug("dcid=%s scid=%s", dcid_hex_str, scid_hex_str);
228   }
229 }
230 
231 // Initialize QUICNetVC for in coming connection (NET_VCONNECTION_IN)
232 void
init(QUICConnectionId peer_cid,QUICConnectionId original_cid,QUICConnectionId first_cid,UDPConnection * udp_con,QUICPacketHandler * packet_handler,QUICConnectionTable * ctable)233 QUICNetVConnection::init(QUICConnectionId peer_cid, QUICConnectionId original_cid, QUICConnectionId first_cid,
234                          UDPConnection *udp_con, QUICPacketHandler *packet_handler, QUICConnectionTable *ctable)
235 {
236   SET_HANDLER((NetVConnHandler)&QUICNetVConnection::acceptEvent);
237   this->_udp_con                     = udp_con;
238   this->_packet_handler              = packet_handler;
239   this->_peer_quic_connection_id     = peer_cid;
240   this->_original_quic_connection_id = original_cid;
241   this->_first_quic_connection_id    = first_cid;
242   this->_quic_connection_id.randomize();
243 
244   if (ctable) {
245     this->_ctable = ctable;
246     this->_ctable->insert(this->_quic_connection_id, this);
247     this->_ctable->insert(this->_original_quic_connection_id, this);
248   }
249 
250   this->_update_cids();
251 
252   if (is_debug_tag_set(QUIC_DEBUG_TAG.data())) {
253     char dcid_hex_str[QUICConnectionId::MAX_HEX_STR_LENGTH];
254     char scid_hex_str[QUICConnectionId::MAX_HEX_STR_LENGTH];
255     this->_peer_quic_connection_id.hex(dcid_hex_str, QUICConnectionId::MAX_HEX_STR_LENGTH);
256     this->_quic_connection_id.hex(scid_hex_str, QUICConnectionId::MAX_HEX_STR_LENGTH);
257 
258     QUICConDebug("dcid=%s scid=%s", dcid_hex_str, scid_hex_str);
259   }
260 }
261 
262 bool
shouldDestroy()263 QUICNetVConnection::shouldDestroy()
264 {
265   return this->refcount() == 0;
266 }
267 
268 VIO *
do_io_read(Continuation * c,int64_t nbytes,MIOBuffer * buf)269 QUICNetVConnection::do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf)
270 {
271   ink_assert(false);
272   return nullptr;
273 }
274 
275 VIO *
do_io_write(Continuation * c,int64_t nbytes,IOBufferReader * buf,bool owner)276 QUICNetVConnection::do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *buf, bool owner)
277 {
278   ink_assert(false);
279   return nullptr;
280 }
281 
282 int
acceptEvent(int event,Event * e)283 QUICNetVConnection::acceptEvent(int event, Event *e)
284 {
285   EThread *t    = (e == nullptr) ? this_ethread() : e->ethread;
286   NetHandler *h = get_NetHandler(t);
287 
288   MUTEX_TRY_LOCK(lock, h->mutex, t);
289   if (!lock.is_locked()) {
290     if (event == EVENT_NONE) {
291       t->schedule_in(this, HRTIME_MSECONDS(net_retry_delay));
292       return EVENT_DONE;
293     } else {
294       e->schedule_in(HRTIME_MSECONDS(net_retry_delay));
295       return EVENT_CONT;
296     }
297   }
298 
299   // this->thread is already assigned by QUICPacketHandlerIn::_recv_packet
300   ink_assert(this->thread == this_ethread());
301 
302   // Send this NetVC to NetHandler and start to polling read & write event.
303   if (h->startIO(this) < 0) {
304     free(t);
305     return EVENT_DONE;
306   }
307 
308   // FIXME: complete do_io_xxxx instead
309   this->read.enabled = 1;
310 
311   // Handshake callback handler.
312   SET_HANDLER((NetVConnHandler)&QUICNetVConnection::state_pre_handshake);
313 
314   // Send this netvc to InactivityCop.
315   nh->startCop(this);
316 
317   if (inactivity_timeout_in) {
318     set_inactivity_timeout(inactivity_timeout_in);
319   } else {
320     set_inactivity_timeout(0);
321   }
322 
323   if (active_timeout_in) {
324     set_active_timeout(active_timeout_in);
325   }
326 
327   this->start();
328 
329   action_.continuation->handleEvent(NET_EVENT_ACCEPT, this);
330   this->_schedule_packet_write_ready();
331 
332   return EVENT_DONE;
333 }
334 
335 int
startEvent(int event,Event * e)336 QUICNetVConnection::startEvent(int event, Event *e)
337 {
338   ink_assert(event == EVENT_IMMEDIATE);
339   MUTEX_TRY_LOCK(lock, get_NetHandler(e->ethread)->mutex, e->ethread);
340   if (!lock.is_locked()) {
341     e->schedule_in(HRTIME_MSECONDS(net_retry_delay));
342     return EVENT_CONT;
343   }
344 
345   if (!action_.cancelled) {
346     this->connectUp(e->ethread, NO_FD);
347   } else {
348     this->free(e->ethread);
349   }
350 
351   return EVENT_DONE;
352 }
353 
354 // XXX This might be called on ET_UDP thread
355 void
start()356 QUICNetVConnection::start()
357 {
358   ink_release_assert(this->thread != nullptr);
359   this->_context = std::make_unique<QUICContextImpl>(&this->_rtt_measure, this, &this->_pp_key_info);
360   this->_five_tuple.update(this->local_addr, this->remote_addr, SOCK_DGRAM);
361   QUICPath trusted_path = {{}, {}};
362   // Version 0x00000001 uses stream 0 for cryptographic handshake with TLS 1.3, but newer version may not
363   if (this->direction() == NET_VCONNECTION_IN) {
364     QUICCertConfig::scoped_config server_cert;
365 
366     this->_pp_key_info.set_context(QUICPacketProtectionKeyInfo::Context::SERVER);
367     this->_ack_frame_manager.set_ack_delay_exponent(this->_quic_config->ack_delay_exponent_in());
368     this->_reset_token = QUICStatelessResetToken(this->_quic_connection_id, this->_quic_config->instance_id());
369     this->_hs_protocol = this->_setup_handshake_protocol(server_cert->ssl_default);
370     this->_handshake_handler =
371       new QUICHandshake(this, this->_hs_protocol, this->_reset_token, this->_quic_config->stateless_retry());
372     this->_ack_frame_manager.set_max_ack_delay(this->_quic_config->max_ack_delay_in());
373     this->_schedule_ack_manager_periodic(this->_quic_config->max_ack_delay_in());
374   } else {
375     trusted_path = {this->local_addr, this->remote_addr};
376     QUICTPConfigQCP tp_config(this->_quic_config, NET_VCONNECTION_OUT);
377     this->_pp_key_info.set_context(QUICPacketProtectionKeyInfo::Context::CLIENT);
378     this->_ack_frame_manager.set_ack_delay_exponent(this->_quic_config->ack_delay_exponent_out());
379     this->_hs_protocol       = this->_setup_handshake_protocol(this->_quic_config->client_ssl_ctx());
380     this->_handshake_handler = new QUICHandshake(this, this->_hs_protocol);
381     this->_handshake_handler->start(tp_config, &this->_packet_factory, this->_quic_config->vn_exercise_enabled());
382     this->_handshake_handler->do_handshake();
383     this->_ack_frame_manager.set_max_ack_delay(this->_quic_config->max_ack_delay_out());
384     this->_schedule_ack_manager_periodic(this->_quic_config->max_ack_delay_out());
385   }
386 
387   this->_application_map = new QUICApplicationMap();
388 
389   this->_frame_dispatcher = new QUICFrameDispatcher(this);
390 
391   // Create frame handlers
392   this->_pinger = new QUICPinger();
393   this->_padder = new QUICPadder(this->netvc_context);
394   this->_rtt_measure.init(this->_context->ld_config());
395   this->_congestion_controller = new QUICNewRenoCongestionController(*_context);
396   this->_loss_detector =
397     new QUICLossDetector(*_context, this->_congestion_controller, &this->_rtt_measure, this->_pinger, this->_padder);
398   this->_frame_dispatcher->add_handler(this->_loss_detector);
399 
400   this->_remote_flow_controller = new QUICRemoteConnectionFlowController(UINT64_MAX);
401   this->_local_flow_controller  = new QUICLocalConnectionFlowController(&this->_rtt_measure, UINT64_MAX);
402   this->_path_validator         = new QUICPathValidator(*this, [this](bool succeeded) {
403     if (succeeded) {
404       this->_alt_con_manager->drop_cid(this->_peer_old_quic_connection_id);
405       // FIXME This is a kind of workaround for connection migration.
406       // This PING make peer to send an ACK frame so that ATS can detect packet loss.
407       // It would be better if QUICLossDetector could detect the loss in another way.
408       this->ping();
409     }
410   });
411   this->_stream_manager         = new QUICStreamManager(this, &this->_rtt_measure, this->_application_map);
412   this->_path_manager           = new QUICPathManager(*this, *this->_path_validator);
413   this->_path_manager->set_trusted_path(trusted_path);
414   this->_token_creator = new QUICTokenCreator(this->_context.get());
415 
416   static constexpr int QUIC_STREAM_MANAGER_WEIGHT = QUICFrameGeneratorWeight::AFTER_DATA - 1;
417   static constexpr int QUIC_PINGER_WEIGHT         = QUICFrameGeneratorWeight::LATE + 1;
418   static constexpr int QUIC_PADDER_WEIGHT         = QUICFrameGeneratorWeight::LATE + 2;
419 
420   // Register frame generators
421   this->_frame_generators.add_generator(*this->_handshake_handler, QUICFrameGeneratorWeight::EARLY); // CRYPTO
422   this->_frame_generators.add_generator(*this->_path_validator, QUICFrameGeneratorWeight::EARLY); // PATH_CHALLENGE, PATH_RESPOSNE
423   this->_frame_generators.add_generator(*this->_local_flow_controller, QUICFrameGeneratorWeight::BEFORE_DATA);  // MAX_DATA
424   this->_frame_generators.add_generator(*this->_remote_flow_controller, QUICFrameGeneratorWeight::BEFORE_DATA); // DATA_BLOCKED
425   this->_frame_generators.add_generator(*this->_token_creator, QUICFrameGeneratorWeight::BEFORE_DATA);          // NEW_TOKEN
426   this->_frame_generators.add_generator(*this->_stream_manager,
427                                         QUIC_STREAM_MANAGER_WEIGHT); // STREAM, MAX_STREAM_DATA, STREAM_DATA_BLOCKED
428   this->_frame_generators.add_generator(this->_ack_frame_manager, QUICFrameGeneratorWeight::BEFORE_DATA); // ACK
429 
430   this->_frame_generators.add_generator(*this->_pinger, QUIC_PINGER_WEIGHT); // PING
431   // Warning: padder should be tail of the frame generators
432   this->_frame_generators.add_generator(*this->_padder, QUIC_PADDER_WEIGHT); // PADDING
433 
434   // Register frame handlers
435   this->_frame_dispatcher->add_handler(this);
436   this->_frame_dispatcher->add_handler(this->_stream_manager);
437   this->_frame_dispatcher->add_handler(this->_path_validator);
438   this->_frame_dispatcher->add_handler(this->_handshake_handler);
439 }
440 
441 void
free(EThread * t)442 QUICNetVConnection::free(EThread *t)
443 {
444   QUICConDebug("Free connection");
445 
446   /* TODO: Uncmment these blocks after refactoring read / write process
447     this->_udp_con        = nullptr;
448     this->_packet_handler = nullptr;
449 
450     _unschedule_packet_write_ready();
451 
452     delete this->_handshake_handler;
453     delete this->_application_map;
454     delete this->_hs_protocol;
455     delete this->_loss_detector;
456     delete this->_frame_dispatcher;
457     delete this->_stream_manager;
458     delete this->_congestion_controller;
459     if (this->_alt_con_manager) {
460       delete this->_alt_con_manager;
461     }
462 
463     super::clear();
464   */
465   ALPNSupport::clear();
466   this->_packet_handler->close_connection(this);
467 }
468 
469 void
free()470 QUICNetVConnection::free()
471 {
472   this->free(this_ethread());
473 }
474 
475 // called by ET_UDP
476 void
remove_connection_ids()477 QUICNetVConnection::remove_connection_ids()
478 {
479   if (this->_ctable) {
480     this->_ctable->erase(this->_original_quic_connection_id, this);
481     this->_ctable->erase(this->_quic_connection_id, this);
482   }
483 
484   if (this->_alt_con_manager) {
485     this->_alt_con_manager->invalidate_alt_connections();
486   }
487 }
488 
489 // called by ET_UDP
490 void
destroy(EThread * t)491 QUICNetVConnection::destroy(EThread *t)
492 {
493   QUICConDebug("Destroy connection");
494   /*  TODO: Uncmment these blocks after refactoring read / write process
495     if (from_accept_thread) {
496       quicNetVCAllocator.free(this);
497     } else {
498       THREAD_FREE(this, quicNetVCAllocator, t);
499     }
500   */
501 }
502 
503 void
set_local_addr()504 QUICNetVConnection::set_local_addr()
505 {
506   int local_sa_size = sizeof(local_addr);
507   ATS_UNUSED_RETURN(safe_getsockname(this->_udp_con->getFd(), &local_addr.sa, &local_sa_size));
508 }
509 
510 void
reenable(VIO * vio)511 QUICNetVConnection::reenable(VIO *vio)
512 {
513   return;
514 }
515 
516 int
connectUp(EThread * t,int fd)517 QUICNetVConnection::connectUp(EThread *t, int fd)
518 {
519   int res        = 0;
520   NetHandler *nh = get_NetHandler(t);
521   this->thread   = this_ethread();
522   ink_assert(nh->mutex->thread_holding == this->thread);
523 
524   SET_HANDLER((NetVConnHandler)&QUICNetVConnection::state_pre_handshake);
525 
526   if ((res = nh->startIO(this)) < 0) {
527     // FIXME: startIO only return 0 now! what should we do if it failed ?
528   }
529 
530   nh->startCop(this);
531 
532   // FIXME: complete do_io_xxxx instead
533   this->read.enabled = 1;
534 
535   this->set_local_addr();
536   this->remote_addr = con.addr;
537 
538   this->start();
539 
540   // start QUIC handshake
541   this->_schedule_packet_write_ready();
542 
543   return CONNECT_SUCCESS;
544 }
545 
546 QUICConnectionId
peer_connection_id() const547 QUICNetVConnection::peer_connection_id() const
548 {
549   return this->_peer_quic_connection_id;
550 }
551 
552 QUICConnectionId
original_connection_id() const553 QUICNetVConnection::original_connection_id() const
554 {
555   return this->_original_quic_connection_id;
556 }
557 
558 QUICConnectionId
first_connection_id() const559 QUICNetVConnection::first_connection_id() const
560 {
561   return this->_first_quic_connection_id;
562 }
563 
564 QUICConnectionId
connection_id() const565 QUICNetVConnection::connection_id() const
566 {
567   return this->_quic_connection_id;
568 }
569 
570 /*
571  Return combination of dst connection id and src connection id for debug log
572  e.g. "aaaaaaaa-bbbbbbbb"
573    - "aaaaaaaa" : high 32 bit of dst connection id
574    - "bbbbbbbb" : high 32 bit of src connection id
575  */
576 std::string_view
cids() const577 QUICNetVConnection::cids() const
578 {
579   return this->_cids;
580 }
581 
582 const QUICFiveTuple
five_tuple() const583 QUICNetVConnection::five_tuple() const
584 {
585   return this->_five_tuple;
586 }
587 
588 uint32_t
pmtu() const589 QUICNetVConnection::pmtu() const
590 {
591   return this->_pmtu;
592 }
593 
594 NetVConnectionContext_t
direction() const595 QUICNetVConnection::direction() const
596 {
597   return this->netvc_context;
598 }
599 
600 uint32_t
_minimum_quic_packet_size()601 QUICNetVConnection::_minimum_quic_packet_size()
602 {
603   if (netvc_context == NET_VCONNECTION_OUT) {
604     // FIXME Only the first packet need to be 1200 bytes at least
605     return MINIMUM_INITIAL_PACKET_SIZE;
606   } else {
607     // FIXME This size should be configurable and should have some randomness
608     // This is just for providing protection against packet analysis for protected packets
609     return 32 + (this->_rnd() & 0x3f); // 32 to 96
610   }
611 }
612 
613 uint32_t
_maximum_quic_packet_size() const614 QUICNetVConnection::_maximum_quic_packet_size() const
615 {
616   if (this->options.ip_family == PF_INET6) {
617     return this->_pmtu - UDP_HEADER_SIZE - IPV6_HEADER_SIZE;
618   } else {
619     return this->_pmtu - UDP_HEADER_SIZE - IPV4_HEADER_SIZE;
620   }
621 }
622 
623 uint64_t
_maximum_stream_frame_data_size()624 QUICNetVConnection::_maximum_stream_frame_data_size()
625 {
626   return this->_maximum_quic_packet_size() - MAX_STREAM_FRAME_OVERHEAD - MAX_PACKET_OVERHEAD;
627 }
628 
629 QUICStreamManager *
stream_manager()630 QUICNetVConnection::stream_manager()
631 {
632   return this->_stream_manager;
633 }
634 
635 void
handle_received_packet(UDPPacket * packet)636 QUICNetVConnection::handle_received_packet(UDPPacket *packet)
637 {
638   this->_packet_recv_queue.enqueue(packet);
639 }
640 
641 void
ping()642 QUICNetVConnection::ping()
643 {
644   this->_pinger->request();
645 }
646 
647 void
close(QUICConnectionErrorUPtr error)648 QUICNetVConnection::close(QUICConnectionErrorUPtr error)
649 {
650   if (this->handler == reinterpret_cast<ContinuationHandler>(&QUICNetVConnection::state_connection_closed) ||
651       this->handler == reinterpret_cast<ContinuationHandler>(&QUICNetVConnection::state_connection_closing)) {
652     // do nothing
653   } else {
654     this->_switch_to_closing_state(std::move(error));
655   }
656 }
657 
658 std::vector<QUICFrameType>
interests()659 QUICNetVConnection::interests()
660 {
661   return {QUICFrameType::CONNECTION_CLOSE, QUICFrameType::DATA_BLOCKED, QUICFrameType::MAX_DATA};
662 }
663 
664 QUICConnectionErrorUPtr
handle_frame(QUICEncryptionLevel level,const QUICFrame & frame)665 QUICNetVConnection::handle_frame(QUICEncryptionLevel level, const QUICFrame &frame)
666 {
667   QUICConnectionErrorUPtr error = nullptr;
668 
669   switch (frame.type()) {
670   case QUICFrameType::MAX_DATA:
671     this->_remote_flow_controller->forward_limit(static_cast<const QUICMaxDataFrame &>(frame).maximum_data());
672     QUICFCDebug("[REMOTE] %" PRIu64 "/%" PRIu64, this->_remote_flow_controller->current_offset(),
673                 this->_remote_flow_controller->current_limit());
674     this->_schedule_packet_write_ready();
675     break;
676   case QUICFrameType::DATA_BLOCKED:
677     // DATA_BLOCKED frame is for debugging. Nothing to do here.
678     break;
679   case QUICFrameType::CONNECTION_CLOSE:
680     if (this->handler == reinterpret_cast<NetVConnHandler>(&QUICNetVConnection::state_connection_closed) ||
681         this->handler == reinterpret_cast<NetVConnHandler>(&QUICNetVConnection::state_connection_draining)) {
682       return error;
683     }
684 
685     // 7.9.1. Closing and Draining Connection States
686     // An endpoint MAY transition from the closing period to the draining period if it can confirm that its peer is also closing or
687     // draining. Receiving a closing frame is sufficient confirmation, as is receiving a stateless reset.
688     {
689       uint16_t error_code = static_cast<const QUICConnectionCloseFrame &>(frame).error_code();
690       this->_switch_to_draining_state(
691         QUICConnectionErrorUPtr(std::make_unique<QUICConnectionError>(static_cast<QUICTransErrorCode>(error_code))));
692     }
693     break;
694   default:
695     QUICConDebug("Unexpected frame type: %02x", static_cast<unsigned int>(frame.type()));
696     ink_assert(false);
697     break;
698   }
699 
700   return error;
701 }
702 
703 // XXX Setup QUICNetVConnection on regular EThread.
704 // QUICNetVConnection::init() might be called on ET_UDP EThread.
705 int
state_pre_handshake(int event,Event * data)706 QUICNetVConnection::state_pre_handshake(int event, Event *data)
707 {
708   SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
709 
710   // this->thread should be assigned on any direction
711   ink_assert(this->thread == this_ethread());
712 
713   if (!this->nh) {
714     this->nh = get_NetHandler(this_ethread());
715   }
716 
717   // FIXME: Should be accept_no_activity_timeout?
718   if (this->get_context() == NET_VCONNECTION_IN) {
719     this->set_inactivity_timeout(HRTIME_MSECONDS(this->_quic_config->no_activity_timeout_in()));
720   } else {
721     this->set_inactivity_timeout(HRTIME_MSECONDS(this->_quic_config->no_activity_timeout_out()));
722   }
723 
724   this->add_to_active_queue();
725 
726   this->_switch_to_handshake_state();
727   return this->handleEvent(event, data);
728 }
729 
730 // TODO: Timeout by active_timeout
731 int
state_handshake(int event,Event * data)732 QUICNetVConnection::state_handshake(int event, Event *data)
733 {
734   SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
735 
736   if (this->_handshake_handler && this->_handshake_handler->is_completed()) {
737     this->_switch_to_established_state();
738     return this->handleEvent(event, data);
739   }
740 
741   QUICConnectionErrorUPtr error = nullptr;
742 
743   switch (event) {
744   case QUIC_EVENT_PACKET_READ_READY: {
745     QUICPacketCreationResult result;
746     net_activity(this, this_ethread());
747     do {
748       QUICPacketUPtr packet = this->_dequeue_recv_packet(result);
749       if (result == QUICPacketCreationResult::NOT_READY) {
750         error = nullptr;
751       } else if (result == QUICPacketCreationResult::FAILED) {
752         // Don't make this error, and discard the packet.
753         // Because:
754         // - Attacker can terminate connections
755         // - It could be just an errora on lower layer
756         error = nullptr;
757       } else if (result == QUICPacketCreationResult::SUCCESS || result == QUICPacketCreationResult::UNSUPPORTED) {
758         error = this->_state_handshake_process_packet(*packet);
759       }
760 
761       // if we complete handshake, switch to establish state
762       if (this->_handshake_handler && this->_handshake_handler->is_completed()) {
763         this->_switch_to_established_state();
764         return this->handleEvent(event, data);
765       }
766 
767     } while (error == nullptr && (result == QUICPacketCreationResult::SUCCESS || result == QUICPacketCreationResult::IGNORED));
768     break;
769   }
770   case QUIC_EVENT_ACK_PERIODIC:
771     this->_handle_periodic_ack_event();
772     break;
773   case QUIC_EVENT_PACKET_WRITE_READY:
774     this->_close_packet_write_ready(data);
775     // TODO: support RETRY packet
776     error = this->_state_common_send_packet();
777     // Reschedule WRITE_READY
778     this->_schedule_packet_write_ready(true);
779     break;
780   case VC_EVENT_INACTIVITY_TIMEOUT:
781     // Start Immediate Close because of Idle Timeout
782     this->_handle_idle_timeout();
783     break;
784   default:
785     QUICConDebug("Unexpected event: %s (%d)", QUICDebugNames::quic_event(event), event);
786   }
787 
788   if (error != nullptr) {
789     this->_handle_error(std::move(error));
790   }
791 
792   return EVENT_CONT;
793 }
794 
795 int
state_connection_established(int event,Event * data)796 QUICNetVConnection::state_connection_established(int event, Event *data)
797 {
798   SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
799   QUICConnectionErrorUPtr error = nullptr;
800   switch (event) {
801   case QUIC_EVENT_PACKET_READ_READY:
802     error = this->_state_connection_established_receive_packet();
803     break;
804   case QUIC_EVENT_ACK_PERIODIC:
805     this->_handle_periodic_ack_event();
806     break;
807   case QUIC_EVENT_PACKET_WRITE_READY:
808     this->_close_packet_write_ready(data);
809     error = this->_state_common_send_packet();
810     // Reschedule WRITE_READY
811     this->_schedule_packet_write_ready(true);
812     break;
813   case VC_EVENT_INACTIVITY_TIMEOUT:
814     // Start Immediate Close because of Idle Timeout
815     this->_handle_idle_timeout();
816     break;
817   default:
818     QUICConDebug("Unexpected event: %s (%d)", QUICDebugNames::quic_event(event), event);
819   }
820 
821   if (error != nullptr) {
822     QUICConDebug("QUICError: cls=%u, code=0x%" PRIx16, static_cast<unsigned int>(error->cls), error->code);
823     this->_handle_error(std::move(error));
824   }
825 
826   return EVENT_CONT;
827 }
828 
829 int
state_connection_closing(int event,Event * data)830 QUICNetVConnection::state_connection_closing(int event, Event *data)
831 {
832   SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
833 
834   QUICConnectionErrorUPtr error = nullptr;
835   switch (event) {
836   case QUIC_EVENT_PACKET_READ_READY:
837     error = this->_state_closing_receive_packet();
838     break;
839   case QUIC_EVENT_PACKET_WRITE_READY:
840     this->_close_packet_write_ready(data);
841     this->_state_closing_send_packet();
842     break;
843   case QUIC_EVENT_CLOSING_TIMEOUT:
844     this->_close_closing_timeout(data);
845     this->_switch_to_close_state();
846     break;
847   case QUIC_EVENT_ACK_PERIODIC:
848   default:
849     QUICConDebug("Unexpected event: %s (%d)", QUICDebugNames::quic_event(event), event);
850     ink_assert(false);
851   }
852 
853   return EVENT_DONE;
854 }
855 
856 int
state_connection_draining(int event,Event * data)857 QUICNetVConnection::state_connection_draining(int event, Event *data)
858 {
859   SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
860 
861   QUICConnectionErrorUPtr error = nullptr;
862   switch (event) {
863   case QUIC_EVENT_PACKET_READ_READY:
864     error = this->_state_draining_receive_packet();
865     break;
866   case QUIC_EVENT_PACKET_WRITE_READY:
867     // Do not send any packets in this state.
868     // This should be the only difference between this and closing_state.
869     this->_close_packet_write_ready(data);
870     break;
871   case QUIC_EVENT_CLOSING_TIMEOUT:
872     this->_close_closing_timeout(data);
873     this->_switch_to_close_state();
874     break;
875   case QUIC_EVENT_ACK_PERIODIC:
876   default:
877     QUICConDebug("Unexpected event: %s (%d)", QUICDebugNames::quic_event(event), event);
878     ink_assert(false);
879   }
880 
881   return EVENT_DONE;
882 }
883 
884 int
state_connection_closed(int event,Event * data)885 QUICNetVConnection::state_connection_closed(int event, Event *data)
886 {
887   SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
888   switch (event) {
889   case QUIC_EVENT_SHUTDOWN: {
890     this->_unschedule_ack_manager_periodic();
891     this->_unschedule_packet_write_ready();
892     this->_unschedule_closing_timeout();
893     this->_close_closed_event(data);
894     this->next_inactivity_timeout_at = 0;
895     this->next_activity_timeout_at   = 0;
896 
897     this->inactivity_timeout_in = 0;
898     this->active_timeout_in     = 0;
899 
900     // TODO: Drop record from Connection-ID - QUICNetVConnection table in QUICPacketHandler
901     // Shutdown loss detector
902     SCOPED_MUTEX_LOCK(lock2, this->_loss_detector->mutex, this_ethread());
903     this->_loss_detector->handleEvent(QUIC_EVENT_LD_SHUTDOWN, nullptr);
904 
905     // FIXME I'm not sure whether we can block here, but it's needed to not crash.
906     SCOPED_MUTEX_LOCK(lock, this->nh->mutex, this_ethread());
907     if (this->nh) {
908       this->nh->free_netevent(this);
909     } else {
910       this->free(this->mutex->thread_holding);
911     }
912     break;
913   }
914   case QUIC_EVENT_PACKET_WRITE_READY: {
915     this->_close_packet_write_ready(data);
916     break;
917   }
918   default:
919     QUICConDebug("Unexpected event: %s (%d)", QUICDebugNames::quic_event(event), event);
920   }
921 
922   return EVENT_DONE;
923 }
924 
925 UDPConnection *
get_udp_con()926 QUICNetVConnection::get_udp_con()
927 {
928   return this->_udp_con;
929 }
930 
931 void
net_read_io(NetHandler * nh,EThread * lthread)932 QUICNetVConnection::net_read_io(NetHandler *nh, EThread *lthread)
933 {
934   SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
935   this->handleEvent(QUIC_EVENT_PACKET_READ_READY, nullptr);
936 
937   return;
938 }
939 
940 int64_t
load_buffer_and_write(int64_t towrite,MIOBufferAccessor & buf,int64_t & total_written,int & needs)941 QUICNetVConnection::load_buffer_and_write(int64_t towrite, MIOBufferAccessor &buf, int64_t &total_written, int &needs)
942 {
943   ink_assert(false);
944 
945   return 0;
946 }
947 
948 int
populate_protocol(std::string_view * results,int n) const949 QUICNetVConnection::populate_protocol(std::string_view *results, int n) const
950 {
951   int retval = 0;
952   if (n > retval) {
953     results[retval++] = IP_PROTO_TAG_QUIC;
954     if (n > retval) {
955       retval += super::populate_protocol(results + retval, n - retval);
956     }
957   }
958   return retval;
959 }
960 
961 const char *
protocol_contains(std::string_view prefix) const962 QUICNetVConnection::protocol_contains(std::string_view prefix) const
963 {
964   const char *retval   = nullptr;
965   std::string_view tag = IP_PROTO_TAG_QUIC;
966   if (prefix.size() <= tag.size() && strncmp(tag.data(), prefix.data(), prefix.size()) == 0) {
967     retval = tag.data();
968   } else {
969     retval = super::protocol_contains(prefix);
970   }
971   return retval;
972 }
973 
974 // ALPN TLS extension callback. Given the client's set of offered
975 // protocols, we have to select a protocol to use for this session.
976 int
select_next_protocol(SSL * ssl,const unsigned char ** out,unsigned char * outlen,const unsigned char * in,unsigned inlen) const977 QUICNetVConnection::select_next_protocol(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in,
978                                          unsigned inlen) const
979 {
980   const unsigned char *npnptr = nullptr;
981   unsigned int npnsize        = 0;
982   if (this->getNPN(&npnptr, &npnsize)) {
983     // SSL_select_next_proto chooses the first server-offered protocol that appears in the clients protocol set, ie. the
984     // server selects the protocol. This is a n^2 search, so it's preferable to keep the protocol set short.
985     if (SSL_select_next_proto((unsigned char **)out, outlen, npnptr, npnsize, in, inlen) == OPENSSL_NPN_NEGOTIATED) {
986       Debug("ssl", "selected ALPN protocol %.*s", (int)(*outlen), *out);
987       return SSL_TLSEXT_ERR_OK;
988     }
989   }
990 
991   *out    = nullptr;
992   *outlen = 0;
993   return SSL_TLSEXT_ERR_NOACK;
994 }
995 
996 bool
is_closed() const997 QUICNetVConnection::is_closed() const
998 {
999   return this->handler == reinterpret_cast<NetVConnHandler>(&QUICNetVConnection::state_connection_closed);
1000 }
1001 
1002 QUICPacketNumber
_largest_acked_packet_number(QUICEncryptionLevel level) const1003 QUICNetVConnection::_largest_acked_packet_number(QUICEncryptionLevel level) const
1004 {
1005   auto index = QUICTypeUtil::pn_space(level);
1006 
1007   return this->_loss_detector->largest_acked_packet_number(index);
1008 }
1009 
1010 std::string_view
negotiated_application_name() const1011 QUICNetVConnection::negotiated_application_name() const
1012 {
1013   const uint8_t *name;
1014   unsigned int name_len = 0;
1015 
1016   this->_hs_protocol->negotiated_application_name(&name, &name_len);
1017 
1018   return std::string_view(reinterpret_cast<const char *>(name), name_len);
1019 }
1020 
1021 QUICConnectionErrorUPtr
_state_handshake_process_packet(const QUICPacket & packet)1022 QUICNetVConnection::_state_handshake_process_packet(const QUICPacket &packet)
1023 {
1024   QUICConnectionErrorUPtr error = nullptr;
1025   switch (packet.type()) {
1026   case QUICPacketType::VERSION_NEGOTIATION:
1027     error = this->_state_handshake_process_version_negotiation_packet(packet);
1028     break;
1029   case QUICPacketType::INITIAL:
1030     error = this->_state_handshake_process_initial_packet(packet);
1031     break;
1032   case QUICPacketType::RETRY:
1033     error = this->_state_handshake_process_retry_packet(packet);
1034     break;
1035   case QUICPacketType::HANDSHAKE:
1036     error = this->_state_handshake_process_handshake_packet(packet);
1037     if (this->_pp_key_info.is_decryption_key_available(QUICKeyPhase::INITIAL) && this->netvc_context == NET_VCONNECTION_IN) {
1038       this->_pp_key_info.drop_keys(QUICKeyPhase::INITIAL);
1039       this->_minimum_encryption_level = QUICEncryptionLevel::HANDSHAKE;
1040     }
1041     break;
1042   case QUICPacketType::ZERO_RTT_PROTECTED:
1043     error = this->_state_handshake_process_zero_rtt_protected_packet(packet);
1044     break;
1045   case QUICPacketType::PROTECTED:
1046   default:
1047     QUICConDebug("Ignore %s(%" PRIu8 ") packet", QUICDebugNames::packet_type(packet.type()), static_cast<uint8_t>(packet.type()));
1048 
1049     error = std::make_unique<QUICConnectionError>(QUICTransErrorCode::INTERNAL_ERROR);
1050     break;
1051   }
1052   return error;
1053 }
1054 
1055 QUICConnectionErrorUPtr
_state_handshake_process_version_negotiation_packet(const QUICPacket & packet)1056 QUICNetVConnection::_state_handshake_process_version_negotiation_packet(const QUICPacket &packet)
1057 {
1058   QUICConnectionErrorUPtr error = nullptr;
1059 
1060   if (packet.destination_cid() != this->connection_id()) {
1061     QUICConDebug("Ignore Version Negotiation packet");
1062     return error;
1063   }
1064 
1065   if (this->_handshake_handler->is_version_negotiated()) {
1066     QUICConDebug("ignore VN - already negotiated");
1067   } else {
1068     error = this->_handshake_handler->negotiate_version(packet, &this->_packet_factory);
1069 
1070     // discard all transport state except packet number
1071     this->_loss_detector->reset();
1072 
1073     this->_congestion_controller->reset();
1074 
1075     // start handshake over
1076     this->_handshake_handler->reset();
1077     this->_handshake_handler->do_handshake();
1078     this->_schedule_packet_write_ready();
1079   }
1080 
1081   return error;
1082 }
1083 
1084 QUICConnectionErrorUPtr
_state_handshake_process_initial_packet(const QUICPacket & packet)1085 QUICNetVConnection::_state_handshake_process_initial_packet(const QUICPacket &packet)
1086 {
1087   // QUIC packet could be smaller than MINIMUM_INITIAL_PACKET_SIZE when coalescing packets
1088   // if (packet->size() < MINIMUM_INITIAL_PACKET_SIZE) {
1089   //   QUICConDebug("Packet size is smaller than the minimum initial packet size");
1090   //   // Ignore the packet
1091   //   return QUICErrorUPtr(new QUICNoError());
1092   // }
1093 
1094   QUICConnectionErrorUPtr error = nullptr;
1095 
1096   // Start handshake
1097   if (this->netvc_context == NET_VCONNECTION_IN) {
1098     this->local_addr.sa  = packet.to().sa;
1099     this->remote_addr.sa = packet.from().sa;
1100     this->_five_tuple.update(this->local_addr, this->remote_addr, SOCK_DGRAM);
1101 
1102     if (!this->_alt_con_manager) {
1103       this->_alt_con_manager =
1104         new QUICAltConnectionManager(this, *this->_ctable, this->_peer_quic_connection_id, this->_quic_config->instance_id(),
1105                                      this->_quic_config->active_cid_limit_in(), this->_quic_config->preferred_address_ipv4(),
1106                                      this->_quic_config->preferred_address_ipv6());
1107       this->_frame_generators.add_generator(*this->_alt_con_manager, QUICFrameGeneratorWeight::EARLY);
1108       this->_frame_dispatcher->add_handler(this->_alt_con_manager);
1109     }
1110     QUICTPConfigQCP tp_config(this->_quic_config, NET_VCONNECTION_IN);
1111     error = this->_handshake_handler->start(tp_config, packet, &this->_packet_factory, this->_alt_con_manager->preferred_address());
1112 
1113     // If version negotiation was failed and VERSION NEGOTIATION packet was sent, nothing to do.
1114     if (this->_handshake_handler->is_version_negotiated()) {
1115       error = this->_recv_and_ack(packet);
1116 
1117       if (error == nullptr && !this->_handshake_handler->has_remote_tp()) {
1118         error = std::make_unique<QUICConnectionError>(QUICTransErrorCode::TRANSPORT_PARAMETER_ERROR);
1119       }
1120     }
1121   } else {
1122     if (!this->_alt_con_manager) {
1123       this->_alt_con_manager =
1124         new QUICAltConnectionManager(this, *this->_ctable, this->_peer_quic_connection_id, this->_quic_config->instance_id(),
1125                                      this->_quic_config->active_cid_limit_out());
1126       this->_frame_generators.add_generator(*this->_alt_con_manager, QUICFrameGeneratorWeight::BEFORE_DATA);
1127       this->_frame_dispatcher->add_handler(this->_alt_con_manager);
1128     }
1129 
1130     // on client side, _handshake_handler is already started. Just process packet like _state_handshake_process_handshake_packet()
1131     error = this->_recv_and_ack(packet);
1132   }
1133 
1134   return error;
1135 }
1136 
1137 /**
1138    This doesn't call this->_recv_and_ack(), because RETRY packet doesn't have any frames.
1139  */
1140 QUICConnectionErrorUPtr
_state_handshake_process_retry_packet(const QUICPacket & packet)1141 QUICNetVConnection::_state_handshake_process_retry_packet(const QUICPacket &packet)
1142 {
1143   ink_assert(this->netvc_context == NET_VCONNECTION_OUT);
1144 
1145   if (this->_av_token) {
1146     QUICConDebug("Ignore RETRY packet - already processed before");
1147     return nullptr;
1148   }
1149 
1150   // TODO: move packet->payload to _av_token
1151   this->_av_token_len = packet.payload_length();
1152   this->_av_token     = ats_unique_malloc(this->_av_token_len);
1153   memcpy(this->_av_token.get(), packet.payload(), this->_av_token_len);
1154 
1155   this->_padder->set_av_token_len(this->_av_token_len);
1156 
1157   // discard all transport state
1158   this->_handshake_handler->reset();
1159   this->_packet_factory.reset();
1160   this->_loss_detector->reset();
1161 
1162   this->_congestion_controller->reset();
1163   this->_packet_recv_queue.reset();
1164 
1165   // Initialize Key Materials with peer CID. Because peer CID is DCID of (second) INITIAL packet from client which reply to RETRY
1166   // packet from server
1167   this->_hs_protocol->initialize_key_materials(this->_peer_quic_connection_id);
1168 
1169   // start handshake over
1170   this->_handshake_handler->do_handshake();
1171   this->_schedule_packet_write_ready();
1172 
1173   return nullptr;
1174 }
1175 
1176 QUICConnectionErrorUPtr
_state_handshake_process_handshake_packet(const QUICPacket & packet)1177 QUICNetVConnection::_state_handshake_process_handshake_packet(const QUICPacket &packet)
1178 {
1179   // Source address is verified by receiving any message from the client encrypted using the
1180   // Handshake keys.
1181   if (this->netvc_context == NET_VCONNECTION_IN && !this->_verfied_state.is_verified()) {
1182     this->_verfied_state.set_addr_verifed();
1183   }
1184   return this->_recv_and_ack(packet);
1185 }
1186 
1187 QUICConnectionErrorUPtr
_state_handshake_process_zero_rtt_protected_packet(const QUICPacket & packet)1188 QUICNetVConnection::_state_handshake_process_zero_rtt_protected_packet(const QUICPacket &packet)
1189 {
1190   this->_stream_manager->init_flow_control_params(this->_handshake_handler->local_transport_parameters(),
1191                                                   this->_handshake_handler->remote_transport_parameters());
1192   this->_start_application();
1193   return this->_recv_and_ack(packet);
1194 }
1195 
1196 QUICConnectionErrorUPtr
_state_connection_established_process_protected_packet(const QUICPacket & packet)1197 QUICNetVConnection::_state_connection_established_process_protected_packet(const QUICPacket &packet)
1198 {
1199   QUICConnectionErrorUPtr error = nullptr;
1200   bool has_non_probing_frame    = false;
1201 
1202   error = this->_recv_and_ack(packet, &has_non_probing_frame);
1203   if (error != nullptr) {
1204     return error;
1205   }
1206 
1207   // Migrate connection if required
1208   // FIXME Connection migration will be initiated when a peer sent non-probing frames.
1209   // We need to two or more paths because we need to respond to probing packets on a new path and also need to send other frames
1210   // on the old path until they initiate migration.
1211   // if (packet.destination_cid() == this->_quic_connection_id && has_non_probing_frame) {
1212   if (this->_alt_con_manager != nullptr) {
1213     if (packet.destination_cid() != this->_quic_connection_id || !ats_ip_addr_port_eq(packet.from(), this->remote_addr)) {
1214       if (!has_non_probing_frame) {
1215         QUICConDebug("FIXME: Connection migration has been initiated without non-probing frames");
1216       }
1217       error = this->_state_connection_established_migrate_connection(packet);
1218       if (error != nullptr) {
1219         return error;
1220       }
1221     }
1222   }
1223 
1224   // For Connection Migration excercise
1225   if (this->netvc_context == NET_VCONNECTION_OUT && this->_quic_config->cm_exercise_enabled()) {
1226     this->_state_connection_established_initiate_connection_migration();
1227   }
1228 
1229   return error;
1230 }
1231 
1232 QUICConnectionErrorUPtr
_state_connection_established_receive_packet()1233 QUICNetVConnection::_state_connection_established_receive_packet()
1234 {
1235   QUICConnectionErrorUPtr error = nullptr;
1236   QUICPacketCreationResult result;
1237 
1238   // Receive a QUIC packet
1239   net_activity(this, this_ethread());
1240   do {
1241     QUICPacketUPtr packet = this->_dequeue_recv_packet(result);
1242     if (result == QUICPacketCreationResult::FAILED) {
1243       // Don't make this error, and discard the packet.
1244       // Because:
1245       // - Attacker can terminate connections
1246       // - It could be just an errora on lower layer
1247       continue;
1248     } else if (result == QUICPacketCreationResult::NO_PACKET) {
1249       return error;
1250     } else if (result == QUICPacketCreationResult::NOT_READY) {
1251       return error;
1252     } else if (result == QUICPacketCreationResult::IGNORED) {
1253       continue;
1254     }
1255 
1256     // Process the packet
1257     switch (packet->type()) {
1258     case QUICPacketType::PROTECTED:
1259       error = this->_state_connection_established_process_protected_packet(*packet);
1260       break;
1261     case QUICPacketType::INITIAL:
1262     case QUICPacketType::HANDSHAKE:
1263     case QUICPacketType::ZERO_RTT_PROTECTED:
1264       // Pass packet to _recv_and_ack to send ack to the packet. Stream data will be discarded by offset mismatch.
1265       error = this->_recv_and_ack(*packet);
1266       break;
1267     default:
1268       QUICConDebug("Unknown packet type: %s(%" PRIu8 ")", QUICDebugNames::packet_type(packet->type()),
1269                    static_cast<uint8_t>(packet->type()));
1270 
1271       error = std::make_unique<QUICConnectionError>(QUICTransErrorCode::INTERNAL_ERROR);
1272       break;
1273     }
1274 
1275   } while (error == nullptr && (result == QUICPacketCreationResult::SUCCESS || result == QUICPacketCreationResult::IGNORED));
1276   return error;
1277 }
1278 
1279 QUICConnectionErrorUPtr
_state_closing_receive_packet()1280 QUICNetVConnection::_state_closing_receive_packet()
1281 {
1282   while (this->_packet_recv_queue.size() > 0) {
1283     QUICPacketCreationResult result;
1284     QUICPacketUPtr packet = this->_dequeue_recv_packet(result);
1285     if (result == QUICPacketCreationResult::SUCCESS) {
1286       switch (packet->type()) {
1287       case QUICPacketType::VERSION_NEGOTIATION:
1288         // Ignore VN packets on closing state
1289         break;
1290       default:
1291         this->_recv_and_ack(*packet);
1292         break;
1293       }
1294     }
1295     ++this->_state_closing_recv_packet_count;
1296 
1297     if (this->_state_closing_recv_packet_window < STATE_CLOSING_MAX_RECV_PKT_WIND &&
1298         this->_state_closing_recv_packet_count >= this->_state_closing_recv_packet_window) {
1299       this->_state_closing_recv_packet_count = 0;
1300       this->_state_closing_recv_packet_window <<= 1;
1301 
1302       this->_schedule_packet_write_ready(true);
1303       break;
1304     }
1305   }
1306 
1307   return nullptr;
1308 }
1309 
1310 QUICConnectionErrorUPtr
_state_draining_receive_packet()1311 QUICNetVConnection::_state_draining_receive_packet()
1312 {
1313   while (this->_packet_recv_queue.size() > 0) {
1314     QUICPacketCreationResult result;
1315     QUICPacketUPtr packet = this->_dequeue_recv_packet(result);
1316     if (result == QUICPacketCreationResult::SUCCESS) {
1317       this->_recv_and_ack(*packet);
1318       // Do NOT schedule WRITE_READY event from this point.
1319       // An endpoint in the draining state MUST NOT send any packets.
1320     }
1321   }
1322 
1323   return nullptr;
1324 }
1325 
1326 /**
1327  * 1. Check congestion window
1328  * 2. Allocate buffer for UDP Payload
1329  * 3. Generate QUIC Packet
1330  * 4. Store data to the paylaod
1331  * 5. Send UDP Packet
1332  */
1333 QUICConnectionErrorUPtr
_state_common_send_packet()1334 QUICNetVConnection::_state_common_send_packet()
1335 {
1336   uint32_t packet_count = 0;
1337   uint32_t error        = 0;
1338   while (error == 0 && packet_count < PACKET_PER_EVENT) {
1339     uint32_t window = this->_congestion_controller->credit();
1340 
1341     if (window == 0) {
1342       break;
1343     }
1344 
1345     Ptr<IOBufferBlock> udp_payload(new_IOBufferBlock());
1346     uint32_t udp_payload_len = std::min(window, this->_pmtu);
1347     udp_payload->alloc(iobuffer_size_to_index(udp_payload_len));
1348 
1349     uint32_t written = 0;
1350     for (int i = static_cast<int>(this->_minimum_encryption_level); i <= static_cast<int>(QUICEncryptionLevel::ONE_RTT); ++i) {
1351       auto level = QUIC_ENCRYPTION_LEVELS[i];
1352       if (level == QUICEncryptionLevel::ONE_RTT && !this->_handshake_handler->is_completed()) {
1353         continue;
1354       }
1355 
1356       uint32_t max_packet_size = udp_payload_len - written;
1357       if (this->netvc_context == NET_VCONNECTION_IN && !this->_verfied_state.is_verified()) {
1358         max_packet_size = std::min(max_packet_size, this->_verfied_state.windows());
1359       }
1360 
1361       QUICPacketInfoUPtr packet_info = std::make_unique<QUICPacketInfo>();
1362       QUICPacketUPtr packet          = this->_packetize_frames(level, max_packet_size, packet_info->frames);
1363 
1364       if (packet) {
1365         packet_info->packet_number    = packet->packet_number();
1366         packet_info->time_sent        = Thread::get_hrtime();
1367         packet_info->ack_eliciting    = packet->is_ack_eliciting();
1368         packet_info->is_crypto_packet = packet->is_crypto_packet();
1369         packet_info->in_flight        = true;
1370         if (packet_info->ack_eliciting) {
1371           packet_info->sent_bytes = packet->size();
1372         } else {
1373           packet_info->sent_bytes = 0;
1374         }
1375         packet_info->type     = packet->type();
1376         packet_info->pn_space = QUICTypeUtil::pn_space(level);
1377 
1378         if (this->netvc_context == NET_VCONNECTION_IN && !this->_verfied_state.is_verified()) {
1379           QUICConDebug("send to unverified window: %u", this->_verfied_state.windows());
1380           this->_verfied_state.consume(packet->size());
1381         }
1382 
1383         // TODO: do not write two QUIC Short Header Packets
1384         uint8_t *buf = reinterpret_cast<uint8_t *>(udp_payload->end());
1385         size_t len   = 0;
1386         packet->store(buf, &len);
1387         udp_payload->fill(len);
1388         written += len;
1389 
1390         int dcil = (this->_peer_quic_connection_id == QUICConnectionId::ZERO()) ? 0 : this->_peer_quic_connection_id.length();
1391         if (!this->_ph_protector.protect(buf, len, dcil)) {
1392           ink_assert(!"failed to protect buffer");
1393         }
1394 
1395         QUICConDebug("[TX] %s packet #%" PRIu64 " size=%zu", QUICDebugNames::packet_type(packet->type()), packet->packet_number(),
1396                      len);
1397 
1398         if (this->_pp_key_info.is_encryption_key_available(QUICKeyPhase::INITIAL) && packet->type() == QUICPacketType::HANDSHAKE &&
1399             this->netvc_context == NET_VCONNECTION_OUT) {
1400           this->_pp_key_info.drop_keys(QUICKeyPhase::INITIAL);
1401           this->_minimum_encryption_level = QUICEncryptionLevel::HANDSHAKE;
1402         }
1403 
1404         this->_loss_detector->on_packet_sent(std::move(packet_info));
1405         packet_count++;
1406       }
1407     }
1408 
1409     if (written) {
1410       this->_packet_handler->send_packet(this, udp_payload);
1411     } else {
1412       udp_payload->dealloc();
1413       break;
1414     }
1415   }
1416 
1417   if (packet_count) {
1418     QUIC_INCREMENT_DYN_STAT_EX(QUICStats::total_packets_sent_stat, packet_count);
1419     net_activity(this, this_ethread());
1420   }
1421 
1422   return nullptr;
1423 }
1424 
1425 QUICConnectionErrorUPtr
_state_closing_send_packet()1426 QUICNetVConnection::_state_closing_send_packet()
1427 {
1428   this->_packetize_closing_frame();
1429 
1430   // TODO: should credit of congestion controller be checked?
1431 
1432   // During the closing period, an endpoint that sends a
1433   // closing frame SHOULD respond to any packet that it receives with
1434   // another packet containing a closing frame.  To minimize the state
1435   // that an endpoint maintains for a closing connection, endpoints MAY
1436   // send the exact same packet.
1437   if (this->_the_final_packet) {
1438     this->_packet_handler->send_packet(*this->_the_final_packet, this, this->_ph_protector);
1439   }
1440 
1441   return nullptr;
1442 }
1443 
1444 Ptr<IOBufferBlock>
_store_frame(Ptr<IOBufferBlock> parent_block,size_t & size_added,uint64_t & max_frame_size,QUICFrame & frame,std::vector<QUICFrameInfo> & frames)1445 QUICNetVConnection::_store_frame(Ptr<IOBufferBlock> parent_block, size_t &size_added, uint64_t &max_frame_size, QUICFrame &frame,
1446                                  std::vector<QUICFrameInfo> &frames)
1447 {
1448   Ptr<IOBufferBlock> new_block = frame.to_io_buffer_block(max_frame_size);
1449 
1450   size_added             = 0;
1451   Ptr<IOBufferBlock> tmp = new_block;
1452   while (tmp) {
1453     size_added += tmp->size();
1454     tmp = tmp->next;
1455   }
1456 
1457   if (parent_block == nullptr) {
1458     parent_block = new_block;
1459   } else {
1460     parent_block->next = new_block;
1461   }
1462 
1463   // frame should be stored because it's created with max_frame_size
1464   ink_assert(size_added != 0);
1465 
1466   max_frame_size -= size_added;
1467 
1468   if (is_debug_tag_set(QUIC_DEBUG_TAG.data())) {
1469     char msg[1024];
1470     frame.debug_msg(msg, sizeof(msg));
1471     QUICConDebug("[TX] | %s", msg);
1472   }
1473 
1474   frames.emplace_back(frame.id(), frame.generated_by());
1475 
1476   while (parent_block->next) {
1477     parent_block = parent_block->next;
1478   }
1479   return parent_block;
1480 }
1481 
1482 QUICPacketUPtr
_packetize_frames(QUICEncryptionLevel level,uint64_t max_packet_size,std::vector<QUICFrameInfo> & frames)1483 QUICNetVConnection::_packetize_frames(QUICEncryptionLevel level, uint64_t max_packet_size, std::vector<QUICFrameInfo> &frames)
1484 {
1485   QUICPacketUPtr packet = QUICPacketFactory::create_null_packet();
1486   if (max_packet_size <= MAX_PACKET_OVERHEAD) {
1487     return packet;
1488   }
1489 
1490   // TODO: adjust MAX_PACKET_OVERHEAD for each encryption level
1491   uint64_t max_frame_size = max_packet_size - MAX_PACKET_OVERHEAD;
1492   if (level == QUICEncryptionLevel::INITIAL && this->_av_token) {
1493     max_frame_size = max_frame_size - (QUICVariableInt::size(this->_av_token_len) + this->_av_token_len);
1494   }
1495   max_frame_size = std::min(max_frame_size, this->_maximum_stream_frame_data_size());
1496 
1497   bool probing                   = false;
1498   int frame_count                = 0;
1499   size_t len                     = 0;
1500   Ptr<IOBufferBlock> first_block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
1501   Ptr<IOBufferBlock> last_block  = first_block;
1502   first_block->alloc(iobuffer_size_to_index(0));
1503   first_block->fill(0);
1504 
1505   uint32_t seq_num   = this->_seq_num++;
1506   size_t size_added  = 0;
1507   bool ack_eliciting = false;
1508   bool crypto        = false;
1509   uint8_t frame_instance_buffer[QUICFrame::MAX_INSTANCE_SIZE]; // This is for a frame instance but not serialized frame data
1510   QUICFrame *frame = nullptr;
1511   for (auto g : this->_frame_generators.generators()) {
1512     // a non-ack_eliciting packet is ready, but we can not send continuous two ack_eliciting packets.
1513     while (g->will_generate_frame(level, len, ack_eliciting, seq_num)) {
1514       // FIXME will_generate_frame should receive more parameters so we don't need extra checks
1515       if (g == this->_remote_flow_controller && !this->_stream_manager->will_generate_frame(level, len, ack_eliciting, seq_num)) {
1516         break;
1517       }
1518 
1519       if (g == this->_stream_manager) {
1520         // Don't send DATA frames if current path is not validated
1521         // FIXME will_generate_frame should receive more parameters so we don't need extra checks
1522         if (auto path = this->_path_manager->get_verified_path(); !path.remote_ep().isValid()) {
1523           break;
1524         }
1525       }
1526 
1527       // Common block
1528       frame =
1529         g->generate_frame(frame_instance_buffer, level, this->_remote_flow_controller->credit(), max_frame_size, len, seq_num);
1530       if (frame) {
1531         // Some frame types must not be sent on Initial and Handshake packets
1532         switch (auto t = frame->type(); level) {
1533         case QUICEncryptionLevel::INITIAL:
1534         case QUICEncryptionLevel::HANDSHAKE:
1535           ink_assert(t == QUICFrameType::CRYPTO || t == QUICFrameType::ACK || t == QUICFrameType::PADDING ||
1536                      t == QUICFrameType::CONNECTION_CLOSE);
1537           break;
1538         default:
1539           break;
1540         }
1541 
1542         ++frame_count;
1543         probing |= frame->is_probing_frame();
1544         if (frame->is_flow_controlled()) {
1545           int ret = this->_remote_flow_controller->update(this->_stream_manager->total_offset_sent());
1546           QUICFCDebug("[REMOTE] %" PRIu64 "/%" PRIu64, this->_remote_flow_controller->current_offset(),
1547                       this->_remote_flow_controller->current_limit());
1548           ink_assert(ret == 0);
1549         }
1550         last_block = this->_store_frame(last_block, size_added, max_frame_size, *frame, frames);
1551         len += size_added;
1552 
1553         // FIXME ACK frame should have priority
1554         if (frame->type() == QUICFrameType::STREAM) {
1555           if (++this->_stream_frames_sent % MAX_CONSECUTIVE_STREAMS == 0) {
1556             break;
1557           }
1558         }
1559 
1560         if (!ack_eliciting && frame->ack_eliciting()) {
1561           ack_eliciting = true;
1562         }
1563 
1564         if (frame->type() == QUICFrameType::CRYPTO && frame->ack_eliciting()) {
1565           crypto = true;
1566         }
1567 
1568         frame->~QUICFrame();
1569       } else {
1570         // Move to next generator
1571         break;
1572       }
1573     }
1574   }
1575 
1576   // Schedule a packet
1577   if (len != 0) {
1578     // Packet is retransmittable if it's not ack only packet
1579     packet = this->_build_packet(level, first_block, ack_eliciting, probing, crypto);
1580   }
1581 
1582   return packet;
1583 }
1584 
1585 void
_packetize_closing_frame()1586 QUICNetVConnection::_packetize_closing_frame()
1587 {
1588   if (this->_connection_error == nullptr || this->_the_final_packet) {
1589     return;
1590   }
1591 
1592   QUICFrame *frame = nullptr;
1593 
1594   // CONNECTION_CLOSE
1595   uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE];
1596   frame = QUICFrameFactory::create_connection_close_frame(frame_buf, *this->_connection_error);
1597 
1598   uint32_t max_size = this->_maximum_quic_packet_size();
1599 
1600   size_t size_added       = 0;
1601   uint64_t max_frame_size = static_cast<uint64_t>(max_size);
1602   std::vector<QUICFrameInfo> frames;
1603   Ptr<IOBufferBlock> parent_block;
1604   parent_block = nullptr;
1605   parent_block = this->_store_frame(parent_block, size_added, max_frame_size, *frame, frames);
1606 
1607   QUICEncryptionLevel level = this->_hs_protocol->current_encryption_level();
1608   ink_assert(level != QUICEncryptionLevel::ZERO_RTT);
1609   this->_the_final_packet = this->_build_packet(level, parent_block, true, false, false);
1610 }
1611 
1612 QUICConnectionErrorUPtr
_recv_and_ack(const QUICPacket & packet,bool * has_non_probing_frame)1613 QUICNetVConnection::_recv_and_ack(const QUICPacket &packet, bool *has_non_probing_frame)
1614 {
1615   ink_assert(packet.type() != QUICPacketType::RETRY);
1616 
1617   const uint8_t *payload      = packet.payload();
1618   uint16_t size               = packet.payload_length();
1619   QUICPacketNumber packet_num = packet.packet_number();
1620   QUICEncryptionLevel level   = QUICTypeUtil::encryption_level(packet.type());
1621 
1622   bool ack_only;
1623   bool is_flow_controlled;
1624 
1625   QUICConnectionErrorUPtr error = nullptr;
1626   if (has_non_probing_frame) {
1627     *has_non_probing_frame = false;
1628   }
1629 
1630   error =
1631     this->_frame_dispatcher->receive_frames(level, payload, size, ack_only, is_flow_controlled, has_non_probing_frame, &packet);
1632   if (error != nullptr) {
1633     return error;
1634   }
1635 
1636   if (is_flow_controlled) {
1637     int ret = this->_local_flow_controller->update(this->_stream_manager->total_offset_received());
1638     QUICFCDebug("[LOCAL] %" PRIu64 "/%" PRIu64, this->_local_flow_controller->current_offset(),
1639                 this->_local_flow_controller->current_limit());
1640 
1641     if (ret != 0) {
1642       return std::make_unique<QUICConnectionError>(QUICTransErrorCode::FLOW_CONTROL_ERROR);
1643     }
1644 
1645     this->_local_flow_controller->forward_limit(this->_stream_manager->total_reordered_bytes() + this->_flow_control_buffer_size);
1646     QUICFCDebug("[LOCAL] %" PRIu64 "/%" PRIu64, this->_local_flow_controller->current_offset(),
1647                 this->_local_flow_controller->current_limit());
1648   }
1649 
1650   this->_ack_frame_manager.update(level, packet_num, size, ack_only);
1651 
1652   return error;
1653 }
1654 
1655 QUICPacketUPtr
_build_packet(QUICEncryptionLevel level,Ptr<IOBufferBlock> parent_block,bool ack_eliciting,bool probing,bool crypto)1656 QUICNetVConnection::_build_packet(QUICEncryptionLevel level, Ptr<IOBufferBlock> parent_block, bool ack_eliciting, bool probing,
1657                                   bool crypto)
1658 {
1659   QUICPacketType type   = QUICTypeUtil::packet_type(level);
1660   QUICPacketUPtr packet = QUICPacketFactory::create_null_packet();
1661 
1662   // FIXME Pass parent_block to create_x_packet
1663   // No need to make a unique buf here
1664   ats_unique_buf buf = ats_unique_malloc(2048);
1665   uint8_t *raw_buf   = buf.get();
1666   size_t len         = 0;
1667   while (parent_block) {
1668     memcpy(raw_buf + len, parent_block->start(), parent_block->size());
1669     len += parent_block->size();
1670     parent_block = parent_block->next;
1671   }
1672 
1673   switch (type) {
1674   case QUICPacketType::INITIAL: {
1675     QUICConnectionId dcid = this->_peer_quic_connection_id;
1676     ats_unique_buf token  = {nullptr};
1677     size_t token_len      = 0;
1678 
1679     if (this->netvc_context == NET_VCONNECTION_OUT) {
1680       // TODO: Add a case of using token which is advertized by NEW_TOKEN frame
1681       if (this->_av_token) {
1682         token     = ats_unique_malloc(this->_av_token_len);
1683         token_len = this->_av_token_len;
1684         memcpy(token.get(), this->_av_token.get(), token_len);
1685       } else {
1686         dcid = this->_original_quic_connection_id;
1687       }
1688     }
1689 
1690     packet = this->_packet_factory.create_initial_packet(
1691       dcid, this->_quic_connection_id, this->_largest_acked_packet_number(QUICEncryptionLevel::INITIAL), std::move(buf), len,
1692       ack_eliciting, probing, crypto, std::move(token), token_len);
1693     break;
1694   }
1695   case QUICPacketType::HANDSHAKE: {
1696     packet = this->_packet_factory.create_handshake_packet(this->_peer_quic_connection_id, this->_quic_connection_id,
1697                                                            this->_largest_acked_packet_number(QUICEncryptionLevel::HANDSHAKE),
1698                                                            std::move(buf), len, ack_eliciting, probing, crypto);
1699     break;
1700   }
1701   case QUICPacketType::ZERO_RTT_PROTECTED: {
1702     packet = this->_packet_factory.create_zero_rtt_packet(this->_original_quic_connection_id, this->_quic_connection_id,
1703                                                           this->_largest_acked_packet_number(QUICEncryptionLevel::ZERO_RTT),
1704                                                           std::move(buf), len, ack_eliciting, probing);
1705     break;
1706   }
1707   case QUICPacketType::PROTECTED: {
1708     packet = this->_packet_factory.create_protected_packet(this->_peer_quic_connection_id,
1709                                                            this->_largest_acked_packet_number(QUICEncryptionLevel::ONE_RTT),
1710                                                            std::move(buf), len, ack_eliciting, probing);
1711     break;
1712   }
1713   default:
1714     // should not be here
1715     ink_assert(false);
1716     break;
1717   }
1718 
1719   return packet;
1720 }
1721 
1722 void
_init_flow_control_params(const std::shared_ptr<const QUICTransportParameters> & local_tp,const std::shared_ptr<const QUICTransportParameters> & remote_tp)1723 QUICNetVConnection::_init_flow_control_params(const std::shared_ptr<const QUICTransportParameters> &local_tp,
1724                                               const std::shared_ptr<const QUICTransportParameters> &remote_tp)
1725 {
1726   this->_stream_manager->init_flow_control_params(local_tp, remote_tp);
1727 
1728   uint64_t local_initial_max_data  = 0;
1729   uint64_t remote_initial_max_data = 0;
1730   if (local_tp) {
1731     local_initial_max_data          = local_tp->getAsUInt(QUICTransportParameterId::INITIAL_MAX_DATA);
1732     this->_flow_control_buffer_size = local_initial_max_data;
1733   }
1734   if (remote_tp) {
1735     remote_initial_max_data = remote_tp->getAsUInt(QUICTransportParameterId::INITIAL_MAX_DATA);
1736   }
1737 
1738   this->_local_flow_controller->set_limit(local_initial_max_data);
1739   this->_remote_flow_controller->set_limit(remote_initial_max_data);
1740   QUICFCDebug("[LOCAL] %" PRIu64 "/%" PRIu64, this->_local_flow_controller->current_offset(),
1741               this->_local_flow_controller->current_limit());
1742   QUICFCDebug("[REMOTE] %" PRIu64 "/%" PRIu64, this->_remote_flow_controller->current_offset(),
1743               this->_remote_flow_controller->current_limit());
1744 }
1745 
1746 void
_handle_error(QUICConnectionErrorUPtr error)1747 QUICNetVConnection::_handle_error(QUICConnectionErrorUPtr error)
1748 {
1749   QUICError("QUICError: %s (%u), %s (0x%" PRIx16 ")", QUICDebugNames::error_class(error->cls),
1750             static_cast<unsigned int>(error->cls), QUICDebugNames::error_code(error->code), error->code);
1751 
1752   // Connection Error
1753   this->close(std::move(error));
1754 }
1755 
1756 QUICPacketUPtr
_dequeue_recv_packet(QUICPacketCreationResult & result)1757 QUICNetVConnection::_dequeue_recv_packet(QUICPacketCreationResult &result)
1758 {
1759   QUICPacketUPtr packet = this->_packet_recv_queue.dequeue(result);
1760 
1761   if (result == QUICPacketCreationResult::SUCCESS) {
1762     if (this->direction() == NET_VCONNECTION_OUT) {
1763       // Reset CID if a server sent back a new CID
1764       // FIXME This should happen only once
1765       QUICConnectionId src_cid = packet->source_cid();
1766       // FIXME src connection id could be zero ? if so, check packet header type.
1767       if (src_cid != QUICConnectionId::ZERO()) {
1768         if (this->_peer_quic_connection_id != src_cid) {
1769           this->_update_peer_cid(src_cid);
1770         }
1771       }
1772     }
1773 
1774     if (!this->_verfied_state.is_verified()) {
1775       this->_verfied_state.fill(packet->size());
1776     }
1777   }
1778 
1779   // Debug prints
1780   switch (result) {
1781   case QUICPacketCreationResult::NO_PACKET:
1782     break;
1783   case QUICPacketCreationResult::NOT_READY:
1784     QUICConDebug("Not ready to decrypt the packet");
1785     break;
1786   case QUICPacketCreationResult::IGNORED:
1787     QUICConDebug("Ignored");
1788     break;
1789   case QUICPacketCreationResult::UNSUPPORTED:
1790     QUICConDebug("Unsupported version");
1791     break;
1792   case QUICPacketCreationResult::SUCCESS:
1793     if (packet->type() == QUICPacketType::VERSION_NEGOTIATION) {
1794       QUICConDebug("[RX] %s packet size=%u", QUICDebugNames::packet_type(packet->type()), packet->size());
1795     } else {
1796       QUICConDebug("[RX] %s packet #%" PRIu64 " size=%u header_len=%u payload_len=%u", QUICDebugNames::packet_type(packet->type()),
1797                    packet->packet_number(), packet->size(), packet->header_size(), packet->payload_length());
1798     }
1799     break;
1800   default:
1801     QUICConDebug("Failed to decrypt the packet");
1802     break;
1803   }
1804 
1805   return packet;
1806 }
1807 
1808 void
_schedule_packet_write_ready(bool delay)1809 QUICNetVConnection::_schedule_packet_write_ready(bool delay)
1810 {
1811   if (!this->_packet_write_ready) {
1812     QUICConVVVDebug("Schedule %s event", QUICDebugNames::quic_event(QUIC_EVENT_PACKET_WRITE_READY));
1813     if (delay) {
1814       this->_packet_write_ready = this->thread->schedule_in(this, WRITE_READY_INTERVAL, QUIC_EVENT_PACKET_WRITE_READY, nullptr);
1815     } else {
1816       this->_packet_write_ready = this->thread->schedule_imm(this, QUIC_EVENT_PACKET_WRITE_READY, nullptr);
1817     }
1818   }
1819 }
1820 
1821 void
_unschedule_packet_write_ready()1822 QUICNetVConnection::_unschedule_packet_write_ready()
1823 {
1824   if (this->_packet_write_ready) {
1825     this->_packet_write_ready->cancel();
1826     this->_packet_write_ready = nullptr;
1827   }
1828 }
1829 
1830 void
_close_packet_write_ready(Event * data)1831 QUICNetVConnection::_close_packet_write_ready(Event *data)
1832 {
1833   ink_assert(this->_packet_write_ready == data);
1834   this->_packet_write_ready = nullptr;
1835 }
1836 
1837 void
_schedule_closing_timeout(ink_hrtime interval)1838 QUICNetVConnection::_schedule_closing_timeout(ink_hrtime interval)
1839 {
1840   if (!this->_closing_timeout) {
1841     QUICConDebug("Schedule %s event in %" PRIu64 "ms", QUICDebugNames::quic_event(QUIC_EVENT_CLOSING_TIMEOUT),
1842                  interval / HRTIME_MSECOND);
1843     this->_closing_timeout = this->thread->schedule_in_local(this, interval, QUIC_EVENT_CLOSING_TIMEOUT);
1844   }
1845 }
1846 
1847 void
_unschedule_closing_timeout()1848 QUICNetVConnection::_unschedule_closing_timeout()
1849 {
1850   if (this->_closing_timeout) {
1851     QUICConDebug("Unschedule %s event", QUICDebugNames::quic_event(QUIC_EVENT_CLOSING_TIMEOUT));
1852     this->_closing_timeout->cancel();
1853     this->_closing_timeout = nullptr;
1854   }
1855 }
1856 
1857 void
_schedule_ack_manager_periodic(ink_hrtime interval)1858 QUICNetVConnection::_schedule_ack_manager_periodic(ink_hrtime interval)
1859 {
1860   this->_ack_manager_periodic = this->thread->schedule_every(this, interval, QUIC_EVENT_ACK_PERIODIC);
1861 }
1862 
1863 void
_unschedule_ack_manager_periodic()1864 QUICNetVConnection::_unschedule_ack_manager_periodic()
1865 {
1866   if (this->_ack_manager_periodic) {
1867     QUICConDebug("Unschedule %s event", QUICDebugNames::quic_event(QUIC_EVENT_ACK_PERIODIC));
1868     this->_ack_manager_periodic->cancel();
1869     this->_ack_manager_periodic = nullptr;
1870   }
1871 }
1872 
1873 void
_close_closing_timeout(Event * data)1874 QUICNetVConnection::_close_closing_timeout(Event *data)
1875 {
1876   ink_assert(this->_closing_timeout == data);
1877   this->_closing_timeout = nullptr;
1878 }
1879 
1880 void
_schedule_closed_event()1881 QUICNetVConnection::_schedule_closed_event()
1882 {
1883   if (!this->_closed_event) {
1884     QUICConDebug("Schedule %s event", QUICDebugNames::quic_event(QUIC_EVENT_SHUTDOWN));
1885     this->_closed_event = this->thread->schedule_imm(this, QUIC_EVENT_SHUTDOWN, nullptr);
1886   }
1887 }
1888 
1889 void
_unschedule_closed_event()1890 QUICNetVConnection::_unschedule_closed_event()
1891 {
1892   if (!this->_closed_event) {
1893     QUICConDebug("Unschedule %s event", QUICDebugNames::quic_event(QUIC_EVENT_SHUTDOWN));
1894     this->_closed_event->cancel();
1895     this->_closed_event = nullptr;
1896   }
1897 }
1898 
1899 void
_close_closed_event(Event * data)1900 QUICNetVConnection::_close_closed_event(Event *data)
1901 {
1902   ink_assert(this->_closed_event == data);
1903   this->_closed_event = nullptr;
1904 }
1905 
1906 int
_complete_handshake_if_possible()1907 QUICNetVConnection::_complete_handshake_if_possible()
1908 {
1909   if (this->handler != reinterpret_cast<NetVConnHandler>(&QUICNetVConnection::state_handshake)) {
1910     return 0;
1911   }
1912 
1913   if (!(this->_handshake_handler && this->_handshake_handler->is_completed())) {
1914     return -1;
1915   }
1916 
1917   if (this->netvc_context == NET_VCONNECTION_OUT && !this->_handshake_handler->has_remote_tp()) {
1918     return -1;
1919   }
1920 
1921   this->_init_flow_control_params(this->_handshake_handler->local_transport_parameters(),
1922                                   this->_handshake_handler->remote_transport_parameters());
1923 
1924   // PN space doesn't matter but seems like this is the way to pick the LossDetector for 0-RTT and Short packet
1925   uint64_t ack_delay_exponent =
1926     this->_handshake_handler->remote_transport_parameters()->getAsUInt(QUICTransportParameterId::ACK_DELAY_EXPONENT);
1927   this->_loss_detector->update_ack_delay_exponent(ack_delay_exponent);
1928 
1929   this->_start_application();
1930 
1931   return 0;
1932 }
1933 
1934 void
_start_application()1935 QUICNetVConnection::_start_application()
1936 {
1937   if (!this->_application_started) {
1938     this->_application_started = true;
1939 
1940     const uint8_t *app_name;
1941     unsigned int app_name_len = 0;
1942     this->_handshake_handler->negotiated_application_name(&app_name, &app_name_len);
1943     if (app_name == nullptr) {
1944       app_name     = reinterpret_cast<const uint8_t *>(IP_PROTO_TAG_HTTP_QUIC.data());
1945       app_name_len = IP_PROTO_TAG_HTTP_QUIC.size();
1946     }
1947 
1948     if (netvc_context == NET_VCONNECTION_IN) {
1949       if (!this->setSelectedProtocol(app_name, app_name_len)) {
1950         this->_handle_error(std::make_unique<QUICConnectionError>(QUICTransErrorCode::PROTOCOL_VIOLATION));
1951       } else {
1952         this->endpoint()->handleEvent(NET_EVENT_ACCEPT, this);
1953       }
1954     } else {
1955       this->action_.continuation->handleEvent(NET_EVENT_OPEN, this);
1956     }
1957   }
1958 }
1959 
1960 void
_switch_to_handshake_state()1961 QUICNetVConnection::_switch_to_handshake_state()
1962 {
1963   QUICConDebug("Enter state_handshake");
1964   SET_HANDLER((NetVConnHandler)&QUICNetVConnection::state_handshake);
1965 }
1966 
1967 void
_switch_to_established_state()1968 QUICNetVConnection::_switch_to_established_state()
1969 {
1970   if (this->_complete_handshake_if_possible() == 0) {
1971     QUICConDebug("Enter state_connection_established");
1972     QUICConDebug("Negotiated cipher suite: %s", this->_handshake_handler->negotiated_cipher_suite());
1973 
1974     SET_HANDLER((NetVConnHandler)&QUICNetVConnection::state_connection_established);
1975 
1976     std::shared_ptr<const QUICTransportParameters> remote_tp = this->_handshake_handler->remote_transport_parameters();
1977 
1978     uint64_t active_cid_limit = remote_tp->getAsUInt(QUICTransportParameterId::ACTIVE_CONNECTION_ID_LIMIT);
1979     if (active_cid_limit) {
1980       this->_alt_con_manager->set_remote_active_cid_limit(active_cid_limit);
1981     }
1982 
1983     if (this->direction() == NET_VCONNECTION_OUT) {
1984       uint16_t len;
1985       const uint8_t *pref_addr_buf = remote_tp->getAsBytes(QUICTransportParameterId::PREFERRED_ADDRESS, len);
1986       if (pref_addr_buf) {
1987         this->_alt_con_manager->set_remote_preferred_address({pref_addr_buf, len});
1988       }
1989     } else {
1990       QUICPath trusted_path = {this->local_addr, this->remote_addr};
1991       this->_path_manager->set_trusted_path(trusted_path);
1992     }
1993   } else {
1994     // Illegal state change
1995     ink_assert(!"Handshake has to be completed");
1996   }
1997 }
1998 
1999 void
_switch_to_closing_state(QUICConnectionErrorUPtr error)2000 QUICNetVConnection::_switch_to_closing_state(QUICConnectionErrorUPtr error)
2001 {
2002   if (this->_complete_handshake_if_possible() != 0) {
2003     QUICConDebug("Switching state without handshake completion");
2004   }
2005   if (error->msg) {
2006     QUICConDebug("Reason: %.*s", static_cast<int>(strlen(error->msg)), error->msg);
2007   }
2008 
2009   // Once we are in closing or draining state, the ack_manager is not needed anymore. Because we don't send
2010   // any frame other than close_frame.
2011   this->_unschedule_ack_manager_periodic();
2012 
2013   this->_connection_error = std::move(error);
2014   this->_schedule_packet_write_ready();
2015 
2016   this->remove_from_active_queue();
2017   this->set_inactivity_timeout(0);
2018 
2019   ink_hrtime rto = this->_rtt_measure.current_pto_period();
2020 
2021   QUICConDebug("Enter state_connection_closing");
2022   SET_HANDLER((NetVConnHandler)&QUICNetVConnection::state_connection_closing);
2023 
2024   // This states SHOULD persist for three times the
2025   // current Retransmission Timeout (RTO) interval as defined in
2026   // [QUIC-RECOVERY].
2027   this->_schedule_closing_timeout(3 * rto);
2028 }
2029 
2030 void
_switch_to_draining_state(QUICConnectionErrorUPtr error)2031 QUICNetVConnection::_switch_to_draining_state(QUICConnectionErrorUPtr error)
2032 {
2033   if (this->_complete_handshake_if_possible() != 0) {
2034     QUICConDebug("Switching state without handshake completion");
2035   }
2036   if (error->msg) {
2037     QUICConDebug("Reason: %.*s", static_cast<int>(strlen(error->msg)), error->msg);
2038   }
2039 
2040   // Once we are in closing or draining state, the ack_manager is not needed anymore. Because we don't send
2041   // any frame other than close_frame.
2042   this->_unschedule_ack_manager_periodic();
2043 
2044   this->remove_from_active_queue();
2045   this->set_inactivity_timeout(0);
2046 
2047   ink_hrtime rto = this->_rtt_measure.current_pto_period();
2048 
2049   QUICConDebug("Enter state_connection_draining");
2050   SET_HANDLER((NetVConnHandler)&QUICNetVConnection::state_connection_draining);
2051 
2052   // This states SHOULD persist for three times the
2053   // current Retransmission Timeout (RTO) interval as defined in
2054   // [QUIC-RECOVERY].
2055 
2056   this->_schedule_closing_timeout(3 * rto);
2057 }
2058 
2059 void
_switch_to_close_state()2060 QUICNetVConnection::_switch_to_close_state()
2061 {
2062   this->_unschedule_closing_timeout();
2063 
2064   if (this->_complete_handshake_if_possible() != 0) {
2065     QUICConDebug("Switching state without handshake completion");
2066   }
2067   QUICConDebug("Enter state_connection_closed");
2068   SET_HANDLER((NetVConnHandler)&QUICNetVConnection::state_connection_closed);
2069   this->_schedule_closed_event();
2070 }
2071 
2072 void
_handle_idle_timeout()2073 QUICNetVConnection::_handle_idle_timeout()
2074 {
2075   this->remove_from_active_queue();
2076   this->_switch_to_draining_state(std::make_unique<QUICConnectionError>(QUICTransErrorCode::NO_ERROR, "Idle Timeout"));
2077 
2078   // TODO: signal VC_EVENT_ACTIVE_TIMEOUT/VC_EVENT_INACTIVITY_TIMEOUT to application
2079 }
2080 
2081 void
_validate_new_path(const QUICPath & path)2082 QUICNetVConnection::_validate_new_path(const QUICPath &path)
2083 {
2084   // Not sure how long we should wait. The spec says just "enough time".
2085   // Use the same time amount as the closing timeout.
2086   ink_hrtime rto = this->_rtt_measure.current_pto_period();
2087   this->_path_manager->open_new_path(path, 3 * rto);
2088 }
2089 
2090 void
_update_cids()2091 QUICNetVConnection::_update_cids()
2092 {
2093   snprintf(this->_cids_data, sizeof(this->_cids_data), "%08" PRIx32 "-%08" PRIx32 "", this->_peer_quic_connection_id.h32(),
2094            this->_quic_connection_id.h32());
2095 
2096   this->_cids = {this->_cids_data, sizeof(this->_cids_data)};
2097 }
2098 
2099 void
_update_peer_cid(const QUICConnectionId & new_cid)2100 QUICNetVConnection::_update_peer_cid(const QUICConnectionId &new_cid)
2101 {
2102   if (is_debug_tag_set(QUIC_DEBUG_TAG.data())) {
2103     char old_cid_str[QUICConnectionId::MAX_HEX_STR_LENGTH];
2104     char new_cid_str[QUICConnectionId::MAX_HEX_STR_LENGTH];
2105     this->_peer_quic_connection_id.hex(old_cid_str, QUICConnectionId::MAX_HEX_STR_LENGTH);
2106     new_cid.hex(new_cid_str, QUICConnectionId::MAX_HEX_STR_LENGTH);
2107 
2108     QUICConDebug("dcid: %s -> %s", old_cid_str, new_cid_str);
2109   }
2110 
2111   this->_peer_old_quic_connection_id = this->_peer_quic_connection_id;
2112   this->_peer_quic_connection_id     = new_cid;
2113   this->_update_cids();
2114 }
2115 
2116 void
_update_local_cid(const QUICConnectionId & new_cid)2117 QUICNetVConnection::_update_local_cid(const QUICConnectionId &new_cid)
2118 {
2119   if (is_debug_tag_set(QUIC_DEBUG_TAG.data())) {
2120     char old_cid_str[QUICConnectionId::MAX_HEX_STR_LENGTH];
2121     char new_cid_str[QUICConnectionId::MAX_HEX_STR_LENGTH];
2122     this->_quic_connection_id.hex(old_cid_str, QUICConnectionId::MAX_HEX_STR_LENGTH);
2123     new_cid.hex(new_cid_str, QUICConnectionId::MAX_HEX_STR_LENGTH);
2124 
2125     QUICConDebug("scid: %s -> %s", old_cid_str, new_cid_str);
2126   }
2127 
2128   this->_quic_connection_id = new_cid;
2129   this->_update_cids();
2130 }
2131 
2132 void
_rerandomize_original_cid()2133 QUICNetVConnection::_rerandomize_original_cid()
2134 {
2135   QUICConnectionId tmp = this->_original_quic_connection_id;
2136   this->_original_quic_connection_id.randomize();
2137 
2138   if (is_debug_tag_set(QUIC_DEBUG_TAG.data())) {
2139     char old_cid_str[QUICConnectionId::MAX_HEX_STR_LENGTH];
2140     char new_cid_str[QUICConnectionId::MAX_HEX_STR_LENGTH];
2141     tmp.hex(old_cid_str, QUICConnectionId::MAX_HEX_STR_LENGTH);
2142     this->_original_quic_connection_id.hex(new_cid_str, QUICConnectionId::MAX_HEX_STR_LENGTH);
2143 
2144     QUICConDebug("original cid: %s -> %s", old_cid_str, new_cid_str);
2145   }
2146 }
2147 
2148 QUICHandshakeProtocol *
_setup_handshake_protocol(shared_SSL_CTX ctx)2149 QUICNetVConnection::_setup_handshake_protocol(shared_SSL_CTX ctx)
2150 {
2151   // Initialize handshake protocol specific stuff
2152   // For QUICv1 TLS is the only option
2153   QUICTLS *tls = new QUICTLS(this->_pp_key_info, ctx.get(), this->direction(), this->options,
2154                              this->_quic_config->client_session_file(), this->_quic_config->client_keylog_file());
2155   SSL_set_ex_data(tls->ssl_handle(), QUIC::ssl_quic_qc_index, static_cast<QUICConnection *>(this));
2156 
2157   return tls;
2158 }
2159 
2160 QUICConnectionErrorUPtr
_state_connection_established_migrate_connection(const QUICPacket & p)2161 QUICNetVConnection::_state_connection_established_migrate_connection(const QUICPacket &p)
2162 {
2163   ink_assert(this->_handshake_handler->is_completed());
2164 
2165   QUICConnectionErrorUPtr error = nullptr;
2166   QUICConnectionId dcid         = p.destination_cid();
2167 
2168   if (this->netvc_context == NET_VCONNECTION_IN) {
2169     if (!this->_alt_con_manager->is_ready_to_migrate()) {
2170       // TODO: Should endpoint send connection error when remote endpoint doesn't send NEW_CONNECTION_ID frames before initiating
2171       // connection migration ?
2172       QUICConDebug("Ignore connection migration - remote endpoint initiated CM before sending NEW_CONNECTION_ID frames");
2173       return error;
2174     }
2175     QUICConDebug("Connection migration is initiated by remote");
2176   }
2177 
2178   if (this->connection_id() == dcid) {
2179     QUICConDebug("Maybe NAT rebinding");
2180     // On client side (NET_VCONNECTION_OUT), nothing to do any more
2181     if (this->netvc_context == NET_VCONNECTION_IN) {
2182       Connection con;
2183       con.setRemote(&(p.from().sa));
2184       this->con.move(con);
2185       this->set_remote_addr();
2186       this->_udp_con = p.udp_con();
2187 
2188       QUICPath new_path = {p.to(), p.from()};
2189       this->_validate_new_path(new_path);
2190     }
2191   } else {
2192     QUICConDebug("Different CID");
2193     if (this->_alt_con_manager->migrate_to(dcid, this->_reset_token)) {
2194       // DCID of received packet is local cid
2195       this->_update_local_cid(dcid);
2196 
2197       // On client side (NET_VCONNECTION_OUT), nothing to do any more
2198       if (this->netvc_context == NET_VCONNECTION_IN) {
2199         Connection con;
2200         con.setRemote(&(p.from().sa));
2201         this->con.move(con);
2202         this->set_remote_addr();
2203         this->_udp_con = p.udp_con();
2204 
2205         this->_update_peer_cid(this->_alt_con_manager->migrate_to_alt_cid());
2206 
2207         QUICPath new_path = {this->local_addr, con.addr};
2208         this->_validate_new_path(new_path);
2209       }
2210     } else {
2211       char dcid_str[QUICConnectionId::MAX_HEX_STR_LENGTH];
2212       dcid.hex(dcid_str, QUICConnectionId::MAX_HEX_STR_LENGTH);
2213       QUICConDebug("Connection migration failed cid=%s", dcid_str);
2214     }
2215   }
2216 
2217   return error;
2218 }
2219 
2220 /**
2221  * Connection Migration Excercise from client
2222  */
2223 QUICConnectionErrorUPtr
_state_connection_established_initiate_connection_migration()2224 QUICNetVConnection::_state_connection_established_initiate_connection_migration()
2225 {
2226   ink_assert(this->_handshake_handler->is_completed());
2227   ink_assert(this->netvc_context == NET_VCONNECTION_OUT);
2228 
2229   QUICConnectionErrorUPtr error = nullptr;
2230 
2231   std::shared_ptr<const QUICTransportParameters> remote_tp = this->_handshake_handler->remote_transport_parameters();
2232 
2233   if (this->_connection_migration_initiated || remote_tp->contains(QUICTransportParameterId::DISABLE_ACTIVE_MIGRATION) ||
2234       !this->_alt_con_manager->is_ready_to_migrate() ||
2235       this->_alt_con_manager->will_generate_frame(QUICEncryptionLevel::ONE_RTT, 0, true, this->_seq_num++)) {
2236     return error;
2237   }
2238 
2239   QUICConDebug("Initiated connection migration");
2240   this->_connection_migration_initiated = true;
2241 
2242   this->_update_peer_cid(this->_alt_con_manager->migrate_to_alt_cid());
2243 
2244   auto current_path = this->_path_manager->get_verified_path();
2245   QUICPath new_path = {current_path.local_ep(), current_path.remote_ep()};
2246   this->_validate_new_path(new_path);
2247 
2248   return error;
2249 }
2250 
2251 void
_handle_periodic_ack_event()2252 QUICNetVConnection::_handle_periodic_ack_event()
2253 {
2254   bool need_schedule = false;
2255   for (int i = static_cast<int>(this->_minimum_encryption_level); i <= static_cast<int>(QUICEncryptionLevel::ONE_RTT); ++i) {
2256     if (this->_ack_frame_manager.will_generate_frame(QUIC_ENCRYPTION_LEVELS[i], 0, true, this->_seq_num++)) {
2257       need_schedule = true;
2258       break;
2259     }
2260   }
2261 
2262   if (need_schedule) {
2263     // we have ack to send
2264     // FIXME: should sent depend on socket event.
2265     this->_schedule_packet_write_ready();
2266   }
2267 }
2268