From 7690f9e34b36124948abe07d2ef4895ab685f403 Mon Sep 17 00:00:00 2001
From: Sergey Lyubka <valenok@gmail.com>
Date: Fri, 17 Jan 2014 10:17:15 +0000
Subject: [PATCH] Fixed websocket example, and websocket callback calling
 logic.

---
 examples/Makefile                       |  9 ++-
 examples/mkdata.pl                      | 53 ++++++++++++++
 examples/qcomm.c                        | 48 -------------
 examples/websocket.c                    | 92 ++++++++++---------------
 examples/websocket_html_root/index.html | 44 ------------
 examples/websocket_html_root/ws.html    | 43 ------------
 mongoose.c                              |  2 +-
 7 files changed, 96 insertions(+), 195 deletions(-)
 create mode 100644 examples/mkdata.pl
 delete mode 100644 examples/qcomm.c
 delete mode 100644 examples/websocket_html_root/index.html
 delete mode 100644 examples/websocket_html_root/ws.html

diff --git a/examples/Makefile b/examples/Makefile
index 8dbb6512f..51537035a 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -18,9 +18,9 @@ else
   endif
 endif
 
-all:
+all: websocket_html.c
 	$(CC) hello.c ../mongoose.c  -o hello $(CFLAGS)
-	$(CC) qcomm.c ../mongoose.c  -o qcomm $(CFLAGS)
+	$(CC) websocket.c websocket_html.c ../mongoose.c  -o websocket $(CFLAGS)
 	$(CC) post.c ../mongoose.c -o post $(CFLAGS)
 	$(CC) multi_threaded.c ../mongoose.c -o multi_threaded $(CFLAGS)
 	$(CC) upload.c ../mongoose.c -o upload $(CFLAGS)
@@ -31,6 +31,8 @@ all:
 #	$(CC) chat.c ../mongoose.c -o chat $(CFLAGS)
 #	$(CC) lua_dll.c ../build/lua_5.2.1.c -o $@.so $(CFLAGS) $(DLL_FLAGS)
 
+websocket_html.c: websocket.html
+	perl mkdata.pl $< > $@
 
 MSVC    = ../../vc6
 CL      = $(MSVC)/bin/cl
@@ -38,8 +40,9 @@ CLFLAGS = /MD /TC /nologo $(DBG) /W3 /DNO_SSL \
         /I$(MSVC)/include /I.. /Dsnprintf=_snprintf
 LFLAGS  = /link /incremental:no /libpath:$(MSVC)/lib /machine:IX86
 
-windows:
+windows: websocket_html.c
 	$(CL) hello.c ../mongoose.c $(CLFLAGS) $(LFLAGS)
+	$(CL) websocket.c websocket_html.c ../mongoose.c $(CLFLAGS) $(LFLAGS)
 	$(CL) post.c ../mongoose.c $(CLFLAGS) $(LFLAGS)
 	$(CL) multi_threaded.c ../mongoose.c $(CLFLAGS) $(LFLAGS)
 	$(CL) upload.c ../mongoose.c $(CLFLAGS) $(LFLAGS)
