Skip to content

TCP: Add Matter TCP transport support#3472

Open
Apollon77 wants to merge 30 commits intomainfrom
tcp-rebased
Open

TCP: Add Matter TCP transport support#3472
Apollon77 wants to merge 30 commits intomainfrom
tcp-rebased

Conversation

@Apollon77
Copy link
Copy Markdown
Collaborator

@Apollon77 Apollon77 commented Mar 27, 2026

Summary

Adds full TCP transport support to matter.js for both client and server side, following the Matter 1.5.1 specification. This replaces the draft PR #3465 with a clean, rebased commit history.

Commit overview (8 commits):

  1. Generalize transport abstractions — Rename ConnectionlessTransportTransport, add ChannelType enum (UDP/TCP), ServerAddressTcp type
  2. TCP socket platform layerTcpSocket/TcpServerSocket interfaces, Node.js implementation (NodeJsTcpSocket/NodeJsTcpServer), React Native support, mock infrastructure
  3. TCP transport coreTcpConnection (4-byte LE length-prefix framing, stream reassembly, receive buffer cap), TcpTransport (connection pool, max 3 connections/peer IP, 10s idle timeout)
  4. Server/client runtime wiringNetworkServer TCP config (tcp: boolean | {incoming, outgoing}, transportPreference), NetworkClient per-peer preference, ServerNetworkRuntime port retry loop (UDP IPv4/IPv6 + TCP), DNS-SD T key, multicast interface fallback
  5. Session/exchange/peer integration — Session-to-connection binding (connection drop → evict sessions, last session → close connection), MessageChannel TCP lifecycle, Peer.newestSession(type?) with soft/hard transport preference, PeerConnection transport constraint, group sessions always UDP
  6. Invoke & Large Message QualitylargeMessage quality → requiredTransport: TCP, CommissioningController/MatterController TCP option forwarding, PASE always UDP
  7. Test suite — 85+ tests across 8 files (TcpConnection, TcpTransport, MockTcp, TcpSessionBinding, InvokeLargeMessage, NodeJsTcpSocket, NodeJsTcpServer, ClientNodeTcp, DeviceAdvertiser)
  8. Shell, examples, CI — Shell TCP enabled by default, nodes tcp/nodes descriptor commands, --tcp device flag, TEST_PREFER_TCP=1 env var, matterjs-tests-core-tcp CI job, PICS MCORE.SC.TCP=1

Key design decisions

  • N:1 session-to-connection mapping matching CHIP SDK pattern
  • Soft transport preference (TCP preferred → fall back to UDP) vs hard requirement (requiredTransport for Large Message Quality, no fallback)
  • TCP incoming connections use ephemeral remote ports — operational address sourced from mDNS, not TCP connection
  • DoS protections: receive buffer cap (2x maxPayloadSize), max 3 connections per peer IP, 10s idle timeout on new connections, zero-length message rejection
  • Port retry loop: when auto-assigning ports, retries up to 10 times if IPv4 or TCP port conflicts with IPv6

Follow-up items (not in this PR)

  • Socket abstraction refactoring (StreamSocket/UdpSocket with AsyncIterable)
  • MESSAGE_TOO_LARGE status report before close
  • BDX auto-prefer TCP when peer supports it

Replaces #3465.

🤖 Generated with Claude Code

Apollon77 and others added 7 commits March 27, 2026 08:39
Rename ConnectionlessTransport to Transport as the base interface.
Add ChannelType enum (UDP/TCP) to Channel and ServerAddressTcp type.
Update all consumers (BLE, UDP, protocol layer) to use the new names.
This prepares the transport layer for connection-oriented (TCP) support.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add TcpSocket/TcpServerSocket interfaces with shared constants
(DEFAULT_MAX_TCP_MESSAGE_SIZE=64000, timeouts, keep-alive).
Implement NodeJsTcpSocket/NodeJsTcpServer for Node.js with
TCP_NODELAY, keep-alive, graceful close with timeout fallback.
Add React Native TCP support via react-native-tcp-socket.
Add mock TCP socket/server for testing infrastructure.
Add connectTcp/createTcpServer to Network abstraction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
TcpConnection: Matter message framing with 4-byte LE length prefix,
stream reassembly, receive buffer cap (2x maxPayloadSize), oversized
message rejection, incoming vs outgoing connection distinction.
TcpTransport: connection pool keyed by ip:port, max 3 connections per
peer IP, 10s idle timeout on new inbound connections, combined TCP
server and client roles.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add TCP configuration to NetworkServer (tcp: boolean | {incoming, outgoing},
transportPreference: "tcp" | "udp") and NetworkClient (per-peer preference).
Create TcpTransport in ServerNetworkRuntime with port retry loop ensuring
UDP IPv4/IPv6 and TCP all bind to the same port. Set DNS-SD TCP bitmap on
DeviceAdvertiser. Add multicast interface fallback for TCP-preferred
controllers where no inbound UDP traffic provides interface discovery.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ExchangeManager: session-to-connection binding — connection drop evicts
all sessions, last session close triggers connection close. Safety
cleanup for session observers on close.
MessageChannel: TCP channels not closed by MessageChannel.close()
(lifecycle managed by ExchangeManager). Add supportsLargeMessages.
Peer: newestSession() method with optional ChannelType filter,
transportPreference field, TCP operational address from mDNS.
PeerExchangeProvider: transport selection — requiredTransport is hard
(no fallback), preference is soft (TCP → fall back to any).
PeerConnection: transportConstraint converts addresses to TCP type.
PeerSet: skip TCP sessions in operationalAddressOf (ephemeral ports).
Sessions: TCP suffix in NodeSession.via and UnsecuredSession.via,
group sessions always use UDP.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ClientCommandMethod reads commandModel.effectiveQuality.largeMessage at
factory time and sets invoke.largeMessage = true for Large Message
Quality commands, which maps to requiredTransport: ChannelType.TCP.
CommissioningController/MatterController forward tcp and
transportPreference options. PASE always uses UDP (never TCP).
ControllerCommissioningFlow enforces UDP for commissioning.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
85+ tests across 8 test files covering:
- TcpConnection: framing, reassembly, buffer cap, oversized rejection (16)
- TcpTransport: connection pool, idle timeout, per-IP limits (11)
- MockTcp: mock socket/server integration (11)
- TcpSessionBinding: session eviction on disconnect, connection close
  on last session removal, lifecycle management (17)
- InvokeLargeMessage: Large Message Quality → TCP requirement (7)
- NodeJsTcpSocket: connect, close, destroy, timeout (6)
- NodeJsTcpServer: listen, accept, close cleanup (5)
- ClientNodeTcp: transport preference, TCP session selection (12)
- DeviceAdvertiser: DNS-SD T key TCP advertisement (3)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 27, 2026 08:11
@Apollon77 Apollon77 requested a review from lauckhart as a code owner March 27, 2026 08:11
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds first-class TCP transport support across the matter.js stack (general/network abstractions, protocol/session/exchange, node runtime wiring, platform implementations, tests, and CHIP harness/CI), aligning behavior with Matter 1.5.1 transport expectations.

Changes:

  • Introduces TCP socket + transport abstractions and platform implementations (Node.js, React Native, mock network), and generalizes ConnectionlessTransportTransport (+ TransportSet).
  • Integrates TCP into protocol/session/exchange lifecycle (transport preference/constraints, session binding, disconnect eviction, large-message invoke requiring TCP, DNS-SD “T” key advertisement).
  • Adds extensive TCP-focused unit/integration tests and updates CHIP testing/CI configuration and examples/shell UX.

Reviewed changes

Copilot reviewed 91 out of 93 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
support/chip-testing/src/TvTestInstance.ts Enables TCP + env-driven transport preference in CHIP TV test app config
support/chip-testing/src/RvcTestInstance.ts Enables TCP + env-driven transport preference in CHIP RVC test app config
support/chip-testing/src/ControllerTestInstance.ts Enables outgoing TCP for controller instances when TEST_PREFER_TCP=1
support/chip-testing/src/BridgeTestInstance.ts Enables TCP + env-driven transport preference in CHIP bridge test app config
support/chip-testing/src/AllClustersTestInstance.ts Enables TCP + env-driven transport preference in CHIP all-clusters test app config
support/chip-testing/patched-test-files/certification/ci-pics-values Sets MCORE.SC.TCP=1 for certification PICS
packages/testing/src/chip/matter-js-pics.properties Updates PICS to reflect TCP support
packages/react-native/src/net/react-native-tcp-socket.d.ts Adds module augmentation typings for react-native-tcp-socket
packages/react-native/src/net/index.ts Exports React Native TCP server/socket implementations
packages/react-native/src/net/TcpSocketReactNative.ts React Native TcpSocket wrapper + connect helper
packages/react-native/src/net/TcpServerReactNative.ts React Native TcpServerSocket wrapper
packages/react-native/src/net/NetworkReactNative.ts Wires TCP server/connect into React Native Network implementation
packages/react-native/src/ble/ReactNativeBleChannel.ts Migrates BLE central interface to new Transport type
packages/react-native/src/ble/ReactNativeBle.ts Updates BLE central interface typing to Transport
packages/react-native/package.json Adds react-native-tcp-socket dependency
packages/protocol/test/protocol/TcpSessionBindingTest.ts Adds tests for session↔TCP connection binding + disconnect behavior
packages/protocol/test/protocol/DeviceAdvertiserTest.ts Adds tests for operational advertisement TCP “T” key exposure
packages/protocol/test/mdns/MdnsTest.ts Updates tests for Transport.Listener rename
packages/protocol/test/action/InvokeLargeMessageTest.ts Adds tests for Large Message Quality → invoke.largeMessage behavior
packages/protocol/src/session/UnsecuredSession.ts Improves diagnostics to include transport type for unsecured sessions
packages/protocol/src/session/SessionManager.ts Updates transport provider types to Transport.Provider
packages/protocol/src/session/NodeSession.ts Improves diagnostics to include transport type for secure sessions
packages/protocol/src/session/GroupSession.ts Updates group session creation to use Transport.Provider
packages/protocol/src/protocol/ProtocolMocks.ts Updates mock channel typing to UdpNetworkChannel
packages/protocol/src/protocol/MessageChannel.ts Adds TCP-aware behavior for large messages + address override rules + TCP close semantics
packages/protocol/src/protocol/ExchangeProvider.ts Adds requiredTransport constraint for exchanges
packages/protocol/src/protocol/ExchangeManager.ts Adds disconnect handling + session eviction + last-session TCP connection closure
packages/protocol/src/protocol/DeviceAdvertiser.ts Adds TCP transport bitmap support to operational advertisements
packages/protocol/src/peer/PeerSet.ts Extends socket opening to TCP/UDP addresses and improves errors
packages/protocol/src/peer/PeerExchangeProvider.ts Implements session selection/connect logic honoring TCP preference/requirements
packages/protocol/src/peer/PeerDescriptor.ts Broadens operational address type to ServerAddressIp
packages/protocol/src/peer/PeerConnection.ts Adds transport constraint and address typing updates for TCP connections
packages/protocol/src/peer/PeerAddressMonitor.ts Updates to newestSession() call form
packages/protocol/src/peer/Peer.ts Adds transport preference, session filtering by type, and TCP operational address handling
packages/protocol/src/peer/NetworkProfile.ts Adjusts fallback defaults to conservative and removes legacy “unknown” template
packages/protocol/src/peer/ControllerCommissioningFlow.ts Tightens typing around cluster schemas and cluster .Complete usage
packages/protocol/src/peer/ControllerCommissioner.ts Migrates to TransportSet and enforces “PASE cannot use TCP” guard
packages/protocol/src/ble/Ble.ts Migrates BLE transport typing to Transport
packages/protocol/src/action/request/Invoke.ts Removes legacy invoke command path and adds largeMessage support surface
packages/protocol/src/action/client/ClientInteraction.ts Enforces TCP for large-message invokes and adjusts response decoding logic
packages/nodejs/test/net/NodeJsTcpSocketTest.ts Adds Node.js TCP socket wrapper tests
packages/nodejs/test/net/NodeJsTcpServerTest.ts Adds Node.js TCP server wrapper tests
packages/nodejs/src/net/index.ts Exports Node.js TCP server/socket
packages/nodejs/src/net/NodeJsUdpChannel.ts Adds multicast interface fallback when UDP inbound traffic is absent (e.g. TCP sessions)
packages/nodejs/src/net/NodeJsTcpSocket.ts Implements Node.js TcpSocket wrapper
packages/nodejs/src/net/NodeJsTcpServer.ts Implements Node.js TcpServerSocket wrapper
packages/nodejs/src/net/NodeJsNetwork.ts Adds TCP server/connect support to Node.js Network
packages/nodejs-shell/src/shell/cmd_nodes.ts Adds shell commands for TCP preference + descriptor inspection
packages/nodejs-shell/src/MatterNode.ts Enables TCP by default for shell controller node
packages/nodejs-ble/src/NodeJsBle.ts Migrates BLE transport typing to Transport
packages/nodejs-ble/src/NobleBleChannel.ts Migrates BLE central interface to Transport
packages/nodejs-ble/src/BlenoPeripheralInterface.ts Migrates peripheral interface listener typing to Transport.Listener
packages/node/test/node/ClientNodeTest.ts Updates persisted peer state schema to include transportPreference
packages/node/test/node/ClientNodeTcpTest.ts Adds ClientNode TCP wiring tests (availability + preference plumbing)
packages/node/test/node/ClientAddressProbeTest.ts Updates address typing to ServerAddressIp
packages/node/src/node/server/InteractionServer.ts Removes stored operational address from subscription model
packages/node/src/node/client/PeerBehavior.ts Updates cluster instrumentation to use registry/composer and supports unknown attrs/commands
packages/node/src/node/client/ClientCommandMethod.ts Plumbs Large Message Quality into invoke.largeMessage
packages/node/src/behavior/system/subscriptions/SubscriptionsServer.ts Re-establishes subscriptions with TCP constraint when last address was TCP
packages/node/src/behavior/system/sessions/SessionsBehavior.ts Updates behavior state/event declarations
packages/node/src/behavior/system/network/ServerNetworkRuntime.ts Adds TcpTransport creation + advertises TCP support bitmap; switches to TransportSet
packages/node/src/behavior/system/network/NetworkServer.ts Adds server TCP enablement + default transport preference config
packages/node/src/behavior/system/network/NetworkClient.ts Adds per-peer transportPreference persisted state and maps to protocol Peer
packages/node/src/behavior/system/network/NetworkBehavior.ts Updates behavior state declaration
packages/node/src/behavior/system/controller/ControllerBehavior.ts Migrates controller networking to TransportSet
packages/node/src/behavior/cluster/ClusterBehaviorType.ts Refactors behavior derivation to be driven by ClusterType (and command model plumbing)
packages/matter.js/src/MatterController.ts Adds controller TCP options and migrates to TransportSet
packages/matter.js/src/CommissioningController.ts Adds controller TCP options and updates BasicInformation typing
packages/general/test/net/tcp/TcpTransportTest.ts Adds TcpTransport tests (connect/reuse/disconnect/close paths)
packages/general/test/net/tcp/TcpConnectionTest.ts Adds TcpConnection framing/reassembly/limits tests
packages/general/test/net/mock/MockTcpTest.ts Adds mock TCP socket/server tests and MockNetwork TCP capability checks
packages/general/test/net/dns-sd/dns-sd-helpers.ts Broadens helper typing to ServerAddressIp
packages/general/src/net/udp/UdpInterface.ts Migrates UDP interface to Transport and renames channel typing to UdpNetworkChannel
packages/general/src/net/udp/UdpChannel.ts Migrates listener typing to Transport.Listener
packages/general/src/net/tcp/index.ts Adds TCP net exports
packages/general/src/net/tcp/TcpTransport.ts Implements TcpTransport with pooling, inbound server, and disconnect hooks
packages/general/src/net/tcp/TcpSocket.ts Defines TcpSocket/TcpServerSocket abstractions and constants
packages/general/src/net/tcp/TcpConnection.ts Implements TCP framing, reassembly, and DoS protections
packages/general/src/net/mock/index.ts Exports mock TCP server/socket
packages/general/src/net/mock/NetworkSimulator.ts Adds host registry + IP→network lookup for TCP routing
packages/general/src/net/mock/MockTcpSocket.ts Implements mock TCP socket pairs for tests
packages/general/src/net/mock/MockTcpServer.ts Implements mock TCP server registration/accept logic
packages/general/src/net/mock/MockRouter.ts Extends mock router packet typing to include TCP packets
packages/general/src/net/mock/MockNetwork.ts Adds TCP server/connect support and advertises TCP capability
packages/general/src/net/index.ts Exports TCP modules and replaces ConnectionlessTransport with Transport
packages/general/src/net/dns-sd/IpService.ts Broadens discovered addresses to ServerAddressIp
packages/general/src/net/Transport.ts Introduces Transport, ConnectionOrientedTransport, and TransportSet
packages/general/src/net/ServerAddress.ts Adds ServerAddressIp union and TCP equality handling
packages/general/src/net/Network.ts Adds default TCP server/connect hooks to Network abstraction
packages/general/src/net/Channel.ts Adds TCP channel type, IpNetworkChannel widening, and isUdpNetworkChannel helper
package-lock.json Updates lockfile for new React Native TCP dependency chain
examples/device-onoff/src/DeviceNode.ts Adds --tcp config flag and passes it into network config
.github/workflows/chip-tool-tests.yml Adds CI job to run CHIP core tests with TCP preferred

