swh:1:snp:c53ab93da1867a0ee99951a3636bca865f9194df
Raw File
Tip revision: 274eefef703d5c5621a202edda8f5e5fc619b309 authored by einaros on 27 December 2011, 12:06:12 UTC
updated history
Tip revision: 274eefe
wscat
#!/usr/bin/env node

/*!
 * ws: a node.js websocket client
 * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var WebSocket = require('../')
  , program = require('commander')
  , util = require('util')
  , events = require('events')
  , tty = require('tty');

/**
 * InputReader - processes console input
 */

function Console(onData) {
  this.stdin = process.openStdin();
  tty.setRawMode(true);
  this.line = '';
  this.pause = true;
  var self = this;
  this.stdin.on('keypress', function (chunk, key) {
    if (key && key.ctrl && key.name == 'c') self.emit('break');
    else if (key && key.name == 'enter') {
      if (self.line.length > 0) {
        process.stdout.write('\n');
        var line = self.line;
        self.line = '';
        process.stdout.write(chunk);
        self.emit('data', line);
      }
    }
    else if (key && key.name == 'backspace') {
      if (self.line.length > 0) {
        self.line = self.line.substr(0, self.line.length - 1);
        process.stdout.write('\033[1D \033[1D');
      }
    }
    else if (typeof chunk != 'undefined' && !self.pause){
      self.line += chunk;
      process.stdout.write(chunk);
    }
  });
}
util.inherits(Console, events.EventEmitter);

Console.Colors = {
  Red: '\033[31m',
  Green: '\033[32m',
  Yellow: '\033[33m',
  Blue: '\033[34m',
  Default: '\033[39m'
};

Console.prototype.prompt = function() {
  this.pause = false;
  this.line = '';
  process.stdout.write('> ');
}

Console.prototype.print = function(msg, color) {
  this.clear();
  color = color || Console.Colors.Default;
  process.stdout.write(color + msg + Console.Colors.Default + '\n');
  this.restore();
}

Console.prototype.clear = function() {
  if (this.pause) return;
  process.stdout.write('\033[2K\033[E');
}

Console.prototype.restore = function() {
  if (this.pause) return;
  process.stdout.write('> ' + this.line);
}

/**
 * The actual application
 */

program
  .version('0.3.8')
  .usage('[options] <url>')
  .option('-l, --listen <port>', 'listen on port')
  .option('-c, --connect <url>', 'connect to a websocket server')
  .option('-p, --protocol <version>', 'optional protocol version')
  .option('-o, --origin <origin>', 'optional origin')
  .parse(process.argv);

if (program.listen && program.connect) {
  console.error('\033[33merror: use either --listen or --connect\033[39m');
  process.exit(-1);
}
else if (program.listen) {
  var wsConsole = new Console();
  var options = {};
  if (program.protocol) options.protocolVersion = program.protocol;
  if (program.origin) options.origin = program.origin;
  var ws = null;
  var wss = new WebSocket.Server({port: program.listen}, function() {
    wsConsole.print('listening on port ' + program.listen + ' (press CTRL+C to quit)', Console.Colors.Green);
  });
  wsConsole.on('break', function() {
    if (ws) {
      try {
        ws.close();
      }
      catch (e) {}
    }
    process.exit(0);
  });
  wsConsole.on('data', function(data) {
    if (ws) {
      ws.send(data, {mask: true});
      wsConsole.prompt();
    }
  });
  wss.on('connection', function(newClient) {
    if (ws) {
      // limit to one client
      newClient.terminate();
      return;
    };
    ws = newClient;
    wsConsole.prompt();
    wsConsole.print('client connected', Console.Colors.Green);
    ws.on('close', function() {
      wsConsole.print('disconnected', Console.Colors.Green);
      wsConsole.clear();
      ws = null;
    });
    ws.on('error', function(code, description) {
      wsConsole.print('error: ' + code + ' ' + description, Console.Colors.Yellow);
    });
    ws.on('message', function(data, flags) {
      wsConsole.print('< ' + data, Console.Colors.Blue);
    });
  });
  wss.on('error', function(error) {
    wsConsole.print('error: ' + error.toString(), Console.Colors.Yellow);
    process.exit(-1);
  });
}
else if (program.connect) {
  var wsConsole = new Console();
  var options = {};
  if (program.protocol) options.protocolVersion = program.protocol;
  if (program.origin) options.origin = program.origin;
  var ws = new WebSocket(program.connect, options);
  ws.on('open', function() {
    wsConsole.print('connected (press CTRL+C to quit)', Console.Colors.Green);
    wsConsole.prompt();
    wsConsole.on('data', function(data) {
      ws.send(data, {mask: true});
      wsConsole.prompt();
    });
  });
  ws.on('close', function() {
    wsConsole.print('disconnected', Console.Colors.Green);
    wsConsole.clear();
    process.exit();
  });
  ws.on('error', function(code, description) {
    wsConsole.print('error: ' + code + ' ' + description, Console.Colors.Yellow);
    process.exit(-1);
  });
  ws.on('message', function(data, flags) {
    wsConsole.print('< ' + data, Console.Colors.Blue);
  });
  wsConsole.on('break', function() {
    if (ws) {
      try {
        ws.close();
      }
      catch(e) {}
      process.exit();
    }
  });
}
else {
  console.error('\033[33merror: use either --listen or --connect\033[39m');
  process.exit(-1);
}
back to top