From f3a29b9b2b907cd26e92b9be1e970d981f08e2c9 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 4 Jun 2014 08:10:44 +0000 Subject: [PATCH] Updated to latest mongoose, used new added features (nw) --- src/emu/webengine.c | 73 +++++---------- src/lib/lib.mak | 4 + src/lib/web/mongoose.c | 196 +++++++++++++++++++++++------------------ src/lib/web/mongoose.h | 20 ++--- web/index.html | 1 + 5 files changed, 147 insertions(+), 147 deletions(-) diff --git a/src/emu/webengine.c b/src/emu/webengine.c index 5381638a5c3..6d9d7437132 100644 --- a/src/emu/webengine.c +++ b/src/emu/webengine.c @@ -236,58 +236,31 @@ int web_engine::begin_request_handler(struct mg_connection *conn) } else if (!strncmp(conn->uri, "/screenshot.png",15)) { - FILE *fp = (FILE *) conn->connection_param; - char buf[200]; - size_t n = 0; - if (fp == NULL) + screen_device_iterator iter(m_machine->root_device()); + screen_device *screen = iter.first(); + + if (screen == NULL) { - screen_device_iterator iter(m_machine->root_device()); - screen_device *screen = iter.first(); - - if (screen == NULL) - { - return 0; - } - - astring fname("screenshot.png"); - { - emu_file file(m_machine->options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - file_error filerr = file.open(fname); - - if (filerr != FILERR_NONE) - { - return 0; - } - - m_machine->video().save_snapshot(screen, file); - astring fullpath(file.fullpath()); - file.close(); - } - - { - emu_file file(m_machine->options().snapshot_directory(), OPEN_FLAG_READ); - file_error filerr = file.open(fname); - - if (filerr != FILERR_NONE) - { - return 0; - } - - file.seek(0, SEEK_SET); - mg_send_header(conn, "Content-Type", "image/png"); - mg_send_header(conn, "Cache-Control", "no-cache, no-store, must-revalidate"); - mg_send_header(conn, "Pragma", "no-cache"); - mg_send_header(conn, "Expires", "0"); - do - { - n = file.read(buf, sizeof(buf)); - mg_send_data(conn, buf, n); - } - while (n==sizeof(buf)); - file.close(); - } + return 0; } - return MG_TRUE; + + astring fname("screenshot.png"); + emu_file file(m_machine->options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); + file_error filerr = file.open(fname); + + if (filerr != FILERR_NONE) + { + return 0; + } + + m_machine->video().save_snapshot(screen, file); + astring fullpath(file.fullpath()); + file.close(); + mg_send_header(conn, "Cache-Control", "no-cache, no-store, must-revalidate"); + mg_send_header(conn, "Pragma", "no-cache"); + mg_send_header(conn, "Expires", "0"); + mg_send_file(conn, fullpath.cstr()); + return MG_MORE; // It is important to return MG_MORE after mg_send_file! } return 0; } diff --git a/src/lib/lib.mak b/src/lib/lib.mak index 9dfcdf997af..4631d2744c0 100644 --- a/src/lib/lib.mak +++ b/src/lib/lib.mak @@ -532,3 +532,7 @@ $(OBJ)/libweb.a: $(WEBOBJS) $(LIBOBJ)/web/%.o: $(LIBSRC)/web/%.cpp | $(OSPREBUILD) @echo Compiling $<... $(CC) $(CDEFS) $(CFLAGS) -I$(LIBSRC)/web -c $< -o $@ + +$(LIBOBJ)/web/%.o: $(LIBSRC)/web/%.c | $(OSPREBUILD) + @echo Compiling $<... + $(CC) $(CDEFS) $(CFLAGS) -I$(LIBSRC)/web -DNS_STACK_SIZE=0 -c $< -o $@ 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,10 +337,8 @@ 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); @@ -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; @@ -4137,73 +4138,13 @@ static void open_local_endpoint(struct connection *conn, int skip_user) { const char *dir_lst = conn->server->config_options[ENABLE_DIRECTORY_LISTING]; #else const char *dir_lst = "yes"; -#endif #endif - // If EP_USER was set in a prev call, reset it - conn->endpoint_type = EP_NONE; - -#ifndef MONGOOSE_NO_AUTH - if (conn->server->event_handler && call_user(conn, MG_AUTH) == MG_FALSE) { - mg_send_digest_auth_request(&conn->mg_conn); - return; - } -#endif - - // Call URI handler if one is registered for this URI - if (skip_user == 0 && conn->server->event_handler != NULL) { - conn->endpoint_type = EP_USER; -#if MONGOOSE_POST_SIZE_LIMIT > 1 - { - const char *cl = mg_get_header(&conn->mg_conn, "Content-Length"); - if ((strcmp(conn->mg_conn.request_method, "POST") == 0 || - strcmp(conn->mg_conn.request_method, "PUT") == 0) && - (cl == NULL || to64(cl) > MONGOOSE_POST_SIZE_LIMIT)) { - send_http_error(conn, 500, "POST size > %zu", - (size_t) MONGOOSE_POST_SIZE_LIMIT); - } - } -#endif - return; - } - - if (strcmp(conn->mg_conn.request_method, "CONNECT") == 0 || - memcmp(conn->mg_conn.uri, "http", 4) == 0) { - 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); - } -#else - exists = convert_uri_to_file_name(conn, path, sizeof(path), &st); + mg_snprintf(path, sizeof(path), "%s", file_name); + exists = stat(path, &st) == 0; is_directory = S_ISDIR(st.st_mode); - - if (!strcmp(conn->mg_conn.request_method, "OPTIONS")) { - send_options(conn); - } else if (conn->server->config_options[DOCUMENT_ROOT] == NULL) { - send_http_error(conn, 404, NULL); -#ifndef MONGOOSE_NO_AUTH - } else if ((!is_dav_request(conn) && !is_authorized(conn, path)) || - (is_dav_request(conn) && !is_authorized_for_dav(conn))) { - mg_send_digest_auth_request(&conn->mg_conn); - close_local_endpoint(conn); -#endif -#ifndef MONGOOSE_NO_DAV - } else if (!strcmp(conn->mg_conn.request_method, "PROPFIND")) { - handle_propfind(conn, path, &st, exists); - } else if (!strcmp(conn->mg_conn.request_method, "MKCOL")) { - handle_mkcol(conn, path); - } else if (!strcmp(conn->mg_conn.request_method, "DELETE")) { - handle_delete(conn, path); - } else if (!strcmp(conn->mg_conn.request_method, "PUT")) { - handle_put(conn, path); -#endif - } else if (!exists || must_hide_file(conn, path)) { + + 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] != '/') { @@ -4242,6 +4183,80 @@ static void open_local_endpoint(struct connection *conn, int skip_user) { } 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; + +#ifndef MONGOOSE_NO_AUTH + if (conn->server->event_handler && call_user(conn, MG_AUTH) == MG_FALSE) { + mg_send_digest_auth_request(&conn->mg_conn); + return; + } +#endif + + // Call URI handler if one is registered for this URI + if (skip_user == 0 && conn->server->event_handler != NULL) { + conn->endpoint_type = EP_USER; +#if MONGOOSE_POST_SIZE_LIMIT > 1 + { + const char *cl = mg_get_header(&conn->mg_conn, "Content-Length"); + if ((strcmp(conn->mg_conn.request_method, "POST") == 0 || + strcmp(conn->mg_conn.request_method, "PUT") == 0) && + (cl == NULL || to64(cl) > MONGOOSE_POST_SIZE_LIMIT)) { + send_http_error(conn, 500, "POST size > %zu", + (size_t) MONGOOSE_POST_SIZE_LIMIT); + } + } +#endif + return; + } + + if (strcmp(conn->mg_conn.request_method, "CONNECT") == 0 || + memcmp(conn->mg_conn.uri, "http", 4) == 0) { + proxify_connection(conn); + return; + } + + if (!strcmp(conn->mg_conn.request_method, "OPTIONS")) { + send_options(conn); + return; + } + +#ifdef MONGOOSE_NO_FILESYSTEM + send_http_error(conn, 404, NULL); +#else + exists = convert_uri_to_file_name(conn, path, sizeof(path), &st); + + if (!strcmp(conn->mg_conn.request_method, "OPTIONS")) { + send_options(conn); + } else if (conn->server->config_options[DOCUMENT_ROOT] == NULL) { + send_http_error(conn, 404, NULL); +#ifndef MONGOOSE_NO_AUTH + } else if ((!is_dav_request(conn) && !is_authorized(conn, path)) || + (is_dav_request(conn) && !is_authorized_for_dav(conn))) { + mg_send_digest_auth_request(&conn->mg_conn); + close_local_endpoint(conn); +#endif +#ifndef MONGOOSE_NO_DAV + } else if (!strcmp(conn->mg_conn.request_method, "PROPFIND")) { + handle_propfind(conn, path, &st, exists); + } else if (!strcmp(conn->mg_conn.request_method, "MKCOL")) { + handle_mkcol(conn, path); + } else if (!strcmp(conn->mg_conn.request_method, "DELETE")) { + handle_delete(conn, path); + } else if (!strcmp(conn->mg_conn.request_method, "PUT")) { + handle_put(conn, path); +#endif + } else { + 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); diff --git a/src/lib/web/mongoose.h b/src/lib/web/mongoose.h index 008a54580b8..c1e1a374b13 100644 --- a/src/lib/web/mongoose.h +++ b/src/lib/web/mongoose.h @@ -99,17 +99,17 @@ struct mg_connection *mg_connect(struct mg_server *, const char *, int, int); // Connection management functions void mg_send_status(struct mg_connection *, int status_code); void mg_send_header(struct mg_connection *, const char *name, const char *val); -void mg_send_data(struct mg_connection *, const void *data, int data_len); -void mg_printf_data(struct mg_connection *, const char *format, ...); +size_t mg_send_data(struct mg_connection *, const void *data, int data_len); +size_t mg_printf_data(struct mg_connection *, const char *format, ...); +size_t mg_write(struct mg_connection *, const void *buf, int len); +size_t mg_printf(struct mg_connection *conn, const char *fmt, ...); -int mg_websocket_write(struct mg_connection *, int opcode, - const char *data, size_t data_len); -int mg_websocket_printf(struct mg_connection* conn, int opcode, - const char *fmt, ...); - -// Deprecated in favor of mg_send_* interface -int mg_write(struct mg_connection *, const void *buf, int len); -int mg_printf(struct mg_connection *conn, const char *fmt, ...); +size_t mg_websocket_write(struct mg_connection *, int opcode, + const char *data, size_t data_len); +size_t mg_websocket_printf(struct mg_connection* conn, int opcode, + const char *fmt, ...); + +void mg_send_file(struct mg_connection *, const char *path); const char *mg_get_header(const struct mg_connection *, const char *name); const char *mg_get_mime_type(const char *name, const char *default_mime_type); diff --git a/web/index.html b/web/index.html index e21ac49aa88..bd019dcb22d 100644 --- a/web/index.html +++ b/web/index.html @@ -187,6 +187,7 @@ // Now, actually update the status bar.. updateStatusBar('',statusbar_ispaused.join(''),statusbar_runningdriver.join('')); + takeScreenshot(); }, error: function (request, status, error) { alert(status + ", " + error); } });