node-datachannel 0.7.0 → 0.8.0

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/CMakeLists.txt CHANGED
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.15)
2
2
  cmake_policy(SET CMP0091 NEW)
3
3
  cmake_policy(SET CMP0042 NEW)
4
4
 
5
- project(node_datachannel VERSION 0.7.0)
5
+ project(node_datachannel VERSION 0.8.0)
6
6
 
7
7
  # -Dnapi_build_version=8
8
8
  add_definitions(-DNAPI_VERSION=8)
@@ -29,7 +29,7 @@ include(FetchContent)
29
29
  FetchContent_Declare(
30
30
  libdatachannel
31
31
  GIT_REPOSITORY https://github.com/paullouisageneau/libdatachannel.git
32
- GIT_TAG "v0.20.2"
32
+ GIT_TAG "v0.20.3"
33
33
  )
34
34
 
35
35
  option(NO_MEDIA "Disable media transport support in libdatachannel" OFF)
@@ -34,7 +34,7 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "electron-squirrel-startup": "^1.0.0",
37
- "node-datachannel": "^0.5.2"
37
+ "node-datachannel": "^0.8.0"
38
38
  },
39
39
  "cmake-js": {
40
40
  "runtime": "electron",
@@ -0,0 +1,313 @@
1
+ import * as stream from 'stream';
2
+
3
+ export as namespace NodeDataChannel;
4
+
5
+ // Enum in d.ts is tricky
6
+ export type LogLevel = 'Verbose' | 'Debug' | 'Info' | 'Warning' | 'Error' | 'Fatal';
7
+
8
+ // SCTP Settings
9
+ export interface SctpSettings {
10
+ recvBufferSize?: number;
11
+ sendBufferSize?: number;
12
+ maxChunksOnQueue?: number;
13
+ initialCongestionWindow?: number;
14
+ congestionControlModule?: number;
15
+ delayedSackTime?: number;
16
+ }
17
+
18
+ // Functions
19
+ export function preload(): void;
20
+ export function initLogger(level: LogLevel, callback?: (level: LogLevel, message: string) => void): void;
21
+ export function cleanup(): void;
22
+ export function setSctpSettings(settings: SctpSettings): void;
23
+
24
+ // Proxy Server
25
+ export type ProxyServerType = 'Socks5' | 'Http';
26
+ export interface ProxyServer {
27
+ type: ProxyServerType;
28
+ ip: string;
29
+ port: number;
30
+ username?: string;
31
+ password?: string;
32
+ }
33
+
34
+ export const enum RelayType {
35
+ TurnUdp = 'TurnUdp',
36
+ TurnTcp = 'TurnTcp',
37
+ TurnTls = 'TurnTls',
38
+ }
39
+
40
+ export interface IceServer {
41
+ hostname: string;
42
+ port: number;
43
+ username?: string;
44
+ password?: string;
45
+ relayType?: RelayType;
46
+ }
47
+
48
+ export type TransportPolicy = 'all' | 'relay';
49
+
50
+ export interface RtcConfig {
51
+ iceServers: (string | IceServer)[];
52
+ proxyServer?: ProxyServer;
53
+ bindAddress?: string;
54
+ enableIceTcp?: boolean;
55
+ enableIceUdpMux?: boolean;
56
+ disableAutoNegotiation?: boolean;
57
+ forceMediaTransport?: boolean;
58
+ portRangeBegin?: number;
59
+ portRangeEnd?: number;
60
+ maxMessageSize?: number;
61
+ mtu?: number;
62
+ iceTransportPolicy?: TransportPolicy;
63
+ }
64
+
65
+ // Lowercase to match the description type string from libdatachannel
66
+ export const enum DescriptionType {
67
+ Unspec = 'unspec',
68
+ Offer = 'offer',
69
+ Answer = 'answer',
70
+ Pranswer = 'pranswer',
71
+ Rollback = 'rollback',
72
+ }
73
+
74
+ export const enum ReliabilityType {
75
+ Reliable = 0,
76
+ Rexmit = 1,
77
+ Timed = 2,
78
+ }
79
+
80
+ export interface DataChannelInitConfig {
81
+ protocol?: string;
82
+ negotiated?: boolean;
83
+ id?: number;
84
+ ordered?: boolean;
85
+ maxPacketLifeTime?: number;
86
+ maxRetransmits?: number;
87
+
88
+ // Deprecated, use ordered, maxPacketLifeTime, and maxRetransmits
89
+ reliability?: {
90
+ type?: ReliabilityType;
91
+ unordered?: boolean;
92
+ rexmit?: number;
93
+ };
94
+ }
95
+
96
+ export interface SelectedCandidateInfo {
97
+ address: string;
98
+ port: number;
99
+ type: string;
100
+ transportType: string;
101
+ candidate: string;
102
+ mid: string;
103
+ priority: number;
104
+ }
105
+
106
+ // Must be same as rtc enum class Direction
107
+ export const enum Direction {
108
+ SendOnly = 'SendOnly',
109
+ RecvOnly = 'RecvOnly',
110
+ SendRecv = 'SendRecv',
111
+ Inactive = 'Inactive',
112
+ Unknown = 'Unknown',
113
+ }
114
+
115
+ export class RtcpReceivingSession {
116
+ requestBitrate(bitRate: number): void;
117
+ requestKeyframe(): boolean;
118
+ }
119
+
120
+ export class Audio {
121
+ constructor(mid: string, dir: Direction);
122
+ addAudioCodec(payloadType: number, codec: string, profile?: string): void;
123
+ addOpusCodec(payloadType: number, profile?: string): string;
124
+
125
+ direction(): Direction;
126
+ generateSdp(eol: string, addr: string, port: number): string;
127
+ mid(): string;
128
+ setDirection(dir: Direction): void;
129
+ description(): string;
130
+ removeFormat(fmt: string): void;
131
+ addSSRC(ssrc: number, name?: string, msid?: string, trackID?: string): void;
132
+ removeSSRC(ssrc: number): void;
133
+ replaceSSRC(oldSsrc: number, ssrc: number, name?: string, msid?: string, trackID?: string): void;
134
+ hasSSRC(ssrc: number): boolean;
135
+ getSSRCs(): number[];
136
+ getCNameForSsrc(ssrc: number): string;
137
+ setBitrate(bitRate: number): void;
138
+ getBitrate(): number;
139
+ hasPayloadType(payloadType: number): boolean;
140
+ addRTXCodec(payloadType: number, originalPayloadType: number, clockRate: number): void;
141
+ addRTPMap(): void;
142
+ parseSdpLine(line: string): void;
143
+ }
144
+
145
+ export class Video {
146
+ constructor(mid: string, dir: Direction);
147
+ addVideoCodec(payloadType: number, codec: string, profile?: string): void;
148
+ addH264Codec(payloadType: number, profile?: string): void;
149
+ addVP8Codec(payloadType: number): void;
150
+ addVP9Codec(payloadType: number): void;
151
+
152
+ direction(): Direction;
153
+ generateSdp(eol: string, addr: string, port: number): string;
154
+ mid(): string;
155
+ setDirection(dir: Direction): void;
156
+ description(): string;
157
+ removeFormat(fmt: string): void;
158
+ addSSRC(ssrc: number, name?: string, msid?: string, trackID?: string): void;
159
+ removeSSRC(ssrc: number): void;
160
+ replaceSSRC(oldSsrc: number, ssrc: number, name?: string, msid?: string, trackID?: string): void;
161
+ hasSSRC(ssrc: number): boolean;
162
+ getSSRCs(): number[];
163
+ getCNameForSsrc(ssrc: number): string;
164
+ setBitrate(bitRate: number): void;
165
+ getBitrate(): number;
166
+ hasPayloadType(payloadType: number): boolean;
167
+ addRTXCodec(payloadType: number, originalPayloadType: number, clockRate: number): void;
168
+ addRTPMap(): void;
169
+ parseSdpLine(line: string): void;
170
+ }
171
+
172
+ export class Track {
173
+ direction(): Direction;
174
+ mid(): string;
175
+ type(): string;
176
+ close(): void;
177
+ sendMessage(msg: string): boolean;
178
+ sendMessageBinary(buffer: Buffer): boolean;
179
+ isOpen(): boolean;
180
+ isClosed(): boolean;
181
+ bufferedAmount(): number;
182
+ maxMessageSize(): number;
183
+ setBufferedAmountLowThreshold(newSize: number): void;
184
+ requestKeyframe(): boolean;
185
+ setMediaHandler(handler: RtcpReceivingSession): void;
186
+ onOpen(cb: () => void): void;
187
+ onClosed(cb: () => void): void;
188
+ onError(cb: (err: string) => void): void;
189
+ onMessage(cb: (msg: Buffer) => void): void;
190
+ }
191
+
192
+ export interface Channel {
193
+ close(): void;
194
+ sendMessage(msg: string): boolean;
195
+ sendMessageBinary(buffer: Uint8Array): boolean;
196
+ isOpen(): boolean;
197
+ bufferedAmount(): number;
198
+ maxMessageSize(): number;
199
+ setBufferedAmountLowThreshold(newSize: number): void;
200
+ onOpen(cb: () => void): void;
201
+ onClosed(cb: () => void): void;
202
+ onError(cb: (err: string) => void): void;
203
+ onBufferedAmountLow(cb: () => void): void;
204
+ onMessage(cb: (msg: string | Buffer) => void): void;
205
+ }
206
+ export class DataChannel implements Channel {
207
+ getLabel(): string;
208
+ getId(): number;
209
+ getProtocol(): string;
210
+
211
+ // Channel implementation
212
+ close(): void;
213
+ sendMessage(msg: string): boolean;
214
+ sendMessageBinary(buffer: Uint8Array): boolean;
215
+ isOpen(): boolean;
216
+ bufferedAmount(): number;
217
+ maxMessageSize(): number;
218
+ setBufferedAmountLowThreshold(newSize: number): void;
219
+ onOpen(cb: () => void): void;
220
+ onClosed(cb: () => void): void;
221
+ onError(cb: (err: string) => void): void;
222
+ onBufferedAmountLow(cb: () => void): void;
223
+ onMessage(cb: (msg: string | Buffer) => void): void;
224
+ }
225
+
226
+ export interface WebSocketConfiguration {
227
+ disableTlsVerification?: boolean; // default = false, if true, don't verify the TLS certificate
228
+ proxyServer?: ProxyServer; // only non-authenticated http supported for now
229
+ protocols?: string[];
230
+ connectionTimeout?: number; // miliseconds, zero to disable
231
+ pingInterval?: number; // millisecondrs, zero to disable
232
+ maxOutstandingPings?: number;
233
+ caCertificatePemFile?: string;
234
+ certificatePemFile?: string;
235
+ keyPemFile?: string;
236
+ keyPemPass?: string;
237
+ maxMessageSize: number;
238
+ }
239
+ export class WebSocket implements Channel {
240
+ constructor(config?: WebSocketConfiguration);
241
+ open(url: string): void;
242
+ forceClose(): void;
243
+ remoteAddress(): string | undefined;
244
+ path(): string | undefined;
245
+
246
+ // Channel implementation
247
+ close(): void;
248
+ sendMessage(msg: string): boolean;
249
+ sendMessageBinary(buffer: Uint8Array): boolean;
250
+ isOpen(): boolean;
251
+ bufferedAmount(): number;
252
+ maxMessageSize(): number;
253
+ setBufferedAmountLowThreshold(newSize: number): void;
254
+ onOpen(cb: () => void): void;
255
+ onClosed(cb: () => void): void;
256
+ onError(cb: (err: string) => void): void;
257
+ onBufferedAmountLow(cb: () => void): void;
258
+ onMessage(cb: (msg: string | Buffer) => void): void;
259
+ }
260
+
261
+ export interface WebSocketServerConfiguration {
262
+ port?: number; // default 8080
263
+ enableTls?: boolean; // default = false;
264
+ certificatePemFile?: string;
265
+ keyPemFile?: string;
266
+ keyPemPass?: string;
267
+ bindAddress?: string;
268
+ connectionTimeout?: number; // milliseconds
269
+ maxMessageSize?: number;
270
+ }
271
+
272
+ export class WebSocketServer {
273
+ constructor(config?: WebSocketServerConfiguration);
274
+ port(): number;
275
+ stop(): void;
276
+ onClient(cb: (ws: WebSocket) => void): void;
277
+ }
278
+
279
+ export class PeerConnection {
280
+ constructor(peerName: string, config: RtcConfig);
281
+ close(): void;
282
+ setLocalDescription(type?: DescriptionType): void;
283
+ setRemoteDescription(sdp: string, type: DescriptionType): void;
284
+ localDescription(): { type: string; sdp: string } | null;
285
+ remoteDescription(): { type: string; sdp: string } | null;
286
+ addRemoteCandidate(candidate: string, mid: string): void;
287
+ createDataChannel(label: string, config?: DataChannelInitConfig): DataChannel;
288
+ addTrack(media: Video | Audio): Track;
289
+ hasMedia(): boolean;
290
+ state(): RTCPeerConnectionState;
291
+ iceState(): RTCIceConnectionState;
292
+ signalingState(): RTCSignalingState;
293
+ gatheringState(): RTCIceGatheringState;
294
+ onLocalDescription(cb: (sdp: string, type: DescriptionType) => void): void;
295
+ onLocalCandidate(cb: (candidate: string, mid: string) => void): void;
296
+ onStateChange(cb: (state: string) => void): void;
297
+ onIceStateChange(cb: (state: string) => void): void;
298
+ onSignalingStateChange(cb: (state: string) => void): void;
299
+ onGatheringStateChange(cb: (state: string) => void): void;
300
+ onDataChannel(cb: (dc: DataChannel) => void): void;
301
+ onTrack(cb: (track: Track) => void): void;
302
+ bytesSent(): number;
303
+ bytesReceived(): number;
304
+ rtt(): number;
305
+ getSelectedCandidatePair(): { local: SelectedCandidateInfo; remote: SelectedCandidateInfo } | null;
306
+ maxDataChannelId(): number;
307
+ maxMessageSize(): number;
308
+ }
309
+
310
+ export class DataChannelStream extends stream.Duplex {
311
+ constructor(rawChannel: DataChannel, options?: Omit<stream.DuplexOptions, 'objectMode'>);
312
+ get label(): string;
313
+ }
package/lib/index.d.ts CHANGED
@@ -238,6 +238,10 @@ export interface WebSocketConfiguration {
238
238
  }
239
239
  export class WebSocket implements Channel {
240
240
  constructor(config?: WebSocketConfiguration);
241
+ open(url: string): void;
242
+ forceClose(): void;
243
+ remoteAddress(): string | undefined;
244
+ path(): string | undefined;
241
245
 
242
246
  // Channel implementation
243
247
  close(): void;
package/package.json CHANGED
@@ -1,19 +1,30 @@
1
1
  {
2
2
  "name": "node-datachannel",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "libdatachannel node bindings",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  ".": {
8
- "import": "./lib/index.js",
9
- "require": "./lib/index.cjs"
8
+ "import": {
9
+ "default": "./lib/index.js",
10
+ "types": "./lib/index.d.ts"
11
+ },
12
+ "require": {
13
+ "default": "./lib/index.cjs",
14
+ "types": "./lib/index.d.cts"
15
+ }
10
16
  },
11
17
  "./polyfill": {
12
- "import": "./polyfill/index.js",
13
- "require": "./polyfill/polyfill.cjs"
18
+ "import": {
19
+ "default": "./polyfill/index.js",
20
+ "types": "./polyfill/index.d.ts"
21
+ },
22
+ "require": {
23
+ "default": "./polyfill/index.cjs",
24
+ "types": "./polyfill/index.d.cts"
25
+ }
14
26
  }
15
27
  },
16
- "typings": "lib/index.d.ts",
17
28
  "engines": {
18
29
  "node": ">=16.0.0"
19
30
  },
@@ -34,7 +45,7 @@
34
45
  "test": "NODE_OPTIONS=--experimental-vm-modules jest",
35
46
  "wpt-test": "node test/wpt.js",
36
47
  "test-types": "tsc",
37
- "prepublishOnly": "rollup lib/index.js --file lib/index.cjs --format cjs && rollup polyfill/index.js --file polyfill/polyfill.cjs --format cjs"
48
+ "prepublishOnly": "cp lib/index.d.ts lib/index.d.cts && cp polyfill/index.d.ts polyfill/index.d.cts && rollup lib/index.js --file lib/index.cjs --format cjs && rollup polyfill/index.js --file polyfill/index.cjs --format cjs"
38
49
  },
39
50
  "binary": {
40
51
  "napi_versions": [
@@ -547,7 +547,7 @@ class DataChannelStream extends stream.Duplex {
547
547
  }
548
548
 
549
549
  // createRequire is native in node version >= 12
550
- const require$1 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.src || new URL('polyfill.cjs', document.baseURI).href)));
550
+ const require$1 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
551
551
 
