mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-26 12:14:56 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
268d2e9cbe | ||
|
|
1e7da874a4 | ||
|
|
7875a8c2bd | ||
|
|
b0355d45ae | ||
|
|
91136d7731 | ||
|
|
01a058d29b | ||
|
|
e6eca1738f | ||
|
|
2108ec5a0c | ||
|
|
bc4e47630a | ||
|
|
f41c9a2a1f | ||
|
|
6c77208236 | ||
|
|
386d2e5cd4 | ||
|
|
b738fdbffa | ||
|
|
b5704850db | ||
|
|
9c67e8960e | ||
|
|
d3dff4e1d5 | ||
|
|
82872e86fd | ||
|
|
ac229b6606 | ||
|
|
a6bf2bcbf4 | ||
|
|
b0cf8304cb | ||
|
|
0d9fe39dbb | ||
|
|
708af6d9c5 | ||
|
|
e4c71425c9 | ||
|
|
6e07215c1c | ||
|
|
ca9603301e | ||
|
|
d6c388042c | ||
|
|
6f66d794e8 | ||
|
|
1389eec784 | ||
|
|
6ef795e082 | ||
|
|
1e5d258e9e | ||
|
|
70eb4c4bbc | ||
|
|
a639e10a4d | ||
|
|
48750e67f6 | ||
|
|
ce60379af6 | ||
|
|
e0b9e4abfd | ||
|
|
665f205527 | ||
|
|
030daaf5d5 | ||
|
|
760511ec49 | ||
|
|
203688a34b | ||
|
|
29f4703e4f | ||
|
|
3cec6f6745 | ||
|
|
abcea07641 | ||
|
|
6a54704b29 | ||
|
|
8a2fbac4c0 | ||
|
|
96ce6bac69 | ||
|
|
50c0b958ff | ||
|
|
44416902d6 | ||
|
|
25e646c1a1 | ||
|
|
bd723bdc38 | ||
|
|
5e57031724 | ||
|
|
c583913290 | ||
|
|
870ca615de | ||
|
|
64b51699f8 | ||
|
|
50a889dac0 | ||
|
|
0ff0788458 | ||
|
|
fec6009edb | ||
|
|
c4f172a120 | ||
|
|
464c77314d | ||
|
|
f51ca8d5d1 | ||
|
|
7b37e0cb8b | ||
|
|
c7925353e7 | ||
|
|
bd23ec4323 | ||
|
|
3671b2632d | ||
|
|
25115a694c | ||
|
|
2436f9d6c3 | ||
|
|
2238951c18 | ||
|
|
f266dd2c94 | ||
|
|
b03358cb03 | ||
|
|
1bede7e28b | ||
|
|
3536670b82 | ||
|
|
3235c05fd6 | ||
|
|
63db54e7b5 | ||
|
|
1db51eb788 | ||
|
|
0e640ae885 | ||
|
|
1bff6df2a7 | ||
|
|
d0e66de225 | ||
|
|
f537670ce2 | ||
|
|
4cb3341a15 | ||
|
|
d52d9a4a6f | ||
|
|
4a076c7ea4 | ||
|
|
db6e883c22 | ||
|
|
804da054b5 | ||
|
|
fb4e701545 | ||
|
|
ccff4abf13 | ||
|
|
24a7936907 | ||
|
|
0993994139 | ||
|
|
8b740536de | ||
|
|
e851aac853 | ||
|
|
a39861b7bf | ||
|
|
63490249ba | ||
|
|
704f057384 | ||
|
|
40968bc496 | ||
|
|
6873f3c5f6 | ||
|
|
ba5cd7267a | ||
|
|
1bb98e5e8e | ||
|
|
a7774d0f1a | ||
|
|
f52c756fbb | ||
|
|
cc586c6ba2 | ||
|
|
606eab7f4f | ||
|
|
872b85b5f2 | ||
|
|
35bd2b6032 | ||
|
|
c5287b9044 | ||
|
|
223f6d960e | ||
|
|
464b895116 | ||
|
|
05d7b7c8bc | ||
|
|
d8b4db37a0 | ||
|
|
6bb49c780c | ||
|
|
3a60c5764d | ||
|
|
a8b38e4ab9 | ||
|
|
8750f8af1f | ||
|
|
e94a02dc12 | ||
|
|
5680b0fcc5 | ||
|
|
33c56b0edc | ||
|
|
e62e48397d | ||
|
|
8be30350be | ||
|
|
2609a2ab72 | ||
|
|
5a04ab2c56 | ||
|
|
4739de6c28 | ||
|
|
639d7a2fd8 | ||
|
|
8115ce1d82 | ||
|
|
3558b587b7 | ||
|
|
e21ec58ea8 | ||
|
|
74135bca7d | ||
|
|
d369f31608 | ||
|
|
d4b14ca3c1 | ||
|
|
f0994896d5 | ||
|
|
cfdd430b98 | ||
|
|
a6c05a9e83 | ||
|
|
94f63787bb | ||
|
|
367f5df328 | ||
|
|
f096138d6e | ||
|
|
0d00cd51e6 | ||
|
|
b216210a13 | ||
|
|
166833f330 | ||
|
|
4d6bedfd4e | ||
|
|
ace8c1736c | ||
|
|
c658a54d18 | ||
|
|
781a1dc25e | ||
|
|
3ea3b8dfa4 | ||
|
|
a514e143ff | ||
|
|
e1486a79e3 | ||
|
|
ee615248e3 | ||
|
|
687e0e2ee8 | ||
|
|
19aefcb7dd | ||
|
|
6a46244a21 | ||
|
|
60674c11c9 | ||
|
|
91c9ab807b | ||
|
|
9231c7346c | ||
|
|
20cb3a823a | ||
|
|
cbd8d69e6d | ||
|
|
f7fcfa6a42 | ||
|
|
293c5e5852 | ||
|
|
ceb866b4ee | ||
|
|
2f9166e96e | ||
|
|
fe0e0e69e5 | ||
|
|
db96641c10 | ||
|
|
fe83928ca4 | ||
|
|
014414f17f | ||
|
|
6ffe2d7f7a | ||
|
|
30c82d7efe | ||
|
|
999c4ad26c |
No files matched your search
@@ -1,33 +1,47 @@
|
||||
# Mongoose Web Server
|
||||
# <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.
|
||||
|
||||
|
||||
Mongoose is easy to use, powerful, embeddable web server.
|
||||
* [Mailing list](http://groups.google.com/group/mongoose-users)
|
||||
* [Downloads & Documentation](http://cesanta.com/mongoose.shtml)
|
||||
* [How to use Lua Server Pages](http://cesanta.com/docs/Lua.shtml)
|
||||
* [How to create basic website with Mongoose](http://cesanta.com/docs/BasicWebsite.shtml)
|
||||
* [How to create PHP website with Mongoose](http://cesanta.com/docs/PhpWebsite.shtml)
|
||||
* [Embedding Guide](http://cesanta.com/docs/Embed.shtml)
|
||||
* [Downloads](http://cesanta.com/mongoose.shtml)
|
||||
* [Documentation](http://cesanta.com/docs.shtml)
|
||||
|
||||
# Features
|
||||
|
||||
- Works on Windows, Mac, UNIX/Linux, iPhone, Android, 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
|
||||
- Scripting and database support ([Lua](http://lua.org) +
|
||||
[Sqlite](http://sqlite.org), see
|
||||
[dirscan.lp](https://github.com/cesanta/mongoose/blob/master/examples/lua/dirscan.lp) ),
|
||||
which provides ready to go, powerful web development platform in
|
||||
one single-click executable with no dependencies
|
||||
- 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
|
||||
- Asyncronouns, non-blocking core supporting single- or multi-threaded usage
|
||||
- On the market since 2004, stable, mature and tested,
|
||||
has several man-years invested in continuous improvement and refinement
|
||||
- Professional support and consultancy available from
|
||||
[Cesanta Software](http://cesanta.com), developer of Mongoose
|
||||
- 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
|
||||
|
||||
@@ -50,14 +64,23 @@ F.Morenius, and 10 others.
|
||||
|
||||
# Licensing
|
||||
|
||||
Mongoose is released under
|
||||
[GNU GPL v.2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html).
|
||||
Businesses have an option to get non-restrictive, royalty-free commercial
|
||||
license and professional support from
|
||||
[Cesanta Software](http://cesanta.com).
|
||||
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.
|
||||
|
||||
[Frozen JSON parser](https://github.com/cesanta/frozen),
|
||||
[Super Light Regular Expression library](https://github.com/cesanta/slre),
|
||||
[Super Light DNS Resolver](https://github.com/cesanta/sldr)
|
||||
are other projects by Cesanta Software, developed with the same philosophy
|
||||
of functionality and simplicity.
|
||||
# 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
|
||||
+28
-24
@@ -71,23 +71,23 @@ occur. Sequence of events for the accepted connection is this:
|
||||
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 send `MG_POLL` events on each iteration of `mg_poll_server()`
|
||||
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 only to those connections which returned `MG_MORE`.
|
||||
Event handler should try to complete the reply. If reply is completed,
|
||||
then event handler should return `MG_TRUE`. Otherwise, it should
|
||||
return `MG_FALSE`, and polling will continue until
|
||||
handler returns `MG_TRUE`.
|
||||
* `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`
|
||||
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.
|
||||
if it was allocated. Event handler return value is ignored.
|
||||
|
||||
Sequence of events for the client connection is this:
|
||||
|
||||
@@ -96,7 +96,11 @@ Sequence of events for the client connection is this:
|
||||
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.
|
||||
|
||||
|
||||
@@ -132,23 +136,14 @@ 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, ...);
|
||||
|
||||
void mg_iterate_over_connections(struct mg_server *, mg_handler_t func);
|
||||
|
||||
This is an interface primarily designed to push arbitrary data to websocket
|
||||
connections at any time. This function could be called from the Mongoose thread
|
||||
only. When it returns, Mongoose thread calls `func()` for each active
|
||||
connection.
|
||||
It is allowed to call `mg_send_data()` or `mg_websocket_write()` within a
|
||||
callback, cause `func` is executed in the context of the Mongoose thread.
|
||||
|
||||
void mg_wakeup_server(struct mg_server *);
|
||||
|
||||
Makes `mg_poll_server()` that could be sleeping in the `select()` syscall
|
||||
to break the call and return. This function can be called from any thread.
|
||||
It is designed to let other threads wake up Mongoose thread from the sleep
|
||||
and let it do a fresh new IO iteration over all connection. Usually it is done
|
||||
when other threads decides there is new data ready to be sent by Mongoose.
|
||||
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,
|
||||
@@ -176,6 +171,15 @@ a response body. Mongoose provides functions for all three parts:
|
||||
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);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
How To Create A PHP Website With Mongoose
|
||||
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`:
|
||||
@@ -26,7 +26,7 @@ How To Create A PHP Website With Mongoose
|
||||
|
||||

|
||||
|
||||
## 7. Click on the mongoose icon and choose "Start browser" menu:
|
||||
## 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.
|
||||
|
||||
+13
-7
@@ -71,16 +71,20 @@ The sequence of events for every connection is this:
|
||||
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 send `MG_POLL` events on each iteration of `mg_poll_server()`
|
||||
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 only to those connections which returned `MG_MORE`.
|
||||
Event handler should try to complete the reply. If reply is completed,
|
||||
then event handler should return `MG_TRUE`. Otherwise, it should
|
||||
return `MG_FALSE`, and polling will continue until
|
||||
handler returns `MG_TRUE`.
|
||||
* `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.
|
||||
@@ -128,7 +132,7 @@ Mongoose source code contains a well-commented example code, listed below:
|
||||
* [upload.c](https://github.com/cesanta/mongoose/blob/master/examples/post.c)
|
||||
shows how to upload files
|
||||
* [websocket.c](https://github.com/cesanta/mongoose/blob/master/examples/websocket.c) demonstrates websocket usage
|
||||
* [auth.c](https://github.com/cesanta/mongoose/blob/master/examples/websocket.c) demonstrates API-controlled Digest authorization
|
||||
* [auth.c](https://github.com/cesanta/mongoose/blob/master/examples/auth.c) demonstrates API-controlled Digest authorization
|
||||
* [mjpg.c](https://github.com/cesanta/mongoose/blob/master/examples/mjpg.c) demonstrates MJPEG streaming implementation
|
||||
|
||||
## Compilation flags
|
||||
@@ -171,3 +175,5 @@ all Net Skeleton functions will be available too.
|
||||
-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
|
||||
+24
-2
@@ -1,6 +1,28 @@
|
||||
# Mongoose FAQ
|
||||
|
||||
### PHP doesn't work: getting empty page, or 'File not found' error
|
||||
## 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
|
||||
@@ -8,7 +30,7 @@ full path to the PHP interpreter, e.g.:
|
||||
|
||||
mongoose -cgi_interpreter /full/path/to/php-cgi
|
||||
|
||||
### Mongoose fails to start
|
||||
## Mongoose fails to start
|
||||
|
||||
If Mongoose exits immediately when run, this
|
||||
usually indicates a syntax error in the configuration file
|
||||
|
||||
+4
-5
@@ -5,15 +5,14 @@ How To Share Files With Mongoose
|
||||
|
||||

|
||||
|
||||
## 2. Double-click mongoose executable. An icon will appear on a system tray in the bottom right corner of the desktop:
|
||||
## 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 and choose "Start browser" menu:
|
||||
## 3. Click on the mongoose icon
|
||||

|
||||
|
||||
## 4. A browser will popup displaying files. That's all! To access those files from another computer, start a browser and type `http://<your_machine_ip_address>:8080/` in the address bar.
|
||||
|
||||
## 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:
|
||||
|
||||

|
||||
|
||||
## Tip: to find out what is your machine IP address, take a look at http://windows.microsoft.com/en-us/windows/find-computers-ip-address
|
||||
+6
-5
@@ -10,8 +10,12 @@ 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. To learn
|
||||
more about subnet masks, see the
|
||||
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.
|
||||
@@ -86,9 +90,6 @@ 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.
|
||||
|
||||
### idle\_timeout\_ms
|
||||
Timeout for idle connections in milliseconds. Default: `30000` (30 seconds)
|
||||
|
||||
### 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`
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ How To Create A PHP Website With Mongoose
|
||||
|
||||

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

|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
# Mongoose Release Notes
|
||||
|
||||
## 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 buy 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)
|
||||
+18
-2
@@ -12,6 +12,8 @@ ifeq ($(OS),Windows_NT)
|
||||
CFLAGS += $(CFLAGS_EXTRA)
|
||||
else
|
||||
UNAME_S := $(shell uname -s)
|
||||
CC = g++
|
||||
CFLAGS += -lssl -g -O0
|
||||
|
||||
ifeq ($(UNAME_S),Linux)
|
||||
CFLAGS += -ldl
|
||||
@@ -48,15 +50,29 @@ upload: upload.c ../mongoose.c
|
||||
auth: auth.c ../mongoose.c
|
||||
$(CC) auth.c ../mongoose.c $(OUT) $(CFLAGS)
|
||||
|
||||
file: file.c ../mongoose.c
|
||||
$(CC) file.c ../mongoose.c $(OUT) $(CFLAGS)
|
||||
|
||||
form: form.c ../mongoose.c
|
||||
$(CC) form.c ../mongoose.c $(OUT) $(CFLAGS)
|
||||
|
||||
mjpg: mjpg.c ../mongoose.c
|
||||
$(CC) mjpg.c ../mongoose.c $(OUT) $(CFLAGS)
|
||||
|
||||
pubsub: websocket2.c ../mongoose.c
|
||||
$(CC) websocket2.c ../mongoose.c $(OUT) $(CFLAGS)
|
||||
|
||||
|
||||
proxy: proxy.c ../mongoose.c
|
||||
$(CC) proxy.c ../mongoose.c $(OUT) \
|
||||
-I../../net_skeleton -DNS_ENABLE_SSL -lssl $(CFLAGS)
|
||||
|
||||
websocket_html.c: websocket.html
|
||||
perl mkdata.pl $< > $@
|
||||
|
||||
u:
|
||||
g++ unit_test.c -Wall -W -pedantic -lssl -g -O0 $(CFLAGS_EXTRA) && ./a.out
|
||||
$(CC) unit_test.c $(OUT) $(CFLAGS)
|
||||
./$@
|
||||
|
||||
clean:
|
||||
-@$(RM) hello mjpg upload post websocket auth server multi_threaded websocket_html.c *.exe *.dSYM *.obj .*o
|
||||
-@$(RM) hello mjpg upload post websocket auth file server multi_threaded proxy websocket_html.c *.exe *.dSYM *.obj .*o u a.out
|
||||
@@ -0,0 +1,88 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "mongoose.h"
|
||||
|
||||
struct file_data {
|
||||
FILE *fp;
|
||||
const char *data;
|
||||
int data_len;
|
||||
int written;
|
||||
};
|
||||
|
||||
static int handle_request(struct mg_connection *conn) {
|
||||
const char *data;
|
||||
int data_len;
|
||||
char var_name[100], file_name[100], path[100];
|
||||
|
||||
if (strcmp(conn->uri, "/upload") == 0) {
|
||||
if (mg_parse_multipart(conn->content, conn->content_len,
|
||||
var_name, sizeof(var_name),
|
||||
file_name, sizeof(file_name),
|
||||
&data, &data_len) > 0) {
|
||||
struct file_data *p = (struct file_data *) malloc(sizeof(*p));
|
||||
snprintf(path, sizeof(path), "UPLOAD_%s", file_name);
|
||||
p->fp = fopen(path, "wb");
|
||||
p->data = data;
|
||||
p->data_len = data_len;
|
||||
p->written = 0;
|
||||
conn->connection_param = p;
|
||||
mg_send_header(conn, "Content-Type", "text/html");
|
||||
}
|
||||
return MG_MORE; // Tell mongoose to keep this connection open
|
||||
} 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
|
||||
}
|
||||
}
|
||||
|
||||
static int handle_poll(struct mg_connection *conn) {
|
||||
struct file_data *p = (struct file_data *) conn->connection_param;
|
||||
if (p != NULL) {
|
||||
// Write no more then 100 bytes in one go
|
||||
int len = p->data_len - p->written;
|
||||
int n = fwrite(p->data + p->written, 1, len > 100 ? 100 : len, p->fp);
|
||||
if (n > 0) {
|
||||
p->written += n;
|
||||
mg_send_data(conn, " ", 1); // Send something back to wake up select()
|
||||
}
|
||||
|
||||
// If everything is written, close the connection
|
||||
if (p->written >= p->data_len) {
|
||||
mg_printf_data(conn, "Written %d bytes.", p->written);
|
||||
fclose(p->fp);
|
||||
free(p);
|
||||
conn->connection_param = NULL;
|
||||
return MG_TRUE; // Tell mongoose to close this connection
|
||||
}
|
||||
}
|
||||
return MG_FALSE; // Tell mongoose to keep this connection open
|
||||
}
|
||||
|
||||
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_POLL: return handle_poll(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;
|
||||
}
|
||||
+29
-23
@@ -2,36 +2,42 @@
|
||||
// https://github.com/cesanta/mongoose
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
public class Program {
|
||||
static private int EventHandler(MongooseEvent ev) {
|
||||
if (ev.type != 1) {
|
||||
return 0; // Mark as unhandled
|
||||
}
|
||||
static private int EventHandler(IntPtr conn_ptr, int ev) {
|
||||
MongooseConnection conn = (MongooseConnection)
|
||||
System.Runtime.InteropServices.Marshal.PtrToStructure(
|
||||
conn_ptr , typeof(MongooseConnection));
|
||||
|
||||
MongooseRequestInfo request_info = (MongooseRequestInfo)
|
||||
Marshal.PtrToStructure(ev.request_info, typeof(MongooseRequestInfo));
|
||||
|
||||
if (request_info.uri != "/test") {
|
||||
return 0; // Mark as unhandled
|
||||
}
|
||||
|
||||
Mongoose.write(ev.conn, "HTTP/1.1 200 OK\r\n\r\n");
|
||||
Mongoose.write(ev.conn, "Hello from C#!\n");
|
||||
|
||||
return 1; // Mark as handled
|
||||
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(".", "9000",
|
||||
Mongoose web_server = new Mongoose(".", "9001",
|
||||
new MongooseEventHandler(EventHandler));
|
||||
|
||||
Console.WriteLine("Mongoose v." + web_server.version_ + " started.");
|
||||
Console.WriteLine("Press enter to exit program.");
|
||||
|
||||
// Serve requests until user presses "enter" on a keyboard
|
||||
Console.ReadLine();
|
||||
web_server.stop();
|
||||
Console.WriteLine("Mongoose started, press Ctrl-C to exit.");
|
||||
for (;;) {
|
||||
web_server.poll(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
+40
-65
@@ -9,85 +9,60 @@ using System.Runtime.InteropServices;
|
||||
[MarshalAs(UnmanagedType.LPTStr)] public IntPtr value;
|
||||
};
|
||||
|
||||
// mongoose.h :: struct mg_request_info
|
||||
[StructLayout(LayoutKind.Sequential)] public struct MongooseRequestInfo {
|
||||
// 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.LPTStr)] public string remote_user;
|
||||
public int remote_ip;
|
||||
public int remote_port;
|
||||
public int is_ssl;
|
||||
[MarshalAs(UnmanagedType.ByValArray,SizeConst=64)]
|
||||
|
||||
[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;
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)] public struct MongooseEvent {
|
||||
public int type;
|
||||
public IntPtr user_data;
|
||||
public IntPtr conn_data;
|
||||
public IntPtr event_param;
|
||||
public IntPtr conn;
|
||||
public IntPtr request_info;
|
||||
};
|
||||
|
||||
public delegate int MongooseEventHandlerN(ref MongooseEvent ev);
|
||||
public delegate int MongooseEventHandler(MongooseEvent ev);
|
||||
public delegate int MongooseEventHandler(IntPtr c, int ev);
|
||||
|
||||
public class Mongoose {
|
||||
public const string dll_name_ = "mongoose";
|
||||
public string version_ = "??";
|
||||
public const string dll_ = "mongoose";
|
||||
private IntPtr server_;
|
||||
|
||||
// These are here to store a ref to the callbacks
|
||||
// while they are over in unmanaged code, to prevent garbage collection.
|
||||
private event MongooseEventHandlerN delegates;
|
||||
|
||||
private IntPtr ctx_;
|
||||
|
||||
[DllImport(dll_name_)] private static extern
|
||||
IntPtr mg_start([MarshalAs(UnmanagedType.LPArray,
|
||||
ArraySubType=UnmanagedType.LPTStr)] string[] options,
|
||||
MongooseEventHandlerN callback,
|
||||
IntPtr user_data);
|
||||
[DllImport(dll_name_)] private static extern void mg_stop(IntPtr ctx);
|
||||
[DllImport(dll_name_)] private static extern IntPtr mg_version();
|
||||
[DllImport(dll_name_)] public static extern int mg_write(IntPtr conn,
|
||||
string data, int length);
|
||||
[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_ports,
|
||||
string listening_port,
|
||||
MongooseEventHandler event_handler) {
|
||||
version_ = Marshal.PtrToStringAnsi(mg_version());
|
||||
|
||||
string[] options = {
|
||||
"document_root", document_root,
|
||||
"listening_ports", listening_ports,
|
||||
null
|
||||
};
|
||||
|
||||
MongooseEventHandlerN cb = delegate(ref MongooseEvent ev) {
|
||||
return event_handler(ev);
|
||||
};
|
||||
|
||||
// Prevent garbage collection
|
||||
delegates += cb;
|
||||
|
||||
ctx_ = mg_start(options, cb, IntPtr.Zero);
|
||||
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 write(IntPtr conn, string data) {
|
||||
return mg_write(conn, data, data.Length);
|
||||
|
||||
public static int send_data(IntPtr conn, string data) {
|
||||
return mg_send_data(conn, data, data.Length);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (this.ctx_ != IntPtr.Zero) {
|
||||
mg_stop(this.ctx_);
|
||||
}
|
||||
this.ctx_ = IntPtr.Zero;
|
||||
}
|
||||
|
||||
~Mongoose() {
|
||||
stop();
|
||||
|
||||
public void poll(int milli) {
|
||||
mg_poll_server(server_, milli);
|
||||
}
|
||||
|
||||
// TODO: add destructor and call mg_destroy_server()
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEA8FV466yTGIUkJqjBv2CTU/HeYKXYd7D6m8fY9daRLm9cKPhB
|
||||
kPvLyhdenOH88uAAYqmKf2dZvP5SxFnBKT52Hr0XpUfC8Y3iVjHxwMgNRaiSkfDP
|
||||
mIEb2qcpJoMrdos/ff46itqwr9wW3+7kjRlxM1Mu5pq4EibSHeVyaPWVCgENcA1m
|
||||
4beQujI1SSBkLOfmgpw/SsyzyTgXm+kOdj7vKy3EbXseGPtHJ04oZ7qwol1NFrrq
|
||||
HwO87HWHxyQr7uJ4TBH37gL7QCdjHsOdN94alxEUWTRfmzZFXVlsTnq5DBnnGhtq
|
||||
ibpUC8WeI3QiFNtTBKkHviAm+6iWW6gG2TO4twIDAQABAoIBAHxLWBxaxkB6KzYr
|
||||
NPirE8boYiAN5aQRTarfcp/B9pfTVBCERDSdZMoByBbO8akSnGBqWoyFgO2zgk62
|
||||
NKYF/cTr+pyqPnH69UGq1uLjE6ohApyjtFmk/CjbJvcaA5JtdcrNfq1taM+qvdHW
|
||||
lTE8JUVsEeeFwQjyNtzrW35Y9FmVLSmMNsESChLnrsa7IxwnfRpHc+hmj+7lxZO6
|
||||
ZzAaCCo9qHR1Ddi5f+0DJoXGBBGOk6C4BWLaV+fHPcsYHESrepitGfS96AQ0Wspn
|
||||
qqtAp6jv+iIfgpohYylIjOPcHf3dXpINTxwz/r3XicqBaSAx2lXb+vnxERmagGKC
|
||||
RUpELVECgYEA/EHUDwJRBUMvGXjRQO9R0JLp59U2UZOvAjmIAHkLM/48k8//kpgJ
|
||||
CDUVvuyQUfwCphmaiAm5BZfDbmhBEirjCai8fYkrGugQl9H1YrVsi+UhQudnSRM0
|
||||
7plKIb9nz9by31J1iu5YHTpovO5MQjH5UP1boqAioBNoBuzFI0QK1uMCgYEA8+Za
|
||||
0NDocnE+V2NpRag+oMbM/LBgSWyk49NXYUOhuv4CZ8f20nFYx6p9RLD0ICUOxC3B
|
||||
TkHybnGhRjuR+LkbuynW2wM2+jwcLe+ZPnXZsNKJwST9fzus06BWHyBTJHfhUDO3
|
||||
cq6PUDJua6NQa++rj+ur1LSFPuwnC+X2FxMd6x0CgYEAweyhZ4ByZMdHWB+nTnIs
|
||||
xVmL9CvW/FO6gM1Vnndvg2L5kvCeG0ZB+0tEEmiucjh4mNSqFdbTpFcNaL1A+QR7
|
||||
UZukfCWNO7wXtX81U9MBRXK6ZUKcBnN7h8nUUalh10f5onEz58BfgOi8SDIx8dmV
|
||||
Pwvm/Fh7BfClUl2HGBtg8d0CgYBEDWwdg4y4EdzhKT3AT9dZqN6dSuEy23uOjfN9
|
||||
kg9YS3OEXYkC4tlwrKNTPUSAi5Z5KoMbQM9R/aaQICL0kUGpkVz/sv/uBkOelZHe
|
||||
madp7PS+zYFltNLeIYimGrDYJhLZ+/QdrZMTP18L7X+M/kySVaGWMeBT1DR432sw
|
||||
uQbKCQKBgQC9D9fxDXCFxJmJc2Cp8ZYQha4Oc10JsanM1DM1YWIaOILfoExz46vZ
|
||||
UJzRfe2LkkhhRN9YG4ZW6zJ1E/HZSjKC2iwHog/4bDjykVPrFIfPdWS2C1CQF/Jq
|
||||
tYnHTpuxE3JFXZrLXbDobFKbxHOZRdlSUu8NK/V507Y34NaMPHnffw==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIID4DCCAsigAwIBAgIJAM1yCH8CR4Z+MA0GCSqGSIb3DQEBBQUAMFMxFDASBgNV
|
||||
BAMTC2Nlc2FudGEuY29tMR0wGwYDVQQKExRDZXNhbnRhIFNvZnR3YXJlIEx0ZDEL
|
||||
MAkGA1UEBhMCSUUxDzANBgNVBAcTBkR1YmxpbjAeFw0xNDA2MjcxMDUwNTBaFw0y
|
||||
NDA2MjQxMDUwNTBaMFMxFDASBgNVBAMTC2Nlc2FudGEuY29tMR0wGwYDVQQKExRD
|
||||
ZXNhbnRhIFNvZnR3YXJlIEx0ZDELMAkGA1UEBhMCSUUxDzANBgNVBAcTBkR1Ymxp
|
||||
bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPBVeOuskxiFJCaowb9g
|
||||
k1Px3mCl2Hew+pvH2PXWkS5vXCj4QZD7y8oXXpzh/PLgAGKpin9nWbz+UsRZwSk+
|
||||
dh69F6VHwvGN4lYx8cDIDUWokpHwz5iBG9qnKSaDK3aLP33+OorasK/cFt/u5I0Z
|
||||
cTNTLuaauBIm0h3lcmj1lQoBDXANZuG3kLoyNUkgZCzn5oKcP0rMs8k4F5vpDnY+
|
||||
7ystxG17Hhj7RydOKGe6sKJdTRa66h8DvOx1h8ckK+7ieEwR9+4C+0AnYx7DnTfe
|
||||
GpcRFFk0X5s2RV1ZbE56uQwZ5xobaom6VAvFniN0IhTbUwSpB74gJvuolluoBtkz
|
||||
uLcCAwEAAaOBtjCBszAdBgNVHQ4EFgQUwvetHY2/J2F788UvFPADTlaUS10wgYMG
|
||||
A1UdIwR8MHqAFML3rR2Nvydhe/PFLxTwA05WlEtdoVekVTBTMRQwEgYDVQQDEwtj
|
||||
ZXNhbnRhLmNvbTEdMBsGA1UEChMUQ2VzYW50YSBTb2Z0d2FyZSBMdGQxCzAJBgNV
|
||||
BAYTAklFMQ8wDQYDVQQHEwZEdWJsaW6CCQDNcgh/AkeGfjAMBgNVHRMEBTADAQH/
|
||||
MA0GCSqGSIb3DQEBBQUAA4IBAQDA3QTlZ2aUe4IIDU+yZmu3XRxJ4FGpOlC0nD1j
|
||||
uwHWDaHfr0WMDjwSoEHbhsc0tapXOpG+hFImHemDS82SuC2c8lNKEJeXgdF3Rqeo
|
||||
aIB8sklgHsJG1DoCwC5TIMaccmbALWctouELGFb8aDF+dczKaaDTW+/dgR47GvD5
|
||||
NBTka2A56U3emmXRpOOtzOz/68lxgACXc+M3yrxbYt9a95rl6wwzNlLHDwPzqhzd
|
||||
ayQ9Q8wmZpWZK1oc8oKKuEXA3zG6jJkrmC8VD5j0WRLgC7SV/zlaAUR/zEisstrh
|
||||
ZVMiJ0NoZmAPVRm0MyBHtBHJFcn/z/FlhqCBLsmDxJ/aOEMT
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,46 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEA4+LVrSV4kvgr2AM5NSIewSfGwK5fXUOoYQ4vpjq2+H2hhOPP
|
||||
0WVyHkLWZXYek8ZmCqPFBvavzO9bveBprQIDTHexj83paaoV8IMugzymeWVONEwU
|
||||
8E9S6sGihCF01yOO5g4X7lmX7mypUDNJHZd/0SuSGezwSd+c41pY/CWmCW+61hls
|
||||
HjKdBp3Nked/u2aJ619D8NYPeu03V89P5x5hWrOWLSfmpd8pQ5tceVO56XjgmZLr
|
||||
FwUTK5Dq/3hUv1lyxHoSWGp5sQirZ5artLgkqCI+K+dwc2YZeeJBACllSqVuzJYh
|
||||
HSpnmKUwMXykJfKtTckfLoJX2VGgbqJWSZFkowIDAQABAoIBAHAKDR30p0QyyXOJ
|
||||
mi26Wb6DbN88m9xBsF4PWHP0uBKRycCJNJpxstqX58q4eS4URAUFIZBb5nDuWX+P
|
||||
/sS1kaOd0WmvRgvSOLkn9c1GG17h5MInib/gcBbFHr6xqD1B2TbYRQHFgMITIGcy
|
||||
38axvoC7WDhw2m6nhv3sZIWLiQdnvsUWF+mXQoRwyK9Me/3/N9atRELPd9rvbwkz
|
||||
ITyZQPE7IScSwVClspSBQMdJj4Bak8sQ8uKpxmIqpRGe9bqz2IO2hxkW9RiAT2CE
|
||||
4KZ1eqSM8q+VUlFfEo7IJ1lh8Anuo/h/qVnN2JTyCWoAW/YLIWUreLAOVCm3feV/
|
||||
fFO5sQkCgYEA8yzhvPegx1cPgtvEaAVJKbI9WBVCT7qAroDrfxBS3m37jHip8SDr
|
||||
4qfh+5OWG6J0hXEKCf1FbhDCDQOf6sQCMlBgR5BU/ALqiFWfEp+ysC10VtdCpEhA
|
||||
PgldtzLhXyApw536y05Ak3Yucii70m80bsXZR2alGWTfJ64e511hSM0CgYEA7+eI
|
||||
QXh9kuKwM143Bk7HWvLNJ71TAb+mp0OkOjmzMe2duoGi0DzTBlSh6AYdSYkMYSbc
|
||||
PW8bF88bTiq4rak9PuJGiFr7Iq5SMccpaZ+JIPnF2S8gdNB1hgfRsUDNHhb691/u
|
||||
3Q/7gOUpiWGrP5uP55/yuFyKkrp+gPGKLhrFIy8CgYA096q34WxI30LGqx3t1nDo
|
||||
PyWzgPXvrd0HpZcmFyUlw+kN4N6LYjNfLFhB1xTUMh+VTVj1chBkeAv8j7SOi2E7
|
||||
GlzOWbbZKb1yMswyX0ypqUz0+XBPnlk36gxash96++N883VEQWg5dn2Jaiv3Gzfd
|
||||
hQTd05LUpC8jUn7ywFlHZQKBgE3agWldxMKqNiw1Yv31CtUE/nbrBckHfPnDBcSv
|
||||
fOuzBQDFmSSi2IixZml5sn9urknI5qg5Kj2rxFy1mIEi7vE9VU5i2CUFFT96NoJE
|
||||
d6fv5rj4hjvieoEogHBZazdclc05oLa0vRWzSKuAuqZFwYmVaptRzNaZFvyZZhJY
|
||||
NamZAoGBANL8Jqht1s1qcLuBis1jZdjzUuF3xNMuxwqszD0zFZFAIUN097460zw+
|
||||
8LIeZgVMJOCmbVHja/RII9PI4vQ7h5rhTmeFWS80QMe22C1yukqEqljYO0POhxsu
|
||||
sm3plGS3rfGkMp1URDgnJL6m/y8gC4+/O6NIEoVaHpraW8//qCD6
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDEjCCAfoCBRQDhmJSMA0GCSqGSIb3DQEBBQUAMFMxFDASBgNVBAMTC2Nlc2Fu
|
||||
dGEuY29tMR0wGwYDVQQKExRDZXNhbnRhIFNvZnR3YXJlIEx0ZDELMAkGA1UEBhMC
|
||||
SUUxDzANBgNVBAcTBkR1YmxpbjAeFw0xNDA2MjcxMDUwNTFaFw0yNDA2MjQxMDUw
|
||||
NTFaMEcxFTATBgNVBAMTDDE5Mi4xNjguMS4yODEQMA4GA1UEChMHRm9vK0x0ZDEL
|
||||
MAkGA1UEBhMCSUUxDzANBgNVBAcTBkdhbHdheTCCASIwDQYJKoZIhvcNAQEBBQAD
|
||||
ggEPADCCAQoCggEBAOPi1a0leJL4K9gDOTUiHsEnxsCuX11DqGEOL6Y6tvh9oYTj
|
||||
z9Flch5C1mV2HpPGZgqjxQb2r8zvW73gaa0CA0x3sY/N6WmqFfCDLoM8pnllTjRM
|
||||
FPBPUurBooQhdNcjjuYOF+5Zl+5sqVAzSR2Xf9Erkhns8EnfnONaWPwlpglvutYZ
|
||||
bB4ynQadzZHnf7tmietfQ/DWD3rtN1fPT+ceYVqzli0n5qXfKUObXHlTuel44JmS
|
||||
6xcFEyuQ6v94VL9ZcsR6ElhqebEIq2eWq7S4JKgiPivncHNmGXniQQApZUqlbsyW
|
||||
IR0qZ5ilMDF8pCXyrU3JHy6CV9lRoG6iVkmRZKMCAwEAATANBgkqhkiG9w0BAQUF
|
||||
AAOCAQEAAxJSilcxos3v5aKllKTsx04Q/P39wQ07ywS1Yf9NsA7MlPU++qs3BqJJ
|
||||
kAaCPpfeAl8GjQLh75XV7rLvycvrluthpHzMRZhnbd+DLCt+FrS5zWWhm6M7535V
|
||||
FHGjuW59sAurARgcB530+bh6a0YNhKJbp3Si5ONhQfEuKPf+R6bPA1Slr2k/ts+K
|
||||
GIzwJbNTVRSor/wlb4F0seHFEv2rdtHt1g+VYlFVwBFawIOx3dU7hHxgzeoRYnik
|
||||
RGrPvhqK3u1wQ+2s/m2HPWj8CFjZ8V7f4sYRjLhpsbeJCy4A28nWvl+cCjAhCQKq
|
||||
Rawa0TcZiQtsj0jaTe71jhAMSMC6qw==
|
||||
-----END CERTIFICATE-----
|
||||
+10
-35
@@ -1,47 +1,22 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mongoose.h"
|
||||
|
||||
|
||||
static int index_html(struct mg_connection *conn) {
|
||||
FILE *fp = (FILE *) conn->connection_param;
|
||||
char buf[200];
|
||||
size_t n = 0;
|
||||
|
||||
if (fp == NULL) {
|
||||
fp = fopen("../mongoose.c", "r");
|
||||
conn->connection_param = (void *) fp;
|
||||
static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||
switch (ev) {
|
||||
case MG_REQUEST:
|
||||
mg_send_file(conn, "file.c");
|
||||
return MG_MORE; // It is important to return MG_MORE after mg_send_file!
|
||||
case MG_AUTH: return MG_TRUE;
|
||||
default: return MG_FALSE;
|
||||
}
|
||||
|
||||
if (fp != NULL) {
|
||||
n = fread(buf, 1, sizeof(buf), fp);
|
||||
mg_send_data(conn, buf, n);
|
||||
|
||||
if (n < sizeof(buf) || conn->wsbits != 0) {
|
||||
fclose(fp);
|
||||
conn->connection_param = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return n < sizeof(buf) ? MG_REQUEST_PROCESSED : MG_REQUEST_CALL_AGAIN;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
struct mg_server *server;
|
||||
|
||||
// Create and configure the server
|
||||
server = mg_create_server(NULL);
|
||||
struct mg_server *server = mg_create_server(NULL, ev_handler);
|
||||
mg_set_option(server, "listening_port", "8080");
|
||||
mg_set_request_handler(server, index_html);
|
||||
|
||||
// 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
|
||||
for (;;) mg_poll_server(server, 1000);
|
||||
mg_destroy_server(&server);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "mongoose.h"
|
||||
|
||||
static int static_value = 123; // Exposed and changeable via the form
|
||||
|
||||
static void print_html_form(struct mg_connection *conn) {
|
||||
mg_send_header(conn, "Content-Type", "text/html");
|
||||
mg_send_header(conn, "Cache-Control", "max-age=0, post-check=0, "
|
||||
"pre-check=0, no-store, no-cache, must-revalidate");
|
||||
|
||||
// Note that all the following normally should reside in static HTML page
|
||||
mg_printf_data(conn, "%s", "<html><head>");
|
||||
// It is better to use local copy though
|
||||
mg_printf_data(conn, "<script src=\"%s\"></script>",
|
||||
"http://code.jquery.com/jquery-1.11.0.min.js");
|
||||
mg_printf_data(conn, "%s", "<script> jQuery(function() {\n");
|
||||
// Here is the ajax call that fetches data from the device and
|
||||
// updates the form
|
||||
mg_printf_data(conn, "%s", "$.ajax({ url: '/get_value', dataType: 'json', "
|
||||
"success: function(d) { $('#val').val(d.value); }});\n");
|
||||
// This ajax call is triggered when submit button is pressed. It sends new
|
||||
// value to the device.
|
||||
mg_printf_data(conn, "%s", "$(document).on('click', '#button', function() {"
|
||||
" $.ajax({ url: '/set_value', dataType: 'json', "
|
||||
" data: { new_value: $('#val').val() } });\n"
|
||||
" return false; });\n");
|
||||
mg_printf_data(conn, "%s", "});</script>");
|
||||
mg_printf_data(conn, "%s", "</head><body>");
|
||||
mg_printf_data(conn, "%s", "<h1>Ajax form submission example</h1>");
|
||||
mg_printf_data(conn, "%s", "<form>");
|
||||
mg_printf_data(conn, "%s", "Device value: <input type=text id=val />");
|
||||
mg_printf_data(conn, "%s", "<input type=submit id=button />");
|
||||
mg_printf_data(conn, "%s", "</form>");
|
||||
mg_printf_data(conn, "%s", "</body></html>");
|
||||
}
|
||||
|
||||
static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
|
||||
if (ev == MG_REQUEST) {
|
||||
if (strcmp(conn->uri, "/get_value") == 0) {
|
||||
mg_printf_data(conn, "{\"value\": %d}", static_value);
|
||||
} else if (strcmp(conn->uri, "/set_value") == 0) {
|
||||
// This Ajax endpoint sets the new value for the device variable
|
||||
char buf[100] = "";
|
||||
mg_get_var(conn, "new_value", buf, sizeof(buf)); // Get form variable
|
||||
static_value = atoi(buf); // Set new value
|
||||
mg_printf_data(conn, "%s", "{\"success\": true}");
|
||||
printf("Setting value to [%d]\n", static_value); // Debug trace
|
||||
} else {
|
||||
// Better way is to set "document_root" option, put "index.html" file
|
||||
// into document_root and return MG_FALSE here. We're printing HTML
|
||||
// page by hands just to keep everything in one C file.
|
||||
print_html_form(conn);
|
||||
}
|
||||
return MG_TRUE;
|
||||
} else if (ev == MG_AUTH) {
|
||||
return MG_TRUE;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<? 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>
|
||||
+1
-1
@@ -13,7 +13,7 @@ static void send_file(struct mg_connection *conn, const char *path) {
|
||||
|
||||
if (stat(path, &st) == 0 && (fp = fopen(path, "rb")) != NULL) {
|
||||
mg_printf(conn, "--myboundary\r\nContent-Type: image/jpeg\r\n"
|
||||
"Content-Length: %zu\r\n\r\n", st.st_size);
|
||||
"Content-Length: %llu\r\n\r\n", (unsigned long long) st.st_size);
|
||||
while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) {
|
||||
mg_write(conn, buf, n);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
// 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 "net_skeleton.h"
|
||||
#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 *cert = NULL, *ca_cert = NULL, *port = "2014";
|
||||
const char *mitm = NULL, *dump = NULL, *root = "proxy_web_root";
|
||||
int i;
|
||||
|
||||
// Parse command line options
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-ca_cert") == 0 && i + 1 < argc) {
|
||||
ca_cert = argv[++i];
|
||||
} else if (strcmp(argv[i], "-cert") == 0 && i + 1 < argc) {
|
||||
cert = argv[++i];
|
||||
} else if (strcmp(argv[i], "-port") == 0 && i + 1 < argc) {
|
||||
port = argv[++i];
|
||||
} else if (strcmp(argv[i], "-mitm") == 0 && i + 1 < argc) {
|
||||
mitm = 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, "ssl_certificate", cert);
|
||||
setopt(s_server, "ssl_ca_certificate", ca_cert);
|
||||
setopt(s_server, "hexdump_file", dump);
|
||||
setopt(s_server, "ssl_mitm_certs", mitm);
|
||||
|
||||
// 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;
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
+52
-29
@@ -67,6 +67,11 @@ typedef struct _stat file_stat_t;
|
||||
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))
|
||||
@@ -75,12 +80,19 @@ typedef struct stat file_stat_t;
|
||||
#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 config_file[PATH_MAX]; // Set by process_command_line_arguments()
|
||||
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"
|
||||
@@ -131,7 +143,7 @@ static void show_usage_and_exit(void) {
|
||||
int i;
|
||||
|
||||
fprintf(stderr, "Mongoose version %s (c) Sergey Lyubka, built on %s\n",
|
||||
MONGOOSE_VERSION, __DATE__);
|
||||
MVER, __DATE__);
|
||||
fprintf(stderr, "Usage:\n");
|
||||
#ifndef MONGOOSE_NO_AUTH
|
||||
fprintf(stderr, " mongoose -A <htpasswd_file> <realm> <user> <passwd>\n");
|
||||
@@ -180,32 +192,34 @@ static void set_option(char **options, const char *name, const char *value) {
|
||||
}
|
||||
|
||||
static void process_command_line_arguments(char *argv[], char **options) {
|
||||
char line[MAX_CONF_FILE_LINE_SIZE], opt[sizeof(line)], val[sizeof(line)], *p;
|
||||
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(config_file, sizeof(config_file), "%s", argv[1]);
|
||||
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(config_file, sizeof(config_file), "%s", CONFIG_FILE);
|
||||
snprintf(cpath, sizeof(cpath), "%s", CONFIG_FILE);
|
||||
} else {
|
||||
snprintf(config_file, sizeof(config_file), "%.*s%c%s",
|
||||
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(config_file, "r");
|
||||
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", config_file, strerror(errno));
|
||||
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", config_file);
|
||||
fprintf(stderr, "Loading config file %s\n", s_config_file);
|
||||
|
||||
// Loop over the lines in config file
|
||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
||||
@@ -219,7 +233,7 @@ static void process_command_line_arguments(char *argv[], char **options) {
|
||||
|
||||
if (sscanf(line, "%s %[^\r\n#]", opt, val) != 2) {
|
||||
printf("%s: line %d is invalid, ignoring it:\n %s",
|
||||
config_file, (int) line_no, line);
|
||||
s_config_file, (int) line_no, line);
|
||||
} else {
|
||||
set_option(options, opt, val);
|
||||
}
|
||||
@@ -246,7 +260,7 @@ static void process_command_line_arguments(char *argv[], char **options) {
|
||||
static void init_server_name(void) {
|
||||
const char *descr = "";
|
||||
snprintf(server_name, sizeof(server_name), "Mongoose web server v.%s%s",
|
||||
MONGOOSE_VERSION, descr);
|
||||
MVER, descr);
|
||||
}
|
||||
|
||||
static int is_path_absolute(const char *path) {
|
||||
@@ -269,6 +283,14 @@ static char *get_option(char **options, const char *option_name) {
|
||||
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 &&
|
||||
@@ -284,8 +306,7 @@ static void verify_existence(char **options, const char *name, int is_dir) {
|
||||
}
|
||||
}
|
||||
|
||||
static void set_absolute_path(char *options[], const char *option_name,
|
||||
const char *path_to_mongoose_exe) {
|
||||
static void set_absolute_path(char *options[], const char *option_name) {
|
||||
char path[PATH_MAX], abs[PATH_MAX], *option_value;
|
||||
const char *p;
|
||||
|
||||
@@ -298,11 +319,11 @@ static void set_absolute_path(char *options[], const char *option_name,
|
||||
// Not absolute. Use the directory where mongoose executable lives
|
||||
// be the relative directory for everything.
|
||||
// Extract mongoose executable directory into path.
|
||||
if ((p = strrchr(path_to_mongoose_exe, DIRSEP)) == NULL) {
|
||||
if ((p = strrchr(s_config_file, DIRSEP)) == NULL) {
|
||||
getcwd(path, sizeof(path));
|
||||
} else {
|
||||
snprintf(path, sizeof(path), "%.*s", (int) (p - path_to_mongoose_exe),
|
||||
path_to_mongoose_exe);
|
||||
snprintf(path, sizeof(path), "%.*s", (int) (p - s_config_file),
|
||||
s_config_file);
|
||||
}
|
||||
|
||||
strncat(path, "/", sizeof(path) - 1);
|
||||
@@ -380,9 +401,7 @@ int modify_passwords_file(const char *fname, const char *domain,
|
||||
#endif
|
||||
|
||||
static void start_mongoose(int argc, char *argv[]) {
|
||||
char *options[MAX_OPTIONS];
|
||||
int i;
|
||||
|
||||
s_argv = argv;
|
||||
if ((server = mg_create_server(NULL, EV_HANDLER)) == NULL) {
|
||||
die("%s", "Failed to start Mongoose.");
|
||||
}
|
||||
@@ -402,6 +421,12 @@ static void start_mongoose(int argc, char *argv[]) {
|
||||
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);
|
||||
@@ -412,16 +437,16 @@ static void start_mongoose(int argc, char *argv[]) {
|
||||
|
||||
// Make sure we have absolute paths for files and directories
|
||||
// https://github.com/valenok/mongoose/issues/181
|
||||
set_absolute_path(options, "document_root", argv[0]);
|
||||
set_absolute_path(options, "dav_auth_file", argv[0]);
|
||||
set_absolute_path(options, "cgi_interpreter", argv[0]);
|
||||
set_absolute_path(options, "access_log_file", argv[0]);
|
||||
set_absolute_path(options, "global_auth_file", argv[0]);
|
||||
set_absolute_path(options, "ssl_certificate", argv[0]);
|
||||
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", argv[0]);
|
||||
set_absolute_path(options, "document_root");
|
||||
notify("Setting document_root to [%s]",
|
||||
mg_get_option(server, "document_root"));
|
||||
}
|
||||
@@ -472,9 +497,7 @@ int main(int argc, char *argv[]) {
|
||||
server_name, mg_get_option(server, "document_root"),
|
||||
mg_get_option(server, "listening_port"));
|
||||
fflush(stdout); // Needed, Windows terminals might not be line-buffered
|
||||
while (exit_flag == 0) {
|
||||
mg_poll_server(server, 1000);
|
||||
}
|
||||
serving_thread_func(server);
|
||||
printf("Exiting on signal %d ...", exit_flag);
|
||||
fflush(stdout);
|
||||
mg_destroy_server(&server);
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEAtafk8OvgJX6SLEtnwRmE1oEmk3zsDD0UGW+qD+DtIPOb37xR
|
||||
NIpOGFU8GXAn2GmIIkk7L53bnyh08osTnJKnhprBMDIpwZoMp4HECH4Dk0M7H2S3
|
||||
CMJRT+wYG4GJZt3Tp2U5y9T+T+4YMGCVXOOC7MiEq1nA/iQnljhhGJO61yVgDb/d
|
||||
asnI6igrDQUY30NHIBdtws2s+ysWLYh/LugLZurEtvnzwnt/qQoe7UF/MW51gvu7
|
||||
ywfSvxRksCKZKOFjLIMcEmkReA28Y+mhfKT1bjU6Gte2XZj+5f2TqYvCO+n/d5dY
|
||||
41/Nuk9ujjo/G19dUUOZu3OLL59Q9Rg+6j1FVwIDAQABAoIBAQCE7iW0v4c5KNQi
|
||||
odN9FQWGSuBF0YaStid9LZ+PGxOrp1kLcq0h+4uGdukR3GbsEN3T6S7se2H5qAtc
|
||||
abWiQBdjgt+YOz0fNXHJKkafyEcpfmtHX9YpDLmf+K7zgelgYze9KXAP3v9y0lLV
|
||||
I/hpDvwB9gJPudBmqWJmpT84UvLI+I1HtJ1Q3EgMxFSlx+TrGxqIQmYCaXIIZqdk
|
||||
c1B2neQLGZQ1Dbulr7/KYOkkcPkAQKRY73WHvhhN/0LsD25U6P00etz1VQmLBcWe
|
||||
Y9RaCBD7D3UqSat6ZABv7mtFp8USAEy4a8clayQRdolGTb+gxBUnEMDtRzwcE4zF
|
||||
uh/SGFEBAoGBAPBU/19v82Jqy41D8nqjTN6WXRX37kN1ElS5yvstIdO3oHEywll8
|
||||
tV8Bm+L0ODn/dOWmCZxKWO3hwr8KoEgk8ouv/vDsMRBuwtqZmmdtue5kPEnw3kMB
|
||||
F6RR4Pd9dqmwbF/s4NwpIVFaQEZE6JkhEsXHAJSivKm4m0MadSfm6F5BAoGBAMF/
|
||||
oArSDqsz5BvTZ3pbhUxIMY98IR7jf1ewjsgpthqZFhTggD0KxVcfUYSzg3BXUkl9
|
||||
NFKPQgfOfgW2fiEe999/CRPB0lTtlMybs3L+gb74SmUWxkVmm4mjhfnPoh9AKga2
|
||||
AFtZEcx+1bzkVvyZoSV4s0R61jJcVptutWFcDG2XAoGAKcltmad6dvtApzBQQdiQ
|
||||
7gbQ6pfwOpRpeofPbjrbrdc4s1XzCuIvGvTJqP1zpUnwhlmHREB9E+d0GAl98u1R
|
||||
qs4QEs3Ofh/0C1Q3z5H5iSSuguC5lIblGHIQHpgXAMwnG8qxEjaoj1+U22Lx2mYw
|
||||
wGiohi+BhDUP8evwwN5aOsECgYEAq3qN+2jihQhsi9hSqNW4kLyd5zmrJHOaI70d
|
||||
G/gTIQkvz3qRSwdjkWz40jBAOGu6SdRCbTP14XM2rZtntbR7GL687Zxj6M3Pg3As
|
||||
nKk9lF73lxSSy2g+SMD490TxuN4lIGNkd4+8vUxd4JM/H4aKj+mifPqbHnBEdGSt
|
||||
K0Xm4asCgYEAxM1MNlaS6BD8jLcEQZ/PX9G+ReN7u5zMiw62KQj0wsMy+p92ib1l
|
||||
Jvsv2LI4Ps6SEf4XdDctoAjgk7wsv45rS2RxiBg3wSVz5SSR513+VjlIgmNGWTlI
|
||||
U7tngF/p+qh2Kd5XtqSj5TK3Ts9UPfv3TjBe85LaxxT9WJ8SH3NiEAg=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDEjCCAfoCBRQDhmJRMA0GCSqGSIb3DQEBBQUAMFMxFDASBgNVBAMTC2Nlc2Fu
|
||||
dGEuY29tMR0wGwYDVQQKExRDZXNhbnRhIFNvZnR3YXJlIEx0ZDELMAkGA1UEBhMC
|
||||
SUUxDzANBgNVBAcTBkR1YmxpbjAeFw0xNDA2MjcxMDUwNTBaFw0yNDA2MjQxMDUw
|
||||
NTBaMEcxFTATBgNVBAMTDDE5Mi4xNjguMS4yODEQMA4GA1UEChMHRm9vK0x0ZDEL
|
||||
MAkGA1UEBhMCSUUxDzANBgNVBAcTBkdhbHdheTCCASIwDQYJKoZIhvcNAQEBBQAD
|
||||
ggEPADCCAQoCggEBALWn5PDr4CV+kixLZ8EZhNaBJpN87Aw9FBlvqg/g7SDzm9+8
|
||||
UTSKThhVPBlwJ9hpiCJJOy+d258odPKLE5ySp4aawTAyKcGaDKeBxAh+A5NDOx9k
|
||||
twjCUU/sGBuBiWbd06dlOcvU/k/uGDBglVzjguzIhKtZwP4kJ5Y4YRiTutclYA2/
|
||||
3WrJyOooKw0FGN9DRyAXbcLNrPsrFi2Ify7oC2bqxLb588J7f6kKHu1BfzFudYL7
|
||||
u8sH0r8UZLAimSjhYyyDHBJpEXgNvGPpoXyk9W41OhrXtl2Y/uX9k6mLwjvp/3eX
|
||||
WONfzbpPbo46PxtfXVFDmbtziy+fUPUYPuo9RVcCAwEAATANBgkqhkiG9w0BAQUF
|
||||
AAOCAQEAtWSuAbC62J0rdSu5GZg7k7hu6e9s11dc5PS/VRk4h+99RoLxWYO7c6Bp
|
||||
PdDGt6IAWDu2u/aowlKr0sWwThR+nAlQHlufSieS6udfFR1O6cjXa0hRUCKU5Ant
|
||||
+mgPNsfmxV6A6pBSfwgYiv6KLaCRr7tvJqyaNl0MbxMCPmUHy+/Fplab6+h91DsO
|
||||
FxECw/P73iNmSrx9sYrbl83snXMDoMgHq08LwebBcdfiKXGB7mobi0lRfNbh7rqv
|
||||
xVZZ26shxUKLZrtDH0+ACPO6/e6dogOIO9/Frlp+E955Y6F+SeF4QexfbZn5mW8X
|
||||
c7pDVtADI3bClzuYM6PPvOp+sXKM9Q==
|
||||
-----END CERTIFICATE-----
|
||||
+40
-28
@@ -166,34 +166,34 @@ static const char *test_should_keep_alive(void) {
|
||||
}
|
||||
|
||||
static const char *test_match_prefix(void) {
|
||||
ASSERT(match_prefix("/api", 4, "/api") == 4);
|
||||
ASSERT(match_prefix("/a/", 3, "/a/b/c") == 3);
|
||||
ASSERT(match_prefix("/a/", 3, "/ab/c") == -1);
|
||||
ASSERT(match_prefix("/*/", 3, "/ab/c") == 4);
|
||||
ASSERT(match_prefix("**", 2, "/a/b/c") == 6);
|
||||
ASSERT(match_prefix("/*", 2, "/a/b/c") == 2);
|
||||
ASSERT(match_prefix("*/*", 3, "/a/b/c") == 2);
|
||||
ASSERT(match_prefix("**/", 3, "/a/b/c") == 5);
|
||||
ASSERT(match_prefix("**.foo|**.bar", 13, "a.bar") == 5);
|
||||
ASSERT(match_prefix("a|b|cd", 6, "cdef") == 2);
|
||||
ASSERT(match_prefix("a|b|c?", 6, "cdef") == 2);
|
||||
ASSERT(match_prefix("a|?|cd", 6, "cdef") == 1);
|
||||
ASSERT(match_prefix("/a/**.cgi", 9, "/foo/bar/x.cgi") == -1);
|
||||
ASSERT(match_prefix("/a/**.cgi", 9, "/a/bar/x.cgi") == 12);
|
||||
ASSERT(match_prefix("**/", 3, "/a/b/c") == 5);
|
||||
ASSERT(match_prefix("**/$", 4, "/a/b/c") == -1);
|
||||
ASSERT(match_prefix("**/$", 4, "/a/b/") == 5);
|
||||
ASSERT(match_prefix("$", 1, "") == 0);
|
||||
ASSERT(match_prefix("$", 1, "x") == -1);
|
||||
ASSERT(match_prefix("*$", 2, "x") == 1);
|
||||
ASSERT(match_prefix("/$", 2, "/") == 1);
|
||||
ASSERT(match_prefix("**/$", 4, "/a/b/c") == -1);
|
||||
ASSERT(match_prefix("**/$", 4, "/a/b/") == 5);
|
||||
ASSERT(match_prefix("*", 1, "/hello/") == 0);
|
||||
ASSERT(match_prefix("**.a$|**.b$", 11, "/a/b.b/") == -1);
|
||||
ASSERT(match_prefix("**.a$|**.b$", 11, "/a/b.b") == 6);
|
||||
ASSERT(match_prefix("**.a$|**.b$", 11, "/a/B.A") == 6);
|
||||
ASSERT(match_prefix("**o$", 4, "HELLO") == 5);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -271,6 +271,17 @@ static const char *test_url_decode(void) {
|
||||
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);
|
||||
@@ -498,6 +509,7 @@ static const char *run_all_tests(void) {
|
||||
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);
|
||||
|
||||
+15
-17
@@ -5,9 +5,9 @@
|
||||
#include <string.h>
|
||||
#include "mongoose.h"
|
||||
|
||||
static void send_index_page(struct mg_connection *conn) {
|
||||
static int send_index_page(struct mg_connection *conn) {
|
||||
const char *data;
|
||||
int data_len;
|
||||
int data_len, ofs = 0;
|
||||
char var_name[100], file_name[100];
|
||||
|
||||
mg_printf_data(conn, "%s",
|
||||
@@ -15,30 +15,28 @@ static void send_index_page(struct mg_connection *conn) {
|
||||
"<form method=\"POST\" action=\"/handle_post_request\" "
|
||||
" enctype=\"multipart/form-data\">"
|
||||
"<input type=\"file\" name=\"file\" /> <br/>"
|
||||
"<input type=\"text\" name=\"input1\" value=hello! /> <br/>"
|
||||
"<input type=\"submit\" value=\"Upload\" />"
|
||||
"</form>");
|
||||
|
||||
if (mg_parse_multipart(conn->content, conn->content_len,
|
||||
var_name, sizeof(var_name),
|
||||
file_name, sizeof(file_name),
|
||||
&data, &data_len) > 0) {
|
||||
|
||||
mg_printf_data(conn, "%s", "Uploaded file:<pre>");
|
||||
mg_send_data(conn, data, data_len);
|
||||
mg_printf_data(conn, "%s", "/pre>");
|
||||
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) {
|
||||
if (ev == MG_REQUEST) {
|
||||
send_index_page(conn);
|
||||
return MG_TRUE;
|
||||
} else if (ev == MG_AUTH) {
|
||||
return MG_TRUE;
|
||||
} else {
|
||||
return MG_FALSE;
|
||||
switch (ev) {
|
||||
case MG_AUTH: return MG_TRUE;
|
||||
case MG_REQUEST: return send_index_page(conn);
|
||||
default: return MG_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
extern const char *find_embedded_file(const char *, size_t *);
|
||||
|
||||
static int iterate_callback(struct mg_connection *c, enum mg_event ev) {
|
||||
static int counter = 0;
|
||||
if (ev == MG_POLL && c->is_websocket) {
|
||||
char buf[20];
|
||||
int len = snprintf(buf, sizeof(buf), "%d", counter++);
|
||||
int len = snprintf(buf, sizeof(buf), "%lu",
|
||||
(unsigned long) * (time_t *) c->callback_param);
|
||||
mg_websocket_write(c, 1, buf, len);
|
||||
}
|
||||
return MG_TRUE;
|
||||
@@ -58,7 +58,7 @@ int main(void) {
|
||||
current_timer = time(NULL);
|
||||
if (current_timer - last_timer > 0) {
|
||||
last_timer = current_timer;
|
||||
mg_iterate_over_connections(server, iterate_callback);
|
||||
mg_iterate_over_connections(server, iterate_callback, ¤t_timer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
#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, "pubsub.html"); // Return MG_MORE after mg_send_file()
|
||||
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;
|
||||
}
|
||||
+953
-721
File diff suppressed because it is too large.
Load diff
+40
-22
@@ -20,7 +20,7 @@
|
||||
#ifndef MONGOOSE_HEADER_INCLUDED
|
||||
#define MONGOOSE_HEADER_INCLUDED
|
||||
|
||||
#define MONGOOSE_VERSION "5.3"
|
||||
#define MONGOOSE_VERSION "5.4"
|
||||
|
||||
#include <stdio.h> // required for FILE
|
||||
#include <stddef.h> // required for size_t
|
||||
@@ -37,7 +37,7 @@ struct mg_connection {
|
||||
const char *query_string; // URL part after '?', not including '?', or NULL
|
||||
|
||||
char remote_ip[48]; // Max IPv6 string length is 45 characters
|
||||
const char *local_ip; // Local IP address
|
||||
char local_ip[48]; // Local IP address
|
||||
unsigned short remote_port; // Client's port
|
||||
unsigned short local_port; // Local port number
|
||||
|
||||
@@ -48,13 +48,14 @@ struct mg_connection {
|
||||
} http_headers[30];
|
||||
|
||||
char *content; // POST (or websocket message) data, or NULL
|
||||
size_t content_len; // content length
|
||||
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()
|
||||
};
|
||||
|
||||
struct mg_server; // Opaque structure describing server instance
|
||||
@@ -65,12 +66,23 @@ enum mg_event {
|
||||
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_CLOSE, // Connection is closed
|
||||
MG_LUA, // Called before LSP page invoked
|
||||
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
|
||||
};
|
||||
|
||||
// Server management functions
|
||||
struct mg_server *mg_create_server(void *server_param, mg_handler_t handler);
|
||||
void mg_destroy_server(struct mg_server **);
|
||||
@@ -80,22 +92,26 @@ 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 mg_iterate_over_connections(struct mg_server *, mg_handler_t, void *);
|
||||
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);
|
||||
|
||||
// Connection management functions
|
||||
void mg_send_status(struct mg_connection *, int status_code);
|
||||
void mg_send_header(struct mg_connection *, const char *name, const char *val);
|
||||
void mg_send_data(struct mg_connection *, const void *data, int data_len);
|
||||
void mg_printf_data(struct mg_connection *, const char *format, ...);
|
||||
size_t mg_send_data(struct mg_connection *, const void *data, int data_len);
|
||||
size_t mg_printf_data(struct mg_connection *, const char *format, ...);
|
||||
size_t mg_write(struct mg_connection *, const void *buf, int len);
|
||||
size_t mg_printf(struct mg_connection *conn, const char *fmt, ...);
|
||||
|
||||
int mg_websocket_write(struct mg_connection *, int opcode,
|
||||
const char *data, size_t data_len);
|
||||
size_t mg_websocket_write(struct mg_connection *, int opcode,
|
||||
const char *data, size_t data_len);
|
||||
size_t mg_websocket_printf(struct mg_connection* conn, int opcode,
|
||||
const char *fmt, ...);
|
||||
|
||||
// Deprecated in favor of mg_send_* interface
|
||||
int mg_write(struct mg_connection *, const void *buf, int len);
|
||||
int mg_printf(struct mg_connection *conn, const char *fmt, ...);
|
||||
void mg_send_file(struct mg_connection *, const char *path);
|
||||
|
||||
const char *mg_get_header(const struct mg_connection *, const char *name);
|
||||
const char *mg_get_mime_type(const char *name, const char *default_mime_type);
|
||||
@@ -111,16 +127,18 @@ int mg_parse_multipart(const char *buf, int buf_len,
|
||||
void *mg_start_thread(void *(*func)(void *), void *param);
|
||||
char *mg_md5(char buf[33], ...);
|
||||
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);
|
||||
|
||||
// Templates support
|
||||
struct mg_expansion {
|
||||
const char *keyword;
|
||||
void (*handler)(struct mg_connection *);
|
||||
};
|
||||
void mg_template(struct mg_connection *, const char *text,
|
||||
struct mg_expansion *expansions);
|
||||
|
||||
// Lua utility functions
|
||||
#ifdef MONGOOSE_USE_LUA
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
void reg_string(lua_State *L, const char *name, const char *val);
|
||||
void reg_int(lua_State *L, const char *name, int val);
|
||||
void reg_function(lua_State *L, const char *,
|
||||
lua_CFunction, struct mg_connection *);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user