mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-29 12:41:03 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
409c12a851 | ||
|
|
bcdcbf20ee | ||
|
|
8fc5b5a55f | ||
|
|
faeedb2930 | ||
|
|
c8e8f94ffe | ||
|
|
22aeb6111b | ||
|
|
2d1d2e6534 | ||
|
|
05c88a98fc | ||
|
|
5224afb946 | ||
|
|
3bd79c7cd5 | ||
|
|
c52e0744cb | ||
|
|
6c09c303d0 | ||
|
|
b6fde06990 | ||
|
|
af892c9726 | ||
|
|
df7ad13680 | ||
|
|
057c2d4b42 | ||
|
|
6c9b43bcf5 | ||
|
|
a91438acae | ||
|
|
a6fa51dbc2 | ||
|
|
6ceac6c84c | ||
|
|
288efe3c23 | ||
|
|
5207545a8b | ||
|
|
716d524f9b | ||
|
|
a434bab767 | ||
|
|
e9633a8d2d | ||
|
|
c7b6a6f0ea | ||
|
|
6cdb9f7ed3 | ||
|
|
4502dd0c86 | ||
|
|
95055f6048 | ||
|
|
2c36532ec4 | ||
|
|
f2b0b9c737 | ||
|
|
b3866439a0 | ||
|
|
4f2205a667 | ||
|
|
6cec1d36a8 | ||
|
|
4238370ae1 | ||
|
|
b4924b715e | ||
|
|
7a0385dcac | ||
|
|
44a146faf6 | ||
|
|
53a55da7bc | ||
|
|
bf44277764 | ||
|
|
a2e1da6e30 | ||
|
|
bef3f85ba8 | ||
|
|
eb72a63cca | ||
|
|
f19bbc73cc | ||
|
|
25326b3b12 | ||
|
|
10ee430bfd | ||
|
|
10d0bfdab4 | ||
|
|
6b6637c337 | ||
|
|
878acca213 | ||
|
|
ace9285966 | ||
|
|
cdc167b0cc | ||
|
|
a0dd396b95 | ||
|
|
8082501b9c | ||
|
|
e4ad3010be | ||
|
|
03a82ef848 | ||
|
|
9459d69dcc | ||
|
|
b28662362d | ||
|
|
66450bf3d1 | ||
|
|
478ca05e7a | ||
|
|
8cad0a72f9 | ||
|
|
31178f4d48 | ||
|
|
7a5485493e | ||
|
|
d3cbb160f5 | ||
|
|
45ff2c2c19 | ||
|
|
c3db7b141b | ||
|
|
0a0ea36ace | ||
|
|
72ed954721 | ||
|
|
33e035273a | ||
|
|
223f36c130 | ||
|
|
4c0bc5bd03 | ||
|
|
808a5f6f53 | ||
|
|
404e635665 | ||
|
|
9d7a60a63f | ||
|
|
ba9c74187b | ||
|
|
e9d4847cbb | ||
|
|
ea76de07ee | ||
|
|
5a8c468ff7 | ||
|
|
5b143a6237 | ||
|
|
d244a7fdfd | ||
|
|
300a27de99 | ||
|
|
04a15a0c10 | ||
|
|
f0f6ae05aa | ||
|
|
8a7d535d92 | ||
|
|
e7ac6024de | ||
|
|
9981b99ac8 | ||
|
|
87a36c0c30 | ||
|
|
f2b13761c0 | ||
|
|
9786478a31 | ||
|
|
7d236d7f33 | ||
|
|
e098a7292d | ||
|
|
632b3a38a9 |
No files matched your search
-20
@@ -1,20 +0,0 @@
|
|||||||
language: cpp
|
|
||||||
|
|
||||||
env:
|
|
||||||
matrix:
|
|
||||||
- MONGOOSE_NO_SOCKETPAIR
|
|
||||||
- MONGOOSE_NO_FILESYSTEM
|
|
||||||
- MONGOOSE_NO_AUTH
|
|
||||||
- MONGOOSE_NO_DAV
|
|
||||||
- MONGOOSE_NO_DIRECTORY_LISTING
|
|
||||||
- MONGOOSE_NO_LOGGING
|
|
||||||
- MONGOOSE_NO_SSI
|
|
||||||
- MONGOOSE_NO_DL
|
|
||||||
- MONGOOSE_NO_WEBSOCKET
|
|
||||||
|
|
||||||
compiler:
|
|
||||||
- gcc
|
|
||||||
- clang
|
|
||||||
|
|
||||||
script:
|
|
||||||
- cd test && make
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
|
Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
|
||||||
Copyright (c) 2013 Cesanta Software Limited
|
Copyright (c) 2013-2015 Cesanta Software Limited
|
||||||
All rights reserved
|
All rights reserved
|
||||||
|
|
||||||
This code is dual-licensed: you can redistribute it and/or modify
|
This code is dual-licensed: you can redistribute it and/or modify
|
||||||
|
|||||||
@@ -11,9 +11,11 @@ manufacturing, finance, research, automotive, gaming, IT.
|
|||||||
|
|
||||||
|
|
||||||
* [Mailing list](http://groups.google.com/group/mongoose-users)
|
* [Mailing list](http://groups.google.com/group/mongoose-users)
|
||||||
* [Downloads](http://cesanta.com/mongoose.shtml)
|
* [Downloads](http://cesanta.com/products.shtml)
|
||||||
* [Documentation](http://cesanta.com/docs.shtml)
|
* [Documentation](http://cesanta.com/docs.shtml)
|
||||||
|
|
||||||
|
Check out Fossa - our [embedded multi-protocol library](https://github.com/cesanta/fossa) with TCP,UDP,HTTP,Websocket,MQTT,DNS support, designed for Internet Of Things!
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
|
|
||||||
- Works on Windows, Mac, UNIX/Linux, iPhone, Android eCos, QNX
|
- Works on Windows, Mac, UNIX/Linux, iPhone, Android eCos, QNX
|
||||||
@@ -43,24 +45,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
|
||||||
|
|
||||||
@@ -70,17 +61,16 @@ 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
|
||||||
- [SSL Wrapper](https://github.com/cesanta/ssl_wrapper) - application to
|
- [SSL Wrapper](https://github.com/cesanta/ssl_wrapper) - application to
|
||||||
secure network communications
|
secure network communications
|
||||||
- [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
|
||||||
- [Net Skeleton](https://github.com/cesanta/net_skeleton) - framework for
|
- [V7](https://github.com/cesanta/v7) - Embedded JavaScript engine
|
||||||
building network applications
|
|
||||||
- [SLDR](https://github.com/cesanta/sldr) - Super Light DNS Resolver
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
LOCAL_PATH := $(call my-dir)/../..
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
|
|
||||||
# To build with lua support, uncomment two lines below:
|
|
||||||
#LUA_SOURCES := build/lua_5.2.1.c build/sqlite3.c build/lsqlite3.c
|
|
||||||
#LUA_FLAGS := -I$(LOCAL_PATH)/build -DTHREADSAFE=1 -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DUSE_LUA -DUSE_LUA_SQLITE3 -DLUA_COMPAT_ALL -D"getlocaledecpoint() ='.'"
|
|
||||||
|
|
||||||
LOCAL_CFLAGS := -std=c99 -O2 -W -Wall -pthread -pipe $(LUA_FLAGS) $(COPT)
|
|
||||||
LOCAL_MODULE := mongoose
|
|
||||||
LOCAL_SRC_FILES := examples/server.c mongoose.c $(LUA_SOURCES)
|
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
|
||||||
+7
-4
@@ -1,6 +1,6 @@
|
|||||||
# Mongoose API Reference
|
# Mongoose API Reference
|
||||||
|
|
||||||
struct mg_server *mg_create_server(void *server_param);
|
struct mg_server *mg_create_server(void *server_param, mg_handler_t handler);
|
||||||
|
|
||||||
Creates web server instance. Returns opaque instance pointer, or NULL if
|
Creates web server instance. Returns opaque instance pointer, or NULL if
|
||||||
there is not enough memory. `server_param`: Could be any pointer, or NULL.
|
there is not enough memory. `server_param`: Could be any pointer, or NULL.
|
||||||
@@ -183,11 +183,14 @@ points to a directory, Mongoose will show directory listing. If this function
|
|||||||
is used, no calls to `mg_send*` or `mg_printf*` functions must be made, and
|
is used, no calls to `mg_send*` or `mg_printf*` functions must be made, and
|
||||||
event handler must return `MG_MORE`.
|
event handler must return `MG_MORE`.
|
||||||
|
|
||||||
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);
|
const char *data, size_t data_len);
|
||||||
|
size_t mg_websocket_printf(struct mg_connection* conn, int opcode,
|
||||||
|
const char *fmt, ...);
|
||||||
|
|
||||||
Similar to `mg_write()`, but wraps the data into a websocket frame with a
|
|
||||||
given websocket `opcode`.
|
Similar to `mg_write()` and `mg_printf()`, but wraps the data into a
|
||||||
|
websocket frame with a given websocket `opcode`.
|
||||||
|
|
||||||
const char *mg_get_header(const struct mg_connection *, const char *name);
|
const char *mg_get_header(const struct mg_connection *, const char *name);
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Note : You dont need root access to run mongoose on Android.
|
|||||||
|
|
||||||
- Clone Mongoose Git repo
|
- Clone Mongoose Git repo
|
||||||
- Download the Android NDK from [http://developer.android.com/tools/sdk/ndk/index.html](http://developer.android.com/tools/sdk/ndk/index.html)
|
- Download the Android NDK from [http://developer.android.com/tools/sdk/ndk/index.html](http://developer.android.com/tools/sdk/ndk/index.html)
|
||||||
- Run `/path-to-ndk/ndk-build -C /path-to-mongoose/examples`
|
- Run `/path-to-ndk/ndk-build -C /path/to/mongoose`
|
||||||
That should generate mongoose/lib/armeabi/mongoose
|
That should generate mongoose/lib/armeabi/mongoose
|
||||||
- Using the adb tool (you need to have Android SDK installed for that),
|
- Using the adb tool (you need to have Android SDK installed for that),
|
||||||
push the generated mongoose binary to `/data/local` folder on device.
|
push the generated mongoose binary to `/data/local` folder on device.
|
||||||
|
|||||||
+3
-1
@@ -149,8 +149,10 @@ all Net Skeleton functions will be available too.
|
|||||||
-DMONGOOSE_NO_DIRECTORY_LISTING Disable directory listing
|
-DMONGOOSE_NO_DIRECTORY_LISTING Disable directory listing
|
||||||
-DMONGOOSE_NO_FILESYSTEM Disables all file IO, serving from memory only
|
-DMONGOOSE_NO_FILESYSTEM Disables all file IO, serving from memory only
|
||||||
-DMONGOOSE_NO_LOGGING Disable access/error logging
|
-DMONGOOSE_NO_LOGGING Disable access/error logging
|
||||||
-DMONGOOSE_NO_THREADS
|
-DMONGOOSE_ENABLE_THREADS Enable mg_start_thread() function
|
||||||
-DMONGOOSE_NO_WEBSOCKET Disable WebSocket support
|
-DMONGOOSE_NO_WEBSOCKET Disable WebSocket support
|
||||||
|
-DMONGOOSE_NO_USER No concept of a user on used platform.
|
||||||
|
(Platform does not provide getpwnam, setgid or setuid)
|
||||||
|
|
||||||
-DMONGOOSE_USE_IDLE_TIMEOUT_SECONDS=X Idle connection timeout, default is 30
|
-DMONGOOSE_USE_IDLE_TIMEOUT_SECONDS=X Idle connection timeout, default is 30
|
||||||
-DMONGOOSE_USE_LUA Enable Lua scripting
|
-DMONGOOSE_USE_LUA Enable Lua scripting
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
# Mongoose Lua Server Pages
|
|
||||||
|
|
||||||
Pre-built Windows and Mac mongoose binaries support Lua Server Pages
|
|
||||||
functionality.
|
|
||||||
That means it is possible to write PHP-like scripts with mongoose
|
|
||||||
using Lua programming language instead of PHP. Lua is known
|
|
||||||
for it's speed and small size. Mongoose uses Lua version 5.2.3, the
|
|
||||||
documentation for it can be found at
|
|
||||||
[Lua 5.2 reference manual](http://www.lua.org/manual/5.2/).
|
|
||||||
|
|
||||||
To create a Lua Page, make a file that is called `ANY_NAME.lp`. For example,
|
|
||||||
`my_page.lp`. It is important to have a file
|
|
||||||
name that ends up with `.lp`, cause this is the way mongoose recognises
|
|
||||||
Lua Page file. The contents of the file, just like
|
|
||||||
with PHP, is HTML with embedded Lua code. Lua code must be enclosed within
|
|
||||||
`<? ?>` blocks, and can appear anywhere on the page.
|
|
||||||
|
|
||||||
Mongoose does not send HTTP headers for Lua pages. Therefore,
|
|
||||||
every Lua Page must begin with HTTP status line and headers, like this:
|
|
||||||
|
|
||||||
<? mg.write('HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n') ?>
|
|
||||||
<html><body>
|
|
||||||
<span>Today is:</span> <? mg.write(os.date("%A")) ?>
|
|
||||||
</body></html>
|
|
||||||
|
|
||||||
Note that this example uses function `mg.write()`, which prints data to the
|
|
||||||
web page. Using function `mg.write()` is the way to generate web content from
|
|
||||||
inside Lua code. In addition to `mg.write()`, all standard library functions
|
|
||||||
are accessible from the Lua code (please check reference manual for details).
|
|
||||||
Information about the request is available via the `mg.request_info` object.
|
|
||||||
I contains request method, all headers, etcetera. Please refer to
|
|
||||||
`struct mg_request_info` definition in
|
|
||||||
[mongoose.h](https://github.com/cesanta/mongoose/blob/master/mongoose.h)
|
|
||||||
to see what is available via the `mg.request_info` object.
|
|
||||||
Check out [prime_numbers.lp](https://github.com/cesanta/mongoose/blob/master/examples/lua/prime_numbers.lp) for some example.
|
|
||||||
|
|
||||||
Mongoose exports the following to the Lua Server Page:
|
|
||||||
|
|
||||||
mg.write(str) -- writes string to the client
|
|
||||||
mg.onerror(msg) -- error handler, can be overridden
|
|
||||||
mg.request_info -- a table with request information
|
|
||||||
|
|
||||||
Using Lua scripting it is easy to emulate SSI functionality. For example,
|
|
||||||
to include the content of another file, one can write:
|
|
||||||
|
|
||||||
<? mg.write(io.open('MY_FILE.TXT'):read('*all')) ?>
|
|
||||||
|
|
||||||
To serve a Lua Page, mongoose creates Lua context. That context is used for
|
|
||||||
all Lua blocks within the page. That means, all Lua blocks on the same page
|
|
||||||
share the same context. If one block defines a variable, for example, that
|
|
||||||
variable is visible in all following blocks.
|
|
||||||
+27
-2
@@ -1,12 +1,37 @@
|
|||||||
# Mongoose Release Notes
|
# Mongoose Release Notes
|
||||||
|
|
||||||
|
## Release 5.6, 2015-03-17
|
||||||
|
|
||||||
|
Changes in Libmongoose library:
|
||||||
|
|
||||||
|
- Added `-dav_root` configuration option that gives an ability to mount
|
||||||
|
a different root directory (not document_root)
|
||||||
|
- Fixes for build under Win23 and MinGW
|
||||||
|
- Bugfix: Double dots removal
|
||||||
|
- Bugfix: final chunked response double-send
|
||||||
|
- Fixed compilation in 64-bit environments
|
||||||
|
- Added OS/2 compatibility
|
||||||
|
- Added `getaddrinfo()` call and `NS_ENABLE_GETADDRINFO`
|
||||||
|
- Various SSL-related fixes
|
||||||
|
- Added integer overflow protection in `iobuf_append()` and `deliver_websocket_frame()`
|
||||||
|
- Fixed NetBSD build
|
||||||
|
- Enabled `NS_ENABLE_IPV6` build for Visual Studio 2008+
|
||||||
|
- Enhanced comma detection in `parse_header()`
|
||||||
|
- Fixed unchanged memory accesses on ARM
|
||||||
|
- Added ability to use custom memory allocator through NS_MALLOC, NS_FREE, NS_REALLOC
|
||||||
|
|
||||||
|
Changes in Mongoose binary:
|
||||||
|
|
||||||
|
- Added `-start_browser` option to disable automatic browser launch
|
||||||
|
- Added experimental SSL support. To listen on HTTPS port, use `ssl://PORT:SSL_CERT` format. For example, to listen on HTTP port 8080 and HTTPS port 8043, use `-listening_port 8080,ssl://8043:ssl_cert.pem`
|
||||||
|
|
||||||
## Release 5.5, October 28 2014
|
## Release 5.5, October 28 2014
|
||||||
|
|
||||||
Changes in Libmongoose library:
|
Changes in Libmongoose library:
|
||||||
|
|
||||||
- Added new API function: `mg_forward()` for proxying functionality
|
- Added new API function: `mg_forward()` for proxying functionality
|
||||||
- Added new API function: `mg_send_file_data()` for sending file data
|
- Added new API function: `mg_send_file_data()` for sending file data
|
||||||
- Added new utility API functions: `mg_mmap() and mg_munpap()`
|
- Added new utility API functions: `mg_mmap() and mg_munmap()`
|
||||||
- Changed the way SSL settings are handled: removed `ssl_certificate` and
|
- Changed the way SSL settings are handled: removed `ssl_certificate` and
|
||||||
`ssl_ca_certificate` options, and instead made `listening_port` accept
|
`ssl_ca_certificate` options, and instead made `listening_port` accept
|
||||||
`ssl://PORT:SSL_CERT:CA_CERT` notation
|
`ssl://PORT:SSL_CERT:CA_CERT` notation
|
||||||
@@ -82,7 +107,7 @@ Changes in Libmongoose library:
|
|||||||
|
|
||||||
Changes in pre-compiled binaries:
|
Changes in pre-compiled binaries:
|
||||||
|
|
||||||
* New awesome Mongoose logos buy our designer Katrin - thanks Katrin!
|
* New awesome Mongoose logos by our designer Katrin - thanks Katrin!
|
||||||
Check them out at http://cesanta.com/products.shtml
|
Check them out at http://cesanta.com/products.shtml
|
||||||
* Added Lua Server Pages support to the free version, quick intro is at
|
* Added Lua Server Pages support to the free version, quick intro is at
|
||||||
http://cesanta.com/docs/Lua.shtml
|
http://cesanta.com/docs/Lua.shtml
|
||||||
|
|||||||
+4
-9
@@ -1,20 +1,15 @@
|
|||||||
# Mongoose SSL guide
|
# Mongoose SSL guide
|
||||||
|
|
||||||
SSL is a protocol that makes web communication secure. To enable SSL
|
SSL is a protocol that makes web communication secure. To enable SSL
|
||||||
in mongoose, 3 steps are required:
|
in mongoose, 2 steps are required:
|
||||||
|
|
||||||
1. Valid certificate file must be created
|
1. Create valid SSL certificate file
|
||||||
2. `ssl_certificate` options must be set to contain path to the
|
2. Append SSL certificate file path to the `listening_ports` option
|
||||||
certificate file.
|
|
||||||
3. `listening_ports` option must contain a port number with letter `s`
|
|
||||||
appended to it, which instructs Mongoose to use SSL for all connections
|
|
||||||
made to that port.
|
|
||||||
|
|
||||||
Below is the `mongoose.conf` file snippet for typical SSL setup:
|
Below is the `mongoose.conf` file snippet for typical SSL setup:
|
||||||
|
|
||||||
document_root www_root # Serve files in www_root directory
|
document_root www_root # Serve files in www_root directory
|
||||||
listening_ports 80r,443s # Redirect all HTTP requests to HTTPS
|
listening_ports 80,443:cert.pem # Listen on ports 80 and 443
|
||||||
ssl_certificate ssl_cert.pem # Location of certificate file
|
|
||||||
|
|
||||||
## How to create SSL certificate file
|
## How to create SSL certificate file
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
*.exe
|
||||||
+6
-1
@@ -3,13 +3,18 @@
|
|||||||
|
|
||||||
SUBDIRS = $(sort $(filter-out csharp/, $(dir $(wildcard */))))
|
SUBDIRS = $(sort $(filter-out csharp/, $(dir $(wildcard */))))
|
||||||
X = $(SUBDIRS)
|
X = $(SUBDIRS)
|
||||||
|
ifdef WINDIR
|
||||||
|
# appending the Winsock2 library at the end of the compiler
|
||||||
|
# invocation
|
||||||
|
CFLAGS_EXTRA += -lws2_32
|
||||||
|
endif
|
||||||
|
|
||||||
.PHONY: $(SUBDIRS)
|
.PHONY: $(SUBDIRS)
|
||||||
|
|
||||||
all: $(SUBDIRS)
|
all: $(SUBDIRS)
|
||||||
|
|
||||||
$(SUBDIRS):
|
$(SUBDIRS):
|
||||||
@$(MAKE) -C $@
|
@$(MAKE) CFLAGS_EXTRA="$(CFLAGS_EXTRA)" -C $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
for d in $(SUBDIRS) ; do $(MAKE) -C $$d clean ; done
|
for d in $(SUBDIRS) ; do $(MAKE) -C $$d clean ; done
|
||||||
@@ -9,4 +9,4 @@ unix: $(SOURCES)
|
|||||||
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib
|
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp *.o *.lib
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
# All rights reserved
|
# All rights reserved
|
||||||
|
|
||||||
PROG = multi_threaded_server
|
PROG = multi_threaded_server
|
||||||
CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA)
|
CFLAGS = -W -Wall -I../.. -pthread -g -O0 -DMONGOOSE_ENABLE_THREADS $(CFLAGS_EXTRA)
|
||||||
SOURCES = $(PROG).c ../../mongoose.c
|
SOURCES = $(PROG).c ../../mongoose.c
|
||||||
|
|
||||||
$(PROG): $(SOURCES)
|
$(PROG): $(SOURCES)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
PROG = proxy_server
|
PROG = proxy_server
|
||||||
FLAGS = -I../.. -DNS_ENABLE_SSL
|
FLAGS = -I../.. -DNS_ENABLE_SSL
|
||||||
CFLAGS = -W -Wall -g -O0 -pthread -lssl $(FLAGS) $(CFLAGS_EXTRA)
|
CFLAGS = -W -Wall -g -O0 -pthread -lssl -DMONGOOSE_ENABLE_THREADS $(FLAGS) $(CFLAGS_EXTRA)
|
||||||
SOURCES = $(PROG).c ../../mongoose.c
|
SOURCES = $(PROG).c ../../mongoose.c
|
||||||
|
|
||||||
unix: $(SOURCES)
|
unix: $(SOURCES)
|
||||||
|
|||||||
@@ -160,20 +160,13 @@ static void setopt(struct mg_server *s, const char *opt, const char *val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
const char *cert = NULL, *ca_cert = NULL, *port = "2014";
|
const char *port = "2014", *dump = NULL, *root = "proxy_web_root";
|
||||||
const char *mitm = NULL, *dump = NULL, *root = "proxy_web_root";
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// Parse command line options
|
// Parse command line options
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
if (strcmp(argv[i], "-ca_cert") == 0 && i + 1 < argc) {
|
if (strcmp(argv[i], "-port") == 0 && i + 1 < argc) {
|
||||||
ca_cert = argv[++i];
|
|
||||||
} else if (strcmp(argv[i], "-cert") == 0 && i + 1 < argc) {
|
|
||||||
cert = argv[++i];
|
|
||||||
} else if (strcmp(argv[i], "-port") == 0 && i + 1 < argc) {
|
|
||||||
port = argv[++i];
|
port = argv[++i];
|
||||||
} else if (strcmp(argv[i], "-mitm") == 0 && i + 1 < argc) {
|
|
||||||
mitm = argv[++i];
|
|
||||||
} else if (strcmp(argv[i], "-root") == 0 && i + 1 < argc) {
|
} else if (strcmp(argv[i], "-root") == 0 && i + 1 < argc) {
|
||||||
root = argv[++i];
|
root = argv[++i];
|
||||||
} else if (strcmp(argv[i], "-dump") == 0 && i + 1 < argc) {
|
} else if (strcmp(argv[i], "-dump") == 0 && i + 1 < argc) {
|
||||||
@@ -191,10 +184,7 @@ int main(int argc, char *argv[]) {
|
|||||||
setopt(s_server, "enable_proxy", "yes");
|
setopt(s_server, "enable_proxy", "yes");
|
||||||
setopt(s_server, "document_root", root);
|
setopt(s_server, "document_root", root);
|
||||||
setopt(s_server, "listening_port", port);
|
setopt(s_server, "listening_port", port);
|
||||||
setopt(s_server, "ssl_certificate", cert);
|
|
||||||
setopt(s_server, "ssl_ca_certificate", ca_cert);
|
|
||||||
setopt(s_server, "hexdump_file", dump);
|
setopt(s_server, "hexdump_file", dump);
|
||||||
setopt(s_server, "ssl_mitm_certs", mitm);
|
|
||||||
|
|
||||||
// Start two SSE pushing threads
|
// Start two SSE pushing threads
|
||||||
mg_start_thread(sse_pusher_thread_func, (void *) "sse_pusher_thread_1");
|
mg_start_thread(sse_pusher_thread_func, (void *) "sse_pusher_thread_1");
|
||||||
|
|||||||
@@ -2,11 +2,27 @@
|
|||||||
# All rights reserved
|
# All rights reserved
|
||||||
|
|
||||||
PROG = web_server
|
PROG = web_server
|
||||||
CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA)
|
CFLAGS = -W -Wall -I../.. -pthread -g -O0 -DMONGOOSE_ENABLE_THREADS $(CFLAGS_EXTRA)
|
||||||
SOURCES = $(PROG).c ../../mongoose.c
|
SOURCES = $(PROG).c ../../mongoose.c
|
||||||
|
OPENSSL_FLAGS = -DNS_ENABLE_SSL -lssl
|
||||||
|
|
||||||
|
# PolarSSL paths and flags
|
||||||
|
POLARSSL_PATH = /usr/local
|
||||||
|
POLARSSLCOMPAT_PATH = ./../../../polar
|
||||||
|
SOURCES_POLAR = $(SOURCES) $(POLARSSLCOMPAT_PATH)/polarssl_compat.c
|
||||||
|
INCDIR_POLAR = -I$(POLARSSLCOMPAT_PATH) -I$(POLARSSL_PATH)/include
|
||||||
|
LDFLAGS_POLAR = -L$(POLARSSL_PATH)/lib -lmbedtls
|
||||||
|
CFLAGS_POLAR = $(CFLAGS) $(INCDIR_POLAR) -DNS_ENABLE_SSL
|
||||||
|
#
|
||||||
|
|
||||||
$(PROG): $(SOURCES)
|
$(PROG): $(SOURCES)
|
||||||
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
||||||
|
|
||||||
|
openssl:
|
||||||
|
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS) $(OPENSSL_FLAGS)
|
||||||
|
|
||||||
|
polarssl:
|
||||||
|
$(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
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIC+zCCAeOgAwIBAgIJAPhB8jbL+G82MA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
|
||||||
|
BAMMCTEyNy4wLjAuMTAeFw0xNTAzMDYxMjQzMzNaFw0yNTAzMDMxMjQzMzNaMBQx
|
||||||
|
EjAQBgNVBAMMCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
|
||||||
|
ggEBALi3b3daMgzUEROKob1Caf68i+//cTRkPdBJv2cOBak21CdQzY0Nvx73GLzf
|
||||||
|
5TKB347BCHNbYRKGJXDbYdmFp20/WeBHkY7RS3Ad2Q5lzyx66u9PxNx7hJIiqBgF
|
||||||
|
58VU+E3o/I+o8QNIoOT+wtCiq3Nwkp+zGBJmS32rzMEV9bcKxSzMrkfRhF+XAREd
|
||||||
|
DwM9vfPg6WRb/b+vv06uvVwcw390RprLautGfBdaRddVYkIAKJGRRTqZAvTRFW1J
|
||||||
|
FcIVOxlN+iA7qP7xjr3tUP78qMmlu0MXsHrUR2cgfveZK2sdUW5G804yHsU5sC8l
|
||||||
|
FbtLKMEOyLsk2bEIScOXgum7g2sCAwEAAaNQME4wHQYDVR0OBBYEFHtLzUqAsXkH
|
||||||
|
Il8S5sMhJuVhRJLdMB8GA1UdIwQYMBaAFHtLzUqAsXkHIl8S5sMhJuVhRJLdMAwG
|
||||||
|
A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAEzHc0AOr+qs0OFvWMfcSMi7
|
||||||
|
O/aYlLS6f7Sos+lli69+61EcmCTJVarVeAVUsAoqmzBKDbeOpAK1hGX6/GGcXjR2
|
||||||
|
BmuU0hUKyX9l1lwdMKU45BayH/riElwnvAyj2GxKoPpdIjlHns4SAITOCUx9NfpM
|
||||||
|
agd7kjolton0ZQ5DI/2a43PkqHv1lY4Dp60wJlxit9U68bsGOycCJ/BsAyrPROb2
|
||||||
|
D1MkpMBIdfHc8uxRywM3/l9buFX8yrrMUGOYKgfjDwdzbj0iwIixoGpHL7IfeBtu
|
||||||
|
dvGO/g2rEhbtAP+xIgOR3GvzqjZh30er3no7zjDMn65tTME18Aq3tBQY7vPDKms=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC4t293WjIM1BET
|
||||||
|
iqG9Qmn+vIvv/3E0ZD3QSb9nDgWpNtQnUM2NDb8e9xi83+Uygd+OwQhzW2EShiVw
|
||||||
|
22HZhadtP1ngR5GO0UtwHdkOZc8seurvT8Tce4SSIqgYBefFVPhN6PyPqPEDSKDk
|
||||||
|
/sLQoqtzcJKfsxgSZkt9q8zBFfW3CsUszK5H0YRflwERHQ8DPb3z4OlkW/2/r79O
|
||||||
|
rr1cHMN/dEaay2rrRnwXWkXXVWJCACiRkUU6mQL00RVtSRXCFTsZTfogO6j+8Y69
|
||||||
|
7VD+/KjJpbtDF7B61EdnIH73mStrHVFuRvNOMh7FObAvJRW7SyjBDsi7JNmxCEnD
|
||||||
|
l4Lpu4NrAgMBAAECggEAaFuqbAHXOQwuwZ2XFzgIblTTsrncmT7w9VZU/sIbTKif
|
||||||
|
X771AnX7vmDX5w2PjeN2DE7emV3NEAwd5w7qz1wFZWFfQ6jrgYaZWjRixxGZ5IVl
|
||||||
|
aeLlU7OtCGrwEPJ1KTWCO3IgDoHh+Hr1+6o7Imhk+QlmrTcfqHWGvO9s9MGVWt2S
|
||||||
|
RLAnSTFiOe5brdJnmlqq1sKZmnLmpydBaPUOYpZGAgRasrjdMZB+lZOazd1x23/5
|
||||||
|
GAcm0rDREMnO9b2Jt+TNEZHT6d5KpVoExztZEZj8QCLXoic/SpFIqHGtpNlQXa+d
|
||||||
|
BVqgQbIYjO8ldldxZ8YIyJDVF+9e/uBBwu6jBIIsEQKBgQDspEHCyyuh4LG+7BbZ
|
||||||
|
eXlsfCxPTM6K9w31ZwHAwRtAuGqrOrE+pFJG9CEsFZbAI1aOGmZZdjexuSMcOlXl
|
||||||
|
TIVJTQHoFtoGEsanYEXO4O1t02Ab/DCYSpXusXUraRBRPpsTC77Sh5mxLUNd23d9
|
||||||
|
NhnDBuwChAmC+IYexjkXeqPYFwKBgQDH08PEd+2PVo4MD8UVKUlEcgoyCr6ESiyp
|
||||||
|
HfYyhhfd5x3DbZLoKCkunDfBs/hakQk8DA2nn4tl4ZjfmzXmX0EBx+E5YTdYshW7
|
||||||
|
ZcjN5x64B5PEOAR/NZA6agNlp3XGXXXgX+gnN6pgE49eVU22nZ4G+QBKD6NcCviB
|
||||||
|
LBPUxMbvzQKBgHgZYRqonGtaqzsXfP1AjmSFnMNeWtDiU95BOf2Gw/sT3WcrsXr2
|
||||||
|
UJ+cFR3XkxvOk4YpVdp/igKT0ILqBGAMdvTdtWMB/gLpEpMt5B/7veRoS7XIRy1z
|
||||||
|
ZSawP6QZfWOOX4vKAT29/j2SmEcRNFKC245EfBFGy8EBuqfxuFX3MyJfAoGBAJ0y
|
||||||
|
tjsErVmpma1baosvI3g4zlR3p1CimWehLmCopHXorr1iocMIdP0535L+ZU258y3N
|
||||||
|
vaA0HpFTW9PsYgaMwLMJ7uAY3lVkIzx84e849i2HqHMgLkl0dbW+WFXL2xblxylv
|
||||||
|
yU2wuNNED/EB4lTawcpycAvTKYvrBXt4lVE4S9exAoGAGl6vZV3zyw4jpIw4uDfk
|
||||||
|
LTPYUrghFDDGKExyeOnC/W9pqR2veqzfBz02C3jqwhewoqgAcnNc2sg0rJmM+6Oz
|
||||||
|
Z2mmGZTHO9xR++7+W7e8AkQBbS6TB8a+7yNcM4USLP+b9sX5N+8gFhFs9tG7j/no
|
||||||
|
G44qLsJ/yve7/QsOA37uEMs=
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
@@ -96,11 +96,8 @@ static void __cdecl signal_handler(int sig_num) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void vnotify(const char *fmt, va_list ap, int must_exit) {
|
static void vnotify(const char *fmt, va_list ap, int must_exit) {
|
||||||
char msg[200];
|
vfprintf(stderr, fmt, ap);
|
||||||
|
fputc('\n', stderr);
|
||||||
vsnprintf(msg, sizeof(msg), fmt, ap);
|
|
||||||
fprintf(stderr, "%s\n", msg);
|
|
||||||
|
|
||||||
if (must_exit) {
|
if (must_exit) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,26 @@
|
|||||||
# All rights reserved
|
# All rights reserved
|
||||||
|
|
||||||
PROG = ws_ssl
|
PROG = ws_ssl
|
||||||
CFLAGS = -W -Wall -I../.. -I. -pthread -g -O0 $(CFLAGS_EXTRA)
|
CFLAGS = -W -Wall -I../.. -I. -pthread -g -O0 -DMONGOOSE_ENABLE_THREADS -DNS_ENABLE_SSL -DSSL_WRAPPER_USE_AS_LIBRARY $(CFLAGS_EXTRA)
|
||||||
|
LDFLAGS = -lssl
|
||||||
SOURCES = ws_ssl.c ../../mongoose.c ssl_wrapper.c
|
SOURCES = ws_ssl.c ../../mongoose.c ssl_wrapper.c
|
||||||
|
|
||||||
|
# PolarSSL paths and flags
|
||||||
|
POLARSSL_PATH = /usr/local
|
||||||
|
POLARSSLCOMPAT_PATH = ./../../../polar
|
||||||
|
SOURCES_POLAR = $(SOURCES) $(POLARSSLCOMPAT_PATH)/polarssl_compat.c
|
||||||
|
INCDIR_POLAR = -I$(POLARSSLCOMPAT_PATH) -I$(POLARSSL_PATH)/include
|
||||||
|
LDFLAGS_POLAR = -L$(POLARSSL_PATH)/lib -lmbedtls
|
||||||
|
CFLAGS_POLAR = $(CFLAGS) $(INCDIR_POLAR)
|
||||||
|
#
|
||||||
|
|
||||||
all: $(PROG)
|
all: $(PROG)
|
||||||
|
|
||||||
$(PROG): $(SOURCES)
|
$(PROG): $(SOURCES)
|
||||||
$(CC) -o $(PROG) $(SOURCES) \
|
$(CC) -o $(PROG) $(SOURCES) $(LDFLAGS) $(CFLAGS)
|
||||||
-DNS_ENABLE_SSL -DSSL_WRAPPER_USE_AS_LIBRARY -lssl $(CFLAGS)
|
|
||||||
|
polarssl: $(SOURCES_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
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
LOCAL_PATH := $(call my-dir)/..
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_CFLAGS := -std=c99 -O2 -W -Wall -pthread -pipe $(COPT)
|
||||||
|
LOCAL_MODULE := mongoose
|
||||||
|
LOCAL_SRC_FILES := examples/web_server/web_server.c mongoose.c
|
||||||
|
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
+264
-110
@@ -14,8 +14,6 @@
|
|||||||
//
|
//
|
||||||
// Alternatively, you can license this library under a commercial
|
// Alternatively, you can license this library under a commercial
|
||||||
// license, as set out in <http://cesanta.com/>.
|
// license, as set out in <http://cesanta.com/>.
|
||||||
//
|
|
||||||
// $Date: 2014-09-16 06:47:40 UTC $
|
|
||||||
|
|
||||||
#ifdef NOEMBED_NET_SKELETON
|
#ifdef NOEMBED_NET_SKELETON
|
||||||
#include "net_skeleton.h"
|
#include "net_skeleton.h"
|
||||||
@@ -36,8 +34,6 @@
|
|||||||
//
|
//
|
||||||
// Alternatively, you can license this software under a commercial
|
// Alternatively, you can license this software under a commercial
|
||||||
// license, as set out in <http://cesanta.com/>.
|
// license, as set out in <http://cesanta.com/>.
|
||||||
//
|
|
||||||
// $Date: 2014-09-28 05:04:41 UTC $
|
|
||||||
|
|
||||||
#ifndef NS_SKELETON_HEADER_INCLUDED
|
#ifndef NS_SKELETON_HEADER_INCLUDED
|
||||||
#define NS_SKELETON_HEADER_INCLUDED
|
#define NS_SKELETON_HEADER_INCLUDED
|
||||||
@@ -50,7 +46,9 @@
|
|||||||
#define _INTEGRAL_MAX_BITS 64 // Enable _stati64() on Windows
|
#define _INTEGRAL_MAX_BITS 64 // Enable _stati64() on Windows
|
||||||
#define _CRT_SECURE_NO_WARNINGS // Disable deprecation warning in VS2005+
|
#define _CRT_SECURE_NO_WARNINGS // Disable deprecation warning in VS2005+
|
||||||
#undef WIN32_LEAN_AND_MEAN // Let windows.h always include winsock2.h
|
#undef WIN32_LEAN_AND_MEAN // Let windows.h always include winsock2.h
|
||||||
|
#ifdef __Linux__
|
||||||
#define _XOPEN_SOURCE 600 // For flockfile() on Linux
|
#define _XOPEN_SOURCE 600 // For flockfile() on Linux
|
||||||
|
#endif
|
||||||
#define __STDC_FORMAT_MACROS // <inttypes.h> wants this for C++
|
#define __STDC_FORMAT_MACROS // <inttypes.h> wants this for C++
|
||||||
#define __STDC_LIMIT_MACROS // C++ wants that for INT64_MAX
|
#define __STDC_LIMIT_MACROS // C++ wants that for INT64_MAX
|
||||||
#ifndef _LARGEFILE_SOURCE
|
#ifndef _LARGEFILE_SOURCE
|
||||||
@@ -80,7 +78,11 @@
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma comment(lib, "ws2_32.lib") // Linking with winsock library
|
#pragma comment(lib, "ws2_32.lib") // Linking with winsock library
|
||||||
|
#include <BaseTsd.h>
|
||||||
|
typedef SSIZE_T ssize_t;
|
||||||
#endif
|
#endif
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
#ifndef EINPROGRESS
|
#ifndef EINPROGRESS
|
||||||
@@ -124,7 +126,12 @@ typedef struct _stati64 ns_stat_t;
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#define closesocket(x) close(x)
|
#define closesocket(x) close(x)
|
||||||
|
#ifndef __OS2__
|
||||||
#define __cdecl
|
#define __cdecl
|
||||||
|
#else
|
||||||
|
#include <sys/time.h>
|
||||||
|
typedef int socklen_t;
|
||||||
|
#endif
|
||||||
#define INVALID_SOCKET (-1)
|
#define INVALID_SOCKET (-1)
|
||||||
#define to64(x) strtoll(x, NULL, 10)
|
#define to64(x) strtoll(x, NULL, 10)
|
||||||
typedef int sock_t;
|
typedef int sock_t;
|
||||||
@@ -255,7 +262,7 @@ struct ns_connection *ns_bind(struct ns_mgr *, const char *,
|
|||||||
struct ns_connection *ns_connect(struct ns_mgr *, const char *,
|
struct ns_connection *ns_connect(struct ns_mgr *, const char *,
|
||||||
ns_callback_t, void *);
|
ns_callback_t, void *);
|
||||||
|
|
||||||
int ns_send(struct ns_connection *, const void *buf, int len);
|
int ns_send(struct ns_connection *, const void *buf, size_t len);
|
||||||
int ns_printf(struct ns_connection *, const char *fmt, ...);
|
int ns_printf(struct ns_connection *, const char *fmt, ...);
|
||||||
int ns_vprintf(struct ns_connection *, const char *fmt, va_list ap);
|
int ns_vprintf(struct ns_connection *, const char *fmt, va_list ap);
|
||||||
|
|
||||||
@@ -305,12 +312,18 @@ int ns_resolve(const char *domain_name, char *ip_addr_buf, size_t buf_len);
|
|||||||
#define NS_FREE free
|
#define NS_FREE free
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef NS_CALLOC
|
||||||
|
#define NS_CALLOC calloc
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NS_CTL_MSG_MESSAGE_SIZE (8 * 1024)
|
||||||
|
#define NS_READ_BUFFER_SIZE 2048
|
||||||
#define NS_UDP_RECEIVE_BUFFER_SIZE 2000
|
#define NS_UDP_RECEIVE_BUFFER_SIZE 2000
|
||||||
#define NS_VPRINTF_BUFFER_SIZE 500
|
#define NS_VPRINTF_BUFFER_SIZE 500
|
||||||
|
|
||||||
struct ctl_msg {
|
struct ctl_msg {
|
||||||
ns_callback_t callback;
|
ns_callback_t callback;
|
||||||
char message[1024 * 8];
|
char message[NS_CTL_MSG_MESSAGE_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
void iobuf_resize(struct iobuf *io, size_t new_size) {
|
void iobuf_resize(struct iobuf *io, size_t new_size) {
|
||||||
@@ -341,6 +354,11 @@ size_t iobuf_append(struct iobuf *io, const void *buf, size_t len) {
|
|||||||
assert(io != NULL);
|
assert(io != NULL);
|
||||||
assert(io->len <= io->size);
|
assert(io->len <= io->size);
|
||||||
|
|
||||||
|
/* check overflow */
|
||||||
|
if (len > ~(size_t)0 - (size_t)(io->buf + io->len)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (len <= 0) {
|
if (len <= 0) {
|
||||||
} else if (io->len + len <= io->size) {
|
} else if (io->len + len <= io->size) {
|
||||||
memcpy(io->buf + io->len, buf, len);
|
memcpy(io->buf + io->len, buf, len);
|
||||||
@@ -366,7 +384,8 @@ void iobuf_remove(struct iobuf *io, size_t n) {
|
|||||||
|
|
||||||
static size_t ns_out(struct ns_connection *nc, const void *buf, size_t len) {
|
static size_t ns_out(struct ns_connection *nc, const void *buf, size_t len) {
|
||||||
if (nc->flags & NSF_UDP) {
|
if (nc->flags & NSF_UDP) {
|
||||||
long n = sendto(nc->sock, buf, len, 0, &nc->sa.sa, sizeof(nc->sa.sin));
|
long n = sendto(nc->sock, (const char *) buf, len, 0, &nc->sa.sa,
|
||||||
|
sizeof(nc->sa.sin));
|
||||||
DBG(("%p %d send %ld (%d %s)", nc, nc->sock, n, errno, strerror(errno)));
|
DBG(("%p %d send %ld (%d %s)", nc, nc->sock, n, errno, strerror(errno)));
|
||||||
return n < 0 ? 0 : n;
|
return n < 0 ? 0 : n;
|
||||||
} else {
|
} else {
|
||||||
@@ -427,7 +446,7 @@ int ns_avprintf(char **buf, size_t size, const char *fmt, va_list ap) {
|
|||||||
// succeed or out of memory.
|
// succeed or out of memory.
|
||||||
*buf = NULL;
|
*buf = NULL;
|
||||||
while (len < 0) {
|
while (len < 0) {
|
||||||
if (*buf) free(*buf);
|
if (*buf) NS_FREE(*buf);
|
||||||
size *= 2;
|
size *= 2;
|
||||||
if ((*buf = (char *) NS_MALLOC(size)) == NULL) break;
|
if ((*buf = (char *) NS_MALLOC(size)) == NULL) break;
|
||||||
va_copy(ap_copy, ap);
|
va_copy(ap_copy, ap);
|
||||||
@@ -456,7 +475,7 @@ int ns_vprintf(struct ns_connection *nc, const char *fmt, va_list ap) {
|
|||||||
ns_out(nc, buf, len);
|
ns_out(nc, buf, len);
|
||||||
}
|
}
|
||||||
if (buf != mem && buf != NULL) {
|
if (buf != mem && buf != NULL) {
|
||||||
free(buf);
|
NS_FREE(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
@@ -490,7 +509,7 @@ static void hexdump(struct ns_connection *nc, const char *path,
|
|||||||
ns_hexdump(io->buf + (ev == NS_SEND ? 0 : io->len) -
|
ns_hexdump(io->buf + (ev == NS_SEND ? 0 : io->len) -
|
||||||
(ev == NS_SEND ? 0 : num_bytes), num_bytes, buf, buf_size);
|
(ev == NS_SEND ? 0 : num_bytes), num_bytes, buf, buf_size);
|
||||||
fprintf(fp, "%s", buf);
|
fprintf(fp, "%s", buf);
|
||||||
free(buf);
|
NS_FREE(buf);
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
@@ -589,6 +608,30 @@ int ns_socketpair(sock_t sp[2]) {
|
|||||||
|
|
||||||
// TODO(lsm): use non-blocking resolver
|
// TODO(lsm): use non-blocking resolver
|
||||||
static int ns_resolve2(const char *host, struct in_addr *ina) {
|
static int ns_resolve2(const char *host, struct in_addr *ina) {
|
||||||
|
#ifdef NS_ENABLE_GETADDRINFO
|
||||||
|
int rv = 0;
|
||||||
|
struct addrinfo hints, *servinfo, *p;
|
||||||
|
struct sockaddr_in *h = NULL;
|
||||||
|
char *ip = NS_MALLOC(17);
|
||||||
|
memset(ip, '\0', 17);
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof hints);
|
||||||
|
hints.ai_family = AF_INET;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
|
if((rv = getaddrinfo(host, NULL , NULL, &servinfo)) != 0) {
|
||||||
|
DBG(("getaddrinfo(%s) failed: %s", host, strerror(errno)));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(p = servinfo; p != NULL; p = p->ai_next) {
|
||||||
|
memcpy(&h, &p->ai_addr, sizeof(struct sockaddr_in *));
|
||||||
|
memcpy(ina, &h->sin_addr, sizeof(ina));
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo(servinfo);
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
struct hostent *he;
|
struct hostent *he;
|
||||||
if ((he = gethostbyname(host)) == NULL) {
|
if ((he = gethostbyname(host)) == NULL) {
|
||||||
DBG(("gethostbyname(%s) failed: %s", host, strerror(errno)));
|
DBG(("gethostbyname(%s) failed: %s", host, strerror(errno)));
|
||||||
@@ -597,6 +640,7 @@ static int ns_resolve2(const char *host, struct in_addr *ina) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve FDQN "host", store IP address in the "ip".
|
// Resolve FDQN "host", store IP address in the "ip".
|
||||||
@@ -655,8 +699,8 @@ static int ns_parse_address(const char *str, union socket_address *sa,
|
|||||||
sa->sin.sin_port = htons((uint16_t) port);
|
sa->sin.sin_port = htons((uint16_t) port);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*use_ssl && (sscanf(str + len, ":%99[^:]:%99[^:]%n", cert, ca, &n) == 2 ||
|
if (*use_ssl && (sscanf(str + len, ":%99[^:,]:%99[^:,]%n", cert, ca, &n) == 2 ||
|
||||||
sscanf(str + len, ":%99[^:]%n", cert, &n) == 1)) {
|
sscanf(str + len, ":%99[^:,]%n", cert, &n) == 1)) {
|
||||||
len += n;
|
len += n;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -868,7 +912,7 @@ static int ns_ssl_err(struct ns_connection *conn, int res) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void ns_read_from_socket(struct ns_connection *conn) {
|
static void ns_read_from_socket(struct ns_connection *conn) {
|
||||||
char buf[2048];
|
char buf[NS_READ_BUFFER_SIZE];
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
if (conn->flags & NSF_CONNECTING) {
|
if (conn->flags & NSF_CONNECTING) {
|
||||||
@@ -889,6 +933,7 @@ static void ns_read_from_socket(struct ns_connection *conn) {
|
|||||||
} else {
|
} else {
|
||||||
ok = 1;
|
ok = 1;
|
||||||
}
|
}
|
||||||
|
conn->flags &= ~(NSF_WANT_READ | NSF_WANT_WRITE);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
conn->flags &= ~NSF_CONNECTING;
|
conn->flags &= ~NSF_CONNECTING;
|
||||||
@@ -917,6 +962,7 @@ static void ns_read_from_socket(struct ns_connection *conn) {
|
|||||||
int ssl_err = ns_ssl_err(conn, res);
|
int ssl_err = ns_ssl_err(conn, res);
|
||||||
if (res == 1) {
|
if (res == 1) {
|
||||||
conn->flags |= NSF_SSL_HANDSHAKE_DONE;
|
conn->flags |= NSF_SSL_HANDSHAKE_DONE;
|
||||||
|
conn->flags &= ~(NSF_WANT_READ | NSF_WANT_WRITE);
|
||||||
} else if (ssl_err == SSL_ERROR_WANT_READ ||
|
} else if (ssl_err == SSL_ERROR_WANT_READ ||
|
||||||
ssl_err == SSL_ERROR_WANT_WRITE) {
|
ssl_err == SSL_ERROR_WANT_WRITE) {
|
||||||
return; // Call us again
|
return; // Call us again
|
||||||
@@ -954,6 +1000,8 @@ static void ns_write_to_socket(struct ns_connection *conn) {
|
|||||||
} else {
|
} else {
|
||||||
conn->flags |= NSF_CLOSE_IMMEDIATELY;
|
conn->flags |= NSF_CLOSE_IMMEDIATELY;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
conn->flags &= ~(NSF_WANT_READ | NSF_WANT_WRITE);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
@@ -969,14 +1017,14 @@ static void ns_write_to_socket(struct ns_connection *conn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int ns_send(struct ns_connection *conn, const void *buf, int len) {
|
int ns_send(struct ns_connection *conn, const void *buf, size_t len) {
|
||||||
return (int) ns_out(conn, buf, len);
|
return (int) ns_out(conn, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ns_handle_udp(struct ns_connection *ls) {
|
static void ns_handle_udp(struct ns_connection *ls) {
|
||||||
struct ns_connection nc;
|
struct ns_connection nc;
|
||||||
char buf[NS_UDP_RECEIVE_BUFFER_SIZE];
|
char buf[NS_UDP_RECEIVE_BUFFER_SIZE];
|
||||||
int n;
|
ssize_t n;
|
||||||
socklen_t s_len = sizeof(nc.sa);
|
socklen_t s_len = sizeof(nc.sa);
|
||||||
|
|
||||||
memset(&nc, 0, sizeof(nc));
|
memset(&nc, 0, sizeof(nc));
|
||||||
@@ -1024,6 +1072,9 @@ time_t ns_mgr_poll(struct ns_mgr *mgr, int milli) {
|
|||||||
if (!(conn->flags & (NSF_LISTENING | NSF_CONNECTING))) {
|
if (!(conn->flags & (NSF_LISTENING | NSF_CONNECTING))) {
|
||||||
ns_call(conn, NS_POLL, ¤t_time);
|
ns_call(conn, NS_POLL, ¤t_time);
|
||||||
}
|
}
|
||||||
|
if (conn->flags & NSF_CLOSE_IMMEDIATELY) {
|
||||||
|
ns_close_conn(conn);
|
||||||
|
} else {
|
||||||
if (!(conn->flags & NSF_WANT_WRITE)) {
|
if (!(conn->flags & NSF_WANT_WRITE)) {
|
||||||
//DBG(("%p read_set", conn));
|
//DBG(("%p read_set", conn));
|
||||||
ns_add_to_set(conn->sock, &read_set, &max_fd);
|
ns_add_to_set(conn->sock, &read_set, &max_fd);
|
||||||
@@ -1034,8 +1085,6 @@ time_t ns_mgr_poll(struct ns_mgr *mgr, int milli) {
|
|||||||
//DBG(("%p write_set", conn));
|
//DBG(("%p write_set", conn));
|
||||||
ns_add_to_set(conn->sock, &write_set, &max_fd);
|
ns_add_to_set(conn->sock, &write_set, &max_fd);
|
||||||
}
|
}
|
||||||
if (conn->flags & NSF_CLOSE_IMMEDIATELY) {
|
|
||||||
ns_close_conn(conn);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1247,21 +1296,21 @@ void ns_mgr_free(struct ns_mgr *s) {
|
|||||||
#define fopen(x, y) mg_fopen((x), (y))
|
#define fopen(x, y) mg_fopen((x), (y))
|
||||||
#define open(x, y, z) mg_open((x), (y), (z))
|
#define open(x, y, z) mg_open((x), (y), (z))
|
||||||
#define close(x) _close(x)
|
#define close(x) _close(x)
|
||||||
|
#define fileno(x) _fileno(x)
|
||||||
#define lseek(x, y, z) _lseeki64((x), (y), (z))
|
#define lseek(x, y, z) _lseeki64((x), (y), (z))
|
||||||
|
#define read(x, y, z) _read((x), (y), (z))
|
||||||
|
#define write(x, y, z) _write((x), (y), (z))
|
||||||
#define popen(x, y) _popen((x), (y))
|
#define popen(x, y) _popen((x), (y))
|
||||||
#define pclose(x) _pclose(x)
|
#define pclose(x) _pclose(x)
|
||||||
#define mkdir(x, y) _mkdir(x)
|
#define mkdir(x, y) _mkdir(x)
|
||||||
|
#define rmdir(x) _rmdir(x)
|
||||||
|
#define strdup(x) _strdup(x)
|
||||||
#ifndef __func__
|
#ifndef __func__
|
||||||
#define STRX(x) #x
|
#define STRX(x) #x
|
||||||
#define STR(x) STRX(x)
|
#define STR(x) STRX(x)
|
||||||
#define __func__ __FILE__ ":" STR(__LINE__)
|
#define __func__ __FILE__ ":" STR(__LINE__)
|
||||||
#endif
|
#endif
|
||||||
/* MINGW has adopted the MSVC formatting for 64-bit ints as of gcc 4.4 till 4.8*/
|
|
||||||
#if (defined(__MINGW32__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4 && __GNUC_MINOR__ < 8))) || defined(_MSC_VER)
|
|
||||||
#define INT64_FMT "I64d"
|
#define INT64_FMT "I64d"
|
||||||
#else
|
|
||||||
#define INT64_FMT "lld"
|
|
||||||
#endif
|
|
||||||
#define flockfile(x) ((void) (x))
|
#define flockfile(x) ((void) (x))
|
||||||
#define funlockfile(x) ((void) (x))
|
#define funlockfile(x) ((void) (x))
|
||||||
typedef struct _stati64 file_stat_t;
|
typedef struct _stati64 file_stat_t;
|
||||||
@@ -1269,11 +1318,18 @@ typedef HANDLE process_id_t;
|
|||||||
|
|
||||||
#else ////////////// UNIX specific defines and includes
|
#else ////////////// UNIX specific defines and includes
|
||||||
|
|
||||||
|
#if !defined(MONGOOSE_NO_FILESYSTEM) &&\
|
||||||
|
(!defined(MONGOOSE_NO_DAV) || !defined(MONGOOSE_NO_DIRECTORY_LISTING))
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#endif
|
||||||
|
#if !defined(MONGOOSE_NO_FILESYSTEM) && !defined(MONGOOSE_NO_DL)
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
#endif
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
#if !defined(O_BINARY)
|
||||||
#define O_BINARY 0
|
#define O_BINARY 0
|
||||||
|
#endif
|
||||||
#define INT64_FMT PRId64
|
#define INT64_FMT PRId64
|
||||||
typedef struct stat file_stat_t;
|
typedef struct stat file_stat_t;
|
||||||
typedef pid_t process_id_t;
|
typedef pid_t process_id_t;
|
||||||
@@ -1307,13 +1363,15 @@ typedef pid_t process_id_t;
|
|||||||
#define MONGOOSE_IDLE_TIMEOUT_SECONDS 300
|
#define MONGOOSE_IDLE_TIMEOUT_SECONDS 300
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef NS_DISABLE_SOCKETPAIR
|
#if defined(NS_DISABLE_SOCKETPAIR) && !defined(MONGOOSE_NO_CGI)
|
||||||
#define MONGOOSE_NO_CGI
|
#define MONGOOSE_NO_CGI
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MONGOOSE_NO_FILESYSTEM
|
#ifdef MONGOOSE_NO_FILESYSTEM
|
||||||
#define MONGOOSE_NO_AUTH
|
#define MONGOOSE_NO_AUTH
|
||||||
|
#if !defined(MONGOOSE_NO_CGI)
|
||||||
#define MONGOOSE_NO_CGI
|
#define MONGOOSE_NO_CGI
|
||||||
|
#endif
|
||||||
#define MONGOOSE_NO_DAV
|
#define MONGOOSE_NO_DAV
|
||||||
#define MONGOOSE_NO_DIRECTORY_LISTING
|
#define MONGOOSE_NO_DIRECTORY_LISTING
|
||||||
#define MONGOOSE_NO_LOGGING
|
#define MONGOOSE_NO_LOGGING
|
||||||
@@ -1323,7 +1381,7 @@ typedef pid_t process_id_t;
|
|||||||
|
|
||||||
struct vec {
|
struct vec {
|
||||||
const char *ptr;
|
const char *ptr;
|
||||||
int len;
|
size_t len;
|
||||||
};
|
};
|
||||||
|
|
||||||
// For directory listing and WevDAV support
|
// For directory listing and WevDAV support
|
||||||
@@ -1346,6 +1404,7 @@ enum {
|
|||||||
CGI_PATTERN,
|
CGI_PATTERN,
|
||||||
#endif
|
#endif
|
||||||
DAV_AUTH_FILE,
|
DAV_AUTH_FILE,
|
||||||
|
DAV_ROOT,
|
||||||
DOCUMENT_ROOT,
|
DOCUMENT_ROOT,
|
||||||
#ifndef MONGOOSE_NO_DIRECTORY_LISTING
|
#ifndef MONGOOSE_NO_DIRECTORY_LISTING
|
||||||
ENABLE_DIRECTORY_LISTING,
|
ENABLE_DIRECTORY_LISTING,
|
||||||
@@ -1384,6 +1443,7 @@ static const char *static_config_options[] = {
|
|||||||
"cgi_pattern", DEFAULT_CGI_PATTERN,
|
"cgi_pattern", DEFAULT_CGI_PATTERN,
|
||||||
#endif
|
#endif
|
||||||
"dav_auth_file", NULL,
|
"dav_auth_file", NULL,
|
||||||
|
"dav_root", NULL,
|
||||||
"document_root", NULL,
|
"document_root", NULL,
|
||||||
#ifndef MONGOOSE_NO_DIRECTORY_LISTING
|
#ifndef MONGOOSE_NO_DIRECTORY_LISTING
|
||||||
"enable_directory_listing", "yes",
|
"enable_directory_listing", "yes",
|
||||||
@@ -1428,7 +1488,7 @@ enum endpoint_type {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define MG_HEADERS_SENT NSF_USER_1
|
#define MG_HEADERS_SENT NSF_USER_1
|
||||||
#define MG_LONG_RUNNING NSF_USER_2
|
#define MG_USING_CHUNKED_API NSF_USER_2
|
||||||
#define MG_CGI_CONN NSF_USER_3
|
#define MG_CGI_CONN NSF_USER_3
|
||||||
#define MG_PROXY_CONN NSF_USER_4
|
#define MG_PROXY_CONN NSF_USER_4
|
||||||
#define MG_PROXY_DONT_PARSE NSF_USER_5
|
#define MG_PROXY_DONT_PARSE NSF_USER_5
|
||||||
@@ -1443,7 +1503,7 @@ struct connection {
|
|||||||
char *request;
|
char *request;
|
||||||
int64_t num_bytes_recv; // Total number of bytes received
|
int64_t num_bytes_recv; // Total number of bytes received
|
||||||
int64_t cl; // Reply content length, for Range support
|
int64_t cl; // Reply content length, for Range support
|
||||||
int request_len; // Request length, including last \r\n after last header
|
ssize_t request_len; // Request length, including last \r\n after last header
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MG_CONN_2_CONN(c) ((struct connection *) ((char *) (c) - \
|
#define MG_CONN_2_CONN(c) ((struct connection *) ((char *) (c) - \
|
||||||
@@ -1463,7 +1523,7 @@ static const struct {
|
|||||||
{".shtm", 5, "text/html"},
|
{".shtm", 5, "text/html"},
|
||||||
{".shtml", 6, "text/html"},
|
{".shtml", 6, "text/html"},
|
||||||
{".css", 4, "text/css"},
|
{".css", 4, "text/css"},
|
||||||
{".js", 3, "application/x-javascript"},
|
{".js", 3, "application/javascript"},
|
||||||
{".ico", 4, "image/x-icon"},
|
{".ico", 4, "image/x-icon"},
|
||||||
{".gif", 4, "image/gif"},
|
{".gif", 4, "image/gif"},
|
||||||
{".jpg", 4, "image/jpeg"},
|
{".jpg", 4, "image/jpeg"},
|
||||||
@@ -1508,11 +1568,11 @@ static const struct {
|
|||||||
{NULL, 0, NULL}
|
{NULL, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef MONGOOSE_NO_THREADS
|
#ifdef MONGOOSE_ENABLE_THREADS
|
||||||
void *mg_start_thread(void *(*f)(void *), void *p) {
|
void *mg_start_thread(void *(*f)(void *), void *p) {
|
||||||
return ns_start_thread(f, p);
|
return ns_start_thread(f, p);
|
||||||
}
|
}
|
||||||
#endif // MONGOOSE_NO_THREADS
|
#endif // MONGOOSE_ENABLE_THREADS
|
||||||
|
|
||||||
#ifndef MONGOOSE_NO_MMAP
|
#ifndef MONGOOSE_NO_MMAP
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -1528,6 +1588,37 @@ static void *mmap(void *addr, int64_t len, int prot, int flags, int fd,
|
|||||||
#define MAP_FAILED NULL
|
#define MAP_FAILED NULL
|
||||||
#define MAP_PRIVATE 0
|
#define MAP_PRIVATE 0
|
||||||
#define PROT_READ 0
|
#define PROT_READ 0
|
||||||
|
#elif defined(__OS2__)
|
||||||
|
static void *mmap(void *addr, int64_t len, int prot, int flags, int fd,
|
||||||
|
int offset) {
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
int pos = lseek( fd, 0, SEEK_CUR ); /* Get a current position */
|
||||||
|
|
||||||
|
if (pos == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Seek to offset offset */
|
||||||
|
if (lseek( fd, offset, SEEK_SET) == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
p = malloc(len);
|
||||||
|
|
||||||
|
/* Read in a file */
|
||||||
|
if (!p || read(fd, p, len) == -1) {
|
||||||
|
free(p);
|
||||||
|
p = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restore the position */
|
||||||
|
lseek(fd, pos, SEEK_SET);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
#define munmap(x, y) free(x)
|
||||||
|
#define MAP_FAILED NULL
|
||||||
|
#define MAP_PRIVATE 0
|
||||||
|
#define PROT_READ 0
|
||||||
#else
|
#else
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -1654,9 +1745,9 @@ static int mg_snprintf(char *buf, size_t buflen, const char *fmt, ...) {
|
|||||||
// -1 if request is malformed
|
// -1 if request is malformed
|
||||||
// 0 if request is not yet fully buffered
|
// 0 if request is not yet fully buffered
|
||||||
// >0 actual request length, including last \r\n\r\n
|
// >0 actual request length, including last \r\n\r\n
|
||||||
static int get_request_len(const char *s, int buf_len) {
|
static int get_request_len(const char *s, size_t buf_len) {
|
||||||
const unsigned char *buf = (unsigned char *) s;
|
const unsigned char *buf = (unsigned char *) s;
|
||||||
int i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < buf_len; i++) {
|
for (i = 0; i < buf_len; i++) {
|
||||||
// Control characters are not allowed but >=128 are.
|
// Control characters are not allowed but >=128 are.
|
||||||
@@ -1890,7 +1981,7 @@ static void *push_to_stdin(void *arg) {
|
|||||||
}
|
}
|
||||||
DBG(("%s", "FORWARED EVERYTHING TO CGI"));
|
DBG(("%s", "FORWARED EVERYTHING TO CGI"));
|
||||||
CloseHandle(tp->hPipe);
|
CloseHandle(tp->hPipe);
|
||||||
free(tp);
|
NS_FREE(tp);
|
||||||
_endthread();
|
_endthread();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1911,14 +2002,14 @@ static void *pull_from_stdout(void *arg) {
|
|||||||
CloseHandle(tp->hPipe);
|
CloseHandle(tp->hPipe);
|
||||||
shutdown(tp->s, 2); // Without this, IO thread may get truncated data
|
shutdown(tp->s, 2); // Without this, IO thread may get truncated data
|
||||||
closesocket(tp->s);
|
closesocket(tp->s);
|
||||||
free(tp);
|
NS_FREE(tp);
|
||||||
_endthread();
|
_endthread();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spawn_stdio_thread(sock_t sock, HANDLE hPipe,
|
static void spawn_stdio_thread(sock_t sock, HANDLE hPipe,
|
||||||
void *(*func)(void *)) {
|
void *(*func)(void *)) {
|
||||||
struct threadparam *tp = (struct threadparam *)malloc(sizeof(*tp));
|
struct threadparam *tp = (struct threadparam *)NS_MALLOC(sizeof(*tp));
|
||||||
if (tp != NULL) {
|
if (tp != NULL) {
|
||||||
tp->s = sock;
|
tp->s = sock;
|
||||||
tp->hPipe = hPipe;
|
tp->hPipe = hPipe;
|
||||||
@@ -2247,7 +2338,7 @@ static void on_cgi_data(struct ns_connection *nc) {
|
|||||||
// If reply has not been parsed yet, parse it
|
// If reply has not been parsed yet, parse it
|
||||||
if (conn->ns_conn->flags & NSF_BUFFER_BUT_DONT_SEND) {
|
if (conn->ns_conn->flags & NSF_BUFFER_BUT_DONT_SEND) {
|
||||||
struct iobuf *io = &conn->ns_conn->send_iobuf;
|
struct iobuf *io = &conn->ns_conn->send_iobuf;
|
||||||
int s_len = sizeof(cgi_status) - 1;
|
size_t s_len = sizeof(cgi_status) - 1;
|
||||||
int len = get_request_len(io->buf + s_len, io->len - s_len);
|
int len = get_request_len(io->buf + s_len, io->len - s_len);
|
||||||
char buf[MAX_REQUEST_SIZE], *s = buf;
|
char buf[MAX_REQUEST_SIZE], *s = buf;
|
||||||
|
|
||||||
@@ -2277,7 +2368,7 @@ static void on_cgi_data(struct ns_connection *nc) {
|
|||||||
#endif // !MONGOOSE_NO_CGI
|
#endif // !MONGOOSE_NO_CGI
|
||||||
|
|
||||||
static char *mg_strdup(const char *str) {
|
static char *mg_strdup(const char *str) {
|
||||||
char *copy = (char *) malloc(strlen(str) + 1);
|
char *copy = (char *) NS_MALLOC(strlen(str) + 1);
|
||||||
if (copy != NULL) {
|
if (copy != NULL) {
|
||||||
strcpy(copy, str);
|
strcpy(copy, str);
|
||||||
}
|
}
|
||||||
@@ -2339,7 +2430,9 @@ static void remove_double_dots_and_double_slashes(char *s) {
|
|||||||
// Skip all following slashes, backslashes and double-dots
|
// Skip all following slashes, backslashes and double-dots
|
||||||
while (s[0] != '\0') {
|
while (s[0] != '\0') {
|
||||||
if (s[0] == '/' || s[0] == '\\') { s++; }
|
if (s[0] == '/' || s[0] == '\\') { s++; }
|
||||||
else if (s[0] == '.' && s[1] == '.') { s += 2; }
|
else if (s[0] == '.' && (s[1] == '/' || s[1] == '\\')) { s += 2; }
|
||||||
|
else if (s[0] == '.' && s[1] == '.' && s[2] == '\0') { s += 2; }
|
||||||
|
else if (s[0] == '.' && s[1] == '.' && (s[2] == '/' || s[2] == '\\')) { s += 3; }
|
||||||
else { break; }
|
else { break; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2347,13 +2440,14 @@ static void remove_double_dots_and_double_slashes(char *s) {
|
|||||||
*p = '\0';
|
*p = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_url_decode(const char *src, int src_len, char *dst,
|
int mg_url_decode(const char *src, size_t src_len, char *dst,
|
||||||
int dst_len, int is_form_url_encoded) {
|
size_t dst_len, int is_form_url_encoded) {
|
||||||
int i, j, a, b;
|
size_t i, j = 0;
|
||||||
#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
|
int a, b;
|
||||||
|
#define HEXTOI(x) (isdigit(x) ? (x) - '0' : (x) - 'W')
|
||||||
|
|
||||||
for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) {
|
for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) {
|
||||||
if (src[i] == '%' && i < src_len - 2 &&
|
if (src[i] == '%' && i + 2 < src_len &&
|
||||||
isxdigit(* (const unsigned char *) (src + i + 1)) &&
|
isxdigit(* (const unsigned char *) (src + i + 1)) &&
|
||||||
isxdigit(* (const unsigned char *) (src + i + 2))) {
|
isxdigit(* (const unsigned char *) (src + i + 2))) {
|
||||||
a = tolower(* (const unsigned char *) (src + i + 1));
|
a = tolower(* (const unsigned char *) (src + i + 1));
|
||||||
@@ -2382,7 +2476,8 @@ static int is_valid_http_method(const char *s) {
|
|||||||
// This function modifies the buffer by NUL-terminating
|
// This function modifies the buffer by NUL-terminating
|
||||||
// HTTP request components, header names and header values.
|
// HTTP request components, header names and header values.
|
||||||
// Note that len must point to the last \n of HTTP headers.
|
// Note that len must point to the last \n of HTTP headers.
|
||||||
static int parse_http_message(char *buf, int len, struct mg_connection *ri) {
|
static size_t parse_http_message(char *buf, size_t len,
|
||||||
|
struct mg_connection *ri) {
|
||||||
int is_request, n;
|
int is_request, n;
|
||||||
|
|
||||||
// Reset the connection. Make sure that we don't touch fields that are
|
// Reset the connection. Make sure that we don't touch fields that are
|
||||||
@@ -2390,6 +2485,8 @@ static int parse_http_message(char *buf, int len, struct mg_connection *ri) {
|
|||||||
ri->request_method = ri->uri = ri->http_version = ri->query_string = NULL;
|
ri->request_method = ri->uri = ri->http_version = ri->query_string = NULL;
|
||||||
ri->num_headers = ri->status_code = ri->is_websocket = ri->content_len = 0;
|
ri->num_headers = ri->status_code = ri->is_websocket = ri->content_len = 0;
|
||||||
|
|
||||||
|
if (len < 1) return ~0;
|
||||||
|
|
||||||
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 ingored
|
||||||
@@ -2405,7 +2502,7 @@ static int parse_http_message(char *buf, int len, struct mg_connection *ri) {
|
|||||||
is_request = is_valid_http_method(ri->request_method);
|
is_request = is_valid_http_method(ri->request_method);
|
||||||
if ((is_request && memcmp(ri->http_version, "HTTP/", 5) != 0) ||
|
if ((is_request && memcmp(ri->http_version, "HTTP/", 5) != 0) ||
|
||||||
(!is_request && memcmp(ri->request_method, "HTTP/", 5) != 0)) {
|
(!is_request && memcmp(ri->request_method, "HTTP/", 5) != 0)) {
|
||||||
len = -1;
|
len = ~0;
|
||||||
} else {
|
} else {
|
||||||
if (is_request) {
|
if (is_request) {
|
||||||
ri->http_version += 5;
|
ri->http_version += 5;
|
||||||
@@ -2464,7 +2561,7 @@ const char *mg_get_header(const struct mg_connection *ri, const char *s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Perform case-insensitive match of string against pattern
|
// Perform case-insensitive match of string against pattern
|
||||||
int mg_match_prefix(const char *pattern, int pattern_len, const char *str) {
|
int mg_match_prefix(const char *pattern, ssize_t pattern_len, const char *str) {
|
||||||
const char *or_str;
|
const char *or_str;
|
||||||
int len, res, i = 0, j = 0;
|
int len, res, i = 0, j = 0;
|
||||||
|
|
||||||
@@ -2536,6 +2633,12 @@ void mg_template(struct mg_connection *conn, const char *s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef MONGOOSE_NO_FILESYSTEM
|
#ifndef MONGOOSE_NO_FILESYSTEM
|
||||||
|
static int is_dav_request(const struct connection *conn) {
|
||||||
|
const char *s = conn->mg_conn.request_method;
|
||||||
|
return !strcmp(s, "PUT") || !strcmp(s, "DELETE") ||
|
||||||
|
!strcmp(s, "MKCOL") || !strcmp(s, "PROPFIND");
|
||||||
|
}
|
||||||
|
|
||||||
static int must_hide_file(struct connection *conn, const char *path) {
|
static int must_hide_file(struct connection *conn, const char *path) {
|
||||||
const char *pw_pattern = "**" PASSWORDS_FILE_NAME "$";
|
const char *pw_pattern = "**" PASSWORDS_FILE_NAME "$";
|
||||||
const char *pattern = conn->server->config_options[HIDE_FILES_PATTERN];
|
const char *pattern = conn->server->config_options[HIDE_FILES_PATTERN];
|
||||||
@@ -2548,19 +2651,24 @@ static int convert_uri_to_file_name(struct connection *conn, char *buf,
|
|||||||
size_t buf_len, file_stat_t *st) {
|
size_t buf_len, file_stat_t *st) {
|
||||||
struct vec a, b;
|
struct vec a, b;
|
||||||
const char *rewrites = conn->server->config_options[URL_REWRITES];
|
const char *rewrites = conn->server->config_options[URL_REWRITES];
|
||||||
const char *root = conn->server->config_options[DOCUMENT_ROOT];
|
const char *root =
|
||||||
|
#ifndef MONGOOSE_NO_DAV
|
||||||
|
is_dav_request(conn) && conn->server->config_options[DAV_ROOT] != NULL ?
|
||||||
|
conn->server->config_options[DAV_ROOT] :
|
||||||
|
#endif
|
||||||
|
conn->server->config_options[DOCUMENT_ROOT];
|
||||||
#ifndef MONGOOSE_NO_CGI
|
#ifndef MONGOOSE_NO_CGI
|
||||||
const char *cgi_pat = conn->server->config_options[CGI_PATTERN];
|
const char *cgi_pat = conn->server->config_options[CGI_PATTERN];
|
||||||
char *p;
|
char *p;
|
||||||
#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");
|
||||||
int match_len, root_len = root == NULL ? 0 : strlen(root);
|
size_t 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) {
|
||||||
const char *colon = strchr(domain, ':');
|
const char *colon = strchr(domain, ':');
|
||||||
int domain_len = colon == NULL ? (int) strlen(domain) : colon - domain;
|
size_t domain_len = colon == NULL ? strlen(domain) : colon - domain;
|
||||||
|
|
||||||
while ((rewrites = next_option(rewrites, &a, &b)) != NULL) {
|
while ((rewrites = next_option(rewrites, &a, &b)) != NULL) {
|
||||||
if (a.len > 1 && a.ptr[0] == '@' && a.len == domain_len + 1 &&
|
if (a.len > 1 && a.ptr[0] == '@' && a.len == domain_len + 1 &&
|
||||||
@@ -2620,25 +2728,29 @@ static int should_keep_alive(const struct mg_connection *conn) {
|
|||||||
(header == NULL && http_version && !strcmp(http_version, "1.1")));
|
(header == NULL && http_version && !strcmp(http_version, "1.1")));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t mg_write(struct mg_connection *c, const void *buf, int len) {
|
size_t mg_write(struct mg_connection *c, const void *buf, size_t len) {
|
||||||
struct connection *conn = MG_CONN_2_CONN(c);
|
struct connection *conn = MG_CONN_2_CONN(c);
|
||||||
ns_send(conn->ns_conn, buf, len);
|
ns_send(conn->ns_conn, buf, len);
|
||||||
return conn->ns_conn->send_iobuf.len;
|
return conn->ns_conn->send_iobuf.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_send_status(struct mg_connection *c, int status) {
|
void mg_send_status(struct mg_connection *c, int status) {
|
||||||
|
struct connection *conn = MG_CONN_2_CONN(c);
|
||||||
if (c->status_code == 0) {
|
if (c->status_code == 0) {
|
||||||
c->status_code = status;
|
c->status_code = status;
|
||||||
mg_printf(c, "HTTP/1.1 %d %s\r\n", status, status_code_to_str(status));
|
mg_printf(c, "HTTP/1.1 %d %s\r\n", status, status_code_to_str(status));
|
||||||
}
|
}
|
||||||
|
conn->ns_conn->flags |= MG_USING_CHUNKED_API;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_send_header(struct mg_connection *c, const char *name, const char *v) {
|
void mg_send_header(struct mg_connection *c, const char *name, const char *v) {
|
||||||
|
struct connection *conn = MG_CONN_2_CONN(c);
|
||||||
if (c->status_code == 0) {
|
if (c->status_code == 0) {
|
||||||
c->status_code = 200;
|
c->status_code = 200;
|
||||||
mg_printf(c, "HTTP/1.1 %d %s\r\n", 200, status_code_to_str(200));
|
mg_printf(c, "HTTP/1.1 %d %s\r\n", 200, status_code_to_str(200));
|
||||||
}
|
}
|
||||||
mg_printf(c, "%s: %s\r\n", name, v);
|
mg_printf(c, "%s: %s\r\n", name, v);
|
||||||
|
conn->ns_conn->flags |= MG_USING_CHUNKED_API;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void terminate_headers(struct mg_connection *c) {
|
static void terminate_headers(struct mg_connection *c) {
|
||||||
@@ -2673,7 +2785,7 @@ size_t mg_printf_data(struct mg_connection *c, const char *fmt, ...) {
|
|||||||
write_chunk((struct connection *) conn, buf, len);
|
write_chunk((struct connection *) conn, buf, len);
|
||||||
}
|
}
|
||||||
if (buf != mem && buf != NULL) {
|
if (buf != mem && buf != NULL) {
|
||||||
free(buf);
|
NS_FREE(buf);
|
||||||
}
|
}
|
||||||
return conn->ns_conn->send_iobuf.len;
|
return conn->ns_conn->send_iobuf.len;
|
||||||
}
|
}
|
||||||
@@ -2780,8 +2892,8 @@ static void SHA1Init(SHA1_CTX *context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void SHA1Update(SHA1_CTX *context, const unsigned char *data,
|
static void SHA1Update(SHA1_CTX *context, const unsigned char *data,
|
||||||
uint32_t len) {
|
size_t len) {
|
||||||
uint32_t i, j;
|
size_t i, j;
|
||||||
|
|
||||||
j = context->count[0];
|
j = context->count[0];
|
||||||
if ((context->count[0] += len << 3) < j)
|
if ((context->count[0] += len << 3) < j)
|
||||||
@@ -2869,10 +2981,10 @@ static void send_websocket_handshake(struct mg_connection *conn,
|
|||||||
mg_write(conn, buf, strlen(buf));
|
mg_write(conn, buf, strlen(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int deliver_websocket_frame(struct connection *conn) {
|
static size_t deliver_websocket_frame(struct connection *conn) {
|
||||||
// Having buf unsigned char * is important, as it is used below in arithmetic
|
// Having buf unsigned char * is important, as it is used below in arithmetic
|
||||||
unsigned char *buf = (unsigned char *) conn->ns_conn->recv_iobuf.buf;
|
unsigned char *buf = (unsigned char *) conn->ns_conn->recv_iobuf.buf;
|
||||||
int i, len, buf_len = conn->ns_conn->recv_iobuf.len, frame_len = 0,
|
size_t i, len, buf_len = conn->ns_conn->recv_iobuf.len, frame_len = 0,
|
||||||
mask_len = 0, header_len = 0, data_len = 0, buffered = 0;
|
mask_len = 0, header_len = 0, data_len = 0, buffered = 0;
|
||||||
|
|
||||||
if (buf_len >= 2) {
|
if (buf_len >= 2) {
|
||||||
@@ -2883,10 +2995,10 @@ static int deliver_websocket_frame(struct connection *conn) {
|
|||||||
header_len = 2 + mask_len;
|
header_len = 2 + mask_len;
|
||||||
} else if (len == 126 && buf_len >= 4 + mask_len) {
|
} else if (len == 126 && buf_len >= 4 + mask_len) {
|
||||||
header_len = 4 + mask_len;
|
header_len = 4 + mask_len;
|
||||||
data_len = ((((int) buf[2]) << 8) + buf[3]);
|
data_len = ((((size_t) buf[2]) << 8) + buf[3]);
|
||||||
} else if (buf_len >= 10 + mask_len) {
|
} else if (buf_len >= 10 + mask_len) {
|
||||||
header_len = 10 + mask_len;
|
header_len = 10 + mask_len;
|
||||||
data_len = (int) (((uint64_t) htonl(* (uint32_t *) &buf[2])) << 32) +
|
data_len = (size_t) (((uint64_t) htonl(* (uint32_t *) &buf[2])) << 32) +
|
||||||
htonl(* (uint32_t *) &buf[6]);
|
htonl(* (uint32_t *) &buf[6]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2921,8 +3033,13 @@ size_t mg_websocket_write(struct mg_connection *conn, int opcode,
|
|||||||
unsigned char mem[4192], *copy = mem;
|
unsigned char mem[4192], *copy = mem;
|
||||||
size_t copy_len = 0;
|
size_t copy_len = 0;
|
||||||
|
|
||||||
|
/* Check overflow */
|
||||||
|
if (data_len > ~(size_t)0 - (size_t)10) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (data_len + 10 > sizeof(mem) &&
|
if (data_len + 10 > sizeof(mem) &&
|
||||||
(copy = (unsigned char *) malloc(data_len + 10)) == NULL) {
|
(copy = (unsigned char *) NS_MALLOC(data_len + 10)) == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2942,10 +3059,11 @@ size_t mg_websocket_write(struct mg_connection *conn, int opcode,
|
|||||||
copy_len = 4 + data_len;
|
copy_len = 4 + data_len;
|
||||||
} else {
|
} else {
|
||||||
// 64-bit length field
|
// 64-bit length field
|
||||||
|
const uint32_t hi = htonl((uint32_t) ((uint64_t) data_len >> 32));
|
||||||
|
const uint32_t lo = htonl(data_len & 0xffffffff);
|
||||||
copy[1] = 127;
|
copy[1] = 127;
|
||||||
* (uint32_t *) (copy + 2) = (uint32_t)
|
memcpy(copy+2,&hi,sizeof(hi));
|
||||||
htonl((uint32_t) ((uint64_t) data_len >> 32));
|
memcpy(copy+6,&lo,sizeof(lo));
|
||||||
* (uint32_t *) (copy + 6) = (uint32_t) htonl(data_len & 0xffffffff);
|
|
||||||
memcpy(copy + 10, data, data_len);
|
memcpy(copy + 10, data, data_len);
|
||||||
copy_len = 10 + data_len;
|
copy_len = 10 + data_len;
|
||||||
}
|
}
|
||||||
@@ -2954,7 +3072,7 @@ size_t mg_websocket_write(struct mg_connection *conn, int opcode,
|
|||||||
mg_write(conn, copy, copy_len);
|
mg_write(conn, copy, copy_len);
|
||||||
}
|
}
|
||||||
if (copy != mem) {
|
if (copy != mem) {
|
||||||
free(copy);
|
NS_FREE(copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we send closing frame, schedule a connection to be closed after
|
// If we send closing frame, schedule a connection to be closed after
|
||||||
@@ -2979,7 +3097,7 @@ size_t mg_websocket_printf(struct mg_connection *conn, int opcode,
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if (buf != mem && buf != NULL) {
|
if (buf != mem && buf != NULL) {
|
||||||
free(buf);
|
NS_FREE(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
return MG_CONN_2_CONN(conn)->ns_conn->send_iobuf.len;
|
return MG_CONN_2_CONN(conn)->ns_conn->send_iobuf.len;
|
||||||
@@ -3014,7 +3132,8 @@ static int call_request_handler(struct connection *conn) {
|
|||||||
int result;
|
int result;
|
||||||
conn->mg_conn.content = conn->ns_conn->recv_iobuf.buf;
|
conn->mg_conn.content = conn->ns_conn->recv_iobuf.buf;
|
||||||
if ((result = call_user(conn, MG_REQUEST)) == MG_TRUE) {
|
if ((result = call_user(conn, MG_REQUEST)) == MG_TRUE) {
|
||||||
if (conn->ns_conn->flags & MG_HEADERS_SENT) {
|
if (conn->ns_conn->flags & MG_USING_CHUNKED_API) {
|
||||||
|
terminate_headers(&conn->mg_conn);
|
||||||
write_terminating_chunk(conn);
|
write_terminating_chunk(conn);
|
||||||
}
|
}
|
||||||
close_local_endpoint(conn);
|
close_local_endpoint(conn);
|
||||||
@@ -3141,7 +3260,8 @@ static int find_index_file(struct connection *conn, char *path,
|
|||||||
const char *list = conn->server->config_options[INDEX_FILES];
|
const char *list = conn->server->config_options[INDEX_FILES];
|
||||||
file_stat_t st;
|
file_stat_t st;
|
||||||
struct vec filename_vec;
|
struct vec filename_vec;
|
||||||
size_t n = strlen(path), found = 0;
|
size_t n = strlen(path);
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
// The 'path' given to us points to the directory. Remove all trailing
|
// The 'path' given to us points to the directory. Remove all trailing
|
||||||
// directory separator characters from the end of the path, and
|
// directory separator characters from the end of the path, and
|
||||||
@@ -3155,8 +3275,12 @@ static int find_index_file(struct connection *conn, char *path,
|
|||||||
// path and see if the file exists. If it exists, break the loop
|
// path and see if the file exists. If it exists, break the loop
|
||||||
while ((list = next_option(list, &filename_vec, NULL)) != NULL) {
|
while ((list = next_option(list, &filename_vec, NULL)) != NULL) {
|
||||||
|
|
||||||
|
if (path_len <= n + 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Ignore too long entries that may overflow path buffer
|
// Ignore too long entries that may overflow path buffer
|
||||||
if (filename_vec.len > (int) (path_len - (n + 2)))
|
if (filename_vec.len > (path_len - (n + 2)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Prepare full path to the index file
|
// Prepare full path to the index file
|
||||||
@@ -3292,7 +3416,7 @@ static DIR *opendir(const char *name) {
|
|||||||
|
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
SetLastError(ERROR_BAD_ARGUMENTS);
|
SetLastError(ERROR_BAD_ARGUMENTS);
|
||||||
} else if ((dir = (DIR *) malloc(sizeof(*dir))) == NULL) {
|
} else if ((dir = (DIR *) NS_MALLOC(sizeof(*dir))) == NULL) {
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
} else {
|
} else {
|
||||||
to_wchar(name, wpath, ARRAY_SIZE(wpath));
|
to_wchar(name, wpath, ARRAY_SIZE(wpath));
|
||||||
@@ -3303,7 +3427,7 @@ static DIR *opendir(const char *name) {
|
|||||||
dir->handle = FindFirstFileW(wpath, &dir->info);
|
dir->handle = FindFirstFileW(wpath, &dir->info);
|
||||||
dir->result.d_name[0] = '\0';
|
dir->result.d_name[0] = '\0';
|
||||||
} else {
|
} else {
|
||||||
free(dir);
|
NS_FREE(dir);
|
||||||
dir = NULL;
|
dir = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3318,7 +3442,7 @@ static int closedir(DIR *dir) {
|
|||||||
if (dir->handle != INVALID_HANDLE_VALUE)
|
if (dir->handle != INVALID_HANDLE_VALUE)
|
||||||
result = FindClose(dir->handle) ? 0 : -1;
|
result = FindClose(dir->handle) ? 0 : -1;
|
||||||
|
|
||||||
free(dir);
|
NS_FREE(dir);
|
||||||
} else {
|
} else {
|
||||||
result = -1;
|
result = -1;
|
||||||
SetLastError(ERROR_BAD_ARGUMENTS);
|
SetLastError(ERROR_BAD_ARGUMENTS);
|
||||||
@@ -3376,7 +3500,7 @@ static int scan_directory(struct connection *conn, const char *dir,
|
|||||||
// Resize the array if nesessary
|
// Resize the array if nesessary
|
||||||
if (arr_ind >= arr_size) {
|
if (arr_ind >= arr_size) {
|
||||||
if ((p = (struct dir_entry *)
|
if ((p = (struct dir_entry *)
|
||||||
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, otherwize 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
|
||||||
@@ -3399,7 +3523,7 @@ static int scan_directory(struct connection *conn, const char *dir,
|
|||||||
return arr_ind;
|
return arr_ind;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_url_encode(const char *src, size_t s_len, char *dst, size_t dst_len) {
|
size_t mg_url_encode(const char *src, size_t s_len, char *dst, size_t dst_len) {
|
||||||
static const char *dont_escape = "._-$,;~()";
|
static const char *dont_escape = "._-$,;~()";
|
||||||
static const char *hex = "0123456789abcdef";
|
static const char *hex = "0123456789abcdef";
|
||||||
size_t i = 0, j = 0;
|
size_t i = 0, j = 0;
|
||||||
@@ -3502,9 +3626,9 @@ static void send_directory_listing(struct connection *conn, const char *dir) {
|
|||||||
qsort(arr, num_entries, sizeof(arr[0]), compare_dir_entries);
|
qsort(arr, num_entries, sizeof(arr[0]), compare_dir_entries);
|
||||||
for (i = 0; i < num_entries; i++) {
|
for (i = 0; i < num_entries; i++) {
|
||||||
print_dir_entry(&arr[i]);
|
print_dir_entry(&arr[i]);
|
||||||
free(arr[i].file_name);
|
NS_FREE(arr[i].file_name);
|
||||||
}
|
}
|
||||||
free(arr);
|
NS_FREE(arr);
|
||||||
|
|
||||||
write_terminating_chunk(conn);
|
write_terminating_chunk(conn);
|
||||||
close_local_endpoint(conn);
|
close_local_endpoint(conn);
|
||||||
@@ -3572,9 +3696,9 @@ static void handle_propfind(struct connection *conn, const char *path,
|
|||||||
struct dir_entry *de = &arr[i];
|
struct dir_entry *de = &arr[i];
|
||||||
mg_url_encode(de->file_name, strlen(de->file_name), buf, sizeof(buf));
|
mg_url_encode(de->file_name, strlen(de->file_name), buf, sizeof(buf));
|
||||||
print_props(conn, buf, &de->st);
|
print_props(conn, buf, &de->st);
|
||||||
free(de->file_name);
|
NS_FREE(de->file_name);
|
||||||
}
|
}
|
||||||
free(arr);
|
NS_FREE(arr);
|
||||||
}
|
}
|
||||||
ns_send(conn->ns_conn, footer, sizeof(footer) - 1);
|
ns_send(conn->ns_conn, footer, sizeof(footer) - 1);
|
||||||
}
|
}
|
||||||
@@ -3696,7 +3820,7 @@ static void handle_put(struct connection *conn, const char *path) {
|
|||||||
static void forward_put_data(struct connection *conn) {
|
static void forward_put_data(struct connection *conn) {
|
||||||
struct iobuf *io = &conn->ns_conn->recv_iobuf;
|
struct iobuf *io = &conn->ns_conn->recv_iobuf;
|
||||||
size_t k = conn->cl < (int64_t) io->len ? conn->cl : (int64_t) io->len; // To write
|
size_t k = conn->cl < (int64_t) io->len ? conn->cl : (int64_t) io->len; // To write
|
||||||
int n = write(conn->endpoint.fd, io->buf, k); // Write them!
|
size_t n = write(conn->endpoint.fd, io->buf, k); // Write them!
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
iobuf_remove(io, n);
|
iobuf_remove(io, n);
|
||||||
conn->cl -= n;
|
conn->cl -= n;
|
||||||
@@ -3754,6 +3878,23 @@ static FILE *open_auth_file(struct connection *conn, const char *path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(HAVE_MD5) && !defined(MONGOOSE_NO_AUTH)
|
#if !defined(HAVE_MD5) && !defined(MONGOOSE_NO_AUTH)
|
||||||
|
/*
|
||||||
|
* This code implements the MD5 message-digest algorithm.
|
||||||
|
* The algorithm is due to Ron Rivest. This code was
|
||||||
|
* written by Colin Plumb in 1993, no copyright is claimed.
|
||||||
|
* This code is in the public domain; do with it what you wish.
|
||||||
|
*
|
||||||
|
* Equivalent code is available from RSA Data Security, Inc.
|
||||||
|
* This code has been tested against that, and is equivalent,
|
||||||
|
* except that you don't need to include two pages of legalese
|
||||||
|
* with every copy.
|
||||||
|
*
|
||||||
|
* To compute the message digest of a chunk of bytes, declare an
|
||||||
|
* MD5Context structure, pass it to MD5Init, call MD5Update as
|
||||||
|
* needed on buffers full of bytes, and then call MD5Final, which
|
||||||
|
* will fill a supplied 16-byte array with the digest.
|
||||||
|
*/
|
||||||
|
|
||||||
typedef struct MD5Context {
|
typedef struct MD5Context {
|
||||||
uint32_t buf[4];
|
uint32_t buf[4];
|
||||||
uint32_t bits[2];
|
uint32_t bits[2];
|
||||||
@@ -4058,33 +4199,28 @@ static int is_authorized_for_dav(struct connection *conn) {
|
|||||||
|
|
||||||
return authorized;
|
return authorized;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_dav_request(const struct connection *conn) {
|
|
||||||
const char *s = conn->mg_conn.request_method;
|
|
||||||
return !strcmp(s, "PUT") || !strcmp(s, "DELETE") ||
|
|
||||||
!strcmp(s, "MKCOL") || !strcmp(s, "PROPFIND");
|
|
||||||
}
|
|
||||||
#endif // MONGOOSE_NO_AUTH
|
#endif // MONGOOSE_NO_AUTH
|
||||||
|
|
||||||
static int parse_header(const char *str, int str_len, const char *var_name,
|
static int parse_header(const char *str, size_t str_len, const char *var_name,
|
||||||
char *buf, size_t buf_size) {
|
char *buf, size_t buf_size) {
|
||||||
int ch = ' ', len = 0, n = strlen(var_name);
|
int ch = ' ', ch1 = ',', len = 0;
|
||||||
|
size_t n = strlen(var_name);
|
||||||
const char *p, *end = str + str_len, *s = NULL;
|
const char *p, *end = str + str_len, *s = NULL;
|
||||||
|
|
||||||
if (buf != NULL && buf_size > 0) buf[0] = '\0';
|
if (buf != NULL && buf_size > 0) buf[0] = '\0';
|
||||||
|
|
||||||
// Find where variable starts
|
// Find where variable starts
|
||||||
for (s = str; s != NULL && s + n < end; s++) {
|
for (s = str; s != NULL && s + n < end; s++) {
|
||||||
if ((s == str || s[-1] == ' ' || s[-1] == ',') && s[n] == '=' &&
|
if ((s == str || s[-1] == ch || s[-1] == ch1) && s[n] == '=' &&
|
||||||
!memcmp(s, var_name, n)) break;
|
!memcmp(s, var_name, n)) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s != NULL && &s[n + 1] < end) {
|
if (s != NULL && &s[n + 1] < end) {
|
||||||
s += n + 1;
|
s += n + 1;
|
||||||
if (*s == '"' || *s == '\'') ch = *s++;
|
if (*s == '"' || *s == '\'') ch = ch1 = *s++;
|
||||||
p = s;
|
p = s;
|
||||||
while (p < end && p[0] != ch && p[0] != ',' && len < (int) buf_size) {
|
while (p < end && p[0] != ch && p[0] != ch1 && len < (int) buf_size) {
|
||||||
if (p[0] == '\\' && p[1] == ch) p++;
|
if (ch == ch1 && p[0] == '\\' && p[1] == ch) p++;
|
||||||
buf[len++] = *p++;
|
buf[len++] = *p++;
|
||||||
}
|
}
|
||||||
if (len >= (int) buf_size || (ch != ' ' && *p != ch)) {
|
if (len >= (int) buf_size || (ch != ' ' && *p != ch)) {
|
||||||
@@ -4109,7 +4245,7 @@ static void send_ssi_file(struct mg_connection *, const char *, FILE *, int);
|
|||||||
|
|
||||||
static void send_file_data(struct mg_connection *conn, FILE *fp) {
|
static void send_file_data(struct mg_connection *conn, FILE *fp) {
|
||||||
char buf[IOBUF_SIZE];
|
char buf[IOBUF_SIZE];
|
||||||
int n;
|
size_t n;
|
||||||
while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) {
|
while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) {
|
||||||
mg_write(conn, buf, n);
|
mg_write(conn, buf, n);
|
||||||
}
|
}
|
||||||
@@ -4544,7 +4680,7 @@ static void try_parse(struct connection *conn) {
|
|||||||
// If request is buffered in, remove it from the iobuf. This is because
|
// If request is buffered in, remove it from the iobuf. This is because
|
||||||
// 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 *) malloc(conn->request_len);
|
conn->request = (char *) NS_MALLOC(conn->request_len);
|
||||||
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);
|
||||||
@@ -4638,7 +4774,7 @@ static void call_http_client_handler(struct connection *conn) {
|
|||||||
iobuf_remove(&conn->ns_conn->recv_iobuf, conn->mg_conn.content_len);
|
iobuf_remove(&conn->ns_conn->recv_iobuf, conn->mg_conn.content_len);
|
||||||
conn->mg_conn.status_code = 0;
|
conn->mg_conn.status_code = 0;
|
||||||
conn->cl = conn->num_bytes_recv = conn->request_len = 0;
|
conn->cl = conn->num_bytes_recv = conn->request_len = 0;
|
||||||
free(conn->request);
|
NS_FREE(conn->request);
|
||||||
conn->request = NULL;
|
conn->request = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4662,7 +4798,7 @@ struct mg_connection *mg_connect(struct mg_server *server, const char *addr) {
|
|||||||
nsconn = ns_connect(&server->ns_mgr, addr, mg_ev_handler, NULL);
|
nsconn = ns_connect(&server->ns_mgr, addr, mg_ev_handler, NULL);
|
||||||
if (nsconn == NULL) return 0;
|
if (nsconn == NULL) return 0;
|
||||||
|
|
||||||
if ((conn = (struct connection *) calloc(1, sizeof(*conn))) == NULL) {
|
if ((conn = (struct connection *) NS_CALLOC(1, sizeof(*conn))) == NULL) {
|
||||||
nsconn->flags |= NSF_CLOSE_IMMEDIATELY;
|
nsconn->flags |= NSF_CLOSE_IMMEDIATELY;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -4754,8 +4890,8 @@ static void close_local_endpoint(struct connection *conn) {
|
|||||||
|
|
||||||
// Gobble possible POST data sent to the URI handler
|
// Gobble possible POST data sent to the URI handler
|
||||||
iobuf_free(&conn->ns_conn->recv_iobuf);
|
iobuf_free(&conn->ns_conn->recv_iobuf);
|
||||||
free(conn->request);
|
NS_FREE(conn->request);
|
||||||
free(conn->path_info);
|
NS_FREE(conn->path_info);
|
||||||
conn->endpoint.nc = NULL;
|
conn->endpoint.nc = NULL;
|
||||||
conn->request = conn->path_info = NULL;
|
conn->request = conn->path_info = NULL;
|
||||||
|
|
||||||
@@ -4763,7 +4899,7 @@ static void close_local_endpoint(struct connection *conn) {
|
|||||||
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_BUFFER_BUT_DONT_SEND | NSF_CLOSE_IMMEDIATELY |
|
NSF_BUFFER_BUT_DONT_SEND | NSF_CLOSE_IMMEDIATELY |
|
||||||
MG_HEADERS_SENT | MG_LONG_RUNNING);
|
MG_HEADERS_SENT | MG_USING_CHUNKED_API);
|
||||||
|
|
||||||
// Do not memset() the whole structure, as some of the fields
|
// Do not memset() the whole structure, as some of the fields
|
||||||
// (IP addresses & ports, server_param) must survive. Nullify the rest.
|
// (IP addresses & ports, server_param) must survive. Nullify the rest.
|
||||||
@@ -4781,7 +4917,7 @@ static void close_local_endpoint(struct connection *conn) {
|
|||||||
|
|
||||||
static void transfer_file_data(struct connection *conn) {
|
static void transfer_file_data(struct connection *conn) {
|
||||||
char buf[IOBUF_SIZE];
|
char buf[IOBUF_SIZE];
|
||||||
int n;
|
size_t n;
|
||||||
|
|
||||||
// If output buffer is too big, don't send anything. Wait until
|
// If output buffer is too big, don't send anything. Wait until
|
||||||
// mongoose drains already buffered data to the client.
|
// mongoose drains already buffered data to the client.
|
||||||
@@ -4802,7 +4938,7 @@ static void transfer_file_data(struct connection *conn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int mg_poll_server(struct mg_server *server, int milliseconds) {
|
time_t mg_poll_server(struct mg_server *server, int milliseconds) {
|
||||||
return ns_mgr_poll(&server->ns_mgr, milliseconds);
|
return ns_mgr_poll(&server->ns_mgr, milliseconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4813,9 +4949,9 @@ void mg_destroy_server(struct mg_server **server) {
|
|||||||
|
|
||||||
ns_mgr_free(&s->ns_mgr);
|
ns_mgr_free(&s->ns_mgr);
|
||||||
for (i = 0; i < (int) ARRAY_SIZE(s->config_options); i++) {
|
for (i = 0; i < (int) ARRAY_SIZE(s->config_options); i++) {
|
||||||
free(s->config_options[i]); // It is OK to free(NULL)
|
NS_FREE(s->config_options[i]); // It is OK to free(NULL)
|
||||||
}
|
}
|
||||||
free(s);
|
NS_FREE(s);
|
||||||
*server = NULL;
|
*server = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4941,7 +5077,7 @@ void mg_copy_listeners(struct mg_server *s, struct mg_server *to) {
|
|||||||
for (c = ns_next(&s->ns_mgr, NULL); c != NULL; c = ns_next(&s->ns_mgr, c)) {
|
for (c = ns_next(&s->ns_mgr, NULL); c != NULL; c = ns_next(&s->ns_mgr, c)) {
|
||||||
struct ns_connection *tmp;
|
struct ns_connection *tmp;
|
||||||
if ((c->flags & NSF_LISTENING) &&
|
if ((c->flags & NSF_LISTENING) &&
|
||||||
(tmp = (struct ns_connection *) malloc(sizeof(*tmp))) != NULL) {
|
(tmp = (struct ns_connection *) NS_MALLOC(sizeof(*tmp))) != NULL) {
|
||||||
memcpy(tmp, c, sizeof(*tmp));
|
memcpy(tmp, c, sizeof(*tmp));
|
||||||
tmp->mgr = &to->ns_mgr;
|
tmp->mgr = &to->ns_mgr;
|
||||||
ns_add_conn(tmp->mgr, tmp);
|
ns_add_conn(tmp->mgr, tmp);
|
||||||
@@ -4988,7 +5124,7 @@ const char *mg_set_option(struct mg_server *server, const char *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (*v != NULL) {
|
if (*v != NULL) {
|
||||||
free(*v);
|
NS_FREE(*v);
|
||||||
*v = NULL;
|
*v = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4998,7 +5134,14 @@ const char *mg_set_option(struct mg_server *server, const char *name,
|
|||||||
DBG(("%s [%s]", name, *v));
|
DBG(("%s [%s]", name, *v));
|
||||||
|
|
||||||
if (ind == LISTENING_PORT) {
|
if (ind == LISTENING_PORT) {
|
||||||
|
char buf[500] = "";
|
||||||
|
size_t n = 0;
|
||||||
struct vec vec;
|
struct vec vec;
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* the user, we rewrite all 0 port to chosen values.
|
||||||
|
*/
|
||||||
while ((value = next_option(value, &vec, NULL)) != NULL) {
|
while ((value = next_option(value, &vec, NULL)) != NULL) {
|
||||||
struct ns_connection *c = ns_bind(&server->ns_mgr, vec.ptr,
|
struct ns_connection *c = ns_bind(&server->ns_mgr, vec.ptr,
|
||||||
mg_ev_handler, NULL);
|
mg_ev_handler, NULL);
|
||||||
@@ -5006,17 +5149,28 @@ const char *mg_set_option(struct mg_server *server, const char *name,
|
|||||||
error_msg = "Cannot bind to port";
|
error_msg = "Cannot bind to port";
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
char buf[100];
|
char buf2[50], cert[100], ca[100];
|
||||||
ns_sock_to_str(c->sock, buf, sizeof(buf), 2);
|
union socket_address sa;
|
||||||
free(*v);
|
int proto, use_ssl;
|
||||||
|
|
||||||
|
ns_parse_address(vec.ptr, &sa, &proto, &use_ssl, cert, ca);
|
||||||
|
ns_sock_to_str(c->sock, buf2, sizeof(buf2),
|
||||||
|
memchr(vec.ptr, ':', vec.len) == NULL ? 2 : 3);
|
||||||
|
|
||||||
|
n += snprintf(buf + n, sizeof(buf) - n, "%s%s%s%s%s%s%s",
|
||||||
|
n > 0 ? "," : "",
|
||||||
|
use_ssl ? "ssl://" : "",
|
||||||
|
buf2, cert[0] ? ":" : "", cert, ca[0] ? ":" : "", ca);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf[sizeof(buf) - 1] = '\0';
|
||||||
|
NS_FREE(*v);
|
||||||
*v = mg_strdup(buf);
|
*v = mg_strdup(buf);
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifndef MONGOOSE_NO_FILESYSTEM
|
#ifndef MONGOOSE_NO_FILESYSTEM
|
||||||
} else if (ind == HEXDUMP_FILE) {
|
} else if (ind == HEXDUMP_FILE) {
|
||||||
server->ns_mgr.hexdump_file = *v;
|
server->ns_mgr.hexdump_file = *v;
|
||||||
#endif
|
#endif
|
||||||
#ifndef _WIN32
|
#if !defined(_WIN32) && !defined(MONGOOSE_NO_USER)
|
||||||
} else if (ind == RUN_AS_USER) {
|
} else if (ind == RUN_AS_USER) {
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
if ((pw = getpwnam(value)) == NULL) {
|
if ((pw = getpwnam(value)) == NULL) {
|
||||||
@@ -5050,7 +5204,7 @@ static void on_accept(struct ns_connection *nc, union socket_address *sa) {
|
|||||||
|
|
||||||
if (!check_acl(server->config_options[ACCESS_CONTROL_LIST],
|
if (!check_acl(server->config_options[ACCESS_CONTROL_LIST],
|
||||||
ntohl(* (uint32_t *) &sa->sin.sin_addr)) ||
|
ntohl(* (uint32_t *) &sa->sin.sin_addr)) ||
|
||||||
(conn = (struct connection *) calloc(1, sizeof(*conn))) == NULL) {
|
(conn = (struct connection *) NS_CALLOC(1, sizeof(*conn))) == NULL) {
|
||||||
nc->flags |= NSF_CLOSE_IMMEDIATELY;
|
nc->flags |= NSF_CLOSE_IMMEDIATELY;
|
||||||
} else {
|
} else {
|
||||||
// Circularly link two connection structures
|
// Circularly link two connection structures
|
||||||
@@ -5162,7 +5316,7 @@ static void mg_ev_handler(struct ns_connection *nc, int ev, void *p) {
|
|||||||
call_user(conn, MG_CLOSE);
|
call_user(conn, MG_CLOSE);
|
||||||
close_local_endpoint(conn);
|
close_local_endpoint(conn);
|
||||||
conn->ns_conn = NULL;
|
conn->ns_conn = NULL;
|
||||||
free(conn);
|
NS_FREE(conn);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -5209,7 +5363,7 @@ static void iter2(struct ns_connection *nc, int ev, void *param) {
|
|||||||
(void) ev;
|
(void) ev;
|
||||||
|
|
||||||
//DBG(("%p [%s]", conn, msg));
|
//DBG(("%p [%s]", conn, msg));
|
||||||
if (sscanf(msg, "%p %n", &func, &n) && func != NULL) {
|
if (sscanf(msg, "%p %n", &func, &n) && func != NULL && conn != NULL) {
|
||||||
conn->mg_conn.callback_param = (void *) (msg + n);
|
conn->mg_conn.callback_param = (void *) (msg + n);
|
||||||
func(&conn->mg_conn, MG_POLL);
|
func(&conn->mg_conn, MG_POLL);
|
||||||
}
|
}
|
||||||
@@ -5242,7 +5396,7 @@ const char *mg_get_option(const struct mg_server *server, const char *name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct mg_server *mg_create_server(void *server_data, mg_handler_t handler) {
|
struct mg_server *mg_create_server(void *server_data, mg_handler_t handler) {
|
||||||
struct mg_server *server = (struct mg_server *) calloc(1, sizeof(*server));
|
struct mg_server *server = (struct mg_server *) NS_CALLOC(1, sizeof(*server));
|
||||||
ns_mgr_init(&server->ns_mgr, server_data);
|
ns_mgr_init(&server->ns_mgr, server_data);
|
||||||
set_default_option_values(server->config_options);
|
set_default_option_values(server->config_options);
|
||||||
server->event_handler = handler;
|
server->event_handler = handler;
|
||||||
|
|||||||
+10
-11
@@ -2,28 +2,27 @@
|
|||||||
// Copyright (c) 2013-2014 Cesanta Software Limited
|
// Copyright (c) 2013-2014 Cesanta Software Limited
|
||||||
// All rights reserved
|
// All rights reserved
|
||||||
//
|
//
|
||||||
// This library is dual-licensed: you can redistribute it and/or modify
|
// This software is dual-licensed: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License version 2 as
|
// it under the terms of the GNU General Public License version 2 as
|
||||||
// published by the Free Software Foundation. For the terms of this
|
// published by the Free Software Foundation. For the terms of this
|
||||||
// license, see <http://www.gnu.org/licenses/>.
|
// license, see <http://www.gnu.org/licenses/>.
|
||||||
//
|
//
|
||||||
// You are free to use this library under the terms of the GNU General
|
// You are free to use this software under the terms of the GNU General
|
||||||
// Public License, but WITHOUT ANY WARRANTY; without even the implied
|
// Public License, but WITHOUT ANY WARRANTY; without even the implied
|
||||||
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
// See the GNU General Public License for more details.
|
// See the GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
// Alternatively, you can license this library under a commercial
|
// Alternatively, you can license this software under a commercial
|
||||||
// license, as set out in <http://cesanta.com/>.
|
// license, as set out in <http://cesanta.com/>.
|
||||||
//
|
|
||||||
// $Date: 2014-09-09 17:07:55 UTC $
|
|
||||||
|
|
||||||
#ifndef MONGOOSE_HEADER_INCLUDED
|
#ifndef MONGOOSE_HEADER_INCLUDED
|
||||||
#define MONGOOSE_HEADER_INCLUDED
|
#define MONGOOSE_HEADER_INCLUDED
|
||||||
|
|
||||||
#define MONGOOSE_VERSION "5.5"
|
#define MONGOOSE_VERSION "5.6"
|
||||||
|
|
||||||
#include <stdio.h> // required for FILE
|
#include <stdio.h> // required for FILE
|
||||||
#include <stddef.h> // required for size_t
|
#include <stddef.h> // required for size_t
|
||||||
|
#include <sys/types.h> // required for time_t
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -53,7 +52,7 @@ struct mg_connection {
|
|||||||
int is_websocket; // Connection is a websocket connection
|
int is_websocket; // Connection is a websocket connection
|
||||||
int status_code; // HTTP status code for HTTP error handler
|
int status_code; // HTTP status code for HTTP error handler
|
||||||
int wsbits; // First byte of the websocket frame
|
int wsbits; // First byte of the websocket frame
|
||||||
void *server_param; // Parameter passed to mg_add_uri_handler()
|
void *server_param; // Parameter passed to mg_create_server()
|
||||||
void *connection_param; // Placeholder for connection-specific data
|
void *connection_param; // Placeholder for connection-specific data
|
||||||
void *callback_param;
|
void *callback_param;
|
||||||
};
|
};
|
||||||
@@ -90,7 +89,7 @@ enum {
|
|||||||
struct mg_server *mg_create_server(void *server_param, mg_handler_t handler);
|
struct mg_server *mg_create_server(void *server_param, mg_handler_t handler);
|
||||||
void mg_destroy_server(struct mg_server **);
|
void mg_destroy_server(struct mg_server **);
|
||||||
const char *mg_set_option(struct mg_server *, const char *opt, const char *val);
|
const char *mg_set_option(struct mg_server *, const char *opt, const char *val);
|
||||||
int mg_poll_server(struct mg_server *, int milliseconds);
|
time_t mg_poll_server(struct mg_server *, int milliseconds);
|
||||||
const char **mg_get_valid_option_names(void);
|
const char **mg_get_valid_option_names(void);
|
||||||
const char *mg_get_option(const struct mg_server *server, const char *name);
|
const char *mg_get_option(const struct mg_server *server, const char *name);
|
||||||
void mg_copy_listeners(struct mg_server *from, struct mg_server *to);
|
void mg_copy_listeners(struct mg_server *from, struct mg_server *to);
|
||||||
@@ -104,7 +103,7 @@ 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_write(struct mg_connection *, const void *buf, int 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_websocket_write(struct mg_connection *, int opcode,
|
size_t mg_websocket_write(struct mg_connection *, int opcode,
|
||||||
@@ -130,8 +129,8 @@ int mg_parse_multipart(const char *buf, int buf_len,
|
|||||||
void *mg_start_thread(void *(*func)(void *), void *param);
|
void *mg_start_thread(void *(*func)(void *), void *param);
|
||||||
char *mg_md5(char buf[33], ...);
|
char *mg_md5(char buf[33], ...);
|
||||||
int mg_authorize_digest(struct mg_connection *c, FILE *fp);
|
int mg_authorize_digest(struct mg_connection *c, FILE *fp);
|
||||||
int mg_url_encode(const char *src, size_t s_len, char *dst, size_t dst_len);
|
size_t mg_url_encode(const char *src, size_t s_len, char *dst, size_t dst_len);
|
||||||
int mg_url_decode(const char *src, int src_len, char *dst, int dst_len, int);
|
int mg_url_decode(const char *src, size_t src_len, char *dst, size_t dst_len, int);
|
||||||
int mg_terminate_ssl(struct mg_connection *c, const char *cert);
|
int mg_terminate_ssl(struct mg_connection *c, const char *cert);
|
||||||
int mg_forward(struct mg_connection *c, const char *addr);
|
int mg_forward(struct mg_connection *c, const char *addr);
|
||||||
void *mg_mmap(FILE *fp, size_t size);
|
void *mg_mmap(FILE *fp, size_t size);
|
||||||
|
|||||||
+13
-9
@@ -120,8 +120,8 @@ static const char *test_parse_http_message() {
|
|||||||
ASSERT(strcmp(ri.http_version, "1.1") == 0);
|
ASSERT(strcmp(ri.http_version, "1.1") == 0);
|
||||||
ASSERT(ri.num_headers == 0);
|
ASSERT(ri.num_headers == 0);
|
||||||
|
|
||||||
ASSERT(parse_http_message(req2, sizeof(req2) - 1, &ri) == -1);
|
ASSERT(parse_http_message(req2, sizeof(req2) - 1, &ri) == (size_t) ~0);
|
||||||
ASSERT(parse_http_message(req6, 0, &ri) == -1);
|
ASSERT(parse_http_message(req6, 0, &ri) == (size_t) ~0);
|
||||||
ASSERT(parse_http_message(req8, sizeof(req8) - 1, &ri) == sizeof(req8) - 1);
|
ASSERT(parse_http_message(req8, sizeof(req8) - 1, &ri) == sizeof(req8) - 1);
|
||||||
|
|
||||||
// TODO(lsm): Fix this. Header value may span multiple lines.
|
// TODO(lsm): Fix this. Header value may span multiple lines.
|
||||||
@@ -198,17 +198,19 @@ static const char *test_match_prefix(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const char *test_remove_double_dots() {
|
static const char *test_remove_double_dots() {
|
||||||
struct { char before[20], after[20]; } data[] = {
|
struct { char before[30], after[30]; } data[] = {
|
||||||
{"////a", "/a"},
|
{"////a", "/a"},
|
||||||
{"/.....", "/."},
|
{"/.....", "/....."},
|
||||||
{"/......", "/"},
|
{"/......", "/......"},
|
||||||
{"...", "..."},
|
{"...", "..."},
|
||||||
{"/...///", "/./"},
|
{"/...///", "/.../"},
|
||||||
{"/a...///", "/a.../"},
|
{"/a...///", "/a.../"},
|
||||||
{"/.x", "/.x"},
|
{"/.x", "/.x"},
|
||||||
{"/\\", "/"},
|
{"/\\", "/"},
|
||||||
{"/a\\", "/a\\"},
|
{"/a\\", "/a\\"},
|
||||||
{"/a\\\\...", "/a\\."},
|
{"/a\\\\...", "/a\\..."},
|
||||||
|
{"foo/x..y/././y/../../..", "foo/x..y/y/"},
|
||||||
|
{"foo/..x", "foo/..x"},
|
||||||
};
|
};
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
@@ -261,6 +263,7 @@ static const char *test_url_decode(void) {
|
|||||||
ASSERT(strcmp(buf, "a ") == 0);
|
ASSERT(strcmp(buf, "a ") == 0);
|
||||||
|
|
||||||
ASSERT(mg_url_decode("%61", 1, buf, sizeof(buf), 1) == 1);
|
ASSERT(mg_url_decode("%61", 1, buf, sizeof(buf), 1) == 1);
|
||||||
|
printf("[%s]\n", buf);
|
||||||
ASSERT(strcmp(buf, "%") == 0);
|
ASSERT(strcmp(buf, "%") == 0);
|
||||||
|
|
||||||
ASSERT(mg_url_decode("%61", 2, buf, sizeof(buf), 1) == 2);
|
ASSERT(mg_url_decode("%61", 2, buf, sizeof(buf), 1) == 2);
|
||||||
@@ -306,9 +309,9 @@ static const char *test_base64_encode(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const char *test_mg_parse_header(void) {
|
static const char *test_mg_parse_header(void) {
|
||||||
const char *str = "xx=1 kl yy, ert=234 kl=123, "
|
const char *str = "xx=1 kl yy, ert=234 kl=123, uri=\"/?name=x,y\", "
|
||||||
"ii=\"12\\\"34\" zz='aa bb',tt=2,gf=\"xx d=1234";
|
"ii=\"12\\\"34\" zz='aa bb',tt=2,gf=\"xx d=1234";
|
||||||
char buf[10];
|
char buf[20];
|
||||||
ASSERT(mg_parse_header(str, "yy", buf, sizeof(buf)) == 0);
|
ASSERT(mg_parse_header(str, "yy", buf, sizeof(buf)) == 0);
|
||||||
ASSERT(mg_parse_header(str, "ert", buf, sizeof(buf)) == 3);
|
ASSERT(mg_parse_header(str, "ert", buf, sizeof(buf)) == 3);
|
||||||
ASSERT(strcmp(buf, "234") == 0);
|
ASSERT(strcmp(buf, "234") == 0);
|
||||||
@@ -331,6 +334,7 @@ static const char *test_mg_parse_header(void) {
|
|||||||
ASSERT(strcmp(buf, "12\"34") == 0);
|
ASSERT(strcmp(buf, "12\"34") == 0);
|
||||||
ASSERT(mg_parse_header(str, "tt", buf, sizeof(buf)) == 1);
|
ASSERT(mg_parse_header(str, "tt", buf, sizeof(buf)) == 1);
|
||||||
ASSERT(strcmp(buf, "2") == 0);
|
ASSERT(strcmp(buf, "2") == 0);
|
||||||
|
ASSERT(mg_parse_header(str, "uri", buf, sizeof(buf)) == 10);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user