Open-Source Wikis

/

nginx

/

Primitives

/

Connection (`ngx_connection_t`)

nginx/nginx

Connection (ngx_connection_t)

Active contributors: Sergey Kandaurov, Maxim Dounin

What it is

ngx_connection_t is the per-connection state struct: the file descriptor, the read and write events, the connection's pool, the listener it came from, the peer's address, optional TLS state, optional QUIC stream pointer, optional UDP state, and a handful of flags. It's also re-used as the per-stream state inside QUIC — every HTTP/3 stream gets its own ngx_connection_t even though there's no separate fd. This is the layer that lets the higher protocols pretend everything is a TCP connection.

Definition

src/core/ngx_connection.h:

struct ngx_connection_s {
    void                  *data;                 /* per-protocol pointer */
    ngx_event_t           *read;
    ngx_event_t           *write;

    ngx_socket_t           fd;

    ngx_recv_pt            recv;
    ngx_send_pt            send;
    ngx_recv_chain_pt      recv_chain;
    ngx_send_chain_pt      send_chain;

    ngx_listening_t       *listening;

    off_t                  sent;
    ngx_log_t             *log;
    ngx_pool_t            *pool;

    int                    type;

    struct sockaddr       *sockaddr;
    socklen_t              socklen;
    ngx_str_t              addr_text;

    ngx_proxy_protocol_t  *proxy_protocol;
    ngx_quic_stream_t     *quic;        /* set if this is a QUIC stream */
    ngx_ssl_connection_t  *ssl;         /* set if this is a TLS connection */
    ngx_udp_connection_t  *udp;

    struct sockaddr       *local_sockaddr;
    socklen_t              local_socklen;

    ngx_buf_t             *buffer;

    ngx_queue_t            queue;       /* link in the per-cycle reusable list */

    ngx_atomic_uint_t      number;      /* the *N counter you see in logs */

    ngx_msec_t             start_time;
    ngx_uint_t             requests;

    unsigned               buffered:8;
    unsigned               log_error:3;
    unsigned               timedout:1;
    unsigned               error:1;
    unsigned               destroyed:1;
    unsigned               pipeline:1;
    unsigned               idle:1;
    unsigned               reusable:1;
    unsigned               close:1;
    unsigned               shared:1;
    unsigned               sendfile:1;
    unsigned               sndlowat:1;
    unsigned               tcp_nodelay:2;
    unsigned               tcp_nopush:2;
    unsigned               need_last_buf:1;
    unsigned               need_flush_buf:1;

#if (NGX_THREADS || NGX_COMPAT)
    ngx_thread_task_t     *sendfile_task;
#endif
};

Lifecycle

stateDiagram-v2
    [*] --> Pool: ngx_get_connection (pop from free list)
    Pool --> Reading: ngx_http_init_connection / ngx_mail_init_connection / ngx_stream_init_connection
    Reading --> Working: read handler fires
    Working --> Reading: keep-alive cycle
    Working --> Closing: ngx_close_connection
    Closing --> [*]: pool destroyed, slot pushed back

ngx_get_connection(fd, log) (src/core/ngx_connection.c) pops a slot from cycle->free_connections, attaches the fd, the log, and a freshly-allocated pool, and returns. ngx_close_connection(c) (same file) cancels timers, removes events from the kernel poller, destroys the pool, and pushes the slot back.

The connection table is pre-allocated to worker_connections entries at cycle init. There's no per-connection malloc on the hot path.

The data pointer

c->data is the protocol-specific state. For HTTP/1.1, it's the ngx_http_connection_t (which itself holds a pointer to the current ngx_http_request_t). For HTTP/2, it's the ngx_http_v2_connection_t. For HTTP/3, it's the QUIC connection or stream-specific state. For Mail / Stream, it's their session structs.

This is the indirection that lets generic event-loop code call c->read->handler(c->read) without knowing what protocol is in play.

I/O function pointers

c->recv, c->send, c->recv_chain, c->send_chain are set per-connection:

  • For plain TCP — set by ngx_io (the per-OS function table) at connection init.
  • For TLS — replaced by ngx_ssl_recv / ngx_ssl_send after handshake.
  • For QUIC streams — replaced by ngx_quic_* functions.

Higher-level code calls c->send_chain(c, chain, limit) and lets the right implementation handle the details.

Connection numbering

c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1) — a globally unique id for the connection. This is the *N you see in error logs. Useful for grepping out one connection's lifecycle from error_log debug.

Reusable connections

The c->reusable bit means "this connection is idle and can be closed if we run out of slots." Workers keep a cycle->reusable_connections_queue (LRU). When a worker hits the connection limit, it walks this queue and closes the oldest reusable connections to free slots for new accepts.

ngx_reusable_connection(c, 1) adds; (c, 0) removes. HTTP keep-alive idle connections are typically reusable.

QUIC streams as connections

In QUIC, each stream gets a fresh ngx_connection_t with c->quic = stream_ptr and c->fd = -1. c->recv / c->send are wired to QUIC stream-buffer functions. The HTTP/3 layer creates one such fake connection per stream so the request engine can reuse all the existing code.

This is one of the more elegant pieces of design — the "connection" abstraction is general enough to cover both TCP sockets and QUIC streams without conditionals scattered throughout the request engine.

Listeners

ngx_listening_t (in the same header) is the configured listening socket. Each carries:

  • The bound sockaddr
  • The accept handler (the per-protocol init_connection)
  • Reuseport / IPv6-only / TCP-fastopen / deferred-accept flags
  • A backpointer to the connection that's been allocated for the listen fd

Listeners survive across reloads — ngx_init_cycle matches new listening blocks against old_cycle->listening and reuses fds where possible. That's what keeps in-flight connections alive across nginx -s reload.

Cross-references

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Connection (`ngx_connection_t`) – nginx wiki | Factory