diff --git a/examples/mkdata.pl b/examples/mkdata.pl
new file mode 100644
index 000000000..cf75a0d25
--- /dev/null
+++ b/examples/mkdata.pl
@@ -0,0 +1,53 @@
+# This program is used to embed arbitrary data into a C binary. It takes
+# a list of files as an input, and produces a .c data file that contains
+# contents of all these files as collection of char arrays.
+#
+# Usage: perl <this_file> <file1> [file2, ...] > embedded_data.c
+
+foreach my $i (0 .. $#ARGV) {
+  open FD, '<:raw', $ARGV[$i] or die "Cannot open $ARGV[$i]: $!\n";
+  printf("static const unsigned char v%d[] = {", $i);
+  my $byte;
+  my $j = 0;
+  while (read(FD, $byte, 1)) {
+    if (($j % 12) == 0) {
+      print "\n";
+    }
+    printf ' %#04x,', ord($byte);
+    $j++;
+  }
+  print " 0x00\n};\n";
+  close FD;
+}
+
+print <<EOS;
+
+#include <stddef.h>
+#include <string.h>
+
+static const struct embedded_file {
+  const char *name;
+  const unsigned char *data;
+  size_t size;
+} embedded_files[] = {
+EOS
+
+foreach my $i (0 .. $#ARGV) {
+  print "  {\"$ARGV[$i]\", v$i, sizeof(v$i) - 1},\n";
+}
+
+print <<EOS;
+  {NULL, NULL, 0}
+};
+
+const char *find_embedded_file(const char *name, size_t *size) {
+  const struct embedded_file *p;
+  for (p = embedded_files; p->name != NULL; p++) {
+    if (!strcmp(p->name, name)) {
+      if (size != NULL) { *size = p->size; }
+      return (const char *) p->data;
+    }
+  }
+  return NULL;
+}
+EOS
diff --git a/examples/qcomm.c b/examples/qcomm.c
deleted file mode 100644
index 5212a3615..000000000
--- a/examples/qcomm.c
+++ /dev/null
@@ -1,48 +0,0 @@
-#include <unistd.h>
-#include <string.h>
-
-#include "mongoose.h"
-
-static void iterate_callback(struct mg_connection *c, void *param) {
-  if (c->is_websocket) {
-    char buf[20];
-    int len = snprintf(buf, sizeof(buf), "%d", * (int *) param);
-    mg_websocket_write(c, 1, buf, len);
-  }
-}
-
-// This handler is called for each incoming websocket frame, one or more
-// times for connection lifetime.
-static int handler(struct mg_connection *conn) {
-  static const char oops[] = "HTTP/1.0 200 OK\r\n\r\nwebsocket data expected\n";
-
-  if (!conn->is_websocket) {
-    mg_write(conn, oops, sizeof(oops) - 1);
-    return 1;
-  }
-
-  mg_websocket_write(conn, 1, conn->content, conn->content_len);
-
-  return conn->content_len == 4 && !memcmp(conn->content, "exit", 4);
-}
-
-int main(int argc, char *argv[]) {
-  struct mg_server *server = mg_create_server(NULL);
-  unsigned int current_timer = 0, last_timer = 0;
-
-  mg_set_option(server, "listening_port", "8080");
-  mg_set_option(server, "document_root", argc > 1 ? argv[1] : ".");
-  mg_add_uri_handler(server, "/ws", handler);
-
-  printf("Started on port %s\n", mg_get_option(server, "listening_port"));
-  for (;;) {
-    current_timer = mg_poll_server(server, 1);
-    if (current_timer - last_timer > 4) {
-      last_timer = current_timer;
-      mg_iterate_over_connections(server, iterate_callback, &current_timer);
-    }
-  }
-
-  mg_destroy_server(&server);
-  return 0;
-}
diff --git a/examples/websocket.c b/examples/websocket.c
index 5fbf5005f..67306d9d4 100644
--- a/examples/websocket.c
+++ b/examples/websocket.c
@@ -1,67 +1,47 @@
-// Copyright (c) 2004-2012 Sergey Lyubka
-// This file is a part of mongoose project, http://github.com/valenok/mongoose
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
 #include "mongoose.h"
 
-static int event_handler(struct mg_event *event) {
-
-  if (event->type == MG_REQUEST_BEGIN) {
-    const char *version_header = mg_get_header(event->conn,
-                                               "Sec-WebSocket-Version");
-
-    if (version_header != NULL) {
-      // Websocket request, process it
-      if (strcmp(version_header, "13") != 0) {
-        mg_printf(event->conn, "%s", "HTTP/1.1 426 Upgrade Required\r\n\r\n");
-      } else {
-        static const char *server_ready_message = "server ready";
-        char *data;
-        int bits, len, must_exit = 0;
-
-        // Handshake, and send initial server message
-        mg_websocket_handshake(event->conn);
-        mg_websocket_write(event->conn, WEBSOCKET_OPCODE_TEXT,
-                           server_ready_message, strlen(server_ready_message));
-
-        // Read messages sent by client. Echo them back.
-        while (must_exit == 0 &&
-               (len = mg_websocket_read(event->conn, &bits, &data)) > 0) {
-
-          printf("got message: [%.*s]\n", len, data);
-          mg_websocket_write(event->conn, WEBSOCKET_OPCODE_TEXT, data, len);
-
-          // If the message is "exit", close the connection, exit the loop
-          if (memcmp(data, "exit", 4) == 0) {
-            mg_websocket_write(event->conn,
-                               WEBSOCKET_OPCODE_CONNECTION_CLOSE, "", 0);
-            must_exit = 1;
-          }
+extern const char *find_embedded_file(const char *, size_t *);
 
-          // It's our responsibility to free allocated message
-          free(data);
-        }
-      }
-      return 1;
-    }
+static void iterate_callback(struct mg_connection *c, void *param) {
+  if (c->is_websocket) {
+    char buf[20];
+    int len = snprintf(buf, sizeof(buf), "%d", * (int *) param);
+    mg_websocket_write(c, 1, buf, len);
   }
+}
 
-  return 0;
+// This handler is called for each incoming websocket frame, one or more
+// times for connection lifetime.
+static int index_html(struct mg_connection *conn) {
+  size_t index_size;
+  const char *index_html = find_embedded_file("websocket.html", &index_size);
+
+  if (conn->is_websocket) {
+    mg_websocket_write(conn, 1, conn->content, conn->content_len);
+    return conn->content_len == 4 && !memcmp(conn->content, "exit", 4);
+  } else {
+    mg_send_header(conn, "Content-Type", "text/html");
+    mg_send_data(conn, index_html, index_size);
+    return 1;
+  }
 }
 
 int main(void) {
-  struct mg_context *ctx;
-  const char *options[] = {
-    "listening_ports", "8080",
-    "document_root", "websocket_html_root",
-    NULL
-  };
-
-  ctx = mg_start(options, &event_handler, NULL);
-  getchar();  // Wait until user hits "enter"
-  mg_stop(ctx);
+  struct mg_server *server = mg_create_server(NULL);
+  unsigned int current_timer = 0, last_timer = 0;
+
+  mg_set_option(server, "listening_port", "8080");
+  mg_add_uri_handler(server, "/", index_html);
+
+  printf("Started on port %s\n", mg_get_option(server, "listening_port"));
+  for (;;) {
+    current_timer = mg_poll_server(server, 100);
+    if (current_timer - last_timer > 4) {
+      last_timer = current_timer;
+      mg_iterate_over_connections(server, iterate_callback, &current_timer);
+    }
+  }
 
+  mg_destroy_server(&server);
   return 0;
 }
diff --git a/examples/websocket_html_root/index.html b/examples/websocket_html_root/index.html
deleted file mode 100644
index 8c5f765fc..000000000
--- a/examples/websocket_html_root/index.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8" />
-<title>WebSocket Test</title>
-<script language="javascript" type="text/javascript">
-
-  var writeToScreen = function(message) {
-    var div = document.createElement('div');
-    div.innerHTML = message;
-    document.getElementById('output').appendChild(div);
-  };
-  window.onload = function() {
-    var url = 'ws://' + window.location.host + '/foo';
-    websocket = new WebSocket(url);
-    websocket.onopen = function(ev) {
-      writeToScreen('CONNECTED');
-      var message = 'Не всё подчиняется разуму. Но всё подчиняется упорству. ';
-      writeToScreen('SENT: ' + message);
-      websocket.send(message);
-    };
-    websocket.onclose = function(ev) {
-      writeToScreen('DISCONNECTED');
-    };
-    websocket.onmessage = function(ev) {
-      writeToScreen('<span style="color: blue;">RESPONSE: ' + ev.data +
-                    ' </span>');
-      websocket.send('exit');
-    };
-    websocket.onerror = function(ev) {
-      writeToScreen('<span style="color: red; ">ERROR: </span> ' + ev.data);
-    };
-  };
-</script>
-<style> div {font: small Verdana; } </style>
-<h2>Mongoose WebSocket Test</h2>
-
-  <div style="width: 400px; color: #aaa; padding: 1em; ">
-  This page code creates websocket to the URI "/foo",
-  sends a message to it, waits for the reply, then sends an "exit" message.
-  Server must echo all messages back, and terminate the conversation after
-  receiving the "exit" message.
-  </div>
-
-<div id="output"></div>
-</html>
diff --git a/examples/websocket_html_root/ws.html b/examples/websocket_html_root/ws.html
deleted file mode 100644
index 8f83a0bb7..000000000
--- a/examples/websocket_html_root/ws.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8" />
-<title>WebSocket Test</title>
-<script language="javascript" type="text/javascript">
-
-  var out = function(message) {
-    var div = document.createElement('div');
-    div.innerHTML = message;
-    document.getElementById('output').appendChild(div);
-  };
-
-  window.onload = function() {
-    var url = 'ws://' + location.host + '/ws';
-    var num_messages = 0;
-
-    websocket = new WebSocket(url);
-    websocket.onopen = function(ev) {
-      out('CONNECTED');
-      var msg = 'Не всё подчиняется разуму. Но всё подчиняется упорству. ';
-      out('SENT: ' + msg);
-      websocket.send(msg);
-    };
-    websocket.onclose = function(ev) {
-      out('DISCONNECTED');
-    };
-    websocket.onmessage = function(ev) {
-      if (!ev.data) return; // No data, this is a PING message, ignore it
-      out('<span style="color: blue;">RESPONSE: ' + ev.data + ' </span>');
-      num_messages++;
-      if (num_messages > 100) {
-        websocket.send('exit');
-      }
-    };
-    websocket.onerror = function(ev) {
-      out('<span style="color: red; ">ERROR: </span> ' + ev.data);
-    };
-  };
-</script>
-<style> div {font: small Verdana; } </style>
-<h2>Qualcomm WebSocket Test</h2>
-
-<div id="output"></div>
-</html>
diff --git a/mongoose.c b/mongoose.c
index ad9afc5cb..d9bdaebf0 100644
--- a/mongoose.c
+++ b/mongoose.c
@@ -1940,7 +1940,7 @@ static void write_to_client(struct connection *conn) {
     conn->num_bytes_sent += n;
   }
 
-  if (conn->endpoint_type == EP_USER) {
+  if (conn->endpoint_type == EP_USER && !conn->mg_conn.is_websocket) {
     conn->mg_conn.wsbits = conn->flags & CONN_CLOSE ? 1 : 0;
     call_uri_handler(conn);
   }
-- 
GitLab