fa493cdb1d173ea454e13524a8240145ded952a6
[platform/upstream/libwebsockets.git] / test-server / test.html
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4  <meta charset=utf-8 http-equiv="Content-Language" content="en"/>
5  <title>Minimal Websocket test app</title>
6 <style type="text/css">
7         span.title { font-size:18pt; font: Arial; font-weight:normal; text-align:center; color:#000000; }
8         .browser { font-size:18pt; font: Arial; font-weight:normal; text-align:center; color:#ffff00; vertical-align:middle; text-align:center; background:#d0b070; padding:12px; -webkit-border-radius:10px; -moz-border-radius:10px; border-radius:10px;}
9         .group2 { vertical-align:middle;
10                 text-align:center;
11                 background:#f0f0e0; 
12                 padding:12px; 
13                 -webkit-border-radius:10px; 
14                 -moz-border-radius:10px;
15                 border-radius:10px; }
16         .explain { vertical-align:middle;
17                 text-align:center;
18                 background:#f0f0c0; padding:12px;
19                 -webkit-border-radius:10px;
20                 -moz-border-radius:10px;
21                 border-radius:10px;
22                 color:#404000; }
23         td.wsstatus { vertical-align:middle; width:200px; height:50px;
24                 text-align:center;
25                 background:#f0f0c0; padding:6px;
26                 -webkit-border-radius:8px;
27                 -moz-border-radius:8px;
28                 border-radius:8px;
29                 color:#404000; }
30         td.l { vertical-align:middle;
31                 text-align:center;
32                 background:#d0d0b0; 
33                 padding:3px; 
34                 -webkit-border-radius:3px; 
35                 -moz-border-radius:3px;
36                 border-radius:3px; }
37         .content { vertical-align:top; text-align:center; background:#fffff0; padding:12px; -webkit-border-radius:10px; -moz-border-radius:10px; border-radius:10px; }
38         .canvas { vertical-align:top; text-align:center; background:#efefd0; padding:12px; -webkit-border-radius:10px; -moz-border-radius:10px; border-radius:10px; }
39 .tabs {
40   position: relative;   
41   min-height: 750px; /* This part sucks */
42   clear: both;
43   margin: 25px 0;
44 }
45 .tab {
46   float: left;
47 }
48 .tab label {
49   background: #eee; 
50   padding: 10px; 
51   border: 1px solid #ccc; 
52   margin-left: -1px; 
53   position: relative;
54   left: 1px; 
55 }
56 .tab [type=radio] {
57   display: none;   
58 }
59 .content {
60   position: absolute;
61   top: 28px;
62   left: 0;
63   background: white;
64   right: 0;
65   bottom: 0;
66   padding: 20px;
67   border: 1px solid #ccc; 
68 }
69 [type=radio]:checked ~ label {
70   background: white;
71   border-bottom: 1px solid white;
72   z-index: 2;
73 }
74 [type=radio]:checked ~ label ~ .content {
75   z-index: 1;
76 }
77 </style>
78 </head>
79
80 <body>
81 <header></header>
82 <article>
83
84 <table><tr><td>
85
86 <table width=600px>
87  <tr>
88   <td valign=middle align=center>
89    <a href="https://libwebsockets.org">
90     <img src="libwebsockets.org-logo.png"></a></td><td>
91         <section class="browser">Detected Browser: 
92         <div id=brow>...</div></section>
93   </td>
94  </tr>
95
96 </table>
97 </td></tr>
98 <tr><td colspan=2 align=center>
99 Click <a href="leaf.jpg" target="_blank">Here</a> to
100 have the test server send a big picture by http.
101 </td></tr>
102 <tr><td colspan=2>
103 <div class="tabs">
104
105    <div class="tab">
106        <input type="radio" id="tab-1" name="tab-group-1" checked>
107        <label for="tab-1">Dumb Increment Demo</label>
108        
109        <div class="content">
110         <div id="dumb" class="group2">
111          <table>
112           <tr>
113            <td id=wsdi_statustd align=center class="wsstatus">
114              <span id=wsdi_status>Websocket connection not initialized</span></td>
115            <td><span class="title">dumb increment-protocol</span></td>
116            </tr>
117            <tr>
118            <td class="explain" colspan=2>
119 The incrementing number is coming from the server at 20Hz and is individual for
120 each connection to the server... try opening a second browser window.
121 <br/><br/>
122 The button sends a message over the websocket link to ask the server
123 to zero just this connection's number.
124            </td>
125           </tr>
126            <tr>
127             <td align=center><div id=number style="font-size:120%;"> </div></td>
128             <td align=center>
129              <input type=button id=offset value="Reset counter" onclick="reset();" >
130              <input type=button id=junk value="Send junk" onclick="junk();" >
131             </td>
132             </tr>
133          </table>
134         </div>
135        </div> 
136    </div>
137
138    <div class="tab">
139     <input type="radio" id="tab-2" name="tab-group-1">
140     <label for="tab-2">Mirror Demo</label>
141        
142     <div class="content">
143      <div id="mirror" class="group2">
144       <table>
145        <tr>
146          <td colspan=1 id=wslm_statustd align=center class="wsstatus">
147          <span id=wslm_status>Websocket connection not initialized</span>
148         </td>
149         <td>
150          <span class="title">lws-mirror-protocol</span>
151         </td>
152        </tr>
153        <tr>
154        <td colspan=2>
155          <div class="explain">
156 Use the mouse to draw on the canvas below -- all other browser windows open
157 on this page see your drawing in realtime and you can see any of theirs as
158 well.
159 <br/><br/>
160 The lws-mirror protocol doesn't interpret what is being sent to it, it just
161 re-sends it to every other websocket it has a connection with using that
162 protocol, including the guy who sent the packet.
163 <br/><br/>
164 <b>libwebsockets-test-client</b> joins in by spamming circles on to this shared canvas when
165 run.
166          </div>
167         </td>
168        </tr>
169        <tr>
170         <td colspan=2>Drawing color:
171           <select id="color" onchange="update_color();">
172                 <option value=#000000>Black</option>
173                 <option value=#0000ff>Blue</option>
174                 <option value=#20ff20>Green</option>
175                 <option value=#802020>Dark Red</option>
176           </select>
177        </tr>
178        <tr>
179          <td colspan=2 width=500 height=320>
180                 <div id="wslm_drawing" style="background:white"></div>
181         </td>
182        </tr>
183       </table>
184      </div>
185     </div> 
186    </div>
187     
188     <div class="tab">
189        <input type="radio" id="tab-3" name="tab-group-1">
190        <label for="tab-3">Close Testing</label>
191      
192        <div class="content">
193 <div id="ot" class="group2">
194       <table>
195        <tr>
196         <td>
197
198                 </td></tr>
199                 <tr><td id=ot_statustd align=center class="wsstatus">
200                  <span id=ot_status>Websocket connection not initialized</span>
201                 </td>
202                 <td colspan=2><span class="title">Open and close testing</span></td>
203                 </tr>
204                 <tr>    
205 <td class="explain" colspan=3 style="padding:3">
206 To help with open and close testing, you can open and close a connection by hand using
207  the buttons.<br>
208  "<b>Close</b>" closes the connection from the browser with code 3000
209   and reason 'Bye!".<br>
210  "<b>Request Server Close</b>" sends a message asking the server to
211 initiate the close, which it does with code 1001 and reason "Seeya".
212 </td></tr>
213                 <tr>
214                 <td align=center><input type=button id=ot_open_btn value="Open" onclick="ot_open();" ></td>
215                 <td align=center><input type=button id=ot_close_btn disabled value="Close" onclick="ot_close();" ></td>
216                 <td align=center><input type=button id=ot_req_close_btn disabled value="Request Server Close" onclick="ot_req_close();" ></td>
217                 </tr>
218
219 </table>
220
221 </div>
222        </div> 
223    </div>
224    
225     <div class="tab">
226        <input type="radio" id="tab-4" name="tab-group-1">
227        <label for="tab-4">Server info</label>
228
229        <div class="content">
230 <div id="ot" class="group2">
231       <table>
232        <tr>
233         <td id=s_statustd align=center class="wsstatus">
234          <div id=s_status>Websocket connection not initialized</div>
235         </td>
236                 <td colspan=1>
237 <span class="title">Server Info</span>
238         </td>
239         </tr><tr>
240 <td class="explain" colspan=2>
241 This information is sent by the server over a ws[s] link and updated live
242 whenever the information changes server-side.
243 </td></tr>
244         <tr>
245         <td align=center colspan=2><div id=servinfo></</div></td>
246         </tr>
247         <tr>
248         <td align=center colspan=2><div id=conninfo style="border : solid 2px #e0d040; padding : 4px; width : 500px; height : 350px; overflow : auto; "></</div></td>
249         </tr>
250 </table>
251 </div>
252        </div> 
253    </div>
254
255 </div>
256 </td></tr></table>
257
258 Looking for support? <a href="https://libwebsockets.org">https://libwebsockets.org</a>, <a href="https://github.com/warmcat/libwebsockets">https://github.com/warmcat/libwebsockets</a></a><br/>
259 Join the mailing list: <a href="https://libwebsockets.org/mailman/listinfo/libwebsockets">https://libwebsockets.org/mailman/listinfo/libwebsockets</a>
260
261 </article>
262
263 <script>
264
265 /*
266  * We display untrusted stuff in html context... reject anything
267  * that has HTML stuff in it
268  */
269
270 function san(s)
271 {
272         if (s.search("<") != -1)
273                 return "invalid string";
274         
275         return s;
276 }
277
278 /* BrowserDetect came from http://www.quirksmode.org/js/detect.html */
279
280 var BrowserDetect = {
281         init: function () {
282                 this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
283                 this.version = this.searchVersion(navigator.userAgent)
284                         || this.searchVersion(navigator.appVersion)
285                         || "an unknown version";
286                 this.OS = this.searchString(this.dataOS) || "an unknown OS";
287         },
288         searchString: function (data) {
289                 for (var i=0;i<data.length;i++) {
290                         var dataString = data[i].string;
291                         var dataProp = data[i].prop;
292                         this.versionSearchString = data[i].versionSearch || data[i].identity;
293                         if (dataString) {
294                                 if (dataString.indexOf(data[i].subString) != -1)
295                                         return data[i].identity;
296                         }
297                         else if (dataProp)
298                                 return data[i].identity;
299                 }
300         },
301         searchVersion: function (dataString) {
302                 var index = dataString.indexOf(this.versionSearchString);
303                 if (index == -1) return;
304                 return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
305         },
306         dataBrowser: [
307                 {
308                         string: navigator.userAgent,
309                         subString: "Chrome",
310                         identity: "Chrome"
311                 },
312                 {       string: navigator.userAgent,
313                         subString: "OmniWeb",
314                         versionSearch: "OmniWeb/",
315                         identity: "OmniWeb"
316                 },
317                 {
318                         string: navigator.vendor,
319                         subString: "Apple",
320                         identity: "Safari",
321                         versionSearch: "Version"
322                 },
323                 {
324                         prop: window.opera,
325                         identity: "Opera",
326                         versionSearch: "Version"
327                 },
328                 {
329                         string: navigator.vendor,
330                         subString: "iCab",
331                         identity: "iCab"
332                 },
333                 {
334                         string: navigator.vendor,
335                         subString: "KDE",
336                         identity: "Konqueror"
337                 },
338                 {
339                         string: navigator.userAgent,
340                         subString: "Firefox",
341                         identity: "Firefox"
342                 },
343                 {
344                         string: navigator.vendor,
345                         subString: "Camino",
346                         identity: "Camino"
347                 },
348                 {               // for newer Netscapes (6+)
349                         string: navigator.userAgent,
350                         subString: "Netscape",
351                         identity: "Netscape"
352                 },
353                 {
354                         string: navigator.userAgent,
355                         subString: "MSIE",
356                         identity: "Explorer",
357                         versionSearch: "MSIE"
358                 },
359                 {
360                         string: navigator.userAgent,
361                         subString: "Gecko",
362                         identity: "Mozilla",
363                         versionSearch: "rv"
364                 },
365                 {               // for older Netscapes (4-)
366                         string: navigator.userAgent,
367                         subString: "Mozilla",
368                         identity: "Netscape",
369                         versionSearch: "Mozilla"
370                 }
371         ],
372         dataOS : [
373                 {
374                         string: navigator.platform,
375                         subString: "Win",
376                         identity: "Windows"
377                 },
378                 {
379                         string: navigator.platform,
380                         subString: "Mac",
381                         identity: "Mac"
382                 },
383                 {
384                            string: navigator.userAgent,
385                            subString: "iPhone",
386                            identity: "iPhone/iPod"
387             },
388                 {
389                         string: navigator.platform,
390                         subString: "Linux",
391                         identity: "Linux"
392                 }
393         ]
394
395 };
396 BrowserDetect.init();
397
398 document.getElementById("brow").textContent = " " + BrowserDetect.browser + " "
399         + BrowserDetect.version +" " + BrowserDetect.OS +" ";
400
401         var pos = 0;
402
403 function get_appropriate_ws_url()
404 {
405         var pcol;
406         var u = document.URL;
407
408         /*
409          * We open the websocket encrypted if this page came on an
410          * https:// url itself, otherwise unencrypted
411          */
412
413         if (u.substring(0, 5) == "https") {
414                 pcol = "wss://";
415                 u = u.substr(8);
416         } else {
417                 pcol = "ws://";
418                 if (u.substring(0, 4) == "http")
419                         u = u.substr(7);
420         }
421
422         u = u.split('/');
423
424         /* + "/xxx" bit is for IE10 workaround */
425
426         return pcol + u[0] + "/xxx";
427 }
428
429
430 document.getElementById("number").textContent = get_appropriate_ws_url();
431
432 /* dumb increment protocol */
433         
434         var socket_di;
435
436         if (typeof MozWebSocket != "undefined") {
437                 socket_di = new MozWebSocket(get_appropriate_ws_url(),
438                                    "dumb-increment-protocol");
439         } else {
440                 socket_di = new WebSocket(get_appropriate_ws_url(),
441                                    "dumb-increment-protocol");
442         }
443
444
445         try {
446                 socket_di.onopen = function() {
447                         document.getElementById("wsdi_statustd").style.backgroundColor = "#40ff40";
448                         document.getElementById("wsdi_status").innerHTML =
449                                 " <b>websocket connection opened</b><br>" +
450                                 san(socket_di.extensions);
451                 } 
452
453                 socket_di.onmessage =function got_packet(msg) {
454                         document.getElementById("number").textContent = msg.data + "\n";
455                 } 
456
457                 socket_di.onclose = function(){
458                         document.getElementById("wsdi_statustd").style.backgroundColor = "#ff4040";
459                         document.getElementById("wsdi_status").textContent = " websocket connection CLOSED ";
460                 }
461         } catch(exception) {
462                 alert('<p>Error' + exception);  
463         }
464         
465         var socket_status, jso, s;
466
467         if (typeof MozWebSocket != "undefined") {
468                 socket_status = new MozWebSocket(get_appropriate_ws_url(),
469                                    "lws-status");
470         } else {
471                 socket_status = new WebSocket(get_appropriate_ws_url(),
472                                    "lws-status");
473         }
474
475
476         try {
477                 socket_status.onopen = function() {
478                         document.getElementById("s_statustd").style.backgroundColor = "#40ff40";
479                         document.getElementById("s_status").innerHTML =
480                                 " <b>websocket connection opened</b><br>" +
481                                 san(socket_status.extensions);
482                 } 
483
484                 socket_status.onmessage =function got_packet(msg) {
485                         jso = JSON.parse(msg.data);
486                         
487                         document.getElementById("servinfo").innerHTML = 
488                                 "<table><tr><td class=l>Build info</td><td>"+
489                                         san(jso.version) + "</td></tr>" +
490                                         "<tr><td class=l>Server info</td><td>" +
491                                         san(jso.hostname) + "</td></tr>" +
492                                         "</table>";
493                         s="<table>";
494                         var n;
495                         for (n = 0; n < jso.conns.length; n++)
496                                 s = s + "<tr><td class=l>client " + (n + 1) +
497                                 "</td><td><b>" + san(jso.conns[n].peer) +
498                                 "</b><br>" + san(jso.conns[n].time) +
499                                 "<br>" + san(jso.conns[n].ua) +
500                                 "</td></tr>";
501                         s = s + "</table>";
502                         
503                         document.getElementById("conninfo").innerHTML = s;
504                 } 
505
506                 socket_status.onclose = function(){
507                         document.getElementById("s_statustd").style.backgroundColor = "#ff4040";
508                         document.getElementById("s_status").textContent = " websocket connection CLOSED ";
509                 }
510         } catch(exception) {
511                 alert('<p>Error' + exception);  
512         }
513
514 function reset() {
515         socket_di.send("reset\n");
516 }
517
518
519 function junk() {
520         for(var word = ''; word.length < 9000; word += 'a'){}
521         socket_di.send(word);
522 }
523
524 var socket_ot;
525
526 function ot_open() {
527         if (typeof MozWebSocket != "undefined") {
528                 socket_ot = new MozWebSocket(get_appropriate_ws_url(),
529                                    "dumb-increment-protocol");
530         } else {
531                 socket_ot = new WebSocket(get_appropriate_ws_url(),
532                                    "dumb-increment-protocol");
533         }
534         try {
535                 socket_ot.onopen = function() {
536                         document.getElementById("ot_statustd").style.backgroundColor = "#40ff40";
537                         document.getElementById("ot_status").innerHTML = " <b>websocket connection opened</b><br>" + san(socket_di.extensions);
538                         document.getElementById("ot_open_btn").disabled = true;
539                         document.getElementById("ot_close_btn").disabled = false;
540                         document.getElementById("ot_req_close_btn").disabled = false;
541                 } 
542
543                 socket_ot.onclose = function(e){
544                         document.getElementById("ot_statustd").style.backgroundColor = "#ff4040";
545                         document.getElementById("ot_status").textContent = " websocket connection CLOSED, code: " + e.code +
546                         ", reason: " + e.reason;
547                         document.getElementById("ot_open_btn").disabled = false;
548                         document.getElementById("ot_close_btn").disabled = true;
549                         document.getElementById("ot_req_close_btn").disabled = true;
550                 }
551         } catch(exception) {
552                 alert('<p>Error' + exception);  
553         }
554 }
555
556 /* browser will close the ws in a controlled way */
557 function ot_close() {
558         socket_ot.close(3000, "Bye!");
559 }
560
561 /* we ask the server to close the ws in a controlled way */
562 function ot_req_close() {
563         socket_ot.send("closeme\n");
564 }
565
566 /* lws-mirror protocol */
567
568         var down = 0;
569         var no_last = 1;
570         var last_x = 0, last_y = 0;
571         var ctx;
572         var socket_lm;
573         var color = "#000000";
574
575         if (typeof MozWebSocket != "undefined") {
576                 socket_lm = new MozWebSocket(get_appropriate_ws_url(),
577                                    "lws-mirror-protocol");
578         } else {
579                 socket_lm = new WebSocket(get_appropriate_ws_url(),
580                                    "lws-mirror-protocol");
581         }
582
583
584         try {
585                 socket_lm.onopen = function() {
586                         document.getElementById("wslm_statustd").style.backgroundColor = "#40ff40";
587                         document.getElementById("wslm_status").innerHTML =
588                                 " <b>websocket connection opened</b><br>" +
589                                 san(socket_lm.extensions);
590                 } 
591
592                 socket_lm.onmessage =function got_packet(msg) {
593                         j = msg.data.split(';');
594                         f = 0;
595                         while (f < j.length - 1) {
596                                 i = j[f].split(' ');
597                                 if (i[0] == 'd') {
598                                         ctx.strokeStyle = i[1];
599                                         ctx.beginPath();
600                                         ctx.moveTo(+(i[2]), +(i[3]));
601                                         ctx.lineTo(+(i[4]), +(i[5]));
602                                         ctx.stroke();
603                                 }
604                                 if (i[0] == 'c') {
605                                         ctx.strokeStyle = i[1];
606                                         ctx.beginPath();
607                                         ctx.arc(+(i[2]), +(i[3]), +(i[4]), 0, Math.PI*2, true); 
608                                         ctx.stroke();
609                                 }
610
611                                 f++;
612                         }
613                 }
614
615                 socket_lm.onclose = function(){
616                         document.getElementById("wslm_statustd").style.backgroundColor = "#ff4040";
617                         document.getElementById("wslm_status").textContent = " websocket connection CLOSED ";
618                 }
619         } catch(exception) {
620                 alert('<p>Error' + exception);  
621         }
622
623         var canvas = document.createElement('canvas');
624         canvas.height = 300;
625         canvas.width = 480;
626         ctx = canvas.getContext("2d");
627
628         document.getElementById('wslm_drawing').appendChild(canvas);
629
630         canvas.addEventListener('mousemove', ev_mousemove, false);
631         canvas.addEventListener('mousedown', ev_mousedown, false);
632         canvas.addEventListener('mouseup', ev_mouseup, false);
633
634         offsetX = offsetY = 0;
635         element = canvas;
636       if (element.offsetParent) {
637         do {
638           offsetX += element.offsetLeft;
639           offsetY += element.offsetTop;
640         } while ((element = element.offsetParent));
641       }
642  
643 function update_color() {
644         color = document.getElementById("color").value;
645 }
646
647 function ev_mousedown (ev) {
648         down = 1;
649 }
650
651 function ev_mouseup(ev) {
652         down = 0;
653         no_last = 1;
654 }
655
656 function ev_mousemove (ev) {
657         var x, y;
658
659         if (ev.offsetX) {
660                 x = ev.offsetX;
661                 y = ev.offsetY;
662         } else {
663                 x = ev.layerX - offsetX;
664                 y = ev.layerY - offsetY;
665
666         }
667
668         if (!down)
669                 return;
670         if (no_last) {
671                 no_last = 0;
672                 last_x = x;
673                 last_y = y;
674                 return;
675         }
676         socket_lm.send("d " + color + " " + last_x + " " + last_y + " " + x + ' ' + y + ';');
677
678         last_x = x;
679         last_y = y;
680 }
681
682
683 </script>
684
685 </body>
686 </html>