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