Pārlūkot izejas kodu

removed demo folder

Michelle Bu 12 gadi atpakaļ
vecāks
revīzija
55c39fa795
8 mainītis faili ar 2 papildinājumiem un 2948 dzēšanām
  1. 2 1
      .gitignore
  2. 0 1219
      demo/peer.js
  3. 0 17
      demo/server.js
  4. 0 37
      demo/source.html
  5. 0 17
      demo/static/page.html
  6. 0 41
      demo/static/peer.html
  7. 0 1578
      demo/static/peer.js
  8. 0 38
      demo/static/peer1.html

+ 2 - 1
.gitignore

@@ -10,6 +10,7 @@ lib-cov
 pids
 logs
 results
+demo
 
 node_modules
-npm-debug.log
+npm-debug.log

+ 0 - 1219
demo/peer.js

@@ -1,1219 +0,0 @@
-/*! peerjs.js build:0.0.1, development. Copyright(c) 2013 Michelle Bu <michelle@michellebu.com> */
-(function(exports){
-var binaryFeatures = {};
-binaryFeatures.useBlobBuilder = (function(){
-  try {
-    new Blob([]);
-    return false;
-  } catch (e) {
-    return true;
-  }
-})();
-
-binaryFeatures.useArrayBufferView = !binaryFeatures.useBlobBuilder && (function(){
-  try {
-    return (new Blob([new Uint8Array([])])).size === 0;
-  } catch (e) {
-    return true;
-  }
-})();
-binaryFeatures.supportsBinaryWebsockets = (function(){
-  try {
-    var wstest = new WebSocket('ws://null');
-    wstest.onerror = function(){};
-    if (typeof(wstest.binaryType) !== "undefined") {
-      return true;
-    } else {
-      return false;
-    }
-    wstest.close();
-    wstest = null;
-  } catch (e) {
-    return false;
-  }
-})();
-
-exports.binaryFeatures = binaryFeatures;
-exports.BlobBuilder = window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder || window.BlobBuilder;
-
-function BufferBuilder(){
-  this._pieces = [];
-  this._parts = [];
-}
-
-BufferBuilder.prototype.append = function(data) {
-  if(typeof data === 'number') {
-    this._pieces.push(data);
-  } else {
-    this._flush();
-    this._parts.push(data);
-  }
-};
-
-BufferBuilder.prototype._flush = function() {
-  if (this._pieces.length > 0) {    
-    var buf = new Uint8Array(this._pieces);
-    if(!binaryFeatures.useArrayBufferView) {
-      buf = buf.buffer;
-    }
-    this._parts.push(buf);
-    this._pieces = [];
-  }
-};
-
-BufferBuilder.prototype.getBuffer = function() {
-  this._flush();
-  if(binaryFeatures.useBlobBuilder) {
-    var builder = new BlobBuilder();
-    for(var i = 0, ii = this._parts.length; i < ii; i++) {
-      builder.append(this._parts[i]);
-    }
-    return builder.getBlob();
-  } else {
-    return new Blob(this._parts);
-  }
-};
-exports.BinaryPack = {
-  unpack: function(data){
-    var unpacker = new Unpacker(data);
-    return unpacker.unpack();
-  },
-  pack: function(data){
-    var packer = new Packer();
-    var buffer = packer.pack(data);
-    return buffer;
-  }
-};
-
-function Unpacker (data){
-  // Data is ArrayBuffer
-  this.index = 0;
-  this.dataBuffer = data;
-  this.dataView = new Uint8Array(this.dataBuffer);
-  this.length = this.dataBuffer.byteLength;
-}
-
-
-Unpacker.prototype.unpack = function(){
-  var type = this.unpack_uint8();
-  if (type < 0x80){
-    var positive_fixnum = type;
-    return positive_fixnum;
-  } else if ((type ^ 0xe0) < 0x20){
-    var negative_fixnum = (type ^ 0xe0) - 0x20;
-    return negative_fixnum;
-  }
-  var size;
-  if ((size = type ^ 0xa0) <= 0x0f){
-    return this.unpack_raw(size);
-  } else if ((size = type ^ 0xb0) <= 0x0f){
-    return this.unpack_string(size);
-  } else if ((size = type ^ 0x90) <= 0x0f){
-    return this.unpack_array(size);
-  } else if ((size = type ^ 0x80) <= 0x0f){
-    return this.unpack_map(size);
-  }
-  switch(type){
-    case 0xc0:
-      return null;
-    case 0xc1:
-      return undefined;
-    case 0xc2:
-      return false;
-    case 0xc3:
-      return true;
-    case 0xca:
-      return this.unpack_float();
-    case 0xcb:
-      return this.unpack_double();
-    case 0xcc:
-      return this.unpack_uint8();
-    case 0xcd:
-      return this.unpack_uint16();
-    case 0xce:
-      return this.unpack_uint32();
-    case 0xcf:
-      return this.unpack_uint64();
-    case 0xd0:
-      return this.unpack_int8();
-    case 0xd1:
-      return this.unpack_int16();
-    case 0xd2:
-      return this.unpack_int32();
-    case 0xd3:
-      return this.unpack_int64();
-    case 0xd4:
-      return undefined;
-    case 0xd5:
-      return undefined;
-    case 0xd6:
-      return undefined;
-    case 0xd7:
-      return undefined;
-    case 0xd8:
-      size = this.unpack_uint16();
-      return this.unpack_string(size);
-    case 0xd9:
-      size = this.unpack_uint32();
-      return this.unpack_string(size);
-    case 0xda:
-      size = this.unpack_uint16();
-      return this.unpack_raw(size);
-    case 0xdb:
-      size = this.unpack_uint32();
-      return this.unpack_raw(size);
-    case 0xdc:
-      size = this.unpack_uint16();
-      return this.unpack_array(size);
-    case 0xdd:
-      size = this.unpack_uint32();
-      return this.unpack_array(size);
-    case 0xde:
-      size = this.unpack_uint16();
-      return this.unpack_map(size);
-    case 0xdf:
-      size = this.unpack_uint32();
-      return this.unpack_map(size);
-  }
-}
-
-Unpacker.prototype.unpack_uint8 = function(){
-  var byte = this.dataView[this.index] & 0xff;
-  this.index++;
-  return byte;
-};
-
-Unpacker.prototype.unpack_uint16 = function(){
-  var bytes = this.read(2);
-  var uint16 =
-    ((bytes[0] & 0xff) * 256) + (bytes[1] & 0xff);
-  this.index += 2;
-  return uint16;
-}
-
-Unpacker.prototype.unpack_uint32 = function(){
-  var bytes = this.read(4);
-  var uint32 =
-     ((bytes[0]  * 256 +
-       bytes[1]) * 256 +
-       bytes[2]) * 256 +
-       bytes[3];
-  this.index += 4;
-  return uint32;
-}
-
-Unpacker.prototype.unpack_uint64 = function(){
-  var bytes = this.read(8);
-  var uint64 =
-   ((((((bytes[0]  * 256 +
-       bytes[1]) * 256 +
-       bytes[2]) * 256 +
-       bytes[3]) * 256 +
-       bytes[4]) * 256 +
-       bytes[5]) * 256 +
-       bytes[6]) * 256 +
-       bytes[7];
-  this.index += 8;
-  return uint64;
-}
-
-
-Unpacker.prototype.unpack_int8 = function(){
-  var uint8 = this.unpack_uint8();
-  return (uint8 < 0x80 ) ? uint8 : uint8 - (1 << 8);
-};
-
-Unpacker.prototype.unpack_int16 = function(){
-  var uint16 = this.unpack_uint16();
-  return (uint16 < 0x8000 ) ? uint16 : uint16 - (1 << 16);
-}
-
-Unpacker.prototype.unpack_int32 = function(){
-  var uint32 = this.unpack_uint32();
-  return (uint32 < Math.pow(2, 31) ) ? uint32 :
-    uint32 - Math.pow(2, 32);
-}
-
-Unpacker.prototype.unpack_int64 = function(){
-  var uint64 = this.unpack_uint64();
-  return (uint64 < Math.pow(2, 63) ) ? uint64 :
-    uint64 - Math.pow(2, 64);
-}
-
-Unpacker.prototype.unpack_raw = function(size){
-  if ( this.length < this.index + size){
-    throw new Error('BinaryPackFailure: index is out of range'
-      + ' ' + this.index + ' ' + size + ' ' + this.length);
-  }
-  var buf = this.dataBuffer.slice(this.index, this.index + size);
-  this.index += size;
-  
-    //buf = util.bufferToString(buf);
-  
-  return buf;
-}
-
-Unpacker.prototype.unpack_string = function(size){
-  var bytes = this.read(size);
-  var i = 0, str = '', c, code;
-  while(i < size){
-    c = bytes[i];
-    if ( c < 128){
-      str += String.fromCharCode(c);
-      i++;
-    } else if ((c ^ 0xc0) < 32){
-      code = ((c ^ 0xc0) << 6) | (bytes[i+1] & 63);
-      str += String.fromCharCode(code);
-      i += 2;
-    } else {
-      code = ((c & 15) << 12) | ((bytes[i+1] & 63) << 6) |
-        (bytes[i+2] & 63);
-      str += String.fromCharCode(code);
-      i += 3;
-    }
-  }
-  this.index += size;
-  return str;
-}
-
-Unpacker.prototype.unpack_array = function(size){
-  var objects = new Array(size);
-  for(var i = 0; i < size ; i++){
-    objects[i] = this.unpack();
-  }
-  return objects;
-}
-
-Unpacker.prototype.unpack_map = function(size){
-  var map = {};
-  for(var i = 0; i < size ; i++){
-    var key  = this.unpack();
-    var value = this.unpack();
-    map[key] = value;
-  }
-  return map;
-}
-
-Unpacker.prototype.unpack_float = function(){
-  var uint32 = this.unpack_uint32();
-  var sign = uint32 >> 31;
-  var exp  = ((uint32 >> 23) & 0xff) - 127;
-  var fraction = ( uint32 & 0x7fffff ) | 0x800000;
-  return (sign == 0 ? 1 : -1) *
-    fraction * Math.pow(2, exp - 23);
-}
-
-Unpacker.prototype.unpack_double = function(){
-  var h32 = this.unpack_uint32();
-  var l32 = this.unpack_uint32();
-  var sign = h32 >> 31;
-  var exp  = ((h32 >> 20) & 0x7ff) - 1023;
-  var hfrac = ( h32 & 0xfffff ) | 0x100000;
-  var frac = hfrac * Math.pow(2, exp - 20) +
-    l32   * Math.pow(2, exp - 52);
-  return (sign == 0 ? 1 : -1) * frac;
-}
-
-Unpacker.prototype.read = function(length){
-  var j = this.index;
-  if (j + length <= this.length) {
-    return this.dataView.subarray(j, j + length);
-  } else {
-    throw new Error('BinaryPackFailure: read index out of range');
-  }
-}
-  
-function Packer (){
-  this.bufferBuilder = new BufferBuilder();
-}
-
-Packer.prototype.pack = function(value){
-  var type = typeof(value);
-  if (type == 'string'){
-    this.pack_string(value);
-  } else if (type == 'number'){
-    if (Math.floor(value) === value){
-      this.pack_integer(value);
-    } else{
-      this.pack_double(value);
-    }
-  } else if (type == 'boolean'){
-    if (value === true){
-      this.bufferBuilder.append(0xc3);
-    } else if (value === false){
-      this.bufferBuilder.append(0xc2);
-    }
-  } else if (type == 'undefined'){
-    this.bufferBuilder.append(0xc0);
-  } else if (type == 'object'){
-    if (value === null){
-      this.bufferBuilder.append(0xc0);
-    } else {
-      var constructor = value.constructor;
-      if (constructor == Array){
-        this.pack_array(value);
-      } else if (constructor == Blob || constructor == File) {
-        this.pack_bin(value);
-      } else if (constructor == ArrayBuffer) {
-        if(binaryFeatures.useArrayBufferView) {
-          this.pack_bin(new Uint8Array(value));
-        } else {
-          this.pack_bin(value);
-        }
-      } else if ('BYTES_PER_ELEMENT' in value){
-        if(binaryFeatures.useArrayBufferView) {
-          this.pack_bin(value);
-        } else {
-          this.pack_bin(value.buffer);
-        }
-      } else if (constructor == Object){
-        this.pack_object(value);
-      } else if (constructor == Date){
-        this.pack_string(value.toString());
-      } else if (typeof value.toBinaryPack == 'function'){
-        this.bufferBuilder.append(value.toBinaryPack());
-      } else {
-        throw new Error('Type "' + constructor.toString() + '" not yet supported');
-      }
-    }
-  } else {
-    throw new Error('Type "' + type + '" not yet supported');
-  }
-  return this.bufferBuilder.getBuffer();
-}
-
-
-Packer.prototype.pack_bin = function(blob){
-  var length = blob.length || blob.byteLength || blob.size;
-  if (length <= 0x0f){
-    this.pack_uint8(0xa0 + length);
-  } else if (length <= 0xffff){
-    this.bufferBuilder.append(0xda) ;
-    this.pack_uint16(length);
-  } else if (length <= 0xffffffff){
-    this.bufferBuilder.append(0xdb);
-    this.pack_uint32(length);
-  } else{
-    throw new Error('Invalid length');
-    return;
-  }
-  this.bufferBuilder.append(blob);
-}
-
-Packer.prototype.pack_string = function(str){
-  var length = str.length;
-  if (length <= 0x0f){
-    this.pack_uint8(0xb0 + length);
-  } else if (length <= 0xffff){
-    this.bufferBuilder.append(0xd8) ;
-    this.pack_uint16(length);
-  } else if (length <= 0xffffffff){
-    this.bufferBuilder.append(0xd9);
-    this.pack_uint32(length);
-  } else{
-    throw new Error('Invalid length');
-    return;
-  }
-  this.bufferBuilder.append(str);
-}
-
-Packer.prototype.pack_array = function(ary){
-  var length = ary.length;
-  if (length <= 0x0f){
-    this.pack_uint8(0x90 + length);
-  } else if (length <= 0xffff){
-    this.bufferBuilder.append(0xdc)
-    this.pack_uint16(length);
-  } else if (length <= 0xffffffff){
-    this.bufferBuilder.append(0xdd);
-    this.pack_uint32(length);
-  } else{
-    throw new Error('Invalid length');
-  }
-  for(var i = 0; i < length ; i++){
-    this.pack(ary[i]);
-  }
-}
-
-Packer.prototype.pack_integer = function(num){
-  if ( -0x20 <= num && num <= 0x7f){
-    this.bufferBuilder.append(num & 0xff);
-  } else if (0x00 <= num && num <= 0xff){
-    this.bufferBuilder.append(0xcc);
-    this.pack_uint8(num);
-  } else if (-0x80 <= num && num <= 0x7f){
-    this.bufferBuilder.append(0xd0);
-    this.pack_int8(num);
-  } else if ( 0x0000 <= num && num <= 0xffff){
-    this.bufferBuilder.append(0xcd);
-    this.pack_uint16(num);
-  } else if (-0x8000 <= num && num <= 0x7fff){
-    this.bufferBuilder.append(0xd1);
-    this.pack_int16(num);
-  } else if ( 0x00000000 <= num && num <= 0xffffffff){
-    this.bufferBuilder.append(0xce);
-    this.pack_uint32(num);
-  } else if (-0x80000000 <= num && num <= 0x7fffffff){
-    this.bufferBuilder.append(0xd2);
-    this.pack_int32(num);
-  } else if (-0x8000000000000000 <= num && num <= 0x7FFFFFFFFFFFFFFF){
-    this.bufferBuilder.append(0xd3);
-    this.pack_int64(num);
-  } else if (0x0000000000000000 <= num && num <= 0xFFFFFFFFFFFFFFFF){
-    this.bufferBuilder.append(0xcf);
-    this.pack_uint64(num);
-  } else{
-    throw new Error('Invalid integer');
-  }
-}
-
-Packer.prototype.pack_double = function(num){
-  var sign = 0;
-  if (num < 0){
-    sign = 1;
-    num = -num;
-  }
-  var exp  = Math.floor(Math.log(num) / Math.LN2);
-  var frac0 = num / Math.pow(2, exp) - 1;
-  var frac1 = Math.floor(frac0 * Math.pow(2, 52));
-  var b32   = Math.pow(2, 32);
-  var h32 = (sign << 31) | ((exp+1023) << 20) |
-      (frac1 / b32) & 0x0fffff;
-  var l32 = frac1 % b32;
-  this.bufferBuilder.append(0xcb);
-  this.pack_int32(h32);
-  this.pack_int32(l32);
-}
-
-Packer.prototype.pack_object = function(obj){
-  var keys = Object.keys(obj);
-  var length = keys.length;
-  if (length <= 0x0f){
-    this.pack_uint8(0x80 + length);
-  } else if (length <= 0xffff){
-    this.bufferBuilder.append(0xde);
-    this.pack_uint16(length);
-  } else if (length <= 0xffffffff){
-    this.bufferBuilder.append(0xdf);
-    this.pack_uint32(length);
-  } else{
-    throw new Error('Invalid length');
-  }
-  for(var prop in obj){
-    if (obj.hasOwnProperty(prop)){
-      this.pack(prop);
-      this.pack(obj[prop]);
-    }
-  }
-}
-
-Packer.prototype.pack_uint8 = function(num){
-  this.bufferBuilder.append(num);
-}
-
-Packer.prototype.pack_uint16 = function(num){
-  this.bufferBuilder.append(num >> 8);
-  this.bufferBuilder.append(num & 0xff);
-}
-
-Packer.prototype.pack_uint32 = function(num){
-  var n = num & 0xffffffff;
-  this.bufferBuilder.append((n & 0xff000000) >>> 24);
-  this.bufferBuilder.append((n & 0x00ff0000) >>> 16);
-  this.bufferBuilder.append((n & 0x0000ff00) >>>  8);
-  this.bufferBuilder.append((n & 0x000000ff));
-}
-
-Packer.prototype.pack_uint64 = function(num){
-  var high = num / Math.pow(2, 32);
-  var low  = num % Math.pow(2, 32);
-  this.bufferBuilder.append((high & 0xff000000) >>> 24);
-  this.bufferBuilder.append((high & 0x00ff0000) >>> 16);
-  this.bufferBuilder.append((high & 0x0000ff00) >>>  8);
-  this.bufferBuilder.append((high & 0x000000ff));
-  this.bufferBuilder.append((low  & 0xff000000) >>> 24);
-  this.bufferBuilder.append((low  & 0x00ff0000) >>> 16);
-  this.bufferBuilder.append((low  & 0x0000ff00) >>>  8);
-  this.bufferBuilder.append((low  & 0x000000ff));
-}
-
-Packer.prototype.pack_int8 = function(num){
-  this.bufferBuilder.append(num & 0xff);
-}
-
-Packer.prototype.pack_int16 = function(num){
-  this.bufferBuilder.append((num & 0xff00) >> 8);
-  this.bufferBuilder.append(num & 0xff);
-}
-
-Packer.prototype.pack_int32 = function(num){
-  this.bufferBuilder.append((num >>> 24) & 0xff);
-  this.bufferBuilder.append((num & 0x00ff0000) >>> 16);
-  this.bufferBuilder.append((num & 0x0000ff00) >>> 8);
-  this.bufferBuilder.append((num & 0x000000ff));
-}
-
-Packer.prototype.pack_int64 = function(num){
-  var high = Math.floor(num / Math.pow(2, 32));
-  var low  = num % Math.pow(2, 32);
-  this.bufferBuilder.append((high & 0xff000000) >>> 24);
-  this.bufferBuilder.append((high & 0x00ff0000) >>> 16);
-  this.bufferBuilder.append((high & 0x0000ff00) >>>  8);
-  this.bufferBuilder.append((high & 0x000000ff));
-  this.bufferBuilder.append((low  & 0xff000000) >>> 24);
-  this.bufferBuilder.append((low  & 0x00ff0000) >>> 16);
-  this.bufferBuilder.append((low  & 0x0000ff00) >>>  8);
-  this.bufferBuilder.append((low  & 0x000000ff));
-}
-/**
- * Light EventEmitter. Ported from Node.js/events.js
- * Eric Zhang
- */
-
-/**
- * EventEmitter class
- * Creates an object with event registering and firing methods
- */
-function EventEmitter() {
-  // Initialise required storage variables
-  this._events = {};
-}
-
-var isArray = Array.isArray;
-
-
-EventEmitter.prototype.addListener = function(type, listener, scope, once) {
-  if ('function' !== typeof listener) {
-    throw new Error('addListener only takes instances of Function');
-  }
-  
-  // To avoid recursion in the case that type == "newListeners"! Before
-  // adding it to the listeners, first emit "newListeners".
-  this.emit('newListener', type, typeof listener.listener === 'function' ?
-            listener.listener : listener);
-            
-  if (!this._events[type]) {
-    // Optimize the case of one listener. Don't need the extra array object.
-    this._events[type] = listener;
-  } else if (isArray(this._events[type])) {
-
-    // If we've already got an array, just append.
-    this._events[type].push(listener);
-
-  } else {
-    // Adding the second element, need to change to array.
-    this._events[type] = [this._events[type], listener];
-  }
-  
-};
-
-EventEmitter.prototype.on = EventEmitter.prototype.addListener;
-
-EventEmitter.prototype.once = function(type, listener, scope) {
-  if ('function' !== typeof listener) {
-    throw new Error('.once only takes instances of Function');
-  }
-
-  var self = this;
-  function g() {
-    self.removeListener(type, g);
-    listener.apply(this, arguments);
-  };
-
-  g.listener = listener;
-  self.on(type, g);
-
-  return this;
-};
-
-EventEmitter.prototype.removeListener = function(type, listener, scope) {
-  if ('function' !== typeof listener) {
-    throw new Error('removeListener only takes instances of Function');
-  }
-
-  // does not use listeners(), so no side effect of creating _events[type]
-  if (!this._events[type]) return this;
-
-  var list = this._events[type];
-
-  if (isArray(list)) {
-    var position = -1;
-    for (var i = 0, length = list.length; i < length; i++) {
-      if (list[i] === listener ||
-          (list[i].listener && list[i].listener === listener))
-      {
-        position = i;
-        break;
-      }
-    }
-
-    if (position < 0) return this;
-    list.splice(position, 1);
-    if (list.length == 0)
-      delete this._events[type];
-  } else if (list === listener ||
-             (list.listener && list.listener === listener))
-  {
-    delete this._events[type];
-  }
-
-  return this;
-};
-
-
-EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
-
-
-EventEmitter.prototype.removeAllListeners = function(type) {
-  if (arguments.length === 0) {
-    this._events = {};
-    return this;
-  }
-
-  // does not use listeners(), so no side effect of creating _events[type]
-  if (type && this._events && this._events[type]) this._events[type] = null;
-  return this;
-};
-
-EventEmitter.prototype.listeners = function(type) {
-  if (!this._events[type]) this._events[type] = [];
-  if (!isArray(this._events[type])) {
-    this._events[type] = [this._events[type]];
-  }
-  return this._events[type];
-};
-
-EventEmitter.prototype.emit = function(type) {
-  var type = arguments[0];
-  var handler = this._events[type];
-  if (!handler) return false;
-
-  if (typeof handler == 'function') {
-    switch (arguments.length) {
-      // fast cases
-      case 1:
-        handler.call(this);
-        break;
-      case 2:
-        handler.call(this, arguments[1]);
-        break;
-      case 3:
-        handler.call(this, arguments[1], arguments[2]);
-        break;
-      // slower
-      default:
-        var l = arguments.length;
-        var args = new Array(l - 1);
-        for (var i = 1; i < l; i++) args[i - 1] = arguments[i];
-        handler.apply(this, args);
-    }
-    return true;
-
-  } else if (isArray(handler)) {
-    var l = arguments.length;
-    var args = new Array(l - 1);
-    for (var i = 1; i < l; i++) args[i - 1] = arguments[i];
-
-    var listeners = handler.slice();
-    for (var i = 0, l = listeners.length; i < l; i++) {
-      listeners[i].apply(this, args);
-    }
-    return true;
-  } else {
-    return false;
-  }
-};
-
-
-
-var util = {
-  
-  debug: false,
-  
-  inherits: function(ctor, superCtor) {
-    ctor.super_ = superCtor;
-    ctor.prototype = Object.create(superCtor.prototype, {
-      constructor: {
-        value: ctor,
-        enumerable: false,
-        writable: true,
-        configurable: true
-      }
-    });
-  },
-  extend: function(dest, source) {
-    for(var key in source) {
-      if(source.hasOwnProperty(key)) {
-        dest[key] = source[key];
-      }
-    }
-    return dest;
-  },
-  pack: BinaryPack.pack,
-  unpack: BinaryPack.unpack,
-  randomPort: function() {
-    return Math.round(Math.random() * 60535) + 5000;
-  },
-  
-  log: function () {
-    if (util.debug) {
-      for (var i = 0; i < arguments.length; i++) {
-        console.log('*', i, '-- ', arguments[i]);
-      }
-    }
-  },
-
-  setZeroTimeout: (function(global) {
-    var timeouts = [];
-    var messageName = 'zero-timeout-message';
-
-    // Like setTimeout, but only takes a function argument.	 There's
-    // no time argument (always zero) and no arguments (you have to
-    // use a closure).
-    function setZeroTimeoutPostMessage(fn) {
-      timeouts.push(fn);
-      global.postMessage(messageName, '*');
-    }		
-
-    function handleMessage(event) {
-      if (event.source == global && event.data == messageName) {
-        if (event.stopPropagation) {
-          event.stopPropagation();
-        }
-        if (timeouts.length) {
-          timeouts.shift()();
-        }
-      }
-    }
-    if (global.addEventListener) {
-      global.addEventListener('message', handleMessage, true);
-    } else if (global.attachEvent) {
-      global.attachEvent('onmessage', handleMessage);
-    }
-    return setZeroTimeoutPostMessage;
-  }(this))
-};
-var RTCPeerConnection = null;
-var getUserMedia = null;
-var attachMediaStream = null;
-var browserisms = null;
-
-if (navigator.mozGetUserMedia) {
-  browserisms = 'Firefox'
-
-  RTCPeerConnection = mozRTCPeerConnection;
-
-  getUserMedia = navigator.mozGetUserMedia.bind(navigator);
-  attachMediaStream = function(element, stream) {
-    console.log("Attaching media stream");
-    element.mozSrcObject = stream;
-    element.play();
-  };
-} else if (navigator.webkitGetUserMedia) {
-  browserisms = 'Webkit'
-
-  RTCPeerConnection = webkitRTCPeerConnection;
-
-  getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
-  attachMediaStream = function(element, stream) {
-    element.src = webkitURL.createObjectURL(stream);
-  };
-}
-
-exports.RTCPeerConnection = RTCPeerConnection;
-exports.getUserMedia = getUserMedia;
-exports.attachMediaStream = attachMediaStream;
-exports.browserisms = browserisms;
-function Peer(options) {
-  if (!(this instanceof Peer)) return new Peer(options);
-  EventEmitter.call(this);
-
-  options = util.extend({
-    debug: false,
-    config: { 'iceServers': [{ 'url': 'stun:stun.l.google.com:19302' }] },
-    ws: 'ws://localhost'
-  }, options);
-  util.debug = options.debug;
-
-  this._id = null;
-
-  // Connections
-  this.connections = {};
-  this._socket = new WebSocket(options.ws);
-
-  // Init socket msg handlers
-  var self = this;
-  this._socket.onopen = function() {
-    self.socketInit();
-  };
-};
-
-util.inherits(Peer, EventEmitter);
-
-/** Start up websocket communications. */
-Peer.prototype.socketInit = function() {
-  var self = this;
-  // Announce as a PEER to receive an ID.
-  this._socket.send(JSON.stringify({
-    type: 'PEER'
-  }));
-
-  this._socket.onmessage = function(event) {
-    var message = JSON.parse(event.data);
-    var peer = message.src;
-    var connection = self.connections[peer];
-
-    switch (message.type) {
-      case 'ID':
-        self._id = message.id;
-        self.emit('ready', self._id);
-        break;
-      case 'OFFER':
-        var options = {
-          metadata: message.metadata,
-          peer: peer,
-          id: self._id,
-          originator: false,
-          sdp: message.sdp
-        };
-        var connection = new DataConnection(options, socket, function(err, connection) {
-          if (!err) {
-            self.emit('connection', connection);
-          }
-        });
-        self.connections[peer] = connection;
-        break;
-      case 'ANSWER':
-        if (connection) connection.handleAnswer(message);
-        break;
-      case 'CANDIDATE':
-        if (connection) connection.handleCandidate(message);
-        break;
-      case 'LEAVE':
-        if (connection) connection.handleLeave(message);
-        break;
-      case 'PORT':
-        if (browserisms && browserisms == 'Firefox') {
-          connection.handlePort(message);
-          break;
-        }
-      case 'DEFAULT':
-        util.log('PEER: unrecognized message ', message.type);
-        break;
-    }
-  };
-
-};
-
-
-Peer.prototype.connect = function(peer, metadata, cb) {
-  if (typeof metadata === 'function' && !cb) cb = metadata; metadata = false;
-
-  var options = {
-    metadata: metadata,
-    id: this._id,
-    peer: peer,
-    originator: true
-  };
-  var connection = new DataConnection(options, socket, cb);
-  this.connections[peer] = connection;
-};
-
-
-exports.Peer = Peer;
-
-function DataConnection(options, socket, cb) {
-  if (!(this instanceof DataConnection)) return new DataConnection(options);
-  EventEmitter.call(this);
-
-  // Is this the originator?
-  this._originator = options.originator || false;
-  this._cb = cb;
-  this._peer = options.peer;
-  this._id = options.id;
-
-  var sdp = options.sdp;
-  this.metadata = options.metadata;
-
-  // Set up socket handlers.
-  this._socket = socket;
-
-  // Firefoxism: connectDataConnection ports.
-  if (browserisms == 'Firefox') {
-    if (!DataConnection.usedPorts) {
-      DataConnection.usedPorts = [];
-    }
-    this.localPort = util.randomPort();
-    while (DataConnection.usedPorts.indexOf(this.localPort) != -1) {
-      this.localPort = util.randomPort();
-    }
-    this.remotePort = util.randomPort();
-    while (this.remotePort == this.localPort ||
-        DataConnection.usedPorts.indexOf(this.localPort) != -1) {
-      this.remotePort = util.randomPort();
-    }
-    DataConnection.usedPorts.push(this.remotePort);
-    DataConnection.usedPorts.push(this.localPort);
-  }
-
-  // Set up PeerConnection.
-  this._startPeerConnection();
-  if (this._originator) {
-    var self = this;
-    this._setupDataConnection(function() {
-      this._maybeBrowserisms();
-    });
-  } else if (sdp) {
-    try {
-      sdp = new RTCSessionDescription(message.sdp);
-    } catch(e) {
-      util.log('Firefox');
-    }
-    this._pc.setRemoteDescription(sdp, function() {
-      util.log('setRemoteDescription: offer');
-
-      self._setupDataChannel(function() {
-        self._maybeBrowserisms();
-      });
-    }, function(err) {
-      util.log('failed to setRemoteDescription with offer, ', err);
-    });
-  }
-};
-
-
-DataConnection.prototype.handleAnswer(message) {
-  var sdp = message.sdp;
-  try {
-    sdp = new RTCSessionDescription(message.sdp);
-  } catch(e) {
-    util.log('Firefox');
-  }
-  var self = this;
-  this._pc.setRemoteDescription(sdp, function() {
-    util.log('setRemoteDescription: answer');
-    // Firefoxism
-    if (browserisms == 'Firefox') {
-      self._pc.connectDataConnection(self.localPort, self.remotePort);
-      self._socket.send(JSON.stringify({
-        type: 'PORT',
-        dst: self._peer,
-        src: self._id,
-        remote: self.localPort,
-        local: self.remotePort
-      }));
-    }
-    util.log('ORIGINATOR: PeerConnection success');
-  }, function(err) {
-    util.log('failed to setRemoteDescription, ', err);
-  });
-};
-
-
-DataConnection.prototype.handleCandidate(message) {
-  util.log(message.candidate);
-  var candidate = new RTCIceCandidate(message.candidate);
-  this._pc.addIceCandidate(candidate);
-};
-
-
-DataConnection.prototype.handleLeave(message) {
-  util.log('counterpart disconnected');
-  if (!!this._pc && this._pc.readyState != 'closed') {
-    this._pc.close();
-    this._pc = null;
-  }
-  if (!!this._dc && this._dc.readyState != 'closed') {
-    this._dc.close();
-    this._dc = null;
-  }
-  this.emit('close', this._peer);
-};
-
-DataConnection.prototype.handlePort(message) {
-  if (!DataConnection.usedPorts) {
-    DataConnection.usedPorts = [];
-  }
-  DataConnection.usedPorts.push(message.local);
-  DataConnection.usedPorts.push(message.remote);
-  this._pc.connectDataConnection(message.local, message.remote);
-};
-
-
-/** Starts a PeerConnection and sets up handlers. */
-DataConnection.prototype._startPeerConnection = function() {
-  this._pc = new RTCPeerConnection(this._config, { optional:[ { RtpDataChannels: true } ]});
-  this._setupIce();
-};
-
-
-/** Takes care of ice handlers. */
-DataConnection.prototype._setupIce = function() {
-  var self = this;
-  this._pc.onicecandidate = function(event) {
-    util.log('candidates received');
-    if (event.candidate) {
-      self._socket.send(JSON.stringify({
-        type: 'CANDIDATE',
-        candidate: event.candidate,
-        dst: self._peer,
-        src: self._id
-      }));
-    } else {
-      util.log("End of candidates.");
-    }
-  };
-};
-
-
-/** Sets up DataChannel handlers. */
-DataConnection.prototype._setupDataChannel = function(cb) {
-  var self = this;
-  if (this._originator) {
-    /** ORIGINATOR SETUP */
-    if (browserisms == 'Webkit') {
-
-      // TODO: figure out the right thing to do with this.
-      this._pc.onstatechange = function() {
-        util.log('State Change: ', self._pc.readyState);
-      }
-
-    } else {
-      this._pc.onconnection = function() {
-        util.log('ORIGINATOR: onconnection triggered');
-        self._startDataChannel();
-      };
-    }
-  } else {
-    /** TARGET SETUP */
-    this._pc.ondatachannel = function(dc) {
-      util.log('SINK: ondatachannel triggered');
-      self._dc = dc;
-      self._dc.binaryType = 'blob';
-
-      self._cb(null, self);
-
-      self._dc.onmessage = function(e) {
-        self._handleDataMessage(e);
-      };
-    };
-
-    this._pc.onconnection = function() {
-      util.log('SINK: onconnection triggered');
-    };
-  }
-
-
-  this._pc.onclosedconnection = function() {
-    // Remove socket handlers perhaps.
-    self.emit('close', self._peer);
-  };
-};
-
-
-DataConnection.prototype._startDataChannel = function() {
-  var self = this;
-  this._dc = this._pc.createDataChannel(this._peer, { reliable: false });
-  this._dc.binaryType = 'blob';
-
-  this._cb(null, self);
-
-  this._dc.onmessage = function(e) {
-    self._handleDataMessage(e);
-  };
-};
-
-
-/** Decide whether to handle Firefoxisms. */
-DataConnection.prototype._maybeBrowserisms = function() {
-  var self = this;
-  if (browserisms == 'Firefox') {
-    getUserMedia({ audio: true, fake: true }, function(s) {
-      self._pc.addStream(s);
-
-      if (self._originator) {
-        self._makeOffer();
-      } else {
-        self._makeAnswer();
-      }
-
-    }, function(err) { util.log('crap'); });
-  } else {
-    if (self._originator) {
-      this._makeOffer();
-    } else {
-      this._makeAnswer();
-    }
-  }
-}
-
-
-/** Create an answer for PC. */
-DataConnection.prototype._makeAnswer = function() {
-  var self = this;
-
-  this._pc.createAnswer(function(answer) {
-    util.log('createAnswer');
-    self._pc.setLocalDescription(answer, function() {
-      util.log('setLocalDescription: answer');
-      self._socket.send(JSON.stringify({
-        type: 'ANSWER',
-        src: self._id,
-        sdp: answer,
-        dst: self._peer
-      }));
-    }, function(err) {
-      util.log('failed to setLocalDescription, ', err)
-    });
-  }, function(err) {
-    util.log('failed to create answer, ', err)
-  });
-};
-
-
-/** Create an offer for PC. */
-DataConnection.prototype._makeOffer = function() {
-  var self = this;
-
-  this._pc.createOffer(function(offer) {
-    util.log('createOffer')
-    self._pc.setLocalDescription(offer, function() {
-      util.log('setLocalDescription: offer');
-      self._socket.send(JSON.stringify({
-        type: 'OFFER',
-        sdp: offer,
-        dst: self._peer,
-        src: self._id,
-        metadata: self._metadata
-      }));
-    }, function(err) {
-      util.log('failed to setLocalDescription, ', err);
-    });
-  });
-};
-
-
-/** Allows user to send data. */
-DataConnection.prototype.send = function(data) {
-  var ab = BinaryPack.pack(data);
-  this._dc.send(ab);
-};
-
-
-// Handles a DataChannel message.
-DataConnection.prototype._handleDataMessage = function(e) {
-  var self = this;
-  var fr = new FileReader();
-  fr.onload = function(evt) {
-    var ab = evt.target.result;
-    var data = BinaryPack.unpack(ab);
-
-    self.emit('data', data);
-  };
-  fr.readAsArrayBuffer(e.data);
-};
-
-exports.DataChannel = DataChannel;
-
-
-})(this);