Comment thread packages/general/src/net/tcp/TcpConnection.ts Outdated
Comment thread packages/nodejs/src/net/NodeJsTcpListener.ts
Comment thread packages/react-native/src/net/TcpSocketReactNative.ts Outdated
Comment thread packages/general/src/net/tcp/TcpConnection.ts Outdated
Comment thread packages/general/src/net/tcp/TcpConnection.ts Outdated
Comment thread packages/general/src/net/tcp/TcpConnection.ts Outdated
Shell: TCP enabled by default, 'nodes tcp <id> on/off' command for
per-node transport preference, 'nodes descriptor <id>' for diagnostics.
Device example: --tcp flag enables TCP on the onoff device.
CHIP testing: TCP enabled on AllClusters/RVC/TV/Bridge test apps,
TEST_PREFER_TCP=1 env var sets transport preference for controller
identities (outgoing-only TCP). New matterjs-tests-core-tcp CI job.
PICS: MCORE.SC.TCP=1.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Apollon77 Apollon77 force-pushed the tcp-rebased branch 2 times, most recently from 7666f8a to acb494f Compare March 27, 2026 10:05
…await server close

- Fix >= to > in send/receive size checks so messages exactly at
  maxMessageSize are accepted (inclusive boundary)
- Close connection on zero-length TCP frames instead of silently
  discarding (DoS protection)
