@libp2p/webrtc 1.2.0 → 2.0.1

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.
Files changed (97) hide show
  1. package/README.md +3 -3
  2. package/dist/index.min.js +19 -16
  3. package/dist/src/index.d.ts +2 -2
  4. package/dist/src/index.d.ts.map +1 -1
  5. package/dist/src/index.js +2 -2
  6. package/dist/src/index.js.map +1 -1
  7. package/dist/src/maconn.d.ts.map +1 -1
  8. package/dist/src/maconn.js +5 -0
  9. package/dist/src/maconn.js.map +1 -1
  10. package/dist/src/pb/message.d.ts +20 -0
  11. package/dist/src/pb/message.d.ts.map +1 -0
  12. package/dist/src/pb/message.js +73 -0
  13. package/dist/src/pb/message.js.map +1 -0
  14. package/dist/src/{peer_transport → private-to-private}/handler.d.ts +10 -2
  15. package/dist/src/private-to-private/handler.d.ts.map +1 -0
  16. package/dist/src/{peer_transport → private-to-private}/handler.js +23 -11
  17. package/dist/src/private-to-private/handler.js.map +1 -0
  18. package/dist/src/{peer_transport → private-to-private}/listener.d.ts +6 -7
  19. package/dist/src/private-to-private/listener.d.ts.map +1 -0
  20. package/dist/src/private-to-private/listener.js +35 -0
  21. package/dist/src/private-to-private/listener.js.map +1 -0
  22. package/dist/src/{peer_transport/pb/index.d.ts → private-to-private/pb/message.d.ts} +2 -2
  23. package/dist/src/private-to-private/pb/message.d.ts.map +1 -0
  24. package/dist/src/{peer_transport/pb/index.js → private-to-private/pb/message.js} +1 -1
  25. package/dist/src/private-to-private/pb/message.js.map +1 -0
  26. package/dist/src/{peer_transport → private-to-private}/transport.d.ts +4 -6
  27. package/dist/src/private-to-private/transport.d.ts.map +1 -0
  28. package/dist/src/{peer_transport → private-to-private}/transport.js +21 -20
  29. package/dist/src/private-to-private/transport.js.map +1 -0
  30. package/dist/src/{peer_transport → private-to-private}/util.d.ts +3 -4
  31. package/dist/src/private-to-private/util.d.ts.map +1 -0
  32. package/dist/src/{peer_transport → private-to-private}/util.js +4 -6
  33. package/dist/src/private-to-private/util.js.map +1 -0
  34. package/dist/src/private-to-public/options.d.ts.map +1 -0
  35. package/dist/src/private-to-public/options.js.map +1 -0
  36. package/dist/src/private-to-public/sdp.d.ts.map +1 -0
  37. package/dist/src/{sdp.js → private-to-public/sdp.js} +1 -1
  38. package/dist/src/private-to-public/sdp.js.map +1 -0
  39. package/dist/src/private-to-public/transport.d.ts.map +1 -0
  40. package/dist/src/{transport.js → private-to-public/transport.js} +10 -12
  41. package/dist/src/private-to-public/transport.js.map +1 -0
  42. package/dist/src/private-to-public/util.d.ts +2 -0
  43. package/dist/src/private-to-public/util.d.ts.map +1 -0
  44. package/dist/src/private-to-public/util.js +3 -0
  45. package/dist/src/private-to-public/util.js.map +1 -0
  46. package/dist/src/stream.d.ts +2 -2
  47. package/dist/src/stream.d.ts.map +1 -1
  48. package/dist/src/stream.js +17 -17
  49. package/dist/src/stream.js.map +1 -1
  50. package/dist/src/util.d.ts +1 -1
  51. package/dist/src/util.d.ts.map +1 -1
  52. package/dist/src/util.js +3 -2
  53. package/dist/src/util.js.map +1 -1
  54. package/package.json +11 -16
  55. package/src/index.ts +3 -3
  56. package/src/maconn.ts +6 -0
  57. package/src/{message.proto → pb/message.proto} +2 -4
  58. package/src/pb/message.ts +92 -0
  59. package/src/{peer_transport → private-to-private}/handler.ts +32 -14
  60. package/src/private-to-private/listener.ts +55 -0
  61. package/src/{peer_transport/pb/index.ts → private-to-private/pb/message.ts} +1 -1
  62. package/src/{peer_transport → private-to-private}/transport.ts +29 -24
  63. package/src/{peer_transport → private-to-private}/util.ts +6 -9
  64. package/src/{sdp.ts → private-to-public/sdp.ts} +1 -1
  65. package/src/{transport.ts → private-to-public/transport.ts} +10 -12
  66. package/src/private-to-public/util.ts +3 -0
  67. package/src/stream.ts +19 -19
  68. package/src/util.ts +5 -3
  69. package/dist/proto_ts/message.d.ts +0 -56
  70. package/dist/proto_ts/message.d.ts.map +0 -1
  71. package/dist/proto_ts/message.js +0 -86
  72. package/dist/proto_ts/message.js.map +0 -1
  73. package/dist/src/options.d.ts.map +0 -1
  74. package/dist/src/options.js.map +0 -1
  75. package/dist/src/peer_transport/handler.d.ts.map +0 -1
  76. package/dist/src/peer_transport/handler.js.map +0 -1
  77. package/dist/src/peer_transport/listener.d.ts.map +0 -1
  78. package/dist/src/peer_transport/listener.js +0 -33
  79. package/dist/src/peer_transport/listener.js.map +0 -1
  80. package/dist/src/peer_transport/pb/index.d.ts.map +0 -1
  81. package/dist/src/peer_transport/pb/index.js.map +0 -1
  82. package/dist/src/peer_transport/transport.d.ts.map +0 -1
  83. package/dist/src/peer_transport/transport.js.map +0 -1
  84. package/dist/src/peer_transport/util.d.ts.map +0 -1
  85. package/dist/src/peer_transport/util.js.map +0 -1
  86. package/dist/src/sdp.d.ts.map +0 -1
  87. package/dist/src/sdp.js.map +0 -1
  88. package/dist/src/transport.d.ts.map +0 -1
  89. package/dist/src/transport.js.map +0 -1
  90. package/proto_ts/message.ts +0 -106
  91. package/src/peer_transport/listener.ts +0 -44
  92. /package/dist/src/{options.d.ts → private-to-public/options.d.ts} +0 -0
  93. /package/dist/src/{options.js → private-to-public/options.js} +0 -0
  94. /package/dist/src/{sdp.d.ts → private-to-public/sdp.d.ts} +0 -0
  95. /package/dist/src/{transport.d.ts → private-to-public/transport.d.ts} +0 -0
  96. /package/src/{peer_transport/pb/index.proto → private-to-private/pb/message.proto} +0 -0
  97. /package/src/{options.ts → private-to-public/options.ts} +0 -0
