@libp2p/webrtc 5.1.1-754fe84db → 5.1.1-cc7fcfe98
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.min.js +3 -3
- package/dist/src/private-to-public/listener.d.ts +2 -1
- package/dist/src/private-to-public/listener.d.ts.map +1 -1
- package/dist/src/private-to-public/listener.js +61 -27
- package/dist/src/private-to-public/listener.js.map +1 -1
- package/package.json +12 -10
- package/src/private-to-public/listener.ts +77 -31
@@ -20,7 +20,7 @@ export interface WebRTCListenerMetrics {
|
|
20
20
|
listenerEvents: CounterGroup;
|
21
21
|
}
|
22
22
|
export declare class WebRTCDirectListener extends TypedEventEmitter<ListenerEvents> implements Listener {
|
23
|
-
private
|
23
|
+
private readonly servers;
|
24
24
|
private readonly multiaddrs;
|
25
25
|
private certificate?;
|
26
26
|
private readonly connections;
|
@@ -30,6 +30,7 @@ export declare class WebRTCDirectListener extends TypedEventEmitter<ListenerEven
|
|
30
30
|
private readonly metrics?;
|
31
31
|
constructor(components: WebRTCDirectListenerComponents, init: WebRTCDirectListenerInit);
|
32
32
|
listen(ma: Multiaddr): Promise<void>;
|
33
|
+
private startUDPMuxServer;
|
33
34
|
private incomingConnection;
|
34
35
|
getAddrs(): Multiaddr[];
|
35
36
|
close(): Promise<void>;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../../../src/private-to-public/listener.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAUrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAG3E,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,EAAE,eAAe,EAAU,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC/I,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AASxD,MAAM,WAAW,8BAA8B;IAC7C,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,UAAU,CAAA;IACtB,MAAM,EAAE,eAAe,CAAA;IACvB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,QAAQ,CAAA;IAClB,YAAY,CAAC,EAAE,oBAAoB,EAAE,CAAA;IACrC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,WAAW,CAAC,EAAE,kBAAkB,CAAA;IAChC,gBAAgB,CAAC,EAAE,gBAAgB,GAAG,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAA;IAC1F,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC,cAAc,EAAE,YAAY,CAAA;CAC7B;
|
1
|
+
{"version":3,"file":"listener.d.ts","sourceRoot":"","sources":["../../../src/private-to-public/listener.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAUrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAG3E,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,EAAE,eAAe,EAAU,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC/I,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AASxD,MAAM,WAAW,8BAA8B;IAC7C,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,UAAU,CAAA;IACtB,MAAM,EAAE,eAAe,CAAA;IACvB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,QAAQ,CAAA;IAClB,YAAY,CAAC,EAAE,oBAAoB,EAAE,CAAA;IACrC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,WAAW,CAAC,EAAE,kBAAkB,CAAA;IAChC,gBAAgB,CAAC,EAAE,gBAAgB,GAAG,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAA;IAC1F,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC,cAAc,EAAE,YAAY,CAAA;CAC7B;AAaD,qBAAa,oBAAqB,SAAQ,iBAAiB,CAAC,cAAc,CAAE,YAAW,QAAQ;IAC7F,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,WAAW,CAAC,CAAsB;IAC1C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAsC;IAClE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0B;IAC/C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgC;IAC3D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAuB;gBAEnC,UAAU,EAAE,8BAA8B,EAAE,IAAI,EAAE,wBAAwB;IAqBjF,MAAM,CAAE,EAAE,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAgD3C,OAAO,CAAC,iBAAiB;YAuCX,kBAAkB;IAgDhC,QAAQ,IAAK,SAAS,EAAE;IAIlB,KAAK,IAAK,OAAO,CAAC,IAAI,CAAC;CAqB9B"}
|
@@ -19,7 +19,7 @@ const UDP_PROTOCOL = protocols('udp');
|
|
19
19
|
const IP4_PROTOCOL = protocols('ip4');
|
20
20
|
const IP6_PROTOCOL = protocols('ip6');
|
21
21
|
export class WebRTCDirectListener extends TypedEventEmitter {
|
22
|
-
|
22
|
+
servers;
|
23
23
|
multiaddrs;
|
24
24
|
certificate;
|
25
25
|
connections;
|
@@ -32,6 +32,7 @@ export class WebRTCDirectListener extends TypedEventEmitter {
|
|
32
32
|
this.init = init;
|
33
33
|
this.components = components;
|
34
34
|
this.multiaddrs = [];
|
35
|
+
this.servers = [];
|
35
36
|
this.connections = new Map();
|
36
37
|
this.log = components.logger.forComponent('libp2p:webrtc-direct:listener');
|
37
38
|
this.certificate = init.certificates?.[0];
|
@@ -55,39 +56,68 @@ export class WebRTCDirectListener extends TypedEventEmitter {
|
|
55
56
|
if (host == null) {
|
56
57
|
throw new Error('IP4/6 host must be specified in webrtc-direct mulitaddr');
|
57
58
|
}
|
58
|
-
|
59
|
+
const port = parseInt(parts
|
59
60
|
.filter(([code, value]) => code === UDP_PROTOCOL.code)
|
60
61
|
.pop()?.[1] ?? '');
|
61
62
|
if (isNaN(port)) {
|
62
63
|
throw new Error('UDP port must be specified in webrtc-direct mulitaddr');
|
63
64
|
}
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
65
|
+
// have to do this before any async work happens so starting two listeners
|
66
|
+
// for the same port concurrently (e.g. ipv4/ipv6 both port 0) results in a
|
67
|
+
// single mux listener. This is necessary because libjuice binds to all
|
68
|
+
// interfaces for a given port so we we need to key on just the port number
|
69
|
+
// not the host + the port number
|
70
|
+
let existingServer = this.servers.find(s => s.port === port);
|
71
|
+
// if the server has not been started yet, or the port is a wildcard port
|
72
|
+
// and there is already a wildcard port for this address family, start a new
|
73
|
+
// UDP mux server
|
74
|
+
const wildcardPorts = port === 0 && existingServer?.port === 0;
|
75
|
+
const sameAddressFamily = (existingServer?.isIPv4 === true && isIPv4(host)) || (existingServer?.isIPv6 === true && isIPv6(host));
|
76
|
+
if (existingServer == null || (wildcardPorts && sameAddressFamily)) {
|
77
|
+
existingServer = this.startUDPMuxServer(host, port);
|
78
|
+
this.servers.push(existingServer);
|
68
79
|
}
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
});
|
74
|
-
});
|
75
|
-
let certificate = this.certificate;
|
76
|
-
if (certificate == null) {
|
77
|
-
const keyPair = await crypto.subtle.generateKey({
|
78
|
-
name: 'ECDSA',
|
79
|
-
namedCurve: 'P-256'
|
80
|
-
}, true, ['sign', 'verify']);
|
81
|
-
certificate = this.certificate = await generateTransportCertificate(keyPair, {
|
82
|
-
days: 365
|
83
|
-
});
|
84
|
-
}
|
85
|
-
const address = this.server.address();
|
86
|
-
getNetworkAddresses(address.address, address.port, ipVersion).forEach((ma) => {
|
87
|
-
this.multiaddrs.push(multiaddr(`${ma}/webrtc-direct/certhash/${certificate.certhash}`));
|
80
|
+
const server = await existingServer.server;
|
81
|
+
const address = server.address();
|
82
|
+
getNetworkAddresses(host, address.port, ipVersion).forEach((ma) => {
|
83
|
+
this.multiaddrs.push(multiaddr(`${ma}/webrtc-direct/certhash/${this.certificate?.certhash}`));
|
88
84
|
});
|
89
85
|
this.safeDispatchEvent('listening');
|
90
86
|
}
|
87
|
+
startUDPMuxServer(host, port) {
|
88
|
+
return {
|
89
|
+
port,
|
90
|
+
isIPv4: isIPv4(host),
|
91
|
+
isIPv6: isIPv6(host),
|
92
|
+
server: Promise.resolve()
|
93
|
+
.then(async () => {
|
94
|
+
if (port === 0) {
|
95
|
+
// libjuice doesn't map 0 to a random free port so we have to do it
|
96
|
+
// ourselves
|
97
|
+
port = await getPort();
|
98
|
+
}
|
99
|
+
// ensure we have a certificate
|
100
|
+
if (this.certificate == null) {
|
101
|
+
const keyPair = await crypto.subtle.generateKey({
|
102
|
+
name: 'ECDSA',
|
103
|
+
namedCurve: 'P-256'
|
104
|
+
}, true, ['sign', 'verify']);
|
105
|
+
const certificate = await generateTransportCertificate(keyPair, {
|
106
|
+
days: 365 * 10
|
107
|
+
});
|
108
|
+
if (this.certificate == null) {
|
109
|
+
this.certificate = certificate;
|
110
|
+
}
|
111
|
+
}
|
112
|
+
return stunListener(host, port, this.log, (ufrag, remoteHost, remotePort) => {
|
113
|
+
this.incomingConnection(ufrag, remoteHost, remotePort)
|
114
|
+
.catch(err => {
|
115
|
+
this.log.error('error processing incoming STUN request', err);
|
116
|
+
});
|
117
|
+
});
|
118
|
+
})
|
119
|
+
};
|
120
|
+
}
|
91
121
|
async incomingConnection(ufrag, remoteHost, remotePort) {
|
92
122
|
const key = `${remoteHost}:${remotePort}:${ufrag}`;
|
93
123
|
let peerConnection = this.connections.get(key);
|
@@ -137,7 +167,11 @@ export class WebRTCDirectListener extends TypedEventEmitter {
|
|
137
167
|
for (const connection of this.connections.values()) {
|
138
168
|
connection.close();
|
139
169
|
}
|
140
|
-
|
170
|
+
// stop all UDP mux listeners
|
171
|
+
await Promise.all(this.servers.map(async (p) => {
|
172
|
+
const server = await p.server;
|
173
|
+
await server.close();
|
174
|
+
}));
|
141
175
|
// RTCPeerConnections will be removed from the connections map when their
|
142
176
|
// connection state changes to 'closed'/'disconnected'/'failed
|
143
177
|
await pWaitFor(() => {
|
@@ -147,7 +181,7 @@ export class WebRTCDirectListener extends TypedEventEmitter {
|
|
147
181
|
}
|
148
182
|
}
|
149
183
|
function getNetworkAddresses(host, port, version) {
|
150
|
-
if (host === '0.0.0.0' || host === '::
|
184
|
+
if (host === '0.0.0.0' || host === '::') {
|
151
185
|
// return all ip4 interfaces
|
152
186
|
return Object.entries(networkInterfaces())
|
153
187
|
.flatMap(([_, addresses]) => addresses)
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"listener.js","sourceRoot":"","sources":["../../../src/private-to-public/listener.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAC9D,OAAO,EAAE,GAAG,EAAE,MAAM,iCAAiC,CAAA;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAC5C,OAAO,OAAO,MAAM,UAAU,CAAA;AAC9B,OAAO,QAAQ,MAAM,YAAY,CAAA;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,OAAO,EAAE,4BAA4B,EAAE,MAAM,kCAAkC,CAAA;AAC/E,OAAO,EAAE,6BAA6B,EAAE,MAAM,kCAAkC,CAAA;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAOvD,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAA;AAE3B;;GAEG;AACH,MAAM,oBAAoB,GAAG,MAAM,CAAA;AAsBnC,MAAM,YAAY,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;AACrC,MAAM,YAAY,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;AACrC,MAAM,YAAY,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;
|
1
|
+
{"version":3,"file":"listener.js","sourceRoot":"","sources":["../../../src/private-to-public/listener.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@libp2p/webrtc",
|
3
|
-
"version": "5.1.1-
|
3
|
+
"version": "5.1.1-cc7fcfe98",
|
4
4
|
"description": "A libp2p transport using WebRTC connections",
|
5
5
|
"license": "Apache-2.0 OR MIT",
|
6
6
|
"homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/transport-webrtc#readme",
|
@@ -54,10 +54,10 @@
|
|
54
54
|
"@chainsafe/is-ip": "^2.0.2",
|
55
55
|
"@chainsafe/libp2p-noise": "^16.0.0",
|
56
56
|
"@ipshipyard/node-datachannel": "^0.26.4",
|
57
|
-
"@libp2p/interface": "2.5.0-
|
58
|
-
"@libp2p/interface-internal": "2.3.1-
|
59
|
-
"@libp2p/peer-id": "5.0.12-
|
60
|
-
"@libp2p/utils": "6.5.1-
|
57
|
+
"@libp2p/interface": "2.5.0-cc7fcfe98",
|
58
|
+
"@libp2p/interface-internal": "2.3.1-cc7fcfe98",
|
59
|
+
"@libp2p/peer-id": "5.0.12-cc7fcfe98",
|
60
|
+
"@libp2p/utils": "6.5.1-cc7fcfe98",
|
61
61
|
"@multiformats/multiaddr": "^12.3.3",
|
62
62
|
"@multiformats/multiaddr-matcher": "^1.6.0",
|
63
63
|
"@peculiar/webcrypto": "^1.5.0",
|
@@ -83,9 +83,9 @@
|
|
83
83
|
"uint8arrays": "^5.1.0"
|
84
84
|
},
|
85
85
|
"devDependencies": {
|
86
|
-
"@libp2p/crypto": "5.0.11-
|
87
|
-
"@libp2p/interface-compliance-tests": "6.3.1-
|
88
|
-
"@libp2p/logger": "5.1.8-
|
86
|
+
"@libp2p/crypto": "5.0.11-cc7fcfe98",
|
87
|
+
"@libp2p/interface-compliance-tests": "6.3.1-cc7fcfe98",
|
88
|
+
"@libp2p/logger": "5.1.8-cc7fcfe98",
|
89
89
|
"@types/sinon": "^17.0.3",
|
90
90
|
"aegir": "^45.0.5",
|
91
91
|
"delay": "^6.0.0",
|
@@ -94,13 +94,15 @@
|
|
94
94
|
"p-retry": "^6.2.1",
|
95
95
|
"protons": "^7.6.0",
|
96
96
|
"sinon": "^19.0.2",
|
97
|
-
"sinon-ts": "^2.0.0"
|
97
|
+
"sinon-ts": "^2.0.0",
|
98
|
+
"wherearewe": "^2.0.1"
|
98
99
|
},
|
99
100
|
"browser": {
|
100
101
|
"./dist/src/webrtc/index.js": "./dist/src/webrtc/index.browser.js",
|
101
102
|
"./dist/src/private-to-public/listener.js": "./dist/src/private-to-public/listener.browser.js",
|
102
103
|
"./dist/src/private-to-public/utils/get-rtcpeerconnection.js": "./dist/src/private-to-public/utils/get-rtcpeerconnection.browser.js",
|
103
|
-
"node:net": false
|
104
|
+
"node:net": false,
|
105
|
+
"node:os": false
|
104
106
|
},
|
105
107
|
"react-native": {
|
106
108
|
"./dist/src/webrtc/index.js": "./dist/src/webrtc/index.react-native.js"
|
@@ -47,8 +47,15 @@ const UDP_PROTOCOL = protocols('udp')
|
|
47
47
|
const IP4_PROTOCOL = protocols('ip4')
|
48
48
|
const IP6_PROTOCOL = protocols('ip6')
|
49
49
|
|
50
|
+
interface UDPMuxServer {
|
51
|
+
server: Promise<StunServer>
|
52
|
+
isIPv4: boolean
|
53
|
+
isIPv6: boolean
|
54
|
+
port: number
|
55
|
+
}
|
56
|
+
|
50
57
|
export class WebRTCDirectListener extends TypedEventEmitter<ListenerEvents> implements Listener {
|
51
|
-
private
|
58
|
+
private readonly servers: UDPMuxServer[]
|
52
59
|
private readonly multiaddrs: Multiaddr[]
|
53
60
|
private certificate?: TransportCertificate
|
54
61
|
private readonly connections: Map<string, DirectRTCPeerConnection>
|
@@ -63,6 +70,7 @@ export class WebRTCDirectListener extends TypedEventEmitter<ListenerEvents> impl
|
|
63
70
|
this.init = init
|
64
71
|
this.components = components
|
65
72
|
this.multiaddrs = []
|
73
|
+
this.servers = []
|
66
74
|
this.connections = new Map()
|
67
75
|
this.log = components.logger.forComponent('libp2p:webrtc-direct:listener')
|
68
76
|
this.certificate = init.certificates?.[0]
|
@@ -89,7 +97,7 @@ export class WebRTCDirectListener extends TypedEventEmitter<ListenerEvents> impl
|
|
89
97
|
if (host == null) {
|
90
98
|
throw new Error('IP4/6 host must be specified in webrtc-direct mulitaddr')
|
91
99
|
}
|
92
|
-
|
100
|
+
const port = parseInt(parts
|
93
101
|
.filter(([code, value]) => code === UDP_PROTOCOL.code)
|
94
102
|
.pop()?.[1] ?? '')
|
95
103
|
|
@@ -97,41 +105,73 @@ export class WebRTCDirectListener extends TypedEventEmitter<ListenerEvents> impl
|
|
97
105
|
throw new Error('UDP port must be specified in webrtc-direct mulitaddr')
|
98
106
|
}
|
99
107
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
108
|
+
// have to do this before any async work happens so starting two listeners
|
109
|
+
// for the same port concurrently (e.g. ipv4/ipv6 both port 0) results in a
|
110
|
+
// single mux listener. This is necessary because libjuice binds to all
|
111
|
+
// interfaces for a given port so we we need to key on just the port number
|
112
|
+
// not the host + the port number
|
113
|
+
let existingServer = this.servers.find(s => s.port === port)
|
114
|
+
|
115
|
+
// if the server has not been started yet, or the port is a wildcard port
|
116
|
+
// and there is already a wildcard port for this address family, start a new
|
117
|
+
// UDP mux server
|
118
|
+
const wildcardPorts = port === 0 && existingServer?.port === 0
|
119
|
+
const sameAddressFamily = (existingServer?.isIPv4 === true && isIPv4(host)) || (existingServer?.isIPv6 === true && isIPv6(host))
|
120
|
+
|
121
|
+
if (existingServer == null || (wildcardPorts && sameAddressFamily)) {
|
122
|
+
existingServer = this.startUDPMuxServer(host, port)
|
123
|
+
this.servers.push(existingServer)
|
104
124
|
}
|
105
125
|
|
106
|
-
|
107
|
-
|
108
|
-
.catch(err => {
|
109
|
-
this.log.error('error processing incoming STUN request', err)
|
110
|
-
})
|
111
|
-
})
|
112
|
-
|
113
|
-
let certificate = this.certificate
|
114
|
-
|
115
|
-
if (certificate == null) {
|
116
|
-
const keyPair = await crypto.subtle.generateKey({
|
117
|
-
name: 'ECDSA',
|
118
|
-
namedCurve: 'P-256'
|
119
|
-
}, true, ['sign', 'verify'])
|
126
|
+
const server = await existingServer.server
|
127
|
+
const address = server.address()
|
120
128
|
|
121
|
-
|
122
|
-
|
123
|
-
})
|
124
|
-
}
|
125
|
-
|
126
|
-
const address = this.server.address()
|
127
|
-
|
128
|
-
getNetworkAddresses(address.address, address.port, ipVersion).forEach((ma) => {
|
129
|
-
this.multiaddrs.push(multiaddr(`${ma}/webrtc-direct/certhash/${certificate.certhash}`))
|
129
|
+
getNetworkAddresses(host, address.port, ipVersion).forEach((ma) => {
|
130
|
+
this.multiaddrs.push(multiaddr(`${ma}/webrtc-direct/certhash/${this.certificate?.certhash}`))
|
130
131
|
})
|
131
132
|
|
132
133
|
this.safeDispatchEvent('listening')
|
133
134
|
}
|
134
135
|
|
136
|
+
private startUDPMuxServer (host: string, port: number): UDPMuxServer {
|
137
|
+
return {
|
138
|
+
port,
|
139
|
+
isIPv4: isIPv4(host),
|
140
|
+
isIPv6: isIPv6(host),
|
141
|
+
server: Promise.resolve()
|
142
|
+
.then(async (): Promise<StunServer> => {
|
143
|
+
if (port === 0) {
|
144
|
+
// libjuice doesn't map 0 to a random free port so we have to do it
|
145
|
+
// ourselves
|
146
|
+
port = await getPort()
|
147
|
+
}
|
148
|
+
|
149
|
+
// ensure we have a certificate
|
150
|
+
if (this.certificate == null) {
|
151
|
+
const keyPair = await crypto.subtle.generateKey({
|
152
|
+
name: 'ECDSA',
|
153
|
+
namedCurve: 'P-256'
|
154
|
+
}, true, ['sign', 'verify'])
|
155
|
+
|
156
|
+
const certificate = await generateTransportCertificate(keyPair, {
|
157
|
+
days: 365 * 10
|
158
|
+
})
|
159
|
+
|
160
|
+
if (this.certificate == null) {
|
161
|
+
this.certificate = certificate
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
return stunListener(host, port, this.log, (ufrag, remoteHost, remotePort) => {
|
166
|
+
this.incomingConnection(ufrag, remoteHost, remotePort)
|
167
|
+
.catch(err => {
|
168
|
+
this.log.error('error processing incoming STUN request', err)
|
169
|
+
})
|
170
|
+
})
|
171
|
+
})
|
172
|
+
}
|
173
|
+
}
|
174
|
+
|
135
175
|
private async incomingConnection (ufrag: string, remoteHost: string, remotePort: number): Promise<void> {
|
136
176
|
const key = `${remoteHost}:${remotePort}:${ufrag}`
|
137
177
|
let peerConnection = this.connections.get(key)
|
@@ -189,7 +229,13 @@ export class WebRTCDirectListener extends TypedEventEmitter<ListenerEvents> impl
|
|
189
229
|
connection.close()
|
190
230
|
}
|
191
231
|
|
192
|
-
|
232
|
+
// stop all UDP mux listeners
|
233
|
+
await Promise.all(
|
234
|
+
this.servers.map(async p => {
|
235
|
+
const server = await p.server
|
236
|
+
await server.close()
|
237
|
+
})
|
238
|
+
)
|
193
239
|
|
194
240
|
// RTCPeerConnections will be removed from the connections map when their
|
195
241
|
// connection state changes to 'closed'/'disconnected'/'failed
|
@@ -202,7 +248,7 @@ export class WebRTCDirectListener extends TypedEventEmitter<ListenerEvents> impl
|
|
202
248
|
}
|
203
249
|
|
204
250
|
function getNetworkAddresses (host: string, port: number, version: 4 | 6): string[] {
|
205
|
-
if (host === '0.0.0.0' || host === '::
|
251
|
+
if (host === '0.0.0.0' || host === '::') {
|
206
252
|
// return all ip4 interfaces
|
207
253
|
return Object.entries(networkInterfaces())
|
208
254
|
.flatMap(([_, addresses]) => addresses)
|