552
552
  const nodeDataChannel = require$1('../build/Release/node_datachannel.node');
553
553
 
@@ -0,0 +1,37 @@
1
+ import RTCCertificate from './RTCCertificate.js';
2
+ import RTCDataChannel from './RTCDataChannel.js';
3
+ import RTCDtlsTransport from './RTCDtlsTransport.js';
4
+ import RTCIceCandidate from './RTCIceCandidate.js';
5
+ import RTCIceTransport from './RTCIceTransport.js';
6
+ import RTCPeerConnection from './RTCPeerConnection.js';
7
+ import RTCSctpTransport from './RTCSctpTransport.js';
8
+ import RTCSessionDescription from './RTCSessionDescription.js';
9
+ import { RTCDataChannelEvent, RTCPeerConnectionIceEvent } from './Events.js';
10
+
11
+ export {
12
+ RTCCertificate,
13
+ RTCDataChannel,
14
+ RTCDtlsTransport,
15
+ RTCIceCandidate,
16
+ RTCIceTransport,
17
+ RTCPeerConnection,
18
+ RTCSctpTransport,
19
+ RTCSessionDescription,
20
+ RTCDataChannelEvent,
21
+ RTCPeerConnectionIceEvent,
22
+ };
23
+
24
+ declare const _default: {
25
+ RTCCertificate: typeof RTCCertificate;
26
+ RTCDataChannel: typeof RTCDataChannel;
27
+ RTCDtlsTransport: typeof RTCDtlsTransport;
28
+ RTCIceCandidate: typeof RTCIceCandidate;
29
+ RTCIceTransport: typeof RTCIceTransport;
30
+ RTCPeerConnection: typeof RTCPeerConnection;
31
+ RTCSctpTransport: typeof RTCSctpTransport;
32
+ RTCSessionDescription: typeof RTCSessionDescription;
33
+ RTCDataChannelEvent: typeof RTCDataChannelEvent;
34
+ RTCPeerConnectionIceEvent: typeof RTCPeerConnectionIceEvent;
35
+ };
36
+
37
+ export default _default;
@@ -31,6 +31,7 @@ Napi::Object WebSocketWrapper::Init(Napi::Env env, Napi::Object exports)
31
31
  {
32
32
  InstanceMethod("open", &WebSocketWrapper::open),
33
33
  InstanceMethod("close", &WebSocketWrapper::close),
34
+ InstanceMethod("forceClose", &WebSocketWrapper::forceClose),
34
35
  InstanceMethod("sendMessage", &WebSocketWrapper::sendMessage),
35
36
  InstanceMethod("sendMessageBinary", &WebSocketWrapper::sendMessageBinary),
36
37
  InstanceMethod("isOpen", &WebSocketWrapper::isOpen),
@@ -42,6 +43,8 @@ Napi::Object WebSocketWrapper::Init(Napi::Env env, Napi::Object exports)
42
43
  InstanceMethod("onError", &WebSocketWrapper::onError),
43
44
  InstanceMethod("onBufferedAmountLow", &WebSocketWrapper::onBufferedAmountLow),
44
45
  InstanceMethod("onMessage", &WebSocketWrapper::onMessage),
46
+ InstanceMethod("remoteAddress", &WebSocketWrapper::remoteAddress),
47
+ InstanceMethod("path", &WebSocketWrapper::path),
45
48
  });
