nodejs/node
Net, TCP, UDP, TLS, and DNS
Owners: @nodejs/net (most paths), @nodejs/crypto (TLS).
Purpose
Expose the BSD-socket-style networking surface that everything else builds on: net.Socket, net.Server, tls.TLSSocket, dgram.Socket, dns.lookup / dns.resolve*. Each of these is a JS class wrapping a libuv handle wrapped by a *Wrap C++ object.
Directory layout
lib/
net.js
tls.js
dns.js
dgram.js
_tls_common.js / _tls_wrap.js // legacy export shells
internal/
net.js
js_stream_socket.js // Duplex-over-Duplex helper used by mock TLS
socketaddress.js
socket_list.js
blocklist.js // SocketAddress block list
dns/ // resolver, promises, utils
tls/ // TLSSocket internals: secure-context, parent, etc.
src/
tcp_wrap.{cc,h} // TCP handle wrap
udp_wrap.{cc,h} // UDP handle wrap
pipe_wrap.{cc,h} // named pipe (uv_pipe_t)
tty_wrap.{cc,h} // TTY (uv_tty_t)
cares_wrap.{cc,h} // c-ares DNS resolver glue
connect_wrap.{cc,h} // ConnectWrap : ReqWrap
connection_wrap.{cc,h} // shared base for TCP + Pipe
node_sockaddr.{cc,h} // SocketAddress / Block list
node_blob.{cc,h} // Blob (used by some net APIs)
crypto/crypto_tls.{cc,h} // TLSWrap : StreamBase
deps/
cares/ // c-aresKey abstractions
| Type / file | Role |
|---|---|
net.Socket (lib/net.js) |
Duplex stream over TCPWrap or PipeWrap. |
net.Server (lib/net.js) |
Listening server; uses TCPWrap.listen + accept. |
TCPWrap (src/tcp_wrap.cc) |
Wraps uv_tcp_t, inherits ConnectionWrap : LibuvStreamWrap : StreamBase. |
UDPWrap (src/udp_wrap.cc) |
Wraps uv_udp_t with recv/send. |
PipeWrap (src/pipe_wrap.cc) |
Wraps uv_pipe_t for IPC and named pipes. |
TTYWrap (src/tty_wrap.cc) |
TTY-aware variant of pipe (uv_tty_t). |
tls.TLSSocket (lib/_tls_wrap.js → lib/tls.js) |
Duplex layered over TLSWrap and a parent Socket. |
TLSWrap (src/crypto/crypto_tls.cc) |
Streams plaintext into OpenSSL and ciphertext out. |
ChannelWrap (src/cares_wrap.cc) |
c-ares DNS channel; dns.resolve* lives here. |
dns.lookup (lib/dns.js) |
Uses libuv getaddrinfo from the threadpool. |
SocketAddress / BlockList (src/node_sockaddr.cc) |
Address parsing + block-list filter for connection acceptance. |
How a TCP request flows
sequenceDiagram
participant JS as net.Socket
participant TCPWrap as TCPWrap (C++)
participant uv as libuv uv_tcp_*
participant K as kernel
JS->>TCPWrap: connect(host, port)
TCPWrap->>uv: uv_tcp_connect
uv->>K: connect(2)
K-->>uv: EPOLLOUT / IOCP
uv-->>TCPWrap: OnConnect
TCPWrap-->>JS: emit 'connect'
JS->>TCPWrap: write(buffer)
TCPWrap->>uv: uv_write
uv->>K: write(2)
K-->>uv: completion
uv-->>TCPWrap: OnAfterWrite
TCPWrap-->>JS: 'drain' if buffer crosses HWM
K->>uv: data ready (EPOLLIN)
uv-->>TCPWrap: OnAlloc + OnRead
TCPWrap-->>JS: emit 'data'TLS layering
graph LR
Plain["TLSSocket (Duplex)"] --> Wrap[TLSWrap]
Wrap --> SSL[OpenSSL BIOs]
Wrap --> Parent[parent net.Socket]
Parent --> TCP[TCPWrap]
SSL --> WrapTLSWrap is itself a StreamBase, so the parent socket can read encrypted bytes from one StreamBase and feed them to OpenSSL via two BIOs (crypto_bio.cc). TLSWrap then exposes the decrypted stream to JS as another StreamBase. The wrap-of-wrap structure is what lets tls.TLSSocket chain over both raw net.Socket and over Duplex user streams (used by tls.connect({ socket })).
OpenSSL access goes through deps/ncrypto/, the project's wrapper library; src/crypto/crypto_tls.cc is built on top.
DNS
Two layers:
dns.lookup— libuv'sgetaddrinfo; runs in the threadpool. JS inlib/dns.js(lookup); C++ insrc/cares_wrap.cc(theGetAddrInfoReqWrap).dns.resolve*anddns.Resolver— c-ares (deps/cares/). TheResolverJS class wraps aChannelWrapthat owns a c-aresares_channel. Eachresolve*call posts aQueryWrapReqWrap; completion fires JS callbacks.
dns.promises exposes the same surface returning Promises (lib/internal/dns/promises.js).
UDP / dgram
dgram.Socket is a EventEmitter (not a stream) over UDPWrap. The C++ side handles receive via uv_udp_recv_start; sends are queued through SendWrap. Multicast / membership is exposed JS-side.
SocketAddress and BlockList
net.SocketAddress / net.BlockList (and the dgram BlockList integration) live in src/node_sockaddr.cc. BlockList allows servers to reject inbound IPs at accept time without ever surfacing them to JS.
Integration points
- HTTP:
http.Serverandhttp.ClientRequestride onnet.Socket. HTTP/2 uses TLS sockets directly; see systems › http-and-quic. undicifetch: vendored atdeps/undici/; uses Node'snet/tlsand an HTTP/1+2 implementation.- Permission model: the
netpermission domain (src/permission/net_permission.cc) gates outbound connect / inbound listen. - Inspector: opens a listening TCP socket using
TCPWrapdirectly from C++.
Entry points for modification
- New TCP feature?
lib/net.jsfor the JS surface,src/tcp_wrap.ccfor handle ops, libuv handle for syscall plumbing. - New TLS option? Threading new options through is awkward — there are three layers:
lib/_tls_wrap.js, thesecureContext(lib/internal/tls/), andsrc/crypto/crypto_context.cc/crypto_tls.cc. Look at any recent--tls-keylog-style PR for the pattern. - New DNS resolver? See
src/cares_wrap.ccQuery<>template; tests attest/parallel/test-dns-*.jsand (for network)test/internet/test-dns-*.js.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.