lsquic_mini_conn.c revision b8fa6195
1/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc.  See LICENSE. */
2/*
3 * lsquic_mini_conn.c -- Mini connection.
4 *
5 * Mini connection is only used in server mode -- this assumption is relied
6 * upon by the code in this file.
7 *
8 * The purpose of this connection is to process incoming handshakes using
9 * minimal amount of resources until we confirm that the client is sending
10 * valid data.  Here, we only process Stream 1 data; other packets are
11 * spooled, if necessary.  When mini connection is promoted to full
12 * connection, the state, including spooled incoming packets, is transferred
13 * to the full connection.
14 *
15 * Note that mini connections do not retransmit lost packets.  This is to
16 * minimize the effect of magnification attacks.  Clients like Chrome and
17 * Opera fall back to using TCP if QUIC handshake times out.
18 */
19
20
21#include <assert.h>
22#include <errno.h>
23#include <inttypes.h>
24#include <stdlib.h>
25#include <string.h>
26#include <sys/queue.h>
27#include <time.h>
28
29#include "lsquic.h"
30#include "lsquic_int_types.h"
31#include "lsquic_hash.h"
32#include "lsquic_conn.h"
33#include "lsquic_rtt.h"
34#include "lsquic_mini_conn.h"
35#include "lsquic_mm.h"
36#include "lsquic_malo.h"
37#include "lsquic_packet_common.h"
38#include "lsquic_packet_gquic.h"
39#include "lsquic_packet_ietf.h"
40#include "lsquic_packet_in.h"
41#include "lsquic_packet_out.h"
42#include "lsquic_util.h"
43#include "lsquic_str.h"
44#include "lsquic_enc_sess.h"
45#include "lsquic_parse.h"
46#include "lsquic_engine_public.h"
47#include "lsquic_sfcw.h"
48#include "lsquic_varint.h"
49#include "lsquic_hq.h"
50#include "lsquic_stream.h"
51#include "lsquic_rechist.h"
52#include "lsquic_ev_log.h"
53#include "lsquic_qtags.h"
54#include "lsquic_attq.h"
55#include "lsquic_alarmset.h"
56
57#define LSQUIC_LOGGER_MODULE LSQLM_MINI_CONN
58#define LSQUIC_LOG_CONN_ID lsquic_conn_log_cid(&mc->mc_conn)
59#include "lsquic_logger.h"
60
61
62static const struct conn_iface mini_conn_iface_standard;
63static const struct conn_iface mini_conn_iface_standard_Q050;
64
65#if LSQUIC_KEEP_MINICONN_HISTORY
66
67static void
68mchist_append (struct mini_conn *mc, enum miniconn_history_event mh_event)
69{
70    enum miniconn_history_event prev_event;
71    mchist_idx_t idx;
72    int plus;
73
74    idx = (mc->mc_hist_idx - 1) & MCHIST_MASK;
75    plus = MCHE_PLUS == mc->mc_hist_buf[ idx ];
76    idx = (idx - plus) & MCHIST_MASK;
77    prev_event = mc->mc_hist_buf[ idx ];
78
79    if (!(prev_event == mh_event && plus))
80    {
81        if (prev_event == mh_event)
82            mh_event = MCHE_PLUS;
83        mc->mc_hist_buf[ MCHIST_MASK & mc->mc_hist_idx++ ] = mh_event;
84    }
85}
86
87
88#   define MCHIST_APPEND(mc, event) mchist_append(mc, event)
89#else
90#   define MCHIST_APPEND(mc, event)
91#endif
92
93static void
94process_deferred_packets (struct mini_conn *mc);
95
96
97/* If this is not true, highest_bit_set() may be broken */
98typedef char packno_set_is_unsigned_long[
99        sizeof(unsigned long long) == sizeof(mconn_packno_set_t) ? 1 : -1 ];
100
101static unsigned
102highest_bit_set (unsigned long long sz)
103{
104#if __GNUC__
105    unsigned clz = __builtin_clzll(sz);
106    return 63 - clz;
107#else
108    unsigned long y;
109    unsigned n;
110    n = 64;
111    y = sz >> 32;     if (y) { n -= 32; sz = y; }
112    y = sz >> 16;     if (y) { n -= 16; sz = y; }
113    y = sz >>  8;     if (y) { n -=  8; sz = y; }
114    y = sz >>  4;     if (y) { n -=  4; sz = y; }
115    y = sz >>  2;     if (y) { n -=  2; sz = y; }
116    y = sz >>  1;     if (y) return 63 - n + 2;
117    return 63 - n + sz;
118#endif
119}
120
121
122static unsigned
123lowest_bit_set (unsigned v)
124{
125#if __GNUC__
126    return __builtin_ctz(v);
127#else
128    unsigned n;
129    n = 0;
130    if (0 == (v & ((1 << 16) - 1))) { n += 16; v >>= 16; }
131    if (0 == (v & ((1 <<  8) - 1))) { n +=  8; v >>=  8; }
132    if (0 == (v & ((1 <<  4) - 1))) { n +=  4; v >>=  4; }
133    if (0 == (v & ((1 <<  2) - 1))) { n +=  2; v >>=  2; }
134    if (0 == (v & ((1 <<  1) - 1))) { n +=  1;           }
135    return n;
136#endif
137}
138
139
140static int
141is_handshake_stream_id (const struct mini_conn *conn,
142                                                lsquic_stream_id_t stream_id)
143{
144    return conn->mc_conn.cn_version < LSQVER_050 && stream_id == 1;
145}
146
147
148static void
149mini_destroy_packet (struct mini_conn *mc, struct lsquic_packet_out *packet_out)
150{
151    lsquic_packet_out_destroy(packet_out, mc->mc_enpub,
152                                                    mc->mc_path.np_peer_ctx);
153}
154
155
156static int
157packet_in_is_ok (enum lsquic_version version,
158                                    const struct lsquic_packet_in *packet_in)
159{
160    size_t min_size;
161
162    if (packet_in->pi_data_sz > GQUIC_MAX_PACKET_SZ)
163    {
164        LSQ_LOG1(LSQ_LOG_DEBUG, "incoming packet too large: %hu bytes",
165                                                    packet_in->pi_data_sz);
166        return 0;
167    }
168
169    if ((1 << version) & LSQUIC_GQUIC_HEADER_VERSIONS)
170        /* This is a very lax number, it allows the server to send
171         * 64 * 200 = 12KB of output (REJ and SHLO).
172         */
173        min_size = 200;
174    else
175        /* Chrome enforces 1200-byte minimum initial packet limit */
176        min_size = IQUIC_MIN_INIT_PACKET_SZ;
177
178    if (packet_in->pi_data_sz < min_size)
179    {
180        LSQ_LOG1(LSQ_LOG_DEBUG, "incoming packet too small: %hu bytes",
181                                                    packet_in->pi_data_sz);
182        return 0;
183    }
184    return 1;
185}
186
187
188lsquic_conn_t *
189lsquic_mini_conn_new (struct lsquic_engine_public *enp,
190               const struct lsquic_packet_in *packet_in,
191               enum lsquic_version version)
192{
193    struct mini_conn *mc;
194    const struct conn_iface *conn_iface;
195
196    if (!packet_in_is_ok(version, packet_in))
197        return NULL;
198    switch (version)
199    {
200    case LSQVER_050:
201        conn_iface = &mini_conn_iface_standard_Q050;
202        break;
203    default:
204        conn_iface = &mini_conn_iface_standard;
205        break;
206    }
207
208    mc = lsquic_malo_get(enp->enp_mm.malo.mini_conn);
209    if (!mc)
210    {
211        LSQ_LOG1(LSQ_LOG_WARN, "cannot allocate mini connection: %s",
212                                                            strerror(errno));
213        return NULL;
214    }
215
216    memset(mc, 0, sizeof(*mc));
217    TAILQ_INIT(&mc->mc_deferred);
218    TAILQ_INIT(&mc->mc_packets_in);
219    TAILQ_INIT(&mc->mc_packets_out);
220    mc->mc_enpub = enp;
221    mc->mc_created = packet_in->pi_received;
222    mc->mc_path.np_pack_size = packet_in->pi_data_sz;
223    mc->mc_conn.cn_cces = mc->mc_cces;
224    mc->mc_conn.cn_cces_mask = 1;
225    mc->mc_conn.cn_n_cces = sizeof(mc->mc_cces) / sizeof(mc->mc_cces[0]);
226    mc->mc_conn.cn_version = version;
227    mc->mc_conn.cn_pf = select_pf_by_ver(version);
228    mc->mc_conn.cn_esf_c = select_esf_common_by_ver(version);
229    mc->mc_conn.cn_esf.g = select_esf_gquic_by_ver(version);
230    mc->mc_conn.cn_cid = packet_in->pi_conn_id;
231    mc->mc_conn.cn_flags = LSCONN_MINI | LSCONN_SERVER;
232    mc->mc_conn.cn_if = conn_iface;
233    LSQ_DEBUG("created mini connection object");
234    MCHIST_APPEND(mc, MCHE_CREATED);
235    return &mc->mc_conn;
236}
237
238
239static int
240in_acked_range (const struct ack_info *acki, lsquic_packno_t n)  /* This is a copy */
241{
242    int in_range = 0;
243    unsigned i;
244    for (i = 0; i < acki->n_ranges; ++i)
245        in_range += acki->ranges[i].high >= n
246                 && acki->ranges[i].low  <= n;
247    return in_range > 0;
248}
249
250
251static void
252take_rtt_sample (struct mini_conn *mc, const lsquic_packet_out_t *packet_out,
253                 lsquic_time_t now, lsquic_time_t lack_delta)
254{
255    assert(packet_out->po_sent);
256    lsquic_time_t measured_rtt = now - packet_out->po_sent;
257    if (lack_delta < measured_rtt)
258    {
259        lsquic_rtt_stats_update(&mc->mc_rtt_stats, measured_rtt, lack_delta);
260        LSQ_DEBUG("srtt: %"PRIu64" usec, var: %"PRIu64,
261                        lsquic_rtt_stats_get_srtt(&mc->mc_rtt_stats),
262                        lsquic_rtt_stats_get_rttvar(&mc->mc_rtt_stats));
263    }
264}
265
266
267static unsigned
268process_ack_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in,
269                                        const unsigned char *p, size_t len)
270{
271    int parsed_len;
272    int n_newly_acked;
273    unsigned n;
274    lsquic_packet_out_t *packet_out, *next;
275    struct ack_info *acki;
276    lsquic_packno_t packno;
277    lsquic_time_t warn_time;
278    char buf[200];
279
280    acki = mc->mc_enpub->enp_mm.acki;
281    parsed_len = mc->mc_conn.cn_pf->pf_parse_ack_frame(p, len, acki, 0);
282    if (parsed_len < 0)
283        return 0;
284    if (empty_ack_frame(acki))
285    {
286        LSQ_DEBUG("Ignore empty ACK frame");
287        return parsed_len;
288    }
289    if (packet_in->pi_packno <= mc->mc_max_ack_packno)
290    {
291        LSQ_DEBUG("Ignore old ack (max %u)", mc->mc_max_ack_packno);
292        return parsed_len;
293    }
294
295    /* Verify ACK frame and update list of acked packet numbers: */
296    for (n = 0; n < acki->n_ranges; ++n)
297        for (packno = acki->ranges[n].low; packno <= acki->ranges[n].high;
298                                                                    ++packno)
299            if (packno > MINICONN_MAX_PACKETS ||
300                0 == (MCONN_PACKET_MASK(packno) & mc->mc_sent_packnos))
301                {
302                    warn_time = lsquic_time_now();
303                    if (0 == mc->mc_enpub->enp_last_warning[WT_ACKPARSE_MINI]
304                        || mc->mc_enpub->enp_last_warning[WT_ACKPARSE_MINI]
305                                + WARNING_INTERVAL < warn_time)
306                    {
307                        mc->mc_enpub->enp_last_warning[WT_ACKPARSE_MINI]
308                                                                = warn_time;
309                        lsquic_hexdump(p, len, buf, sizeof(buf));
310                        LSQ_WARN("packet %"PRIu64" was never sent; ACK "
311                            "frame:\n%s", packno, buf);
312                    }
313                    else
314                        LSQ_DEBUG("packet %"PRIu64" was never sent", packno);
315                    MCHIST_APPEND(mc, MCHE_UNSENT_ACKED);
316                    return 0;
317                }
318            else
319                mc->mc_acked_packnos |= MCONN_PACKET_MASK(packno);
320
321    EV_LOG_ACK_FRAME_IN(LSQUIC_LOG_CONN_ID, acki);
322    n_newly_acked = 0;
323    for (packet_out = TAILQ_FIRST(&mc->mc_packets_out); packet_out;
324                                                            packet_out = next)
325    {
326        next = TAILQ_NEXT(packet_out, po_next);
327        if (in_acked_range(acki, packet_out->po_packno))
328        {
329            ++n_newly_acked;
330            LSQ_DEBUG("Got ACK for packet %"PRIu64, packet_out->po_packno);
331            if (packet_out->po_packno == largest_acked(acki))
332                take_rtt_sample(mc, packet_out, packet_in->pi_received,
333                                                            acki->lack_delta);
334            TAILQ_REMOVE(&mc->mc_packets_out, packet_out, po_next);
335            mini_destroy_packet(mc, packet_out);
336        }
337    }
338
339    if (n_newly_acked > 0)
340        mc->mc_hsk_count = 0;
341
342    return parsed_len;
343}
344
345
346static unsigned
347process_blocked_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in,
348                                            const unsigned char *p, size_t len)
349{
350    lsquic_stream_id_t stream_id;
351    int parsed_len;
352    parsed_len = mc->mc_conn.cn_pf->pf_parse_blocked_frame(p, len, &stream_id);
353    if (parsed_len < 0)
354        return 0;
355    EV_LOG_BLOCKED_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_id);
356    LSQ_DEBUG("Peer reports stream %"PRIu64" as blocked", stream_id);
357    return parsed_len;
358}
359
360
361static mconn_packno_set_t
362drop_packets_out (struct mini_conn *mc)
363{
364    struct lsquic_packet_out *packet_out;
365    mconn_packno_set_t in_flight = 0;
366
367    while ((packet_out = TAILQ_FIRST(&mc->mc_packets_out)))
368    {
369        TAILQ_REMOVE(&mc->mc_packets_out, packet_out, po_next);
370        if (packet_out->po_flags & PO_SENT)
371            in_flight |= MCONN_PACKET_MASK(packet_out->po_packno);
372        mini_destroy_packet(mc, packet_out);
373    }
374
375    return in_flight;
376}
377
378
379static unsigned
380process_connection_close_frame (struct mini_conn *mc,
381        lsquic_packet_in_t *packet_in, const unsigned char *p, size_t len)
382{
383    uint64_t error_code;
384    uint16_t reason_len;
385    uint8_t reason_off;
386    int parsed_len;
387
388    (void) drop_packets_out(mc);
389    parsed_len = mc->mc_conn.cn_pf->pf_parse_connect_close_frame(p, len,
390                            NULL, &error_code, &reason_len, &reason_off);
391    if (parsed_len < 0)
392        return 0;
393    mc->mc_error_code = (uint64_t) error_code;
394    EV_LOG_CONNECTION_CLOSE_FRAME_IN(LSQUIC_LOG_CONN_ID, error_code,
395                            (int) reason_len, (const char *) p + reason_off);
396    if (error_code != 25        /* No recent network activity */
397        && error_code != 62     /* An active session exists for the given IP */
398        && error_code != 27 )   /* Write failed with error: -142 (Unknown error)*/
399    {
400        LSQ_WARN("Received CONNECTION_CLOSE frame (code: %"PRIu64"; reason: %.*s)",
401                 error_code, (int) reason_len, (const char *) p + reason_off);
402    }
403    MCHIST_APPEND(mc, MCHE_CONN_CLOSE);
404    return 0;   /* This shuts down the connection */
405}
406
407
408static unsigned
409process_goaway_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in,
410                                        const unsigned char *p, size_t len)
411{
412    lsquic_stream_id_t stream_id;
413    uint32_t error_code;
414    uint16_t reason_length;
415    const char *reason;
416    int parsed_len;
417    parsed_len = mc->mc_conn.cn_pf->pf_parse_goaway_frame(p, len, &error_code, &stream_id,
418                                              &reason_length, &reason);
419    if (parsed_len < 0)
420        return 0;
421    EV_LOG_GOAWAY_FRAME_IN(LSQUIC_LOG_CONN_ID, error_code, stream_id,
422        reason_length, reason);
423    LSQ_DEBUG("received GOAWAY frame, last good stream ID: %"PRIu64", "
424        "error code: 0x%X, reason: `%.*s'", stream_id, error_code,
425        reason_length, reason);
426    if (stream_id != 0) /* This is odd.  We warn: */
427        LSQ_WARN("stream ID is %"PRIu64" in GOAWAY frame", stream_id);
428    mc->mc_conn.cn_flags |= LSCONN_PEER_GOING_AWAY;
429    return parsed_len;
430}
431
432
433static unsigned
434process_invalid_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in,
435                                        const unsigned char *p, size_t len)
436{
437    LSQ_INFO("invalid frame");
438    MCHIST_APPEND(mc, MCHE_INVALID_FRAME);
439    return 0;
440}
441
442
443static unsigned
444count_zero_bytes (const unsigned char *p, size_t len)
445{
446    const unsigned char *const end = p + len;
447    while (p < end && 0 == *p)
448        ++p;
449    return len - (end - p);
450}
451
452
453static unsigned
454process_padding_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in,
455                                        const unsigned char *p, size_t len)
456{
457    len = (size_t) count_zero_bytes(p, len);
458    EV_LOG_PADDING_FRAME_IN(LSQUIC_LOG_CONN_ID, len);
459    return len;
460}
461
462
463static unsigned
464process_ping_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in,
465                                        const unsigned char *p, size_t len)
466{
467    EV_LOG_PING_FRAME_IN(LSQUIC_LOG_CONN_ID);
468    return 1;
469}
470
471
472static unsigned
473process_rst_stream_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in,
474                                            const unsigned char *p, size_t len)
475{
476    lsquic_stream_id_t stream_id;
477    uint64_t offset, error_code;
478    int parsed_len;
479    parsed_len = mc->mc_conn.cn_pf->pf_parse_rst_frame(p, len, &stream_id, &offset, &error_code);
480    if (parsed_len < 0)
481        return 0;
482    EV_LOG_RST_STREAM_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_id, offset,
483                                                                error_code);
484    LSQ_DEBUG("Got RST_STREAM; stream: %"PRIu64"; offset: 0x%"PRIX64, stream_id,
485                                                                    offset);
486    if (is_handshake_stream_id(mc, stream_id))
487    {
488        LSQ_INFO("handshake stream reset, closing connection");
489        return 0;
490    }
491    else
492        return parsed_len;
493}
494
495
496static unsigned
497process_stop_waiting_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in,
498                                             const unsigned char *p, size_t len)
499{
500    lsquic_packno_t least;
501    enum packno_bits bits = lsquic_packet_in_packno_bits(packet_in);
502    int parsed_len;
503    parsed_len = mc->mc_conn.cn_pf->pf_parse_stop_waiting_frame(p, len, packet_in->pi_packno, bits,
504                                                                        &least);
505    if (parsed_len < 0)
506        return 0;
507    EV_LOG_STOP_WAITING_FRAME_IN(LSQUIC_LOG_CONN_ID, least);
508    LSQ_DEBUG("Got STOP_WAITING frame, least unacked: %"PRIu64, least);
509    if (least > MINICONN_MAX_PACKETS)
510        return 0;
511    else
512    {
513        mc->mc_cutoff = least;
514        return parsed_len;
515    }
516}
517
518
519static unsigned
520process_stream_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in,
521                                          const unsigned char *p, size_t len)
522{
523    stream_frame_t stream_frame;
524    int parsed_len;
525    parsed_len = mc->mc_conn.cn_pf->pf_parse_stream_frame(p, len, &stream_frame);
526    if (parsed_len < 0)
527        return 0;
528    EV_LOG_STREAM_FRAME_IN(LSQUIC_LOG_CONN_ID, &stream_frame);
529    LSQ_DEBUG("Got stream frame for stream #%"PRIu64, stream_frame.stream_id);
530    if (is_handshake_stream_id(mc, stream_frame.stream_id))
531    {
532        if (packet_in->pi_flags & PI_HSK_STREAM)
533        {   /* This is not supported for simplicity.  The spec recommends
534             * not putting more than one stream frame from the same stream
535             * into a single packet.  If this changes and clients actually
536             * do that, we can revisit this code.
537             */
538            LSQ_INFO("two handshake stream frames in single incoming packet");
539            MCHIST_APPEND(mc, MCHE_2HSK_1STREAM);
540            return 0;
541        }
542        if (stream_frame.data_frame.df_offset >= mc->mc_read_off)
543        {
544            packet_in->pi_flags |= PI_HSK_STREAM;
545            packet_in->pi_hsk_stream = p - packet_in->pi_data;
546            mc->mc_flags |= MC_HAVE_NEW_HSK;
547            MCHIST_APPEND(mc, MCHE_NEW_HSK);
548            if (0 == stream_frame.data_frame.df_offset)
549            {
550                /* First CHLO message: update maximum packet size */
551                mc->mc_path.np_pack_size = packet_in->pi_data_sz;
552                LSQ_DEBUG("update packet size to %hu",
553                                                    mc->mc_path.np_pack_size);
554            }
555        }
556        else
557        {
558            LSQ_DEBUG("drop duplicate frame");
559            MCHIST_APPEND(mc, MCHE_DUP_HSK);
560        }
561    }
562    return parsed_len;
563}
564
565
566static unsigned
567process_crypto_frame (struct mini_conn *mc, struct lsquic_packet_in *packet_in,
568                                          const unsigned char *p, size_t len)
569{
570    stream_frame_t stream_frame;
571    int parsed_len;
572    parsed_len = mc->mc_conn.cn_pf->pf_parse_crypto_frame(p, len,
573                                                                &stream_frame);
574    if (parsed_len < 0)
575        return 0;
576    EV_LOG_CRYPTO_FRAME_IN(LSQUIC_LOG_CONN_ID, &stream_frame,
577                                        lsquic_packet_in_enc_level(packet_in));
578    LSQ_DEBUG("Got CRYPTO frame at encryption level %s",
579                    lsquic_enclev2str[lsquic_packet_in_enc_level(packet_in)]);
580    if (packet_in->pi_flags & PI_HSK_STREAM)
581    {   /* This is not supported for simplicity: assume a single CRYPTO frame
582         * per packet.  If this changes, we can revisit this code.
583         */
584        LSQ_INFO("two CRYPTO frames in single incoming packet");
585        MCHIST_APPEND(mc, MCHE_2HSK_1STREAM);
586        return 0;
587    }
588    if (stream_frame.data_frame.df_offset >= mc->mc_read_off)
589    {
590        packet_in->pi_flags |= PI_HSK_STREAM;
591        packet_in->pi_hsk_stream = p - packet_in->pi_data;
592        mc->mc_flags |= MC_HAVE_NEW_HSK;
593        MCHIST_APPEND(mc, MCHE_NEW_HSK);
594        if (0 == stream_frame.data_frame.df_offset)
595        {
596            /* First CHLO message: update maximum packet size */
597            mc->mc_path.np_pack_size = packet_in->pi_data_sz
598                /* Q050 and later adjust pi_data_sz of Initial packets during
599                 * decryption, here we have to add the tag length back:
600                 */
601                                        + mc->mc_conn.cn_esf_c->esf_tag_len;
602            LSQ_DEBUG("update packet size to %hu", mc->mc_path.np_pack_size);
603        }
604    }
605    else
606    {
607        LSQ_DEBUG("drop duplicate frame");
608        MCHIST_APPEND(mc, MCHE_DUP_HSK);
609    }
610    return parsed_len;
611}
612
613
614static unsigned
615process_window_update_frame (struct mini_conn *mc,
616            lsquic_packet_in_t *packet_in, const unsigned char *p, size_t len)
617{
618    lsquic_stream_id_t stream_id;
619    uint64_t offset;
620    int parsed_len;
621    parsed_len = mc->mc_conn.cn_pf->pf_parse_window_update_frame(p, len, &stream_id, &offset);
622    if (parsed_len < 0)
623        return 0;
624    EV_LOG_WINDOW_UPDATE_FRAME_IN(LSQUIC_LOG_CONN_ID, stream_id, offset);
625    if (is_handshake_stream_id(mc, stream_id))
626        /* This should not happen: why would the client send us WINDOW_UPDATE
627         * on stream 1?
628         */
629        LSQ_WARN("client sent WINDOW_UPDATE for handshake stream, "
630                                                    "offset %"PRIu64, offset);
631    return parsed_len;
632}
633
634
635typedef unsigned (*process_frame_f)(
636    struct mini_conn *, lsquic_packet_in_t *, const unsigned char *p, size_t);
637
638
639static process_frame_f const process_frames[N_QUIC_FRAMES] =
640{
641    [QUIC_FRAME_ACK]                  =  process_ack_frame,
642    [QUIC_FRAME_BLOCKED]              =  process_blocked_frame,
643    [QUIC_FRAME_CONNECTION_CLOSE]     =  process_connection_close_frame,
644    [QUIC_FRAME_CRYPTO]               =  process_crypto_frame,
645    [QUIC_FRAME_GOAWAY]               =  process_goaway_frame,
646    [QUIC_FRAME_INVALID]              =  process_invalid_frame,
647    [QUIC_FRAME_PADDING]              =  process_padding_frame,
648    [QUIC_FRAME_PING]                 =  process_ping_frame,
649    [QUIC_FRAME_RST_STREAM]           =  process_rst_stream_frame,
650    [QUIC_FRAME_STOP_WAITING]         =  process_stop_waiting_frame,
651    [QUIC_FRAME_STREAM]               =  process_stream_frame,
652    [QUIC_FRAME_WINDOW_UPDATE]        =  process_window_update_frame,
653};
654
655
656static unsigned
657process_packet_frame (struct mini_conn *mc, lsquic_packet_in_t *packet_in,
658                      const unsigned char *p, size_t len)
659{
660    enum quic_frame_type type = mc->mc_conn.cn_pf->pf_parse_frame_type(p, len);
661    packet_in->pi_frame_types |= 1 << type;
662    return process_frames[type](mc, packet_in, p, len);
663}
664
665
666static void
667record_largest_recv (struct mini_conn *mc, lsquic_time_t t)
668{
669    if (t < mc->mc_created)
670    {
671        LSQ_WARN("largest received predates creation");
672        return;
673    }
674    t -= mc->mc_created;
675    mc->mc_largest_recv[0] = t;
676    mc->mc_largest_recv[1] = t >> 8;
677    mc->mc_largest_recv[2] = t >> 16;
678    LSQ_DEBUG("recorded largest received timestamp as %"PRIu64" usec since "
679                                                            "creation", t);
680}
681
682
683static enum dec_packin
684conn_decrypt_packet (struct mini_conn *conn, lsquic_packet_in_t *packet_in)
685{
686    return conn->mc_conn.cn_esf_c->esf_decrypt_packet(
687                        conn->mc_conn.cn_enc_session, conn->mc_enpub,
688                        &conn->mc_conn, packet_in);
689}
690
691
692/* PRP: Process Regular Packet */
693enum proc_rp { PRP_KEEP, PRP_DEFER, PRP_DROP, PRP_ERROR, };
694
695
696static enum proc_rp
697conn_decrypt_packet_or (struct mini_conn *mc,
698                                        struct lsquic_packet_in *packet_in)
699{
700    if (DECPI_OK == conn_decrypt_packet(mc, packet_in))
701    {
702        MCHIST_APPEND(mc, MCHE_DECRYPTED);
703        return PRP_KEEP;
704    }
705    else if (mc->mc_conn.cn_esf.g->esf_have_key_gt_one(
706                                            mc->mc_conn.cn_enc_session))
707    {
708        LSQ_INFO("could not decrypt packet: drop");
709        mc->mc_dropped_packnos |= MCONN_PACKET_MASK(packet_in->pi_packno);
710        MCHIST_APPEND(mc, MCHE_UNDECR_DROP);
711        return PRP_DROP;
712    }
713    else if ((packet_in->pi_flags & PI_OWN_DATA) ||
714            0 == lsquic_conn_copy_and_release_pi_data(&mc->mc_conn,
715                                                mc->mc_enpub, packet_in))
716    {
717        assert(packet_in->pi_flags & PI_OWN_DATA);
718        LSQ_INFO("could not decrypt packet: defer");
719        mc->mc_deferred_packnos |= MCONN_PACKET_MASK(packet_in->pi_packno);
720        MCHIST_APPEND(mc, MCHE_UNDECR_DEFER);
721        return PRP_DEFER;
722    }
723    else
724    {
725        MCHIST_APPEND(mc, MCHE_ENOMEM);
726        return PRP_ERROR;   /* Memory allocation must have failed */
727    }
728}
729
730
731static enum proc_rp
732process_regular_packet (struct mini_conn *mc, lsquic_packet_in_t *packet_in)
733{
734    const unsigned char *p, *pend;
735    enum proc_rp prp;
736    unsigned len;
737
738    /* Decrypt packet if necessary */
739    if (0 == (packet_in->pi_flags & PI_DECRYPTED))
740    {
741        prp = conn_decrypt_packet_or(mc, packet_in);
742        if (prp != PRP_KEEP)
743            return prp;
744    }
745
746    /* Update receive history before processing the packet: if there is an
747     * error, the connection is terminated and recording this packet number
748     * is helpful when it is printed along with other diagnostics in dtor.
749     */
750    if (0 == mc->mc_received_packnos ||
751            packet_in->pi_packno > highest_bit_set(mc->mc_received_packnos) + 1)
752        record_largest_recv(mc, packet_in->pi_received);
753    mc->mc_received_packnos |= MCONN_PACKET_MASK(packet_in->pi_packno);
754
755    /* Parse and process frames */
756    p = packet_in->pi_data + packet_in->pi_header_sz;
757    pend = packet_in->pi_data + packet_in->pi_data_sz;
758    while (p < pend)
759    {
760        len = process_packet_frame(mc, packet_in, p, pend - p);
761        if (len > 0)
762            p += len;
763        else
764        {
765            if (mc->mc_conn.cn_pf->pf_parse_frame_type(p, pend - p) !=
766                                                    QUIC_FRAME_CONNECTION_CLOSE)
767                LSQ_WARN("error parsing frame: packno %"PRIu64"; sz: %u; type: "
768                    "0x%X", packet_in->pi_packno, packet_in->pi_data_sz, p[0]);
769            MCHIST_APPEND(mc, MCHE_EFRAME);
770            return PRP_ERROR;
771        }
772    }
773
774    mc->mc_flags |= MC_GEN_ACK;
775
776    return PRP_KEEP;
777}
778
779
780struct hsk_chunk
781{
782    lsquic_packet_in_t  *hsk_packet_in;
783    const unsigned char *hsk_data;
784    unsigned             hsk_off;
785    unsigned             hsk_sz;
786};
787
788
789static int
790compare_hsk_chunks (const void *ap, const void *bp)
791{
792    const struct hsk_chunk *a = ap;
793    const struct hsk_chunk *b = bp;
794    return (a->hsk_off > b->hsk_off) - (b->hsk_off > a->hsk_off);
795}
796
797
798struct mini_stream_ctx
799{
800    const unsigned char     *buf;
801    size_t                   bufsz;
802    size_t                   off;
803};
804
805
806static int
807mini_stream_has_data (const struct mini_stream_ctx *ms_ctx)
808{
809    return ms_ctx->off < ms_ctx->bufsz;
810}
811
812
813static size_t
814mini_stream_read (void *stream, void *buf, size_t len, int *reached_fin)
815{
816    struct mini_stream_ctx *ms_ctx = stream;
817    size_t avail = ms_ctx->bufsz - ms_ctx->off;
818    if (avail < len)
819        len = avail;
820    memcpy(buf, ms_ctx->buf + ms_ctx->off, len);
821    ms_ctx->off += len;
822    *reached_fin = 0;
823    return len;
824}
825
826
827/* Wrapper to throw out reached_fin */
828static size_t
829mini_stream_read_for_crypto (void *stream, void *buf, size_t len, int *fin)
830{
831    size_t retval;
832    int reached_fin;
833
834    retval = mini_stream_read(stream, buf, len, &reached_fin);
835    return retval;
836}
837
838
839static size_t
840mini_stream_size (void *stream)
841{
842    struct mini_stream_ctx *ms_ctx = stream;
843    size_t avail = ms_ctx->bufsz - ms_ctx->off;
844    return avail;
845}
846
847
848static int
849mini_stream_fin (void *stream)
850{   /* There is never a FIN on the handshake stream */
851    return 0;
852}
853
854
855static lsquic_packno_t
856next_packno (struct mini_conn *mc)
857{
858    if (mc->mc_cur_packno < MINICONN_MAX_PACKETS)
859    {
860        return ++mc->mc_cur_packno;
861    }
862    else
863    {
864        if (!(mc->mc_flags & MC_OO_PACKNOS))
865        {
866            MCHIST_APPEND(mc, MCHE_OUT_OF_PACKNOS);
867            mc->mc_flags |= MC_OO_PACKNOS;
868            LSQ_DEBUG("ran out of outgoing packet numbers");
869        }
870        return MINICONN_MAX_PACKETS + 1;
871    }
872}
873
874
875static lsquic_packet_out_t *
876allocate_packet_out (struct mini_conn *mc, const unsigned char *nonce)
877{
878    lsquic_packet_out_t *packet_out;
879    lsquic_packno_t packno;
880    packno = next_packno(mc);
881    if (packno > MINICONN_MAX_PACKETS)
882    {
883        LSQ_DEBUG("ran out of outgoing packet numbers, won't allocate packet");
884        return NULL;
885    }
886    packet_out = lsquic_packet_out_new(&mc->mc_enpub->enp_mm, NULL, 1,
887                &mc->mc_conn, GQUIC_PACKNO_LEN_1, NULL, nonce, &mc->mc_path);
888    if (!packet_out)
889    {
890        LSQ_WARN("could not allocate packet: %s", strerror(errno));
891        return NULL;
892    }
893    packet_out->po_loss_chain = packet_out;
894    packet_out->po_packno = packno;
895    packet_out->po_flags |= PO_MINI;
896    if (mc->mc_flags & MC_HAVE_SHLO)
897    {
898        packet_out->po_flags |= PO_HELLO;
899        packet_out->po_header_type = HETY_0RTT;
900    }
901    if (mc->mc_conn.cn_version >= LSQVER_050)
902    {
903        if (nonce)
904            packet_out->po_header_type = HETY_0RTT;
905        else
906            packet_out->po_header_type = HETY_INITIAL;
907    }
908    lsquic_packet_out_set_pns(packet_out, PNS_APP);
909    TAILQ_INSERT_TAIL(&mc->mc_packets_out, packet_out, po_next);
910    LSQ_DEBUG("allocated packet #%"PRIu64", nonce: %d", packno, !!nonce);
911    MCHIST_APPEND(mc, MCHE_NEW_PACKET_OUT);
912    EV_LOG_PACKET_CREATED(LSQUIC_LOG_CONN_ID, packet_out);
913    return packet_out;
914}
915
916
917static struct lsquic_packet_out *
918to_packet_pre_Q050 (struct mini_conn *mc, struct mini_stream_ctx *ms_ctx,
919                    const unsigned char *nonce)
920{
921    struct lsquic_packet_out *packet_out;
922    size_t cur_off;
923    int len;
924
925    packet_out = allocate_packet_out(mc, nonce);
926    if (!packet_out)
927        return NULL;
928    cur_off = ms_ctx->off;
929    len = mc->mc_conn.cn_pf->pf_gen_stream_frame(
930            packet_out->po_data + packet_out->po_data_sz,
931            lsquic_packet_out_avail(packet_out),
932            1, mc->mc_write_off, mini_stream_fin(ms_ctx),
933            mini_stream_size(ms_ctx), mini_stream_read, ms_ctx);
934    if (len < 0)
935    {
936        LSQ_WARN("cannot generate STREAM frame (avail: %u)",
937                                    lsquic_packet_out_avail(packet_out));
938        return NULL;
939    }
940    mc->mc_write_off += ms_ctx->off - cur_off;
941    EV_LOG_GENERATED_STREAM_FRAME(LSQUIC_LOG_CONN_ID, mc->mc_conn.cn_pf,
942                        packet_out->po_data + packet_out->po_data_sz, len);
943    packet_out->po_data_sz += len;
944    packet_out->po_frame_types |= 1 << QUIC_FRAME_STREAM;
945    if (0 == lsquic_packet_out_avail(packet_out))
946        packet_out->po_flags |= PO_STREAM_END;
947
948    return packet_out;
949}
950
951
952static struct lsquic_packet_out *
953to_packet_Q050plus (struct mini_conn *mc, struct mini_stream_ctx *ms_ctx,
954                    const unsigned char *nonce)
955{
956    struct lsquic_packet_out *packet_out;
957    size_t cur_off;
958    int len;
959
960    if (nonce && !(mc->mc_flags & MC_WR_OFF_RESET))
961    {
962        mc->mc_write_off = 0;
963        mc->mc_flags |= MC_WR_OFF_RESET;
964    }
965
966    packet_out = allocate_packet_out(mc, nonce);
967    if (!packet_out)
968        return NULL;
969    cur_off = ms_ctx->off;
970    len = mc->mc_conn.cn_pf->pf_gen_crypto_frame(
971            packet_out->po_data + packet_out->po_data_sz,
972            lsquic_packet_out_avail(packet_out), 0, mc->mc_write_off, 0,
973            mini_stream_size(ms_ctx), mini_stream_read_for_crypto, ms_ctx);
974    if (len < 0)
975    {
976        LSQ_WARN("cannot generate CRYPTO frame (avail: %u)",
977                                    lsquic_packet_out_avail(packet_out));
978        return NULL;
979    }
980    mc->mc_write_off += ms_ctx->off - cur_off;
981    EV_LOG_GENERATED_CRYPTO_FRAME(LSQUIC_LOG_CONN_ID, mc->mc_conn.cn_pf,
982                        packet_out->po_data + packet_out->po_data_sz, len);
983    packet_out->po_data_sz += len;
984    packet_out->po_frame_types |= 1 << QUIC_FRAME_CRYPTO;
985
986    return packet_out;
987}
988
989
990static int
991packetize_response (struct mini_conn *mc, const unsigned char *buf,
992                    size_t bufsz, const unsigned char *nonce)
993{
994    struct mini_stream_ctx ms_ctx;
995    lsquic_packet_out_t *packet_out;
996    struct lsquic_packet_out * (*const to_packet) (struct mini_conn *,
997                struct mini_stream_ctx *, const unsigned char *)
998        = mc->mc_conn.cn_version < LSQVER_050
999            ? to_packet_pre_Q050 : to_packet_Q050plus;
1000
1001    LSQ_DEBUG("Packetizing %zd bytes of handshake response", bufsz);
1002
1003    ms_ctx.buf   = buf;
1004    ms_ctx.bufsz = bufsz;
1005    ms_ctx.off   = 0;
1006
1007    do
1008    {
1009        packet_out = to_packet(mc, &ms_ctx, nonce);
1010        if (!packet_out)
1011            return -1;
1012    }
1013    while (mini_stream_has_data(&ms_ctx));
1014
1015    /* PAD the last packet with NULs.  ACK and STOP_WAITING go into a separate
1016     * packet.
1017     */
1018    if (lsquic_packet_out_avail(packet_out))
1019    {
1020        EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "generated PADDING frame %u "
1021                            "bytes long", lsquic_packet_out_avail(packet_out));
1022        memset(packet_out->po_data + packet_out->po_data_sz, 0,
1023                                        lsquic_packet_out_avail(packet_out));
1024        packet_out->po_data_sz += lsquic_packet_out_avail(packet_out);
1025        packet_out->po_frame_types |= 1 << QUIC_FRAME_PADDING;
1026    }
1027
1028    return 0;
1029}
1030
1031
1032static int
1033continue_handshake (struct mini_conn *mc)
1034{
1035    lsquic_packet_in_t *packet_in;
1036    unsigned n_hsk_chunks = 0, n_contig, n, bufsz, off;
1037    int s, rv;
1038    size_t out_len;
1039    enum handshake_error he;
1040    unsigned char *buf_in_16k, *buf_out;
1041    const unsigned char *buf_in;
1042    time_t t;
1043    stream_frame_t frame;
1044    struct hsk_chunk hsk_chunks[MINICONN_MAX_PACKETS], *hsk_chunk;
1045    unsigned char nonce_buf[32];
1046    int nonce_set = 0;
1047    int (*parse_frame)(const unsigned char *, size_t, struct stream_frame *)
1048        = mc->mc_conn.cn_version < LSQVER_050
1049            ? mc->mc_conn.cn_pf->pf_parse_stream_frame
1050            : mc->mc_conn.cn_pf->pf_parse_crypto_frame;
1051
1052    /* Get handshake stream data from each packet that contains a handshake
1053     * stream frame and place them into `hsk_chunks' array.
1054     */
1055    TAILQ_FOREACH(packet_in, &mc->mc_packets_in, pi_next)
1056    {
1057        assert(n_hsk_chunks < sizeof(hsk_chunks) / sizeof(hsk_chunks[0]));
1058        if (0 == (packet_in->pi_flags & PI_HSK_STREAM))
1059            continue;
1060        s = parse_frame(packet_in->pi_data + packet_in->pi_hsk_stream,
1061                packet_in->pi_data_sz - packet_in->pi_hsk_stream, &frame);
1062        if (-1 == s)
1063        {
1064            LSQ_WARN("cannot process hsk stream frame in packet %"PRIu64,
1065                packet_in->pi_packno);
1066            return -1;
1067        }
1068        hsk_chunk = &hsk_chunks[ n_hsk_chunks++ ];
1069        hsk_chunk->hsk_packet_in = packet_in;
1070        hsk_chunk->hsk_data      = frame.data_frame.df_data;
1071        hsk_chunk->hsk_off       = frame.data_frame.df_offset;
1072        hsk_chunk->hsk_sz        = frame.data_frame.df_size;
1073    }
1074    assert(n_hsk_chunks > 0);
1075
1076    if (n_hsk_chunks > 1)
1077    {
1078        /* Sort handshake stream data */
1079        qsort(hsk_chunks, n_hsk_chunks, sizeof(hsk_chunks[0]),
1080                                                        compare_hsk_chunks);
1081        /* Figure out how many packets contain handshake stream data in a
1082         * contiguous buffer and how large this data is.
1083         */
1084        for (n = 1, n_contig = 1, bufsz = hsk_chunks[0].hsk_sz;
1085                                                        n < n_hsk_chunks; ++n)
1086            if (hsk_chunks[n - 1].hsk_off + hsk_chunks[n - 1].hsk_sz ==
1087                                                        hsk_chunks[n].hsk_off)
1088            {
1089                ++n_contig;
1090                bufsz += hsk_chunks[n].hsk_sz;
1091            }
1092            else
1093                break;
1094    }
1095    else
1096    {
1097        n_contig = 1;
1098        bufsz = hsk_chunks[0].hsk_sz;
1099    }
1100
1101    /* Handshake handler expects to start reading at a particular offset.
1102     */
1103    if (hsk_chunks[0].hsk_off != mc->mc_read_off)
1104    {
1105        LSQ_DEBUG("smallest hsk offset is %u, need %hu",
1106                                hsk_chunks[0].hsk_off, mc->mc_read_off);
1107        MCHIST_APPEND(mc, MCHE_HELLO_HOLE);
1108        return 0;
1109    }
1110
1111    LSQ_DEBUG("# of contiguous stream frames: %u out of %u; offset: %u; "
1112        "total size: %u", n_contig, n_hsk_chunks, hsk_chunks[0].hsk_off, bufsz);
1113
1114    if (bufsz > 16 * 1024)
1115    {
1116        LSQ_INFO("too much contiguous handshake data (%u bytes); max: %u",
1117            bufsz, 16 * 1024);
1118        MCHIST_APPEND(mc, MCHE_HELLO_TOO_MUCH);
1119        return -1;
1120    }
1121
1122    /* From here on, since we need to clean up, we use `rv' and `goto end'
1123     * to handle error conditions and cleanup.
1124     */
1125    rv = -1;
1126    if (n_contig > 1)
1127    {
1128        buf_in = buf_in_16k = lsquic_mm_get_16k(&mc->mc_enpub->enp_mm);
1129        if (!buf_in)
1130        {
1131            LSQ_WARN("could not allocate in buffer: %s", strerror(errno));
1132            buf_out = NULL;
1133            goto end;
1134        }
1135        /* Create a single contiguous buffer to pass to lsquic_enc_session_handle_chlo */
1136        off = 0;
1137        for (n = 0; n < n_contig; ++n)
1138        {
1139            memcpy(buf_in_16k + off, hsk_chunks[n].hsk_data,
1140                                                    hsk_chunks[n].hsk_sz);
1141            off += hsk_chunks[n].hsk_sz;
1142        }
1143        assert(off == bufsz);
1144    }
1145    else
1146    {
1147        buf_in_16k = NULL;
1148        buf_in = hsk_chunks[0].hsk_data;
1149    }
1150
1151    buf_out = lsquic_mm_get_16k(&mc->mc_enpub->enp_mm);
1152    if (!buf_out)
1153    {
1154        LSQ_WARN("could not allocate out buffer: %s", strerror(errno));
1155        goto end;
1156    }
1157    out_len = 16 * 1024;
1158
1159    /* Allocate enc_session for the server if first time around: */
1160    if (!mc->mc_conn.cn_enc_session)
1161    {
1162        mc->mc_conn.cn_enc_session =
1163            mc->mc_conn.cn_esf.g->esf_create_server(&mc->mc_conn,
1164                                        mc->mc_conn.cn_cid, mc->mc_enpub);
1165        if (!mc->mc_conn.cn_enc_session)
1166        {
1167            LSQ_WARN("cannot create new enc session");
1168            goto end;
1169        }
1170        MCHIST_APPEND(mc, MCHE_NEW_ENC_SESS);
1171    }
1172
1173    t = time(NULL);
1174    he = mc->mc_conn.cn_esf.g->esf_handle_chlo(mc->mc_conn.cn_enc_session,
1175            mc->mc_conn.cn_version,
1176            buf_in, bufsz, t, NP_PEER_SA(&mc->mc_path),
1177            NP_LOCAL_SA(&mc->mc_path),
1178            buf_out, &out_len, nonce_buf, &nonce_set);
1179
1180    if (HS_SHLO == he)
1181        mc->mc_flags |=  MC_HAVE_SHLO;
1182    else
1183        mc->mc_flags &= ~MC_HAVE_SHLO;
1184
1185    MCHIST_APPEND(mc, he == DATA_NOT_ENOUGH ? MCHE_HANDLE_NOT_ENOUGH :
1186                      he == HS_SHLO         ? MCHE_HANDLE_SHLO :
1187                      he == HS_1RTT         ? MCHE_HANDLE_1RTT :
1188                      he == HS_2RTT         ? MCHE_HANDLE_2RTT :
1189                      he == HS_ERROR        ? MCHE_HANDLE_ERROR :
1190                                              MCHE_HAHDLE_UNKNOWN);
1191
1192    if ((HS_SHLO == he || HS_1RTT == he) && !mc->mc_rtt_stats.srtt)
1193    {
1194        uint32_t irtt;
1195        if (0 == mc->mc_conn.cn_esf.g->esf_get_peer_setting(
1196                        mc->mc_conn.cn_enc_session, QTAG_IRTT, &irtt))
1197        {
1198            /* Do not allow the client to specify unreasonable values:
1199             * smaller than 10ms or larger than 15s.  Per reference
1200             * implementation.
1201             */
1202            if (irtt > 15 * 1000 * 1000)
1203                irtt = 15 * 1000 * 1000;
1204            else if (irtt < 10 * 1000)
1205                irtt = 10 * 1000;
1206            lsquic_rtt_stats_update(&mc->mc_rtt_stats, irtt, 0);
1207            LSQ_DEBUG("Set initial SRTT to %"PRIu32" usec based on client-"
1208                "supplied IRTT value", irtt);
1209        }
1210    }
1211
1212    switch (he)
1213    {
1214    case DATA_NOT_ENOUGH:
1215        LSQ_DEBUG("lsquic_enc_session_handle_chlo needs more data");
1216        break;
1217    case HS_SHLO:
1218        mc->mc_conn.cn_flags |= LSCONN_HANDSHAKE_DONE;
1219        mc->mc_flags |= MC_PROMOTE;
1220        LSQ_DEBUG("lsquic_enc_session_handle_chlo returned %d, promote", he);
1221        /* Fall through */
1222    case HS_1RTT:
1223        assert(out_len > 0);
1224        if (mc->mc_conn.cn_version < LSQVER_046
1225                    && !mc->mc_conn.cn_esf.g->esf_get_peer_option(
1226                                    mc->mc_conn.cn_enc_session, QTAG_NSTP))
1227            mc->mc_flags |= MC_STOP_WAIT_ON;
1228        if (0 != packetize_response(mc, buf_out, out_len,
1229                                            nonce_set ? nonce_buf : NULL))
1230            goto end;
1231        mc->mc_read_off += bufsz;
1232        for (n = 0; n < n_contig; ++n)
1233            hsk_chunks[n].hsk_packet_in->pi_flags &= ~PI_HSK_STREAM;
1234        LSQ_DEBUG("read offset is now %hu", mc->mc_read_off);
1235        break;
1236    default:
1237        LSQ_WARN("unexpected return value from lsquic_enc_session_handle_chlo: %u", he);
1238        /* fallthru */
1239    case HS_ERROR:
1240#if !LSQUIC_KEEP_ENC_SESS_HISTORY
1241        mc->mc_conn.cn_esf.g->esf_destroy(mc->mc_conn.cn_enc_session);
1242        mc->mc_conn.cn_enc_session = NULL;
1243#endif
1244        mc->mc_flags |= MC_HSK_ERR;
1245        LSQ_INFO("lsquic_enc_session_handle_chlo returned an error (%d)", he);
1246        goto end;
1247    }
1248
1249    rv = 0;
1250
1251  end:
1252    mc->mc_flags &= ~MC_HAVE_SHLO;
1253    if (buf_in_16k)
1254        lsquic_mm_put_16k(&mc->mc_enpub->enp_mm, buf_in_16k);
1255    if (buf_out)
1256        lsquic_mm_put_16k(&mc->mc_enpub->enp_mm, buf_out);
1257    return rv;
1258}
1259
1260
1261struct mini_rechist
1262{
1263    const struct mini_conn     *mc;
1264    mconn_packno_set_t          cur_set;
1265    int                         cur_idx;
1266    struct lsquic_packno_range  range;   /* We return a pointer to this */
1267};
1268
1269
1270static void
1271mini_rechist_init (struct mini_rechist *rechist, const struct mini_conn *mc)
1272{
1273    rechist->mc      = mc;
1274    rechist->cur_set = 0;
1275    rechist->cur_idx = 0;
1276}
1277
1278
1279static lsquic_time_t
1280mini_rechist_largest_recv (void *rechist_ctx)
1281{
1282    struct mini_rechist *rechist = rechist_ctx;
1283    const struct mini_conn *mc = rechist->mc;
1284    lsquic_time_t delta =  mc->mc_largest_recv[0]
1285                        + (mc->mc_largest_recv[1] << 8)
1286                        + (mc->mc_largest_recv[2] << 16);
1287    LSQ_DEBUG("%s: largest received: %"PRIu64" usec since creation",
1288                                                            __func__, delta);
1289    return mc->mc_created + delta;
1290}
1291
1292
1293static const struct lsquic_packno_range *
1294mini_rechist_next (void *rechist_ctx)
1295{
1296    struct mini_rechist *rechist = rechist_ctx;
1297    const struct mini_conn *mc = rechist->mc;
1298    mconn_packno_set_t packnos;
1299    int i;
1300
1301    packnos = rechist->cur_set;
1302    if (0 == packnos)
1303        return NULL;
1304
1305    /* There may be a faster way to do this, but for now, we just want
1306     * correctness.
1307     */
1308    for (i = rechist->cur_idx; i >= 0; --i)
1309        if (packnos & (1ULL << i))
1310        {
1311            rechist->range.low  = i + 1;
1312            rechist->range.high = i + 1;
1313            break;
1314        }
1315    assert(i >= 0); /* We must have hit at least one bit */
1316    --i;
1317    for ( ; i >= 0 && (packnos & (1ULL << i)); --i)
1318        rechist->range.low = i + 1;
1319    if (i >= 0)
1320    {
1321        rechist->cur_set = packnos & ((1ULL << i) - 1);
1322        rechist->cur_idx = i;
1323    }
1324    else
1325        rechist->cur_set = 0;
1326    LSQ_DEBUG("%s: return [%"PRIu64", %"PRIu64"]", __func__,
1327                                rechist->range.low, rechist->range.high);
1328    return &rechist->range;
1329}
1330
1331
1332static const struct lsquic_packno_range *
1333mini_rechist_first (void *rechist_ctx)
1334{
1335    struct mini_rechist *rechist = rechist_ctx;
1336    rechist->cur_set = rechist->mc->mc_received_packnos;
1337    rechist->cur_idx = highest_bit_set(rechist->cur_set);
1338    return mini_rechist_next(rechist_ctx);
1339}
1340
1341
1342static lsquic_packno_t
1343least_unacked (const struct mini_conn *mc)
1344{
1345    mconn_packno_set_t unacked;
1346    lsquic_packno_t packno;
1347    unacked = mc->mc_sent_packnos & ~mc->mc_acked_packnos;
1348    if (unacked)
1349        packno = lowest_bit_set(unacked) + 1;
1350    else
1351        packno = highest_bit_set(mc->mc_sent_packnos) + 2;
1352    LSQ_DEBUG("%s: least unacked: %"PRIu64, __func__, packno);
1353    return packno;
1354}
1355
1356
1357static int
1358generate_ack_and_stop_waiting (struct mini_conn *mc, lsquic_time_t now)
1359{
1360    lsquic_packet_out_t *packet_out;
1361    struct mini_rechist rechist;
1362    int len, not_used_has_missing;
1363    lsquic_packno_t lunack;
1364
1365    /* Chrome's quic_server places ACK and STOP_WAITING frames into a separate
1366     * packet.
1367     */
1368    packet_out = allocate_packet_out(mc, NULL);
1369    if (!packet_out)
1370        return -1;
1371
1372    /* Generate ACK frame */
1373    mini_rechist_init(&rechist, mc);
1374    len = mc->mc_conn.cn_pf->pf_gen_ack_frame(packet_out->po_data + packet_out->po_data_sz,
1375                lsquic_packet_out_avail(packet_out), mini_rechist_first,
1376                mini_rechist_next, mini_rechist_largest_recv, &rechist,
1377                now, &not_used_has_missing, &packet_out->po_ack2ed, NULL);
1378    if (len < 0)
1379    {
1380        LSQ_WARN("could not generate ACK frame");
1381        return -1;
1382    }
1383    EV_LOG_GENERATED_ACK_FRAME(LSQUIC_LOG_CONN_ID, mc->mc_conn.cn_pf,
1384                        packet_out->po_data + packet_out->po_data_sz, len);
1385    packet_out->po_frame_types |= 1 << QUIC_FRAME_ACK;
1386    packet_out->po_data_sz += len;
1387    packet_out->po_regen_sz += len;
1388    LSQ_DEBUG("wrote ACK frame of size %d", len);
1389
1390    /* Generate STOP_WAITING frame */
1391    if ((mc->mc_flags & MC_STOP_WAIT_ON) && mc->mc_sent_packnos)
1392    {
1393        lunack = least_unacked(mc);
1394        len = mc->mc_conn.cn_pf->pf_gen_stop_waiting_frame(packet_out->po_data +
1395                                                packet_out->po_data_sz,
1396                lsquic_packet_out_avail(packet_out), packet_out->po_packno,
1397                lsquic_packet_out_packno_bits(packet_out), lunack);
1398        if (len < 0)
1399        {
1400            LSQ_WARN("could not generate STOP_WAITING frame");
1401            return -1;
1402        }
1403        packet_out->po_data_sz += len;
1404        packet_out->po_regen_sz += len;
1405        packet_out->po_frame_types |= 1 << QUIC_FRAME_STOP_WAITING;
1406        LSQ_DEBUG("wrote STOP_WAITING frame of size %d", len);
1407        EV_LOG_GENERATED_STOP_WAITING_FRAME(LSQUIC_LOG_CONN_ID, lunack);
1408    }
1409    else if (mc->mc_flags & MC_STOP_WAIT_ON)
1410        LSQ_DEBUG("nothing sent: no need to generate STOP_WAITING frame");
1411
1412    mc->mc_flags |= MC_UNSENT_ACK;
1413    return 0;
1414}
1415
1416
1417static int
1418calc_retx_timeout (const struct mini_conn *mc)
1419{
1420    lsquic_time_t to;
1421    to = lsquic_rtt_stats_get_srtt(&mc->mc_rtt_stats);
1422    if (to)
1423    {
1424        to += to / 2;
1425        if (to < 10000)
1426            to = 10000;
1427    }
1428    else
1429        to = 300000;
1430    return to << mc->mc_hsk_count;
1431}
1432
1433
1434static void
1435return_enc_data (struct mini_conn *mc, struct lsquic_packet_out *packet_out)
1436{
1437    mc->mc_enpub->enp_pmi->pmi_return(mc->mc_enpub->enp_pmi_ctx,
1438        mc->mc_path.np_peer_ctx, packet_out->po_enc_data,
1439        lsquic_packet_out_ipv6(packet_out));
1440    packet_out->po_flags &= ~PO_ENCRYPTED;
1441    packet_out->po_enc_data = NULL;
1442}
1443
1444
1445static int
1446repackage_packet (struct mini_conn *mc, lsquic_packet_out_t *packet_out)
1447{
1448    const lsquic_packno_t oldno = packet_out->po_packno;
1449    const lsquic_packno_t packno = next_packno(mc);
1450    if (packno > MINICONN_MAX_PACKETS)
1451        return -1;
1452
1453    LSQ_DEBUG("Packet %"PRIu64" repackaged for resending as packet %"PRIu64,
1454                                                        oldno, packno);
1455    EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "packet %"PRIu64" repackaged for "
1456        "resending as packet %"PRIu64, oldno, packno);
1457    packet_out->po_packno = packno;
1458    packet_out->po_flags &= ~PO_SENT;
1459    if (packet_out->po_flags & PO_ENCRYPTED)
1460        return_enc_data(mc, packet_out);
1461    TAILQ_INSERT_TAIL(&mc->mc_packets_out, packet_out, po_next);
1462    return 0;
1463}
1464
1465
1466static int
1467handle_losses_and_have_unsent (struct mini_conn *mc, lsquic_time_t now)
1468{
1469    TAILQ_HEAD(, lsquic_packet_out) lost_packets =
1470                                    TAILQ_HEAD_INITIALIZER(lost_packets);
1471    lsquic_packet_out_t *packet_out, *next;
1472    lsquic_time_t retx_to = 0;
1473    unsigned n_to_send = 0;
1474
1475    for (packet_out = TAILQ_FIRST(&mc->mc_packets_out); packet_out;
1476                                                        packet_out = next)
1477    {
1478        next = TAILQ_NEXT(packet_out, po_next);
1479        if (packet_out->po_flags & PO_SENT)
1480        {
1481            if (0 == retx_to)
1482                retx_to = calc_retx_timeout(mc);
1483            if (packet_out->po_sent + retx_to < now)
1484            {
1485                LSQ_DEBUG("packet %"PRIu64" has been lost (rto: %"PRIu64")",
1486                                                packet_out->po_packno, retx_to);
1487                TAILQ_REMOVE(&mc->mc_packets_out, packet_out, po_next);
1488                TAILQ_INSERT_TAIL(&lost_packets, packet_out, po_next);
1489                mc->mc_lost_packnos |= MCONN_PACKET_MASK(packet_out->po_packno);
1490                MCHIST_APPEND(mc, MCHE_PACKET_LOST);
1491            }
1492        }
1493        else
1494            ++n_to_send;
1495    }
1496
1497    mc->mc_hsk_count += !TAILQ_EMPTY(&lost_packets);
1498
1499    while ((packet_out = TAILQ_FIRST(&lost_packets)))
1500    {
1501        TAILQ_REMOVE(&lost_packets, packet_out, po_next);
1502        if ((packet_out->po_frame_types & GQUIC_FRAME_RETRANSMITTABLE_MASK)
1503                                    && 0 == repackage_packet(mc, packet_out))
1504            ++n_to_send;
1505        else
1506            mini_destroy_packet(mc, packet_out);
1507    }
1508
1509    return n_to_send > 0;
1510}
1511
1512
1513static int
1514warning_is_warranted (const struct mini_conn *mc)
1515{
1516    return (mc->mc_flags & (MC_HSK_ERR|MC_OO_PACKNOS))
1517        || 0x1C /* QUIC_HANDSHAKE_FAILED                    */ == mc->mc_error_code
1518        || 0x1D /* QUIC_CRYPTO_TAGS_OUT_OF_ORDER            */ == mc->mc_error_code
1519        || 0x1E /* QUIC_CRYPTO_TOO_MANY_ENTRIES             */ == mc->mc_error_code
1520        || 0x1F /* QUIC_CRYPTO_INVALID_VALUE_LENGTH         */ == mc->mc_error_code
1521        || 0x21 /* QUIC_INVALID_CRYPTO_MESSAGE_TYPE         */ == mc->mc_error_code
1522        || 0x22 /* QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER    */ == mc->mc_error_code
1523        || 0x23 /* QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND  */ == mc->mc_error_code
1524        || 0x24 /* QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP */ == mc->mc_error_code
1525        || 0x29 /* QUIC_CRYPTO_TOO_MANY_REJECTS             */ == mc->mc_error_code
1526        || 0x2A /* QUIC_PROOF_INVALID                       */ == mc->mc_error_code
1527        || 0x2B /* QUIC_CRYPTO_DUPLICATE_TAG                */ == mc->mc_error_code
1528        || 0x2C /* QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT   */ == mc->mc_error_code
1529        || 0x2D /* QUIC_CRYPTO_SERVER_CONFIG_EXPIRED        */ == mc->mc_error_code
1530        || 0x35 /* QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED   */ == mc->mc_error_code
1531        ;
1532}
1533
1534
1535#if LSQUIC_KEEP_ENC_SESS_HISTORY
1536static void
1537maybe_log_enc_sess_history (const struct mini_conn *mc)
1538{
1539    char eshist[ESHIST_STR_SIZE];
1540    enum lsq_log_level log_level;
1541    const char *ua;
1542
1543    if (warning_is_warranted(mc))
1544        log_level = LSQ_LOG_WARN;
1545    else
1546        log_level = LSQ_LOG_DEBUG;
1547
1548    if (mc->mc_conn.cn_enc_session)
1549    {
1550        mc->mc_conn.cn_esf.g->esf_get_hist(mc->mc_conn.cn_enc_session, eshist);
1551        ua = mc->mc_conn.cn_esf.g->esf_get_ua(mc->mc_conn.cn_enc_session);
1552        LSQ_LOG1(log_level, "enc hist %s; User-Agent: %s", eshist,
1553                                                        ua ? ua : "<not set>");
1554    }
1555    else
1556        LSQ_LOG1(log_level, "enc session gone: no history to log");
1557}
1558
1559
1560#endif
1561
1562
1563
1564
1565static int
1566have_packets_to_send (struct mini_conn *mc, lsquic_time_t now)
1567{
1568    return handle_losses_and_have_unsent(mc, now);
1569}
1570
1571
1572static enum tick_st
1573mini_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now)
1574{
1575    struct mini_conn *mc = (struct mini_conn *) lconn;
1576    enum tick_st tick;
1577
1578    ++mc->mc_n_ticks;
1579
1580    if (mc->mc_created + mc->mc_enpub->enp_settings.es_handshake_to < now)
1581    {
1582        LSQ_DEBUG("connection expired: closing");
1583        tick = TICK_CLOSE;
1584        goto end;
1585    }
1586
1587    if (mc->mc_flags & MC_ERROR)
1588    {
1589        tick = TICK_CLOSE;
1590        goto end;
1591    }
1592
1593
1594    if ((mc->mc_flags & (MC_UNSENT_ACK|MC_GEN_ACK)) == MC_GEN_ACK)
1595    {
1596        if (0 != generate_ack_and_stop_waiting(mc, now))
1597        {
1598            mc->mc_flags |= MC_ERROR;
1599            tick = TICK_CLOSE;
1600            goto end;
1601        }
1602        else
1603            mc->mc_flags &= ~MC_GEN_ACK;
1604    }
1605
1606    if (have_packets_to_send(mc, now))
1607        tick = TICK_SEND;
1608    else
1609        tick = TICK_QUIET;
1610
1611    if (mc->mc_flags & MC_PROMOTE)
1612        tick |= TICK_PROMOTE;
1613
1614  end:
1615#if LSQUIC_KEEP_ENC_SESS_HISTORY
1616    if (tick & (TICK_CLOSE|TICK_PROMOTE))
1617        maybe_log_enc_sess_history(mc);
1618#endif
1619
1620    return tick;
1621}
1622
1623
1624static void
1625process_packet (struct mini_conn *mc, struct lsquic_packet_in *packet_in)
1626{
1627    switch (process_regular_packet(mc, packet_in))
1628    {
1629    case PRP_KEEP:
1630        assert(packet_in->pi_flags & PI_OWN_DATA);
1631        lsquic_packet_in_upref(packet_in);
1632        TAILQ_INSERT_TAIL(&mc->mc_packets_in, packet_in, pi_next);
1633        if (mc->mc_flags & MC_HAVE_NEW_HSK)
1634        {
1635            if (0 != continue_handshake(mc))
1636                mc->mc_flags |= MC_ERROR;
1637            mc->mc_flags &= ~MC_HAVE_NEW_HSK;
1638        }
1639        break;
1640    case PRP_DEFER:
1641        assert(packet_in->pi_flags & PI_OWN_DATA);
1642        lsquic_packet_in_upref(packet_in);
1643        if (mc->mc_n_deferred < MINI_CONN_MAX_DEFERRED)
1644        {
1645            TAILQ_INSERT_TAIL(&mc->mc_deferred, packet_in, pi_next);
1646            ++mc->mc_n_deferred;
1647        }
1648        else
1649            LSQ_DEBUG("won't defer more than %u packets: drop",
1650                                                MINI_CONN_MAX_DEFERRED);
1651        break;
1652    case PRP_ERROR:
1653        mc->mc_flags |= MC_ERROR;
1654        break;
1655    case PRP_DROP:
1656        break;
1657    }
1658}
1659
1660
1661/* Keep deferred list ordered by packet number, so that we can process all
1662 * of them in a single pass.
1663 */
1664static void
1665insert_into_deferred (struct mini_conn *mc, lsquic_packet_in_t *new_packet)
1666{
1667    lsquic_packet_in_t *packet_in;
1668
1669    lsquic_packet_in_upref(new_packet);
1670
1671    TAILQ_FOREACH(packet_in, &mc->mc_deferred, pi_next)
1672    if (packet_in->pi_packno > new_packet->pi_packno)
1673        break;
1674
1675    if (packet_in)
1676        TAILQ_INSERT_BEFORE(packet_in, new_packet, pi_next);
1677    else
1678        TAILQ_INSERT_TAIL(&mc->mc_deferred, new_packet, pi_next);
1679    ++mc->mc_n_deferred;
1680}
1681
1682
1683static void
1684process_deferred_packets (struct mini_conn *mc)
1685{
1686    lsquic_packet_in_t *last, *packet_in;
1687    int reached_last;
1688
1689    last = TAILQ_LAST(&mc->mc_deferred, head_packet_in);
1690    do
1691    {
1692        packet_in = TAILQ_FIRST(&mc->mc_deferred);
1693        TAILQ_REMOVE(&mc->mc_deferred, packet_in, pi_next);
1694        --mc->mc_n_deferred;
1695        process_packet(mc, packet_in);
1696        reached_last = packet_in == last;
1697        lsquic_packet_in_put(&mc->mc_enpub->enp_mm, packet_in);
1698    }
1699    while (!reached_last);
1700}
1701
1702
1703#if LSQUIC_RECORD_INORD_HIST
1704/* Packet number is encoded as a sequence of 1-bits and stored in mc_inord_hist
1705 * separated by 0 bits.  For example, sequence of packet numbers 3, 2, 1 would
1706 * be encoded as (starting with LSB) 1110110100000000...  This is not the most
1707 * space-efficient scheme, but it is simple to implement and should suffice for
1708 * our purposes.
1709 */
1710static void
1711record_inord_packno (struct mini_conn *mc, lsquic_packno_t packno)
1712{
1713    int n_avail;
1714    lsquic_packno_t mask;
1715
1716    for ( ; mc->mc_inord_idx < sizeof(mc->mc_inord_hist) /
1717                            sizeof(mc->mc_inord_hist[0]); ++mc->mc_inord_idx)
1718    {
1719        if (mc->mc_inord_hist[ mc->mc_inord_idx ])
1720            n_avail = __builtin_clzll(mc->mc_inord_hist[ mc->mc_inord_idx ]) - 1;
1721        else
1722            n_avail = sizeof(mc->mc_inord_hist[ mc->mc_inord_idx ]) * 8;
1723        if (n_avail >= (int) packno)
1724        {
1725            mask = (1ULL << (int) packno) - 1;
1726            mask <<= sizeof(mc->mc_inord_hist[ mc->mc_inord_idx ]) * 8 - n_avail;
1727            mc->mc_inord_hist[ mc->mc_inord_idx ] |= mask;
1728            return;                                             /* Success */
1729        }
1730    }
1731}
1732
1733
1734static void
1735inord_to_str (const struct mini_conn *mc, char *buf, size_t bufsz)
1736{
1737    unsigned long long hist;
1738    size_t off;
1739    ssize_t nw;
1740    unsigned n;
1741    int n_trail;
1742
1743    off = 0;
1744    for (n = 0; n < sizeof(mc->mc_inord_hist) /
1745                                        sizeof(mc->mc_inord_hist[0]); ++n)
1746    {
1747        hist = mc->mc_inord_hist[n];
1748        while (hist)
1749        {
1750            n_trail = __builtin_ctzll(~hist);
1751            nw = snprintf(buf + off, bufsz - off,
1752                /* No spaces are included on purpose: this makes it a single
1753                 * field and thus easy to process log using standard command-
1754                 * line tools, such as sork -k, for example.
1755                 */
1756                                        (off ? ",%d" : "%d"), n_trail);
1757            if ((size_t) nw > bufsz - off || nw < 0)
1758                break;
1759            off += nw;
1760            hist >>= n_trail + 1;
1761        }
1762    }
1763    buf[ bufsz - 1 ] = '\0';    /* CYA */
1764}
1765
1766
1767#endif
1768
1769
1770static void
1771mini_conn_ci_packet_in (struct lsquic_conn *lconn,
1772                        struct lsquic_packet_in *packet_in)
1773{
1774    struct mini_conn *mc = (struct mini_conn *) lconn;
1775
1776#if LSQUIC_RECORD_INORD_HIST
1777    record_inord_packno(mc, packet_in->pi_packno);
1778#endif
1779#if 0
1780    /* A convenient way to test lsquic_is_valid_hs_packet(): */
1781    if (!(mc->mc_sent_packnos))
1782        assert(lsquic_is_valid_hs_packet(NULL, packet_in->pi_data,
1783                                                    packet_in->pi_data_sz));
1784#endif
1785
1786    if (mc->mc_flags & MC_ERROR)
1787    {
1788        LSQ_DEBUG("error state: ignore packet %"PRIu64, packet_in->pi_packno);
1789        return;
1790    }
1791
1792    if (lsquic_packet_in_is_gquic_prst(packet_in))
1793    {
1794        LSQ_INFO("received reset packet");
1795        mc->mc_flags |= MC_ERROR;
1796        MCHIST_APPEND(mc, MCHE_PRST_IN);
1797        return;
1798    }
1799
1800    LSQ_DEBUG("packet in: %"PRIu64, packet_in->pi_packno);
1801    EV_LOG_PACKET_IN(LSQUIC_LOG_CONN_ID, packet_in);
1802
1803
1804    /* Check receive history */
1805    if (0 == packet_in->pi_packno)
1806    {
1807        LSQ_DEBUG("invalid packet number 0");
1808        mc->mc_flags |= MC_ERROR;
1809        MCHIST_APPEND(mc, MCHE_PACKET0_IN);
1810        return;
1811    }
1812    if (packet_in->pi_packno > MINICONN_MAX_PACKETS)
1813    {
1814        LSQ_DEBUG("packet number %"PRIu64" is too large (max %zd)",
1815                            packet_in->pi_packno, MINICONN_MAX_PACKETS);
1816        mc->mc_flags |= MC_ERROR;
1817        MCHIST_APPEND(mc, MCHE_PACKET2LARGE_IN);
1818        return;
1819    }
1820    if (MCONN_PACKET_MASK(packet_in->pi_packno) & mc->mc_received_packnos)
1821    {
1822        LSQ_DEBUG("duplicate packet %"PRIu64", ignoring", packet_in->pi_packno);
1823        MCHIST_APPEND(mc, MCHE_PACKET_DUP_IN);
1824        return;
1825    }
1826
1827    if (TAILQ_EMPTY(&mc->mc_deferred))
1828        process_packet(mc, packet_in);
1829    else if (mc->mc_n_deferred < MINI_CONN_MAX_DEFERRED)
1830    {
1831        insert_into_deferred(mc, packet_in);
1832        process_deferred_packets(mc);
1833    }
1834    else
1835        LSQ_DEBUG("won't defer more than %u packets: drop",
1836                                                MINI_CONN_MAX_DEFERRED);
1837}
1838
1839
1840/* Q050 is different is that packet numbers are not known until after the
1841 * packet is decrypted, so we have to follow different logic here.
1842 */
1843static void
1844mini_conn_ci_Q050_packet_in (struct lsquic_conn *lconn,
1845                        struct lsquic_packet_in *packet_in)
1846{
1847    struct mini_conn *mc = (struct mini_conn *) lconn;
1848    enum proc_rp prp;
1849
1850    if (mc->mc_flags & MC_ERROR)
1851    {
1852        LSQ_DEBUG("error state: ignore packet");
1853        return;
1854    }
1855
1856
1857    if (!mc->mc_conn.cn_enc_session)
1858    {
1859        mc->mc_conn.cn_enc_session =
1860            mc->mc_conn.cn_esf.g->esf_create_server(&mc->mc_conn,
1861                                        mc->mc_conn.cn_cid, mc->mc_enpub);
1862        if (!mc->mc_conn.cn_enc_session)
1863        {
1864            LSQ_WARN("cannot create new enc session");
1865            mc->mc_flags |= MC_ERROR;
1866            return;
1867        }
1868        MCHIST_APPEND(mc, MCHE_NEW_ENC_SESS);
1869    }
1870
1871    assert(!(packet_in->pi_flags & PI_DECRYPTED));
1872    prp = conn_decrypt_packet_or(mc, packet_in);
1873    switch (prp)
1874    {
1875    case PRP_KEEP:
1876        break;
1877    case PRP_DROP:
1878        return;
1879    case PRP_ERROR:
1880        mc->mc_flags |= MC_ERROR;
1881        return;
1882    default:
1883        if (mc->mc_n_deferred >= MINI_CONN_MAX_DEFERRED)
1884        {
1885            LSQ_DEBUG("won't defer more than %u packets: drop",
1886                                                MINI_CONN_MAX_DEFERRED);
1887            return;
1888        }
1889        assert(prp == PRP_DEFER);
1890        assert(packet_in->pi_flags & PI_OWN_DATA);
1891        lsquic_packet_in_upref(packet_in);
1892        TAILQ_INSERT_TAIL(&mc->mc_deferred, packet_in, pi_next);
1893        ++mc->mc_n_deferred;
1894        return;
1895    }
1896
1897    assert(prp == PRP_KEEP);
1898    process_packet(mc, packet_in);
1899}
1900
1901
1902static struct lsquic_packet_out *
1903mini_conn_ci_next_packet_to_send (struct lsquic_conn *lconn, size_t size)
1904{
1905    struct mini_conn *mc = (struct mini_conn *) lconn;
1906    lsquic_packet_out_t *packet_out;
1907
1908    assert(0 == size);
1909    TAILQ_FOREACH(packet_out, &mc->mc_packets_out, po_next)
1910    {
1911        if (packet_out->po_flags & PO_SENT)
1912            continue;
1913        packet_out->po_flags |= PO_SENT;
1914        LSQ_DEBUG("packet_to_send: %"PRIu64, packet_out->po_packno);
1915        return packet_out;
1916    }
1917    return NULL;
1918}
1919
1920
1921static void
1922mini_conn_ci_packet_sent (struct lsquic_conn *lconn,
1923                          struct lsquic_packet_out *packet_out)
1924{
1925    struct mini_conn *mc = (struct mini_conn *) lconn;
1926    mc->mc_sent_packnos |= MCONN_PACKET_MASK(packet_out->po_packno);
1927    if (packet_out->po_frame_types & (1 << QUIC_FRAME_ACK))
1928    {
1929        assert(mc->mc_flags & MC_UNSENT_ACK);
1930        mc->mc_flags &= ~MC_UNSENT_ACK;
1931    }
1932    LSQ_DEBUG("%s: packet %"PRIu64" sent", __func__, packet_out->po_packno);
1933    MCHIST_APPEND(mc, MCHE_PACKET_SENT);
1934}
1935
1936
1937static void
1938mini_conn_ci_packet_not_sent (struct lsquic_conn *lconn,
1939                              struct lsquic_packet_out *packet_out)
1940{
1941    struct mini_conn *mc = (struct mini_conn *) lconn;
1942    packet_out->po_flags &= ~PO_SENT;
1943    LSQ_DEBUG("%s: packet %"PRIu64" not sent", __func__, packet_out->po_packno);
1944    MCHIST_APPEND(mc, MCHE_PACKET_DELAYED);
1945}
1946
1947
1948static void
1949mini_conn_ci_destroy (struct lsquic_conn *lconn)
1950{
1951    assert(!(lconn->cn_flags & LSCONN_HASHED));
1952    struct mini_conn *mc = (struct mini_conn *) lconn;
1953    lsquic_packet_in_t *packet_in;
1954    mconn_packno_set_t still_deferred = 0, in_flight;
1955    enum lsq_log_level log_level;
1956#if LSQUIC_RECORD_INORD_HIST
1957    char inord_str[0x100];
1958#endif
1959    while ((packet_in = TAILQ_FIRST(&mc->mc_packets_in)))
1960    {
1961        TAILQ_REMOVE(&mc->mc_packets_in, packet_in, pi_next);
1962        lsquic_packet_in_put(&mc->mc_enpub->enp_mm, packet_in);
1963    }
1964    while ((packet_in = TAILQ_FIRST(&mc->mc_deferred)))
1965    {
1966        TAILQ_REMOVE(&mc->mc_deferred, packet_in, pi_next);
1967        --mc->mc_n_deferred;
1968        still_deferred |= MCONN_PACKET_MASK(packet_in->pi_packno);
1969        lsquic_packet_in_put(&mc->mc_enpub->enp_mm, packet_in);
1970    }
1971    if (TAILQ_EMPTY(&mc->mc_packets_out))
1972        in_flight = ~0ull;  /* Indicates that packets were dropped before */
1973    else
1974        in_flight = drop_packets_out(mc);
1975    if (mc->mc_conn.cn_enc_session)
1976        mc->mc_conn.cn_esf.g->esf_destroy(mc->mc_conn.cn_enc_session);
1977    log_level = warning_is_warranted(mc) ? LSQ_LOG_WARN : LSQ_LOG_DEBUG;
1978#if LSQUIC_RECORD_INORD_HIST
1979    if (LSQ_LOG_ENABLED(log_level))
1980        inord_to_str(mc, inord_str, sizeof(inord_str));
1981#endif
1982#if LSQUIC_KEEP_MINICONN_HISTORY
1983    const unsigned hist_idx = MCHIST_MASK & mc->mc_hist_idx;
1984    if (MCHE_EMPTY == mc->mc_hist_buf[ hist_idx ])
1985        LSQ_LOG(log_level, "destroyed.  Diagnostics: conn flags: 0x%X, "
1986            "mc flags: 0x%X, "
1987#if LSQUIC_RECORD_INORD_HIST
1988            "incoming-history (trunc: %d) %s, "
1989#endif
1990            "received: %"PRIX64", sent: %"PRIX64", lost: %"PRIX64", "
1991            "deferred: %"PRIX64", still-deferred: %"PRIX64", "
1992            "dropped: %"PRIX64", in-flight: %"PRIX64", acked: %"PRIX64", "
1993            "error_code: 0x%X, ticks: %hu, pack size: %hu, "
1994            "lifetime: %"PRIu64" usec, version: %s, "
1995            "mc hist: %.*s", mc->mc_conn.cn_flags,
1996            mc->mc_flags,
1997#if LSQUIC_RECORD_INORD_HIST
1998            mc->mc_inord_idx >= sizeof(mc->mc_inord_hist) /
1999                                    sizeof(mc->mc_inord_hist[0]), inord_str,
2000#endif
2001            mc->mc_received_packnos, mc->mc_sent_packnos, mc->mc_lost_packnos,
2002            mc->mc_deferred_packnos, still_deferred,
2003            mc->mc_dropped_packnos, in_flight, mc->mc_acked_packnos,
2004            mc->mc_error_code, mc->mc_n_ticks, mc->mc_conn.cn_pack_size,
2005            lsquic_time_now() - mc->mc_created,
2006            lsquic_ver2str[mc->mc_conn.cn_version],
2007            (int) hist_idx, mc->mc_hist_buf);
2008    else
2009        LSQ_LOG(log_level, "destroyed.  Diagnostics: conn flags: 0x%X, "
2010            "mc flags: 0x%X, "
2011#if LSQUIC_RECORD_INORD_HIST
2012            "incoming-history (trunc: %d) %s, "
2013#endif
2014            "received: %"PRIX64", sent: %"PRIX64", lost: %"PRIX64", "
2015            "deferred: %"PRIX64", still-deferred: %"PRIX64", "
2016            "dropped: %"PRIX64", in-flight: %"PRIX64", acked: %"PRIX64", "
2017            "error_code: 0x%X, ticks: %hu, pack size: %hu, "
2018            "lifetime: %"PRIu64" usec, version: %s, "
2019            "mc hist: %.*s%.*s", mc->mc_conn.cn_flags,
2020            mc->mc_flags,
2021#if LSQUIC_RECORD_INORD_HIST
2022            mc->mc_inord_idx >= sizeof(mc->mc_inord_hist) /
2023                                    sizeof(mc->mc_inord_hist[0]), inord_str,
2024#endif
2025            mc->mc_received_packnos, mc->mc_sent_packnos, mc->mc_lost_packnos,
2026            mc->mc_deferred_packnos, still_deferred,
2027            mc->mc_dropped_packnos, in_flight, mc->mc_acked_packnos,
2028            mc->mc_error_code, mc->mc_n_ticks, mc->mc_conn.cn_pack_size,
2029            lsquic_time_now() - mc->mc_created,
2030            lsquic_ver2str[mc->mc_conn.cn_version],
2031            (int) (sizeof(mc->mc_hist_buf) - hist_idx),
2032            mc->mc_hist_buf + hist_idx, (int) hist_idx, mc->mc_hist_buf);
2033#else
2034    if (LSQ_LOG_ENABLED(log_level))
2035        lsquic_logger_log2(log_level, LSQUIC_LOGGER_MODULE,
2036                                   LSQUIC_LOG_CONN_ID,
2037        "destroyed.  Diagnostics: conn flags: 0x%X, "
2038        "mc flags: 0x%X, "
2039#if LSQUIC_RECORD_INORD_HIST
2040        "incoming-history (trunc: %d) %s, "
2041#endif
2042        "received: %"PRIX64", sent: %"PRIX64", lost: %"PRIX64", "
2043        "deferred: %"PRIX64", still-deferred: %"PRIX64", "
2044        "dropped: %"PRIX64", in-flight: %"PRIX64", acked: %"PRIX64", "
2045        "error_code: 0x%X, ticks: %hu, pack size: %hu, "
2046        "lifetime: %"PRIu64" usec",
2047        mc->mc_conn.cn_flags,
2048        mc->mc_flags,
2049#if LSQUIC_RECORD_INORD_HIST
2050        mc->mc_inord_idx >= sizeof(mc->mc_inord_hist) /
2051                                sizeof(mc->mc_inord_hist[0]), inord_str,
2052#endif
2053        mc->mc_received_packnos, mc->mc_sent_packnos, mc->mc_lost_packnos,
2054        mc->mc_deferred_packnos, still_deferred,
2055        mc->mc_dropped_packnos, in_flight, mc->mc_acked_packnos,
2056        mc->mc_error_code, mc->mc_n_ticks, mc->mc_path.np_pack_size,
2057        lsquic_time_now() - mc->mc_created);
2058#endif
2059    EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "mini connection destroyed");
2060    lsquic_malo_put(mc);
2061}
2062
2063
2064static struct lsquic_engine *
2065mini_conn_ci_get_engine (struct lsquic_conn *lconn)
2066{
2067    struct mini_conn *mc = (struct mini_conn *) lconn;
2068    return mc->mc_enpub->enp_engine;
2069}
2070
2071
2072static void
2073mini_conn_ci_hsk_done (struct lsquic_conn *lconn, enum lsquic_hsk_status status)
2074{
2075    assert(0);
2076}
2077
2078
2079/* A mini connection is only tickable if it has unsent packets.  This can
2080 * occur when packet sending is delayed.
2081 *
2082 * Otherwise, a mini connection is not tickable:  Either there are incoming
2083 * packets, in which case, the connection is going to be ticked, or there is
2084 * an alarm pending, in which case it will be handled via the attq.
2085 */
2086static int
2087mini_conn_ci_is_tickable (struct lsquic_conn *lconn)
2088{
2089    struct mini_conn *const mc = (struct mini_conn *) lconn;
2090    const struct lsquic_packet_out *packet_out;
2091
2092    if (mc->mc_enpub->enp_flags & ENPUB_CAN_SEND)
2093        TAILQ_FOREACH(packet_out, &mc->mc_packets_out, po_next)
2094            if (!(packet_out->po_flags & PO_SENT))
2095                return 1;
2096
2097    return 0;
2098}
2099
2100
2101static lsquic_time_t
2102mini_conn_ci_next_tick_time (struct lsquic_conn *lconn, unsigned *why)
2103{
2104    struct mini_conn *mc = (struct mini_conn *) lconn;
2105    lsquic_packet_out_t *packet_out;
2106    lsquic_time_t exp_time, retx_time;
2107
2108    exp_time = mc->mc_created + mc->mc_enpub->enp_settings.es_handshake_to;
2109
2110    TAILQ_FOREACH(packet_out, &mc->mc_packets_out, po_next)
2111        if (packet_out->po_flags & PO_SENT)
2112        {
2113            retx_time = packet_out->po_sent + calc_retx_timeout(mc);
2114            if (retx_time < exp_time)
2115            {
2116                *why = N_AEWS + AL_RETX_HSK;
2117                return retx_time;
2118            }
2119            else
2120            {
2121                *why = AEW_MINI_EXPIRE;
2122                return exp_time;
2123            }
2124        }
2125
2126    *why = AEW_MINI_EXPIRE;
2127    return exp_time;
2128}
2129
2130
2131static void
2132mini_conn_ci_client_call_on_new (struct lsquic_conn *lconn)
2133{
2134    assert(0);
2135}
2136
2137
2138static void
2139mini_conn_ci_internal_error (struct lsquic_conn *lconn,
2140                                                    const char *format, ...)
2141{
2142    struct mini_conn *mc = (struct mini_conn *) lconn;
2143    LSQ_INFO("internal error reported");
2144    mc->mc_flags |= MC_ERROR;
2145}
2146
2147
2148/* This function should not be called, as this is specific to IETF QUIC */
2149static void
2150mini_conn_ci_abort_error (struct lsquic_conn *lconn, int is_app,
2151                                unsigned error_code, const char *fmt, ...)
2152{
2153    struct mini_conn *mc = (struct mini_conn *) lconn;
2154    assert(0);
2155    LSQ_WARN("(GQUIC) abort error is called unexpectedly");
2156    mc->mc_flags |= MC_ERROR;
2157}
2158
2159
2160static void
2161mini_conn_ci_tls_alert (struct lsquic_conn *lconn, uint8_t alert)
2162{
2163    assert(0);
2164}
2165
2166
2167static unsigned char
2168mini_conn_ci_record_addrs (struct lsquic_conn *lconn, void *peer_ctx,
2169            const struct sockaddr *local_sa, const struct sockaddr *peer_sa)
2170{
2171    struct mini_conn *mc = (struct mini_conn *) lconn;
2172    struct lsquic_packet_out *packet_out;
2173    size_t len;
2174
2175
2176    if (NP_IS_IPv6(&mc->mc_path) != (AF_INET6 == peer_sa->sa_family))
2177        TAILQ_FOREACH(packet_out, &mc->mc_packets_out, po_next)
2178            if ((packet_out->po_flags & (PO_SENT|PO_ENCRYPTED)) == PO_ENCRYPTED)
2179                return_enc_data(mc, packet_out);
2180
2181    len = local_sa->sa_family == AF_INET ? sizeof(struct sockaddr_in)
2182                                                : sizeof(struct sockaddr_in6);
2183
2184    memcpy(mc->mc_path.np_peer_addr, peer_sa, len);
2185    memcpy(mc->mc_path.np_local_addr, local_sa, len);
2186    mc->mc_path.np_peer_ctx = peer_ctx;
2187    return 0;
2188}
2189
2190
2191static struct network_path *
2192mini_conn_ci_get_path (struct lsquic_conn *lconn, const struct sockaddr *sa)
2193{
2194    struct mini_conn *mc = (struct mini_conn *) lconn;
2195
2196    return &mc->mc_path;
2197}
2198
2199
2200static const struct conn_iface mini_conn_iface_standard = {
2201    .ci_abort_error          =  mini_conn_ci_abort_error,
2202    .ci_client_call_on_new   =  mini_conn_ci_client_call_on_new,
2203    .ci_destroy              =  mini_conn_ci_destroy,
2204    .ci_get_engine           =  mini_conn_ci_get_engine,
2205    .ci_get_path             =  mini_conn_ci_get_path,
2206    .ci_hsk_done             =  mini_conn_ci_hsk_done,
2207    .ci_internal_error       =  mini_conn_ci_internal_error,
2208    .ci_is_tickable          =  mini_conn_ci_is_tickable,
2209    .ci_next_packet_to_send  =  mini_conn_ci_next_packet_to_send,
2210    .ci_next_tick_time       =  mini_conn_ci_next_tick_time,
2211    .ci_packet_in            =  mini_conn_ci_packet_in,
2212    .ci_packet_not_sent      =  mini_conn_ci_packet_not_sent,
2213    .ci_packet_sent          =  mini_conn_ci_packet_sent,
2214    .ci_record_addrs         =  mini_conn_ci_record_addrs,
2215    .ci_tick                 =  mini_conn_ci_tick,
2216    .ci_tls_alert            =  mini_conn_ci_tls_alert,
2217};
2218
2219
2220static const struct conn_iface mini_conn_iface_standard_Q050 = {
2221    .ci_abort_error          =  mini_conn_ci_abort_error,
2222    .ci_client_call_on_new   =  mini_conn_ci_client_call_on_new,
2223    .ci_destroy              =  mini_conn_ci_destroy,
2224    .ci_get_engine           =  mini_conn_ci_get_engine,
2225    .ci_get_path             =  mini_conn_ci_get_path,
2226    .ci_hsk_done             =  mini_conn_ci_hsk_done,
2227    .ci_internal_error       =  mini_conn_ci_internal_error,
2228    .ci_is_tickable          =  mini_conn_ci_is_tickable,
2229    .ci_next_packet_to_send  =  mini_conn_ci_next_packet_to_send,
2230    .ci_next_tick_time       =  mini_conn_ci_next_tick_time,
2231    .ci_packet_in            =  mini_conn_ci_Q050_packet_in,
2232    .ci_packet_not_sent      =  mini_conn_ci_packet_not_sent,
2233    .ci_packet_sent          =  mini_conn_ci_packet_sent,
2234    .ci_record_addrs         =  mini_conn_ci_record_addrs,
2235    .ci_tick                 =  mini_conn_ci_tick,
2236    .ci_tls_alert            =  mini_conn_ci_tls_alert,
2237};
2238
2239
2240typedef char largest_recv_holds_at_least_16_seconds[
2241    ((1 << (sizeof(((struct mini_conn *) 0)->mc_largest_recv) * 8)) / 1000000
2242                                                                    >= 16) ? 1 : -1];
2243
2244typedef char max_lifespan_smaller_than_largest_recv[
2245    ((1 << (sizeof(((struct mini_conn *) 0)->mc_largest_recv) * 8)) >
2246                                           MAX_MINI_CONN_LIFESPAN_IN_USEC) ? 1 : -1];
2247