introduce-mirror-test-protocol.patch
Signed-off-by: Andy Green <andy@warmcat.com>
diff --git a/test-server/test-server.c b/test-server/test-server.c
index 50a4975..d35e826 100644
--- a/test-server/test-server.c
+++ b/test-server/test-server.c
@@ -27,6 +27,20 @@
#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 @@
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 @@
}
+/* 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 @@
.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
}
diff --git a/test-server/test.html b/test-server/test.html
index 1539209..e2c9934 100644
--- a/test-server/test.html
+++ b/test-server/test.html
@@ -15,48 +15,161 @@
<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>