From af85a7cadd2471c6d1ad730b659783453e9e5e37 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Tue, 2 Jul 2024 18:52:17 +0200 Subject: [PATCH] fix: add default STUN servers to WebRTC transport (#2606) To make it easier to connect to remote nodes, add default STUN servers to the WebRTC transport. --- packages/transport-webrtc/src/constants.ts | 16 ++++++++++++++++ .../src/private-to-private/transport.ts | 5 +++-- .../src/private-to-public/transport.ts | 4 ++-- packages/transport-webrtc/src/util.ts | 17 +++++++++++++++++ 4 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 packages/transport-webrtc/src/constants.ts diff --git a/packages/transport-webrtc/src/constants.ts b/packages/transport-webrtc/src/constants.ts new file mode 100644 index 0000000000..0626d8e6a2 --- /dev/null +++ b/packages/transport-webrtc/src/constants.ts @@ -0,0 +1,16 @@ +/** + * STUN servers help clients discover their own public IPs + * + * @see https://gist.github.com/mondain/b0ec1cf5f60ae726202e + */ +export const DEFAULT_ICE_SERVERS = [ + 'stun:stun.l.google.com:19302', + 'stun:stun1.l.google.com:19302', + 'stun:stun2.l.google.com:19302', + 'stun:stun3.l.google.com:19302', + 'stun:stun4.l.google.com:19302', + 'stun:global.stun.twilio.com:3478', + 'stun:stun.cloudflare.com:3478', + 'stun:stun.services.mozilla.com:3478', + 'stun:stun.1und1.de:3478' +] diff --git a/packages/transport-webrtc/src/private-to-private/transport.ts b/packages/transport-webrtc/src/private-to-private/transport.ts index 134bd7a9b8..cc76f5a3da 100644 --- a/packages/transport-webrtc/src/private-to-private/transport.ts +++ b/packages/transport-webrtc/src/private-to-private/transport.ts @@ -6,6 +6,7 @@ import { WebRTC } from '@multiformats/multiaddr-matcher' import { codes } from '../error.js' import { WebRTCMultiaddrConnection } from '../maconn.js' import { DataChannelMuxerFactory } from '../muxer.js' +import { getRtcConfiguration } from '../util.js' import { RTCPeerConnection } from '../webrtc/index.js' import { initiateConnection } from './initiate-connection.js' import { WebRTCPeerListener } from './listener.js' @@ -134,7 +135,7 @@ export class WebRTCTransport implements Transport, Startable { this.log.trace('dialing address: %a', ma) const { remoteAddress, peerConnection, muxerFactory } = await initiateConnection({ - rtcConfiguration: typeof this.init.rtcConfiguration === 'function' ? await this.init.rtcConfiguration() : this.init.rtcConfiguration, + rtcConfiguration: await getRtcConfiguration(this.init.rtcConfiguration), dataChannel: this.init.dataChannel, multiaddr: ma, dataChannelOptions: this.init.dataChannel, @@ -166,7 +167,7 @@ export class WebRTCTransport implements Transport, Startable { async _onProtocol ({ connection, stream }: IncomingStreamData): Promise { const signal = AbortSignal.timeout(this.init.inboundConnectionTimeout ?? INBOUND_CONNECTION_TIMEOUT) - const peerConnection = new RTCPeerConnection(typeof this.init.rtcConfiguration === 'function' ? await this.init.rtcConfiguration() : this.init.rtcConfiguration) + const peerConnection = new RTCPeerConnection(await getRtcConfiguration(this.init.rtcConfiguration)) const muxerFactory = new DataChannelMuxerFactory(this.components, { peerConnection, dataChannelOptions: this.init.dataChannel diff --git a/packages/transport-webrtc/src/private-to-public/transport.ts b/packages/transport-webrtc/src/private-to-public/transport.ts index bf026fabc8..900f936a51 100644 --- a/packages/transport-webrtc/src/private-to-public/transport.ts +++ b/packages/transport-webrtc/src/private-to-public/transport.ts @@ -10,7 +10,7 @@ import { dataChannelError, inappropriateMultiaddr, unimplemented, invalidArgumen import { WebRTCMultiaddrConnection } from '../maconn.js' import { DataChannelMuxerFactory } from '../muxer.js' import { createStream } from '../stream.js' -import { isFirefox } from '../util.js' +import { getRtcConfiguration, isFirefox } from '../util.js' import { RTCPeerConnection } from '../webrtc/index.js' import * as sdp from './sdp.js' import { genUfrag } from './util.js' @@ -139,7 +139,7 @@ export class WebRTCDirectTransport implements Transport { } as any) const peerConnection = new RTCPeerConnection({ - ...(typeof this.init.rtcConfiguration === 'function' ? await this.init.rtcConfiguration() : this.init.rtcConfiguration ?? {}), + ...(await getRtcConfiguration(this.init.rtcConfiguration)), certificates: [certificate] }) diff --git a/packages/transport-webrtc/src/util.ts b/packages/transport-webrtc/src/util.ts index 6dbff5e24c..17f713cbd5 100644 --- a/packages/transport-webrtc/src/util.ts +++ b/packages/transport-webrtc/src/util.ts @@ -1,6 +1,7 @@ import { detect } from 'detect-browser' import pDefer from 'p-defer' import pTimeout from 'p-timeout' +import { DEFAULT_ICE_SERVERS } from './constants.js' import type { LoggerOptions } from '@libp2p/interface' const browser = detect() @@ -64,3 +65,19 @@ export interface AbortPromiseOptions { signal?: AbortSignal message?: string } + +export async function getRtcConfiguration (config?: RTCConfiguration | (() => RTCConfiguration | Promise)): Promise { + config = config ?? {} + + if (typeof config === 'function') { + config = await config() + } + + config.iceServers = config.iceServers ?? DEFAULT_ICE_SERVERS.map(url => ({ + urls: [ + url + ] + })) + + return config +}