mirror of
https://github.com/holub/mame
synced 2025-07-02 00:29:37 +03:00
newest mongoose.. PRETTY sure I didn't alter anything (NW)
This commit is contained in:
parent
6e855b9cf7
commit
43ef9c65e0
30
3rdparty/mongoose/README.md
vendored
30
3rdparty/mongoose/README.md
vendored
@ -1,5 +1,7 @@
|
|||||||
# <img src="http://cesanta.com/images/mongoose_logo.png" width="64" height="64"> Mongoose Web Server
|
# <img src="http://cesanta.com/images/mongoose_logo.png" width="64" height="64"> Mongoose Web Server
|
||||||
|
|
||||||
|
[](https://gitter.im/cesanta/mongoose?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
|
||||||
Mongoose is the most easy to use web server on the planet. A web server of choice for Web developers (PHP, Ruby, Python, etc) and Web designers.
|
Mongoose is the most easy to use web server on the planet. A web server of choice for Web developers (PHP, Ruby, Python, etc) and Web designers.
|
||||||
|
|
||||||
Mongoose is built on top of Libmongoose embedded library, which can turn
|
Mongoose is built on top of Libmongoose embedded library, which can turn
|
||||||
@ -45,24 +47,13 @@ Download, double-click to start, run browser -- that's all!
|
|||||||

|

|
||||||

|

|
||||||
|
|
||||||
# Acknowledgements
|
# Contributions
|
||||||
|
|
||||||
Mongoose made better thanks to the contribution of following people:
|
People who have agreed to the
|
||||||
|
[Cesanta CLA](http://cesanta.com/contributors_la.html)
|
||||||
Arnout Vandecappelle, Benoît Amiaux, Boris Pek, Cody Hanson, Colin Leitner,
|
can make contributions. Note that the CLA isn't a copyright
|
||||||
Daniel Oaks, Eric Bakan, Erik Oomen, Filipp Kovalev, Ger Hobbelt,
|
_assigment_ but rather a copyright _license_.
|
||||||
Hendrik Polczynski, Igor Okulist, Jay, Joe Mucchiello, John Safranek,
|
You retain the copyright on your contributions.
|
||||||
José Miguel Gonçalves, Shueng Chuan, Katerina Blinova, Konstantin Sorokin,
|
|
||||||
Marin Atanasov, Matt Healy, Mitch Hendrickson, Nigel Stewart, Pavel Khlebovich,
|
|
||||||
Sebastian Reinhard, Stefan Doehla, abadc0de, nullable.type,
|
|
||||||
T.Barmann, D.Hughes, J.C.Sloan, R.Romeo, L.E.Spencer, S.Kotay, R.M.Shorter,
|
|
||||||
W.Mar, J.Wilander, Santa from Memphis, S.Davies, C.Beck,
|
|
||||||
O.M.Vilhunen, C.Radik, G.Woodcock, M.Szczepkowski,
|
|
||||||
Eternal Lands Dev Team, T.Tollet, C.Tangerino, G.Karsai, A.Bourgett,
|
|
||||||
C.Blakemore, D.Fonaryov, T.Andrle, O.IJsselmuiden, R.Womack, M.Tomlinson,
|
|
||||||
A.Slåttå, L.Farrell, J.D.P.Ballestero, V.Albaev, B.Harker, T.Scheffel, H.Klein,
|
|
||||||
R.Merit, T.Bennett, H.Solis, A.Zincenko, M.S., S.Krul, K.Cooke, S.McCallum,
|
|
||||||
F.Morenius, and 10 others.
|
|
||||||
|
|
||||||
# Licensing
|
# Licensing
|
||||||
|
|
||||||
@ -72,11 +63,11 @@ source licenses. The GPLv2 open source License does not generally permit
|
|||||||
incorporating this software into non-open source programs.
|
incorporating this software into non-open source programs.
|
||||||
For those customers who do not wish to comply with the GPLv2 open
|
For those customers who do not wish to comply with the GPLv2 open
|
||||||
source license requirements,
|
source license requirements,
|
||||||
[Cesanta Software](http://cesanta.com) offers a full,
|
[Cesanta](http://cesanta.com) offers a full,
|
||||||
royalty-free commercial license and professional support
|
royalty-free commercial license and professional support
|
||||||
without any of the GPL restrictions.
|
without any of the GPL restrictions.
|
||||||
|
|
||||||
# Other products by Cesanta Software: simple and effective
|
# Other products by Cesanta
|
||||||
|
|
||||||
- [Fossa](http://github.com/cesanta/fossa) - Multi-protocol networking library
|
- [Fossa](http://github.com/cesanta/fossa) - Multi-protocol networking library
|
||||||
- [SSL Wrapper](https://github.com/cesanta/ssl_wrapper) - application to
|
- [SSL Wrapper](https://github.com/cesanta/ssl_wrapper) - application to
|
||||||
@ -84,3 +75,4 @@ without any of the GPL restrictions.
|
|||||||
- [Frozen](https://github.com/cesanta/frozen) - JSON parser and generator
|
- [Frozen](https://github.com/cesanta/frozen) - JSON parser and generator
|
||||||
- [SLRE](https://github.com/cesanta/slre) - Super Light Regular Expression
|
- [SLRE](https://github.com/cesanta/slre) - Super Light Regular Expression
|
||||||
library
|
library
|
||||||
|
- [V7](https://github.com/cesanta/v7) - Embedded JavaScript engine
|
||||||
|
4
3rdparty/mongoose/docs/ReleaseNotes.md
vendored
4
3rdparty/mongoose/docs/ReleaseNotes.md
vendored
@ -168,7 +168,7 @@ Changes in pre-compiled binaries:
|
|||||||
since mongoose buffers all data prior to calling the callback
|
since mongoose buffers all data prior to calling the callback
|
||||||
* keep-alive support is the default
|
* keep-alive support is the default
|
||||||
* Dropped SSI support and throttling support
|
* Dropped SSI support and throttling support
|
||||||
* Several configuraition parameters are gone:
|
* Several configuration parameters are gone:
|
||||||
* `cgi_environment` (replaced with MONGOOSE_CGI),
|
* `cgi_environment` (replaced with MONGOOSE_CGI),
|
||||||
* `protect_uri` (not useful)
|
* `protect_uri` (not useful)
|
||||||
* `ssi_pattern` (SSI support is gone)
|
* `ssi_pattern` (SSI support is gone)
|
||||||
@ -214,5 +214,5 @@ Changes in pre-compiled binaries:
|
|||||||
* Couple of bugfixes, thanks to contributors
|
* Couple of bugfixes, thanks to contributors
|
||||||
|
|
||||||
|
|
||||||
Eearlier release notes could be found by searching
|
Earlier release notes could be found by searching
|
||||||
[Mongoose mailing list](https://groups.google.com/forum/#!forum/mongoose-users)
|
[Mongoose mailing list](https://groups.google.com/forum/#!forum/mongoose-users)
|
||||||
|
21
3rdparty/mongoose/examples/array_vars/Makefile
vendored
Normal file
21
3rdparty/mongoose/examples/array_vars/Makefile
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Copyright (c) 2014 Cesanta Software
|
||||||
|
# All rights reserved
|
||||||
|
|
||||||
|
PROG = array_vars
|
||||||
|
CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA)
|
||||||
|
SOURCES = $(PROG).c ../../mongoose.c
|
||||||
|
|
||||||
|
all: $(PROG)
|
||||||
|
|
||||||
|
run: $(PROG)
|
||||||
|
./$(PROG)
|
||||||
|
|
||||||
|
$(PROG): $(SOURCES) Makefile
|
||||||
|
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
||||||
|
|
||||||
|
win:
|
||||||
|
wine cl $(SOURCES) /MD /nologo /DNDEBUG /O1 /I../.. /Fe$(PROG).exe
|
||||||
|
wine $(PROG).exe
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib *.gc*
|
45
3rdparty/mongoose/examples/array_vars/array_vars.c
vendored
Normal file
45
3rdparty/mongoose/examples/array_vars/array_vars.c
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// Copyright (c) 2014 Cesanta Software
|
||||||
|
// All rights reserved
|
||||||
|
//
|
||||||
|
// This example demostrates how to use array get variables using mg_get_n_var
|
||||||
|
// $Date: 2014-09-09 22:20:23 UTC $
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||||
|
switch (ev) {
|
||||||
|
case MG_AUTH: return MG_TRUE;
|
||||||
|
case MG_REQUEST:
|
||||||
|
{
|
||||||
|
mg_printf_data(conn, "Hello! Requested URI is [%s] ", conn->uri);
|
||||||
|
char buffer[1024];
|
||||||
|
int i, ret;
|
||||||
|
for(i=0; (ret = mg_get_var_n(conn, "foo[]", buffer, 1024, i)) > 0; i++)
|
||||||
|
mg_printf_data(conn, "\nfoo[%d] = %s", i, buffer);
|
||||||
|
|
||||||
|
return MG_TRUE;
|
||||||
|
}
|
||||||
|
default: return MG_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
struct mg_server *server;
|
||||||
|
|
||||||
|
// Create and configure the server
|
||||||
|
server = mg_create_server(NULL, ev_handler);
|
||||||
|
mg_set_option(server, "listening_port", "8080");
|
||||||
|
|
||||||
|
// Serve request. Hit Ctrl-C to terminate the program
|
||||||
|
printf("Starting on port %s\n", mg_get_option(server, "listening_port"));
|
||||||
|
for (;;) {
|
||||||
|
mg_poll_server(server, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup, and free server instance
|
||||||
|
mg_destroy_server(&server);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -58,6 +58,7 @@ static int check_login_form_submission(struct mg_connection *conn) {
|
|||||||
mg_printf(conn,
|
mg_printf(conn,
|
||||||
"HTTP/1.1 302 Moved\r\n"
|
"HTTP/1.1 302 Moved\r\n"
|
||||||
"Set-Cookie: ssid=%s; expire=\"%s\"; http-only; HttpOnly;\r\n"
|
"Set-Cookie: ssid=%s; expire=\"%s\"; http-only; HttpOnly;\r\n"
|
||||||
|
"Content-Length: 0\r\n"
|
||||||
"Location: /\r\n\r\n",
|
"Location: /\r\n\r\n",
|
||||||
ssid, expire);
|
ssid, expire);
|
||||||
return MG_TRUE;
|
return MG_TRUE;
|
||||||
|
@ -7,23 +7,25 @@
|
|||||||
|
|
||||||
static int send_index_page(struct mg_connection *conn) {
|
static int send_index_page(struct mg_connection *conn) {
|
||||||
const char *data;
|
const char *data;
|
||||||
int data_len, ofs = 0;
|
int data_len, n1, n2;
|
||||||
char var_name[100], file_name[100];
|
char var_name[100], file_name[100];
|
||||||
|
|
||||||
mg_printf_data(conn, "%s",
|
mg_printf_data(conn, "%s",
|
||||||
"<html><body>Upload example."
|
"<html><body>Upload example."
|
||||||
"<form method=\"POST\" action=\"/handle_post_request\" "
|
"<form method=\"POST\" action=\"/handle_post_request\" "
|
||||||
" enctype=\"multipart/form-data\">"
|
" enctype=\"multipart/form-data\">"
|
||||||
"<input type=\"file\" name=\"file\" /> <br/>"
|
"<input type=\"file\" name=\"file1\" /> <br/>"
|
||||||
|
"<input type=\"file\" name=\"file2\" /> <br/>"
|
||||||
"<input type=\"submit\" value=\"Upload\" />"
|
"<input type=\"submit\" value=\"Upload\" />"
|
||||||
"</form>");
|
"</form>");
|
||||||
|
|
||||||
while ((ofs = mg_parse_multipart(conn->content + ofs, conn->content_len - ofs,
|
n1 = n2 = 0;
|
||||||
var_name, sizeof(var_name),
|
while ((n2 = mg_parse_multipart(conn->content + n1, conn->content_len - n1,
|
||||||
file_name, sizeof(file_name),
|
var_name, sizeof(var_name), file_name,
|
||||||
&data, &data_len)) > 0) {
|
sizeof(file_name), &data, &data_len)) > 0) {
|
||||||
mg_printf_data(conn, "var: %s, file_name: %s, size: %d bytes<br>",
|
mg_printf_data(conn, "var: %s, file_name: %s, size: %d bytes<br>",
|
||||||
var_name, file_name, data_len);
|
var_name, file_name, data_len);
|
||||||
|
n1 += n2;
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_printf_data(conn, "%s", "</body></html>");
|
mg_printf_data(conn, "%s", "</body></html>");
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# All rights reserved
|
# All rights reserved
|
||||||
|
|
||||||
PROG = web_server
|
PROG = web_server
|
||||||
CFLAGS = -W -Wall -I../.. -pthread -g -O0 -DMONGOOSE_ENABLE_THREADS $(CFLAGS_EXTRA)
|
CFLAGS = -W -Wall -I../.. -g -O0 $(CFLAGS_EXTRA)
|
||||||
SOURCES = $(PROG).c ../../mongoose.c
|
SOURCES = $(PROG).c ../../mongoose.c
|
||||||
OPENSSL_FLAGS = -DNS_ENABLE_SSL -lssl
|
OPENSSL_FLAGS = -DNS_ENABLE_SSL -lssl
|
||||||
|
|
||||||
@ -13,16 +13,18 @@ SOURCES_POLAR = $(SOURCES) $(POLARSSLCOMPAT_PATH)/polarssl_compat.c
|
|||||||
INCDIR_POLAR = -I$(POLARSSLCOMPAT_PATH) -I$(POLARSSL_PATH)/include
|
INCDIR_POLAR = -I$(POLARSSLCOMPAT_PATH) -I$(POLARSSL_PATH)/include
|
||||||
LDFLAGS_POLAR = -L$(POLARSSL_PATH)/lib -lmbedtls
|
LDFLAGS_POLAR = -L$(POLARSSL_PATH)/lib -lmbedtls
|
||||||
CFLAGS_POLAR = $(CFLAGS) $(INCDIR_POLAR) -DNS_ENABLE_SSL
|
CFLAGS_POLAR = $(CFLAGS) $(INCDIR_POLAR) -DNS_ENABLE_SSL
|
||||||
#
|
|
||||||
|
|
||||||
$(PROG): $(SOURCES)
|
$(PROG): $(SOURCES)
|
||||||
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
||||||
|
|
||||||
|
$(PROG).exe: $(SOURCES)
|
||||||
|
cl -Fo $(PROG) $(SOURCES) -nologo -MD -I../..
|
||||||
|
|
||||||
openssl:
|
openssl:
|
||||||
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS) $(OPENSSL_FLAGS)
|
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS) $(OPENSSL_FLAGS)
|
||||||
|
|
||||||
polarssl:
|
polarssl:
|
||||||
$(CC) -o $(PROG) $(SOURCES_POLAR) $(LDFLAGS_POLAR) $(CFLAGS_POLAR)
|
$(CC) -o $(PROG) $(SOURCES_POLAR) $(LDFLAGS_POLAR) $(CFLAGS_POLAR)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib
|
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib
|
||||||
|
@ -40,7 +40,9 @@
|
|||||||
#define DIRSEP '\\'
|
#define DIRSEP '\\'
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
#define vsnprintf _vsnprintf
|
#define vsnprintf _vsnprintf
|
||||||
|
#ifndef sleep
|
||||||
#define sleep(x) Sleep((x) * 1000)
|
#define sleep(x) Sleep((x) * 1000)
|
||||||
|
#endif
|
||||||
#define abs_path(rel, abs, abs_size) _fullpath((abs), (rel), (abs_size))
|
#define abs_path(rel, abs, abs_size) _fullpath((abs), (rel), (abs_size))
|
||||||
#define SIGCHLD 0
|
#define SIGCHLD 0
|
||||||
typedef struct _stat file_stat_t;
|
typedef struct _stat file_stat_t;
|
||||||
|
228
3rdparty/mongoose/mongoose.c
vendored
228
3rdparty/mongoose/mongoose.c
vendored
@ -63,6 +63,10 @@
|
|||||||
#pragma warning (disable : 4204) // missing c99 support
|
#pragma warning (disable : 4204) // missing c99 support
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(MONGOOSE_NO_CGI)
|
||||||
|
#define MONGOOSE_ENABLE_THREADS /* Windows uses stdio threads for CGI */
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef MONGOOSE_ENABLE_THREADS
|
#ifndef MONGOOSE_ENABLE_THREADS
|
||||||
#define NS_DISABLE_THREADS
|
#define NS_DISABLE_THREADS
|
||||||
#endif
|
#endif
|
||||||
@ -91,6 +95,9 @@
|
|||||||
#include <BaseTsd.h>
|
#include <BaseTsd.h>
|
||||||
typedef SSIZE_T ssize_t;
|
typedef SSIZE_T ssize_t;
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef FD_SETSIZE
|
||||||
|
#define FD_SETSIZE 1024
|
||||||
|
#endif
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@ -231,6 +238,7 @@ struct ns_connection {
|
|||||||
|
|
||||||
sock_t sock; // Socket
|
sock_t sock; // Socket
|
||||||
union socket_address sa; // Peer address
|
union socket_address sa; // Peer address
|
||||||
|
size_t recv_iobuf_limit; /* Max size of recv buffer */
|
||||||
struct iobuf recv_iobuf; // Received data
|
struct iobuf recv_iobuf; // Received data
|
||||||
struct iobuf send_iobuf; // Data scheduled for sending
|
struct iobuf send_iobuf; // Data scheduled for sending
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
@ -250,6 +258,7 @@ struct ns_connection {
|
|||||||
#define NSF_WANT_WRITE (1 << 6)
|
#define NSF_WANT_WRITE (1 << 6)
|
||||||
#define NSF_LISTENING (1 << 7)
|
#define NSF_LISTENING (1 << 7)
|
||||||
#define NSF_UDP (1 << 8)
|
#define NSF_UDP (1 << 8)
|
||||||
|
#define NSF_DISCARD (1 << 9)
|
||||||
|
|
||||||
#define NSF_USER_1 (1 << 20)
|
#define NSF_USER_1 (1 << 20)
|
||||||
#define NSF_USER_2 (1 << 21)
|
#define NSF_USER_2 (1 << 21)
|
||||||
@ -326,6 +335,7 @@ int ns_resolve(const char *domain_name, char *ip_addr_buf, size_t buf_len);
|
|||||||
#define NS_CALLOC calloc
|
#define NS_CALLOC calloc
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define NS_MAX_SOCKETPAIR_ATTEMPTS 10
|
||||||
#define NS_CTL_MSG_MESSAGE_SIZE (8 * 1024)
|
#define NS_CTL_MSG_MESSAGE_SIZE (8 * 1024)
|
||||||
#define NS_READ_BUFFER_SIZE 2048
|
#define NS_READ_BUFFER_SIZE 2048
|
||||||
#define NS_UDP_RECEIVE_BUFFER_SIZE 2000
|
#define NS_UDP_RECEIVE_BUFFER_SIZE 2000
|
||||||
@ -854,7 +864,17 @@ static int ns_is_error(int n) {
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
&& WSAGetLastError() != WSAEINTR && WSAGetLastError() != WSAEWOULDBLOCK
|
&& WSAGetLastError() != WSAEINTR && WSAGetLastError() != WSAEWOULDBLOCK
|
||||||
#endif
|
#endif
|
||||||
);
|
)
|
||||||
|
#ifdef NS_ENABLE_SSL
|
||||||
|
/*
|
||||||
|
* OpenSSL can return an error when the peer is closing the socket.
|
||||||
|
* We don't encounter this error with openssl actually, but it's returned
|
||||||
|
* by our polarssl <-> openssl wrapper who tries to speak the openssl API
|
||||||
|
* as we understood it.
|
||||||
|
*/
|
||||||
|
|| n == SSL_AD_CLOSE_NOTIFY
|
||||||
|
#endif
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ns_sock_to_str(sock_t sock, char *buf, size_t len, int flags) {
|
void ns_sock_to_str(sock_t sock, char *buf, size_t len, int flags) {
|
||||||
@ -1056,7 +1076,7 @@ static void ns_handle_udp(struct ns_connection *ls) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void ns_add_to_set(sock_t sock, fd_set *set, sock_t *max_fd) {
|
static void ns_add_to_set(sock_t sock, fd_set *set, sock_t *max_fd) {
|
||||||
if (sock != INVALID_SOCKET) {
|
if ( (sock != INVALID_SOCKET) && (sock < FD_SETSIZE) ) {
|
||||||
FD_SET(sock, set);
|
FD_SET(sock, set);
|
||||||
if (*max_fd == INVALID_SOCKET || sock > *max_fd) {
|
if (*max_fd == INVALID_SOCKET || sock > *max_fd) {
|
||||||
*max_fd = sock;
|
*max_fd = sock;
|
||||||
@ -1099,7 +1119,9 @@ time_t ns_mgr_poll(struct ns_mgr *mgr, int milli) {
|
|||||||
tv.tv_sec = milli / 1000;
|
tv.tv_sec = milli / 1000;
|
||||||
tv.tv_usec = (milli % 1000) * 1000;
|
tv.tv_usec = (milli % 1000) * 1000;
|
||||||
|
|
||||||
if (select((int) max_fd + 1, &read_set, &write_set, NULL, &tv) > 0) {
|
if (select((int) max_fd + 1, &read_set, &write_set, NULL, &tv) < 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
// select() might have been waiting for a long time, reset current_time
|
// select() might have been waiting for a long time, reset current_time
|
||||||
// now to prevent last_io_time being set to the past.
|
// now to prevent last_io_time being set to the past.
|
||||||
current_time = time(NULL);
|
current_time = time(NULL);
|
||||||
@ -1250,9 +1272,12 @@ void ns_mgr_init(struct ns_mgr *s, void *user_data) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NS_DISABLE_SOCKETPAIR
|
#ifndef NS_DISABLE_SOCKETPAIR
|
||||||
do {
|
{
|
||||||
ns_socketpair2(s->ctl, SOCK_DGRAM);
|
int attempts = 0, max_attempts = NS_MAX_SOCKETPAIR_ATTEMPTS;
|
||||||
} while (s->ctl[0] == INVALID_SOCKET);
|
do {
|
||||||
|
ns_socketpair2(s->ctl, SOCK_DGRAM);
|
||||||
|
} while (s->ctl[0] == INVALID_SOCKET && ++attempts < max_attempts);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef NS_ENABLE_SSL
|
#ifdef NS_ENABLE_SSL
|
||||||
@ -1404,7 +1429,7 @@ struct dir_entry {
|
|||||||
file_stat_t st;
|
file_stat_t st;
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOTE(lsm): this enum shoulds be in sync with the config_options.
|
// NOTE(lsm): this enum should be in sync with the config_options.
|
||||||
enum {
|
enum {
|
||||||
ACCESS_CONTROL_LIST,
|
ACCESS_CONTROL_LIST,
|
||||||
#ifndef MONGOOSE_NO_FILESYSTEM
|
#ifndef MONGOOSE_NO_FILESYSTEM
|
||||||
@ -1948,13 +1973,21 @@ static void write_chunk(struct connection *conn, const char *buf, int len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t 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);
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
int ret;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
ns_vprintf(c->ns_conn, fmt, ap);
|
ret = mg_vprintf(conn, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t mg_vprintf(struct mg_connection *conn, const char *fmt, va_list ap) {
|
||||||
|
struct connection *c = MG_CONN_2_CONN(conn);
|
||||||
|
|
||||||
|
ns_vprintf(c->ns_conn, fmt, ap);
|
||||||
|
|
||||||
return c->ns_conn->send_iobuf.len;
|
return c->ns_conn->send_iobuf.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1973,6 +2006,8 @@ struct threadparam {
|
|||||||
|
|
||||||
static int wait_until_ready(sock_t sock, int for_read) {
|
static int wait_until_ready(sock_t sock, int for_read) {
|
||||||
fd_set set;
|
fd_set set;
|
||||||
|
if ( (sock == INVALID_SOCKET) || (sock >= FD_SETSIZE) )
|
||||||
|
return 0;
|
||||||
FD_ZERO(&set);
|
FD_ZERO(&set);
|
||||||
FD_SET(sock, &set);
|
FD_SET(sock, &set);
|
||||||
select(sock + 1, for_read ? &set : 0, for_read ? 0 : &set, 0, 0);
|
select(sock + 1, for_read ? &set : 0, for_read ? 0 : &set, 0, 0);
|
||||||
@ -1992,7 +2027,7 @@ static void *push_to_stdin(void *arg) {
|
|||||||
if (!WriteFile(tp->hPipe, buf + sent, n - sent, &k, 0)) stop = 1;
|
if (!WriteFile(tp->hPipe, buf + sent, n - sent, &k, 0)) stop = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DBG(("%s", "FORWARED EVERYTHING TO CGI"));
|
DBG(("%s", "FORWARDED EVERYTHING TO CGI"));
|
||||||
CloseHandle(tp->hPipe);
|
CloseHandle(tp->hPipe);
|
||||||
NS_FREE(tp);
|
NS_FREE(tp);
|
||||||
_endthread();
|
_endthread();
|
||||||
@ -2312,9 +2347,17 @@ static void open_cgi_endpoint(struct connection *conn, const char *prog) {
|
|||||||
// Try to create socketpair in a loop until success. ns_socketpair()
|
// Try to create socketpair in a loop until success. ns_socketpair()
|
||||||
// can be interrupted by a signal and fail.
|
// can be interrupted by a signal and fail.
|
||||||
// TODO(lsm): use sigaction to restart interrupted syscall
|
// TODO(lsm): use sigaction to restart interrupted syscall
|
||||||
do {
|
{
|
||||||
ns_socketpair(fds);
|
int attempts = 0, max_attempts = NS_MAX_SOCKETPAIR_ATTEMPTS;
|
||||||
} while (fds[0] == INVALID_SOCKET);
|
do {
|
||||||
|
ns_socketpair(fds);
|
||||||
|
} while (fds[0] == INVALID_SOCKET && ++attempts < max_attempts);
|
||||||
|
|
||||||
|
if (fds[0] == INVALID_SOCKET) {
|
||||||
|
closesocket(fds[0]);
|
||||||
|
send_http_error(conn, 500, "ns_socketpair() failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (start_process(conn->server->config_options[CGI_INTERPRETER],
|
if (start_process(conn->server->config_options[CGI_INTERPRETER],
|
||||||
prog, blk.buf, blk.vars, dir, fds[1]) != 0) {
|
prog, blk.buf, blk.vars, dir, fds[1]) != 0) {
|
||||||
@ -2503,7 +2546,7 @@ static size_t parse_http_message(char *buf, size_t len,
|
|||||||
|
|
||||||
buf[len - 1] = '\0';
|
buf[len - 1] = '\0';
|
||||||
|
|
||||||
// RFC says that all initial whitespaces should be ingored
|
// RFC says that all initial whitespaces should be ignored
|
||||||
while (*buf != '\0' && isspace(* (unsigned char *) buf)) {
|
while (*buf != '\0' && isspace(* (unsigned char *) buf)) {
|
||||||
buf++;
|
buf++;
|
||||||
}
|
}
|
||||||
@ -2677,7 +2720,8 @@ static int convert_uri_to_file_name(struct connection *conn, char *buf,
|
|||||||
#endif
|
#endif
|
||||||
const char *uri = conn->mg_conn.uri;
|
const char *uri = conn->mg_conn.uri;
|
||||||
const char *domain = mg_get_header(&conn->mg_conn, "Host");
|
const char *domain = mg_get_header(&conn->mg_conn, "Host");
|
||||||
size_t match_len, root_len = root == NULL ? 0 : strlen(root);
|
// Important: match_len has to be declared as int, unless rewrites break.
|
||||||
|
int match_len, root_len = root == NULL ? 0 : strlen(root);
|
||||||
|
|
||||||
// Perform virtual hosting rewrites
|
// Perform virtual hosting rewrites
|
||||||
if (rewrites != NULL && domain != NULL) {
|
if (rewrites != NULL && domain != NULL) {
|
||||||
@ -2784,16 +2828,24 @@ size_t mg_send_data(struct mg_connection *c, const void *data, int data_len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t 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;
|
va_list ap;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
ret = mg_vprintf_data(c, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t mg_vprintf_data(struct mg_connection *c, const char *fmt, va_list ap) {
|
||||||
|
struct connection *conn = MG_CONN_2_CONN(c);
|
||||||
int len;
|
int len;
|
||||||
char mem[IOBUF_SIZE], *buf = mem;
|
char mem[IOBUF_SIZE], *buf = mem;
|
||||||
|
|
||||||
terminate_headers(c);
|
terminate_headers(c);
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
len = ns_avprintf(&buf, sizeof(mem), fmt, ap);
|
len = ns_avprintf(&buf, sizeof(mem), fmt, ap);
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if (len >= 0) {
|
if (len >= 0) {
|
||||||
write_chunk((struct connection *) conn, buf, len);
|
write_chunk((struct connection *) conn, buf, len);
|
||||||
@ -2816,7 +2868,7 @@ static int is_big_endian(void) {
|
|||||||
// Copyright(c) By Steve Reid <steve@edmweb.com>
|
// Copyright(c) By Steve Reid <steve@edmweb.com>
|
||||||
#define SHA1HANDSOFF
|
#define SHA1HANDSOFF
|
||||||
#if defined(__sun)
|
#if defined(__sun)
|
||||||
//#include "solarisfixes.h"
|
#include "solarisfixes.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
union char64long16 { unsigned char c[64]; uint32_t l[16]; };
|
union char64long16 { unsigned char c[64]; uint32_t l[16]; };
|
||||||
@ -3033,7 +3085,8 @@ static size_t deliver_websocket_frame(struct connection *conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Call the handler and remove frame from the iobuf
|
// Call the handler and remove frame from the iobuf
|
||||||
if (call_user(conn, MG_REQUEST) == MG_FALSE) {
|
if (call_user(conn, MG_REQUEST) == MG_FALSE ||
|
||||||
|
(buf[0] & 0x0f) == WEBSOCKET_OPCODE_CONNECTION_CLOSE) {
|
||||||
conn->ns_conn->flags |= NSF_FINISHED_SENDING_DATA;
|
conn->ns_conn->flags |= NSF_FINISHED_SENDING_DATA;
|
||||||
}
|
}
|
||||||
iobuf_remove(&conn->ns_conn->recv_iobuf, frame_len);
|
iobuf_remove(&conn->ns_conn->recv_iobuf, frame_len);
|
||||||
@ -3314,14 +3367,17 @@ static int find_index_file(struct connection *conn, char *path,
|
|||||||
|
|
||||||
// If no index file exists, restore directory path
|
// If no index file exists, restore directory path
|
||||||
if (!found) {
|
if (!found) {
|
||||||
path[n] = '\0';
|
path[n] = '/';
|
||||||
|
path[n + 1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_range_header(const char *header, int64_t *a, int64_t *b) {
|
static int parse_range_header(const char *header, int64_t *a, int64_t *b) {
|
||||||
return sscanf(header, "bytes=%" INT64_FMT "-%" INT64_FMT, a, b);
|
// return sscanf(header, "bytes=%" INT64_FMT "-%" INT64_FMT, a, b);
|
||||||
|
// return sscanf(header, "bytes=%ld-%ld" INT64_FMT, a, b);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gmt_time_string(char *buf, size_t buf_len, time_t *t) {
|
static void gmt_time_string(char *buf, size_t buf_len, time_t *t) {
|
||||||
@ -3332,7 +3388,7 @@ static void open_file_endpoint(struct connection *conn, const char *path,
|
|||||||
file_stat_t *st, const char *extra_headers) {
|
file_stat_t *st, const char *extra_headers) {
|
||||||
char date[64], lm[64], etag[64], range[64], headers[1000];
|
char date[64], lm[64], etag[64], range[64], headers[1000];
|
||||||
const char *msg = "OK", *hdr;
|
const char *msg = "OK", *hdr;
|
||||||
time_t curtime = time(NULL);
|
time_t t, curtime = time(NULL);
|
||||||
int64_t r1, r2;
|
int64_t r1, r2;
|
||||||
struct vec mime_vec;
|
struct vec mime_vec;
|
||||||
int n;
|
int n;
|
||||||
@ -3362,7 +3418,7 @@ static void open_file_endpoint(struct connection *conn, const char *path,
|
|||||||
// Prepare Etag, Date, Last-Modified headers. Must be in UTC, according to
|
// Prepare Etag, Date, Last-Modified headers. Must be in UTC, according to
|
||||||
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3
|
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3
|
||||||
gmt_time_string(date, sizeof(date), &curtime);
|
gmt_time_string(date, sizeof(date), &curtime);
|
||||||
time_t t = st->st_mtime;
|
t = st->st_mtime; // store in local variable for NDK compile
|
||||||
gmt_time_string(lm, sizeof(lm), &t);
|
gmt_time_string(lm, sizeof(lm), &t);
|
||||||
construct_etag(etag, sizeof(etag), st);
|
construct_etag(etag, sizeof(etag), st);
|
||||||
|
|
||||||
@ -3512,11 +3568,11 @@ static int scan_directory(struct connection *conn, const char *dir,
|
|||||||
}
|
}
|
||||||
mg_snprintf(path, sizeof(path), "%s%c%s", dir, '/', dp->d_name);
|
mg_snprintf(path, sizeof(path), "%s%c%s", dir, '/', dp->d_name);
|
||||||
|
|
||||||
// Resize the array if nesessary
|
// Resize the array if necessary
|
||||||
if (arr_ind >= arr_size) {
|
if (arr_ind >= arr_size) {
|
||||||
if ((p = (struct dir_entry *)
|
if ((p = (struct dir_entry *)
|
||||||
NS_REALLOC(*arr, (inc + arr_size) * sizeof(**arr))) != NULL) {
|
NS_REALLOC(*arr, (inc + arr_size) * sizeof(**arr))) != NULL) {
|
||||||
// Memset new chunk to zero, otherwize st_mtime will have garbage which
|
// Memset new chunk to zero, otherwise st_mtime will have garbage which
|
||||||
// can make strftime() segfault, see
|
// can make strftime() segfault, see
|
||||||
// http://code.google.com/p/mongoose/issues/detail?id=79
|
// http://code.google.com/p/mongoose/issues/detail?id=79
|
||||||
memset(p + arr_size, 0, sizeof(**arr) * inc);
|
memset(p + arr_size, 0, sizeof(**arr) * inc);
|
||||||
@ -3567,6 +3623,7 @@ static void print_dir_entry(const struct dir_entry *de) {
|
|||||||
int64_t fsize = de->st.st_size;
|
int64_t fsize = de->st.st_size;
|
||||||
int is_dir = S_ISDIR(de->st.st_mode);
|
int is_dir = S_ISDIR(de->st.st_mode);
|
||||||
const char *slash = is_dir ? "/" : "";
|
const char *slash = is_dir ? "/" : "";
|
||||||
|
time_t t;
|
||||||
|
|
||||||
if (is_dir) {
|
if (is_dir) {
|
||||||
mg_snprintf(size, sizeof(size), "%s", "[DIRECTORY]");
|
mg_snprintf(size, sizeof(size), "%s", "[DIRECTORY]");
|
||||||
@ -3583,7 +3640,7 @@ static void print_dir_entry(const struct dir_entry *de) {
|
|||||||
mg_snprintf(size, sizeof(size), "%.1fG", (double) fsize / 1073741824);
|
mg_snprintf(size, sizeof(size), "%.1fG", (double) fsize / 1073741824);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
time_t t = de->st.st_mtime;
|
t = de->st.st_mtime; // store in local variable for NDK compile
|
||||||
strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", localtime(&t));
|
strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", localtime(&t));
|
||||||
mg_url_encode(de->file_name, strlen(de->file_name), href, sizeof(href));
|
mg_url_encode(de->file_name, strlen(de->file_name), href, sizeof(href));
|
||||||
mg_printf_data(&de->conn->mg_conn,
|
mg_printf_data(&de->conn->mg_conn,
|
||||||
@ -3639,12 +3696,14 @@ static void send_directory_listing(struct connection *conn, const char *dir) {
|
|||||||
sort_direction, sort_direction, sort_direction);
|
sort_direction, sort_direction, sort_direction);
|
||||||
|
|
||||||
num_entries = scan_directory(conn, dir, &arr);
|
num_entries = scan_directory(conn, dir, &arr);
|
||||||
qsort(arr, num_entries, sizeof(arr[0]), compare_dir_entries);
|
if (arr) {
|
||||||
for (i = 0; i < num_entries; i++) {
|
qsort(arr, num_entries, sizeof(arr[0]), compare_dir_entries);
|
||||||
print_dir_entry(&arr[i]);
|
for (i = 0; i < num_entries; i++) {
|
||||||
NS_FREE(arr[i].file_name);
|
print_dir_entry(&arr[i]);
|
||||||
|
NS_FREE(arr[i].file_name);
|
||||||
|
}
|
||||||
|
NS_FREE(arr);
|
||||||
}
|
}
|
||||||
NS_FREE(arr);
|
|
||||||
|
|
||||||
write_terminating_chunk(conn);
|
write_terminating_chunk(conn);
|
||||||
close_local_endpoint(conn);
|
close_local_endpoint(conn);
|
||||||
@ -3655,7 +3714,7 @@ static void send_directory_listing(struct connection *conn, const char *dir) {
|
|||||||
static void print_props(struct connection *conn, const char *uri,
|
static void print_props(struct connection *conn, const char *uri,
|
||||||
file_stat_t *stp) {
|
file_stat_t *stp) {
|
||||||
char mtime[64];
|
char mtime[64];
|
||||||
time_t t = stp->st_mtime;
|
time_t t = stp->st_mtime; // store in local variable for NDK compile
|
||||||
gmt_time_string(mtime, sizeof(mtime), &t);
|
gmt_time_string(mtime, sizeof(mtime), &t);
|
||||||
mg_printf(&conn->mg_conn,
|
mg_printf(&conn->mg_conn,
|
||||||
"<d:response>"
|
"<d:response>"
|
||||||
@ -3861,11 +3920,16 @@ void mg_send_digest_auth_request(struct mg_connection *c) {
|
|||||||
c->status_code = 401;
|
c->status_code = 401;
|
||||||
mg_printf(c,
|
mg_printf(c,
|
||||||
"HTTP/1.1 401 Unauthorized\r\n"
|
"HTTP/1.1 401 Unauthorized\r\n"
|
||||||
|
"Content-Length: 0\r\n"
|
||||||
"WWW-Authenticate: Digest qop=\"auth\", "
|
"WWW-Authenticate: Digest qop=\"auth\", "
|
||||||
"realm=\"%s\", nonce=\"%lu\"\r\n\r\n",
|
"realm=\"%s\", nonce=\"%lu\"\r\n\r\n",
|
||||||
conn->server->config_options[AUTH_DOMAIN],
|
conn->server->config_options[AUTH_DOMAIN],
|
||||||
(unsigned long) time(NULL));
|
(unsigned long) time(NULL));
|
||||||
close_local_endpoint(conn);
|
if (conn->cl > 0) {
|
||||||
|
conn->ns_conn->flags |= NSF_DISCARD;
|
||||||
|
} else {
|
||||||
|
close_local_endpoint(conn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the global passwords file, if specified by auth_gpass option,
|
// Use the global passwords file, if specified by auth_gpass option,
|
||||||
@ -4285,7 +4349,7 @@ static void do_ssi_include(struct mg_connection *conn, const char *ssi,
|
|||||||
mg_snprintf(path, sizeof(path), "%s", file_name);
|
mg_snprintf(path, sizeof(path), "%s", file_name);
|
||||||
} else if (sscanf(tag, " file=\"%[^\"]\"", file_name) == 1 ||
|
} else if (sscanf(tag, " file=\"%[^\"]\"", file_name) == 1 ||
|
||||||
sscanf(tag, " \"%[^\"]\"", file_name) == 1) {
|
sscanf(tag, " \"%[^\"]\"", file_name) == 1) {
|
||||||
// File name is relative to the currect document
|
// File name is relative to the current document
|
||||||
mg_snprintf(path, sizeof(path), "%s", ssi);
|
mg_snprintf(path, sizeof(path), "%s", ssi);
|
||||||
if ((p = strrchr(path, '/')) != NULL) {
|
if ((p = strrchr(path, '/')) != NULL) {
|
||||||
p[1] = '\0';
|
p[1] = '\0';
|
||||||
@ -4697,6 +4761,10 @@ static void try_parse(struct connection *conn) {
|
|||||||
// iobuf could be reallocated, and pointers in parsed request could
|
// iobuf could be reallocated, and pointers in parsed request could
|
||||||
// become invalid.
|
// become invalid.
|
||||||
conn->request = (char *) NS_MALLOC(conn->request_len);
|
conn->request = (char *) NS_MALLOC(conn->request_len);
|
||||||
|
if (conn->request == NULL) {
|
||||||
|
conn->ns_conn->flags |= NSF_CLOSE_IMMEDIATELY;
|
||||||
|
return;
|
||||||
|
}
|
||||||
memcpy(conn->request, io->buf, conn->request_len);
|
memcpy(conn->request, io->buf, conn->request_len);
|
||||||
//DBG(("%p [%.*s]", conn, conn->request_len, conn->request));
|
//DBG(("%p [%.*s]", conn, conn->request_len, conn->request));
|
||||||
iobuf_remove(io, conn->request_len);
|
iobuf_remove(io, conn->request_len);
|
||||||
@ -4734,6 +4802,19 @@ static void on_recv_data(struct connection *conn) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (conn->ns_conn->flags & NSF_DISCARD) {
|
||||||
|
size_t n = conn->cl;
|
||||||
|
if (n > io->len) {
|
||||||
|
n = io->len;
|
||||||
|
}
|
||||||
|
iobuf_remove(io, n);
|
||||||
|
conn->cl -= n;
|
||||||
|
if (conn->cl == 0) {
|
||||||
|
close_local_endpoint(conn);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try_parse(conn);
|
try_parse(conn);
|
||||||
DBG(("%p %d %lu %d", conn, conn->request_len, (unsigned long)io->len,
|
DBG(("%p %d %lu %d", conn, conn->request_len, (unsigned long)io->len,
|
||||||
conn->ns_conn->flags));
|
conn->ns_conn->flags));
|
||||||
@ -4913,7 +4994,7 @@ static void close_local_endpoint(struct connection *conn) {
|
|||||||
|
|
||||||
conn->endpoint_type = EP_NONE;
|
conn->endpoint_type = EP_NONE;
|
||||||
conn->cl = conn->num_bytes_recv = conn->request_len = 0;
|
conn->cl = conn->num_bytes_recv = conn->request_len = 0;
|
||||||
conn->ns_conn->flags &= ~(NSF_FINISHED_SENDING_DATA |
|
conn->ns_conn->flags &= ~(NSF_FINISHED_SENDING_DATA | NSF_DISCARD |
|
||||||
NSF_BUFFER_BUT_DONT_SEND | NSF_CLOSE_IMMEDIATELY |
|
NSF_BUFFER_BUT_DONT_SEND | NSF_CLOSE_IMMEDIATELY |
|
||||||
MG_HEADERS_SENT | MG_USING_CHUNKED_API);
|
MG_HEADERS_SENT | MG_USING_CHUNKED_API);
|
||||||
|
|
||||||
@ -4921,7 +5002,7 @@ static void close_local_endpoint(struct connection *conn) {
|
|||||||
// (IP addresses & ports, server_param) must survive. Nullify the rest.
|
// (IP addresses & ports, server_param) must survive. Nullify the rest.
|
||||||
c->request_method = c->uri = c->http_version = c->query_string = NULL;
|
c->request_method = c->uri = c->http_version = c->query_string = NULL;
|
||||||
c->num_headers = c->status_code = c->is_websocket = c->content_len = 0;
|
c->num_headers = c->status_code = c->is_websocket = c->content_len = 0;
|
||||||
c->connection_param = c->callback_param = NULL;
|
c->callback_param = NULL;
|
||||||
|
|
||||||
if (keep_alive) {
|
if (keep_alive) {
|
||||||
on_recv_data(conn); // Can call us recursively if pipelining is used
|
on_recv_data(conn); // Can call us recursively if pipelining is used
|
||||||
@ -4983,20 +5064,17 @@ struct mg_connection *mg_next(struct mg_server *s, struct mg_connection *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int get_var(const char *data, size_t data_len, const char *name,
|
static int get_var(const char *data, size_t data_len, const char *name,
|
||||||
char *dst, size_t dst_len) {
|
char *dst, size_t dst_len, int n) {
|
||||||
const char *p, *e, *s;
|
const char *p, *e = data + data_len, *s;
|
||||||
size_t name_len;
|
size_t name_len;
|
||||||
int len;
|
int i = 0, len = -1;
|
||||||
|
|
||||||
if (dst == NULL || dst_len == 0) {
|
if (dst == NULL || dst_len == 0) {
|
||||||
len = -2;
|
len = -2;
|
||||||
} else if (data == NULL || name == NULL || data_len == 0) {
|
} else if (data == NULL || name == NULL || data_len == 0) {
|
||||||
len = -1;
|
|
||||||
dst[0] = '\0';
|
dst[0] = '\0';
|
||||||
} else {
|
} else {
|
||||||
name_len = strlen(name);
|
name_len = strlen(name);
|
||||||
e = data + data_len;
|
|
||||||
len = -1;
|
|
||||||
dst[0] = '\0';
|
dst[0] = '\0';
|
||||||
|
|
||||||
// data is "var1=val1&var2=val2...". Find variable first
|
// data is "var1=val1&var2=val2...". Find variable first
|
||||||
@ -5004,6 +5082,8 @@ static int get_var(const char *data, size_t data_len, const char *name,
|
|||||||
if ((p == data || p[-1] == '&') && p[name_len] == '=' &&
|
if ((p == data || p[-1] == '&') && p[name_len] == '=' &&
|
||||||
!mg_strncasecmp(name, p, name_len)) {
|
!mg_strncasecmp(name, p, name_len)) {
|
||||||
|
|
||||||
|
if (n != i++) continue;
|
||||||
|
|
||||||
// Point p to variable value
|
// Point p to variable value
|
||||||
p += name_len + 1;
|
p += name_len + 1;
|
||||||
|
|
||||||
@ -5029,16 +5109,21 @@ static int get_var(const char *data, size_t data_len, const char *name,
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_get_var(const struct mg_connection *conn, const char *name,
|
int mg_get_var_n(const struct mg_connection *conn, const char *name,
|
||||||
char *dst, size_t dst_len) {
|
char *dst, size_t dst_len, int n) {
|
||||||
int len = get_var(conn->query_string, conn->query_string == NULL ? 0 :
|
int len = get_var(conn->query_string, conn->query_string == NULL ? 0 :
|
||||||
strlen(conn->query_string), name, dst, dst_len);
|
strlen(conn->query_string), name, dst, dst_len, n);
|
||||||
if (len < 0) {
|
if (len == -1) {
|
||||||
len = get_var(conn->content, conn->content_len, name, dst, dst_len);
|
len = get_var(conn->content, conn->content_len, name, dst, dst_len, n);
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mg_get_var(const struct mg_connection *conn, const char *name,
|
||||||
|
char *dst, size_t dst_len) {
|
||||||
|
return mg_get_var_n(conn, name, dst, dst_len, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static int get_line_len(const char *buf, int buf_len) {
|
static int get_line_len(const char *buf, int buf_len) {
|
||||||
int len = 0;
|
int len = 0;
|
||||||
while (len < buf_len && buf[len] != '\n') len++;
|
while (len < buf_len && buf[len] != '\n') len++;
|
||||||
@ -5095,6 +5180,14 @@ void mg_copy_listeners(struct mg_server *s, struct mg_server *to) {
|
|||||||
if ((c->flags & NSF_LISTENING) &&
|
if ((c->flags & NSF_LISTENING) &&
|
||||||
(tmp = (struct ns_connection *) NS_MALLOC(sizeof(*tmp))) != NULL) {
|
(tmp = (struct ns_connection *) NS_MALLOC(sizeof(*tmp))) != NULL) {
|
||||||
memcpy(tmp, c, sizeof(*tmp));
|
memcpy(tmp, c, sizeof(*tmp));
|
||||||
|
|
||||||
|
#if defined(NS_ENABLE_SSL) && defined(HEADER_SSL_H)
|
||||||
|
/* OpenSSL only. See https://github.com/cesanta/mongoose/issues/441 */
|
||||||
|
if (tmp->ssl_ctx != NULL) {
|
||||||
|
tmp->ssl_ctx->references++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
tmp->mgr = &to->ns_mgr;
|
tmp->mgr = &to->ns_mgr;
|
||||||
ns_add_conn(tmp->mgr, tmp);
|
ns_add_conn(tmp->mgr, tmp);
|
||||||
}
|
}
|
||||||
@ -5153,6 +5246,7 @@ const char *mg_set_option(struct mg_server *server, const char *name,
|
|||||||
char buf[500] = "";
|
char buf[500] = "";
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
struct vec vec;
|
struct vec vec;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ports can be specified as 0, meaning that OS has to choose any
|
* Ports can be specified as 0, meaning that OS has to choose any
|
||||||
* free port that is available. In order to pass chosen port number to
|
* free port that is available. In order to pass chosen port number to
|
||||||
@ -5247,31 +5341,32 @@ static void process_udp(struct ns_connection *nc) {
|
|||||||
//ns_printf(nc, "%s", "HTTP/1.0 200 OK\r\n\r\n");
|
//ns_printf(nc, "%s", "HTTP/1.0 200 OK\r\n\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MONGOOSE_SEND_NS_EVENTS
|
||||||
|
static void send_ns_event(struct ns_connection *nc, int ev, void *p) {
|
||||||
|
struct connection *conn = (struct connection *) nc->user_data;
|
||||||
|
if (conn != NULL) {
|
||||||
|
void *param[2] = { nc, p };
|
||||||
|
conn->mg_conn.callback_param = param;
|
||||||
|
call_user(conn, (enum mg_event) ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void send_ns_event(struct ns_connection *nc, int ev, void *p) {
|
||||||
|
(void) nc; (void) p; (void) ev;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void mg_ev_handler(struct ns_connection *nc, int ev, void *p) {
|
static void mg_ev_handler(struct ns_connection *nc, int ev, void *p) {
|
||||||
struct connection *conn = (struct connection *) nc->user_data;
|
struct connection *conn = (struct connection *) nc->user_data;
|
||||||
|
|
||||||
// Send NS event to the handler. Note that call_user won't send an event
|
// Send NS event to the handler. Note that call_user won't send an event
|
||||||
// if conn == NULL. Therefore, repeat this for NS_ACCEPT event as well.
|
// if conn == NULL. Therefore, repeat this for NS_ACCEPT event as well.
|
||||||
#ifdef MONGOOSE_SEND_NS_EVENTS
|
send_ns_event(nc, ev, p);
|
||||||
{
|
|
||||||
struct connection *conn = (struct connection *) nc->user_data;
|
|
||||||
void *param[2] = { nc, p };
|
|
||||||
if (conn != NULL) conn->mg_conn.callback_param = param;
|
|
||||||
call_user(conn, (enum mg_event) ev);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch (ev) {
|
switch (ev) {
|
||||||
case NS_ACCEPT:
|
case NS_ACCEPT:
|
||||||
on_accept(nc, (union socket_address *) p);
|
on_accept(nc, (union socket_address *) p);
|
||||||
#ifdef MONGOOSE_SEND_NS_EVENTS
|
send_ns_event(nc, ev, p);
|
||||||
{
|
|
||||||
struct connection *conn = (struct connection *) nc->user_data;
|
|
||||||
void *param[2] = { nc, p };
|
|
||||||
if (conn != NULL) conn->mg_conn.callback_param = param;
|
|
||||||
call_user(conn, (enum mg_event) ev);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NS_CONNECT:
|
case NS_CONNECT:
|
||||||
@ -5343,6 +5438,11 @@ static void mg_ev_handler(struct ns_connection *nc, int ev, void *p) {
|
|||||||
write_terminating_chunk(conn);
|
write_terminating_chunk(conn);
|
||||||
}
|
}
|
||||||
close_local_endpoint(conn);
|
close_local_endpoint(conn);
|
||||||
|
/*
|
||||||
|
* MG_POLL callback returned MG_TRUE,
|
||||||
|
* i.e. data is sent, set corresponding flag
|
||||||
|
*/
|
||||||
|
conn->ns_conn->flags |= NSF_FINISHED_SENDING_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conn->endpoint_type == EP_FILE) {
|
if (conn->endpoint_type == EP_FILE) {
|
||||||
|
7
3rdparty/mongoose/mongoose.h
vendored
7
3rdparty/mongoose/mongoose.h
vendored
@ -60,7 +60,8 @@ struct mg_connection {
|
|||||||
struct mg_server; // Opaque structure describing server instance
|
struct mg_server; // Opaque structure describing server instance
|
||||||
enum mg_result { MG_FALSE, MG_TRUE, MG_MORE };
|
enum mg_result { MG_FALSE, MG_TRUE, MG_MORE };
|
||||||
enum mg_event {
|
enum mg_event {
|
||||||
MG_POLL = 100, // Callback return value is ignored
|
MG_POLL = 100, // If callback returns MG_TRUE connection closes
|
||||||
|
// after all of data is sent
|
||||||
MG_CONNECT, // If callback returns MG_FALSE, connect fails
|
MG_CONNECT, // If callback returns MG_FALSE, connect fails
|
||||||
MG_AUTH, // If callback returns MG_FALSE, authentication fails
|
MG_AUTH, // If callback returns MG_FALSE, authentication fails
|
||||||
MG_REQUEST, // If callback returns MG_FALSE, Mongoose continues with req
|
MG_REQUEST, // If callback returns MG_FALSE, Mongoose continues with req
|
||||||
@ -103,8 +104,10 @@ 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_header(struct mg_connection *, const char *name, const char *val);
|
||||||
size_t mg_send_data(struct mg_connection *, const void *data, int data_len);
|
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_printf_data(struct mg_connection *, const char *format, ...);
|
||||||
|
size_t mg_vprintf_data(struct mg_connection *, const char *format, va_list ap);
|
||||||
size_t mg_write(struct mg_connection *, const void *buf, size_t len);
|
size_t mg_write(struct mg_connection *, const void *buf, size_t len);
|
||||||
size_t mg_printf(struct mg_connection *conn, const char *fmt, ...);
|
size_t mg_printf(struct mg_connection *conn, const char *fmt, ...);
|
||||||
|
size_t mg_vprintf(struct mg_connection *conn, const char *fmt, va_list ap);
|
||||||
|
|
||||||
size_t mg_websocket_write(struct mg_connection *, int opcode,
|
size_t mg_websocket_write(struct mg_connection *, int opcode,
|
||||||
const char *data, size_t data_len);
|
const char *data, size_t data_len);
|
||||||
@ -118,6 +121,8 @@ 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);
|
const char *mg_get_mime_type(const char *name, const char *default_mime_type);
|
||||||
int mg_get_var(const struct mg_connection *conn, const char *var_name,
|
int mg_get_var(const struct mg_connection *conn, const char *var_name,
|
||||||
char *buf, size_t buf_len);
|
char *buf, size_t buf_len);
|
||||||
|
int mg_get_var_n(const struct mg_connection *conn, const char *var_name,
|
||||||
|
char *buf, size_t buf_len, int n);
|
||||||
int mg_parse_header(const char *hdr, const char *var_name, char *buf, size_t);
|
int mg_parse_header(const char *hdr, const char *var_name, char *buf, size_t);
|
||||||
int mg_parse_multipart(const char *buf, int buf_len,
|
int mg_parse_multipart(const char *buf, int buf_len,
|
||||||
char *var_name, int var_name_len,
|
char *var_name, int var_name_len,
|
||||||
|
30
3rdparty/mongoose/test/unit_test.c
vendored
30
3rdparty/mongoose/test/unit_test.c
vendored
@ -169,6 +169,7 @@ static const char *test_match_prefix(void) {
|
|||||||
ASSERT(mg_match_prefix("/api", 4, "/api") == 4);
|
ASSERT(mg_match_prefix("/api", 4, "/api") == 4);
|
||||||
ASSERT(mg_match_prefix("/a/", 3, "/a/b/c") == 3);
|
ASSERT(mg_match_prefix("/a/", 3, "/a/b/c") == 3);
|
||||||
ASSERT(mg_match_prefix("/a/", 3, "/ab/c") == -1);
|
ASSERT(mg_match_prefix("/a/", 3, "/ab/c") == -1);
|
||||||
|
ASSERT(mg_match_prefix("/blog/", 6, "/") == -1);
|
||||||
ASSERT(mg_match_prefix("/*/", 3, "/ab/c") == 4);
|
ASSERT(mg_match_prefix("/*/", 3, "/ab/c") == 4);
|
||||||
ASSERT(mg_match_prefix("**", 2, "/a/b/c") == 6);
|
ASSERT(mg_match_prefix("**", 2, "/a/b/c") == 6);
|
||||||
ASSERT(mg_match_prefix("/*", 2, "/a/b/c") == 2);
|
ASSERT(mg_match_prefix("/*", 2, "/a/b/c") == 2);
|
||||||
@ -223,29 +224,28 @@ static const char *test_remove_double_dots() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const char *test_get_var(void) {
|
static const char *test_get_var(void) {
|
||||||
static const char *post[] = {
|
static const char *data = "a=1&&b=2&d&=&c=3%20&e=&k=aa&a=23";
|
||||||
"a=1&&b=2&d&=&c=3%20&e=",
|
static const char *data2 = "q=&st=2012%2F11%2F13+17%3A05&et=&team_id=";
|
||||||
"q=&st=2012%2F11%2F13+17%3A05&et=&team_id=",
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
char buf[20];
|
char buf[20];
|
||||||
|
|
||||||
ASSERT(get_var(post[0], strlen(post[0]), "a", buf, sizeof(buf)) == 1);
|
ASSERT(get_var(data, strlen(data), "a", buf, sizeof(buf), 0) == 1);
|
||||||
ASSERT(buf[0] == '1' && buf[1] == '\0');
|
ASSERT(buf[0] == '1' && buf[1] == '\0');
|
||||||
ASSERT(get_var(post[0], strlen(post[0]), "b", buf, sizeof(buf)) == 1);
|
ASSERT(get_var(data, strlen(data), "a", buf, sizeof(buf), 1) == 2);
|
||||||
|
ASSERT(strcmp(buf, "23") == 0);
|
||||||
|
ASSERT(get_var(data, strlen(data), "b", buf, sizeof(buf), 0) == 1);
|
||||||
ASSERT(buf[0] == '2' && buf[1] == '\0');
|
ASSERT(buf[0] == '2' && buf[1] == '\0');
|
||||||
ASSERT(get_var(post[0], strlen(post[0]), "c", buf, sizeof(buf)) == 2);
|
ASSERT(get_var(data, strlen(data), "c", buf, sizeof(buf), 0) == 2);
|
||||||
ASSERT(buf[0] == '3' && buf[1] == ' ' && buf[2] == '\0');
|
ASSERT(buf[0] == '3' && buf[1] == ' ' && buf[2] == '\0');
|
||||||
ASSERT(get_var(post[0], strlen(post[0]), "e", buf, sizeof(buf)) == 0);
|
ASSERT(get_var(data, strlen(data), "e", buf, sizeof(buf), 0) == 0);
|
||||||
ASSERT(buf[0] == '\0');
|
ASSERT(buf[0] == '\0');
|
||||||
|
|
||||||
ASSERT(get_var(post[0], strlen(post[0]), "d", buf, sizeof(buf)) == -1);
|
ASSERT(get_var(data, strlen(data), "d", buf, sizeof(buf), 0) == -1);
|
||||||
ASSERT(get_var(post[0], strlen(post[0]), "c", buf, 2) == -2);
|
ASSERT(get_var(data, strlen(data), "c", buf, 2, 0) == -2);
|
||||||
|
|
||||||
ASSERT(get_var(post[0], strlen(post[0]), "x", NULL, 10) == -2);
|
ASSERT(get_var(data, strlen(data), "x", NULL, 10, 0) == -2);
|
||||||
ASSERT(get_var(post[0], strlen(post[0]), "x", buf, 0) == -2);
|
ASSERT(get_var(data, strlen(data), "x", buf, 0, 0) == -2);
|
||||||
ASSERT(get_var(post[1], strlen(post[1]), "st", buf, 16) == -2);
|
ASSERT(get_var(data2, strlen(data2), "st", buf, 16, 0) == -2);
|
||||||
ASSERT(get_var(post[1], strlen(post[1]), "st", buf, 17) == 16);
|
ASSERT(get_var(data2, strlen(data2), "st", buf, 17, 0) == 16);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user