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