@@ -16,18 +16,16 @@ const Ipfs = require('ipfs')
16
16
const HttpApi = require ( 'ipfs/src/http' )
17
17
const multiaddr = require ( 'multiaddr' )
18
18
const maToUri = require ( 'multiaddr-to-uri' )
19
+ const getPort = require ( 'get-port' )
19
20
20
21
const { optionDefaults } = require ( '../options' )
21
22
22
23
// js-ipfs with embedded hapi HTTP server
23
24
let node = null
24
25
let nodeHttpApi = null
25
26
26
- exports . init = function init ( opts ) {
27
- log ( 'init embedded:chromesockets' )
28
-
27
+ async function buildConfig ( opts ) {
29
28
const defaultOpts = JSON . parse ( optionDefaults . ipfsNodeConfig )
30
-
31
29
defaultOpts . libp2p = {
32
30
config : {
33
31
dht : {
@@ -36,9 +34,31 @@ exports.init = function init (opts) {
36
34
}
37
35
}
38
36
}
39
-
40
37
const userOpts = JSON . parse ( opts . ipfsNodeConfig )
41
- const ipfsOpts = mergeOptions . call ( { concatArrays : true } , defaultOpts , userOpts , { start : false } )
38
+ const ipfsNodeConfig = mergeOptions . call ( { concatArrays : true } , defaultOpts , userOpts , { start : false } )
39
+
40
+ // Detect when API or Gateway port is not available (taken by something else)
41
+ // We find the next free port and update configuration to use it instead
42
+ const multiaddr2port = ( ma ) => parseInt ( new URL ( multiaddr2httpUrl ( ma ) ) . port , 10 )
43
+ const gatewayPort = multiaddr2port ( ipfsNodeConfig . config . Addresses . Gateway )
44
+ const apiPort = multiaddr2port ( ipfsNodeConfig . config . Addresses . API )
45
+ log ( `checking if ports are available: api: ${ apiPort } , gateway: ${ gatewayPort } ` )
46
+ const freeGatewayPort = await getPort ( { port : getPort . makeRange ( gatewayPort , gatewayPort + 100 ) } )
47
+ const freeApiPort = await getPort ( { port : getPort . makeRange ( apiPort , apiPort + 100 ) } )
48
+ if ( gatewayPort !== freeGatewayPort || apiPort !== freeApiPort ) {
49
+ log ( `updating config to available ports: api: ${ freeApiPort } , gateway: ${ freeGatewayPort } ` )
50
+ const addrs = ipfsNodeConfig . config . Addresses
51
+ addrs . Gateway = addrs . Gateway . replace ( gatewayPort . toString ( ) , freeGatewayPort . toString ( ) )
52
+ addrs . API = addrs . API . replace ( apiPort . toString ( ) , freeApiPort . toString ( ) )
53
+ }
54
+
55
+ return ipfsNodeConfig
56
+ }
57
+
58
+ exports . init = async function init ( opts ) {
59
+ log ( 'init embedded:chromesockets' )
60
+
61
+ const ipfsOpts = await buildConfig ( opts )
42
62
log ( 'creating js-ipfs with opts: ' , ipfsOpts )
43
63
node = new Ipfs ( ipfsOpts )
44
64
@@ -90,9 +110,9 @@ async function updateConfigWithHttpEndpoints (ipfs, opts) {
90
110
ipfsApiUrl : httpApi ,
91
111
ipfsNodeConfig : JSON . stringify ( ipfsNodeConfig , null , 2 )
92
112
}
93
- // update current runtime config (in place, effective without restart )
113
+ // update current runtime config (in place)
94
114
Object . assign ( opts , configChanges )
95
- // update user config in storage (effective on next run )
115
+ // update user config in storage (triggers async client restart if ports changed )
96
116
log ( `synchronizing ipfsNodeConfig with customGatewayUrl (${ configChanges . customGatewayUrl } ) and ipfsApiUrl (${ configChanges . ipfsApiUrl } )` )
97
117
await browser . storage . local . set ( configChanges )
98
118
}
0 commit comments