/ lib / core / ipc.js
ipc.js
  1  const fs = require('./fs.js');
  2  const ipc = require('node-ipc');
  3  const {parse, stringify} = require('flatted/cjs');
  4  
  5  class IPC {
  6  
  7    constructor(options) {
  8      this.logger = options.logger;
  9      this.socketPath = options.socketPath || fs.dappPath(".embark/embark.ipc");
 10      this.ipcRole = options.ipcRole;
 11      ipc.config.silent = true;
 12      this.connected = false;
 13    }
 14  
 15    connect(done) {
 16      const self = this;
 17      function connecting(_socket) {
 18        let connectedBefore = false, alreadyDisconnected = false;
 19        ipc.of['embark'].on('connect',function() {
 20          connectedBefore = true;
 21          if (!alreadyDisconnected) {
 22            self.connected = true;
 23            done();
 24          }
 25        });
 26        ipc.of['embark'].on('disconnect',function() {
 27          self.connected = false;
 28          ipc.disconnect('embark');
 29  
 30          // we only want to trigger the error callback the first time
 31          if (!connectedBefore && !alreadyDisconnected) {
 32            alreadyDisconnected = true;
 33            done(new Error("no connection found"));
 34          }
 35        });
 36      }
 37  
 38      ipc.connectTo('embark', this.socketPath, connecting);
 39    }
 40  
 41    serve() {
 42      fs.mkdirpSync(fs.dappPath(".embark"));
 43      ipc.serve(this.socketPath, () => {});
 44      ipc.server.start();
 45  
 46      this.logger.info(`pid ${process.pid} listening on ${this.socketPath}`);
 47    }
 48  
 49    on(action, done) {
 50      const self = this;
 51      ipc.server.on('message', function(messageString, socket) {
 52        const message = parse(messageString);
 53        if (message.action !== action) {
 54          return;
 55        }
 56        let reply = function(error, replyData) {
 57          self.reply(socket, action, error, replyData);
 58        };
 59        done(message.data, reply, socket);
 60      });
 61    }
 62  
 63    reply(client, action, error, data) {
 64      const message = stringify({action, data, error: (error && error.stack)});
 65      ipc.server.emit(client, 'message', message);
 66    }
 67  
 68    listenTo(action, callback) {
 69      ipc.of['embark'].on(action, (messageString) => {
 70        callback(parse(messageString));
 71      });
 72    }
 73  
 74    broadcast(action, data) {
 75      ipc.server.broadcast(action, stringify(data));
 76    }
 77  
 78    once(action, cb) {
 79      ipc.of['embark'].once('message', function(messageString) {
 80        const message = parse(messageString);
 81        if (message.action !== action) {
 82          return;
 83        }
 84        cb(message.error, message.data);
 85      });
 86    }
 87  
 88    request(action, data, cb) {
 89      if (cb) {
 90        this.once(action, cb);
 91      }
 92      ipc.of['embark'].emit('message', stringify({action: action, data: data}));
 93    }
 94  
 95    isClient() {
 96      return this.ipcRole === 'client';
 97    }
 98  
 99    isServer() {
100      return this.ipcRole === 'server';
101    }
102  
103  }
104  
105  module.exports = IPC;