Inital Commit
[oweals/finalsclub.git] / bruml / lib / socket.io / support / socket.io-client / lib / transport.js
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         
13         var frame = '~m~',
14         
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" }';
20                         }
21                         return '~j~' + JSON.stringify(message);
22                 } else {
23                         return String(message);
24                 }
25         };
26         
27         Transport = io.Transport = function(base, options){
28                 this.base = base;
29                 this.options = {
30                         timeout: 15000 // based on heartbeat interval default
31                 };
32                 io.util.merge(this.options, options);
33         };
34
35         Transport.prototype.send = function(){
36                 throw new Error('Missing send() implementation');
37         };
38
39         Transport.prototype.connect = function(){
40                 throw new Error('Missing connect() implementation');
41         };
42
43         Transport.prototype.disconnect = function(){
44                 throw new Error('Missing disconnect() implementation');
45         };
46         
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;
53                 }
54                 return ret;
55         };
56         
57         Transport.prototype._decode = function(data){
58                 var messages = [], number, n;
59                 do {
60                         if (data.substr(0, 3) !== frame) return messages;
61                         data = data.substr(3);
62                         number = '', n = '';
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){
66                                         number += n;
67                                 } else {        
68                                         data = data.substr(number.length + frame.length);
69                                         number = Number(number);
70                                         break;
71                                 } 
72                         }
73                         messages.push(data.substr(0, number)); // here
74                         data = data.substr(number);
75                 } while(data !== '');
76                 return messages;
77         };
78         
79         Transport.prototype._onData = function(data){
80                 this._setTimeout();
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]);
85                         }
86                 }
87         };
88         
89         Transport.prototype._setTimeout = function(){
90                 var self = this;
91                 if (this._timeout) clearTimeout(this._timeout);
92                 this._timeout = setTimeout(function(){
93                         self._onTimeout();
94                 }, this.options.timeout);
95         };
96         
97         Transport.prototype._onTimeout = function(){
98                 this._onDisconnect();
99         };
100         
101         Transport.prototype._onMessage = function(message){
102                 if (!this.sessionid){
103                         this.sessionid = message;
104                         this._onConnect();
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)));
109                 } else {
110                         this.base._onMessage(message);
111                 }
112         },
113         
114         Transport.prototype._onHeartbeat = function(heartbeat){
115                 this.send('~h~' + heartbeat); // echo
116         };
117         
118         Transport.prototype._onConnect = function(){
119                 this.connected = true;
120                 this.connecting = false;
121                 this.base._onConnect();
122                 this._setTimeout();
123         };
124
125         Transport.prototype._onDisconnect = function(){
126                 this.connecting = false;
127                 this.connected = false;
128                 this.sessionid = null;
129                 this.base._onDisconnect();
130         };
131
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
137                         + '/' + this.type
138                         + (this.sessionid ? ('/' + this.sessionid) : '/');
139         };
140
141 })();