Skip to content

net: support AF_UNIX paths in net.BoundSocket#64399

Open
guybedford wants to merge 3 commits into
nodejs:mainfrom
guybedford:net-boundsocket-pipe
Open

net: support AF_UNIX paths in net.BoundSocket#64399
guybedford wants to merge 3 commits into
nodejs:mainfrom
guybedford:net-boundsocket-pipe

Conversation

@guybedford

Copy link
Copy Markdown
Contributor

Extends net.BoundSocket (#63951) with a path option so it can immediately bind a named unix-domain socket (or Windows pipe) synchronously, not just TCP. This gives a public synchronous UDS bind through the same role-neutral handle, instead of reaching into process.binding('pipe_wrap'), just as it replaces the need for tcp_wrap and udp_wrap similarly.

path is mutually exclusive with host/port/ipv6Only/reusePort, and binds in the constructor so conflicts throw there like TCP does. A leading '\0' uses the Linux abstract namespace; an abstract path elsewhere throws ERR_INVALID_ARG_VALUE.

  • address() returns the path string for a pipe (as Server.address() does), the address object for TCP.
  • New isPipe getter to tell the two apart.
  • server.listen(bound) and new net.Socket({ handle: bound }).connect() pick pipe vs TCP from the adopted handle's type.
  • A bound client pipe reports its source path as localAddress.

Note two error codes match libuv rather than intuition: missing parent dir is EACCES (libuv maps ENOENT), over-long path is EINVAL (UV_PIPE_NO_TRUNCATE).

Tests cover sync bind + address(), duplicate-bind EADDRINUSE, the listen/connect round-trip, bound-client localAddress, the abstract namespace, and the error paths.

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/net

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. net Issues and PRs related to the net subsystem. labels Jul 10, 2026
@guybedford guybedford force-pushed the net-boundsocket-pipe branch from 1e91371 to 6a4fee8 Compare July 10, 2026 00:24
@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.93878% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.23%. Comparing base (f2ba101) to head (3429149).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
lib/net.js 96.93% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #64399      +/-   ##
==========================================
- Coverage   92.01%   90.23%   -1.78%     
==========================================
  Files         379      739     +360     
  Lines      170129   241738   +71609     
  Branches    26090    45560   +19470     
==========================================
+ Hits       156544   218139   +61595     
- Misses      13293    15153    +1860     
- Partials      292     8446    +8154     
Files with missing lines Coverage Δ
lib/net.js 94.43% <96.93%> (+3.40%) ⬆️

... and 484 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Ethan-Arrowood Ethan-Arrowood left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with just some doc changes and one question about the implementation.

Comment thread doc/api/net.md
Comment thread doc/api/net.md
Comment thread doc/api/net.md Outdated
Comment thread lib/net.js Outdated
// rather than inferring pipe-ness from a path option on the connect call.
// Other pre-existing handles (e.g. a TLSWrap) are not transport handles, so
// fall back to the path option in that case.
const pipe = this[kBoundSource] ? this._handle instanceof Pipe : !!path;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens here if this._handle is null from the if (this.destroyed) { line just before?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Yeah it would wrongly attempt a TCP connect - fixed to fall back to the path option if the handle is already gone.

@guybedford guybedford force-pushed the net-boundsocket-pipe branch 2 times, most recently from 31a96f5 to 9571737 Compare July 10, 2026 19:52
Signed-off-by: Guy Bedford <guybedford@gmail.com>
Only trust the adopted handle's type when it came from a BoundSocket;
a TLSSocket's _handle is a TLSWrap, not a Pipe, so TLS/HTTPS over pipes
must still infer pipe-ness from the path option.
@guybedford guybedford force-pushed the net-boundsocket-pipe branch from 9571737 to 3429149 Compare July 16, 2026 01:18
Comment thread doc/api/net.md
synchronous port reservation, while for `new net.Socket()`, it allows control
over the local egress port/IP, via `bind(2)` semantics.

A `BoundSocket` binds either a TCP endpoint (`host`/`port`) or a

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the `host`/`port` suggest `host` or `port` here.

Comment thread lib/net.js
// selects the Linux abstract namespace. path is mutually exclusive with the
// TCP options; uv_pipe_bind is synchronous so conflicts throw here.
#bindPipe(options) {
const { path } = options;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, you're destructing path here but not host, port, ipv6Only, and reusePort below. I'd destructure them all.

@jasnell jasnell left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple of nits but otherwise LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-ci PRs that need a full CI run. net Issues and PRs related to the net subsystem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants