diff --git a/MeshCentralServer.njsproj b/MeshCentralServer.njsproj index 37ee0ca1..6097d310 100644 --- a/MeshCentralServer.njsproj +++ b/MeshCentralServer.njsproj @@ -97,6 +97,7 @@ + @@ -618,25 +619,31 @@ + + + + + + diff --git a/firebase.js b/firebase.js new file mode 100644 index 00000000..1bf752cb --- /dev/null +++ b/firebase.js @@ -0,0 +1,72 @@ +/** +* @description MeshCentral Firebase communication module +* @author Ylian Saint-Hilaire +* @copyright Intel Corporation 2018-2021 +* @license Apache-2.0 +* @version v0.0.1 +*/ + +/*xjslint node: true */ +/*xjslint plusplus: true */ +/*xjslint maxlen: 256 */ +/*jshint node: true */ +/*jshint strict: false */ +/*jshint esversion: 6 */ +"use strict"; + +// Construct the Firebase object +module.exports.CreateFirebase = function (parent, senderid, serverkey) { + var obj = {}; + obj.messageId = 1; + + const Sender = require('node-xcs').Sender; + const Message = require('node-xcs').Message; + const Notification = require('node-xcs').Notification; + const xcs = new Sender(senderid, serverkey); + + // Messages received from client (excluding receipts) + xcs.on('message', function (messageId, from, data, category) { + console.log('Firebase-Message', messageId, from, data, category); + }); + + // Only fired for messages where options.delivery_receipt_requested = true + /* + xcs.on('receipt', function (messageId, from, data, category) { console.log('Firebase-Receipt', messageId, from, data, category); }); + xcs.on('connected', function () { console.log('Connected'); }); + xcs.on('disconnected', function () { console.log('disconnected'); }); + xcs.on('online', function () { console.log('online'); }); + xcs.on('error', function (e) { console.log('error', e); }); + xcs.on('message-error', function (e) { console.log('message-error', e); }); + */ + + xcs.start(); + + //var payload = { notification: { title: command.title, body: command.msg }, data: { url: obj.msgurl } }; + //var options = { priority: 'High', timeToLive: 5 * 60 }; // TTL: 5 minutes, priority 'Normal' or 'High' + + // Send an outbound push notification + obj.sendToDevice = function (token, payload, options, func) { + // Built the on-screen notification + var notification = null; + if (payload.notification) { + var notification = new Notification('ic_launcher') + .title(payload.notification.title) + .body(payload.notification.body) + .build(); + } + + // Build the message + var message = new Message('msg_' + (++obj.messageId)); + if (options.priority) { message.priority(options.priority); } + if (payload.data) { for (var i in payload.data) { message.addData(i, payload.data[i]); } } + if (notification) { message.notification(notification) } + message.build(); + + // Send the message + function callback(result) { callback.func(result.getMessageId(), result.getError(), result.getErrorDescription()) } + callback.func = func; + xcs.sendNoRetry(message, token, callback); + } + + return obj; +}; \ No newline at end of file diff --git a/meshcentral.js b/meshcentral.js index 32d782d8..712ccb9f 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -1545,15 +1545,8 @@ function CreateMeshCentralServer(config, args) { } // Setup Firebase - if (config.firebase != null) { - try { - obj.firebase = require('firebase-admin'); - var firebaseServiceAccount = require(obj.path.join(obj.datapath, config.firebase.serviceaccountkeyfile)); - obj.firebase.initializeApp({ credential: obj.firebase.credential.cert(firebaseServiceAccount) }); - } catch (ex) { - console.log('Unable to setup Firebase: ' + ex); - delete obj.firebase; - } + if ((config.firebase != null) && (typeof config.firebase.senderid == 'string') && (typeof config.firebase.serverkey == 'string')) { + obj.firebase = require('./firebase').CreateFirebase(this, config.firebase.senderid, config.firebase.serverkey); } // Start periodic maintenance @@ -3066,7 +3059,7 @@ function mainStart() { } // Firebase Support - if (config.firebase != null) { modules.push('firebase-admin'); } + if (config.firebase != null) { modules.push('node-xcs'); } // Syslog support if ((require('os').platform() != 'win32') && (config.settings.syslog || config.settings.syslogjson)) { modules.push('modern-syslog'); } diff --git a/meshrelay.js b/meshrelay.js index 46f1bdac..aec63528 100644 --- a/meshrelay.js +++ b/meshrelay.js @@ -414,11 +414,12 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) { } } }); + parent.wsrelays[obj.id] = { peer1: obj, state: 1 }; // No timeout on connections with push notification. } else { ws._socket.pause(); // Hold traffic until the other connection parent.parent.debug('relay', 'Relay holding: ' + obj.id + ' (' + obj.req.clientIp + ') ' + (obj.authenticated ? 'Authenticated' : '')); + parent.wsrelays[obj.id] = { peer1: obj, state: 1, timeout: setTimeout(closeBothSides, 60000) }; } - parent.wsrelays[obj.id] = { peer1: obj, state: 1, timeout: setTimeout(closeBothSides, 30000) }; // Check if a peer server has this connection if (parent.parent.multiServer != null) { @@ -485,15 +486,15 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) { command.title = (domain.title ? domain.title : 'MeshCentral'); var payload = { notification: { title: command.title, body: command.msg }, data: { url: obj.msgurl } }; var options = { priority: 'High', timeToLive: 5 * 60 }; // TTL: 5 minutes, priority 'Normal' or 'High' - parent.parent.firebase.messaging().sendToDevice(obj.pmt, payload, options) - .then(function (response) { + parent.parent.firebase.sendToDevice(obj.pmt, payload, options, function (id, err, errdesc) { + if (err == null) { parent.parent.debug('email', 'Successfully send push message to device ' + obj.nodename + ', title: ' + command.title + ', msg: ' + command.msg); try { ws.send(JSON.stringify({ action: 'ctrl', value: 1 })); } catch (ex) { } // Push notification success - }) - .catch(function (error) { - parent.parent.debug('email', 'Failed to send push message to device ' + obj.nodename + ', title: ' + command.title + ', msg: ' + command.msg + ', error: ' + error); + } else { + parent.parent.debug('email', 'Failed to send push message to device ' + obj.nodename + ', title: ' + command.title + ', msg: ' + command.msg + ', error: ' + errdesc); try { ws.send(JSON.stringify({ action: 'ctrl', value: 2 })); } catch (ex) { } // Push notification failed - }); + } + }); } } }); diff --git a/meshuser.js b/meshuser.js index 260bfbc2..52fdb590 100644 --- a/meshuser.js +++ b/meshuser.js @@ -5207,13 +5207,13 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use // Send out a push message to the device var payload = { notification: { title: command.title, body: command.msg } }; var options = { priority: "Normal", timeToLive: 5 * 60 }; // TTL: 5 minutes - parent.parent.firebase.messaging().sendToDevice(node.pmt, payload, options) - .then(function (response) { + parent.parent.firebase.sendToDevice(node.pmt, payload, options, function (id, err, errdesc) { + if (err == null) { parent.parent.debug('email', 'Successfully send push message to device ' + node.name + ', title: ' + command.title + ', msg: ' + command.msg); - }) - .catch(function (error) { - parent.parent.debug('email', 'Failed to send push message to device ' + node.name + ', title: ' + command.title + ', msg: ' + command.msg + ', error: ' + error); - }); + } else { + parent.parent.debug('email', 'Failed to send push message to device ' + node.name + ', title: ' + command.title + ', msg: ' + command.msg + ', error: ' + errdesc); + } + }); } } }); @@ -5231,14 +5231,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use // Send out a push message to the device var payload = { data: { console: command.console, session: ws.sessionId } }; var options = { priority: "Normal", timeToLive: 60 }; // TTL: 1 minutes, priority 'Normal' or 'High' - parent.parent.firebase.messaging().sendToDevice(node.pmt, payload, options) - .then(function (response) { + parent.parent.firebase.sendToDevice(node.pmt, payload, options, function (id, err, errdesc) { + if (err == null) { try { ws.send(JSON.stringify({ action: 'msg', type: 'console', nodeid: node._id, value: 'OK' })); } catch (ex) { } - }) - .catch(function (error) { - try { ws.send(JSON.stringify({ action: 'msg', type: 'console', nodeid: node._id, value: 'Failed: ' + error })); } catch (ex) { } - parent.parent.debug('email', 'Failed to send push console message to device ' + node.name + ', command: ' + command.console + ', error: ' + error); - }); + } else { + try { ws.send(JSON.stringify({ action: 'msg', type: 'console', nodeid: node._id, value: 'Failed: ' + errdesc })); } catch (ex) { } + parent.parent.debug('email', 'Failed to send push console message to device ' + node.name + ', command: ' + command.console + ', error: ' + errdesc); + } + }); } } }); diff --git a/package.json b/package.json index 987d0f3d..3510ece1 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "author": "Ylian Saint-Hilaire ", "main": "meshcentral.js", "bin": { - "meshcentral": "./bin/meshcentral" + "meshcentral": "bin/meshcentral" }, "license": "Apache-2.0", "files": [ @@ -53,7 +53,6 @@ "xmldom": "^0.1.27", "yauzl": "^2.10.0" }, - "devDependencies": {}, "repository": { "type": "git", "url": "https://github.com/Ylianst/MeshCentral.git"