13eeb7b0027ad069e1d00b328aff103cd7a15017
[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_type_cur:   null,
548     transp_port_cur:     80,
549     transp_fback:         0,
550     transp:            null,
551     console:           null,
552     gst:               null,
553     from:              null,
554     cookiename:        null,
555     sess:              null,
556     sandbox:           null,
557     page:              null,
558     cmdproc:           null,
559
560     start_time:        0,
561     restart_wait:      5000, // wait restart_wait millisec before begin to check if restart is needed
562
563     doc:               null,
564     cookiepath: "/brisk/",
565     watchdog_hdl:      null,
566     hbit:              function () {},
567     keepalive_old:    -1,
568     keepalive_new:    -1,
569     keepalives_equal:  0,
570     /* NOTE: right watch_timeout value to 100, for devel reasons use 1000 or more */
571     /* restart after  4 * 40 * 100 millisec if server ping is missing => 16secs */
572     keepalives_eq_max: 4,
573     watchdog_checktm:  40,
574     watchdog_timeout:  100,
575     watchdog_ct:       0,
576     watchable:         false,
577     restart_n:         0,
578     comm_match:        /_*@BEGIN@(.*?)@END@/g,
579     comm_clean:        /_*@BEGIN@(.*?)@END@/,
580     stream:            "",
581     the_end:           false,
582
583     mon_time:         -1,
584     mon_wrntime:       0,
585     mon_errtime:       0,
586
587     mon_stat_old:      "",
588
589     mon_update: function()
590     {
591         var date = new Date();
592
593         this.mon_time = date.getTime();
594     },
595
596     /*
597       ping arrives at least every RD_KEEPALIVE_TOUT secs (currently 4 secs)
598
599       return values: 0 unknown
600                      1 ok
601                      2 warning
602                      3 error
603      */
604     mon_status: function()
605     {
606         var delta, date;
607
608         var date = new Date();
609
610         delta = date.getTime() - this.mon_time;
611
612         if (delta < this.mon_wrntime)
613             return 1;
614         else if (delta < this.mon_errtime)
615             return 2;
616         else
617             return 3;
618     },
619
620     start: function() { /* public */
621         var transp_type;
622         var page;
623
624         // this.log("start "+this.transp_type+" "+this.transp_fback);
625         if (this.the_end)
626             return;
627
628         createCookie(this.cookiename, sess, 24*365, this.cookiepath);
629         // alert("start");
630         this.log("xynt_streaming:start restart: "+this.restart_n);
631         this.keepalives_equal = 0;
632
633         // page arrangement
634         this.page = url_complete(this.win.location.href, this.page);
635
636         // DEFAULT TRANSPORT PROTOCOL HERE websocketsec, websocket
637         if (this.transp_fback > 0) {
638             if (location.protocol == 'https:') {
639                 transp_type = "websocketsec";
640                 transp_port = 443;
641             }
642             else {
643                 transp_type = "websocket";
644                 transp_port = (this.transp_fback == 2 ? 80 : 8080);
645             }
646
647         }
648         else {
649             transp_type = this.transp_type;
650             transp_port = this.transp_port;
651         }
652
653         this.transp_type_cur = transp_type;
654         this.transp_port_cur = transp_port;
655
656         if (transp_type == "websocket" || transp_type == "websocketsec") {
657             var end_proto, first_slash, newpage;
658
659             // change protocol
660             this.log("precha ["+this.page+"]");
661             if (transp_type == "websocketsec") {
662                 newpage = this.page.replace(/\.php$/g, "_wss.php").replace(/\.php\?/g, "_wss.php?");
663                 }
664             else {
665                 newpage = this.page;
666                 }
667             end_proto = newpage.indexOf("://");
668             first_slash = newpage.substring(end_proto+3).indexOf("/");
669
670             page = (transp_type == "websocketsec" ? "wss://" : "ws://")
671                 + newpage.substring(end_proto+3, end_proto+3 + first_slash) + ":"
672                 + transp_port + newpage.substring(end_proto+3 + first_slash);
673             // this.log("MOP WS: " + page);
674         }
675         else {
676             page = this.page;
677         }
678         // stat, subst, this.gst.st
679
680         page = url_append_args(page, "sess", this.sess, "stat", stat, "subst", subst, "step", this.gst.st, "from", this.from);
681         // this.log("the page:");
682         // this.log(page);
683
684         try {
685             // transport instantiation
686             if (transp_type == "websocketsec") {
687                 page = url_append_args(page, "transp", "websocketsec");
688                 this.transp = new transport_ws(this.doc, this, page, true);
689             }
690             else if (transp_type == "websocket") {
691                 page = url_append_args(page, "transp", "websocket");
692                 this.transp = new transport_ws(this.doc, this, page);
693             }
694             else if (transp_type == "xhr") {
695                 page = url_append_args(page, "transp", "xhr");
696                 this.transp = new transport_xhr(this.doc, this, page);
697             }
698             else if (transp_type == "iframe") {
699                 page = url_append_args(page, "transp", "iframe");
700                 this.transp = new transport_iframe(this.doc, this, page);
701             }
702             else if (transp_type == "htmlfile") {
703                 page = url_append_args(page, "transp", "htmlfile");
704                 this.transp = new transport_htmlfile(this.doc, this, page);
705             }
706             else
707                 return;
708         }
709         catch (err) {
710             if (this.transp_fback > 0) {
711                 this.transp_fback--;
712                 this.start();
713                 return;
714             }
715         }
716
717         // watchdog setting
718         this.watchdog_ct  = 0;
719         if (!this.the_end) {
720             this.watchdog_hdl = setTimeout(function(obj) { obj.log("tout1"); obj.watchdog(); }, this.watchdog_timeout, this);
721         }
722
723         var date = new Date();
724         this.start_time = date.getTime();
725     },
726
727     stop: function() {
728         this.the_end = true;
729         this.abort();
730     },
731
732     hbit_set: function (hbit) {
733         this.hbit = hbit;
734     },
735
736
737     hbit_status: function () {
738         var ret;
739
740         ret = this.mon_status();
741         // console.log("mon_status: "+ret+" 0: "+this.mon_time);
742         switch (ret) {
743         case 0:
744             mon_stat = "b";
745             break;
746         case 1:
747             mon_stat = "g";
748             break;
749         case 2:
750             mon_stat = "y";
751             break;
752         case 3:
753             mon_stat = "r";
754             break;
755         }
756
757         if (this.mon_stat_old != mon_stat) {
758             this.hbit(mon_stat);
759             this.mon_stat_old = mon_stat;
760         }
761     },
762
763
764     watchdog: function () {
765         // alert("watchdog");
766         var i, again;
767         var comm_newpart, comm_len, comm_arr;
768         var ctx_new_len;
769
770         if (this.sandbox != null) {
771             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;
772             if (zug != this.sandbox.innerHTML)
773                 this.sandbox.innerHTML = zug;
774         }
775
776         // WATCHDOGING THE CONNECTION
777         this.log("hs::watchdog: start, cur equal times: "+this.keepalives_equal);
778         if (!this.watchable) {
779             do {
780                 try{
781                     // if (typeof(this.ifra.contentWindow.xynt_streaming) == 'undefined')
782                     if (!this.transp.xstr_is_init()) {
783                         this.log("hs::watchdog: xstr_is_init = false");
784                         break;
785                     }
786                 }
787                 catch(b) {
788                     this.log("hs::watchdog: exception");
789                     break;
790                 }
791
792                 /*
793                   on IE7 the the window frame scope is cleaned after the href is set, so we wait
794                   for a well know variable value before assign this object value to it (OO is a passion)
795                 */
796                 // if (this.ifra.contentWindow.xynt_streaming == "ready") {
797                 if (this.transp.xstr_set()) {
798                     // this.ifra.contentWindow.xynt_streaming = this;
799                     this.watchable = true;
800                     this.watchdog_ct = 0;
801                     this.log("hs::watchdog: watchable = yes");
802                 }
803             } while (false);
804         }
805         if ( (this.watchdog_ct % this.watchdog_checktm) == 0) {
806             this.log("hs::watchdog: this.keepalive_old: "+this.keepalive_old+" this.keepalive_new: "+this.keepalive_new);
807             if (this.keepalive_old == this.keepalive_new) {
808                 this.keepalives_equal++;
809             }
810             else {
811                 this.keepalive_old = this.keepalive_new;
812                 this.keepalives_equal = 0;
813             }
814
815             if (this.keepalives_equal >= this.keepalives_eq_max) {
816                 this.log("hs::watchdog: MAX ACHIEVED "+this.keepalives_equal);
817                 this.reload();
818                 // alert("watchdog return reload");
819                 this.hbit_status();
820                 return;
821             }
822         }
823
824         // PICK COMMANDS FROM STREAM
825         do {
826             // alert("do--while begin ["+again+"]");
827             // CHECK: maybe again here isn't needed
828             again = 0;
829             try {
830                 /* if (typeof(this.ifra.contentWindow.ctx_new)     == 'undefined' ||
831                    typeof(this.ifra.contentWindow.ctx_old_len) == 'undefined') */
832                 if (!this.transp.ctx_new_is_set() || !this.transp.ctx_old_len_is_set())
833                     break;
834             }
835             catch(b) {
836                 break;
837             }
838
839             // ctx_new_len = this.ifra.contentWindow.ctx_new.length;
840             ctx_new_len = this.transp.ctx_new_curlen_get();
841             // if (ctx_new_len <= this.ifra.contentWindow.ctx_old_len) {
842             if (ctx_new_len <= this.transp.ctx_old_len_get()) {
843                 break;
844             }
845             this.log("new: "+ ctx_new_len + "  old: "+this.transp.ctx_old_len_get());
846             this.keepalive_new++;
847             // alert("pre-loop 1");
848             for (i = this.transp.ctx_old_len_get() ; i < ctx_new_len ; i++) {
849                 // if (this.ifra.contentWindow.ctx_new.charAt(i) != '_') {
850                 if (this.transp.ctx_new_getchar(i) != '_') {
851                     // this.log("ctx_new.char(i) != '_' ["+this.ifra.contentWindow.ctx_new.charAt(i)+"]");
852                     break;
853                 }
854                 this.mon_update();
855                 this.hbit_status();
856
857                 // else {
858                 //     this.log("ctx_new.charAt(i) == '_'");
859                 // }
860             }
861             // this.ifra.contentWindow.ctx_old_len = i;
862             this.transp.ctx_old_len_set(i);
863             if (i == ctx_new_len) {
864                 this.log("old_len == i");
865                 break;
866             }
867             else {
868                 this.log("old_len != i: "+i);
869             }
870             // alert("do--while middle ["+this.ifra.contentWindow.ctx_old_len+"]");
871
872             comm_newpart = this.transp.new_part();
873             this.log("COM_NEWPART: ["+comm_newpart+"]");
874             comm_len = 0;
875             comm_arr = comm_newpart.match(this.comm_match);
876
877             // alert("do--while middle2 ["+again+"]");
878             if (comm_arr) {
879                 var comm_arr_len = comm_arr.length;
880                 for (i = 0 ; i < comm_arr_len ; i++) {
881                     var temp = comm_arr[i].replace(this.comm_clean,"$1").split("|");
882                     this.gst.comms = this.gst.comms.concat(temp);
883                     comm_len += comm_arr[i].length;
884                 }
885                 again = 1;
886                 this.mon_update();
887                 this.hbit_status();
888             }
889             // this.ifra.contentWindow.ctx_old_len += comm_len;
890             this.transp.ctx_old_len_add(comm_len);
891             // this.ifra.contentWindow.script_clean = this.gst.st;
892             this.transp.scrcls_set(this.gst.st);
893             // alert("do--while end ["+again+"]");
894         } while (again);
895
896         // alert("post while");
897         // EXECUTION OF STREAM COMMANDS
898         do {
899             again = 0;
900             //MOP ?? xhrrestart = 0;
901             if (this.gst.st_loc < this.gst.st_loc_new) {
902                 // there is some slow actions running
903                 break;
904             }
905             else if (this.gst.comms.length > 0) {
906                 var singlecomm;
907
908                 singlecomm = this.gst.comms.shift();
909                 // alert("EXE"+gugu);
910                 // $("xhrdeltalog").innerHTML = "EVALL: "+singlecomm.replace("<", "&lt;", "g"); +"<br>";
911                 //xx this.hbit("+");
912
913                 // alert("SINGLE: ["+singlecomm+"]");
914                 // window.console.log("["+singlecomm+"]");
915                 this.cmdproc(singlecomm);
916                 if (this.transp_type_cur) {
917                     this.transp_type = this.transp_type_cur;
918                     this.transp_port = this.transp_port_cur;
919                 }
920                 again = 1;
921             }
922         } while (again);
923         this.watchdog_ct++;
924         if (!this.the_end) {
925             var date = new Date();
926             if (date.getTime() > (this.start_time + this.restart_wait)) {
927                 this.transp.postproc();
928             }
929             this.watchdog_hdl = setTimeout(function(obj) { /* obj.log("tout2"); */ obj.watchdog(); }, this.watchdog_timeout, this);
930             this.hbit_status();
931         }
932         // alert("watchdog return normal");
933
934         return;
935     },
936
937     //
938     // moved to xynt-streaming-ifra as push()
939     //
940     // keepalive: function (s) {
941     //     this.log("hs::keepalive");
942     //     if (s != null) {
943     //         this.log(s);
944     //         this.ifra.contentWindow.ctx_new += "@BEGIN@"+s+"@END@";
945     //     }
946     //     else {
947     //         this.ifra.contentWindow.ctx_new += "_";
948     //     }
949     //     // this.keepalive_new++;
950     // },
951
952     abort: function () { /* public */
953         // this.log("PATH: "+this.ifra.contentWindow.location.protocol + "://" + this.ifra.contentWindow.location.host + "/" + this.ifra.contentWindow.location.pathname);
954
955         this.gst.abort();
956         if (this.watchdog_hdl != null) {
957             clearTimeout(this.watchdog_hdl);
958             this.watchdog_hdl = null;
959         }
960
961         this.restart_n++;
962         this.log("hs::reload");
963         this.watchable = false;
964         if (this.transp != null) {
965             this.transp.destroy();
966             delete this.transp;
967             this.transp = null;
968         }
969     },
970
971     reload: function () {
972         this.abort();
973         this.start(null);
974     },
975
976     log: function (s) {
977         if (this.console != null) {
978             return (this.console.log(s));
979         }
980     }
981 }