/*
 * @ndt-client.js
 * A WebSocket client for the Network Diagnostic Tool (NDT)
 *
 * This is an NDT client, written in javascript.  It speaks the WebSocket
 * version of the NDT protocol.  The NDT protocol is documented at:
 * https://code.google.com/p/ndt/wiki/NDTProtocol
 */

/* jslint bitwise: true, browser: true, nomen: true, indent: 2, -W097 */
/* global Uint8Array, Blob, WebSocket, console */

'use strict';

/**
 * NDTjs Constructor.
 *
 * @param {String} serverAddress - NDT Server FQDN or IP Address
 * @param {Number} [serverPort="3001"] - NDT Server Port
 * @param {String} [serverPath="/ndt_protocol"] NDT Server URL Path
 * @param {Boolean} [verboseDebug="true"] Level of Debugging for NDTjs Client
 * @constructor
 */

var NDTjs = function(serverAddress, serverPort, serverPath, verboseDebug) {
  var defaultSettings = {
    serverPort: Number(3001),
    serverPath: String('/ndt_protocol'),
    verboseDebug: Boolean(true)
  };

  this.constants = {
    /*
     * Send 1MiB websocket messages, as this seems to cause Chrome to have the
     * fewest performance problems.  It is important that this number be a
     * multiple of 8192, as the NDT protocol asks that we send 8192 bytes at a
     * time.  We can't force websocket implementations to hold to that (RFC6455
     * sec. 5.4 makes explicit that websocket clients may fragment messages in
     * any way they want), but we should at least make it possible for them to
     * send multiples of 8192 bytes.
     */
    SEND_BUFFER_SIZE: 8192 * 128
  };
  this.settings = {
    metaInformation: {
      'client.application': String('NDTjs')
    }
  };
  this.results = {
    c2sRate: undefined,
    s2cRate: undefined
  };

  this.settings.serverAddress = String(serverAddress);
  this.settings.serverPort = (serverPort !== undefined) ? Number(serverPort) :
      defaultSettings.serverPort;
  this.settings.serverPath = (serverPath !== undefined) ? String(serverPath) :
      defaultSettings.serverPath;
  this.settings.verboseDebug = (verboseDebug !== undefined &&
      verboseDebug instanceof Boolean) ? verboseDebug :
      defaultSettings.verboseDebug;

  this.logger('Initialized NDTjs with the following settings: ' +
      JSON.stringify(this.settings));

  if (!this.checkBrowserSupport()) {
    this.logger('Browser or runtime environment does not support WebSockets');
    throw new Error('UnsupportedBrowser');
  }
};

/**
 * Log a message to the console if debugging is enabled.
 *
 * @param {String} logMessage - The message to log.
 */

NDTjs.prototype.logger = function(logMessage) {

  if (this.settings.verboseDebug) {
    console.log(logMessage);
  }
};

/**
 * Check that the browser supports the NDT test.
 *
 * @returns {Boolean} Browser supports necessary functions for test client.
 */

NDTjs.prototype.checkBrowserSupport = function() {

  if (WebSocket === undefined && window.WebSocket === undefined &&
      window.MozWebSocket === undefined) {
    return false;
  }
  return true;
};

@@ -2980,12 +2980,1541 @@
 rn true;%0A%7D;%0A
+%0A/**%0A * Parses messages received from the NDT server.%0A *%0A * @param %7BBuffer%7D passedBuffer Raw message received from the NDT server.%0A * @returns %7BObject%7D Parsed messaged with type and message properties.%0A */%0A%0ANDTjs.prototype.parseNDTMessage = function(passedBuffer) %7B%0A  var i;%0A  var bufferUint8;%0A  var NDTMessage = %7B%0A    'type': %5B%5D,%0A    'message': undefined,%0A  %7D;%0A  try %7B%0A    bufferUint8 = new Uint8Array(passedBuffer);%0A    NDTMessage.message = String.fromCharCode.apply(null,%0A        new Uint8Array(passedBuffer.slice(3)));%0A  %7D catch (caughtError) %7B%0A    this.logger('Caught exception: ' + caughtError);%0A    throw new Error('NDTMessageParserError');%0A  %7D%0A%0A  for (i = 0; i %3C 3; i += 1) %7B%0A    NDTMessage.type%5Bi%5D = bufferUint8%5Bi%5D;%0A  %7D%0A%0A  return NDTMessage;%0A%7D;%0A%0A/**%0A * A simple helper function to create a WebSocket consistently.%0A *%0A * @param %7BString%7D serverAddress The FQDN or IP of the NDT server.%0A * @param %7BNumber%7D serverPort The port expected for the NDT test.%0A * @param %7BString%7D serverPath The path of the resource to request from NDT.%0A * @param %7BString%7D websocketProtocol The WebSocket protocol to build for.%0A * @returns %7BWebSocket%7D The WebSocket we created;%0A */%0A%0ANDTjs.prototype.createWebSocket = function(serverAddress, serverPort,%0A                                           serverPath, websocketProtocol) %7B%0A  var createdWebSocket;%0A  createdWebSocket = new WebSocket('ws://' + serverAddress + ':' +%0A      serverPort + serverPath, websocketProtocol);%0A  createdWebSocket.binaryType = 'arraybuffer';%0A  return createdWebSocket;%0A%7D;%0A

Add WebSocket helper and NDT Parser