46
49
 
47
50
  constructor = Napi::Persistent(func);
@@ -257,7 +260,31 @@ void WebSocketWrapper::doClose()
257
260
  }
258
261
  catch (std::exception &ex)
259
262
  {
260
- std::cerr << std::string("libWebSocket error while closing WebSocket: ") + ex.what() << std::endl;
263
+ std::cerr << std::string("libdatachannel error while closing WebSocket: ") + ex.what() << std::endl;
264
+ return;
265
+ }
266
+ }
267
+
268
+ mOnOpenCallback.reset();
269
+ mOnErrorCallback.reset();
270
+ mOnBufferedAmountLowCallback.reset();
271
+ mOnMessageCallback.reset();
272
+ }
273
+
274
+ void WebSocketWrapper::doForceClose()
275
+ {
276
+ PLOG_DEBUG << "doForceClose() called";
277
+ if (mWebSocketPtr)
278
+ {
279
+ PLOG_DEBUG << "Force closing...";
280
+ try
281
+ {
282
+ mWebSocketPtr->forceClose();
283
+ mWebSocketPtr.reset();
284
+ }
285
+ catch (std::exception &ex)
286
+ {
287
+ std::cerr << std::string("libdatachannel error while force closing WebSocket: ") + ex.what() << std::endl;
261
288
  return;
262
289
  }
263
290
  }
@@ -297,7 +324,7 @@ void WebSocketWrapper::open(const Napi::CallbackInfo &info)
297
324
  }
