LCOV - code coverage report
Current view: top level - home/net-next/net/quic - stream.c (source / functions) Hit Total Coverage
Test: quic.info Lines: 271 284 95.4 %
Date: 2025-07-04 13:24:45 Functions: 15 15 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /* QUIC kernel implementation
       3             :  * (C) Copyright Red Hat Corp. 2023
       4             :  *
       5             :  * This file is part of the QUIC kernel implementation
       6             :  *
       7             :  * Initialization/cleanup for QUIC protocol support.
       8             :  *
       9             :  * Written or modified by:
      10             :  *    Xin Long <lucien.xin@gmail.com>
      11             :  */
      12             : 
      13             : #include <linux/quic.h>
      14             : 
      15             : #include "common.h"
      16             : #include "stream.h"
      17             : 
      18             : /* Check if a stream ID is valid for sending. */
      19     2252848 : static bool quic_stream_id_send(s64 stream_id, bool is_serv)
      20             : {
      21     2252848 :         u8 type = (stream_id & QUIC_STREAM_TYPE_MASK);
      22             : 
      23     2252848 :         if (is_serv) {
      24       26267 :                 if (type == QUIC_STREAM_TYPE_CLIENT_UNI)
      25             :                         return false;
      26     2226581 :         } else if (type == QUIC_STREAM_TYPE_SERVER_UNI) {
      27             :                 return false;
      28             :         }
      29             :         return true;
      30             : }
      31             : 
      32             : /* Check if a stream ID is valid for receiving. */
      33     6372034 : static bool quic_stream_id_recv(s64 stream_id, bool is_serv)
      34             : {
      35     6372034 :         u8 type = (stream_id & QUIC_STREAM_TYPE_MASK);
      36             : 
      37     6372034 :         if (is_serv) {
      38     6189927 :                 if (type == QUIC_STREAM_TYPE_SERVER_UNI)
      39             :                         return false;
      40      182107 :         } else if (type == QUIC_STREAM_TYPE_CLIENT_UNI) {
      41             :                 return false;
      42             :         }
      43             :         return true;
      44             : }
      45             : 
      46             : /* Check if a stream ID was initiated locally. */
      47       34990 : static bool quic_stream_id_local(s64 stream_id, u8 is_serv)
      48             : {
      49       34990 :         return is_serv ^ !(stream_id & QUIC_STREAM_TYPE_SERVER_MASK);
      50             : }
      51             : 
      52             : /* Check if a stream ID represents a unidirectional stream. */
      53      123566 : static bool quic_stream_id_uni(s64 stream_id)
      54             : {
      55      123566 :         return stream_id & QUIC_STREAM_TYPE_UNI_MASK;
      56             : }
      57             : 
      58     8610192 : struct quic_stream *quic_stream_find(struct quic_stream_table *streams, s64 stream_id)
      59             : {
      60     8610192 :         struct quic_hash_head *head = quic_stream_head(&streams->ht, stream_id);
      61     8609649 :         struct quic_stream *stream;
      62             : 
      63    18500328 :         hlist_for_each_entry(stream, &head->head, node) {
      64     9239829 :                 if (stream->id == stream_id)
      65             :                         break;
      66             :         }
      67     8609649 :         return stream;
      68             : }
      69             : 
      70       20274 : static void quic_stream_add(struct quic_stream_table *streams, struct quic_stream *stream)
      71             : {
      72       20274 :         struct quic_hash_head *head;
      73             : 
      74       20274 :         head = quic_stream_head(&streams->ht, stream->id);
      75       20274 :         hlist_add_head(&stream->node, &head->head);
      76       20274 : }
      77             : 
      78       17753 : static void quic_stream_delete(struct quic_stream *stream)
      79             : {
      80       17753 :         hlist_del_init(&stream->node);
      81       17753 :         kfree(stream);
      82       17755 : }
      83             : 
      84             : /* Create and register new streams for sending. */
      85        9006 : static struct quic_stream *quic_stream_send_create(struct quic_stream_table *streams,
      86             :                                                    s64 max_stream_id, u8 is_serv)
      87             : {
      88        9006 :         struct quic_stream *stream;
      89        9006 :         s64 stream_id;
      90             : 
      91        9006 :         stream_id = streams->send.next_bidi_stream_id;
      92        9006 :         if (quic_stream_id_uni(max_stream_id))
      93         202 :                 stream_id = streams->send.next_uni_stream_id;
      94             : 
      95             :         /* rfc9000#section-2.1: A stream ID that is used out of order results in all streams
      96             :          * of that type with lower-numbered stream IDs also being opened.
      97             :          */
      98       19224 :         while (stream_id <= max_stream_id) {
      99       10218 :                 stream = kzalloc(sizeof(*stream), GFP_KERNEL);
     100       10218 :                 if (!stream)
     101             :                         return NULL;
     102             : 
     103       10218 :                 stream->id = stream_id;
     104       10218 :                 if (quic_stream_id_uni(stream_id)) {
     105        1010 :                         stream->send.max_bytes = streams->send.max_stream_data_uni;
     106             : 
     107        1010 :                         if (streams->send.next_uni_stream_id < stream_id + QUIC_STREAM_ID_STEP)
     108        1010 :                                 streams->send.next_uni_stream_id = stream_id + QUIC_STREAM_ID_STEP;
     109        1010 :                         streams->send.streams_uni++;
     110             : 
     111        1010 :                         quic_stream_add(streams, stream);
     112        1010 :                         stream_id += QUIC_STREAM_ID_STEP;
     113        1010 :                         continue;
     114             :                 }
     115             : 
     116        9208 :                 if (streams->send.next_bidi_stream_id < stream_id + QUIC_STREAM_ID_STEP)
     117        9208 :                         streams->send.next_bidi_stream_id = stream_id + QUIC_STREAM_ID_STEP;
     118        9208 :                 streams->send.streams_bidi++;
     119             : 
     120        9208 :                 if (quic_stream_id_local(stream_id, is_serv)) {
     121        9208 :                         stream->send.max_bytes = streams->send.max_stream_data_bidi_remote;
     122        9208 :                         stream->recv.max_bytes = streams->recv.max_stream_data_bidi_local;
     123             :                 } else {
     124           0 :                         stream->send.max_bytes = streams->send.max_stream_data_bidi_local;
     125           0 :                         stream->recv.max_bytes = streams->recv.max_stream_data_bidi_remote;
     126             :                 }
     127        9208 :                 stream->recv.window = stream->recv.max_bytes;
     128             : 
     129        9208 :                 quic_stream_add(streams, stream);
     130        9208 :                 stream_id += QUIC_STREAM_ID_STEP;
     131             :         }
     132             :         return stream;
     133             : }
     134             : 
     135             : /* Create and register new streams for receiving. */
     136        8827 : static struct quic_stream *quic_stream_recv_create(struct quic_stream_table *streams,
     137             :                                                    s64 max_stream_id, u8 is_serv)
     138             : {
     139        8827 :         struct quic_stream *stream;
     140        8827 :         s64 stream_id;
     141             : 
     142        8827 :         stream_id = streams->recv.next_bidi_stream_id;
     143        8827 :         if (quic_stream_id_uni(max_stream_id))
     144         179 :                 stream_id = streams->recv.next_uni_stream_id;
     145             : 
     146             :         /* rfc9000#section-2.1: A stream ID that is used out of order results in all streams
     147             :          * of that type with lower-numbered stream IDs also being opened.
     148             :          */
     149       18883 :         while (stream_id <= max_stream_id) {
     150       10056 :                 stream = kzalloc(sizeof(*stream), GFP_ATOMIC);
     151       10056 :                 if (!stream)
     152             :                         return NULL;
     153             : 
     154       10056 :                 stream->id = stream_id;
     155       10056 :                 if (quic_stream_id_uni(stream_id)) {
     156        1004 :                         stream->recv.window = streams->recv.max_stream_data_uni;
     157        1004 :                         stream->recv.max_bytes = stream->recv.window;
     158             : 
     159        1004 :                         if (streams->recv.next_uni_stream_id < stream_id + QUIC_STREAM_ID_STEP)
     160        1004 :                                 streams->recv.next_uni_stream_id = stream_id + QUIC_STREAM_ID_STEP;
     161        1004 :                         streams->recv.streams_uni++;
     162             : 
     163        1004 :                         quic_stream_add(streams, stream);
     164        1004 :                         stream_id += QUIC_STREAM_ID_STEP;
     165        1004 :                         continue;
     166             :                 }
     167             : 
     168        9052 :                 if (streams->recv.next_bidi_stream_id < stream_id + QUIC_STREAM_ID_STEP)
     169        9052 :                         streams->recv.next_bidi_stream_id = stream_id + QUIC_STREAM_ID_STEP;
     170        9052 :                 streams->recv.streams_bidi++;
     171             : 
     172        9052 :                 if (quic_stream_id_local(stream_id, is_serv)) {
     173           0 :                         stream->send.max_bytes = streams->send.max_stream_data_bidi_remote;
     174           0 :                         stream->recv.max_bytes = streams->recv.max_stream_data_bidi_local;
     175             :                 } else {
     176        9052 :                         stream->send.max_bytes = streams->send.max_stream_data_bidi_local;
     177        9052 :                         stream->recv.max_bytes = streams->recv.max_stream_data_bidi_remote;
     178             :                 }
     179        9052 :                 stream->recv.window = stream->recv.max_bytes;
     180             : 
     181        9052 :                 quic_stream_add(streams, stream);
     182        9052 :                 stream_id += QUIC_STREAM_ID_STEP;
     183             :         }
     184             :         return stream;
     185             : }
     186             : 
     187             : /* Check if a send stream ID is already closed. */
     188        9962 : static bool quic_stream_id_send_closed(struct quic_stream_table *streams, s64 stream_id)
     189             : {
     190        9962 :         if (quic_stream_id_uni(stream_id)) {
     191         222 :                 if (stream_id < streams->send.next_uni_stream_id)
     192             :                         return true;
     193             :         } else {
     194        9740 :                 if (stream_id < streams->send.next_bidi_stream_id)
     195             :                         return true;
     196             :         }
     197             :         return false;
     198             : }
     199             : 
     200             : /* Check if a receive stream ID is already closed. */
     201        8836 : static bool quic_stream_id_recv_closed(struct quic_stream_table *streams, s64 stream_id)
     202             : {
     203        8836 :         if (quic_stream_id_uni(stream_id)) {
     204         179 :                 if (stream_id < streams->recv.next_uni_stream_id)
     205             :                         return true;
     206             :         } else {
     207        8657 :                 if (stream_id < streams->recv.next_bidi_stream_id)
     208             :                         return true;
     209             :         }
     210             :         return false;
     211             : }
     212             : 
     213             : /* Check if a receive stream ID exceeds would exceed local's limits. */
     214        8827 : static bool quic_stream_id_recv_exceeds(struct quic_stream_table *streams, s64 stream_id)
     215             : {
     216        8827 :         if (quic_stream_id_uni(stream_id)) {
     217         179 :                 if (stream_id > streams->recv.max_uni_stream_id)
     218             :                         return true;
     219             :         } else {
     220        8648 :                 if (stream_id > streams->recv.max_bidi_stream_id)
     221             :                         return true;
     222             :         }
     223             :         return false;
     224             : }
     225             : 
     226             : /* Check if a send stream ID would exceed peer's limits. */
     227       13709 : bool quic_stream_id_send_exceeds(struct quic_stream_table *streams, s64 stream_id)
     228             : {
     229       13709 :         u64 nstreams;
     230             : 
     231       13709 :         if (quic_stream_id_uni(stream_id)) {
     232         218 :                 if (stream_id > streams->send.max_uni_stream_id)
     233             :                         return true;
     234             :         } else {
     235       13491 :                 if (stream_id > streams->send.max_bidi_stream_id)
     236             :                         return true;
     237             :         }
     238             : 
     239        9887 :         if (quic_stream_id_uni(stream_id)) {
     240         202 :                 stream_id -= streams->send.next_uni_stream_id;
     241         202 :                 nstreams = quic_stream_id_to_streams(stream_id);
     242         202 :                 if (nstreams + streams->send.streams_uni > streams->send.max_streams_uni)
     243           0 :                         return true;
     244             :         } else {
     245        9685 :                 stream_id -= streams->send.next_bidi_stream_id;
     246        9685 :                 nstreams = quic_stream_id_to_streams(stream_id);
     247        9685 :                 if (nstreams + streams->send.streams_bidi > streams->send.max_streams_bidi)
     248           0 :                         return true;
     249             :         }
     250             :         return false;
     251             : }
     252             : 
     253             : /* Get or create a send stream by ID. */
     254     2244021 : struct quic_stream *quic_stream_send_get(struct quic_stream_table *streams, s64 stream_id,
     255             :                                          u32 flags, bool is_serv)
     256             : {
     257     2244021 :         struct quic_stream *stream;
     258             : 
     259     2244021 :         if (!quic_stream_id_send(stream_id, is_serv))
     260             :                 return ERR_PTR(-EINVAL);
     261             : 
     262     2244021 :         stream = quic_stream_find(streams, stream_id);
     263     2244021 :         if (stream) {
     264     2234090 :                 if ((flags & MSG_STREAM_NEW) &&
     265         112 :                     stream->send.state != QUIC_STREAM_SEND_STATE_READY)
     266             :                         return ERR_PTR(-EINVAL);
     267     2234078 :                 return stream;
     268             :         }
     269             : 
     270        9931 :         if (quic_stream_id_send_closed(streams, stream_id))
     271             :                 return ERR_PTR(-ENOSTR);
     272             : 
     273        9907 :         if (!(flags & MSG_STREAM_NEW))
     274             :                 return ERR_PTR(-EINVAL);
     275             : 
     276        9903 :         if (quic_stream_id_send_exceeds(streams, stream_id))
     277             :                 return ERR_PTR(-EAGAIN);
     278             : 
     279        9006 :         stream = quic_stream_send_create(streams, stream_id, is_serv);
     280        9006 :         if (!stream)
     281             :                 return ERR_PTR(-ENOSTR);
     282        9006 :         streams->send.active_stream_id = stream_id;
     283        9006 :         return stream;
     284             : }
     285             : 
     286             : /* Get or create a receive stream by ID. */
     287     6372034 : struct quic_stream *quic_stream_recv_get(struct quic_stream_table *streams, s64 stream_id,
     288             :                                          bool is_serv)
     289             : {
     290     6372034 :         struct quic_stream *stream;
     291             : 
     292     6372034 :         if (!quic_stream_id_recv(stream_id, is_serv))
     293             :                 return ERR_PTR(-EINVAL);
     294             : 
     295     6372034 :         stream = quic_stream_find(streams, stream_id);
     296     6372034 :         if (stream)
     297             :                 return stream;
     298             : 
     299        8867 :         if (quic_stream_id_local(stream_id, is_serv)) {
     300          31 :                 if (quic_stream_id_send_closed(streams, stream_id))
     301             :                         return ERR_PTR(-ENOSTR);
     302           0 :                 return ERR_PTR(-EINVAL);
     303             :         }
     304             : 
     305        8836 :         if (quic_stream_id_recv_closed(streams, stream_id))
     306             :                 return ERR_PTR(-ENOSTR);
     307             : 
     308        8827 :         if (quic_stream_id_recv_exceeds(streams, stream_id))
     309             :                 return ERR_PTR(-EAGAIN);
     310             : 
     311        8827 :         stream = quic_stream_recv_create(streams, stream_id, is_serv);
     312        8827 :         if (!stream)
     313             :                 return ERR_PTR(-ENOSTR);
     314        8827 :         if (quic_stream_id_send(stream_id, is_serv))
     315        8648 :                 streams->send.active_stream_id = stream_id;
     316             :         return stream;
     317             : }
     318             : 
     319             : /* Release or clean up a send stream. This function updates stream counters and state when
     320             :  * a send stream has either successfully sent all data or has been reset.
     321             :  */
     322       17656 : void quic_stream_send_put(struct quic_stream_table *streams, struct quic_stream *stream,
     323             :                           bool is_serv)
     324             : {
     325       17656 :         if (quic_stream_id_uni(stream->id)) {
     326             :                 /* For unidirectional streams, decrement uni count and delete immediately. */
     327         138 :                 streams->send.streams_uni--;
     328         138 :                 quic_stream_delete(stream);
     329         138 :                 return;
     330             :         }
     331             : 
     332             :         /* For bidi streams, only proceed if receive side is in a final state. */
     333       17518 :         if (stream->recv.state != QUIC_STREAM_RECV_STATE_RECVD &&
     334       17518 :             stream->recv.state != QUIC_STREAM_RECV_STATE_READ &&
     335             :             stream->recv.state != QUIC_STREAM_RECV_STATE_RESET_RECVD)
     336             :                 return;
     337             : 
     338       11907 :         if (quic_stream_id_local(stream->id, is_serv)) {
     339             :                 /* Local-initiated stream: mark send done and decrement send.bidi count. */
     340        3241 :                 if (!stream->send.done) {
     341        3241 :                         stream->send.done = 1;
     342        3241 :                         streams->send.streams_bidi--;
     343             :                 }
     344        3241 :                 goto out;
     345             :         }
     346             :         /* Remote-initiated stream: mark recv done and decrement recv bidi count. */
     347        8666 :         if (!stream->recv.done) {
     348        8666 :                 stream->recv.done = 1;
     349        8666 :                 streams->recv.streams_bidi--;
     350        8666 :                 streams->recv.bidi_pending = 1;
     351             :         }
     352           0 : out:
     353             :         /* Delete stream if fully read or no data received. */
     354       11907 :         if (stream->recv.state == QUIC_STREAM_RECV_STATE_READ || !stream->recv.offset)
     355        8853 :                 quic_stream_delete(stream);
     356             : }
     357             : 
     358             : /* Release or clean up a receive stream. This function updates stream counters and state when
     359             :  * the receive side has either consumed all data or has been reset.
     360             :  */
     361       35296 : void quic_stream_recv_put(struct quic_stream_table *streams, struct quic_stream *stream,
     362             :                           bool is_serv)
     363             : {
     364       35296 :         if (quic_stream_id_uni(stream->id)) {
     365             :                 /* For uni streams, decrement uni count and mark done. */
     366         268 :                 if (!stream->recv.done) {
     367         142 :                         stream->recv.done = 1;
     368         142 :                         streams->recv.streams_uni--;
     369         142 :                         streams->recv.uni_pending = 1;
     370             :                 }
     371         268 :                 goto out;
     372             :         }
     373             : 
     374             :         /* For bidi streams, only proceed if send side is in a final state. */
     375       35028 :         if (stream->send.state != QUIC_STREAM_SEND_STATE_RECVD &&
     376             :             stream->send.state != QUIC_STREAM_SEND_STATE_RESET_RECVD)
     377             :                 return;
     378             : 
     379       14216 :         if (quic_stream_id_local(stream->id, is_serv)) {
     380             :                 /* Local-initiated stream: mark send done and decrement send.bidi count. */
     381       14216 :                 if (!stream->send.done) {
     382        5581 :                         stream->send.done = 1;
     383        5581 :                         streams->send.streams_bidi--;
     384             :                 }
     385       14216 :                 goto out;
     386             :         }
     387             :         /* Remote-initiated stream: mark recv done and decrement recv bidi count. */
     388           0 :         if (!stream->recv.done) {
     389           0 :                 stream->recv.done = 1;
     390           0 :                 streams->recv.streams_bidi--;
     391           0 :                 streams->recv.bidi_pending = 1;
     392             :         }
     393           0 : out:
     394             :         /* Delete stream if fully read or no data received. */
     395       14484 :         if (stream->recv.state == QUIC_STREAM_RECV_STATE_READ || !stream->recv.offset)
     396        8765 :                 quic_stream_delete(stream);
     397             : }
     398             : 
     399             : /* Updates the maximum allowed incoming stream IDs if any streams were recently closed.
     400             :  * Recalculates the max_uni and max_bidi stream ID limits based on the number of open
     401             :  * streams and whether any were marked for deletion.
     402             :  *
     403             :  * Returns true if either max_uni or max_bidi was updated, indicating that a
     404             :  * MAX_STREAMS_UNI or MAX_STREAMS_BIDI frame should be sent to the peer.
     405             :  */
     406     6570917 : bool quic_stream_max_streams_update(struct quic_stream_table *streams, s64 *max_uni, s64 *max_bidi)
     407             : {
     408     6570917 :         if (streams->recv.uni_pending) {
     409         142 :                 streams->recv.max_uni_stream_id =
     410         142 :                         streams->recv.next_uni_stream_id - QUIC_STREAM_ID_STEP +
     411         142 :                         ((streams->recv.max_streams_uni - streams->recv.streams_uni) <<
     412             :                          QUIC_STREAM_TYPE_BITS);
     413         142 :                 *max_uni = quic_stream_id_to_streams(streams->recv.max_uni_stream_id);
     414         142 :                 streams->recv.uni_pending = 0;
     415             :         }
     416     6570917 :         if (streams->recv.bidi_pending) {
     417         689 :                 streams->recv.max_bidi_stream_id =
     418         689 :                         streams->recv.next_bidi_stream_id - QUIC_STREAM_ID_STEP +
     419         689 :                         ((streams->recv.max_streams_bidi - streams->recv.streams_bidi) <<
     420             :                          QUIC_STREAM_TYPE_BITS);
     421         689 :                 *max_bidi = quic_stream_id_to_streams(streams->recv.max_bidi_stream_id);
     422         689 :                 streams->recv.bidi_pending = 0;
     423             :         }
     424             : 
     425     6570917 :         return *max_uni || *max_bidi;
     426             : }
     427             : 
     428        1119 : int quic_stream_init(struct quic_stream_table *streams)
     429             : {
     430        1119 :         struct quic_hash_table *ht = &streams->ht;
     431        1119 :         struct quic_hash_head *head;
     432        1119 :         int i, size = QUIC_HT_SIZE;
     433             : 
     434        1119 :         head = kmalloc_array(size, sizeof(*head), GFP_KERNEL);
     435        1119 :         if (!head)
     436             :                 return -ENOMEM;
     437       72735 :         for (i = 0; i < size; i++)
     438       71616 :                 INIT_HLIST_HEAD(&head[i].head);
     439        1119 :         ht->size = size;
     440        1119 :         ht->hash = head;
     441        1119 :         return 0;
     442             : }
     443             : 
     444        1118 : void quic_stream_free(struct quic_stream_table *streams)
     445             : {
     446        1118 :         struct quic_hash_table *ht = &streams->ht;
     447        1118 :         struct quic_hash_head *head;
     448        1118 :         struct quic_stream *stream;
     449        1118 :         struct hlist_node *tmp;
     450        1118 :         int i;
     451             : 
     452       72653 :         for (i = 0; i < ht->size; i++) {
     453       71535 :                 head = &ht->hash[i];
     454      146733 :                 hlist_for_each_entry_safe(stream, tmp, &head->head, node) {
     455        2146 :                         hlist_del_init(&stream->node);
     456        2146 :                         kfree(stream);
     457             :                 }
     458             :         }
     459        1118 :         kfree(ht->hash);
     460        1118 : }
     461             : 
     462             : /* Populate transport parameters from stream hash table. */
     463        2079 : void quic_stream_get_param(struct quic_stream_table *streams, struct quic_transport_param *p,
     464             :                            bool is_serv)
     465             : {
     466        2079 :         if (p->remote) {
     467          24 :                 p->max_stream_data_bidi_remote = streams->send.max_stream_data_bidi_remote;
     468          24 :                 p->max_stream_data_bidi_local = streams->send.max_stream_data_bidi_local;
     469          24 :                 p->max_stream_data_uni = streams->send.max_stream_data_uni;
     470          24 :                 p->max_streams_bidi = streams->send.max_streams_bidi;
     471          24 :                 p->max_streams_uni = streams->send.max_streams_uni;
     472          24 :                 return;
     473             :         }
     474             : 
     475        2055 :         p->max_stream_data_bidi_remote = streams->recv.max_stream_data_bidi_remote;
     476        2055 :         p->max_stream_data_bidi_local = streams->recv.max_stream_data_bidi_local;
     477        2055 :         p->max_stream_data_uni = streams->recv.max_stream_data_uni;
     478        2055 :         p->max_streams_bidi = streams->recv.max_streams_bidi;
     479        2055 :         p->max_streams_uni = streams->recv.max_streams_uni;
     480             : }
     481             : 
     482             : /* Configure stream hashtable from transport parameters. */
     483        3172 : void quic_stream_set_param(struct quic_stream_table *streams, struct quic_transport_param *p,
     484             :                            bool is_serv)
     485             : {
     486        3172 :         u8 type;
     487             : 
     488        3172 :         if (p->remote) {
     489        1004 :                 streams->send.max_stream_data_bidi_local = p->max_stream_data_bidi_local;
     490        1004 :                 streams->send.max_stream_data_bidi_remote = p->max_stream_data_bidi_remote;
     491        1004 :                 streams->send.max_stream_data_uni = p->max_stream_data_uni;
     492        1004 :                 streams->send.max_streams_bidi = p->max_streams_bidi;
     493        1004 :                 streams->send.max_streams_uni = p->max_streams_uni;
     494        1004 :                 streams->send.active_stream_id = -1;
     495             : 
     496        1004 :                 if (is_serv) {
     497         420 :                         type = QUIC_STREAM_TYPE_SERVER_BIDI;
     498         420 :                         streams->send.max_bidi_stream_id =
     499         420 :                                 quic_stream_streams_to_id(p->max_streams_bidi, type);
     500         420 :                         streams->send.next_bidi_stream_id = type;
     501             : 
     502         420 :                         type = QUIC_STREAM_TYPE_SERVER_UNI;
     503         420 :                         streams->send.max_uni_stream_id =
     504         420 :                                 quic_stream_streams_to_id(p->max_streams_uni, type);
     505         420 :                         streams->send.next_uni_stream_id = type;
     506         420 :                         return;
     507             :                 }
     508             : 
     509         584 :                 type = QUIC_STREAM_TYPE_CLIENT_BIDI;
     510         584 :                 streams->send.max_bidi_stream_id =
     511         584 :                         quic_stream_streams_to_id(p->max_streams_bidi, type);
     512         584 :                 streams->send.next_bidi_stream_id = type;
     513             : 
     514         584 :                 type = QUIC_STREAM_TYPE_CLIENT_UNI;
     515         584 :                 streams->send.max_uni_stream_id =
     516         584 :                         quic_stream_streams_to_id(p->max_streams_uni, type);
     517         584 :                 streams->send.next_uni_stream_id = type;
     518         584 :                 return;
     519             :         }
     520             : 
     521        2168 :         streams->recv.max_stream_data_bidi_local = p->max_stream_data_bidi_local;
     522        2168 :         streams->recv.max_stream_data_bidi_remote = p->max_stream_data_bidi_remote;
     523        2168 :         streams->recv.max_stream_data_uni = p->max_stream_data_uni;
     524        2168 :         streams->recv.max_streams_bidi = p->max_streams_bidi;
     525        2168 :         streams->recv.max_streams_uni = p->max_streams_uni;
     526             : 
     527        2168 :         if (is_serv) {
     528         424 :                 type = QUIC_STREAM_TYPE_CLIENT_BIDI;
     529         424 :                 streams->recv.max_bidi_stream_id =
     530         424 :                         quic_stream_streams_to_id(p->max_streams_bidi, type);
     531         424 :                 streams->recv.next_bidi_stream_id = type;
     532             : 
     533         424 :                 type = QUIC_STREAM_TYPE_CLIENT_UNI;
     534         424 :                 streams->recv.max_uni_stream_id =
     535         424 :                         quic_stream_streams_to_id(p->max_streams_uni, type);
     536         424 :                 streams->recv.next_uni_stream_id = type;
     537         424 :                 return;
     538             :         }
     539             : 
     540        1744 :         type = QUIC_STREAM_TYPE_SERVER_BIDI;
     541        1744 :         streams->recv.max_bidi_stream_id =
     542        1744 :                 quic_stream_streams_to_id(p->max_streams_bidi, type);
     543        1744 :         streams->recv.next_bidi_stream_id = type;
     544             : 
     545        1744 :         type = QUIC_STREAM_TYPE_SERVER_UNI;
     546        1744 :         streams->recv.max_uni_stream_id =
     547        1744 :                 quic_stream_streams_to_id(p->max_streams_uni, type);
     548        1744 :         streams->recv.next_uni_stream_id = type;
     549             : }

Generated by: LCOV version 1.14