+ u32 cur_deq = svm_fifo_max_dequeue (f) - *fifo_offset;
+
+ if (cur_deq == 0)
+ {
+ *max_packet = packet_n + 1;
+ return 0;
+ }
+
+ if (cur_deq < SESSION_CONN_HDR_LEN)
+ {
+ QUIC_DBG (1, "Not enough data for even a header in RX");
+ return 1;
+ }
+ ret = svm_fifo_peek (f, *fifo_offset, SESSION_CONN_HDR_LEN, (u8 *) & ph);
+ if (ret != SESSION_CONN_HDR_LEN)
+ {
+ QUIC_DBG (1, "Not enough data for header in RX");
+ return 1;
+ }
+ ASSERT (ph.data_offset == 0);
+ full_len = ph.data_length + SESSION_CONN_HDR_LEN;
+ if (full_len > cur_deq)
+ {
+ QUIC_DBG (1, "Not enough data in fifo RX");
+ return 1;
+ }
+
+ /* Quicly can read len bytes from the fifo at offset:
+ * ph.data_offset + SESSION_CONN_HDR_LEN */
+ ret =
+ svm_fifo_peek (f, SESSION_CONN_HDR_LEN + *fifo_offset, ph.data_length,
+ packet_ctx->data);
+ if (ret != ph.data_length)
+ {
+ QUIC_DBG (1, "Not enough data peeked in RX");
+ return 1;
+ }
+
+ rv = 0;
+ quic_build_sockaddr (sa, &salen, &ph.rmt_ip, ph.rmt_port, ph.is_ip4);
+ quicly_ctx = quic_get_quicly_ctx_from_udp (udp_session_handle);
+ plen =
+ quicly_decode_packet (quicly_ctx, &packet_ctx->packet, packet_ctx->data,
+ ph.data_length);
+
+ if (plen == SIZE_MAX)
+ {
+ *fifo_offset += SESSION_CONN_HDR_LEN + ph.data_length;
+ return 1;
+ }
+
+ err =
+ quic_find_packet_ctx (&packet_ctx->thread_index, &packet_ctx->ctx_index,
+ sa, salen, &packet_ctx->packet, thread_index);
+ if (err == 0)
+ {
+ ctx = quic_ctx_get (packet_ctx->ctx_index, thread_index);
+ rv = quicly_receive (ctx->conn, &packet_ctx->packet);
+ if (rv)
+ QUIC_DBG (1, "quicly_receive return error %d", rv);
+ }
+ else if (packet_ctx->ctx_index != UINT32_MAX)
+ {
+ /* Connection found but on wrong thread, ask move */
+ *max_packet = packet_n + 1;
+ return 0;
+ }
+ else if ((packet_ctx->packet.octets.base[0] & QUICLY_PACKET_TYPE_BITMASK) ==
+ QUICLY_PACKET_TYPE_INITIAL)
+ {
+ /* Try to find matching "opening" ctx */
+ opening_ctx_pool = quic_main.wrk_ctx[thread_index].opening_ctx_pool;
+
+ /* *INDENT-OFF* */
+ pool_foreach (ctx_index_ptr, opening_ctx_pool,
+ ({
+ ctx = quic_ctx_get (*ctx_index_ptr, thread_index);
+ if (ctx->udp_session_handle == udp_session_handle)
+ {
+ /* Right ctx found, create conn & remove from pool */
+ quic_create_connection(*ctx_index_ptr, sa, salen, packet_ctx->packet);
+ pool_put (opening_ctx_pool, ctx_index_ptr);
+ *max_packet = packet_n + 1;
+ packet_ctx->thread_index = thread_index;
+ packet_ctx->ctx_index = *ctx_index_ptr;
+ goto updateOffset;
+ }
+ }));
+ /* *INDENT-ON* */
+ }
+ else
+ {
+ quic_reset_connection (udp_session_handle, sa, salen,
+ packet_ctx->packet);
+ }
+
+updateOffset:
+ *fifo_offset += SESSION_CONN_HDR_LEN + ph.data_length;
+ return 0;
+}
+
+static int
+quic_app_rx_callback (session_t * udp_session)
+{
+ /* Read data from UDP rx_fifo and pass it to the quicly conn. */
+ application_t *app;
+ quic_ctx_t *ctx = NULL;
+ svm_fifo_t *f;
+ u32 max_deq;