/** * @license * Copyright 2022-2026 Matter.js Authors * SPDX-License-Identifier: Apache-2.0 */ import { ServerAddressIp, ServerAddressUdp } from "#net/ServerAddress.js"; import type { Transport } from "#net/Transport.js"; import { Bytes } from "#util/Bytes.js"; import { Observable } from "#util/index.js"; import { isObject } from "#util/Type.js"; export enum ChannelType { UDP = "udp", BLE = "ble", TCP = "tcp", } /** * Subset of {@link ChannelType} usable for IP-based peer connections (excludes BLE). */ export type IpChannelType = ChannelType.UDP | ChannelType.TCP; export interface Channel { /** Maximum Payload size for this channel */ maxPayloadSize: number; /** Is the transport Reliable? UDP is not, TCP and BTP are. */ isReliable: boolean; /** Does the channel support large messages? */ supportsLargeMessages: boolean; /** Channel name */ name: string; type: ChannelType; /** Method to send data to the remote endpoint */ send(data: T): Promise; /** Method to close the channel */ close(): Promise; } export interface IpNetworkChannel extends Channel { networkAddress: ServerAddressIp; networkAddressChanged: Observable<[ServerAddressIp]>; /** Send data to the remote endpoint */ send(data: T): Promise; } /** UDP-specific channel with per-send address override capability. */ export interface UdpNetworkChannel extends IpNetworkChannel { networkAddress: ServerAddressUdp; networkAddressChanged: Observable<[ServerAddressUdp]>; /** Send data, optionally overriding the destination address for this single send. */ send(data: T, addressOverride?: ServerAddressUdp): Promise; } /** * Stream-oriented channel with a fixed peer (TCP, BLE/BTP). * * Both TCP and BLE channels are inherently reliable and have a connection lifecycle. * Incoming messages are delivered as an async iterable; outgoing messages via send(). */ export interface ConnectedChannel extends Channel, AsyncIterable { readonly isReliable: true; readonly supportsLargeMessages: boolean; readonly type: ChannelType; /** Send a complete Matter message to the peer. */ send(data: Bytes): Promise; /** Close the connection. */ close(): Promise; /** Register a listener for connection close/disconnect. */ onClose(listener: () => void): Transport.Listener; } /** * Type guard for connected (stream-oriented) channels. */ export function isConnectedChannel(channel?: Channel): channel is ConnectedChannel { return channel !== undefined && channel.isReliable && typeof (channel as ConnectedChannel).onClose === "function"; } /** * Returns true (and guards types) if the channel is an IP channel */ export function isIpNetworkChannel(channel?: Channel): channel is IpNetworkChannel { return isObject((channel as IpNetworkChannel | undefined)?.networkAddress); } /** * Returns true if the channel is a UDP network channel (supports address override). */ export function isUdpNetworkChannel(channel?: Channel): channel is UdpNetworkChannel { return isIpNetworkChannel(channel) && channel.type === ChannelType.UDP; } /** * Checks if two IPNetworkChannels are referencing the same address. */ export function sameIpNetworkChannel(channel1: IpNetworkChannel, channel2: IpNetworkChannel) { const { networkAddress: addr1 } = channel1; const { networkAddress: addr2 } = channel2; return addr1.ip === addr2.ip && addr1.port === addr2.port; }