a144f1cbda4890b9088cce9e450e56bf8198f09e
[brisk.git] / web / xynt-streaming.js
1 // old targetpage == page and moved into start method
2
3 //
4 // CLASS transport_ws
5 //
6 function transport_ws(doc, xynt_streaming, page)
7 {
8     // if four arguments manage if WS or WSS connection
9     if (arguments.length > 3)
10         this.is_secure = arguments[3];
11     else
12         this.is_secure = false;
13
14     if (this.is_secure)
15         this.name = "WebSocketSecure";
16     else
17         this.name = "WebSocket";
18     this.ctx_new = "";
19     var self = this;
20
21     this.doc = doc;
22     this.failed = false;
23     this.xynt_streaming = xynt_streaming;
24     try {
25         this.xynt_streaming.log("PAGE: "+page);
26         this.ws = new WebSocket(page);
27         this.ws.onopen = function () {
28             self.xynt_streaming.log("onopen");
29             if (this.readyState == 1) {
30                 // connected
31                 self.ws_cb("open");
32                 self.init_steps = 1;
33             }
34         };
35         this.ws.onmessage = function (msg) {
36             self.xynt_streaming.log("onmessage");
37             // new data in msg.data
38             self.ctx_new += msg.data;
39         };
40         this.ws.onclose = function (msg) {
41             this.onopen  = null;
42             this.onclose = null;
43             this.onerror = null;
44             self.xynt_streaming.log("onclose"+self.init_steps);
45             if (self.init_steps == 0)
46                 self.ws_cb("error");
47             else
48                 self.ws_cb("close");
49         };
50         this.ws.onerror = function () {
51             // on error
52             this.onopen  = null;
53             this.onclose = null;
54             this.onerror = null;
55             self.xynt_streaming.log("onerror");
56             self.ws_cb("error");
57         };
58     }
59     catch (ex) {
60         throw "websocket creation failed";
61     }
62
63     this.stopped = false;
64 }
65
66 transport_ws.prototype = {
67     doc: null,
68     name: null,
69     xynt_streaming: "ready",
70     ws: null,
71     stopped: true,
72     failed: false,
73
74     init_steps: 0,
75
76     ctx_old: "",
77     ctx_old_len: 0,
78     ctx_new: "",
79
80     // script_clean: 0,
81
82     destroy: function () { /* public */
83         if (this.ws != null) {
84             this.ws_abort();
85         }
86         delete this.ws;
87     },
88
89     ws_cb: function (from) {
90         var ret;
91
92         if (from == "error") {
93             if (this.xynt_streaming != "ready") {
94                 if (this.xynt_streaming.transp_fback > 0) {
95 this.xynt_streaming.log("DEC: "+this.xynt_streaming.transp_fback);
96                     this.xynt_streaming.transp_fback--;
97                     this.stopped = true;
98                     this.xynt_streaming.reload();
99                 }
100             }
101         }
102         if (this.ws != null && this.ws.readyState > 1) {
103             this.stopped = true;
104         }
105     },
106
107     ws_abort: function() {
108         if (this.ws != null) {
109 this.xynt_streaming.log("WSCLOSE");
110             this.ws.close();
111         }
112     },
113
114     xstr_is_init: function () { /* public */
115         return (true);
116     },
117
118     /* only after a successfull is_initialized call */
119     xstr_is_ready: function () { /* public */
120         return (this.ws.readyState == 1);
121     },
122
123     xstr_set: function () { /* public */
124         // already set
125     },
126
127     ctx_new_is_set: function () { /* public */
128         return (this.ctx_new != null);
129     },
130
131     ctx_new_curlen_get: function () { /* public */
132         return (this.ctx_new.length);
133     },
134
135     ctx_new_getchar: function(idx) { /* public */
136         return (this.ctx_new[idx]);
137     },
138
139     ctx_old_len_is_set: function () { /* public */
140         return (true);
141     },
142
143     ctx_old_len_get: function () { /* public */
144         return (this.ctx_old_len);
145     },
146
147     ctx_old_len_set: function (len) { /* public */
148         this.ctx_old_len = len;
149     },
150
151     ctx_old_len_add: function (len) { /* public */
152         this.ctx_old_len += len;
153     },
154
155     new_part: function () { /* public */
156         return (this.ctx_new.substr(this.ctx_old_len));
157     },
158
159     scrcls_set: function (step) { /* public */
160         // this.script_clean = step;
161     },
162
163     postproc: function () {
164         if (this.stopped && !this.xstr_is_ready()) {
165             this.xynt_streaming.reload();
166         }
167     }
168 }
169
170 //
171 // CLASS transport_xhr
172 //
173 function transport_xhr(doc, xynt_streaming, page)
174 {
175     this.name = "XHR";
176     this.doc = doc;
177     this.xynt_streaming = xynt_streaming;
178     this.xhr = createXMLHttpRequest();
179     this.xhr.open('GET', page);
180
181     var self = this;
182     this.xhr.onreadystatechange = function () { self.xhr_cb(); };
183     this.xhr.send(null);
184
185     this.stopped = false;
186 }
187
188 transport_xhr.prototype = {
189     doc: null,
190     name: null,
191     xynt_streaming: "ready",
192     xhr: null,
193     stopped: true,
194
195     ctx_old: "",
196     ctx_old_len: 0,
197     ctx_new: null,
198
199     // script_clean: 0,
200
201     destroy: function () { /* public */
202         if (this.xhr != null) {
203             this.xhr_abort();
204         }
205         delete this.xhr;
206     },
207
208     xhr_cb: function () {
209         var ret;
210
211         if (this.xhr.readyState == 4) {
212             // console.log("SS: "+safestatus(xhr));
213
214             // NOTE: delay management later
215             // try {
216             //     if ((ret = safestatus(this.xhr)) == 200) {
217             //         this.delay = 0;
218             //         // console.log("del a null "+this.delayed);
219             //     } else if (ret != -1) {
220             //         this.delay = 5000;
221             //         this.hbit('X');
222             //         // alert('There was a problem with the request.' + ret);
223             //     }
224             // } catch(b) {};
225
226             // this.delayed = null;
227             this.stopped = true;
228         }
229     },
230
231     xhr_abort: function() {
232         if (this.xhr != null) {
233             this.xhr.abort();
234         }
235     },
236
237     xstr_is_init: function () { /* public */
238         try {
239             if (this.xhr.responseText != null) {
240                 this.ctx_new = this.xhr.responseText;
241             }
242         }
243         catch (e) {
244         }
245
246         return (this.ctx_new != null);
247     },
248
249     /* only after a successfull is_initialized call */
250     xstr_is_ready: function () { /* public */
251         return (this.xynt_streaming == "ready");
252     },
253
254     xstr_set: function () { /* public */
255         // already set
256     },
257
258     ctx_new_is_set: function () { /* public */
259         return (this.ctx_new != null);
260     },
261
262     ctx_new_curlen_get: function () { /* public */
263         return (this.ctx_new.length);
264     },
265
266     ctx_new_getchar: function(idx) { /* public */
267         return (this.ctx_new[idx]);
268     },
269
270     ctx_old_len_is_set: function () { /* public */
271         return (true);
272     },
273
274     ctx_old_len_get: function () { /* public */
275         return (this.ctx_old_len);
276     },
277
278     ctx_old_len_set: function (len) { /* public */
279         this.ctx_old_len = len;
280     },
281
282     ctx_old_len_add: function (len) { /* public */
283         this.ctx_old_len += len;
284     },
285
286     new_part: function () { /* public */
287         return (this.ctx_new.substr(this.ctx_old_len));
288     },
289
290     scrcls_set: function (step) { /* public */
291         // this.script_clean = step;
292     },
293
294     postproc: function () {
295         if (this.stopped && !this.xstr_is_ready()) {
296             this.xynt_streaming.reload();
297         }
298     }
299 }
300
301 //
302 // CLASS transport_htmlfile
303 //
304 function transport_htmlfile(doc, xynt_streaming, page)
305 {
306     this.name = "HTMLFile";
307     this.doc = doc;
308     this.xynt_streaming = xynt_streaming;
309     this.transfdoc = new ActiveXObject("htmlfile");
310     this.transfdoc.open();
311     this.transfdoc.write("<html><body><iframe id='iframe'></iframe></body></html>");
312     this.transfdoc.close();
313
314     this.ifra = this.transfdoc.getElementById("iframe");
315     this.ifra.contentWindow.location.href = page;
316     this.stopped = false;
317 }
318
319 transport_htmlfile.prototype = {
320     doc: null,
321     name: null,
322     xynt_streaming: null,
323     stopped: true,
324     ifra: null,
325     tradoc: null,
326
327     destroy: function () { /* public */
328         if (this.ifra != null) {
329         //     this.doc.body.removeChild(this.ifra);
330         //     delete this.ifra;
331              this.ifra = null;
332         }
333
334         if (this.transfdoc) {
335             delete this.transfdoc;
336             this.transfdoc = null;
337         }
338     },
339
340     xstr_is_init: function () { /* public */
341         return (typeof(this.ifra.contentWindow.xynt_streaming) != 'undefined');
342     },
343
344     /* only after a successfull is_initialized call */
345     xstr_is_ready: function () { /* public */
346         return (this.ifra.contentWindow.xynt_streaming == "ready");
347     },
348
349     /* only after a successfull is_initialized call */
350     xstr_set: function () { /* public */
351         if (this.ifra.contentWindow.xynt_streaming == "ready") {
352             this.ifra.contentWindow.xynt_streaming = this.xynt_streaming;
353             return (true);
354         }
355         else if (this.ifra.contentWindow.xynt_streaming == this.xynt_streaming) {
356             return (true);
357         }
358         else {
359             return (false);
360         }
361     },
362
363     ctx_new_is_set: function () { /* public */
364         return (typeof(this.ifra.contentWindow.ctx_new) != 'undefined');
365     },
366
367     ctx_new_curlen_get: function () { /* public */
368         return (this.ifra.contentWindow.ctx_new.length);
369     },
370
371     ctx_new_getchar: function(idx) { /* public */
372         return (this.ifra.contentWindow.ctx_new.charAt(idx));
373     },
374
375     ctx_old_len_is_set: function () { /* public */
376         return (typeof(this.ifra.contentWindow.ctx_old_len) != 'undefined');
377     },
378
379     ctx_old_len_get: function () { /* public */
380         return (this.ifra.contentWindow.ctx_old_len);
381     },
382
383     ctx_old_len_set: function (len) { /* public */
384         this.ifra.contentWindow.ctx_old_len = len;
385     },
386
387     ctx_old_len_add: function (len) { /* public */
388         this.ifra.contentWindow.ctx_old_len += len;
389     },
390
391     new_part: function () { /* public */
392         return (this.ifra.contentWindow.ctx_new.substr(this.ifra.contentWindow.ctx_old_len));
393     },
394
395     scrcls_set: function (step) { /* public */
396         this.ifra.contentWindow.script_clean = step;
397     },
398
399     postproc: function () { /* public */
400         if (this.stopped && !this.xstr_is_ready()) {
401             this.xynt_streaming.reload();
402         }
403     }
404 }
405
406 //
407 // CLASS transport_iframe
408 //
409 function transport_iframe(doc, xynt_streaming, page)
410 {
411     this.name = "IFRAME";
412     this.doc = doc;
413     this.xynt_streaming = xynt_streaming;
414     this.ifra = doc.createElement("iframe");
415     this.ifra.style.visibility = "hidden";
416     doc.body.appendChild(this.ifra);
417     this.ifra.contentWindow.location.href = page;
418     this.stopped = false;
419 }
420
421 transport_iframe.prototype = {
422     doc: null,
423     name: null,
424     xynt_streaming: null,
425     stopped: true,
426     ifra: null,
427
428     destroy: function () { /* public */
429         try {
430             if (this.ifra != null) {
431                 // NOTE:  on Opera this remove child crash js if called from
432                 //        inside of the iframe, on IE on Windows without
433                 //        it stream abort fails.
434                 //        the problem is fixed setting into the iframe's onload
435                 //        function the stopped attribute to true and delegate
436                 //        postproc() fired by xynt_streaming watchdog()
437                 this.doc.body.removeChild(this.ifra);
438                 delete this.ifra;
439                 this.ifra = null;
440             }
441         } catch (b) {
442             alert("destroy exception catched");
443         }
444     },
445
446     xstr_is_init: function () { /* public */
447         return (typeof(this.ifra.contentWindow.xynt_streaming) != 'undefined');
448     },
449
450     /* only after a successfull is_initialized call */
451     xstr_is_ready: function () { /* public */
452         return (this.ifra.contentWindow.xynt_streaming == "ready");
453     },
454
455     /* only after a successfull is_initialized call */
456     xstr_set: function () { /* public */
457         if (this.ifra.contentWindow.xynt_streaming == "ready") {
458             this.ifra.contentWindow.xynt_streaming = this.xynt_streaming;
459             return (true);
460         }
461         else if (this.ifra.contentWindow.xynt_streaming == this.xynt_streaming) {
462             return (true);
463         }
464         else {
465             return (false);
466         }
467     },
468
469
470     /* only after a successfull is_ready call to be sure the accessibility of the var */
471     xstr_set_old: function (xynt_streaming) { /* public */
472         this.ifra.contentWindow.xynt_streaming = xynt_streaming;
473     },
474
475     ctx_new_is_set: function () { /* public */
476         return (typeof(this.ifra.contentWindow.ctx_new) != 'undefined');
477     },
478
479     ctx_new_curlen_get: function () { /* public */
480         return (this.ifra.contentWindow.ctx_new.length);
481     },
482
483     ctx_new_getchar: function(idx) { /* public */
484         return (this.ifra.contentWindow.ctx_new.charAt(idx));
485     },
486
487     ctx_old_len_is_set: function () { /* public */
488         return (typeof(this.ifra.contentWindow.ctx_old_len) != 'undefined');
489     },
490
491     ctx_old_len_get: function () { /* public */
492         return (this.ifra.contentWindow.ctx_old_len);
493     },
494
495     ctx_old_len_set: function (len) { /* public */
496         this.ifra.contentWindow.ctx_old_len = len;
497     },
498
499     ctx_old_len_add: function (len) { /* public */
500         this.ifra.contentWindow.ctx_old_len += len;
501     },
502
503     new_part: function () { /* public */
504         return (this.ifra.contentWindow.ctx_new.substr(this.ifra.contentWindow.ctx_old_len));
505     },
506
507     scrcls_set: function (step) { /* public */
508         this.ifra.contentWindow.script_clean = step;
509     },
510
511     postproc: function () { /* public */
512         if (this.stopped && !this.xstr_is_ready()) {
513             this.xynt_streaming.reload();
514         }
515     }
516 }
517
518 function xynt_streaming(win, transp_type, transp_port, transp_fback, console, gst, from, cookiename, sess, sandbox, page, cmdproc)
519 {
520     this.win = win;
521     this.transp_type = transp_type;
522     this.transp_port = transp_port;
523     this.transp_fback = transp_fback;
524     this.console = console;
525     this.gst = gst;
526     this.from = from;
527     this.cookiename = cookiename;
528     this.sess = sess;
529     this.sandbox = sandbox;
530     this.page = page;
531     this.cmdproc = cmdproc;
532     // this.cmdproc = function(com){/* console.log("COM: "+com); */ eval(com);}
533     this.doc = win.document;
534     this.keepalive_old = -1;
535     this.keepalive_new = -1;
536
537     this.mon_errtime = this.keepalives_eq_max * this.watchdog_checktm * this.watchdog_timeout;
538     this.mon_wrntime = this.mon_errtime / 2;
539
540     this.mon_update();
541 }
542
543 xynt_streaming.prototype = {
544     win:               null,
545     transp_type:       null,
546     transp_port:         80,
547     transp_fback:         0,
548     transp:            null,
549     console:           null,
550     gst:               null,
551     from:              null,
552     cookiename:        null,
553     sess:              null,
554     sandbox:           null,
555     page:              null,
556     cmdproc:           null,
557
558     start_time:        0,
559     restart_wait:      5000, // wait restart_wait millisec before begin to check if restart is needed
560
561     doc:               null,
562     cookiepath: "/brisk/",
563     watchdog_hdl:      null,
564     hbit:              function () {},
565     keepalive_old:    -1,
566     keepalive_new:    -1,
567     keepalives_equal:  0,
568     /* NOTE: right watch_timeout value to 100, for devel reasons use 1000 or more */
569     /* restart after  4 * 40 * 100 millisec if server ping is missing => 16secs */
570     keepalives_eq_max: 4,
571     watchdog_checktm:  40,
572     watchdog_timeout:  100,
573     watchdog_ct:       0,
574     watchable:         false,
575     restart_n:         0,
576     comm_match:        /_*@BEGIN@(.*?)@END@/g,
577     comm_clean:        /_*@BEGIN@(.*?)@END@/,
578     stream:            "",
579     the_end:           false,
580
581     mon_time:         -1,
582     mon_wrntime:       0,
583     mon_errtime:       0,
584
585     mon_stat_old:      "",
586
587     mon_update: function()
588     {
589         var date = new Date();
590
591         this.mon_time = date.getTime();
592     },
593
594     /*
595       ping arrives at least every RD_KEEPALIVE_TOUT secs (currently 4 secs)
596
597       return values: 0 unknown
598                      1 ok
599                      2 warning
600                      3 error
601      */
602     mon_status: function()
603     {
604         var delta, date;
605
606         var date = new Date();
607
608         delta = date.getTime() - this.mon_time;
609
610         if (delta < this.mon_wrntime)
611             return 1;
612         else if (delta < this.mon_errtime)
613             return 2;
614         else
615             return 3;
616     },
617
618     start: function() { /* public */
619         var transp_type;
620         var page;
621
622         // this.log("start "+this.transp_type+" "+this.transp_fback);
623         if (this.the_end)
624             return;
625
626         createCookie(this.cookiename, sess, 24*365, this.cookiepath);
627         // alert("start");
628         this.log("xynt_streaming:start restart: "+this.restart_n);
629         this.keepalives_equal = 0;
630
631         // page arrangement
632         this.page = url_complete(this.win.location.href, this.page);
633
634         // DEFAULT TRANSPORT PROTOCOL HERE websocketsec, websocket
635         if (this.transp_fback > 0) {
636             transp_type = "websocketsec";
637             // transp_port = (this.transp_fback == 2 ? 443 : 8080);
638             transp_port = 443;
639         }
640         else {
641             transp_type = this.transp_type;
642             transp_port = this.transp_port;
643         }
644
645         if (transp_type == "websocket" || transp_type == "websocketsec") {
646             var end_proto, first_slash, newpage;
647
648             // change protocol
649             this.log("precha ["+this.page+"]");
650             if (transp_type == "websocketsec") {
651                 newpage = this.page.replace(/\.php$/g, "_wss.php").replace(/\.php\?/g, "_wss.php?");
652                 }
653             else {
654                 newpage = this.page;
655                 }
656             end_proto = newpage.indexOf("://");
657             first_slash = newpage.substring(end_proto+3).indexOf("/");
658
659             page = (transp_type == "websocketsec" ? "wss://" : "ws://")
660                 + newpage.substring(end_proto+3, end_proto+3 + first_slash) + ":"
661                 + transp_port + newpage.substring(end_proto+3 + first_slash);
662             // this.log("MOP WS: " + page);
663         }
664         else {
665             page = this.page;
666         }
667         // stat, subst, this.gst.st
668
669         page = url_append_args(page, "sess", this.sess, "stat", stat, "subst", subst, "step", this.gst.st, "from", this.from);
670         // this.log("the page:");
671         // this.log(page);
672
673         try {
674             // transport instantiation
675             if (transp_type == "websocketsec") {
676                 page = url_append_args(page, "transp", "websocketsec");
677                 this.transp = new transport_ws(this.doc, this, page, true);
678             }
679             else if (transp_type == "websocket") {
680                 page = url_append_args(page, "transp", "websocket");
681                 this.transp = new transport_ws(this.doc, this, page);
682             }
683             else if (transp_type == "xhr") {
684                 page = url_append_args(page, "transp", "xhr");
685                 this.transp = new transport_xhr(this.doc, this, page);
686             }
687             else if (transp_type == "iframe") {
688                 page = url_append_args(page, "transp", "iframe");
689                 this.transp = new transport_iframe(this.doc, this, page);
690             }
691             else if (transp_type == "htmlfile") {
692                 page = url_append_args(page, "transp", "htmlfile");
693                 this.transp = new transport_htmlfile(this.doc, this, page);
694             }
695             else
696                 return;
697         }
698         catch (err) {
699             if (this.transp_fback > 0) {
700                 this.transp_fback--;
701                 this.start();
702                 return;
703             }
704         }
705
706         // watchdog setting
707         this.watchdog_ct  = 0;
708         if (!this.the_end) {
709             this.watchdog_hdl = setTimeout(function(obj) { obj.log("tout1"); obj.watchdog(); }, this.watchdog_timeout, this);
710         }
711
712         var date = new Date();
713         this.start_time = date.getTime();
714     },
715
716     stop: function() {
717         this.the_end = true;
718         this.abort();
719     },
720
721     hbit_set: function (hbit) {
722         this.hbit = hbit;
723     },
724
725
726     hbit_status: function () {
727         var ret;
728
729         ret = this.mon_status();
730         // console.log("mon_status: "+ret+" 0: "+this.mon_time);
731         switch (ret) {
732         case 0:
733             mon_stat = "b";
734             break;
735         case 1:
736             mon_stat = "g";
737             break;
738         case 2:
739             mon_stat = "y";
740             break;
741         case 3:
742             mon_stat = "r";
743             break;
744         }
745
746         if (this.mon_stat_old != mon_stat) {
747             this.hbit(mon_stat);
748             this.mon_stat_old = mon_stat;
749         }
750     },
751
752
753     watchdog: function () {
754         // alert("watchdog");
755         var i, again;
756         var comm_newpart, comm_len, comm_arr;
757         var ctx_new_len;
758
759         if (this.sandbox != null) {
760             var zug = "WATCHDOG  sess = ["+this.sess+"]  step = "+this.gst.st+" step_loc = "+this.gst.st_loc+" step_loc_new = "+this.gst.st_loc_new+"Transport: "+this.transp.name;
761             if (zug != this.sandbox.innerHTML)
762                 this.sandbox.innerHTML = zug;
763         }
764
765         // WATCHDOGING THE CONNECTION
766         this.log("hs::watchdog: start, cur equal times: "+this.keepalives_equal);
767         if (!this.watchable) {
768             do {
769                 try{
770                     // if (typeof(this.ifra.contentWindow.xynt_streaming) == 'undefined')
771                     if (!this.transp.xstr_is_init()) {
772                         this.log("hs::watchdog: xstr_is_init = false");
773                         break;
774                     }
775                 }
776                 catch(b) {
777                     this.log("hs::watchdog: exception");
778                     break;
779                 }
780
781                 /*
782                   on IE7 the the window frame scope is cleaned after the href is set, so we wait
783                   for a well know variable value before assign this object value to it (OO is a passion)
784                 */
785                 // if (this.ifra.contentWindow.xynt_streaming == "ready") {
786                 if (this.transp.xstr_set()) {
787                     // this.ifra.contentWindow.xynt_streaming = this;
788                     this.watchable = true;
789                     this.watchdog_ct = 0;
790                     this.log("hs::watchdog: watchable = yes");
791                 }
792             } while (false);
793         }
794         if ( (this.watchdog_ct % this.watchdog_checktm) == 0) {
795             this.log("hs::watchdog: this.keepalive_old: "+this.keepalive_old+" this.keepalive_new: "+this.keepalive_new);
796             if (this.keepalive_old == this.keepalive_new) {
797                 this.keepalives_equal++;
798             }
799             else {
800                 this.keepalive_old = this.keepalive_new;
801                 this.keepalives_equal = 0;
802             }
803
804             if (this.keepalives_equal >= this.keepalives_eq_max) {
805                 this.log("hs::watchdog: MAX ACHIEVED "+this.keepalives_equal);
806                 this.reload();
807                 // alert("watchdog return reload");
808                 this.hbit_status();
809                 return;
810             }
811         }
812
813         // PICK COMMANDS FROM STREAM
814         do {
815             // alert("do--while begin ["+again+"]");
816             // CHECK: maybe again here isn't needed
817             again = 0;
818             try {
819                 /* if (typeof(this.ifra.contentWindow.ctx_new)     == 'undefined' ||
820                    typeof(this.ifra.contentWindow.ctx_old_len) == 'undefined') */
821                 if (!this.transp.ctx_new_is_set() || !this.transp.ctx_old_len_is_set())
822                     break;
823             }
824             catch(b) {
825                 break;
826             }
827
828             // ctx_new_len = this.ifra.contentWindow.ctx_new.length;
829             ctx_new_len = this.transp.ctx_new_curlen_get();
830             // if (ctx_new_len <= this.ifra.contentWindow.ctx_old_len) {
831             if (ctx_new_len <= this.transp.ctx_old_len_get()) {
832                 break;
833             }
834             this.log("new: "+ ctx_new_len + "  old: "+this.transp.ctx_old_len_get());
835             this.keepalive_new++;
836             // alert("pre-loop 1");
837             for (i = this.transp.ctx_old_len_get() ; i < ctx_new_len ; i++) {
838                 // if (this.ifra.contentWindow.ctx_new.charAt(i) != '_') {
839                 if (this.transp.ctx_new_getchar(i) != '_') {
840                     // this.log("ctx_new.char(i) != '_' ["+this.ifra.contentWindow.ctx_new.charAt(i)+"]");
841                     break;
842                 }
843                 this.mon_update();
844                 this.hbit_status();
845
846                 // else {
847                 //     this.log("ctx_new.charAt(i) == '_'");
848                 // }
849             }
850             // this.ifra.contentWindow.ctx_old_len = i;
851             this.transp.ctx_old_len_set(i);
852             if (i == ctx_new_len) {
853                 this.log("old_len == i");
854                 break;
855             }
856             else {
857                 this.log("old_len != i: "+i);
858             }
859             // alert("do--while middle ["+this.ifra.contentWindow.ctx_old_len+"]");
860
861             comm_newpart = this.transp.new_part();
862             this.log("COM_NEWPART: ["+comm_newpart+"]");
863             comm_len = 0;
864             comm_arr = comm_newpart.match(this.comm_match);
865
866             // alert("do--while middle2 ["+again+"]");
867             if (comm_arr) {
868                 var comm_arr_len = comm_arr.length;
869                 for (i = 0 ; i < comm_arr_len ; i++) {
870                     var temp = comm_arr[i].replace(this.comm_clean,"$1").split("|");
871                     this.gst.comms = this.gst.comms.concat(temp);
872                     comm_len += comm_arr[i].length;
873                 }
874                 again = 1;
875                 this.mon_update();
876                 this.hbit_status();
877             }
878             // this.ifra.contentWindow.ctx_old_len += comm_len;
879             this.transp.ctx_old_len_add(comm_len);
880             // this.ifra.contentWindow.script_clean = this.gst.st;
881             this.transp.scrcls_set(this.gst.st);
882             // alert("do--while end ["+again+"]");
883         } while (again);
884
885         // alert("post while");
886         // EXECUTION OF STREAM COMMANDS
887         do {
888             again = 0;
889             //MOP ?? xhrrestart = 0;
890             if (this.gst.st_loc < this.gst.st_loc_new) {
891                 // there is some slow actions running
892                 break;
893             }
894             else if (this.gst.comms.length > 0) {
895                 var singlecomm;
896
897                 singlecomm = this.gst.comms.shift();
898                 // alert("EXE"+gugu);
899                 // $("xhrdeltalog").innerHTML = "EVALL: "+singlecomm.replace("<", "&lt;", "g"); +"<br>";
900                 //xx this.hbit("+");
901
902                 // alert("SINGLE: ["+singlecomm+"]");
903                 // window.console.log("["+singlecomm+"]");
904                 this.cmdproc(singlecomm);
905                 again = 1;
906             }
907         } while (again);
908         this.watchdog_ct++;
909         if (!this.the_end) {
910             var date = new Date();
911             if (date.getTime() > (this.start_time + this.restart_wait)) {
912                 this.transp.postproc();
913             }
914             this.watchdog_hdl = setTimeout(function(obj) { /* obj.log("tout2"); */ obj.watchdog(); }, this.watchdog_timeout, this);
915             this.hbit_status();
916         }
917         // alert("watchdog return normal");
918
919         return;
920     },
921
922     //
923     // moved to xynt-streaming-ifra as push()
924     //
925     // keepalive: function (s) {
926     //     this.log("hs::keepalive");
927     //     if (s != null) {
928     //         this.log(s);
929     //         this.ifra.contentWindow.ctx_new += "@BEGIN@"+s+"@END@";
930     //     }
931     //     else {
932     //         this.ifra.contentWindow.ctx_new += "_";
933     //     }
934     //     // this.keepalive_new++;
935     // },
936
937     abort: function () { /* public */
938         // this.log("PATH: "+this.ifra.contentWindow.location.protocol + "://" + this.ifra.contentWindow.location.host + "/" + this.ifra.contentWindow.location.pathname);
939
940         this.gst.abort();
941         if (this.watchdog_hdl != null) {
942             clearTimeout(this.watchdog_hdl);
943             this.watchdog_hdl = null;
944         }
945
946         this.restart_n++;
947         this.log("hs::reload");
948         this.watchable = false;
949         if (this.transp != null) {
950             this.transp.destroy();
951             delete this.transp;
952             this.transp = null;
953         }
954     },
955
956     reload: function () {
957         this.abort();
958         this.start(null);
959     },
960
961     log: function (s) {
962         if (this.console != null) {
963             return (this.console.log(s));
964         }
965     }
966 }