Commit 7690f9e3 authored by Sergey Lyubka's avatar Sergey Lyubka

Fixed websocket example, and websocket callback calling logic.

parent 65c12789
...@@ -18,9 +18,9 @@ else ...@@ -18,9 +18,9 @@ else
endif endif
endif endif
all: all: websocket_html.c
$(CC) hello.c ../mongoose.c -o hello $(CFLAGS) $(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) post.c ../mongoose.c -o post $(CFLAGS)
$(CC) multi_threaded.c ../mongoose.c -o multi_threaded $(CFLAGS) $(CC) multi_threaded.c ../mongoose.c -o multi_threaded $(CFLAGS)
$(CC) upload.c ../mongoose.c -o upload $(CFLAGS) $(CC) upload.c ../mongoose.c -o upload $(CFLAGS)
...@@ -31,6 +31,8 @@ all: ...@@ -31,6 +31,8 @@ all:
# $(CC) chat.c ../mongoose.c -o chat $(CFLAGS) # $(CC) chat.c ../mongoose.c -o chat $(CFLAGS)
# $(CC) lua_dll.c ../build/lua_5.2.1.c -o $@.so $(CFLAGS) $(DLL_FLAGS) # $(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 MSVC = ../../vc6
CL = $(MSVC)/bin/cl CL = $(MSVC)/bin/cl
...@@ -38,8 +40,9 @@ CLFLAGS = /MD /TC /nologo $(DBG) /W3 /DNO_SSL \ ...@@ -38,8 +40,9 @@ CLFLAGS = /MD /TC /nologo $(DBG) /W3 /DNO_SSL \
/I$(MSVC)/include /I.. /Dsnprintf=_snprintf /I$(MSVC)/include /I.. /Dsnprintf=_snprintf
LFLAGS = /link /incremental:no /libpath:$(MSVC)/lib /machine:IX86 LFLAGS = /link /incremental:no /libpath:$(MSVC)/lib /machine:IX86
windows: windows: websocket_html.c
$(CL) hello.c ../mongoose.c $(CLFLAGS) $(LFLAGS) $(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) post.c ../mongoose.c $(CLFLAGS) $(LFLAGS)
$(CL) multi_threaded.c ../mongoose.c $(CLFLAGS) $(LFLAGS) $(CL) multi_threaded.c ../mongoose.c $(CLFLAGS) $(LFLAGS)
$(CL) upload.c ../mongoose.c $(CLFLAGS) $(LFLAGS) $(CL) upload.c ../mongoose.c $(CLFLAGS) $(LFLAGS)
......
# 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
#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;
}
// 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" #include "mongoose.h"
static int event_handler(struct mg_event *event) { extern const char *find_embedded_file(const char *, size_t *);
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. static void iterate_callback(struct mg_connection *c, void *param) {
while (must_exit == 0 && if (c->is_websocket) {
(len = mg_websocket_read(event->conn, &bits, &data)) > 0) { char buf[20];
int len = snprintf(buf, sizeof(buf), "%d", * (int *) param);
printf("got message: [%.*s]\n", len, data); mg_websocket_write(c, 1, buf, len);
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;
} }
}
// It's our responsibility to free allocated message // This handler is called for each incoming websocket frame, one or more
free(data); // 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; return 1;
} }
}
return 0;
} }
int main(void) { int main(void) {
struct mg_context *ctx; struct mg_server *server = mg_create_server(NULL);
const char *options[] = { unsigned int current_timer = 0, last_timer = 0;
"listening_ports", "8080",
"document_root", "websocket_html_root", mg_set_option(server, "listening_port", "8080");
NULL mg_add_uri_handler(server, "/", index_html);
};
printf("Started on port %s\n", mg_get_option(server, "listening_port"));
ctx = mg_start(options, &event_handler, NULL); for (;;) {
getchar(); // Wait until user hits "enter" current_timer = mg_poll_server(server, 100);
mg_stop(ctx); 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; return 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>
<!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>
...@@ -1940,7 +1940,7 @@ static void write_to_client(struct connection *conn) { ...@@ -1940,7 +1940,7 @@ static void write_to_client(struct connection *conn) {
conn->num_bytes_sent += n; 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; conn->mg_conn.wsbits = conn->flags & CONN_CLOSE ? 1 : 0;
call_uri_handler(conn); call_uri_handler(conn);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment