4 * @author Guillermo Rauch <guillermo@learnboost.com>
5 * @license The MIT license.
6 * @copyright Copyright (c) 2010 LearnBoost <dev@learnboost.com>
15 stringify = function(message){
16 if (Object.prototype.toString.call(message) == '[object Object]'){
17 if (!('JSON' in window)){
18 if ('console' in window && console.error) console.error('Trying to encode as JSON, but JSON.stringify is missing.');
19 return '{ "$error": "Invalid message" }';
21 return '~j~' + JSON.stringify(message);
23 return String(message);
27 Transport = io.Transport = function(base, options){
30 timeout: 15000 // based on heartbeat interval default
32 io.util.merge(this.options, options);
35 Transport.prototype.send = function(){
36 throw new Error('Missing send() implementation');
39 Transport.prototype.connect = function(){
40 throw new Error('Missing connect() implementation');
43 Transport.prototype.disconnect = function(){
44 throw new Error('Missing disconnect() implementation');
47 Transport.prototype._encode = function(messages){
48 var ret = '', message,
49 messages = io.util.isArray(messages) ? messages : [messages];
50 for (var i = 0, l = messages.length; i < l; i++){
51 message = messages[i] === null || messages[i] === undefined ? '' : stringify(messages[i]);
52 ret += frame + message.length + frame + message;
57 Transport.prototype._decode = function(data){
58 var messages = [], number, n;
60 if (data.substr(0, 3) !== frame) return messages;
61 data = data.substr(3);
63 for (var i = 0, l = data.length; i < l; i++){
64 n = Number(data.substr(i, 1));
65 if (data.substr(i, 1) == n){
68 data = data.substr(number.length + frame.length);
69 number = Number(number);
73 messages.push(data.substr(0, number)); // here
74 data = data.substr(number);
79 Transport.prototype._onData = function(data){
81 var msgs = this._decode(data);
82 if (msgs && msgs.length){
83 for (var i = 0, l = msgs.length; i < l; i++){
84 this._onMessage(msgs[i]);
89 Transport.prototype._setTimeout = function(){
91 if (this._timeout) clearTimeout(this._timeout);
92 this._timeout = setTimeout(function(){
94 }, this.options.timeout);
97 Transport.prototype._onTimeout = function(){
101 Transport.prototype._onMessage = function(message){
102 if (!this.sessionid){
103 this.sessionid = message;
105 } else if (message.substr(0, 3) == '~h~'){
106 this._onHeartbeat(message.substr(3));
107 } else if (message.substr(0, 3) == '~j~'){
108 this.base._onMessage(JSON.parse(message.substr(3)));
110 this.base._onMessage(message);
114 Transport.prototype._onHeartbeat = function(heartbeat){
115 this.send('~h~' + heartbeat); // echo
118 Transport.prototype._onConnect = function(){
119 this.connected = true;
120 this.connecting = false;
121 this.base._onConnect();
125 Transport.prototype._onDisconnect = function(){
126 this.connecting = false;
127 this.connected = false;
128 this.sessionid = null;
129 this.base._onDisconnect();
132 Transport.prototype._prepareUrl = function(){
133 return (this.base.options.secure ? 'https' : 'http')
134 + '://' + this.base.host
135 + ':' + this.base.options.port
136 + '/' + this.base.options.resource
138 + (this.sessionid ? ('/' + this.sessionid) : '/');