quic_rcidm.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #ifndef OSSL_INTERNAL_QUIC_RCIDM_H
  10. # define OSSL_INTERNAL_QUIC_RCIDM_H
  11. # pragma once
  12. # include "internal/e_os.h"
  13. # include "internal/time.h"
  14. # include "internal/quic_types.h"
  15. # include "internal/quic_wire.h"
  16. # ifndef OPENSSL_NO_QUIC
  17. /*
  18. * QUIC Remote Connection ID Manager
  19. * =================================
  20. *
  21. * This manages connection IDs for the TX side. The RCIDM tracks remote CIDs
  22. * (RCIDs) which a peer has issued to us and which we can use as the DCID of
  23. * packets we transmit. It is entirely separate from the LCIDM, which handles
  24. * routing received packets by their DCIDs.
  25. *
  26. * RCIDs fall into four categories:
  27. *
  28. * 1. A client's Initial ODCID (0..1)
  29. * 2. A peer's Initial SCID (1)
  30. * 3. A server's Retry SCID (0..1)
  31. * 4. A CID issued via a NEW_CONNECTION_ID frame (n)
  32. *
  33. * Unlike a LCIDM, which is per port, a RCIDM is per connection, as there is no
  34. * need for routing of outgoing packets.
  35. */
  36. typedef struct quic_rcidm_st QUIC_RCIDM;
  37. /*
  38. * Creates a new RCIDM. Returns NULL on failure.
  39. *
  40. * For a client, initial_odcid is the client's Initial ODCID.
  41. * For a server, initial_odcid is NULL.
  42. */
  43. QUIC_RCIDM *ossl_quic_rcidm_new(const QUIC_CONN_ID *initial_odcid);
  44. /* Frees a RCIDM. */
  45. void ossl_quic_rcidm_free(QUIC_RCIDM *rcidm);
  46. /*
  47. * CID Events
  48. * ==========
  49. */
  50. /*
  51. * To be called by a client when a server responds to the first Initial packet
  52. * sent with its own Initial packet with its own SCID; or to be called by a
  53. * server when we first get an Initial packet from a client with the client's
  54. * supplied SCID. The added RCID implicitly has a sequence number of 0.
  55. *
  56. * We immediately switch to using this SCID as our preferred RCID. This SCID
  57. * must be enrolled using this function. May only be called once.
  58. */
  59. int ossl_quic_rcidm_add_from_initial(QUIC_RCIDM *rcidm,
  60. const QUIC_CONN_ID *rcid);
  61. /*
  62. * To be called by a client when a server responds to the first Initial packet
  63. * sent with a Retry packet with its own SCID (the "Retry ODCID"). We
  64. * immediately switch to using this SCID as our preferred RCID when conducting
  65. * the retry. This SCID must be enrolled using this function. May only be called
  66. * once. The added RCID has no sequence number associated with it as it is
  67. * essentially a new ODCID (hereafter a Retry ODCID).
  68. *
  69. * Not for server use.
  70. */
  71. int ossl_quic_rcidm_add_from_server_retry(QUIC_RCIDM *rcidm,
  72. const QUIC_CONN_ID *retry_odcid);
  73. /*
  74. * Processes an incoming NEW_CONN_ID frame, recording the new CID as a potential
  75. * RCID. The RCIDM retirement mechanism is ratcheted according to the
  76. * ncid->retire_prior_to field. The stateless_reset field is ignored; the caller
  77. * is responsible for handling it separately.
  78. */
  79. int ossl_quic_rcidm_add_from_ncid(QUIC_RCIDM *rcidm,
  80. const OSSL_QUIC_FRAME_NEW_CONN_ID *ncid);
  81. /*
  82. * Other Events
  83. * ============
  84. */
  85. /*
  86. * Notifies the RCIDM that the handshake for a connection is complete.
  87. * Should only be called once; further calls are ignored.
  88. *
  89. * This may influence the RCIDM's RCID change policy.
  90. */
  91. void ossl_quic_rcidm_on_handshake_complete(QUIC_RCIDM *rcidm);
  92. /*
  93. * Notifies the RCIDM that one or more packets have been sent.
  94. *
  95. * This may influence the RCIDM's RCID change policy.
  96. */
  97. void ossl_quic_rcidm_on_packet_sent(QUIC_RCIDM *rcidm, uint64_t num_packets);
  98. /*
  99. * Manually request switching to a new RCID as soon as possible.
  100. */
  101. void ossl_quic_rcidm_request_roll(QUIC_RCIDM *rcidm);
  102. /*
  103. * Queries
  104. * =======
  105. */
  106. /*
  107. * The RCIDM decides when it will never use a given RCID again. When it does
  108. * this, it outputs the sequence number of that RCID using this function, which
  109. * pops from a logical queue of retired RCIDs. The caller is responsible
  110. * for polling this function and generating Retire CID frames from the result.
  111. *
  112. * If nothing needs doing and the queue is empty, this function returns 0. If
  113. * there is an RCID which needs retiring, the sequence number of that RCID is
  114. * written to *seq_num (if seq_num is non-NULL) and this function returns 1. The
  115. * queue entry is popped (and the caller is thus assumed to have taken
  116. * responsibility for transmitting the necessary Retire CID frame).
  117. *
  118. * Note that the caller should not transmit a Retire CID frame immediately as
  119. * packets using the RCID may still be in flight. The caller must determine an
  120. * appropriate delay using knowledge of network conditions (RTT, etc.) which is
  121. * outside the scope of the RCIDM. The caller is responsible for implementing
  122. * this delay based on the last time a packet was transmitted using the RCID
  123. * being retired.
  124. */
  125. int ossl_quic_rcidm_pop_retire_seq_num(QUIC_RCIDM *rcid, uint64_t *seq_num);
  126. /*
  127. * Like ossl_quic_rcidm_pop_retire_seq_num, but does not pop the item from the
  128. * queue. If this call succeeds, the next call to
  129. * ossl_quic_rcidm_pop_retire_seq_num is guaranteed to output the same sequence
  130. * number.
  131. */
  132. int ossl_quic_rcidm_peek_retire_seq_num(QUIC_RCIDM *rcid, uint64_t *seq_num);
  133. /*
  134. * Writes the DCID preferred for a newly transmitted packet at this time to
  135. * *tx_dcid. This function should be called to determine what DCID to use when
  136. * transmitting a packet to the peer. The RCIDM may implement arbitrary policy
  137. * to decide when to change the preferred RCID.
  138. *
  139. * Returns 1 on success and 0 on failure.
  140. */
  141. int ossl_quic_rcidm_get_preferred_tx_dcid(QUIC_RCIDM *rcidm,
  142. QUIC_CONN_ID *tx_dcid);
  143. /*
  144. * Returns 1 if the value output by ossl_quic_rcidm_get_preferred_tx_dcid() has
  145. * changed since the last call to this function with clear set. If clear is set,
  146. * clears the changed flag. Returns the old value of the changed flag.
  147. */
  148. int ossl_quic_rcidm_get_preferred_tx_dcid_changed(QUIC_RCIDM *rcidm,
  149. int clear);
  150. /*
  151. * Returns the number of active numbered RCIDs we have. Note that this includes
  152. * RCIDs on the retir*ing* queue accessed via
  153. * ossl_quic_rcidm_pop_retire_seq_num() as these are still active until actually
  154. * retired.
  155. */
  156. size_t ossl_quic_rcidm_get_num_active(const QUIC_RCIDM *rcidm);
  157. /*
  158. * Returns the number of retir*ing* numbered RCIDs we have.
  159. */
  160. size_t ossl_quic_rcidm_get_num_retiring(const QUIC_RCIDM *rcidm);
  161. # endif
  162. #endif