view src/http/v3/ngx_http_v3.c @ 9054:6546c2ae1c7b quic

HTTP/3: unified hq code with regular HTTP/3 code. The change removes hq-specific request handler. Now hq requests are handled by the HTTP/3 request handler.
author Roman Arutyunyan <arut@nginx.com>
date Wed, 19 Oct 2022 17:45:30 +0400
parents 81a3429db8b0
children be39ffdf9208
line wrap: on
line source


/*
 * Copyright (C) Roman Arutyunyan
 * Copyright (C) Nginx, Inc.
 */


#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>


static void ngx_http_v3_keepalive_handler(ngx_event_t *ev);
static void ngx_http_v3_cleanup_session(void *data);


ngx_int_t
ngx_http_v3_init_session(ngx_connection_t *c)
{
    ngx_connection_t        *pc;
    ngx_pool_cleanup_t      *cln;
    ngx_http_connection_t   *hc;
    ngx_http_v3_session_t   *h3c;
#if (NGX_HTTP_V3_HQ)
    ngx_http_v3_srv_conf_t  *h3scf;
#endif

    pc = c->quic->parent;
    hc = pc->data;

    if (hc->v3_session) {
        return NGX_OK;
    }

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 init session");

    h3c = ngx_pcalloc(pc->pool, sizeof(ngx_http_v3_session_t));
    if (h3c == NULL) {
        goto failed;
    }

    h3c->max_push_id = (uint64_t) -1;
    h3c->goaway_push_id = (uint64_t) -1;

#if (NGX_HTTP_V3_HQ)
    h3scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v3_module);
    if (h3scf->hq) {
        h3c->hq = 1;
    }
#endif

    ngx_queue_init(&h3c->blocked);
    ngx_queue_init(&h3c->pushing);

    h3c->keepalive.log = pc->log;
    h3c->keepalive.data = pc;
    h3c->keepalive.handler = ngx_http_v3_keepalive_handler;
    h3c->keepalive.cancelable = 1;

    h3c->table.send_insert_count.log = pc->log;
    h3c->table.send_insert_count.data = pc;
    h3c->table.send_insert_count.handler = ngx_http_v3_inc_insert_count_handler;

    cln = ngx_pool_cleanup_add(pc->pool, 0);
    if (cln == NULL) {
        goto failed;
    }

    cln->handler = ngx_http_v3_cleanup_session;
    cln->data = h3c;

    hc->v3_session = h3c;

#if (NGX_HTTP_V3_HQ)
    if (h3c->hq) {
        return NGX_OK;
    }
#endif

    return ngx_http_v3_send_settings(c);

failed:

    ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to create http3 session");

    ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_INTERNAL_ERROR,
                                    "failed to create http3 session");
    return NGX_ERROR;
}


static void
ngx_http_v3_keepalive_handler(ngx_event_t *ev)
{
    ngx_connection_t  *c;

    c = ev->data;

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 keepalive handler");

    ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_NO_ERROR,
                                    "keepalive timeout");
}


static void
ngx_http_v3_cleanup_session(void *data)
{
    ngx_http_v3_session_t  *h3c = data;

    ngx_http_v3_cleanup_table(h3c);

    if (h3c->keepalive.timer_set) {
        ngx_del_timer(&h3c->keepalive);
    }

    if (h3c->table.send_insert_count.posted) {
        ngx_delete_posted_event(&h3c->table.send_insert_count);
    }
}


ngx_int_t
ngx_http_v3_check_flood(ngx_connection_t *c)
{
    ngx_http_v3_session_t  *h3c;

    h3c = ngx_http_v3_get_session(c);

    if (h3c->total_bytes / 8 > h3c->payload_bytes + 1048576) {
        ngx_log_error(NGX_LOG_INFO, c->log, 0, "http3 flood detected");

        ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_NO_ERROR,
                                        "HTTP/3 flood detected");
        return NGX_ERROR;
    }

    return NGX_OK;
}