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