/js/lib/Socket.IO-node/support/socket.io-client/lib/transport.js
JavaScript | 142 lines | 115 code | 19 blank | 8 comment | 25 complexity | e0995767d65c44d423bf2e1cc9d2b3ab MD5 | raw file
1/** 2 * Socket.IO client 3 * 4 * @author Guillermo Rauch <guillermo@learnboost.com> 5 * @license The MIT license. 6 * @copyright Copyright (c) 2010 LearnBoost <dev@learnboost.com> 7 */ 8 9// abstract 10 11(function(){ 12 var io = this.io; 13 14 var frame = '~m~', 15 16 stringify = function(message){ 17 if (Object.prototype.toString.call(message) == '[object Object]'){ 18 if (!('JSON' in window)){ 19 if ('console' in window && console.error) console.error('Trying to encode as JSON, but JSON.stringify is missing.'); 20 return '{ "$error": "Invalid message" }'; 21 } 22 return '~j~' + JSON.stringify(message); 23 } else { 24 return String(message); 25 } 26 }; 27 28 Transport = io.Transport = function(base, options){ 29 this.base = base; 30 this.options = { 31 timeout: 15000 // based on heartbeat interval default 32 }; 33 io.util.merge(this.options, options); 34 }; 35 36 Transport.prototype.send = function(){ 37 throw new Error('Missing send() implementation'); 38 }; 39 40 Transport.prototype.connect = function(){ 41 throw new Error('Missing connect() implementation'); 42 }; 43 44 Transport.prototype.disconnect = function(){ 45 throw new Error('Missing disconnect() implementation'); 46 }; 47 48 Transport.prototype._encode = function(messages){ 49 var ret = '', message, 50 messages = io.util.isArray(messages) ? messages : [messages]; 51 for (var i = 0, l = messages.length; i < l; i++){ 52 message = messages[i] === null || messages[i] === undefined ? '' : stringify(messages[i]); 53 ret += frame + message.length + frame + message; 54 } 55 return ret; 56 }; 57 58 Transport.prototype._decode = function(data){ 59 var messages = [], number, n; 60 do { 61 if (data.substr(0, 3) !== frame) return messages; 62 data = data.substr(3); 63 number = '', n = ''; 64 for (var i = 0, l = data.length; i < l; i++){ 65 n = Number(data.substr(i, 1)); 66 if (data.substr(i, 1) == n){ 67 number += n; 68 } else { 69 data = data.substr(number.length + frame.length); 70 number = Number(number); 71 break; 72 } 73 } 74 messages.push(data.substr(0, number)); // here 75 data = data.substr(number); 76 } while(data !== ''); 77 return messages; 78 }; 79 80 Transport.prototype._onData = function(data){ 81 this._setTimeout(); 82 var msgs = this._decode(data); 83 if (msgs && msgs.length){ 84 for (var i = 0, l = msgs.length; i < l; i++){ 85 this._onMessage(msgs[i]); 86 } 87 } 88 }; 89 90 Transport.prototype._setTimeout = function(){ 91 var self = this; 92 if (this._timeout) clearTimeout(this._timeout); 93 this._timeout = setTimeout(function(){ 94 self._onTimeout(); 95 }, this.options.timeout); 96 }; 97 98 Transport.prototype._onTimeout = function(){ 99 this._onDisconnect(); 100 }; 101 102 Transport.prototype._onMessage = function(message){ 103 if (!this.sessionid){ 104 this.sessionid = message; 105 this._onConnect(); 106 } else if (message.substr(0, 3) == '~h~'){ 107 this._onHeartbeat(message.substr(3)); 108 } else if (message.substr(0, 3) == '~j~'){ 109 this.base._onMessage(JSON.parse(message.substr(3))); 110 } else { 111 this.base._onMessage(message); 112 } 113 }, 114 115 Transport.prototype._onHeartbeat = function(heartbeat){ 116 this.send('~h~' + heartbeat); // echo 117 }; 118 119 Transport.prototype._onConnect = function(){ 120 this.connected = true; 121 this.connecting = false; 122 this.base._onConnect(); 123 this._setTimeout(); 124 }; 125 126 Transport.prototype._onDisconnect = function(){ 127 this.connecting = false; 128 this.connected = false; 129 this.sessionid = null; 130 this.base._onDisconnect(); 131 }; 132 133 Transport.prototype._prepareUrl = function(){ 134 return (this.base.options.secure ? 'https' : 'http') 135 + '://' + this.base.host 136 + ':' + this.base.options.port 137 + '/' + this.base.options.resource 138 + '/' + this.type 139 + (this.sessionid ? ('/' + this.sessionid) : '/'); 140 }; 141 142})();