298
325
  catch (std::exception &ex)
299
326
  {
300
- Napi::Error::New(env, std::string("libWebSocket error while opening WebSocket: ") + ex.what()).ThrowAsJavaScriptException();
327
+ Napi::Error::New(env, std::string("libdatachannel error while opening WebSocket: ") + ex.what()).ThrowAsJavaScriptException();
301
328
  return;
302
329
  }
303
330
  }
@@ -308,6 +335,12 @@ void WebSocketWrapper::close(const Napi::CallbackInfo &info)
308
335
  doClose();
309
336
  }
310
337
 
338
+ void WebSocketWrapper::forceClose(const Napi::CallbackInfo &info)
339
+ {
340
+ PLOG_DEBUG << "forceClose() called";
341
+ doForceClose();
342
+ }
343
+
311
344
  Napi::Value WebSocketWrapper::sendMessage(const Napi::CallbackInfo &info)
312
345
  {
313
346
  PLOG_DEBUG << "sendMessage() called";
@@ -333,7 +366,7 @@ Napi::Value WebSocketWrapper::sendMessage(const Napi::CallbackInfo &info)
333
366
  }
334
367
  catch (std::exception &ex)
335
368
  {
336
- Napi::Error::New(env, std::string("libWebSocket error while sending data channel message: ") + ex.what()).ThrowAsJavaScriptException();
369
+ Napi::Error::New(env, std::string("libdatachannel error while sending data channel message: ") + ex.what()).ThrowAsJavaScriptException();
337
370
  return Napi::Boolean::New(info.Env(), false);
338
371
  }
