Coverage Report

Created: 2025-06-22 06:19

/src/h2o/deps/quicly/lib/sentmap.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2017 Fastly, Kazuho Oku
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a copy
5
 * of this software and associated documentation files (the "Software"), to
6
 * deal in the Software without restriction, including without limitation the
7
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8
 * sell copies of the Software, and to permit persons to whom the Software is
9
 * furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice shall be included in
12
 * all copies or substantial portions of the Software.
13
 *
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20
 * IN THE SOFTWARE.
21
 */
22
#include <assert.h>
23
#include <stdlib.h>
24
#include "picotls.h"
25
#include "quicly/sentmap.h"
26
27
const quicly_sent_t quicly_sentmap__end_iter = {quicly_sentmap__type_packet, {{UINT64_MAX, INT64_MAX}}};
28
29
static void next_entry(quicly_sentmap_iter_t *iter)
30
0
{
31
0
    if (--iter->count != 0) {
32
0
        ++iter->p;
33
0
    } else if (*(iter->ref = &(*iter->ref)->next) == NULL) {
34
0
        iter->p = (quicly_sent_t *)&quicly_sentmap__end_iter;
35
0
        iter->count = 0;
36
0
        return;
37
0
    } else {
38
0
        assert((*iter->ref)->num_entries != 0);
39
0
        iter->count = (*iter->ref)->num_entries;
40
0
        iter->p = (*iter->ref)->entries;
41
0
    }
42
0
    while (iter->p->acked == NULL)
43
0
        ++iter->p;
44
0
}
45
46
static struct st_quicly_sent_block_t **free_block(quicly_sentmap_t *map, struct st_quicly_sent_block_t **ref)
47
0
{
48
0
    static const struct st_quicly_sent_block_t dummy = {NULL};
49
0
    static const struct st_quicly_sent_block_t *const dummy_ref = &dummy;
50
0
    struct st_quicly_sent_block_t *block = *ref;
51
52
0
    if (block->next != NULL) {
53
0
        *ref = block->next;
54
0
        assert((*ref)->num_entries != 0);
55
0
    } else {
56
0
        assert(block == map->tail);
57
0
        if (ref == &map->head) {
58
0
            map->head = NULL;
59
0
            map->tail = NULL;
60
0
        } else {
61
0
            map->tail = (void *)((char *)ref - offsetof(struct st_quicly_sent_block_t, next));
62
0
            map->tail->next = NULL;
63
0
        }
64
0
        ref = (struct st_quicly_sent_block_t **)&dummy_ref;
65
0
    }
66
67
0
    free(block);
68
0
    return ref;
69
0
}
70
71
static void discard_entry(quicly_sentmap_t *map, quicly_sentmap_iter_t *iter)
72
0
{
73
0
    assert(iter->p->acked != NULL);
74
0
    iter->p->acked = NULL;
75
76
0
    struct st_quicly_sent_block_t *block = *iter->ref;
77
0
    if (--block->num_entries == 0) {
78
0
        iter->ref = free_block(map, iter->ref);
79
0
        block = *iter->ref;
80
0
        iter->p = block->entries - 1;
81
0
        iter->count = block->num_entries + 1;
82
0
    }
83
0
}
84
85
void quicly_sentmap_dispose(quicly_sentmap_t *map)
86
0
{
87
0
    struct st_quicly_sent_block_t *block;
88
89
0
    while ((block = map->head) != NULL) {
90
0
        map->head = block->next;
91
0
        free(block);
92
0
    }
93
0
}
94
95
quicly_error_t quicly_sentmap_prepare(quicly_sentmap_t *map, uint64_t packet_number, int64_t now, uint8_t ack_epoch)
96
0
{
97
0
    assert(map->_pending_packet == NULL);
98
99
0
    if ((map->_pending_packet = quicly_sentmap_allocate(map, quicly_sentmap__type_packet)) == NULL)
100
0
        return PTLS_ERROR_NO_MEMORY;
101
0
    map->_pending_packet->data.packet = (quicly_sent_packet_t){packet_number, now, ack_epoch};
102
0
    return 0;
103
0
}
104
105
struct st_quicly_sent_block_t *quicly_sentmap__new_block(quicly_sentmap_t *map)
106
0
{
107
0
    struct st_quicly_sent_block_t *block;
108
109
0
    if ((block = malloc(sizeof(*block))) == NULL)
110
0
        return NULL;
111
112
0
    block->next = NULL;
113
0
    block->num_entries = 0;
114
0
    block->next_insert_at = 0;
115
0
    if (map->tail != NULL) {
116
0
        map->tail->next = block;
117
0
        map->tail = block;
118
0
    } else {
119
0
        map->head = map->tail = block;
120
0
    }
121
122
0
    return block;
123
0
}
124
125
void quicly_sentmap_skip(quicly_sentmap_iter_t *iter)
126
0
{
127
0
    do {
128
0
        next_entry(iter);
129
0
    } while (iter->p->acked != quicly_sentmap__type_packet);
130
0
}
131
132
quicly_error_t quicly_sentmap_update(quicly_sentmap_t *map, quicly_sentmap_iter_t *iter, quicly_sentmap_event_t event)
133
0
{
134
0
    quicly_sent_packet_t packet;
135
0
    quicly_error_t ret = 0;
136
137
0
    assert(iter->p != &quicly_sentmap__end_iter);
138
0
    assert(iter->p->acked == quicly_sentmap__type_packet);
139
140
    /* copy packet info */
141
0
    packet = iter->p->data.packet;
142
143
    /* update CC state unless the event is PTO */
144
0
    if (packet.cc_bytes_in_flight != 0 && event != QUICLY_SENTMAP_EVENT_PTO) {
145
0
        assert(map->bytes_in_flight >= packet.cc_bytes_in_flight);
146
0
        map->bytes_in_flight -= packet.cc_bytes_in_flight;
147
0
        iter->p->data.packet.cc_bytes_in_flight = 0;
148
0
    }
149
0
    iter->p->data.packet.frames_in_flight = 0;
150
151
0
    int should_notify = event == QUICLY_SENTMAP_EVENT_ACKED || packet.frames_in_flight,
152
0
        should_discard = event == QUICLY_SENTMAP_EVENT_ACKED || event == QUICLY_SENTMAP_EVENT_EXPIRED;
153
154
    /* Advance to next packet, while if necessary, doing either or both of the following:
155
     * * discard entries (if should_discard is set)
156
     * * invoke the frame-level callbacks (if should_notify is set) */
157
0
    if (should_discard) {
158
0
        discard_entry(map, iter);
159
0
        --map->num_packets;
160
0
    }
161
0
    for (next_entry(iter); iter->p->acked != quicly_sentmap__type_packet; next_entry(iter)) {
162
0
        if (should_notify && (ret = iter->p->acked(map, &packet, event == QUICLY_SENTMAP_EVENT_ACKED, iter->p)) != 0)
163
0
            goto Exit;
164
0
        if (should_discard)
165
0
            discard_entry(map, iter);
166
0
    }
167
168
0
Exit:
169
0
    return ret;
170
0
}
171
172
quicly_error_t quicly_sentmap__type_packet(quicly_sentmap_t *map, const quicly_sent_packet_t *packet, int acked,
173
                                           quicly_sent_t *sent)
174
0
{
175
0
    assert(!"quicly_sentmap__type_packet cannot be called");
176
0
    return QUICLY_TRANSPORT_ERROR_INTERNAL;
177
0
}