@libp2p/webrtc 4.1.10 → 5.0.0-7cd984569
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/README.md +4 -4
- package/dist/index.min.js +5 -6
- package/dist/src/error.d.ts +5 -25
- package/dist/src/error.d.ts.map +1 -1
- package/dist/src/error.js +18 -54
- package/dist/src/error.js.map +1 -1
- package/dist/src/index.d.ts +4 -4
- package/dist/src/index.js +4 -4
- package/dist/src/pb/message.d.ts +2 -2
- package/dist/src/pb/message.d.ts.map +1 -1
- package/dist/src/pb/message.js +10 -7
- package/dist/src/pb/message.js.map +1 -1
- package/dist/src/private-to-private/initiate-connection.d.ts.map +1 -1
- package/dist/src/private-to-private/initiate-connection.js +10 -8
- package/dist/src/private-to-private/initiate-connection.js.map +1 -1
- package/dist/src/private-to-private/pb/message.d.ts +2 -2
- package/dist/src/private-to-private/pb/message.d.ts.map +1 -1
- package/dist/src/private-to-private/pb/message.js +10 -7
- package/dist/src/private-to-private/pb/message.js.map +1 -1
- package/dist/src/private-to-private/signaling-stream-handler.d.ts.map +1 -1
- package/dist/src/private-to-private/signaling-stream-handler.js +9 -8
- package/dist/src/private-to-private/signaling-stream-handler.js.map +1 -1
- package/dist/src/private-to-private/transport.d.ts.map +1 -1
- package/dist/src/private-to-private/transport.js +6 -7
- package/dist/src/private-to-private/transport.js.map +1 -1
- package/dist/src/private-to-private/util.d.ts +1 -0
- package/dist/src/private-to-private/util.d.ts.map +1 -1
- package/dist/src/private-to-private/util.js +5 -5
- package/dist/src/private-to-private/util.js.map +1 -1
- package/dist/src/private-to-public/sdp.d.ts.map +1 -1
- package/dist/src/private-to-public/sdp.js +7 -6
- package/dist/src/private-to-public/sdp.js.map +1 -1
- package/dist/src/private-to-public/transport.d.ts +2 -1
- package/dist/src/private-to-public/transport.d.ts.map +1 -1
- package/dist/src/private-to-public/transport.js +12 -10
- package/dist/src/private-to-public/transport.js.map +1 -1
- package/dist/src/stream.js +6 -6
- package/dist/src/stream.js.map +1 -1
- package/package.json +15 -15
- package/src/error.ts +18 -64
- package/src/index.ts +4 -4
- package/src/pb/message.ts +10 -8
- package/src/private-to-private/initiate-connection.ts +11 -8
- package/src/private-to-private/pb/message.ts +10 -8
- package/src/private-to-private/signaling-stream-handler.ts +10 -8
- package/src/private-to-private/transport.ts +6 -7
- package/src/private-to-private/util.ts +5 -5
- package/src/private-to-public/sdp.ts +7 -6
- package/src/private-to-public/transport.ts +14 -12
- package/src/stream.ts +6 -6
- package/dist/typedoc-urls.json +0 -8
package/src/error.ts
CHANGED
|
@@ -1,122 +1,76 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
ERR_DATA_CHANNEL = 'ERR_DATA_CHANNEL',
|
|
7
|
-
ERR_CONNECTION_CLOSED = 'ERR_CONNECTION_CLOSED',
|
|
8
|
-
ERR_HASH_NOT_SUPPORTED = 'ERR_HASH_NOT_SUPPORTED',
|
|
9
|
-
ERR_INVALID_MULTIADDR = 'ERR_INVALID_MULTIADDR',
|
|
10
|
-
ERR_INVALID_FINGERPRINT = 'ERR_INVALID_FINGERPRINT',
|
|
11
|
-
ERR_INVALID_PARAMETERS = 'ERR_INVALID_PARAMETERS',
|
|
12
|
-
ERR_NOT_IMPLEMENTED = 'ERR_NOT_IMPLEMENTED',
|
|
13
|
-
ERR_TOO_MANY_INBOUND_PROTOCOL_STREAMS = 'ERR_TOO_MANY_INBOUND_PROTOCOL_STREAMS',
|
|
14
|
-
ERR_TOO_MANY_OUTBOUND_PROTOCOL_STREAMS = 'ERR_TOO_MANY_OUTBOUND_PROTOCOL_STREAMS',
|
|
1
|
+
export class WebRTCTransportError extends Error {
|
|
2
|
+
constructor (msg: string) {
|
|
3
|
+
super(`WebRTC transport error: ${msg}`)
|
|
4
|
+
this.name = 'WebRTCTransportError'
|
|
5
|
+
}
|
|
15
6
|
}
|
|
16
7
|
|
|
17
|
-
export class
|
|
18
|
-
constructor (
|
|
19
|
-
super(
|
|
20
|
-
this.name = '
|
|
8
|
+
export class SDPHandshakeFailedError extends WebRTCTransportError {
|
|
9
|
+
constructor (message = 'SDP handshake failed') {
|
|
10
|
+
super(message)
|
|
11
|
+
this.name = 'SDPHandshakeFailedError'
|
|
21
12
|
}
|
|
22
13
|
}
|
|
23
14
|
|
|
24
15
|
export class ConnectionClosedError extends WebRTCTransportError {
|
|
25
16
|
constructor (state: RTCPeerConnectionState, msg: string) {
|
|
26
|
-
super(`peerconnection moved to state: ${state}: ${msg}
|
|
17
|
+
super(`peerconnection moved to state: ${state}: ${msg}`)
|
|
27
18
|
this.name = 'WebRTC/ConnectionClosed'
|
|
28
19
|
}
|
|
29
20
|
}
|
|
30
21
|
|
|
31
|
-
export function connectionClosedError (state: RTCPeerConnectionState, msg: string): ConnectionClosedError {
|
|
32
|
-
return new ConnectionClosedError(state, msg)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
22
|
export class DataChannelError extends WebRTCTransportError {
|
|
36
23
|
constructor (streamLabel: string, msg: string) {
|
|
37
|
-
super(`[stream: ${streamLabel}] data channel error: ${msg}
|
|
24
|
+
super(`[stream: ${streamLabel}] data channel error: ${msg}`)
|
|
38
25
|
this.name = 'WebRTC/DataChannelError'
|
|
39
26
|
}
|
|
40
27
|
}
|
|
41
28
|
|
|
42
|
-
export function dataChannelError (streamLabel: string, msg: string): DataChannelError {
|
|
43
|
-
return new DataChannelError(streamLabel, msg)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
29
|
export class InappropriateMultiaddrError extends WebRTCTransportError {
|
|
47
30
|
constructor (msg: string) {
|
|
48
|
-
super(`There was a problem with the Multiaddr which was passed in: ${msg}
|
|
31
|
+
super(`There was a problem with the Multiaddr which was passed in: ${msg}`)
|
|
49
32
|
this.name = 'WebRTC/InappropriateMultiaddrError'
|
|
50
33
|
}
|
|
51
34
|
}
|
|
52
35
|
|
|
53
|
-
export function inappropriateMultiaddr (msg: string): InappropriateMultiaddrError {
|
|
54
|
-
return new InappropriateMultiaddrError(msg)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
36
|
export class InvalidArgumentError extends WebRTCTransportError {
|
|
58
37
|
constructor (msg: string) {
|
|
59
|
-
super(`There was a problem with a provided argument: ${msg}
|
|
38
|
+
super(`There was a problem with a provided argument: ${msg}`)
|
|
60
39
|
this.name = 'WebRTC/InvalidArgumentError'
|
|
61
40
|
}
|
|
62
41
|
}
|
|
63
42
|
|
|
64
|
-
export function invalidArgument (msg: string): InvalidArgumentError {
|
|
65
|
-
return new InvalidArgumentError(msg)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
43
|
export class InvalidFingerprintError extends WebRTCTransportError {
|
|
69
44
|
constructor (fingerprint: string, source: string) {
|
|
70
|
-
super(`Invalid fingerprint "${fingerprint}" within ${source}
|
|
45
|
+
super(`Invalid fingerprint "${fingerprint}" within ${source}`)
|
|
71
46
|
this.name = 'WebRTC/InvalidFingerprintError'
|
|
72
47
|
}
|
|
73
48
|
}
|
|
74
49
|
|
|
75
|
-
export function invalidFingerprint (fingerprint: string, source: string): InvalidFingerprintError {
|
|
76
|
-
return new InvalidFingerprintError(fingerprint, source)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
50
|
export class OperationAbortedError extends WebRTCTransportError {
|
|
80
51
|
constructor (context: string, abortReason: string) {
|
|
81
|
-
super(`Signalled to abort because (${abortReason}}) ${context}
|
|
52
|
+
super(`Signalled to abort because (${abortReason}}) ${context}`)
|
|
82
53
|
this.name = 'WebRTC/OperationAbortedError'
|
|
83
54
|
}
|
|
84
55
|
}
|
|
85
56
|
|
|
86
|
-
export function operationAborted (context: string, reason: string): OperationAbortedError {
|
|
87
|
-
return new OperationAbortedError(context, reason)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
57
|
export class OverStreamLimitError extends WebRTCTransportError {
|
|
91
58
|
constructor (msg: string) {
|
|
92
|
-
|
|
93
|
-
super(msg, code)
|
|
59
|
+
super(msg)
|
|
94
60
|
this.name = 'WebRTC/OverStreamLimitError'
|
|
95
61
|
}
|
|
96
62
|
}
|
|
97
63
|
|
|
98
|
-
export function overStreamLimit (dir: Direction, proto: string): OverStreamLimitError {
|
|
99
|
-
return new OverStreamLimitError(`${dir} stream limit reached for protocol - ${proto}`)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
64
|
export class UnimplementedError extends WebRTCTransportError {
|
|
103
65
|
constructor (methodName: string) {
|
|
104
|
-
super(`A method (${methodName}) was called though it has been intentionally left unimplemented
|
|
66
|
+
super(`A method (${methodName}) was called though it has been intentionally left unimplemented.`)
|
|
105
67
|
this.name = 'WebRTC/UnimplementedError'
|
|
106
68
|
}
|
|
107
69
|
}
|
|
108
70
|
|
|
109
|
-
export function unimplemented (methodName: string): UnimplementedError {
|
|
110
|
-
return new UnimplementedError(methodName)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
71
|
export class UnsupportedHashAlgorithmError extends WebRTCTransportError {
|
|
114
72
|
constructor (algo: number) {
|
|
115
|
-
super(`unsupported hash algorithm code: ${algo} please see the codes at https://github.com/multiformats/multicodec/blob/master/table.csv
|
|
73
|
+
super(`unsupported hash algorithm code: ${algo} please see the codes at https://github.com/multiformats/multicodec/blob/master/table.csv `)
|
|
116
74
|
this.name = 'WebRTC/UnsupportedHashAlgorithmError'
|
|
117
75
|
}
|
|
118
76
|
}
|
|
119
|
-
|
|
120
|
-
export function unsupportedHashAlgorithmCode (code: number): UnsupportedHashAlgorithmError {
|
|
121
|
-
return new UnsupportedHashAlgorithmError(code)
|
|
122
|
-
}
|
package/src/index.ts
CHANGED
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
* transports: [
|
|
62
62
|
* webSockets({filter: filters.all})
|
|
63
63
|
* ],
|
|
64
|
-
*
|
|
64
|
+
* connectionEncrypters: [noise()],
|
|
65
65
|
* streamMuxers: [yamux()],
|
|
66
66
|
* services: {
|
|
67
67
|
* identify: identify(),
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
* discoverRelays: 1
|
|
84
84
|
* })
|
|
85
85
|
* ],
|
|
86
|
-
*
|
|
86
|
+
* connectionEncrypters: [noise()],
|
|
87
87
|
* streamMuxers: [yamux()],
|
|
88
88
|
* services: {
|
|
89
89
|
* identify: identify(),
|
|
@@ -120,7 +120,7 @@
|
|
|
120
120
|
* webRTC(),
|
|
121
121
|
* circuitRelayTransport()
|
|
122
122
|
* ],
|
|
123
|
-
*
|
|
123
|
+
* connectionEncrypters: [noise()],
|
|
124
124
|
* streamMuxers: [yamux()],
|
|
125
125
|
* services: {
|
|
126
126
|
* identify: identify(),
|
|
@@ -166,7 +166,7 @@
|
|
|
166
166
|
* transports: [
|
|
167
167
|
* webRTCDirect()
|
|
168
168
|
* ],
|
|
169
|
-
*
|
|
169
|
+
* connectionEncrypters: [
|
|
170
170
|
* noise()
|
|
171
171
|
* ]
|
|
172
172
|
* })
|
package/src/pb/message.ts
CHANGED
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */
|
|
5
5
|
/* eslint-disable @typescript-eslint/no-empty-interface */
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
import type { Codec } from 'protons-runtime'
|
|
7
|
+
import { type Codec, decodeMessage, type DecodeOptions, encodeMessage, enumeration, message } from 'protons-runtime'
|
|
9
8
|
import type { Uint8ArrayList } from 'uint8arraylist'
|
|
10
9
|
|
|
11
10
|
export interface Message {
|
|
@@ -56,7 +55,7 @@ export namespace Message {
|
|
|
56
55
|
if (opts.lengthDelimited !== false) {
|
|
57
56
|
w.ldelim()
|
|
58
57
|
}
|
|
59
|
-
}, (reader, length) => {
|
|
58
|
+
}, (reader, length, opts = {}) => {
|
|
60
59
|
const obj: any = {}
|
|
61
60
|
|
|
62
61
|
const end = length == null ? reader.len : reader.pos + length
|
|
@@ -65,15 +64,18 @@ export namespace Message {
|
|
|
65
64
|
const tag = reader.uint32()
|
|
66
65
|
|
|
67
66
|
switch (tag >>> 3) {
|
|
68
|
-
case 1:
|
|
67
|
+
case 1: {
|
|
69
68
|
obj.flag = Message.Flag.codec().decode(reader)
|
|
70
69
|
break
|
|
71
|
-
|
|
70
|
+
}
|
|
71
|
+
case 2: {
|
|
72
72
|
obj.message = reader.bytes()
|
|
73
73
|
break
|
|
74
|
-
|
|
74
|
+
}
|
|
75
|
+
default: {
|
|
75
76
|
reader.skipType(tag & 7)
|
|
76
77
|
break
|
|
78
|
+
}
|
|
77
79
|
}
|
|
78
80
|
}
|
|
79
81
|
|
|
@@ -88,7 +90,7 @@ export namespace Message {
|
|
|
88
90
|
return encodeMessage(obj, Message.codec())
|
|
89
91
|
}
|
|
90
92
|
|
|
91
|
-
export const decode = (buf: Uint8Array | Uint8ArrayList): Message => {
|
|
92
|
-
return decodeMessage(buf, Message.codec())
|
|
93
|
+
export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions<Message>): Message => {
|
|
94
|
+
return decodeMessage(buf, Message.codec(), opts)
|
|
93
95
|
}
|
|
94
96
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InvalidParametersError } from '@libp2p/interface'
|
|
2
2
|
import { peerIdFromString } from '@libp2p/peer-id'
|
|
3
3
|
import { pbStream } from 'it-protobuf-stream'
|
|
4
4
|
import { CustomProgressEvent } from 'progress-events'
|
|
5
|
+
import { SDPHandshakeFailedError } from '../error.js'
|
|
5
6
|
import { DataChannelMuxerFactory } from '../muxer.js'
|
|
6
7
|
import { RTCPeerConnection, RTCSessionDescription } from '../webrtc/index.js'
|
|
7
8
|
import { Message } from './pb/message.js'
|
|
@@ -41,7 +42,7 @@ export async function initiateConnection ({ rtcConfiguration, dataChannel, signa
|
|
|
41
42
|
const relayPeer = baseAddr.getPeerId()
|
|
42
43
|
|
|
43
44
|
if (relayPeer == null) {
|
|
44
|
-
throw new
|
|
45
|
+
throw new InvalidParametersError('Relay peer was missing')
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
const connections = connectionManager.getConnections(peerIdFromString(relayPeer))
|
|
@@ -72,7 +73,7 @@ export async function initiateConnection ({ rtcConfiguration, dataChannel, signa
|
|
|
72
73
|
|
|
73
74
|
const stream = await connection.newStream(SIGNALING_PROTO_ID, {
|
|
74
75
|
signal,
|
|
75
|
-
|
|
76
|
+
runOnLimitedConnection: true
|
|
76
77
|
})
|
|
77
78
|
|
|
78
79
|
const messageStream = pbStream(stream).pb(Message)
|
|
@@ -117,7 +118,7 @@ export async function initiateConnection ({ rtcConfiguration, dataChannel, signa
|
|
|
117
118
|
// create an offer
|
|
118
119
|
const offerSdp = await peerConnection.createOffer().catch(err => {
|
|
119
120
|
log.error('could not execute createOffer', err)
|
|
120
|
-
throw new
|
|
121
|
+
throw new SDPHandshakeFailedError('Failed to set createOffer')
|
|
121
122
|
})
|
|
122
123
|
|
|
123
124
|
log.trace('initiator send SDP offer %s', offerSdp.sdp)
|
|
@@ -132,26 +133,28 @@ export async function initiateConnection ({ rtcConfiguration, dataChannel, signa
|
|
|
132
133
|
// set offer as local description
|
|
133
134
|
await peerConnection.setLocalDescription(offerSdp).catch(err => {
|
|
134
135
|
log.error('could not execute setLocalDescription', err)
|
|
135
|
-
throw new
|
|
136
|
+
throw new SDPHandshakeFailedError('Failed to set localDescription')
|
|
136
137
|
})
|
|
137
138
|
|
|
138
139
|
onProgress?.(new CustomProgressEvent('webrtc:read-sdp-answer'))
|
|
139
140
|
|
|
141
|
+
log.trace('initiator read SDP answer')
|
|
142
|
+
|
|
140
143
|
// read answer
|
|
141
144
|
const answerMessage = await messageStream.read({
|
|
142
145
|
signal
|
|
143
146
|
})
|
|
144
147
|
|
|
145
148
|
if (answerMessage.type !== Message.Type.SDP_ANSWER) {
|
|
146
|
-
throw new
|
|
149
|
+
throw new SDPHandshakeFailedError('Remote should send an SDP answer')
|
|
147
150
|
}
|
|
148
151
|
|
|
149
|
-
log.trace('initiator
|
|
152
|
+
log.trace('initiator received SDP answer %s', answerMessage.data)
|
|
150
153
|
|
|
151
154
|
const answerSdp = new RTCSessionDescription({ type: 'answer', sdp: answerMessage.data })
|
|
152
155
|
await peerConnection.setRemoteDescription(answerSdp).catch(err => {
|
|
153
156
|
log.error('could not execute setRemoteDescription', err)
|
|
154
|
-
throw new
|
|
157
|
+
throw new SDPHandshakeFailedError('Failed to set remoteDescription')
|
|
155
158
|
})
|
|
156
159
|
|
|
157
160
|
log.trace('initiator read candidates until connected')
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */
|
|
5
5
|
/* eslint-disable @typescript-eslint/no-empty-interface */
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
import type { Codec } from 'protons-runtime'
|
|
7
|
+
import { type Codec, decodeMessage, type DecodeOptions, encodeMessage, enumeration, message } from 'protons-runtime'
|
|
9
8
|
import type { Uint8ArrayList } from 'uint8arraylist'
|
|
10
9
|
|
|
11
10
|
export interface Message {
|
|
@@ -54,7 +53,7 @@ export namespace Message {
|
|
|
54
53
|
if (opts.lengthDelimited !== false) {
|
|
55
54
|
w.ldelim()
|
|
56
55
|
}
|
|
57
|
-
}, (reader, length) => {
|
|
56
|
+
}, (reader, length, opts = {}) => {
|
|
58
57
|
const obj: any = {}
|
|
59
58
|
|
|
60
59
|
const end = length == null ? reader.len : reader.pos + length
|
|
@@ -63,15 +62,18 @@ export namespace Message {
|
|
|
63
62
|
const tag = reader.uint32()
|
|
64
63
|
|
|
65
64
|
switch (tag >>> 3) {
|
|
66
|
-
case 1:
|
|
65
|
+
case 1: {
|
|
67
66
|
obj.type = Message.Type.codec().decode(reader)
|
|
68
67
|
break
|
|
69
|
-
|
|
68
|
+
}
|
|
69
|
+
case 2: {
|
|
70
70
|
obj.data = reader.string()
|
|
71
71
|
break
|
|
72
|
-
|
|
72
|
+
}
|
|
73
|
+
default: {
|
|
73
74
|
reader.skipType(tag & 7)
|
|
74
75
|
break
|
|
76
|
+
}
|
|
75
77
|
}
|
|
76
78
|
}
|
|
77
79
|
|
|
@@ -86,7 +88,7 @@ export namespace Message {
|
|
|
86
88
|
return encodeMessage(obj, Message.codec())
|
|
87
89
|
}
|
|
88
90
|
|
|
89
|
-
export const decode = (buf: Uint8Array | Uint8ArrayList): Message => {
|
|
90
|
-
return decodeMessage(buf, Message.codec())
|
|
91
|
+
export const decode = (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions<Message>): Message => {
|
|
92
|
+
return decodeMessage(buf, Message.codec(), opts)
|
|
91
93
|
}
|
|
92
94
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { CodeError } from '@libp2p/interface'
|
|
2
1
|
import { multiaddr, type Multiaddr } from '@multiformats/multiaddr'
|
|
3
2
|
import { pbStream } from 'it-protobuf-stream'
|
|
3
|
+
import { SDPHandshakeFailedError } from '../error.js'
|
|
4
4
|
import { type RTCPeerConnection, RTCSessionDescription } from '../webrtc/index.js'
|
|
5
5
|
import { Message } from './pb/message.js'
|
|
6
|
-
import { readCandidatesUntilConnected } from './util.js'
|
|
6
|
+
import { getConnectionState, readCandidatesUntilConnected } from './util.js'
|
|
7
7
|
import type { Logger } from '@libp2p/interface'
|
|
8
8
|
import type { IncomingStreamData } from '@libp2p/interface-internal'
|
|
9
9
|
|
|
@@ -40,16 +40,18 @@ export async function handleIncomingStream ({ peerConnection, stream, signal, co
|
|
|
40
40
|
})
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
log.trace('recipient read SDP offer')
|
|
44
|
+
|
|
43
45
|
// read an SDP offer
|
|
44
46
|
const pbOffer = await messageStream.read({
|
|
45
47
|
signal
|
|
46
48
|
})
|
|
47
49
|
|
|
48
50
|
if (pbOffer.type !== Message.Type.SDP_OFFER) {
|
|
49
|
-
throw new
|
|
51
|
+
throw new SDPHandshakeFailedError(`expected message type SDP_OFFER, received: ${pbOffer.type ?? 'undefined'} `)
|
|
50
52
|
}
|
|
51
53
|
|
|
52
|
-
log.trace('recipient
|
|
54
|
+
log.trace('recipient received SDP offer %s', pbOffer.data)
|
|
53
55
|
|
|
54
56
|
const offer = new RTCSessionDescription({
|
|
55
57
|
type: 'offer',
|
|
@@ -58,13 +60,13 @@ export async function handleIncomingStream ({ peerConnection, stream, signal, co
|
|
|
58
60
|
|
|
59
61
|
await peerConnection.setRemoteDescription(offer).catch(err => {
|
|
60
62
|
log.error('could not execute setRemoteDescription', err)
|
|
61
|
-
throw new
|
|
63
|
+
throw new SDPHandshakeFailedError('Failed to set remoteDescription')
|
|
62
64
|
})
|
|
63
65
|
|
|
64
66
|
// create and write an SDP answer
|
|
65
67
|
const answer = await peerConnection.createAnswer().catch(err => {
|
|
66
68
|
log.error('could not execute createAnswer', err)
|
|
67
|
-
throw new
|
|
69
|
+
throw new SDPHandshakeFailedError('Failed to create answer')
|
|
68
70
|
})
|
|
69
71
|
|
|
70
72
|
log.trace('recipient send SDP answer %s', answer.sdp)
|
|
@@ -76,7 +78,7 @@ export async function handleIncomingStream ({ peerConnection, stream, signal, co
|
|
|
76
78
|
|
|
77
79
|
await peerConnection.setLocalDescription(answer).catch(err => {
|
|
78
80
|
log.error('could not execute setLocalDescription', err)
|
|
79
|
-
throw new
|
|
81
|
+
throw new SDPHandshakeFailedError('Failed to set localDescription')
|
|
80
82
|
})
|
|
81
83
|
|
|
82
84
|
log.trace('recipient read candidates until connected')
|
|
@@ -88,7 +90,7 @@ export async function handleIncomingStream ({ peerConnection, stream, signal, co
|
|
|
88
90
|
log
|
|
89
91
|
})
|
|
90
92
|
} catch (err: any) {
|
|
91
|
-
if (peerConnection
|
|
93
|
+
if (getConnectionState(peerConnection) !== 'connected') {
|
|
92
94
|
log.error('error while handling signaling stream from peer %a', connection.remoteAddr, err)
|
|
93
95
|
|
|
94
96
|
peerConnection.close()
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InvalidParametersError, serviceCapabilities, serviceDependencies, setMaxListeners, transportSymbol } from '@libp2p/interface'
|
|
2
2
|
import { peerIdFromString } from '@libp2p/peer-id'
|
|
3
3
|
import { multiaddr, type Multiaddr } from '@multiformats/multiaddr'
|
|
4
4
|
import { WebRTC } from '@multiformats/multiaddr-matcher'
|
|
5
|
-
import { codes } from '../error.js'
|
|
6
5
|
import { WebRTCMultiaddrConnection } from '../maconn.js'
|
|
7
6
|
import { DataChannelMuxerFactory } from '../muxer.js'
|
|
8
7
|
import { getRtcConfiguration } from '../util.js'
|
|
@@ -108,7 +107,7 @@ export class WebRTCTransport implements Transport<WebRTCDialEvents>, Startable {
|
|
|
108
107
|
await this.components.registrar.handle(SIGNALING_PROTO_ID, (data: IncomingStreamData) => {
|
|
109
108
|
this._onProtocol(data).catch(err => { this.log.error('failed to handle incoming connect from %p', data.connection.remotePeer, err) })
|
|
110
109
|
}, {
|
|
111
|
-
|
|
110
|
+
runOnLimitedConnection: true
|
|
112
111
|
})
|
|
113
112
|
this._started = true
|
|
114
113
|
}
|
|
@@ -247,11 +246,11 @@ export class WebRTCTransport implements Transport<WebRTCDialEvents>, Startable {
|
|
|
247
246
|
export function splitAddr (ma: Multiaddr): { baseAddr: Multiaddr, peerId: PeerId } {
|
|
248
247
|
const addrs = ma.toString().split(WEBRTC_TRANSPORT + '/')
|
|
249
248
|
if (addrs.length !== 2) {
|
|
250
|
-
throw new
|
|
249
|
+
throw new InvalidParametersError('webrtc protocol was not present in multiaddr')
|
|
251
250
|
}
|
|
252
251
|
|
|
253
252
|
if (!addrs[0].includes(CIRCUIT_RELAY_TRANSPORT)) {
|
|
254
|
-
throw new
|
|
253
|
+
throw new InvalidParametersError('p2p-circuit protocol was not present in multiaddr')
|
|
255
254
|
}
|
|
256
255
|
|
|
257
256
|
// look for remote peerId
|
|
@@ -260,12 +259,12 @@ export function splitAddr (ma: Multiaddr): { baseAddr: Multiaddr, peerId: PeerId
|
|
|
260
259
|
|
|
261
260
|
const destinationIdString = destination.getPeerId()
|
|
262
261
|
if (destinationIdString == null) {
|
|
263
|
-
throw new
|
|
262
|
+
throw new InvalidParametersError('destination peer id was missing')
|
|
264
263
|
}
|
|
265
264
|
|
|
266
265
|
const lastProtoInRemote = remoteAddr.protos().pop()
|
|
267
266
|
if (lastProtoInRemote === undefined) {
|
|
268
|
-
throw new
|
|
267
|
+
throw new InvalidParametersError('invalid multiaddr')
|
|
269
268
|
}
|
|
270
269
|
if (lastProtoInRemote.name !== 'p2p') {
|
|
271
270
|
remoteAddr = remoteAddr.encapsulate(`/p2p/${destinationIdString}`)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ConnectionFailedError, InvalidMessageError } from '@libp2p/interface'
|
|
2
2
|
import pDefer from 'p-defer'
|
|
3
3
|
import { CustomProgressEvent } from 'progress-events'
|
|
4
4
|
import { isFirefox } from '../util.js'
|
|
@@ -38,7 +38,7 @@ export const readCandidatesUntilConnected = async (pc: RTCPeerConnection, stream
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
if (message.type !== Message.Type.ICE_CANDIDATE) {
|
|
41
|
-
throw new
|
|
41
|
+
throw new InvalidMessageError('ICE candidate message expected')
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
const candidateInit = JSON.parse(message.data ?? 'null')
|
|
@@ -67,13 +67,13 @@ export const readCandidatesUntilConnected = async (pc: RTCPeerConnection, stream
|
|
|
67
67
|
} catch (err) {
|
|
68
68
|
options.log.error('%s error parsing ICE candidate', options.direction, err)
|
|
69
69
|
|
|
70
|
-
if (options.signal?.aborted === true) {
|
|
70
|
+
if (options.signal?.aborted === true && getConnectionState(pc) !== 'connected') {
|
|
71
71
|
throw err
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
function getConnectionState (pc: RTCPeerConnection): string {
|
|
76
|
+
export function getConnectionState (pc: RTCPeerConnection): string {
|
|
77
77
|
return isFirefox ? pc.iceConnectionState : pc.connectionState
|
|
78
78
|
}
|
|
79
79
|
|
|
@@ -86,7 +86,7 @@ function resolveOnConnected (pc: RTCPeerConnection, promise: DeferredPromise<voi
|
|
|
86
86
|
case 'failed':
|
|
87
87
|
case 'disconnected':
|
|
88
88
|
case 'closed':
|
|
89
|
-
promise.reject(new
|
|
89
|
+
promise.reject(new ConnectionFailedError('RTCPeerConnection was closed'))
|
|
90
90
|
break
|
|
91
91
|
default:
|
|
92
92
|
break
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { InvalidParametersError } from '@libp2p/interface'
|
|
1
2
|
import { type Multiaddr } from '@multiformats/multiaddr'
|
|
2
3
|
import { bases, digest } from 'multiformats/basics'
|
|
3
|
-
import {
|
|
4
|
+
import { InvalidFingerprintError, UnsupportedHashAlgorithmError } from '../error.js'
|
|
4
5
|
import { MAX_MESSAGE_SIZE } from '../stream.js'
|
|
5
6
|
import { CERTHASH_CODE } from './transport.js'
|
|
6
7
|
import type { LoggerOptions } from '@libp2p/interface'
|
|
@@ -32,7 +33,7 @@ export function getLocalFingerprint (pc: RTCPeerConnection, options: LoggerOptio
|
|
|
32
33
|
|
|
33
34
|
const fingerprint = localCert.getFingerprints()[0].value
|
|
34
35
|
if (fingerprint == null) {
|
|
35
|
-
throw
|
|
36
|
+
throw new InvalidFingerprintError('', 'no fingerprint on local certificate')
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
return fingerprint
|
|
@@ -63,7 +64,7 @@ export function certhash (ma: Multiaddr): string {
|
|
|
63
64
|
const certhash = tups.filter((tup) => tup[0] === CERTHASH_CODE).map((tup) => tup[1])[0]
|
|
64
65
|
|
|
65
66
|
if (certhash === undefined || certhash === '') {
|
|
66
|
-
throw
|
|
67
|
+
throw new InvalidParametersError(`Couldn't find a certhash component of multiaddr: ${ma.toString()}`)
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
return certhash
|
|
@@ -86,7 +87,7 @@ export function ma2Fingerprint (ma: Multiaddr): string[] {
|
|
|
86
87
|
const sdp = fingerprint.match(/.{1,2}/g)
|
|
87
88
|
|
|
88
89
|
if (sdp == null) {
|
|
89
|
-
throw
|
|
90
|
+
throw new InvalidFingerprintError(fingerprint, ma.toString())
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
return [`${prefix} ${sdp.join(':').toUpperCase()}`, fingerprint]
|
|
@@ -104,7 +105,7 @@ export function toSupportedHashFunction (code: number): 'SHA-1' | 'SHA-256' | 'S
|
|
|
104
105
|
case 0x13:
|
|
105
106
|
return 'SHA-512'
|
|
106
107
|
default:
|
|
107
|
-
throw
|
|
108
|
+
throw new UnsupportedHashAlgorithmError(code)
|
|
108
109
|
}
|
|
109
110
|
}
|
|
110
111
|
|
|
@@ -148,7 +149,7 @@ export function fromMultiAddr (ma: Multiaddr, ufrag: string): RTCSessionDescript
|
|
|
148
149
|
*/
|
|
149
150
|
export function munge (desc: RTCSessionDescriptionInit, ufrag: string): RTCSessionDescriptionInit {
|
|
150
151
|
if (desc.sdp === undefined) {
|
|
151
|
-
throw
|
|
152
|
+
throw new InvalidParametersError("Can't munge a missing SDP")
|
|
152
153
|
}
|
|
153
154
|
|
|
154
155
|
desc.sdp = desc.sdp
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { noise } from '@chainsafe/libp2p-noise'
|
|
2
|
-
import { transportSymbol, serviceCapabilities } from '@libp2p/interface'
|
|
2
|
+
import { transportSymbol, serviceCapabilities, InvalidParametersError } from '@libp2p/interface'
|
|
3
3
|
import * as p from '@libp2p/peer-id'
|
|
4
4
|
import { protocols } from '@multiformats/multiaddr'
|
|
5
5
|
import { WebRTCDirect } from '@multiformats/multiaddr-matcher'
|
|
6
6
|
import * as Digest from 'multiformats/hashes/digest'
|
|
7
7
|
import { concat } from 'uint8arrays/concat'
|
|
8
8
|
import { fromString as uint8arrayFromString } from 'uint8arrays/from-string'
|
|
9
|
-
import {
|
|
9
|
+
import { DataChannelError, InappropriateMultiaddrError, UnimplementedError } from '../error.js'
|
|
10
10
|
import { WebRTCMultiaddrConnection } from '../maconn.js'
|
|
11
11
|
import { DataChannelMuxerFactory } from '../muxer.js'
|
|
12
12
|
import { createStream } from '../stream.js'
|
|
@@ -16,7 +16,7 @@ import * as sdp from './sdp.js'
|
|
|
16
16
|
import { genUfrag } from './util.js'
|
|
17
17
|
import type { WebRTCDialOptions } from './options.js'
|
|
18
18
|
import type { DataChannelOptions } from '../index.js'
|
|
19
|
-
import type { CreateListenerOptions, Transport, Listener, ComponentLogger, Logger, Connection, CounterGroup, Metrics, PeerId } from '@libp2p/interface'
|
|
19
|
+
import type { CreateListenerOptions, Transport, Listener, ComponentLogger, Logger, Connection, CounterGroup, Metrics, PeerId, PrivateKey } from '@libp2p/interface'
|
|
20
20
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
21
21
|
|
|
22
22
|
/**
|
|
@@ -43,6 +43,7 @@ export const CERTHASH_CODE: number = protocols('certhash').code
|
|
|
43
43
|
*/
|
|
44
44
|
export interface WebRTCDirectTransportComponents {
|
|
45
45
|
peerId: PeerId
|
|
46
|
+
privateKey: PrivateKey
|
|
46
47
|
metrics?: Metrics
|
|
47
48
|
logger: ComponentLogger
|
|
48
49
|
}
|
|
@@ -96,7 +97,7 @@ export class WebRTCDirectTransport implements Transport {
|
|
|
96
97
|
* Create transport listeners no supported by browsers
|
|
97
98
|
*/
|
|
98
99
|
createListener (options: CreateListenerOptions): Listener {
|
|
99
|
-
throw
|
|
100
|
+
throw new UnimplementedError('WebRTCTransport.createListener')
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
/**
|
|
@@ -122,7 +123,7 @@ export class WebRTCDirectTransport implements Transport {
|
|
|
122
123
|
|
|
123
124
|
const remotePeerString = ma.getPeerId()
|
|
124
125
|
if (remotePeerString === null) {
|
|
125
|
-
throw
|
|
126
|
+
throw new InappropriateMultiaddrError("we need to have the remote's PeerId")
|
|
126
127
|
}
|
|
127
128
|
const theirPeerId = p.peerIdFromString(remotePeerString)
|
|
128
129
|
|
|
@@ -153,7 +154,7 @@ export class WebRTCDirectTransport implements Transport {
|
|
|
153
154
|
const error = `Data channel was never opened: state: ${handshakeDataChannel.readyState}`
|
|
154
155
|
this.log.error(error)
|
|
155
156
|
this.metrics?.dialerEvents.increment({ open_error: true })
|
|
156
|
-
reject(
|
|
157
|
+
reject(new DataChannelError('data', error))
|
|
157
158
|
}, HANDSHAKE_TIMEOUT_MS)
|
|
158
159
|
|
|
159
160
|
handshakeDataChannel.onopen = (_) => {
|
|
@@ -169,7 +170,7 @@ export class WebRTCDirectTransport implements Transport {
|
|
|
169
170
|
this.log.error(error)
|
|
170
171
|
// NOTE: We use unknown error here but this could potentially be considered a reset by some standards.
|
|
171
172
|
this.metrics?.dialerEvents.increment({ unknown_error: true })
|
|
172
|
-
reject(
|
|
173
|
+
reject(new DataChannelError('data', error))
|
|
173
174
|
}
|
|
174
175
|
})
|
|
175
176
|
|
|
@@ -190,8 +191,6 @@ export class WebRTCDirectTransport implements Transport {
|
|
|
190
191
|
// wait for peerconnection.onopen to fire, or for the datachannel to open
|
|
191
192
|
const handshakeDataChannel = await dataChannelOpenPromise
|
|
192
193
|
|
|
193
|
-
const myPeerId = this.components.peerId
|
|
194
|
-
|
|
195
194
|
// Do noise handshake.
|
|
196
195
|
// Set the Noise Prologue to libp2p-webrtc-noise:<FINGERPRINTS> before starting the actual Noise handshake.
|
|
197
196
|
// <FINGERPRINTS> is the concatenation of the of the two TLS fingerprints of A and B in their multihash byte representation, sorted in ascending order.
|
|
@@ -260,7 +259,10 @@ export class WebRTCDirectTransport implements Transport {
|
|
|
260
259
|
|
|
261
260
|
// For outbound connections, the remote is expected to start the noise handshake.
|
|
262
261
|
// Therefore, we need to secure an inbound noise connection from the remote.
|
|
263
|
-
await connectionEncrypter.secureInbound(
|
|
262
|
+
await connectionEncrypter.secureInbound(wrappedDuplex, {
|
|
263
|
+
signal,
|
|
264
|
+
remotePeer: theirPeerId
|
|
265
|
+
})
|
|
264
266
|
|
|
265
267
|
return await options.upgrader.upgradeOutbound(maConn, { skipProtection: true, skipEncryption: true, muxerFactory })
|
|
266
268
|
} catch (err) {
|
|
@@ -275,14 +277,14 @@ export class WebRTCDirectTransport implements Transport {
|
|
|
275
277
|
*/
|
|
276
278
|
private generateNoisePrologue (pc: RTCPeerConnection, hashCode: number, ma: Multiaddr): Uint8Array {
|
|
277
279
|
if (pc.getConfiguration().certificates?.length === 0) {
|
|
278
|
-
throw
|
|
280
|
+
throw new InvalidParametersError('no local certificate')
|
|
279
281
|
}
|
|
280
282
|
|
|
281
283
|
const localFingerprint = sdp.getLocalFingerprint(pc, {
|
|
282
284
|
log: this.log
|
|
283
285
|
})
|
|
284
286
|
if (localFingerprint == null) {
|
|
285
|
-
throw
|
|
287
|
+
throw new InvalidParametersError('no local fingerprint found')
|
|
286
288
|
}
|
|
287
289
|
|
|
288
290
|
const localFpString = localFingerprint.trim().toLowerCase().replaceAll(':', '')
|