339
372
  }
@@ -363,7 +396,7 @@ Napi::Value WebSocketWrapper::sendMessageBinary(const Napi::CallbackInfo &info)
363
396
  }
364
397
  catch (std::exception &ex)
365
398
  {
366
- Napi::Error::New(env, std::string("libWebSocket error while sending data channel message: ") + ex.what()).ThrowAsJavaScriptException();
399
+ Napi::Error::New(env, std::string("libdatachannel error while sending data channel message: ") + ex.what()).ThrowAsJavaScriptException();
367
400
  return Napi::Boolean::New(info.Env(), false);
368
401
  }
369
402
  }
@@ -384,7 +417,7 @@ Napi::Value WebSocketWrapper::isOpen(const Napi::CallbackInfo &info)
384
417
  }
385
418
  catch (std::exception &ex)
386
419
  {
387
- Napi::Error::New(env, std::string("libWebSocket error: ") + ex.what()).ThrowAsJavaScriptException();
420
+ Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
388
421
  return Napi::Boolean::New(info.Env(), false);
389
422
  }
390
423
  }
@@ -405,7 +438,7 @@ Napi::Value WebSocketWrapper::bufferedAmount(const Napi::CallbackInfo &info)
405
438
  }
406
439
  catch (std::exception &ex)
407
440
  {
408
- Napi::Error::New(env, std::string("libWebSocket error: ") + ex.what()).ThrowAsJavaScriptException();
441
+ Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
409
442
  return Napi::Number::New(info.Env(), 0);
410
443
  }
