2016-03-23 15:07:25 +01:00
'use strict'
2017-01-20 17:27:50 +00:00
const multiaddr = require ( 'multiaddr' )
/ *
* Valid combinations
* /
2017-01-22 14:36:58 +00:00
const DNS4 = base ( 'dns4' )
const DNS6 = base ( 'dns6' )
2017-03-22 02:16:06 -07:00
const _DNS = or (
2018-02-12 11:15:11 +01:00
base ( 'dnsaddr' ) ,
2017-01-22 14:36:58 +00:00
DNS4 ,
DNS6
)
2017-01-20 17:27:50 +00:00
const IP = or ( base ( 'ip4' ) , base ( 'ip6' ) )
2018-09-12 11:21:52 +02:00
const TCP = or (
and ( IP , base ( 'tcp' ) ) ,
and ( _DNS , base ( 'tcp' ) )
)
2017-01-20 17:27:50 +00:00
const UDP = and ( IP , base ( 'udp' ) )
const UTP = and ( UDP , base ( 'utp' ) )
2017-03-22 02:16:06 -07:00
const DNS = or (
and ( _DNS , base ( 'tcp' ) ) ,
_DNS
)
2017-01-20 17:27:50 +00:00
const WebSockets = or (
and ( TCP , base ( 'ws' ) ) ,
and ( DNS , base ( 'ws' ) )
)
2017-01-20 17:46:26 +00:00
const WebSocketsSecure = or (
and ( TCP , base ( 'wss' ) ) ,
and ( DNS , base ( 'wss' ) )
)
2017-01-20 17:27:50 +00:00
const HTTP = or (
and ( TCP , base ( 'http' ) ) ,
2018-04-06 17:09:16 +01:00
and ( IP , base ( 'http' ) ) ,
and ( DNS , base ( 'http' ) ) ,
and ( DNS )
)
const HTTPS = or (
and ( TCP , base ( 'https' ) ) ,
and ( IP , base ( 'https' ) ) ,
and ( DNS , base ( 'https' ) )
2017-01-20 17:27:50 +00:00
)
2017-01-20 17:46:26 +00:00
const WebRTCStar = or (
2017-09-03 09:46:57 +01:00
and ( WebSockets , base ( 'p2p-webrtc-star' ) , base ( 'ipfs' ) ) ,
and ( WebSocketsSecure , base ( 'p2p-webrtc-star' ) , base ( 'ipfs' ) )
2017-01-20 17:46:26 +00:00
)
2017-09-06 14:13:17 +02:00
const WebSocketStar = or (
and ( WebSockets , base ( 'p2p-websocket-star' ) , base ( 'ipfs' ) ) ,
and ( WebSocketsSecure , base ( 'p2p-websocket-star' ) , base ( 'ipfs' ) ) ,
and ( WebSockets , base ( 'p2p-websocket-star' ) ) ,
and ( WebSocketsSecure , base ( 'p2p-websocket-star' ) )
2017-09-03 09:46:57 +01:00
)
2018-04-06 17:09:16 +01:00
const WebRTCDirect = or (
and ( HTTP , base ( 'p2p-webrtc-direct' ) ) ,
and ( HTTPS , base ( 'p2p-webrtc-direct' ) )
)
2017-01-20 17:27:50 +00:00
2017-01-20 17:46:26 +00:00
const Reliable = or (
WebSockets ,
WebSocketsSecure ,
HTTP ,
2018-04-06 17:09:16 +01:00
HTTPS ,
2017-01-20 17:46:26 +00:00
WebRTCStar ,
WebRTCDirect ,
TCP ,
UTP
)
2017-01-20 17:27:50 +00:00
2019-02-07 12:04:12 +01:00
// Unlike ws-star, stardust can run over any transport thus removing the requirement for websockets (but don't even think about running a stardust server over webrtc-star ;) )
const Stardust = or (
and ( Reliable , base ( 'p2p-stardust' ) , base ( 'ipfs' ) ) ,
and ( Reliable , base ( 'p2p-stardust' ) )
)
2017-02-25 23:41:14 -08:00
let _IPFS = or (
2017-01-20 17:27:50 +00:00
and ( Reliable , base ( 'ipfs' ) ) ,
2017-02-25 23:41:14 -08:00
WebRTCStar ,
base ( 'ipfs' )
)
2017-03-26 19:40:06 -07:00
const _Circuit = or (
2017-02-25 23:41:14 -08:00
and ( _IPFS , base ( 'p2p-circuit' ) , _IPFS ) ,
and ( _IPFS , base ( 'p2p-circuit' ) ) ,
and ( base ( 'p2p-circuit' ) , _IPFS ) ,
2017-03-14 10:57:21 -07:00
and ( Reliable , base ( 'p2p-circuit' ) ) ,
2017-03-26 19:40:06 -07:00
and ( base ( 'p2p-circuit' ) , Reliable ) ,
2017-02-25 23:41:14 -08:00
base ( 'p2p-circuit' )
)
2017-03-26 19:40:06 -07:00
const CircuitRecursive = ( ) => or (
and ( _Circuit , CircuitRecursive ) ,
_Circuit
)
const Circuit = CircuitRecursive ( )
2017-02-25 23:41:14 -08:00
const IPFS = or (
2017-03-26 19:40:06 -07:00
and ( Circuit , _IPFS , Circuit ) ,
2017-02-25 23:41:14 -08:00
and ( _IPFS , Circuit ) ,
2017-02-26 00:07:33 -08:00
and ( Circuit , _IPFS ) ,
Circuit ,
2017-02-25 23:41:14 -08:00
_IPFS
2017-01-20 17:27:50 +00:00
)
exports . DNS = DNS
2017-01-22 14:36:58 +00:00
exports . DNS4 = DNS4
exports . DNS6 = DNS6
2016-01-19 17:23:52 +01:00
exports . IP = IP
exports . TCP = TCP
exports . UDP = UDP
exports . UTP = UTP
2017-01-16 14:59:35 +00:00
exports . HTTP = HTTP
2018-04-06 17:09:16 +01:00
exports . HTTPS = HTTPS
2016-03-12 12:36:19 +00:00
exports . WebSockets = WebSockets
2017-01-20 17:46:26 +00:00
exports . WebSocketsSecure = WebSocketsSecure
2017-09-06 14:13:17 +02:00
exports . WebSocketStar = WebSocketStar
2016-05-21 19:57:26 +01:00
exports . WebRTCStar = WebRTCStar
2017-01-16 14:59:35 +00:00
exports . WebRTCDirect = WebRTCDirect
2016-01-19 17:23:52 +01:00
exports . Reliable = Reliable
2019-02-07 12:04:12 +01:00
exports . Stardust = Stardust
2017-02-25 23:41:14 -08:00
exports . Circuit = Circuit
2016-01-19 17:23:52 +01:00
exports . IPFS = IPFS
2017-01-20 17:27:50 +00:00
/ *
* Validation funcs
* /
2019-01-25 13:03:41 +01:00
function makeMatchesFunction ( partialMatch ) {
return function matches ( a ) {
2019-02-26 16:31:50 +01:00
if ( ! multiaddr . isMultiaddr ( a ) ) {
2019-01-25 13:03:41 +01:00
try {
a = multiaddr ( a )
} catch ( err ) { // catch error
return false // also if it's invalid it's propably not matching as well so return false
}
2016-01-19 17:23:52 +01:00
}
2017-01-20 17:27:50 +00:00
let out = partialMatch ( a . protoNames ( ) )
2016-01-19 17:23:52 +01:00
if ( out === null ) {
return false
}
return out . length === 0
}
2019-01-25 13:03:41 +01:00
}
2016-01-19 17:23:52 +01:00
2019-01-25 13:03:41 +01:00
function and ( ) {
const args = Array . from ( arguments )
2016-01-19 17:23:52 +01:00
function partialMatch ( a ) {
if ( a . length < args . length ) {
return null
}
2017-09-03 09:46:57 +01:00
args . some ( ( arg ) => {
a = typeof arg === 'function'
? arg ( ) . partialMatch ( a )
: arg . partialMatch ( a )
2016-01-19 17:23:52 +01:00
if ( a === null ) {
return true
}
} )
return a
}
return {
2018-04-06 17:09:16 +01:00
toString : function ( ) { return '{ ' + args . join ( ' ' ) + ' }' } ,
2016-01-19 17:23:52 +01:00
input : args ,
2019-01-25 13:03:41 +01:00
matches : makeMatchesFunction ( partialMatch ) ,
2016-01-19 17:23:52 +01:00
partialMatch : partialMatch
}
}
function or ( ) {
2017-01-20 17:27:50 +00:00
const args = Array . from ( arguments )
2016-01-19 17:23:52 +01:00
function partialMatch ( a ) {
2017-01-20 17:27:50 +00:00
let out = null
2017-09-03 09:46:57 +01:00
args . some ( ( arg ) => {
const res = typeof arg === 'function'
? arg ( ) . partialMatch ( a )
: arg . partialMatch ( a )
2016-01-19 17:23:52 +01:00
if ( res ) {
out = res
return true
}
} )
return out
}
2017-01-20 17:27:50 +00:00
const result = {
2016-01-19 17:23:52 +01:00
toString : function ( ) { return '{ ' + args . join ( ' ' ) + ' }' } ,
input : args ,
2019-01-25 13:03:41 +01:00
matches : makeMatchesFunction ( partialMatch ) ,
2016-01-19 17:23:52 +01:00
partialMatch : partialMatch
}
2016-05-28 15:34:50 +01:00
return result
2016-01-19 17:23:52 +01:00
}
function base ( n ) {
2017-01-20 17:27:50 +00:00
const name = n
2017-03-26 19:40:06 -07:00
2016-01-19 17:23:52 +01:00
function matches ( a ) {
if ( typeof a === 'string' ) {
2019-01-25 13:03:41 +01:00
try {
a = multiaddr ( a )
} catch ( err ) { // catch error
return false // also if it's invalid it's propably not matching as well so return false
}
2016-01-19 17:23:52 +01:00
}
2017-01-20 17:27:50 +00:00
const pnames = a . protoNames ( )
2016-01-19 17:23:52 +01:00
if ( pnames . length === 1 && pnames [ 0 ] === name ) {
return true
}
return false
}
function partialMatch ( protos ) {
if ( protos . length === 0 ) {
return null
}
if ( protos [ 0 ] === name ) {
return protos . slice ( 1 )
}
return null
}
return {
toString : function ( ) { return name } ,
matches : matches ,
partialMatch : partialMatch
}
}