renamed xhr.js to http_streaming.js and move hbit to externa heartbit.js file
[brisk.git] / web / http_streaming.js
1 /*
2  *  brisk - http_streaming.js
3  *
4  *  Copyright (C) 2006-2011 Matteo Nastasi
5  *                          mailto: nastasi@alternativeoutput.it 
6  *                                  matteo.nastasi@milug.org
7  *                          web: http://www.alternativeoutput.it
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABLILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * General Public License for more details. You should have received a
18  * copy of the GNU General Public License along with this program; if
19  * not, write to the Free Software Foundation, Inc, 59 Temple Place -
20  * Suite 330, Boston, MA 02111-1307, USA.
21  *
22  * TODO:
23  *
24  *   MANDATORY
25  *
26  *   NOT MANDATORY
27  *   - gst management
28  *   - sandbox management
29  *   - myfrom into the constructor
30  *   - target page into the constructor
31  *   - type of streaming into the constructor
32  *   - all iframe related streaming add
33  *   - substitute fixed "eval" with a generic command hunks processor
34  *
35  *   DONE - xhr_rd prefix remove from inner class attrs
36  *   DONE - move hbit implementation to external file
37  *
38  */
39
40 function http_streaming(cookiename)
41 {
42     this.xhr = createXMLHttpRequest();
43     // this.xhr.setRequestHeader("Content-type", "text/html; charset=utf-8");
44     this.cookiename = cookiename;
45 }
46
47 http_streaming.prototype = {
48     cookiename: null,
49     cookiepath: "/brisk/",
50     xhr: null,
51     watchdog: null,
52     delay: 0,
53     delayed: null,
54     stopped: true,
55     the_end: false,
56     oldctx: "",
57     newctx: "",
58     cur_n: -1,
59     old_n: -1,
60     checkedlen: 0,
61     /* watchdog_old: 0, */
62     ct: 0,
63
64     hbit: function () {
65     },
66
67     hbit_set: function (hbit) {
68         this.hbit = hbit;
69     },
70
71     xhr_cb: function () {
72         var ret;
73         
74         if (this.xhr.readyState == 4) {
75             if (this.watchdog != null) {
76                 this.hbit('C');
77                 clearTimeout(this.watchdog);
78                 this.watchdog = null;
79             }
80             
81             // console.log("SS: "+safestatus(xhr));
82             
83             try {
84                 if ((ret = safestatus(this.xhr)) == 200) {
85                     this.delay = 0;
86                     // console.log("del a null "+this.delayed);
87                 } else if (ret != -1) {
88                     this.delay = 5000;
89                     this.hbit('X');
90                     // alert('There was a problem with the request.' + ret);
91                 }
92             } catch(b) {};
93             
94             this.delayed = null;
95             this.stopped = true;
96         }
97     },
98
99     xhr_abort: function()
100     {
101         this.hbit('A');
102         if (this.xhr != null)
103             this.xhr.abort();
104         // alert("de che");
105     },
106
107     run: function(sess, stat, subst, step) 
108     {
109         if (this.the_end) {
110             //x alert("the_end1");
111             if (this.watchdog != null) {
112                 this.hbit('C');
113                 clearTimeout(this.watchdog);
114                 this.watchdog = null;
115             }
116             return;
117         }
118         createCookie(this.cookie_name, sess, 24*365, this.cookiepath);
119         
120         // NOTE: *ctx = "" to prevent konqueror stream commands duplication.
121         this.oldctx = "";
122         this.newctx = "";
123         
124         /* NOTE document.uniqueID exists only under IE  */
125         // if (g_is_spawn == 1)
126         // alert("di qui3: "+(g_is_spawn == 1 ? "&table_idx="+g_table_idx : ""));
127         this.xhr.open('GET', 'index_rd.php?sess='+sess+"&stat="+stat+"&subst="+subst+"&step="+step+"&onlyone="+(document.uniqueID ? "TRUE" : "FALSE")+"&myfrom="+myfrom, true);
128         //    try { 
129
130         var self = this;
131         this.xhr.onreadystatechange = function () { self.xhr_cb(); };
132         this.xhr.send(null);
133         // 
134         // TODO: qui avvio del timer per riavviare xhr
135         // 
136         this.watchdog = setTimeout(function(obj){ obj.xhr_abort(); }, 60000, this);
137         this.cur_n++;
138         this.stopped = false;
139         // } catch (e) {}
140     },
141     
142     /* WORK HERE TO RUN WIN OR LIN STREAM */
143     
144     start: function(sess)
145     {
146         this.poll(sess);
147     },
148
149     stop: function()
150     {
151         this.the_end = true;
152     },
153
154     poll: function(sess)
155     {
156         var tout = 100;
157         var again;
158         var xhrrestart;
159         
160         this.ct++;
161         
162         /*
163           if (this.watchdog_old >= 50) {
164           this.watchdog_old = 0;
165           // alert("ABORT XHR");
166           this.stopped = true;
167           this.xhr.abort();     
168           }
169         */
170         var zug = "POLL sess = "+sess+" stat = "+stat+" subst = "+subst+" step = "+gst.st+" step_loc = "+gst.st_loc+" step_loc_new = "+gst.st_loc_new+" STOP: "+this.stopped;
171         
172         if (zug != $("sandbox").innerHTML)
173             $("sandbox").innerHTML = zug;
174         
175         /* heartbit log */
176         this.hbit("_");
177         do {
178             again = 0;
179             xhrrestart = 0;
180             if (gst.st_loc < gst.st_loc_new) {
181                 // there is some slow actions running
182                 break;
183             }
184             else if (gst.comms.length > 0) {
185                 var singlecomm;
186                 
187                 singlecomm = gst.comms.shift();
188                 // alert("EXE"+gugu);
189                 // $("xhrdeltalog").innerHTML = "EVALL: "+singlecomm.replace("<", "&lt;", "g"); +"<br>";
190                 this.hbit("+");
191                 
192                 eval(singlecomm);
193                 again = 1;
194             }
195             else {
196                 xhrrestart = 1;
197                 try { 
198                     if (this.xhr == null)
199                         throw "restart";
200                     if (this.xhr.responseText != null)
201                         this.newctx = this.xhr.responseText;
202                 }
203                 catch (e) {
204                     if (this.stopped == true) {
205                         this.stopped = false;
206                         // XX $("xhrstart").innerHTML += "XHRSTART: da catch<br>";
207                         if (this.delay > 0) {
208                             if (this.delayed == null) {
209                                 // console.log("XXX DI QUI "+this.delay);
210
211                                 this.delayed = setTimeout(
212                                     function(f_obj, f_sess, f_stat, f_subst, f_step){ f_obj.run(f_sess, f_stat, f_subst, f_step); },
213                                     this.delay, this, sess, stat, subst, gst.st);
214                                 // console.log("XXX DI QUI post"+this.delayed);
215                             }
216                         }
217                         else {
218                             // console.log("yyy DI QUI "+this.delay);
219                             this.run(sess, stat, subst, gst.st);
220                         }
221                     }
222                     
223                     
224                     // $("sandbox").innerHTML += "return 1<br>";
225                     if (this.the_end != true) {
226                         /* this.watchdog_old = 0; */
227                         setTimeout(function(obj, sess){ obj.poll(sess); }, tout, this, sess);
228                         
229                         // this.hbit(".");
230                         
231                     }
232                     else {
233                         //x alert("the_end2");
234                         if (this.watchdog != null) {
235                             clearTimeout(this.watchdog);
236                             this.watchdog = null;
237                         }
238                     }    
239                     return;
240                 }
241                 
242                 
243                 // no new char from the last loop, break
244                 if (this.old_n == this.cur_n && 
245                     this.newctx.length == this.checkedlen) {
246                     /* this.watchdog++; */
247                     break;
248                 }
249                 else {
250                     // $("sandbox").innerHTML += "BIG IF<br>";
251                     var comm_match;
252                     var comm_clean;
253                     var comm_len;
254                     var comm_newpart;
255                     var comm_arr;
256                     var i;
257                     var delta = 0;
258                     var match_lines = /^_*$/;
259                     
260                     /* this.watchdog = 0; */
261                     this.hbit("/\\");
262                     
263                     // check for the same command group
264                     if (this.old_n != this.cur_n) {
265                         this.old_n = this.cur_n;
266                         this.checkedlen = 0;
267                         this.oldctx = "";
268                     }
269                     else
270                         delta = this.oldctx.length;
271                     
272                     // $("xhrlog").innerHTML += "EVERY SEC<br>";                
273                     for (i = delta ; i < this.newctx.length ; i++) {
274                         if (this.newctx[i] != '_') 
275                             break;
276                     }
277                     if (i == this.newctx.length) {
278                         this.checkedlen = i;
279                         break;
280                     }
281                     
282                     // $("xhrlog").innerHTML += "CHECK COM<br>";                
283                     // extracts the new part of the command string
284                     comm_newpart = this.newctx.substr(delta);
285                     
286                     // XX $("xhrlog").innerHTML = newctx.replace("<", "&lt;", "g");
287                     
288                     // $("response").innerHTML = comm_newpart;
289                     comm_match = /_*@BEGIN@(.*?)@END@/g;
290                     comm_clean = /_*@BEGIN@(.*?)@END@/;
291                     comm_len = 0;
292                     comm_arr = comm_newpart.match(comm_match);
293                     
294                     // $("sandbox").innerHTML += "PRE COMMARR<br>";
295                     if (comm_arr) {
296                         // XX $("xhrdeltalog").innerHTML += "DELTA: "+delta +"<br>";
297                         // XX alert("newctx: "+this.newctx);
298                         // $("sandbox").innerHTML += "POST COMMARR<br>";
299                         for (i = 0 ; i < comm_arr.length ; i++) {
300                             var temp = comm_arr[i].replace(comm_clean,"$1").split("|");
301                             gst.comms = gst.comms.concat(temp);
302                             // XX alert("COMM_ARR["+i+"]: "+comm_arr[i]+"  LEN:"+comm_arr[i].length);
303                             comm_len += comm_arr[i].length;
304                         }
305                         tout = 0;
306                         this.oldctx += comm_newpart.substr(0,comm_len);
307                         // XX alert("OLDCTX: "+this.oldctx);
308                         again = 1;
309                     }
310                     this.checkedlen = this.oldctx.length;
311                 }
312             }
313         } while (again);
314
315         if (xhrrestart == 1 && this.stopped == true) {
316             // $("sandbox").innerHTML += "LITTLE IF<br>";
317             // alert("di qui");
318             // XX $("xhrstart").innerHTML += "XHRSTART: da end poll<br>";
319             if (this.delay > 0) {
320                 if (this.delayed == null) {
321                     // console.log("XXX DI QUO "+this.delay);
322                     
323                     this.delayed = setTimeout(
324                         function(obj, sess, stat, subst, step){ obj.run(sess, stat, subst, step); },
325                         this.delay, this, sess, stat, subst, gst.st);
326                     // console.log("XXX DI QUO post"+this.delayed);
327                 }
328             }
329             else {
330                 // console.log("yyy DI QUO "+this.delay);
331                 this.run(sess, stat, subst, gst.st);
332             }
333             
334         }
335         
336         if (this.the_end != true) {
337             setTimeout(function(obj, sess){ obj.poll(sess); }, tout, this, sess);
338         }
339         else {
340             //x alert("the_end3");
341             if (this.watchdog != null) {
342                 clearTimeout(this.watchdog);
343                 this.watchdog = null;
344             }
345         }
346         return;
347     }
348 }
349     
350 /*
351   window.onload = function () {
352   xhr = createXMLHttpRequest();
353
354   sess = $("user").value;
355   window.setTimeout(poll, 0, sess);
356   };
357 */