411
444
  }
@@ -426,11 +459,69 @@ Napi::Value WebSocketWrapper::maxMessageSize(const Napi::CallbackInfo &info)
426
459
  }
427
460
  catch (std::exception &ex)
428
461
  {
429
- Napi::Error::New(env, std::string("libWebSocket error: ") + ex.what()).ThrowAsJavaScriptException();
462
+ Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
430
463
  return Napi::Number::New(info.Env(), 0);
431
464
  }
432
465
  }
433
466
 
467
+ Napi::Value WebSocketWrapper::remoteAddress(const Napi::CallbackInfo &info)
468
+ {
469
+ PLOG_DEBUG << "remoteAddress() called";
470
+ Napi::Env env = info.Env();
471
+
472
+ if (!mWebSocketPtr)
473
+ {
474
+ return env.Undefined();
475
+ }
476
+
477
+ try
478
+ {
479
+ auto address = mWebSocketPtr->remoteAddress();
480
+ if (address.has_value())
481
+ {
482
+ return Napi::String::New(info.Env(), address.value());
483
+ }
484
+ else
485
+ {
486
+ return env.Undefined();
487
+ }
488
+ }
489
+ catch (std::exception &ex)
490
+ {
491
+ Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
492
+ return env.Undefined();
493
+ }
494
+ }
495
+
496
+ Napi::Value WebSocketWrapper::path(const Napi::CallbackInfo &info)
497
+ {
498
+ PLOG_DEBUG << "path() called";
499
+ Napi::Env env = info.Env();
500
+
501
+ if (!mWebSocketPtr)
502
+ {
503
+ return env.Undefined();
504
+ }
505
+
506
+ try
507
+ {
508
+ auto path = mWebSocketPtr->path();
509
+ if (path.has_value())
510
+ {
511
+ return Napi::String::New(info.Env(), path.value());
512
+ }
513
+ else
514
+ {
515
+ return env.Undefined();
516
+ }
517
+ }
518
+ catch (std::exception &ex)
519
+ {
520
+ Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
521
+ return env.Undefined();
522
+ }
523
+ }
524
+
434
525
  void WebSocketWrapper::setBufferedAmountLowThreshold(const Napi::CallbackInfo &info)
