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