- Await server.close() callback in NodeJsTcpServer so callers don't
  race with still-open ports
- Use ServerAddressIp for Observable type to match IpNetworkChannel
- Remove Buffer dependency in RN TCP socket (use TextEncoder instead)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Apollon77 and others added 2 commits March 27, 2026 11:15
The merge from main silently dropped changes from #3469. Re-apply:
add "unknown" template to NetworkProfiles.Templates, auto-detect
fallback profile at startup based on endpoint device classification.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread packages/general/src/net/Transport.ts
Comment thread packages/general/src/net/Transport.ts
Comment thread packages/general/src/net/tcp/TcpSocket.ts Outdated
Comment thread packages/general/src/net/Network.ts Outdated
Comment thread packages/nodejs/src/net/NodeJsNetwork.ts
Comment thread packages/protocol/src/peer/Peer.ts Outdated
Comment thread packages/protocol/src/peer/PeerConnection.ts Outdated
Comment thread packages/node/src/behavior/cluster/ClusterBehaviorType.ts Outdated
Comment thread packages/protocol/src/peer/ControllerCommissioningFlow.ts Outdated
Comment thread packages/node/src/behavior/cluster/ClusterBehaviorType.ts
Apollon77 and others added 9 commits March 27, 2026 17:24
ProtocolService.ts: restore deprecated/disallowed attribute exclusion
ProtocolServiceTest.ts: restore EventList deprecation test
Shell.ts: restore SIGINT handling fix

