mirror of
https://github.com/holub/mame
synced 2025-04-20 15:32:45 +03:00
Added integral source of mongoose (nw)
This commit is contained in:
parent
61f7cd05df
commit
8556d0cdf7
16
3rdparty/mongoose/LICENSE
vendored
Normal file
16
3rdparty/mongoose/LICENSE
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
|
||||
Copyright (c) 2013 Cesanta Software Limited
|
||||
All rights reserved
|
||||
|
||||
This code is dual-licensed: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 as
|
||||
published by the Free Software Foundation. For the terms of this
|
||||
license, see <http://www.gnu.org/licenses>.
|
||||
|
||||
You are free to use this code under the terms of the GNU General
|
||||
Public License, but WITHOUT ANY WARRANTY; without even the implied
|
||||
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
Alternatively, you can license this code under a commercial
|
||||
license, as set out in <http://cesanta.com/>.
|
88
3rdparty/mongoose/README.md
vendored
Normal file
88
3rdparty/mongoose/README.md
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
# <img src="http://cesanta.com/images/mongoose_logo.png" width="64" height="64"> Mongoose Web Server
|
||||
|
||||
Mongoose is the most easy to use web server on the planet. A web server of choice for Web developers (PHP, Ruby, Python, etc) and Web designers.
|
||||
|
||||
Mongoose is built on top of Libmongoose embedded library, which can turn
|
||||
anything into a web server in 5 minutes worth of effort and few lines of code.
|
||||
Libmongoose is used to serve Web GUI on embedded devices, implement RESTful
|
||||
services, RPC frameworks (e.g. JSON-RPC), handle telemetry data exchange, and
|
||||
perform many other tasks in various different industries including aerospace,
|
||||
manufacturing, finance, research, automotive, gaming, IT.
|
||||
|
||||
|
||||
* [Mailing list](http://groups.google.com/group/mongoose-users)
|
||||
* [Downloads](http://cesanta.com/products.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
|
||||
|
||||
- Works on Windows, Mac, UNIX/Linux, iPhone, Android eCos, QNX
|
||||
and many other platforms
|
||||
- CGI, SSI, SSL, Digest auth, Websocket, WEbDAV, Resumed download,
|
||||
URL rewrite, file blacklist
|
||||
- Custom error pages, Virtual hosts, IP-based ACL, Windows service,
|
||||
HTTP/HTTPS client
|
||||
- Simple and clean
|
||||
[embedding API](https://github.com/cesanta/mongoose/blob/master/mongoose.h).
|
||||
The source is in single
|
||||
[mongoose.c](https://github.com/cesanta/mongoose/blob/master/mongoose.c) file
|
||||
to make embedding easy
|
||||
- Extremely lightweight, has a core of under 40kB and tiny runtime footprint
|
||||
- Asynchronous, non-blocking core supporting single- or multi-threaded usage
|
||||
- On the market since 2004 with over 1 million cumulative downloads
|
||||
- Stable, mature and tested, has several man-years invested
|
||||
in continuous improvement and refinement
|
||||
|
||||
# Screenshots
|
||||
|
||||
Download, double-click to start, run browser -- that's all!
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
# Acknowledgements
|
||||
|
||||
Mongoose made better thanks to the contribution of following people:
|
||||
|
||||
Arnout Vandecappelle, Benoît Amiaux, Boris Pek, Cody Hanson, Colin Leitner,
|
||||
Daniel Oaks, Eric Bakan, Erik Oomen, Filipp Kovalev, Ger Hobbelt,
|
||||
Hendrik Polczynski, Igor Okulist, Jay, Joe Mucchiello, John Safranek,
|
||||
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
|
||||
|
||||
Mongoose is released under commercial and
|
||||
[GNU GPL v.2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) open
|
||||
source licenses. The GPLv2 open source License does not generally permit
|
||||
incorporating this software into non-open source programs.
|
||||
For those customers who do not wish to comply with the GPLv2 open
|
||||
source license requirements,
|
||||
[Cesanta Software](http://cesanta.com) offers a full,
|
||||
royalty-free commercial license and professional support
|
||||
without any of the GPL restrictions.
|
||||
|
||||
# Other products by Cesanta Software: simple and effective
|
||||
|
||||
- [SSL Wrapper](https://github.com/cesanta/ssl_wrapper) - application to
|
||||
secure network communications
|
||||
- [Frozen](https://github.com/cesanta/frozen) - JSON parser and generator
|
||||
- [SLRE](https://github.com/cesanta/slre) - Super Light Regular Expression
|
||||
library
|
||||
- [Net Skeleton](https://github.com/cesanta/net_skeleton) - framework for
|
||||
building network applications
|
||||
- [SLDR](https://github.com/cesanta/sldr) - Super Light DNS Resolver
|
246
3rdparty/mongoose/docs/API.md
vendored
Normal file
246
3rdparty/mongoose/docs/API.md
vendored
Normal file
@ -0,0 +1,246 @@
|
||||
# Mongoose API Reference
|
||||
|
||||
struct mg_server *mg_create_server(void *server_param);
|
||||
|
||||
Creates web server instance. Returns opaque instance pointer, or NULL if
|
||||
there is not enough memory. `server_param`: Could be any pointer, or NULL.
|
||||
This pointer will be passed
|
||||
to the callback functions as `struct mg_connection::server_param` field.
|
||||
A common use case is to pass `this` pointer of the C++ wrapper class
|
||||
as `user_param`, to let the callback get the pointer to the C++ object.
|
||||
|
||||
Note that this function doesn't make the
|
||||
server instance to serve. Serving is done by `mg_poll_server()` function.
|
||||
Mongoose has single-threaded, event-driven, asynchronous, non-blocking core.
|
||||
When server instance is created, it contains an information about
|
||||
the configuration and the state of each connection.
|
||||
Server instance is capable on listening on only one port. After creation,
|
||||
`struct mg_server` has a list
|
||||
of active connections and configuration parameters.
|
||||
|
||||
Side-effect: on UNIX, `mg_create_server()` ignores SIGPIPE signals. If custom
|
||||
processing is required SIGPIPE, signal handler must be set up after
|
||||
calling `mg_create_server()`.
|
||||
|
||||
Important: Mongoose does not install `SIGCHLD` handler. If CGI is used,
|
||||
`SIGCHLD` handler must be set up to reap CGI zombie processes.
|
||||
|
||||
|
||||
void mg_destroy_server(struct mg_server **server);
|
||||
|
||||
Deallocates web server instance, closes all pending connections, and makes
|
||||
server pointer a NULL pointer.
|
||||
|
||||
const char mg_set_option(struct mg_server *server, const char *name,
|
||||
const char *value);
|
||||
|
||||
Sets a particular server option. Note that at least one option,
|
||||
`listening_port`, must be specified. To serve static files, `document_root`
|
||||
must be specified too. If `document_root` option is left unset, Mongoose
|
||||
will not access filesystem at all. `mg_set_option()` returns NULL if option was
|
||||
set successfully, otherwise it returns human-readable error string. It is
|
||||
allowed to call `mg_set_option()` by the same thread that does
|
||||
`mg_poll_server()` (Mongoose thread) and change server configuration while it
|
||||
is serving, in between `mg_poll_server()` calls.
|
||||
|
||||
int mg_poll_server(struct mg_server *server, int milliseconds);
|
||||
|
||||
Performs one iteration of IO loop by iterating over all
|
||||
active connections, performing `select()` syscall on all sockets with a timeout
|
||||
of `milliseconds`. When `select()` returns, Mongoose
|
||||
does an IO for each socket that has data to be sent or received. Application
|
||||
code must call `mg_poll_server()` in a loop. It is an error to have more then
|
||||
one thread calling `mg_poll_server()`, `mg_set_option()` or any other function
|
||||
that take `struct mg_server *` parameter. Mongoose does not
|
||||
mutex-protect `struct mg_server *`, therefore only single thread
|
||||
(Mongoose thread) should make Mongoose calls.
|
||||
|
||||
`mg_poll_server()` calls user-specified event handler when certain events
|
||||
occur. Sequence of events for the accepted connection is this:
|
||||
|
||||
* `MG_AUTH` - Mongoose asks whether this connection is authorized. If event
|
||||
handler returns `MG_FALSE`, then Mongoose does not serve the request but
|
||||
sends authorization request to the client. If `MG_TRUE` is returned,
|
||||
then Mongoose continues on with the request.
|
||||
* `MG_REQUEST` - Mongoose asks event handler to serve the request. If
|
||||
event handler serves the request by sending a reply,
|
||||
it should return `MG_TRUE`. Otherwise,
|
||||
it should return `MG_FALSE` which tells Mongoose that request is not
|
||||
served and Mongoose should serve it. For example, event handler might
|
||||
choose to serve only RESTful API requests with URIs that start with
|
||||
certain prefix, and let Mongoose serve all static files.
|
||||
If event handler decides to serve the request, but doesn't have
|
||||
all the data at the moment, it should return `MG_MORE`. That tells
|
||||
Mongoose to keep the connection open after callback returns.
|
||||
|
||||
`mg_connection::connection_param` pointer is a placeholder to keep
|
||||
user-specific data. For example, handler could decide to open a DB
|
||||
connection and store DB connection handle in `connection_param`.
|
||||
* `MG_POLL` is sent to every connection on every iteration of
|
||||
`mg_poll_server()`. Event handler should return `MG_FALSE` to ignore
|
||||
this event. If event handler returns `MG_TRUE`, then Mongoose assumes
|
||||
that event handler has finished sending data, and Mongoose will
|
||||
close the connection.
|
||||
* `MG_HTTP_ERROR` sent when Mongoose is about to send HTTP error back
|
||||
to the client. Event handler can choose to send a reply itself, in which
|
||||
case event handler must return `MG_TRUE`. Otherwise, event handler must
|
||||
return `MG_FALSE`.
|
||||
* `MG_CLOSE` is sent when the connection is closed. This event is used
|
||||
to cleanup per-connection state stored in `connection_param`
|
||||
if it was allocated. Event handler return value is ignored.
|
||||
|
||||
Sequence of events for the client connection is this:
|
||||
|
||||
* `MG_CONNECT` sent when Mongoose has connected to the remote host.
|
||||
This event is sent to the connection initiated by `mg_connect()` call.
|
||||
Connection status is held in `mg_connection::status_code`: if zero,
|
||||
then connection was successful, otherwise connection was not established.
|
||||
User should send a request upon successful connection.
|
||||
Event handler should return `MG_TRUE` if connection was successful and
|
||||
HTTP request has been sent. Otherwise, it should send `MG_FALSE`.
|
||||
* `MG_REPLY` is sent when response has been received from the remote host.
|
||||
If event handler sends another request, then it should return `MG_TRUE`.
|
||||
Otherwise it should return `MG_FALSE` and Mongoose will close the connection.
|
||||
* `MG_CLOSE` same as for the accepted connection.
|
||||
|
||||
|
||||
When mongoose buffers in HTTP request and successfully parses it, it sends
|
||||
`MG_REQUEST` event for GET requests immediately. For POST requests,
|
||||
Mongoose delays the call until the whole POST request is buffered in memory.
|
||||
POST data is available to the callback as `struct mg_connection::content`,
|
||||
and POST data length is in `struct mg_connection::content_len`.
|
||||
|
||||
Note that websocket connections are treated the same way. Mongoose buffers
|
||||
websocket frame in memory, and calls event handler when frame is fully
|
||||
buffered. Frame data is available `struct mg_connection::content`, and
|
||||
data length is in `struct mg_connection::content_len`, i.e. very similar to
|
||||
the POST request. `struct mg_connection::is_websocket` flag indicates
|
||||
whether the request is websocket or not. Also, for websocket requests,
|
||||
there is `struct mg_connection::wsbits` field which contains first byte
|
||||
of the websocket frame which URI handler can examine. Note that to
|
||||
reply to the websocket client, `mg_websocket_write()` should be used.
|
||||
To reply to the plain HTTP client, `mg_write_data()` should be used.
|
||||
|
||||
Return value: number of active connections.
|
||||
|
||||
|
||||
const char **mg_get_valid_option_names(void);
|
||||
|
||||
Returns a NULL-terminated array of option names and their default values.
|
||||
There are two entries per option in an array: an option name followed by a
|
||||
default value. A default value could be NULL. A NULL name indicates an end
|
||||
of the array.
|
||||
|
||||
const char *mg_get_option(const struct mg_server *server, const char *name);
|
||||
|
||||
Returns the value of particular configuration parameter. If
|
||||
given parameter name is not valid, NULL is returned. For valid names, return
|
||||
value is guaranteed to be non-NULL. If parameter is not set, zero-length string
|
||||
is returned.
|
||||
|
||||
void mg_wakeup_server_ex(struct mg_server *, mg_handler_t func,
|
||||
const char *fmt, ...);
|
||||
|
||||
Sends string message to a server. Function `func` is called for every active
|
||||
connection. String message is passed in `struct mg_connection::callback_param`.
|
||||
This function is designed to push data to the connected clients, and
|
||||
can be called from any thread. There is a limitation on the length of
|
||||
the message, currently at 8 kilobytes.
|
||||
|
||||
void mg_send_status(struct mg_connection *, int status_code);
|
||||
void mg_send_header(struct mg_connection *, const char *name,
|
||||
const char *value);
|
||||
void mg_send_data(struct mg_connection *, const void *data, int data_len);
|
||||
void mg_printf_data(struct mg_connection *, const char *format, ...);
|
||||
|
||||
These functions are used to construct a response to the client. HTTP response
|
||||
consists of three parts: a status line, zero or more HTTP headers,
|
||||
a response body. Mongoose provides functions for all three parts:
|
||||
* `mg_send_status()` is used to create status line. This function can be
|
||||
called zero or once. If `mg_send_status()` is not called, then Mongoose
|
||||
will send status 200 (success) implicitly.
|
||||
* `mg_send_header()` adds HTTP header to the response. This function could
|
||||
be called zero or more times.
|
||||
* `mg_send_data()` and `mg_printf_data()` are used to send data to the
|
||||
client. Note that Mongoose adds `Transfer-Encoding: chunked` header
|
||||
implicitly, and sends data in chunks. Therefore, it is not necessary to
|
||||
set `Content-Length` header. Note that `mg_send_data()` and
|
||||
`mg_printf_data()` do not send data immediately. Instead, they spool
|
||||
data in memory, and Mongoose sends that data later after URI handler
|
||||
returns. If data to be sent is huge, an URI handler might
|
||||
send data in pieces by saving state in
|
||||
`struct mg_connection::connection_param` variable and returning `0`. Then
|
||||
Mongoose will call a handler repeatedly after each socket write.
|
||||
|
||||
<!-- -->
|
||||
|
||||
void mg_send_file(struct mg_connection *, const char *path);
|
||||
|
||||
Tells Mongoose to serve given file. Mongoose handles file according to
|
||||
it's extensions, i.e. Mongoose will invoke CGI script if `path` has CGI
|
||||
extension, it'll render SSI file if `path` has SSI extension, etc. If `path`
|
||||
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
|
||||
event handler must return `MG_MORE`.
|
||||
|
||||
int mg_websocket_write(struct mg_connection* conn, int opcode,
|
||||
const char *data, size_t data_len);
|
||||
|
||||
Similar to `mg_write()`, 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);
|
||||
|
||||
Get the value of particular HTTP header. This is a helper function.
|
||||
It traverses http_headers array, and if the header is present in the array,
|
||||
returns its value. If it is not present, NULL is returned.
|
||||
|
||||
|
||||
int mg_get_var(const struct mg_connection *conn, const char *var_name,
|
||||
char *buf, size_t buf_len);
|
||||
|
||||
Gets HTTP form variable. Both POST buffer and query string are inspected.
|
||||
Form variable is url-decoded and written to the buffer. On success, this
|
||||
function returns the length of decoded variable. On error, -1 is returned if
|
||||
variable not found, and -2 is returned if destination buffer is too small
|
||||
to hold the variable. Destination buffer is guaranteed to be
|
||||
'\0' - terminated if it is not NULL or zero length.
|
||||
|
||||
int mg_parse_header(const char *hdr, const char *var_name, char *buf,
|
||||
size_t buf_size);
|
||||
|
||||
This function parses HTTP header and fetches given variable's value in a buffer.
|
||||
A header should be like `x=123, y=345, z="other value"`. This function is
|
||||
designed to parse Cookie headers, Authorization headers, and similar. Returns
|
||||
the length of the fetched value, or 0 if variable not found.
|
||||
|
||||
int mg_modify_passwords_file(const char *passwords_file_name,
|
||||
const char *domain,
|
||||
const char *user,
|
||||
const char *password);
|
||||
|
||||
Add, edit or delete the entry in the passwords file.
|
||||
This function allows an application to manipulate .htpasswd files on the
|
||||
fly by adding, deleting and changing user records. This is one of the
|
||||
several ways of implementing authentication on the server side.
|
||||
If password is not NULL, entry is added (or modified if already exists).
|
||||
If password is NULL, entry is deleted.
|
||||
Return: 1 on success, 0 on error.
|
||||
|
||||
|
||||
int mg_parse_multipart(const char *buf, int buf_len,
|
||||
char *var_name, int var_name_len,
|
||||
char *file_name, int file_name_len,
|
||||
const char **data, int *data_len);
|
||||
|
||||
Parses a buffer that contains multipart form data. Stores chunk name
|
||||
in a `var_name` buffer. If chunk is an uploaded file, then `file_name`
|
||||
will have a file name. `data` and `data_len` will point to the chunk data.
|
||||
Returns number of bytes to skip to the next chunk.
|
||||
|
||||
struct mg_connection *mg_connect(struct mg_server *server,
|
||||
const char *host, int port, int use_ssl);
|
||||
|
||||
Create connection to the remote host. Returns `NULL` on error, non-null
|
||||
if the connection has been scheduled for connection. Upon a connection,
|
||||
Mongoose will send `MG_CONNECT` event to the event handler.
|
27
3rdparty/mongoose/docs/AndroidBuild.md
vendored
Normal file
27
3rdparty/mongoose/docs/AndroidBuild.md
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
# Mongoose Build on Android
|
||||
|
||||
This is a small guide to help you run mongoose on Android. Currently it is
|
||||
tested on the HTC Wildfire. If you have managed to run it on other devices
|
||||
as well, please comment or drop an email in the mailing list.
|
||||
Note : You dont need root access to run mongoose on Android.
|
||||
|
||||
- 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)
|
||||
- Run `/path-to-ndk/ndk-build -C /path/to/mongoose`
|
||||
That should generate mongoose/lib/armeabi/mongoose
|
||||
- Using the adb tool (you need to have Android SDK installed for that),
|
||||
push the generated mongoose binary to `/data/local` folder on device.
|
||||
- From adb shell, navigate to `/data/local` and execute `./mongoose`.
|
||||
- To test if the server is running fine, visit your web-browser and
|
||||
navigate to `http://127.0.0.1:8080` You should see the `Index of /` page.
|
||||
|
||||

|
||||
|
||||
|
||||
Notes:
|
||||
|
||||
- `jni` stands for Java Native Interface. Read up on Android NDK if you want
|
||||
to know how to interact with the native C functions of mongoose in Android
|
||||
Java applications.
|
||||
- TODO: A Java application that interacts with the native binary or a
|
||||
shared library.
|
34
3rdparty/mongoose/docs/BasicWebsite.md
vendored
Normal file
34
3rdparty/mongoose/docs/BasicWebsite.md
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
How To Create Basic Website With Mongoose
|
||||
===========================================
|
||||
|
||||
## 1. Create a directory which will contain your website files. For example, on drive `C:\`, create a directory called `my_website`:
|
||||
|
||||

|
||||
|
||||
## 2. Inside `my_website` directory, create a new file called "index". This will be the default web page shown when the website is visited.
|
||||
|
||||

|
||||
|
||||
## 3. Open index file with your favorite editor (for example, Notepad) and enter some HTML code:
|
||||
|
||||

|
||||
|
||||
## 4. Save this file as `index.html`:
|
||||
|
||||

|
||||
|
||||
|
||||
## 5. Download Mongoose executable from http://cesanta.com/mongoose.shtml and copy the executable inside `my_website` directory:
|
||||
|
||||

|
||||
|
||||
## 6. Double-click mongoose executable. An icon will appear on a system tray in the bottom right corner of the desktop:
|
||||
|
||||

|
||||
|
||||
## 7. Click on the mongoose icon and choose "Go to my address" menu:
|
||||

|
||||
|
||||
## 8. A browser will popup displaying `index.html` file. Now, you can expand your website by adding more content.
|
||||
|
||||

|
173
3rdparty/mongoose/docs/Embed.md
vendored
Normal file
173
3rdparty/mongoose/docs/Embed.md
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
# Mongoose Embedding Guide
|
||||
|
||||
Embedding Mongoose is done in two steps:
|
||||
|
||||
1. Copy
|
||||
[mongoose.c](https://raw.github.com/cesanta/mongoose/master/mongoose.c) and
|
||||
[mongoose.h](https://raw.github.com/cesanta/mongoose/master/mongoose.h)
|
||||
to your application's source tree and include them in the build.
|
||||
2. Somewhere in the application code, call `mg_create_server()` to create
|
||||
a server, configure it with `mg_set_option()` and loop with
|
||||
`mg_poll_server()` until done. Call `mg_destroy_server()` to cleanup.
|
||||
|
||||
Here's a minimal application `app.c` that embeds mongoose:
|
||||
|
||||
#include "mongoose.h"
|
||||
|
||||
int main(void) {
|
||||
struct mg_server *server = mg_create_server(NULL, NULL);
|
||||
mg_set_option(server, "document_root", "."); // Serve current directory
|
||||
mg_set_option(server, "listening_port", "8080"); // Open port 8080
|
||||
|
||||
for (;;) {
|
||||
mg_poll_server(server, 1000); // Infinite loop, Ctrl-C to stop
|
||||
}
|
||||
mg_destroy_server(&server);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
To compile it, put `mongoose.c`, `mongoose.h` and `app.c` into one
|
||||
folder, start terminal on UNIX or Visual Studio command line prompt on Windows,
|
||||
and run the following command:
|
||||
|
||||
cc app.c mongoose.c -pthread -o app # on Unix
|
||||
cl.exe app.c mongoose.c /TC /MD # on Windows
|
||||
|
||||
When run, this simple application opens port 8080 and serves static files,
|
||||
CGI files and lists directory content in the current working directory.
|
||||
|
||||
It is possible to generate HTML page content. Mongoose can call user-defined
|
||||
function when certain events occur.
|
||||
That function is called _an event handler_, and it is the second parameter
|
||||
to `mg_create_server()` function. Here is the example event handler function:
|
||||
|
||||
int event_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||
switch (ev) {
|
||||
case MG_AUTH: return MG_TRUE;
|
||||
default: return MG_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
Event handler is called by Mongoose with `struct mg_connection *`
|
||||
pointer and an event number. `struct mg_connection *conn`
|
||||
has all information about the request: HTTP headers, POST or websocket
|
||||
data buffer, etcetera. `enum mg_event ev` tells which exactly event is sent.
|
||||
For each event, an event handler returns a value which tells Mongoose how
|
||||
to behave.
|
||||
|
||||
The sequence of events for every connection is this:
|
||||
|
||||
* `MG_AUTH` - Mongoose asks whether this connection is authorized. If event
|
||||
handler returns `MG_FALSE`, then Mongoose does not serve the request but
|
||||
sends authorization request to the client. If `MG_TRUE` is returned,
|
||||
then Mongoose continues on with the request.
|
||||
* `MG_REQUEST` - Mongoose asks event handler to serve the request. If
|
||||
event handler serves the request by sending a reply,
|
||||
it should return `MG_TRUE`. Otherwise,
|
||||
it should return `MG_FALSE` which tells Mongoose that request is not
|
||||
served and Mongoose should serve it. For example, event handler might
|
||||
choose to serve only RESTful API requests with URIs that start with
|
||||
certain prefix, and let Mongoose serve all static files.
|
||||
If event handler decides to serve the request, but doesn't have
|
||||
all the data at the moment, it should return `MG_MORE`. That tells
|
||||
Mongoose to keep the connection open after callback returns.
|
||||
|
||||
`mg_connection::connection_param` pointer is a placeholder to keep
|
||||
user-specific data. For example, handler could decide to open a DB
|
||||
connection and store DB connection handle in `connection_param`.
|
||||
* `MG_POLL` is sent to every connection on every iteration of
|
||||
`mg_poll_server()`. Event handler should return `MG_FALSE` to ignore
|
||||
this event. If event handler returns `MG_TRUE`, then Mongoose assumes
|
||||
that event handler has finished sending data, and Mongoose will
|
||||
close the connection.
|
||||
* `MG_HTTP_ERROR` sent when Mongoose is about to send HTTP error back
|
||||
to the client. Event handler can choose to send a reply itself, in which
|
||||
case event handler must return `MG_TRUE`. Otherwise, event handler must
|
||||
return `MG_FALSE`
|
||||
* `MG_CLOSE` is sent when the connection is closed. This event is used
|
||||
to cleanup per-connection state stored in `connection_param`
|
||||
if it was allocated.
|
||||
|
||||
Let's extend our minimal application example and
|
||||
create an URI that will be served by user's C code. The app will handle
|
||||
`/hello` URI by showing a hello message. So, when app is run,
|
||||
http://127.0.0.1:8080/hello will say hello, and here's the code:
|
||||
|
||||
#include <string.h>
|
||||
#include "mongoose.h"
|
||||
|
||||
static int event_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||
if (ev == MG_AUTH) {
|
||||
return MG_TRUE; // Authorize all requests
|
||||
} else if (ev == MG_REQUEST && !strcmp(conn->uri, "/hello")) {
|
||||
mg_printf_data(conn, "%s", "Hello world");
|
||||
return MG_TRUE; // Mark as processed
|
||||
} else {
|
||||
return MG_FALSE; // Rest of the events are not processed
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
struct mg_server *server = mg_create_server(NULL, event_handler);
|
||||
mg_set_option(server, "document_root", ".");
|
||||
mg_set_option(server, "listening_port", "8080");
|
||||
|
||||
for (;;) {
|
||||
mg_poll_server(server, 1000); // Infinite loop, Ctrl-C to stop
|
||||
}
|
||||
mg_destroy_server(&server);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
## Example code
|
||||
|
||||
Mongoose source code contains number of examples, located in the
|
||||
[examples](https://github.com/cesanta/mongoose/blob/master/examples/) directory.
|
||||
To build any example, go to the respective directory and run `make`.
|
||||
|
||||
## Compilation flags
|
||||
|
||||
Below is the list of compilation flags that enable or disable certain
|
||||
features. By default, some features are enabled, and could be disabled
|
||||
by setting appropriate `NO_*` flag. Features that are disabled by default
|
||||
could be enabled by setting appropriate `USE_*` flag. Bare bones Mongoose
|
||||
is quite small, about 30 kilobytes of compiled x86 code. Each feature adds
|
||||
a couple of kilobytes to the executable size, and also has some runtime penalty.
|
||||
|
||||
Note that some flags start with `NS_` prefix. This is because Mongoose uses
|
||||
[Net Skeleton](http://github.com/cesanta/net_skeleton) as a low-level
|
||||
networking engine. If user code has `#include <net_skeleton.h>`, then
|
||||
all Net Skeleton functions will be available too.
|
||||
|
||||
|
||||
-DMONGOOSE_NO_AUTH Disable MD5 authorization support
|
||||
-DMONGOOSE_NO_CGI Disable CGI support
|
||||
-DMONGOOSE_NO_DAV Disable WebDAV support
|
||||
(PUT, DELETE, MKCOL, PROPFIND methods)
|
||||
-DMONGOOSE_NO_DIRECTORY_LISTING Disable directory listing
|
||||
-DMONGOOSE_NO_FILESYSTEM Disables all file IO, serving from memory only
|
||||
-DMONGOOSE_NO_LOGGING Disable access/error logging
|
||||
-DMONGOOSE_NO_THREADS
|
||||
-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_LUA Enable Lua scripting
|
||||
-DMONGOOSE_USE_LUA_SQLITE3 Enable sqlite3 binding for Lua
|
||||
-DMONGOOSE_USE_POST_SIZE_LIMIT=X POST requests larger than X will be
|
||||
rejected, not set by default
|
||||
-DMONGOOSE_USE_EXTRA_HTTP_HEADERS=X Append X to the HTTP headers
|
||||
for static files, empty by default
|
||||
|
||||
-DNS_ENABLE_DEBUG Enables debug messages on stdout, very noisy
|
||||
-DNS_ENABLE_SSL Enable SSL
|
||||
-DNS_ENABLE_IPV6 Enable IPv6 support
|
||||
-DNS_ENABLE_HEXDUMP Enables hexdump of sent and received traffic
|
||||
-DNS_STACK_SIZE=X Sets stack size to X for ns_start_thread()
|
||||
-DNS_DISABLE_THREADS Disable threads support
|
||||
-DNS_DISABLE_SOCKETPAIR For systems without loopback interface
|
||||
-DMONGOOSE_SEND_NS_EVENTS Send Net Skeleton events to the event handler
|
||||
in addition to the Mongoose events
|
45
3rdparty/mongoose/docs/FAQ.md
vendored
Normal file
45
3rdparty/mongoose/docs/FAQ.md
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
# Mongoose FAQ
|
||||
|
||||
## My Antivirus Software reports Mongoose as a security threat
|
||||
|
||||
Mongoose doesn't contain any malicious logic. Antivirus reports a
|
||||
[false positive](http://en.wikipedia.org/wiki/Type_I_and_type_II_errors#False_positive_error).
|
||||
This is when certain byte sequence in Mongoose accidentally matches
|
||||
virus signature in the Antivirus database.
|
||||
|
||||
## Download page doesn't work
|
||||
|
||||
Please make sure Javascript is enabled in your browser, and that the
|
||||
antivirus software is not blocking the download.
|
||||
|
||||
|
||||
## MacOS message: "Mongoose.app is damaged and can’t be opened. You should move it to the Trash"
|
||||
|
||||
This happens on newer MacOS systems. The reason for the message
|
||||
is the fact Mongoose.app is not digitally signed.
|
||||
Mongoose download procedure changes the app on the fly by injecting
|
||||
user information in the binary, making any prior digital signature void.
|
||||
Open "System Preferences" -> "Security" and set "Allow apps downloaded from"
|
||||
to "Anywhere". Revert the settings once Mongoose is installed.
|
||||
|
||||
## PHP doesn't work: getting empty page, or 'File not found' error
|
||||
|
||||
The reason for that is wrong paths to the interpreter. Remember that with PHP,
|
||||
correct interpreter is `php-cgi.exe` (`php-cgi` on UNIX). Solution: specify
|
||||
full path to the PHP interpreter, e.g.:
|
||||
|
||||
mongoose -cgi_interpreter /full/path/to/php-cgi
|
||||
|
||||
## Mongoose fails to start
|
||||
|
||||
If Mongoose exits immediately when run, this
|
||||
usually indicates a syntax error in the configuration file
|
||||
(named `mongoose.conf` by default) or the command-line arguments.
|
||||
Syntax checking is omitted from Mongoose to keep its size low. However,
|
||||
the Manual should be of help. Note: the syntax changes from time to time,
|
||||
so updating the config file might be necessary after executable update.
|
||||
|
||||
### Embedding with OpenSSL on Windows might fail because of calling convention
|
||||
|
||||
To force Mongoose to use `__stdcall` convention, add `/Gz` compilation
|
||||
flag to the Visual Studio project settings.
|
18
3rdparty/mongoose/docs/FileSharing.md
vendored
Normal file
18
3rdparty/mongoose/docs/FileSharing.md
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
How To Share Files With Mongoose
|
||||
===========================================
|
||||
|
||||
## 1. Download Mongoose executable from http://cesanta.com/mongoose.shtml and copy the executable inside the directory you want to share:
|
||||
|
||||

|
||||
|
||||
## 2. Double-click mongoose executable. A browser will start automatically, an icon will appear on a system tray in the bottom right corner of the desktop:
|
||||
|
||||

|
||||
|
||||
## 3. Click on the mongoose icon
|
||||

|
||||
|
||||
|
||||
## 4. Click on "Go to my address" to launch a browser locally. Or, to access a folder from another machine, launch a browser and type in the URL:
|
||||
|
||||

|
44
3rdparty/mongoose/docs/Internals.md
vendored
Normal file
44
3rdparty/mongoose/docs/Internals.md
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
# Mongoose Internals
|
||||
|
||||
Mongoose has single-threaded, event-driven, asynchronous, non-blocking core.
|
||||
`mg_create_server()` creates a web server instance. An instance is a container
|
||||
for the config options and list of active connections. To do the actual
|
||||
serving, user must call `mg_poll_server()`, which iterates over all
|
||||
active connections, performing `select()` syscall on all sockets with a
|
||||
timeout of specified number of milliseconds. When `select()` returns, Mongoose
|
||||
does an IO for each socket that has data to be sent or received. Application
|
||||
code must call `mg_poll_server()` in a loop.
|
||||
|
||||
Mongoose server instance is designed to be used by a single thread.
|
||||
It is an error to have more then
|
||||
one thread calling `mg_poll_server()`, `mg_set_option()` or any other function
|
||||
that take `struct mg_server *` parameter. Mongoose does not
|
||||
mutex-protect `struct mg_server *`, therefore the best practice is
|
||||
to call server management functions from the same thread (an IO thread).
|
||||
On a multi-core systems, many server instances can be created, sharing the
|
||||
same listening socket and managed by separate threads (see [multi_threaded.c](https://github.com/cesanta/mongoose/blob/master/examples/multi_threaded.c))
|
||||
example.
|
||||
|
||||
It is an error to pass and store `struct mg_connection *` pointers for
|
||||
later use to send data. The reason is that they can be invalidated by the
|
||||
next `mg_poll_server()` call. For such a task,
|
||||
there is `mg_iterate_over_connections()` API
|
||||
exists, which sends a callback function to the IO thread, then IO thread
|
||||
calls specified function for all active connection.
|
||||
|
||||
When mongoose buffers in HTTP request and successfully parses it, it calls
|
||||
appropriate URI handler immediately for GET requests. For POST requests,
|
||||
Mongoose delays the call until the whole POST request is buffered in memory.
|
||||
POST data is available to the callback as `struct mg_connection::content`,
|
||||
and POST data length is in `struct mg_connection::content_len`.
|
||||
|
||||
Note that websocket connections are treated the same way. Mongoose buffers
|
||||
websocket frame in memory, and calls URI handler when frame is fully
|
||||
buffered. Frame data is available `struct mg_connection::content`, and
|
||||
data length is in `struct mg_connection::content_len`, i.e. very similar to
|
||||
the POST request. `struct mg_connection::is_websocket` flag indicates
|
||||
whether the request is websocket or not. Also, for websocket requests,
|
||||
there is `struct mg_connection::wsbits` field which contains first byte
|
||||
of the websocket frame which URI handler can examine. Note that to
|
||||
reply to the websocket client, `mg_websocket_write()` should be used.
|
||||
To reply to the plain HTTP client, `mg_write()` should be used.
|
51
3rdparty/mongoose/docs/LuaSqlite.md
vendored
Normal file
51
3rdparty/mongoose/docs/LuaSqlite.md
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
# 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.
|
154
3rdparty/mongoose/docs/Options.md
vendored
Normal file
154
3rdparty/mongoose/docs/Options.md
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
# Mongoose Configuration Options
|
||||
|
||||
### access\_control\_list
|
||||
An Access Control List (ACL) allows restrictions to be put on the list of IP
|
||||
addresses which have access to the web server. In the case of the Mongoose
|
||||
web server, the ACL is a comma separated list of IP subnets, where each
|
||||
subnet is prepended by either a `-` or a `+` sign. A plus sign means allow,
|
||||
where a minus sign means deny. If a subnet mask is omitted, such as `-1.2.3.4`,
|
||||
this means to deny only that single IP address.
|
||||
|
||||
Subnet masks may vary from 0 to 32, inclusive. The default setting is to allow
|
||||
all accesses. On each request the full list is traversed, and
|
||||
the last match wins. Example: `$ mongoose -access_control_list -0.0.0.0/0,+192.168/16` to deny all acccesses except those from `192.168/16` subnet. Note that if the option is set, then all accesses are forbidden
|
||||
by default. Thus in a previous example, `-0.0.0.0` part is not necessary.
|
||||
For example, `$mongoose access_control_list +10.0.0.0/8`
|
||||
means disallow all, allow subnet 10/8 only.
|
||||
|
||||
To learn more about subnet masks, see the
|
||||
[Wikipedia page on Subnetwork](http://en.wikipedia.org/wiki/Subnetwork)
|
||||
|
||||
Default: not set, all accesses are allowed.
|
||||
|
||||
### access\_log\_file
|
||||
Path to a file for access logs. Either full path, or relative to the
|
||||
mongoose executable. Default: not set, no query logging is done.
|
||||
|
||||
### auth_domain
|
||||
Authorization realm used in `.htpasswd` authorization. Default: `mydomain.com`
|
||||
|
||||
### cgi_interpreter
|
||||
Path to an executable to be used use as an interpreter for __all__ CGI scripts
|
||||
regardless script extension. Default: not set, Mongoose looks at
|
||||
[shebang line](http://en.wikipedia.org/wiki/Shebang_(Unix\).
|
||||
|
||||
For example, if both PHP and perl CGIs are used, then
|
||||
`#!/path/to/php-cgi.exe` and `#!/path/to/perl.exe` must be first lines of the
|
||||
respective CGI scripts. Note that paths should be either full file paths,
|
||||
or file paths relative to the directory where mongoose executable is located.
|
||||
|
||||
If all CGIs use the same interpreter, for example they are all PHP, then
|
||||
`cgi_interpreter` option can be set to the path to `php-cgi.exe` executable and
|
||||
shebang line in the CGI scripts can be omitted.
|
||||
**Note**: PHP scripts must use `php-cgi.exe`, not `php.exe`.
|
||||
|
||||
### cgi_pattern
|
||||
All files that match `cgi_pattern` are treated as CGI files. Default pattern
|
||||
allows CGI files be anywhere. To restrict CGIs to a certain directory,
|
||||
use `/path/to/cgi-bin/**.cgi` as a pattern. Note that **full file path** is
|
||||
matched against the pattern, not the URI.
|
||||
|
||||
When Mongoose starts CGI program, it creates new environment for it (in
|
||||
contrast, usually child program inherits the environment from parent). Several
|
||||
environment variables however are inherited from Mongoose's environment,
|
||||
they are: `PATH`, `TMP`, `TEMP`, `TMPDIR`, `PERLLIB`, `MONGOOSE_CGI`. On UNIX
|
||||
it is also `LD_LIBRARY_PATH`. On Windows it is also `COMSPEC`, `SYSTEMROOT`,
|
||||
`SystemDrive`, `ProgramFiles`, `ProgramFiles(x86)`, `CommonProgramFiles(x86)`.
|
||||
|
||||
Default: `**.cgi$|**.pl$|**.php$`
|
||||
|
||||
### dav\_auth\_file
|
||||
Authentication file for WebDAV mutation requests: `PUT`, `DELETE`, `MKCOL`.
|
||||
The format of that file is the same as for the `.htpasswd` file
|
||||
used for digest authentication. It can be created and managed by
|
||||
`mongoose -A` command. Default: not set, WebDAV mutations are disallowed.
|
||||
|
||||
### document_root
|
||||
A directory to serve. Default: current working directory.
|
||||
|
||||
### enable\_directory\_listing
|
||||
Enable directory listing, either `yes` or `no`. Default: `yes`.
|
||||
|
||||
### enable\_proxy
|
||||
Enable proxy functionality, either `yes` or `no`. If set to `yes`, then
|
||||
browsers can be configured to use Mongoose as a proxy. Default: `no`.
|
||||
|
||||
|
||||
### extra\_mime\_types
|
||||
Extra mime types to recognize, in form `extension1=type1,extension2=type2,...`.
|
||||
Extension must include dot. Example:
|
||||
`mongoose -extra_mime_types .cpp=plain/text,.java=plain/text`. Default: not set.
|
||||
|
||||
|
||||
### global\_auth\_file
|
||||
Path to a global passwords file, either full path or relative to the mongoose
|
||||
executable. If set, per-directory `.htpasswd` files are ignored,
|
||||
and all requests are authorised against that file. Use `mongoose -A` to
|
||||
manage passwords, or third party utilities like
|
||||
[htpasswd-generator](http://www.askapache.com/online-tools/htpasswd-generator).
|
||||
Default: not set, per-directory `.htpasswd` files are respected.
|
||||
|
||||
### hide\_files\_patterns
|
||||
A pattern for the files to hide. Files that match the pattern will not
|
||||
show up in directory listing and return `404 Not Found` if requested. Pattern
|
||||
must be for a file name only, not including directory name, e.g.
|
||||
`mongoose -hide_files_patterns secret.txt|even_more_secret.txt`. Default:
|
||||
not set.
|
||||
|
||||
### index_files
|
||||
Comma-separated list of files to be treated as directory index
|
||||
files. Default: `index.html,index.htm,index.cgi,index.shtml,index.php`
|
||||
|
||||
### listening_port
|
||||
Port to listen on. Port could be prepended by the specific IP address to bind
|
||||
to, e.g. `mongoose -listening_port 127.0.0.1:8080`. Otherwise Mongoose
|
||||
will bind to all addresses. To enable SSL, build Mongoose with
|
||||
`-DNS_ENABLE_SSL` compilation option, and specify `listening_port` as
|
||||
`ssl://PORT:SSL_CERTIFICATE.PEM`. Example SSL listener:
|
||||
`mongoose -listening_port ssl://8043:ssl_cert.pem`. Note that PEM file should
|
||||
be in PEM format, and must have both certificate and private key in it,
|
||||
concatenated together. More than one listening port can be specified,
|
||||
separated by comma,
|
||||
for example `mongoose -listening_port 8080,8000`. Default: 8080.
|
||||
|
||||
### run\_as\_user
|
||||
Switch to given user credentials after startup. UNIX-only. This option is
|
||||
required when mongoose needs to bind on privileged port on UNIX, e.g.
|
||||
|
||||
$ sudo mongoose -listening_port 80 -run_as_user nobody
|
||||
|
||||
Default: not set.
|
||||
|
||||
### url\_rewrites
|
||||
Comma-separated list of URL rewrites in the form of
|
||||
`uri_pattern=file_or_directory_path`. When Mongoose receives the request,
|
||||
it constructs the file name to show by combining `document_root` and the URI.
|
||||
However, if the rewrite option is used and `uri_pattern` matches the
|
||||
requested URI, then `document_root` is ignored. Instead,
|
||||
`file_or_directory_path` is used, which should be a full path name or
|
||||
a path relative to the web server's current working directory. Note that
|
||||
`uri_pattern`, as all mongoose patterns, is a prefix pattern. If `uri_pattern`
|
||||
is a number, then it is treated as HTTP error code, and `file_or_directory_path`
|
||||
should be an URI to redirect to. Mongoose will issue `302` temporary redirect
|
||||
to the specified URI with following parameters:
|
||||
`?code=HTTP_ERROR_CODE&orig_uri=ORIGINAL_URI&query_string=QUERY_STRING`.
|
||||
|
||||
If `uri_pattern` starts with `@` symbol, then Mongoose compares
|
||||
it with the `HOST` header of the request. If they are equal, Mongoose sets
|
||||
document root to `file_or_directory_path`, implementing virtual hosts support.
|
||||
|
||||
Examples:
|
||||
|
||||
# Redirect all accesses to `.doc` files to a special script
|
||||
mongoose -url_rewrites **.doc$=/path/to/cgi-bin/handle_doc.cgi
|
||||
|
||||
# Implement user home directories support
|
||||
mongoose -url_rewrites /~joe/=/home/joe/,/~bill=/home/bill/
|
||||
|
||||
# Redirect 404 errors to a specific error page
|
||||
mongoose -url_rewrites 404=/cgi-bin/error.cgi
|
||||
|
||||
# Virtual hosts example: serve foo.com domain from different directory
|
||||
mongoose -url_rewrites @foo.com=/var/www/foo.com
|
||||
|
||||
Default: not set.
|
49
3rdparty/mongoose/docs/PhpWebsite.md
vendored
Normal file
49
3rdparty/mongoose/docs/PhpWebsite.md
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
How To Create A PHP Website With Mongoose
|
||||
===========================================
|
||||
|
||||
## 1. Create a directory which will contain your website files. For example, on drive `C:\`, create a directory called `my_website`:
|
||||
|
||||

|
||||
|
||||
## 2. Inside `my_website` directory, create a new file called "index". This will be the default web page shown when the website is visited.
|
||||
|
||||

|
||||
|
||||
## 3. Open index file with your favorite editor (for example, Notepad) and enter some HTML / PHP code:
|
||||
|
||||

|
||||
|
||||
## 4. Save this file as `index.php`:
|
||||
|
||||

|
||||
|
||||
|
||||
## 5. Download Mongoose executable from http://cesanta.com/mongoose.shtml and copy the executable inside `my_website` directory:
|
||||
|
||||

|
||||
|
||||
## 6. Double-click mongoose executable. An icon will appear on a system tray in the bottom right corner of the desktop:
|
||||
|
||||

|
||||
|
||||
## 7. Download PHP 5.3 zip (do NOT download PHP 5.5 cause you might have missing DLLs problem) from http://windows.php.net/download and extract it to `C:\php5` directory:
|
||||

|
||||
|
||||
## 8. Click on the mongoose icon and choose "Edit Settings" menu.:
|
||||

|
||||
|
||||
## 9. A settings dialog will appear. Click on `cgi_interpreter` button:
|
||||
|
||||

|
||||
|
||||
## 10. Choose `C:\php5\php-cgi.exe` and click "Save Settings":
|
||||
|
||||

|
||||
|
||||
## 11. Click on the mongoose icon and choose "Go to my address" menu:
|
||||

|
||||
|
||||
|
||||
## 12. A browser will popup displaying `index.php`.
|
||||
|
||||

|
193
3rdparty/mongoose/docs/ReleaseNotes.md
vendored
Normal file
193
3rdparty/mongoose/docs/ReleaseNotes.md
vendored
Normal file
@ -0,0 +1,193 @@
|
||||
# Mongoose Release Notes
|
||||
|
||||
## Release 5.5, October 28 2014
|
||||
|
||||
Changes in Libmongoose library:
|
||||
|
||||
- Added new API function: `mg_forward()` for proxying functionality
|
||||
- Added new API function: `mg_send_file_data()` for sending file data
|
||||
- Added new utility API functions: `mg_mmap() and mg_munmap()`
|
||||
- Changed the way SSL settings are handled: removed `ssl_certificate` and
|
||||
`ssl_ca_certificate` options, and instead made `listening_port` accept
|
||||
`ssl://PORT:SSL_CERT:CA_CERT` notation
|
||||
- Added ability to listen on multiple ports, see `listening_port` documentation
|
||||
- Added `enable_proxy` option
|
||||
- Added [cookie_authentication](https://github.com/cesanta/mongoose/tree/master/examples/cookie_authentication) example
|
||||
- Added [websocket\_ssl\_proxy](https://github.com/cesanta/mongoose/tree/master/examples/websocket_ssl_proxy) example
|
||||
- Added [http_client](https://github.com/cesanta/mongoose/tree/master/examples/http_client) example
|
||||
- Increased default 'idle connection' timeout from 30 to 300 seconds
|
||||
- Fixed MinGW build
|
||||
- Refactored all examples, put each in it's own directory with dedicated build
|
||||
- Many smaller bugfixed, including SSL, CGI, API, proxy, etc
|
||||
|
||||
Changes in pre-compiled binaries:
|
||||
|
||||
- Support for multiple listening ports
|
||||
- Fixed CGI handling for scripts that specify interpreter in the hashbang line
|
||||
|
||||
## Release 5.4, July 28 2014
|
||||
|
||||
Changes in Libmongoose library:
|
||||
|
||||
- Added `hexdump_file` option for low-level request/reply debugging
|
||||
- Added `mg_template()` API function for generating HTML pages from
|
||||
templates with expansions
|
||||
- Fixed `struct mg_connection::local_ip` handling, `mg_set_option()`
|
||||
behavior with NULL values
|
||||
- Added `mg_send_file()` call to send arbitrary file to the client
|
||||
- Added `mg_terminate_ssl()` for SSL termination functionality
|
||||
- Added HTTP proxy support, `enable_proxy` config option
|
||||
- Added `mg_next()` for iterating over existing active connections
|
||||
- Added client-side SSL auth, `ssl_ca_certificate` option
|
||||
- Added `mg_wakeup_server_ex()` for pushing messages to existing connections
|
||||
- Added `MG_WS_HANDSHAKE` and `MG_WS_CONNECT` events that are sent on
|
||||
Websocket handshake is connection establishment, respectively
|
||||
- Removed server-side Lua support
|
||||
- Filesystem access, reading from socket/SSL performance improvements
|
||||
- DAV PROPFIND memory leak fixed
|
||||
- Added `big_upload.c` and enhanced `upload.c` example
|
||||
- Added `proxy.c` example that demonstrates proxy functionality and SSE pushes
|
||||
- Added `websocket2.c` example that shows simple web chat implementation
|
||||
over websockets
|
||||
- Various minor fixes
|
||||
|
||||
|
||||
Changes in pre-compiled binaries:
|
||||
|
||||
- Created HTML administration console
|
||||
- When server is started, browser is started automatically
|
||||
- Fixed directory listing bug when directory contains `#` character
|
||||
- Removed built-in Lua Server Pages in the binary, and instead
|
||||
added Mongoose + Lua developer bundle which has Lua Server Pages support.
|
||||
That also solves external Lua modules loading problem.
|
||||
|
||||
|
||||
## Release 5.3, March 10 2014
|
||||
|
||||
Changes in Libmongoose library:
|
||||
|
||||
* Moved to the evented API. Updated API documentation is at
|
||||
http://cesanta.com/docs/Embed.shtml
|
||||
http://cesanta.com/docs/API.shtml
|
||||
* Added `MG_LUA` event for exporting custom variables to the Lua environment
|
||||
* Added virtual hosts capability, see `url_rewrites` option description at
|
||||
http://cesanta.com/docs/Options.shtml
|
||||
* Added mjpg serving example
|
||||
* Cleaned up and documented HTTP client API, with unit tests
|
||||
* Added `mg_wakeup_server()` to awaken `mg_poll_server()`
|
||||
from another thread
|
||||
* Moved Mongoose IO core to [https://github.com/cesanta/net_skeleton](Net Skeleton)
|
||||
* Added connection hexdump functionality for developers
|
||||
* Bug fixes
|
||||
|
||||
Changes in pre-compiled binaries:
|
||||
|
||||
* New awesome Mongoose logos by our designer Katrin - thanks Katrin!
|
||||
Check them out at http://cesanta.com/products.shtml
|
||||
* Added Lua Server Pages support to the free version, quick intro is at
|
||||
http://cesanta.com/docs/Lua.shtml
|
||||
* Added quick "Set shared directory" menu item to set `document_root`
|
||||
* Added SSI support to the Pro version
|
||||
* Removed SSL support from the Pro version
|
||||
|
||||
## Release 5.2, Feb 1 2014
|
||||
|
||||
* Windows binary made fully UNICODE aware. In previous versions,
|
||||
the presence of non-ASCII chars in document root, CGI script name,
|
||||
or directory name might have broken Mongoose as stand-alone
|
||||
or as Windows service. Now Mongoose works with non-ASCII paths properly.
|
||||
Internally, Mongoose uses UTF8 encoding. When making WinAPI calls,
|
||||
mongoose converts UTF8 strings to wide chars and calls UNICODE API.
|
||||
* Enhanced authorization API by providing `mg_set_auth_handler()` and
|
||||
`mg_authorize_digest()`
|
||||
* Removed `mg_add_uri_handler()`, added `mg_set_request_handler()`.
|
||||
There is only oneURI handler that handles all requests, just like in 4.x.
|
||||
The reason for this change is to provide an ability to catch all URIs,
|
||||
and at the same time signal Mongoose to continue handling specific URIs.
|
||||
* Added `mg_parse_multipart()` API for file uploads.
|
||||
Note that the restriction on uploading huge files still exists,
|
||||
and will be eliminated in the next release.
|
||||
* Allowing mongoose to bind to port 0, in which case it'll bind to any
|
||||
random unused port.
|
||||
* Moved `idle_timeout_ms` run-time option to compile-time flag
|
||||
* Added asynchronous HTTP client, not documented yet. Documentation and
|
||||
examples are coming in the next couple of weeks. Async Websocket client
|
||||
is scheduled for the next release. See usage examples at `unit_test.c`
|
||||
* Windows and MacOS pre-built binaries are now split to free and paid ones,
|
||||
paid binaries include CGI, SSL, Lua, Sqlite, support and updates.
|
||||
Linux pre-built binary includes all functionality and is free, and will
|
||||
continue to be free. Source code for Windows and MacOS GUI is closed.
|
||||
Disclaimer: source code for the command line stand-alone server,
|
||||
as well as Mongoose library itself, will never be closed.
|
||||
* Multiple bug fixes and minor enhancements
|
||||
|
||||
## Release 5.1, Jan 10 2014
|
||||
|
||||
* CGI-related bugs where fixed, primarily for Windows platform
|
||||
* Bugs on Windows related to UNICODE support were fixed
|
||||
* Added a feature to support "error pages" through redirect.
|
||||
Done using `-url_redirects` option, details are on
|
||||
http://cesanta.com/docs/Options.shtml
|
||||
|
||||
## Release 5.0, Jan 6 2014
|
||||
|
||||
* Internal core has been changed from blocking, thread-per-connection to
|
||||
non-blocking, asynchronous, one thread for all.
|
||||
* API modification for server creation and response creation. That allowed
|
||||
keep-alive support for dynamic requests, boosting the embedded performance
|
||||
to 100+ thousands requests per second on a single core
|
||||
(as measured on my development MacBook laptop)
|
||||
* Unified handling of POST requests and Websocket requests by putting a
|
||||
payload into `conn->content`, `conn->content_len` attributes.
|
||||
That simplified user code and eliminated the need of `mg_read()`,
|
||||
since mongoose buffers all data prior to calling the callback
|
||||
* keep-alive support is the default
|
||||
* Dropped SSI support and throttling support
|
||||
* Several configuraition parameters are gone:
|
||||
* `cgi_environment` (replaced with MONGOOSE_CGI),
|
||||
* `protect_uri` (not useful)
|
||||
* `ssi_pattern` (SSI support is gone)
|
||||
* `throttle` (throttling support is gone)
|
||||
* `error_log_file` (not used)
|
||||
* `enable_keep_alive` (enabled by default)
|
||||
* `listening_ports` (renamed to listening_port)
|
||||
* `num_threads` (core has changed to single thread)
|
||||
* `put_delete_auth_file` (renamed to dav_auth_file)
|
||||
* `authentication_domain` (renamed to auth_domain)
|
||||
* Due to the async, non-blocking nature of the core, few restrictions
|
||||
are now in place:
|
||||
* user callbacks must not block
|
||||
* POST and Websocket data are now buffered, and cannot be huge
|
||||
* mongoose is now capable on listening on only one port
|
||||
|
||||
## Release 4.1, Oct 2013
|
||||
## Release 4.0, Oct 2013
|
||||
## Release 3.8, Sep 2013
|
||||
|
||||
## Release 3.7, Feb 2 2013
|
||||
|
||||
* Added "redirect to SSL port" functionality, e.g. if you specify
|
||||
`-listening_ports 8080r,8043s`
|
||||
then all requests to HTTP port 8080 will be redirected to HTTPS port 8043
|
||||
* Added `mg_download()` API, an HTTP client interface!
|
||||
* Lua server pages now must output HTTP headers -- full control for Lua
|
||||
* Added pre-built binary for MacOS, with initial GUI support
|
||||
* API change: got rid of events, moved to struct `mg_callbacks`
|
||||
* Bugfixes, thanks to contributors
|
||||
|
||||
|
||||
## Release 3.7, Jan 18 2013
|
||||
* Fixed source code archive (main.c was missing)
|
||||
* Extended Windows GUI functionality:
|
||||
* Added "Start browser" systray popup menu item
|
||||
* Enhanced configuration editor
|
||||
* Renamed config options:
|
||||
* `put_delete_passwords_file` -> `put_delete_auth_file`
|
||||
* `global_passwords_file` -> `global_auth_file`
|
||||
* `select()` changed to `poll()`, to avoid big file descriptor
|
||||
`FD_SET` problem on UNIX
|
||||
* Couple of bugfixes, thanks to contributors
|
||||
|
||||
|
||||
Eearlier release notes could be found by searching
|
||||
[Mongoose mailing list](https://groups.google.com/forum/#!forum/mongoose-users)
|
75
3rdparty/mongoose/docs/SSL.md
vendored
Normal file
75
3rdparty/mongoose/docs/SSL.md
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
# Mongoose SSL guide
|
||||
|
||||
SSL is a protocol that makes web communication secure. To enable SSL
|
||||
in mongoose, 3 steps are required:
|
||||
|
||||
1. Valid certificate file must be created
|
||||
2. `ssl_certificate` options must be set to contain path to the
|
||||
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:
|
||||
|
||||
document_root www_root # Serve files in www_root directory
|
||||
listening_ports 80r,443s # Redirect all HTTP requests to HTTPS
|
||||
ssl_certificate ssl_cert.pem # Location of certificate file
|
||||
|
||||
## How to create SSL certificate file
|
||||
|
||||
SSL certificate file is a text file that must contain at least two
|
||||
sections:
|
||||
|
||||
1. A private key
|
||||
2. A certificate
|
||||
|
||||
Both sections should be chunks of text in PEM format. When PEM file is
|
||||
opened in a text editor, it looks like this:
|
||||
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAwONaLOP7EdegqjRuQKSDXzvHmFMZfBufjhELhNjo5KsL4ieH
|
||||
hYN0Zii2yTb63jGxKY6gH1R/r9dL8kXaJmcZrfSa3AgywnteJWg=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDBjCCAe4CCQCX05m0b053QzANBgkqhkiG9w0BAQQFADBFMQswCQYDVQQGEwJB
|
||||
SEGI4JSxV56lYg==
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
Two aforementioned sections are clearly seen. Typically, those section
|
||||
are bigger then in the example shown. The text between the `BEGIN` and
|
||||
`END` is the text representation of binary data, a private key and a
|
||||
certificate. Therefore, in order to create a certificate file,
|
||||
|
||||
* private key must be converted to PEM format
|
||||
* certificate must be converted to PEM format
|
||||
* those two should be concatenated into a single file
|
||||
|
||||
If the certificate chain in used, a chain file also needs to be
|
||||
converted into PEM format and appended to the certificate file.
|
||||
|
||||
## How SSL works
|
||||
|
||||
SSL is a protocol that can encrypt communication between two parties. If third
|
||||
party observes all messages passed by, it would be very
|
||||
hard for the third party (though not impossible) to decrypt the communication.
|
||||
|
||||
The idea is based on so-called public key encryption. Communicating parties
|
||||
have two keys: a public key and a private key. A public key is advertised
|
||||
to everybody, and it is contained in a certificate. A private key is kept
|
||||
secret. Security algorithm works in a way that anybody can encrypt
|
||||
a message using public key, and only private key can decrypt it.
|
||||
|
||||
This is why web server needs both private key and certificate: private key
|
||||
is used to decrypt incoming messages, and certificate is used to tell the
|
||||
public key to the other party. When communication starts, parties exchange
|
||||
their public keys, and keep private keys to themselves. Man-in-the-middle
|
||||
who observes the communication is unable to decrypt the messages cause
|
||||
private keys are required for decryption.
|
||||
|
||||
Encryption algorithms are built on top of hard mathematical problem, which
|
||||
makes it very expensive for man-in-the-middle to compute private keys.
|
||||
For example, RSA algorithm is based on a mathematical problem of factorization.
|
||||
It is easy to generate two very large prime numbers `P` and `Q` and make
|
||||
a product `P * Q`. But given a product, it is very hard to recover these
|
||||
two prime numbers - this is called factorization.
|
86
3rdparty/mongoose/docs/Usage.md
vendored
Normal file
86
3rdparty/mongoose/docs/Usage.md
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
# Mongoose User Guide
|
||||
|
||||
Mongoose is small and easy to use web server built on top of
|
||||
mongoose library. It is designed with maximum simplicity in mind. For example,
|
||||
to share any directory, just drop mongoose executable in that directory,
|
||||
double-click it (on UNIX, run it from shell) and launch a browser at
|
||||
[http://localhost:8080](http://localhost:8080) Note that 'localhost' should
|
||||
be changed to a machine's name if a folder is accessed from other computer.
|
||||
|
||||
On Windows and Mac, Mongoose iconifies itself to the system tray when started.
|
||||
Right-click on the icon to pop up a menu, where it is possible to stop
|
||||
mongoose, or configure it.
|
||||
|
||||
On UNIX, `mongoose` is a command line utility. Running `mongoose` in
|
||||
terminal, optionally followed by configuration parameters
|
||||
(`mongoose [OPTIONS]`) or configuration file name
|
||||
(`mongoose [config_file_name]`) starts the
|
||||
web server:
|
||||
|
||||
$ mongoose -document_root /var/www # Running mongoose with cmdline options
|
||||
$ mongoose /etc/my_config.txt # Running mongoose with config file
|
||||
$ mongoose # Running with no parameters. This will
|
||||
# serve current directory on port 8080
|
||||
|
||||
Mongoose does not detach from terminal. Pressing `Ctrl-C` keys
|
||||
stops the server.
|
||||
|
||||
When started, mongoose first searches for the configuration file.
|
||||
If configuration file is specified explicitly in the command line, then
|
||||
specified configuration file is used.
|
||||
Otherwise, mongoose would search for file `mongoose.conf` in the same directory
|
||||
where binary is located, and use it. Configuration file can be absent.
|
||||
|
||||
Configuration file is a sequence of lines, each line containing
|
||||
command line argument name and it's value. Empty lines and lines beginning
|
||||
with `#` are ignored. Here is the example of `mongoose.conf` file:
|
||||
|
||||
# This is a comment
|
||||
document_root C:\www
|
||||
listening_port 80
|
||||
ssl_certificate C:\mongoose\ssl_cert.pem
|
||||
|
||||
Command line arguments are highest priority and can override
|
||||
configuration file settings. For example, if `mongoose.conf` has line
|
||||
`document_root /var/www`, and mongoose has been started as
|
||||
`mongoose -document_root /etc`, then `/etc` directory will be used as
|
||||
document root.
|
||||
|
||||
Note that configuration options on the command line must start with `-`,
|
||||
and their names are the same as in the config file. Exampli gratia,
|
||||
the following two setups are equivalent:
|
||||
|
||||
$ mongoose -listening_port 1234 -document_root /var/www
|
||||
|
||||
$ cat > mongoose.conf
|
||||
listening_ports 1234
|
||||
document_root /var/www
|
||||
^D
|
||||
$ mongoose
|
||||
|
||||
Mongoose can also be used to modify `.htpasswd` passwords file:
|
||||
|
||||
$ mongoose -A .htpasswd mydomain.com user_name user_password
|
||||
|
||||
Unlike other web servers, mongoose does not require CGI scripts be located in
|
||||
a special directory. CGI scripts can be anywhere. CGI (and SSI) files are
|
||||
recognized by the file name pattern. Mongoose uses shell-like glob
|
||||
patterns. Pattern match starts at the beginning of the string, so essentially
|
||||
patterns are prefix patterns. Syntax is as follows:
|
||||
|
||||
** Matches everything
|
||||
* Matches everything but slash character, '/'
|
||||
? Matches any character
|
||||
$ Matches the end of the string
|
||||
| Matches if pattern on the left side or the right side matches.
|
||||
|
||||
All other characters in the pattern match themselves. Examples:
|
||||
|
||||
# Pattern Meaning
|
||||
**.cgi$ Any string that ends with .cgi
|
||||
/foo Any string that begins with /foo
|
||||
**a$|**b$ Any string that ends with a or b
|
||||
|
||||
To restrict CGI files only to `/cgi-bin/` directory, use this setting:
|
||||
|
||||
$ mongoose -cgi_pattern /cgi-bin/*.cgi # Emulate /cgi-bin/ restriction
|
15
3rdparty/mongoose/examples/Makefile
vendored
Normal file
15
3rdparty/mongoose/examples/Makefile
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
# Copyright (c) 2014 Cesanta Software
|
||||
# All rights reserved
|
||||
|
||||
SUBDIRS = $(sort $(filter-out csharp/, $(dir $(wildcard */))))
|
||||
X = $(SUBDIRS)
|
||||
|
||||
.PHONY: $(SUBDIRS)
|
||||
|
||||
all: $(SUBDIRS)
|
||||
|
||||
$(SUBDIRS):
|
||||
@$(MAKE) -C $@
|
||||
|
||||
clean:
|
||||
for d in $(SUBDIRS) ; do $(MAKE) -C $$d clean ; done
|
12
3rdparty/mongoose/examples/big_upload/Makefile
vendored
Normal file
12
3rdparty/mongoose/examples/big_upload/Makefile
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# Copyright (c) 2014 Cesanta Software
|
||||
# All rights reserved
|
||||
|
||||
PROG = big_upload
|
||||
CFLAGS = -W -Wall -pthread -I../.. -g -O0 $(CFLAGS_EXTRA)
|
||||
SOURCES = $(PROG).c ../../mongoose.c
|
||||
|
||||
$(PROG): $(SOURCES)
|
||||
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib
|
84
3rdparty/mongoose/examples/big_upload/big_upload.c
vendored
Normal file
84
3rdparty/mongoose/examples/big_upload/big_upload.c
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "mongoose.h"
|
||||
|
||||
static int handle_request(struct mg_connection *conn) {
|
||||
if (strcmp(conn->uri, "/upload") == 0) {
|
||||
FILE *fp = (FILE *) conn->connection_param;
|
||||
if (fp != NULL) {
|
||||
fwrite(conn->content, 1, conn->content_len, fp); // Write last bits
|
||||
mg_printf(conn, "HTTP/1.1 200 OK\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"Connection: close\r\n\r\n"
|
||||
"Written %ld of POST data to a temp file:\n\n",
|
||||
(long) ftell(fp));
|
||||
|
||||
// Temp file will be destroyed after fclose(), do something with the
|
||||
// data here -- for example, parse it and extract uploaded files.
|
||||
// As an example, we just echo the whole POST buffer back to the client.
|
||||
rewind(fp);
|
||||
mg_send_file_data(conn, fileno(fp));
|
||||
return MG_MORE; // Tell Mongoose reply is not completed yet
|
||||
} else {
|
||||
mg_printf_data(conn, "%s", "Had no data to write...");
|
||||
return MG_TRUE; // Tell Mongoose we're done with this request
|
||||
}
|
||||
} else {
|
||||
mg_printf_data(conn, "%s",
|
||||
"<html><body>Upload example."
|
||||
"<form method=\"POST\" action=\"/upload\" "
|
||||
" enctype=\"multipart/form-data\">"
|
||||
"<input type=\"file\" name=\"file\" /> <br/>"
|
||||
"<input type=\"submit\" value=\"Upload\" />"
|
||||
"</form></body></html>");
|
||||
return MG_TRUE; // Tell mongoose to close this connection
|
||||
}
|
||||
}
|
||||
|
||||
// Mongoose sends MG_RECV for every received POST chunk.
|
||||
// When last POST chunk is received, Mongoose sends MG_REQUEST, then MG_CLOSE.
|
||||
static int handle_recv(struct mg_connection *conn) {
|
||||
FILE *fp = (FILE *) conn->connection_param;
|
||||
|
||||
// Open temporary file where we going to write data
|
||||
if (fp == NULL && ((conn->connection_param = fp = tmpfile())) == NULL) {
|
||||
return -1; // Close connection on error
|
||||
}
|
||||
|
||||
// Return number of bytes written to a temporary file: that is how many
|
||||
// bytes we want to discard from the receive buffer
|
||||
return fwrite(conn->content, 1, conn->content_len, fp);
|
||||
}
|
||||
|
||||
// Make sure we free all allocated resources
|
||||
static int handle_close(struct mg_connection *conn) {
|
||||
if (conn->connection_param != NULL) {
|
||||
fclose((FILE *) conn->connection_param);
|
||||
conn->connection_param = NULL;
|
||||
}
|
||||
return MG_TRUE;
|
||||
}
|
||||
|
||||
static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||
switch (ev) {
|
||||
case MG_AUTH: return MG_TRUE;
|
||||
case MG_REQUEST: return handle_request(conn);
|
||||
case MG_RECV: return handle_recv(conn);
|
||||
case MG_CLOSE: return handle_close(conn);
|
||||
default: return MG_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
struct mg_server *server = mg_create_server(NULL, ev_handler);
|
||||
mg_set_option(server, "listening_port", "8080");
|
||||
printf("Starting on port %s\n", mg_get_option(server, "listening_port"));
|
||||
|
||||
for (;;) {
|
||||
mg_poll_server(server, 1000);
|
||||
}
|
||||
|
||||
mg_destroy_server(&server);
|
||||
return 0;
|
||||
}
|
12
3rdparty/mongoose/examples/cookie_authentication/Makefile
vendored
Normal file
12
3rdparty/mongoose/examples/cookie_authentication/Makefile
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# Copyright (c) 2014 Cesanta Software
|
||||
# All rights reserved
|
||||
|
||||
PROG = cookie_auth
|
||||
CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA)
|
||||
SOURCES = $(PROG).c ../../mongoose.c
|
||||
|
||||
$(PROG): $(SOURCES)
|
||||
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib
|
96
3rdparty/mongoose/examples/cookie_authentication/cookie_auth.c
vendored
Normal file
96
3rdparty/mongoose/examples/cookie_authentication/cookie_auth.c
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
// Copyright (c) 2014 Cesanta Software
|
||||
// All rights reserved
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "mongoose.h"
|
||||
|
||||
static const char *s_login_uri = "/login.html";
|
||||
static const char *s_secret = ":-)"; // Must be known only to server
|
||||
|
||||
static void generate_ssid(const char *user_name, const char *expiration_date,
|
||||
char *ssid, size_t ssid_size) {
|
||||
char hash[33];
|
||||
mg_md5(hash, user_name, ":", expiration_date, ":", s_secret, NULL);
|
||||
snprintf(ssid, ssid_size, "%s|%s|%s", user_name, expiration_date, hash);
|
||||
}
|
||||
|
||||
static int check_auth(struct mg_connection *conn) {
|
||||
char ssid[100], calculated_ssid[100], name[100], expire[100];
|
||||
|
||||
// Always authenticate requests to login page
|
||||
if (strcmp(conn->uri, s_login_uri) == 0) {
|
||||
return MG_TRUE;
|
||||
}
|
||||
|
||||
// Look for session ID in the Cookie.
|
||||
// That session ID can be validated against the database that stores
|
||||
// current active sessions.
|
||||
mg_parse_header(mg_get_header(conn, "Cookie"), "ssid", ssid, sizeof(ssid));
|
||||
if (sscanf(ssid, "%[^|]|%[^|]|", name, expire) == 2) {
|
||||
generate_ssid(name, expire, calculated_ssid, sizeof(calculated_ssid));
|
||||
if (strcmp(ssid, calculated_ssid) == 0) {
|
||||
return MG_TRUE; // Authenticate
|
||||
}
|
||||
}
|
||||
|
||||
// Auth failed, do NOT authenticate, redirect to login page
|
||||
mg_printf(conn, "HTTP/1.1 302 Moved\r\nLocation: %s\r\n\r\n", s_login_uri);
|
||||
return MG_FALSE;
|
||||
}
|
||||
|
||||
static int check_login_form_submission(struct mg_connection *conn) {
|
||||
char name[100], password[100], ssid[100], expire[100], expire_epoch[100];
|
||||
|
||||
mg_get_var(conn, "name", name, sizeof(name));
|
||||
mg_get_var(conn, "password", password, sizeof(password));
|
||||
|
||||
// A real authentication mechanism should be employed here.
|
||||
// Also, the whole site should be served through HTTPS.
|
||||
if (strcmp(name, "Joe") == 0 && strcmp(password, "Doe") == 0) {
|
||||
// Generate expiry date
|
||||
time_t t = time(NULL) + 3600; // Valid for 1 hour
|
||||
snprintf(expire_epoch, sizeof(expire_epoch), "%lu", (unsigned long) t);
|
||||
strftime(expire, sizeof(expire), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t));
|
||||
generate_ssid(name, expire_epoch, ssid, sizeof(ssid));
|
||||
// Set "session id" cookie, there could be some data encoded in it.
|
||||
mg_printf(conn,
|
||||
"HTTP/1.1 302 Moved\r\n"
|
||||
"Set-Cookie: ssid=%s; expire=\"%s\"; http-only; HttpOnly;\r\n"
|
||||
"Location: /\r\n\r\n",
|
||||
ssid, expire);
|
||||
return MG_TRUE;
|
||||
}
|
||||
return MG_FALSE;
|
||||
}
|
||||
|
||||
static int serve_request(struct mg_connection *conn) {
|
||||
if (strcmp(conn->uri, s_login_uri) == 0 &&
|
||||
strcmp(conn->request_method, "POST") == 0) {
|
||||
return check_login_form_submission(conn);
|
||||
}
|
||||
return MG_FALSE; // Serve files in the document_root
|
||||
}
|
||||
|
||||
static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||
switch (ev) {
|
||||
case MG_AUTH: return check_auth(conn);
|
||||
case MG_REQUEST: return serve_request(conn);
|
||||
default: return MG_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
struct mg_server *server = mg_create_server(NULL, ev_handler);
|
||||
mg_set_option(server, "listening_port", "8080");
|
||||
mg_set_option(server, "document_root", ".");
|
||||
|
||||
printf("Starting on port %s\n", mg_get_option(server, "listening_port"));
|
||||
for (;;) {
|
||||
mg_poll_server(server, 1000);
|
||||
}
|
||||
mg_destroy_server(&server);
|
||||
|
||||
return 0;
|
||||
}
|
33
3rdparty/mongoose/examples/cookie_authentication/index.html
vendored
Normal file
33
3rdparty/mongoose/examples/cookie_authentication/index.html
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>WebSocket Test</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<style type="text/css">
|
||||
body {
|
||||
background-color: #cde; margin: 0;
|
||||
padding: 0; font: 14px Helvetica, Arial, sans-serif;
|
||||
}
|
||||
* { outline: none; }
|
||||
div.content {
|
||||
width: 800px; margin: 2em auto; padding: 20px 50px;
|
||||
background-color: #fff; border-radius: 1em;
|
||||
}
|
||||
label { display: inline-block; min-width: 7em; }
|
||||
input { border: 1px solid #ccc; padding: 0.4em; margin: 0 0 10px 0; }
|
||||
a:link, a:visited { color: #69c; text-decoration: none; }
|
||||
@media (max-width: 700px) {
|
||||
body { background-color: #fff; }
|
||||
div.content {
|
||||
width: auto; margin: 0 auto; border-radius: 0; padding: 1em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<div class="content">
|
||||
<h1>Mongoose Cookie Base Authentication</h1>
|
||||
<p>This is an index page. Authentication succeeded.</p>
|
||||
</body>
|
||||
</html>
|
44
3rdparty/mongoose/examples/cookie_authentication/login.html
vendored
Normal file
44
3rdparty/mongoose/examples/cookie_authentication/login.html
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>WebSocket Test</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<style type="text/css">
|
||||
body {
|
||||
background-color: #cde; margin: 0;
|
||||
padding: 0; font: 14px Helvetica, Arial, sans-serif;
|
||||
}
|
||||
* { outline: none; }
|
||||
div.content {
|
||||
width: 800px; margin: 2em auto; padding: 20px 50px;
|
||||
background-color: #fff; border-radius: 1em;
|
||||
}
|
||||
label { display: inline-block; min-width: 7em; }
|
||||
input { border: 1px solid #ccc; padding: 0.4em; margin: 0 0 10px 0; }
|
||||
a:link, a:visited { color: #69c; text-decoration: none; }
|
||||
@media (max-width: 700px) {
|
||||
body { background-color: #fff; }
|
||||
div.content {
|
||||
width: auto; margin: 0 auto; border-radius: 0; padding: 1em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<div class="content">
|
||||
<h1>Mongoose Cookie Based Authentication</h1>
|
||||
<p>Use name "Joe", password "Doe" to login.</p>
|
||||
<form method="POST">
|
||||
<div>
|
||||
<label>Name:</label>
|
||||
<input type="text" name="name"/>
|
||||
</div><div>
|
||||
<label>Password:</label>
|
||||
<input type="password" name="password"/>
|
||||
</div><div>
|
||||
<input type="submit" value="Login"/>
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
43
3rdparty/mongoose/examples/csharp/example.cs
vendored
Normal file
43
3rdparty/mongoose/examples/csharp/example.cs
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
// This file is part of mongoose web server project,
|
||||
// https://github.com/cesanta/mongoose
|
||||
|
||||
using System;
|
||||
|
||||
public class Program {
|
||||
static private int EventHandler(IntPtr conn_ptr, int ev) {
|
||||
MongooseConnection conn = (MongooseConnection)
|
||||
System.Runtime.InteropServices.Marshal.PtrToStructure(
|
||||
conn_ptr , typeof(MongooseConnection));
|
||||
|
||||
if (ev == 102) {
|
||||
// MG_AUTH
|
||||
return 1;
|
||||
} else if (ev == 103) {
|
||||
// MG_REQUEST
|
||||
Mongoose.send_data(conn_ptr, "Hello from C#!\n");
|
||||
Mongoose.send_data(conn_ptr, "URI: " + conn.uri + "\n");
|
||||
Mongoose.send_data(conn_ptr, "HTTP Headers:\n");
|
||||
|
||||
for (int i = 0; i < conn.num_headers; i++) {
|
||||
IntPtr name = conn.http_headers[i].name;
|
||||
IntPtr val = conn.http_headers[i].value;
|
||||
System.Runtime.InteropServices.Marshal.PtrToStringAnsi(name);
|
||||
Mongoose.send_data(conn_ptr, " " +
|
||||
System.Runtime.InteropServices.Marshal.PtrToStringAnsi(name) + ": " +
|
||||
System.Runtime.InteropServices.Marshal.PtrToStringAnsi(val) + "\n");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void Main() {
|
||||
Mongoose web_server = new Mongoose(".", "9001",
|
||||
new MongooseEventHandler(EventHandler));
|
||||
|
||||
Console.WriteLine("Mongoose started, press Ctrl-C to exit.");
|
||||
for (;;) {
|
||||
web_server.poll(1000);
|
||||
}
|
||||
}
|
||||
}
|
68
3rdparty/mongoose/examples/csharp/mongoose.cs
vendored
Normal file
68
3rdparty/mongoose/examples/csharp/mongoose.cs
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
// This file is part of mongoose web server project,
|
||||
// https://github.com/cesanta/mongoose
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)] public struct MongooseHeader {
|
||||
[MarshalAs(UnmanagedType.LPTStr)] public IntPtr name;
|
||||
[MarshalAs(UnmanagedType.LPTStr)] public IntPtr value;
|
||||
};
|
||||
|
||||
// mongoose.h :: struct mg_connection
|
||||
[StructLayout(LayoutKind.Sequential)] public struct MongooseConnection {
|
||||
[MarshalAs(UnmanagedType.LPTStr)] public string request_method;
|
||||
[MarshalAs(UnmanagedType.LPTStr)] public string uri;
|
||||
[MarshalAs(UnmanagedType.LPTStr)] public string http_version;
|
||||
[MarshalAs(UnmanagedType.LPTStr)] public string query_string;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray,SizeConst=48)] public char[] remote_ip;
|
||||
[MarshalAs(UnmanagedType.LPTStr)] public string local_ip;
|
||||
[MarshalAs(UnmanagedType.U2)] public short remote_port;
|
||||
[MarshalAs(UnmanagedType.U2)] public short local_port;
|
||||
|
||||
[MarshalAs(UnmanagedType.SysInt)] public int num_headers;
|
||||
[MarshalAs(UnmanagedType.ByValArray,SizeConst=30)]
|
||||
public MongooseHeader[] http_headers;
|
||||
|
||||
[MarshalAs(UnmanagedType.LPTStr)] public IntPtr content;
|
||||
[MarshalAs(UnmanagedType.SysInt)] public int content_len;
|
||||
|
||||
[MarshalAs(UnmanagedType.SysInt)] public int is_websocket;
|
||||
[MarshalAs(UnmanagedType.SysInt)] public int status_code;
|
||||
[MarshalAs(UnmanagedType.SysInt)] public int wsbits;
|
||||
};
|
||||
|
||||
public delegate int MongooseEventHandler(IntPtr c, int ev);
|
||||
|
||||
public class Mongoose {
|
||||
public const string dll_ = "mongoose";
|
||||
private IntPtr server_;
|
||||
|
||||
[DllImport(dll_)] private static extern IntPtr
|
||||
mg_create_server(IntPtr user_data, MongooseEventHandler eh);
|
||||
[DllImport(dll_)] private static extern int
|
||||
mg_poll_server(IntPtr server, int milli);
|
||||
[DllImport(dll_)] private static extern IntPtr
|
||||
mg_set_option(IntPtr server, string name, string value);
|
||||
[DllImport(dll_)] public static extern int
|
||||
mg_send_data(IntPtr conn, string data, int length);
|
||||
|
||||
public Mongoose(string document_root,
|
||||
string listening_port,
|
||||
MongooseEventHandler event_handler) {
|
||||
server_ = mg_create_server(IntPtr.Zero, event_handler);
|
||||
mg_set_option(server_, "document_root", document_root);
|
||||
mg_set_option(server_, "listening_port", listening_port);
|
||||
}
|
||||
|
||||
public static int send_data(IntPtr conn, string data) {
|
||||
return mg_send_data(conn, data, data.Length);
|
||||
}
|
||||
|
||||
public void poll(int milli) {
|
||||
mg_poll_server(server_, milli);
|
||||
}
|
||||
|
||||
// TODO: add destructor and call mg_destroy_server()
|
||||
}
|
12
3rdparty/mongoose/examples/digest_authentication/Makefile
vendored
Normal file
12
3rdparty/mongoose/examples/digest_authentication/Makefile
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# Copyright (c) 2014 Cesanta Software
|
||||
# All rights reserved
|
||||
|
||||
PROG = digest_auth
|
||||
CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA)
|
||||
SOURCES = $(PROG).c ../../mongoose.c
|
||||
|
||||
$(PROG): $(SOURCES)
|
||||
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib
|
36
3rdparty/mongoose/examples/digest_authentication/digest_auth.c
vendored
Normal file
36
3rdparty/mongoose/examples/digest_authentication/digest_auth.c
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mongoose.h"
|
||||
|
||||
static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||
|
||||
if (ev == MG_AUTH) {
|
||||
int result = MG_FALSE; // Not authorized
|
||||
FILE *fp;
|
||||
|
||||
// To populate passwords file, do
|
||||
// mongoose -A my_passwords.txt mydomain.com admin admin
|
||||
if ((fp = fopen("my_passwords.txt", "r")) != NULL) {
|
||||
result = mg_authorize_digest(conn, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return MG_FALSE;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
struct mg_server *server = mg_create_server(NULL, ev_handler);
|
||||
mg_set_option(server, "listening_port", "8080");
|
||||
mg_set_option(server, "document_root", ".");
|
||||
|
||||
printf("Starting on port %s\n", mg_get_option(server, "listening_port"));
|
||||
for (;;) {
|
||||
mg_poll_server(server, 1000);
|
||||
}
|
||||
mg_destroy_server(&server);
|
||||
|
||||
return 0;
|
||||
}
|
20
3rdparty/mongoose/examples/file_upload/Makefile
vendored
Normal file
20
3rdparty/mongoose/examples/file_upload/Makefile
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
# Copyright (c) 2014 Cesanta Software
|
||||
# All rights reserved
|
||||
|
||||
PROG = file_upload
|
||||
CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA)
|
||||
SOURCES = $(PROG).c ../../mongoose.c
|
||||
|
||||
all: $(PROG)
|
||||
|
||||
run: $(PROG)
|
||||
./$(PROG)
|
||||
|
||||
$(PROG): $(SOURCES) Makefile
|
||||
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
||||
|
||||
win:
|
||||
wine cl $(SOURCES) /MD /nologo /DNDEBUG /O1 /I../.. /Fe$(PROG).exe
|
||||
|
||||
clean:
|
||||
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib *.gc*
|
59
3rdparty/mongoose/examples/file_upload/file_upload.c
vendored
Normal file
59
3rdparty/mongoose/examples/file_upload/file_upload.c
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2004-2012 Sergey Lyubka
|
||||
// This file is a part of mongoose project, http://github.com/valenok/mongoose
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mongoose.h"
|
||||
|
||||
static int send_index_page(struct mg_connection *conn) {
|
||||
const char *data;
|
||||
int data_len, ofs = 0;
|
||||
char var_name[100], file_name[100];
|
||||
|
||||
mg_printf_data(conn, "%s",
|
||||
"<html><body>Upload example."
|
||||
"<form method=\"POST\" action=\"/handle_post_request\" "
|
||||
" enctype=\"multipart/form-data\">"
|
||||
"<input type=\"file\" name=\"file\" /> <br/>"
|
||||
"<input type=\"submit\" value=\"Upload\" />"
|
||||
"</form>");
|
||||
|
||||
while ((ofs = mg_parse_multipart(conn->content + ofs, conn->content_len - ofs,
|
||||
var_name, sizeof(var_name),
|
||||
file_name, sizeof(file_name),
|
||||
&data, &data_len)) > 0) {
|
||||
mg_printf_data(conn, "var: %s, file_name: %s, size: %d bytes<br>",
|
||||
var_name, file_name, data_len);
|
||||
}
|
||||
|
||||
mg_printf_data(conn, "%s", "</body></html>");
|
||||
|
||||
return MG_TRUE;
|
||||
}
|
||||
|
||||
static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||
switch (ev) {
|
||||
case MG_AUTH: return MG_TRUE;
|
||||
case MG_REQUEST: return send_index_page(conn);
|
||||
default: return MG_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
struct mg_server *server;
|
||||
|
||||
// Create and configure the server
|
||||
server = mg_create_server(NULL, ev_handler);
|
||||
mg_set_option(server, "listening_port", "8080");
|
||||
|
||||
// Serve request. Hit Ctrl-C to terminate the program
|
||||
printf("Starting on port %s\n", mg_get_option(server, "listening_port"));
|
||||
for (;;) {
|
||||
mg_poll_server(server, 1000);
|
||||
}
|
||||
|
||||
// Cleanup, and free server instance
|
||||
mg_destroy_server(&server);
|
||||
|
||||
return 0;
|
||||
}
|
12
3rdparty/mongoose/examples/form_submit/Makefile
vendored
Normal file
12
3rdparty/mongoose/examples/form_submit/Makefile
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# Copyright (c) 2014 Cesanta Software
|
||||
# All rights reserved
|
||||
|
||||
PROG = form_submit
|
||||
CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA)
|
||||
SOURCES = $(PROG).c ../../mongoose.c
|
||||
|
||||
$(PROG): $(SOURCES)
|
||||
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib
|
62
3rdparty/mongoose/examples/form_submit/form_submit.c
vendored
Normal file
62
3rdparty/mongoose/examples/form_submit/form_submit.c
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mongoose.h"
|
||||
|
||||
static const char *html_form =
|
||||
"<html><body>POST example."
|
||||
"<form method=\"POST\" action=\"/handle_post_request\">"
|
||||
"Input 1: <input type=\"text\" name=\"input_1\" /> <br/>"
|
||||
"Input 2: <input type=\"text\" name=\"input_2\" /> <br/>"
|
||||
"<input type=\"submit\" />"
|
||||
"</form></body></html>";
|
||||
|
||||
static void send_reply(struct mg_connection *conn) {
|
||||
char var1[500], var2[500];
|
||||
|
||||
if (strcmp(conn->uri, "/handle_post_request") == 0) {
|
||||
// User has submitted a form, show submitted data and a variable value
|
||||
// Parse form data. var1 and var2 are guaranteed to be NUL-terminated
|
||||
mg_get_var(conn, "input_1", var1, sizeof(var1));
|
||||
mg_get_var(conn, "input_2", var2, sizeof(var2));
|
||||
|
||||
// Send reply to the client, showing submitted form values.
|
||||
// POST data is in conn->content, data length is in conn->content_len
|
||||
mg_send_header(conn, "Content-Type", "text/plain");
|
||||
mg_printf_data(conn,
|
||||
"Submitted data: [%.*s]\n"
|
||||
"Submitted data length: %d bytes\n"
|
||||
"input_1: [%s]\n"
|
||||
"input_2: [%s]\n",
|
||||
conn->content_len, conn->content,
|
||||
conn->content_len, var1, var2);
|
||||
} else {
|
||||
// Show HTML form.
|
||||
mg_send_data(conn, html_form, strlen(html_form));
|
||||
}
|
||||
}
|
||||
|
||||
static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||
if (ev == MG_REQUEST) {
|
||||
send_reply(conn);
|
||||
return MG_TRUE;
|
||||
} else if (ev == MG_AUTH) {
|
||||
return MG_TRUE;
|
||||
} else {
|
||||
return MG_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
struct mg_server *server = mg_create_server(NULL, ev_handler);
|
||||
|
||||
mg_set_option(server, "listening_port", "8080");
|
||||
|
||||
printf("Starting on port %s\n", mg_get_option(server, "listening_port"));
|
||||
for (;;) {
|
||||
mg_poll_server(server, 1000);
|
||||
}
|
||||
|
||||
mg_destroy_server(&server);
|
||||
|
||||
return 0;
|
||||
}
|
21
3rdparty/mongoose/examples/hello_world/Makefile
vendored
Normal file
21
3rdparty/mongoose/examples/hello_world/Makefile
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# Copyright (c) 2014 Cesanta Software
|
||||
# All rights reserved
|
||||
|
||||
PROG = hello_world
|
||||
CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA)
|
||||
SOURCES = $(PROG).c ../../mongoose.c
|
||||
|
||||
all: $(PROG)
|
||||
|
||||
run: $(PROG)
|
||||
./$(PROG)
|
||||
|
||||
$(PROG): $(SOURCES) Makefile
|
||||
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
||||
|
||||
win:
|
||||
wine cl $(SOURCES) /MD /nologo /DNDEBUG /O1 /I../.. /Fe$(PROG).exe
|
||||
wine $(PROG).exe
|
||||
|
||||
clean:
|
||||
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib *.gc*
|
38
3rdparty/mongoose/examples/hello_world/hello_world.c
vendored
Normal file
38
3rdparty/mongoose/examples/hello_world/hello_world.c
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2014 Cesanta Software
|
||||
// All rights reserved
|
||||
//
|
||||
// This example demostrates basic use of Mongoose embedded web server.
|
||||
// $Date: 2014-09-09 22:20:23 UTC $
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mongoose.h"
|
||||
|
||||
static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||
switch (ev) {
|
||||
case MG_AUTH: return MG_TRUE;
|
||||
case MG_REQUEST:
|
||||
mg_printf_data(conn, "Hello! Requested URI is [%s]", conn->uri);
|
||||
return MG_TRUE;
|
||||
default: return MG_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
struct mg_server *server;
|
||||
|
||||
// Create and configure the server
|
||||
server = mg_create_server(NULL, ev_handler);
|
||||
mg_set_option(server, "listening_port", "8080");
|
||||
|
||||
// Serve request. Hit Ctrl-C to terminate the program
|
||||
printf("Starting on port %s\n", mg_get_option(server, "listening_port"));
|
||||
for (;;) {
|
||||
mg_poll_server(server, 1000);
|
||||
}
|
||||
|
||||
// Cleanup, and free server instance
|
||||
mg_destroy_server(&server);
|
||||
|
||||
return 0;
|
||||
}
|
12
3rdparty/mongoose/examples/http_client/Makefile
vendored
Normal file
12
3rdparty/mongoose/examples/http_client/Makefile
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# Copyright (c) 2014 Cesanta Software
|
||||
# All rights reserved
|
||||
|
||||
PROG = http_client
|
||||
CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA)
|
||||
SOURCES = $(PROG).c ../../mongoose.c
|
||||
|
||||
unix: $(SOURCES)
|
||||
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib
|
82
3rdparty/mongoose/examples/http_client/http_client.c
vendored
Normal file
82
3rdparty/mongoose/examples/http_client/http_client.c
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright (c) 2014 Cesanta Software
|
||||
// All rights reserved
|
||||
//
|
||||
// This example demostrates how to connect to the remote Web server,
|
||||
// download data, process it and send back a reply.
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mongoose.h"
|
||||
|
||||
static int s_received_signal = 0;
|
||||
static struct mg_server *s_server = NULL;
|
||||
static const char *s_remote_addr = "glosbe.com:80";
|
||||
|
||||
static void signal_handler(int sig_num) {
|
||||
signal(sig_num, signal_handler);
|
||||
s_received_signal = sig_num;
|
||||
}
|
||||
|
||||
static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||
struct mg_connection *client, *orig;
|
||||
|
||||
switch (ev) {
|
||||
case MG_AUTH:
|
||||
return MG_TRUE;
|
||||
|
||||
case MG_CONNECT:
|
||||
// Send request to the remote host.
|
||||
// TODO(lsm): handle connect error here.
|
||||
mg_printf(conn, "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n",
|
||||
"/gapi/translate?from=eng&dest=fra&format=json&phrase=cat",
|
||||
s_remote_addr);
|
||||
return MG_TRUE;
|
||||
|
||||
case MG_REPLY:
|
||||
// Send reply to the original connection
|
||||
orig = (struct mg_connection *) conn->connection_param;
|
||||
mg_send_status(orig, conn->status_code);
|
||||
mg_send_header(orig, "Content-Type", "text/plain");
|
||||
mg_send_data(orig, conn->content, conn->content_len);
|
||||
mg_send_data(orig, "", 0); // Last chunk: mark the end of reply
|
||||
|
||||
// Disconnect connections
|
||||
orig->connection_param = NULL;
|
||||
conn->connection_param = NULL;
|
||||
return MG_TRUE;
|
||||
|
||||
case MG_REQUEST:
|
||||
if ((client = mg_connect(s_server, s_remote_addr)) != NULL) {
|
||||
// Interconnect requests
|
||||
client->connection_param = conn;
|
||||
conn->connection_param = client;
|
||||
return MG_MORE;
|
||||
} else {
|
||||
mg_printf_data(conn, "%s", "cannot send API request");
|
||||
return MG_TRUE;
|
||||
}
|
||||
|
||||
default:
|
||||
return MG_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
s_server = mg_create_server(NULL, ev_handler);
|
||||
|
||||
mg_set_option(s_server, "listening_port", "8080");
|
||||
|
||||
// Setup signal handlers
|
||||
signal(SIGTERM, signal_handler);
|
||||
signal(SIGINT, signal_handler);
|
||||
|
||||
printf("Listening on port %s\n", mg_get_option(s_server, "listening_port"));
|
||||
while (s_received_signal == 0) {
|
||||
mg_poll_server(s_server, 1000);
|
||||
}
|
||||
mg_destroy_server(&s_server);
|
||||
printf("Existing on signal %d\n", s_received_signal);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
12
3rdparty/mongoose/examples/mjpg_streamer/Makefile
vendored
Normal file
12
3rdparty/mongoose/examples/mjpg_streamer/Makefile
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# Copyright (c) 2014 Cesanta Software
|
||||
# All rights reserved
|
||||
|
||||
PROG = mjpg_streamer
|
||||
CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA)
|
||||
SOURCES = $(PROG).c ../../mongoose.c
|
||||
|
||||
$(PROG): $(SOURCES)
|
||||
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib
|
105
3rdparty/mongoose/examples/mjpg_streamer/mjpg_streamer.c
vendored
Normal file
105
3rdparty/mongoose/examples/mjpg_streamer/mjpg_streamer.c
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "mongoose.h"
|
||||
|
||||
static void send_file(struct mg_connection *conn, const char *path) {
|
||||
char buf[1024];
|
||||
struct stat st;
|
||||
int n;
|
||||
FILE *fp;
|
||||
|
||||
if (stat(path, &st) == 0 && (fp = fopen(path, "rb")) != NULL) {
|
||||
mg_printf(conn, "--w00t\r\nContent-Type: image/jpeg\r\n"
|
||||
"Content-Length: %lu\r\n\r\n", (unsigned long) st.st_size);
|
||||
while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) {
|
||||
mg_write(conn, buf, n);
|
||||
}
|
||||
fclose(fp);
|
||||
mg_write(conn, "\r\n", 2);
|
||||
}
|
||||
}
|
||||
|
||||
struct conn_state {
|
||||
int file_index;
|
||||
time_t last_poll;
|
||||
};
|
||||
|
||||
static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||
const char **file_names = (const char **) conn->server_param;
|
||||
struct conn_state *state;
|
||||
time_t now = time(NULL);
|
||||
|
||||
switch (ev) {
|
||||
|
||||
case MG_AUTH:
|
||||
return MG_TRUE;
|
||||
|
||||
case MG_REQUEST:
|
||||
if (strcmp(conn->uri, "/stream") != 0) {
|
||||
mg_send_header(conn, "Content-Type", "text/html");
|
||||
mg_printf_data(conn, "%s",
|
||||
"Go to <a href=/stream>/stream</a> for MJPG stream");
|
||||
return MG_TRUE;
|
||||
}
|
||||
|
||||
mg_printf(conn, "%s",
|
||||
"HTTP/1.0 200 OK\r\n" "Cache-Control: no-cache\r\n"
|
||||
"Pragma: no-cache\r\nExpires: Thu, 01 Dec 1994 16:00:00 GMT\r\n"
|
||||
"Connection: close\r\nContent-Type: multipart/x-mixed-replace; "
|
||||
"boundary=--w00t\r\n\r\n");
|
||||
|
||||
send_file(conn, file_names[0]);
|
||||
|
||||
state = (struct conn_state *) malloc(sizeof(*state));
|
||||
conn->connection_param = state;
|
||||
state->file_index = 1; // First file is already sent
|
||||
state->last_poll = time(NULL);
|
||||
return MG_MORE;
|
||||
|
||||
case MG_POLL:
|
||||
state = (struct conn_state *) conn->connection_param;
|
||||
|
||||
if (state != NULL && now > state->last_poll) {
|
||||
if (file_names[state->file_index] != NULL) {
|
||||
send_file(conn, file_names[state->file_index]);
|
||||
state->file_index++;
|
||||
if (file_names[state->file_index] == NULL) {
|
||||
return MG_TRUE; // No more images, close connection
|
||||
}
|
||||
}
|
||||
state->last_poll = now;
|
||||
}
|
||||
return MG_FALSE;
|
||||
|
||||
case MG_CLOSE:
|
||||
free(conn->connection_param);
|
||||
conn->connection_param = NULL;
|
||||
return MG_FALSE;
|
||||
|
||||
default:
|
||||
return MG_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct mg_server *server;
|
||||
|
||||
if (argc < 3) {
|
||||
printf("Usage: %s image1.jpg image2.jpg ...\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
server = mg_create_server(&argv[1], ev_handler);
|
||||
mg_set_option(server, "listening_port", "8080");
|
||||
|
||||
printf("Starting on port %s\n", mg_get_option(server, "listening_port"));
|
||||
for (;;) {
|
||||
mg_poll_server(server, 1000);
|
||||
}
|
||||
mg_destroy_server(&server);
|
||||
|
||||
return 0;
|
||||
}
|
12
3rdparty/mongoose/examples/multi_threaded_server/Makefile
vendored
Normal file
12
3rdparty/mongoose/examples/multi_threaded_server/Makefile
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# Copyright (c) 2014 Cesanta Software
|
||||
# All rights reserved
|
||||
|
||||
PROG = multi_threaded_server
|
||||
CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA)
|
||||
SOURCES = $(PROG).c ../../mongoose.c
|
||||
|
||||
$(PROG): $(SOURCES)
|
||||
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib
|
40
3rdparty/mongoose/examples/multi_threaded_server/multi_threaded_server.c
vendored
Normal file
40
3rdparty/mongoose/examples/multi_threaded_server/multi_threaded_server.c
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
#include "mongoose.h"
|
||||
|
||||
// Start a browser and hit refresh couple of times. The replies will
|
||||
// come from both server instances.
|
||||
static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||
if (ev == MG_REQUEST) {
|
||||
mg_send_header(conn, "Content-Type", "text/plain");
|
||||
mg_printf_data(conn, "This is a reply from server instance # %s",
|
||||
(char *) conn->server_param);
|
||||
return MG_TRUE;
|
||||
} else if (ev == MG_AUTH) {
|
||||
return MG_TRUE;
|
||||
} else {
|
||||
return MG_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void *serve(void *server) {
|
||||
for (;;) mg_poll_server((struct mg_server *) server, 1000);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
struct mg_server *server1, *server2;
|
||||
|
||||
server1 = mg_create_server((void *) "1", ev_handler);
|
||||
server2 = mg_create_server((void *) "2", ev_handler);
|
||||
|
||||
// Make both server1 and server2 listen on the same sockets
|
||||
mg_set_option(server1, "listening_port", "8080");
|
||||
mg_copy_listeners(server1, server2);
|
||||
|
||||
// server1 goes to separate thread, server 2 runs in main thread.
|
||||
// IMPORTANT: NEVER LET DIFFERENT THREADS HANDLE THE SAME SERVER.
|
||||
mg_start_thread(serve, server1);
|
||||
mg_start_thread(serve, server2);
|
||||
getchar();
|
||||
|
||||
return 0;
|
||||
}
|
13
3rdparty/mongoose/examples/proxy_server/Makefile
vendored
Normal file
13
3rdparty/mongoose/examples/proxy_server/Makefile
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2014 Cesanta Software
|
||||
# All rights reserved
|
||||
|
||||
PROG = proxy_server
|
||||
FLAGS = -I../.. -DNS_ENABLE_SSL
|
||||
CFLAGS = -W -Wall -g -O0 -pthread -lssl $(FLAGS) $(CFLAGS_EXTRA)
|
||||
SOURCES = $(PROG).c ../../mongoose.c
|
||||
|
||||
unix: $(SOURCES)
|
||||
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib
|
202
3rdparty/mongoose/examples/proxy_server/proxy_server.c
vendored
Normal file
202
3rdparty/mongoose/examples/proxy_server/proxy_server.c
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
// Copyright (c) 2014 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// To build and run this example:
|
||||
// git clone https://github.com/cesanta/net_skeleton.git
|
||||
// git clone https://github.com/cesanta/mongoose.git
|
||||
// cd mongoose/examples
|
||||
// make proxy
|
||||
// ./proxy
|
||||
//
|
||||
// Configure your browser to use localhost:2014 as a proxy for all protocols
|
||||
// Then, navigate to https://cesanta.com
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define sleep(x) Sleep((x) * 1000)
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "mongoose.h"
|
||||
|
||||
static int s_received_signal = 0;
|
||||
static struct mg_server *s_server = NULL;
|
||||
|
||||
#define SSE_CONNECTION ((void *) 1)
|
||||
|
||||
static void elog(int do_exit, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stderr);
|
||||
if (do_exit) exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void signal_handler(int sig_num) {
|
||||
signal(sig_num, signal_handler);
|
||||
s_received_signal = sig_num;
|
||||
}
|
||||
|
||||
static int sse_push(struct mg_connection *conn, enum mg_event ev) {
|
||||
if (ev == MG_POLL && conn->connection_param == SSE_CONNECTION) {
|
||||
mg_printf(conn, "data: %s\r\n\r\n", (const char *) conn->callback_param);
|
||||
}
|
||||
return MG_TRUE;
|
||||
}
|
||||
|
||||
static void *sse_pusher_thread_func(void *param) {
|
||||
while (s_received_signal == 0) {
|
||||
mg_wakeup_server_ex(s_server, sse_push, "%lu %s",
|
||||
(unsigned long) time(NULL), (const char *) param);
|
||||
sleep(1);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Return: 1 if regular file, 2 if directory, 0 if not found
|
||||
static int exists(const char *path) {
|
||||
struct stat st;
|
||||
return stat(path, &st) != 0 ? 0 : S_ISDIR(st.st_mode) == 0 ? 1 : 2;
|
||||
}
|
||||
|
||||
// Return: 1 if regular file, 2 if directory, 0 if not found
|
||||
static int is_local_file(const char *uri, char *path, size_t path_len) {
|
||||
snprintf(path, path_len, "%s/%s",
|
||||
mg_get_option(s_server, "document_root"), uri);
|
||||
return exists(path);
|
||||
}
|
||||
|
||||
static int try_to_serve_locally(struct mg_connection *conn) {
|
||||
char path[500], buf[2000];
|
||||
int n, res;
|
||||
FILE *fp = NULL;
|
||||
|
||||
if ((res = is_local_file(conn->uri, path, sizeof(path))) == 2) {
|
||||
strncat(path, "/index.html", sizeof(path) - strlen(path) - 1);
|
||||
res = exists(path);
|
||||
printf("PATH: [%s]\n", path);
|
||||
}
|
||||
if (res == 0) return MG_FALSE;
|
||||
|
||||
if ((fp = fopen(path, "rb")) != NULL) {
|
||||
printf("Serving [%s] locally \n", path);
|
||||
mg_send_header(conn, "Connection", "close");
|
||||
mg_send_header(conn, "Content-Type", mg_get_mime_type(path, "text/plain"));
|
||||
while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) {
|
||||
mg_send_data(conn, buf, n);
|
||||
}
|
||||
mg_send_data(conn, "", 0);
|
||||
fclose(fp);
|
||||
}
|
||||
return fp == NULL ? MG_FALSE : MG_TRUE;
|
||||
}
|
||||
|
||||
static int is_resource_present_locally(const char *uri) {
|
||||
char path[500];
|
||||
return is_local_file(uri, path, sizeof(path)) || strcmp(uri, "/api/sse") == 0;
|
||||
}
|
||||
|
||||
static int proxy_event_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||
static const char target_url[] = "http://cesanta.com";
|
||||
static int target_url_size = sizeof(target_url) - 1;
|
||||
const char *host;
|
||||
|
||||
switch (ev) {
|
||||
case MG_REQUEST:
|
||||
host = mg_get_header(conn, "Host");
|
||||
printf("[%s] [%s] [%s]\n", conn->request_method, conn->uri,
|
||||
host == NULL ? "" : host);
|
||||
if (strstr(conn->uri, "/qqq") != NULL) s_received_signal = SIGTERM;
|
||||
|
||||
// Proxied HTTPS requests use "CONNECT foo.com:443"
|
||||
// Proxied HTTP requests use "GET http://..... "
|
||||
// Serve requests for target_url from the local FS.
|
||||
if (memcmp(conn->uri, target_url, target_url_size) == 0 &&
|
||||
is_resource_present_locally(conn->uri + target_url_size)) {
|
||||
conn->uri += target_url_size; // Leave only path in the URI
|
||||
}
|
||||
|
||||
if (strcmp(conn->uri, "/api/sse") == 0) {
|
||||
conn->connection_param = SSE_CONNECTION;
|
||||
mg_printf(conn, "%s", "HTTP/1.0 200 OK\r\n"
|
||||
"Content-Type: text/event-stream\r\n"
|
||||
"Cache-Control: no-cache\r\n\r\n");
|
||||
return MG_MORE;
|
||||
}
|
||||
|
||||
if (host != NULL && strstr(host, "cesanta") != NULL) {
|
||||
return try_to_serve_locally(conn);
|
||||
}
|
||||
|
||||
// Enable man-in-the-middle SSL mode for oracle.com
|
||||
if (!strcmp(conn->request_method, "CONNECT") &&
|
||||
!strcmp(host, "oracle.com")) {
|
||||
mg_terminate_ssl(conn, "ssl_cert.pem"); // MUST return MG_MORE after
|
||||
return MG_MORE;
|
||||
}
|
||||
|
||||
return MG_FALSE;
|
||||
case MG_AUTH:
|
||||
return MG_TRUE;
|
||||
default:
|
||||
return MG_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void setopt(struct mg_server *s, const char *opt, const char *val) {
|
||||
const char *err_msg = mg_set_option(s, opt, val);
|
||||
if (err_msg != NULL) {
|
||||
elog(1, "Error setting [%s]: [%s]", opt, err_msg);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
const char *port = "2014", *dump = NULL, *root = "proxy_web_root";
|
||||
int i;
|
||||
|
||||
// Parse command line options
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-port") == 0 && i + 1 < argc) {
|
||||
port = argv[++i];
|
||||
} else if (strcmp(argv[i], "-root") == 0 && i + 1 < argc) {
|
||||
root = argv[++i];
|
||||
} else if (strcmp(argv[i], "-dump") == 0 && i + 1 < argc) {
|
||||
dump = argv[++i];
|
||||
} else {
|
||||
elog(1, "Usage: %s [-cert FILE] [-ca_cert FILE] [-port PORT]", argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
signal(SIGTERM, signal_handler);
|
||||
signal(SIGINT, signal_handler);
|
||||
|
||||
// Create and configure proxy server
|
||||
s_server = mg_create_server(NULL, &proxy_event_handler);
|
||||
setopt(s_server, "enable_proxy", "yes");
|
||||
setopt(s_server, "document_root", root);
|
||||
setopt(s_server, "listening_port", port);
|
||||
setopt(s_server, "hexdump_file", dump);
|
||||
|
||||
// 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_2");
|
||||
|
||||
// Start serving in the main thread
|
||||
printf("Starting on port %s\n", mg_get_option(s_server, "listening_port"));
|
||||
while (s_received_signal == 0) {
|
||||
mg_poll_server(s_server, 1000);
|
||||
}
|
||||
printf("Existing on signal %d\n", s_received_signal);
|
||||
mg_destroy_server(&s_server);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
23
3rdparty/mongoose/examples/proxy_server/proxy_web_root/app1/index.html
vendored
Normal file
23
3rdparty/mongoose/examples/proxy_server/proxy_web_root/app1/index.html
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>App1 Index</title>
|
||||
<style>
|
||||
img { height: 40px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>App1 index page. Served locally from the the proxy server filesystem</h1>
|
||||
|
||||
<p>image that references non-existent local resource. Forwarded to
|
||||
the 'real' proxy target:</p>
|
||||
<img src="http://cesanta.com/images/logo.png" />
|
||||
|
||||
<p>Google logo via HTTPS (external resource, served by remote host):</p>
|
||||
<img src="https://www.google.ie/images/srpr/logo11w.png" />
|
||||
|
||||
<p>Same image via HTTP:</p>
|
||||
<img src="http://www.google.ie/images/srpr/logo11w.png" />
|
||||
|
||||
</body>
|
||||
</html>
|
37
3rdparty/mongoose/examples/proxy_server/proxy_web_root/app2/index.html
vendored
Normal file
37
3rdparty/mongoose/examples/proxy_server/proxy_web_root/app2/index.html
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>App2 Index</title>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
window.onload = function() {
|
||||
// Using secure websocket connection, wss://
|
||||
var ws = new WebSocket('wss://echo.websocket.org');
|
||||
var div = document.getElementById('events');
|
||||
ws.onmessage = function(ev) {
|
||||
var el = document.createElement('div');
|
||||
el.innerHTML = 'websocket message: ' + ev.data;
|
||||
div.appendChild(el);
|
||||
// Keep only last 5 messages in the list
|
||||
while (div.childNodes.length > 5) div.removeChild(div.firstChild);
|
||||
};
|
||||
|
||||
// Send random stuff to the websocket connection periodically.
|
||||
// websocket server much echo that stuff back.
|
||||
window.setInterval(function() {
|
||||
var d = new Date();
|
||||
ws.send(d.toString());
|
||||
}, 1000);
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>App2 index page. Served locally from the
|
||||
the proxy's filesystem.</h1>
|
||||
<p>
|
||||
Following div shows proxy forwarding of websocket connection, served by
|
||||
ws://echo.websocket.org:
|
||||
</p>
|
||||
|
||||
<div id="events"></div>
|
||||
</body>
|
||||
</html>
|
29
3rdparty/mongoose/examples/proxy_server/proxy_web_root/index.html
vendored
Normal file
29
3rdparty/mongoose/examples/proxy_server/proxy_web_root/index.html
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<html>
|
||||
<head>
|
||||
<title> proxy index </title>
|
||||
<script type="text/javascript">
|
||||
window.onload = function() {
|
||||
var es = new EventSource("/api/sse");
|
||||
var div = document.getElementById('events');
|
||||
es.onmessage = function(ev) {
|
||||
var el = document.createElement('div');
|
||||
el.innerHTML = 'sse message: ' + ev.data;
|
||||
div.appendChild(el);
|
||||
// Keep only last 5 messages in the list
|
||||
while (div.childNodes.length > 5) div.removeChild(div.firstChild);
|
||||
};
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1> proxy index page.</h1>
|
||||
<ul>
|
||||
<li><a href="app1">App1</a> - App1 root</li>
|
||||
<li><a href="app2">App2</a> - App2 root</li>
|
||||
</ul>
|
||||
|
||||
<h2>SSE pushes, done by separate threads at random times:</h2>
|
||||
<div id="events"></div>
|
||||
|
||||
</body>
|
||||
</html>
|
50
3rdparty/mongoose/examples/proxy_server/ssl_cert.pem
vendored
Normal file
50
3rdparty/mongoose/examples/proxy_server/ssl_cert.pem
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAwONaLOP7EdegqjRuQKSDXzvHmFMZfBufjhELhNjo5KsL4ieH
|
||||
hMSGCcSV6y32hzhqR5lvTViaQez+xhc58NZRu+OUgEhodRBW/vAOjpz/xdMz5HaC
|
||||
EhP3E9W1pkitVseS8B5rrgJo1BfCGai1fPav1nutPq2Kj7vMy24+g460Lonf6ln1
|
||||
di4aTIRtAqXtUU6RFpPJP35PkCXbTK65O8HJSxxt/XtfoezHCU5+UIwmZGYx46UB
|
||||
Wzg3IfK6bGPSiHU3pdiTol0uMPt/GUK+x4NyZJ4/ImsNAicRwMBdja4ywHKXJehH
|
||||
gXBthsVIHbL21x+4ibsg9eVM/XioTV6tW3IrdwIDAQABAoIBACFfdLutmkQFBcRN
|
||||
HAJNNHmmsyr0vcUOVnXTFyYeDXV67qxrYHQlOHe6LqIpKq1Mon7O2kYMnWvooFAP
|
||||
trOnsS6L+qaTYJdYg2TKjgo4ubw1hZXytyB/mdExuaMSkgMgtpia+tB5lD+V+LxN
|
||||
x1DesZ+veFMO3Zluyckswt4qM5yVa04YFrt31H0E1rJfIen61lidXIKYmHHWuRxK
|
||||
SadjFfbcqJ6P9ZF22BOkleg5Fm5NaxJmyQynOWaAkSZa5w1XySFfRjRfsbDr64G6
|
||||
+LSG8YtRuvfxnvUNhynVPHcpE40eiPo6v8Ho6yZKXpV5klCKciodXAORsswSoGJa
|
||||
N3nnu/ECgYEA6Yb2rM3QUEPIALdL8f/OzZ1GBSdiQB2WSAxzl9pR/dLF2H+0pitS
|
||||
to0830mk92ppVmRVD3JGxYDRZQ56tlFXyGaCzJBMRIcsotAhBoNbjV0i9n5bLJYf
|
||||
BmjU9yvWcgsTt0tr3B0FrtYyp2tCvwHqlxvFpFdUCj2oRw2uGpkhmNkCgYEA03M6
|
||||
WxFhsix3y6eVCVvShfbLBSOqp8l0qiTEty+dgVQcWN4CO/5eyaZXKxlCG9KMmKxy
|
||||
Yx+YgxZrDhfaZ0cxhHGPRKEAxM3IKwT2C8/wCaSiLWXZZpTifnSD99vtOt4wEfrG
|
||||
+AghNd5kamFiM9tU0AyvhJc2vdJFuXrfeC7ntM8CgYBGDA+t4cZcbRhu7ow/OKYF
|
||||
kulP3nJgHP/Y+LMrl3cEldZ2jEfZmCElVNQvfd2XwTl7injhOzvzPiKRF3jDez7D
|
||||
g8w0JAxceddvttJRK9GoY4l7OoeKpjUELSnEQkf+yUfOsTbXPXVY7jMfeNL6jE6b
|
||||
qN7t3qv8rmXtejMBE3G6cQKBgGR5W2BMiRSlxqKx1cKlrApV87BUe1HRCyuR3xuA
|
||||
d6Item7Lx1oEi7vb242yKdSYnpApWQ06xTh83Y/Ly87JaIEbiM0+h+P8OEIg0F1a
|
||||
iB+86AcUX1I8KseVy+Np0HbpfwP8GrFfA5DaRPK7pXMopEtby8cAJ1XZZaI1/ZvZ
|
||||
BebHAoGAcQU9WvCkT+nIp9FpXfBybYUsvgkaizMIqp66/l3GYgYAq8p1VLGvN4v5
|
||||
ec0dW58SJrCpqsM3NP78DtEzQf9OOsk+FsjBFzDU2RkeUreyt2/nQBj/2mN/+hEy
|
||||
hYN0Zii2yTb63jGxKY6gH1R/r9dL8kXaJmcZrfSa3AgywnteJWg=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDBjCCAe4CCQCX05m0b053QzANBgkqhkiG9w0BAQQFADBFMQswCQYDVQQGEwJB
|
||||
VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0
|
||||
cyBQdHkgTHRkMB4XDTA4MTIwNzEwMjUyMloXDTE4MTIwNTEwMjUyMlowRTELMAkG
|
||||
A1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0
|
||||
IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
|
||||
AMDjWizj+xHXoKo0bkCkg187x5hTGXwbn44RC4TY6OSrC+Inh4TEhgnElest9oc4
|
||||
akeZb01YmkHs/sYXOfDWUbvjlIBIaHUQVv7wDo6c/8XTM+R2ghIT9xPVtaZIrVbH
|
||||
kvAea64CaNQXwhmotXz2r9Z7rT6tio+7zMtuPoOOtC6J3+pZ9XYuGkyEbQKl7VFO
|
||||
kRaTyT9+T5Al20yuuTvByUscbf17X6HsxwlOflCMJmRmMeOlAVs4NyHyumxj0oh1
|
||||
N6XYk6JdLjD7fxlCvseDcmSePyJrDQInEcDAXY2uMsBylyXoR4FwbYbFSB2y9tcf
|
||||
uIm7IPXlTP14qE1erVtyK3cCAwEAATANBgkqhkiG9w0BAQQFAAOCAQEAW4yZdqpB
|
||||
oIdiuXRosr86Sg9FiMg/cn+2OwQ0QIaA8ZBwKsc+wIIHEgXCS8J6316BGQeUvMD+
|
||||
plNe0r4GWzzmlDMdobeQ5arPRB89qd9skE6pAMdLg3FyyfEjz3A0VpskolW5VBMr
|
||||
P5R7uJ1FLgH12RyAjZCWYcCRqEMOffqvyMCH6oAjyDmQOA5IssRKX/HsHntSH/HW
|
||||
W7slTcP45ty1b44Nq22/ubYk0CJRQgqKOIQ3cLgPomN1jNFQbAbfVTaK1DpEysrQ
|
||||
5V8a8gNW+3sVZmV6d1Mj3pN2Le62wUKuV2g6BNU7iiwcoY8HI68aRxz2hVMS+t5f
|
||||
SEGI4JSxV56lYg==
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN DH PARAMETERS-----
|
||||
MEYCQQD+ef8hZ4XbdoyIpJyCTF2UrUEfX6mYDvxuS5O1UNYcslUqlj6JkA11e/yS
|
||||
6DK8Z86W6mSj5CEk4IjbyEOECXH7AgEC
|
||||
-----END DH PARAMETERS-----
|
12
3rdparty/mongoose/examples/restful_api/Makefile
vendored
Normal file
12
3rdparty/mongoose/examples/restful_api/Makefile
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# Copyright (c) 2014 Cesanta Software
|
||||
# All rights reserved
|
||||
|
||||
PROG = restful_api
|
||||
CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA)
|
||||
SOURCES = $(PROG).c ../../mongoose.c
|
||||
|
||||
$(PROG): $(SOURCES)
|
||||
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib
|
66
3rdparty/mongoose/examples/restful_api/index.html
vendored
Normal file
66
3rdparty/mongoose/examples/restful_api/index.html
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>RESTful API demo</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<style type="text/css">
|
||||
* { outline: none; font: 16px/1.4 Helvetica, Arial, sans-serif; }
|
||||
body {
|
||||
background-color: #cde; margin: 0;
|
||||
padding: 0; font: 16px/1.4 Helvetica, Arial, sans-serif;
|
||||
}
|
||||
div.content {
|
||||
width: 800px; margin: 2em auto; padding: 20px 50px;
|
||||
background-color: #fff; border-radius: 1em;
|
||||
}
|
||||
label { display: inline-block; min-width: 7em; }
|
||||
input { border: 1px solid #ccc; padding: 0.2em; }
|
||||
a:link, a:visited { color: #69c; text-decoration: none; }
|
||||
@media (max-width: 700px) {
|
||||
body { background-color: #fff; }
|
||||
div.content { width: auto; margin: 0 auto; padding: 1em; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
|
||||
<script language="javascript" type="text/javascript">
|
||||
jQuery(function() {
|
||||
|
||||
$(document).on('keyup', '#n1, #n2', function() {
|
||||
$.ajax({
|
||||
url: '/api/sum',
|
||||
method: 'POST',
|
||||
dataType: 'json',
|
||||
data: { n1: $('#n1').val(), n2: $('#n2').val() },
|
||||
success: function(json) {
|
||||
$('#result').html(json.result);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content">
|
||||
<h1>RESTful API demo.</h1>
|
||||
|
||||
<p>
|
||||
This page demonstrates how Mongoose web server could be used to implement
|
||||
RESTful APIs. Enter numbers below, and press Submit. Browser will send
|
||||
two numbers to <tt>/api/sum</tt> URI, Mongoose calclulates the sum of
|
||||
two and returns the result.
|
||||
</p>
|
||||
|
||||
<div>
|
||||
<label>Number 1:</label> <input type="text" id="n1" />
|
||||
</div><div>
|
||||
<label>Number 2:</label> <input type="text" id="n2" />
|
||||
</div><div>
|
||||
<label>Result:</label> <span id="result"> </span>
|
||||
</div><div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
51
3rdparty/mongoose/examples/restful_api/restful_api.c
vendored
Normal file
51
3rdparty/mongoose/examples/restful_api/restful_api.c
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "mongoose.h"
|
||||
|
||||
static const char *s_no_cache_header =
|
||||
"Cache-Control: max-age=0, post-check=0, "
|
||||
"pre-check=0, no-store, no-cache, must-revalidate\r\n";
|
||||
|
||||
static void handle_restful_call(struct mg_connection *conn) {
|
||||
char n1[100], n2[100];
|
||||
|
||||
// Get form variables
|
||||
mg_get_var(conn, "n1", n1, sizeof(n1));
|
||||
mg_get_var(conn, "n2", n2, sizeof(n2));
|
||||
|
||||
mg_printf_data(conn, "{ \"result\": %lf }", strtod(n1, NULL) + strtod(n2, NULL));
|
||||
}
|
||||
|
||||
static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||
switch (ev) {
|
||||
case MG_AUTH: return MG_TRUE;
|
||||
case MG_REQUEST:
|
||||
if (!strcmp(conn->uri, "/api/sum")) {
|
||||
handle_restful_call(conn);
|
||||
return MG_TRUE;
|
||||
}
|
||||
mg_send_file(conn, "index.html", s_no_cache_header);
|
||||
return MG_MORE;
|
||||
default: return MG_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
struct mg_server *server;
|
||||
|
||||
// Create and configure the server
|
||||
server = mg_create_server(NULL, ev_handler);
|
||||
mg_set_option(server, "listening_port", "8000");
|
||||
|
||||
// Serve request. Hit Ctrl-C to terminate the program
|
||||
printf("Starting on port %s\n", mg_get_option(server, "listening_port"));
|
||||
for (;;) {
|
||||
mg_poll_server(server, 1000);
|
||||
}
|
||||
|
||||
// Cleanup, and free server instance
|
||||
mg_destroy_server(&server);
|
||||
|
||||
return 0;
|
||||
}
|
21
3rdparty/mongoose/examples/send_file/Makefile
vendored
Normal file
21
3rdparty/mongoose/examples/send_file/Makefile
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# Copyright (c) 2014 Cesanta Software
|
||||
# All rights reserved
|
||||
|
||||
PROG = send_file
|
||||
CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA)
|
||||
SOURCES = $(PROG).c ../../mongoose.c
|
||||
|
||||
all: $(PROG)
|
||||
|
||||
run: $(PROG)
|
||||
./$(PROG)
|
||||
|
||||
$(PROG): $(SOURCES) Makefile
|
||||
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
||||
|
||||
win:
|
||||
wine cl $(SOURCES) /MD /nologo /DNDEBUG /O1 /I../.. /Fe$(PROG).exe
|
||||
wine $(PROG).exe
|
||||
|
||||
clean:
|
||||
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib *.gc*
|
27
3rdparty/mongoose/examples/send_file/send_file.c
vendored
Normal file
27
3rdparty/mongoose/examples/send_file/send_file.c
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright (c) 2014 Cesanta Software
|
||||
// All rights reserved
|
||||
//
|
||||
// This example demostrates how to send arbitrary files to the client.
|
||||
|
||||
#include "mongoose.h"
|
||||
|
||||
static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||
switch (ev) {
|
||||
case MG_REQUEST:
|
||||
mg_send_file(conn, "send_file.c", NULL); // Also could be a dir, or CGI
|
||||
return MG_MORE; // It is important to return MG_MORE after mg_send_file!
|
||||
case MG_AUTH: return MG_TRUE;
|
||||
default: return MG_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
struct mg_server *server = mg_create_server(NULL, ev_handler);
|
||||
mg_set_option(server, "listening_port", "8080");
|
||||
|
||||
printf("Starting on port %s\n", mg_get_option(server, "listening_port"));
|
||||
for (;;) mg_poll_server(server, 1000);
|
||||
mg_destroy_server(&server);
|
||||
|
||||
return 0;
|
||||
}
|
12
3rdparty/mongoose/examples/web_server/Makefile
vendored
Normal file
12
3rdparty/mongoose/examples/web_server/Makefile
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# Copyright (c) 2014 Cesanta Software
|
||||
# All rights reserved
|
||||
|
||||
PROG = web_server
|
||||
CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA)
|
||||
SOURCES = $(PROG).c ../../mongoose.c
|
||||
|
||||
$(PROG): $(SOURCES)
|
||||
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib
|
491
3rdparty/mongoose/examples/web_server/web_server.c
vendored
Normal file
491
3rdparty/mongoose/examples/web_server/web_server.c
vendored
Normal file
@ -0,0 +1,491 @@
|
||||
// Copyright (c) 2004-2013 Sergey Lyubka
|
||||
// Copyright (c) 2013-2014 Cesanta Software Limited
|
||||
|
||||
#undef UNICODE // Use ANSI WinAPI functions
|
||||
#undef _UNICODE // Use multibyte encoding on Windows
|
||||
#define _MBCS // Use multibyte encoding on Windows
|
||||
#define _WIN32_WINNT 0x500 // Enable MIIM_BITMAP
|
||||
#define _CRT_SECURE_NO_WARNINGS // Disable deprecation warning in VS2005
|
||||
#define _XOPEN_SOURCE 600 // For PATH_MAX on linux
|
||||
#undef WIN32_LEAN_AND_MEAN // Let windows.h always include winsock2.h
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "mongoose.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <direct.h> // For chdir()
|
||||
#include <winsvc.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX MAX_PATH
|
||||
#endif
|
||||
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR(x) ((x) & _S_IFDIR)
|
||||
#endif
|
||||
|
||||
#define DIRSEP '\\'
|
||||
#define snprintf _snprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
#define sleep(x) Sleep((x) * 1000)
|
||||
#define abs_path(rel, abs, abs_size) _fullpath((abs), (rel), (abs_size))
|
||||
#define SIGCHLD 0
|
||||
typedef struct _stat file_stat_t;
|
||||
#define stat(x, y) _stat((x), (y))
|
||||
#else
|
||||
typedef struct stat file_stat_t;
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef IOS
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
|
||||
#define DIRSEP '/'
|
||||
#define __cdecl
|
||||
#define abs_path(rel, abs, abs_size) realpath((rel), (abs))
|
||||
#endif // _WIN32
|
||||
|
||||
#define MAX_OPTIONS 100
|
||||
#define MAX_CONF_FILE_LINE_SIZE (8 * 1024)
|
||||
|
||||
#ifndef MVER
|
||||
#define MVER MONGOOSE_VERSION
|
||||
#endif
|
||||
|
||||
static int exit_flag;
|
||||
static char server_name[50]; // Set by init_server_name()
|
||||
static char s_config_file[PATH_MAX]; // Set by process_command_line_arguments
|
||||
static struct mg_server *server; // Set by start_mongoose()
|
||||
static const char *s_default_document_root = ".";
|
||||
static const char *s_default_listening_port = "8080";
|
||||
static char **s_argv = { NULL };
|
||||
|
||||
static void set_options(char *argv[]);
|
||||
|
||||
#if !defined(CONFIG_FILE)
|
||||
#define CONFIG_FILE "mongoose.conf"
|
||||
#endif /* !CONFIG_FILE */
|
||||
|
||||
static void __cdecl signal_handler(int sig_num) {
|
||||
// Reinstantiate signal handler
|
||||
signal(sig_num, signal_handler);
|
||||
|
||||
#ifndef _WIN32
|
||||
// Do not do the trick with ignoring SIGCHLD, cause not all OSes (e.g. QNX)
|
||||
// reap zombies if SIGCHLD is ignored. On QNX, for example, waitpid()
|
||||
// fails if SIGCHLD is ignored, making system() non-functional.
|
||||
if (sig_num == SIGCHLD) {
|
||||
do {} while (waitpid(-1, &sig_num, WNOHANG) > 0);
|
||||
} else
|
||||
#endif
|
||||
{ exit_flag = sig_num; }
|
||||
}
|
||||
|
||||
static void vnotify(const char *fmt, va_list ap, int must_exit) {
|
||||
char msg[200];
|
||||
|
||||
vsnprintf(msg, sizeof(msg), fmt, ap);
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
|
||||
if (must_exit) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
static void notify(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vnotify(fmt, ap, 0);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void die(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vnotify(fmt, ap, 1);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void show_usage_and_exit(void) {
|
||||
const char **names;
|
||||
int i;
|
||||
|
||||
fprintf(stderr, "Mongoose version %s (c) Sergey Lyubka, built on %s\n",
|
||||
MVER, __DATE__);
|
||||
fprintf(stderr, "Usage:\n");
|
||||
#if !defined(MONGOOSE_NO_AUTH) && !defined(MONGOOSE_NO_FILESYSTEM)
|
||||
fprintf(stderr, " mongoose -A <htpasswd_file> <realm> <user> <passwd>\n");
|
||||
#endif
|
||||
fprintf(stderr, " mongoose [config_file]\n");
|
||||
fprintf(stderr, " mongoose [-option value ...]\n");
|
||||
fprintf(stderr, "\nOPTIONS:\n");
|
||||
|
||||
names = mg_get_valid_option_names();
|
||||
for (i = 0; names[i] != NULL; i += 2) {
|
||||
fprintf(stderr, " -%s %s\n",
|
||||
names[i], names[i + 1] == NULL ? "<empty>" : names[i + 1]);
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#define EV_HANDLER NULL
|
||||
|
||||
static char *sdup(const char *str) {
|
||||
char *p;
|
||||
if ((p = (char *) malloc(strlen(str) + 1)) != NULL) {
|
||||
strcpy(p, str);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static void set_option(char **options, const char *name, const char *value) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_OPTIONS - 3; i++) {
|
||||
if (options[i] == NULL) {
|
||||
options[i] = sdup(name);
|
||||
options[i + 1] = sdup(value);
|
||||
options[i + 2] = NULL;
|
||||
break;
|
||||
} else if (!strcmp(options[i], name)) {
|
||||
free(options[i + 1]);
|
||||
options[i + 1] = sdup(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == MAX_OPTIONS - 3) {
|
||||
die("%s", "Too many options specified");
|
||||
}
|
||||
}
|
||||
|
||||
static void process_command_line_arguments(char *argv[], char **options) {
|
||||
char line[MAX_CONF_FILE_LINE_SIZE], opt[sizeof(line)], val[sizeof(line)],
|
||||
*p, cpath[PATH_MAX];
|
||||
FILE *fp = NULL;
|
||||
size_t i, cmd_line_opts_start = 1, line_no = 0;
|
||||
|
||||
// Should we use a config file ?
|
||||
if (argv[1] != NULL && argv[1][0] != '-') {
|
||||
snprintf(cpath, sizeof(cpath), "%s", argv[1]);
|
||||
cmd_line_opts_start = 2;
|
||||
} else if ((p = strrchr(argv[0], DIRSEP)) == NULL) {
|
||||
// No command line flags specified. Look where binary lives
|
||||
snprintf(cpath, sizeof(cpath), "%s", CONFIG_FILE);
|
||||
} else {
|
||||
snprintf(cpath, sizeof(cpath), "%.*s%c%s",
|
||||
(int) (p - argv[0]), argv[0], DIRSEP, CONFIG_FILE);
|
||||
}
|
||||
abs_path(cpath, s_config_file, sizeof(s_config_file));
|
||||
|
||||
fp = fopen(s_config_file, "r");
|
||||
|
||||
// If config file was set in command line and open failed, die
|
||||
if (cmd_line_opts_start == 2 && fp == NULL) {
|
||||
die("Cannot open config file %s: %s", s_config_file, strerror(errno));
|
||||
}
|
||||
|
||||
// Load config file settings first
|
||||
if (fp != NULL) {
|
||||
fprintf(stderr, "Loading config file %s\n", s_config_file);
|
||||
|
||||
// Loop over the lines in config file
|
||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
||||
line_no++;
|
||||
|
||||
// Ignore empty lines and comments
|
||||
for (i = 0; isspace(* (unsigned char *) &line[i]); ) i++;
|
||||
if (line[i] == '#' || line[i] == '\0') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sscanf(line, "%s %[^\r\n#]", opt, val) != 2) {
|
||||
printf("%s: line %d is invalid, ignoring it:\n %s",
|
||||
s_config_file, (int) line_no, line);
|
||||
} else {
|
||||
set_option(options, opt, val);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
// If we're under MacOS and started by launchd, then the second
|
||||
// argument is process serial number, -psn_.....
|
||||
// In this case, don't process arguments at all.
|
||||
if (argv[1] == NULL || memcmp(argv[1], "-psn_", 5) != 0) {
|
||||
// Handle command line flags.
|
||||
// They override config file and default settings.
|
||||
for (i = cmd_line_opts_start; argv[i] != NULL; i += 2) {
|
||||
if (argv[i][0] != '-' || argv[i + 1] == NULL) {
|
||||
show_usage_and_exit();
|
||||
}
|
||||
set_option(options, &argv[i][1], argv[i + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void init_server_name(void) {
|
||||
const char *descr = "";
|
||||
snprintf(server_name, sizeof(server_name), "Mongoose web server v.%s%s",
|
||||
MVER, descr);
|
||||
}
|
||||
|
||||
static int is_path_absolute(const char *path) {
|
||||
#ifdef _WIN32
|
||||
return path != NULL &&
|
||||
((path[0] == '\\' && path[1] == '\\') || // UNC path, e.g. \\server\dir
|
||||
(isalpha(path[0]) && path[1] == ':' && path[2] == '\\')); // E.g. X:\dir
|
||||
#else
|
||||
return path != NULL && path[0] == '/';
|
||||
#endif
|
||||
}
|
||||
|
||||
static char *get_option(char **options, const char *option_name) {
|
||||
int i;
|
||||
|
||||
for (i = 0; options[i] != NULL; i++)
|
||||
if (!strcmp(options[i], option_name))
|
||||
return options[i + 1];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *serving_thread_func(void *param) {
|
||||
struct mg_server *srv = (struct mg_server *) param;
|
||||
while (exit_flag == 0) {
|
||||
mg_poll_server(srv, 1000);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int path_exists(const char *path, int is_dir) {
|
||||
file_stat_t st;
|
||||
return path == NULL || (stat(path, &st) == 0 &&
|
||||
((S_ISDIR(st.st_mode) ? 1 : 0) == is_dir));
|
||||
}
|
||||
|
||||
static void verify_existence(char **options, const char *name, int is_dir) {
|
||||
const char *path = get_option(options, name);
|
||||
if (!path_exists(path, is_dir)) {
|
||||
notify("Invalid path for %s: [%s]: (%s). Make sure that path is either "
|
||||
"absolute, or it is relative to mongoose executable.",
|
||||
name, path, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
static void set_absolute_path(char *options[], const char *option_name) {
|
||||
char path[PATH_MAX], abs[PATH_MAX], *option_value;
|
||||
const char *p;
|
||||
|
||||
// Check whether option is already set
|
||||
option_value = get_option(options, option_name);
|
||||
|
||||
// If option is already set and it is an absolute path,
|
||||
// leave it as it is -- it's already absolute.
|
||||
if (option_value != NULL && !is_path_absolute(option_value)) {
|
||||
// Not absolute. Use the directory where mongoose executable lives
|
||||
// be the relative directory for everything.
|
||||
// Extract mongoose executable directory into path.
|
||||
if ((p = strrchr(s_config_file, DIRSEP)) == NULL) {
|
||||
getcwd(path, sizeof(path));
|
||||
} else {
|
||||
snprintf(path, sizeof(path), "%.*s", (int) (p - s_config_file),
|
||||
s_config_file);
|
||||
}
|
||||
|
||||
strncat(path, "/", sizeof(path) - 1);
|
||||
strncat(path, option_value, sizeof(path) - 1);
|
||||
|
||||
// Absolutize the path, and set the option
|
||||
abs_path(path, abs, sizeof(abs));
|
||||
set_option(options, option_name, abs);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(MONGOOSE_NO_AUTH) && !defined(MONGOOSE_NO_FILESYSTEM)
|
||||
int modify_passwords_file(const char *fname, const char *domain,
|
||||
const char *user, const char *pass) {
|
||||
int found;
|
||||
char line[512], u[512], d[512], ha1[33], tmp[PATH_MAX];
|
||||
FILE *fp, *fp2;
|
||||
|
||||
found = 0;
|
||||
fp = fp2 = NULL;
|
||||
|
||||
// Regard empty password as no password - remove user record.
|
||||
if (pass != NULL && pass[0] == '\0') {
|
||||
pass = NULL;
|
||||
}
|
||||
|
||||
(void) snprintf(tmp, sizeof(tmp), "%s.tmp", fname);
|
||||
|
||||
// Create the file if does not exist
|
||||
if ((fp = fopen(fname, "a+")) != NULL) {
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
// Open the given file and temporary file
|
||||
if ((fp = fopen(fname, "r")) == NULL) {
|
||||
return 0;
|
||||
} else if ((fp2 = fopen(tmp, "w+")) == NULL) {
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Copy the stuff to temporary file
|
||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
||||
if (sscanf(line, "%[^:]:%[^:]:%*s", u, d) != 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(u, user) && !strcmp(d, domain)) {
|
||||
found++;
|
||||
if (pass != NULL) {
|
||||
mg_md5(ha1, user, ":", domain, ":", pass, NULL);
|
||||
fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
|
||||
}
|
||||
} else {
|
||||
fprintf(fp2, "%s", line);
|
||||
}
|
||||
}
|
||||
|
||||
// If new user, just add it
|
||||
if (!found && pass != NULL) {
|
||||
mg_md5(ha1, user, ":", domain, ":", pass, NULL);
|
||||
fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
|
||||
}
|
||||
|
||||
// Close files
|
||||
fclose(fp);
|
||||
fclose(fp2);
|
||||
|
||||
// Put the temp file in place of real file
|
||||
remove(fname);
|
||||
rename(tmp, fname);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void start_mongoose(int argc, char *argv[]) {
|
||||
s_argv = argv;
|
||||
if ((server = mg_create_server(NULL, EV_HANDLER)) == NULL) {
|
||||
die("%s", "Failed to start Mongoose.");
|
||||
}
|
||||
|
||||
#if !defined(MONGOOSE_NO_AUTH) && !defined(MONGOOSE_NO_FILESYSTEM)
|
||||
// Edit passwords file if -A option is specified
|
||||
if (argc > 1 && !strcmp(argv[1], "-A")) {
|
||||
if (argc != 6) {
|
||||
show_usage_and_exit();
|
||||
}
|
||||
exit(modify_passwords_file(argv[2], argv[3], argv[4], argv[5]) ?
|
||||
EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Show usage if -h or --help options are specified
|
||||
if (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) {
|
||||
show_usage_and_exit();
|
||||
}
|
||||
set_options(argv);
|
||||
}
|
||||
|
||||
static void set_options(char *argv[]) {
|
||||
char *options[MAX_OPTIONS];
|
||||
int i;
|
||||
|
||||
options[0] = NULL;
|
||||
set_option(options, "document_root", s_default_document_root);
|
||||
set_option(options, "listening_port", s_default_listening_port);
|
||||
|
||||
// Update config based on command line arguments
|
||||
process_command_line_arguments(argv, options);
|
||||
|
||||
// Make sure we have absolute paths for files and directories
|
||||
// https://github.com/valenok/mongoose/issues/181
|
||||
set_absolute_path(options, "document_root");
|
||||
set_absolute_path(options, "dav_auth_file");
|
||||
set_absolute_path(options, "cgi_interpreter");
|
||||
set_absolute_path(options, "access_log_file");
|
||||
set_absolute_path(options, "global_auth_file");
|
||||
set_absolute_path(options, "ssl_certificate");
|
||||
|
||||
if (!path_exists(get_option(options, "document_root"), 1)) {
|
||||
set_option(options, "document_root", s_default_document_root);
|
||||
set_absolute_path(options, "document_root");
|
||||
notify("Setting document_root to [%s]",
|
||||
mg_get_option(server, "document_root"));
|
||||
}
|
||||
|
||||
// Make extra verification for certain options
|
||||
verify_existence(options, "document_root", 1);
|
||||
verify_existence(options, "cgi_interpreter", 0);
|
||||
verify_existence(options, "ssl_certificate", 0);
|
||||
|
||||
for (i = 0; options[i] != NULL; i += 2) {
|
||||
const char *msg = mg_set_option(server, options[i], options[i + 1]);
|
||||
if (msg != NULL) {
|
||||
notify("Failed to set option [%s] to [%s]: %s",
|
||||
options[i], options[i + 1], msg);
|
||||
if (!strcmp(options[i], "listening_port")) {
|
||||
mg_set_option(server, "listening_port", s_default_listening_port);
|
||||
notify("Setting %s to [%s]", options[i], s_default_listening_port);
|
||||
}
|
||||
}
|
||||
free(options[i]);
|
||||
free(options[i + 1]);
|
||||
}
|
||||
|
||||
// Change current working directory to document root. This way,
|
||||
// scripts can use relative paths.
|
||||
chdir(mg_get_option(server, "document_root"));
|
||||
|
||||
#if 0
|
||||
// Add an ability to pass listening socket to mongoose
|
||||
{
|
||||
const char *env = getenv("MONGOOSE_LISTENING_SOCKET");
|
||||
if (env != NULL && atoi(env) > 0 ) {
|
||||
mg_set_listening_socket(server, atoi(env));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Setup signal handler: quit on Ctrl-C
|
||||
signal(SIGTERM, signal_handler);
|
||||
signal(SIGINT, signal_handler);
|
||||
#ifndef _WIN32
|
||||
signal(SIGCHLD, signal_handler);
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
init_server_name();
|
||||
start_mongoose(argc, argv);
|
||||
printf("%s serving [%s] on port %s\n",
|
||||
server_name, mg_get_option(server, "document_root"),
|
||||
mg_get_option(server, "listening_port"));
|
||||
fflush(stdout); // Needed, Windows terminals might not be line-buffered
|
||||
serving_thread_func(server);
|
||||
printf("Exiting on signal %d ...", exit_flag);
|
||||
fflush(stdout);
|
||||
mg_destroy_server(&server);
|
||||
printf("%s\n", " done.");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
12
3rdparty/mongoose/examples/websocket_chat/Makefile
vendored
Normal file
12
3rdparty/mongoose/examples/websocket_chat/Makefile
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# Copyright (c) 2014 Cesanta Software
|
||||
# All rights reserved
|
||||
|
||||
PROG = websocket_chat
|
||||
CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA)
|
||||
SOURCES = $(PROG).c ../../mongoose.c
|
||||
|
||||
$(PROG): $(SOURCES)
|
||||
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib
|
98
3rdparty/mongoose/examples/websocket_chat/index.html
vendored
Normal file
98
3rdparty/mongoose/examples/websocket_chat/index.html
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>WebSocket Test</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<style type="text/css">
|
||||
body {
|
||||
background-color: #cde; margin: 0;
|
||||
padding: 0; font: 14px Helvetica, Arial, sans-serif;
|
||||
}
|
||||
div.content {
|
||||
width: 800px; margin: 2em auto; padding: 20px 50px;
|
||||
background-color: #fff; border-radius: 1em;
|
||||
}
|
||||
#messages {
|
||||
border: 2px solid #fec; border-radius: 1em;
|
||||
height: 10em; overflow: scroll; padding: 0.5em 1em;
|
||||
}
|
||||
a:link, a:visited { color: #69c; text-decoration: none; }
|
||||
@media (max-width: 700px) {
|
||||
body { background-color: #fff; }
|
||||
div.content {
|
||||
width: auto; margin: 0 auto; border-radius: 0;
|
||||
padding: 1em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script language="javascript" type="text/javascript">
|
||||
|
||||
var rooms = [];
|
||||
var ws = new WebSocket('ws://' + location.host + '/ws');
|
||||
|
||||
if (!window.console) { window.console = { log: function() {} } };
|
||||
|
||||
ws.onopen = function(ev) { console.log(ev); };
|
||||
ws.onerror = function(ev) { console.log(ev); };
|
||||
ws.onclose = function(ev) { console.log(ev); };
|
||||
ws.onmessage = function(ev) {
|
||||
console.log(ev);
|
||||
var m = (ev.data || '').match(/^(\S+) (.+)/);
|
||||
if (m[1] == 'id') {
|
||||
document.getElementById('my_id').innerText = m[2];
|
||||
} else if (m[1] == 'msg') {
|
||||
var div = document.createElement('div');
|
||||
div.innerHTML = m[2];
|
||||
document.getElementById('messages').appendChild(div);
|
||||
}
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
document.getElementById('send_button').onclick = function(ev) {
|
||||
var msg = document.getElementById('send_input').value;
|
||||
ws.send('msg ' + msg);
|
||||
};
|
||||
document.getElementById('room_sel').onchange = function(ev) {
|
||||
var roomName = this.value || '?';
|
||||
ws.send('join ' + roomName);
|
||||
};
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content">
|
||||
<h1>Websocket PubSub Demonstration</h1>
|
||||
|
||||
<p>
|
||||
This page demonstrates how Mongoose web server could be used to implement
|
||||
<a href="http://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern">
|
||||
publish–subscribe pattern</a>. Open this page in several browser
|
||||
windows. Each window initiates persistent
|
||||
<a href="http://en.wikipedia.org/wiki/WebSocket">WebSocket</a>
|
||||
connection with Mongoose, making each browser window a websocket client.
|
||||
Join a room, send messages, and see messages sent by other clients.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
My ID: <b><span id="my_id"></b></span>
|
||||
</p>
|
||||
<p>
|
||||
Join room: <select id="room_sel">
|
||||
<option value="">-- select room -- </option>
|
||||
<option>A</option>
|
||||
<option>B</option>
|
||||
</select>
|
||||
</p>
|
||||
|
||||
<div id="messages">
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<input type="text" id="send_input" />
|
||||
<button id="send_button">Send Message</button>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
83
3rdparty/mongoose/examples/websocket_chat/websocket_chat.c
vendored
Normal file
83
3rdparty/mongoose/examples/websocket_chat/websocket_chat.c
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
// Copyright (c) 2013-2014 Cesanta Software Limited
|
||||
// $Date: 2014-09-09 17:07:55 UTC $
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include "mongoose.h"
|
||||
|
||||
static int s_signal_received = 0;
|
||||
static struct mg_server *s_server = NULL;
|
||||
|
||||
// Data associated with each websocket connection
|
||||
struct conn_data {
|
||||
int room;
|
||||
};
|
||||
|
||||
static void signal_handler(int sig_num) {
|
||||
signal(sig_num, signal_handler); // Reinstantiate signal handler
|
||||
s_signal_received = sig_num;
|
||||
}
|
||||
|
||||
static void handle_websocket_message(struct mg_connection *conn) {
|
||||
struct conn_data *d = (struct conn_data *) conn->connection_param;
|
||||
struct mg_connection *c;
|
||||
|
||||
printf("[%.*s]\n", (int) conn->content_len, conn->content);
|
||||
if (conn->content_len > 5 && !memcmp(conn->content, "join ", 5)) {
|
||||
// Client joined new room
|
||||
d->room = conn->content[5];
|
||||
} else if (conn->content_len > 4 && !memcmp(conn->content, "msg ", 4) &&
|
||||
d->room != 0 && d->room != '?') {
|
||||
// Client has sent a message. Push this message to all clients
|
||||
// that are subscribed to the same room as client
|
||||
for (c = mg_next(s_server, NULL); c != NULL; c = mg_next(s_server, c)) {
|
||||
struct conn_data *d2 = (struct conn_data *) c->connection_param;
|
||||
if (!c->is_websocket || d2->room != d->room) continue;
|
||||
mg_websocket_printf(c, WEBSOCKET_OPCODE_TEXT, "msg %c %p %.*s",
|
||||
(char) d->room, conn,
|
||||
conn->content_len - 4, conn->content + 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||
switch (ev) {
|
||||
case MG_REQUEST:
|
||||
if (conn->is_websocket) {
|
||||
handle_websocket_message(conn);
|
||||
return MG_TRUE;
|
||||
} else {
|
||||
mg_send_file(conn, "index.html", NULL); // Return MG_MORE after!
|
||||
return MG_MORE;
|
||||
}
|
||||
case MG_WS_CONNECT:
|
||||
// New websocket connection. Send connection ID back to the client.
|
||||
conn->connection_param = calloc(1, sizeof(struct conn_data));
|
||||
mg_websocket_printf(conn, WEBSOCKET_OPCODE_TEXT, "id %p", conn);
|
||||
return MG_FALSE;
|
||||
case MG_CLOSE:
|
||||
free(conn->connection_param);
|
||||
return MG_TRUE;
|
||||
case MG_AUTH:
|
||||
return MG_TRUE;
|
||||
default:
|
||||
return MG_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
s_server = mg_create_server(NULL, ev_handler);
|
||||
mg_set_option(s_server, "listening_port", "8080");
|
||||
|
||||
signal(SIGTERM, signal_handler);
|
||||
signal(SIGINT, signal_handler);
|
||||
|
||||
printf("Started on port %s\n", mg_get_option(s_server, "listening_port"));
|
||||
while (s_signal_received == 0) {
|
||||
mg_poll_server(s_server, 100);
|
||||
}
|
||||
mg_destroy_server(&s_server);
|
||||
return 0;
|
||||
}
|
12
3rdparty/mongoose/examples/websocket_echo_server/Makefile
vendored
Normal file
12
3rdparty/mongoose/examples/websocket_echo_server/Makefile
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# Copyright (c) 2014 Cesanta Software
|
||||
# All rights reserved
|
||||
|
||||
PROG = websocket_echo_server
|
||||
CFLAGS = -W -Wall -I../.. -pthread -g -O0 $(CFLAGS_EXTRA)
|
||||
SOURCES = $(PROG).c ../../mongoose.c
|
||||
|
||||
$(PROG): $(SOURCES)
|
||||
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib
|
46
3rdparty/mongoose/examples/websocket_echo_server/index.html
vendored
Normal file
46
3rdparty/mongoose/examples/websocket_echo_server/index.html
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8" />
|
||||
<title>WebSocket Test</title>
|
||||
<script language="javascript" type="text/javascript">
|
||||
|
||||
var out = function(message) {
|
||||
var div = document.createElement('div');
|
||||
div.innerHTML = message;
|
||||
document.getElementById('output').appendChild(div);
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
var url = 'ws://' + location.host + '/ws';
|
||||
var num_messages = 0;
|
||||
|
||||
websocket = new WebSocket(url);
|
||||
websocket.onopen = function(ev) {
|
||||
out('CONNECTED');
|
||||
var msg = 'Не всё подчиняется разуму. Но всё подчиняется упорству. ';
|
||||
out('SENT: ' + msg);
|
||||
websocket.send(msg);
|
||||
};
|
||||
websocket.onclose = function(ev) {
|
||||
out('DISCONNECTED');
|
||||
};
|
||||
websocket.onmessage = function(ev) {
|
||||
if (!ev.data) {
|
||||
out('<span style="color: blue;">PING... </span>');
|
||||
} else {
|
||||
out('<span style="color: blue;">RESPONSE: ' + ev.data + ' </span>');
|
||||
num_messages++;
|
||||
}
|
||||
if (num_messages > 3) {
|
||||
websocket.send('exit');
|
||||
}
|
||||
};
|
||||
websocket.onerror = function(ev) {
|
||||
out('<span style="color: red; ">ERROR: </span> ' + ev.data);
|
||||
};
|
||||
};
|
||||
</script>
|
||||
<style> div {font: small Verdana; } </style>
|
||||
<h2>Mongoose WebSocket Test</h2>
|
||||
|
||||
<div id="output"></div>
|
||||
</html>
|
61
3rdparty/mongoose/examples/websocket_echo_server/websocket_echo_server.c
vendored
Normal file
61
3rdparty/mongoose/examples/websocket_echo_server/websocket_echo_server.c
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright (c) 2013-2014 Cesanta Software Limited
|
||||
// $Date: 2014-09-09 17:07:55 UTC $
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "mongoose.h"
|
||||
|
||||
static void push_message(struct mg_server *server, time_t current_time) {
|
||||
struct mg_connection *c;
|
||||
char buf[20];
|
||||
int len = sprintf(buf, "%lu", (unsigned long) current_time);
|
||||
|
||||
// Iterate over all connections, and push current time message to websocket ones.
|
||||
for (c = mg_next(server, NULL); c != NULL; c = mg_next(server, c)) {
|
||||
if (c->is_websocket) {
|
||||
mg_websocket_write(c, 1, buf, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int send_reply(struct mg_connection *conn) {
|
||||
if (conn->is_websocket) {
|
||||
// This handler is called for each incoming websocket frame, one or more
|
||||
// times for connection lifetime.
|
||||
// Echo websocket data back to the client.
|
||||
mg_websocket_write(conn, 1, conn->content, conn->content_len);
|
||||
return conn->content_len == 4 && !memcmp(conn->content, "exit", 4) ?
|
||||
MG_FALSE : MG_TRUE;
|
||||
} else {
|
||||
mg_send_file(conn, "index.html", NULL);
|
||||
return MG_MORE;
|
||||
}
|
||||
}
|
||||
|
||||
static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||
switch (ev) {
|
||||
case MG_AUTH: return MG_TRUE;
|
||||
case MG_REQUEST: return send_reply(conn);
|
||||
default: return MG_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
struct mg_server *server = mg_create_server(NULL, ev_handler);
|
||||
time_t current_timer = 0, last_timer = time(NULL);
|
||||
|
||||
mg_set_option(server, "listening_port", "8080");
|
||||
|
||||
printf("Started on port %s\n", mg_get_option(server, "listening_port"));
|
||||
for (;;) {
|
||||
mg_poll_server(server, 100);
|
||||
current_timer = time(NULL);
|
||||
if (current_timer - last_timer > 0) {
|
||||
last_timer = current_timer;
|
||||
push_message(server, current_timer);
|
||||
}
|
||||
}
|
||||
|
||||
mg_destroy_server(&server);
|
||||
return 0;
|
||||
}
|
15
3rdparty/mongoose/examples/websocket_ssl_proxy/Makefile
vendored
Normal file
15
3rdparty/mongoose/examples/websocket_ssl_proxy/Makefile
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
# Copyright (c) 2014 Cesanta Software
|
||||
# All rights reserved
|
||||
|
||||
PROG = ws_ssl
|
||||
CFLAGS = -W -Wall -I../.. -I. -pthread -g -O0 $(CFLAGS_EXTRA)
|
||||
SOURCES = ws_ssl.c ../../mongoose.c ssl_wrapper.c
|
||||
|
||||
all: $(PROG)
|
||||
|
||||
$(PROG): $(SOURCES)
|
||||
$(CC) -o $(PROG) $(SOURCES) \
|
||||
-DNS_ENABLE_SSL -DSSL_WRAPPER_USE_AS_LIBRARY -lssl $(CFLAGS)
|
||||
|
||||
clean:
|
||||
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib
|
49
3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws1_ca.pem
vendored
Normal file
49
3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws1_ca.pem
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAwizPnrCx+/kPSdEeSJFLDXrBH+cSQsSLrCm99G1hCjzqSlIk
|
||||
1BhkZMEHxBaiVLky4+M/nwhjwwRHI10h6U2Or3tbPLv7z94cPf+uCx1aF7TE3Fm3
|
||||
6YnDk+CjrYVFN5GRPGOPPdFxGoc+vFvQJyAAimvchnS1ZoEQFvermwzOnKspA6gc
|
||||
Px+7wnOeju9TyJuDr5ngtDXFnkcpkBNPxz3En4MJY4xJiaueafh9pIES2vSl7uP0
|
||||
J/qot9v2rdiL7nt1H1vwseeEkZhQ+NLB5e2z4psyktJcwDX7wQ6j7JnKfHeP+ixO
|
||||
TUORgV4foBMVOqo//Guo92Q5HoLNK77V0y4+ZQIDAQABAoIBAGEsx+LlDs3JQQty
|
||||
KjOq8uKWElyC6bKcZkIMydGvg6b6AU6ceW3jnyqFJ/vMUAUSghNmQQq3yiVo2Kks
|
||||
DLKTa9sKYwisE0NeJsgoUtOhJttCTlrwU4f+t/AjtgY68f7zTLnqIV+Ql4ftM0pU
|
||||
sIFEFMExZbWsZrQb1w+Hd0wrRqNEbSOfSjHeigvuw1T3GH2tSBUTGTpcoewCzy7U
|
||||
PKS5pkYyiKySQQNqZTac3NHPjxdK6xxzwURZp1irKdiPdt04KHLVLX8KXelt/J0k
|
||||
AeYkVbpFIeQ9rNBerMEp6uRBt+nE5mvP+xx1XPqKRxuxbMyTnBXeOM2zS/a/dBiz
|
||||
fwokwcECgYEA9RSsv9AQ/AR8tt+aPEQvjhJ5pn/YbCb1DA9IDXpaq3tzacGd8JHj
|
||||
3kUtb79nosu85LvSkAYmtzgfJs6xZyUkscra6q+xlsJ12QRxLzqfxcp9Y0wsdqM4
|
||||
AcOwuiPKrjkWxOQpyWPWRwbmAefLfRMekHt4Y/QY0CwhslpnsOsj3O0CgYEAytOE
|
||||
8I4GBfSQfSjXwfrso++Oi75VSsl5ZeiMGihfEhYFTE8/3rEZf7nf9iFSkN3TT+7f
|
||||
pFqQzddzPBZXlpVM6k1jcEjdpJizbeR8DmICpABFrZvKz1o8pQ2Yw+FYI86ih0x4
|
||||
806snMNgg/RgcVijXKFrC5joJOI+DVgwWoQyMFkCgYBxt4MkiV2oIkjf7ca6GgVa
|
||||
zbXGjOGV5Umkq96J6nDxyplVw/IN8xOhScX4aP6kahaep4vfKguCzjaeIh/stS5e
|
||||
lLqZVKZ5Roe6B7ag7HnAI+GkVm73KWrOXse8xui/iFvJRfkhqgJ9+HR3A9/GjD2N
|
||||
Ws0Uy+lLhn6oLAya6bA9TQKBgAVfZP4aRP6TY+Bs3Io+41XUWqpI+GlqvNR+PHfU
|
||||
6e/ItYs37jEv78T6X3xdlZpQxfAwG6x22a8aLetBjEBo5Aiw1Bl9VKGvidE3ZDHd
|
||||
VsSRXUckAVNMyJ52pb1KktMf/h4nYGzRgLEGW+Ai8QsPlgQ2ImfEPSH8/DfORjmf
|
||||
ltTBAoGBAMxIZ52DrJvuxogSOfA1MoCD6a90trkXCquvi+A/fXojZ8BHmMQshvhK
|
||||
rAO7SDIV1i1Nh3jQ/oFWE8KOprqrOLO6jNTyF65vh+zk7ztGsEME9FkDhHasUiXf
|
||||
t5PE9KeTChHRvIa4FGCl9We9GftE5Ii77LWMOIq22pyxYbvHQFEf
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDlDCCAnygAwIBAgIJAIOoO+AapJ5WMA0GCSqGSIb3DQEBBQUAMDoxDDAKBgNV
|
||||
BAMTA3dzMTEMMAoGA1UEChMDd3MxMQswCQYDVQQGEwJJRTEPMA0GA1UEBxMGRHVi
|
||||
bGluMB4XDTE0MDgwMzA5MTU0NVoXDTI0MDczMTA5MTU0NVowOjEMMAoGA1UEAxMD
|
||||
d3MxMQwwCgYDVQQKEwN3czExCzAJBgNVBAYTAklFMQ8wDQYDVQQHEwZEdWJsaW4w
|
||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCLM+esLH7+Q9J0R5IkUsN
|
||||
esEf5xJCxIusKb30bWEKPOpKUiTUGGRkwQfEFqJUuTLj4z+fCGPDBEcjXSHpTY6v
|
||||
e1s8u/vP3hw9/64LHVoXtMTcWbfpicOT4KOthUU3kZE8Y4890XEahz68W9AnIACK
|
||||
a9yGdLVmgRAW96ubDM6cqykDqBw/H7vCc56O71PIm4OvmeC0NcWeRymQE0/HPcSf
|
||||
gwljjEmJq55p+H2kgRLa9KXu4/Qn+qi32/at2Ivue3UfW/Cx54SRmFD40sHl7bPi
|
||||
mzKS0lzANfvBDqPsmcp8d4/6LE5NQ5GBXh+gExU6qj/8a6j3ZDkegs0rvtXTLj5l
|
||||
AgMBAAGjgZwwgZkwHQYDVR0OBBYEFL54xAgtJTW6US4Mbr4QG0yKzvaxMGoGA1Ud
|
||||
IwRjMGGAFL54xAgtJTW6US4Mbr4QG0yKzvaxoT6kPDA6MQwwCgYDVQQDEwN3czEx
|
||||
DDAKBgNVBAoTA3dzMTELMAkGA1UEBhMCSUUxDzANBgNVBAcTBkR1YmxpboIJAIOo
|
||||
O+AapJ5WMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAJz/RzMa9Wa2
|
||||
eEXed7ijH1gcWtgVsVT1xZo0ksFl+QJ5Be1AJpOIe8nKdzYjxPWUkofIoaGHdMLL
|
||||
Uc/udRzsXncup+0mD+Yos6Cqyo9yHq7L1HbXfKYZtBXIjWHdF2+RP8j9tHfITXYI
|
||||
Pb2zsQ+A6PYpp5OLGZTDAnI2qffqsmwXFNhPfFhOANrGlOjsvy1P7JDzvymj/90m
|
||||
NomlO3vjxLHOf6MvedTgCB0dRcAoUWPgbxPWifjBmGBjQjA4ukMQ58wbBQgvIoCW
|
||||
obrXmLCNZIkpWTw4gMRYquY880IYK/OuFNJH/dawxx/WzuVr7IdLmbFY15zf5TUb
|
||||
ZpIpwqRCysg=
|
||||
-----END CERTIFICATE-----
|
45
3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws1_client.pem
vendored
Normal file
45
3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws1_client.pem
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEAwOp1RS9RnE8L5TszDPIOmpf/1pqb+ki99l/sGhqB/KZBKCuq
|
||||
uoCc2VPK3PCByBE15/xJ7t691FnJfForI9DO5p2R0FPD6o357hqRsh0dJNBm0VgG
|
||||
iNtLQ8lyYoE72HJbkgCAUZW4N0OBibOmvp/s3Fmr7rEjW5LmZxOtX+iULKIUZ0w6
|
||||
gJlM8G5QA1SuqndN0PbPx+RZKSXZCoJj+Nboqw03nyJUexzs+lynR9ITMziUaaVM
|
||||
4rzG+P6joQAnUkDNydxo/d4tj4xaioZdKxWLYEbj2BUtOlJJydotWo2wcG85ONrT
|
||||
Gw0ltR1vku1hidMm2QL30uGIL5SeqyE8TqWk4QIDAQABAoIBAQCxHtKauc45MA4g
|
||||
4hCGAzvLTmETnRI2YlEfAoTYlpvf5pkOE8GFyI25r4gjACJ4GO0gWG9dBF7Pt7wZ
|
||||
EwRmttEvxV3aIv5OvRnKNdSs7rQSV9D+xc4CGy1oSG1f6X2TxbMzQoiN32OqQa2O
|
||||
S0Z94IFs8lu8JCDtc9tcqiFVXEmnC3RvJZOShWpsCsbmh5ue1Xed0MQQ47vt7Zt7
|
||||
I0cutvwSFJMsZkZUJp5+KjVNYo9TEJxVD3m2NJNJxBfBoRVHXNii3hUEHcTIdIAz
|
||||
omtRwBU8AKgJirGIRo1h2ZFyubI8ScGOJWIiWMQvQqTHKiOaz3yUar1NSG+kFn0U
|
||||
cj7s3FhdAoGBAOQbx8Jwhtp4iOkP6aW1nVTgiaTj4LMlyJZioFwgPFRIcA3oRHt9
|
||||
5SRetmgFZNvcuNw1udfeaObKmlzxwUruprwOpihgAQWJFTtOjQNrt2gsYuX4l3W6
|
||||
T46dO2W1pV+mW4A5gt0aqhLv7pCS4lpreNAqyHSPqcQWcCeiTzmp/LfDAoGBANiB
|
||||
FQOTyMElR9OzKwmcGfIvnhUfJQwi5qNE3R+xXiP5x36a9HQBey5ri2lnBle0Ksr/
|
||||
G+RKoflmk1eFXVHN0w35yw0dVco//WE4vOknldNEnIT85k02ld8lDTa2Q/EJZtPH
|
||||
un6zeU0Q2/4SZ/GXPssEZPlpPM7WtQzztlH3+sqLAoGBAKnhppvAgi4ippQsLa4j
|
||||
29BiiSAsNiQ1d3XIbfUubL+4UvuIh7gQwp6biu1dVwgHEgWuXYHPOgDn0p51zaao
|
||||
pbRYlJZtKVWeChnpHkv15NnIdL8grGwZHTbxElNlPIxHsM2GB1fzi8YeumUhf0In
|
||||
2AnwUum8NIq8yzo5PxeK6ZNRAoGBAIEA2Q6ankJH/nZsCbbeJq+iI+Wd+ysyGI8s
|
||||
Vz2tJ9Tz3iTYG9SLlWRhfF4/nw3fMqhmPa5Xsg+zSRQbSTGXHKz1LEISOq4aVtX5
|
||||
QscCaUnLVh//uRJE9iRSJX92NyGGYpjKJ5ubQSnkY9EOEpVnc2jwo2HhjPQKBzNC
|
||||
fF53Dh5lAoGALwTN5uxrBZLPu4DtZkOosKkv4l+kzFoOjLJR4vA7ONBx2CSe9G7F
|
||||
tSsH7lZS3b0mxBWjO90WhaSvtMWWrfqq8vrqmoTE795fYxNoLfCLK13W31aTDUsI
|
||||
pQRJIL30MPvASbcFHN2MD2dXz2nQzY8C9lvtvap/krYiDKDU2L7+iP8=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC7DCCAdQCBRQHBXNHMA0GCSqGSIb3DQEBBQUAMDoxDDAKBgNVBAMTA3dzMTEM
|
||||
MAoGA1UEChMDd3MxMQswCQYDVQQGEwJJRTEPMA0GA1UEBxMGRHVibGluMB4XDTE0
|
||||
MDgwMzA5MTU0NVoXDTI0MDczMTA5MTU0NVowOjEMMAoGA1UEAxMDd3MxMQwwCgYD
|
||||
VQQKEwN3czExCzAJBgNVBAYTAklFMQ8wDQYDVQQHEwZHYWx3YXkwggEiMA0GCSqG
|
||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA6nVFL1GcTwvlOzMM8g6al//Wmpv6SL32
|
||||
X+waGoH8pkEoK6q6gJzZU8rc8IHIETXn/Enu3r3UWcl8Wisj0M7mnZHQU8Pqjfnu
|
||||
GpGyHR0k0GbRWAaI20tDyXJigTvYcluSAIBRlbg3Q4GJs6a+n+zcWavusSNbkuZn
|
||||
E61f6JQsohRnTDqAmUzwblADVK6qd03Q9s/H5FkpJdkKgmP41uirDTefIlR7HOz6
|
||||
XKdH0hMzOJRppUzivMb4/qOhACdSQM3J3Gj93i2PjFqKhl0rFYtgRuPYFS06UknJ
|
||||
2i1ajbBwbzk42tMbDSW1HW+S7WGJ0ybZAvfS4YgvlJ6rITxOpaThAgMBAAEwDQYJ
|
||||
KoZIhvcNAQEFBQADggEBABPLmq6zKOMY0WRjtBoSymq6f+vXeEwtWCfVejdG6RlG
|
||||
/PTdCKNvp3OL7FDnmQQ+r5rMs4+Os4fX/g315QFKXu01rqxmFb2XVNhhaECdUWtK
|
||||
QP6ZoVZviUiDjhK6a+05aerPCJpkGy/lz0W6gmj4qhuAQbobxb6UbzqTRYY+ZwGk
|
||||
+SI3TAVCdmXFlxN/M9b0DbmkseRG8GGFmyRYyRb84vbV6zemFI++5ROUT9zXT7ey
|
||||
nYfFJvAAk5jJhY5UP2aMlVWYYa4jUZrrPLoiBLUuRrp67EKGebCH9mgCIf8ztNJF
|
||||
fpuvcz++LUeRyTlAGDefe+FyHGIwFzIfZn39D7CaRvM=
|
||||
-----END CERTIFICATE-----
|
45
3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws1_server.pem
vendored
Normal file
45
3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws1_server.pem
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAyal0BZKRYd+Wpxv4MB8LjjgXv/MxSN5oSAKThlCZ/AWG0FEP
|
||||
d4nrBACT2xUxwo+xbYl3joiwL/eCPAp6QNKRGhvXVOnSIFVSjKZWbdX+toqK9pDS
|
||||
QMDTL4ZJvK6pLZXknyHjEr0PxZh22F7iS1+C8HxBPj0Xgg/u5/+jPhFPPZ1d5elv
|
||||
4cm/z+xy6RjFlA80aIeK7dcWssOsOIPjUNFfmoYgR63ScZIlUZj6j8VX9oX7fJID
|
||||
jumGajDxgD2nBWFbHcGKin6bz/wZ+OIhXOCDdY7oKuMW4JiBwbfBtedkQuQYS11s
|
||||
PRFFYDLoZH59Ivcu0c4F2tomE86qM8THsI910wIDAQABAoIBAG55FAQRfO8/C0rU
|
||||
eavy9eOdOvV+hltC66G3N5X3BcQYSvhHz89OkJ6KqnT0MWRCT5KQIhzFKK++SWwW
|
||||
2U41jCPfaKEtzlzEIQrH/MUC3Byn3OSiBWxPteFtEWv5ytgcKzg52iljxQYcNc7m
|
||||
e9WKpzKS/zLXSM+JZvlVA9p2pRA88kUZ/EE5H+FW3kHj5eGNqX+cxUVpL0VKTiLv
|
||||
aXWjYotpmDJW/Rn9wRQethm6Gdx3bvo+LEVlJRELNq8NM5H/tZIVRzudJOgzsw5v
|
||||
3OQGhfKB6Eg/vqSFoZxX6ApXDxmtaSO83B0kK550bDVv4sBnOExGjKCzybt04tet
|
||||
KtLPPoECgYEA5WUD+mFL99sCX6pzIyUVlxp9eUhVy5nvhoF6u3mvhay2XsZUY0wy
|
||||
+/qVqYSZTvuvJ6JSXc4iVIX8u/gj7914805AwujepIF/8E0AaXLBMndzDE4ze5S5
|
||||
2RHI7Cy4/3AWOcQ9wFFmUdSs7/6oAkcQtvzP40hGg3J2jAEhIdCqmbMCgYEA4Q0G
|
||||
BYP9XeTdh0C+BcP9B5VUEC0jerYS8VqVqriB+9JfT3InI7K08sOG2DiQQBhAHuzL
|
||||
RhCECU2a9j0+u5F5JNeY5m3IhU73Lw+lOlUkMaAO6x7JJEzhXhonE7Kv8fWygr/0
|
||||
OB7yzqz+YsWdQ2VOPZ88ntlAYE65vzcaVswZY2ECgYEAr7Gt2VA6Ei0A5Wq0Yr+d
|
||||
iKz2WzUG2TkelqOG8B4kTDrbNz2qFp+fERV9GWgAz9i+75lIgqZF7vzsdL96LtYv
|
||||
NBLEUURwegjhh5hCb4E/7bpFOLCQh9+CdHpFrHYYfzRHIZlnPmxZ9OTyS6J85bmu
|
||||
WKjLRKXvs++wUkzvJmoesDcCgYEAkTOB6xUZ5/a+J4HSGI43NylVr4owFgBbgHVd
|
||||
k2SwGPXGoM+aCSJINUmKOv9jsrbyyAEntfD5/7aegLlLPGHDs82WzTWP5tLoEOkb
|
||||
ReOhEpOejHy0ckNYNQrSo5bqhkZsAogu3fa52jcrejbeHJnEPWX8CtFJA9pHZeP7
|
||||
jnzo9IECgYBefHg0dymSj2xxN0XmC+S5cvQu2K/NYUpatoWvHnPiQ87wIM0AWz0O
|
||||
D0ghEI+Ze57NbtSrrcTE7hY/LHrAqXGAB9XNIM5g9Pp/lM+XjzKVr1FMf4xpuHf1
|
||||
VJJRHrOU14CvMvKbgbPrL6B0d5yrYmeex7GxNw0ZVvtjCa502Eck+w==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC7DCCAdQCBRQHBXNGMA0GCSqGSIb3DQEBBQUAMDoxDDAKBgNVBAMTA3dzMTEM
|
||||
MAoGA1UEChMDd3MxMQswCQYDVQQGEwJJRTEPMA0GA1UEBxMGRHVibGluMB4XDTE0
|
||||
MDgwMzA5MTU0NVoXDTI0MDczMTA5MTU0NVowOjEMMAoGA1UEAxMDd3MxMQwwCgYD
|
||||
VQQKEwN3czExCzAJBgNVBAYTAklFMQ8wDQYDVQQHEwZHYWx3YXkwggEiMA0GCSqG
|
||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJqXQFkpFh35anG/gwHwuOOBe/8zFI3mhI
|
||||
ApOGUJn8BYbQUQ93iesEAJPbFTHCj7FtiXeOiLAv94I8CnpA0pEaG9dU6dIgVVKM
|
||||
plZt1f62ior2kNJAwNMvhkm8rqktleSfIeMSvQ/FmHbYXuJLX4LwfEE+PReCD+7n
|
||||
/6M+EU89nV3l6W/hyb/P7HLpGMWUDzRoh4rt1xayw6w4g+NQ0V+ahiBHrdJxkiVR
|
||||
mPqPxVf2hft8kgOO6YZqMPGAPacFYVsdwYqKfpvP/Bn44iFc4IN1jugq4xbgmIHB
|
||||
t8G152RC5BhLXWw9EUVgMuhkfn0i9y7RzgXa2iYTzqozxMewj3XTAgMBAAEwDQYJ
|
||||
KoZIhvcNAQEFBQADggEBAE20gAykuuaCoP49GnZ/Z6ZItFry4Fl6iCWBDdEsWI9R
|
||||
wRNYumeaeejdFPXfSJdTT7UlrVK1WWGLQLq+ixHRDX+V9T67ou85F92H/OxbUoPr
|
||||
iz/TZAEBTC1GvTJl49lsfPl1dTWH8T4Ej2hxCUvIJrkCkI2Ov4Wwef6A26USrwBt
|
||||
S/CPInjCe6qkE5E8xfTDl8k5IIgMadTPhi5sbV2piBJoN4floJPqR0hdDKbgUymn
|
||||
5WNSiRkuI6UIDZwQEp+A8TmFBHbSwfTGt2Sz5iI27P8J6pFvR5eRA1k57dRUWNXC
|
||||
WAU1nqteP3QAjj9L3o8IO0T62scaiJX8x01gTmVVe2I=
|
||||
-----END CERTIFICATE-----
|
49
3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws2_ca.pem
vendored
Normal file
49
3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws2_ca.pem
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAwXIMpHuTNsro2pxe6y1mu27md2Olhvfx26rO3maO0/stIC2z
|
||||
G/xQatFDLIWzfKFYOT0iSEj252ENFDCw6aDRKpiaUFtXcMAWkNkkKntEyoEgE45k
|
||||
rTrvpay0v0B+ojwjA1Jz/9v35cgvDwTs3vNFno5HhI0m2YF4ocTmeHJ6u0xRL/qy
|
||||
atfKsfuVq5s5CXOYCXp3Ux6kJ1c22J0EdZMvS75SVjAZgRkqQpqt9L3e2ZBCEgUr
|
||||
w0KwlERvpeJF+sJJOshXjfrDzvwL8IpPnGZLJNINFbSJMk5MFGcMyq/28pSZLB9E
|
||||
Dh8vk5D5gUnxM60ONUy2nYPcYr5p1PLDiC8hfQIDAQABAoIBAB0Twpi6xn8W8vdh
|
||||
R9c75NRJsDTD8q6d+GnXe+7sJY3xlG/gzqpnO8NCn0FC+57BNdystsl8xjgzW17s
|
||||
jrsfZDFt7MwlXrhg90NgkFIeY1G5JRQrdDChykHx+t1AmYhTV8P5EdykuNd+RqyQ
|
||||
RfahRJa3tkJTYUKSdoqCaU4zjwU2CSxltuJx24V+WoZE12EwewJ8HPg2XTnbsGE7
|
||||
Fnx5s29O4ItM70CC0536AY/OgfuPix5z573VQiilqqfOQkVkKa1fHd6tGpWU+3kH
|
||||
X9FnhEBf9cN9tVgmaB0sCSVVrfgqSXg1EwKHqe/+FCumuesA68Q35+/K3b+QrNiR
|
||||
ka2yliECgYEA+V/4pbgG/lPYvTwWhKxGXXdJmrSPgZC0mwE+fRuYkeptbIkS0pwt
|
||||
/UDTXk9nttj1f1ZJ3NgQbT/1w8jpXfsCJ8VeGzL9+ADhRKWVFRlu/nyFCMXawLEV
|
||||
rot7SEr8BW/m8moHgY5lYipM3dXJPk0F+KLrN60U/aNmFUtPGW802BkCgYEAxpWy
|
||||
FGL2sEQ0QaRDTcqqF5faVqw+5rVGvN+EX5o26E0QWWnoo3L2c2/5X93iBl+Fqtnm
|
||||
9jSIQUC3rYOawKnZ/HcIE2ergFit/p6JaV9NiLDRtDUmSzlffEGVCj0neYFsnWp5
|
||||
zcmkUyZ6fr19EmKQWfdteNBlXue32TjVlFbfUQUCgYAfMbgi0sBdNBPaqBeRBRPQ
|
||||
QUm9xnRlGrrc4Oz2LWuKZS7G8uad3deK5H8MPxaUMtOS2DJpI8X6RJPzp8A5d1qv
|
||||
quq4sEpAqauEMMpTV1khEGZ70HQqwnwZ12zWgDrCW1siW80QkcVw4CW5YjLITk4+
|
||||
6fJOhqInkDcG1uLQJa8QkQKBgQCfs8l4DbJ4RRGFbLXXvNGXkb68j18yqLxPrq3F
|
||||
OL9JiJhKYBsAP7clVPrG9ykLmQxlP0I35D1jxMkymLD+mlo9Z/itqmTJHggnyZWW
|
||||
kVdIQ3MSKuA2BNjek9tpVY8Gb2hLHFMChVRKrpo6jOclvvB5+bsnOukbLtyyq7tP
|
||||
xaFohQKBgByCmlltjOBWZLFLeA1x8j3inm9zM/FAJuANbHUOZ1RwrRcNFbDv/FXm
|
||||
rLPnPCaH5AwAWhVRJcNHo37Ee0s/xqe+Q4dG4xL943k+6KlopAw1SXhuXF6PnBfF
|
||||
y+ArVlh9d2oWN5cBEzRddnWnKJuMi70kMzYf6dIW9s/dHbq/gFDy
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDlDCCAnygAwIBAgIJAJDtcXU2wiJIMA0GCSqGSIb3DQEBBQUAMDoxDDAKBgNV
|
||||
BAMTA3dzMjEMMAoGA1UEChMDd3MyMQswCQYDVQQGEwJJRTEPMA0GA1UEBxMGRHVi
|
||||
bGluMB4XDTE0MDgwMzA5MTU0OFoXDTI0MDczMTA5MTU0OFowOjEMMAoGA1UEAxMD
|
||||
d3MyMQwwCgYDVQQKEwN3czIxCzAJBgNVBAYTAklFMQ8wDQYDVQQHEwZEdWJsaW4w
|
||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBcgyke5M2yujanF7rLWa7
|
||||
buZ3Y6WG9/Hbqs7eZo7T+y0gLbMb/FBq0UMshbN8oVg5PSJISPbnYQ0UMLDpoNEq
|
||||
mJpQW1dwwBaQ2SQqe0TKgSATjmStOu+lrLS/QH6iPCMDUnP/2/flyC8PBOze80We
|
||||
jkeEjSbZgXihxOZ4cnq7TFEv+rJq18qx+5WrmzkJc5gJendTHqQnVzbYnQR1ky9L
|
||||
vlJWMBmBGSpCmq30vd7ZkEISBSvDQrCURG+l4kX6wkk6yFeN+sPO/Avwik+cZksk
|
||||
0g0VtIkyTkwUZwzKr/bylJksH0QOHy+TkPmBSfEzrQ41TLadg9xivmnU8sOILyF9
|
||||
AgMBAAGjgZwwgZkwHQYDVR0OBBYEFLK4flD5QD/mRufsPx63xlEKM8pwMGoGA1Ud
|
||||
IwRjMGGAFLK4flD5QD/mRufsPx63xlEKM8pwoT6kPDA6MQwwCgYDVQQDEwN3czIx
|
||||
DDAKBgNVBAoTA3dzMjELMAkGA1UEBhMCSUUxDzANBgNVBAcTBkR1YmxpboIJAJDt
|
||||
cXU2wiJIMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAEYD+CReikYr
|
||||
Rzvk+/Vdi/7IcaH9CFknIdtineSIw1y98nxnbnNJqxwfNaRblbYvg6OFdUI3POuI
|
||||
+rdYLCFl8z3tWqRHLkGqHSJA9xcng3jLJxz0+ctiVcekJvXaB3O6eSZjhGbmmI/s
|
||||
CQhdy2zpEIVOeUq50DrSJp9CknyGu/IkaGx5GOZtkiHMrpig50CRjX1lS6qrMNYp
|
||||
vB8gfuqpjsL4Ar3vg+lgMSwNWXBNHrIRPHB5VEzBEdmLFZlvueR0ooEMCklpwX/a
|
||||
lFImVc6JcY1pBEkHTiTLGMpGAHG3I1aVUaWb3L+V+2ym/KNRNL5C2+1eiqql5u8m
|
||||
HUaOcNC90ew=
|
||||
-----END CERTIFICATE-----
|
45
3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws2_client.pem
vendored
Normal file
45
3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws2_client.pem
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEA0ucemqFwBFziVOgTgx4mZII4WnGDpA/rWAGHvUZOqy2dQ3Pz
|
||||
woGKxBaVPAl5kxEosROVGa7dTuq5yFZ4XIGvwCKxF30vCmdGCytqq6MMp904jG32
|
||||
KikkmjCApIMGxMO4eoBHZZxiyVvKTbg9M2CRXErwnYWhFH/qGdPnuo0CEaHJA4VK
|
||||
A9incT9dpeEhU30R6ajAe/je9rCj2OMLMFSMfd51L/VYfO60zDwUNY7YVIghQZgJ
|
||||
e44EVGsp1pXaqaD6o3PvGY3ohw2aZjJzlJ7MJHbKV9lft98R3pklbpBzMH849cEy
|
||||
Q/51L/rlfTUgCpTy7wEZpWHQNtHfu/1rhJjpNQIDAQABAoIBAQCUNIHXG/dBuZv7
|
||||
GpMLotZL7w520Co30lAJqhmfMpb5x7YpvoPffXTsUwpQBECAzqAPv7kZMT6nxF8F
|
||||
n245Y5EDrd1QqlGyN9yK4Nm2/39XPygL1wITopHsIIVmFgVdpEQxIZAKoZjx8yT4
|
||||
9K1dO1Eq0CbCKzOE2lbCC51eBNUdWZIMxwC6O/j/KoIkZ/HwlG2hpUuXg8x/XawA
|
||||
ZJDCoTcWHCjYP10FxKVN3vAyWM2IM44o9IbsAGEOswR4gUwRsgq6Ehc1U59XUHi+
|
||||
x30oda55I1/8xD+SfP/zk2dDPHkv/hq5+258GU/THsw2+AAexocvSIS/g9EppTEg
|
||||
biFaDKzJAoGBAPqey10JeyiOlHbBjoSSa7lJYUjocQANFQ4ayOAgfNX72iyabrKF
|
||||
p9sVAeO/nM00+DPrm2wWws03ScsPeh+9BDJMPRBUHfSNp7+F+oyj7PWHBEFHbyO9
|
||||
5HnYZP+1vhdG2dYPIY2gRSFXpiGn3j0M1D0w9c7Ilm8ee3krdR4E/mw3AoGBANdu
|
||||
EfS1dK3+m7sEgc2+3U32z83GpuCHeUIKGPYMLI0fIb1CPpboHU9YjOFJZH9iIIdl
|
||||
00JC963O3+pqLe0XbMOmBVt9QjZfhfB+AY+JHtbPgoQVLtq9X/WvW7h3xn6S971r
|
||||
Crkhqay3Cs4BzsgYDYraQCTw3oq4twR9Nuy4etfzAoGAXOsG5wWe3diO/sCggFJx
|
||||
Eg88vHVBgA1ZoxMXKtGgtw1bRHI1XIblRvqw6qmeDw72fvl5dEe0DbXT7C9ezemc
|
||||
ZrGRaj5lpMfoS7/2trIIJrfaQgGkGRJMZUhvmcbeJW8lUJHnlMS5HLWMaKn+YZAi
|
||||
GFXQrMv9ylD44mHUWD7tvV0CgYBNctPfvvCQsQ05ofgsiKa1Jbs1hmpuJCYy2MB6
|
||||
jIvjvEJ78PnhdNc8tGAJikIoDZYWN0RI+RxkDxCvDLcwGpDOkbwxVQnd1F+pwxM6
|
||||
kBhXL8kDRT5QA28hO4bk/aKN1LZeEcKMJg8C+ddXkozNoOAVgDs5TKMlCh057u41
|
||||
EmmPgwKBgQDOlYi7fPYOCy0yjHMxSrp2SZOS06AMWGbbCoGkjRtvuP+FmKSNB+LZ
|
||||
pOSEPJgzjsRutKjneww4LpV6dViAyTcP5JoeQpokHf7UVo7yq2QH/iwF3zJwsC/S
|
||||
OuVLkqpZzWuye/QCH5NOTfw27ye8jG8VcQW2QPbcbkLXLM7zg2yX7g==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC7DCCAdQCBRQHBXNJMA0GCSqGSIb3DQEBBQUAMDoxDDAKBgNVBAMTA3dzMjEM
|
||||
MAoGA1UEChMDd3MyMQswCQYDVQQGEwJJRTEPMA0GA1UEBxMGRHVibGluMB4XDTE0
|
||||
MDgwMzA5MTU0OFoXDTI0MDczMTA5MTU0OFowOjEMMAoGA1UEAxMDd3MyMQwwCgYD
|
||||
VQQKEwN3czIxCzAJBgNVBAYTAklFMQ8wDQYDVQQHEwZHYWx3YXkwggEiMA0GCSqG
|
||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDS5x6aoXAEXOJU6BODHiZkgjhacYOkD+tY
|
||||
AYe9Rk6rLZ1Dc/PCgYrEFpU8CXmTESixE5UZrt1O6rnIVnhcga/AIrEXfS8KZ0YL
|
||||
K2qrowyn3TiMbfYqKSSaMICkgwbEw7h6gEdlnGLJW8pNuD0zYJFcSvCdhaEUf+oZ
|
||||
0+e6jQIRockDhUoD2KdxP12l4SFTfRHpqMB7+N72sKPY4wswVIx93nUv9Vh87rTM
|
||||
PBQ1jthUiCFBmAl7jgRUaynWldqpoPqjc+8ZjeiHDZpmMnOUnswkdspX2V+33xHe
|
||||
mSVukHMwfzj1wTJD/nUv+uV9NSAKlPLvARmlYdA20d+7/WuEmOk1AgMBAAEwDQYJ
|
||||
KoZIhvcNAQEFBQADggEBACCCAJypO9DFU6GeOH+FwE0JCLTypHoIwERWxNL7xfjg
|
||||
rwVqIxwAEo+fJjL+QY7JbAb/eqKaXIBYkAF2lFc4iEmecXX/A3Aqw95AYi78o7HD
|
||||
MwRPqJha9mxLcCWwjX8XK8pT152BvYFPNhi+6jd++rDRxKDfmNvgdUQ2/YW6a5Wv
|
||||
zEmLDPUWRIuMQIEmOa2/JhlllDviMExTw51nbqYgCghycRvDACyQAuu8re7P6gcg
|
||||
bXObNlfxcU/8Ph6MFI+2S9ODtQ4BHyuKd4kRNsYn8vV42a0h3bCYSGPk3kSIgxd7
|
||||
XijwHT/o8E9ddH2BvDv+6Nhno9C6/MbezEOIs4nlhRk=
|
||||
-----END CERTIFICATE-----
|
45
3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws2_server.pem
vendored
Normal file
45
3rdparty/mongoose/examples/websocket_ssl_proxy/certs/ws2_server.pem
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEA29iFnMf4pjty6knOt4wT0joPUlU2dGCFWxQ5Eg77Yx3Lou2a
|
||||
FOzNGp7zLYH8gauOK+mgY+B9cBv8PvVtUQQKB0SKTTV8ZNKVyP3O5F2gRSJ+tHtT
|
||||
FqaPfG0WPOn/f02YbOpAe6Rk+NnlJoeuBxG4uapUSq7r0mTGJQe+52y1LcMs23ID
|
||||
ENBfDoUMVt5vCnF+cYK5ndeFVLyPO3JjohDH1zv3a9ECG28rtjKHLpNYFDsPJaD7
|
||||
UPuyyk3hIvfPCZoJOUlEVfpLT/lM+9oCPnq9PwIp5NqYofkuc3eKooCo7N4r4IlP
|
||||
Ajktaao6b0ScNwNQB3leOIdEUFSIYy8N1JszVwIDAQABAoIBAFlIvjrGG/2m9yyf
|
||||
fQyeHw6p9b8CTHNHH+G1fNgQrZe7ahBpXsJQyZueIjTBLcOb4MmEwFbPvSHiu7b2
|
||||
Bcd5VHlPJLvmlPZ9b8eJDJVCUOzC7aJu03fHfU6THwzuG42f/d9942JTiY5nL+FO
|
||||
CSdl0xfUTRdnou53buFrG+TxCUPj13HP1HY6DAVzEIq1H4TZwIZo7KRRTIYpTB3P
|
||||
6yvr9xsISLlnmfQ4tp2pApl5o+bHJEhr1VO6SAT/pSyShi79KmMMqYtyTmOMz7w6
|
||||
VJkre5ybnXBDN6tfMHWqdobJ4gRWK9rqf+LIZig5XQnyzkue8k+I7aPgO4xNFh56
|
||||
dkejQcECgYEA9MDCWViqpfvof+epiKzccqnIRnz1EfHdRQjiKsKGRe39+K+pyaqJ
|
||||
FOOPFy3aOw6M4cFWwcdMYzKTItvzyLVhDqMzT5eup/NVqo5tPoy93XPf2qRYiTl4
|
||||
2j5wvm0RVkYEONd3pk2lbfbUmn7XQXj0+AG60SvsqErF/UhIBGec/xsCgYEA5fLC
|
||||
EdiiC98kr4sVaE8G854WI+aAkStqO5YXyrnsMzRsqk8KVVYE1yCC9rYyymDBYmlx
|
||||
uEW+vbWqLc8PO3v4ty3o5ff303lPMWIrvKiUldjqMjS6ncWxsQjU0bygGVgOgHO7
|
||||
c8rjiDH5M0JgWSREYUVFT5mW/5+Y1LVT8mYNlHUCgYEAhMSX6N23XGkFW3Twu2qB
|
||||
/1Vohgw86OoaDNvfzDBPpFmQ3rlz0ijHSeSTd5BxBH5FICXACUgygNErjcphOSxj
|
||||
JQyUxgVTQlo2y1mNm1O/nwS/lxx1xqK9ky4x/Kqvr+w1WBxSFI2kQr2V4OUTobma
|
||||
sXpGvDcmnrhJJLd0EaefO6cCgYEA3Xw/S9tC8nZjqqYn34nHI16Q6tF54tpTf8Np
|
||||
dT4x8Xw8cqqhRGMPVHsfSi1irKYXfwgbnienuqlBmtAHVv9pKF+TJfb7gXkmO2XY
|
||||
xOYIAHGn2uYJHjCun9vmyYKLHv4/MaDH3Jd/I88mviXgEdyp9Js5UJua4utB1Rg3
|
||||
HJMJ34UCgYEAr0PpHEBMbZXZBybNU96+jRTgkrNeJpzlnMy7et2IsRAtLjZ0mpbn
|
||||
NaX8i8eO+ubweqFdhOvbh7Hd0zr7BzrYcUG1e3njhtxJE1MgWL5plnLVUbIyDAm3
|
||||
iBpIHIBASNCN3sqeq+VqXvavRmeZh5O0vyLP46/kxZx0rzR/NCi9xxU=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC7DCCAdQCBRQHBXNIMA0GCSqGSIb3DQEBBQUAMDoxDDAKBgNVBAMTA3dzMjEM
|
||||
MAoGA1UEChMDd3MyMQswCQYDVQQGEwJJRTEPMA0GA1UEBxMGRHVibGluMB4XDTE0
|
||||
MDgwMzA5MTU0OFoXDTI0MDczMTA5MTU0OFowOjEMMAoGA1UEAxMDd3MyMQwwCgYD
|
||||
VQQKEwN3czIxCzAJBgNVBAYTAklFMQ8wDQYDVQQHEwZHYWx3YXkwggEiMA0GCSqG
|
||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDb2IWcx/imO3LqSc63jBPSOg9SVTZ0YIVb
|
||||
FDkSDvtjHcui7ZoU7M0anvMtgfyBq44r6aBj4H1wG/w+9W1RBAoHRIpNNXxk0pXI
|
||||
/c7kXaBFIn60e1MWpo98bRY86f9/TZhs6kB7pGT42eUmh64HEbi5qlRKruvSZMYl
|
||||
B77nbLUtwyzbcgMQ0F8OhQxW3m8KcX5xgrmd14VUvI87cmOiEMfXO/dr0QIbbyu2
|
||||
Mocuk1gUOw8loPtQ+7LKTeEi988Jmgk5SURV+ktP+Uz72gI+er0/Aink2pih+S5z
|
||||
d4qigKjs3ivgiU8COS1pqjpvRJw3A1AHeV44h0RQVIhjLw3UmzNXAgMBAAEwDQYJ
|
||||
KoZIhvcNAQEFBQADggEBALi/RmqeXGazT/WRj9+ZqdcnbcHwK5wwr2/YkpFPJ0Hf
|
||||
ZDm+2vgjDdTT6cJS6fau0M5nliYdz89aQQo1j9RSRZnzlc/2YCFXyRLCOJYaINbj
|
||||
1MEUAvNDGL7xTpepK9hVkXASRkbyNXERXRKFI1N+vpKu6UorT6/osEV/qM+MFJ3s
|
||||
24xE8/J3J4MirVQVt6eY6Jb+tkliOPMIugr6YQlLsqJygEWATP8Qsr81XSfcZhVq
|
||||
rXzVt7QV8dO0nStMjKK5omrtEAhVnASk7w1tFHkpBF1rqXGoo9ML40RnFZ+E5zqi
|
||||
iZtzp+NzzLnEnWMNs+fJpPJ96P0kbq2bQzuSBcUynq0=
|
||||
-----END CERTIFICATE-----
|
253
3rdparty/mongoose/examples/websocket_ssl_proxy/net_skeleton.h
vendored
Normal file
253
3rdparty/mongoose/examples/websocket_ssl_proxy/net_skeleton.h
vendored
Normal file
@ -0,0 +1,253 @@
|
||||
// Copyright (c) 2014 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// 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
|
||||
// published by the Free Software Foundation. For the terms of this
|
||||
// license, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// You are free to use this software under the terms of the GNU General
|
||||
// Public License, but WITHOUT ANY WARRANTY; without even the implied
|
||||
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the GNU General Public License for more details.
|
||||
//
|
||||
// Alternatively, you can license this software under a commercial
|
||||
// license, as set out in <http://cesanta.com/>.
|
||||
//
|
||||
// $Date: 2014-09-28 05:04:41 UTC $
|
||||
|
||||
#ifndef NS_SKELETON_HEADER_INCLUDED
|
||||
#define NS_SKELETON_HEADER_INCLUDED
|
||||
|
||||
#define NS_SKELETON_VERSION "2.1.0"
|
||||
|
||||
#undef UNICODE // Use ANSI WinAPI functions
|
||||
#undef _UNICODE // Use multibyte encoding on Windows
|
||||
#define _MBCS // Use multibyte encoding on Windows
|
||||
#define _INTEGRAL_MAX_BITS 64 // Enable _stati64() on Windows
|
||||
#define _CRT_SECURE_NO_WARNINGS // Disable deprecation warning in VS2005+
|
||||
#undef WIN32_LEAN_AND_MEAN // Let windows.h always include winsock2.h
|
||||
#define _XOPEN_SOURCE 600 // For flockfile() on Linux
|
||||
#define __STDC_FORMAT_MACROS // <inttypes.h> wants this for C++
|
||||
#define __STDC_LIMIT_MACROS // C++ wants that for INT64_MAX
|
||||
#ifndef _LARGEFILE_SOURCE
|
||||
#define _LARGEFILE_SOURCE // Enable fseeko() and ftello() functions
|
||||
#endif
|
||||
#define _FILE_OFFSET_BITS 64 // Enable 64-bit file offsets
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable : 4127) // FD_SET() emits warning, disable it
|
||||
#pragma warning (disable : 4204) // missing c99 support
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "ws2_32.lib") // Linking with winsock library
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#ifndef EINPROGRESS
|
||||
#define EINPROGRESS WSAEINPROGRESS
|
||||
#endif
|
||||
#ifndef EWOULDBLOCK
|
||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#endif
|
||||
#ifndef __func__
|
||||
#define STRX(x) #x
|
||||
#define STR(x) STRX(x)
|
||||
#define __func__ __FILE__ ":" STR(__LINE__)
|
||||
#endif
|
||||
#ifndef va_copy
|
||||
#define va_copy(x,y) x = y
|
||||
#endif // MINGW #defines va_copy
|
||||
#define snprintf _snprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
#define sleep(x) Sleep((x) * 1000)
|
||||
#define to64(x) _atoi64(x)
|
||||
typedef int socklen_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef SOCKET sock_t;
|
||||
typedef struct _stati64 ns_stat_t;
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR(x) ((x) & _S_IFDIR)
|
||||
#endif
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <pthread.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h> // For inet_pton() when NS_ENABLE_IPV6 is defined
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#define closesocket(x) close(x)
|
||||
#define __cdecl
|
||||
#define INVALID_SOCKET (-1)
|
||||
#define to64(x) strtoll(x, NULL, 10)
|
||||
typedef int sock_t;
|
||||
typedef struct stat ns_stat_t;
|
||||
#endif
|
||||
|
||||
#ifdef NS_ENABLE_DEBUG
|
||||
#define DBG(x) do { printf("%-20s ", __func__); printf x; putchar('\n'); \
|
||||
fflush(stdout); } while(0)
|
||||
#else
|
||||
#define DBG(x)
|
||||
#endif
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
|
||||
#endif
|
||||
|
||||
#ifdef NS_ENABLE_SSL
|
||||
#ifdef __APPLE__
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
#include <openssl/ssl.h>
|
||||
#else
|
||||
typedef void *SSL;
|
||||
typedef void *SSL_CTX;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
union socket_address {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sin;
|
||||
#ifdef NS_ENABLE_IPV6
|
||||
struct sockaddr_in6 sin6;
|
||||
#else
|
||||
struct sockaddr sin6;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Describes chunk of memory
|
||||
struct ns_str {
|
||||
const char *p;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
// IO buffers interface
|
||||
struct iobuf {
|
||||
char *buf;
|
||||
size_t len;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
void iobuf_init(struct iobuf *, size_t initial_size);
|
||||
void iobuf_free(struct iobuf *);
|
||||
size_t iobuf_append(struct iobuf *, const void *data, size_t data_size);
|
||||
void iobuf_remove(struct iobuf *, size_t data_size);
|
||||
void iobuf_resize(struct iobuf *, size_t new_size);
|
||||
|
||||
// Callback function (event handler) prototype, must be defined by user.
|
||||
// Net skeleton will call event handler, passing events defined above.
|
||||
struct ns_connection;
|
||||
typedef void (*ns_callback_t)(struct ns_connection *, int event_num, void *evp);
|
||||
|
||||
// Events. Meaning of event parameter (evp) is given in the comment.
|
||||
#define NS_POLL 0 // Sent to each connection on each call to ns_mgr_poll()
|
||||
#define NS_ACCEPT 1 // New connection accept()-ed. union socket_address *addr
|
||||
#define NS_CONNECT 2 // connect() succeeded or failed. int *success_status
|
||||
#define NS_RECV 3 // Data has benn received. int *num_bytes
|
||||
#define NS_SEND 4 // Data has been written to a socket. int *num_bytes
|
||||
#define NS_CLOSE 5 // Connection is closed. NULL
|
||||
|
||||
|
||||
struct ns_mgr {
|
||||
struct ns_connection *active_connections;
|
||||
const char *hexdump_file; // Debug hexdump file path
|
||||
sock_t ctl[2]; // Socketpair for mg_wakeup()
|
||||
void *user_data; // User data
|
||||
};
|
||||
|
||||
|
||||
struct ns_connection {
|
||||
struct ns_connection *next, *prev; // ns_mgr::active_connections linkage
|
||||
struct ns_connection *listener; // Set only for accept()-ed connections
|
||||
struct ns_mgr *mgr;
|
||||
|
||||
sock_t sock; // Socket
|
||||
union socket_address sa; // Peer address
|
||||
struct iobuf recv_iobuf; // Received data
|
||||
struct iobuf send_iobuf; // Data scheduled for sending
|
||||
SSL *ssl;
|
||||
SSL_CTX *ssl_ctx;
|
||||
void *user_data; // User-specific data
|
||||
void *proto_data; // Application protocol-specific data
|
||||
time_t last_io_time; // Timestamp of the last socket IO
|
||||
ns_callback_t callback; // Event handler function
|
||||
|
||||
unsigned int flags;
|
||||
#define NSF_FINISHED_SENDING_DATA (1 << 0)
|
||||
#define NSF_BUFFER_BUT_DONT_SEND (1 << 1)
|
||||
#define NSF_SSL_HANDSHAKE_DONE (1 << 2)
|
||||
#define NSF_CONNECTING (1 << 3)
|
||||
#define NSF_CLOSE_IMMEDIATELY (1 << 4)
|
||||
#define NSF_WANT_READ (1 << 5)
|
||||
#define NSF_WANT_WRITE (1 << 6)
|
||||
#define NSF_LISTENING (1 << 7)
|
||||
#define NSF_UDP (1 << 8)
|
||||
|
||||
#define NSF_USER_1 (1 << 20)
|
||||
#define NSF_USER_2 (1 << 21)
|
||||
#define NSF_USER_3 (1 << 22)
|
||||
#define NSF_USER_4 (1 << 23)
|
||||
#define NSF_USER_5 (1 << 24)
|
||||
#define NSF_USER_6 (1 << 25)
|
||||
};
|
||||
|
||||
void ns_mgr_init(struct ns_mgr *, void *user_data);
|
||||
void ns_mgr_free(struct ns_mgr *);
|
||||
time_t ns_mgr_poll(struct ns_mgr *, int milli);
|
||||
void ns_broadcast(struct ns_mgr *, ns_callback_t, void *, size_t);
|
||||
|
||||
struct ns_connection *ns_next(struct ns_mgr *, struct ns_connection *);
|
||||
struct ns_connection *ns_add_sock(struct ns_mgr *, sock_t,
|
||||
ns_callback_t, void *);
|
||||
struct ns_connection *ns_bind(struct ns_mgr *, const char *,
|
||||
ns_callback_t, void *);
|
||||
struct ns_connection *ns_connect(struct ns_mgr *, const char *,
|
||||
ns_callback_t, void *);
|
||||
|
||||
int ns_send(struct ns_connection *, const void *buf, int len);
|
||||
int ns_printf(struct ns_connection *, const char *fmt, ...);
|
||||
int ns_vprintf(struct ns_connection *, const char *fmt, va_list ap);
|
||||
|
||||
// Utility functions
|
||||
void *ns_start_thread(void *(*f)(void *), void *p);
|
||||
int ns_socketpair(sock_t [2]);
|
||||
int ns_socketpair2(sock_t [2], int sock_type); // SOCK_STREAM or SOCK_DGRAM
|
||||
void ns_set_close_on_exec(sock_t);
|
||||
void ns_sock_to_str(sock_t sock, char *buf, size_t len, int flags);
|
||||
int ns_hexdump(const void *buf, int len, char *dst, int dst_len);
|
||||
int ns_avprintf(char **buf, size_t size, const char *fmt, va_list ap);
|
||||
int ns_resolve(const char *domain_name, char *ip_addr_buf, size_t buf_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // NS_SKELETON_HEADER_INCLUDED
|
123
3rdparty/mongoose/examples/websocket_ssl_proxy/ssl_wrapper.c
vendored
Normal file
123
3rdparty/mongoose/examples/websocket_ssl_proxy/ssl_wrapper.c
vendored
Normal file
@ -0,0 +1,123 @@
|
||||
// Copyright (c) 2014 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// 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
|
||||
// published by the Free Software Foundation. For the terms of this
|
||||
// license, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// You are free to use this software under the terms of the GNU General
|
||||
// Public License, but WITHOUT ANY WARRANTY; without even the implied
|
||||
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the GNU General Public License for more details.
|
||||
//
|
||||
// Alternatively, you can license this software under a commercial
|
||||
// license, as set out in <http://cesanta.com/products.html>.
|
||||
//
|
||||
// $Date$
|
||||
|
||||
#include "net_skeleton.h"
|
||||
#include "ssl_wrapper.h"
|
||||
|
||||
static void ev_handler(struct ns_connection *nc, int ev, void *p) {
|
||||
const char *target_addr = (const char *) nc->mgr->user_data;
|
||||
struct ns_connection *pc = (struct ns_connection *) nc->user_data;
|
||||
struct iobuf *io = &nc->recv_iobuf;
|
||||
|
||||
(void) p;
|
||||
switch (ev) {
|
||||
case NS_ACCEPT:
|
||||
// Create a connection to the target, and interlink both connections
|
||||
nc->user_data = ns_connect(nc->mgr, target_addr, ev_handler, nc);
|
||||
if (nc->user_data == NULL) {
|
||||
nc->flags |= NSF_CLOSE_IMMEDIATELY;
|
||||
}
|
||||
break;
|
||||
|
||||
case NS_CLOSE:
|
||||
// If either connection closes, unlink them and shedule closing
|
||||
if (pc != NULL) {
|
||||
pc->flags |= NSF_FINISHED_SENDING_DATA;
|
||||
pc->user_data = NULL;
|
||||
}
|
||||
nc->user_data = NULL;
|
||||
break;
|
||||
|
||||
case NS_RECV:
|
||||
// Forward arrived data to the other connection, and discard from buffer
|
||||
if (pc != NULL) {
|
||||
ns_send(pc, io->buf, io->len);
|
||||
iobuf_remove(io, io->len);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void *ssl_wrapper_init(const char *local_addr, const char *target_addr,
|
||||
const char **err_msg) {
|
||||
struct ns_mgr *mgr = (struct ns_mgr *) calloc(1, sizeof(mgr[0]));
|
||||
*err_msg = NULL;
|
||||
|
||||
if (mgr == NULL) {
|
||||
*err_msg = "malloc failed";
|
||||
} else {
|
||||
ns_mgr_init(mgr, (void *) target_addr);
|
||||
if (ns_bind(mgr, local_addr, ev_handler, NULL) == NULL) {
|
||||
*err_msg = "ns_bind() failed: bad listening_port";
|
||||
ns_mgr_free(mgr);
|
||||
free(mgr);
|
||||
mgr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return mgr;
|
||||
}
|
||||
|
||||
void ssl_wrapper_serve(void *param, volatile int *quit) {
|
||||
struct ns_mgr *mgr = (struct ns_mgr *) param;
|
||||
|
||||
while (*quit == 0) {
|
||||
ns_mgr_poll(mgr, 1000);
|
||||
}
|
||||
ns_mgr_free(mgr);
|
||||
free(mgr);
|
||||
}
|
||||
|
||||
#ifndef SSL_WRAPPER_USE_AS_LIBRARY
|
||||
static int s_received_signal = 0;
|
||||
|
||||
static void signal_handler(int sig_num) {
|
||||
signal(sig_num, signal_handler);
|
||||
s_received_signal = sig_num;
|
||||
}
|
||||
|
||||
static void show_usage_and_exit(const char *prog) {
|
||||
fprintf(stderr, "Usage: %s <listening_address> <target_address>\n", prog);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
void *wrapper;
|
||||
const char *err_msg;
|
||||
|
||||
if (argc != 3) {
|
||||
show_usage_and_exit(argv[0]);
|
||||
}
|
||||
|
||||
// Setup signal handlers
|
||||
signal(SIGTERM, signal_handler);
|
||||
signal(SIGINT, signal_handler);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
if ((wrapper = ssl_wrapper_init(argv[1], argv[2], &err_msg)) == NULL) {
|
||||
fprintf(stderr, "Error: %s\n", err_msg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
ssl_wrapper_serve(wrapper, &s_received_signal);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
#endif // SSL_WRAPPER_USE_AS_LIBRARY
|
34
3rdparty/mongoose/examples/websocket_ssl_proxy/ssl_wrapper.h
vendored
Normal file
34
3rdparty/mongoose/examples/websocket_ssl_proxy/ssl_wrapper.h
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2014 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// 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
|
||||
// published by the Free Software Foundation. For the terms of this
|
||||
// license, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// You are free to use this software under the terms of the GNU General
|
||||
// Public License, but WITHOUT ANY WARRANTY; without even the implied
|
||||
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the GNU General Public License for more details.
|
||||
//
|
||||
// Alternatively, you can license this software under a commercial
|
||||
// license, as set out in <http://cesanta.com/products.html>.
|
||||
//
|
||||
// $Date$
|
||||
|
||||
#ifndef SSL_WRAPPER_HEADER_INCLUDED
|
||||
#define SSL_WRAPPER_HEADER_INCLUDED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
void *ssl_wrapper_init(const char *listen_addr, const char *target_addr,
|
||||
const char **err_msg);
|
||||
void ssl_wrapper_serve(void *, volatile int *stop_marker);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // SSL_WRAPPER_HEADER_INCLUDED
|
182
3rdparty/mongoose/examples/websocket_ssl_proxy/ws_ssl.c
vendored
Normal file
182
3rdparty/mongoose/examples/websocket_ssl_proxy/ws_ssl.c
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
// Copyright (c) 2014 Cesanta Software
|
||||
// All rights reserved
|
||||
//
|
||||
// This example demostrates proxying of WebSocket traffic, regardless of the
|
||||
// protocol (ws:// or wss://).
|
||||
// To use this example:
|
||||
// 1. configure your browser to use a proxy on port 2014
|
||||
// 2. import certs/ws1_ca.pem and certs/ws2_ca.pem into the trusted
|
||||
// certificates list on your browser
|
||||
// 3. make && ./ws_ssl
|
||||
// 4. Point your browser to http://ws_ssl.com
|
||||
// A page with 4 sections should appear, showing websocket echoes
|
||||
|
||||
#include "net_skeleton.h"
|
||||
#include "mongoose.h"
|
||||
#include "ssl_wrapper.h"
|
||||
|
||||
#define S1_PEM "certs/ws1_server.pem"
|
||||
#define C1_PEM "certs/ws1_client.pem"
|
||||
#define CA1_PEM "certs/ws1_ca.pem"
|
||||
#define S2_PEM "certs/ws2_server.pem"
|
||||
#define C2_PEM "certs/ws2_client.pem"
|
||||
#define CA2_PEM "certs/ws2_ca.pem"
|
||||
|
||||
struct config {
|
||||
const char *uri;
|
||||
const char *wrapper_server_addr;
|
||||
const char *wrapper_client_addr;
|
||||
const char *target_addr;
|
||||
};
|
||||
|
||||
static struct config s_wrappers[] = {
|
||||
{
|
||||
"ws1:80",
|
||||
"tcp://127.0.0.1:7001",
|
||||
"tcp://127.0.0.1:7001",
|
||||
"tcp://127.0.0.1:9001"
|
||||
},
|
||||
{
|
||||
"ws1:443",
|
||||
"ssl://127.0.0.1:7002:" S1_PEM,
|
||||
"tcp://127.0.0.1:7002",
|
||||
"tcp://127.0.0.1:9001"
|
||||
},
|
||||
{
|
||||
"ws2:80",
|
||||
"tcp://127.0.0.1:7003",
|
||||
"tcp://127.0.0.1:7003",
|
||||
"ssl://127.0.0.1:9002:" C2_PEM ":" CA2_PEM
|
||||
},
|
||||
{
|
||||
"ws2:443",
|
||||
"ssl://127.0.0.1:7004:" S2_PEM,
|
||||
"tcp://127.0.0.1:7004",
|
||||
"ssl://127.0.0.1:9002:" C2_PEM ":" CA2_PEM
|
||||
},
|
||||
};
|
||||
|
||||
static int s_received_signal = 0;
|
||||
|
||||
static void signal_handler(int sig_num) {
|
||||
signal(sig_num, signal_handler);
|
||||
s_received_signal = sig_num;
|
||||
}
|
||||
|
||||
static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||
int i;
|
||||
|
||||
switch (ev) {
|
||||
case MG_AUTH:
|
||||
return MG_TRUE;
|
||||
|
||||
case MG_REQUEST:
|
||||
printf("==> [%s] [%s]\n", conn->request_method, conn->uri);
|
||||
|
||||
if (strcmp(conn->request_method, "CONNECT") == 0) {
|
||||
// Iterate over configured wrappers, see if we can use one of them
|
||||
for (i = 0; i < (int) ARRAY_SIZE(s_wrappers); i++) {
|
||||
if (strcmp(conn->uri, s_wrappers[i].uri) == 0) {
|
||||
mg_forward(conn, s_wrappers[i].wrapper_client_addr);
|
||||
return MG_MORE;
|
||||
}
|
||||
}
|
||||
|
||||
// No suitable wrappers found. Disallow that CONNECT request.
|
||||
mg_send_status(conn, 405);
|
||||
return MG_TRUE;
|
||||
}
|
||||
|
||||
// Not a CONNECT request, serve HTML file.
|
||||
mg_send_file(conn, "ws_ssl.html", NULL);
|
||||
return MG_MORE;
|
||||
|
||||
default:
|
||||
return MG_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static int ws_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||
switch (ev) {
|
||||
case MG_AUTH:
|
||||
return MG_TRUE;
|
||||
case MG_REQUEST:
|
||||
if (conn->is_websocket) {
|
||||
// Simple websocket echo server
|
||||
mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT,
|
||||
conn->content, conn->content_len);
|
||||
} else {
|
||||
mg_printf_data(conn, "%s", "websocket connection expected");
|
||||
}
|
||||
return MG_TRUE;
|
||||
default:
|
||||
return MG_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void *serve_thread_func(void *param) {
|
||||
struct mg_server *server = (struct mg_server *) param;
|
||||
printf("Listening on port %s\n", mg_get_option(server, "listening_port"));
|
||||
while (s_received_signal == 0) {
|
||||
mg_poll_server(server, 1000);
|
||||
}
|
||||
mg_destroy_server(&server);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *wrapper_thread_func(void *param) {
|
||||
struct config *c = (struct config *) param;
|
||||
const char *err_msg;
|
||||
void *wrapper;
|
||||
|
||||
wrapper = ssl_wrapper_init(c->wrapper_server_addr, c->target_addr, &err_msg);
|
||||
if (wrapper == NULL) {
|
||||
fprintf(stderr, "Error: %s\n", err_msg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
//((struct ns_mgr *) wrapper)->hexdump_file = "/dev/stderr";
|
||||
ssl_wrapper_serve(wrapper, &s_received_signal);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
struct mg_server *proxy_server = mg_create_server(NULL, ev_handler);
|
||||
struct mg_server *ws1_server = mg_create_server(NULL, ws_handler);
|
||||
struct mg_server *ws2_server = mg_create_server(NULL, ws_handler);
|
||||
size_t i;
|
||||
|
||||
((struct ns_mgr *) proxy_server)->hexdump_file = "/dev/stderr";
|
||||
|
||||
// Configure proxy server to listen on port 2014
|
||||
mg_set_option(proxy_server, "listening_port", "2014");
|
||||
//mg_set_option(proxy_server, "enable_proxy", "yes");
|
||||
|
||||
// Configure two websocket echo servers:
|
||||
// ws1 is WS, listening on 9001
|
||||
// ws2 is WSS, listening on 9002
|
||||
// Note that HTML page thinks that ws1 is WSS, and ws2 is WS,
|
||||
// where in reality it is vice versa and proxy server makes the decision.
|
||||
mg_set_option(ws1_server, "listening_port", "tcp://127.0.0.1:9001");
|
||||
mg_set_option(ws2_server, "listening_port",
|
||||
"ssl://127.0.0.1:9002:" S2_PEM ":" CA2_PEM);
|
||||
|
||||
// Setup signal handlers
|
||||
signal(SIGTERM, signal_handler);
|
||||
signal(SIGINT, signal_handler);
|
||||
|
||||
// Start SSL wrappers, each in it's own thread
|
||||
for (i = 0; i < ARRAY_SIZE(s_wrappers); i++) {
|
||||
ns_start_thread(wrapper_thread_func, &s_wrappers[i]);
|
||||
}
|
||||
|
||||
// Start websocket servers in separate threads
|
||||
mg_start_thread(serve_thread_func, ws1_server);
|
||||
mg_start_thread(serve_thread_func, ws2_server);
|
||||
|
||||
// Finally, start proxy server in this thread: this call blocks
|
||||
serve_thread_func(proxy_server);
|
||||
|
||||
printf("Existing on signal %d\n", s_received_signal);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
50
3rdparty/mongoose/examples/websocket_ssl_proxy/ws_ssl.html
vendored
Normal file
50
3rdparty/mongoose/examples/websocket_ssl_proxy/ws_ssl.html
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Websocket Proxy SSL Test</title>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
window.onload = function() {
|
||||
var protocols = ['ws://', 'wss://'];
|
||||
var websocketServers = ['ws1', 'ws2'];
|
||||
//protocols = ['wss://'];
|
||||
//websocketServers = ['ws1']
|
||||
|
||||
var createWebsocketConnection = function(proto, server) {
|
||||
var conn = new WebSocket(proto + server);
|
||||
|
||||
var div = document.createElement('div');
|
||||
var h2 = document.createElement('h2');
|
||||
h2.innerHTML = 'Connection to ' + proto + server;
|
||||
document.body.appendChild(h2);
|
||||
document.body.appendChild(div);
|
||||
|
||||
conn.onmessage = function(ev) {
|
||||
var el = document.createElement('div');
|
||||
el.innerHTML = 'websocket message: ' + ev.data;
|
||||
div.appendChild(el);
|
||||
// Keep only last 5 messages in the list
|
||||
while (div.childNodes.length > 5) div.removeChild(div.firstChild);
|
||||
};
|
||||
|
||||
// Send some string to the websocket connection periodically.
|
||||
// websocket server much echo it back.
|
||||
window.setInterval(function() { conn.send(Math.random()); }, 1000);
|
||||
};
|
||||
|
||||
for (var i = 0; i < protocols.length; i++) {
|
||||
for (var j = 0; j < websocketServers.length; j++) {
|
||||
createWebsocketConnection(protocols[i], websocketServers[j]);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
body > div {
|
||||
border: 1px solid #ccc; background: #f0f0f0; padding: 0 1em;
|
||||
margin: 0 2em; min-height: 4em; max-width: 40em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
8
3rdparty/mongoose/jni/Android.mk
vendored
Normal file
8
3rdparty/mongoose/jni/Android.mk
vendored
Normal file
@ -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)
|
5287
3rdparty/mongoose/mongoose.c
vendored
Normal file
5287
3rdparty/mongoose/mongoose.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,25 +2,23 @@
|
||||
// Copyright (c) 2013-2014 Cesanta Software Limited
|
||||
// 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
|
||||
// published by the Free Software Foundation. For the terms of this
|
||||
// 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
|
||||
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// 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/>.
|
||||
//
|
||||
// $Date: 2014-09-01 19:53:26 UTC $
|
||||
|
||||
#ifndef MONGOOSE_HEADER_INCLUDED
|
||||
#define MONGOOSE_HEADER_INCLUDED
|
||||
|
||||
#define MONGOOSE_VERSION "5.4"
|
||||
#define MONGOOSE_VERSION "5.6"
|
||||
|
||||
#include <stdio.h> // required for FILE
|
||||
#include <stddef.h> // required for size_t
|
||||
@ -31,59 +29,59 @@ extern "C" {
|
||||
|
||||
// This structure contains information about HTTP request.
|
||||
struct mg_connection {
|
||||
const char *request_method; // "GET", "POST", etc
|
||||
const char *uri; // URL-decoded URI
|
||||
const char *http_version; // E.g. "1.0", "1.1"
|
||||
const char *query_string; // URL part after '?', not including '?', or NULL
|
||||
const char *request_method; // "GET", "POST", etc
|
||||
const char *uri; // URL-decoded URI
|
||||
const char *http_version; // E.g. "1.0", "1.1"
|
||||
const char *query_string; // URL part after '?', not including '?', or NULL
|
||||
|
||||
char remote_ip[48]; // Max IPv6 string length is 45 characters
|
||||
char local_ip[48]; // Local IP address
|
||||
unsigned short remote_port; // Client's port
|
||||
unsigned short local_port; // Local port number
|
||||
char remote_ip[48]; // Max IPv6 string length is 45 characters
|
||||
char local_ip[48]; // Local IP address
|
||||
unsigned short remote_port; // Client's port
|
||||
unsigned short local_port; // Local port number
|
||||
|
||||
int num_headers; // Number of HTTP headers
|
||||
struct mg_header {
|
||||
const char *name; // HTTP header name
|
||||
const char *value; // HTTP header value
|
||||
} http_headers[30];
|
||||
int num_headers; // Number of HTTP headers
|
||||
struct mg_header {
|
||||
const char *name; // HTTP header name
|
||||
const char *value; // HTTP header value
|
||||
} http_headers[30];
|
||||
|
||||
char *content; // POST (or websocket message) data, or NULL
|
||||
size_t content_len; // Data length
|
||||
char *content; // POST (or websocket message) data, or NULL
|
||||
size_t content_len; // Data length
|
||||
|
||||
int is_websocket; // Connection is a websocket connection
|
||||
int status_code; // HTTP status code for HTTP error handler
|
||||
int wsbits; // First byte of the websocket frame
|
||||
void *server_param; // Parameter passed to mg_add_uri_handler()
|
||||
void *connection_param; // Placeholder for connection-specific data
|
||||
void *callback_param; // Needed by mg_iterate_over_connections()
|
||||
int is_websocket; // Connection is a websocket connection
|
||||
int status_code; // HTTP status code for HTTP error handler
|
||||
int wsbits; // First byte of the websocket frame
|
||||
void *server_param; // Parameter passed to mg_create_server()
|
||||
void *connection_param; // Placeholder for connection-specific data
|
||||
void *callback_param;
|
||||
};
|
||||
|
||||
struct mg_server; // Opaque structure describing server instance
|
||||
enum mg_result { MG_FALSE, MG_TRUE, MG_MORE };
|
||||
enum mg_event {
|
||||
MG_POLL = 100, // Callback return value is ignored
|
||||
MG_CONNECT, // If callback returns MG_FALSE, connect fails
|
||||
MG_AUTH, // If callback returns MG_FALSE, authentication fails
|
||||
MG_REQUEST, // If callback returns MG_FALSE, Mongoose continues with req
|
||||
MG_REPLY, // If callback returns MG_FALSE, Mongoose closes connection
|
||||
MG_RECV, // Mongoose has received POST data chunk.
|
||||
// Callback should return a number of bytes to discard from
|
||||
// the receive buffer, or -1 to close the connection.
|
||||
MG_CLOSE, // Connection is closed, callback return value is ignored
|
||||
MG_WS_HANDSHAKE, // New websocket connection, handshake request
|
||||
MG_WS_CONNECT, // New websocket connection established
|
||||
MG_HTTP_ERROR // If callback returns MG_FALSE, Mongoose continues with err
|
||||
MG_POLL = 100, // Callback return value is ignored
|
||||
MG_CONNECT, // If callback returns MG_FALSE, connect fails
|
||||
MG_AUTH, // If callback returns MG_FALSE, authentication fails
|
||||
MG_REQUEST, // If callback returns MG_FALSE, Mongoose continues with req
|
||||
MG_REPLY, // If callback returns MG_FALSE, Mongoose closes connection
|
||||
MG_RECV, // Mongoose has received POST data chunk.
|
||||
// Callback should return a number of bytes to discard from
|
||||
// the receive buffer, or -1 to close the connection.
|
||||
MG_CLOSE, // Connection is closed, callback return value is ignored
|
||||
MG_WS_HANDSHAKE, // New websocket connection, handshake request
|
||||
MG_WS_CONNECT, // New websocket connection established
|
||||
MG_HTTP_ERROR // If callback returns MG_FALSE, Mongoose continues with err
|
||||
};
|
||||
typedef int (*mg_handler_t)(struct mg_connection *, enum mg_event);
|
||||
|
||||
// Websocket opcodes, from http://tools.ietf.org/html/rfc6455
|
||||
enum {
|
||||
WEBSOCKET_OPCODE_CONTINUATION = 0x0,
|
||||
WEBSOCKET_OPCODE_TEXT = 0x1,
|
||||
WEBSOCKET_OPCODE_BINARY = 0x2,
|
||||
WEBSOCKET_OPCODE_CONNECTION_CLOSE = 0x8,
|
||||
WEBSOCKET_OPCODE_PING = 0x9,
|
||||
WEBSOCKET_OPCODE_PONG = 0xa
|
||||
WEBSOCKET_OPCODE_CONTINUATION = 0x0,
|
||||
WEBSOCKET_OPCODE_TEXT = 0x1,
|
||||
WEBSOCKET_OPCODE_BINARY = 0x2,
|
||||
WEBSOCKET_OPCODE_CONNECTION_CLOSE = 0x8,
|
||||
WEBSOCKET_OPCODE_PING = 0x9,
|
||||
WEBSOCKET_OPCODE_PONG = 0xa
|
||||
};
|
||||
|
||||
// Server management functions
|
||||
@ -93,13 +91,11 @@ const char *mg_set_option(struct mg_server *, const char *opt, const char *val);
|
||||
int mg_poll_server(struct mg_server *, int milliseconds);
|
||||
const char **mg_get_valid_option_names(void);
|
||||
const char *mg_get_option(const struct mg_server *server, const char *name);
|
||||
void mg_set_listening_socket(struct mg_server *, int sock);
|
||||
int mg_get_listening_socket(struct mg_server *);
|
||||
void mg_iterate_over_connections(struct mg_server *, mg_handler_t, void *);
|
||||
void mg_copy_listeners(struct mg_server *from, struct mg_server *to);
|
||||
struct mg_connection *mg_next(struct mg_server *, struct mg_connection *);
|
||||
void mg_wakeup_server(struct mg_server *);
|
||||
void mg_wakeup_server_ex(struct mg_server *, mg_handler_t, const char *, ...);
|
||||
struct mg_connection *mg_connect(struct mg_server *, const char *, int, int);
|
||||
struct mg_connection *mg_connect(struct mg_server *, const char *);
|
||||
|
||||
// Connection management functions
|
||||
void mg_send_status(struct mg_connection *, int status_code);
|
||||
@ -110,22 +106,23 @@ size_t mg_write(struct mg_connection *, const void *buf, int len);
|
||||
size_t mg_printf(struct mg_connection *conn, const char *fmt, ...);
|
||||
|
||||
size_t mg_websocket_write(struct mg_connection *, int opcode,
|
||||
const char *data, size_t data_len);
|
||||
const char *data, size_t data_len);
|
||||
size_t mg_websocket_printf(struct mg_connection* conn, int opcode,
|
||||
const char *fmt, ...);
|
||||
const char *fmt, ...);
|
||||
|
||||
void mg_send_file(struct mg_connection *, const char *path);
|
||||
void mg_send_file(struct mg_connection *, const char *path, const char *);
|
||||
void mg_send_file_data(struct mg_connection *, int fd);
|
||||
|
||||
const char *mg_get_header(const struct mg_connection *, const char *name);
|
||||
const char *mg_get_mime_type(const char *name, const char *default_mime_type);
|
||||
int mg_get_var(const struct mg_connection *conn, const char *var_name,
|
||||
char *buf, size_t buf_len);
|
||||
char *buf, size_t buf_len);
|
||||
int mg_parse_header(const char *hdr, const char *var_name, char *buf, size_t);
|
||||
int mg_parse_multipart(const char *buf, int buf_len,
|
||||
char *var_name, int var_name_len,
|
||||
char *file_name, int file_name_len,
|
||||
const char **data, int *data_len);
|
||||
char *var_name, int var_name_len,
|
||||
char *file_name, int file_name_len,
|
||||
const char **data, int *data_len);
|
||||
|
||||
|
||||
// Utility functions
|
||||
void *mg_start_thread(void *(*func)(void *), void *param);
|
||||
@ -134,19 +131,18 @@ 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);
|
||||
int mg_url_decode(const char *src, int src_len, char *dst, int dst_len, int);
|
||||
int mg_terminate_ssl(struct mg_connection *c, const char *cert);
|
||||
int mg_forward(struct mg_connection *, const char *host, int port, int use_ssl);
|
||||
int mg_forward(struct mg_connection *c, const char *addr);
|
||||
void *mg_mmap(FILE *fp, size_t size);
|
||||
void mg_munmap(void *p, size_t size);
|
||||
|
||||
|
||||
// Templates support
|
||||
struct mg_expansion {
|
||||
const char *keyword;
|
||||
void (*handler)(struct mg_connection *);
|
||||
const char *keyword;
|
||||
void (*handler)(struct mg_connection *);
|
||||
};
|
||||
void mg_template(struct mg_connection *, const char *text,
|
||||
struct mg_expansion *expansions);
|
||||
|
||||
struct mg_expansion *expansions);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
53
3rdparty/mongoose/scripts/embed_binary_files.pl
vendored
Normal file
53
3rdparty/mongoose/scripts/embed_binary_files.pl
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
# This program is used to embed arbitrary data into a C binary. It takes
|
||||
# a list of files as an input, and produces a .c data file that contains
|
||||
# contents of all these files as collection of char arrays.
|
||||
#
|
||||
# Usage: perl <this_file> <file1> [file2, ...] > embedded_data.c
|
||||
|
||||
foreach my $i (0 .. $#ARGV) {
|
||||
open FD, '<:raw', $ARGV[$i] or die "Cannot open $ARGV[$i]: $!\n";
|
||||
printf("static const unsigned char v%d[] = {", $i);
|
||||
my $byte;
|
||||
my $j = 0;
|
||||
while (read(FD, $byte, 1)) {
|
||||
if (($j % 12) == 0) {
|
||||
print "\n";
|
||||
}
|
||||
printf ' %#04x,', ord($byte);
|
||||
$j++;
|
||||
}
|
||||
print " 0x00\n};\n";
|
||||
close FD;
|
||||
}
|
||||
|
||||
print <<EOS;
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
static const struct embedded_file {
|
||||
const char *name;
|
||||
const unsigned char *data;
|
||||
size_t size;
|
||||
} embedded_files[] = {
|
||||
EOS
|
||||
|
||||
foreach my $i (0 .. $#ARGV) {
|
||||
print " {\"$ARGV[$i]\", v$i, sizeof(v$i) - 1},\n";
|
||||
}
|
||||
|
||||
print <<EOS;
|
||||
{NULL, NULL, 0}
|
||||
};
|
||||
|
||||
const char *find_embedded_file(const char *name, size_t *size) {
|
||||
const struct embedded_file *p;
|
||||
for (p = embedded_files; p->name != NULL; p++) {
|
||||
if (!strcmp(p->name, name)) {
|
||||
if (size != NULL) { *size = p->size; }
|
||||
return (const char *) p->data;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
EOS
|
21
3rdparty/mongoose/test/Makefile
vendored
Normal file
21
3rdparty/mongoose/test/Makefile
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# Copyright (c) 2014 Cesanta Software
|
||||
# All rights reserved
|
||||
|
||||
PROG = unit_test
|
||||
PROF_FLAGS = -fprofile-arcs -ftest-coverage -g -O0 -DGUI
|
||||
CFLAGS = -W -Wall -pthread -I.. $(PROF_FLAGS) $(CFLAGS_EXTRA)
|
||||
SOURCES = $(PROG).c
|
||||
|
||||
all: $(PROG)
|
||||
./$(PROG)
|
||||
gcov -b $(PROG).c | egrep '^(File|Lines)'
|
||||
|
||||
$(PROG): $(SOURCES) Makefile ../mongoose.c clean
|
||||
$(CC) -o $(PROG) $(SOURCES) $(CFLAGS) -ldl -lssl
|
||||
|
||||
win:
|
||||
wine cl $(SOURCES) /MD /nologo /DNDEBUG /O1 /Fe$(PROG).exe
|
||||
wine $(PROG).exe
|
||||
|
||||
clean:
|
||||
rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib *.gc*
|
530
3rdparty/mongoose/test/unit_test.c
vendored
Normal file
530
3rdparty/mongoose/test/unit_test.c
vendored
Normal file
@ -0,0 +1,530 @@
|
||||
// Unit test for the mongoose web server.
|
||||
// g++ -W -Wall -pedantic -g unit_test.c -lssl && ./a.out
|
||||
// cl unit_test.c /MD
|
||||
|
||||
#ifndef _WIN32
|
||||
#define NS_ENABLE_IPV6
|
||||
#define NS_ENABLE_SSL
|
||||
#endif
|
||||
#define MONGOOSE_POST_SIZE_LIMIT 999
|
||||
|
||||
// USE_* definitions must be made before #include "mongoose.c" !
|
||||
#include "../mongoose.c"
|
||||
|
||||
#define FAIL(str, line) do { \
|
||||
printf("Fail on line %d: [%s]\n", line, str); \
|
||||
return str; \
|
||||
} while (0)
|
||||
|
||||
#define ASSERT(expr) do { \
|
||||
static_num_tests++; \
|
||||
if (!(expr)) FAIL(#expr, __LINE__); \
|
||||
} while (0)
|
||||
|
||||
#define RUN_TEST(test) do { const char *msg = test(); \
|
||||
if (msg) return msg; } while (0)
|
||||
|
||||
#define HTTP_PORT "45772"
|
||||
#define LISTENING_ADDR "127.0.0.1:" HTTP_PORT
|
||||
|
||||
static int static_num_tests = 0;
|
||||
|
||||
#if 0
|
||||
// Connects to host:port, and sends formatted request to it. Returns
|
||||
// malloc-ed reply and reply length, or NULL on error. Reply contains
|
||||
// everything including headers, not just the message body.
|
||||
static char *wget(const char *host, int port, int *len, const char *fmt, ...) {
|
||||
char buf[2000], *reply = NULL;
|
||||
int request_len, reply_size = 0, n, sock = -1;
|
||||
struct sockaddr_in sin;
|
||||
struct hostent *he = NULL;
|
||||
va_list ap;
|
||||
|
||||
if (host != NULL &&
|
||||
(he = gethostbyname(host)) != NULL &&
|
||||
(sock = socket(PF_INET, SOCK_STREAM, 0)) != -1) {
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons((uint16_t) port);
|
||||
sin.sin_addr = * (struct in_addr *) he->h_addr_list[0];
|
||||
if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) == 0) {
|
||||
|
||||
// Format and send the request.
|
||||
va_start(ap, fmt);
|
||||
request_len = vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
while (request_len > 0 && (n = send(sock, buf, request_len, 0)) > 0) {
|
||||
request_len -= n;
|
||||
}
|
||||
if (request_len == 0) {
|
||||
*len = 0;
|
||||
while ((n = recv(sock, buf, sizeof(buf), 0)) > 0) {
|
||||
if (*len + n > reply_size) {
|
||||
// Leak possible
|
||||
reply = (char *) realloc(reply, reply_size + sizeof(buf));
|
||||
reply_size += sizeof(buf);
|
||||
}
|
||||
if (reply != NULL) {
|
||||
memcpy(reply + *len, buf, n);
|
||||
*len += n;
|
||||
}
|
||||
}
|
||||
}
|
||||
closesocket(sock);
|
||||
}
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
#endif
|
||||
|
||||
static char *read_file(const char *path, int *size) {
|
||||
FILE *fp;
|
||||
struct stat st;
|
||||
char *data = NULL;
|
||||
if ((fp = fopen(path, "rb")) != NULL && !fstat(fileno(fp), &st)) {
|
||||
*size = (int) st.st_size;
|
||||
data = (char *) malloc(*size);
|
||||
fread(data, 1, *size, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
static const char *test_parse_http_message() {
|
||||
struct mg_connection ri;
|
||||
char req1[] = "GET / HTTP/1.1\r\n\r\n";
|
||||
char req2[] = "BLAH / HTTP/1.1\r\n\r\n";
|
||||
char req3[] = "GET / HTTP/1.1\r\nBah\r\n";
|
||||
char req4[] = "GET / HTTP/1.1\r\nA: foo bar\r\nB: bar\r\nbaz\r\n\r\n";
|
||||
char req5[] = "GET / HTTP/1.1\r\n\r\n";
|
||||
char req6[] = "G";
|
||||
char req7[] = " blah ";
|
||||
char req8[] = " HTTP/1.1 200 OK \n\n";
|
||||
char req9[] = "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n";
|
||||
|
||||
ASSERT(get_request_len("\r\n", 3) == -1);
|
||||
ASSERT(get_request_len("\r\n", 2) == 0);
|
||||
ASSERT(get_request_len("GET", 3) == 0);
|
||||
ASSERT(get_request_len("\n\n", 2) == 2);
|
||||
ASSERT(get_request_len("\n\r\n", 3) == 3);
|
||||
ASSERT(get_request_len("\xdd\xdd", 2) == 0);
|
||||
ASSERT(get_request_len("\xdd\x03", 2) == -1);
|
||||
ASSERT(get_request_len(req3, sizeof(req3) - 1) == 0);
|
||||
ASSERT(get_request_len(req6, sizeof(req6) - 1) == 0);
|
||||
ASSERT(get_request_len(req7, sizeof(req7) - 1) == 0);
|
||||
|
||||
ASSERT(parse_http_message(req9, sizeof(req9) - 1, &ri) == sizeof(req9) - 1);
|
||||
ASSERT(ri.num_headers == 1);
|
||||
|
||||
ASSERT(parse_http_message(req1, sizeof(req1) - 1, &ri) == sizeof(req1) - 1);
|
||||
ASSERT(strcmp(ri.http_version, "1.1") == 0);
|
||||
ASSERT(ri.num_headers == 0);
|
||||
|
||||
ASSERT(parse_http_message(req2, sizeof(req2) - 1, &ri) == -1);
|
||||
ASSERT(parse_http_message(req6, 0, &ri) == -1);
|
||||
ASSERT(parse_http_message(req8, sizeof(req8) - 1, &ri) == sizeof(req8) - 1);
|
||||
|
||||
// TODO(lsm): Fix this. Header value may span multiple lines.
|
||||
ASSERT(parse_http_message(req4, sizeof(req4) - 1, &ri) == sizeof(req4) - 1);
|
||||
ASSERT(strcmp(ri.http_version, "1.1") == 0);
|
||||
ASSERT(ri.num_headers == 3);
|
||||
ASSERT(strcmp(ri.http_headers[0].name, "A") == 0);
|
||||
ASSERT(strcmp(ri.http_headers[0].value, "foo bar") == 0);
|
||||
ASSERT(strcmp(ri.http_headers[1].name, "B") == 0);
|
||||
ASSERT(strcmp(ri.http_headers[1].value, "bar") == 0);
|
||||
ASSERT(strcmp(ri.http_headers[2].name, "baz\r\n\r") == 0);
|
||||
ASSERT(strcmp(ri.http_headers[2].value, "") == 0);
|
||||
|
||||
ASSERT(parse_http_message(req5, sizeof(req5) - 1, &ri) == sizeof(req5) - 1);
|
||||
ASSERT(strcmp(ri.request_method, "GET") == 0);
|
||||
ASSERT(strcmp(ri.http_version, "1.1") == 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *test_should_keep_alive(void) {
|
||||
struct mg_connection conn;
|
||||
char req1[] = "GET / HTTP/1.1\r\n\r\n";
|
||||
char req2[] = "GET / HTTP/1.0\r\n\r\n";
|
||||
char req3[] = "GET / HTTP/1.1\r\nConnection: close\r\n\r\n";
|
||||
char req4[] = "GET / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n";
|
||||
|
||||
memset(&conn, 0, sizeof(conn));
|
||||
ASSERT(parse_http_message(req1, sizeof(req1) - 1, &conn) == sizeof(req1) - 1);
|
||||
ASSERT(should_keep_alive(&conn) != 0);
|
||||
|
||||
parse_http_message(req2, sizeof(req2) - 1, &conn);
|
||||
ASSERT(should_keep_alive(&conn) == 0);
|
||||
|
||||
parse_http_message(req3, sizeof(req3) - 1, &conn);
|
||||
ASSERT(should_keep_alive(&conn) == 0);
|
||||
|
||||
parse_http_message(req4, sizeof(req4) - 1, &conn);
|
||||
ASSERT(should_keep_alive(&conn) != 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *test_match_prefix(void) {
|
||||
ASSERT(mg_match_prefix("/api", 4, "/api") == 4);
|
||||
ASSERT(mg_match_prefix("/a/", 3, "/a/b/c") == 3);
|
||||
ASSERT(mg_match_prefix("/a/", 3, "/ab/c") == -1);
|
||||
ASSERT(mg_match_prefix("/*/", 3, "/ab/c") == 4);
|
||||
ASSERT(mg_match_prefix("**", 2, "/a/b/c") == 6);
|
||||
ASSERT(mg_match_prefix("/*", 2, "/a/b/c") == 2);
|
||||
ASSERT(mg_match_prefix("*/*", 3, "/a/b/c") == 2);
|
||||
ASSERT(mg_match_prefix("**/", 3, "/a/b/c") == 5);
|
||||
ASSERT(mg_match_prefix("**.foo|**.bar", 13, "a.bar") == 5);
|
||||
ASSERT(mg_match_prefix("a|b|cd", 6, "cdef") == 2);
|
||||
ASSERT(mg_match_prefix("a|b|c?", 6, "cdef") == 2);
|
||||
ASSERT(mg_match_prefix("a|?|cd", 6, "cdef") == 1);
|
||||
ASSERT(mg_match_prefix("/a/**.cgi", 9, "/foo/bar/x.cgi") == -1);
|
||||
ASSERT(mg_match_prefix("/a/**.cgi", 9, "/a/bar/x.cgi") == 12);
|
||||
ASSERT(mg_match_prefix("**/", 3, "/a/b/c") == 5);
|
||||
ASSERT(mg_match_prefix("**/$", 4, "/a/b/c") == -1);
|
||||
ASSERT(mg_match_prefix("**/$", 4, "/a/b/") == 5);
|
||||
ASSERT(mg_match_prefix("$", 1, "") == 0);
|
||||
ASSERT(mg_match_prefix("$", 1, "x") == -1);
|
||||
ASSERT(mg_match_prefix("*$", 2, "x") == 1);
|
||||
ASSERT(mg_match_prefix("/$", 2, "/") == 1);
|
||||
ASSERT(mg_match_prefix("**/$", 4, "/a/b/c") == -1);
|
||||
ASSERT(mg_match_prefix("**/$", 4, "/a/b/") == 5);
|
||||
ASSERT(mg_match_prefix("*", 1, "/hello/") == 0);
|
||||
ASSERT(mg_match_prefix("**.a$|**.b$", 11, "/a/b.b/") == -1);
|
||||
ASSERT(mg_match_prefix("**.a$|**.b$", 11, "/a/b.b") == 6);
|
||||
ASSERT(mg_match_prefix("**.a$|**.b$", 11, "/a/B.A") == 6);
|
||||
ASSERT(mg_match_prefix("**o$", 4, "HELLO") == 5);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *test_remove_double_dots() {
|
||||
struct { char before[20], after[20]; } data[] = {
|
||||
{"////a", "/a"},
|
||||
{"/.....", "/."},
|
||||
{"/......", "/"},
|
||||
{"...", "..."},
|
||||
{"/...///", "/./"},
|
||||
{"/a...///", "/a.../"},
|
||||
{"/.x", "/.x"},
|
||||
{"/\\", "/"},
|
||||
{"/a\\", "/a\\"},
|
||||
{"/a\\\\...", "/a\\."},
|
||||
};
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(data); i++) {
|
||||
remove_double_dots_and_double_slashes(data[i].before);
|
||||
ASSERT(strcmp(data[i].before, data[i].after) == 0);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *test_get_var(void) {
|
||||
static const char *post[] = {
|
||||
"a=1&&b=2&d&=&c=3%20&e=",
|
||||
"q=&st=2012%2F11%2F13+17%3A05&et=&team_id=",
|
||||
NULL
|
||||
};
|
||||
char buf[20];
|
||||
|
||||
ASSERT(get_var(post[0], strlen(post[0]), "a", buf, sizeof(buf)) == 1);
|
||||
ASSERT(buf[0] == '1' && buf[1] == '\0');
|
||||
ASSERT(get_var(post[0], strlen(post[0]), "b", buf, sizeof(buf)) == 1);
|
||||
ASSERT(buf[0] == '2' && buf[1] == '\0');
|
||||
ASSERT(get_var(post[0], strlen(post[0]), "c", buf, sizeof(buf)) == 2);
|
||||
ASSERT(buf[0] == '3' && buf[1] == ' ' && buf[2] == '\0');
|
||||
ASSERT(get_var(post[0], strlen(post[0]), "e", buf, sizeof(buf)) == 0);
|
||||
ASSERT(buf[0] == '\0');
|
||||
|
||||
ASSERT(get_var(post[0], strlen(post[0]), "d", buf, sizeof(buf)) == -1);
|
||||
ASSERT(get_var(post[0], strlen(post[0]), "c", buf, 2) == -2);
|
||||
|
||||
ASSERT(get_var(post[0], strlen(post[0]), "x", NULL, 10) == -2);
|
||||
ASSERT(get_var(post[0], strlen(post[0]), "x", buf, 0) == -2);
|
||||
ASSERT(get_var(post[1], strlen(post[1]), "st", buf, 16) == -2);
|
||||
ASSERT(get_var(post[1], strlen(post[1]), "st", buf, 17) == 16);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *test_url_decode(void) {
|
||||
char buf[100];
|
||||
|
||||
ASSERT(mg_url_decode("foo", 3, buf, 3, 0) == -1); // No space for \0
|
||||
ASSERT(mg_url_decode("foo", 3, buf, 4, 0) == 3);
|
||||
ASSERT(strcmp(buf, "foo") == 0);
|
||||
|
||||
ASSERT(mg_url_decode("a+", 2, buf, sizeof(buf), 0) == 2);
|
||||
ASSERT(strcmp(buf, "a+") == 0);
|
||||
|
||||
ASSERT(mg_url_decode("a+", 2, buf, sizeof(buf), 1) == 2);
|
||||
ASSERT(strcmp(buf, "a ") == 0);
|
||||
|
||||
ASSERT(mg_url_decode("%61", 1, buf, sizeof(buf), 1) == 1);
|
||||
ASSERT(strcmp(buf, "%") == 0);
|
||||
|
||||
ASSERT(mg_url_decode("%61", 2, buf, sizeof(buf), 1) == 2);
|
||||
ASSERT(strcmp(buf, "%6") == 0);
|
||||
|
||||
ASSERT(mg_url_decode("%61", 3, buf, sizeof(buf), 1) == 1);
|
||||
ASSERT(strcmp(buf, "a") == 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *test_url_encode(void) {
|
||||
char buf[100];
|
||||
ASSERT(mg_url_encode("", 0, buf, sizeof(buf)) == 0);
|
||||
ASSERT(buf[0] == '\0');
|
||||
ASSERT(mg_url_encode("foo", 3, buf, sizeof(buf)) == 3);
|
||||
ASSERT(strcmp(buf, "foo") == 0);
|
||||
ASSERT(mg_url_encode("f o", 3, buf, sizeof(buf)) == 5);
|
||||
ASSERT(strcmp(buf, "f%20o") == 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *test_to64(void) {
|
||||
ASSERT(to64("0") == 0);
|
||||
ASSERT(to64("") == 0);
|
||||
ASSERT(to64("123") == 123);
|
||||
ASSERT(to64("-34") == -34);
|
||||
ASSERT(to64("3566626116") == 3566626116);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *test_base64_encode(void) {
|
||||
const char *in[] = {"a", "ab", "abc", "abcd", NULL};
|
||||
const char *out[] = {"YQ==", "YWI=", "YWJj", "YWJjZA=="};
|
||||
char buf[100];
|
||||
int i;
|
||||
|
||||
for (i = 0; in[i] != NULL; i++) {
|
||||
base64_encode((unsigned char *) in[i], strlen(in[i]), buf);
|
||||
ASSERT(!strcmp(buf, out[i]));
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *test_mg_parse_header(void) {
|
||||
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";
|
||||
char buf[20];
|
||||
ASSERT(mg_parse_header(str, "yy", buf, sizeof(buf)) == 0);
|
||||
ASSERT(mg_parse_header(str, "ert", buf, sizeof(buf)) == 3);
|
||||
ASSERT(strcmp(buf, "234") == 0);
|
||||
ASSERT(mg_parse_header(str, "ert", buf, 2) == 0);
|
||||
ASSERT(mg_parse_header(str, "ert", buf, 3) == 0);
|
||||
ASSERT(mg_parse_header(str, "ert", buf, 4) == 3);
|
||||
ASSERT(mg_parse_header(str, "gf", buf, sizeof(buf)) == 0);
|
||||
ASSERT(mg_parse_header(str, "zz", buf, sizeof(buf)) == 5);
|
||||
ASSERT(strcmp(buf, "aa bb") == 0);
|
||||
ASSERT(mg_parse_header(str, "d", buf, sizeof(buf)) == 4);
|
||||
ASSERT(strcmp(buf, "1234") == 0);
|
||||
buf[0] = 'x';
|
||||
ASSERT(mg_parse_header(str, "MMM", buf, sizeof(buf)) == 0);
|
||||
ASSERT(buf[0] == '\0');
|
||||
ASSERT(mg_parse_header(str, "kl", buf, sizeof(buf)) == 3);
|
||||
ASSERT(strcmp(buf, "123") == 0);
|
||||
ASSERT(mg_parse_header(str, "xx", buf, sizeof(buf)) == 1);
|
||||
ASSERT(strcmp(buf, "1") == 0);
|
||||
ASSERT(mg_parse_header(str, "ii", buf, sizeof(buf)) == 5);
|
||||
ASSERT(strcmp(buf, "12\"34") == 0);
|
||||
ASSERT(mg_parse_header(str, "tt", buf, sizeof(buf)) == 1);
|
||||
ASSERT(strcmp(buf, "2") == 0);
|
||||
ASSERT(mg_parse_header(str, "uri", buf, sizeof(buf)) == 10);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *test_next_option(void) {
|
||||
const char *p, *list = "x/8,/y**=1;2k,z";
|
||||
struct vec a, b;
|
||||
int i;
|
||||
|
||||
ASSERT(next_option(NULL, &a, &b) == NULL);
|
||||
for (i = 0, p = list; (p = next_option(p, &a, &b)) != NULL; i++) {
|
||||
ASSERT(i != 0 || (a.ptr == list && a.len == 3 && b.len == 0));
|
||||
ASSERT(i != 1 || (a.ptr == list + 4 && a.len == 4 && b.ptr == list + 9 &&
|
||||
b.len == 4));
|
||||
|
||||
ASSERT(i != 2 || (a.ptr == list + 14 && a.len == 1 && b.len == 0));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int evh1(struct mg_connection *conn, enum mg_event ev) {
|
||||
char *buf = (char *) conn->connection_param;
|
||||
int result = MG_FALSE;
|
||||
|
||||
switch (ev) {
|
||||
case MG_CONNECT:
|
||||
mg_printf(conn, "GET %s HTTP/1.0\r\n\r\n",
|
||||
buf[0] == '1' ? "/cb1" : "/non_exist");
|
||||
result = MG_TRUE;
|
||||
break;
|
||||
case MG_HTTP_ERROR:
|
||||
mg_printf(conn, "HTTP/1.0 404 NF\r\n\r\nERR: %d", conn->status_code);
|
||||
result = MG_TRUE;
|
||||
break;
|
||||
case MG_REQUEST:
|
||||
if (!strcmp(conn->uri, "/cb1")) {
|
||||
mg_printf(conn, "HTTP/1.0 200 OK\r\n\r\n%s %s %s",
|
||||
(char *) conn->server_param,
|
||||
buf == NULL ? "?" : "!", conn->remote_ip);
|
||||
result = MG_TRUE;
|
||||
}
|
||||
break;
|
||||
case MG_REPLY:
|
||||
if (buf != NULL) {
|
||||
sprintf(buf + 1, "%.*s", (int) conn->content_len, conn->content);
|
||||
}
|
||||
break;
|
||||
case MG_AUTH:
|
||||
result = MG_TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char *test_server(void) {
|
||||
char buf1[100] = "1", buf2[100] = "2";
|
||||
struct mg_server *server = mg_create_server((void *) "foo", evh1);
|
||||
struct mg_connection *conn;
|
||||
|
||||
ASSERT(server != NULL);
|
||||
ASSERT(mg_set_option(server, "listening_port", LISTENING_ADDR) == NULL);
|
||||
ASSERT(mg_set_option(server, "document_root", ".") == NULL);
|
||||
|
||||
ASSERT((conn = mg_connect(server, "127.0.0.1:" HTTP_PORT)) != NULL);
|
||||
conn->connection_param = buf1;
|
||||
ASSERT((conn = mg_connect(server, "127.0.0.1:" HTTP_PORT)) != NULL);
|
||||
conn->connection_param = buf2;
|
||||
|
||||
{ int i; for (i = 0; i < 50; i++) mg_poll_server(server, 1); }
|
||||
ASSERT(strcmp(buf1, "1foo ? 127.0.0.1") == 0);
|
||||
ASSERT(strcmp(buf2, "2ERR: 404") == 0);
|
||||
|
||||
ASSERT(strcmp(static_config_options[URL_REWRITES * 2], "url_rewrites") == 0);
|
||||
mg_destroy_server(&server);
|
||||
ASSERT(server == NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define DISP "Content-Disposition: form/data; "
|
||||
#define CRLF "\r\n"
|
||||
#define BOUNDARY "--xyz"
|
||||
static const char *test_parse_multipart(void) {
|
||||
char a[100], b[100];
|
||||
const char *p;
|
||||
static const char f1[] = BOUNDARY CRLF DISP "name=f1" CRLF CRLF
|
||||
"some_content" CRLF BOUNDARY CRLF
|
||||
BOUNDARY CRLF DISP "name=f2; filename=\"foo bar.txt\"" CRLF CRLF
|
||||
"another_content" CRLF BOUNDARY CRLF
|
||||
"--" CRLF;
|
||||
int n, n2, len, f1_len = sizeof(f1) - 1;
|
||||
|
||||
ASSERT(mg_parse_multipart("", 0, a, sizeof(a), b, sizeof(b), &p, &len) == 0);
|
||||
ASSERT(mg_parse_multipart("a", 1, a, sizeof(a), b, sizeof(b), &p, &len) == 0);
|
||||
ASSERT((n = mg_parse_multipart(f1, f1_len, a, sizeof(a),
|
||||
b, sizeof(b), &p, &len)) > 0);
|
||||
ASSERT(len == 12);
|
||||
ASSERT(memcmp(p, "some_content", len) == 0);
|
||||
ASSERT(strcmp(a, "f1") == 0);
|
||||
ASSERT(b[0] == '\0');
|
||||
|
||||
ASSERT((n2 = mg_parse_multipart(f1 + n, f1_len - n, a, sizeof(a),
|
||||
b, sizeof(b), &p, &len)) > 0);
|
||||
ASSERT(len == 15);
|
||||
ASSERT(memcmp(p, "another_content", len) == 0);
|
||||
ASSERT(strcmp(a, "f2") == 0);
|
||||
ASSERT(strcmp(b, "foo bar.txt") == 0);
|
||||
|
||||
ASSERT((n2 = mg_parse_multipart(f1 + n + n2, f1_len - (n + n2), a, sizeof(a),
|
||||
b, sizeof(b), &p, &len)) == 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int evh2(struct mg_connection *conn, enum mg_event ev) {
|
||||
char *file_data, *cp = (char *) conn->connection_param;
|
||||
int file_size, result = MG_FALSE;
|
||||
|
||||
switch (ev) {
|
||||
case MG_AUTH:
|
||||
result = MG_TRUE;
|
||||
break;
|
||||
case MG_CONNECT:
|
||||
mg_printf(conn, "GET /%s HTTP/1.0\r\n\r\n", cp);
|
||||
result = MG_TRUE;
|
||||
break;
|
||||
case MG_REQUEST:
|
||||
break;
|
||||
case MG_REPLY:
|
||||
file_data = read_file("unit_test.c", &file_size);
|
||||
sprintf(cp, "%d %s", (size_t) file_size == conn->content_len &&
|
||||
memcmp(file_data, conn->content, file_size) == 0 ? 1 : 0,
|
||||
conn->query_string == NULL ? "?" : conn->query_string);
|
||||
free(file_data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char *test_mg_set_option(void) {
|
||||
struct mg_server *server = mg_create_server(NULL, NULL);
|
||||
ASSERT(mg_set_option(server, "listening_port", "0") == NULL);
|
||||
ASSERT(mg_get_option(server, "listening_port")[0] != '\0');
|
||||
mg_destroy_server(&server);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *test_rewrites(void) {
|
||||
char buf1[100] = "xx", addr[50];
|
||||
struct mg_server *server = mg_create_server(NULL, evh2);
|
||||
struct mg_connection *conn;
|
||||
const char *port;
|
||||
|
||||
ASSERT(mg_set_option(server, "listening_port", "0") == NULL);
|
||||
ASSERT(mg_set_option(server, "document_root", ".") == NULL);
|
||||
ASSERT(mg_set_option(server, "url_rewrites", "/xx=unit_test.c") == NULL);
|
||||
ASSERT((port = mg_get_option(server, "listening_port")) != NULL);
|
||||
snprintf(addr, sizeof(addr), "127.0.0.1:%s", port);
|
||||
ASSERT((conn = mg_connect(server, addr)) != NULL);
|
||||
conn->connection_param = buf1;
|
||||
|
||||
{ int i; for (i = 0; i < 50; i++) mg_poll_server(server, 1); }
|
||||
|
||||
ASSERT(strcmp(buf1, "1 ?") == 0);
|
||||
mg_destroy_server(&server);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *run_all_tests(void) {
|
||||
RUN_TEST(test_should_keep_alive);
|
||||
RUN_TEST(test_match_prefix);
|
||||
RUN_TEST(test_remove_double_dots);
|
||||
RUN_TEST(test_parse_http_message);
|
||||
RUN_TEST(test_to64);
|
||||
RUN_TEST(test_url_decode);
|
||||
RUN_TEST(test_url_encode);
|
||||
RUN_TEST(test_base64_encode);
|
||||
RUN_TEST(test_mg_parse_header);
|
||||
RUN_TEST(test_get_var);
|
||||
RUN_TEST(test_next_option);
|
||||
RUN_TEST(test_parse_multipart);
|
||||
RUN_TEST(test_mg_set_option);
|
||||
RUN_TEST(test_server);
|
||||
RUN_TEST(test_rewrites);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int __cdecl main(void) {
|
||||
const char *fail_msg = run_all_tests();
|
||||
printf("%s, tests run: %d\n", fail_msg ? "FAIL" : "PASS", static_num_tests);
|
||||
return fail_msg == NULL ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
@ -25,6 +25,7 @@ OBJDIRS += \
|
||||
$(LIBOBJ)/portmidi \
|
||||
$(LIBOBJ)/lua \
|
||||
$(LIBOBJ)/lua/lib \
|
||||
$(LIBOBJ)/mongoose \
|
||||
$(LIBOBJ)/web \
|
||||
$(LIBOBJ)/web/json \
|
||||
$(LIBOBJ)/sqlite3 \
|
||||
@ -535,7 +536,7 @@ $(LIBOBJ)/lua/%.o: $(LIBSRC)/lua/%.c | $(OSPREBUILD)
|
||||
#-------------------------------------------------
|
||||
|
||||
WEBOBJS = \
|
||||
$(LIBOBJ)/web/mongoose.o \
|
||||
$(LIBOBJ)/mongoose/mongoose.o \
|
||||
$(LIBOBJ)/web/json/json_reader.o \
|
||||
$(LIBOBJ)/web/json/json_value.o \
|
||||
$(LIBOBJ)/web/json/json_writer.o \
|
||||
@ -546,9 +547,9 @@ $(LIBOBJ)/web/%.o: $(LIBSRC)/web/%.cpp | $(OSPREBUILD)
|
||||
@echo Compiling $<...
|
||||
$(CC) $(CDEFS) $(CFLAGS) -I$(LIBSRC)/web -c $< -o $@
|
||||
|
||||
$(LIBOBJ)/web/%.o: $(LIBSRC)/web/%.c | $(OSPREBUILD)
|
||||
$(LIBOBJ)/mongoose/%.o: $(3RDPARTY)/mongoose/%.c | $(OSPREBUILD)
|
||||
@echo Compiling $<...
|
||||
$(CC) $(CDEFS) $(CFLAGS) -I$(LIBSRC)/web -DNS_STACK_SIZE=0 -c $< -o $@
|
||||
$(CC) $(CDEFS) $(CFLAGS) -I$(3RDPARTY)/mongoose -DNS_STACK_SIZE=0 -c $< -o $@
|
||||
|
||||
#-------------------------------------------------
|
||||
# SQLite3 library objects
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user