lsquic_rechist.c revision c51ce338
1/* Copyright (c) 2017 LiteSpeed Technologies Inc. See LICENSE. */ 2/* 3 * lsquic_rechist.c -- History of received packets. 4 */ 5 6#include <assert.h> 7#include <errno.h> 8#include <inttypes.h> 9#include <stdlib.h> 10#include <string.h> 11 12#include "lsquic_int_types.h" 13#include "lsquic_types.h" 14#include "lsquic_rechist.h" 15 16#define LSQUIC_LOGGER_MODULE LSQLM_RECHIST 17#define LSQUIC_LOG_CONN_ID rechist->rh_cid 18#include "lsquic_logger.h" 19 20 21void 22lsquic_rechist_init (struct lsquic_rechist *rechist, lsquic_cid_t cid) 23{ 24 memset(rechist, 0, sizeof(*rechist)); 25 rechist->rh_cid = cid; 26 rechist->rh_cutoff = 1; 27 lsquic_packints_init(&rechist->rh_pints); 28 LSQ_DEBUG("instantiated received packet history"); 29} 30 31 32void 33lsquic_rechist_cleanup (lsquic_rechist_t *rechist) 34{ 35 lsquic_packints_cleanup(&rechist->rh_pints); 36 memset(rechist, 0, sizeof(*rechist)); 37} 38 39 40enum received_st 41lsquic_rechist_received (lsquic_rechist_t *rechist, lsquic_packno_t packno, 42 lsquic_time_t now) 43{ 44 const struct lsquic_packno_range *first_range; 45 46 LSQ_DEBUG("received %"PRIu64, packno); 47 if (packno < rechist->rh_cutoff) 48 { 49 if (packno) 50 return REC_ST_DUP; 51 else 52 return REC_ST_ERR; 53 } 54 55 first_range = lsquic_packints_first(&rechist->rh_pints); 56 if (!first_range || packno > first_range->high) 57 rechist->rh_largest_acked_received = now; 58 59 switch (lsquic_packints_add(&rechist->rh_pints, packno)) 60 { 61 case PACKINTS_OK: 62 ++rechist->rh_n_packets; 63 return REC_ST_OK; 64 case PACKINTS_DUP: 65 return REC_ST_DUP; 66 default: 67 assert(0); 68 case PACKINTS_ERR: 69 return REC_ST_ERR; 70 } 71} 72 73 74void 75lsquic_rechist_stop_wait (lsquic_rechist_t *rechist, lsquic_packno_t cutoff) 76{ 77 LSQ_INFO("stop wait: %"PRIu64, cutoff); 78 79 if (rechist->rh_flags & RH_CUTOFF_SET) 80 { 81 assert(cutoff >= rechist->rh_cutoff); /* Check performed in full_conn */ 82 if (cutoff == rechist->rh_cutoff) 83 return; 84 } 85 86 rechist->rh_cutoff = cutoff; 87 rechist->rh_flags |= RH_CUTOFF_SET; 88 struct packet_interval *pi, *next; 89 for (pi = TAILQ_FIRST(&rechist->rh_pints.pk_intervals); pi; pi = next) 90 { 91 next = TAILQ_NEXT(pi, next_pi); 92 if (pi->range.low < cutoff) 93 { 94 if (pi->range.high < cutoff) 95 { 96 rechist->rh_n_packets -= pi->range.high - pi->range.low + 1; 97 TAILQ_REMOVE(&rechist->rh_pints.pk_intervals, pi, next_pi); 98 free(pi); 99 } 100 else 101 { 102 rechist->rh_n_packets -= cutoff - pi->range.low; 103 pi->range.low = cutoff; 104 } 105 } 106 } 107 lsquic_packints_sanity_check(&rechist->rh_pints); 108} 109 110 111lsquic_packno_t 112lsquic_rechist_largest_packno (const lsquic_rechist_t *rechist) 113{ 114 const struct packet_interval *pi = 115 TAILQ_FIRST(&rechist->rh_pints.pk_intervals); 116 if (pi) 117 return pi->range.high; 118 else 119 return 0; /* Don't call this function if history is empty */ 120} 121 122 123lsquic_packno_t 124lsquic_rechist_cutoff (const lsquic_rechist_t *rechist) 125{ 126 if (rechist->rh_flags & RH_CUTOFF_SET) 127 return rechist->rh_cutoff; 128 else 129 return 0; 130} 131 132 133lsquic_time_t 134lsquic_rechist_largest_recv (const lsquic_rechist_t *rechist) 135{ 136 return rechist->rh_largest_acked_received; 137} 138 139 140const struct lsquic_packno_range * 141lsquic_rechist_first (lsquic_rechist_t *rechist) 142{ 143 return lsquic_packints_first(&rechist->rh_pints); 144} 145 146 147const struct lsquic_packno_range * 148lsquic_rechist_next (lsquic_rechist_t *rechist) 149{ 150 return lsquic_packints_next(&rechist->rh_pints); 151} 152 153 154size_t 155lsquic_rechist_mem_used (const struct lsquic_rechist *rechist) 156{ 157 return sizeof(*rechist) 158 - sizeof(rechist->rh_pints) 159 + lsquic_packints_mem_used(&rechist->rh_pints); 160} 161