envoyproxy/envoy
Listener manager
The listener manager is the subsystem that turns a Listener configuration message — static from the bootstrap or dynamic from LDS — into a bound socket on every worker, complete with filter chains and TLS contexts. The implementation lives in source/common/listener_manager/.
Purpose
Concretely the listener manager is responsible for:
- Parsing
envoy::config::listener::v3::Listenermessages and constructing in-processListenerImplobjects. - Subscribing to LDS for dynamic listener updates.
- Selecting the right filter chain for each new connection (by SNI, ALPN, source IP, transport, …).
- Coordinating listener add/update/remove with workers, including in-place updates that don't drop connections.
- Draining listeners during shutdown and hot restart.
Layout
source/common/listener_manager/
├── listener_manager_impl.{h,cc} # The top-level manager (main thread)
├── listener_impl.{h,cc} # A single listener (large, ~68k lines)
├── filter_chain_manager_impl.{h,cc} # Picks the right filter chain for a connection
├── connection_handler_impl.{h,cc} # Per-worker accept loop
├── active_tcp_listener.{h,cc} # Active TCP listener on a worker
├── active_tcp_socket.{h,cc} # Single accepted socket pre-filter-chain
├── active_stream_listener_base.{h,cc}
├── active_raw_udp_listener_config.{h,cc}
└── lds_api.{h,cc} # LDS subscription glueKey abstractions
| Type | File | Purpose |
|---|---|---|
ListenerManagerImpl |
listener_manager_impl.h |
Owns ListenerImpls, processes adds/updates/removes |
ListenerImpl |
listener_impl.h |
A configured listener: address, options, filter chain manager |
FilterChainManagerImpl |
filter_chain_manager_impl.h |
Indexes filter chains and matches connections to them |
ConnectionHandlerImpl |
connection_handler_impl.h |
Per-worker accept dispatcher |
ActiveTcpListener |
active_tcp_listener.h |
Listener instance running on a single worker |
ActiveTcpSocket |
active_tcp_socket.h |
An accepted socket while listener filters run |
LdsApi |
lds_api.h |
xDS subscription that feeds the manager |
Lifecycle of a listener
sequenceDiagram
participant XDS as xDS / Bootstrap
participant LM as ListenerManagerImpl<br/>(main thread)
participant LI as ListenerImpl
participant W as Worker
participant CH as ConnectionHandlerImpl<br/>(per-worker)
XDS->>LM: addOrUpdateListener(Listener msg)
LM->>LI: construct ListenerImpl
LI->>LI: parse address, build FilterChainManager
LI->>LI: build TLS contexts
LM->>W: server_->workers().addListener(listener)
W->>CH: post addListener
CH->>CH: bind socket / inherit hot-restart fd
CH->>CH: start acceptingWhen a Listener arrives, the manager walks a state machine:
- Construct a fresh
ListenerImplon the main thread — including all filter chain factories, transport socket factories, and the SDS subscriptions for any inline TLS contexts. - Wait for any init targets registered by the listener (typically SDS) to complete.
- Distribute the listener to every worker via
Server::WorkerImpl::addListener. Each worker'sConnectionHandlerImplthen opens the socket and binds it. - If this is an update, the new listener takes over from the old one in-place when configured to do so (LISTENER_REPLACING_VIA_REPLACE on the worker), and the old listener is drained.
Filter chain matching
FilterChainManagerImpl::findFilterChain (filter_chain_manager_impl.cc) is the heart of the listener at request time. Given an ActiveTcpSocket carrying server name (SNI), ALPN, source IP, transport, and connection-time metadata, it finds the matching filter chain by walking a series of indexed lookups (most-specific first):
destination port → server names → transport protocol → application protocols
→ source type → source IPs → source ports → direct source IPsEach filter chain in the configuration becomes a leaf in this tree, ordered by specificity. The result is a Network::FilterChain* that the ActiveTcpSocket then uses to instantiate the network filters.
Listener filters
Before a filter chain is selected, listener filters (source/extensions/filters/listener/) inspect the bare socket. They can read the first few bytes (TLS ClientHello, proxy protocol, …) to influence matching. The shipped listener filters:
tls_inspector— peeks at the TLS ClientHello to discover SNI/ALPN.original_dst— reads the SO_ORIGINAL_DST socket option.original_src— restores the original source IP for transparent proxying.proxy_protocol— parses HAProxy proxy protocol v1/v2.http_inspector— peeks at HTTP/1 first bytes to distinguish HTTP/1 vs HTTP/2 upgrade.
Listener filters run on the worker thread, in ActiveTcpSocket::startFilterChain. They are async: a filter can StopIteration to wait for more bytes and ContinueIteration once it has what it needs.
Network filters
Once a filter chain is selected, ActiveTcpListener::onAcceptWorker constructs a Network::ConnectionImpl and instantiates the chain of network filters (source/extensions/filters/network/). The terminal network filter for HTTP listeners is the HTTP connection manager; for TCP it is tcp_proxy.
In-place updates
A listener update with the same address can be applied without dropping existing connections, provided the new listener's traffic-direction settings, socket options, etc. are compatible. The mechanism is in listener_impl.cc:
- The new listener inherits the old socket's file descriptor.
- New connections use the new filter chain manager.
- Old connections continue with their existing filter chains until they close.
- The old
ListenerImpllingers (and counts toward stats) until its final connection drains.
This is the same socket-passing pattern used by hot restart, but within a single process.
LDS
LdsApiImpl (lds_api.cc) is the bridge between xDS and the listener manager. It subscribes to envoy.service.listener.v3.ListenerDiscoveryService over a configured ConfigSource, deserialises the Listener resources, and calls ListenerManagerImpl::addOrUpdateListener for each.
LDS supports both state-of-the-world (SotW) and delta variants. The manager treats a missing resource in a SotW response as a removal.
Drain
When a listener is removed (via LDS, POST /drain_listeners, or shutdown), the manager:
- Stops accepting new connections immediately.
- Asks each worker to begin draining its
ActiveTcpListener. - Coordinates with the drain manager to apply the configured drain timing.
- Once the last connection is gone, frees the listener.
For HTTP/2 listeners this includes sending GOAWAY; for HTTP/1 it includes adding Connection: close. The behaviour is implemented in the codecs and triggered by the listener's drain state.
Integration points
- Workers — every worker has its own
ConnectionHandlerImpland per-workerActiveTcpListenerinstances. The listener manager is the only entity that adds/removes listeners on workers. - xDS — LDS subscription. Bootstrap-static listeners skip xDS entirely.
- Cluster manager — listener filter chains reference clusters (e.g.
tcp_proxyconfig). The cluster manager must already exist before listeners are constructed. - Secret manager — TLS contexts in listener filter chains are populated by SDS.
- Init manager — listeners with SDS subscriptions register init targets that gate "ready to serve".
- Drain manager — drives the drain sequence on shutdown / removal.
Entry points for modification
- Adding a listener filter: implement
Network::ListenerFilterand a config factory; register insource/extensions/filters/listener/<name>/and add toextensions_build_config.bzl. - Adding a network filter: same, under
source/extensions/filters/network/<name>/. - Changing the matching algorithm: read
filter_chain_manager_impl.ccand the user-facing rules inapi/envoy/config/listener/v3/listener_components.proto. - Modifying listener lifecycle:
listener_manager_impl.ccandlistener_impl.cc.
See also
- HTTP connection manager — the filter that runs after listener+network filters for HTTP traffic.
- Hot restart — uses the same socket-passing pattern to migrate listeners across processes.
- xDS configuration — LDS lives here.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.