diff --git a/app/js/app.config.js b/app/js/app.config.js index cedf5665fd070b4e8f2202b46a724da523b38046..823ae41d8edc8838fd81e989ab10848ffe7164f6 100644 --- a/app/js/app.config.js +++ b/app/js/app.config.js @@ -1,5 +1,4 @@ module.exports = () => { - require('./services/bma')(angular); require('./services/webmin')(angular); const duniterApp = angular.module('duniterUIApp', [ @@ -66,7 +65,7 @@ module.exports = () => { } }; - let homeControllers = angular.module('homeControllers', ['duniter.services.bma', 'duniter.services.webmin', 'ngFileUpload']); + let homeControllers = angular.module('homeControllers', ['duniter.services.webmin', 'ngFileUpload']); homeControllers.controller('IndexController', require('./controllers/IndexController')); homeControllers.controller('AboutController', require('./controllers/AboutController')); diff --git a/app/js/controllers/IndexController.js b/app/js/controllers/IndexController.js index 77daba155323efc5348a8cfa6c6cda0eb611773d..7ab86dca7958b042ea80c165209df78491c6b195 100644 --- a/app/js/controllers/IndexController.js +++ b/app/js/controllers/IndexController.js @@ -2,7 +2,7 @@ var co = require('co'); -module.exports = ($scope, $http, $state, BMA, Webmin, summary, UIUtils) => { +module.exports = ($scope, $http, $state, Webmin, summary, UIUtils) => { UIUtils.changeTitle(summary.version); diff --git a/app/js/controllers/init/create/RootBlockController.js b/app/js/controllers/init/create/RootBlockController.js index 21b332859eab132e5901d64d3c7afba59840f164..6a264506e2821da8c0d2d86c9a05a0ce398b9529 100644 --- a/app/js/controllers/init/create/RootBlockController.js +++ b/app/js/controllers/init/create/RootBlockController.js @@ -3,7 +3,7 @@ var co = require('co'); var conf = require('js/lib/conf/conf'); -module.exports = ($scope, $http, $state, BMA, Webmin) => { +module.exports = ($scope, $http, $state, Webmin) => { $scope.generated = ''; $scope.started = false; @@ -48,8 +48,7 @@ module.exports = ($scope, $http, $state, BMA, Webmin) => { }); $scope.accept = () => co(function *() { - const node_address = $scope.$parent.conf.local_ipv4 || $scope.$parent.conf.local_ipv6; - let res = yield BMA(node_address + ":" + $scope.$parent.conf.lport).blockchain.block_add({ + let res = yield Webmin.blockchain.block_add({ block: $scope.generated }); if (res.number == 0) { diff --git a/app/js/controllers/init/sync/SyncController.js b/app/js/controllers/init/sync/SyncController.js index 493811bad50928fe6a2eeb9d8868fd1da6b81e18..6e827a6b25807c47c901e96cfc18488d26ad7ce9 100644 --- a/app/js/controllers/init/sync/SyncController.js +++ b/app/js/controllers/init/sync/SyncController.js @@ -2,7 +2,7 @@ var co = require('co'); -module.exports = ($scope, $http, $state, $timeout, $stateParams, $translate, BMA, UIUtils, Webmin) => { +module.exports = ($scope, $http, $state, $timeout, $stateParams, $translate, UIUtils, Webmin) => { let syncWS = Webmin.ws(); diff --git a/app/js/controllers/main/MainController.js b/app/js/controllers/main/MainController.js index 60be9e3bdbc4c4903829a07784b864d4c383c82f..3a112f5ee11131e3a95bb0d45a15d4a8f7f738b8 100644 --- a/app/js/controllers/main/MainController.js +++ b/app/js/controllers/main/MainController.js @@ -2,7 +2,7 @@ var co = require('co'); -module.exports = ($scope, $state, $http, $timeout, $interval, BMA, Webmin, summary, UIUtils, Base58) => { +module.exports = ($scope, $state, $http, $timeout, $interval, Webmin, summary, UIUtils, Base58) => { const local_host = summary.host.split(':')[0]; // We suppose IPv4 configuration const local_port = summary.host.split(':')[1]; diff --git a/app/js/controllers/main/graphs/GraphsBlockchainController.js b/app/js/controllers/main/graphs/GraphsBlockchainController.js index 014aecdf00c9e881e13115cba967ab50f60fcd5a..ac92208528e3c823075665181ce54fdd6583dcb2 100644 --- a/app/js/controllers/main/graphs/GraphsBlockchainController.js +++ b/app/js/controllers/main/graphs/GraphsBlockchainController.js @@ -4,7 +4,7 @@ const BLOCKS_COUNT = 40; var co = require('co'); -module.exports = ($scope, $state, $timeout, BMA, Webmin, UIUtils, Graph) => { +module.exports = ($scope, $state, $timeout, Webmin, UIUtils, Graph) => { let data = {}; @@ -32,8 +32,8 @@ module.exports = ($scope, $state, $timeout, BMA, Webmin, UIUtils, Graph) => { $scope.updateGraphs = () => { return co(function *() { let summary = yield Webmin.summary(); - let parameters = yield BMA(summary.host).currency.parameters(); - let blocks = yield BMA(summary.host).blockchain.blocks({ + let parameters = yield Webmin.currency.parameters(); + let blocks = yield Webmin.blockchain.blocks({ count: $scope.blocksCount, from: Math.max(0, summary.current.number - $scope.blocksCount) }); diff --git a/app/js/controllers/main/home/tabs/HomeNetworkController.js b/app/js/controllers/main/home/tabs/HomeNetworkController.js index 6ea67504c11d1d7c311cdb4e1b4cff3d680941ab..0a81476690fa71ff5acd1fe44c6d9941e2fce365 100644 --- a/app/js/controllers/main/home/tabs/HomeNetworkController.js +++ b/app/js/controllers/main/home/tabs/HomeNetworkController.js @@ -1,6 +1,6 @@ "use strict"; -module.exports = ($scope, BMA, peers, summary) => { +module.exports = ($scope, Webmin, peers) => { $scope.peers = peers.peers; @@ -9,7 +9,7 @@ module.exports = ($scope, BMA, peers, summary) => { $scope.update = () => co(function *() { $scope.searching = true; let delayP = Q.delay(500); - $scope.peers = (yield BMA(summary.host).network.peers()).peers; + $scope.peers = (yield Webmin.network.peers()).peers; yield delayP; $scope.searching = false; $scope.$apply(); diff --git a/app/js/controllers/main/home/tabs/OverviewController.js b/app/js/controllers/main/home/tabs/OverviewController.js index efa415015b4821c7c07d7cf85bd89995d4461e09..33657160fb2bbdd0a63033e8680e3ae3809d4fba 100644 --- a/app/js/controllers/main/home/tabs/OverviewController.js +++ b/app/js/controllers/main/home/tabs/OverviewController.js @@ -1,6 +1,6 @@ "use strict"; -module.exports = ($scope, $interval, BMA, Webmin, UIUtils, summary, ws) => { +module.exports = ($scope, $interval, Webmin, UIUtils, summary, ws) => { let co = require('co'); let moment = require('moment'); @@ -17,6 +17,11 @@ module.exports = ($scope, $interval, BMA, Webmin, UIUtils, summary, ws) => { UD = parseInt((summary.lastUDBlock.dividend * Math.pow(10, summary.lastUDBlock.unitbase) + Math.pow(summary.parameters.c, 2) * M / N).toFixed(0)); } $scope.current = summary.current; + $scope.current_currency = summary.current.currency; + $scope.current_number = summary.current.number; + $scope.current_membersCount = summary.current.membersCount; + $scope.current_medianTime = summary.current.medianTime; + $scope.current_powMin = summary.current.powMin; $scope.monetaryMass = parseInt(M / UD) || 0; $scope.server_started = true; $scope.server_stopped = false; @@ -106,7 +111,7 @@ module.exports = ($scope, $interval, BMA, Webmin, UIUtils, summary, ws) => { }); function bindBlockWS(cb) { - BMA(summary.host).websocket.block().on(undefined, (block) => { + Webmin.wsBlock().on(undefined, (block) => { $scope.current_currency = block.currency; $scope.current_number = block.number; $scope.current_membersCount = block.membersCount; diff --git a/app/js/controllers/main/settings/SettingsController.js b/app/js/controllers/main/settings/SettingsController.js index bec568e8d794c1ca5ee5f6a2d1387cc5fb8e1015..dcb7b94f194a8675dbd86b48baa7a89157ebaf03 100644 --- a/app/js/controllers/main/settings/SettingsController.js +++ b/app/js/controllers/main/settings/SettingsController.js @@ -2,7 +2,7 @@ var co = require('co'); -module.exports = ($scope, $http, $state, $location, BMA, Webmin, UIUtils) => { +module.exports = ($scope, $http, $state, $location, Webmin, UIUtils) => { UIUtils.enableTabs(); diff --git a/app/js/lib/conf/routes.js b/app/js/lib/conf/routes.js index 0b20964a7db1378b3dedf136d35a089166d1a485..967ab26bab28fad02eb9e7ee22fcb8b4d55ec670 100644 --- a/app/js/lib/conf/routes.js +++ b/app/js/lib/conf/routes.js @@ -133,9 +133,8 @@ module.exports = (app) => { url: '/network', template: require('views/main/home/tabs/network'), resolve: { - peers: (Webmin, BMA) => co(function *() { - const summary = yield Webmin.summary(); - return BMA(summary.host).network.peers(); + peers: (Webmin) => co(function *() { + return Webmin.network.peers(); }) }, controller: 'HomeNetworkController' @@ -155,11 +154,10 @@ module.exports = (app) => { url: '/data', template: require('views/main/settings/tabs/data'), resolve: { - peers: (Webmin, BMA) => co(function *() { + peers: (Webmin) => co(function *() { try { - const summary = yield Webmin.summary(); - let self = yield BMA(summary.host).network.peering.self(); - let res = yield BMA(summary.host).network.peers(); + let self = yield Webmin.network.selfPeer(); + let res = yield Webmin.network.peers(); return _.filter(res.peers, (p) => p.pubkey != self.pubkey && p.status == 'UP'); } catch (e) { console.error(e); diff --git a/app/js/services/bma.js b/app/js/services/bma.js deleted file mode 100644 index 6f1dcea273c20fb0d47f298a95eedb2e50618530..0000000000000000000000000000000000000000 --- a/app/js/services/bma.js +++ /dev/null @@ -1,192 +0,0 @@ -const co = require('co'); -const _ = require('underscore'); -const conf = require('../lib/conf/conf'); - -module.exports = (angular) => { - - angular.module('duniter.services.bma', ['ngResource']) - - .factory('BMA', function($http, $q) { - function httpProtocol() { - return window.location.protocol + '//'; - } - - function wsProtocol() { - return window.location.protocol === 'https:' ? 'wss://' : 'ws://'; - } - - function BMA(host) { - function getResource(uri, protocol) { - return function (params) { - return $q.when(httpGet(uri, params, protocol)); - } - } - - function httpGet(uri, params, protocol) { - return Q.Promise((resolve, reject) => { - var config = { - timeout: conf.api_timeout - }, suffix = '', pkeys = [], queryParams = null; - if (typeof params == 'object') { - pkeys = _.keys(params); - queryParams = {}; - } - pkeys.forEach(function (pkey) { - var prevURI = uri; - uri = uri.replace(new RegExp(':' + pkey), params[pkey]); - if (prevURI == uri) { - queryParams[pkey] = params[pkey]; - } - }); - config.params = queryParams; - const url = (protocol || httpProtocol()) + host + uri + suffix; - $http.get(url, config) - .success(function (data, status, headers, config) { - resolve(data); - }) - .error(function (data, status, headers, config) { - console.log(data); - reject(data); - }); - }); - } - - function postResource(uri) { - return function (data, params) { - return $q.when(Q.Promise((resolve, reject) => { - var config = { - timeout: 4000 - }, suffix = '', pkeys = [], queryParams = null; - if (typeof params == 'object') { - pkeys = _.keys(params); - queryParams = {}; - } - pkeys.forEach(function (pkey) { - var prevURI = uri; - uri = uri.replace(new RegExp(':' + pkey), params[pkey]); - if (prevURI == uri) { - queryParams[pkey] = params[pkey]; - } - }); - config.params = queryParams; - const url = httpProtocol() + host + uri + suffix; - $http.post(url, data, config) - .success(function (data, status, headers, config) { - resolve(data); - }) - .error(function (data, status, headers, config) { - reject(data); - }); - })); - } - } - - function bmaGET(uri) { - return getResource('' + uri); - } - - function bmaPOST(uri) { - return postResource('' + uri); - } - - function bmaWS(uri) { - return ws(wsProtocol() + host + '' + uri); - } - - let wsMap = {}; - - function ws(uri) { - var sock = wsMap[uri] || new WebSocket(uri); - wsMap[uri] = sock; - sock.onclose = function (e) { - console.log('close'); - console.log(e); - }; - sock.onerror = function (e) { - console.log('onerror'); - console.log(e); - }; - let opened = false, openedCallback; - sock.onopen = function () { - opened = true; - openedCallback && openedCallback(); - }; - let listener, messageType; - sock.onmessage = function (e) { - let res = JSON.parse(e.data); - if (res.type == 'log') { - for (let i = 0, len = res.value.length; i < len; i++) { - let log = res.value[i]; - // console[log.level](log.msg); - } - } - if (listener && (messageType === undefined || (res.type === messageType))) { - listener(res); - } - }; - return { - on: function (type, callback) { - messageType = type; - listener = callback; - }, - whenOpened: () => co(function *() { - if (opened) return true; - else { - yield Q.Promise((resolve) => { - openedCallback = resolve; - }); - } - }), - send: (msg) => sock.send(msg) - }; - } - - return { - node: { - summary: bmaGET('/node/summary') - }, - wot: { - lookup: bmaGET('/wot/lookup/:search'), - members: bmaGET('/wot/members') - }, - network: { - peering: { - self: bmaGET('/network/peering'), - peers: bmaGET('/network/peering/peers') - }, - peers: bmaGET('/network/peers') - }, - currency: { - parameters: bmaGET('/blockchain/parameters') - }, - blockchain: { - current: bmaGET('/blockchain/current'), - block: bmaGET('/blockchain/block/:block'), - blocks: bmaGET('/blockchain/blocks/:count/:from'), - block_add: bmaPOST('/blockchain/block'), - stats: { - ud: bmaGET('/blockchain/with/ud'), - tx: bmaGET('/blockchain/with/tx') - } - }, - websocket: { - block: function () { - return bmaWS('/ws/block'); - }, - peer: function () { - return bmaWS('/ws/peer'); - } - }, - origin: { - network: { - peering: { - self: getResource('/network/peering', 'http://') - } - } - } - } - } - - return BMA; - }); -}; diff --git a/app/js/services/webmin.js b/app/js/services/webmin.js index 8e14c8862f67d421a0a57d26cad8ac06bf946801..2712a811f3941577fa3202d39c9d580d7eb27cc1 100644 --- a/app/js/services/webmin.js +++ b/app/js/services/webmin.js @@ -134,9 +134,15 @@ module.exports = (angular) => { getImportURL: () => httpProtocol() + server + '/webmin/data/duniter_import', isNodePubliclyReachable: getResource('/webmin/server/reachable'), ws: () => ws(wsProtocol() + server + '/webmin/ws'), + wsBlock: () => ws(wsProtocol() + server + '/webmin/ws_block'), + wsPeer: () => ws(wsProtocol() + server + '/webmin/ws_peer'), summary: getResource('/webmin/summary'), powSummary: getResource('/webmin/summary/pow'), logsExport: (nbLines) => getResource('/webmin/logs/export/' + nbLines)(), + blockchain: { + blocks: (opts) => getResource('/webmin/blockchain/blocks/' + opts.count + '/' + opts.from)(), + block_add: postResource('/webmin/blockchain/add') + }, server: { http: { start: getResource('/webmin/server/http/start'), @@ -163,7 +169,12 @@ module.exports = (angular) => { preview: postResource('/webmin/key/preview') }, network: { - interfaces: getResource('/webmin/network/interfaces') + interfaces: getResource('/webmin/network/interfaces'), + selfPeer: getResource('/webmin/network/self'), + peers: getResource('/webmin/network/peers') + }, + currency: { + parameters: getResource('/webmin/currency/parameters') } } } diff --git a/server/controller/webmin.js b/server/controller/webmin.js index 91d13f79111b53fcfa002cae003ca0986ce2d45b..41dc112bdc46090596446c12c03445b1842c8e87 100644 --- a/server/controller/webmin.js +++ b/server/controller/webmin.js @@ -401,6 +401,19 @@ function WebAdmin (duniterServer) { }; }); + this.selfPeer = () => co(function*(){ + return server.PeeringService.peer(); + }); + + this.peers = () => co(function*(){ + const peers = yield server.dal.listAllPeers(); + return { peers }; + }); + + this.currencyParameters = () => co(function*(){ + return server.dal.getParameters(); + }); + this.startAllServices = () => co(function *() { // Allow services to be stopped stopServicesP = null; @@ -533,6 +546,25 @@ function WebAdmin (duniterServer) { }; }); + this.blockchainBlocks = (req) => co(function *() { + const start = parseInt(req.params.from); + const end = parseInt(req.params.from) + parseInt(req.params.count) - 1; + const blocks = yield server.dal.getBlocksBetween(start, end); + return blocks; + }); + + this.blockchainAdd = (req) => co(function *() { + try { + let rawBlock = http2raw.block(req); + rawBlock = dos2unix(rawBlock); + const written = yield server.writeRaw(rawBlock, constants.ENTITY_BLOCK); + return written.json(); + } catch (e) { + logger.error(e); + throw e; + } + }); + function plugForConf() { return co(function *() { yield server.plugFileSystem(); diff --git a/server/lib/routes.js b/server/lib/routes.js index 2d7102ec40e35d707e9637b850789fce79a7fb96..37d008479c07df765cc5e96d9d2584417a3b9053 100644 --- a/server/lib/routes.js +++ b/server/lib/routes.js @@ -12,7 +12,10 @@ module.exports = { webmin: function(webminCtrl, app) { handleRequest(app.get.bind(app), '/webmin/summary', webminCtrl.summary); handleRequest(app.get.bind(app), '/webmin/summary/pow', webminCtrl.powSummary); - handleRequest(app.get.bind(app), '/webmin/logs/export/:quantity', webminCtrl.logsExport); + handleRequest(app.get.bind(app), '/webmin/currency/parameters', webminCtrl.currencyParameters); + handleRequest(app.get.bind(app), '/webmin/blockchain/blocks/:count/:from', webminCtrl.blockchainBlocks); + handleRequest(app.post.bind(app), '/webmin/blockchain/add', webminCtrl.blockchainAdd); + handleRequest(app.get.bind(app), '/webmin/logs/export/:quantity', webminCtrl.logsExport); handleRequest(app.post.bind(app), '/webmin/key/preview', webminCtrl.previewPubkey); handleRequest(app.get.bind(app), '/webmin/server/reachable', webminCtrl.isNodePubliclyReachable); handleRequest(app.get.bind(app), '/webmin/server/http/start', webminCtrl.startHTTP); @@ -32,6 +35,8 @@ module.exports = { handleRequest(app.get.bind(app), '/webmin/server/services/stop_all', webminCtrl.stopAllServices); handleRequest(app.get.bind(app), '/webmin/server/reset/data', webminCtrl.resetData); handleRequest(app.get.bind(app), '/webmin/network/interfaces', webminCtrl.listInterfaces); + handleRequest(app.get.bind(app), '/webmin/network/self', webminCtrl.selfPeer); + handleRequest(app.get.bind(app), '/webmin/network/peers', webminCtrl.peers); handleFileRequest(app.get.bind(app),'/webmin/data/duniter_export', webminCtrl.exportData); handleRequest(app.post.bind(app), '/webmin/data/duniter_import', webminCtrl.importData); }, @@ -135,6 +140,54 @@ module.exports = { })); } })); + + /****** + * BLOCKS + */ + + // Socket for synchronization events + const server = webminCtrl.server; + let currentBlock; + const wssBlock = new WebSocketServer({ + server: httpServer, + path: '/webmin/ws_block' + }); + + wssBlock.on('error', function (error) { + logger.error('Error on WS Server'); + logger.error(error); + }); + + wssBlock.on('connection', function connection(ws) { + co(function *() { + currentBlock = yield server.dal.getCurrentBlockOrNull(); + if (currentBlock) { + ws.send(JSON.stringify(currentBlock)); + } + }); + }); + + wssBlock.broadcast = (data) => wssBlock.clients.forEach((client) => { + try { + client.send(data); + } catch (e) { + logger.error('error on ws: %s', e); + } + }); + + // Forward blocks & peers + server + .pipe(es.mapSync(function(data) { + try { + // Broadcast block + if (data.joiners) { + currentBlock = data; + wssBlock.broadcast(JSON.stringify(currentBlock)); + } + } catch (e) { + logger.error('error on ws mapSync:', e); + } + })); }; } };