1 /* 2 * ngtcp2 3 * 4 * Copyright (c) 2019 ngtcp2 contributors 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sublicense, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be 15 * included in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 #ifndef NGTCP2_PV_H 26 #define NGTCP2_PV_H 27 28 #ifdef HAVE_CONFIG_H 29 # include <config.h> 30 #endif /* HAVE_CONFIG_H */ 31 32 #include <ngtcp2/ngtcp2.h> 33 34 #include "ngtcp2_cid.h" 35 #include "ngtcp2_ringbuf.h" 36 37 /* NGTCP2_PV_MAX_ENTRIES is the maximum number of entries that 38 ngtcp2_pv can contain. It must be power of 2. */ 39 #define NGTCP2_PV_MAX_ENTRIES 8 40 /* NGTCP2_PV_NUM_PROBE_PKT is the number of probe packets containing 41 PATH_CHALLENGE sent at a time. */ 42 #define NGTCP2_PV_NUM_PROBE_PKT 2 43 44 typedef struct ngtcp2_log ngtcp2_log; 45 46 typedef struct ngtcp2_frame_chain ngtcp2_frame_chain; 47 48 /* NGTCP2_PV_ENTRY_FLAG_NONE indicates that no flag is set. */ 49 #define NGTCP2_PV_ENTRY_FLAG_NONE 0x00 50 /* NGTCP2_PV_ENTRY_FLAG_UNDERSIZED indicates that UDP datagram which 51 contains PATH_CHALLENGE is undersized (< 1200 bytes) */ 52 #define NGTCP2_PV_ENTRY_FLAG_UNDERSIZED 0x01 53 54 typedef struct ngtcp2_pv_entry { 55 /* expiry is the timestamp when this PATH_CHALLENGE expires. */ 56 ngtcp2_tstamp expiry; 57 /* flags is zero or more of NGTCP2_PV_ENTRY_FLAG_*. */ 58 uint8_t flags; 59 /* data is a byte string included in PATH_CHALLENGE. */ 60 uint8_t data[8]; 61 } ngtcp2_pv_entry; 62 63 void ngtcp2_pv_entry_init(ngtcp2_pv_entry *pvent, const uint8_t *data, 64 ngtcp2_tstamp expiry, uint8_t flags); 65 66 /* NGTCP2_PV_FLAG_NONE indicates no flag is set. */ 67 #define NGTCP2_PV_FLAG_NONE 0x00 68 /* NGTCP2_PV_FLAG_DONT_CARE indicates that the outcome of path 69 validation should be ignored entirely. */ 70 #define NGTCP2_PV_FLAG_DONT_CARE 0x01 71 /* NGTCP2_PV_FLAG_CANCEL_TIMER indicates that the expiry timer is 72 cancelled. */ 73 #define NGTCP2_PV_FLAG_CANCEL_TIMER 0x02 74 /* NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE indicates that fallback DCID is 75 available in ngtcp2_pv. If path validation fails, fallback to the 76 fallback DCID. If path validation succeeds, fallback DCID is 77 retired if it does not equal to the current DCID. */ 78 #define NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE 0x04 79 /* NGTCP2_PV_FLAG_MTU_PROBE indicates that a validation must probe 80 least MTU that QUIC requires, which is 1200 bytes. If it fails, a 81 path is not viable. */ 82 #define NGTCP2_PV_FLAG_MTU_PROBE 0x08 83 /* NGTCP2_PV_FLAG_PREFERRED_ADDR indicates that client is migrating to 84 server's preferred address. This flag is only used by client. */ 85 #define NGTCP2_PV_FLAG_PREFERRED_ADDR 0x10 86 87 typedef struct ngtcp2_pv ngtcp2_pv; 88 89 /* 90 * ngtcp2_pv is the context of a single path validation. 91 */ 92 struct ngtcp2_pv { 93 const ngtcp2_mem *mem; 94 ngtcp2_log *log; 95 /* dcid is DCID and path this path validation uses. */ 96 ngtcp2_dcid dcid; 97 /* fallback_dcid is the usually validated DCID and used as a 98 fallback if this path validation fails. */ 99 ngtcp2_dcid fallback_dcid; 100 /* ents is the ring buffer of ngtcp2_pv_entry */ 101 ngtcp2_ringbuf ents; 102 /* timeout is the duration within which this path validation should 103 succeed. */ 104 ngtcp2_duration timeout; 105 /* fallback_pto is PTO of fallback connection. */ 106 ngtcp2_duration fallback_pto; 107 /* started_ts is the timestamp this path validation starts. */ 108 ngtcp2_tstamp started_ts; 109 /* round is the number of times that probe_pkt_left is reset. */ 110 size_t round; 111 /* probe_pkt_left is the number of probe packets containing 112 PATH_CHALLENGE which can be send without waiting for an 113 expiration of a previous flight. */ 114 size_t probe_pkt_left; 115 /* flags is bitwise-OR of zero or more of NGTCP2_PV_FLAG_*. */ 116 uint8_t flags; 117 }; 118 119 /* 120 * ngtcp2_pv_new creates new ngtcp2_pv object and assigns its pointer 121 * to |*ppv|. This function makes a copy of |dcid|. |timeout| is a 122 * duration within which this path validation must succeed. 123 * 124 * This function returns 0 if it succeeds, or one of the following 125 * negative error codes: 126 * 127 * NGTCP2_ERR_NOMEM 128 * Out of memory 129 */ 130 int ngtcp2_pv_new(ngtcp2_pv **ppv, const ngtcp2_dcid *dcid, 131 ngtcp2_duration timeout, uint8_t flags, ngtcp2_log *log, 132 const ngtcp2_mem *mem); 133 134 /* 135 * ngtcp2_pv_del deallocates |pv|. This function frees memory |pv| 136 * points too. 137 */ 138 void ngtcp2_pv_del(ngtcp2_pv *pv); 139 140 /* 141 * ngtcp2_pv_add_entry adds new entry with |data|. |expiry| is the 142 * expiry time of the entry. 143 */ 144 void ngtcp2_pv_add_entry(ngtcp2_pv *pv, const uint8_t *data, 145 ngtcp2_tstamp expiry, uint8_t flags, ngtcp2_tstamp ts); 146 147 /* 148 * ngtcp2_pv_full returns nonzero if |pv| is full of ngtcp2_pv_entry. 149 */ 150 int ngtcp2_pv_full(ngtcp2_pv *pv); 151 152 /* 153 * ngtcp2_pv_validate validates that the received |data| matches the 154 * one of the existing entry. The flag of ngtcp2_pv_entry that 155 * matches |data| is assigned to |*pflags| if this function succeeds. 156 * 157 * This function returns 0 if it succeeds, or one of the following 158 * negative error codes: 159 * 160 * NGTCP2_ERR_PATH_VALIDATION_FAILED 161 * path validation has failed and must be abandoned 162 * NGTCP2_ERR_INVALID_STATE 163 * |pv| includes no entry 164 * NGTCP2_ERR_INVALID_ARGUMENT 165 * |pv| does not have an entry which has |data| and |path| 166 */ 167 int ngtcp2_pv_validate(ngtcp2_pv *pv, uint8_t *pflags, const uint8_t *data); 168 169 /* 170 * ngtcp2_pv_handle_entry_expiry checks expiry of existing entries. 171 */ 172 void ngtcp2_pv_handle_entry_expiry(ngtcp2_pv *pv, ngtcp2_tstamp ts); 173 174 /* 175 * ngtcp2_pv_should_send_probe returns nonzero if new entry can be 176 * added by ngtcp2_pv_add_entry. 177 */ 178 int ngtcp2_pv_should_send_probe(ngtcp2_pv *pv); 179 180 /* 181 * ngtcp2_pv_validation_timed_out returns nonzero if the path 182 * validation fails because of timeout. 183 */ 184 int ngtcp2_pv_validation_timed_out(ngtcp2_pv *pv, ngtcp2_tstamp ts); 185 186 /* 187 * ngtcp2_pv_next_expiry returns the earliest expiry. 188 */ 189 ngtcp2_tstamp ngtcp2_pv_next_expiry(ngtcp2_pv *pv); 190 191 /* 192 * ngtcp2_pv_cancel_expired_timer cancels the expired timer. 193 */ 194 void ngtcp2_pv_cancel_expired_timer(ngtcp2_pv *pv, ngtcp2_tstamp ts); 195 196 #endif /* NGTCP2_PV_H */ 197