Commit 2260c8dd authored by Igor Okulist's avatar Igor Okulist

Merge branch 'master' of https://github.com/okigan/mongoose

parents 4f01f101 edffc46b
......@@ -14,7 +14,8 @@ Features
- IP-based ACL, Windows service, GET, POST, HEAD, PUT, DELETE methods
- Small footprint: executable size is 40 kB on Linux 2.6 i386 system
- Embeddable with [simple and clean API](https://github.com/valenok/mongoose/blob/master/mongoose.h). Source is in single .c file to make things easy.
- Examples: [hello.c](https://github.com/valenok/mongoose/blob/master/examples/hello.c), [post.c](https://github.com/valenok/mongoose/blob/master/examples/post.c), [upload.c](https://github.com/valenok/mongoose/blob/master/examples/upload.c)
- Examples: [hello.c](https://github.com/valenok/mongoose/blob/master/examples/hello.c), [post.c](https://github.com/valenok/mongoose/blob/master/examples/post.c), [upload.c](https://github.com/valenok/mongoose/blob/master/examples/upload.c), [websocket.c](https://github.com/valenok/mongoose/blob/master/examples/websocket.c)
- Python and C# bindings
......
......@@ -4,5 +4,7 @@ all:
OS=`uname`; \
test "$$OS" = Linux && LIBS="-ldl" ; \
$(CC) $(CFLAGS) hello.c ../mongoose.c $$LIBS $(ADD) -o hello;
$(CC) $(CFLAGS) upload.c ../mongoose.c $$LIBS $(ADD) -o upload;
$(CC) $(CFLAGS) post.c ../mongoose.c $$LIBS $(ADD) -o post;
$(CC) $(CFLAGS) -DUSE_WEBSOCKET websocket.c ../mongoose.c $$LIBS $(ADD) -o websocket;
$(CC) $(CFLAGS) chat.c ../mongoose.c $$LIBS $(ADD) -o chat
// 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 "mongoose.h"
static void *callback(enum mg_event event, struct mg_connection *conn) {
if (event == MG_WEBSOCKET_READY) {
static const char *hello = "hello from mongoose! waiting for message ...";
char frame[2];
// Prepare websocket frame.
frame[0] = 0x81; // text frame
frame[1] = strlen(hello); // length is < 126
// Write frame and a text message
mg_write(conn, frame, sizeof(frame));
mg_write(conn, hello, strlen(hello));
return "";
} else if (event == MG_WEBSOCKET_MESSAGE) {
unsigned char buf[500], reply[500];
int len, msg_len, i, mask_len, xor;
// Read message from the client and echo it back
if ((len = mg_read(conn, buf, sizeof(buf))) > 8) {
msg_len = buf[1] & 127;
mask_len = (buf[1] & 128) ? 4 : 0;
if (msg_len < 126) {
reply[0] = 0x81; // text, FIN set
reply[1] = msg_len;
for (i = 0; i < msg_len; i++) {
xor = mask_len == 0 ? 0 : buf[2 + (i % 4)];
reply[i + 2] = buf[i + 2 + mask_len] ^ xor;
}
mg_write(conn, reply, 2 + msg_len);
}
}
return ""; // Return non-NULL: stop websocket conversation
} else {
return NULL;
}
}
int main(void) {
struct mg_context *ctx;
const char *options[] = {
"listening_ports", "8080",
"document_root", "websocket_html_root",
NULL
};
ctx = mg_start(&callback, NULL, options);
getchar(); // Wait until user hits "enter"
mg_stop(ctx);
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.close();
};
websocket.onerror = function(ev) {
writeToScreen('<span style="color: red; ">ERROR: </span> ' + ev.data);
};
};
</script>
<h2>WebSocket Test</h2>
<div id="output"></div>
</html>
......@@ -219,9 +219,11 @@ static void init_server_name(void) {
static void *mongoose_callback(enum mg_event ev, struct mg_connection *conn) {
if (ev == MG_EVENT_LOG) {
printf("%s\n", mg_get_request_info(conn)->log_message);
printf("%s\n", mg_get_log_message(conn));
}
// Returning NULL marks request as not handled, signalling mongoose to
// proceed with handling it.
return NULL;
}
......
......@@ -82,8 +82,6 @@ Use
as a CGI interpreter for all CGI scripts regardless script extension.
Mongoose decides which interpreter to use by looking at
the first line of a CGI script. Default: "".
.It Fl M Ar max_request_size
Maximum HTTP request size in bytes. Default: "16384"
.It Fl P Ar protect_uri
Comma separated list of URI=PATH pairs, specifying that given URIs
must be protected with respected password files. Default: ""
......
This diff is collapsed.
......@@ -34,16 +34,13 @@ struct mg_connection; // Handle for the individual connection
// This structure contains information about the HTTP request.
struct mg_request_info {
void *user_data; // User-defined pointer passed to mg_start()
char *request_method; // "GET", "POST", etc
char *uri; // URL-decoded URI
char *http_version; // E.g. "1.0", "1.1"
char *query_string; // URL part after '?' (not including '?') or NULL
char *remote_user; // Authenticated user, or NULL if no auth used
char *log_message; // Mongoose error log message, MG_EVENT_LOG only
long remote_ip; // Client's IP address
int remote_port; // Client's port
int status_code; // HTTP reply status code, e.g. 200
int is_ssl; // 1 if SSL-ed, 0 if not
int num_headers; // Number of headers
struct mg_header {
......@@ -52,16 +49,23 @@ struct mg_request_info {
} http_headers[64]; // Maximum 64 headers
};
// Various events on which user-defined function is called by Mongoose.
enum mg_event {
MG_NEW_REQUEST, // New HTTP request has arrived from the client
MG_REQUEST_COMPLETE, // Mongoose has finished handling the request
MG_HTTP_ERROR, // HTTP error must be returned to the client
MG_EVENT_LOG, // Mongoose logs an event, request_info.log_message
MG_INIT_SSL // Mongoose initializes SSL. Instead of mg_connection *,
// SSL context is passed to the callback function.
MG_INIT_SSL, // SSL initialization, sent before certificate setup
MG_WEBSOCKET_CONNECT, // Sent on HTTP connect, before websocket handshake.
// If user callback returns NULL, then mongoose proceeds
// with handshake, otherwise it closes the connection.
MG_WEBSOCKET_READY, // Handshake has been successfully completed.
MG_WEBSOCKET_MESSAGE, // Incoming message from the client
MG_WEBSOCKET_CLOSE, // Client has sent FIN frame
};
// Prototype for the user-defined function. Mongoose calls this function
// on every MG_* event.
//
......@@ -77,8 +81,7 @@ enum mg_event {
// If handler returns NULL, that means that handler has not processed
// the request. Handler must not send any data to the client in this case.
// Mongoose proceeds with request handling as if nothing happened.
typedef void * (*mg_callback_t)(enum mg_event event,
struct mg_connection *conn);
typedef void *(*mg_callback_t)(enum mg_event event, struct mg_connection *conn);
// Start web server.
......@@ -151,9 +154,13 @@ int mg_modify_passwords_file(const char *passwords_file_name,
const char *password);
// Return mg_request_info structure associated with the request.
// Always succeeds.
// Return information associated with the request.
// These functions always succeed.
const struct mg_request_info *mg_get_request_info(const struct mg_connection *);
void *mg_get_user_data(struct mg_connection *);
const char *mg_get_log_message(const struct mg_connection *);
int mg_get_reply_status_code(const struct mg_connection *);
void *mg_get_ssl_context(const struct mg_connection *);
// Send data to the client.
......
......@@ -119,9 +119,10 @@ static void test_get_request_info(struct mg_connection *conn,
static void test_error(struct mg_connection *conn,
const struct mg_request_info *ri) {
(void) ri;
mg_printf(conn, "HTTP/1.1 %d XX\r\n"
"Conntection: close\r\n\r\n", ri->status_code);
mg_printf(conn, "Error: [%d]", ri->status_code);
"Conntection: close\r\n\r\n", mg_get_reply_status_code(conn));
mg_printf(conn, "Error: [%d]", mg_get_reply_status_code(conn));
}
static void test_post(struct mg_connection *conn,
......
......@@ -64,10 +64,10 @@ static void test_should_keep_alive(void) {
parse_http_request(req4, sizeof(req4), &conn.request_info);
ASSERT(should_keep_alive(&conn) == 1);
conn.request_info.status_code = 401;
conn.status_code = 401;
ASSERT(should_keep_alive(&conn) == 0);
conn.request_info.status_code = 200;
conn.status_code = 200;
conn.must_close = 1;
ASSERT(should_keep_alive(&conn) == 0);
}
......@@ -138,7 +138,7 @@ static void *event_handler(enum mg_event event,
"%s", (int) strlen(fetch_data), fetch_data);
return "";
} else if (event == MG_EVENT_LOG) {
printf("%s\n", request_info->log_message);
printf("%s\n", mg_get_log_message(conn));
}
return NULL;
......@@ -196,7 +196,21 @@ static void test_mg_fetch(void) {
mg_stop(ctx);
}
static void test_base64_encode(void) {
const char *in[] = {"a", "ab", "abc", "abcd", NULL};
const char *out[] = {"YQ==", "YWI=", "YWJj", "YWJjZA=="};
char buf[100];
int i;
for (i = 0; in[i] != NULL; i++) {
base64_encode((unsigned char *) in[i], strlen(in[i]), buf);
printf("[%s] [%s]\n", out[i], buf);
ASSERT(!strcmp(buf, out[i]));
}
}
int main(void) {
test_base64_encode();
test_match_prefix();
test_remove_double_dots();
test_should_keep_alive();
......
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