139 uint64_t initial_timeout_ms,
140 uint64_t max_timeout_ms,
141 std::optional<size_t> max_retransmissions,
142 size_t max_handshake_msg_size,
143 uint16_t initial_epoch = 0);
157#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
158 std::vector<uint8_t> start_with_client_hello_from_downgrade(
const Handshake_Message& client_hello)
override;
161 std::vector<uint8_t>
format(
const std::vector<uint8_t>& handshake_msg,
164 void add_record(
const uint8_t record[],
size_t record_len,
Record_Type type, uint64_t sequence_number)
override;
171 uint64_t sequence_number);
173 std::pair<Handshake_Type, std::vector<uint8_t>>
get_next_record(
bool expecting_ccs,
174 size_t max_message_size)
override;
187 uint64_t record_sequence,
188 bool retransmitted_flight);
190 bool reassemble_retransmitted_fragment(
const uint8_t fragment[],
191 size_t fragment_length,
192 size_t fragment_offset,
196 uint16_t message_seq);
198 bool process_previous_handshake_fragment(
const uint8_t fragment[],
199 size_t fragment_length,
200 size_t fragment_offset,
204 uint16_t message_seq,
205 bool retransmitted_flight);
209 void discard_stale_epoch_messages();
211 void retransmit_flight(
size_t flight);
212 void retransmit_last_flight();
213 void replay_last_flight_for_peer();
217 std::optional<size_t> last_completed_flight_index()
const;
219 std::vector<uint8_t> format_fragment(
const uint8_t fragment[],
221 uint32_t frag_offset,
224 uint16_t msg_sequence)
const;
226 std::vector<uint8_t> format_w_seq(
const std::vector<uint8_t>& handshake_msg,
228 uint16_t msg_sequence)
const;
230 std::vector<uint8_t> send_message(uint16_t msg_seq,
233 const std::vector<uint8_t>& msg);
235 class Handshake_Reassembly final {
237 void add_fragment(
const uint8_t fragment[],
238 size_t fragment_length,
239 size_t fragment_offset,
248 bool complete()
const;
250 uint16_t epoch()
const {
return m_epoch; }
253 size_t msg_length()
const {
return m_msg_length; }
255 std::pair<Handshake_Type, std::vector<uint8_t>> message()
const;
258 Handshake_Type m_msg_type = Handshake_Type::None;
259 size_t m_msg_length = 0;
260 size_t m_bytes_received = 0;
261 uint16_t m_epoch = 0;
265 std::vector<uint8_t> m_received_mask;
266 std::vector<uint8_t> m_message;
272 bool charged_add_fragment(Handshake_Reassembly& reassembly,
274 const uint8_t fragment[],
275 size_t fragment_length,
276 size_t fragment_offset,
278 Handshake_Type msg_type,
282 void release_reassembly_bytes(
const Handshake_Reassembly& reassembly);
284 struct Message_Info final {
285 Message_Info(uint16_t e, Handshake_Type mt,
const std::vector<uint8_t>& msg) :
286 epoch(e), msg_type(mt), msg_bits(msg) {}
290 std::vector<uint8_t> msg_bits;
293 class Connection_Sequence_Numbers& m_seqs;
294 std::map<uint16_t, Handshake_Reassembly> m_messages;
295 size_t m_pending_reassembly_bytes = 0;
296 std::set<uint16_t> m_ccs_epochs;
300 std::optional<uint16_t> m_retransmitted_ccs_epoch;
301 std::optional<uint16_t> m_retransmitted_finished_epoch;
302 std::map<Handshake_Type, std::pair<uint16_t, Handshake_Reassembly>> m_retransmitted_messages;
303 std::vector<std::vector<uint16_t>> m_flights;
306 std::vector<std::vector<std::pair<size_t, uint16_t>>> m_flight_ccs;
307 std::map<uint16_t, Message_Info> m_flight_data;
309 std::optional<std::pair<uint16_t, Handshake_Reassembly>> m_retransmitted_client_hello;
310 bool m_awaiting_cookie_client_hello =
false;
311 bool m_recreating_hello_verify_request =
false;
312 bool m_finished =
false;
313 bool m_retransmit_terminal_flight =
false;
315 uint64_t m_initial_timeout = 0;
316 uint64_t m_max_timeout = 0;
322 std::optional<size_t> m_max_retransmissions = 0;
323 size_t m_retransmit_count = 0;
328 std::optional<uint64_t> m_last_write;
333 size_t m_peer_replay_count = 0;
335 uint64_t m_next_timeout = 0;
337 uint16_t m_in_message_seq = 0;
338 uint16_t m_out_message_seq = 0;
343 std::optional<uint16_t> m_first_delivered_epoch;
347 bool m_in_message_seq_wrapped =
false;
351 uint16_t m_initial_epoch;
355 uint16_t m_last_delivered_epoch = 0;
358 steady_clock_fn m_steady_clock_ms;
360 size_t m_max_handshake_msg_size;
361 size_t m_max_pending_reassembly;