435
526
  {
436
527
  PLOG_DEBUG << "setBufferedAmountLowThreshold() called";
@@ -455,7 +546,7 @@ void WebSocketWrapper::setBufferedAmountLowThreshold(const Napi::CallbackInfo &i
455
546
  }
456
547
  catch (std::exception &ex)
457
548
  {
458
- Napi::Error::New(env, std::string("libWebSocket error: ") + ex.what()).ThrowAsJavaScriptException();
549
+ Napi::Error::New(env, std::string("libdatachannel error: ") + ex.what()).ThrowAsJavaScriptException();
459
550
  return;
460
551
  }
461
552
  }
@@ -23,12 +23,15 @@ public:
23
23
  // Functions
24
24
  void open(const Napi::CallbackInfo &info);
25
25
  void close(const Napi::CallbackInfo &info);
26
+ void forceClose(const Napi::CallbackInfo &info);
26
27
  Napi::Value sendMessage(const Napi::CallbackInfo &info);
27
28
  Napi::Value sendMessageBinary(const Napi::CallbackInfo &info);
28
29
  Napi::Value isOpen(const Napi::CallbackInfo &info);
29
30
  Napi::Value bufferedAmount(const Napi::CallbackInfo &info);
30
31
  Napi::Value maxMessageSize(const Napi::CallbackInfo &info);
31
32
  void setBufferedAmountLowThreshold(const Napi::CallbackInfo &info);
33
+ Napi::Value remoteAddress(const Napi::CallbackInfo &info);
34
+ Napi::Value path(const Napi::CallbackInfo &info);
32
35
 
33
36
  // Callbacks
34
37
  void onOpen(const Napi::CallbackInfo &info);
@@ -47,6 +50,7 @@ private:
47
50
  static std::unordered_set<WebSocketWrapper *> instances;
48
51
 
49
52
  void doClose();
53
+ void doForceClose();
50
54
  void doCleanup();
51
55
 
52
56
  std::shared_ptr<rtc::WebSocket> mWebSocketPtr = nullptr;
@@ -6,7 +6,9 @@ nodeDataChannel.preload();
6
6
  const webSocketServer = new nodeDataChannel.WebSocketServer({ bindAddress: '127.0.0.1', port: 1987 });
7
7
 
8
8
  webSocketServer.onClient((serverSocket) => {
9
- console.log('webSocketServer.onClient()');
9
+ console.log(
10
+ 'webSocketServer.onClient() remoteAddress: ' + serverSocket.remoteAddress() + ', path: ' + serverSocket.path(),
11
+ );
10
12
 
11
13
  serverSocket.onOpen(() => {
12
14
  console.log('serverSocket.onOpen()');
@@ -32,7 +34,7 @@ clientSocket.onOpen(() => {
32
34
 
33
35
  clientSocket.onMessage((message) => {
34
36
  console.log('clientSocket.onMessage():', message);
35
- clientSocket.close();
37
+ clientSocket.forceClose();
36
38
  webSocketServer.stop();
37
39
  });
38
40