@@ -3,7 +3,7 @@ import { abortableDuplex } from 'abortable-iterator'
3
3
  import { pbStream } from 'it-pb-stream'
4
4
  import pDefer, { type DeferredPromise } from 'p-defer'
5
5
  import { DataChannelMuxerFactory } from '../muxer.js'
6
- import * as pb from './pb/index.js'
6
+ import { Message } from './pb/message.js'
7
7
  import { readCandidatesUntilConnected, resolveOnConnected } from './util.js'
8
8
  import type { Stream } from '@libp2p/interface-connection'
9
9
  import type { IncomingStreamData } from '@libp2p/interface-registrar'
@@ -15,9 +15,9 @@ const log = logger('libp2p:webrtc:peer')
15
15
 
16
16
  export type IncomingStreamOpts = { rtcConfiguration?: RTCConfiguration } & IncomingStreamData
17
17
 
18
- export async function handleIncomingStream ({ rtcConfiguration, stream: rawStream }: IncomingStreamOpts): Promise<[RTCPeerConnection, StreamMuxerFactory]> {
18
+ export async function handleIncomingStream ({ rtcConfiguration, stream: rawStream }: IncomingStreamOpts): Promise<{ pc: RTCPeerConnection, muxerFactory: StreamMuxerFactory, remoteAddress: string }> {
19
19
  const signal = AbortSignal.timeout(DEFAULT_TIMEOUT)
20
- const stream = pbStream(abortableDuplex(rawStream, signal)).pb(pb.Message)
20
+ const stream = pbStream(abortableDuplex(rawStream, signal)).pb(Message)
21
21
  const pc = new RTCPeerConnection(rtcConfiguration)
22
22
  const muxerFactory = new DataChannelMuxerFactory(pc)
23
23
 
@@ -30,7 +30,7 @@ export async function handleIncomingStream ({ rtcConfiguration, stream: rawStrea
30
30
  answerSentPromise.promise.then(
31
31
  () => {
32
32
  stream.write({
33
- type: pb.Message.Type.ICE_CANDIDATE,
33
+ type: Message.Type.ICE_CANDIDATE,
34
34
  data: (candidate != null) ? JSON.stringify(candidate.toJSON()) : ''
35
35
  })
36
36
  },
@@ -44,7 +44,7 @@ export async function handleIncomingStream ({ rtcConfiguration, stream: rawStrea
44
44
 
45
45
  // read an SDP offer
46
46
  const pbOffer = await stream.read()
47
- if (pbOffer.type !== pb.Message.Type.SDP_OFFER) {
47
+ if (pbOffer.type !== Message.Type.SDP_OFFER) {
48
48
  throw new Error(`expected message type SDP_OFFER, received: ${pbOffer.type ?? 'undefined'} `)
49
49
  }
50
50
  const offer = new RTCSessionDescription({
@@ -64,7 +64,7 @@ export async function handleIncomingStream ({ rtcConfiguration, stream: rawStrea
64
64
  throw new Error('Failed to create answer')
65
65
  })
66
66
  // write the answer to the remote
67
- stream.write({ type: pb.Message.Type.SDP_ANSWER, data: answer.sdp })
67
+ stream.write({ type: Message.Type.SDP_ANSWER, data: answer.sdp })
68
68
 
69
69
  await pc.setLocalDescription(answer).catch(err => {
70
70
  log.error('could not execute setLocalDescription', err)
@@ -76,7 +76,10 @@ export async function handleIncomingStream ({ rtcConfiguration, stream: rawStrea
76
76
 
77
77
  // wait until candidates are connected
78
78
  await readCandidatesUntilConnected(connectedPromise, pc, stream)
79
- return [pc, muxerFactory]
79
+
80
+ const remoteAddress = parseRemoteAddress(pc.currentRemoteDescription?.sdp ?? '')
81
+
82
+ return { pc, muxerFactory, remoteAddress }
80
83
  }
81
84
 
82
85
  export interface ConnectOptions {
@@ -85,9 +88,8 @@ export interface ConnectOptions {
85
88
  rtcConfiguration?: RTCConfiguration
86
89
  }
87
90
 
88
- export async function initiateConnection ({ rtcConfiguration, signal, stream: rawStream }: ConnectOptions): Promise<[RTCPeerConnection, StreamMuxerFactory]> {
89
- const stream = pbStream(abortableDuplex(rawStream, signal)).pb(pb.Message)
90
-
91
+ export async function initiateConnection ({ rtcConfiguration, signal, stream: rawStream }: ConnectOptions): Promise<{ pc: RTCPeerConnection, muxerFactory: StreamMuxerFactory, remoteAddress: string }> {
92
+ const stream = pbStream(abortableDuplex(rawStream, signal)).pb(Message)
91
93
  // setup peer connection
92
94
  const pc = new RTCPeerConnection(rtcConfiguration)
93
95
  const muxerFactory = new DataChannelMuxerFactory(pc)
@@ -105,14 +107,14 @@ export async function initiateConnection ({ rtcConfiguration, signal, stream: ra
105
107
  // peer
106
108
  pc.onicecandidate = ({ candidate }) => {
107
109
  stream.write({
108
- type: pb.Message.Type.ICE_CANDIDATE,
110
+ type: Message.Type.ICE_CANDIDATE,
109
111
  data: (candidate != null) ? JSON.stringify(candidate.toJSON()) : ''
110
112
  })
111
113
  }
112
114
  // create an offer
113
115
  const offerSdp = await pc.createOffer()
114
116
  // write the offer to the stream
115
- stream.write({ type: pb.Message.Type.SDP_OFFER, data: offerSdp.sdp })
117
+ stream.write({ type: Message.Type.SDP_OFFER, data: offerSdp.sdp })
116
118
  // set offer as local description
117
119
  await pc.setLocalDescription(offerSdp).catch(err => {
118
120
  log.error('could not execute setLocalDescription', err)
@@ -121,7 +123,7 @@ export async function initiateConnection ({ rtcConfiguration, signal, stream: ra
121
123
 
122
124
  // read answer
123
125
  const answerMessage = await stream.read()
124
- if (answerMessage.type !== pb.Message.Type.SDP_ANSWER) {
126
+ if (answerMessage.type !== Message.Type.SDP_ANSWER) {
125
127
  throw new Error('remote should send an SDP answer')
126
128
  }
127
129
 
@@ -133,5 +135,21 @@ export async function initiateConnection ({ rtcConfiguration, signal, stream: ra
133
135
 
134
136
  await readCandidatesUntilConnected(connectedPromise, pc, stream)
135
137
  channel.close()
136
- return [pc, muxerFactory]
138
+
139
+ const remoteAddress = parseRemoteAddress(pc.currentRemoteDescription?.sdp ?? '')
140
+
141
+ return { pc, muxerFactory, remoteAddress }
142
+ }
143
+
144
+ function parseRemoteAddress (sdp: string): string {
145
+ // 'a=candidate:1746876089 1 udp 2113937151 0614fbad-b...ocal 54882 typ host generation 0 network-cost 999'
146
+ const candidateLine = sdp.split('\r\n').filter(line => line.startsWith('a=candidate')).pop()
147
+ const candidateParts = candidateLine?.split(' ')
148
+
149
+ if (candidateLine == null || candidateParts == null || candidateParts.length < 5) {
150
+ log('could not parse remote address from', candidateLine)
151
+ return '/webrtc'
152
+ }
153
+
154
+ return `/dnsaddr/${candidateParts[4]}/${candidateParts[2]}/${candidateParts[3]}/webrtc`
137
155
  }
@@ -0,0 +1,55 @@
1
+ import { EventEmitter } from '@libp2p/interfaces/events'
2
+ import type { Libp2pEvents } from '@libp2p/interface-libp2p'
3
+ import type { PeerId } from '@libp2p/interface-peer-id'
4
+ import type { ListenerEvents, Listener } from '@libp2p/interface-transport'
5
+ import type { Multiaddr } from '@multiformats/multiaddr'
6
+
7
+ export interface ListenerOptions {
8
+ peerId: PeerId
9
+ events: EventEmitter<Libp2pEvents>
10
+ }
11
+
12
+ export class WebRTCPeerListener extends EventEmitter<ListenerEvents> implements Listener {
13
+ private readonly peerId: PeerId
14
+ private listeners: Listener[] = []
15
+
16
+ constructor (opts: ListenerOptions) {
17
+ super()
18
+
19
+ this.peerId = opts.peerId
20
+
21
+ opts.events.addEventListener('transport:listening', (event) => {
22
+ const listener = event.detail
23
+
24
+ if (listener === this || this.listeners.includes(listener)) {
25
+ return
26
+ }
27
+
28
+ this.listeners.push(listener)
29
+ })
30
+
31
+ opts.events.addEventListener('transport:close', (event) => {
32
+ const listener = event.detail
33
+
34
+ this.listeners = this.listeners.filter(l => l !== listener)
35
+ })
36
+ }
37
+
38
+ async listen (ma: Multiaddr): Promise<void> {
39
+ this.safeDispatchEvent('listening', {})
40
+ }
41
+
42
+ getAddrs (): Multiaddr[] {
43
+ return this.listeners
44
+ .map(l => l.getAddrs()
45
+ .map(ma => {
46
+ return ma.encapsulate(`/webrtc/p2p/${this.peerId}`)
47
+ })
48
+ )
49
+ .flat()
50
+ }
51
+
52
+ async close (): Promise<void> {
53
+ this.safeDispatchEvent('close', {})
54
+ }
55
+ }
@@ -82,7 +82,7 @@ export namespace Message {
82
82
  return _codec
83
83
  }
84
84
 
85
- export const encode = (obj: Message): Uint8Array => {
85
+ export const encode = (obj: Partial<Message>): Uint8Array => {
86
86
  return encodeMessage(obj, Message.codec())
87
87
  }
88
88
 
@@ -1,4 +1,4 @@
1
- import { type CreateListenerOptions, type DialOptions, type Listener, symbol, type Transport, type TransportManager, type Upgrader } from '@libp2p/interface-transport'
1
+ import { type CreateListenerOptions, type DialOptions, type Listener, symbol, type Transport, type Upgrader, type TransportManager } from '@libp2p/interface-transport'
2
2
  import { CodeError } from '@libp2p/interfaces/errors'
3
3
  import { logger } from '@libp2p/logger'
4
4
  import { peerIdFromString } from '@libp2p/peer-id'
@@ -8,16 +8,18 @@ import { WebRTCMultiaddrConnection } from '../maconn.js'
8
8
  import { initiateConnection, handleIncomingStream } from './handler.js'
9
9
  import { WebRTCPeerListener } from './listener.js'
10
10
  import type { Connection } from '@libp2p/interface-connection'
11
+ import type { Libp2pEvents } from '@libp2p/interface-libp2p'
11
12
  import type { PeerId } from '@libp2p/interface-peer-id'
12
- import type { PeerStore } from '@libp2p/interface-peer-store'
13
13
  import type { IncomingStreamData, Registrar } from '@libp2p/interface-registrar'
14
+ import type { EventEmitter } from '@libp2p/interfaces/events'
14
15
  import type { Startable } from '@libp2p/interfaces/startable'
15
16
 
16
17
  const log = logger('libp2p:webrtc:peer')
17
18
 
18
- export const TRANSPORT = '/webrtc'
19
- export const SIGNALING_PROTO_ID = '/webrtc-signaling/0.0.1'
20
- export const CODE = protocols('webrtc').code
19
+ const WEBRTC_TRANSPORT = '/webrtc'
20
+ const CIRCUIT_RELAY_TRANSPORT = '/p2p-circuit'
21
+ const SIGNALING_PROTO_ID = '/webrtc-signaling/0.0.1'
22
+ const WEBRTC_CODE = protocols('webrtc').code
21
23
 
22
24
  export interface WebRTCTransportInit {
23
25
  rtcConfiguration?: RTCConfiguration
@@ -28,7 +30,7 @@ export interface WebRTCTransportComponents {
28
30
  registrar: Registrar
29
31
  upgrader: Upgrader
30
32
  transportManager: TransportManager
31
- peerStore: PeerStore
33
+ events: EventEmitter<Libp2pEvents>
32
34
  }
33
35
 
34
36
  export class WebRTCTransport implements Transport, Startable {
@@ -67,22 +69,27 @@ export class WebRTCTransport implements Transport, Startable {
67
69
  filter (multiaddrs: Multiaddr[]): Multiaddr[] {
68
70
  return multiaddrs.filter((ma) => {
69
71
  const codes = ma.protoCodes()
70
- return codes.includes(CODE)
72
+ return codes.includes(WEBRTC_CODE)
71
73
  })
72
74
  }
73
75
 
74
76
  private splitAddr (ma: Multiaddr): { baseAddr: Multiaddr, peerId: PeerId } {
75
- const addrs = ma.toString().split(`${TRANSPORT}/`)
77
+ const addrs = ma.toString().split(WEBRTC_TRANSPORT)
76
78
  if (addrs.length !== 2) {
77
- throw new CodeError('invalid multiaddr', codes.ERR_INVALID_MULTIADDR)
79
+ throw new CodeError('webrtc protocol was not present in multiaddr', codes.ERR_INVALID_MULTIADDR)
80
+ }
81
+
82
+ if (!addrs[0].includes(CIRCUIT_RELAY_TRANSPORT)) {
83
+ throw new CodeError('p2p-circuit protocol was not present in multiaddr', codes.ERR_INVALID_MULTIADDR)
78
84
  }
85
+
79
86
  // look for remote peerId
80
87
  let remoteAddr = multiaddr(addrs[0])
81
- const destination = multiaddr('/' + addrs[1])
88
+ const destination = multiaddr(addrs[1])
82
89
 
83
90
  const destinationIdString = destination.getPeerId()
84
91
  if (destinationIdString == null) {
85
- throw new CodeError('bad destination', codes.ERR_INVALID_MULTIADDR)
92
+ throw new CodeError('destination peer id was missing', codes.ERR_INVALID_MULTIADDR)
86
93
  }
87
94
 
88
95
  const lastProtoInRemote = remoteAddr.protos().pop()
@@ -112,22 +119,21 @@ export class WebRTCTransport implements Transport, Startable {
112
119
  options.signal = controller.signal
113
120
  }
114
121
 
115
- const connection = await this.components.transportManager.dial(baseAddr)
116
-
117
- const rawStream = await connection.newStream([SIGNALING_PROTO_ID], options)
122
+ const connection = await this.components.transportManager.dial(baseAddr, options)
123
+ const signalingStream = await connection.newStream([SIGNALING_PROTO_ID], options)
118
124
 
119
125
  try {
120
- const [pc, muxerFactory] = await initiateConnection({
121
- stream: rawStream,
126
+ const { pc, muxerFactory, remoteAddress } = await initiateConnection({
127
+ stream: signalingStream,
122
128
  rtcConfiguration: this.init.rtcConfiguration,
123
129
  signal: options.signal
124
130
  })
125
- const webrtcMultiaddr = baseAddr.encapsulate(`${TRANSPORT}/p2p/${peerId.toString()}`)
131
+
126
132
  const result = await options.upgrader.upgradeOutbound(
127
133
  new WebRTCMultiaddrConnection({
128
134
  peerConnection: pc,
129
135
  timeline: { open: Date.now() },
130
- remoteAddr: webrtcMultiaddr
136
+ remoteAddr: multiaddr(remoteAddress).encapsulate(`/p2p/${peerId.toString()}`)
131
137
  }),
132
138
  {
133
139
  skipProtection: true,
@@ -137,28 +143,27 @@ export class WebRTCTransport implements Transport, Startable {
137
143
  )
138
144
 
139
145
  // close the stream if SDP has been exchanged successfully
140
- rawStream.close()
146
+ signalingStream.close()
141
147
  return result
142
148
  } catch (err) {
143
149
  // reset the stream in case of any error
144
- rawStream.reset()
150
+ signalingStream.reset()
145
151
  throw err
146
152
  }
147
153
  }
148
154
 
149
155
  async _onProtocol ({ connection, stream }: IncomingStreamData): Promise<void> {
150
156
  try {
151
- const [pc, muxerFactory] = await handleIncomingStream({
157
+ const { pc, muxerFactory, remoteAddress } = await handleIncomingStream({
152
158
  rtcConfiguration: this.init.rtcConfiguration,
153
159
  connection,
154
160
  stream
155
161
  })
156
- const remotePeerId = connection.remoteAddr.getPeerId()
157
- const webrtcMultiaddr = connection.remoteAddr.encapsulate(`${TRANSPORT}/p2p/${remotePeerId}`)
162
+
158
163
  await this.components.upgrader.upgradeInbound(new WebRTCMultiaddrConnection({
159
164
  peerConnection: pc,
160
165
  timeline: { open: (new Date()).getTime() },
161
- remoteAddr: webrtcMultiaddr
166
+ remoteAddr: multiaddr(remoteAddress).encapsulate(`/p2p/${connection.remotePeer.toString()}`)
162
167
  }), {
163
168
  skipEncryption: true,
164
169
  skipProtection: true,
@@ -1,14 +1,11 @@
1
1
  import { logger } from '@libp2p/logger'
2
- import { detect } from 'detect-browser'
3
- import * as pb from './pb/index.js'
2
+ import { isFirefox } from '../util.js'
3
+ import { Message } from './pb/message.js'
4
4
  import type { DeferredPromise } from 'p-defer'
5
5
 
6
- const browser = detect()
7
- export const isFirefox = ((browser != null) && browser.name === 'firefox')
8
-
9
6
  interface MessageStream {
10
- read: () => Promise<pb.Message>
11
- write: (d: pb.Message) => void | Promise<void>
7
+ read: () => Promise<Message>
8
+ write: (d: Message) => void | Promise<void>
12
9
  }
13
10
 
14
11
  const log = logger('libp2p:webrtc:peer:util')
@@ -19,7 +16,7 @@ export const readCandidatesUntilConnected = async (connectedPromise: DeferredPro
19
16
  // check if readResult is a message
20
17
  if (readResult instanceof Object) {
21
18
  const message = readResult
22
- if (message.type !== pb.Message.Type.ICE_CANDIDATE) {
19
+ if (message.type !== Message.Type.ICE_CANDIDATE) {
23
20
  throw new Error('expected only ice candidates')
24
21
  }
25
22
  // end of candidates has been signalled
@@ -53,7 +50,7 @@ export function resolveOnConnected (pc: RTCPeerConnection, promise: DeferredProm
53
50
  case 'failed':
54
51
  case 'disconnected':
55
52
  case 'closed':
56
- promise.reject()
53
+ promise.reject(new Error('RTCPeerConnection was closed'))
57
54
  break
58
55
  default:
59
56
  break
@@ -1,7 +1,7 @@
1
1
  import { logger } from '@libp2p/logger'
2
2
  import { bases } from 'multiformats/basics'
3
3
  import * as multihashes from 'multihashes'
4
- import { inappropriateMultiaddr, invalidArgument, invalidFingerprint, unsupportedHashAlgorithm } from './error.js'
4
+ import { inappropriateMultiaddr, invalidArgument, invalidFingerprint, unsupportedHashAlgorithm } from '../error.js'
5
5
  import { CERTHASH_CODE } from './transport.js'
6
6
  import type { Multiaddr } from '@multiformats/multiaddr'
7
7
  import type { HashCode, HashName } from 'multihashes'
@@ -6,12 +6,12 @@ import { protocols } from '@multiformats/multiaddr'
6
6
  import * as multihashes from 'multihashes'
7
7
  import { concat } from 'uint8arrays/concat'
8
8
  import { fromString as uint8arrayFromString } from 'uint8arrays/from-string'
9
- import { dataChannelError, inappropriateMultiaddr, unimplemented, invalidArgument } from './error.js'
10
- import { WebRTCMultiaddrConnection } from './maconn.js'
11
- import { DataChannelMuxerFactory } from './muxer.js'
12
- import { isFirefox } from './peer_transport/util.js'
9
+ import { dataChannelError, inappropriateMultiaddr, unimplemented, invalidArgument } from '../error.js'
10
+ import { WebRTCMultiaddrConnection } from '../maconn.js'
11
+ import { DataChannelMuxerFactory } from '../muxer.js'
12
+ import { WebRTCStream } from '../stream.js'
13
+ import { isFirefox } from '../util.js'
13
14
  import * as sdp from './sdp.js'
14
- import { WebRTCStream } from './stream.js'
15
15
  import { genUfrag } from './util.js'
16
16
  import type { WebRTCDialOptions } from './options.js'
17
17
  import type { Connection } from '@libp2p/interface-connection'
@@ -189,15 +189,13 @@ export class WebRTCDirectTransport implements Transport {
189
189
  const wrappedDuplex = {
190
190
  ...wrappedChannel,
191
191
  sink: wrappedChannel.sink.bind(wrappedChannel),
192
- source: {
193
- [Symbol.asyncIterator]: async function * () {
194
- for await (const list of wrappedChannel.source) {
195
- for (const buf of list) {
196
- yield buf
197
- }
192
+ source: (async function * () {
193
+ for await (const list of wrappedChannel.source) {
194
+ for (const buf of list) {
195
+ yield buf
198
196
  }
199
197
  }
200
- }
198
+ }())
201
199
  }
202
200
 
203
201
  // Creating the connection before completion of the noise
@@ -0,0 +1,3 @@
1
+
2
+ const charset = Array.from('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/')
3
+ export const genUfrag = (len: number): string => [...Array(len)].map(() => charset.at(Math.floor(Math.random() * charset.length))).join('')
package/src/stream.ts CHANGED
@@ -5,7 +5,7 @@ import { pipe } from 'it-pipe'
5
5
  import { pushable } from 'it-pushable'
6
6
  import defer, { type DeferredPromise } from 'p-defer'
7
7
  import { Uint8ArrayList } from 'uint8arraylist'
8
- import * as pb from '../proto_ts/message.js'
8
+ import { Message } from './pb/message.js'
9
9
  import type { Stream, StreamStat, Direction } from '@libp2p/interface-connection'
10
10
  import type { Source } from 'it-stream-types'
11
11
 
@@ -66,7 +66,7 @@ interface StreamStateInput {
66
66
  * 1 = STOP_SENDING
67
67
  * 2 = RESET
68
68
  */
69
- flag: pb.Message_Flag
69
+ flag: Message.Flag
70
70
  }
71
71
 
72
72
  export enum StreamStates {
@@ -99,7 +99,7 @@ class StreamState {
99
99
 
100
100
  if (direction === 'inbound') {
101
101
  switch (flag) {
102
- case pb.Message_Flag.FIN:
102
+ case Message.Flag.FIN:
103
103
  if (this.state === StreamStates.OPEN) {
104
104
  this.state = StreamStates.READ_CLOSED
105
105
  } else if (this.state === StreamStates.WRITE_CLOSED) {
@@ -107,7 +107,7 @@ class StreamState {
107
107
  }
108
108
  break
109
109
 
110
- case pb.Message_Flag.STOP_SENDING:
110
+ case Message.Flag.STOP_SENDING:
111
111
  if (this.state === StreamStates.OPEN) {
112
112
  this.state = StreamStates.WRITE_CLOSED
113
113
  } else if (this.state === StreamStates.READ_CLOSED) {
@@ -115,7 +115,7 @@ class StreamState {
115
115
  }
116
116
  break
117
117
 
118
- case pb.Message_Flag.RESET:
118
+ case Message.Flag.RESET:
119
119
  this.state = StreamStates.CLOSED
120
120
  break
121
121
  default:
@@ -123,7 +123,7 @@ class StreamState {
123
123
  }
124
124
  } else {
125
125
  switch (flag) {
126
- case pb.Message_Flag.FIN:
126
+ case Message.Flag.FIN:
127
127
  if (this.state === StreamStates.OPEN) {
128
128
  this.state = StreamStates.WRITE_CLOSED
129
129
  } else if (this.state === StreamStates.READ_CLOSED) {
@@ -131,7 +131,7 @@ class StreamState {
131
131
  }
132
132
  break
133
133
 
134
- case pb.Message_Flag.STOP_SENDING:
134
+ case Message.Flag.STOP_SENDING:
135
135
  if (this.state === StreamStates.OPEN) {
136
136
  this.state = StreamStates.READ_CLOSED
137
137
  } else if (this.state === StreamStates.WRITE_CLOSED) {
@@ -139,7 +139,7 @@ class StreamState {
139
139
  }
140
140
  break
141
141
 
142
- case pb.Message_Flag.RESET:
142
+ case Message.Flag.RESET:
143
143
  this.state = StreamStates.CLOSED
144
144
  break
145
145
 
@@ -268,7 +268,7 @@ export class WebRTCStream implements Stream {
268
268
  // surface data from the `Message.message` field through a source.
269
269
  this._src = pipe(
270
270
  this._innersrc,
271
- lengthPrefixed.decode(),
271
+ (source) => lengthPrefixed.decode(source),
272
272
  (source) => (async function * () {
273
273
  for await (const buf of source) {
274
274
  const message = self.processIncomingProtobuf(buf.subarray())
@@ -313,7 +313,7 @@ export class WebRTCStream implements Stream {
313
313
  if (this.streamState.isWriteClosed()) {
314
314
  return
315
315
  }
316
- const msgbuf = pb.Message.toBinary({ message: buf.subarray() })
316
+ const msgbuf = Message.encode({ message: buf.subarray() })
317
317
  const sendbuf = lengthPrefixed.encode.single(msgbuf)
318
318
 
319
319
  this.channel.send(sendbuf.subarray())
@@ -324,7 +324,7 @@ export class WebRTCStream implements Stream {
324
324
  * Handle incoming
325
325
  */
326
326
  processIncomingProtobuf (buffer: Uint8Array): Uint8Array | undefined {
327
- const message = pb.Message.fromBinary(buffer)
327
+ const message = Message.decode(buffer)
328
328
 
329
329
  if (message.flag !== undefined) {
330
330
  const [currentState, nextState] = this.streamState.transition({ direction: 'inbound', flag: message.flag })
@@ -371,14 +371,14 @@ export class WebRTCStream implements Stream {
371
371
  * Close a stream for reading only
372
372
  */
373
373
  closeRead (): void {
374
- const [currentState, nextState] = this.streamState.transition({ direction: 'outbound', flag: pb.Message_Flag.STOP_SENDING })
374
+ const [currentState, nextState] = this.streamState.transition({ direction: 'outbound', flag: Message.Flag.STOP_SENDING })
375
375
  if (currentState === nextState) {
376
376
  // No change, no op
377
377
  return
378
378
  }
379
379
 
380
380
  if (currentState === StreamStates.OPEN || currentState === StreamStates.WRITE_CLOSED) {
381
- this._sendFlag(pb.Message_Flag.STOP_SENDING)
381
+ this._sendFlag(Message.Flag.STOP_SENDING)
382
382
  this._innersrc.end()
383
383
  }
384
384
 
@@ -391,14 +391,14 @@ export class WebRTCStream implements Stream {
391
391
  * Close a stream for writing only
392
392
  */
393
393
  closeWrite (): void {
394
- const [currentState, nextState] = this.streamState.transition({ direction: 'outbound', flag: pb.Message_Flag.FIN })
394
+ const [currentState, nextState] = this.streamState.transition({ direction: 'outbound', flag: Message.Flag.FIN })
395
395
  if (currentState === nextState) {
396
396
  // No change, no op
397
397
  return
398
398
  }
399
399
 
400
400
  if (currentState === StreamStates.OPEN || currentState === StreamStates.READ_CLOSED) {
401
- this._sendFlag(pb.Message_Flag.FIN)
401
+ this._sendFlag(Message.Flag.FIN)
402
402
  this.closeWritePromise.resolve()
403
403
  }
404
404
 
@@ -421,20 +421,20 @@ export class WebRTCStream implements Stream {
421
421
  * @see this.closeWrite
422
422
  */
423
423
  reset (): void {
424
- const [currentState, nextState] = this.streamState.transition({ direction: 'outbound', flag: pb.Message_Flag.RESET })
424
+ const [currentState, nextState] = this.streamState.transition({ direction: 'outbound', flag: Message.Flag.RESET })
425
425
  if (currentState === nextState) {
426
426
  // No change, no op
427
427
  return
428
428
  }
429
429
 
430
- this._sendFlag(pb.Message_Flag.RESET)
430
+ this._sendFlag(Message.Flag.RESET)
431
431
  this.close()
432
432
  }
433
433
 
434
- private _sendFlag (flag: pb.Message_Flag): void {
434
+ private _sendFlag (flag: Message.Flag): void {
435
435
  try {
436
436
  log.trace('Sending flag: %s', flag.toString())
437
- const msgbuf = pb.Message.toBinary({ flag })
437
+ const msgbuf = Message.encode({ flag })
438
438
  this.channel.send(lengthPrefixed.encode.single(msgbuf).subarray())
439
439
  } catch (err) {
440
440
  if (err instanceof Error) {
package/src/util.ts CHANGED
@@ -1,6 +1,8 @@
1
+ import { detect } from 'detect-browser'
2
+
3
+ const browser = detect()
4
+ export const isFirefox = ((browser != null) && browser.name === 'firefox')
5
+
1
6
  export const nopSource = async function * nop (): AsyncGenerator<Uint8Array, any, unknown> {}
2
7
 
3
8
  export const nopSink = async (_: any): Promise<void> => {}
4
-
5
- const charset = Array.from('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/')
6
- export const genUfrag = (len: number): string => [...Array(len)].map(() => charset.at(Math.floor(Math.random() * charset.length))).join('')
@@ -1,56 +0,0 @@
1
- import type { BinaryWriteOptions } from "@protobuf-ts/runtime";
2
- import type { IBinaryWriter } from "@protobuf-ts/runtime";
3
- import type { BinaryReadOptions } from "@protobuf-ts/runtime";
4
- import type { IBinaryReader } from "@protobuf-ts/runtime";
5
- import type { PartialMessage } from "@protobuf-ts/runtime";
6
- import { MessageType } from "@protobuf-ts/runtime";
7
- /**
8
- * @generated from protobuf message webrtc.pb.Message
9
- */
10
- export interface Message {
11
- /**
12
- * @generated from protobuf field: optional webrtc.pb.Message.Flag flag = 1;
13
- */
14
- flag?: Message_Flag;
15
- /**
16
- * @generated from protobuf field: optional bytes message = 2;
17
- */
18
- message?: Uint8Array;
19
- }
20
- /**
21
- * @generated from protobuf enum webrtc.pb.Message.Flag
22
- */
23
- export declare enum Message_Flag {
24
- /**
25
- * The sender will no longer send messages on the stream.
26
- *
27
- * @generated from protobuf enum value: FIN = 0;
28
- */
29
- FIN = 0,
30
- /**
31
- * The sender will no longer read messages on the stream. Incoming data is
32
- * being discarded on receipt.
33
- *
34
- * @generated from protobuf enum value: STOP_SENDING = 1;
35
- */
36
- STOP_SENDING = 1,
37
- /**
38
- * The sender abruptly terminates the sending part of the stream. The
39
- * receiver can discard any data that it already received on that stream.
40
- *
41
- * @generated from protobuf enum value: RESET = 2;
42
- */
43
- RESET = 2
44
- }
45
- declare class Message$Type extends MessageType<Message> {
46
- constructor();
47
- create(value?: PartialMessage<Message>): Message;
48
- internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Message): Message;
49
- internalBinaryWrite(message: Message, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter;
50
- }
51
- /**
52
- * @generated MessageType for protobuf message webrtc.pb.Message
53
- */
54
- export declare const Message: Message$Type;
55
- export {};
56
- //# sourceMappingURL=message.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../proto_ts/message.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD;;GAEG;AACH,MAAM,WAAW,OAAO;IACpB;;OAEG;IACH,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB;;OAEG;IACH,OAAO,CAAC,EAAE,UAAU,CAAC;CACxB;AACD;;GAEG;AACH,oBAAY,YAAY;IACpB;;;;OAIG;IACH,GAAG,IAAI;IACP;;;;;OAKG;IACH,YAAY,IAAI;IAChB;;;;;OAKG;IACH,KAAK,IAAI;CACZ;AAED,cAAM,YAAa,SAAQ,WAAW,CAAC,OAAO,CAAC;;IAO3C,MAAM,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC,OAAO,CAAC,GAAG,OAAO;IAOhD,kBAAkB,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO;IAsBhH,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,kBAAkB,GAAG,aAAa;CAY3G;AACD;;GAEG;AACH,eAAO,MAAM,OAAO,cAAqB,CAAC"}