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