summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/web/mongoose.c
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2014-06-04 08:10:44 +0000
committer Miodrag Milanovic <mmicko@gmail.com>2014-06-04 08:10:44 +0000
commitf3a29b9b2b907cd26e92b9be1e970d981f08e2c9 (patch)
tree197a14afbf9e23e67d2eab9a2dac3f9304494b1c /src/lib/web/mongoose.c
parente9a514c441437c64aada72b30d31ab6f1fd9cfa7 (diff)
Updated to latest mongoose, used new added features (nw)
Diffstat (limited to 'src/lib/web/mongoose.c')
-rw-r--r--src/lib/web/mongoose.c152
1 files changed, 87 insertions, 65 deletions
diff --git a/src/lib/web/mongoose.c b/src/lib/web/mongoose.c
index 00e79ca8008..08338fbd60e 100644
--- a/src/lib/web/mongoose.c
+++ b/src/lib/web/mongoose.c
@@ -337,11 +337,9 @@ void *ns_start_thread(void *(*f)(void *), void *p) {
(void) pthread_attr_init(&attr);
(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-#ifdef NS_STACK_SIZE
#if NS_STACK_SIZE > 1
(void) pthread_attr_setstacksize(&attr, NS_STACK_SIZE);
#endif
-#endif
pthread_create(&thread_id, &attr, f, p);
pthread_attr_destroy(&attr);
@@ -807,7 +805,7 @@ static void ns_write_to_socket(struct ns_connection *conn) {
iobuf_remove(io, n);
}
- if (io->len == 0 && conn->flags & NSF_FINISHED_SENDING_DATA) {
+ if (io->len == 0 && (conn->flags & NSF_FINISHED_SENDING_DATA)) {
conn->flags |= NSF_CLOSE_IMMEDIATELY;
}
}
@@ -1604,16 +1602,15 @@ static void write_chunk(struct connection *conn, const char *buf, int len) {
ns_send(conn->ns_conn, "\r\n", 2);
}
-int mg_printf(struct mg_connection *conn, const char *fmt, ...) {
+size_t mg_printf(struct mg_connection *conn, const char *fmt, ...) {
struct connection *c = MG_CONN_2_CONN(conn);
- int len;
va_list ap;
va_start(ap, fmt);
- len = ns_vprintf(c->ns_conn, fmt, ap);
+ ns_vprintf(c->ns_conn, fmt, ap);
va_end(ap);
- return len;
+ return c->ns_conn->send_iobuf.len;
}
static void ns_forward(struct ns_connection *from, struct ns_connection *to) {
@@ -2178,7 +2175,7 @@ static int parse_http_message(char *buf, int len, struct mg_connection *ri) {
n = (int) strlen(ri->uri);
mg_url_decode(ri->uri, n, (char *) ri->uri, n + 1, 0);
if (*ri->uri == '/' || *ri->uri == '.') {
- remove_double_dots_and_double_slashes((char *) ri->uri);
+ remove_double_dots_and_double_slashes((char *) ri->uri);
}
}
@@ -2378,9 +2375,10 @@ static int should_keep_alive(const struct mg_connection *conn) {
(header == NULL && http_version && !strcmp(http_version, "1.1")));
}
-int mg_write(struct mg_connection *c, const void *buf, int len) {
+size_t mg_write(struct mg_connection *c, const void *buf, int len) {
struct connection *conn = MG_CONN_2_CONN(c);
- return ns_send(conn->ns_conn, buf, len);
+ ns_send(conn->ns_conn, buf, len);
+ return conn->ns_conn->send_iobuf.len;
}
void mg_send_status(struct mg_connection *c, int status) {
@@ -2407,12 +2405,14 @@ static void terminate_headers(struct mg_connection *c) {
}
}
-void mg_send_data(struct mg_connection *c, const void *data, int data_len) {
+size_t mg_send_data(struct mg_connection *c, const void *data, int data_len) {
+ struct connection *conn = MG_CONN_2_CONN(c);
terminate_headers(c);
write_chunk(MG_CONN_2_CONN(c), (const char *) data, data_len);
+ return conn->ns_conn->send_iobuf.len;
}
-void mg_printf_data(struct mg_connection *c, const char *fmt, ...) {
+size_t mg_printf_data(struct mg_connection *c, const char *fmt, ...) {
struct connection *conn = MG_CONN_2_CONN(c);
va_list ap;
int len;
@@ -2430,6 +2430,7 @@ void mg_printf_data(struct mg_connection *c, const char *fmt, ...) {
if (buf != mem && buf != NULL) {
free(buf);
}
+ return conn->ns_conn->send_iobuf.len;
}
#if !defined(MONGOOSE_NO_WEBSOCKET) || !defined(MONGOOSE_NO_AUTH)
@@ -2662,15 +2663,14 @@ static int deliver_websocket_frame(struct connection *conn) {
return buffered;
}
-int mg_websocket_write(struct mg_connection* conn, int opcode,
+size_t mg_websocket_write(struct mg_connection* conn, int opcode,
const char *data, size_t data_len) {
unsigned char mem[4192], *copy = mem;
size_t copy_len = 0;
- int retval = -1;
if (data_len + 10 > sizeof(mem) &&
(copy = (unsigned char *) malloc(data_len + 10)) == NULL) {
- return -1;
+ return 0;
}
copy[0] = 0x80 + (opcode & 0x0f);
@@ -2698,17 +2698,17 @@ int mg_websocket_write(struct mg_connection* conn, int opcode,
}
if (copy_len > 0) {
- retval = mg_write(conn, copy, copy_len);
+ mg_write(conn, copy, copy_len);
}
if (copy != mem) {
free(copy);
}
- return retval;
+ return MG_CONN_2_CONN(conn)->ns_conn->send_iobuf.len;
}
-int mg_websocket_printf(struct mg_connection* conn, int opcode,
- const char *fmt, ...) {
+size_t mg_websocket_printf(struct mg_connection* conn, int opcode,
+ const char *fmt, ...) {
char mem[4192], *buf = mem;
va_list ap;
int len;
@@ -2723,7 +2723,7 @@ int mg_websocket_printf(struct mg_connection* conn, int opcode,
free(buf);
}
- return len;
+ return MG_CONN_2_CONN(conn)->ns_conn->send_iobuf.len;
}
static void send_websocket_handshake_if_requested(struct mg_connection *conn) {
@@ -4123,8 +4123,9 @@ static void proxify_connection(struct connection *conn) {
}
}
-static void open_local_endpoint(struct connection *conn, int skip_user) {
#ifndef MONGOOSE_NO_FILESYSTEM
+void mg_send_file(struct mg_connection *c, const char *file_name) {
+ struct connection *conn = MG_CONN_2_CONN(c);
file_stat_t st;
char path[MAX_PATH_SIZE];
int exists = 0, is_directory = 0;
@@ -4138,7 +4139,57 @@ static void open_local_endpoint(struct connection *conn, int skip_user) {
#else
const char *dir_lst = "yes";
#endif
+
+ mg_snprintf(path, sizeof(path), "%s", file_name);
+ exists = stat(path, &st) == 0;
+ is_directory = S_ISDIR(st.st_mode);
+
+ if (!exists || must_hide_file(conn, path)) {
+ send_http_error(conn, 404, NULL);
+ } else if (is_directory &&
+ conn->mg_conn.uri[strlen(conn->mg_conn.uri) - 1] != '/') {
+ conn->mg_conn.status_code = 301;
+ mg_printf(&conn->mg_conn, "HTTP/1.1 301 Moved Permanently\r\n"
+ "Location: %s/\r\n\r\n", conn->mg_conn.uri);
+ close_local_endpoint(conn);
+ } else if (is_directory && !find_index_file(conn, path, sizeof(path), &st)) {
+ if (!mg_strcasecmp(dir_lst, "yes")) {
+#ifndef MONGOOSE_NO_DIRECTORY_LISTING
+ send_directory_listing(conn, path);
+#else
+ send_http_error(conn, 501, NULL);
+#endif
+ } else {
+ send_http_error(conn, 403, NULL);
+ }
+ } else if (mg_match_prefix(cgi_pat, strlen(cgi_pat), path) > 0) {
+#if !defined(MONGOOSE_NO_CGI)
+ open_cgi_endpoint(conn, path);
+#else
+ send_http_error(conn, 501, NULL);
+#endif // !MONGOOSE_NO_CGI
+#ifndef MONGOOSE_NO_SSI
+ } else if (mg_match_prefix(conn->server->config_options[SSI_PATTERN],
+ strlen(conn->server->config_options[SSI_PATTERN]),
+ path) > 0) {
+ handle_ssi_request(conn, path);
#endif
+ } else if (is_not_modified(conn, &st)) {
+ send_http_error(conn, 304, NULL);
+ } else if ((conn->endpoint.fd = open(path, O_RDONLY | O_BINARY)) != -1) {
+ // O_BINARY is required for Windows, otherwise in default text mode
+ // two bytes \r\n will be read as one.
+ open_file_endpoint(conn, path, &st);
+ } else {
+ send_http_error(conn, 404, NULL);
+ }
+}
+#endif // !MONGOOSE_NO_FILESYSTEM
+
+static void open_local_endpoint(struct connection *conn, int skip_user) {
+ char path[MAX_PATH_SIZE];
+ file_stat_t st;
+ int exists = 0;
// If EP_USER was set in a prev call, reset it
conn->endpoint_type = EP_NONE;
@@ -4172,16 +4223,16 @@ static void open_local_endpoint(struct connection *conn, int skip_user) {
proxify_connection(conn);
return;
}
-
-#ifdef MONGOOSE_NO_FILESYSTEM
+
if (!strcmp(conn->mg_conn.request_method, "OPTIONS")) {
send_options(conn);
- } else {
- send_http_error(conn, 404, NULL);
+ return;
}
+
+#ifdef MONGOOSE_NO_FILESYSTEM
+ send_http_error(conn, 404, NULL);
#else
exists = convert_uri_to_file_name(conn, path, sizeof(path), &st);
- is_directory = S_ISDIR(st.st_mode);
if (!strcmp(conn->mg_conn.request_method, "OPTIONS")) {
send_options(conn);
@@ -4203,44 +4254,8 @@ static void open_local_endpoint(struct connection *conn, int skip_user) {
} else if (!strcmp(conn->mg_conn.request_method, "PUT")) {
handle_put(conn, path);
#endif
- } else if (!exists || must_hide_file(conn, path)) {
- send_http_error(conn, 404, NULL);
- } else if (is_directory &&
- conn->mg_conn.uri[strlen(conn->mg_conn.uri) - 1] != '/') {
- conn->mg_conn.status_code = 301;
- mg_printf(&conn->mg_conn, "HTTP/1.1 301 Moved Permanently\r\n"
- "Location: %s/\r\n\r\n", conn->mg_conn.uri);
- close_local_endpoint(conn);
- } else if (is_directory && !find_index_file(conn, path, sizeof(path), &st)) {
- if (!mg_strcasecmp(dir_lst, "yes")) {
-#ifndef MONGOOSE_NO_DIRECTORY_LISTING
- send_directory_listing(conn, path);
-#else
- send_http_error(conn, 501, NULL);
-#endif
- } else {
- send_http_error(conn, 403, NULL);
- }
- } else if (mg_match_prefix(cgi_pat, strlen(cgi_pat), path) > 0) {
-#if !defined(MONGOOSE_NO_CGI)
- open_cgi_endpoint(conn, path);
-#else
- send_http_error(conn, 501, NULL);
-#endif // !MONGOOSE_NO_CGI
-#ifndef MONGOOSE_NO_SSI
- } else if (mg_match_prefix(conn->server->config_options[SSI_PATTERN],
- strlen(conn->server->config_options[SSI_PATTERN]),
- path) > 0) {
- handle_ssi_request(conn, path);
-#endif
- } else if (is_not_modified(conn, &st)) {
- send_http_error(conn, 304, NULL);
- } else if ((conn->endpoint.fd = open(path, O_RDONLY | O_BINARY)) != -1) {
- // O_BINARY is required for Windows, otherwise in default text mode
- // two bytes \r\n will be read as one.
- open_file_endpoint(conn, path, &st);
} else {
- send_http_error(conn, 404, NULL);
+ mg_send_file(&conn->mg_conn, path);
}
#endif // MONGOOSE_NO_FILESYSTEM
}
@@ -4496,8 +4511,15 @@ static void close_local_endpoint(struct connection *conn) {
static void transfer_file_data(struct connection *conn) {
char buf[IOBUF_SIZE];
- int n = read(conn->endpoint.fd, buf, conn->cl < (int64_t) sizeof(buf) ?
- (int) conn->cl : (int) sizeof(buf));
+ int n;
+
+ // If output buffer is too big, don't send anything. Wait until
+ // mongoose drains already buffered data to the client.
+ if (conn->ns_conn->send_iobuf.len > sizeof(buf) * 2) return;
+
+ // Do not send anyt
+ n = read(conn->endpoint.fd, buf, conn->cl < (int64_t) sizeof(buf) ?
+ (int) conn->cl : (int) sizeof(buf));
if (n <= 0) {
close_local_endpoint(conn);