mirror of
https://github.com/cesanta/mongoose.git
synced 2025-06-10 11:22:54 +08:00
API CHANGE: using struct mg_callbacks
This commit is contained in:
parent
62162ff3e4
commit
ee55d38b55
@ -325,12 +325,10 @@ static void redirect_to_ssl(struct mg_connection *conn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *event_handler(enum mg_event event,
|
static int begin_request_handler(struct mg_connection *conn) {
|
||||||
struct mg_connection *conn) {
|
|
||||||
const struct mg_request_info *request_info = mg_get_request_info(conn);
|
const struct mg_request_info *request_info = mg_get_request_info(conn);
|
||||||
void *processed = "yes";
|
int processed = 1;
|
||||||
|
|
||||||
if (event == MG_NEW_REQUEST) {
|
|
||||||
if (!request_info->is_ssl) {
|
if (!request_info->is_ssl) {
|
||||||
redirect_to_ssl(conn, request_info);
|
redirect_to_ssl(conn, request_info);
|
||||||
} else if (!is_authorized(conn, request_info)) {
|
} else if (!is_authorized(conn, request_info)) {
|
||||||
@ -344,15 +342,8 @@ static void *event_handler(enum mg_event event,
|
|||||||
} else {
|
} else {
|
||||||
// No suitable handler found, mark as not processed. Mongoose will
|
// No suitable handler found, mark as not processed. Mongoose will
|
||||||
// try to serve the request.
|
// try to serve the request.
|
||||||
processed = NULL;
|
processed = 0;
|
||||||
}
|
}
|
||||||
} else if (event == MG_EVENT_LOG) {
|
|
||||||
printf("%s\n", (const char *) mg_get_request_info(conn)->ev_data);
|
|
||||||
processed = NULL;
|
|
||||||
} else {
|
|
||||||
processed = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return processed;
|
return processed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,6 +356,7 @@ static const char *options[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
struct mg_callbacks callbacks;
|
||||||
struct mg_context *ctx;
|
struct mg_context *ctx;
|
||||||
|
|
||||||
// Initialize random number generator. It will be used later on for
|
// Initialize random number generator. It will be used later on for
|
||||||
@ -372,7 +364,9 @@ int main(void) {
|
|||||||
srand((unsigned) time(0));
|
srand((unsigned) time(0));
|
||||||
|
|
||||||
// Setup and start Mongoose
|
// Setup and start Mongoose
|
||||||
if ((ctx = mg_start(&event_handler, NULL, options)) == NULL) {
|
memset(&callbacks, 0, sizeof(callbacks));
|
||||||
|
callbacks.begin_request = begin_request_handler;
|
||||||
|
if ((ctx = mg_start(&callbacks, NULL, options)) == NULL) {
|
||||||
printf("%s\n", "Cannot start chat server, fatal exit");
|
printf("%s\n", "Cannot start chat server, fatal exit");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,17 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "mongoose.h"
|
#include "mongoose.h"
|
||||||
|
|
||||||
static void *callback(enum mg_event event,
|
// This function will be called by mongoose on every new request.
|
||||||
struct mg_connection *conn) {
|
static int begin_request_handler(struct mg_connection *conn) {
|
||||||
const struct mg_request_info *request_info = mg_get_request_info(conn);
|
const struct mg_request_info *request_info = mg_get_request_info(conn);
|
||||||
|
char content[100];
|
||||||
|
|
||||||
if (event == MG_NEW_REQUEST) {
|
// Prepare the message we're going to send
|
||||||
char content[1024];
|
|
||||||
int content_length = snprintf(content, sizeof(content),
|
int content_length = snprintf(content, sizeof(content),
|
||||||
"Hello from mongoose! Remote port: %d",
|
"Hello from mongoose! Remote port: %d",
|
||||||
request_info->remote_port);
|
request_info->remote_port);
|
||||||
|
|
||||||
|
// Send HTTP reply to the client
|
||||||
mg_printf(conn,
|
mg_printf(conn,
|
||||||
"HTTP/1.1 200 OK\r\n"
|
"HTTP/1.1 200 OK\r\n"
|
||||||
"Content-Type: text/plain\r\n"
|
"Content-Type: text/plain\r\n"
|
||||||
@ -18,19 +20,31 @@ static void *callback(enum mg_event event,
|
|||||||
"\r\n"
|
"\r\n"
|
||||||
"%s",
|
"%s",
|
||||||
content_length, content);
|
content_length, content);
|
||||||
// Mark as processed
|
|
||||||
return "";
|
// Returning non-zero tells mongoose that our function has replied to
|
||||||
} else {
|
// the client, and mongoose should not send client any more data.
|
||||||
return NULL;
|
return 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
struct mg_context *ctx;
|
struct mg_context *ctx;
|
||||||
|
struct mg_callbacks callbacks;
|
||||||
|
|
||||||
|
// List of options. Last element must be NULL.
|
||||||
const char *options[] = {"listening_ports", "8080", NULL};
|
const char *options[] = {"listening_ports", "8080", NULL};
|
||||||
|
|
||||||
ctx = mg_start(&callback, NULL, options);
|
// Prepare callbacks structure. We have only one callback, the rest are NULL.
|
||||||
getchar(); // Wait until user hits "enter"
|
memset(&callbacks, 0, sizeof(callbacks));
|
||||||
|
callbacks.begin_request = begin_request_handler;
|
||||||
|
|
||||||
|
// Start the web server.
|
||||||
|
ctx = mg_start(&callbacks, NULL, options);
|
||||||
|
|
||||||
|
// Wait until user hits "enter". Server is running in separate thread.
|
||||||
|
// Navigating to http://localhost:8080 will invoke begin_request_handler().
|
||||||
|
getchar();
|
||||||
|
|
||||||
|
// Stop the server.
|
||||||
mg_stop(ctx);
|
mg_stop(ctx);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -10,24 +10,20 @@ static const char *html_form =
|
|||||||
"<input type=\"submit\" />"
|
"<input type=\"submit\" />"
|
||||||
"</form></body></html>";
|
"</form></body></html>";
|
||||||
|
|
||||||
static void *callback(enum mg_event event,
|
static int begin_request_handler(struct mg_connection *conn) {
|
||||||
struct mg_connection *conn) {
|
|
||||||
const struct mg_request_info *ri = mg_get_request_info(conn);
|
const struct mg_request_info *ri = mg_get_request_info(conn);
|
||||||
|
char post_data[1024], input1[sizeof(post_data)], input2[sizeof(post_data)];
|
||||||
if (event == MG_NEW_REQUEST) {
|
|
||||||
if (!strcmp(ri->uri, "/handle_post_request")) {
|
|
||||||
// User has submitted a form, show submitted data and a variable value
|
|
||||||
char post_data[1024],
|
|
||||||
input1[sizeof(post_data)], input2[sizeof(post_data)];
|
|
||||||
int post_data_len;
|
int post_data_len;
|
||||||
|
|
||||||
// Read POST data
|
if (!strcmp(ri->uri, "/handle_post_request")) {
|
||||||
|
// User has submitted a form, show submitted data and a variable value
|
||||||
post_data_len = mg_read(conn, post_data, sizeof(post_data));
|
post_data_len = mg_read(conn, post_data, sizeof(post_data));
|
||||||
|
|
||||||
// Parse form data. input1 and input2 are guaranteed to be NUL-terminated
|
// Parse form data. input1 and input2 are guaranteed to be NUL-terminated
|
||||||
mg_get_var(post_data, post_data_len, "input_1", input1, sizeof(input1));
|
mg_get_var(post_data, post_data_len, "input_1", input1, sizeof(input1));
|
||||||
mg_get_var(post_data, post_data_len, "input_2", input2, sizeof(input2));
|
mg_get_var(post_data, post_data_len, "input_2", input2, sizeof(input2));
|
||||||
|
|
||||||
|
// Send reply to the client, showing submitted form values.
|
||||||
mg_printf(conn, "HTTP/1.0 200 OK\r\n"
|
mg_printf(conn, "HTTP/1.0 200 OK\r\n"
|
||||||
"Content-Type: text/plain\r\n\r\n"
|
"Content-Type: text/plain\r\n\r\n"
|
||||||
"Submitted data: [%.*s]\n"
|
"Submitted data: [%.*s]\n"
|
||||||
@ -42,18 +38,17 @@ static void *callback(enum mg_event event,
|
|||||||
"Content-Type: text/html\r\n\r\n%s",
|
"Content-Type: text/html\r\n\r\n%s",
|
||||||
(int) strlen(html_form), html_form);
|
(int) strlen(html_form), html_form);
|
||||||
}
|
}
|
||||||
// Mark as processed
|
return 1; // Mark request as processed
|
||||||
return "";
|
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
struct mg_context *ctx;
|
struct mg_context *ctx;
|
||||||
const char *options[] = {"listening_ports", "8080", NULL};
|
const char *options[] = {"listening_ports", "8080", NULL};
|
||||||
|
struct mg_callbacks callbacks;
|
||||||
|
|
||||||
ctx = mg_start(&callback, NULL, options);
|
memset(&callbacks, 0, sizeof(callbacks));
|
||||||
|
callbacks.begin_request = begin_request_handler;
|
||||||
|
ctx = mg_start(&callbacks, NULL, options);
|
||||||
getchar(); // Wait until user hits "enter"
|
getchar(); // Wait until user hits "enter"
|
||||||
mg_stop(ctx);
|
mg_stop(ctx);
|
||||||
|
|
||||||
|
@ -17,8 +17,7 @@ typedef __int64 int64_t;
|
|||||||
|
|
||||||
#include "mongoose.h"
|
#include "mongoose.h"
|
||||||
|
|
||||||
static void *callback(enum mg_event event, struct mg_connection *conn) {
|
static int begin_request_handler(struct mg_connection *conn) {
|
||||||
if (event == MG_NEW_REQUEST) {
|
|
||||||
if (!strcmp(mg_get_request_info(conn)->uri, "/handle_post_request")) {
|
if (!strcmp(mg_get_request_info(conn)->uri, "/handle_post_request")) {
|
||||||
mg_printf(conn, "%s", "HTTP/1.0 200 OK\r\n\r\n");
|
mg_printf(conn, "%s", "HTTP/1.0 200 OK\r\n\r\n");
|
||||||
mg_upload(conn, "/tmp");
|
mg_upload(conn, "/tmp");
|
||||||
@ -37,22 +36,25 @@ static void *callback(enum mg_event event, struct mg_connection *conn) {
|
|||||||
"Content-Type: text/html\r\n\r\n%s",
|
"Content-Type: text/html\r\n\r\n%s",
|
||||||
(int) strlen(html_form), html_form);
|
(int) strlen(html_form), html_form);
|
||||||
}
|
}
|
||||||
// Mark as processed
|
|
||||||
return "";
|
// Mark request as processed
|
||||||
} else if (event == MG_UPLOAD) {
|
return 1;
|
||||||
mg_printf(conn, "Saved [%s]", mg_get_request_info(conn)->ev_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
static void upload_handler(struct mg_connection *conn, const char *path) {
|
||||||
|
mg_printf(conn, "Saved [%s]", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
struct mg_context *ctx;
|
struct mg_context *ctx;
|
||||||
const char *options[] = {"listening_ports", "8080", NULL};
|
const char *options[] = {"listening_ports", "8080", NULL};
|
||||||
|
struct mg_callbacks callbacks;
|
||||||
|
|
||||||
ctx = mg_start(&callback, NULL, options);
|
memset(&callbacks, 0, sizeof(callbacks));
|
||||||
|
callbacks.begin_request = begin_request_handler;
|
||||||
|
callbacks.upload = upload_handler;
|
||||||
|
ctx = mg_start(&callbacks, NULL, options);
|
||||||
getchar(); // Wait until user hits "enter"
|
getchar(); // Wait until user hits "enter"
|
||||||
pause();
|
|
||||||
mg_stop(ctx);
|
mg_stop(ctx);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -5,14 +5,14 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "mongoose.h"
|
#include "mongoose.h"
|
||||||
|
|
||||||
static void *callback(enum mg_event event, struct mg_connection *conn) {
|
static void websocket_ready_handler(struct mg_connection *conn) {
|
||||||
if (event == MG_WEBSOCKET_READY) {
|
|
||||||
unsigned char buf[40];
|
unsigned char buf[40];
|
||||||
buf[0] = 0x81;
|
buf[0] = 0x81;
|
||||||
buf[1] = snprintf((char *) buf + 2, sizeof(buf) - 2, "%s", "server ready");
|
buf[1] = snprintf((char *) buf + 2, sizeof(buf) - 2, "%s", "server ready");
|
||||||
mg_write(conn, buf, 2 + buf[1]);
|
mg_write(conn, buf, 2 + buf[1]);
|
||||||
return ""; // MG_WEBSOCKET_READY return value is ignored
|
}
|
||||||
} else if (event == MG_WEBSOCKET_MESSAGE) {
|
|
||||||
|
static int websocket_data_handler(struct mg_connection *conn) {
|
||||||
unsigned char buf[200], reply[200];
|
unsigned char buf[200], reply[200];
|
||||||
int n, i, mask_len, xor, msg_len, len;
|
int n, i, mask_len, xor, msg_len, len;
|
||||||
|
|
||||||
@ -22,14 +22,14 @@ static void *callback(enum mg_event event, struct mg_connection *conn) {
|
|||||||
msg_len = mask_len = 0;
|
msg_len = mask_len = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if ((n = mg_read(conn, buf + len, sizeof(buf) - len)) <= 0) {
|
if ((n = mg_read(conn, buf + len, sizeof(buf) - len)) <= 0) {
|
||||||
return ""; // Read error, close websocket
|
return 0; // Read error, close websocket
|
||||||
}
|
}
|
||||||
len += n;
|
len += n;
|
||||||
if (len >= 2) {
|
if (len >= 2) {
|
||||||
msg_len = buf[1] & 127;
|
msg_len = buf[1] & 127;
|
||||||
mask_len = (buf[1] & 128) ? 4 : 0;
|
mask_len = (buf[1] & 128) ? 4 : 0;
|
||||||
if (msg_len > 125) {
|
if (msg_len > 125) {
|
||||||
return ""; // Message is too long, close websocket
|
return 0; // Message is too long, close websocket
|
||||||
}
|
}
|
||||||
// If we've buffered the whole message, exit the loop
|
// If we've buffered the whole message, exit the loop
|
||||||
if (len >= 2 + mask_len + msg_len) {
|
if (len >= 2 + mask_len + msg_len) {
|
||||||
@ -51,23 +51,24 @@ static void *callback(enum mg_event event, struct mg_connection *conn) {
|
|||||||
// Echo the message back to the client
|
// Echo the message back to the client
|
||||||
mg_write(conn, reply, 2 + msg_len);
|
mg_write(conn, reply, 2 + msg_len);
|
||||||
|
|
||||||
// Return non-NULL means stoping websocket conversation.
|
// Returnint zero means stoping websocket conversation.
|
||||||
// Close the conversation if client has sent us "exit" string.
|
// Close the conversation if client has sent us "exit" string.
|
||||||
return memcmp(reply + 2, "exit", 4) == 0 ? "" : NULL;
|
return memcmp(reply + 2, "exit", 4);
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
struct mg_context *ctx;
|
struct mg_context *ctx;
|
||||||
|
struct mg_callbacks callbacks;
|
||||||
const char *options[] = {
|
const char *options[] = {
|
||||||
"listening_ports", "8080",
|
"listening_ports", "8080",
|
||||||
"document_root", "websocket_html_root",
|
"document_root", "websocket_html_root",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
ctx = mg_start(&callback, NULL, options);
|
memset(&callbacks, 0, sizeof(callbacks));
|
||||||
|
callbacks.websocket_ready = websocket_ready_handler;
|
||||||
|
callbacks.websocket_data = websocket_data_handler;
|
||||||
|
ctx = mg_start(&callbacks, NULL, options);
|
||||||
getchar(); // Wait until user hits "enter"
|
getchar(); // Wait until user hits "enter"
|
||||||
mg_stop(ctx);
|
mg_stop(ctx);
|
||||||
|
|
||||||
|
17
main.c
17
main.c
@ -266,17 +266,14 @@ static void init_server_name(void) {
|
|||||||
mg_version());
|
mg_version());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *mongoose_callback(enum mg_event ev, struct mg_connection *conn) {
|
static int log_message(const struct mg_connection *conn, const char *message) {
|
||||||
if (ev == MG_EVENT_LOG) {
|
(void) conn;
|
||||||
printf("%s\n", (const char *) mg_get_request_info(conn)->ev_data);
|
printf("%s\n", message);
|
||||||
}
|
return 0;
|
||||||
|
|
||||||
// Returning NULL marks request as not handled, signalling mongoose to
|
|
||||||
// proceed with handling it.
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void start_mongoose(int argc, char *argv[]) {
|
static void start_mongoose(int argc, char *argv[]) {
|
||||||
|
struct mg_callbacks callbacks;
|
||||||
char *options[MAX_OPTIONS];
|
char *options[MAX_OPTIONS];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -302,7 +299,9 @@ static void start_mongoose(int argc, char *argv[]) {
|
|||||||
signal(SIGINT, signal_handler);
|
signal(SIGINT, signal_handler);
|
||||||
|
|
||||||
/* Start Mongoose */
|
/* Start Mongoose */
|
||||||
ctx = mg_start(&mongoose_callback, NULL, (const char **) options);
|
memset(&callbacks, 0, sizeof(callbacks));
|
||||||
|
callbacks.log_message = &log_message;
|
||||||
|
ctx = mg_start(&callbacks, NULL, (const char **) options);
|
||||||
for (i = 0; options[i] != NULL; i++) {
|
for (i = 0; options[i] != NULL; i++) {
|
||||||
free(options[i]);
|
free(options[i]);
|
||||||
}
|
}
|
||||||
|
73
mongoose.c
73
mongoose.c
@ -469,7 +469,7 @@ struct mg_context {
|
|||||||
volatile int stop_flag; // Should we stop event loop
|
volatile int stop_flag; // Should we stop event loop
|
||||||
SSL_CTX *ssl_ctx; // SSL context
|
SSL_CTX *ssl_ctx; // SSL context
|
||||||
char *config[NUM_OPTIONS]; // Mongoose configuration parameters
|
char *config[NUM_OPTIONS]; // Mongoose configuration parameters
|
||||||
mg_callback_t user_callback; // User-defined callback function
|
struct mg_callbacks callbacks; // User-defined callback function
|
||||||
void *user_data; // User-defined data
|
void *user_data; // User-defined data
|
||||||
|
|
||||||
struct socket *listening_sockets;
|
struct socket *listening_sockets;
|
||||||
@ -512,20 +512,12 @@ const char **mg_get_valid_option_names(void) {
|
|||||||
return config_options;
|
return config_options;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *call_user(struct mg_connection *conn, enum mg_event event) {
|
|
||||||
if (conn != NULL && conn->ctx != NULL) {
|
|
||||||
conn->request_info.user_data = conn->ctx->user_data;
|
|
||||||
}
|
|
||||||
return conn == NULL || conn->ctx == NULL || conn->ctx->user_callback == NULL ?
|
|
||||||
NULL : conn->ctx->user_callback(event, conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int is_file_in_memory(struct mg_connection *conn, const char *path,
|
static int is_file_in_memory(struct mg_connection *conn, const char *path,
|
||||||
struct file *filep) {
|
struct file *filep) {
|
||||||
conn->request_info.ev_data = (void *) path;
|
size_t size = 0;
|
||||||
if ((filep->membuf = call_user(conn, MG_OPEN_FILE)) != NULL) {
|
filep->membuf = conn->ctx->callbacks.open_file == NULL ? NULL :
|
||||||
filep->size = (long) conn->request_info.ev_data;
|
conn->ctx->callbacks.open_file(conn, path, &size);
|
||||||
}
|
filep->size = size;
|
||||||
return filep->membuf != NULL;
|
return filep->membuf != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -610,8 +602,8 @@ static void cry(struct mg_connection *conn, const char *fmt, ...) {
|
|||||||
// Do not lock when getting the callback value, here and below.
|
// Do not lock when getting the callback value, here and below.
|
||||||
// I suppose this is fine, since function cannot disappear in the
|
// I suppose this is fine, since function cannot disappear in the
|
||||||
// same way string option can.
|
// same way string option can.
|
||||||
conn->request_info.ev_data = buf;
|
if (conn->ctx->callbacks.log_message == NULL ||
|
||||||
if (call_user(conn, MG_EVENT_LOG) == NULL) {
|
conn->ctx->callbacks.log_message(conn, buf) == 0) {
|
||||||
fp = conn->ctx == NULL || conn->ctx->config[ERROR_LOG_FILE] == NULL ? NULL :
|
fp = conn->ctx == NULL || conn->ctx->config[ERROR_LOG_FILE] == NULL ? NULL :
|
||||||
fopen(conn->ctx->config[ERROR_LOG_FILE], "a+");
|
fopen(conn->ctx->config[ERROR_LOG_FILE], "a+");
|
||||||
|
|
||||||
@ -634,7 +626,6 @@ static void cry(struct mg_connection *conn, const char *fmt, ...) {
|
|||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
conn->request_info.ev_data = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return fake connection structure. Used for logging, if connection
|
// Return fake connection structure. Used for logging, if connection
|
||||||
@ -917,13 +908,10 @@ static void send_http_error(struct mg_connection *conn, int status,
|
|||||||
const char *reason, const char *fmt, ...) {
|
const char *reason, const char *fmt, ...) {
|
||||||
char buf[MG_BUF_LEN];
|
char buf[MG_BUF_LEN];
|
||||||
va_list ap;
|
va_list ap;
|
||||||
int len;
|
int len = 0;
|
||||||
|
|
||||||
conn->status_code = status;
|
conn->status_code = status;
|
||||||
conn->request_info.ev_data = (void *) (long) status;
|
|
||||||
if (call_user(conn, MG_HTTP_ERROR) == NULL) {
|
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
len = 0;
|
|
||||||
|
|
||||||
// Errors 1xx, 204 and 304 MUST NOT send a body
|
// Errors 1xx, 204 and 304 MUST NOT send a body
|
||||||
if (status > 199 && status != 204 && status != 304) {
|
if (status > 199 && status != 204 && status != 304) {
|
||||||
@ -942,7 +930,6 @@ static void send_http_error(struct mg_connection *conn, int status,
|
|||||||
suggest_connection_header(conn));
|
suggest_connection_header(conn));
|
||||||
conn->num_bytes_sent += mg_printf(conn, "%s", buf);
|
conn->num_bytes_sent += mg_printf(conn, "%s", buf);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(__SYMBIAN32__)
|
#if defined(_WIN32) && !defined(__SYMBIAN32__)
|
||||||
static int pthread_mutex_init(pthread_mutex_t *mutex, void *unused) {
|
static int pthread_mutex_init(pthread_mutex_t *mutex, void *unused) {
|
||||||
@ -2609,7 +2596,7 @@ static int scan_directory(struct mg_connection *conn, const char *dir,
|
|||||||
// print_dir_entry(). memset is required only if mg_stat()
|
// print_dir_entry(). memset is required only if mg_stat()
|
||||||
// fails. For more details, see
|
// fails. For more details, see
|
||||||
// http://code.google.com/p/mongoose/issues/detail?id=79
|
// http://code.google.com/p/mongoose/issues/detail?id=79
|
||||||
// mg_stat will memset the whole struct file with zeroes.
|
memset(&de.file, 0, sizeof(de.file));
|
||||||
mg_stat(conn, path, &de.file);
|
mg_stat(conn, path, &de.file);
|
||||||
|
|
||||||
de.file_name = dp->d_name;
|
de.file_name = dp->d_name;
|
||||||
@ -3797,7 +3784,8 @@ static void read_websocket(struct mg_connection *conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (conn->content_len > 0) {
|
if (conn->content_len > 0) {
|
||||||
if (call_user(conn, MG_WEBSOCKET_MESSAGE) != NULL) {
|
if (conn->ctx->callbacks.websocket_data != NULL &&
|
||||||
|
conn->ctx->callbacks.websocket_data(conn) == 0) {
|
||||||
break; // Callback signalled to exit
|
break; // Callback signalled to exit
|
||||||
}
|
}
|
||||||
discard_len = conn->content_len > body_len ?
|
discard_len = conn->content_len > body_len ?
|
||||||
@ -3819,13 +3807,15 @@ static void read_websocket(struct mg_connection *conn) {
|
|||||||
static void handle_websocket_request(struct mg_connection *conn) {
|
static void handle_websocket_request(struct mg_connection *conn) {
|
||||||
if (strcmp(mg_get_header(conn, "Sec-WebSocket-Version"), "13") != 0) {
|
if (strcmp(mg_get_header(conn, "Sec-WebSocket-Version"), "13") != 0) {
|
||||||
send_http_error(conn, 426, "Upgrade Required", "%s", "Upgrade Required");
|
send_http_error(conn, 426, "Upgrade Required", "%s", "Upgrade Required");
|
||||||
} else if (call_user(conn, MG_WEBSOCKET_CONNECT) != NULL) {
|
} else if (conn->ctx->callbacks.websocket_connect != NULL &&
|
||||||
// Callback has returned non-NULL, do not proceed with handshake
|
conn->ctx->callbacks.websocket_connect(conn) != 0) {
|
||||||
|
// Callback has returned non-zero, do not proceed with handshake
|
||||||
} else {
|
} else {
|
||||||
send_websocket_handshake(conn);
|
send_websocket_handshake(conn);
|
||||||
call_user(conn, MG_WEBSOCKET_READY);
|
if (conn->ctx->callbacks.websocket_ready != NULL) {
|
||||||
|
conn->ctx->callbacks.websocket_ready(conn);
|
||||||
|
}
|
||||||
read_websocket(conn);
|
read_websocket(conn);
|
||||||
call_user(conn, MG_WEBSOCKET_CLOSE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4035,8 +4025,9 @@ static void handle_lsp_request(struct mg_connection *conn, const char *path,
|
|||||||
} else {
|
} else {
|
||||||
// We're not sending HTTP headers here, Lua page must do it.
|
// We're not sending HTTP headers here, Lua page must do it.
|
||||||
prepare_lua_environment(conn, L);
|
prepare_lua_environment(conn, L);
|
||||||
conn->request_info.ev_data = L;
|
if (conn->ctx->callbacks.init_lua != NULL) {
|
||||||
call_user(conn, MG_INIT_LUA);
|
conn->ctx->callbacks.init_lua(conn, L);
|
||||||
|
}
|
||||||
lsp(conn, filep->membuf == NULL ? p : filep->membuf, filep->size, L);
|
lsp(conn, filep->membuf == NULL ? p : filep->membuf, filep->size, L);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4135,8 +4126,9 @@ int mg_upload(struct mg_connection *conn, const char *destination_dir) {
|
|||||||
fwrite(buf, 1, i, fp);
|
fwrite(buf, 1, i, fp);
|
||||||
fflush(fp);
|
fflush(fp);
|
||||||
num_uploaded_files++;
|
num_uploaded_files++;
|
||||||
conn->request_info.ev_data = (void *) path;
|
if (conn->ctx->callbacks.upload != NULL) {
|
||||||
call_user(conn, MG_UPLOAD);
|
conn->ctx->callbacks.upload(conn, path);
|
||||||
|
}
|
||||||
memmove(buf, &buf[i + bl], len - (i + bl));
|
memmove(buf, &buf[i + bl], len - (i + bl));
|
||||||
len -= i + bl;
|
len -= i + bl;
|
||||||
break;
|
break;
|
||||||
@ -4203,7 +4195,8 @@ static void handle_request(struct mg_connection *conn) {
|
|||||||
get_remote_ip(conn), ri->uri);
|
get_remote_ip(conn), ri->uri);
|
||||||
|
|
||||||
DEBUG_TRACE(("%s", ri->uri));
|
DEBUG_TRACE(("%s", ri->uri));
|
||||||
if (call_user(conn, MG_NEW_REQUEST) != NULL) {
|
if (conn->ctx->callbacks.begin_request != NULL &&
|
||||||
|
conn->ctx->callbacks.begin_request(conn)) {
|
||||||
// Do nothing, callback has served the request
|
// Do nothing, callback has served the request
|
||||||
} else if (!conn->client.is_ssl && conn->client.ssl_redir &&
|
} else if (!conn->client.is_ssl && conn->client.ssl_redir &&
|
||||||
(ssl_index = get_first_ssl_listener_index(conn->ctx)) > -1) {
|
(ssl_index = get_first_ssl_listener_index(conn->ctx)) > -1) {
|
||||||
@ -4550,8 +4543,8 @@ static int set_ssl_option(struct mg_context *ctx) {
|
|||||||
|
|
||||||
// If user callback returned non-NULL, that means that user callback has
|
// If user callback returned non-NULL, that means that user callback has
|
||||||
// set up certificate itself. In this case, skip sertificate setting.
|
// set up certificate itself. In this case, skip sertificate setting.
|
||||||
fc(ctx)->request_info.ev_data = ctx->ssl_ctx;
|
if ((ctx->callbacks.init_ssl == NULL ||
|
||||||
if (call_user(fc(ctx), MG_INIT_SSL) == NULL &&
|
!ctx->callbacks.init_ssl(ctx->ssl_ctx)) &&
|
||||||
(SSL_CTX_use_certificate_file(ctx->ssl_ctx, pem, 1) == 0 ||
|
(SSL_CTX_use_certificate_file(ctx->ssl_ctx, pem, 1) == 0 ||
|
||||||
SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, pem, 1) == 0)) {
|
SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, pem, 1) == 0)) {
|
||||||
cry(fc(ctx), "%s: cannot open %s: %s", __func__, pem, ssl_error());
|
cry(fc(ctx), "%s: cannot open %s: %s", __func__, pem, ssl_error());
|
||||||
@ -4608,7 +4601,7 @@ static int set_acl_option(struct mg_context *ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void reset_per_request_attributes(struct mg_connection *conn) {
|
static void reset_per_request_attributes(struct mg_connection *conn) {
|
||||||
conn->path_info = conn->request_info.ev_data = NULL;
|
conn->path_info = NULL;
|
||||||
conn->num_bytes_sent = conn->consumed_content = 0;
|
conn->num_bytes_sent = conn->consumed_content = 0;
|
||||||
conn->status_code = -1;
|
conn->status_code = -1;
|
||||||
conn->must_close = conn->request_len = conn->throttle = 0;
|
conn->must_close = conn->request_len = conn->throttle = 0;
|
||||||
@ -4811,8 +4804,9 @@ static void process_new_connection(struct mg_connection *conn) {
|
|||||||
|
|
||||||
if (ebuf[0] == '\0') {
|
if (ebuf[0] == '\0') {
|
||||||
handle_request(conn);
|
handle_request(conn);
|
||||||
conn->request_info.ev_data = (void *) (long) conn->status_code;
|
if (conn->ctx->callbacks.end_request != NULL) {
|
||||||
call_user(conn, MG_REQUEST_COMPLETE);
|
conn->ctx->callbacks.end_request(conn, conn->status_code);
|
||||||
|
}
|
||||||
log_access(conn);
|
log_access(conn);
|
||||||
}
|
}
|
||||||
if (ri->remote_user != NULL) {
|
if (ri->remote_user != NULL) {
|
||||||
@ -5087,7 +5081,8 @@ void mg_stop(struct mg_context *ctx) {
|
|||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mg_context *mg_start(mg_callback_t user_callback, void *user_data,
|
struct mg_context *mg_start(const struct mg_callbacks *callbacks,
|
||||||
|
void *user_data,
|
||||||
const char **options) {
|
const char **options) {
|
||||||
struct mg_context *ctx;
|
struct mg_context *ctx;
|
||||||
const char *name, *value, *default_value;
|
const char *name, *value, *default_value;
|
||||||
@ -5104,7 +5099,7 @@ struct mg_context *mg_start(mg_callback_t user_callback, void *user_data,
|
|||||||
if ((ctx = (struct mg_context *) calloc(1, sizeof(*ctx))) == NULL) {
|
if ((ctx = (struct mg_context *) calloc(1, sizeof(*ctx))) == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ctx->user_callback = user_callback;
|
ctx->callbacks = *callbacks;
|
||||||
ctx->user_data = user_data;
|
ctx->user_data = user_data;
|
||||||
|
|
||||||
while (options && (name = *options++) != NULL) {
|
while (options && (name = *options++) != NULL) {
|
||||||
|
128
mongoose.h
128
mongoose.h
@ -42,13 +42,13 @@ struct mg_request_info {
|
|||||||
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 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
|
void *user_data; // User data pointer passed to mg_start()
|
||||||
|
|
||||||
|
int num_headers; // Number of HTTP headers
|
||||||
struct mg_header {
|
struct mg_header {
|
||||||
const char *name; // HTTP header name
|
const char *name; // HTTP header name
|
||||||
const char *value; // HTTP header value
|
const char *value; // HTTP header value
|
||||||
} http_headers[64]; // Maximum 64 headers
|
} http_headers[64]; // Maximum 64 headers
|
||||||
void *user_data; // User data pointer passed to mg_start()
|
|
||||||
void *ev_data; // Event-specific data pointer
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -56,126 +56,23 @@ struct mg_request_info {
|
|||||||
// which callbacks to invoke. For detailed description, see
|
// which callbacks to invoke. For detailed description, see
|
||||||
// https://github.com/valenok/mongoose/blob/master/UserManual.md
|
// https://github.com/valenok/mongoose/blob/master/UserManual.md
|
||||||
struct mg_callbacks {
|
struct mg_callbacks {
|
||||||
int (*request_start)(struct mg_connection *);
|
int (*begin_request)(struct mg_connection *);
|
||||||
void (*request_done)(struct mg_connection *, int reply_status_code);
|
void (*end_request)(const struct mg_connection *, int reply_status_code);
|
||||||
int (*log_message)(struct mg_connection *, const char *message);
|
int (*log_message)(const struct mg_connection *, const char *message);
|
||||||
int (*init_ssl)(void *ssl_context);
|
int (*init_ssl)(void *ssl_context);
|
||||||
void (*websocket_connect)(struct mg_connection *);
|
int (*websocket_connect)(const struct mg_connection *);
|
||||||
void (*websocket_ready)(struct mg_connection *);
|
void (*websocket_ready)(struct mg_connection *);
|
||||||
int (*websocket_data)(struct mg_connection *);
|
int (*websocket_data)(struct mg_connection *);
|
||||||
void (*websocket_close)(struct mg_connection *);
|
const char * (*open_file)(const struct mg_connection *,
|
||||||
void (*open_file)(struct mg_connection *, char **data, size_t *data_len);
|
const char *path, size_t *data_len);
|
||||||
void (*init_lua)(struct mg_connection *, void *lua_context);
|
void (*init_lua)(struct mg_connection *, void *lua_context);
|
||||||
void (*upload)(struct mg_connection *, const char *file_name);
|
void (*upload)(struct mg_connection *, const char *file_name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Various events on which user-defined callback function is called by Mongoose.
|
|
||||||
enum mg_event {
|
|
||||||
// New HTTP request has arrived from the client.
|
|
||||||
// If callback returns non-NULL, Mongoose stops handling current request.
|
|
||||||
// ev_data contains NULL.
|
|
||||||
MG_NEW_REQUEST,
|
|
||||||
|
|
||||||
// Mongoose has finished handling the request.
|
|
||||||
// Callback return value is ignored.
|
|
||||||
// ev_data contains integer HTTP status code:
|
|
||||||
// int http_reply_status_code = (long) request_info->ev_data;
|
|
||||||
MG_REQUEST_COMPLETE,
|
|
||||||
|
|
||||||
// HTTP error must be returned to the client.
|
|
||||||
// If callback returns non-NULL, Mongoose stops handling error.
|
|
||||||
// ev_data contains HTTP error code:
|
|
||||||
// int http_reply_status_code = (long) request_info->ev_data;
|
|
||||||
MG_HTTP_ERROR,
|
|
||||||
|
|
||||||
// Mongoose logs a message.
|
|
||||||
// If callback returns non-NULL, Mongoose stops handling that event.
|
|
||||||
// ev_data contains a message to be logged:
|
|
||||||
// const char *log_message = request_info->ev_data;
|
|
||||||
MG_EVENT_LOG,
|
|
||||||
|
|
||||||
// SSL initialization, sent before certificate setup.
|
|
||||||
// If callback returns non-NULL, Mongoose does not set up certificates.
|
|
||||||
// ev_data contains server's OpenSSL context:
|
|
||||||
// SSL_CTX *ssl_context = request_info->ev_data;
|
|
||||||
MG_INIT_SSL,
|
|
||||||
|
|
||||||
// Sent on HTTP connect, before websocket handshake.
|
|
||||||
// If user callback returns NULL, then mongoose proceeds
|
|
||||||
// with handshake, otherwise it closes the connection.
|
|
||||||
// ev_data contains NULL.
|
|
||||||
MG_WEBSOCKET_CONNECT,
|
|
||||||
|
|
||||||
// Handshake has been successfully completed.
|
|
||||||
// Callback's return value is ignored.
|
|
||||||
// ev_data contains NULL.
|
|
||||||
MG_WEBSOCKET_READY,
|
|
||||||
|
|
||||||
// Incoming message from the client, data could be read with mg_read().
|
|
||||||
// If user callback returns non-NULL, mongoose closes the websocket.
|
|
||||||
// ev_data contains NULL.
|
|
||||||
MG_WEBSOCKET_MESSAGE,
|
|
||||||
|
|
||||||
// Client has closed the connection.
|
|
||||||
// Callback's return value is ignored.
|
|
||||||
// ev_data contains NULL.
|
|
||||||
MG_WEBSOCKET_CLOSE,
|
|
||||||
|
|
||||||
// Mongoose tries to open file.
|
|
||||||
// If callback returns non-NULL, Mongoose will not try to open it, but
|
|
||||||
// will use the returned value as a pointer to the file data. This allows
|
|
||||||
// for example to serve files from memory.
|
|
||||||
// ev_data contains file path, including document root path.
|
|
||||||
// Upon return, ev_data should return file size, which should be a long int.
|
|
||||||
//
|
|
||||||
// const char *file_name = request_info->ev_data;
|
|
||||||
// if (strcmp(file_name, "foo.txt") == 0) {
|
|
||||||
// request_info->ev_data = (void *) (long) 4;
|
|
||||||
// return "data";
|
|
||||||
// }
|
|
||||||
// return NULL;
|
|
||||||
//
|
|
||||||
// Note that this even is sent multiple times during one request. Each
|
|
||||||
// time mongoose tries to open or stat the file, this event is sent, e.g.
|
|
||||||
// for opening .htpasswd file, stat-ting requested file, opening requested
|
|
||||||
// file, etc.
|
|
||||||
MG_OPEN_FILE,
|
|
||||||
|
|
||||||
// Mongoose initializes Lua server page. Sent only if Lua support is enabled.
|
|
||||||
// Callback's return value is ignored.
|
|
||||||
// ev_data contains lua_State pointer.
|
|
||||||
MG_INIT_LUA,
|
|
||||||
|
|
||||||
// Mongoose has uploaded file to a temporary directory.
|
|
||||||
// Callback's return value is ignored.
|
|
||||||
// ev_data contains NUL-terminated file name.
|
|
||||||
MG_UPLOAD,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Prototype for the user-defined function. Mongoose calls this function
|
|
||||||
// on every MG_* event.
|
|
||||||
//
|
|
||||||
// Parameters:
|
|
||||||
// event: which event has been triggered.
|
|
||||||
// conn: opaque connection handler. Could be used to read, write data to the
|
|
||||||
// client, etc. See functions below that have "mg_connection *" arg.
|
|
||||||
//
|
|
||||||
// Return:
|
|
||||||
// If handler returns non-NULL, that means that handler has processed the
|
|
||||||
// request by sending appropriate HTTP reply to the client. Mongoose treats
|
|
||||||
// the request as served.
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
|
|
||||||
// Start web server.
|
// Start web server.
|
||||||
//
|
//
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// callback: user defined event handling function or NULL.
|
// callbacks: mg_callbacks structure with user-defined callbacks.
|
||||||
// options: NULL terminated list of option_name, option_value pairs that
|
// options: NULL terminated list of option_name, option_value pairs that
|
||||||
// specify Mongoose configuration parameters.
|
// specify Mongoose configuration parameters.
|
||||||
//
|
//
|
||||||
@ -197,8 +94,9 @@ typedef void *(*mg_callback_t)(enum mg_event event, struct mg_connection *conn);
|
|||||||
//
|
//
|
||||||
// Return:
|
// Return:
|
||||||
// web server context, or NULL on error.
|
// web server context, or NULL on error.
|
||||||
struct mg_context *mg_start(mg_callback_t callback, void *user_data,
|
struct mg_context *mg_start(const struct mg_callbacks *callbacks,
|
||||||
const char **options);
|
void *user_data,
|
||||||
|
const char **configuration_options);
|
||||||
|
|
||||||
|
|
||||||
// Stop the web server.
|
// Stop the web server.
|
||||||
|
@ -426,7 +426,7 @@ unless (scalar(@ARGV) > 0 and $ARGV[0] eq "basic_tests") {
|
|||||||
do_PUT_test();
|
do_PUT_test();
|
||||||
kill_spawned_child();
|
kill_spawned_child();
|
||||||
do_unit_test();
|
do_unit_test();
|
||||||
do_embedded_test();
|
#do_embedded_test();
|
||||||
}
|
}
|
||||||
|
|
||||||
sub do_PUT_test {
|
sub do_PUT_test {
|
||||||
|
@ -189,32 +189,23 @@ static const char *inmemory_file_data = "hi there";
|
|||||||
static const char *upload_filename = "upload_test.txt";
|
static const char *upload_filename = "upload_test.txt";
|
||||||
static const char *upload_ok_message = "upload successful";
|
static const char *upload_ok_message = "upload successful";
|
||||||
|
|
||||||
static void *event_handler(enum mg_event event, struct mg_connection *conn) {
|
static const char *open_file_cb(const struct mg_connection *conn,
|
||||||
const struct mg_request_info *request_info = mg_get_request_info(conn);
|
const char *path, size_t *size) {
|
||||||
|
(void) conn;
|
||||||
if (event == MG_NEW_REQUEST && !strcmp(request_info->uri, "/data")) {
|
if (!strcmp(path, "./blah")) {
|
||||||
mg_printf(conn, "HTTP/1.1 200 OK\r\n"
|
*size = strlen(inmemory_file_data);
|
||||||
"Content-Length: %d\r\n"
|
return inmemory_file_data;
|
||||||
"Content-Type: text/plain\r\n\r\n"
|
|
||||||
"%s", (int) strlen(fetch_data), fetch_data);
|
|
||||||
return "";
|
|
||||||
} else if (event == MG_NEW_REQUEST && !strcmp(request_info->uri, "/upload")) {
|
|
||||||
ASSERT(mg_upload(conn, ".") == 1);
|
|
||||||
} else if (event == MG_OPEN_FILE) {
|
|
||||||
const char *path = request_info->ev_data;
|
|
||||||
if (strcmp(path, "./blah") == 0) {
|
|
||||||
mg_get_request_info(conn)->ev_data =
|
|
||||||
(void *) (long) strlen(inmemory_file_data);
|
|
||||||
return (void *) inmemory_file_data;
|
|
||||||
}
|
}
|
||||||
} else if (event == MG_EVENT_LOG) {
|
return NULL;
|
||||||
} else if (event == MG_UPLOAD) {
|
}
|
||||||
|
|
||||||
|
static void upload_cb(struct mg_connection *conn, const char *path) {
|
||||||
char *p1, *p2;
|
char *p1, *p2;
|
||||||
int len1, len2;
|
int len1, len2;
|
||||||
|
|
||||||
ASSERT(!strcmp((char *) request_info->ev_data, "./upload_test.txt"));
|
ASSERT(!strcmp(path, "./upload_test.txt"));
|
||||||
ASSERT((p1 = read_file("mongoose.c", &len1)) != NULL);
|
ASSERT((p1 = read_file("mongoose.c", &len1)) != NULL);
|
||||||
ASSERT((p2 = read_file(upload_filename, &len2)) != NULL);
|
ASSERT((p2 = read_file(path, &len2)) != NULL);
|
||||||
ASSERT(len1 == len2);
|
ASSERT(len1 == len2);
|
||||||
ASSERT(memcmp(p1, p2, len1) == 0);
|
ASSERT(memcmp(p1, p2, len1) == 0);
|
||||||
free(p1), free(p2);
|
free(p1), free(p2);
|
||||||
@ -224,9 +215,35 @@ static void *event_handler(enum mg_event event, struct mg_connection *conn) {
|
|||||||
(int) strlen(upload_ok_message), upload_ok_message);
|
(int) strlen(upload_ok_message), upload_ok_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
static int begin_request_handler_cb(struct mg_connection *conn) {
|
||||||
|
const struct mg_request_info *ri = mg_get_request_info(conn);
|
||||||
|
|
||||||
|
if (!strcmp(ri->uri, "/data")) {
|
||||||
|
mg_printf(conn, "HTTP/1.1 200 OK\r\n"
|
||||||
|
"Content-Length: %d\r\n"
|
||||||
|
"Content-Type: text/plain\r\n\r\n"
|
||||||
|
"%s", (int) strlen(fetch_data), fetch_data);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(ri->uri, "/upload")) {
|
||||||
|
ASSERT(mg_upload(conn, ".") == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int log_message_cb(const struct mg_connection *conn, const char *msg) {
|
||||||
|
(void) conn;
|
||||||
|
printf("%s\n", msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct mg_callbacks CALLBACKS = {
|
||||||
|
&begin_request_handler_cb, NULL, &log_message_cb, NULL, NULL, NULL, NULL,
|
||||||
|
&open_file_cb, NULL, &upload_cb
|
||||||
|
};
|
||||||
|
|
||||||
static const char *OPTIONS[] = {
|
static const char *OPTIONS[] = {
|
||||||
"document_root", ".",
|
"document_root", ".",
|
||||||
"listening_ports", LISTENING_ADDR,
|
"listening_ports", LISTENING_ADDR,
|
||||||
@ -252,7 +269,7 @@ static void test_mg_download(void) {
|
|||||||
struct mg_connection *conn;
|
struct mg_connection *conn;
|
||||||
struct mg_context *ctx;
|
struct mg_context *ctx;
|
||||||
|
|
||||||
ASSERT((ctx = mg_start(event_handler, NULL, OPTIONS)) != NULL);
|
ASSERT((ctx = mg_start(&CALLBACKS, NULL, OPTIONS)) != NULL);
|
||||||
|
|
||||||
ASSERT(mg_download(NULL, port, 0, ebuf, sizeof(ebuf), "%s", "") == NULL);
|
ASSERT(mg_download(NULL, port, 0, ebuf, sizeof(ebuf), "%s", "") == NULL);
|
||||||
ASSERT(mg_download("localhost", 0, 0, ebuf, sizeof(ebuf), "%s", "") == NULL);
|
ASSERT(mg_download("localhost", 0, 0, ebuf, sizeof(ebuf), "%s", "") == NULL);
|
||||||
@ -323,7 +340,7 @@ static void test_mg_upload(void) {
|
|||||||
char ebuf[100], buf[20], *file_data, *post_data = NULL;
|
char ebuf[100], buf[20], *file_data, *post_data = NULL;
|
||||||
int file_len, post_data_len;
|
int file_len, post_data_len;
|
||||||
|
|
||||||
ASSERT((ctx = mg_start(event_handler, NULL, OPTIONS)) != NULL);
|
ASSERT((ctx = mg_start(&CALLBACKS, NULL, OPTIONS)) != NULL);
|
||||||
ASSERT((file_data = read_file("mongoose.c", &file_len)) != NULL);
|
ASSERT((file_data = read_file("mongoose.c", &file_len)) != NULL);
|
||||||
post_data_len = alloc_printf(&post_data, 0,
|
post_data_len = alloc_printf(&post_data, 0,
|
||||||
"--%s\r\n"
|
"--%s\r\n"
|
||||||
@ -462,22 +479,6 @@ static void test_lua(void) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void *user_data_tester(enum mg_event event, struct mg_connection *conn) {
|
|
||||||
struct mg_request_info *ri = mg_get_request_info(conn);
|
|
||||||
ASSERT(ri->user_data == (void *) 123);
|
|
||||||
ASSERT(event == MG_NEW_REQUEST || event == MG_INIT_SSL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_user_data(void) {
|
|
||||||
struct mg_context *ctx;
|
|
||||||
|
|
||||||
ASSERT((ctx = mg_start(user_data_tester, (void *) 123, OPTIONS)) != NULL);
|
|
||||||
ASSERT(ctx->user_data == (void *) 123);
|
|
||||||
call_user(fc(ctx), MG_NEW_REQUEST);
|
|
||||||
mg_stop(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_mg_stat(void) {
|
static void test_mg_stat(void) {
|
||||||
static struct mg_context ctx;
|
static struct mg_context ctx;
|
||||||
struct file file = STRUCT_FILE_INITIALIZER;
|
struct file file = STRUCT_FILE_INITIALIZER;
|
||||||
@ -529,7 +530,7 @@ static void test_request_replies(void) {
|
|||||||
{NULL, NULL},
|
{NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
ASSERT((ctx = mg_start(event_handler, NULL, OPTIONS)) != NULL);
|
ASSERT((ctx = mg_start(&CALLBACKS, NULL, OPTIONS)) != NULL);
|
||||||
for (i = 0; tests[i].request != NULL; i++) {
|
for (i = 0; tests[i].request != NULL; i++) {
|
||||||
ASSERT((conn = mg_download("localhost", port, 1, ebuf, sizeof(ebuf), "%s",
|
ASSERT((conn = mg_download("localhost", port, 1, ebuf, sizeof(ebuf), "%s",
|
||||||
tests[i].request)) != NULL);
|
tests[i].request)) != NULL);
|
||||||
@ -549,7 +550,6 @@ int __cdecl main(void) {
|
|||||||
test_mg_get_var();
|
test_mg_get_var();
|
||||||
test_set_throttle();
|
test_set_throttle();
|
||||||
test_next_option();
|
test_next_option();
|
||||||
test_user_data();
|
|
||||||
test_mg_stat();
|
test_mg_stat();
|
||||||
test_skip_quoted();
|
test_skip_quoted();
|
||||||
test_mg_upload();
|
test_mg_upload();
|
||||||
|
Loading…
Reference in New Issue
Block a user