+ 0 - 17
demo/server.js

@@ -1,17 +0,0 @@
-var express = require('express');
-var fs = require('fs');
-var app =  express.createServer();
-
-// Initialize main server
-app.use(express.bodyParser());
-
-app.use(express.static(__dirname + '/static'));
-
-app.set('views', __dirname + '/views');
-
-
-app.listen(8000);
-
-
-var peer = require('peer');
-s = new peer.PeerServer({ debug: true, port: 9000 });

+ 0 - 37
demo/source.html

@@ -1,37 +0,0 @@
-<!DOCTYPE HTML> 
-<html lang="en"> 
-<head>
-<title>Source Test</title>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
-<meta http-equiv="Content-Language" content="en-us"> 
-<meta name="description" content=""> 
-<meta name="keywords" content=""> 
-
-<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> 
-<script src="/socket.io/socket.io.js"></script>
-<script type="text/javascript" src="/js/binarypack/dist/binarypack.js"></script>
-<script type="text/javascript" src="/js/adapter.js"></script>
-<script type="text/javascript" src="/js/source.js"></script>
-<script>
-$(document).ready(function() {
-  source = new SourcePeer({});
-  source.on('ready', function(source_id) {
-    console.log(source_id);
-  });
-  source.on('sink', function(sink_id) {
-    console.log('Creepy message sent to sink');
-    source.send('I see you, ' + sink_id, sink_id);
-    source.send('Guys, ' + sink_id + ' just joined us!');
-  });
-  source.on('data', function(data) {
-    console.log(data);
-  });
-});
-</script>
-
-</head> 
- 
-<body> 
-  This is the P2P source.
-</body> 
-</html> 

+ 0 - 17
demo/static/page.html

@@ -1,17 +0,0 @@
-<!DOCTYPE HTML> 
-<html lang="en"> 
-<head>
-<title>PeerJS Test Page</title>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
-<meta http-equiv="Content-Language" content="en-us"> 
-<meta name="description" content=""> 
-<meta name="keywords" content=""> 
-
-<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> 
-<script type="text/javascript" src="/peer.js"></script>
-
-</head> 
- 
-<body> 
-</body> 
-</html> 

+ 0 - 41
demo/static/peer.html

@@ -1,41 +0,0 @@
-<!DOCTYPE HTML> 
-<html lang="en"> 
-<head>
-<title>Peer Test</title>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
-<meta http-equiv="Content-Language" content="en-us"> 
-<meta name="description" content=""> 
-<meta name="keywords" content=""> 
-
-<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> 
-<script type="text/javascript" src="/peer.js"></script>
-<script>
-$(document).ready(function() {
-  originator = new Peer('michelle', { key: '3lcmbh31bezpk3xr', host: 'localhost', port: '9000', debug: true });
-  originator.on('open', function(id) {
-    console.log(id);
-  });
-  originator.on('error', function(msg) {
-    console.log(msg);
-  });
-  originator.on('connection', function(connection) {
-    x = connection;
-    console.log('connection');
-
-    connection.on('open', function() {
-      connection.send('What is going on?');
-    });
-    connection.on('data', function(data) {
-      console.log(data);
-    });
-  });
-});
-
-</script>
-
-</head> 
- 
-<body> 
-  This is a P2P peer.
-</body> 
-</html> 

+ 0 - 1578
demo/static/peer.js

@@ -1,1578 +0,0 @@
-/*! peerjs.js build:0.0.1, development. Copyright(c) 2013 Michelle Bu <michelle@michellebu.com> */
-(function(exports){
-var binaryFeatures = {};
-binaryFeatures.useBlobBuilder = (function(){
-  try {
-    new Blob([]);
-    return false;
-  } catch (e) {
-    return true;
-  }
-})();
-
-binaryFeatures.useArrayBufferView = !binaryFeatures.useBlobBuilder && (function(){
-  try {
-    return (new Blob([new Uint8Array([])])).size === 0;
-  } catch (e) {
-    return true;
-  }
-})();
-binaryFeatures.supportsBinaryWebsockets = (function(){
-  try {
-    var wstest = new WebSocket('ws://null');
-    wstest.onerror = function(){};
-    if (typeof(wstest.binaryType) !== "undefined") {
-      return true;
-    } else {
-      return false;
-    }
-    wstest.close();
-    wstest = null;
-  } catch (e) {
-    return false;
-  }
-})();
-
-exports.binaryFeatures = binaryFeatures;
-exports.BlobBuilder = window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder || window.BlobBuilder;
-
-function BufferBuilder(){
-  this._pieces = [];
-  this._parts = [];
-}
-
-BufferBuilder.prototype.append = function(data) {
-  if(typeof data === 'number') {
-    this._pieces.push(data);
-  } else {
-    this._flush();
-    this._parts.push(data);
-  }
-};
-
-BufferBuilder.prototype._flush = function() {
-  if (this._pieces.length > 0) {    
-    var buf = new Uint8Array(this._pieces);
-    if(!binaryFeatures.useArrayBufferView) {
-      buf = buf.buffer;
-    }
-    this._parts.push(buf);
-    this._pieces = [];
-  }
-};
-
-BufferBuilder.prototype.getBuffer = function() {
-  this._flush();
-  if(binaryFeatures.useBlobBuilder) {
-    var builder = new BlobBuilder();
-    for(var i = 0, ii = this._parts.length; i < ii; i++) {
-      builder.append(this._parts[i]);
-    }
-    return builder.getBlob();
-  } else {
-    return new Blob(this._parts);
-  }
-};
-exports.BinaryPack = {
-  unpack: function(data){
-    var unpacker = new Unpacker(data);
-    return unpacker.unpack();
-  },
-  pack: function(data){
-    var packer = new Packer();
-    var buffer = packer.pack(data);
-    return buffer;
-  }
-};
-
-function Unpacker (data){
-  // Data is ArrayBuffer
-  this.index = 0;
-  this.dataBuffer = data;
-  this.dataView = new Uint8Array(this.dataBuffer);
-  this.length = this.dataBuffer.byteLength;
-}
-
-
-Unpacker.prototype.unpack = function(){
-  var type = this.unpack_uint8();
-  if (type < 0x80){
-    var positive_fixnum = type;
-    return positive_fixnum;
-  } else if ((type ^ 0xe0) < 0x20){
-    var negative_fixnum = (type ^ 0xe0) - 0x20;
-    return negative_fixnum;
-  }
-  var size;
-  if ((size = type ^ 0xa0) <= 0x0f){
-    return this.unpack_raw(size);
-  } else if ((size = type ^ 0xb0) <= 0x0f){
-    return this.unpack_string(size);
-  } else if ((size = type ^ 0x90) <= 0x0f){
-    return this.unpack_array(size);
-  } else if ((size = type ^ 0x80) <= 0x0f){
-    return this.unpack_map(size);
-  }
-  switch(type){
-    case 0xc0:
-      return null;
-    case 0xc1:
-      return undefined;
-    case 0xc2:
-      return false;
-    case 0xc3:
-      return true;
-    case 0xca:
-      return this.unpack_float();
-    case 0xcb:
-      return this.unpack_double();
-    case 0xcc:
-      return this.unpack_uint8();
-    case 0xcd:
-      return this.unpack_uint16();
-    case 0xce:
-      return this.unpack_uint32();
-    case 0xcf:
-      return this.unpack_uint64();
-    case 0xd0:
-      return this.unpack_int8();
-    case 0xd1:
-      return this.unpack_int16();
-    case 0xd2:
-      return this.unpack_int32();
-    case 0xd3:
-      return this.unpack_int64();
-    case 0xd4:
-      return undefined;
-    case 0xd5:
-      return undefined;
-    case 0xd6:
-      return undefined;
-    case 0xd7:
-      return undefined;
-    case 0xd8:
-      size = this.unpack_uint16();
-      return this.unpack_string(size);
-    case 0xd9:
-      size = this.unpack_uint32();
-      return this.unpack_string(size);
-    case 0xda:
-      size = this.unpack_uint16();
-      return this.unpack_raw(size);
-    case 0xdb:
-      size = this.unpack_uint32();
-      return this.unpack_raw(size);
-    case 0xdc:
-      size = this.unpack_uint16();
-      return this.unpack_array(size);
-    case 0xdd:
-      size = this.unpack_uint32();
-      return this.unpack_array(size);
-    case 0xde:
-      size = this.unpack_uint16();
-      return this.unpack_map(size);
-    case 0xdf:
-      size = this.unpack_uint32();
-      return this.unpack_map(size);
-  }
-}
-
-Unpacker.prototype.unpack_uint8 = function(){
-  var byte = this.dataView[this.index] & 0xff;
-  this.index++;
-  return byte;
-};
-
-Unpacker.prototype.unpack_uint16 = function(){
-  var bytes = this.read(2);
-  var uint16 =
-    ((bytes[0] & 0xff) * 256) + (bytes[1] & 0xff);
-  this.index += 2;
-  return uint16;
-}
-
-Unpacker.prototype.unpack_uint32 = function(){
-  var bytes = this.read(4);
-  var uint32 =
-     ((bytes[0]  * 256 +
-       bytes[1]) * 256 +
-       bytes[2]) * 256 +
-       bytes[3];
-  this.index += 4;
-  return uint32;
-}
-
-Unpacker.prototype.unpack_uint64 = function(){
-  var bytes = this.read(8);
-  var uint64 =
-   ((((((bytes[0]  * 256 +
-       bytes[1]) * 256 +
-       bytes[2]) * 256 +
-       bytes[3]) * 256 +
-       bytes[4]) * 256 +
-       bytes[5]) * 256 +
-       bytes[6]) * 256 +
-       bytes[7];
-  this.index += 8;
-  return uint64;
-}
-
-
-Unpacker.prototype.unpack_int8 = function(){
-  var uint8 = this.unpack_uint8();
-  return (uint8 < 0x80 ) ? uint8 : uint8 - (1 << 8);
-};
-
-Unpacker.prototype.unpack_int16 = function(){
-  var uint16 = this.unpack_uint16();
-  return (uint16 < 0x8000 ) ? uint16 : uint16 - (1 << 16);
-}
-
-Unpacker.prototype.unpack_int32 = function(){
-  var uint32 = this.unpack_uint32();
-  return (uint32 < Math.pow(2, 31) ) ? uint32 :
-    uint32 - Math.pow(2, 32);
-}
-
-Unpacker.prototype.unpack_int64 = function(){
-  var uint64 = this.unpack_uint64();
-  return (uint64 < Math.pow(2, 63) ) ? uint64 :
-    uint64 - Math.pow(2, 64);
-}
-
-Unpacker.prototype.unpack_raw = function(size){
-  if ( this.length < this.index + size){
-    throw new Error('BinaryPackFailure: index is out of range'
-      + ' ' + this.index + ' ' + size + ' ' + this.length);
-  }
-  var buf = this.dataBuffer.slice(this.index, this.index + size);
-  this.index += size;
-  
-    //buf = util.bufferToString(buf);
-  
-  return buf;
-}
-
-Unpacker.prototype.unpack_string = function(size){
-  var bytes = this.read(size);
-  var i = 0, str = '', c, code;
-  while(i < size){
-    c = bytes[i];
-    if ( c < 128){
-      str += String.fromCharCode(c);
-      i++;
-    } else if ((c ^ 0xc0) < 32){
-      code = ((c ^ 0xc0) << 6) | (bytes[i+1] & 63);
-      str += String.fromCharCode(code);
-      i += 2;
-    } else {
-      code = ((c & 15) << 12) | ((bytes[i+1] & 63) << 6) |
-        (bytes[i+2] & 63);
-      str += String.fromCharCode(code);
-      i += 3;
-    }
-  }
-  this.index += size;
-  return str;
-}
-
-Unpacker.prototype.unpack_array = function(size){
-  var objects = new Array(size);
-  for(var i = 0; i < size ; i++){
-    objects[i] = this.unpack();
-  }
-  return objects;
-}
-
-Unpacker.prototype.unpack_map = function(size){
-  var map = {};
-  for(var i = 0; i < size ; i++){
-    var key  = this.unpack();
-    var value = this.unpack();
-    map[key] = value;
-  }
-  return map;
-}
-
-Unpacker.prototype.unpack_float = function(){
-  var uint32 = this.unpack_uint32();
-  var sign = uint32 >> 31;
-  var exp  = ((uint32 >> 23) & 0xff) - 127;
-  var fraction = ( uint32 & 0x7fffff ) | 0x800000;
-  return (sign == 0 ? 1 : -1) *
-    fraction * Math.pow(2, exp - 23);
-}
-
-Unpacker.prototype.unpack_double = function(){
-  var h32 = this.unpack_uint32();
-  var l32 = this.unpack_uint32();
-  var sign = h32 >> 31;
-  var exp  = ((h32 >> 20) & 0x7ff) - 1023;
-  var hfrac = ( h32 & 0xfffff ) | 0x100000;
-  var frac = hfrac * Math.pow(2, exp - 20) +
-    l32   * Math.pow(2, exp - 52);
-  return (sign == 0 ? 1 : -1) * frac;
-}
-
-Unpacker.prototype.read = function(length){
-  var j = this.index;
-  if (j + length <= this.length) {
-    return this.dataView.subarray(j, j + length);
-  } else {
-    throw new Error('BinaryPackFailure: read index out of range');
-  }
-}
-  
-function Packer (){
-  this.bufferBuilder = new BufferBuilder();
-}
-
-Packer.prototype.pack = function(value){
-  var type = typeof(value);
-  if (type == 'string'){
-    this.pack_string(value);
-  } else if (type == 'number'){
-    if (Math.floor(value) === value){
-      this.pack_integer(value);
-    } else{
-      this.pack_double(value);
-    }
-  } else if (type == 'boolean'){
-    if (value === true){
-      this.bufferBuilder.append(0xc3);
-    } else if (value === false){
-      this.bufferBuilder.append(0xc2);
-    }
-  } else if (type == 'undefined'){
-    this.bufferBuilder.append(0xc0);
-  } else if (type == 'object'){
-    if (value === null){
-      this.bufferBuilder.append(0xc0);
-    } else {
-      var constructor = value.constructor;
-      if (constructor == Array){
-        this.pack_array(value);
-      } else if (constructor == Blob || constructor == File) {
-        this.pack_bin(value);
-      } else if (constructor == ArrayBuffer) {
-        if(binaryFeatures.useArrayBufferView) {
-          this.pack_bin(new Uint8Array(value));
-        } else {
-          this.pack_bin(value);
-        }
-      } else if ('BYTES_PER_ELEMENT' in value){
-        if(binaryFeatures.useArrayBufferView) {
-          this.pack_bin(value);
-        } else {
-          this.pack_bin(value.buffer);
-        }
-      } else if (constructor == Object){
-        this.pack_object(value);
-      } else if (constructor == Date){
-        this.pack_string(value.toString());
-      } else if (typeof value.toBinaryPack == 'function'){
-        this.bufferBuilder.append(value.toBinaryPack());
-      } else {
-        throw new Error('Type "' + constructor.toString() + '" not yet supported');
-      }
-    }
-  } else {
-    throw new Error('Type "' + type + '" not yet supported');
-  }
-  return this.bufferBuilder.getBuffer();
-}
-
-
-Packer.prototype.pack_bin = function(blob){
-  var length = blob.length || blob.byteLength || blob.size;
-  if (length <= 0x0f){
-    this.pack_uint8(0xa0 + length);
-  } else if (length <= 0xffff){
-    this.bufferBuilder.append(0xda) ;
-    this.pack_uint16(length);
-  } else if (length <= 0xffffffff){
-    this.bufferBuilder.append(0xdb);
-    this.pack_uint32(length);
-  } else{
-    throw new Error('Invalid length');
-    return;
-  }
-  this.bufferBuilder.append(blob);
-}
-
-Packer.prototype.pack_string = function(str){
-  var length = str.length;
-  if (length <= 0x0f){
-    this.pack_uint8(0xb0 + length);
-  } else if (length <= 0xffff){
-    this.bufferBuilder.append(0xd8) ;
-    this.pack_uint16(length);
-  } else if (length <= 0xffffffff){
-    this.bufferBuilder.append(0xd9);
-    this.pack_uint32(length);
-  } else{
-    throw new Error('Invalid length');
-    return;
-  }
-  this.bufferBuilder.append(str);
-}
-
-Packer.prototype.pack_array = function(ary){
-  var length = ary.length;
-  if (length <= 0x0f){
-    this.pack_uint8(0x90 + length);
-  } else if (length <= 0xffff){
-    this.bufferBuilder.append(0xdc)
-    this.pack_uint16(length);
-  } else if (length <= 0xffffffff){
-    this.bufferBuilder.append(0xdd);
-    this.pack_uint32(length);
-  } else{
-    throw new Error('Invalid length');
-  }
-  for(var i = 0; i < length ; i++){
-    this.pack(ary[i]);
-  }
-}
-
-Packer.prototype.pack_integer = function(num){
-  if ( -0x20 <= num && num <= 0x7f){
-    this.bufferBuilder.append(num & 0xff);
-  } else if (0x00 <= num && num <= 0xff){
-    this.bufferBuilder.append(0xcc);
-    this.pack_uint8(num);
-  } else if (-0x80 <= num && num <= 0x7f){
-    this.bufferBuilder.append(0xd0);
-    this.pack_int8(num);
-  } else if ( 0x0000 <= num && num <= 0xffff){
-    this.bufferBuilder.append(0xcd);
-    this.pack_uint16(num);
-  } else if (-0x8000 <= num && num <= 0x7fff){
-    this.bufferBuilder.append(0xd1);
-    this.pack_int16(num);
-  } else if ( 0x00000000 <= num && num <= 0xffffffff){
-    this.bufferBuilder.append(0xce);
-    this.pack_uint32(num);
-  } else if (-0x80000000 <= num && num <= 0x7fffffff){
-    this.bufferBuilder.append(0xd2);
-    this.pack_int32(num);
-  } else if (-0x8000000000000000 <= num && num <= 0x7FFFFFFFFFFFFFFF){
-    this.bufferBuilder.append(0xd3);
-    this.pack_int64(num);
-  } else if (0x0000000000000000 <= num && num <= 0xFFFFFFFFFFFFFFFF){
-    this.bufferBuilder.append(0xcf);
-    this.pack_uint64(num);
-  } else{
-    throw new Error('Invalid integer');
-  }
-}
-
-Packer.prototype.pack_double = function(num){
-  var sign = 0;
-  if (num < 0){
-    sign = 1;
-    num = -num;
-  }
-  var exp  = Math.floor(Math.log(num) / Math.LN2);
-  var frac0 = num / Math.pow(2, exp) - 1;
-  var frac1 = Math.floor(frac0 * Math.pow(2, 52));
-  var b32   = Math.pow(2, 32);
-  var h32 = (sign << 31) | ((exp+1023) << 20) |
-      (frac1 / b32) & 0x0fffff;
-  var l32 = frac1 % b32;
-  this.bufferBuilder.append(0xcb);
-  this.pack_int32(h32);
-  this.pack_int32(l32);
-}
-
-Packer.prototype.pack_object = function(obj){
-  var keys = Object.keys(obj);
-  var length = keys.length;
-  if (length <= 0x0f){
-    this.pack_uint8(0x80 + length);
-  } else if (length <= 0xffff){
-    this.bufferBuilder.append(0xde);
-    this.pack_uint16(length);
-  } else if (length <= 0xffffffff){
-    this.bufferBuilder.append(0xdf);
-    this.pack_uint32(length);
-  } else{
-    throw new Error('Invalid length');
-  }
-  for(var prop in obj){
-    if (obj.hasOwnProperty(prop)){
-      this.pack(prop);
-      this.pack(obj[prop]);
-    }
-  }
-}
-
-Packer.prototype.pack_uint8 = function(num){
-  this.bufferBuilder.append(num);
-}
-
-Packer.prototype.pack_uint16 = function(num){
-  this.bufferBuilder.append(num >> 8);
-  this.bufferBuilder.append(num & 0xff);
-}
-
-Packer.prototype.pack_uint32 = function(num){
-  var n = num & 0xffffffff;
-  this.bufferBuilder.append((n & 0xff000000) >>> 24);
-  this.bufferBuilder.append((n & 0x00ff0000) >>> 16);
-  this.bufferBuilder.append((n & 0x0000ff00) >>>  8);
-  this.bufferBuilder.append((n & 0x000000ff));
-}
-
-Packer.prototype.pack_uint64 = function(num){
-  var high = num / Math.pow(2, 32);
-  var low  = num % Math.pow(2, 32);
-  this.bufferBuilder.append((high & 0xff000000) >>> 24);
-  this.bufferBuilder.append((high & 0x00ff0000) >>> 16);
-  this.bufferBuilder.append((high & 0x0000ff00) >>>  8);
-  this.bufferBuilder.append((high & 0x000000ff));
-  this.bufferBuilder.append((low  & 0xff000000) >>> 24);
-  this.bufferBuilder.append((low  & 0x00ff0000) >>> 16);
-  this.bufferBuilder.append((low  & 0x0000ff00) >>>  8);
-  this.bufferBuilder.append((low  & 0x000000ff));
-}
-
-Packer.prototype.pack_int8 = function(num){
-  this.bufferBuilder.append(num & 0xff);
-}
-
-Packer.prototype.pack_int16 = function(num){
-  this.bufferBuilder.append((num & 0xff00) >> 8);
-  this.bufferBuilder.append(num & 0xff);
-}
-
-Packer.prototype.pack_int32 = function(num){
-  this.bufferBuilder.append((num >>> 24) & 0xff);
-  this.bufferBuilder.append((num & 0x00ff0000) >>> 16);
-  this.bufferBuilder.append((num & 0x0000ff00) >>> 8);
-  this.bufferBuilder.append((num & 0x000000ff));
-}
-
-Packer.prototype.pack_int64 = function(num){
-  var high = Math.floor(num / Math.pow(2, 32));
-  var low  = num % Math.pow(2, 32);
-  this.bufferBuilder.append((high & 0xff000000) >>> 24);
-  this.bufferBuilder.append((high & 0x00ff0000) >>> 16);
-  this.bufferBuilder.append((high & 0x0000ff00) >>>  8);
-  this.bufferBuilder.append((high & 0x000000ff));
-  this.bufferBuilder.append((low  & 0xff000000) >>> 24);
-  this.bufferBuilder.append((low  & 0x00ff0000) >>> 16);
-  this.bufferBuilder.append((low  & 0x0000ff00) >>>  8);
-  this.bufferBuilder.append((low  & 0x000000ff));
-}
-/**
- * Light EventEmitter. Ported from Node.js/events.js
- * Eric Zhang
- */
-
-/**
- * EventEmitter class
- * Creates an object with event registering and firing methods
- */
-function EventEmitter() {
-  // Initialise required storage variables
-  this._events = {};
-}
-
-var isArray = Array.isArray;
-
-
-EventEmitter.prototype.addListener = function(type, listener, scope, once) {
-  if ('function' !== typeof listener) {
-    throw new Error('addListener only takes instances of Function');
-  }
-  
-  // To avoid recursion in the case that type == "newListeners"! Before
-  // adding it to the listeners, first emit "newListeners".
-  this.emit('newListener', type, typeof listener.listener === 'function' ?
-            listener.listener : listener);
-            
-  if (!this._events[type]) {
-    // Optimize the case of one listener. Don't need the extra array object.
-    this._events[type] = listener;
-  } else if (isArray(this._events[type])) {
-
-    // If we've already got an array, just append.
-    this._events[type].push(listener);
-
-  } else {
-    // Adding the second element, need to change to array.
-    this._events[type] = [this._events[type], listener];
-  }
-  
-};
-
-EventEmitter.prototype.on = EventEmitter.prototype.addListener;
-
-EventEmitter.prototype.once = function(type, listener, scope) {
-  if ('function' !== typeof listener) {
-    throw new Error('.once only takes instances of Function');
-  }
-
-  var self = this;
-  function g() {
-    self.removeListener(type, g);
-    listener.apply(this, arguments);
-  };
-
-  g.listener = listener;
-  self.on(type, g);
-
-  return this;
-};
-
-EventEmitter.prototype.removeListener = function(type, listener, scope) {
-  if ('function' !== typeof listener) {
-    throw new Error('removeListener only takes instances of Function');
-  }
-
-  // does not use listeners(), so no side effect of creating _events[type]
-  if (!this._events[type]) return this;
-
-  var list = this._events[type];
-
-  if (isArray(list)) {
-    var position = -1;
-    for (var i = 0, length = list.length; i < length; i++) {
-      if (list[i] === listener ||
-          (list[i].listener && list[i].listener === listener))
-      {
-        position = i;
-        break;
-      }
-    }
-
-    if (position < 0) return this;
-    list.splice(position, 1);
-    if (list.length == 0)
-      delete this._events[type];
-  } else if (list === listener ||
-             (list.listener && list.listener === listener))
-  {
-    delete this._events[type];
-  }
-
-  return this;
-};
-
-
-EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
-
-
-EventEmitter.prototype.removeAllListeners = function(type) {
-  if (arguments.length === 0) {
-    this._events = {};
-    return this;
-  }
-
-  // does not use listeners(), so no side effect of creating _events[type]
-  if (type && this._events && this._events[type]) this._events[type] = null;
-  return this;
-};
-
-EventEmitter.prototype.listeners = function(type) {
-  if (!this._events[type]) this._events[type] = [];
-  if (!isArray(this._events[type])) {
-    this._events[type] = [this._events[type]];
-  }
-  return this._events[type];
-};
-
-EventEmitter.prototype.emit = function(type) {
-  var type = arguments[0];
-  var handler = this._events[type];
-  if (!handler) return false;
-
-  if (typeof handler == 'function') {
-    switch (arguments.length) {
-      // fast cases
-      case 1:
-        handler.call(this);
-        break;
-      case 2:
-        handler.call(this, arguments[1]);
-        break;
-      case 3:
-        handler.call(this, arguments[1], arguments[2]);
-        break;
-      // slower
-      default:
-        var l = arguments.length;
-        var args = new Array(l - 1);
-        for (var i = 1; i < l; i++) args[i - 1] = arguments[i];
-        handler.apply(this, args);
-    }
-    return true;
-
-  } else if (isArray(handler)) {
-    var l = arguments.length;
-    var args = new Array(l - 1);
-    for (var i = 1; i < l; i++) args[i - 1] = arguments[i];
-
-    var listeners = handler.slice();
-    for (var i = 0, l = listeners.length; i < l; i++) {
-      listeners[i].apply(this, args);
-    }
-    return true;
-  } else {
-    return false;
-  }
-};
-
-
-
-var util = {
-  
-  debug: false,
-  browserisms: '',
-  
-  inherits: function(ctor, superCtor) {
-    ctor.super_ = superCtor;
-    ctor.prototype = Object.create(superCtor.prototype, {
-      constructor: {
-        value: ctor,
-        enumerable: false,
-        writable: true,
-        configurable: true
-      }
-    });
-  },
-  extend: function(dest, source) {
-    for(var key in source) {
-      if(source.hasOwnProperty(key)) {
-        dest[key] = source[key];
-      }
-    }
-    return dest;
-  },
-  pack: BinaryPack.pack,
-  unpack: BinaryPack.unpack,
-  randomPort: function() {
-    return Math.round(Math.random() * 60535) + 5000;
-  },
-  
-  log: function () {
-    if (util.debug) {
-      var copy = [];
-      for (var i = 0; i < arguments.length; i++) {
-        copy[i] = arguments[i];
-      }
-      copy.unshift('PeerJS: ');
-      console.log.apply(console, copy);
-    }
-  },
-
-  setZeroTimeout: (function(global) {
-    var timeouts = [];
-    var messageName = 'zero-timeout-message';
-
-    // Like setTimeout, but only takes a function argument.	 There's
-    // no time argument (always zero) and no arguments (you have to
-    // use a closure).
-    function setZeroTimeoutPostMessage(fn) {
-      timeouts.push(fn);
-      global.postMessage(messageName, '*');
-    }		
-
-    function handleMessage(event) {
-      if (event.source == global && event.data == messageName) {
-        if (event.stopPropagation) {
-          event.stopPropagation();
-        }
-        if (timeouts.length) {
-          timeouts.shift()();
-        }
-      }
-    }
-    if (global.addEventListener) {
-      global.addEventListener('message', handleMessage, true);
-    } else if (global.attachEvent) {
-      global.attachEvent('onmessage', handleMessage);
-    }
-    return setZeroTimeoutPostMessage;
-  }(this)),
-  
-  blobToArrayBuffer: function(blob, cb){
-    var fr = new FileReader();
-    fr.onload = function(evt) {
-      cb(evt.target.result);
-    };
-    fr.readAsArrayBuffer(blob);
-  },
-  blobToBinaryString: function(blob, cb){
-    var fr = new FileReader();
-    fr.onload = function(evt) {
-      cb(evt.target.result);
-    };
-    fr.readAsBinaryString(blob);
-  },
-  binaryStringToArrayBuffer: function(binary) {
-    var byteArray = new Uint8Array(binary.length);
-    for (var i = 0; i < binary.length; i++) {
-      byteArray[i] = binary.charCodeAt(i) & 0xff;
-    }
-    return byteArray.buffer;
-  }
-};
-var RTCPeerConnection = null;
-var getUserMedia = null;
-var attachMediaStream = null;
-
-if (navigator.mozGetUserMedia) {
-  util.browserisms = 'Firefox'
-
-  RTCPeerConnection = mozRTCPeerConnection;
-  getUserMedia = navigator.mozGetUserMedia.bind(navigator);
-} else if (navigator.webkitGetUserMedia) {
-  util.browserisms = 'Webkit'
-
-  RTCPeerConnection = webkitRTCPeerConnection;
-  getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
-}
-
-exports.RTCPeerConnection = RTCPeerConnection;
-exports.getUserMedia = getUserMedia;
-/**
- * A peer who can initiate connections with other peers.
- */
-function Peer(id, options) {
-  if (id.constructor == Object) {
-    options = id;
-    id = undefined;
-  }
-  if (!(this instanceof Peer)) return new Peer(options);
-  EventEmitter.call(this);
-
-  options = util.extend({
-    debug: false,
-    host: '0.peerjs.com',
-    config: { 'iceServers': [{ 'url': 'stun:stun.l.google.com:19302' }] },
-    port: 9000
-  }, options);
-  this._options = options;
-  util.debug = options.debug;
-
-  this._server = options.host + ':' + options.port;
-
-  // Ensure alphanumeric_-
-  if (id && !/^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$/.exec(id)) {
-    throw new Error('Peer ID can only contain alphanumerics, "_", and "-".');
-  }
-  if (options.key && !/^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$/.exec(options.key)) {
-    throw new Error('API key can only contain alphanumerics, "_", and "-".');
-  }
-
-  this.id = id;
-  // Not used unless using cloud server.
-  this._key = options.key;
-
-  this._startSocket();
-
-  // Connections for this peer.
-  this.connections = {};
-
-  // Queued connections to make.
-  this._queued = [];
-};
-
-util.inherits(Peer, EventEmitter);
-
-Peer.prototype._startSocket = function() {
-  var self = this;
-  this._socket = new Socket(this._server, this.id, this._key);
-  this._socket.on('message', function(data) {
-    self._handleServerJSONMessage(data);
-  });
-  this._socket.on('error', function(error) {
-    util.log(error);
-    self.emit('error', error);
-    self.destroy();
-  });
-  this._socket.on('close', function() {
-    var msg = 'Underlying socket has closed';
-    util.log('error', msg);
-    self.emit('error', msg);
-    self.destroy();
-  });
-  this._socket.start();
-}
-
-
-Peer.prototype._handleServerJSONMessage = function(message) {
-  var peer = message.src;
-  var connection = this.connections[peer];
-  switch (message.type) {
-    case 'OPEN':
-      if (!this.id) {
-        // If we're just now getting an ID then we may have a queue.
-        this.id = message.id;
-      }
-      this.emit('open', this.id);
-      this._processQueue();
-      break;
-    case 'ERROR':
-      this.emit('error', message.msg);
-      util.log(message.msg);
-      break;
-    case 'ID-TAKEN':
-      this.emit('error', 'ID `'+this.id+'` is taken');
-      this.destroy();
-      break;
-    case 'OFFER':
-      var options = {
-        metadata: message.metadata,
-        sdp: message.sdp,
-        config: this._options.config,
-      };
-      var connection = new DataConnection(this.id, peer, this._socket, options);
-      this._attachConnectionListeners(connection);
-      this.connections[peer] = connection;
-      this.emit('connection', connection, message.metadata);
-      break;
-    case 'EXPIRE':
-      connection = this.connections[message.expired];
-      if (connection) {
-        connection.close();
-        connection.emit('Could not connect to peer ' + connection.peer);
-      }
-      break;
-    case 'ANSWER':
-      if (connection) {
-        connection.handleSDP(message);
-      }
-      break;
-    case 'CANDIDATE':
-      if (connection) {
-        connection.handleCandidate(message);
-      }
-      break;
-    case 'LEAVE':
-      if (connection) {
-        connection.handleLeave();
-      }
-      break;
-    case 'INVALID-KEY':
-      this.emit('error', 'API KEY "' + this._key + '" is invalid');
-      this.destroy();
-      break;
-    case 'PORT':
-      //if (util.browserisms === 'Firefox') {
-      //  connection.handlePort(message);
-      //  break;
-      //}
-    default:
-      util.log('Unrecognized message type:', message.type);
-      break;
-  }
-};
-
-/** Process queued calls to connect. */
-Peer.prototype._processQueue = function() {
-  while (this._queued.length > 0) {
-    var conn = this._queued.pop();
-    conn.initialize(this.id);
-  }
-};
-
-
-Peer.prototype._cleanup = function() {
-  var self = this;
-  var peers = Object.keys(this.connections);
-  for (var i = 0, ii = peers.length; i < ii; i++) {
-    this.connections[peers[i]].close();
-  }
-  util.setZeroTimeout(function(){
-    self._socket.close();
-  });
-  this.emit('close');
-};
-
-/** Listeners for DataConnection events. */
-Peer.prototype._attachConnectionListeners = function(connection) {
-  var self = this;
-  connection.on('close', function(peer) {
-    if (self.connections[peer]) { 
-      delete self.connections[peer]; 
-    }
-  });
-};
-
-
-
-/** Exposed connect function for users. Will try to connect later if user
- * is waiting for an ID. */
-// TODO: pause XHR streaming when not in use and start again when this is
-// called.
-Peer.prototype.connect = function(peer, metadata, options) {
-  options = util.extend({
-    metadata: metadata,
-    config: this._options.config,
-  }, options);
-
-  var connection = new DataConnection(this.id, peer, this._socket, options);
-  this._attachConnectionListeners(connection);
-
-  this.connections[peer] = connection;
-  if (!this.id) {
-    this._queued.push(connection);
-  }
-  return connection;
-};
-
-Peer.prototype.destroy = function() {
-  this._cleanup();
-};
-
-
-exports.Peer = Peer;
-/**
- * A DataChannel|PeerConnection between two Peers.
- */
-function DataConnection(id, peer, socket, options) {
-  if (!(this instanceof DataConnection)) return new DataConnection(options);
-  EventEmitter.call(this);
-
-  options = util.extend({
-    config: { 'iceServers': [{ 'url': 'stun:stun.l.google.com:19302' }] },
-    reliable: false
-  }, options);
-  this._options = options;
-
-  // Connection is not open yet.
-  this.open = false;
-
-  this.id = id;
-  this.peer = peer;
-  this.metadata = options.metadata;
-
-  this._socket = socket;
-  this._sdp = options.sdp;
-
-  if (!!this.id) {
-    this.initialize();
-  }
-};
-
-util.inherits(DataConnection, EventEmitter);
-
-DataConnection.prototype.initialize = function(id) {
-  if (!!id) {
-    this.id = id;
-  }
-  // Firefoxism: connectDataConnection ports.
-  /*if (util.browserisms === 'Firefox') {
-    this._firefoxPortSetup();
-  }*/
-
-  // Set up PeerConnection.
-  this._startPeerConnection();
-
-  // Listen for ICE candidates
-  this._setupIce();
-
-  // Listen for negotiation needed
-  // ** Chrome only.
-  if (util.browserisms !== 'Firefox' && !!this.id) {
-    this._setupOffer();
-  }
-
-  // Listen for or create a data channel
-  this._setupDataChannel();
-
-  var self = this;
-  if (!!this._sdp) {
-    this.handleSDP({ type: 'OFFER', sdp: this._sdp });
-  }
-
-  // Makes offer if Firefox
-  /*if (util.browserisms === 'Firefox') {
-    this._firefoxAdditional();
-  }*/
-
-  // No-op this.
-  this.initialize = function() {};
-}
-
-
-DataConnection.prototype._setupOffer = function() {
-  var self = this;
-  util.log('Listening for `negotiationneeded`');
-  this._pc.onnegotiationneeded = function() {
-    util.log('`negotiationneeded` triggered');
-    self._makeOffer();
-  };
-}
-
-
-DataConnection.prototype._setupDataChannel = function() {
-  var self = this;
-  if (this._originator) {
-    util.log('Creating data channel');
-    this._dc = this._pc.createDataChannel(this.peer, { reliable: this._options.reliable });
-    this._configureDataChannel();
-  } else {
-    util.log('Listening for data channel');
-    this._pc.ondatachannel = function(evt) {
-      util.log('Received data channel');
-      self._dc = evt.channel;
-      self._configureDataChannel();
-    };
-  }
-};
-
-
-/** Starts a PeerConnection and sets up handlers. */
-DataConnection.prototype._startPeerConnection = function() {
-  util.log('Creating RTCPeerConnection');
-  this._pc = new RTCPeerConnection(this._options.config, { optional:[ { RtpDataChannels: true } ]});
-};
-
-
-/** Takes care of ice handlers. */
-DataConnection.prototype._setupIce = function() {
-  util.log('Listening for ICE candidates');
-  var self = this;
-  this._pc.onicecandidate = function(evt) {
-    if (evt.candidate) {
-      util.log('Received ICE candidates');
-      self._socket.send({
-        type: 'CANDIDATE',
-        candidate: evt.candidate,
-        dst: self.peer,
-        src: self.id
-      });
-    }
-  };
-};
-
-
-/*DataConnection.prototype._firefoxPortSetup = function() {
-  if (!DataConnection.usedPorts) {
-    DataConnection.usedPorts = [];
-  }
-  this.localPort = util.randomPort();
-  while (DataConnection.usedPorts.indexOf(this.localPort) != -1) {
-    this.localPort = util.randomPort();
-  }
-  this.remotePort = util.randomPort();
-  while (this.remotePort === this.localPort ||
-      DataConnection.usedPorts.indexOf(this.localPort) != -1) {
-    this.remotePort = util.randomPort();
-  }
-  DataConnection.usedPorts.push(this.remotePort);
-  DataConnection.usedPorts.push(this.localPort);
-}*/
-
-DataConnection.prototype._configureDataChannel = function() {
-  var self = this;
-  
-  if (util.browserisms !== 'Webkit') {
-    this._dc.binaryType = 'arraybuffer';
-  }
-  this._dc.onopen = function() {
-    util.log('Data channel connection success');
-    self.open = true;
-    self.emit('open');
-  };
-  this._dc.onmessage = function(e) {
-    self._handleDataMessage(e);
-  };
-  this._dc.onclose = function(e) {
-    self.emit('close');
-  };
-};
-
-
-/** Decide whether to handle Firefoxisms. */
-/*DataConnection.prototype._firefoxAdditional = function() {
-  var self = this;
-  getUserMedia({ audio: true, fake: true }, function(s) {
-    self._pc.addStream(s);
-    if (self._originator) {
-      self._makeOffer();
-    }
-  }, function(err) { util.log('Could not getUserMedia'); });
-};*/
-
-DataConnection.prototype._makeOffer = function() {
-  var self = this;
-  this._pc.createOffer(function(offer) {
-    util.log('Created offer');
-    self._pc.setLocalDescription(offer, function() {
-      util.log('Set localDescription to offer');
-      self._socket.send({
-        type: 'OFFER',
-        sdp: offer,
-        dst: self.peer,
-        src: self.id,
-        metadata: self.metadata
-      });
-    }, function(err) {
-      self.emit('error', 'Failed to setLocalDescription');
-      util.log('Failed to setLocalDescription, ', err);
-    });
-  });
-};
-
-/** Create an answer for PC. */
-DataConnection.prototype._makeAnswer = function() {
-  var self = this;
-  this._pc.createAnswer(function(answer) {
-    util.log('Created answer');
-    self._pc.setLocalDescription(answer, function() {
-      util.log('Set localDescription to answer');
-      self._socket.send({
-        type: 'ANSWER',
-        src: self.id,
-        sdp: answer,
-        dst: self.peer
-      });
-    }, function(err) {
-      self.emit('error', 'Failed to setLocalDescription');
-      util.log('Failed to setLocalDescription, ', err)
-    });
-  }, function(err) {
-    self.emit('error', 'Failed to create answer');
-    util.log('Failed to create answer, ', err)
-  });
-};
-
-
-DataConnection.prototype._cleanup = function() {
-  if (!!this._dc && this._dc.readyState != 'closed') {
-    this._dc.close();
-    this._dc = null;
-  }
-  if (!!this._pc && this._pc.readyState != 'closed') {
-    this._pc.close();
-    this._pc = null;
-  }
-};
-
-
-// Handles a DataChannel message.
-DataConnection.prototype._handleDataMessage = function(e) {
-  var self = this;
-  if (e.data.constructor === Blob) {
-    util.blobToArrayBuffer(e.data, function(ab) {
-      var data = BinaryPack.unpack(ab);
-      self.emit('data', data);
-    });
-  } else if (e.data.constructor === ArrayBuffer) {
-      var data = BinaryPack.unpack(e.data);
-      self.emit('data', data);
-  } else if (e.data.constructor === String) {
-      var ab = util.binaryStringToArrayBuffer(e.data);
-      var data = BinaryPack.unpack(ab);
-      self.emit('data', data);
-  }
-};
-
-
-/**
- * Exposed functionality for users.
- */
-
-/** Allows user to close connection. */
-DataConnection.prototype.close = function() {
-  this._cleanup();
-  var self = this;
-  if (this.open) {
-    this._socket.send({
-      type: 'LEAVE',
-      dst: self.peer,
-      src: self.id,
-    });
-  }
-  this.open = false;
-  this.emit('close', this.peer);
-};
-
-
-/** Allows user to send data. */
-DataConnection.prototype.send = function(data) {
-  var self = this;
-  var blob = BinaryPack.pack(data);
-  if (util.browserisms === 'Webkit') {
-    util.blobToBinaryString(blob, function(str){
-      self._dc.send(str);
-    });
-  } else {
-    this._dc.send(blob);
-  }
-};
-
-DataConnection.prototype.handleSDP = function(message) {
-  var sdp = message.sdp;
-  if (util.browserisms != 'Firefox') {
-    sdp = new RTCSessionDescription(sdp);
-  }
-  var self = this;
-  this._pc.setRemoteDescription(sdp, function() {
-    util.log('Set remoteDescription: ' + message.type);
-    // Firefoxism
-    if (message.type === 'ANSWER' && util.browserisms === 'Firefox') {
-      self._pc.connectDataConnection(self.localPort, self.remotePort);
-      self._socket.send({
-        type: 'PORT',
-        dst: self.peer,
-        src: self.id,
-        remote: self.localPort,
-        local: self.remotePort
-      });
-    } else if (message.type === 'OFFER') {
-      self._makeAnswer();
-    }
-  }, function(err) {
-    self.emit('error', 'Failed to setRemoteDescription');
-    util.log('Failed to setRemoteDescription, ', err);
-  });
-};
-
-
-DataConnection.prototype.handleCandidate = function(message) {
-  var candidate = new RTCIceCandidate(message.candidate);
-  this._pc.addIceCandidate(candidate);
-  util.log('Added ice candidate');
-};
-
-
-DataConnection.prototype.handleLeave = function() {
-  util.log('Peer ' + this.peer + ' disconnected');
-  this.close();
-};
-
-/*
-DataConnection.prototype.handlePort = function(message) {
-  if (!DataConnection.usedPorts) {
-    DataConnection.usedPorts = [];
-  }
-  DataConnection.usedPorts.push(message.local);
-  DataConnection.usedPorts.push(message.remote);
-  this._pc.connectDataConnection(message.local, message.remote);
-};
-*/
-
-/**
- * An abstraction on top of WebSockets and XHR streaming to provide fastest
- * possible connection for peers.
- */
-function Socket(server, id, key) {
-  if (!(this instanceof Socket)) return new Socket(server, id, key);
-  EventEmitter.call(this);
-
-  this._id = id;
-  this._server = server;
-  this._httpUrl = 'http://' + this._server;
-  this._key = key;
-};
-
-util.inherits(Socket, EventEmitter);
-
-/** Check in with ID or get one from server. */
-Socket.prototype._checkIn = function() {
-  // If no ID provided, get a unique ID from server.
-  var self = this;
-  if (!this._id) {
-    try {
-      var http = new XMLHttpRequest();
-      var url = this._httpUrl;
-      // Set API key if necessary.
-      if (!!this._key) {
-        url += '/' + this._key;
-      }
-      url += '/id';
-
-      // If there's no ID we need to wait for one before trying to init socket.
-      http.open('get', url, true);
-      http.onreadystatechange = function() {
-        if (!self._id && http.readyState > 2 && !!http.responseText) {
-          try {
-            var response = JSON.parse(http.responseText.split('\n').shift());
-            if (!!response.id) {
-              self._id = response.id;
-              self._startWebSocket();
-              self.emit('message', { type: 'OPEN', id: self._id });
-            }
-          } catch (e) {
-            self._startWebSocket();
-          }
-        }
-        self._handleStream(http, true);
-      };
-      http.send(null);
-    } catch(e) {
-      util.log('XMLHttpRequest not available; defaulting to WebSockets');
-      this._startWebSocket();
-    }
-  } else {
-    this._startXhrStream();
-    this._startWebSocket();
-  }
-};
-
-
-/** Start up websocket communications. */
-Socket.prototype._startWebSocket = function() {
-  if (!!this._socket) {
-    return;
-  }
-
-  var wsurl = 'ws://' + this._server + '/ws';
-  if (!!this._id) {
-    wsurl += '?id=' + this._id;
-    if (!!this._key) {
-      wsurl += '&key=' + this._key;
-    }
-  } else if (!!this._key) {
-    wsurl += '?key=' + this._key;
-  }
-  this._socket = new WebSocket(wsurl);
-
-  var self = this;
-  this._socket.onmessage = function(event) {
-    var data;
-    try {
-      data = JSON.parse(event.data);
-    } catch(e) {
-      data = event.data;
-    }
-    if (data.constructor == Object) {
-      self.emit('message', data);
-    } else {
-      util.log('Invalid server message', event.data);
-    }
-  };
-
-  // Take care of the queue of connections if necessary and make sure Peer knows
-  // socket is open.
-  this._socket.onopen = function() {
-    util.log('Socket open');
-    if (self._id) {
-      self.emit('open');
-    }
-  };
-};
-
-
-/** Start XHR streaming. */
-Socket.prototype._startXhrStream = function() {
-  try {
-    var self = this;
-
-    var http = new XMLHttpRequest();
-    var url = this._httpUrl;
-    // Set API key if necessary.
-    if (!!this._key) {
-      url += '/' + this._key;
-    }
-    url += '/id';
-    http.open('post', url, true);
-    http.setRequestHeader('Content-Type', 'application/json');
-    http.onreadystatechange = function() {
-      self._handleStream(http);
-    };
-    http.send(JSON.stringify({ id: this._id }));
-  } catch(e) {
-    util.log('XMLHttpRequest not available; defaulting to WebSockets');
-  }
-};
-
-
-/** Handles onreadystatechange response as a stream. */
-Socket.prototype._handleStream = function(http, pad) {
-  // 3 and 4 are loading/done state. All others are not relevant.
-  if (http.readyState < 3) {
-    return;
-  } else if (http.readyState == 3 && http.status != 200) {
-    return;
-  }
-
-  if (this._index === undefined) {
-    this._index = pad ? 2 : 1;
-  }
-  
-  if (http.responseText === null) {
-    return;
-  }
-  
-  var message = http.responseText.split('\n')[this._index];
-  if (!!message && http.readyState == 3) {
-    this._index += 1;
-    try {
-      this._handleHTTPErrors(JSON.parse(message));
-    } catch(e) {
-      util.log('Invalid server message', message);
-    }
-  } else if (http.readyState == 4) {
-    this._index = 1;
-  }
-};
-
-
-Socket.prototype._handleHTTPErrors = function(message) {
-  switch (message.type) {
-    // XHR stream closed by timeout.
-    case 'HTTP-END':
-      util.log('XHR stream timed out.');
-      if (!!this._socket && this._socket.readyState != 1) {
-        this._startXhrStream();
-      }
-      break;
-    // XHR stream closed by socket connect.
-    case 'HTTP-SOCKET':
-      util.log('XHR stream closed, WebSocket connected.');
-      break;
-    case 'HTTP-ERROR':
-      util.log('XHR ended in error or the websocket connected first.');
-      break;
-    default:
-      this.emit('message', message);
-  }
-};
-
-
-
-/** Exposed send for DC & Peer. */
-Socket.prototype.send = function(data) {
-  var type = data.type;
-  message = JSON.stringify(data);
-  if (!type) {
-    this.emit('error', 'Invalid message');
-  }
-
-  if (!!this._socket && this._socket.readyState == 1) {
-    this._socket.send(message);
-  } else {
-    var self = this;
-    var http = new XMLHttpRequest();
-    var url = this._httpUrl;
-
-    // Set API key if necessary.
-    if (!!this._key) {
-      url += '/' + this._key;
-    }
-    url += '/' + type.toLowerCase();
-
-    http.open('post', url, true);
-    http.setRequestHeader('Content-Type', 'application/json');
-    http.send(message);
-  }
-};
-
-Socket.prototype.close = function() {
-  if (!!this._socket && this._socket.readyState == 1) {
-    this._socket.close();
-  }
-};
-
-Socket.prototype.start = function() {
-  this._checkIn();
-};
-
-})(this);

+ 0 - 38
demo/static/peer1.html

@@ -1,38 +0,0 @@
-<!DOCTYPE HTML> 
-<html lang="en"> 
-<head>
-<title>Peer Test</title>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
-<meta http-equiv="Content-Language" content="en-us"> 
-<meta name="description" content=""> 
-<meta name="keywords" content=""> 
-
-<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> 
-<script type="text/javascript" src="/peer.js"></script>
-<script>
-$(document).ready(function() {
-  $('#connect').click(function() {
-    var source = $('#source').val();
-
-    sink = new Peer({ key: '3lcmbh31bezpk3xr', host: 'localhost', port: '9000', debug: true });
-    connection = sink.connect(source, { username: 'michelle_spoof' })
-    connection.on('data', function(data) {
-      console.log(data);
-      connection.send('Hi there!');
-    });
-  });
-
-});
-
-</script>
-
-</head> 
- 
-<body> 
-  This is a P2P peer.
-  <br><br>
-  Enter source ID to connect to:
-  <br><input type="text" id="source"></input>
-  <button id="connect">Connect</button>
-</body> 
-</html>