From 000a10b375662b09d7f998a7ee3ddb40f616ef84 Mon Sep 17 00:00:00 2001 From: "Michael Bradley, Jr" Date: Sun, 15 Jul 2018 10:10:55 -0500 Subject: [PATCH 01/10] host utils --- lib/utils/host.js | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 lib/utils/host.js diff --git a/lib/utils/host.js b/lib/utils/host.js new file mode 100644 index 00000000..67588161 --- /dev/null +++ b/lib/utils/host.js @@ -0,0 +1,45 @@ +const isDocker = (() => { + let isDocker; + + const hostname = require('os').hostname(); + const pattern = new RegExp( + '[0-9]+\:[a-z_-]+\:\/docker\/' + hostname + '[0-9a-z]+', 'i' + ); + + try { + isDocker = require('child_process') + .execSync( + 'cat /proc/self/cgroup', + {stdio: ['ignore', 'pipe', 'ignore']} + ) + .toString().match(pattern) !== null; + } catch (e) { + isDocker = false; + } + + return isDocker; +})(); + +const defaultHost = isDocker ? '0.0.0.0' : 'localhost'; + +// when we're runing in Docker, we can expect (generally, in a development +// scenario) that the user would like to connect to the service in the +// container via the **host's** loopback address, so this helper can be used to +// swap 0.0.0.0 for localhost in code/messages that pertain to client-side +function canonicalHost(host) { + return isDocker && host === '0.0.0.0' ? 'localhost' : host; +} + +function dockerHostSwap(host) { + return (isDocker && (host === 'localhost' || host === '127.0.0.1')) ? defaultHost : host; +} + +const defaultCorsHost = canonicalHost(defaultHost); + +module.exports = { + canonicalHost, + defaultCorsHost, + defaultHost, + dockerHostSwap, + isDocker +}; From 2ad8097dcb71a08a291cad33cbca3e007f100e19 Mon Sep 17 00:00:00 2001 From: "Michael Bradley, Jr" Date: Sun, 15 Jul 2018 10:12:18 -0500 Subject: [PATCH 02/10] simulator -- defaultHost, dockerHostSwap --- lib/cmds/simulator.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/cmds/simulator.js b/lib/cmds/simulator.js index 511bd2bf..6892b8ec 100644 --- a/lib/cmds/simulator.js +++ b/lib/cmds/simulator.js @@ -2,6 +2,7 @@ let shelljs = require('shelljs'); let proxy = require('../core/proxy'); const Ipc = require('../core/ipc'); const constants = require('../constants.json'); +const {defaultHost, dockerHostSwap} = require('../utils/host'); class Simulator { constructor(options) { @@ -21,7 +22,7 @@ class Simulator { } let useProxy = this.blockchainConfig.proxy || false; - let host = (options.host || this.blockchainConfig.rpcHost || 'localhost'); + let host = (dockerHostSwap(options.host || this.blockchainConfig.rpcHost) || defaultHost); let port = (options.port || this.blockchainConfig.rpcPort || 8545); cmds.push("-p " + (port + (useProxy ? constants.blockchain.servicePortOnProxy : 0))); From d70264adb6da3816fdf615f99409dd6a20e91cb9 Mon Sep 17 00:00:00 2001 From: "Michael Bradley, Jr" Date: Sun, 15 Jul 2018 12:30:51 -0500 Subject: [PATCH 03/10] blockchain -- defaultHost, dockerHostSwap --- lib/cmds/blockchain/blockchain.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/cmds/blockchain/blockchain.js b/lib/cmds/blockchain/blockchain.js index c556ac40..2ab7fc74 100644 --- a/lib/cmds/blockchain/blockchain.js +++ b/lib/cmds/blockchain/blockchain.js @@ -8,6 +8,8 @@ const constants = require('../../constants.json'); const GethCommands = require('./geth_commands.js'); const DevFunds = require('./dev_funds.js'); +const {defaultHost, dockerHostSwap} = require('../../utils/host'); + /*eslint complexity: ["error", 36]*/ var Blockchain = function(options) { this.blockchainConfig = options.blockchainConfig; @@ -31,7 +33,7 @@ var Blockchain = function(options) { genesisBlock: this.blockchainConfig.genesisBlock || false, datadir: this.blockchainConfig.datadir || false, mineWhenNeeded: this.blockchainConfig.mineWhenNeeded || false, - rpcHost: this.blockchainConfig.rpcHost || 'localhost', + rpcHost: dockerHostSwap(this.blockchainConfig.rpcHost) || defaultHost, rpcPort: this.blockchainConfig.rpcPort || 8545, rpcCorsDomain: this.blockchainConfig.rpcCorsDomain || false, networkId: this.blockchainConfig.networkId || 1337, @@ -44,7 +46,7 @@ var Blockchain = function(options) { bootnodes: this.blockchainConfig.bootnodes || "", rpcApi: (this.blockchainConfig.rpcApi || ['eth', 'web3', 'net', 'debug']), wsRPC: (this.blockchainConfig.wsRPC === undefined) || this.blockchainConfig.wsRPC, - wsHost: this.blockchainConfig.wsHost || 'localhost', + wsHost: dockerHostSwap(this.blockchainConfig.wsHost) || defaultHost, wsPort: this.blockchainConfig.wsPort || 8546, wsOrigins: this.blockchainConfig.wsOrigins || false, wsApi: (this.blockchainConfig.wsApi || defaultWsApi), From 0191ec9d240099eee52fe5f124a9815d66c34cbe Mon Sep 17 00:00:00 2001 From: "Michael Bradley, Jr" Date: Thu, 26 Jul 2018 12:13:18 -0500 Subject: [PATCH 04/10] webserver -- canonicalHost, defaultHost, dockerHostSwap --- lib/modules/webserver/index.js | 3 ++- lib/modules/webserver/server.js | 13 ++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/modules/webserver/index.js b/lib/modules/webserver/index.js index a13fb1b7..a4dada8a 100644 --- a/lib/modules/webserver/index.js +++ b/lib/modules/webserver/index.js @@ -1,3 +1,4 @@ +var {canonicalHost} = require('../../utils/host.js'); var utils = require('../../utils/utils.js'); var Server = require('./server.js'); @@ -26,7 +27,7 @@ class WebServer { } setServiceCheck() { - let url = 'http://' + this.host + ':' + this.port; + let url = 'http://' + canonicalHost(this.host) + ':' + this.port; this.events.request("services:register", 'Webserver', function (cb) { utils.checkIsAvailable(url, function (available) { diff --git a/lib/modules/webserver/server.js b/lib/modules/webserver/server.js index 9f1c64ed..8d974796 100644 --- a/lib/modules/webserver/server.js +++ b/lib/modules/webserver/server.js @@ -1,19 +1,23 @@ let finalhandler = require('finalhandler'); let http = require('http'); let serveStatic = require('serve-static'); +const {canonicalHost, defaultHost, dockerHostSwap} = require('../../utils/host'); require('http-shutdown').extend(); class Server { constructor(options) { this.dist = options.dist || 'dist/'; this.port = options.port || 8000; - this.hostname = options.host || 'localhost'; + this.hostname = dockerHostSwap(options.host) || defaultHost; this.logger = options.logger; } start(callback) { if (this.server && this.server.listening) { - this.logger.warn(__("a webserver is already running at") + " " + ("http://" + this.hostname + ":" + this.port).bold.underline.green); + this.logger.warn(__("a webserver is already running at") + + " " + + ("http://" + canonicalHost(this.hostname) + + ":" + this.port).bold.underline.green); if (callback) { callback(); } @@ -25,7 +29,10 @@ class Server { serve(req, res, finalhandler(req, res)); }).withShutdown(); - this.logger.info(__("webserver available at") + " " + ("http://" + this.hostname + ":" + this.port).bold.underline.green); + this.logger.info(__("webserver available at") + + " " + + ("http://" + canonicalHost(this.hostname) + + ":" + this.port).bold.underline.green); this.server.listen(this.port, this.hostname); if (callback) { callback(); From 6d482cfb95fb4c5e22bef5e41736fe527ef66869 Mon Sep 17 00:00:00 2001 From: "Michael Bradley, Jr" Date: Sun, 15 Jul 2018 12:43:00 -0500 Subject: [PATCH 05/10] buildUrlFromConfig -- canonicalHost --- lib/utils/utils.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/utils/utils.js b/lib/utils/utils.js index 2faea985..193b142d 100644 --- a/lib/utils/utils.js +++ b/lib/utils/utils.js @@ -1,5 +1,6 @@ let http = require('follow-redirects').http; let https = require('follow-redirects').https; +const {canonicalHost} = require('./host'); const balanceRegex = /([0-9]+) ?([a-zA-Z]*)/; @@ -296,7 +297,7 @@ function buildUrl (protocol, host, port){ function buildUrlFromConfig (configObj){ if(!configObj) throw new Error('[utils.buildUrlFromConfig]: config object must cannot be null'); if(!configObj.host) throw new Error('[utils.buildUrlFromConfig]: object must contain a \'host\' property'); - return this.buildUrl(configObj.protocol, configObj.host, configObj.port); + return this.buildUrl(configObj.protocol, canonicalHost(configObj.host), configObj.port); } function getWeiBalanceFromString(balanceString, web3){ From 3885128e180b935aa9ed27b68d5d37790dbe5366 Mon Sep 17 00:00:00 2001 From: "Michael Bradley, Jr" Date: Sun, 15 Jul 2018 15:33:48 -0500 Subject: [PATCH 06/10] config -- canonicalHost, defaultHost --- lib/core/config.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/core/config.js b/lib/core/config.js index 608d1f58..785c75b2 100644 --- a/lib/core/config.js +++ b/lib/core/config.js @@ -5,6 +5,7 @@ const utils = require('../utils/utils.js'); const path = require('path'); const deepEqual = require('deep-equal'); const constants = require('../constants'); +const {canonicalHost, defaultHost} = require('../utils/host'); var Config = function(options) { const self = this; @@ -106,6 +107,9 @@ Config.prototype._updateBlockchainCors = function(){ // remove /ipfs or /bzz: from getUrl if it's there let getUrlParts = storageConfig.upload.getUrl.split('/'); getUrlParts = getUrlParts.slice(0, 3); + let host = canonicalHost(getUrlParts[2].split(':')[0]); + let port = getUrlParts[2].split(':')[1]; + getUrlParts[2] = port ? [host, port].join(':') : host; corsParts.push(getUrlParts.join('/')); } // use our modified getUrl or in case it wasn't specified, use a built url @@ -246,7 +250,7 @@ Config.prototype.loadStorageConfigFile = function() { "upload": { "provider": "ipfs", "protocol": "http", - "host": "localhost", + "host" : defaultHost, "port": 5001, "getUrl": "http://localhost:8080/ipfs/" }, @@ -281,7 +285,9 @@ Config.prototype.loadCommunicationConfigFile = function() { "provider": "whisper", "available_providers": ["whisper"], "connection": { - "host": "localhost", "port": 8546, "type": "ws" + "host": defaultHost, + "port": 8546, + "type": "ws" } } }; @@ -293,7 +299,9 @@ Config.prototype.loadCommunicationConfigFile = function() { Config.prototype.loadWebServerConfigFile = function() { var configObject = { - "enabled": true, "host": "localhost", "port": 8000 + "enabled": true, + "host": defaultHost, + "port": 8000 }; let configFilePath = this._getFileOrOject(this.configDir, 'webserver', 'webserver'); From ca7a46224d7c88bb0c9376452b7733e5e6bb4122 Mon Sep 17 00:00:00 2001 From: "Michael Bradley, Jr" Date: Sun, 15 Jul 2018 15:35:01 -0500 Subject: [PATCH 07/10] storage procs launcher -- canonicalHost --- .../storageProcesses/storageProcessesLauncher.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/processes/storageProcesses/storageProcessesLauncher.js b/lib/processes/storageProcesses/storageProcessesLauncher.js index 2ac624a0..6501638a 100644 --- a/lib/processes/storageProcesses/storageProcessesLauncher.js +++ b/lib/processes/storageProcesses/storageProcessesLauncher.js @@ -4,6 +4,7 @@ const utils = require('../../utils/utils'); const ProcessLauncher = require('../../process/processLauncher'); const constants = require('../../constants'); const StorageUtils = require('./storageUtils'); +const {canonicalHost} = require('../../utils/host'); class StorageProcessesLauncher { constructor(options) { @@ -46,6 +47,9 @@ class StorageProcessesLauncher { // remove /ipfs or /bzz: from getUrl if it's there let getUrlParts = dappConn.getUrl.split('/'); getUrlParts = getUrlParts.slice(0, 3); + let host = canonicalHost(getUrlParts[2].split(':')[0]); + let port = getUrlParts[2].split(':')[1]; + getUrlParts[2] = port ? [host, port].join(':') : host; corsParts.push(getUrlParts.join('/')); } // in case getUrl wasn't specified, use a built url @@ -59,12 +63,12 @@ class StorageProcessesLauncher { if(this.blockchainConfig.enabled) { // add our rpc endpoints to CORS if(this.blockchainConfig.rpcHost && this.blockchainConfig.rpcPort){ - corsParts.push(`http://${this.blockchainConfig.rpcHost}:${this.blockchainConfig.rpcPort}`); + corsParts.push(`http://${canonicalHost(this.blockchainConfig.rpcHost)}:${this.blockchainConfig.rpcPort}`); } // add our ws endpoints to CORS if(this.blockchainConfig.wsRPC && this.blockchainConfig.wsHost && this.blockchainConfig.wsPort){ - corsParts.push(`ws://${this.blockchainConfig.wsHost}:${this.blockchainConfig.wsPort}`); + corsParts.push(`ws://${canonicalHost(this.blockchainConfig.wsHost)}:${this.blockchainConfig.wsPort}`); } } return corsParts; From f91baf73bce49952fb0cf257f2b859c33d87074c Mon Sep 17 00:00:00 2001 From: "Michael Bradley, Jr" Date: Sun, 15 Jul 2018 19:34:33 -0500 Subject: [PATCH 08/10] proxy -- canonicalHost, defaultHost --- lib/core/proxy.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/core/proxy.js b/lib/core/proxy.js index 4a2a6bd4..49a600b2 100644 --- a/lib/core/proxy.js +++ b/lib/core/proxy.js @@ -3,9 +3,11 @@ const http = require('http'); const constants = require('../constants.json'); let commList = {}; -let transactions = {}; +let transactions = {}; let receipts = {}; +const {canonicalHost, defaultHost} = require('../utils/host'); + const parseRequest = function(reqBody){ let jsonO; try { @@ -42,7 +44,7 @@ const parseResponse = function(ipc, resBody){ commList[receipts[jsonO.id]].blockNumber = jsonO.result.blockNumber; commList[receipts[jsonO.id]].gasUsed = jsonO.result.gasUsed; commList[receipts[jsonO.id]].status = jsonO.result.status; - + if(ipc.connected && !ipc.connecting){ ipc.request('log', commList[receipts[jsonO.id]]); } else { @@ -61,7 +63,7 @@ const parseResponse = function(ipc, resBody){ exports.serve = function(ipc, host, port, ws){ let proxy = httpProxy.createProxyServer({ target: { - host, + host: canonicalHost(host), port: port + constants.blockchain.servicePortOnProxy }, ws: ws @@ -80,7 +82,7 @@ exports.serve = function(ipc, host, port, ws){ if(resBody){ parseResponse(ipc, resBody); } - }); + }); }); let server = http.createServer((req, res) => { @@ -110,16 +112,16 @@ exports.serve = function(ipc, host, port, ws){ parseResponse(ipc, data.toString().substr(data.indexOf("{"))); }); }); - + proxy.on('proxyReqWs', (proxyReq, req, socket) => { var parser = new WsParser(0, false); socket.pipe(parser); parser.on('frame', function (frame) { parseRequest(frame.data); }); - + }); } - server.listen(port); + server.listen(port, defaultHost); }; From 6d4870f862a918a5c30bb2c3abf9929e281f44a7 Mon Sep 17 00:00:00 2001 From: "Michael Bradley, Jr" Date: Sun, 15 Jul 2018 19:36:52 -0500 Subject: [PATCH 09/10] whisper -- canonicalHost, defaultHost --- lib/modules/whisper/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/modules/whisper/index.js b/lib/modules/whisper/index.js index a92fb7c6..06d7ce79 100644 --- a/lib/modules/whisper/index.js +++ b/lib/modules/whisper/index.js @@ -2,6 +2,8 @@ let utils = require('../../utils/utils.js'); let fs = require('../../core/fs.js'); let Web3 = require('web3'); +const {canonicalHost, defaultHost} = require('../../utils/host'); + class Whisper { constructor(embark, _options) { @@ -69,7 +71,7 @@ class Whisper { let connection = this.communicationConfig.connection || {}; // todo: make the add code a function as well let config = JSON.stringify({ - server: connection.host || 'localhost', + server: canonicalHost(connection.host || defaultHost), port: connection.port || '8546', type: connection.type || 'ws' }); From 4d0b5366191e72a5054500999b7fd9458b272429 Mon Sep 17 00:00:00 2001 From: "Michael Bradley, Jr" Date: Thu, 26 Jul 2018 13:01:22 -0500 Subject: [PATCH 10/10] revise blockchain test re: docker awareness use defaultHost so tests pass in docker container +1 for wsPort relative to rpcPort port change related to proxy now doing `server.listen(port, defaultHost)` vs. `server.listen(port)` --- test/blockchain.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/blockchain.js b/test/blockchain.js index 3f8ba16f..84a04acd 100644 --- a/test/blockchain.js +++ b/test/blockchain.js @@ -1,6 +1,7 @@ /*globals describe, it*/ const Blockchain = require('../lib/cmds/blockchain/blockchain'); const constants = require('../lib/constants.json'); +const {defaultHost} = require('../lib/utils/host'); const assert = require('assert'); @@ -19,7 +20,7 @@ describe('embark.Blockchain', function () { geth_bin: 'geth', datadir: false, mineWhenNeeded: false, - rpcHost: 'localhost', + rpcHost: defaultHost, rpcPort: 8545, rpcApi: ['eth', 'web3', 'net', 'debug'], rpcCorsDomain: false, @@ -33,7 +34,7 @@ describe('embark.Blockchain', function () { account: {}, bootnodes: "", wsApi: ["eth", "web3", "net", "shh", "debug"], - wsHost: "localhost", + wsHost: defaultHost, wsOrigins: false, wsPort: 8546, wsRPC: true, @@ -62,7 +63,7 @@ describe('embark.Blockchain', function () { geth_bin: 'geth', datadir: '/foo/datadir/', mineWhenNeeded: true, - rpcHost: 'someserver', + rpcHost: defaultHost, rpcPort: 12345, rpcApi: ['eth', 'web3', 'net', 'debug'], rpcCorsDomain: true, @@ -76,9 +77,9 @@ describe('embark.Blockchain', function () { account: {}, bootnodes: "", wsApi: ["eth", "web3", "net", "shh", "debug"], - wsHost: "localhost", + wsHost: defaultHost, wsOrigins: false, - wsPort: 8546, + wsPort: 12346, wsRPC: true, targetGasLimit: false, syncMode: undefined,