@decentnetwork/peer 0.1.31 → 0.1.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -7,4 +7,4 @@ export { LegacyProtocolNotImplementedError } from "./runtime/errors.js";
7
7
  export type { CarrierPacket, FriendMessagePacket, FriendRequestPacket } from "./compat/packet.js";
8
8
  export type { ToxDhtCryptoRequest } from "./compat/tox-dht-crypto.js";
9
9
  export type { CarrierAddressParts } from "./compat/address.js";
10
- export type { CompatibilityMode, FriendConnectionEvent, FriendConnectionStatus, FriendInfoEvent, FriendRequest, LookupResult, NetworkNode, PeerOptions, TextMessage } from "./types/peer.js";
10
+ export type { CompatibilityMode, CustomPacketEvent, FriendConnectionEvent, FriendConnectionStatus, FriendInfoEvent, FriendRequest, LookupResult, NetworkNode, PeerOptions, TextMessage } from "./types/peer.js";
package/dist/peer.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { type BootstrapResult } from "./compat/bootstrap.js";
2
2
  import type { FriendRecord } from "./store/friends.js";
3
- import type { FriendConnectionEvent, FriendRequest, FriendInfoEvent, LookupResult, NetworkNode, PeerOptions, TextMessage } from "./types/peer.js";
3
+ import type { CustomPacketEvent, FriendConnectionEvent, FriendRequest, FriendInfoEvent, LookupResult, NetworkNode, PeerOptions, TextMessage } from "./types/peer.js";
4
4
  export declare class Peer {
5
5
  #private;
6
6
  private constructor();
@@ -74,6 +74,22 @@ export declare class Peer {
74
74
  waitForFriendConnected(pubkey: string, timeoutMs?: number): Promise<boolean>;
75
75
  onFriendRequest(cb: (req: FriendRequest) => void): void;
76
76
  onText(cb: (msg: TextMessage) => void): void;
77
+ /**
78
+ * Send an application-defined custom packet to a friend. `id` selects the
79
+ * channel and its delivery class by toxcore range: **160–191 lossless**
80
+ * (reliable, ordered) or **192–254 lossy** (best-effort). Apps layered on
81
+ * the peer use this to run their own protocols alongside chat without
82
+ * collision — e.g. decentlan sends IP traffic on `192`. Throws if `pubkey`
83
+ * is not a friend or the session has no transport (fail-fast; callers that
84
+ * want offline delivery should use a message instead).
85
+ */
86
+ sendCustomPacket(pubkey: string, id: number, data: Uint8Array): Promise<void>;
87
+ /**
88
+ * Receive application custom packets (toxcore lossless 160–191 / lossy
89
+ * 192–254). SDK-internal IDs are never delivered here. See
90
+ * {@link sendCustomPacket}.
91
+ */
92
+ onCustomPacket(cb: (evt: CustomPacketEvent) => void): void;
77
93
  onFriendConnection(cb: (ev: FriendConnectionEvent) => void): void;
78
94
  onFriendInfo(cb: (ev: FriendInfoEvent) => void): void;
79
95
  friends(): FriendRecord[];
package/dist/peer.js CHANGED
@@ -851,7 +851,11 @@ export class Peer {
851
851
  return;
852
852
  }
853
853
  // Offline / fallback path via Carrier express HTTP store-and-forward.
854
- if (this.#express?.hasNodes()) {
854
+ // Skipped entirely in control-plane-only mode (decentlan's data plane):
855
+ // a VPN-style daemon must fail fast when a friend is offline rather than
856
+ // silently queue IP packets into HTTPS storage that never get forwarded
857
+ // in real time. Express there is reserved for friend-request bootstrap.
858
+ if (this.#express?.hasNodes() && !this.#opts.expressControlPlaneOnly) {
855
859
  await this.#express.sendOfflineText(pubkey, packet);
856
860
  this.#debugLog(`sendText: queued via express for ${pubkey}`);
857
861
  return;
@@ -887,6 +891,32 @@ export class Peer {
887
891
  onText(cb) {
888
892
  this.#events.on("text", cb);
889
893
  }
894
+ /**
895
+ * Send an application-defined custom packet to a friend. `id` selects the
896
+ * channel and its delivery class by toxcore range: **160–191 lossless**
897
+ * (reliable, ordered) or **192–254 lossy** (best-effort). Apps layered on
898
+ * the peer use this to run their own protocols alongside chat without
899
+ * collision — e.g. decentlan sends IP traffic on `192`. Throws if `pubkey`
900
+ * is not a friend or the session has no transport (fail-fast; callers that
901
+ * want offline delivery should use a message instead).
902
+ */
903
+ async sendCustomPacket(pubkey, id, data) {
904
+ if (!Number.isInteger(id) || id < 160 || id > 254) {
905
+ throw new Error(`custom packet id must be 160-254 (lossless 160-191 / lossy 192-254), got ${id}`);
906
+ }
907
+ if (!this.#friends.get(pubkey)) {
908
+ throw new Error(`Not a friend: ${pubkey}`);
909
+ }
910
+ await this.#sendMessengerPacket(pubkey, id, data);
911
+ }
912
+ /**
913
+ * Receive application custom packets (toxcore lossless 160–191 / lossy
914
+ * 192–254). SDK-internal IDs are never delivered here. See
915
+ * {@link sendCustomPacket}.
916
+ */
917
+ onCustomPacket(cb) {
918
+ this.#events.on("customPacket", cb);
919
+ }
890
920
  onFriendConnection(cb) {
891
921
  this.#events.on("friendConnection", cb);
892
922
  }
@@ -1596,6 +1626,21 @@ export class Peer {
1596
1626
  this.#debugLog(`crypto ${kind === PACKET_ID_ACTION ? "action" : "message"} from ${friendId}: "${text}"`);
1597
1627
  return;
1598
1628
  }
1629
+ if (kind >= 160 && kind <= 254) {
1630
+ // Application custom packet (toxcore lossless 160-191 / lossy
1631
+ // 192-254). SDK-reserved IDs (160 UDP_ENDPOINT, 254 NAT_PING, …)
1632
+ // are handled by earlier branches and never reach here; anything
1633
+ // else belongs to the application layer (e.g. decentlan IP traffic
1634
+ // on 192, control on 161/162). Receiving one proves the friend is
1635
+ // reachable, so mark online.
1636
+ this.#setFriendOnline(friendId, remote.address, remote.port);
1637
+ this.#events.emit("customPacket", {
1638
+ pubkey: friendId,
1639
+ id: kind,
1640
+ data: inner
1641
+ });
1642
+ return;
1643
+ }
1599
1644
  this.#debugVerboseLog(`unknown messenger packet kind ${kind} from ${friendId}`);
1600
1645
  return;
1601
1646
  }
@@ -17,6 +17,17 @@ export type PeerOptions = {
17
17
  friendStoreFile?: string;
18
18
  bootstrapNodes: NetworkNode[];
19
19
  expressNodes?: NetworkNode[];
20
+ /**
21
+ * When true, the express relay is used ONLY for friend-request
22
+ * bootstrap (a one-time control-plane handshake) and NEVER as a
23
+ * fallback for runtime `sendText` data. This lets a VPN-style data
24
+ * plane stay fail-fast (an offline friend surfaces as offline, IP
25
+ * packets don't silently pile into HTTPS store-and-forward) while
26
+ * still letting the initial friend-request reach a peer whose onion
27
+ * announce hasn't propagated. decentlan's daemon sets this; chat-style
28
+ * apps that genuinely want offline message delivery leave it false.
29
+ */
30
+ expressControlPlaneOnly?: boolean;
20
31
  compatibilityMode?: CompatibilityMode;
21
32
  debugLabel?: string;
22
33
  };
@@ -44,6 +55,21 @@ export type TextMessage = {
44
55
  pubkey: string;
45
56
  text: string;
46
57
  };
58
+ /**
59
+ * An application-defined custom packet received from a friend, over the
60
+ * toxcore custom packet ranges: lossless `160–191` (reliable, ordered) or
61
+ * lossy `192–254` (best-effort). Apps layered on the peer (e.g. decentlan's
62
+ * IP traffic on `192`) use these to multiplex their own channels without
63
+ * colliding with chat (`PACKET_ID_MESSAGE = 64`). Packet IDs reserved by the
64
+ * SDK itself (e.g. `160` UDP-endpoint, `254` NAT-ping) are handled internally
65
+ * and never surface here.
66
+ */
67
+ export type CustomPacketEvent = {
68
+ pubkey: string;
69
+ /** toxcore packet ID: 160–191 lossless, 192–254 lossy. */
70
+ id: number;
71
+ data: Uint8Array;
72
+ };
47
73
  export type LookupResult = {
48
74
  pubkey: string;
49
75
  status: "unknown";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decentnetwork/peer",
3
- "version": "0.1.31",
3
+ "version": "0.1.33",
4
4
  "description": "Pure TypeScript port of Elastos Carrier (toxcore-derived) P2P messaging. DHT, onion routing, TCP relay, FlatBuffers app payloads, Express offline relay. Wire-compatible with iOS Beagle and the Carrier C SDK.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",