Repository: nginx/nginx
File: src/event/quic/ngx_event_quic.c (C)

Code before:
        return NULL;
    }

    ctp = &qc->ctp;

    /* defaults to be used before actual client parameters are received */
    ctp->max_udp_payload_size = NGX_QUIC_MAX_UDP_PAYLOAD_SIZE;
    ctp->ack_delay_exponent = NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT;
    ctp->max_ack_delay = NGX_QUIC_DEFAULT_MAX_ACK_DELAY;
    ctp->active_connection_id_limit = 2;

    ngx_queue_init(&qc->streams.uninitialized);
    ngx_queue_init(&qc->streams.free);

    qc->streams.recv_max_data = qc->tp.initial_max_data;
    qc->streams.recv_window = qc->streams.recv_max_data;

    qc->streams.client_max_streams_uni = qc->tp.initial_max_streams_uni;
    qc->streams.client_max_streams_bidi = qc->tp.initial_max_streams_bidi;

    qc->congestion.window = ngx_min(10 * NGX_QUIC_MIN_INITIAL_SIZE,
                                    ngx_max(2 * NGX_QUIC_MIN_INITIAL_SIZE,
                                            14720));
    qc->congestion.ssthresh = (size_t) -1;
    qc->congestion.recovery_start = ngx_current_msec - 1;

    if (pkt->validated && pkt->retried) {
        qc->tp.retry_scid.len = pkt->dcid.len;
        qc->tp.retry_scid.data = ngx_pstrdup(c->pool, &pkt->dcid);
        if (qc->tp.retry_scid.data == NULL) {
            return NULL;
        }
    }

    if (ngx_quic_keys_set_initial_secret(qc->keys, &pkt->dcid, c->log)
        != NGX_OK)
    {
        return NULL;
    }

    qc->validated = pkt->validated;

    if (ngx_quic_open_sockets(c, qc, pkt) != NGX_OK) {
        ngx_quic_keys_cleanup(qc->keys);
        return NULL;
    }

    c->idle = 1;
    ngx_reusable_connection(c, 1);

    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,

Review comment (bug):
Why not initialize it to the special zero value?
Same goes for persistent congestion (9002, 7.3.1):
```
A sender reenters slow start any time the congestion window is less
than the slow start threshold, which only occurs after persistent
congestion is declared.
```

Further, while reviewing this change, I noticed cg->ssthresh miscalculation
on congestion event (7.3.2):
```
On entering a recovery period, a sender MUST set the slow start
threshold to half the value of the congestion window when loss is
detected.
```

```
@@ -696,13 +696,8 @@ ngx_quic_congestion_lost(ngx_connection_t *c, ngx_quic_frame_t *f)
     }
 
     cg->recovery_start = now;
-    cg->window /= 2;
-
-    if (cg->window < qc->path->mtu * 2) {
-        cg->window = qc->path->mtu * 2;
-    }
-
-    cg->ssthresh = cg->window;
+    cg->ssthresh = cg->window / 2;
+    cg->window = ngx_max(cg->sshthresh, qc->path->mtu * 2);
 
     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
                    "quic congestion lost t:%M win:%uz if:%uz",
```

Code after:
        return NULL;
    }

    ctp = &qc->ctp;

    /* defaults to be used before actual client parameters are received */
    ctp->max_udp_payload_size = NGX_QUIC_MAX_UDP_PAYLOAD_SIZE;
    ctp->ack_delay_exponent = NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT;
    ctp->max_ack_delay = NGX_QUIC_DEFAULT_MAX_ACK_DELAY;
    ctp->active_connection_id_limit = 2;

    ngx_queue_init(&qc->streams.uninitialized);
    ngx_queue_init(&qc->streams.free);

    qc->streams.recv_max_data = qc->tp.initial_max_data;
    qc->streams.recv_window = qc->streams.recv_max_data;

    qc->streams.client_max_streams_uni = qc->tp.initial_max_streams_uni;
    qc->streams.client_max_streams_bidi = qc->tp.initial_max_streams_bidi;

    qc->congestion.window = ngx_min(10 * NGX_QUIC_MIN_INITIAL_SIZE,
                                    ngx_max(2 * NGX_QUIC_MIN_INITIAL_SIZE,
                                            14720));
    qc->congestion.ssthresh = (size_t) -1;
    qc->congestion.mtu = NGX_QUIC_MIN_INITIAL_SIZE;
    qc->congestion.recovery_start = ngx_current_msec - 1;

    qc->max_frames = (conf->max_concurrent_streams_uni
                      + conf->max_concurrent_streams_bidi)
                     * conf->stream_buffer_size / 2000;

    if (pkt->validated && pkt->retried) {
        qc->tp.retry_scid.len = pkt->dcid.len;
        qc->tp.retry_scid.data = ngx_pstrdup(c->pool, &pkt->dcid);
        if (qc->tp.retry_scid.data == NULL) {
            return NULL;
        }
    }

    if (ngx_quic_keys_set_initial_secret(qc->keys, &pkt->dcid, c->log)
        != NGX_OK)
    {
        return NULL;
    }

    qc->validated = pkt->validated;

    if (ngx_quic_open_sockets(c, qc, pkt) != NGX_OK) {
        ngx_quic_keys_cleanup(qc->keys);
        return NULL;
    }