lib/usb/usb-process.js
function USBProcess(id, daemon) {
  // The numerical identifer for this process
  this.id = id;

  /*
  active && !closed = Process is running as usual
  !active && !closed = Process has been sent a signal but not completely closed (resources freed)
  !active && closed = Process has stopped running and has already been destroyed
  */
  // Status of whether this process is running
  this.active = true;
  // Status of whether this process was cleaned up
  this.closed = false;
  // Boolean of whether this process has been forcibly killed
  this.forceKill = false;
  // Code to be set upon process death
  this.exitedWithError = false;
  // Some processes, like `sysupgrade` will not be close-able
  // because OpenWRT does not have the spidaemon active.
  // In these cases, just close without trying to send kill signal
  this.waitForClose = true;

  // 4 remote process streams
  this.control = new RemoteWritableStream(this, daemon, protocol.controlWrite, protocol.controlClose);
  this.stdin = new RemoteWritableStream(this, daemon, protocol.stdinWrite, protocol.stdinClose);
  this.stdout = new RemoteReadableStream(this, daemon, protocol.stdoutAck);
  this.stderr = new RemoteReadableStream(this, daemon, protocol.stderrAck);

  // Once the process is killed
  this.once('death', (data) => {
    // This process is no longer running
    this.active = false;
    // Close the input streams because the remote proc can't handle data
    this.control.end();
    this.stdin.end();

    // Close the process
    this.closeProcessIfReady();

    // Check for a non-zero exit code
    var exitCode = parseInt(data.arg);
    debug(`Death for "${this.commandString}" with exit code: ${exitCode}`);
    if (exitCode !== 0 && !this.forceKill) {
      this.exitedWithError = true;
    }
  });

  // Tell the USBDaemon to close the remote process
  this.close = () => {
    // Write the close command
    daemon.write(protocol.closeProcess(this.id));

    // Mark this process as closed
    this.closed = true;
  };

  // Send a signal to the remote process
  this.kill = (signal) => {
    // Mark our boolean
    this.forceKill = true;

    // If we should wait for close (most processes should)
    if (this.waitForClose) {
      // Write the signal command
      daemon.write(protocol.killProcess(this.id, signal));
    } else {
      // Mark the process as inactive and closed
      this.active = false;
      this.closed = true;
      // Emit the close event
      setImmediate(() => this.emit('close'));
    }
  };

  // Checks if this process is ready to be closed
  // and closes it if it can
  this.closeProcessIfReady = () => {
    // If this process hasn't been closed before
    // and all of the streams are closed
    if (!this.active && !this.closed && this.stdout.closed && this.stderr.closed) {
      // Close this process
      this.close();
    }
  };

  // When any of the streams complete, check if the process is ready to close
  this.stdout.once('end', () => this.closeProcessIfReady());
  this.stderr.once('end', () => this.closeProcessIfReady());

  // This function is primarily intended for compatibility with the ssh2 stream API
  this.stdout.signal = (signalToSend) => {
    switch (signalToSend) {
      case 'KILL':
        this.kill(9);
        break;
      case 'SIGINT':
        this.kill(2);
        break;
    }
  };

  // Tell the remote daemon that this process was created
  daemon.write(protocol.newProcess(this.id));
  // Tell the remote daemon that we can start receiving outbound data
  this.stdout.ack(MAX_BUFFER_SIZE);
  this.stderr.ack(MAX_BUFFER_SIZE);
}
function USBProcess(id, daemon) {
  // The numerical identifer for this process
  this.id = id;

  /*
  active && !closed = Process is running as usual
  !active && !closed = Process has been sent a signal but not completely closed (resources freed)
  !active && closed = Process has stopped running and has already been destroyed
  */
  // Status of whether this process is running
  this.active = true;
  // Status of whether this process was cleaned up
  this.closed = false;
  // Boolean of whether this process has been forcibly killed
  this.forceKill = false;
  // Code to be set upon process death
  this.exitedWithError = false;
  // Some processes, like `sysupgrade` will not be close-able
  // because OpenWRT does not have the spidaemon active.
  // In these cases, just close without trying to send kill signal
  this.waitForClose = true;

  // 4 remote process streams
  this.control = new RemoteWritableStream(this, daemon, protocol.controlWrite, protocol.controlClose);
  this.stdin = new RemoteWritableStream(this, daemon, protocol.stdinWrite, protocol.stdinClose);
  this.stdout = new RemoteReadableStream(this, daemon, protocol.stdoutAck);
  this.stderr = new RemoteReadableStream(this, daemon, protocol.stderrAck);

  // Once the process is killed
  this.once('death', (data) => {
    // This process is no longer running
    this.active = false;
    // Close the input streams because the remote proc can't handle data
    this.control.end();
    this.stdin.end();

    // Close the process
    this.closeProcessIfReady();

    // Check for a non-zero exit code
    var exitCode = parseInt(data.arg);
    debug(`Death for "${this.commandString}" with exit code: ${exitCode}`);
    if (exitCode !== 0 && !this.forceKill) {
      this.exitedWithError = true;
    }
  });

  // Tell the USBDaemon to close the remote process
  this.close = () => {
    // Write the close command
    daemon.write(protocol.closeProcess(this.id));

    // Mark this process as closed
    this.closed = true;
  };

  // Send a signal to the remote process
  this.kill = (signal) => {
    // Mark our boolean
    this.forceKill = true;

    // If we should wait for close (most processes should)
    if (this.waitForClose) {
      // Write the signal command
      daemon.write(protocol.killProcess(this.id, signal));
    } else {
      // Mark the process as inactive and closed
      this.active = false;
      this.closed = true;
      // Emit the close event
      setImmediate(() => this.emit('close'));
    }
  };

  // Checks if this process is ready to be closed
  // and closes it if it can
  this.closeProcessIfReady = () => {
    // If this process hasn't been closed before
    // and all of the streams are closed
    if (!this.active && !this.closed && this.stdout.closed && this.stderr.closed) {
      // Close this process
      this.close();
    }
  };

  // When any of the streams complete, check if the process is ready to close
  this.stdout.once('end', () => this.closeProcessIfReady());
  this.stderr.once('end', () => this.closeProcessIfReady());

  // This function is primarily intended for compatibility with the ssh2 stream API
  this.stdout.signal = (signalToSend) => {
    switch (signalToSend) {
      case 'KILL':
        this.kill(9);
        break;
      case 'SIGINT':
        this.kill(2);
        break;
    }
  };

  // Tell the remote daemon that this process was created
  daemon.write(protocol.newProcess(this.id));
  // Tell the remote daemon that we can start receiving outbound data
  this.stdout.ack(MAX_BUFFER_SIZE);
  this.stderr.ack(MAX_BUFFER_SIZE);
}
function USBProcess ( id , daemon ) { // The numerical identifer for this process this . id = id ; /*
  active && !closed = Process is running as usual
  !active && !closed = Process has been sent a signal but not completely closed (resources freed)
  !active && closed = Process has stopped running and has already been destroyed
  */ // Status of whether this process is running this . active = true ; // Status of whether this process was cleaned up this . closed = false ; // Boolean of whether this process has been forcibly killed this . forceKill = false ; // Code to be set upon process death this . exitedWithError = false ; // Some processes, like `sysupgrade` will not be close-able // because OpenWRT does not have the spidaemon active. // In these cases, just close without trying to send kill signal this . waitForClose = true ; // 4 remote process streams this . control = new RemoteWritableStream ( this , daemon , protocol . controlWrite , protocol . controlClose ) ; this . stdin = new RemoteWritableStream ( this , daemon , protocol . stdinWrite , protocol . stdinClose ) ; this . stdout = new RemoteReadableStream ( this , daemon , protocol . stdoutAck ) ; this . stderr = new RemoteReadableStream ( this , daemon , protocol . stderrAck ) ; // Once the process is killed this . once ( 'death' , ( data ) => { // This process is no longer running this . active = false ; // Close the input streams because the remote proc can't handle data this . control . end ( ) ; this . stdin . end ( ) ; // Close the process this . closeProcessIfReady ( ) ; // Check for a non-zero exit code var exitCode = parseInt ( data . arg ) ; debug ( ` ${ this . commandString } ${ exitCode } ` ) ; if ( exitCode !== 0 && ! this . forceKill ) { this . exitedWithError = true ; } } ) ; // Tell the USBDaemon to close the remote process this . close = ( ) => { // Write the close command daemon . write ( protocol . closeProcess ( this . id ) ) ; // Mark this process as closed this . closed = true ; } ; // Send a signal to the remote process this . kill = ( signal ) => { // Mark our boolean this . forceKill = true ; // If we should wait for close (most processes should) if ( this . waitForClose ) { // Write the signal command daemon . write ( protocol . killProcess ( this . id , signal ) ) ; } else { // Mark the process as inactive and closed this . active = false ; this . closed = true ; // Emit the close event setImmediate ( ( ) => this . emit ( 'close' ) ) ; } } ; // Checks if this process is ready to be closed // and closes it if it can this . closeProcessIfReady = ( ) => { // If this process hasn't been closed before // and all of the streams are closed if ( ! this . active && ! this . closed && this . stdout . closed && this . stderr . closed ) { // Close this process this . close ( ) ; } } ; // When any of the streams complete, check if the process is ready to close this . stdout . once ( 'end' , ( ) => this . closeProcessIfReady ( ) ) ; this . stderr . once ( 'end' , ( ) => this . closeProcessIfReady ( ) ) ; // This function is primarily intended for compatibility with the ssh2 stream API this . stdout . signal = ( signalToSend ) => { switch ( signalToSend ) { case 'KILL' : this . kill ( 9 ) ; break ; case 'SIGINT' : this . kill ( 2 ) ; break ; } } ; // Tell the remote daemon that this process was created daemon . write ( protocol . newProcess ( this . id ) ) ; // Tell the remote daemon that we can start receiving outbound data this . stdout . ack ( MAX_BUFFER_SIZE ) ; this . stderr . ack ( MAX_BUFFER_SIZE ) ; }
A process is running remotely on the Tessel and data is piped in over USB
A process is running remotely on the Tessel and data is piped in over USB