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 <inttypes.h>
27 #include <queue>
28 
29 #include "QUICFrameGenerator.h"
30 #include "QUICTypes.h"
31 #include "QUICConnection.h"
32 
33 class QUICConnectionTable;
34 class QUICResetTokenTable;
35 
36 class QUICAltConnectionManager : public QUICFrameHandler, public QUICFrameGenerator
37 {
38 public:
39   QUICAltConnectionManager(QUICConnection *qc, QUICConnectionTable &ctable, QUICResetTokenTable &rtable,
40                            const QUICConnectionId &peer_initial_cid, uint32_t instance_id, uint8_t active_cid_limit,
41                            const IpEndpoint *preferred_endpoint_ipv4 = nullptr,
42                            const IpEndpoint *preferred_endpoint_ipv6 = nullptr);
43   ~QUICAltConnectionManager();
44 
45   /**
46    * Check if AltConnectionManager has at least one CID advertised by the peer.
47    */
48   bool is_ready_to_migrate() const;
49 
50   /**
51    * Prepare for new CID for the peer, and return one of CIDs advertised by the peer.
52    * New CID for the peer will be sent on next call for generate_frame()
53    */
54   QUICConnectionId migrate_to_alt_cid();
55 
56   /**
57    * Migrate to new CID
58    *
59    * cid need to match with one of alt CID that AltConnectionManager prepared.
60    */
61   bool migrate_to(const QUICConnectionId &cid, QUICStatelessResetToken &new_reset_token);
62 
63   void drop_cid(const QUICConnectionId &cid);
64 
65   void set_remote_preferred_address(const QUICPreferredAddress &preferred_address);
66   void set_remote_active_cid_limit(uint8_t active_cid_limit);
67 
68   /**
69    * Invalidate all CIDs prepared
70    */
71   void invalidate_alt_connections();
72 
73   /**
74    * Returns server preferred address if available
75    */
76   const QUICPreferredAddress *preferred_address() const;
77 
78   // QUICFrameHandler
79   virtual std::vector<QUICFrameType> interests() override;
80   virtual QUICConnectionErrorUPtr handle_frame(QUICEncryptionLevel level, const QUICFrame &frame) override;
81 
82   // QUICFrameGenerator
83   bool will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) override;
84   QUICFrame *generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size,
85                             size_t current_packet_size, uint32_t seq_num) override;
86 
87 private:
88   struct AltConnectionInfo {
89     uint64_t seq_num;
90     QUICConnectionId id;
91     QUICStatelessResetToken token;
92     union {
93       bool advertised; // For local info
94       bool used;       // For remote info
95     };
96   };
97 
98   QUICConnection *_qc = nullptr;
99   QUICConnectionTable &_ctable;
100   QUICResetTokenTable &_rtable;
101   AltConnectionInfo _alt_quic_connection_ids_local[8]; // 8 is perhaps enough
102   std::vector<AltConnectionInfo> _alt_quic_connection_ids_remote;
103   std::queue<uint64_t> _retired_seq_nums;
104   uint32_t _instance_id                          = 0;
105   uint8_t _local_active_cid_limit                = 0;
106   uint8_t _remote_active_cid_limit               = 0;
107   uint64_t _alt_quic_connection_id_seq_num       = 0;
108   bool _need_advertise                           = false;
109   QUICPreferredAddress *_local_preferred_address = nullptr;
110 
111   AltConnectionInfo _generate_next_alt_con_info();
112   void _init_alt_connection_ids();
113   void _update_alt_connection_id(uint64_t chosen_seq_num);
114 
115   void _records_new_connection_id_frame(QUICEncryptionLevel level, const QUICNewConnectionIdFrame &frame);
116   void _records_retire_connection_id_frame(QUICEncryptionLevel, const QUICRetireConnectionIdFrame &frame);
117 
118   void _on_frame_lost(QUICFrameInformationUPtr &info) override;
119 
120   QUICConnectionErrorUPtr _register_remote_connection_id(const QUICNewConnectionIdFrame &frame);
121   QUICConnectionErrorUPtr _retire_remote_connection_id(const QUICRetireConnectionIdFrame &frame);
122 };
123