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