process.js
1 const child_process = require('child_process'); 2 const ProcessWrapper = require('../../core/processes/processWrapper'); 3 const constants = require('../../constants'); 4 5 let ipfsProcess; // eslint-disable-line no-unused-vars 6 7 class IPFSProcess extends ProcessWrapper { 8 constructor(options) { 9 super(); 10 11 this.cors = options.cors; 12 this.command = 'ipfs'; 13 14 this.checkIPFSVersion(); 15 this.startIPFSDaemon(); 16 } 17 18 checkIPFSVersion() { 19 child_process.exec(this.command + ' --version', {silent: true}, (err, stdout, _stderr) => { 20 if (err) { 21 console.error(err); 22 return; 23 } 24 const match = stdout.match(/[0-9]+\.[0-9]+\.[0-9]+/); 25 if (match[0]) { 26 const versions = match[0].split('.'); 27 if (versions[0] <= 0 && versions[1] <= 4 && versions[2] <= 14) { 28 console.error(`You are using IPFS version ${match[0]} which has an issue with processes.`); 29 console.error(`Please update to IPFS version 0.4.15 or more recent: https://github.com/ipfs/ipfs-update`); 30 } 31 } 32 }); 33 } 34 35 _bindChildEvents(childProcess){ 36 const self = this; 37 38 childProcess.on('error', (err) => { 39 err = err.toString(); 40 console.error('IPFS error: ', err); 41 }); 42 43 childProcess.stderr.on('data', (data) => { 44 data = data.toString(); 45 console.log(`IPFS error: ${data}`); 46 // `ipfs daemon called`, but `ipfs init` had not been run yet 47 if(!self.initCalled && data.indexOf('no IPFS repo found') > -1) { 48 self.initCalled = true; 49 let ipfsInitChild = child_process.spawn(this.command, ['init']); 50 self._bindChildEvents(ipfsInitChild); 51 } 52 }); 53 54 childProcess.stdout.on('data', (data) => { 55 data = data.toString(); 56 57 // ipfs init just run, and we have a successful result 58 // re-run `ipfs daemon` 59 if(self.initCalled && !self.readyCalled && data.indexOf('peer identity:') > -1) { 60 self.startIPFSDaemon(); 61 } 62 else if (!self.readyCalled && data.indexOf('Daemon is ready') > -1) { 63 self.readyCalled = true; 64 65 // update IPFS cors before spawning a daemon (muhaha) 66 let ipfsCorsCmd = `${self.command} config --json API.HTTPHeaders.Access-Control-Allow-Origin "[\\"${self.cors.join('\\", \\"')}\\"]"`; 67 console.trace(`Updating IPFS CORS using command: ${ipfsCorsCmd}`); 68 child_process.exec(ipfsCorsCmd, {silent: true}, (err, stdout, _stderr) => { 69 if(err){ 70 err = err.toString(); 71 console.error('IPFS CORS update error: ', err); 72 } 73 if(_stderr){ 74 _stderr = _stderr.toString(); 75 console.error(`IPFS CORS update error: ${_stderr}`); 76 } 77 child_process.exec(self.command + ' config --json API.HTTPHeaders.Access-Control-Allow-Credentials "[\\"true\\"]"', {silent: true}, (err, stdout, _stderr) => { 78 if(err){ 79 err = err.toString(); 80 console.error('IPFS CORS update error: ', err); 81 } 82 if(_stderr){ 83 _stderr = _stderr.toString(); 84 console.error(`IPFS CORS update error: ${_stderr}`); 85 } 86 child_process.exec(self.command + ' config --json API.HTTPHeaders.Access-Control-Allow-Methods "[\\"PUT\\", \\"POST\\", \\"GET\\"]"', {silent: true}, (err, stdout, _stderr) => { 87 if(err){ 88 err = err.toString(); 89 console.error('IPFS CORS update error: ', err); 90 } 91 if(_stderr){ 92 _stderr = _stderr.toString(); 93 console.error(`IPFS CORS update error: ${_stderr}`); 94 } 95 96 self.send({result: constants.storage.initiated}); 97 }); 98 }); 99 }); 100 } 101 console.log('IPFS: ' + data); 102 }); 103 childProcess.on('exit', (code) => { 104 if (code) { 105 console.error('IPFS exited with error code ' + code); 106 } 107 }); 108 } 109 110 startIPFSDaemon() { 111 const self = this; 112 113 // spawn the daemon (muhaha) 114 this.child = child_process.spawn(this.command, ['daemon']); 115 116 self._bindChildEvents(this.child); 117 } 118 119 kill() { 120 if (this.child) { 121 this.child.kill(); 122 } 123 } 124 } 125 126 process.on('message', (msg) => { 127 if (msg === 'exit') { 128 return ipfsProcess.kill(); 129 } 130 if (msg.action === constants.storage.init) { 131 ipfsProcess = new IPFSProcess(msg.options); 132 } 133 });