1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
|
/*
* ngtcp2
*
* Copyright (c) 2017 ngtcp2 contributors
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef NGTCP2_ACKTR_H
#define NGTCP2_ACKTR_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <ngtcp2/ngtcp2.h>
#include "ngtcp2_mem.h"
#include "ngtcp2_ringbuf.h"
#include "ngtcp2_ksl.h"
#include "ngtcp2_pkt.h"
#include "ngtcp2_objalloc.h"
/* NGTCP2_ACKTR_MAX_ENT is the maximum number of ngtcp2_acktr_entry
which ngtcp2_acktr stores. */
#define NGTCP2_ACKTR_MAX_ENT 1024
typedef struct ngtcp2_log ngtcp2_log;
/*
* ngtcp2_acktr_entry is a range of packets which need to be acked.
*/
typedef struct ngtcp2_acktr_entry {
union {
struct {
/* pkt_num is the largest packet number to acknowledge in this
range. */
int64_t pkt_num;
/* len is the consecutive packets started from pkt_num which
includes pkt_num itself counting in decreasing order. So pkt_num
= 987 and len = 2, this entry includes packet 987 and 986. */
size_t len;
/* tstamp is the timestamp when a packet denoted by pkt_num is
received. */
ngtcp2_tstamp tstamp;
};
ngtcp2_opl_entry oplent;
};
} ngtcp2_acktr_entry;
ngtcp2_objalloc_def(acktr_entry, ngtcp2_acktr_entry, oplent);
/*
* ngtcp2_acktr_entry_objalloc_new allocates memory for ent, and
* initializes it with the given parameters. The pointer to the
* allocated object is stored to |*ent|.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGTCP2_ERR_NOMEM
* Out of memory.
*/
int ngtcp2_acktr_entry_objalloc_new(ngtcp2_acktr_entry **ent, int64_t pkt_num,
ngtcp2_tstamp tstamp,
ngtcp2_objalloc *objalloc);
/*
* ngtcp2_acktr_entry_objalloc_del deallocates memory allocated for
* |ent|.
*/
void ngtcp2_acktr_entry_objalloc_del(ngtcp2_acktr_entry *ent,
ngtcp2_objalloc *objalloc);
typedef struct ngtcp2_acktr_ack_entry {
/* largest_ack is the largest packet number in outgoing ACK frame */
int64_t largest_ack;
/* pkt_num is the packet number that ACK frame is included. */
int64_t pkt_num;
} ngtcp2_acktr_ack_entry;
/* NGTCP2_ACKTR_FLAG_NONE indicates that no flag set. */
#define NGTCP2_ACKTR_FLAG_NONE 0x00u
/* NGTCP2_ACKTR_FLAG_IMMEDIATE_ACK indicates that immediate
acknowledgement is required. */
#define NGTCP2_ACKTR_FLAG_IMMEDIATE_ACK 0x01u
/* NGTCP2_ACKTR_FLAG_ACTIVE_ACK indicates that there are pending
protected packet to be acknowledged. */
#define NGTCP2_ACKTR_FLAG_ACTIVE_ACK 0x02u
/* NGTCP2_ACKTR_FLAG_CANCEL_TIMER is set when ACK delay timer is
expired and canceled. */
#define NGTCP2_ACKTR_FLAG_CANCEL_TIMER 0x0100u
/*
* ngtcp2_acktr tracks received packets which we have to send ack.
*/
typedef struct ngtcp2_acktr {
ngtcp2_objalloc objalloc;
ngtcp2_ringbuf acks;
/* ents includes ngtcp2_acktr_entry sorted by decreasing order of
packet number. */
ngtcp2_ksl ents;
ngtcp2_log *log;
const ngtcp2_mem *mem;
/* flags is bitwise OR of zero, or more of NGTCP2_ACKTR_FLAG_*. */
uint16_t flags;
/* first_unacked_ts is timestamp when ngtcp2_acktr_entry is added
first time after the last outgoing ACK frame. */
ngtcp2_tstamp first_unacked_ts;
/* rx_npkt is the number of ACK eliciting packets received without
sending ACK. */
size_t rx_npkt;
} ngtcp2_acktr;
/*
* ngtcp2_acktr_init initializes |acktr|.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGTCP2_ERR_NOMEM
* Out of memory.
*/
int ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log,
const ngtcp2_mem *mem);
/*
* ngtcp2_acktr_free frees resources allocated for |acktr|. It frees
* any ngtcp2_acktr_entry added to |acktr|.
*/
void ngtcp2_acktr_free(ngtcp2_acktr *acktr);
/*
* ngtcp2_acktr_add adds packet number |pkt_num| to |acktr|.
* |active_ack| is nonzero if |pkt_num| is retransmittable packet.
*
* This function assumes that |acktr| does not contain |pkt_num|.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGTCP2_ERR_NOMEM
* OUt of memory.
*/
int ngtcp2_acktr_add(ngtcp2_acktr *acktr, int64_t pkt_num, int active_ack,
ngtcp2_tstamp ts);
/*
* ngtcp2_acktr_forget removes all entries which have the packet
* number that is equal to or less than ent->pkt_num. This function
* assumes that |acktr| includes |ent|.
*/
void ngtcp2_acktr_forget(ngtcp2_acktr *acktr, ngtcp2_acktr_entry *ent);
/*
* ngtcp2_acktr_get returns the pointer to pointer to the entry which
* has the largest packet number to be acked. If there is no entry,
* returned value satisfies ngtcp2_ksl_it_end(&it) != 0.
*/
ngtcp2_ksl_it ngtcp2_acktr_get(ngtcp2_acktr *acktr);
/*
* ngtcp2_acktr_empty returns nonzero if it has no packet to
* acknowledge.
*/
int ngtcp2_acktr_empty(ngtcp2_acktr *acktr);
/*
* ngtcp2_acktr_add_ack records outgoing ACK frame whose largest
* acknowledged packet number is |largest_ack|. |pkt_num| is the
* packet number of a packet in which ACK frame is included. This
* function returns a pointer to the object it adds.
*/
ngtcp2_acktr_ack_entry *
ngtcp2_acktr_add_ack(ngtcp2_acktr *acktr, int64_t pkt_num, int64_t largest_ack);
/*
* ngtcp2_acktr_recv_ack processes the incoming ACK frame |fr|.
* |pkt_num| is a packet number which includes |fr|. If we receive
* ACK which acknowledges the ACKs added by ngtcp2_acktr_add_ack,
* ngtcp2_acktr_entry which the outgoing ACK acknowledges is removed.
*/
void ngtcp2_acktr_recv_ack(ngtcp2_acktr *acktr, const ngtcp2_ack *fr);
/*
* ngtcp2_acktr_commit_ack tells |acktr| that ACK frame is generated.
*/
void ngtcp2_acktr_commit_ack(ngtcp2_acktr *acktr);
/*
* ngtcp2_acktr_require_active_ack returns nonzero if ACK frame should
* be generated actively.
*/
int ngtcp2_acktr_require_active_ack(ngtcp2_acktr *acktr,
ngtcp2_duration max_ack_delay,
ngtcp2_tstamp ts);
/*
* ngtcp2_acktr_immediate_ack tells |acktr| that immediate
* acknowledgement is required.
*/
void ngtcp2_acktr_immediate_ack(ngtcp2_acktr *acktr);
#endif /* NGTCP2_ACKTR_H */
|