From c583913290e6dc9e70dec232f65a3c0271b68b2d Mon Sep 17 00:00:00 2001
From: Sergey Lyubka <valenok@gmail.com>
Date: Mon, 9 Jun 2014 17:25:08 +0100
Subject: [PATCH] Added pubsub example

---
 examples/pubsub.html  | 98 +++++++++++++++++++++++++++++++++++++++++++
 examples/websocket2.c | 92 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 190 insertions(+)
 create mode 100644 examples/pubsub.html
 create mode 100644 examples/websocket2.c

diff --git a/examples/pubsub.html b/examples/pubsub.html
new file mode 100644
index 000000000..f73d8f689
--- /dev/null
+++ b/examples/pubsub.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8" />
+  <title>WebSocket Test</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1" />
+  <style type="text/css">
+    body {
+      background-color: #cde; margin: 0;
+      padding: 0; font: 14px Helvetica, Arial, sans-serif;
+    }
+    div.content {
+      width: 800px; margin: 2em auto; padding: 20px 50px;
+      background-color: #fff; border-radius: 1em;
+    }
+    #messages {
+      border: 2px solid #fec; border-radius: 1em;
+      height: 10em; overflow: scroll; padding: 0.5em 1em;
+    }
+    a:link, a:visited { color: #69c; text-decoration: none; }
+    @media (max-width: 700px) {
+      body { background-color: #fff; }
+      div.content {
+        width: auto; margin: 0 auto; border-radius: 0;
+        padding: 1em;
+      }
+    }
+</style>
+
+<script language="javascript" type="text/javascript">
+
+  var rooms = [];
+  var ws = new WebSocket('ws://' + location.host + '/ws');
+
+  if (!window.console) { window.console = { log: function() {} } };
+
+  ws.onopen = function(ev)  { console.log(ev); };
+  ws.onerror = function(ev) { console.log(ev); };
+  ws.onclose = function(ev) { console.log(ev); };
+  ws.onmessage = function(ev) {
+    console.log(ev);
+    var m = (ev.data || '').match(/^(\S+) (.+)/);
+    if (m[1] == 'id') {
+      document.getElementById('my_id').innerText = m[2];
+    } else if (m[1] == 'msg') {
+      var div = document.createElement('div');
+      div.innerHTML = m[2];
+      document.getElementById('messages').appendChild(div);
+    }
+  };
+  
+  window.onload = function() {
+    document.getElementById('send_button').onclick = function(ev) {
+      var msg = document.getElementById('send_input').value;
+      ws.send('msg ' + msg);
+    };
+    document.getElementById('room_sel').onchange = function(ev) {
+      var roomName = this.value || '?';
+      ws.send('join ' + roomName);
+    };
+  };
+</script>
+</head>
+<body>
+  <div class="content">
+    <h1>Websocket PubSub Demonstration</h1>
+
+    <p>
+      This page demonstrates how Mongoose web server could be used to implement
+      <a href="http://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern">
+       publish–subscribe pattern</a>. Open this page in several browser
+       windows. Each window initiates persistent
+       <a href="http://en.wikipedia.org/wiki/WebSocket">WebSocket</a>
+      connection with Mongoose, making each browser window a websocket client.
+      Join a room, send messages, and see messages sent by other clients.
+    </p>
+    
+    <p>
+      My ID: <b><span id="my_id"></b></span>
+    </p>
+    <p>
+      Join room: <select id="room_sel">
+        <option value="">-- select room -- </option>
+        <option>A</option>
+        <option>B</option>
+      </select>
+    </p>
+
+    <div id="messages">
+    </div>
+    
+    <p>
+      <input type="text" id="send_input" />
+      <button id="send_button">Send Message</button>
+    </p>
+  </div>
+</body>
+</html>
diff --git a/examples/websocket2.c b/examples/websocket2.c
new file mode 100644
index 000000000..d0be9bbec
--- /dev/null
+++ b/examples/websocket2.c
@@ -0,0 +1,92 @@
+#include <string.h>
+#include <time.h>
+#include <signal.h>
+#include <stdlib.h>
+#include "mongoose.h"
+
+static int s_signal_received = 0;
+static struct mg_server *s_server = NULL;
+
+// Data associated with each websocket connection
+struct conn_data {
+  int room;
+};
+
+static void signal_handler(int sig_num) {
+  signal(sig_num, signal_handler);  // Reinstantiate signal handler
+  s_signal_received = sig_num;
+}
+
+#if 0
+static int iterate_callback(struct mg_connection *c, enum mg_event ev) {
+  if (ev == MG_POLL && c->is_websocket) {
+    char buf[20];
+    int len = snprintf(buf, sizeof(buf), "%lu",
+     (unsigned long) * (time_t *) c->callback_param);
+    mg_websocket_write(c, 1, buf, len);
+  }
+  return MG_TRUE;
+}
+#endif
+
+static void handle_websocket_message(struct mg_connection *conn) {
+  struct conn_data *d = (struct conn_data *) conn->connection_param;
+  struct mg_connection *c;
+
+  printf("[%.*s]\n", (int) conn->content_len, conn->content);
+  if (conn->content_len > 5 && !memcmp(conn->content, "join ", 5)) {
+    // Client joined new room
+    d->room = conn->content[5];
+  } else if (conn->content_len > 4 && !memcmp(conn->content, "msg ", 4) &&
+             d->room != 0 && d->room != '?') {
+    // Client has sent a message. Push this message to all clients
+    // that are subscribed to the same room as client
+    for (c = mg_next(s_server, NULL); c != NULL; c = mg_next(s_server, c)) {
+      struct conn_data *d2 = (struct conn_data *) c->connection_param;
+      if (!c->is_websocket || d2->room != d->room) continue;
+      mg_websocket_printf(c, WEBSOCKET_OPCODE_TEXT, "msg %c %p %.*s",
+                          (char) d->room, conn,
+                          conn->content_len - 4, conn->content + 4);
+    }
+  }
+}
+
+static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
+  switch (ev) {
+    case MG_REQUEST:
+      if (conn->is_websocket) {
+        handle_websocket_message(conn);
+        return MG_TRUE;
+      } else {
+        mg_send_file(conn, "pubsub.html");  // Return MG_MORE after mg_send_file()
+        return MG_MORE;
+      }
+    case MG_WS_CONNECT:
+      // New websocket connection. Send connection ID back to the client.
+      conn->connection_param = calloc(1, sizeof(struct conn_data));
+      mg_websocket_printf(conn, WEBSOCKET_OPCODE_TEXT, "id %p", conn);
+      return MG_FALSE;
+    case MG_CLOSE:
+      free(conn->connection_param);
+      return MG_TRUE;
+    case MG_AUTH:
+      return MG_TRUE;
+    default:
+      return MG_FALSE;
+  }
+}
+
+int main(void) {
+  s_server = mg_create_server(NULL, ev_handler);
+  mg_set_option(s_server, "listening_port", "8080");
+  
+  signal(SIGTERM, signal_handler);
+  signal(SIGINT, signal_handler);
+  
+  printf("Started on port %s\n", mg_get_option(s_server, "listening_port"));
+  while (s_signal_received == 0) {
+    mg_poll_server(s_server, 100);
+  }
+  mg_destroy_server(&s_server);
+  return 0;
+}
-- 
GitLab