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 ...@@ -14,7 +14,8 @@ Features
- IP-based ACL, Windows service, GET, POST, HEAD, PUT, DELETE methods - IP-based ACL, Windows service, GET, POST, HEAD, PUT, DELETE methods
- Small footprint: executable size is 40 kB on Linux 2.6 i386 system - 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. - 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 - Python and C# bindings
......
...@@ -4,5 +4,7 @@ all: ...@@ -4,5 +4,7 @@ all:
OS=`uname`; \ OS=`uname`; \
test "$$OS" = Linux && LIBS="-ldl" ; \ test "$$OS" = Linux && LIBS="-ldl" ; \
$(CC) $(CFLAGS) hello.c ../mongoose.c $$LIBS $(ADD) -o hello; $(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) 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 $(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) { ...@@ -219,9 +219,11 @@ static void init_server_name(void) {
static void *mongoose_callback(enum mg_event ev, struct mg_connection *conn) { static void *mongoose_callback(enum mg_event ev, struct mg_connection *conn) {
if (ev == MG_EVENT_LOG) { 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; return NULL;
} }
......
...@@ -82,8 +82,6 @@ Use ...@@ -82,8 +82,6 @@ Use
as a CGI interpreter for all CGI scripts regardless script extension. as a CGI interpreter for all CGI scripts regardless script extension.
Mongoose decides which interpreter to use by looking at Mongoose decides which interpreter to use by looking at
the first line of a CGI script. Default: "". 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 .It Fl P Ar protect_uri
Comma separated list of URI=PATH pairs, specifying that given URIs Comma separated list of URI=PATH pairs, specifying that given URIs
must be protected with respected password files. Default: "" must be protected with respected password files. Default: ""
......
This diff is collapsed.
...@@ -34,16 +34,13 @@ struct mg_connection; // Handle for the individual connection ...@@ -34,16 +34,13 @@ struct mg_connection; // Handle for the individual connection
// This structure contains information about the HTTP request. // This structure contains information about the HTTP request.
struct mg_request_info { struct mg_request_info {
void *user_data; // User-defined pointer passed to mg_start()
char *request_method; // "GET", "POST", etc char *request_method; // "GET", "POST", etc
char *uri; // URL-decoded URI char *uri; // URL-decoded URI
char *http_version; // E.g. "1.0", "1.1" char *http_version; // E.g. "1.0", "1.1"
char *query_string; // URL part after '?' (not including '?') or NULL char *query_string; // URL part after '?' (not including '?') or NULL
char *remote_user; // Authenticated user, or NULL if no auth used 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 long remote_ip; // Client's IP address
int remote_port; // Client's port 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 is_ssl; // 1 if SSL-ed, 0 if not
int num_headers; // Number of headers int num_headers; // Number of headers
struct mg_header { struct mg_header {
...@@ -52,16 +49,23 @@ struct mg_request_info { ...@@ -52,16 +49,23 @@ struct mg_request_info {
} http_headers[64]; // Maximum 64 headers } http_headers[64]; // Maximum 64 headers
}; };
// Various events on which user-defined function is called by Mongoose. // Various events on which user-defined function is called by Mongoose.
enum mg_event { enum mg_event {
MG_NEW_REQUEST, // New HTTP request has arrived from the client MG_NEW_REQUEST, // New HTTP request has arrived from the client
MG_REQUEST_COMPLETE, // Mongoose has finished handling the request MG_REQUEST_COMPLETE, // Mongoose has finished handling the request
MG_HTTP_ERROR, // HTTP error must be returned to the client MG_HTTP_ERROR, // HTTP error must be returned to the client
MG_EVENT_LOG, // Mongoose logs an event, request_info.log_message MG_EVENT_LOG, // Mongoose logs an event, request_info.log_message
MG_INIT_SSL // Mongoose initializes SSL. Instead of mg_connection *, MG_INIT_SSL, // SSL initialization, sent before certificate setup
// SSL context is passed to the callback function. 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 // Prototype for the user-defined function. Mongoose calls this function
// on every MG_* event. // on every MG_* event.
// //
...@@ -77,8 +81,7 @@ enum mg_event { ...@@ -77,8 +81,7 @@ enum mg_event {
// If handler returns NULL, that means that handler has not processed // 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. // the request. Handler must not send any data to the client in this case.
// Mongoose proceeds with request handling as if nothing happened. // Mongoose proceeds with request handling as if nothing happened.
typedef void * (*mg_callback_t)(enum mg_event event, typedef void *(*mg_callback_t)(enum mg_event event, struct mg_connection *conn);
struct mg_connection *conn);
// Start web server. // Start web server.
...@@ -151,9 +154,13 @@ int mg_modify_passwords_file(const char *passwords_file_name, ...@@ -151,9 +154,13 @@ int mg_modify_passwords_file(const char *passwords_file_name,
const char *password); const char *password);
// Return mg_request_info structure associated with the request. // Return information associated with the request.
// Always succeeds. // These functions always succeed.
const struct mg_request_info *mg_get_request_info(const struct mg_connection *); 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. // Send data to the client.
......
...@@ -119,9 +119,10 @@ static void test_get_request_info(struct mg_connection *conn, ...@@ -119,9 +119,10 @@ static void test_get_request_info(struct mg_connection *conn,
static void test_error(struct mg_connection *conn, static void test_error(struct mg_connection *conn,
const struct mg_request_info *ri) { const struct mg_request_info *ri) {
(void) ri;
mg_printf(conn, "HTTP/1.1 %d XX\r\n" mg_printf(conn, "HTTP/1.1 %d XX\r\n"
"Conntection: close\r\n\r\n", ri->status_code); "Conntection: close\r\n\r\n", mg_get_reply_status_code(conn));
mg_printf(conn, "Error: [%d]", ri->status_code); mg_printf(conn, "Error: [%d]", mg_get_reply_status_code(conn));
} }
static void test_post(struct mg_connection *conn, static void test_post(struct mg_connection *conn,
......
...@@ -64,10 +64,10 @@ static void test_should_keep_alive(void) { ...@@ -64,10 +64,10 @@ static void test_should_keep_alive(void) {
parse_http_request(req4, sizeof(req4), &conn.request_info); parse_http_request(req4, sizeof(req4), &conn.request_info);
ASSERT(should_keep_alive(&conn) == 1); ASSERT(should_keep_alive(&conn) == 1);
conn.request_info.status_code = 401; conn.status_code = 401;
ASSERT(should_keep_alive(&conn) == 0); ASSERT(should_keep_alive(&conn) == 0);
conn.request_info.status_code = 200; conn.status_code = 200;
conn.must_close = 1; conn.must_close = 1;
ASSERT(should_keep_alive(&conn) == 0); ASSERT(should_keep_alive(&conn) == 0);
} }
...@@ -138,7 +138,7 @@ static void *event_handler(enum mg_event event, ...@@ -138,7 +138,7 @@ static void *event_handler(enum mg_event event,
"%s", (int) strlen(fetch_data), fetch_data); "%s", (int) strlen(fetch_data), fetch_data);
return ""; return "";
} else if (event == MG_EVENT_LOG) { } else if (event == MG_EVENT_LOG) {
printf("%s\n", request_info->log_message); printf("%s\n", mg_get_log_message(conn));
} }
return NULL; return NULL;
...@@ -196,7 +196,21 @@ static void test_mg_fetch(void) { ...@@ -196,7 +196,21 @@ static void test_mg_fetch(void) {
mg_stop(ctx); 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) { int main(void) {
test_base64_encode();
test_match_prefix(); test_match_prefix();
test_remove_double_dots(); test_remove_double_dots();
test_should_keep_alive(); 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