lsquic_mini_conn.c revision 49f1f4f6
1/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc.  See LICENSE. */
2/*
3 * lsquic_mini_conn.c -- Mini connection.
4 *
5 * Mini connection is only used in server mode -- this assumption is relied
6 * upon by the code in this file.
7 *
8 * The purpose of this connection is to process incoming handshakes using
9 * minimal amount of resources until we confirm that the client is sending
10 * valid data.  Here, we only process Stream 1 data; other packets are
11 * spooled, if necessary.  When mini connection is promoted to full
12 * connection, the state, including spooled incoming packets, is transferred
13 * to the full connection.
14 *
15 * Note that mini connections do not retransmit lost packets.  This is to
16 * minimize the effect of magnification attacks.  Clients like Chrome and
17 * Opera fall back to using TCP if QUIC handshake times out.
18 */
19
20
21#include <assert.h>
22#include <errno.h>
23#include <inttypes.h>
24#include <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    if (!packet_out)
892    {
893        LSQ_WARN("could not allocate packet: %s", strerror(errno));
894        return NULL;
895    }
896    packet_out->po_loss_chain = packet_out;
897    packet_out->po_packno = packno;
898    packet_out->po_flags |= PO_MINI;
899    if (mc->mc_flags & MC_HAVE_SHLO)
900    {
901        packet_out->po_flags |= PO_HELLO;
902        packet_out->po_header_type = HETY_0RTT;
903    }
904    if (mc->mc_conn.cn_version >= LSQVER_050)
905    {
906        if (nonce)
907            packet_out->po_header_type = HETY_0RTT;
908        else
909            packet_out->po_header_type = HETY_INITIAL;
910    }
911    lsquic_packet_out_set_pns(packet_out, PNS_APP);
912    TAILQ_INSERT_TAIL(&mc->mc_packets_out, packet_out, po_next);
913    LSQ_DEBUG("allocated packet #%"PRIu64", nonce: %d", packno, !!nonce);
914    MCHIST_APPEND(mc, MCHE_NEW_PACKET_OUT);
915    EV_LOG_PACKET_CREATED(LSQUIC_LOG_CONN_ID, packet_out);
916    return packet_out;
917}
918
919
920static struct lsquic_packet_out *
921to_packet_pre_Q050 (struct mini_conn *mc, struct mini_stream_ctx *ms_ctx,
922                    const unsigned char *nonce)
923{
924    struct lsquic_packet_out *packet_out;
925    size_t cur_off;
926    int len;
927
928    packet_out = allocate_packet_out(mc, nonce);
929    if (!packet_out)
930        return NULL;
931    cur_off = ms_ctx->off;
932    len = mc->mc_conn.cn_pf->pf_gen_stream_frame(
933            packet_out->po_data + packet_out->po_data_sz,
934            lsquic_packet_out_avail(packet_out),
935            1, mc->mc_write_off, mini_stream_fin(ms_ctx),
936            mini_stream_size(ms_ctx), mini_stream_read, ms_ctx);
937    if (len < 0)
938    {
939        LSQ_WARN("cannot generate STREAM frame (avail: %u)",
940                                    lsquic_packet_out_avail(packet_out));
941        return NULL;
942    }
943    mc->mc_write_off += ms_ctx->off - cur_off;
944    EV_LOG_GENERATED_STREAM_FRAME(LSQUIC_LOG_CONN_ID, mc->mc_conn.cn_pf,
945                        packet_out->po_data + packet_out->po_data_sz, len);
946    packet_out->po_data_sz += len;
947    packet_out->po_frame_types |= 1 << QUIC_FRAME_STREAM;
948    if (0 == lsquic_packet_out_avail(packet_out))
949        packet_out->po_flags |= PO_STREAM_END;
950
951    return packet_out;
952}
953
954
955static struct lsquic_packet_out *
956to_packet_Q050plus (struct mini_conn *mc, struct mini_stream_ctx *ms_ctx,
957                    const unsigned char *nonce)
958{
959    struct lsquic_packet_out *packet_out;
960    size_t cur_off;
961    int len;
962
963    if (nonce && !(mc->mc_flags & MC_WR_OFF_RESET))
964    {
965        mc->mc_write_off = 0;
966        mc->mc_flags |= MC_WR_OFF_RESET;
967    }
968
969    packet_out = allocate_packet_out(mc, nonce);
970    if (!packet_out)
971        return NULL;
972    cur_off = ms_ctx->off;
973    len = mc->mc_conn.cn_pf->pf_gen_crypto_frame(
974            packet_out->po_data + packet_out->po_data_sz,
975            lsquic_packet_out_avail(packet_out), 0, mc->mc_write_off, 0,
976            mini_stream_size(ms_ctx), mini_stream_read_for_crypto, ms_ctx);
977    if (len < 0)
978    {
979        LSQ_WARN("cannot generate CRYPTO frame (avail: %u)",
980                                    lsquic_packet_out_avail(packet_out));
981        return NULL;
982    }
983    mc->mc_write_off += ms_ctx->off - cur_off;
984    EV_LOG_GENERATED_CRYPTO_FRAME(LSQUIC_LOG_CONN_ID, mc->mc_conn.cn_pf,
985                        packet_out->po_data + packet_out->po_data_sz, len);
986    packet_out->po_data_sz += len;
987    packet_out->po_frame_types |= 1 << QUIC_FRAME_CRYPTO;
988
989    return packet_out;
990}
991
992
993static int
994packetize_response (struct mini_conn *mc, const unsigned char *buf,
995                    size_t bufsz, const unsigned char *nonce)
996{
997    struct mini_stream_ctx ms_ctx;
998    lsquic_packet_out_t *packet_out;
999    struct lsquic_packet_out * (*const to_packet) (struct mini_conn *,
1000                struct mini_stream_ctx *, const unsigned char *)
1001        = mc->mc_conn.cn_version < LSQVER_050
1002            ? to_packet_pre_Q050 : to_packet_Q050plus;
1003
1004    LSQ_DEBUG("Packetizing %zd bytes of handshake response", bufsz);
1005
1006    ms_ctx.buf   = buf;
1007    ms_ctx.bufsz = bufsz;
1008    ms_ctx.off   = 0;
1009
1010    do
1011    {
1012        packet_out = to_packet(mc, &ms_ctx, nonce);
1013        if (!packet_out)
1014            return -1;
1015    }
1016    while (mini_stream_has_data(&ms_ctx));
1017
1018    /* PAD the last packet with NULs.  ACK and STOP_WAITING go into a separate
1019     * packet.
1020     */
1021    if (lsquic_packet_out_avail(packet_out))
1022    {
1023        EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "generated PADDING frame %u "
1024                            "bytes long", lsquic_packet_out_avail(packet_out));
1025        memset(packet_out->po_data + packet_out->po_data_sz, 0,
1026                                        lsquic_packet_out_avail(packet_out));
1027        packet_out->po_data_sz += lsquic_packet_out_avail(packet_out);
1028        packet_out->po_frame_types |= 1 << QUIC_FRAME_PADDING;
1029    }
1030
1031    return 0;
1032}
1033
1034
1035static int
1036continue_handshake (struct mini_conn *mc)
1037{
1038    lsquic_packet_in_t *packet_in;
1039    unsigned n_hsk_chunks = 0, n_contig, n, bufsz, off;
1040    int s, rv;
1041    size_t out_len;
1042    enum handshake_error he;
1043    unsigned char *buf_in_16k, *buf_out;
1044    const unsigned char *buf_in;
1045    time_t t;
1046    stream_frame_t frame;
1047    struct hsk_chunk hsk_chunks[MINICONN_MAX_PACKETS], *hsk_chunk;
1048    unsigned char nonce_buf[32];
1049    int nonce_set = 0;
1050    int (*parse_frame)(const unsigned char *, size_t, struct stream_frame *)
1051        = mc->mc_conn.cn_version < LSQVER_050
1052            ? mc->mc_conn.cn_pf->pf_parse_stream_frame
1053            : mc->mc_conn.cn_pf->pf_parse_crypto_frame;
1054
1055    /* Get handshake stream data from each packet that contains a handshake
1056     * stream frame and place them into `hsk_chunks' array.
1057     */
1058    TAILQ_FOREACH(packet_in, &mc->mc_packets_in, pi_next)
1059    {
1060        assert(n_hsk_chunks < sizeof(hsk_chunks) / sizeof(hsk_chunks[0]));
1061        if (0 == (packet_in->pi_flags & PI_HSK_STREAM))
1062            continue;
1063        s = parse_frame(packet_in->pi_data + packet_in->pi_hsk_stream,
1064                packet_in->pi_data_sz - packet_in->pi_hsk_stream, &frame);
1065        if (-1 == s)
1066        {
1067            LSQ_WARN("cannot process hsk stream frame in packet %"PRIu64,
1068                packet_in->pi_packno);
1069            return -1;
1070        }
1071        hsk_chunk = &hsk_chunks[ n_hsk_chunks++ ];
1072        hsk_chunk->hsk_packet_in = packet_in;
1073        hsk_chunk->hsk_data      = frame.data_frame.df_data;
1074        hsk_chunk->hsk_off       = frame.data_frame.df_offset;
1075        hsk_chunk->hsk_sz        = frame.data_frame.df_size;
1076    }
1077    assert(n_hsk_chunks > 0);
1078
1079    if (n_hsk_chunks > 1)
1080    {
1081        /* Sort handshake stream data */
1082        qsort(hsk_chunks, n_hsk_chunks, sizeof(hsk_chunks[0]),
1083                                                        compare_hsk_chunks);
1084        /* Figure out how many packets contain handshake stream data in a
1085         * contiguous buffer and how large this data is.
1086         */
1087        for (n = 1, n_contig = 1, bufsz = hsk_chunks[0].hsk_sz;
1088                                                        n < n_hsk_chunks; ++n)
1089            if (hsk_chunks[n - 1].hsk_off + hsk_chunks[n - 1].hsk_sz ==
1090                                                        hsk_chunks[n].hsk_off)
1091            {
1092                ++n_contig;
1093                bufsz += hsk_chunks[n].hsk_sz;
1094            }
1095            else
1096                break;
1097    }
1098    else
1099    {
1100        n_contig = 1;
1101        bufsz = hsk_chunks[0].hsk_sz;
1102    }
1103
1104    /* Handshake handler expects to start reading at a particular offset.
1105     */
1106    if (hsk_chunks[0].hsk_off != mc->mc_read_off)
1107    {
1108        LSQ_DEBUG("smallest hsk offset is %u, need %hu",
1109                                hsk_chunks[0].hsk_off, mc->mc_read_off);
1110        MCHIST_APPEND(mc, MCHE_HELLO_HOLE);
1111        return 0;
1112    }
1113
1114    LSQ_DEBUG("# of contiguous stream frames: %u out of %u; offset: %u; "
1115        "total size: %u", n_contig, n_hsk_chunks, hsk_chunks[0].hsk_off, bufsz);
1116
1117    if (bufsz > 16 * 1024)
1118    {
1119        LSQ_INFO("too much contiguous handshake data (%u bytes); max: %u",
1120            bufsz, 16 * 1024);
1121        MCHIST_APPEND(mc, MCHE_HELLO_TOO_MUCH);
1122        return -1;
1123    }
1124
1125    /* From here on, since we need to clean up, we use `rv' and `goto end'
1126     * to handle error conditions and cleanup.
1127     */
1128    rv = -1;
1129    if (n_contig > 1)
1130    {
1131        buf_in = buf_in_16k = lsquic_mm_get_16k(&mc->mc_enpub->enp_mm);
1132        if (!buf_in)
1133        {
1134            LSQ_WARN("could not allocate in buffer: %s", strerror(errno));
1135            buf_out = NULL;
1136            goto end;
1137        }
1138        /* Create a single contiguous buffer to pass to lsquic_enc_session_handle_chlo */
1139        off = 0;
1140        for (n = 0; n < n_contig; ++n)
1141        {
1142            memcpy(buf_in_16k + off, hsk_chunks[n].hsk_data,
1143                                                    hsk_chunks[n].hsk_sz);
1144            off += hsk_chunks[n].hsk_sz;
1145        }
1146        assert(off == bufsz);
1147    }
1148    else
1149    {
1150        buf_in_16k = NULL;
1151        buf_in = hsk_chunks[0].hsk_data;
1152    }
1153
1154    buf_out = lsquic_mm_get_16k(&mc->mc_enpub->enp_mm);
1155    if (!buf_out)
1156    {
1157        LSQ_WARN("could not allocate out buffer: %s", strerror(errno));
1158        goto end;
1159    }
1160    out_len = 16 * 1024;
1161
1162    /* Allocate enc_session for the server if first time around: */
1163    if (!mc->mc_conn.cn_enc_session)
1164    {
1165        mc->mc_conn.cn_enc_session =
1166            mc->mc_conn.cn_esf.g->esf_create_server(&mc->mc_conn,
1167                                        mc->mc_conn.cn_cid, mc->mc_enpub);
1168        if (!mc->mc_conn.cn_enc_session)
1169        {
1170            LSQ_WARN("cannot create new enc session");
1171            goto end;
1172        }
1173        MCHIST_APPEND(mc, MCHE_NEW_ENC_SESS);
1174    }
1175
1176    t = time(NULL);
1177    he = mc->mc_conn.cn_esf.g->esf_handle_chlo(mc->mc_conn.cn_enc_session,
1178            mc->mc_conn.cn_version,
1179            buf_in, bufsz, t, NP_PEER_SA(&mc->mc_path),
1180            NP_LOCAL_SA(&mc->mc_path),
1181            buf_out, &out_len, nonce_buf, &nonce_set);
1182
1183    if (HS_SHLO == he)
1184        mc->mc_flags |=  MC_HAVE_SHLO;
1185    else
1186        mc->mc_flags &= ~MC_HAVE_SHLO;
1187
1188    MCHIST_APPEND(mc, he == DATA_NOT_ENOUGH ? MCHE_HANDLE_NOT_ENOUGH :
1189                      he == HS_SHLO         ? MCHE_HANDLE_SHLO :
1190                      he == HS_1RTT         ? MCHE_HANDLE_1RTT :
1191                      he == HS_SREJ         ? MCHE_HANDLE_SREJ :
1192                      he == HS_ERROR        ? MCHE_HANDLE_ERROR :
1193                                              MCHE_HAHDLE_UNKNOWN);
1194
1195    if ((HS_SHLO == he || HS_1RTT == he) && !mc->mc_rtt_stats.srtt)
1196    {
1197        uint32_t irtt;
1198        if (0 == mc->mc_conn.cn_esf.g->esf_get_peer_setting(
1199                        mc->mc_conn.cn_enc_session, QTAG_IRTT, &irtt))
1200        {
1201            /* Do not allow the client to specify unreasonable values:
1202             * smaller than 10ms or larger than 15s.  Per reference
1203             * implementation.
1204             */
1205            if (irtt > 15 * 1000 * 1000)
1206                irtt = 15 * 1000 * 1000;
1207            else if (irtt < 10 * 1000)
1208                irtt = 10 * 1000;
1209            lsquic_rtt_stats_update(&mc->mc_rtt_stats, irtt, 0);
1210            LSQ_DEBUG("Set initial SRTT to %"PRIu32" usec based on client-"
1211                "supplied IRTT value", irtt);
1212        }
1213    }
1214
1215    switch (he)
1216    {
1217    case DATA_NOT_ENOUGH:
1218        LSQ_DEBUG("lsquic_enc_session_handle_chlo needs more data");
1219        break;
1220    case HS_SHLO:
1221        mc->mc_conn.cn_flags |= LSCONN_HANDSHAKE_DONE;
1222        mc->mc_flags |= MC_PROMOTE;
1223        LSQ_DEBUG("lsquic_enc_session_handle_chlo returned %d, promote", he);
1224        /* Fall through */
1225    case HS_1RTT:
1226        assert(out_len > 0);
1227        if (mc->mc_conn.cn_version < LSQVER_046
1228                    && !mc->mc_conn.cn_esf.g->esf_get_peer_option(
1229                                    mc->mc_conn.cn_enc_session, QTAG_NSTP))
1230            mc->mc_flags |= MC_STOP_WAIT_ON;
1231        if (0 != packetize_response(mc, buf_out, out_len,
1232                                            nonce_set ? nonce_buf : NULL))
1233            goto end;
1234        mc->mc_read_off += bufsz;
1235        for (n = 0; n < n_contig; ++n)
1236            hsk_chunks[n].hsk_packet_in->pi_flags &= ~PI_HSK_STREAM;
1237        LSQ_DEBUG("read offset is now %hu", mc->mc_read_off);
1238        break;
1239    default:
1240        LSQ_WARN("unexpected return value from lsquic_enc_session_handle_chlo: %u", he);
1241        /* fallthru */
1242    case HS_ERROR:
1243#if !LSQUIC_KEEP_ENC_SESS_HISTORY
1244        mc->mc_conn.cn_esf.g->esf_destroy(mc->mc_conn.cn_enc_session);
1245        mc->mc_conn.cn_enc_session = NULL;
1246#endif
1247        mc->mc_flags |= MC_HSK_ERR;
1248        LSQ_INFO("lsquic_enc_session_handle_chlo returned an error (%d)", he);
1249        goto end;
1250    }
1251
1252    rv = 0;
1253
1254  end:
1255    mc->mc_flags &= ~MC_HAVE_SHLO;
1256    if (buf_in_16k)
1257        lsquic_mm_put_16k(&mc->mc_enpub->enp_mm, buf_in_16k);
1258    if (buf_out)
1259        lsquic_mm_put_16k(&mc->mc_enpub->enp_mm, buf_out);
1260    return rv;
1261}
1262
1263
1264struct mini_rechist
1265{
1266    const struct mini_conn     *mc;
1267    mconn_packno_set_t          cur_set;
1268    int                         cur_idx;
1269    struct lsquic_packno_range  range;   /* We return a pointer to this */
1270};
1271
1272
1273static void
1274mini_rechist_init (struct mini_rechist *rechist, const struct mini_conn *mc)
1275{
1276    rechist->mc      = mc;
1277    rechist->cur_set = 0;
1278    rechist->cur_idx = 0;
1279}
1280
1281
1282static lsquic_time_t
1283mini_rechist_largest_recv (void *rechist_ctx)
1284{
1285    struct mini_rechist *rechist = rechist_ctx;
1286    const struct mini_conn *mc = rechist->mc;
1287    lsquic_time_t delta =  mc->mc_largest_recv[0]
1288                        + (mc->mc_largest_recv[1] << 8)
1289                        + (mc->mc_largest_recv[2] << 16);
1290    LSQ_DEBUG("%s: largest received: %"PRIu64" usec since creation",
1291                                                            __func__, delta);
1292    return mc->mc_created + delta;
1293}
1294
1295
1296static const struct lsquic_packno_range *
1297mini_rechist_next (void *rechist_ctx)
1298{
1299    struct mini_rechist *rechist = rechist_ctx;
1300    const struct mini_conn *mc = rechist->mc;
1301    mconn_packno_set_t packnos;
1302    int i;
1303
1304    packnos = rechist->cur_set;
1305    if (0 == packnos)
1306        return NULL;
1307
1308    /* There may be a faster way to do this, but for now, we just want
1309     * correctness.
1310     */
1311    for (i = rechist->cur_idx; i >= 0; --i)
1312        if (packnos & (1ULL << i))
1313        {
1314            rechist->range.low  = i + 1;
1315            rechist->range.high = i + 1;
1316            break;
1317        }
1318    assert(i >= 0); /* We must have hit at least one bit */
1319    --i;
1320    for ( ; i >= 0 && (packnos & (1ULL << i)); --i)
1321        rechist->range.low = i + 1;
1322    if (i >= 0)
1323    {
1324        rechist->cur_set = packnos & ((1ULL << i) - 1);
1325        rechist->cur_idx = i;
1326    }
1327    else
1328        rechist->cur_set = 0;
1329    LSQ_DEBUG("%s: return [%"PRIu64", %"PRIu64"]", __func__,
1330                                rechist->range.low, rechist->range.high);
1331    return &rechist->range;
1332}
1333
1334
1335static const struct lsquic_packno_range *
1336mini_rechist_first (void *rechist_ctx)
1337{
1338    struct mini_rechist *rechist = rechist_ctx;
1339    rechist->cur_set = rechist->mc->mc_received_packnos;
1340    rechist->cur_idx = highest_bit_set(rechist->cur_set);
1341    return mini_rechist_next(rechist_ctx);
1342}
1343
1344
1345static lsquic_packno_t
1346least_unacked (const struct mini_conn *mc)
1347{
1348    mconn_packno_set_t unacked;
1349    lsquic_packno_t packno;
1350    unacked = mc->mc_sent_packnos & ~mc->mc_acked_packnos;
1351    if (unacked)
1352        packno = lowest_bit_set(unacked) + 1;
1353    else
1354        packno = highest_bit_set(mc->mc_sent_packnos) + 2;
1355    LSQ_DEBUG("%s: least unacked: %"PRIu64, __func__, packno);
1356    return packno;
1357}
1358
1359
1360static int
1361generate_ack_and_stop_waiting (struct mini_conn *mc, lsquic_time_t now)
1362{
1363    lsquic_packet_out_t *packet_out;
1364    struct mini_rechist rechist;
1365    int len, not_used_has_missing;
1366    lsquic_packno_t lunack;
1367
1368    /* Chrome's quic_server places ACK and STOP_WAITING frames into a separate
1369     * packet.
1370     */
1371    packet_out = allocate_packet_out(mc, NULL);
1372    if (!packet_out)
1373        return -1;
1374
1375    /* Generate ACK frame */
1376    mini_rechist_init(&rechist, mc);
1377    len = mc->mc_conn.cn_pf->pf_gen_ack_frame(packet_out->po_data + packet_out->po_data_sz,
1378                lsquic_packet_out_avail(packet_out), mini_rechist_first,
1379                mini_rechist_next, mini_rechist_largest_recv, &rechist,
1380                now, &not_used_has_missing, &packet_out->po_ack2ed, NULL);
1381    if (len < 0)
1382    {
1383        LSQ_WARN("could not generate ACK frame");
1384        return -1;
1385    }
1386    EV_LOG_GENERATED_ACK_FRAME(LSQUIC_LOG_CONN_ID, mc->mc_conn.cn_pf,
1387                        packet_out->po_data + packet_out->po_data_sz, len);
1388    packet_out->po_frame_types |= 1 << QUIC_FRAME_ACK;
1389    packet_out->po_data_sz += len;
1390    packet_out->po_regen_sz += len;
1391    LSQ_DEBUG("wrote ACK frame of size %d", len);
1392
1393    /* Generate STOP_WAITING frame */
1394    if ((mc->mc_flags & MC_STOP_WAIT_ON) && mc->mc_sent_packnos)
1395    {
1396        lunack = least_unacked(mc);
1397        len = mc->mc_conn.cn_pf->pf_gen_stop_waiting_frame(packet_out->po_data +
1398                                                packet_out->po_data_sz,
1399                lsquic_packet_out_avail(packet_out), packet_out->po_packno,
1400                lsquic_packet_out_packno_bits(packet_out), lunack);
1401        if (len < 0)
1402        {
1403            LSQ_WARN("could not generate STOP_WAITING frame");
1404            return -1;
1405        }
1406        packet_out->po_data_sz += len;
1407        packet_out->po_regen_sz += len;
1408        packet_out->po_frame_types |= 1 << QUIC_FRAME_STOP_WAITING;
1409        LSQ_DEBUG("wrote STOP_WAITING frame of size %d", len);
1410        EV_LOG_GENERATED_STOP_WAITING_FRAME(LSQUIC_LOG_CONN_ID, lunack);
1411    }
1412    else if (mc->mc_flags & MC_STOP_WAIT_ON)
1413        LSQ_DEBUG("nothing sent: no need to generate STOP_WAITING frame");
1414
1415    mc->mc_flags |= MC_UNSENT_ACK;
1416    return 0;
1417}
1418
1419
1420static int
1421calc_retx_timeout (const struct mini_conn *mc)
1422{
1423    lsquic_time_t to;
1424    to = lsquic_rtt_stats_get_srtt(&mc->mc_rtt_stats);
1425    if (to)
1426    {
1427        to += to / 2;
1428        if (to < 10000)
1429            to = 10000;
1430    }
1431    else
1432        to = 300000;
1433    return to << mc->mc_hsk_count;
1434}
1435
1436
1437static void
1438return_enc_data (struct mini_conn *mc, struct lsquic_packet_out *packet_out)
1439{
1440    mc->mc_enpub->enp_pmi->pmi_return(mc->mc_enpub->enp_pmi_ctx,
1441        mc->mc_path.np_peer_ctx, packet_out->po_enc_data,
1442        lsquic_packet_out_ipv6(packet_out));
1443    packet_out->po_flags &= ~PO_ENCRYPTED;
1444    packet_out->po_enc_data = NULL;
1445}
1446
1447
1448static int
1449repackage_packet (struct mini_conn *mc, lsquic_packet_out_t *packet_out)
1450{
1451    const lsquic_packno_t oldno = packet_out->po_packno;
1452    const lsquic_packno_t packno = next_packno(mc);
1453    if (packno > MINICONN_MAX_PACKETS)
1454        return -1;
1455
1456    LSQ_DEBUG("Packet %"PRIu64" repackaged for resending as packet %"PRIu64,
1457                                                        oldno, packno);
1458    EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "packet %"PRIu64" repackaged for "
1459        "resending as packet %"PRIu64, oldno, packno);
1460    packet_out->po_packno = packno;
1461    packet_out->po_flags &= ~PO_SENT;
1462    if (packet_out->po_flags & PO_ENCRYPTED)
1463        return_enc_data(mc, packet_out);
1464    TAILQ_INSERT_TAIL(&mc->mc_packets_out, packet_out, po_next);
1465    return 0;
1466}
1467
1468
1469static int
1470handle_losses_and_have_unsent (struct mini_conn *mc, lsquic_time_t now)
1471{
1472    TAILQ_HEAD(, lsquic_packet_out) lost_packets =
1473                                    TAILQ_HEAD_INITIALIZER(lost_packets);
1474    lsquic_packet_out_t *packet_out, *next;
1475    lsquic_time_t retx_to = 0;
1476    unsigned n_to_send = 0;
1477
1478    for (packet_out = TAILQ_FIRST(&mc->mc_packets_out); packet_out;
1479                                                        packet_out = next)
1480    {
1481        next = TAILQ_NEXT(packet_out, po_next);
1482        if (packet_out->po_flags & PO_SENT)
1483        {
1484            if (0 == retx_to)
1485                retx_to = calc_retx_timeout(mc);
1486            if (packet_out->po_sent + retx_to < now)
1487            {
1488                LSQ_DEBUG("packet %"PRIu64" has been lost (rto: %"PRIu64")",
1489                                                packet_out->po_packno, retx_to);
1490                TAILQ_REMOVE(&mc->mc_packets_out, packet_out, po_next);
1491                TAILQ_INSERT_TAIL(&lost_packets, packet_out, po_next);
1492                mc->mc_lost_packnos |= MCONN_PACKET_MASK(packet_out->po_packno);
1493                MCHIST_APPEND(mc, MCHE_PACKET_LOST);
1494            }
1495        }
1496        else
1497            ++n_to_send;
1498    }
1499
1500    mc->mc_hsk_count += !TAILQ_EMPTY(&lost_packets);
1501
1502    while ((packet_out = TAILQ_FIRST(&lost_packets)))
1503    {
1504        TAILQ_REMOVE(&lost_packets, packet_out, po_next);
1505        if ((packet_out->po_frame_types & GQUIC_FRAME_RETRANSMITTABLE_MASK)
1506                                    && 0 == repackage_packet(mc, packet_out))
1507            ++n_to_send;
1508        else
1509            mini_destroy_packet(mc, packet_out);
1510    }
1511
1512    return n_to_send > 0;
1513}
1514
1515
1516static int
1517warning_is_warranted (const struct mini_conn *mc)
1518{
1519    return (mc->mc_flags & (MC_HSK_ERR|MC_OO_PACKNOS))
1520        || 0x1C /* QUIC_HANDSHAKE_FAILED                    */ == mc->mc_error_code
1521        || 0x1D /* QUIC_CRYPTO_TAGS_OUT_OF_ORDER            */ == mc->mc_error_code
1522        || 0x1E /* QUIC_CRYPTO_TOO_MANY_ENTRIES             */ == mc->mc_error_code
1523        || 0x1F /* QUIC_CRYPTO_INVALID_VALUE_LENGTH         */ == mc->mc_error_code
1524        || 0x21 /* QUIC_INVALID_CRYPTO_MESSAGE_TYPE         */ == mc->mc_error_code
1525        || 0x22 /* QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER    */ == mc->mc_error_code
1526        || 0x23 /* QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND  */ == mc->mc_error_code
1527        || 0x24 /* QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP */ == mc->mc_error_code
1528        || 0x29 /* QUIC_CRYPTO_TOO_MANY_REJECTS             */ == mc->mc_error_code
1529        || 0x2A /* QUIC_PROOF_INVALID                       */ == mc->mc_error_code
1530        || 0x2B /* QUIC_CRYPTO_DUPLICATE_TAG                */ == mc->mc_error_code
1531        || 0x2C /* QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT   */ == mc->mc_error_code
1532        || 0x2D /* QUIC_CRYPTO_SERVER_CONFIG_EXPIRED        */ == mc->mc_error_code
1533        || 0x35 /* QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED   */ == mc->mc_error_code
1534        ;
1535}
1536
1537
1538#if LSQUIC_KEEP_ENC_SESS_HISTORY
1539static void
1540maybe_log_enc_sess_history (const struct mini_conn *mc)
1541{
1542    char eshist[ESHIST_STR_SIZE];
1543    enum lsq_log_level log_level;
1544    const char *ua;
1545
1546    if (warning_is_warranted(mc))
1547        log_level = LSQ_LOG_WARN;
1548    else
1549        log_level = LSQ_LOG_DEBUG;
1550
1551    if (mc->mc_conn.cn_enc_session)
1552    {
1553        mc->mc_conn.cn_esf.g->esf_get_hist(mc->mc_conn.cn_enc_session, eshist);
1554        ua = mc->mc_conn.cn_esf.g->esf_get_ua(mc->mc_conn.cn_enc_session);
1555        LSQ_LOG1(log_level, "enc hist %s; User-Agent: %s", eshist,
1556                                                        ua ? ua : "<not set>");
1557    }
1558    else
1559        LSQ_LOG1(log_level, "enc session gone: no history to log");
1560}
1561
1562
1563#endif
1564
1565
1566
1567
1568static int
1569have_packets_to_send (struct mini_conn *mc, lsquic_time_t now)
1570{
1571    return handle_losses_and_have_unsent(mc, now);
1572}
1573
1574
1575static enum tick_st
1576mini_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now)
1577{
1578    struct mini_conn *mc = (struct mini_conn *) lconn;
1579    enum tick_st tick;
1580
1581    ++mc->mc_n_ticks;
1582
1583    if (mc->mc_created + mc->mc_enpub->enp_settings.es_handshake_to < now)
1584    {
1585        LSQ_DEBUG("connection expired: closing");
1586        tick = TICK_CLOSE;
1587        goto end;
1588    }
1589
1590    if (mc->mc_flags & MC_ERROR)
1591    {
1592        tick = TICK_CLOSE;
1593        goto end;
1594    }
1595
1596
1597    if ((mc->mc_flags & (MC_UNSENT_ACK|MC_GEN_ACK)) == MC_GEN_ACK)
1598    {
1599        if (0 != generate_ack_and_stop_waiting(mc, now))
1600        {
1601            mc->mc_flags |= MC_ERROR;
1602            tick = TICK_CLOSE;
1603            goto end;
1604        }
1605        else
1606            mc->mc_flags &= ~MC_GEN_ACK;
1607    }
1608
1609    if (have_packets_to_send(mc, now))
1610        tick = TICK_SEND;
1611    else
1612        tick = TICK_QUIET;
1613
1614    if (mc->mc_flags & MC_PROMOTE)
1615        tick |= TICK_PROMOTE;
1616
1617  end:
1618#if LSQUIC_KEEP_ENC_SESS_HISTORY
1619    if (tick & (TICK_CLOSE|TICK_PROMOTE))
1620        maybe_log_enc_sess_history(mc);
1621#endif
1622
1623    return tick;
1624}
1625
1626
1627static void
1628process_packet (struct mini_conn *mc, struct lsquic_packet_in *packet_in)
1629{
1630    switch (process_regular_packet(mc, packet_in))
1631    {
1632    case PRP_KEEP:
1633        assert(packet_in->pi_flags & PI_OWN_DATA);
1634        lsquic_packet_in_upref(packet_in);
1635        TAILQ_INSERT_TAIL(&mc->mc_packets_in, packet_in, pi_next);
1636        if (mc->mc_flags & MC_HAVE_NEW_HSK)
1637        {
1638            if (0 != continue_handshake(mc))
1639                mc->mc_flags |= MC_ERROR;
1640            mc->mc_flags &= ~MC_HAVE_NEW_HSK;
1641        }
1642        break;
1643    case PRP_DEFER:
1644        assert(packet_in->pi_flags & PI_OWN_DATA);
1645        lsquic_packet_in_upref(packet_in);
1646        if (mc->mc_n_deferred < MINI_CONN_MAX_DEFERRED)
1647        {
1648            TAILQ_INSERT_TAIL(&mc->mc_deferred, packet_in, pi_next);
1649            ++mc->mc_n_deferred;
1650        }
1651        else
1652            LSQ_DEBUG("won't defer more than %u packets: drop",
1653                                                MINI_CONN_MAX_DEFERRED);
1654        break;
1655    case PRP_ERROR:
1656        mc->mc_flags |= MC_ERROR;
1657        break;
1658    case PRP_DROP:
1659        break;
1660    }
1661}
1662
1663
1664/* Keep deferred list ordered by packet number, so that we can process all
1665 * of them in a single pass.
1666 */
1667static void
1668insert_into_deferred (struct mini_conn *mc, lsquic_packet_in_t *new_packet)
1669{
1670    lsquic_packet_in_t *packet_in;
1671
1672    lsquic_packet_in_upref(new_packet);
1673
1674    TAILQ_FOREACH(packet_in, &mc->mc_deferred, pi_next)
1675    if (packet_in->pi_packno > new_packet->pi_packno)
1676        break;
1677
1678    if (packet_in)
1679        TAILQ_INSERT_BEFORE(packet_in, new_packet, pi_next);
1680    else
1681        TAILQ_INSERT_TAIL(&mc->mc_deferred, new_packet, pi_next);
1682    ++mc->mc_n_deferred;
1683}
1684
1685
1686static void
1687process_deferred_packets (struct mini_conn *mc)
1688{
1689    lsquic_packet_in_t *last, *packet_in;
1690    int reached_last;
1691
1692    last = TAILQ_LAST(&mc->mc_deferred, head_packet_in);
1693    do
1694    {
1695        packet_in = TAILQ_FIRST(&mc->mc_deferred);
1696        TAILQ_REMOVE(&mc->mc_deferred, packet_in, pi_next);
1697        --mc->mc_n_deferred;
1698        process_packet(mc, packet_in);
1699        reached_last = packet_in == last;
1700        lsquic_packet_in_put(&mc->mc_enpub->enp_mm, packet_in);
1701    }
1702    while (!reached_last);
1703}
1704
1705
1706#if LSQUIC_RECORD_INORD_HIST
1707/* FIXME This does not work for Q050, where 0 is a valid packet number. */
1708/* Packet number is encoded as a sequence of 1-bits and stored in mc_inord_hist
1709 * separated by 0 bits.  For example, sequence of packet numbers 3, 2, 1 would
1710 * be encoded as (starting with LSB) 1110110100000000...  This is not the most
1711 * space-efficient scheme, but it is simple to implement and should suffice for
1712 * our purposes.
1713 */
1714static void
1715record_inord_packno (struct mini_conn *mc, lsquic_packno_t packno)
1716{
1717    int n_avail;
1718    lsquic_packno_t mask;
1719
1720    for ( ; mc->mc_inord_idx < sizeof(mc->mc_inord_hist) /
1721                            sizeof(mc->mc_inord_hist[0]); ++mc->mc_inord_idx)
1722    {
1723        if (mc->mc_inord_hist[ mc->mc_inord_idx ])
1724            n_avail = __builtin_clzll(mc->mc_inord_hist[ mc->mc_inord_idx ]) - 1;
1725        else
1726            n_avail = sizeof(mc->mc_inord_hist[ mc->mc_inord_idx ]) * 8;
1727        if (n_avail >= (int) packno)
1728        {
1729            mask = (1ULL << (int) packno) - 1;
1730            mask <<= sizeof(mc->mc_inord_hist[ mc->mc_inord_idx ]) * 8 - n_avail;
1731            mc->mc_inord_hist[ mc->mc_inord_idx ] |= mask;
1732            return;                                             /* Success */
1733        }
1734    }
1735}
1736
1737
1738#if __GNUC__
1739#   define ctz __builtin_ctzll
1740#else
1741static unsigned
1742ctz (unsigned long long x)
1743{
1744    unsigned n = 0;
1745    if (0 == (x & ((1ULL << 32) - 1))) { n += 32; x >>= 32; }
1746    if (0 == (x & ((1ULL << 16) - 1))) { n += 16; x >>= 16; }
1747    if (0 == (x & ((1ULL <<  8) - 1))) { n +=  8; x >>=  8; }
1748    if (0 == (x & ((1ULL <<  4) - 1))) { n +=  4; x >>=  4; }
1749    if (0 == (x & ((1ULL <<  2) - 1))) { n +=  2; x >>=  2; }
1750    if (0 == (x & ((1ULL <<  1) - 1))) { n +=  1; x >>=  1; }
1751    return n;
1752}
1753
1754
1755#endif
1756
1757
1758static void
1759inord_to_str (const struct mini_conn *mc, char *buf, size_t bufsz)
1760{
1761    unsigned long long hist;
1762    size_t off;
1763    ssize_t nw;
1764    unsigned n;
1765    int n_trail;
1766
1767    off = 0;
1768    for (n = 0; n < sizeof(mc->mc_inord_hist) /
1769                                        sizeof(mc->mc_inord_hist[0]); ++n)
1770    {
1771        hist = mc->mc_inord_hist[n];
1772        while (hist)
1773        {
1774            n_trail = ctz(~hist);
1775            nw = snprintf(buf + off, bufsz - off,
1776                /* No spaces are included on purpose: this makes it a single
1777                 * field and thus easy to process log using standard command-
1778                 * line tools, such as sork -k, for example.
1779                 */
1780                                        (off ? ",%d" : "%d"), n_trail);
1781            if ((size_t) nw > bufsz - off || nw < 0)
1782                break;
1783            off += nw;
1784            hist >>= n_trail + 1;
1785        }
1786    }
1787    buf[ bufsz - 1 ] = '\0';    /* CYA */
1788}
1789
1790
1791#endif
1792
1793
1794static void
1795mini_conn_ci_packet_in (struct lsquic_conn *lconn,
1796                        struct lsquic_packet_in *packet_in)
1797{
1798    struct mini_conn *mc = (struct mini_conn *) lconn;
1799
1800#if LSQUIC_RECORD_INORD_HIST
1801    record_inord_packno(mc, packet_in->pi_packno);
1802#endif
1803#if 0
1804    /* A convenient way to test lsquic_is_valid_hs_packet(): */
1805    if (!(mc->mc_sent_packnos))
1806        assert(lsquic_is_valid_hs_packet(NULL, packet_in->pi_data,
1807                                                    packet_in->pi_data_sz));
1808#endif
1809
1810    if (mc->mc_flags & MC_ERROR)
1811    {
1812        LSQ_DEBUG("error state: ignore packet %"PRIu64, packet_in->pi_packno);
1813        return;
1814    }
1815
1816    if (lsquic_packet_in_is_gquic_prst(packet_in))
1817    {
1818        LSQ_INFO("received reset packet");
1819        mc->mc_flags |= MC_ERROR;
1820        MCHIST_APPEND(mc, MCHE_PRST_IN);
1821        return;
1822    }
1823
1824    LSQ_DEBUG("packet in: %"PRIu64, packet_in->pi_packno);
1825    EV_LOG_PACKET_IN(LSQUIC_LOG_CONN_ID, packet_in);
1826
1827
1828    /* Check receive history */
1829    if (0 == packet_in->pi_packno)
1830    {
1831        LSQ_DEBUG("invalid packet number 0");
1832        mc->mc_flags |= MC_ERROR;
1833        MCHIST_APPEND(mc, MCHE_PACKET0_IN);
1834        return;
1835    }
1836    if (packet_in->pi_packno > MINICONN_MAX_PACKETS)
1837    {
1838        LSQ_DEBUG("packet number %"PRIu64" is too large (max %zd)",
1839                            packet_in->pi_packno, MINICONN_MAX_PACKETS);
1840        mc->mc_flags |= MC_ERROR;
1841        MCHIST_APPEND(mc, MCHE_PACKET2LARGE_IN);
1842        return;
1843    }
1844    if (MCONN_PACKET_MASK(packet_in->pi_packno) & mc->mc_received_packnos)
1845    {
1846        LSQ_DEBUG("duplicate packet %"PRIu64", ignoring", packet_in->pi_packno);
1847        MCHIST_APPEND(mc, MCHE_PACKET_DUP_IN);
1848        return;
1849    }
1850
1851    if (TAILQ_EMPTY(&mc->mc_deferred))
1852        process_packet(mc, packet_in);
1853    else if (mc->mc_n_deferred < MINI_CONN_MAX_DEFERRED)
1854    {
1855        insert_into_deferred(mc, packet_in);
1856        process_deferred_packets(mc);
1857    }
1858    else
1859        LSQ_DEBUG("won't defer more than %u packets: drop",
1860                                                MINI_CONN_MAX_DEFERRED);
1861}
1862
1863
1864/* Q050 is different is that packet numbers are not known until after the
1865 * packet is decrypted, so we have to follow different logic here.
1866 */
1867static void
1868mini_conn_ci_Q050_packet_in (struct lsquic_conn *lconn,
1869                        struct lsquic_packet_in *packet_in)
1870{
1871    struct mini_conn *mc = (struct mini_conn *) lconn;
1872    enum proc_rp prp;
1873
1874    if (mc->mc_flags & MC_ERROR)
1875    {
1876        LSQ_DEBUG("error state: ignore packet");
1877        return;
1878    }
1879
1880
1881    if (!mc->mc_conn.cn_enc_session)
1882    {
1883        mc->mc_conn.cn_enc_session =
1884            mc->mc_conn.cn_esf.g->esf_create_server(&mc->mc_conn,
1885                                        mc->mc_conn.cn_cid, mc->mc_enpub);
1886        if (!mc->mc_conn.cn_enc_session)
1887        {
1888            LSQ_WARN("cannot create new enc session");
1889            mc->mc_flags |= MC_ERROR;
1890            return;
1891        }
1892        MCHIST_APPEND(mc, MCHE_NEW_ENC_SESS);
1893    }
1894
1895    assert(!(packet_in->pi_flags & PI_DECRYPTED));
1896    prp = conn_decrypt_packet_or(mc, packet_in);
1897    switch (prp)
1898    {
1899    case PRP_KEEP:
1900        break;
1901    case PRP_DROP:
1902        return;
1903    case PRP_ERROR:
1904        mc->mc_flags |= MC_ERROR;
1905        return;
1906    default:
1907        if (mc->mc_n_deferred >= MINI_CONN_MAX_DEFERRED)
1908        {
1909            LSQ_DEBUG("won't defer more than %u packets: drop",
1910                                                MINI_CONN_MAX_DEFERRED);
1911            return;
1912        }
1913        assert(prp == PRP_DEFER);
1914        assert(packet_in->pi_flags & PI_OWN_DATA);
1915        lsquic_packet_in_upref(packet_in);
1916        TAILQ_INSERT_TAIL(&mc->mc_deferred, packet_in, pi_next);
1917        ++mc->mc_n_deferred;
1918        return;
1919    }
1920
1921    assert(prp == PRP_KEEP);
1922    process_packet(mc, packet_in);
1923}
1924
1925
1926static struct lsquic_packet_out *
1927mini_conn_ci_next_packet_to_send (struct lsquic_conn *lconn, size_t size)
1928{
1929    struct mini_conn *mc = (struct mini_conn *) lconn;
1930    lsquic_packet_out_t *packet_out;
1931
1932    assert(0 == size);
1933    TAILQ_FOREACH(packet_out, &mc->mc_packets_out, po_next)
1934    {
1935        if (packet_out->po_flags & PO_SENT)
1936            continue;
1937        packet_out->po_flags |= PO_SENT;
1938        LSQ_DEBUG("packet_to_send: %"PRIu64, packet_out->po_packno);
1939        return packet_out;
1940    }
1941    return NULL;
1942}
1943
1944
1945static void
1946mini_conn_ci_packet_sent (struct lsquic_conn *lconn,
1947                          struct lsquic_packet_out *packet_out)
1948{
1949    struct mini_conn *mc = (struct mini_conn *) lconn;
1950    mc->mc_sent_packnos |= MCONN_PACKET_MASK(packet_out->po_packno);
1951    if (packet_out->po_frame_types & (1 << QUIC_FRAME_ACK))
1952    {
1953        assert(mc->mc_flags & MC_UNSENT_ACK);
1954        mc->mc_flags &= ~MC_UNSENT_ACK;
1955    }
1956    LSQ_DEBUG("%s: packet %"PRIu64" sent", __func__, packet_out->po_packno);
1957    MCHIST_APPEND(mc, MCHE_PACKET_SENT);
1958}
1959
1960
1961static void
1962mini_conn_ci_packet_not_sent (struct lsquic_conn *lconn,
1963                              struct lsquic_packet_out *packet_out)
1964{
1965    struct mini_conn *mc = (struct mini_conn *) lconn;
1966    packet_out->po_flags &= ~PO_SENT;
1967    LSQ_DEBUG("%s: packet %"PRIu64" not sent", __func__, packet_out->po_packno);
1968    MCHIST_APPEND(mc, MCHE_PACKET_DELAYED);
1969}
1970
1971
1972static void
1973mini_conn_ci_destroy (struct lsquic_conn *lconn)
1974{
1975    assert(!(lconn->cn_flags & LSCONN_HASHED));
1976    struct mini_conn *mc = (struct mini_conn *) lconn;
1977    lsquic_packet_in_t *packet_in;
1978    mconn_packno_set_t still_deferred = 0, in_flight;
1979    enum lsq_log_level log_level;
1980#if LSQUIC_RECORD_INORD_HIST
1981    char inord_str[0x100];
1982#endif
1983    while ((packet_in = TAILQ_FIRST(&mc->mc_packets_in)))
1984    {
1985        TAILQ_REMOVE(&mc->mc_packets_in, packet_in, pi_next);
1986        lsquic_packet_in_put(&mc->mc_enpub->enp_mm, packet_in);
1987    }
1988    while ((packet_in = TAILQ_FIRST(&mc->mc_deferred)))
1989    {
1990        TAILQ_REMOVE(&mc->mc_deferred, packet_in, pi_next);
1991        --mc->mc_n_deferred;
1992        still_deferred |= MCONN_PACKET_MASK(packet_in->pi_packno);
1993        lsquic_packet_in_put(&mc->mc_enpub->enp_mm, packet_in);
1994    }
1995    if (TAILQ_EMPTY(&mc->mc_packets_out))
1996        in_flight = ~0ull;  /* Indicates that packets were dropped before */
1997    else
1998        in_flight = drop_packets_out(mc);
1999    if (mc->mc_conn.cn_enc_session)
2000        mc->mc_conn.cn_esf.g->esf_destroy(mc->mc_conn.cn_enc_session);
2001    log_level = warning_is_warranted(mc) ? LSQ_LOG_WARN : LSQ_LOG_DEBUG;
2002#if LSQUIC_RECORD_INORD_HIST
2003    if (LSQ_LOG_ENABLED(log_level))
2004        inord_to_str(mc, inord_str, sizeof(inord_str));
2005#endif
2006#if LSQUIC_KEEP_MINICONN_HISTORY
2007    const unsigned hist_idx = MCHIST_MASK & mc->mc_hist_idx;
2008    if (MCHE_EMPTY == mc->mc_hist_buf[ hist_idx ])
2009        LSQ_LOG(log_level, "destroyed.  Diagnostics: conn flags: 0x%X, "
2010            "mc flags: 0x%X, "
2011#if LSQUIC_RECORD_INORD_HIST
2012            "incoming-history (trunc: %d) %s, "
2013#endif
2014            "received: %"PRIX64", sent: %"PRIX64", lost: %"PRIX64", "
2015            "deferred: %"PRIX64", still-deferred: %"PRIX64", "
2016            "dropped: %"PRIX64", in-flight: %"PRIX64", acked: %"PRIX64", "
2017            "error_code: 0x%X, ticks: %hu, pack size: %hu, "
2018            "lifetime: %"PRIu64" usec, version: %s, "
2019            "mc hist: %.*s", mc->mc_conn.cn_flags,
2020            mc->mc_flags,
2021#if LSQUIC_RECORD_INORD_HIST
2022            mc->mc_inord_idx >= sizeof(mc->mc_inord_hist) /
2023                                    sizeof(mc->mc_inord_hist[0]), inord_str,
2024#endif
2025            mc->mc_received_packnos, mc->mc_sent_packnos, mc->mc_lost_packnos,
2026            mc->mc_deferred_packnos, still_deferred,
2027            mc->mc_dropped_packnos, in_flight, mc->mc_acked_packnos,
2028            mc->mc_error_code, mc->mc_n_ticks, mc->mc_path.np_pack_size,
2029            lsquic_time_now() - mc->mc_created,
2030            lsquic_ver2str[mc->mc_conn.cn_version],
2031            (int) hist_idx, mc->mc_hist_buf);
2032    else
2033        LSQ_LOG(log_level, "destroyed.  Diagnostics: conn flags: 0x%X, "
2034            "mc flags: 0x%X, "
2035#if LSQUIC_RECORD_INORD_HIST
2036            "incoming-history (trunc: %d) %s, "
2037#endif
2038            "received: %"PRIX64", sent: %"PRIX64", lost: %"PRIX64", "
2039            "deferred: %"PRIX64", still-deferred: %"PRIX64", "
2040            "dropped: %"PRIX64", in-flight: %"PRIX64", acked: %"PRIX64", "
2041            "error_code: 0x%X, ticks: %hu, pack size: %hu, "
2042            "lifetime: %"PRIu64" usec, version: %s, "
2043            "mc hist: %.*s%.*s", mc->mc_conn.cn_flags,
2044            mc->mc_flags,
2045#if LSQUIC_RECORD_INORD_HIST
2046            mc->mc_inord_idx >= sizeof(mc->mc_inord_hist) /
2047                                    sizeof(mc->mc_inord_hist[0]), inord_str,
2048#endif
2049            mc->mc_received_packnos, mc->mc_sent_packnos, mc->mc_lost_packnos,
2050            mc->mc_deferred_packnos, still_deferred,
2051            mc->mc_dropped_packnos, in_flight, mc->mc_acked_packnos,
2052            mc->mc_error_code, mc->mc_n_ticks, mc->mc_path.np_pack_size,
2053            lsquic_time_now() - mc->mc_created,
2054            lsquic_ver2str[mc->mc_conn.cn_version],
2055            (int) (sizeof(mc->mc_hist_buf) - hist_idx),
2056            mc->mc_hist_buf + hist_idx, (int) hist_idx, mc->mc_hist_buf);
2057#else
2058    if (LSQ_LOG_ENABLED(log_level))
2059        lsquic_logger_log2(log_level, LSQUIC_LOGGER_MODULE,
2060                                   LSQUIC_LOG_CONN_ID,
2061        "destroyed.  Diagnostics: conn flags: 0x%X, "
2062        "mc flags: 0x%X, "
2063#if LSQUIC_RECORD_INORD_HIST
2064        "incoming-history (trunc: %d) %s, "
2065#endif
2066        "received: %"PRIX64", sent: %"PRIX64", lost: %"PRIX64", "
2067        "deferred: %"PRIX64", still-deferred: %"PRIX64", "
2068        "dropped: %"PRIX64", in-flight: %"PRIX64", acked: %"PRIX64", "
2069        "error_code: 0x%X, ticks: %hu, pack size: %hu, "
2070        "lifetime: %"PRIu64" usec",
2071        mc->mc_conn.cn_flags,
2072        mc->mc_flags,
2073#if LSQUIC_RECORD_INORD_HIST
2074        mc->mc_inord_idx >= sizeof(mc->mc_inord_hist) /
2075                                sizeof(mc->mc_inord_hist[0]), inord_str,
2076#endif
2077        mc->mc_received_packnos, mc->mc_sent_packnos, mc->mc_lost_packnos,
2078        mc->mc_deferred_packnos, still_deferred,
2079        mc->mc_dropped_packnos, in_flight, mc->mc_acked_packnos,
2080        mc->mc_error_code, mc->mc_n_ticks, mc->mc_path.np_pack_size,
2081        lsquic_time_now() - mc->mc_created);
2082#endif
2083    EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "mini connection destroyed");
2084    lsquic_malo_put(mc);
2085}
2086
2087
2088static struct lsquic_engine *
2089mini_conn_ci_get_engine (struct lsquic_conn *lconn)
2090{
2091    struct mini_conn *mc = (struct mini_conn *) lconn;
2092    return mc->mc_enpub->enp_engine;
2093}
2094
2095
2096static void
2097mini_conn_ci_hsk_done (struct lsquic_conn *lconn, enum lsquic_hsk_status status)
2098{
2099    assert(0);
2100}
2101
2102
2103/* A mini connection is only tickable if it has unsent packets.  This can
2104 * occur when packet sending is delayed.
2105 *
2106 * Otherwise, a mini connection is not tickable:  Either there are incoming
2107 * packets, in which case, the connection is going to be ticked, or there is
2108 * an alarm pending, in which case it will be handled via the attq.
2109 */
2110static int
2111mini_conn_ci_is_tickable (struct lsquic_conn *lconn)
2112{
2113    struct mini_conn *const mc = (struct mini_conn *) lconn;
2114    const struct lsquic_packet_out *packet_out;
2115
2116    if (mc->mc_enpub->enp_flags & ENPUB_CAN_SEND)
2117        TAILQ_FOREACH(packet_out, &mc->mc_packets_out, po_next)
2118            if (!(packet_out->po_flags & PO_SENT))
2119                return 1;
2120
2121    return 0;
2122}
2123
2124
2125static lsquic_time_t
2126mini_conn_ci_next_tick_time (struct lsquic_conn *lconn, unsigned *why)
2127{
2128    struct mini_conn *mc = (struct mini_conn *) lconn;
2129    lsquic_packet_out_t *packet_out;
2130    lsquic_time_t exp_time, retx_time;
2131
2132    exp_time = mc->mc_created + mc->mc_enpub->enp_settings.es_handshake_to;
2133
2134    TAILQ_FOREACH(packet_out, &mc->mc_packets_out, po_next)
2135        if (packet_out->po_flags & PO_SENT)
2136        {
2137            retx_time = packet_out->po_sent + calc_retx_timeout(mc);
2138            if (retx_time < exp_time)
2139            {
2140                *why = N_AEWS + AL_RETX_HSK;
2141                return retx_time;
2142            }
2143            else
2144            {
2145                *why = AEW_MINI_EXPIRE;
2146                return exp_time;
2147            }
2148        }
2149
2150    *why = AEW_MINI_EXPIRE;
2151    return exp_time;
2152}
2153
2154
2155static void
2156mini_conn_ci_client_call_on_new (struct lsquic_conn *lconn)
2157{
2158    assert(0);
2159}
2160
2161
2162static void
2163mini_conn_ci_internal_error (struct lsquic_conn *lconn,
2164                                                    const char *format, ...)
2165{
2166    struct mini_conn *mc = (struct mini_conn *) lconn;
2167    LSQ_INFO("internal error reported");
2168    mc->mc_flags |= MC_ERROR;
2169}
2170
2171
2172/* This function should not be called, as this is specific to IETF QUIC */
2173static void
2174mini_conn_ci_abort_error (struct lsquic_conn *lconn, int is_app,
2175                                unsigned error_code, const char *fmt, ...)
2176{
2177    struct mini_conn *mc = (struct mini_conn *) lconn;
2178    assert(0);
2179    LSQ_WARN("(GQUIC) abort error is called unexpectedly");
2180    mc->mc_flags |= MC_ERROR;
2181}
2182
2183
2184static void
2185mini_conn_ci_tls_alert (struct lsquic_conn *lconn, uint8_t alert)
2186{
2187    assert(0);
2188}
2189
2190
2191static unsigned char
2192mini_conn_ci_record_addrs (struct lsquic_conn *lconn, void *peer_ctx,
2193            const struct sockaddr *local_sa, const struct sockaddr *peer_sa)
2194{
2195    struct mini_conn *mc = (struct mini_conn *) lconn;
2196    struct lsquic_packet_out *packet_out;
2197    size_t len;
2198
2199
2200    if (NP_IS_IPv6(&mc->mc_path) != (AF_INET6 == peer_sa->sa_family))
2201        TAILQ_FOREACH(packet_out, &mc->mc_packets_out, po_next)
2202            if ((packet_out->po_flags & (PO_SENT|PO_ENCRYPTED)) == PO_ENCRYPTED)
2203                return_enc_data(mc, packet_out);
2204
2205    len = local_sa->sa_family == AF_INET ? sizeof(struct sockaddr_in)
2206                                                : sizeof(struct sockaddr_in6);
2207
2208    memcpy(mc->mc_path.np_peer_addr, peer_sa, len);
2209    memcpy(mc->mc_path.np_local_addr, local_sa, len);
2210    mc->mc_path.np_peer_ctx = peer_ctx;
2211    return 0;
2212}
2213
2214
2215static struct network_path *
2216mini_conn_ci_get_path (struct lsquic_conn *lconn, const struct sockaddr *sa)
2217{
2218    struct mini_conn *mc = (struct mini_conn *) lconn;
2219
2220    return &mc->mc_path;
2221}
2222
2223
2224static const struct conn_iface mini_conn_iface_standard = {
2225    .ci_abort_error          =  mini_conn_ci_abort_error,
2226    .ci_client_call_on_new   =  mini_conn_ci_client_call_on_new,
2227    .ci_destroy              =  mini_conn_ci_destroy,
2228    .ci_get_engine           =  mini_conn_ci_get_engine,
2229    .ci_get_path             =  mini_conn_ci_get_path,
2230    .ci_hsk_done             =  mini_conn_ci_hsk_done,
2231    .ci_internal_error       =  mini_conn_ci_internal_error,
2232    .ci_is_tickable          =  mini_conn_ci_is_tickable,
2233    .ci_next_packet_to_send  =  mini_conn_ci_next_packet_to_send,
2234    .ci_next_tick_time       =  mini_conn_ci_next_tick_time,
2235    .ci_packet_in            =  mini_conn_ci_packet_in,
2236    .ci_packet_not_sent      =  mini_conn_ci_packet_not_sent,
2237    .ci_packet_sent          =  mini_conn_ci_packet_sent,
2238    .ci_record_addrs         =  mini_conn_ci_record_addrs,
2239    .ci_tick                 =  mini_conn_ci_tick,
2240    .ci_tls_alert            =  mini_conn_ci_tls_alert,
2241};
2242
2243
2244static const struct conn_iface mini_conn_iface_standard_Q050 = {
2245    .ci_abort_error          =  mini_conn_ci_abort_error,
2246    .ci_client_call_on_new   =  mini_conn_ci_client_call_on_new,
2247    .ci_destroy              =  mini_conn_ci_destroy,
2248    .ci_get_engine           =  mini_conn_ci_get_engine,
2249    .ci_get_path             =  mini_conn_ci_get_path,
2250    .ci_hsk_done             =  mini_conn_ci_hsk_done,
2251    .ci_internal_error       =  mini_conn_ci_internal_error,
2252    .ci_is_tickable          =  mini_conn_ci_is_tickable,
2253    .ci_next_packet_to_send  =  mini_conn_ci_next_packet_to_send,
2254    .ci_next_tick_time       =  mini_conn_ci_next_tick_time,
2255    .ci_packet_in            =  mini_conn_ci_Q050_packet_in,
2256    .ci_packet_not_sent      =  mini_conn_ci_packet_not_sent,
2257    .ci_packet_sent          =  mini_conn_ci_packet_sent,
2258    .ci_record_addrs         =  mini_conn_ci_record_addrs,
2259    .ci_tick                 =  mini_conn_ci_tick,
2260    .ci_tls_alert            =  mini_conn_ci_tls_alert,
2261};
2262
2263
2264typedef char largest_recv_holds_at_least_16_seconds[
2265    ((1 << (sizeof(((struct mini_conn *) 0)->mc_largest_recv) * 8)) / 1000000
2266                                                                    >= 16) ? 1 : -1];
2267
2268typedef char max_lifespan_smaller_than_largest_recv[
2269    ((1 << (sizeof(((struct mini_conn *) 0)->mc_largest_recv) * 8)) >
2270                                           MAX_MINI_CONN_LIFESPAN_IN_USEC) ? 1 : -1];
2271