mirror of
https://github.com/cesanta/mongoose.git
synced 2024-11-28 13:49:01 +08:00
Fixed websocket example, and websocket callback calling logic.
This commit is contained in:
parent
65c1278975
commit
7690f9e34b
@ -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)
|
||||
|
53
examples/mkdata.pl
Normal file
53
examples/mkdata.pl
Normal file
@ -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
|
@ -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, ¤t_timer);
|
||||
}
|
||||
}
|
||||
|
||||
mg_destroy_server(&server);
|
||||
return 0;
|
||||
}
|
@ -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) {
|
||||
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.
|
||||
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;
|
||||
}
|
||||
|
||||
// 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
|
||||
};
|
||||
struct mg_server *server = mg_create_server(NULL);
|
||||
unsigned int current_timer = 0, last_timer = 0;
|
||||
|
||||
ctx = mg_start(options, &event_handler, NULL);
|
||||
getchar(); // Wait until user hits "enter"
|
||||
mg_stop(ctx);
|
||||
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, ¤t_timer);
|
||||
}
|
||||
}
|
||||
|
||||
mg_destroy_server(&server);
|
||||
return 0;
|
||||
}
|
||||
|
@ -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>
|
@ -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>
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user