Implement node:dgram over inbound UDP listeners - #7506
Draft
guybedford wants to merge 2 commits into
Draft
guybedford wants to merge 2 commits into
guybedford wants to merge 2 commits into
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## gbedford/udp-remote-address #7506 +/- ##
===============================================================
- Coverage 38.15% 38.11% -0.05%
===============================================================
Files 858 859 +1
Lines 262910 262561 -349
Branches 24388 24287 -101
===============================================================
- Hits 100313 100073 -240
+ Misses 148928 148856 -72
+ Partials 13669 13632 -37 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Contributor
|
@guybedford Bonk workflow was cancelled. View workflow run · To retry, trigger Bonk again. |
node:dgram was a non-functional stub. A dgram.Socket now works the way net.Server does over TCP listeners: bind() claims a port in the UDP port table (seeded from the worker's declared UDP listeners) and installs a connect handler there; connectHandler() in cloudflare:node routes each inbound UDP flow to the socket bound to the port it arrived on, and every datagram on the flow is emitted as a 'message' event with the peer's rinfo. send() delivers to any peer with a live flow, keyed by address and port, with connected mode fixing the destination; a peer without a flow is unreachable, since the platform has no unconnected UDP egress, and fails with EHOSTUNREACH. An implied bind from send() or connect() takes an ephemeral port rather than a declared listener port. Compatibility: the stub previously accepted anything silently, so code that appeared to work under it did nothing. Argument validation and the already-bound / not-running / is-connected errors now match Node, which only affects call sequences Node itself rejects. No compat flag is added on that basis.
guybedford
force-pushed
the
gbedford/node-dgram
branch
from
September 25, 2026 04:14
d099af6 to
f8d6e48
Compare
Contributor
|
I had a quick look at the code and everything seems good, although I don't think I'm the best person to review this one |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This makes
node:dgramfunctional over the inbound UDPconnect()handler, the same waynode:net'sServeris virtualized over TCP listeners. Previously the module was a silent no-op stub.cloudflare-internal:httpgains audpPortstable seeded from the worker's declared UDP listeners, alongsidetcpPorts.connectHandler()incloudflare:noderoutessocket.protocol === 'udp'flows to thedgram.Socketbound to the port they arrived on.dgram.Socket.bind()claims a declared UDP port with the same rules asnet.Server.listen()(EADDRINUSE/EADDRNOTAVAIL, port 0 takes the first unclaimed declared port). Each inbound flow becomes a peer whose datagrams are emitted as'message'events withrinfo; the flow's request lives until the flow ends or the socket closes.send()(all Node argument forms, plussendtoand connected mode viaconnect()/disconnect()/remoteAddress()) delivers one datagram per call to any peer with a live flow. A v4-mapped peer on the dual-stack listener is reported as IPv4 to audp4socket and matched by either form.EHOSTUNREACHin the callback. An implied bind fromsend()/connect()takes an ephemeral port rather than a declared listener.ERR_FEATURE_UNAVAILABLE_ON_PLATFORM; TTL/broadcast/buffer-size setters validate and record.Tests:
dgram-nodejs-testis rewritten to drive fake platform flows throughhandleAsNodeConnection(declared-port rules, message/rinfo, every send form, mapped addresses, connected mode, implicit bind, close ending flows, option validation); a newudp-dgram-nodeserver test runs a real Node UDP client against anode:dgramecho server in workerd across flow re-creation and concurrent peers.Compatibility: the stub accepted any call sequence silently, so nothing built on it functioned. Validation and the already-bound/not-running/is-connected errors now match Node and only affect sequences Node itself rejects, so no compat flag is added.