lsquic_packet_common.c revision 50aadb33
1/* Copyright (c) 2017 LiteSpeed Technologies Inc.  See LICENSE. */
2/*
3 * lsquic_packet_common.c -- some common packet-related routines
4 */
5
6#include <stdio.h>
7#include <stdlib.h>
8
9#include "lsquic_logger.h"
10#include "lsquic_packet_common.h"
11
12
13static const char * const frame_type_2_str[N_QUIC_FRAMES] = {
14    [QUIC_FRAME_INVALID]           =  "QUIC_FRAME_INVALID",
15    [QUIC_FRAME_STREAM]            =  "QUIC_FRAME_STREAM",
16    [QUIC_FRAME_ACK]               =  "QUIC_FRAME_ACK",
17    [QUIC_FRAME_PADDING]           =  "QUIC_FRAME_PADDING",
18    [QUIC_FRAME_RST_STREAM]        =  "QUIC_FRAME_RST_STREAM",
19    [QUIC_FRAME_CONNECTION_CLOSE]  =  "QUIC_FRAME_CONNECTION_CLOSE",
20    [QUIC_FRAME_GOAWAY]            =  "QUIC_FRAME_GOAWAY",
21    [QUIC_FRAME_WINDOW_UPDATE]     =  "QUIC_FRAME_WINDOW_UPDATE",
22    [QUIC_FRAME_BLOCKED]           =  "QUIC_FRAME_BLOCKED",
23    [QUIC_FRAME_STOP_WAITING]      =  "QUIC_FRAME_STOP_WAITING",
24    [QUIC_FRAME_PING]              =  "QUIC_FRAME_PING",
25};
26
27
28#define SLEN(x) (sizeof(#x) - sizeof("QUIC_FRAME_"))
29
30
31const size_t lsquic_frame_types_str_sz =
32    /* We don't need to include INVALID frame in this list because it is
33     * never a part of any frame list bitmask (e.g. po_frame_types).
34     */
35    SLEN(QUIC_FRAME_STREAM)           + 1 +
36    SLEN(QUIC_FRAME_ACK)              + 1 +
37    SLEN(QUIC_FRAME_PADDING)          + 1 +
38    SLEN(QUIC_FRAME_RST_STREAM)       + 1 +
39    SLEN(QUIC_FRAME_CONNECTION_CLOSE) + 1 +
40    SLEN(QUIC_FRAME_GOAWAY)           + 1 +
41    SLEN(QUIC_FRAME_WINDOW_UPDATE)    + 1 +
42    SLEN(QUIC_FRAME_BLOCKED)          + 1 +
43    SLEN(QUIC_FRAME_STOP_WAITING)     + 1 +
44    SLEN(QUIC_FRAME_PING)             + 1;
45
46
47const char *
48lsquic_frame_types_to_str (char *buf, size_t bufsz, short frame_types)
49{
50    char *p;
51    int i, w;
52    size_t sz;
53
54    if (bufsz > 0)
55        buf[0] = '\0';
56
57    p = buf;
58    for (i = 0; i < N_QUIC_FRAMES; ++i)
59    {
60        if (frame_types & (1 << i))
61        {
62            sz = bufsz - (p - buf);
63            w = snprintf(p, sz, "%.*s%s", p > buf, " ",
64                            frame_type_2_str[i] + sizeof("QUIC_FRAME_") - 1);
65            if (w > (int) sz)
66            {
67                LSQ_WARN("not enough room for all frame types");
68                break;
69            }
70            p += w;
71        }
72        frame_types &= ~(1 << i);
73    }
74
75    return buf;
76}
77
78
79enum lsquic_packno_bits
80calc_packno_bits (lsquic_packno_t packno, lsquic_packno_t least_unacked,
81                  uint64_t n_in_flight)
82{
83    uint64_t delta;
84    unsigned bits;
85
86    delta = packno - least_unacked;
87    if (n_in_flight > delta)
88        delta = n_in_flight;
89
90    delta *= 4;
91    bits = (delta > (1ULL <<  8))
92         + (delta > (1ULL << 16))
93         + (delta > (1ULL << 32));
94
95    return bits;
96}
97
98
99lsquic_packno_t
100restore_packno (lsquic_packno_t cur_packno,
101                enum lsquic_packno_bits cur_packno_bits,
102                lsquic_packno_t max_packno)
103{
104    lsquic_packno_t candidates[3], epoch_delta;
105    int64_t diffs[3];
106    unsigned min, len;
107
108    len = packno_bits2len(cur_packno_bits);
109    epoch_delta = 1ULL << (len << 3);
110    candidates[1] = (max_packno & ~(epoch_delta - 1)) + cur_packno;
111    candidates[0] = candidates[1] - epoch_delta;
112    candidates[2] = candidates[1] + epoch_delta;
113
114    diffs[0] = llabs((int64_t) candidates[0] - (int64_t) max_packno);
115    diffs[1] = llabs((int64_t) candidates[1] - (int64_t) max_packno);
116    diffs[2] = llabs((int64_t) candidates[2] - (int64_t) max_packno);
117
118    min = diffs[1] < diffs[0];
119    if (diffs[2] < diffs[min])
120        min = 2;
121
122    return candidates[min];
123}
124