11import { generateKeyPair , privateKeyToCryptoKeyPair } from '@libp2p/crypto/keys'
2- import { InvalidParametersError , NotFoundError , NotStartedError , serviceCapabilities , transportSymbol } from '@libp2p/interface'
3- import { peerIdFromString } from '@libp2p/peer-id'
4- import { CODE_P2P } from '@multiformats/multiaddr'
2+ import { InvalidParametersError , NotFoundError , NotStartedError } from '@libp2p/interface'
53import { WebRTCDirect } from '@multiformats/multiaddr-matcher'
64import { BasicConstraintsExtension , X509Certificate , X509CertificateGenerator } from '@peculiar/x509'
75import { Key } from 'interface-datastore'
@@ -11,46 +9,19 @@ import { sha256 } from 'multiformats/hashes/sha2'
119import { equals as uint8ArrayEquals } from 'uint8arrays/equals'
1210import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
1311import { DEFAULT_CERTIFICATE_DATASTORE_KEY , DEFAULT_CERTIFICATE_LIFESPAN , DEFAULT_CERTIFICATE_PRIVATE_KEY_NAME , DEFAULT_CERTIFICATE_RENEWAL_THRESHOLD } from '../constants.js'
14- import { genUfrag } from '../util.js'
1512import { WebRTCDirectListener } from './listener.js'
16- import { connect } from './utils/connect.js'
17- import { createDialerRTCPeerConnection } from './utils/get-rtcpeerconnection.js'
1813import { formatAsPem } from './utils/pem.js'
19- import type { DataChannelOptions , TransportCertificate } from '../index.js'
20- import type { WebRTCDialEvents } from '../private-to-private/transport.js'
21- import type { CreateListenerOptions , Transport , Listener , ComponentLogger , Logger , Connection , CounterGroup , Metrics , PeerId , DialTransportOptions , PrivateKey , Upgrader , Startable } from '@libp2p/interface'
22- import type { TransportManager } from '@libp2p/interface-internal'
14+ import type { TransportCertificate } from '../index.js'
15+ import type { CreateListenerOptions , Transport , Listener , PrivateKey , Startable } from '@libp2p/interface'
2316import type { Keychain } from '@libp2p/keychain'
2417import type { Multiaddr } from '@multiformats/multiaddr'
25- import type { Datastore } from 'interface-datastore'
2618import type { TypedEventTarget } from 'main-event'
19+ import { WebRTCDirectTransport as WebRTCDirectBrowserTransport } from './transport.browser.js'
20+ import type { WebRTCTransportDirectInit as WebRTCTransportDirectBrowserInit , WebRTCMetrics , WebRTCDirectTransportComponents } from './transport.browser.ts'
2721
28- export interface WebRTCDirectTransportComponents {
29- peerId : PeerId
30- privateKey : PrivateKey
31- metrics ?: Metrics
32- logger : ComponentLogger
33- transportManager : TransportManager
34- upgrader : Upgrader
35- keychain ?: Keychain
36- datastore : Datastore
37- }
38-
39- export interface WebRTCMetrics {
40- dialerEvents : CounterGroup
41- }
42-
43- export interface WebRTCTransportDirectInit {
44- /**
45- * The default configuration used by all created RTCPeerConnections
46- */
47- rtcConfiguration ?: RTCConfiguration | ( ( ) => RTCConfiguration | Promise < RTCConfiguration > )
48-
49- /**
50- * The default configuration used by all created RTCDataChannels
51- */
52- dataChannel ?: DataChannelOptions
22+ export type { WebRTCMetrics , WebRTCDirectTransportComponents }
5323
24+ export interface WebRTCTransportDirectInit extends WebRTCTransportDirectBrowserInit {
5425 /**
5526 * Use an existing TLS certificate to secure incoming connections or supply
5627 * settings to generate one.
@@ -96,44 +67,32 @@ export interface WebRTCDirectTransportCertificateEvents {
9667 'certificate:renew' : CustomEvent < TransportCertificate >
9768}
9869
99- export class WebRTCDirectTransport implements Transport , Startable {
100- private readonly log : Logger
101- private readonly metrics ?: WebRTCMetrics
102- private readonly components : WebRTCDirectTransportComponents
103- private readonly init : WebRTCTransportDirectInit
70+ interface CertInit {
71+ certificate ?: TransportCertificate
72+ certificateDatastoreKey ?: string
73+ certificateKeychainName ?: string
74+ certificateLifespan ?: number
75+ certificateRenewalThreshold ?: number
76+ }
77+
78+ export class WebRTCDirectTransport extends WebRTCDirectBrowserTransport implements Transport , Startable {
10479 private certificate ?: TransportCertificate
10580 private privateKey ?: PrivateKey
10681 private readonly emitter : TypedEventTarget < WebRTCDirectTransportCertificateEvents >
10782 private renewCertificateTask ?: ReturnType < typeof setTimeout >
83+ private certInit : CertInit
10884
10985 constructor ( components : WebRTCDirectTransportComponents , init : WebRTCTransportDirectInit = { } ) {
110- this . log = components . logger . forComponent ( 'libp2p:webrtc-direct' )
111- this . components = components
112- this . init = init
86+ super ( components , init )
87+
11388 this . emitter = new TypedEventEmitter ( )
89+ this . certInit = init
11490
11591 if ( init . certificateLifespan != null && init . certificateRenewalThreshold != null && init . certificateRenewalThreshold >= init . certificateLifespan ) {
11692 throw new InvalidParametersError ( 'Certificate renewal threshold must be less than certificate lifespan' )
11793 }
118-
119- if ( components . metrics != null ) {
120- this . metrics = {
121- dialerEvents : components . metrics . registerCounterGroup ( 'libp2p_webrtc-direct_dialer_events_total' , {
122- label : 'event' ,
123- help : 'Total count of WebRTC-direct dial events by type'
124- } )
125- }
126- }
12794 }
12895
129- readonly [ transportSymbol ] = true
130-
131- readonly [ Symbol . toStringTag ] = '@libp2p/webrtc-direct'
132-
133- readonly [ serviceCapabilities ] : string [ ] = [
134- '@libp2p/transport'
135- ]
136-
13796 async start ( ) : Promise < void > {
13897 this . certificate = await this . getCertificate ( )
13998 }
@@ -146,51 +105,6 @@ export class WebRTCDirectTransport implements Transport, Startable {
146105 this . certificate = undefined
147106 }
148107
149- /**
150- * Dial a given multiaddr
151- */
152- async dial ( ma : Multiaddr , options : DialTransportOptions < WebRTCDialEvents > ) : Promise < Connection > {
153- this . log ( 'dial %a' , ma )
154- // do not create RTCPeerConnection if the signal has already been aborted
155- options . signal . throwIfAborted ( )
156-
157- let theirPeerId : PeerId | undefined
158- const remotePeerString = ma . getComponents ( ) . findLast ( c => c . code === CODE_P2P ) ?. value
159- if ( remotePeerString != null ) {
160- theirPeerId = peerIdFromString ( remotePeerString )
161- }
162-
163- const ufrag = genUfrag ( )
164-
165- // https://github.com/libp2p/specs/blob/master/webrtc/webrtc-direct.md#browser-to-public-server
166- const {
167- peerConnection,
168- muxerFactory
169- } = await createDialerRTCPeerConnection ( 'client' , ufrag , {
170- rtcConfiguration : typeof this . init . rtcConfiguration === 'function' ? await this . init . rtcConfiguration ( ) : this . init . rtcConfiguration ?? { } ,
171- dataChannel : this . init . dataChannel
172- } )
173-
174- try {
175- return await connect ( peerConnection , muxerFactory , ufrag , {
176- role : 'client' ,
177- log : this . log ,
178- logger : this . components . logger ,
179- events : this . metrics ?. dialerEvents ,
180- signal : options . signal ,
181- remoteAddr : ma ,
182- dataChannel : this . init . dataChannel ,
183- upgrader : options . upgrader ,
184- peerId : this . components . peerId ,
185- remotePeer : theirPeerId ,
186- privateKey : this . components . privateKey
187- } )
188- } catch ( err ) {
189- peerConnection . close ( )
190- throw err
191- }
192- }
193-
194108 /**
195109 * Create a transport listener - this will throw in browsers
196110 */
@@ -222,9 +136,9 @@ export class WebRTCDirectTransport implements Transport, Startable {
222136 }
223137
224138 private async getCertificate ( forceRenew ?: boolean ) : Promise < TransportCertificate > {
225- if ( isTransportCertificate ( this . init . certificate ) ) {
139+ if ( isTransportCertificate ( this . certInit . certificate ) ) {
226140 this . log ( 'using provided TLS certificate' )
227- return this . init . certificate
141+ return this . certInit . certificate
228142 }
229143
230144 const privateKey = await this . loadOrCreatePrivateKey ( )
@@ -242,7 +156,7 @@ export class WebRTCDirectTransport implements Transport, Startable {
242156 return this . privateKey
243157 }
244158
245- const keychainName = this . init . certificateKeychainName ?? DEFAULT_CERTIFICATE_PRIVATE_KEY_NAME
159+ const keychainName = this . certInit . certificateKeychainName ?? DEFAULT_CERTIFICATE_PRIVATE_KEY_NAME
246160 const keychain = this . getKeychain ( )
247161
248162 try {
@@ -278,7 +192,7 @@ export class WebRTCDirectTransport implements Transport, Startable {
278192 }
279193
280194 let cert : X509Certificate
281- const dsKey = new Key ( this . init . certificateDatastoreKey ?? DEFAULT_CERTIFICATE_DATASTORE_KEY )
195+ const dsKey = new Key ( this . certInit . certificateDatastoreKey ?? DEFAULT_CERTIFICATE_DATASTORE_KEY )
282196 const keyPair = await privateKeyToCryptoKeyPair ( privateKey )
283197
284198 try {
@@ -299,7 +213,7 @@ export class WebRTCDirectTransport implements Transport, Startable {
299213 }
300214
301215 // set timeout to renew certificate
302- let renewTime = ( cert . notAfter . getTime ( ) - ( this . init . certificateRenewalThreshold ?? DEFAULT_CERTIFICATE_RENEWAL_THRESHOLD ) ) - Date . now ( )
216+ let renewTime = ( cert . notAfter . getTime ( ) - ( this . certInit . certificateRenewalThreshold ?? DEFAULT_CERTIFICATE_RENEWAL_THRESHOLD ) ) - Date . now ( )
303217
304218 if ( renewTime < 0 ) {
305219 renewTime = 100
@@ -332,7 +246,7 @@ export class WebRTCDirectTransport implements Transport, Startable {
332246 const cert = new X509Certificate ( buf )
333247
334248 // check expiry date
335- const expiryTime = cert . notAfter . getTime ( ) - ( this . init . certificateRenewalThreshold ?? DEFAULT_CERTIFICATE_RENEWAL_THRESHOLD )
249+ const expiryTime = cert . notAfter . getTime ( ) - ( this . certInit . certificateRenewalThreshold ?? DEFAULT_CERTIFICATE_RENEWAL_THRESHOLD )
336250
337251 if ( Date . now ( ) > expiryTime ) {
338252 this . log ( 'stored TLS certificate has expired' )
@@ -362,7 +276,7 @@ export class WebRTCDirectTransport implements Transport, Startable {
362276
363277 async createCertificate ( dsKey : Key , keyPair : CryptoKeyPair ) : Promise < X509Certificate > {
364278 const notBefore = new Date ( )
365- const notAfter = new Date ( Date . now ( ) + ( this . init . certificateLifespan ?? DEFAULT_CERTIFICATE_LIFESPAN ) )
279+ const notAfter = new Date ( Date . now ( ) + ( this . certInit . certificateLifespan ?? DEFAULT_CERTIFICATE_LIFESPAN ) )
366280
367281 // have to set ms to 0 to work around https://github.com/PeculiarVentures/x509/issues/73
368282 notBefore . setMilliseconds ( 0 )
0 commit comments