mirror of
https://github.com/socketio/socket.io.git
synced 2026-04-30 03:00:39 -04:00
141 lines
3.6 KiB
JavaScript
141 lines
3.6 KiB
JavaScript
/**
|
|
* Socket.IO client
|
|
*
|
|
* @author Guillermo Rauch <guillermo@learnboost.com>
|
|
* @license The MIT license.
|
|
* @copyright Copyright (c) 2010 LearnBoost <dev@learnboost.com>
|
|
*/
|
|
|
|
// abstract
|
|
|
|
(function(){
|
|
|
|
var frame = '~m~',
|
|
|
|
stringify = function(message){
|
|
if (Object.prototype.toString.call(message) == '[object Object]'){
|
|
if (!('JSON' in window)){
|
|
if ('console' in window && console.error) console.error('Trying to encode as JSON, but JSON.stringify is missing.');
|
|
return '{ "$error": "Invalid message" }';
|
|
}
|
|
return '~j~' + JSON.stringify(message);
|
|
} else {
|
|
return String(message);
|
|
}
|
|
};
|
|
|
|
Transport = io.Transport = function(base, options){
|
|
this.base = base;
|
|
this.options = {
|
|
timeout: 15000 // based on heartbeat interval default
|
|
};
|
|
io.util.merge(this.options, options);
|
|
};
|
|
|
|
Transport.prototype.send = function(){
|
|
throw new Error('Missing send() implementation');
|
|
};
|
|
|
|
Transport.prototype.connect = function(){
|
|
throw new Error('Missing connect() implementation');
|
|
};
|
|
|
|
Transport.prototype.disconnect = function(){
|
|
throw new Error('Missing disconnect() implementation');
|
|
};
|
|
|
|
Transport.prototype._encode = function(messages){
|
|
var ret = '', message,
|
|
messages = io.util.isArray(messages) ? messages : [messages];
|
|
for (var i = 0, l = messages.length; i < l; i++){
|
|
message = messages[i] === null || messages[i] === undefined ? '' : stringify(messages[i]);
|
|
ret += frame + message.length + frame + message;
|
|
}
|
|
return ret;
|
|
};
|
|
|
|
Transport.prototype._decode = function(data){
|
|
var messages = [], number, n;
|
|
do {
|
|
if (data.substr(0, 3) !== frame) return messages;
|
|
data = data.substr(3);
|
|
number = '', n = '';
|
|
for (var i = 0, l = data.length; i < l; i++){
|
|
n = Number(data.substr(i, 1));
|
|
if (data.substr(i, 1) == n){
|
|
number += n;
|
|
} else {
|
|
data = data.substr(number.length + frame.length);
|
|
number = Number(number);
|
|
break;
|
|
}
|
|
}
|
|
messages.push(data.substr(0, number)); // here
|
|
data = data.substr(number);
|
|
} while(data !== '');
|
|
return messages;
|
|
};
|
|
|
|
Transport.prototype._onData = function(data){
|
|
this._setTimeout();
|
|
var msgs = this._decode(data);
|
|
if (msgs && msgs.length){
|
|
for (var i = 0, l = msgs.length; i < l; i++){
|
|
this._onMessage(msgs[i]);
|
|
}
|
|
}
|
|
};
|
|
|
|
Transport.prototype._setTimeout = function(){
|
|
var self = this;
|
|
if (this._timeout) clearTimeout(this._timeout);
|
|
this._timeout = setTimeout(function(){
|
|
self._onTimeout();
|
|
}, this.options.timeout);
|
|
};
|
|
|
|
Transport.prototype._onTimeout = function(){
|
|
this._onDisconnect();
|
|
};
|
|
|
|
Transport.prototype._onMessage = function(message){
|
|
if (!this.sessionid){
|
|
this.sessionid = message;
|
|
this._onConnect();
|
|
} else if (message.substr(0, 3) == '~h~'){
|
|
this._onHeartbeat(message.substr(3));
|
|
} else if (message.substr(0, 3) == '~j~'){
|
|
this.base._onMessage(JSON.parse(message.substr(3)));
|
|
} else {
|
|
this.base._onMessage(message);
|
|
}
|
|
},
|
|
|
|
Transport.prototype._onHeartbeat = function(heartbeat){
|
|
this.send('~h~' + heartbeat); // echo
|
|
};
|
|
|
|
Transport.prototype._onConnect = function(){
|
|
this.connected = true;
|
|
this.connecting = false;
|
|
this.base._onConnect();
|
|
this._setTimeout();
|
|
};
|
|
|
|
Transport.prototype._onDisconnect = function(){
|
|
this.connecting = false;
|
|
this.connected = false;
|
|
this.sessionid = null;
|
|
this.base._onDisconnect();
|
|
};
|
|
|
|
Transport.prototype._prepareUrl = function(){
|
|
return (this.base.options.secure ? 'https' : 'http')
|
|
+ '://' + this.base.host
|
|
+ ':' + this.base.options.port
|
|
+ '/' + this.base.options.resource
|
|
+ '/' + this.type
|
|
+ (this.sessionid ? ('/' + this.sessionid) : '/');
|
|
};
|
|
|
|
})(); |