introduce-mirror-test-protocol.patch
authorAndy Green <andy@warmcat.com>
Fri, 12 Nov 2010 13:10:40 +0000 (13:10 +0000)
committerAndy Green <andy@warmcat.com>
Fri, 12 Nov 2010 13:10:40 +0000 (13:10 +0000)
Signed-off-by: Andy Green <andy@warmcat.com>
test-server/test-server.c
test-server/test.html

index 50a4975..d35e826 100644 (file)
 
 #include "../lib/libwebsockets.h"
 
+/*
+ * This demo server shows how to use libwebsockets for one or more
+ * websocket protocols in the same server
+ *
+ * It defines the following websocket protocols:
+ *
+ *  dumb-increment-protocol:  once the socket is opened, an incrementing
+ *                             ascii string is sent down it every 50ms.
+ *                             If you send "reset\n" on the websocket, then
+ *                             the incrementing number is reset to 0.
+ * 
+ */
+
+
 #define LOCAL_RESOURCE_PATH "/usr/share/libwebsockets-test-server"
 static int port = 7681;
 static int use_ssl = 0;
@@ -95,6 +109,7 @@ callback_dumb_increment(struct libwebsocket * wsi,
                break;
 
        case LWS_CALLBACK_RECEIVE:
+               fprintf(stderr, "rx %d\n", len);
                if (len < 6)
                        break;
                if (strcmp(in, "reset\n") == 0)
@@ -109,6 +124,91 @@ callback_dumb_increment(struct libwebsocket * wsi,
 }
 
 
+/* lws-mirror_protocol */
+
+#define MAX_MESSAGE_QUEUE 64
+const int MAX_COMMUNE_MEMBERS = 20;
+
+struct per_session_data__lws_mirror {
+       struct libwebsocket * wsi;
+       int ringbuffer_tail;
+};
+
+struct a_message {
+       struct per_session_data * sender;
+       void * payload;
+       size_t len;
+};
+
+static struct a_message ringbuffer[MAX_MESSAGE_QUEUE];
+static int ringbuffer_head;
+
+
+struct per_session_data * all_members;
+
+
+static int
+callback_lws_mirror(struct libwebsocket * wsi,
+                       enum libwebsocket_callback_reasons reason,
+                       void * user, void *in, size_t len)
+{
+       int n;
+       char buf[LWS_SEND_BUFFER_PRE_PADDING + 512 +
+                                                 LWS_SEND_BUFFER_POST_PADDING];
+       unsigned char *p = (unsigned char *)&buf[LWS_SEND_BUFFER_PRE_PADDING];
+       struct per_session_data__lws_mirror * pss = user;
+       
+       switch (reason) {
+
+       case LWS_CALLBACK_ESTABLISHED:
+               pss->wsi = wsi;
+               pss->ringbuffer_tail = ringbuffer_head;
+               break;
+
+       case LWS_CALLBACK_SEND: 
+               /* send everything that's pending */
+               while (pss->ringbuffer_tail != ringbuffer_head) {
+
+                       n = libwebsocket_write(wsi,
+                               (unsigned char *)ringbuffer[pss->ringbuffer_tail].payload +
+                                       LWS_SEND_BUFFER_PRE_PADDING,
+                                  ringbuffer[pss->ringbuffer_tail].len,
+                                                       LWS_WRITE_TEXT);
+                       if (n < 0) {
+                               fprintf(stderr, "ERROR writing to socket");
+                               exit(1);
+                       }
+
+                       if (pss->ringbuffer_tail == (MAX_MESSAGE_QUEUE - 1))
+                               pss->ringbuffer_tail = 0;
+                       else
+                               pss->ringbuffer_tail++;
+               }
+               break;
+
+       case LWS_CALLBACK_RECEIVE:
+//             fprintf(stderr, "Received %d bytes payload\n", (int)len);
+               ringbuffer[ringbuffer_head].payload =
+                               malloc(LWS_SEND_BUFFER_PRE_PADDING + len +
+                                                 LWS_SEND_BUFFER_POST_PADDING);
+               ringbuffer[ringbuffer_head].len = len;
+               ringbuffer[ringbuffer_head].sender = pss;
+               memcpy(ringbuffer[ringbuffer_head].payload +
+                                         LWS_SEND_BUFFER_PRE_PADDING, in, len);
+               if (ringbuffer_head == (MAX_MESSAGE_QUEUE - 1))
+                       ringbuffer_head = 0;
+               else
+                       ringbuffer_head++;
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+
 /* list of supported protocols and callbacks */
 
 static const struct libwebsocket_protocols protocols[] = {
@@ -123,6 +223,12 @@ static const struct libwebsocket_protocols protocols[] = {
                .per_session_data_size =
                                sizeof(struct per_session_data__dumb_increment),
        },
+       {
+               .name = "lws-mirror-protocol",
+               .callback = callback_lws_mirror,
+               .per_session_data_size =
+                               sizeof(struct per_session_data__lws_mirror),
+       },
        {  /* end of list */
                .callback = NULL
        }
index 1539209..e2c9934 100644 (file)
@@ -15,48 +15,161 @@ reset the number.<br><br>
        <tr>
                <td align=center><input type=button id=offset value="Reset counter" onclick="reset();" ></td>
                <td width=100 align=center><div id=number> </div></td>
-               <td id=statustd align=center><div id=wsstatus>Not initialized</div></td>
+               <td id=wsdi_statustd align=center><div id=wsdi_status>Not initialized</div></td>
+       </tr>
+</table>
+
+<h2>libwebsockets "lws-mirror-protocol" test applet</h2>
+Use the mouse to draw on the canvas below -- all other browser windows open
+on this page see your drawing in realtime and you can see any of theirs as
+well.
+<p>
+The lws-mirror protocol doesn't interpret what is being sent to it, it just
+re-sends it to every other websocket it has a connection with using that
+protocol, including the guy who sent the packet.
+<br><br>
+
+<table>
+       <tr>
+               <td>Drawing color:
+               <select id="color" onchange="update_color();">
+                       <option value=#000000>Black</option>
+                       <option value=#0000ff>Blue</option>
+                       <option value=#20ff20>Green</option>
+                       <option value=#802020>Dark Red</option>
+               </select>
+               </td>
+               <td id=wslm_statustd align=center><div id=wslm_status>Not initialized</div></td>
+       </tr>
+       <tr>
+               <td colspan=2 width=500 align=center style="background-color: #e0e0e0;"><div id=wslm_drawing> </div></td>
        </tr>
 </table>
 
 <script>
        var pos = 0;
-       var websocket_ads;
 
+function get_appropriate_ws_url(ads)
+{
        /*
         * We open the websocket encrypted if this page came on an
         * https:// url itself, otherwise unencrypted
         */
 
        if (document.URL.substring(0, 5) == "https")
-               websocket_ads = "wss://127.0.0.1:7681";
+               return "wss://"+ads;
        else
-               websocket_ads = "ws://127.0.0.1:7681"
+               return "ws://"+ads;
+}
+
+/* dumb increment protocol */
        
-       var socket = new WebSocket(websocket_ads, "dumb-increment-protocol");  
+       var socket_di = new WebSocket(get_appropriate_ws_url("127.0.0.1:7681"),
+                                  "dumb-increment-protocol");  
 
        try {
-               socket.onopen = function() {
-                       statustd.style.backgroundColor = "#40ff40";
-                       wsstatus.textContent = " websocket connection opened ";
+               socket_di.onopen = function() {
+                       wsdi_statustd.style.backgroundColor = "#40ff40";
+                       wsdi_status.textContent = " websocket connection opened ";
                } 
 
-               socket.onmessage =function got_packet(msg) {
+               socket_di.onmessage =function got_packet(msg) {
                        number.textContent = msg.data + "\n";
                } 
 
-               socket.onclose = function(){
-                       statustd.style.backgroundColor = "#ff4040";
-                       wsstatus.textContent = " websocket connection closed ";
+               socket_di.onclose = function(){
+                       wsdi_statustd.style.backgroundColor = "#ff4040";
+                       wsdi_status.textContent = " websocket connection closed ";
                }
        } catch(exception) {
-               alert('<p>Error'+exception);  
+               alert('<p>Error' + exception);  
        }
 
 function reset() {
-       socket.send("reset\n");
+       socket_di.send("reset\n");
+}
+
+
+/* lws-mirror protocol */
+
+       var down = 0;
+       var no_last = 1;
+       var last_x, last_y;
+       var ctx;
+       var socket_lm = new WebSocket(get_appropriate_ws_url("127.0.0.1:7681"),
+                                  "lws-mirror-protocol");
+       var color = "#000000";
+
+       try {
+               socket_lm.onopen = function() {
+                       wslm_statustd.style.backgroundColor = "#40ff40";
+                       wslm_status.textContent = " websocket connection opened ";
+               } 
+
+               socket_lm.onmessage =function got_packet(msg) {
+                       i = msg.data.split(' ');
+                       if (i[0] == 'd') {
+                               ctx.strokeStyle = i[1];
+                               ctx.beginPath();
+                               ctx.moveTo(i[2], i[3]);
+                               ctx.lineTo(i[4], i[5]);
+                               ctx.stroke();
+                       }
+               }
+
+               socket_lm.onclose = function(){
+                       wslm_statustd.style.backgroundColor = "#ff4040";
+                       wslm_status.textContent = " websocket connection closed ";
+               }
+       } catch(exception) {
+               alert('<p>Error' + exception);  
+       }
+
+       var canvas = document.createElement('canvas');
+       canvas.height = 300;
+       canvas.width = 480;
+       ctx = canvas.getContext("2d");
+
+       document.getElementById('wslm_drawing').appendChild(canvas);
+
+       canvas.addEventListener('mousemove', ev_mousemove, false);
+       canvas.addEventListener('mousedown', ev_mousedown, false);
+       canvas.addEventListener('mouseup', ev_mouseup, false);
+
+function update_color() {
+       color = document.getElementById("color").value;
+}
+
+function ev_mousedown (ev) {
+       down = 1;
 }
 
+function ev_mouseup(ev) {
+       down = 0;
+       no_last = 1;
+}
+
+function ev_mousemove (ev) {
+       var x, y;
+
+       x = ev.offsetX;
+       y = ev.offsetY;
+
+       if (!down)
+               return;
+       if (no_last) {
+               no_last = 0;
+               last_x = x;
+               last_y = y;
+               return;
+       }
+       socket_lm.send("d " + color + " " + last_x + " " + last_y + " " + x + ' ' + y);
+
+       last_x = x;
+       last_y = y;
+}
+
+
 </script>
 
 </body>