mirror of
				https://git.coolaj86.com/coolaj86/telebit.js.git
				synced 2025-11-04 02:32:47 +00:00 
			
		
		
		
	WIP keep parsing and console output in remote, move other stuff out
This commit is contained in:
		
							parent
							
								
									f3e5945afc
								
							
						
					
					
						commit
						c3e9bbaa5a
					
				@ -8,11 +8,11 @@ var os = require('os');
 | 
				
			|||||||
//var url = require('url');
 | 
					//var url = require('url');
 | 
				
			||||||
var fs = require('fs');
 | 
					var fs = require('fs');
 | 
				
			||||||
var path = require('path');
 | 
					var path = require('path');
 | 
				
			||||||
var http = require('http');
 | 
					 | 
				
			||||||
//var https = require('https');
 | 
					//var https = require('https');
 | 
				
			||||||
var YAML = require('js-yaml');
 | 
					var YAML = require('js-yaml');
 | 
				
			||||||
var TOML = require('toml');
 | 
					var TOML = require('toml');
 | 
				
			||||||
var TPLS = TOML.parse(fs.readFileSync(path.join(__dirname, "../lib/en-us.toml"), 'utf8'));
 | 
					var TPLS = TOML.parse(fs.readFileSync(path.join(__dirname, "../lib/en-us.toml"), 'utf8'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
if ('function' !== typeof TOML.stringify) {
 | 
					if ('function' !== typeof TOML.stringify) {
 | 
				
			||||||
  TOML.stringify = require('json2toml');
 | 
					  TOML.stringify = require('json2toml');
 | 
				
			||||||
@ -314,92 +314,186 @@ function askForConfig(state, mainCb) {
 | 
				
			|||||||
  next();
 | 
					  next();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var utils = {
 | 
					var RC;
 | 
				
			||||||
  request: function request(opts, fn) {
 | 
					 | 
				
			||||||
    if (!opts) { opts = {}; }
 | 
					 | 
				
			||||||
    var service = opts.service || 'config';
 | 
					 | 
				
			||||||
    var req = http.request({
 | 
					 | 
				
			||||||
      socketPath: state._ipc.path
 | 
					 | 
				
			||||||
    , method: opts.method || 'GET'
 | 
					 | 
				
			||||||
    , path: '/rpc/' + service
 | 
					 | 
				
			||||||
    }, function (resp) {
 | 
					 | 
				
			||||||
      var body = '';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      function finish() {
 | 
					function parseConfig(err, text) {
 | 
				
			||||||
        if (200 !== resp.statusCode) {
 | 
					  function handleConfig(err, config) {
 | 
				
			||||||
          console.warn(resp.statusCode);
 | 
					    //console.log('CONFIG');
 | 
				
			||||||
          console.warn(body || ('get' + service + ' failed'));
 | 
					    //console.log(config);
 | 
				
			||||||
          //cb(new Error("not okay"), body);
 | 
					    state.config = config;
 | 
				
			||||||
          return;
 | 
					    var verstrd = [ pkg.name + ' daemon v' + state.config.version ];
 | 
				
			||||||
        }
 | 
					    if (state.config.version && state.config.version !== pkg.version) {
 | 
				
			||||||
 | 
					      console.info(verstr.join(' '), verstrd.join(' '));
 | 
				
			||||||
        if (!body) { fn(null, null); return; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
          body = JSON.parse(body);
 | 
					 | 
				
			||||||
        } catch(e) {
 | 
					 | 
				
			||||||
          // ignore
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        fn(null, body);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (resp.headers['content-length']) {
 | 
					 | 
				
			||||||
        resp.on('data', function (chunk) {
 | 
					 | 
				
			||||||
          body += chunk.toString();
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        resp.on('end', function () {
 | 
					 | 
				
			||||||
          finish();
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        finish();
 | 
					      console.info(verstr.join(' '));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    });
 | 
					
 | 
				
			||||||
    req.on('error', function (err) {
 | 
					 | 
				
			||||||
      // ENOENT - never started, cleanly exited last start, or creating socket at a different path
 | 
					 | 
				
			||||||
      // ECONNREFUSED - leftover socket just needs to be restarted
 | 
					 | 
				
			||||||
    if ('ENOENT' === err.code || 'ECONNREFUSED' === err.code) {
 | 
					    if ('ENOENT' === err.code || 'ECONNREFUSED' === err.code) {
 | 
				
			||||||
        if (opts._taketwo) {
 | 
					 | 
				
			||||||
      console.error("Either the telebit service was not already (and could not be started) or its socket could not be written to.");
 | 
					      console.error("Either the telebit service was not already (and could not be started) or its socket could not be written to.");
 | 
				
			||||||
      console.error(err);
 | 
					      console.error(err);
 | 
				
			||||||
 | 
					    } else if ('ENOTSOCK' === err.code) {
 | 
				
			||||||
 | 
					      console.error(err);
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      console.error(err);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
        require('../usr/share/install-launcher.js').install({ env: process.env }, function (err) {
 | 
					    if (err) { process.exit(101); return; }
 | 
				
			||||||
          if (err) { fn(err); return; }
 | 
					
 | 
				
			||||||
          opts._taketwo = true;
 | 
					    //
 | 
				
			||||||
          setTimeout(function () {
 | 
					    // check for init first, before anything else
 | 
				
			||||||
            utils.request(opts, fn);
 | 
					    // because it has arguments that may help in
 | 
				
			||||||
          }, 2500);
 | 
					    // the next steps
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    if (-1 !== argv.indexOf('init')) {
 | 
				
			||||||
 | 
					      parsers.init(argv, function (err) {
 | 
				
			||||||
 | 
					        if (err) {
 | 
				
			||||||
 | 
					          console.error("Error while initializing config [init]:");
 | 
				
			||||||
 | 
					          throw err;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        getToken(function (err) {
 | 
				
			||||||
 | 
					          if (err) {
 | 
				
			||||||
 | 
					            console.error("Error while getting token [init]:");
 | 
				
			||||||
 | 
					            throw err;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          parseCli(state);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
      if ('ENOTSOCK' === err.code) {
 | 
					
 | 
				
			||||||
        console.error(err);
 | 
					    if (!state.config.relay || !state.config.token) {
 | 
				
			||||||
        return;
 | 
					      if (!state.config.relay) {
 | 
				
			||||||
 | 
					        state.config.relay = 'telebit.cloud';
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      console.error(err);
 | 
					
 | 
				
			||||||
      return;
 | 
					      //console.log("question the user?", Date.now());
 | 
				
			||||||
 | 
					      askForConfig(state, function (err, state) {
 | 
				
			||||||
 | 
					        // no errors actually get passed, so this is just future-proofing
 | 
				
			||||||
 | 
					        if (err) { throw err; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!state.config.token && state._can_pair) {
 | 
				
			||||||
 | 
					          state.config._otp = common.otp();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //console.log("done questioning:", Date.now());
 | 
				
			||||||
 | 
					        if (!state.token && !state.config.token) {
 | 
				
			||||||
 | 
					          if (err) {
 | 
				
			||||||
 | 
					            console.error("Error while initializing config [init]:");
 | 
				
			||||||
 | 
					            throw err;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          getToken(function (err) {
 | 
				
			||||||
 | 
					            if (err) {
 | 
				
			||||||
 | 
					              console.error("Error while getting token [init]:");
 | 
				
			||||||
 | 
					              throw err;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            parseCli(state);
 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
    req.end();
 | 
					        } else {
 | 
				
			||||||
 | 
					          parseCli(state);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
, putConfig: function putConfig(service, args, fn) {
 | 
					      });
 | 
				
			||||||
    var req = http.request({
 | 
					 | 
				
			||||||
      socketPath: state._ipc.path
 | 
					 | 
				
			||||||
    , method: 'POST'
 | 
					 | 
				
			||||||
    , path: '/rpc/' + service + '?_body=' + encodeURIComponent(JSON.stringify(args))
 | 
					 | 
				
			||||||
    }, function (resp) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      function finish() {
 | 
					 | 
				
			||||||
        if ('function' === typeof fn) {
 | 
					 | 
				
			||||||
          fn(null, resp);
 | 
					 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //console.log("no questioning:");
 | 
				
			||||||
 | 
					    parseCli(state);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  function parseCli(/*state*/) {
 | 
				
			||||||
 | 
					    var special = [
 | 
				
			||||||
 | 
					      'false', 'none', 'off', 'disable'
 | 
				
			||||||
 | 
					    , 'true', 'auto', 'on', 'enable'
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					    if (-1 !== argv.indexOf('init')) {
 | 
				
			||||||
 | 
					      RC.request({ service: 'list', method: 'POST', data: [] }, handleRemoteRequest('list'));
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ([ 'ssh', 'http', 'tcp' ].some(function (key) {
 | 
				
			||||||
 | 
					      if (key !== argv[0]) {
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (argv[1]) {
 | 
				
			||||||
 | 
					        if (String(argv[1]) === String(parseInt(argv[1], 10))) {
 | 
				
			||||||
 | 
					          // looks like a port
 | 
				
			||||||
 | 
					          argv[1] = parseInt(argv[1], 10);
 | 
				
			||||||
 | 
					        } else if (/\/|\\/.test(argv[1])) {
 | 
				
			||||||
 | 
					          // looks like a path
 | 
				
			||||||
 | 
					          argv[1] = path.resolve(argv[1]);
 | 
				
			||||||
 | 
					          // TODO make a default assignment here
 | 
				
			||||||
 | 
					        } else if (-1 === special.indexOf(argv[1])) {
 | 
				
			||||||
 | 
					          console.error("Not sure what you meant by '" + argv[1] + "'.");
 | 
				
			||||||
 | 
					          console.error("Remember: paths should begin with ." + path.sep + ", like '." + path.sep + argv[1] + "'");
 | 
				
			||||||
 | 
					          return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        RC.request({ service: argv[0], method: 'POST', data: argv.slice(1) }, handleRemoteRequest(argv[0]));
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
 | 
					    })) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Two styles:
 | 
				
			||||||
 | 
					    //     http 3000
 | 
				
			||||||
 | 
					    //     http modulename
 | 
				
			||||||
 | 
					    function makeRpc(key) {
 | 
				
			||||||
 | 
					      if (key !== argv[0]) {
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      RC.request({ service: argv[0], method: 'POST', data: argv.slice(1) }, handleRemoteRequest(argv[0]));
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if ([ 'status', 'enable', 'disable', 'restart', 'list', 'save' ].some(makeRpc)) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    help();
 | 
				
			||||||
 | 
					    process.exit(11);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    state._clientConfig = JSON.parse(text || '{}');
 | 
				
			||||||
 | 
					  } catch(e1) {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      state._clientConfig = YAML.safeLoad(text || '{}');
 | 
				
			||||||
 | 
					    } catch(e2) {
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        state._clientConfig = TOML.parse(text || '');
 | 
				
			||||||
 | 
					      } catch(e3) {
 | 
				
			||||||
 | 
					        console.error(e1.message);
 | 
				
			||||||
 | 
					        console.error(e2.message);
 | 
				
			||||||
 | 
					        process.exit(1);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  state._clientConfig = camelCopy(state._clientConfig || {}) || {};
 | 
				
			||||||
 | 
					  RC = require('../lib/remote-control-client.js').create(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!Object.keys(state._clientConfig).length) {
 | 
				
			||||||
 | 
					    console.info('(' + state._ipc.comment + ": " + state._ipc.path + ')');
 | 
				
			||||||
    console.info("");
 | 
					    console.info("");
 | 
				
			||||||
        if (200 !== resp.statusCode) {
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ((err && 'ENOENT' === err.code) || !Object.keys(state._clientConfig).length) {
 | 
				
			||||||
 | 
					    if (!err || 'ENOENT' === err.code) {
 | 
				
			||||||
 | 
					      //console.warn("Empty config file. Run 'telebit init' to configure.\n");
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      console.warn("Couldn't load config:\n\n\t" + err.message + "\n");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function handleRemoteRequest(service, fn) {
 | 
				
			||||||
 | 
					    return function (err, body) {
 | 
				
			||||||
 | 
					      if ('function' === typeof fn) {
 | 
				
			||||||
 | 
					        fn(err, body); // XXX was resp
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      console.info("");
 | 
				
			||||||
 | 
					      if (err) {
 | 
				
			||||||
        console.warn("'" + service + "' may have failed."
 | 
					        console.warn("'" + service + "' may have failed."
 | 
				
			||||||
         + " Consider peaking at the logs either with 'journalctl -xeu telebit' or /opt/telebit/var/log/error.log");
 | 
					         + " Consider peaking at the logs either with 'journalctl -xeu telebit' or /opt/telebit/var/log/error.log");
 | 
				
			||||||
          console.warn(resp.statusCode, body);
 | 
					        console.warn(err.statusCode, err.message);
 | 
				
			||||||
        //cb(new Error("not okay"), body);
 | 
					        //cb(new Error("not okay"), body);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -413,6 +507,7 @@ var utils = {
 | 
				
			|||||||
        body = JSON.parse(body);
 | 
					        body = JSON.parse(body);
 | 
				
			||||||
      } catch(e) {
 | 
					      } catch(e) {
 | 
				
			||||||
        // ignore
 | 
					        // ignore
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if ("AWAIT_AUTH" === body.code) {
 | 
					      if ("AWAIT_AUTH" === body.code) {
 | 
				
			||||||
@ -439,62 +534,10 @@ var utils = {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        console.info();
 | 
					        console.info();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      var body = '';
 | 
					  function getToken(fn) {
 | 
				
			||||||
      if (resp.headers['content-length']) {
 | 
					 | 
				
			||||||
        resp.on('data', function (chunk) {
 | 
					 | 
				
			||||||
          body += chunk.toString();
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        resp.on('end', function () {
 | 
					 | 
				
			||||||
          finish();
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        finish();
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    req.on('error', function (err) {
 | 
					 | 
				
			||||||
      console.error('Put Config Error:');
 | 
					 | 
				
			||||||
      console.error(err);
 | 
					 | 
				
			||||||
      return;
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    req.end();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Two styles:
 | 
					 | 
				
			||||||
//     http 3000
 | 
					 | 
				
			||||||
//     http modulename
 | 
					 | 
				
			||||||
function makeRpc(key) {
 | 
					 | 
				
			||||||
  if (key !== argv[0]) {
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  utils.putConfig(argv[0], argv.slice(1));
 | 
					 | 
				
			||||||
  return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function packConfig(config) {
 | 
					 | 
				
			||||||
  return Object.keys(config).map(function (key) {
 | 
					 | 
				
			||||||
    var val = config[key];
 | 
					 | 
				
			||||||
    if ('undefined' === val) {
 | 
					 | 
				
			||||||
      throw new Error("'undefined' used as a string value");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if ('undefined' === typeof val) {
 | 
					 | 
				
			||||||
      //console.warn('[DEBUG]', key, 'is present but undefined');
 | 
					 | 
				
			||||||
      return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (val && 'object' === typeof val && !Array.isArray(val)) {
 | 
					 | 
				
			||||||
      val = JSON.stringify(val);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return key + ':' + val; // converts arrays to strings with ,
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function getToken(err, state) {
 | 
					 | 
				
			||||||
  if (err) {
 | 
					 | 
				
			||||||
    console.error("Error while initializing config [init]:");
 | 
					 | 
				
			||||||
    throw err;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
    state.relay = state.config.relay;
 | 
					    state.relay = state.config.relay;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // { _otp, config: {} }
 | 
					    // { _otp, config: {} }
 | 
				
			||||||
@ -520,17 +563,7 @@ function getToken(err, state) {
 | 
				
			|||||||
        state.config._otp = state.config._otp = authReq.otp;
 | 
					        state.config._otp = state.config._otp = authReq.otp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!state.config.token && state._can_pair) {
 | 
					        if (!state.config.token && state._can_pair) {
 | 
				
			||||||
        console.info("");
 | 
					          console.info(TPLS.remote.code.replace(/0000/g, state.config._otp));
 | 
				
			||||||
        console.info("==============================================");
 | 
					 | 
				
			||||||
        console.info("                 Hey, Listen!                 ");
 | 
					 | 
				
			||||||
        console.info("==============================================");
 | 
					 | 
				
			||||||
        console.info("                                              ");
 | 
					 | 
				
			||||||
        console.info("  GO CHECK YOUR EMAIL!                        ");
 | 
					 | 
				
			||||||
        console.info("                                              ");
 | 
					 | 
				
			||||||
        console.info("  DEVICE PAIR CODE:     0000                  ".replace(/0000/g, state.config._otp));
 | 
					 | 
				
			||||||
        console.info("                                              ");
 | 
					 | 
				
			||||||
        console.info("==============================================");
 | 
					 | 
				
			||||||
        console.info("");
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        next();
 | 
					        next();
 | 
				
			||||||
@ -541,7 +574,7 @@ function getToken(err, state) {
 | 
				
			|||||||
        state._connecting = true;
 | 
					        state._connecting = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // TODO use php-style object querification
 | 
					        // TODO use php-style object querification
 | 
				
			||||||
      utils.putConfig('config', packConfig(state.config), function (err/*, body*/) {
 | 
					        RC.request({ service: 'config', method: 'POST', data: state.config }, handleRemoteRequest('config', function (err/*, body*/) {
 | 
				
			||||||
          if (err) {
 | 
					          if (err) {
 | 
				
			||||||
            state._error = err;
 | 
					            state._error = err;
 | 
				
			||||||
            console.error("Error while initializing config [connect]:");
 | 
					            console.error("Error while initializing config [connect]:");
 | 
				
			||||||
@ -550,7 +583,7 @@ function getToken(err, state) {
 | 
				
			|||||||
          }
 | 
					          }
 | 
				
			||||||
          console.info("waiting...");
 | 
					          console.info("waiting...");
 | 
				
			||||||
          next();
 | 
					          next();
 | 
				
			||||||
      });
 | 
					        }));
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    , offer: function (token, next) {
 | 
					    , offer: function (token, next) {
 | 
				
			||||||
        //console.log("[offer] Pairing Enabled by Relay");
 | 
					        //console.log("[offer] Pairing Enabled by Relay");
 | 
				
			||||||
@ -565,7 +598,7 @@ function getToken(err, state) {
 | 
				
			|||||||
        } catch(e) {
 | 
					        } catch(e) {
 | 
				
			||||||
          console.warn("[warning] could not decode token");
 | 
					          console.warn("[warning] could not decode token");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      utils.putConfig('config', packConfig(state.config), function (err/*, body*/) {
 | 
					        RC.request({ service: 'config', method: 'POST', data: state.config }, handleRemoteRequest('config', function (err/*, body*/) {
 | 
				
			||||||
          if (err) {
 | 
					          if (err) {
 | 
				
			||||||
            state._error = err;
 | 
					            state._error = err;
 | 
				
			||||||
            console.error("Error while initializing config [offer]:");
 | 
					            console.error("Error while initializing config [offer]:");
 | 
				
			||||||
@ -574,14 +607,14 @@ function getToken(err, state) {
 | 
				
			|||||||
          }
 | 
					          }
 | 
				
			||||||
          //console.log("Pairing Enabled Locally");
 | 
					          //console.log("Pairing Enabled Locally");
 | 
				
			||||||
          next();
 | 
					          next();
 | 
				
			||||||
      });
 | 
					        }));
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    , granted: function (_, next) {
 | 
					    , granted: function (_, next) {
 | 
				
			||||||
        //console.log("[grant] Pairing complete!");
 | 
					        //console.log("[grant] Pairing complete!");
 | 
				
			||||||
        next();
 | 
					        next();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    , end: function () {
 | 
					    , end: function () {
 | 
				
			||||||
      utils.putConfig('enable', [], function (err) {
 | 
					        RC.request({ service: 'enable', method: 'POST', data: [] }, handleRemoteRequest('enable', function (err) {
 | 
				
			||||||
          if (err) { console.error(err); return; }
 | 
					          if (err) { console.error(err); return; }
 | 
				
			||||||
          console.info("Success");
 | 
					          console.info("Success");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -601,148 +634,14 @@ function getToken(err, state) {
 | 
				
			|||||||
          }
 | 
					          }
 | 
				
			||||||
          // end workaround
 | 
					          // end workaround
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        parseCli(state);
 | 
					          //parseCli(state);
 | 
				
			||||||
      });
 | 
					          fn();
 | 
				
			||||||
 | 
					        }));
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function parseCli(/*state*/) {
 | 
					 | 
				
			||||||
  var special = [
 | 
					 | 
				
			||||||
    'false', 'none', 'off', 'disable'
 | 
					 | 
				
			||||||
  , 'true', 'auto', 'on', 'enable'
 | 
					 | 
				
			||||||
  ];
 | 
					 | 
				
			||||||
  if (-1 !== argv.indexOf('init')) {
 | 
					 | 
				
			||||||
    utils.putConfig('list', []/*, function (err) {
 | 
					 | 
				
			||||||
    }*/);
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if ([ 'ssh', 'http', 'tcp' ].some(function (key) {
 | 
					  RC.request({ service: 'config', method: 'GET' }, handleRemoteRequest('config', handleConfig));
 | 
				
			||||||
    if (key !== argv[0]) {
 | 
					 | 
				
			||||||
      return false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (argv[1]) {
 | 
					 | 
				
			||||||
      if (String(argv[1]) === String(parseInt(argv[1], 10))) {
 | 
					 | 
				
			||||||
        // looks like a port
 | 
					 | 
				
			||||||
        argv[1] = parseInt(argv[1], 10);
 | 
					 | 
				
			||||||
      } else if (/\/|\\/.test(argv[1])) {
 | 
					 | 
				
			||||||
        // looks like a path
 | 
					 | 
				
			||||||
        argv[1] = path.resolve(argv[1]);
 | 
					 | 
				
			||||||
        // TODO make a default assignment here
 | 
					 | 
				
			||||||
      } else if (-1 === special.indexOf(argv[1])) {
 | 
					 | 
				
			||||||
        console.error("Not sure what you meant by '" + argv[1] + "'.");
 | 
					 | 
				
			||||||
        console.error("Remember: paths should begin with ." + path.sep + ", like '." + path.sep + argv[1] + "'");
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      utils.putConfig(argv[0], argv.slice(1));
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return true;
 | 
					 | 
				
			||||||
  })) {
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if ([ 'status', 'enable', 'disable', 'restart', 'list', 'save' ].some(makeRpc)) {
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  help();
 | 
					 | 
				
			||||||
  process.exit(11);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function handleConfig(err, config) {
 | 
					 | 
				
			||||||
  //console.log('CONFIG');
 | 
					 | 
				
			||||||
  //console.log(config);
 | 
					 | 
				
			||||||
  state.config = config;
 | 
					 | 
				
			||||||
  var verstrd = [ pkg.name + ' daemon v' + state.config.version ];
 | 
					 | 
				
			||||||
  if (state.config.version && state.config.version !== pkg.version) {
 | 
					 | 
				
			||||||
    console.info(verstr.join(' '), verstrd.join(' '));
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    console.info(verstr.join(' '));
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (err) { console.error(err); process.exit(101); return; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  //
 | 
					 | 
				
			||||||
  // check for init first, before anything else
 | 
					 | 
				
			||||||
  // because it has arguments that may help in
 | 
					 | 
				
			||||||
  // the next steps
 | 
					 | 
				
			||||||
  //
 | 
					 | 
				
			||||||
  if (-1 !== argv.indexOf('init')) {
 | 
					 | 
				
			||||||
    parsers.init(argv, getToken);
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (!state.config.relay || !state.config.token) {
 | 
					 | 
				
			||||||
    if (!state.config.relay) {
 | 
					 | 
				
			||||||
      state.config.relay = 'telebit.cloud';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //console.log("question the user?", Date.now());
 | 
					 | 
				
			||||||
    askForConfig(state, function (err, state) {
 | 
					 | 
				
			||||||
      // no errors actually get passed, so this is just future-proofing
 | 
					 | 
				
			||||||
      if (err) { throw err; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (!state.config.token && state._can_pair) {
 | 
					 | 
				
			||||||
        state.config._otp = common.otp();
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      //console.log("done questioning:", Date.now());
 | 
					 | 
				
			||||||
      if (!state.token && !state.config.token) {
 | 
					 | 
				
			||||||
        getToken(err, state);
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        parseCli(state);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  //console.log("no questioning:");
 | 
					 | 
				
			||||||
  parseCli(state);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function parseConfig(err, text) {
 | 
					 | 
				
			||||||
  try {
 | 
					 | 
				
			||||||
    state._clientConfig = JSON.parse(text || '{}');
 | 
					 | 
				
			||||||
  } catch(e1) {
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
      state._clientConfig = YAML.safeLoad(text || '{}');
 | 
					 | 
				
			||||||
    } catch(e2) {
 | 
					 | 
				
			||||||
      try {
 | 
					 | 
				
			||||||
        state._clientConfig = TOML.parse(text || '');
 | 
					 | 
				
			||||||
      } catch(e3) {
 | 
					 | 
				
			||||||
        console.error(e1.message);
 | 
					 | 
				
			||||||
        console.error(e2.message);
 | 
					 | 
				
			||||||
        process.exit(1);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  state._clientConfig = camelCopy(state._clientConfig || {}) || {};
 | 
					 | 
				
			||||||
  common._init(
 | 
					 | 
				
			||||||
    // make a default working dir and log dir
 | 
					 | 
				
			||||||
    state._clientConfig.root || path.join(os.homedir(), '.local/share/telebit')
 | 
					 | 
				
			||||||
  , (state._clientConfig.root && path.join(state._clientConfig.root, 'etc'))
 | 
					 | 
				
			||||||
      || path.resolve(common.DEFAULT_CONFIG_PATH, '..')
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
  state._ipc = common.pipename(state._clientConfig, true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (!Object.keys(state._clientConfig).length) {
 | 
					 | 
				
			||||||
    console.info('(' + state._ipc.comment + ": " + state._ipc.path + ')');
 | 
					 | 
				
			||||||
    console.info("");
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if ((err && 'ENOENT' === err.code) || !Object.keys(state._clientConfig).length) {
 | 
					 | 
				
			||||||
    if (!err || 'ENOENT' === err.code) {
 | 
					 | 
				
			||||||
      //console.warn("Empty config file. Run 'telebit init' to configure.\n");
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      console.warn("Couldn't load config:\n\n\t" + err.message + "\n");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  utils.request({ service: 'config' }, handleConfig);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var parsers = {
 | 
					var parsers = {
 | 
				
			||||||
 | 
				
			|||||||
@ -452,5 +452,17 @@ The secret flags are:
 | 
				
			|||||||
[remote]
 | 
					[remote]
 | 
				
			||||||
version = "telebit remote v{version}"
 | 
					version = "telebit remote v{version}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					code = "
 | 
				
			||||||
 | 
					==============================================
 | 
				
			||||||
 | 
					                 Hey, Listen!
 | 
				
			||||||
 | 
					==============================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  GO CHECK YOUR EMAIL!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  DEVICE PAIR CODE:     0000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					==============================================
 | 
				
			||||||
 | 
					"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[daemon]
 | 
					[daemon]
 | 
				
			||||||
version = "telebit daemon v{version}"
 | 
					version = "telebit daemon v{version}"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										116
									
								
								lib/remote-control-client.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								lib/remote-control-client.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,116 @@
 | 
				
			|||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var os = require('os');
 | 
				
			||||||
 | 
					var path = require('path');
 | 
				
			||||||
 | 
					var http = require('http');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var common = require('./cli-common.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function packConfig(config) {
 | 
				
			||||||
 | 
					  return Object.keys(config).map(function (key) {
 | 
				
			||||||
 | 
					    var val = config[key];
 | 
				
			||||||
 | 
					    if ('undefined' === val) {
 | 
				
			||||||
 | 
					      throw new Error("'undefined' used as a string value");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if ('undefined' === typeof val) {
 | 
				
			||||||
 | 
					      //console.warn('[DEBUG]', key, 'is present but undefined');
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (val && 'object' === typeof val && !Array.isArray(val)) {
 | 
				
			||||||
 | 
					      val = JSON.stringify(val);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return key + ':' + val; // converts arrays to strings with ,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports.create = function (state) {
 | 
				
			||||||
 | 
					  common._init(
 | 
				
			||||||
 | 
					    // make a default working dir and log dir
 | 
				
			||||||
 | 
					    state._clientConfig.root || path.join(os.homedir(), '.local/share/telebit')
 | 
				
			||||||
 | 
					  , (state._clientConfig.root && path.join(state._clientConfig.root, 'etc'))
 | 
				
			||||||
 | 
					      || path.resolve(common.DEFAULT_CONFIG_PATH, '..')
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					  state._ipc = common.pipename(state._clientConfig, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function makeResponder(service, resp, fn) {
 | 
				
			||||||
 | 
					    var body = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function finish() {
 | 
				
			||||||
 | 
					      var err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (200 !== resp.statusCode) {
 | 
				
			||||||
 | 
					        err = new Error(body || ('get' + service + ' failed'));
 | 
				
			||||||
 | 
					        err.statusCode = resp.statusCode;
 | 
				
			||||||
 | 
					        err.code = "E_REQUEST";
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        body = JSON.parse(body);
 | 
				
			||||||
 | 
					      } catch(e) {
 | 
				
			||||||
 | 
					        // ignore
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      fn(err, body);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!resp.headers['content-length'] && !resp.headers['content-type']) {
 | 
				
			||||||
 | 
					      finish();
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // TODO use readable
 | 
				
			||||||
 | 
					    resp.on('data', function (chunk) {
 | 
				
			||||||
 | 
					      body += chunk.toString();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    resp.on('end', finish);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var RC = {};
 | 
				
			||||||
 | 
					  RC.request = function request(opts, fn) {
 | 
				
			||||||
 | 
					    if (!opts) { opts = {}; }
 | 
				
			||||||
 | 
					    var service = opts.service || 'config';
 | 
				
			||||||
 | 
					    var args = opts.data;
 | 
				
			||||||
 | 
					    if (args && 'control' === service) {
 | 
				
			||||||
 | 
					      args = packConfig(args);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    var json = JSON.stringify(args);
 | 
				
			||||||
 | 
					    var url = '/rpc/' + service;
 | 
				
			||||||
 | 
					    if (json) {
 | 
				
			||||||
 | 
					      url += ('?_body=' + encodeURIComponent(json));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    var method = opts.method || (args && 'POST') || 'GET';
 | 
				
			||||||
 | 
					    var req = http.request({
 | 
				
			||||||
 | 
					      socketPath: state._ipc.path
 | 
				
			||||||
 | 
					    , method: method
 | 
				
			||||||
 | 
					    , path: url
 | 
				
			||||||
 | 
					    }, function (resp) {
 | 
				
			||||||
 | 
					      makeResponder(service, resp, fn);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    req.on('error', function (err) {
 | 
				
			||||||
 | 
					      // ENOENT - never started, cleanly exited last start, or creating socket at a different path
 | 
				
			||||||
 | 
					      // ECONNREFUSED - leftover socket just needs to be restarted
 | 
				
			||||||
 | 
					      if ('ENOENT' === err.code || 'ECONNREFUSED' === err.code) {
 | 
				
			||||||
 | 
					        if (opts._taketwo) {
 | 
				
			||||||
 | 
					          fn(err);
 | 
				
			||||||
 | 
					          return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        require('../usr/share/install-launcher.js').install({ env: process.env }, function (err) {
 | 
				
			||||||
 | 
					          if (err) { fn(err); return; }
 | 
				
			||||||
 | 
					          opts._taketwo = true;
 | 
				
			||||||
 | 
					          setTimeout(function () {
 | 
				
			||||||
 | 
					            RC.request(opts, fn);
 | 
				
			||||||
 | 
					          }, 2500);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      fn(err);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    if ('POST' === method && opts.data) {
 | 
				
			||||||
 | 
					      req.write(json || opts.data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    req.end();
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  return RC;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user