Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

fixed a few bugs with leaving and closing connection

  • Loading branch information...
commit 24dffda33d7558f54af9618dc8a22ccb48186a94 1 parent c9c51e1
@michelle michelle authored
View
10 demo/static/peer.js
@@ -1038,7 +1038,10 @@ Peer.prototype._handleServerMessage = function(message) {
if (connection) connection.handleCandidate(message);
break;
case 'LEAVE':
- if (connection) connection.handleLeave();
+ if (connection) {
+ connection.handleLeave();
+ delete this.connections[peer];
+ }
break;
case 'PORT':
if (util.browserisms === 'Firefox') {
@@ -1061,6 +1064,7 @@ Peer.prototype._processQueue = function() {
Peer.prototype._cleanup = function() {
+ this._socket.send(JSON.stringify({ type: 'LEAVE', src: this._id }));
for (var peer in this.connections) {
if (this.connections.hasOwnProperty(peer)) {
this.connections[peer].close();
@@ -1089,6 +1093,10 @@ Peer.prototype.connect = function(peer, metadata, cb) {
this.connections[peer] = connection;
};
+Peer.prototype.leave = function() {
+ this._cleanup();
+};
+
exports.Peer = Peer;
View
10 dist/peer.js
@@ -1038,7 +1038,10 @@ Peer.prototype._handleServerMessage = function(message) {
if (connection) connection.handleCandidate(message);
break;
case 'LEAVE':
- if (connection) connection.handleLeave();
+ if (connection) {
+ connection.handleLeave();
+ delete this.connections[peer];
+ }
break;
case 'PORT':
if (util.browserisms === 'Firefox') {
@@ -1061,6 +1064,7 @@ Peer.prototype._processQueue = function() {
Peer.prototype._cleanup = function() {
+ this._socket.send(JSON.stringify({ type: 'LEAVE', src: this._id }));
for (var peer in this.connections) {
if (this.connections.hasOwnProperty(peer)) {
this.connections[peer].close();
@@ -1089,6 +1093,10 @@ Peer.prototype.connect = function(peer, metadata, cb) {
this.connections[peer] = connection;
};
+Peer.prototype.leave = function() {
+ this._cleanup();
+};
+
exports.Peer = Peer;
View
2  dist/peer.min.js
@@ -1 +1 @@
-/*! peerjs.min.js build:0.0.1, production. Copyright(c) 2013 Michelle Bu <michelle@michellebu.com> */(function(e){function n(){this._pieces=[],this._parts=[]}function r(e){this.index=0,this.dataBuffer=e,this.dataView=new Uint8Array(this.dataBuffer),this.length=this.dataBuffer.byteLength}function i(){this.bufferBuilder=new n}function s(){this._events={}}function c(e){if(!(this instanceof c))return new c(e);s.call(this),e=u.extend({debug:!1,host:"localhost",protocol:"http",config:{iceServers:[{url:"stun:stun.l.google.com:19302"}]},port:80},e),this.options=e,u.debug=e.debug,this._server=e.host+":"+e.port,this._httpUrl=e.protocol+"://"+this._server,this._config=e.config;if(e.id&&!/^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$/.exec(e.id))throw new Error('Peer ID can only contain alphanumerics, "_", and "-".');this._id=e.id,this._apikey=e.apikey,this._checkIn(),this.connections={},this._queued=[],window.onbeforeunload=this._cleanup}function h(e,t,n,r,i,o){if(!(this instanceof h))return new h(o);s.call(this),o=u.extend({socketOpen:!1},o),this.options=o,this._id=e,this._peer=t,this._originator=o.sdp===undefined,this._cb=i,this._httpUrl=r,this.metadata=o.metadata,this._socketOpen=o.socketOpen,this._socket=n,u.browserisms==="Firefox"&&this._firefoxPortSetup(),this._startPeerConnection(),this._setupIce(),u.browserisms==="Webkit"&&this._setupOffer(),this._setupDataChannel();var a=this;o.sdp&&(this.handleSDP({type:"OFFER",sdp:o.sdp}),u.browserisms!=="Firefox"&&this._makeAnswer()),u.browserisms==="Firefox"&&this._firefoxAdditional()}var t={};t.useBlobBuilder=function(){try{return new Blob([]),!1}catch(e){return!0}}(),t.useArrayBufferView=!t.useBlobBuilder&&function(){try{return(new Blob([new Uint8Array([])])).size===0}catch(e){return!0}}(),t.supportsBinaryWebsockets=function(){try{var e=new WebSocket("ws://null");return e.onerror=function(){},typeof e.binaryType!="undefined"?!0:!1}catch(t){return!1}}(),e.binaryFeatures=t,e.BlobBuilder=window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder||window.BlobBuilder,n.prototype.append=function(e){typeof e=="number"?this._pieces.push(e):(this._flush(),this._parts.push(e))},n.prototype._flush=function(){if(this._pieces.length>0){var e=new Uint8Array(this._pieces);t.useArrayBufferView||(e=e.buffer),this._parts.push(e),this._pieces=[]}},n.prototype.getBuffer=function(){this._flush();if(t.useBlobBuilder){var e=new BlobBuilder;for(var n=0,r=this._parts.length;n<r;n++)e.append(this._parts[n]);return e.getBlob()}return new Blob(this._parts)},e.BinaryPack={unpack:function(e){var t=new r(e);return t.unpack()},pack:function(e){var t=new i,n=t.pack(e);return n}},r.prototype.unpack=function(){var e=this.unpack_uint8();if(e<128){var t=e;return t}if((e^224)<32){var n=(e^224)-32;return n}var r;if((r=e^160)<=15)return this.unpack_raw(r);if((r=e^176)<=15)return this.unpack_string(r);if((r=e^144)<=15)return this.unpack_array(r);if((r=e^128)<=15)return this.unpack_map(r);switch(e){case 192:return null;case 193:return undefined;case 194:return!1;case 195:return!0;case 202:return this.unpack_float();case 203:return this.unpack_double();case 204:return this.unpack_uint8();case 205:return this.unpack_uint16();case 206:return this.unpack_uint32();case 207:return this.unpack_uint64();case 208:return this.unpack_int8();case 209:return this.unpack_int16();case 210:return this.unpack_int32();case 211:return this.unpack_int64();case 212:return undefined;case 213:return undefined;case 214:return undefined;case 215:return undefined;case 216:return r=this.unpack_uint16(),this.unpack_string(r);case 217:return r=this.unpack_uint32(),this.unpack_string(r);case 218:return r=this.unpack_uint16(),this.unpack_raw(r);case 219:return r=this.unpack_uint32(),this.unpack_raw(r);case 220:return r=this.unpack_uint16(),this.unpack_array(r);case 221:return r=this.unpack_uint32(),this.unpack_array(r);case 222:return r=this.unpack_uint16(),this.unpack_map(r);case 223:return r=this.unpack_uint32(),this.unpack_map(r)}},r.prototype.unpack_uint8=function(){var e=this.dataView[this.index]&255;return this.index++,e},r.prototype.unpack_uint16=function(){var e=this.read(2),t=(e[0]&255)*256+(e[1]&255);return this.index+=2,t},r.prototype.unpack_uint32=function(){var e=this.read(4),t=((e[0]*256+e[1])*256+e[2])*256+e[3];return this.index+=4,t},r.prototype.unpack_uint64=function(){var e=this.read(8),t=((((((e[0]*256+e[1])*256+e[2])*256+e[3])*256+e[4])*256+e[5])*256+e[6])*256+e[7];return this.index+=8,t},r.prototype.unpack_int8=function(){var e=this.unpack_uint8();return e<128?e:e-256},r.prototype.unpack_int16=function(){var e=this.unpack_uint16();return e<32768?e:e-65536},r.prototype.unpack_int32=function(){var e=this.unpack_uint32();return e<Math.pow(2,31)?e:e-Math.pow(2,32)},r.prototype.unpack_int64=function(){var e=this.unpack_uint64();return e<Math.pow(2,63)?e:e-Math.pow(2,64)},r.prototype.unpack_raw=function(e){if(this.length<this.index+e)throw new Error("BinaryPackFailure: index is out of range "+this.index+" "+e+" "+this.length);var t=this.dataBuffer.slice(this.index,this.index+e);return this.index+=e,t},r.prototype.unpack_string=function(e){var t=this.read(e),n=0,r="",i,s;while(n<e)i=t[n],i<128?(r+=String.fromCharCode(i),n++):(i^192)<32?(s=(i^192)<<6|t[n+1]&63,r+=String.fromCharCode(s),n+=2):(s=(i&15)<<12|(t[n+1]&63)<<6|t[n+2]&63,r+=String.fromCharCode(s),n+=3);return this.index+=e,r},r.prototype.unpack_array=function(e){var t=new Array(e);for(var n=0;n<e;n++)t[n]=this.unpack();return t},r.prototype.unpack_map=function(e){var t={};for(var n=0;n<e;n++){var r=this.unpack(),i=this.unpack();t[r]=i}return t},r.prototype.unpack_float=function(){var e=this.unpack_uint32(),t=e>>31,n=(e>>23&255)-127,r=e&8388607|8388608;return(t==0?1:-1)*r*Math.pow(2,n-23)},r.prototype.unpack_double=function(){var e=this.unpack_uint32(),t=this.unpack_uint32(),n=e>>31,r=(e>>20&2047)-1023,i=e&1048575|1048576,s=i*Math.pow(2,r-20)+t*Math.pow(2,r-52);return(n==0?1:-1)*s},r.prototype.read=function(e){var t=this.index;if(t+e<=this.length)return this.dataView.subarray(t,t+e);throw new Error("BinaryPackFailure: read index out of range")},i.prototype.pack=function(e){var n=typeof e;if(n=="string")this.pack_string(e);else if(n=="number")Math.floor(e)===e?this.pack_integer(e):this.pack_double(e);else if(n=="boolean")e===!0?this.bufferBuilder.append(195):e===!1&&this.bufferBuilder.append(194);else if(n=="undefined")this.bufferBuilder.append(192);else{if(n!="object")throw new Error('Type "'+n+'" not yet supported');if(e===null)this.bufferBuilder.append(192);else{var r=e.constructor;if(r==Array)this.pack_array(e);else if(r==Blob||r==File)this.pack_bin(e);else if(r==ArrayBuffer)t.useArrayBufferView?this.pack_bin(new Uint8Array(e)):this.pack_bin(e);else if("BYTES_PER_ELEMENT"in e)t.useArrayBufferView?this.pack_bin(e):this.pack_bin(e.buffer);else if(r==Object)this.pack_object(e);else if(r==Date)this.pack_string(e.toString());else{if(typeof e.toBinaryPack!="function")throw new Error('Type "'+r.toString()+'" not yet supported');this.bufferBuilder.append(e.toBinaryPack())}}}return this.bufferBuilder.getBuffer()},i.prototype.pack_bin=function(e){var t=e.length||e.byteLength||e.size;if(t<=15)this.pack_uint8(160+t);else if(t<=65535)this.bufferBuilder.append(218),this.pack_uint16(t);else{if(!(t<=4294967295))throw new Error("Invalid length");this.bufferBuilder.append(219),this.pack_uint32(t)}this.bufferBuilder.append(e)},i.prototype.pack_string=function(e){var t=e.length;if(t<=15)this.pack_uint8(176+t);else if(t<=65535)this.bufferBuilder.append(216),this.pack_uint16(t);else{if(!(t<=4294967295))throw new Error("Invalid length");this.bufferBuilder.append(217),this.pack_uint32(t)}this.bufferBuilder.append(e)},i.prototype.pack_array=function(e){var t=e.length;if(t<=15)this.pack_uint8(144+t);else if(t<=65535)this.bufferBuilder.append(220),this.pack_uint16(t);else{if(!(t<=4294967295))throw new Error("Invalid length");this.bufferBuilder.append(221),this.pack_uint32(t)}for(var n=0;n<t;n++)this.pack(e[n])},i.prototype.pack_integer=function(e){if(-32<=e&&e<=127)this.bufferBuilder.append(e&255);else if(0<=e&&e<=255)this.bufferBuilder.append(204),this.pack_uint8(e);else if(-128<=e&&e<=127)this.bufferBuilder.append(208),this.pack_int8(e);else if(0<=e&&e<=65535)this.bufferBuilder.append(205),this.pack_uint16(e);else if(-32768<=e&&e<=32767)this.bufferBuilder.append(209),this.pack_int16(e);else if(0<=e&&e<=4294967295)this.bufferBuilder.append(206),this.pack_uint32(e);else if(-2147483648<=e&&e<=2147483647)this.bufferBuilder.append(210),this.pack_int32(e);else if(-0x8000000000000000<=e&&e<=0x8000000000000000)this.bufferBuilder.append(211),this.pack_int64(e);else{if(!(0<=e&&e<=0x10000000000000000))throw new Error("Invalid integer");this.bufferBuilder.append(207),this.pack_uint64(e)}},i.prototype.pack_double=function(e){var t=0;e<0&&(t=1,e=-e);var n=Math.floor(Math.log(e)/Math.LN2),r=e/Math.pow(2,n)-1,i=Math.floor(r*Math.pow(2,52)),s=Math.pow(2,32),o=t<<31|n+1023<<20|i/s&1048575,u=i%s;this.bufferBuilder.append(203),this.pack_int32(o),this.pack_int32(u)},i.prototype.pack_object=function(e){var t=Object.keys(e),n=t.length;if(n<=15)this.pack_uint8(128+n);else if(n<=65535)this.bufferBuilder.append(222),this.pack_uint16(n);else{if(!(n<=4294967295))throw new Error("Invalid length");this.bufferBuilder.append(223),this.pack_uint32(n)}for(var r in e)e.hasOwnProperty(r)&&(this.pack(r),this.pack(e[r]))},i.prototype.pack_uint8=function(e){this.bufferBuilder.append(e)},i.prototype.pack_uint16=function(e){this.bufferBuilder.append(e>>8),this.bufferBuilder.append(e&255)},i.prototype.pack_uint32=function(e){var t=e&4294967295;this.bufferBuilder.append((t&4278190080)>>>24),this.bufferBuilder.append((t&16711680)>>>16),this.bufferBuilder.append((t&65280)>>>8),this.bufferBuilder.append(t&255)},i.prototype.pack_uint64=function(e){var t=e/Math.pow(2,32),n=e%Math.pow(2,32);this.bufferBuilder.append((t&4278190080)>>>24),this.bufferBuilder.append((t&16711680)>>>16),this.bufferBuilder.append((t&65280)>>>8),this.bufferBuilder.append(t&255),this.bufferBuilder.append((n&4278190080)>>>24),this.bufferBuilder.append((n&16711680)>>>16),this.bufferBuilder.append((n&65280)>>>8),this.bufferBuilder.append(n&255)},i.prototype.pack_int8=function(e){this.bufferBuilder.append(e&255)},i.prototype.pack_int16=function(e){this.bufferBuilder.append((e&65280)>>8),this.bufferBuilder.append(e&255)},i.prototype.pack_int32=function(e){this.bufferBuilder.append(e>>>24&255),this.bufferBuilder.append((e&16711680)>>>16),this.bufferBuilder.append((e&65280)>>>8),this.bufferBuilder.append(e&255)},i.prototype.pack_int64=function(e){var t=Math.floor(e/Math.pow(2,32)),n=e%Math.pow(2,32);this.bufferBuilder.append((t&4278190080)>>>24),this.bufferBuilder.append((t&16711680)>>>16),this.bufferBuilder.append((t&65280)>>>8),this.bufferBuilder.append(t&255),this.bufferBuilder.append((n&4278190080)>>>24),this.bufferBuilder.append((n&16711680)>>>16),this.bufferBuilder.append((n&65280)>>>8),this.bufferBuilder.append(n&255)};var o=Array.isArray;s.prototype.addListener=function(e,t,n,r){if("function"!=typeof t)throw new Error("addListener only takes instances of Function");this.emit("newListener",e,typeof t.listener=="function"?t.listener:t),this._events[e]?o(this._events[e])?this._events[e].push(t):this._events[e]=[this._events[e],t]:this._events[e]=t},s.prototype.on=s.prototype.addListener,s.prototype.once=function(e,t,n){function i(){r.removeListener(e,i),t.apply(this,arguments)}if("function"!=typeof t)throw new Error(".once only takes instances of Function");var r=this;return i.listener=t,r.on(e,i),this},s.prototype.removeListener=function(e,t,n){if("function"!=typeof t)throw new Error("removeListener only takes instances of Function");if(!this._events[e])return this;var r=this._events[e];if(o(r)){var i=-1;for(var s=0,u=r.length;s<u;s++)if(r[s]===t||r[s].listener&&r[s].listener===t){i=s;break}if(i<0)return this;r.splice(i,1),r.length==0&&delete this._events[e]}else(r===t||r.listener&&r.listener===t)&&delete this._events[e];return this},s.prototype.off=s.prototype.removeListener,s.prototype.removeAllListeners=function(e){return arguments.length===0?(this._events={},this):(e&&this._events&&this._events[e]&&(this._events[e]=null),this)},s.prototype.listeners=function(e){return this._events[e]||(this._events[e]=[]),o(this._events[e])||(this._events[e]=[this._events[e]]),this._events[e]},s.prototype.emit=function(e){var e=arguments[0],t=this._events[e];if(!t)return!1;if(typeof t=="function"){switch(arguments.length){case 1:t.call(this);break;case 2:t.call(this,arguments[1]);break;case 3:t.call(this,arguments[1],arguments[2]);break;default:var n=arguments.length,r=new Array(n-1);for(var i=1;i<n;i++)r[i-1]=arguments[i];t.apply(this,r)}return!0}if(o(t)){var n=arguments.length,r=new Array(n-1);for(var i=1;i<n;i++)r[i-1]=arguments[i];var s=t.slice();for(var i=0,n=s.length;i<n;i++)s[i].apply(this,r);return!0}return!1};var u={debug:!1,browserisms:"",inherits:function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})},extend:function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e},pack:BinaryPack.pack,unpack:BinaryPack.unpack,randomPort:function(){return Math.round(Math.random()*60535)+5e3},log:function(){if(u.debug){var e=[];for(var t=0;t<arguments.length;t++)e[t]=arguments[t];e.unshift("PeerJS: "),console.log.apply(console,e)}},setZeroTimeout:function(e){function r(r){t.push(r),e.postMessage(n,"*")}function i(r){r.source==e&&r.data==n&&(r.stopPropagation&&r.stopPropagation(),t.length&&t.shift()())}var t=[],n="zero-timeout-message";return e.addEventListener?e.addEventListener("message",i,!0):e.attachEvent&&e.attachEvent("onmessage",i),r}(this),blobToArrayBuffer:function(e,t){var n=new FileReader;n.onload=function(e){t(e.target.result)},n.readAsArrayBuffer(e)},blobToBinaryString:function(e,t){var n=new FileReader;n.onload=function(e){t(e.target.result)},n.readAsBinaryString(e)},binaryStringToArrayBuffer:function(e){var t=new Uint8Array(e.length);for(var n=0;n<e.length;n++)t[n]=e.charCodeAt(n)&255;return t.buffer}},a=null,f=null,l=null;navigator.mozGetUserMedia?(u.browserisms="Firefox",a=mozRTCPeerConnection,f=navigator.mozGetUserMedia.bind(navigator)):navigator.webkitGetUserMedia&&(u.browserisms="Webkit",a=webkitRTCPeerConnection,f=navigator.webkitGetUserMedia.bind(navigator)),e.RTCPeerConnection=a,e.getUserMedia=f,u.inherits(c,s),c.prototype._checkIn=function(){var e=this;if(!this._id)try{var t=new XMLHttpRequest;t.open("get",this._httpUrl+"/id",!0),t.onreadystatechange=function(){if(!e._id&&t.readyState>2&&!!t.responseText)try{var n=JSON.parse(t.responseText.split("\n").shift());!n.id||(e._id=n.id,e._socketInit(),e.emit("ready",e._id),e._processQueue())}catch(r){e._socketInit()}e._handleStream(t,!0)},t.send(null)}catch(n){u.log("XMLHttpRequest not available; defaulting to WebSockets"),this._socketInit()}else this._startXhrStream(),this._socketInit()},c.prototype._startXhrStream=function(){try{var e=new XMLHttpRequest,t=this;e.open("post",this._httpUrl+"/id",!0),e.setRequestHeader("Content-Type","application/json"),e.onreadystatechange=function(){t._handleStream(e)},e.send(JSON.stringify({id:this._id}))}catch(n){u.log("XMLHttpRequest not available; defaulting to WebSockets")}},c.prototype._handleStream=function(e,t){if(e.readyState<3)return;if(e.readyState==3&&e.status!=200)return;e.readyState==4&&e.status!=200,this._index===undefined&&(this._index=t?2:1);if(e.responseText===null)return;var n=e.responseText.split("\n")[this._index];!n||(this._index+=1,this._handleServerMessage(n)),e.readyState==4&&!this._socketOpen&&this._startXhrStream()},c.prototype._socketInit=function(){if(!!this._socket)return;this._socket=new WebSocket("ws://"+this._server+"/ws?id="+this._id);var e=this;this._socket.onmessage=function(t){e._handleServerMessage(t.data)},this._socket.onopen=function(){u.log("Socket open"),e._socketOpen=!0;for(var t in e.connections)e.connections.hasOwnProperty(t)&&e.connections[t].setSocketOpen();e._id&&e._processQueue()}},c.prototype._handleServerMessage=function(e){var e;try{e=JSON.parse(e)}catch(t){u.log("message unrecognizable:",e);return}var n=e.src,r=this.connections[n];switch(e.type){case"ID":this._id||(this._id=e.id,this.emit("ready",this._id),this._processQueue());break;case"ERROR":this.emit("error",e.msg),u.log(e.msg);break;case"OFFER":var i={metadata:e.metadata,sdp:e.sdp,socketOpen:this._socketOpen,config:this._config},s=this,r=new h(this._id,n,this._socket,this._httpUrl,function(t,n){t||s.emit("connection",n,e.metadata)},i);this.connections[n]=r;break;case"PEER_READY":break;case"ANSWER":r&&r.handleSDP(e);break;case"CANDIDATE":r&&r.handleCandidate(e);break;case"LEAVE":r&&r.handleLeave();break;case"PORT":if(u.browserisms==="Firefox"){r.handlePort(e);break};case"DEFAULT":u.log("PEER: unrecognized message ",e.type)}},c.prototype._processQueue=function(){while(this._queued.length>0){var e=this._queued.pop();this.connect.apply(this,e)}},c.prototype._cleanup=function(){for(var e in this.connections)this.connections.hasOwnProperty(e)&&this.connections[e].close()},c.prototype.connect=function(e,t,n){typeof t=="function"&&!n&&(n=t),t=!1;if(!this._id){this._queued.push(Array.prototype.slice.apply(arguments));return}var r={metadata:t,socketOpen:this._socketOpen,config:this._config},i=new h(this._id,e,this._socket,this._httpUrl,n,r);this.connections[e]=i},e.Peer=c,u.inherits(h,s),h.prototype._setupOffer=function(){var e=this;u.log("Listening for `negotiationneeded`"),this._pc.onnegotiationneeded=function(){u.log("`negotiationneeded` triggered"),e._makeOffer()}},h.prototype._setupDataChannel=function(){var e=this;this._originator?(u.log("Creating data channel"),this._dc=this._pc.createDataChannel(this._peer,{reliable:!1}),this._configureDataChannel()):(u.log("Listening for data channel"),this._pc.ondatachannel=function(t){u.log("Received data channel"),e._dc=t.channel,e._configureDataChannel()})},h.prototype._startPeerConnection=function(){u.log("Creating RTCPeerConnection: ",this._config),this._pc=new a(this._config,{optional:[{RtpDataChannels:!0}]})},h.prototype._setupIce=function(){u.log("Listening for ICE candidates");var e=this;this._pc.onicecandidate=function(t){t.candidate&&(u.log("Received ICE candidates"),e._handleBroker("ice",JSON.stringify({type:"CANDIDATE",candidate:t.candidate,dst:e._peer,src:e._id})))}},h.prototype._handleBroker=function(e,t){if(this._socketOpen)this._socket.send(t);else{var n=this,r=new XMLHttpRequest;r.open("post",this._httpUrl+"/"+e,!0),r.setRequestHeader("Content-Type","application/json"),r.onload=function(){r.responseText!="OK"&&(u.log("Destination peer not available. Connection closing..."),n.close())},r.send(t)}},h.prototype._firefoxPortSetup=function(){h.usedPorts||(h.usedPorts=[]),this.localPort=u.randomPort();while(h.usedPorts.indexOf(this.localPort)!=-1)this.localPort=u.randomPort();this.remotePort=u.randomPort();while(this.remotePort===this.localPort||h.usedPorts.indexOf(this.localPort)!=-1)this.remotePort=u.randomPort();h.usedPorts.push(this.remotePort),h.usedPorts.push(this.localPort)},h.prototype._configureDataChannel=function(){var e=this;u.browserisms==="Firefox"&&(this._dc.binaryType="blob"),this._dc.onopen=function(){u.log("Data channel connection success"),e._cb(null,e)},this._dc.onmessage=function(t){e._handleDataMessage(t)}},h.prototype._firefoxAdditional=function(){var e=this;f({audio:!0,fake:!0},function(t){e._pc.addStream(t),e._originator?e._makeOffer():e._makeAnswer()},function(e){u.log("Could not getUserMedia")})},h.prototype._makeOffer=function(){var e=this;this._pc.createOffer(function(t){u.log("Created offer"),e._pc.setLocalDescription(t,function(){u.log("Set localDescription to offer"),e._handleBroker("offer",JSON.stringify({type:"OFFER",sdp:t,dst:e._peer,src:e._id,metadata:e.metadata}))},function(t){e._cb("Failed to setLocalDescription"),u.log("Failed to setLocalDescription, ",t)})})},h.prototype._makeAnswer=function(){var e=this;this._pc.createAnswer(function(t){u.log("Created answer"),e._pc.setLocalDescription(t,function(){u.log("Set localDescription to answer"),e._handleBroker("answer",JSON.stringify({type:"ANSWER",src:e._id,sdp:t,dst:e._peer}))},function(t){e._cb("Failed to setLocalDescription"),u.log("Failed to setLocalDescription, ",t)})},function(t){e._cb("Failed to create answer"),u.log("Failed to create answer, ",t)})},h.prototype._cleanup=function(){!!this._pc&&this._pc.readyState!="closed"&&(this._pc.close(),this._pc=null),!!this._dc&&this._dc.readyState!="closed"&&(this._dc.close(),this._dc=null),this.emit("close",this._peer)},h.prototype._handleDataMessage=function(e){var t=this;if(e.data.constructor===Blob)u.blobToArrayBuffer(e.data,function(e){var n=BinaryPack.unpack(e);t.emit("data",n)});else if(e.data.constructor===ArrayBuffer){var n=BinaryPack.unpack(e.data);t.emit("data",n)}else if(e.data.constructor===String){var r=u.binaryStringToArrayBuffer(e.data),n=BinaryPack.unpack(r);t.emit("data",n)}},h.prototype.close=function(){this._cleanup();var e=this;this._handleBroker("leave",JSON.stringify({type:"LEAVE",dst:e._peer,src:e._id}))},h.prototype.send=function(e){var t=this,n=BinaryPack.pack(e);u.browserisms==="Webkit"?u.blobToBinaryString(n,function(e){t._dc.send(e)}):this._dc.send(n)},h.prototype.setSocketOpen=function(){this._socketOpen=!0},h.prototype.handleSDP=function(e){var t=e.sdp;u.browserisms!="Firefox"&&(t=new RTCSessionDescription(t));var n=this;this._pc.setRemoteDescription(t,function(){u.log("Set remoteDescription: "+e.type),e.type==="ANSWER"&&u.browserisms==="Firefox"&&(n._pc.connectDataConnection(n.localPort,n.remotePort),n._handleBroker("port",JSON.stringify({type:"PORT",dst:n._peer,src:n._id,remote:n.localPort,local:n.remotePort})))},function(e){this._cb("Failed to setRemoteDescription"),u.log("Failed to setRemoteDescription, ",e)})},h.prototype.handleCandidate=function(e){var t=new RTCIceCandidate(e.candidate);this._pc.addIceCandidate(t),u.log("Added ice candidate")},h.prototype.handleLeave=function(){u.log("Peer "+this._peer+" disconnected"),this._cleanup()},h.prototype.handlePort=function(e){h.usedPorts||(h.usedPorts=[]),h.usedPorts.push(e.local),h.usedPorts.push(e.remote),this._pc.connectDataConnection(e.local,e.remote)}})(this)
+/*! peerjs.min.js build:0.0.1, production. Copyright(c) 2013 Michelle Bu <michelle@michellebu.com> */(function(e){function n(){this._pieces=[],this._parts=[]}function r(e){this.index=0,this.dataBuffer=e,this.dataView=new Uint8Array(this.dataBuffer),this.length=this.dataBuffer.byteLength}function i(){this.bufferBuilder=new n}function s(){this._events={}}function c(e){if(!(this instanceof c))return new c(e);s.call(this),e=u.extend({debug:!1,host:"localhost",protocol:"http",config:{iceServers:[{url:"stun:stun.l.google.com:19302"}]},port:80},e),this.options=e,u.debug=e.debug,this._server=e.host+":"+e.port,this._httpUrl=e.protocol+"://"+this._server,this._config=e.config;if(e.id&&!/^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$/.exec(e.id))throw new Error('Peer ID can only contain alphanumerics, "_", and "-".');this._id=e.id,this._apikey=e.apikey,this._checkIn(),this.connections={},this._queued=[],window.onbeforeunload=this._cleanup}function h(e,t,n,r,i,o){if(!(this instanceof h))return new h(o);s.call(this),o=u.extend({socketOpen:!1},o),this.options=o,this._id=e,this._peer=t,this._originator=o.sdp===undefined,this._cb=i,this._httpUrl=r,this.metadata=o.metadata,this._socketOpen=o.socketOpen,this._socket=n,u.browserisms==="Firefox"&&this._firefoxPortSetup(),this._startPeerConnection(),this._setupIce(),u.browserisms==="Webkit"&&this._setupOffer(),this._setupDataChannel();var a=this;o.sdp&&(this.handleSDP({type:"OFFER",sdp:o.sdp}),u.browserisms!=="Firefox"&&this._makeAnswer()),u.browserisms==="Firefox"&&this._firefoxAdditional()}var t={};t.useBlobBuilder=function(){try{return new Blob([]),!1}catch(e){return!0}}(),t.useArrayBufferView=!t.useBlobBuilder&&function(){try{return(new Blob([new Uint8Array([])])).size===0}catch(e){return!0}}(),t.supportsBinaryWebsockets=function(){try{var e=new WebSocket("ws://null");return e.onerror=function(){},typeof e.binaryType!="undefined"?!0:!1}catch(t){return!1}}(),e.binaryFeatures=t,e.BlobBuilder=window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder||window.BlobBuilder,n.prototype.append=function(e){typeof e=="number"?this._pieces.push(e):(this._flush(),this._parts.push(e))},n.prototype._flush=function(){if(this._pieces.length>0){var e=new Uint8Array(this._pieces);t.useArrayBufferView||(e=e.buffer),this._parts.push(e),this._pieces=[]}},n.prototype.getBuffer=function(){this._flush();if(t.useBlobBuilder){var e=new BlobBuilder;for(var n=0,r=this._parts.length;n<r;n++)e.append(this._parts[n]);return e.getBlob()}return new Blob(this._parts)},e.BinaryPack={unpack:function(e){var t=new r(e);return t.unpack()},pack:function(e){var t=new i,n=t.pack(e);return n}},r.prototype.unpack=function(){var e=this.unpack_uint8();if(e<128){var t=e;return t}if((e^224)<32){var n=(e^224)-32;return n}var r;if((r=e^160)<=15)return this.unpack_raw(r);if((r=e^176)<=15)return this.unpack_string(r);if((r=e^144)<=15)return this.unpack_array(r);if((r=e^128)<=15)return this.unpack_map(r);switch(e){case 192:return null;case 193:return undefined;case 194:return!1;case 195:return!0;case 202:return this.unpack_float();case 203:return this.unpack_double();case 204:return this.unpack_uint8();case 205:return this.unpack_uint16();case 206:return this.unpack_uint32();case 207:return this.unpack_uint64();case 208:return this.unpack_int8();case 209:return this.unpack_int16();case 210:return this.unpack_int32();case 211:return this.unpack_int64();case 212:return undefined;case 213:return undefined;case 214:return undefined;case 215:return undefined;case 216:return r=this.unpack_uint16(),this.unpack_string(r);case 217:return r=this.unpack_uint32(),this.unpack_string(r);case 218:return r=this.unpack_uint16(),this.unpack_raw(r);case 219:return r=this.unpack_uint32(),this.unpack_raw(r);case 220:return r=this.unpack_uint16(),this.unpack_array(r);case 221:return r=this.unpack_uint32(),this.unpack_array(r);case 222:return r=this.unpack_uint16(),this.unpack_map(r);case 223:return r=this.unpack_uint32(),this.unpack_map(r)}},r.prototype.unpack_uint8=function(){var e=this.dataView[this.index]&255;return this.index++,e},r.prototype.unpack_uint16=function(){var e=this.read(2),t=(e[0]&255)*256+(e[1]&255);return this.index+=2,t},r.prototype.unpack_uint32=function(){var e=this.read(4),t=((e[0]*256+e[1])*256+e[2])*256+e[3];return this.index+=4,t},r.prototype.unpack_uint64=function(){var e=this.read(8),t=((((((e[0]*256+e[1])*256+e[2])*256+e[3])*256+e[4])*256+e[5])*256+e[6])*256+e[7];return this.index+=8,t},r.prototype.unpack_int8=function(){var e=this.unpack_uint8();return e<128?e:e-256},r.prototype.unpack_int16=function(){var e=this.unpack_uint16();return e<32768?e:e-65536},r.prototype.unpack_int32=function(){var e=this.unpack_uint32();return e<Math.pow(2,31)?e:e-Math.pow(2,32)},r.prototype.unpack_int64=function(){var e=this.unpack_uint64();return e<Math.pow(2,63)?e:e-Math.pow(2,64)},r.prototype.unpack_raw=function(e){if(this.length<this.index+e)throw new Error("BinaryPackFailure: index is out of range "+this.index+" "+e+" "+this.length);var t=this.dataBuffer.slice(this.index,this.index+e);return this.index+=e,t},r.prototype.unpack_string=function(e){var t=this.read(e),n=0,r="",i,s;while(n<e)i=t[n],i<128?(r+=String.fromCharCode(i),n++):(i^192)<32?(s=(i^192)<<6|t[n+1]&63,r+=String.fromCharCode(s),n+=2):(s=(i&15)<<12|(t[n+1]&63)<<6|t[n+2]&63,r+=String.fromCharCode(s),n+=3);return this.index+=e,r},r.prototype.unpack_array=function(e){var t=new Array(e);for(var n=0;n<e;n++)t[n]=this.unpack();return t},r.prototype.unpack_map=function(e){var t={};for(var n=0;n<e;n++){var r=this.unpack(),i=this.unpack();t[r]=i}return t},r.prototype.unpack_float=function(){var e=this.unpack_uint32(),t=e>>31,n=(e>>23&255)-127,r=e&8388607|8388608;return(t==0?1:-1)*r*Math.pow(2,n-23)},r.prototype.unpack_double=function(){var e=this.unpack_uint32(),t=this.unpack_uint32(),n=e>>31,r=(e>>20&2047)-1023,i=e&1048575|1048576,s=i*Math.pow(2,r-20)+t*Math.pow(2,r-52);return(n==0?1:-1)*s},r.prototype.read=function(e){var t=this.index;if(t+e<=this.length)return this.dataView.subarray(t,t+e);throw new Error("BinaryPackFailure: read index out of range")},i.prototype.pack=function(e){var n=typeof e;if(n=="string")this.pack_string(e);else if(n=="number")Math.floor(e)===e?this.pack_integer(e):this.pack_double(e);else if(n=="boolean")e===!0?this.bufferBuilder.append(195):e===!1&&this.bufferBuilder.append(194);else if(n=="undefined")this.bufferBuilder.append(192);else{if(n!="object")throw new Error('Type "'+n+'" not yet supported');if(e===null)this.bufferBuilder.append(192);else{var r=e.constructor;if(r==Array)this.pack_array(e);else if(r==Blob||r==File)this.pack_bin(e);else if(r==ArrayBuffer)t.useArrayBufferView?this.pack_bin(new Uint8Array(e)):this.pack_bin(e);else if("BYTES_PER_ELEMENT"in e)t.useArrayBufferView?this.pack_bin(e):this.pack_bin(e.buffer);else if(r==Object)this.pack_object(e);else if(r==Date)this.pack_string(e.toString());else{if(typeof e.toBinaryPack!="function")throw new Error('Type "'+r.toString()+'" not yet supported');this.bufferBuilder.append(e.toBinaryPack())}}}return this.bufferBuilder.getBuffer()},i.prototype.pack_bin=function(e){var t=e.length||e.byteLength||e.size;if(t<=15)this.pack_uint8(160+t);else if(t<=65535)this.bufferBuilder.append(218),this.pack_uint16(t);else{if(!(t<=4294967295))throw new Error("Invalid length");this.bufferBuilder.append(219),this.pack_uint32(t)}this.bufferBuilder.append(e)},i.prototype.pack_string=function(e){var t=e.length;if(t<=15)this.pack_uint8(176+t);else if(t<=65535)this.bufferBuilder.append(216),this.pack_uint16(t);else{if(!(t<=4294967295))throw new Error("Invalid length");this.bufferBuilder.append(217),this.pack_uint32(t)}this.bufferBuilder.append(e)},i.prototype.pack_array=function(e){var t=e.length;if(t<=15)this.pack_uint8(144+t);else if(t<=65535)this.bufferBuilder.append(220),this.pack_uint16(t);else{if(!(t<=4294967295))throw new Error("Invalid length");this.bufferBuilder.append(221),this.pack_uint32(t)}for(var n=0;n<t;n++)this.pack(e[n])},i.prototype.pack_integer=function(e){if(-32<=e&&e<=127)this.bufferBuilder.append(e&255);else if(0<=e&&e<=255)this.bufferBuilder.append(204),this.pack_uint8(e);else if(-128<=e&&e<=127)this.bufferBuilder.append(208),this.pack_int8(e);else if(0<=e&&e<=65535)this.bufferBuilder.append(205),this.pack_uint16(e);else if(-32768<=e&&e<=32767)this.bufferBuilder.append(209),this.pack_int16(e);else if(0<=e&&e<=4294967295)this.bufferBuilder.append(206),this.pack_uint32(e);else if(-2147483648<=e&&e<=2147483647)this.bufferBuilder.append(210),this.pack_int32(e);else if(-0x8000000000000000<=e&&e<=0x8000000000000000)this.bufferBuilder.append(211),this.pack_int64(e);else{if(!(0<=e&&e<=0x10000000000000000))throw new Error("Invalid integer");this.bufferBuilder.append(207),this.pack_uint64(e)}},i.prototype.pack_double=function(e){var t=0;e<0&&(t=1,e=-e);var n=Math.floor(Math.log(e)/Math.LN2),r=e/Math.pow(2,n)-1,i=Math.floor(r*Math.pow(2,52)),s=Math.pow(2,32),o=t<<31|n+1023<<20|i/s&1048575,u=i%s;this.bufferBuilder.append(203),this.pack_int32(o),this.pack_int32(u)},i.prototype.pack_object=function(e){var t=Object.keys(e),n=t.length;if(n<=15)this.pack_uint8(128+n);else if(n<=65535)this.bufferBuilder.append(222),this.pack_uint16(n);else{if(!(n<=4294967295))throw new Error("Invalid length");this.bufferBuilder.append(223),this.pack_uint32(n)}for(var r in e)e.hasOwnProperty(r)&&(this.pack(r),this.pack(e[r]))},i.prototype.pack_uint8=function(e){this.bufferBuilder.append(e)},i.prototype.pack_uint16=function(e){this.bufferBuilder.append(e>>8),this.bufferBuilder.append(e&255)},i.prototype.pack_uint32=function(e){var t=e&4294967295;this.bufferBuilder.append((t&4278190080)>>>24),this.bufferBuilder.append((t&16711680)>>>16),this.bufferBuilder.append((t&65280)>>>8),this.bufferBuilder.append(t&255)},i.prototype.pack_uint64=function(e){var t=e/Math.pow(2,32),n=e%Math.pow(2,32);this.bufferBuilder.append((t&4278190080)>>>24),this.bufferBuilder.append((t&16711680)>>>16),this.bufferBuilder.append((t&65280)>>>8),this.bufferBuilder.append(t&255),this.bufferBuilder.append((n&4278190080)>>>24),this.bufferBuilder.append((n&16711680)>>>16),this.bufferBuilder.append((n&65280)>>>8),this.bufferBuilder.append(n&255)},i.prototype.pack_int8=function(e){this.bufferBuilder.append(e&255)},i.prototype.pack_int16=function(e){this.bufferBuilder.append((e&65280)>>8),this.bufferBuilder.append(e&255)},i.prototype.pack_int32=function(e){this.bufferBuilder.append(e>>>24&255),this.bufferBuilder.append((e&16711680)>>>16),this.bufferBuilder.append((e&65280)>>>8),this.bufferBuilder.append(e&255)},i.prototype.pack_int64=function(e){var t=Math.floor(e/Math.pow(2,32)),n=e%Math.pow(2,32);this.bufferBuilder.append((t&4278190080)>>>24),this.bufferBuilder.append((t&16711680)>>>16),this.bufferBuilder.append((t&65280)>>>8),this.bufferBuilder.append(t&255),this.bufferBuilder.append((n&4278190080)>>>24),this.bufferBuilder.append((n&16711680)>>>16),this.bufferBuilder.append((n&65280)>>>8),this.bufferBuilder.append(n&255)};var o=Array.isArray;s.prototype.addListener=function(e,t,n,r){if("function"!=typeof t)throw new Error("addListener only takes instances of Function");this.emit("newListener",e,typeof t.listener=="function"?t.listener:t),this._events[e]?o(this._events[e])?this._events[e].push(t):this._events[e]=[this._events[e],t]:this._events[e]=t},s.prototype.on=s.prototype.addListener,s.prototype.once=function(e,t,n){function i(){r.removeListener(e,i),t.apply(this,arguments)}if("function"!=typeof t)throw new Error(".once only takes instances of Function");var r=this;return i.listener=t,r.on(e,i),this},s.prototype.removeListener=function(e,t,n){if("function"!=typeof t)throw new Error("removeListener only takes instances of Function");if(!this._events[e])return this;var r=this._events[e];if(o(r)){var i=-1;for(var s=0,u=r.length;s<u;s++)if(r[s]===t||r[s].listener&&r[s].listener===t){i=s;break}if(i<0)return this;r.splice(i,1),r.length==0&&delete this._events[e]}else(r===t||r.listener&&r.listener===t)&&delete this._events[e];return this},s.prototype.off=s.prototype.removeListener,s.prototype.removeAllListeners=function(e){return arguments.length===0?(this._events={},this):(e&&this._events&&this._events[e]&&(this._events[e]=null),this)},s.prototype.listeners=function(e){return this._events[e]||(this._events[e]=[]),o(this._events[e])||(this._events[e]=[this._events[e]]),this._events[e]},s.prototype.emit=function(e){var e=arguments[0],t=this._events[e];if(!t)return!1;if(typeof t=="function"){switch(arguments.length){case 1:t.call(this);break;case 2:t.call(this,arguments[1]);break;case 3:t.call(this,arguments[1],arguments[2]);break;default:var n=arguments.length,r=new Array(n-1);for(var i=1;i<n;i++)r[i-1]=arguments[i];t.apply(this,r)}return!0}if(o(t)){var n=arguments.length,r=new Array(n-1);for(var i=1;i<n;i++)r[i-1]=arguments[i];var s=t.slice();for(var i=0,n=s.length;i<n;i++)s[i].apply(this,r);return!0}return!1};var u={debug:!1,browserisms:"",inherits:function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})},extend:function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e},pack:BinaryPack.pack,unpack:BinaryPack.unpack,randomPort:function(){return Math.round(Math.random()*60535)+5e3},log:function(){if(u.debug){var e=[];for(var t=0;t<arguments.length;t++)e[t]=arguments[t];e.unshift("PeerJS: "),console.log.apply(console,e)}},setZeroTimeout:function(e){function r(r){t.push(r),e.postMessage(n,"*")}function i(r){r.source==e&&r.data==n&&(r.stopPropagation&&r.stopPropagation(),t.length&&t.shift()())}var t=[],n="zero-timeout-message";return e.addEventListener?e.addEventListener("message",i,!0):e.attachEvent&&e.attachEvent("onmessage",i),r}(this),blobToArrayBuffer:function(e,t){var n=new FileReader;n.onload=function(e){t(e.target.result)},n.readAsArrayBuffer(e)},blobToBinaryString:function(e,t){var n=new FileReader;n.onload=function(e){t(e.target.result)},n.readAsBinaryString(e)},binaryStringToArrayBuffer:function(e){var t=new Uint8Array(e.length);for(var n=0;n<e.length;n++)t[n]=e.charCodeAt(n)&255;return t.buffer}},a=null,f=null,l=null;navigator.mozGetUserMedia?(u.browserisms="Firefox",a=mozRTCPeerConnection,f=navigator.mozGetUserMedia.bind(navigator)):navigator.webkitGetUserMedia&&(u.browserisms="Webkit",a=webkitRTCPeerConnection,f=navigator.webkitGetUserMedia.bind(navigator)),e.RTCPeerConnection=a,e.getUserMedia=f,u.inherits(c,s),c.prototype._checkIn=function(){var e=this;if(!this._id)try{var t=new XMLHttpRequest;t.open("get",this._httpUrl+"/id",!0),t.onreadystatechange=function(){if(!e._id&&t.readyState>2&&!!t.responseText)try{var n=JSON.parse(t.responseText.split("\n").shift());!n.id||(e._id=n.id,e._socketInit(),e.emit("ready",e._id),e._processQueue())}catch(r){e._socketInit()}e._handleStream(t,!0)},t.send(null)}catch(n){u.log("XMLHttpRequest not available; defaulting to WebSockets"),this._socketInit()}else this._startXhrStream(),this._socketInit()},c.prototype._startXhrStream=function(){try{var e=new XMLHttpRequest,t=this;e.open("post",this._httpUrl+"/id",!0),e.setRequestHeader("Content-Type","application/json"),e.onreadystatechange=function(){t._handleStream(e)},e.send(JSON.stringify({id:this._id}))}catch(n){u.log("XMLHttpRequest not available; defaulting to WebSockets")}},c.prototype._handleStream=function(e,t){if(e.readyState<3)return;if(e.readyState==3&&e.status!=200)return;e.readyState==4&&e.status!=200,this._index===undefined&&(this._index=t?2:1);if(e.responseText===null)return;var n=e.responseText.split("\n")[this._index];!n||(this._index+=1,this._handleServerMessage(n)),e.readyState==4&&!this._socketOpen&&this._startXhrStream()},c.prototype._socketInit=function(){if(!!this._socket)return;this._socket=new WebSocket("ws://"+this._server+"/ws?id="+this._id);var e=this;this._socket.onmessage=function(t){e._handleServerMessage(t.data)},this._socket.onopen=function(){u.log("Socket open"),e._socketOpen=!0;for(var t in e.connections)e.connections.hasOwnProperty(t)&&e.connections[t].setSocketOpen();e._id&&e._processQueue()}},c.prototype._handleServerMessage=function(e){var e;try{e=JSON.parse(e)}catch(t){u.log("message unrecognizable:",e);return}var n=e.src,r=this.connections[n];switch(e.type){case"ID":this._id||(this._id=e.id,this.emit("ready",this._id),this._processQueue());break;case"ERROR":this.emit("error",e.msg),u.log(e.msg);break;case"OFFER":var i={metadata:e.metadata,sdp:e.sdp,socketOpen:this._socketOpen,config:this._config},s=this,r=new h(this._id,n,this._socket,this._httpUrl,function(t,n){t||s.emit("connection",n,e.metadata)},i);this.connections[n]=r;break;case"PEER_READY":break;case"ANSWER":r&&r.handleSDP(e);break;case"CANDIDATE":r&&r.handleCandidate(e);break;case"LEAVE":r&&(r.handleLeave(),delete this.connections[n]);break;case"PORT":if(u.browserisms==="Firefox"){r.handlePort(e);break};case"DEFAULT":u.log("PEER: unrecognized message ",e.type)}},c.prototype._processQueue=function(){while(this._queued.length>0){var e=this._queued.pop();this.connect.apply(this,e)}},c.prototype._cleanup=function(){this._socket.send(JSON.stringify({type:"LEAVE",src:this._id}));for(var e in this.connections)this.connections.hasOwnProperty(e)&&this.connections[e].close()},c.prototype.connect=function(e,t,n){typeof t=="function"&&!n&&(n=t),t=!1;if(!this._id){this._queued.push(Array.prototype.slice.apply(arguments));return}var r={metadata:t,socketOpen:this._socketOpen,config:this._config},i=new h(this._id,e,this._socket,this._httpUrl,n,r);this.connections[e]=i},c.prototype.leave=function(){this._cleanup()},e.Peer=c,u.inherits(h,s),h.prototype._setupOffer=function(){var e=this;u.log("Listening for `negotiationneeded`"),this._pc.onnegotiationneeded=function(){u.log("`negotiationneeded` triggered"),e._makeOffer()}},h.prototype._setupDataChannel=function(){var e=this;this._originator?(u.log("Creating data channel"),this._dc=this._pc.createDataChannel(this._peer,{reliable:!1}),this._configureDataChannel()):(u.log("Listening for data channel"),this._pc.ondatachannel=function(t){u.log("Received data channel"),e._dc=t.channel,e._configureDataChannel()})},h.prototype._startPeerConnection=function(){u.log("Creating RTCPeerConnection: ",this._config),this._pc=new a(this._config,{optional:[{RtpDataChannels:!0}]})},h.prototype._setupIce=function(){u.log("Listening for ICE candidates");var e=this;this._pc.onicecandidate=function(t){t.candidate&&(u.log("Received ICE candidates"),e._handleBroker("ice",JSON.stringify({type:"CANDIDATE",candidate:t.candidate,dst:e._peer,src:e._id})))}},h.prototype._handleBroker=function(e,t){if(this._socketOpen)this._socket.send(t);else{var n=this,r=new XMLHttpRequest;r.open("post",this._httpUrl+"/"+e,!0),r.setRequestHeader("Content-Type","application/json"),r.onload=function(){r.responseText!="OK"&&(u.log("Destination peer not available. Connection closing..."),n.close())},r.send(t)}},h.prototype._firefoxPortSetup=function(){h.usedPorts||(h.usedPorts=[]),this.localPort=u.randomPort();while(h.usedPorts.indexOf(this.localPort)!=-1)this.localPort=u.randomPort();this.remotePort=u.randomPort();while(this.remotePort===this.localPort||h.usedPorts.indexOf(this.localPort)!=-1)this.remotePort=u.randomPort();h.usedPorts.push(this.remotePort),h.usedPorts.push(this.localPort)},h.prototype._configureDataChannel=function(){var e=this;u.browserisms==="Firefox"&&(this._dc.binaryType="blob"),this._dc.onopen=function(){u.log("Data channel connection success"),e._cb(null,e)},this._dc.onmessage=function(t){e._handleDataMessage(t)}},h.prototype._firefoxAdditional=function(){var e=this;f({audio:!0,fake:!0},function(t){e._pc.addStream(t),e._originator?e._makeOffer():e._makeAnswer()},function(e){u.log("Could not getUserMedia")})},h.prototype._makeOffer=function(){var e=this;this._pc.createOffer(function(t){u.log("Created offer"),e._pc.setLocalDescription(t,function(){u.log("Set localDescription to offer"),e._handleBroker("offer",JSON.stringify({type:"OFFER",sdp:t,dst:e._peer,src:e._id,metadata:e.metadata}))},function(t){e._cb("Failed to setLocalDescription"),u.log("Failed to setLocalDescription, ",t)})})},h.prototype._makeAnswer=function(){var e=this;this._pc.createAnswer(function(t){u.log("Created answer"),e._pc.setLocalDescription(t,function(){u.log("Set localDescription to answer"),e._handleBroker("answer",JSON.stringify({type:"ANSWER",src:e._id,sdp:t,dst:e._peer}))},function(t){e._cb("Failed to setLocalDescription"),u.log("Failed to setLocalDescription, ",t)})},function(t){e._cb("Failed to create answer"),u.log("Failed to create answer, ",t)})},h.prototype._cleanup=function(){!!this._pc&&this._pc.readyState!="closed"&&(this._pc.close(),this._pc=null),!!this._dc&&this._dc.readyState!="closed"&&(this._dc.close(),this._dc=null),this.emit("close",this._peer)},h.prototype._handleDataMessage=function(e){var t=this;if(e.data.constructor===Blob)u.blobToArrayBuffer(e.data,function(e){var n=BinaryPack.unpack(e);t.emit("data",n)});else if(e.data.constructor===ArrayBuffer){var n=BinaryPack.unpack(e.data);t.emit("data",n)}else if(e.data.constructor===String){var r=u.binaryStringToArrayBuffer(e.data),n=BinaryPack.unpack(r);t.emit("data",n)}},h.prototype.close=function(){this._cleanup();var e=this;this._handleBroker("leave",JSON.stringify({type:"LEAVE",dst:e._peer,src:e._id}))},h.prototype.send=function(e){var t=this,n=BinaryPack.pack(e);u.browserisms==="Webkit"?u.blobToBinaryString(n,function(e){t._dc.send(e)}):this._dc.send(n)},h.prototype.setSocketOpen=function(){this._socketOpen=!0},h.prototype.handleSDP=function(e){var t=e.sdp;u.browserisms!="Firefox"&&(t=new RTCSessionDescription(t));var n=this;this._pc.setRemoteDescription(t,function(){u.log("Set remoteDescription: "+e.type),e.type==="ANSWER"&&u.browserisms==="Firefox"&&(n._pc.connectDataConnection(n.localPort,n.remotePort),n._handleBroker("port",JSON.stringify({type:"PORT",dst:n._peer,src:n._id,remote:n.localPort,local:n.remotePort})))},function(e){this._cb("Failed to setRemoteDescription"),u.log("Failed to setRemoteDescription, ",e)})},h.prototype.handleCandidate=function(e){var t=new RTCIceCandidate(e.candidate);this._pc.addIceCandidate(t),u.log("Added ice candidate")},h.prototype.handleLeave=function(){u.log("Peer "+this._peer+" disconnected"),this._cleanup()},h.prototype.handlePort=function(e){h.usedPorts||(h.usedPorts=[]),h.usedPorts.push(e.local),h.usedPorts.push(e.remote),this._pc.connectDataConnection(e.local,e.remote)}})(this)
View
10 lib/peer.js
@@ -199,7 +199,10 @@ Peer.prototype._handleServerMessage = function(message) {
if (connection) connection.handleCandidate(message);
break;
case 'LEAVE':
- if (connection) connection.handleLeave();
+ if (connection) {
+ connection.handleLeave();
+ delete this.connections[peer];
+ }
break;
case 'PORT':
if (util.browserisms === 'Firefox') {
@@ -222,6 +225,7 @@ Peer.prototype._processQueue = function() {
Peer.prototype._cleanup = function() {
+ this._socket.send(JSON.stringify({ type: 'LEAVE', src: this._id }));
for (var peer in this.connections) {
if (this.connections.hasOwnProperty(peer)) {
this.connections[peer].close();
@@ -250,6 +254,10 @@ Peer.prototype.connect = function(peer, metadata, cb) {
this.connections[peer] = connection;
};
+Peer.prototype.leave = function() {
+ this._cleanup();
+};
+
exports.Peer = Peer;

0 comments on commit 24dffda

Please sign in to comment.
Something went wrong with that request. Please try again.