add websocketsec(ure) as transport layer
[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         if (this.transp_fback > 0) {
635             transp_type = "websocket";
636             transp_port = (this.transp_fback == 2 ? 80 : 8080);
637         }
638         else {
639             transp_type = this.transp_type;
640             transp_port = this.transp_port;
641         }
642
643         if (transp_type == "websocket" || transp_type == "websocketsec") {
644             var end_proto, first_slash, newpage;
645
646             // change protocol
647             this.log("precha ["+this.page+"]");
648             if (transp_type == "websocketsec") {
649                 newpage = this.page.replace(/\.php$/g, "_wss.php").replace(/\.php\?/g, "_wss.php?");
650                 }
651             else {
652                 newpage = this.page;
653                 }
654             end_proto = newpage.indexOf("://");
655             first_slash = newpage.substring(end_proto+3).indexOf("/");
656
657             page = (transp_type == "websocketsec" ? "wss://" : "ws://")
658                 + newpage.substring(end_proto+3, end_proto+3 + first_slash) + ":"
659                 + transp_port + newpage.substring(end_proto+3 + first_slash);
660             // this.log("MOP WS: " + page);
661         }
662         else {
663             page = this.page;
664         }
665         // stat, subst, this.gst.st
666
667         page = url_append_args(page, "sess", this.sess, "stat", stat, "subst", subst, "step", this.gst.st, "from", this.from);
668         // this.log("the page:");
669         // this.log(page);
670
671         try {
672             // transport instantiation
673             if (transp_type == "websocketsec") {
674                 page = url_append_args(page, "transp", "websocketsec");
675                 this.transp = new transport_ws(this.doc, this, page, true);
676             }
677             else if (transp_type == "websocket") {
678                 page = url_append_args(page, "transp", "websocket");
679                 this.transp = new transport_ws(this.doc, this, page);
680             }
681             else if (transp_type == "xhr") {
682                 page = url_append_args(page, "transp", "xhr");
683                 this.transp = new transport_xhr(this.doc, this, page);
684             }
685             else if (transp_type == "iframe") {
686                 page = url_append_args(page, "transp", "iframe");
687                 this.transp = new transport_iframe(this.doc, this, page);
688             }
689             else if (transp_type == "htmlfile") {
690                 page = url_append_args(page, "transp", "htmlfile");
691                 this.transp = new transport_htmlfile(this.doc, this, page);
692             }
693             else
694                 return;
695         }
696         catch (err) {
697             if (this.transp_fback > 0) {
698                 this.transp_fback--;
699                 this.start();
700                 return;
701             }
702         }
703
704         // watchdog setting
705         this.watchdog_ct  = 0;
706         if (!this.the_end) {
707             this.watchdog_hdl = setTimeout(function(obj) { obj.log("tout1"); obj.watchdog(); }, this.watchdog_timeout, this);
708         }
709
710         var date = new Date();
711         this.start_time = date.getTime();
712     },
713
714     stop: function() {
715         this.the_end = true;
716         this.abort();
717     },
718
719     hbit_set: function (hbit) {
720         this.hbit = hbit;
721     },
722
723
724     hbit_status: function () {
725         var ret;
726
727         ret = this.mon_status();
728         // console.log("mon_status: "+ret+" 0: "+this.mon_time);
729         switch (ret) {
730         case 0:
731             mon_stat = "b";
732             break;
733         case 1:
734             mon_stat = "g";
735             break;
736         case 2:
737             mon_stat = "y";
738             break;
739         case 3:
740             mon_stat = "r";
741             break;
742         }
743
744         if (this.mon_stat_old != mon_stat) {
745             this.hbit(mon_stat);
746             this.mon_stat_old = mon_stat;
747         }
748     },
749
750
751     watchdog: function () {
752         // alert("watchdog");
753         var i, again;
754         var comm_newpart, comm_len, comm_arr;
755         var ctx_new_len;
756
757         if (this.sandbox != null) {
758             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;
759             if (zug != this.sandbox.innerHTML)
760                 this.sandbox.innerHTML = zug;
761         }
762
763         // WATCHDOGING THE CONNECTION
764         this.log("hs::watchdog: start, cur equal times: "+this.keepalives_equal);
765         if (!this.watchable) {
766             do {
767                 try{
768                     // if (typeof(this.ifra.contentWindow.xynt_streaming) == 'undefined')
769                     if (!this.transp.xstr_is_init()) {
770                         this.log("hs::watchdog: xstr_is_init = false");
771                         break;
772                     }
773                 }
774                 catch(b) {
775                     this.log("hs::watchdog: exception");
776                     break;
777                 }
778
779                 /*
780                   on IE7 the the window frame scope is cleaned after the href is set, so we wait
781                   for a well know variable value before assign this object value to it (OO is a passion)
782                 */
783                 // if (this.ifra.contentWindow.xynt_streaming == "ready") {
784                 if (this.transp.xstr_set()) {
785                     // this.ifra.contentWindow.xynt_streaming = this;
786                     this.watchable = true;
787                     this.watchdog_ct = 0;
788                     this.log("hs::watchdog: watchable = yes");
789                 }
790             } while (false);
791         }
792         if ( (this.watchdog_ct % this.watchdog_checktm) == 0) {
793             this.log("hs::watchdog: this.keepalive_old: "+this.keepalive_old+" this.keepalive_new: "+this.keepalive_new);
794             if (this.keepalive_old == this.keepalive_new) {
795                 this.keepalives_equal++;
796             }
797             else {
798                 this.keepalive_old = this.keepalive_new;
799                 this.keepalives_equal = 0;
800             }
801
802             if (this.keepalives_equal >= this.keepalives_eq_max) {
803                 this.log("hs::watchdog: MAX ACHIEVED "+this.keepalives_equal);
804                 this.reload();
805                 // alert("watchdog return reload");
806                 this.hbit_status();
807                 return;
808             }
809         }
810
811         // PICK COMMANDS FROM STREAM
812         do {
813             // alert("do--while begin ["+again+"]");
814             // CHECK: maybe again here isn't needed
815             again = 0;
816             try {
817                 /* if (typeof(this.ifra.contentWindow.ctx_new)     == 'undefined' ||
818                    typeof(this.ifra.contentWindow.ctx_old_len) == 'undefined') */
819                 if (!this.transp.ctx_new_is_set() || !this.transp.ctx_old_len_is_set())
820                     break;
821             }
822             catch(b) {
823                 break;
824             }
825
826             // ctx_new_len = this.ifra.contentWindow.ctx_new.length;
827             ctx_new_len = this.transp.ctx_new_curlen_get();
828             // if (ctx_new_len <= this.ifra.contentWindow.ctx_old_len) {
829             if (ctx_new_len <= this.transp.ctx_old_len_get()) {
830                 break;
831             }
832             this.log("new: "+ ctx_new_len + "  old: "+this.transp.ctx_old_len_get());
833             this.keepalive_new++;
834             // alert("pre-loop 1");
835             for (i = this.transp.ctx_old_len_get() ; i < ctx_new_len ; i++) {
836                 // if (this.ifra.contentWindow.ctx_new.charAt(i) != '_') {
837                 if (this.transp.ctx_new_getchar(i) != '_') {
838                     // this.log("ctx_new.char(i) != '_' ["+this.ifra.contentWindow.ctx_new.charAt(i)+"]");
839                     break;
840                 }
841                 this.mon_update();
842                 this.hbit_status();
843
844                 // else {
845                 //     this.log("ctx_new.charAt(i) == '_'");
846                 // }
847             }
848             // this.ifra.contentWindow.ctx_old_len = i;
849             this.transp.ctx_old_len_set(i);
850             if (i == ctx_new_len) {
851                 this.log("old_len == i");
852                 break;
853             }
854             else {
855                 this.log("old_len != i: "+i);
856             }
857             // alert("do--while middle ["+this.ifra.contentWindow.ctx_old_len+"]");
858
859             comm_newpart = this.transp.new_part();
860             this.log("COM_NEWPART: ["+comm_newpart+"]");
861             comm_len = 0;
862             comm_arr = comm_newpart.match(this.comm_match);
863
864             // alert("do--while middle2 ["+again+"]");
865             if (comm_arr) {
866                 var comm_arr_len = comm_arr.length;
867                 for (i = 0 ; i < comm_arr_len ; i++) {
868                     var temp = comm_arr[i].replace(this.comm_clean,"$1").split("|");
869                     this.gst.comms = this.gst.comms.concat(temp);
870                     comm_len += comm_arr[i].length;
871                 }
872                 again = 1;
873                 this.mon_update();
874                 this.hbit_status();
875             }
876             // this.ifra.contentWindow.ctx_old_len += comm_len;
877             this.transp.ctx_old_len_add(comm_len);
878             // this.ifra.contentWindow.script_clean = this.gst.st;
879             this.transp.scrcls_set(this.gst.st);
880             // alert("do--while end ["+again+"]");
881         } while (again);
882
883         // alert("post while");
884         // EXECUTION OF STREAM COMMANDS
885         do {
886             again = 0;
887             //MOP ?? xhrrestart = 0;
888             if (this.gst.st_loc < this.gst.st_loc_new) {
889                 // there is some slow actions running
890                 break;
891             }
892             else if (this.gst.comms.length > 0) {
893                 var singlecomm;
894
895                 singlecomm = this.gst.comms.shift();
896                 // alert("EXE"+gugu);
897                 // $("xhrdeltalog").innerHTML = "EVALL: "+singlecomm.replace("<", "&lt;", "g"); +"<br>";
898                 //xx this.hbit("+");
899
900                 // alert("SINGLE: ["+singlecomm+"]");
901                 // window.console.log("["+singlecomm+"]");
902                 this.cmdproc(singlecomm);
903                 again = 1;
904             }
905         } while (again);
906         this.watchdog_ct++;
907         if (!this.the_end) {
908             var date = new Date();
909             if (date.getTime() > (this.start_time + this.restart_wait)) {
910                 this.transp.postproc();
911             }
912             this.watchdog_hdl = setTimeout(function(obj) { /* obj.log("tout2"); */ obj.watchdog(); }, this.watchdog_timeout, this);
913             this.hbit_status();
914         }
915         // alert("watchdog return normal");
916
917         return;
918     },
919
920     //
921     // moved to xynt-streaming-ifra as push()
922     //
923     // keepalive: function (s) {
924     //     this.log("hs::keepalive");
925     //     if (s != null) {
926     //         this.log(s);
927     //         this.ifra.contentWindow.ctx_new += "@BEGIN@"+s+"@END@";
928     //     }
929     //     else {
930     //         this.ifra.contentWindow.ctx_new += "_";
931     //     }
932     //     // this.keepalive_new++;
933     // },
934
935     abort: function () { /* public */
936         // this.log("PATH: "+this.ifra.contentWindow.location.protocol + "://" + this.ifra.contentWindow.location.host + "/" + this.ifra.contentWindow.location.pathname);
937
938         this.gst.abort();
939         if (this.watchdog_hdl != null) {
940             clearTimeout(this.watchdog_hdl);
941             this.watchdog_hdl = null;
942         }
943
944         this.restart_n++;
945         this.log("hs::reload");
946         this.watchable = false;
947         if (this.transp != null) {
948             this.transp.destroy();
949             delete this.transp;
950             this.transp = null;
951         }
952     },
953
954     reload: function () {
955         this.abort();
956         this.start(null);
957     },
958
959     log: function (s) {
960         if (this.console != null) {
961             return (this.console.log(s));
962         }
963     }
964 }