|
@@ -0,0 +1,133 @@
|
|
|
+/**
|
|
|
+ * Wraps a DataChannel between two Peers.
|
|
|
+ */
|
|
|
+function DataConnection(peer, dc, options) {
|
|
|
+ if (!(this instanceof DataConnection)) return new DataConnection(peer, dc, options);
|
|
|
+ EventEmitter.call(this);
|
|
|
+
|
|
|
+ options = util.extend({
|
|
|
+ reliable: false,
|
|
|
+ serialization: 'binary'
|
|
|
+ }, options);
|
|
|
+
|
|
|
+ // Connection is not open yet.
|
|
|
+ this.open = false;
|
|
|
+
|
|
|
+ this.label = options.label;
|
|
|
+ this.metadata = options.metadata;
|
|
|
+ this.serialization = options.serialization;
|
|
|
+ this.peer = peer;
|
|
|
+ this._isReliable = options.reliable;
|
|
|
+
|
|
|
+ this._dc = dc;
|
|
|
+ if (!!this._dc) {
|
|
|
+ this._configureDataChannel();
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+util.inherits(DataConnection, EventEmitter);
|
|
|
+
|
|
|
+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');
|
|
|
+ };
|
|
|
+ if (this._reliable) {
|
|
|
+ this._reliable.onmessage = function(msg) {
|
|
|
+ self.emit('data', msg);
|
|
|
+ };
|
|
|
+ } else {
|
|
|
+ this._dc.onmessage = function(e) {
|
|
|
+ self._handleDataMessage(e);
|
|
|
+ };
|
|
|
+ }
|
|
|
+ this._dc.onclose = function(e) {
|
|
|
+ self.emit('close');
|
|
|
+ };
|
|
|
+
|
|
|
+ // Reliable.
|
|
|
+ if (this._isReliable) {
|
|
|
+ this._reliable = new Reliable(this._dc, util.debug);
|
|
|
+ }
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+DataConnection.prototype._cleanup = function() {
|
|
|
+ if (!!this._dc && this._dc.readyState != 'closed') {
|
|
|
+ this._dc.close();
|
|
|
+ this._dc = null;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// Handles a DataChannel message.
|
|
|
+DataConnection.prototype._handleDataMessage = function(e) {
|
|
|
+ var self = this;
|
|
|
+ var data = e.data;
|
|
|
+ var datatype = data.constructor;
|
|
|
+ if (this.serialization === 'binary' || this.serialization === 'binary-utf8') {
|
|
|
+ if (datatype === Blob) {
|
|
|
+ util.blobToArrayBuffer(data, function(ab) {
|
|
|
+ data = util.unpack(ab);
|
|
|
+ self.emit('data', data);
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ } else if (datatype === ArrayBuffer) {
|
|
|
+ data = util.unpack(data);
|
|
|
+ } else if (datatype === String) {
|
|
|
+ var ab = util.binaryStringToArrayBuffer(data);
|
|
|
+ data = util.unpack(ab);
|
|
|
+ }
|
|
|
+ } else if (this.serialization === 'json') {
|
|
|
+ data = JSON.parse(data);
|
|
|
+ }
|
|
|
+ this.emit('data', data);
|
|
|
+};
|
|
|
+
|
|
|
+DataConnection.prototype.addDC = function(dc) {
|
|
|
+ this._dc = dc;
|
|
|
+ this._configureDataChannel();
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * Exposed functionality for users.
|
|
|
+ */
|
|
|
+
|
|
|
+/** Allows user to close connection. */
|
|
|
+DataConnection.prototype.close = function() {
|
|
|
+ this._cleanup();
|
|
|
+ this.open = false;
|
|
|
+ this.emit('close');
|
|
|
+};
|
|
|
+
|
|
|
+/** Allows user to send data. */
|
|
|
+DataConnection.prototype.send = function(data) {
|
|
|
+ if (this._reliable) {
|
|
|
+ // Note: reliable sending will make it so that you cannot customize
|
|
|
+ // serialization.
|
|
|
+ this._reliable.send(data);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var self = this;
|
|
|
+ if (this.serialization === 'none') {
|
|
|
+ this._dc.send(data);
|
|
|
+ } else if (this.serialization === 'json') {
|
|
|
+ this._dc.send(JSON.stringify(data));
|
|
|
+ } else {
|
|
|
+ var utf8 = (this.serialization === 'binary-utf8');
|
|
|
+ var blob = util.pack(data, utf8);
|
|
|
+ // DataChannel currently only supports strings.
|
|
|
+ if (util.browserisms === 'Webkit') {
|
|
|
+ util.blobToBinaryString(blob, function(str){
|
|
|
+ self._dc.send(str);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ this._dc.send(blob);
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|