These were accidentally reverted when checking out files from the
old tcp-backup branch during the rebase.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ServerAddressIp is now transport-agnostic (no type field). Transport
type is only present on ServerAddressUdp/ServerAddressTcp subtypes.
Commissionable discovery stamps addresses as UDP (PASE is always UDP),
operational discovery leaves them typeless.

Address helpers: isIp(), isBle(), protocolOf() replace switch on type.
isEqual() compares IP addresses by ip+port only, ignoring transport.

Renames: TcpServerSocket → TcpServer, tcp → supportedTransports on
DeviceAdvertiser, transportConstraint → transport on Peer/PeerConnection.

TcpConnection: use Bytes.dataViewOf, subarray instead of slice,
extracted #consume helper. connectTcp accepts optional timeout.
NetworkServer: removed redundant defaults. Peer.connect respects
transport filter. Removed verbose framing comments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ller (30s)

PaseDiscovery now defaults to 60s when no timeout is provided,
matching CommissioningDiscovery behavior. The legacy test controller
overrides to 30s for faster test turnaround.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Apollon77 Apollon77 changed the title Add Matter TCP transport support TCP: Add Matter TCP transport support Mar 31, 2026
Apollon77 and others added 5 commits April 2, 2026 08:42
…dChannel -> TCP (#3508)

* Restructure transport abstractions: semantic naming and ConnectedChannel

Rename transport layer types to match their actual roles:
- Layer 1 (Platform): TcpSocket→TcpConnection, TcpServer→TcpListener,
  UdpChannel→UdpSocket (+ all platform implementations and mocks)
- Layer 2 (Channel): TcpConnection class→TcpChannel, UdpConnection→UdpChannel
- Layer 3 (Transport): UdpInterface→UdpTransport

Introduce ConnectedChannel interface (AsyncIterable<Bytes> + send + onClose)
shared by TcpChannel and BleChannel for stream-oriented transports.
TcpChannel and all BLE implementations now support async iteration for
message delivery alongside existing callback-based onMessage/onData.

Simplify ExchangeManager coupling:
- Add transportChannel getter on MessageChannel (replaces .channel.channel)
- Add isConnectionOrientedTransport() type guard (replaces duck-typing)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add tests for TcpChannel async iteration and ConnectedChannel type guard

Tests cover: basic iteration, close termination, remote disconnect
termination, queued-then-close delivery, callback+iterator coexistence,
and isConnectedChannel() type guard.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Address PR review: rename TcpTransport internals, remove duplicate channel getter

TcpTransport: #connections→#channels, #server→#listener,
#registerConnection→#registerChannel, update comment to "registry"
with 1:1 session:channel binding.

Remove old MessageChannel.channel getter — all callers now use
transportChannel. Migrate remaining .channel.channel references
in CASE/PASE/session code.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Move TcpChannel and TcpTransport to @matter/protocol

TcpChannel (Matter framing) and TcpTransport (connection registry) are
protocol-level concerns, not platform abstractions. Move them from
@matter/general to @matter/protocol/src/transport/tcp/.

TcpConnection interface (platform socket abstraction) and constants
stay in @matter/general where platform implementations consume them.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Push AsyncIterable down to TcpConnection socket layer with backpressure

TcpConnection interface now extends AsyncIterable<Bytes>. Platform
implementations deliver raw byte chunks via async iteration:

- NodeJsTcpConnection: socket starts paused, resumes on iterator pull,
  pauses when queue grows — true OS-level TCP backpressure
- MockTcpConnection: queue-based iteration for testing
- TcpConnectionReactNative: queue-based (RN socket lacks pause/resume)

TcpChannel now consumes socket via for-await loop instead of onData
callback, with natural backpressure propagation.

The old onData callback is kept as deprecated optional method for
backward compatibility with existing tests and consumers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix unhandled promise rejections and double-fire in transport code

- BlenoBleServer: replace void handleIncomingBleData with .catch(log)
- TcpChannel: guard #handleClose against double-fire on socket error,
  fire close listeners from close() so they always execute exactly once
- NobleBleChannel: replace silent .catch(() => {}) with error logging
- ReactNativeBleChannel: replace silent .catch(() => {}) with error logging

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Remove onData from TcpConnection — async iteration is the only API

Remove deprecated onData callback from TcpConnection interface and all
platform implementations (NodeJs, Mock, ReactNative). All consumers
now use async iteration for receiving data, which provides natural
backpressure. Update all tests to use for-await / iterator.next().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. TcpChannel: iterator queue only fills when no onMessage listeners
   are active (mutually exclusive) — prevents unbounded memory growth
2. TcpConnectionReactNative.close(): await socket teardown with
   timeout + destroy fallback (matching NodeJs pattern)
3. TcpListenerReactNative: track active sockets, destroy on close
   so server.close() completes (matching NodeJs pattern)
4. TcpChannel.name: incoming connections show tcp://[ip]«port using
   Mark.INBOUND to distinguish client ephemeral port from our listener
5. NobleBleChannel.send(): throw BleDisconnectedError instead of
   silent return so callers know the send failed
6. MockTcpConnection.send(): re-check peer.closed after macrotask
   yield to prevent delivery to closed connections
7. TcpTransport.openChannel: in-flight promise map deduplicates
   concurrent connect attempts for the same address

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Starting the socket paused in the constructor caused close events to
not fire on some Node.js versions/CI environments. Instead, let data
flow normally and only pause when the iterator queue grows beyond 1
chunk. Resume when the queue drains or the iterator waits for data.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Apollon77 and others added 4 commits April 15, 2026 11:04
# Conflicts:
#	package-lock.json
#	packages/protocol/src/action/client/ClientInteraction.ts
#	packages/protocol/src/peer/Peer.ts
#	packages/protocol/src/protocol/MessageChannel.ts
#	packages/react-native/package.json
TCP has 1:1 session-connection binding plus OS keep-alive — connection
drops evict the session directly. Probing is a UDP-only optimization
to avoid full reconnect on transient mDNS churn.

- PeerAddressMonitor.#check: skip when session uses TCP
- ClientInteraction.probe: TCP path returns success immediately after
  confirming session exists (no empty Read needed)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
TCP has 1:1 session-connection binding plus OS keep-alive — the session
is evicted directly on connection drop, so the liveness probe adds no
value. Gate the SustainedSubscription probe callback by transport so
TCP sessions skip the empty Read. ClientInteraction.probe stays
generic and works if called directly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread packages/protocol/src/ble/Ble.ts Fixed
Comment thread packages/protocol/src/ble/Ble.ts Fixed
Comment thread packages/protocol/src/ble/Ble.ts Fixed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants