Compare commits

...
161 Commits
Author SHA1 Message Date
Sergey Lyubka 268d2e9cbe better explanation for websocket2.c example 2014-07-28 12:19:00 +01:00
Sergey Lyubka 1e7da874a4 Merge branch 'master' of ssh://github.com/valenok/mongoose 2014-07-28 12:15:23 +01:00
Sergey Lyubka 7875a8c2bd release notes for 5.4 2014-07-28 12:15:13 +01:00
Sergey Lyubka b0355d45ae Merge pull request #403 from pavel-pimenov/fix-cache-call-stat
stat - function result cache
2014-07-27 11:13:26 +01:00
Sergey Lyubka 91136d7731 Merge pull request #406 from Cykey/master
Set the correct json content-type
2014-07-27 11:12:52 +01:00
Pavel Pimenov 01a058d29b Remove file_stat_t st_cgi; 2014-07-27 13:10:49 +04:00
Pavel Pimenov e6eca1738f 80 characters limit + remove tabs 2014-07-27 12:53:37 +04:00
Pavel Pimenov 2108ec5a0c Fix style for pointer 2014-07-27 12:44:08 +04:00
David M. bc4e47630a Set the correct json content-type
Chance text/json to application/json to comply with the RFC.

See http://www.ietf.org/rfc/rfc4627.txt for more information.
2014-07-26 20:55:59 -04:00
Pavel Pimenov f41c9a2a1f stat - function result cache 2014-07-23 11:26:20 +04:00
Sergey Lyubka 6c77208236 release notes dates 2014-07-21 21:38:45 +01:00
Sergey Lyubka 386d2e5cd4 fix leak in handle_propfind() 2014-07-18 13:00:43 +01:00
Sergey Lyubka b738fdbffa updated net skeleton 2014-07-08 11:28:03 +01:00
Sergey Lyubka b5704850db Merge branch 'master' of ssh://github.com/valenok/mongoose 2014-07-08 11:10:17 +01:00
Sergey Lyubka 9c67e8960e updated certs 2014-07-08 11:10:08 +01:00
Sergey Lyubka d3dff4e1d5 Merge pull request #391 from pavel-pimenov/pvs-studio-fix-zu
Change printf mask %zu -> %lu
2014-07-07 08:58:23 +01:00
Pavel Pimenov 82872e86fd Change printf mask %zu -> %lu
for MS VC++ compatibility http://stackoverflow.com/questions/15610053/correct-printf-format-specifier-for-size-t-zu-or-iu
2014-07-07 09:24:48 +04:00
Sergey Lyubka ac229b6606 Merge pull request #387 from Z-Wave-Me/master
Disallow WebDAV MKCOL/PUT/DELETE requests to protected files
2014-06-28 21:40:11 +01:00
Alex Skalozub a6bf2bcbf4 Should also disallow PROPFIND as well 2014-06-29 00:03:52 +04:00
Alex Skalozub b0cf8304cb Disallow WebDAV MKCOL/PUT/DELETE requests to protected files (like .htpasswd) 2014-06-28 23:14:21 +04:00
Sergey Lyubka 0d9fe39dbb ns_read_from_socket(): calling recv() in a loop until failure 2014-06-25 11:43:07 +01:00
Sergey Lyubka 708af6d9c5 more comments in big_upload.c 2014-06-24 17:09:00 +01:00
Sergey Lyubka e4c71425c9 Added big_upload.c 2014-06-24 17:04:26 +01:00
Sergey Lyubka 6e07215c1c Using Multiple inputs for upload example 2014-06-24 16:35:59 +01:00
Sergey Lyubka ca9603301e removed trailing newline 2014-06-24 16:35:26 +01:00
Sergey Lyubka d6c388042c QNX SSL upload fix 2014-06-23 13:52:07 +01:00
Sergey Lyubka 6f66d794e8 Refactor NS_POLL case in mg_ev_handler 2014-06-20 11:41:13 +01:00
Sergey Lyubka 1389eec784 Added comment for mg_terminate_ssl() call 2014-06-19 09:55:10 +01:00
Sergey Lyubka 6ef795e082 manual mitm for oracle.com 2014-06-19 09:53:38 +01:00
Sergey Lyubka 1e5d258e9e Wording for licensing clarified 2014-06-18 11:30:57 +01:00
Sergey Lyubka 70eb4c4bbc exported mg_terminate_ssl 2014-06-18 10:59:29 +01:00
Sergey Lyubka a639e10a4d squash QNX warning about execle() call 2014-06-17 13:28:45 +01:00
Sergey Lyubka 48750e67f6 ENABLE_PROXY is visible with MONGOOSE_NO_FILESYSTEM 2014-06-17 10:50:47 +01:00
Sergey Lyubka ce60379af6 sending 405 for proxy request if connect is not allowed 2014-06-16 11:27:17 +01:00
Sergey Lyubka e0b9e4abfd Added enable_proxy 2014-06-16 11:06:57 +01:00
Sergey Lyubka 665f205527 squash warning under mingw 2014-06-16 10:46:50 +01:00
Sergey Lyubka 030daaf5d5 squash warning under mingw 2014-06-16 10:44:56 +01:00
Sergey Lyubka 760511ec49 squashed warning around NS_STACK_SIZE 2014-06-16 10:21:31 +01:00
Sergey Lyubka 203688a34b Added comment for Win32 SO_RESUSEADDR 2014-06-13 10:19:46 +01:00
Sergey Lyubka 29f4703e4f Adding zero-length chunk for long-running requests 2014-06-13 07:57:27 +01:00
Sergey Lyubka 3cec6f6745 keeping alive long-lived connections 2014-06-12 10:58:49 +01:00
Sergey Lyubka abcea07641 Fix #373 2014-06-11 20:37:35 +01:00
Sergey Lyubka 6a54704b29 mg_set_option(): always set correct actual listening port 2014-06-11 20:12:23 +01:00
Sergey Lyubka 8a2fbac4c0 Calling event handler in MITM mode before making connection to the target host 2014-06-11 09:56:34 +01:00
Sergey Lyubka 96ce6bac69 ns_server_poll(): setting current_time to now after select() 2014-06-11 09:44:18 +01:00
Sergey Lyubka 50c0b958ff Added -root cmd line flag to proxy example 2014-06-10 12:22:50 +01:00
Sergey Lyubka 44416902d6 Changed debug in do_proxy() 2014-06-10 12:22:30 +01:00
Sergey Lyubka 25e646c1a1 Squashed warnings for MONGOOSE_NO_FILESYSTEM 2014-06-10 10:26:58 +01:00
Sergey Lyubka bd723bdc38 Removed dead code in websocket2.c 2014-06-09 17:33:26 +01:00
Sergey Lyubka 5e57031724 Added pubsub example 2014-06-09 17:26:22 +01:00
Sergey Lyubka c583913290 Added pubsub example 2014-06-09 17:25:08 +01:00
Sergey Lyubka 870ca615de Added mg_next() 2014-06-09 17:24:51 +01:00
Sergey Lyubka 64b51699f8 Added MG_WS_CONNECT 2014-06-09 16:32:56 +01:00
Sergey Lyubka 50a889dac0 Inlined parse_url() 2014-06-04 12:32:47 +01:00
Sergey Lyubka 0ff0788458 Formatting change for mg_send_file() 2014-06-04 12:32:31 +01:00
Sergey Lyubka fec6009edb mg_send_file() doc changed 2014-06-03 18:49:17 +01:00
Sergey Lyubka c4f172a120 Documented mg_send_file() 2014-06-03 18:45:37 +01:00
Sergey Lyubka 464c77314d Amended file sending example 2014-06-03 18:03:13 +01:00
Sergey Lyubka f51ca8d5d1 Added mg_send_file(). Changed sending function to return send_iobuf length. 2014-06-03 18:02:55 +01:00
Sergey Lyubka 7b37e0cb8b Added simplistic flow control in transfer_file_data() 2014-06-03 17:00:52 +01:00
Sergey Lyubka c7925353e7 Added parens around expression to squash warning under QNX SDP 6.6.0 2014-06-03 14:25:54 +01:00
Sergey Lyubka bd23ec4323 Removed a bit of dead code. Added more comments in proxy_event_handler() 2014-05-29 17:40:06 +01:00
Daniel O'Connell 3671b2632d proxy unit test reference implementation 2014-05-29 17:04:28 +01:00
Daniel O'Connell 25115a694c proxy support changes 2014-05-29 17:04:13 +01:00
Sergey Lyubka 2436f9d6c3 squashed win32 warnings 2014-05-22 07:31:19 +01:00
Sergey Lyubka 2238951c18 Integrated Dans net skeleton changes 2014-05-21 16:18:21 +01:00
Daniel O'Connell f266dd2c94 Removed noisy debug messages 2014-05-20 16:40:47 +01:00
Daniel O'Connell b03358cb03 Fixes for the proxy code 2014-05-19 19:08:02 +01:00
Sergey Lyubka 1bede7e28b Added test for parse_url() 2014-05-19 12:56:07 +01:00
Sergey Lyubka 3536670b82 re-worded FAQ section 2014-05-18 16:13:04 +01:00
Daniel O'Connell 3235c05fd6 Added proxy functionality 2014-05-18 13:22:33 +01:00
Daniel O'Connell 63db54e7b5 Added AV faq 2014-05-18 10:53:54 +01:00
Daniel O'Connell 1db51eb788 Moved sse.html to proxy_web_root/index.html 2014-05-13 14:51:16 +01:00
Daniel O'Connell 0e640ae885 Made setopt() wrapper around mg_set_option() 2014-05-13 13:02:08 +01:00
Daniel O'Connell 1bff6df2a7 Enabled SSL for proxy example 2014-05-13 12:33:27 +01:00
Daniel O'Connell d0e66de225 Re-added ssl_ca_certificate option 2014-05-13 12:30:30 +01:00
Daniel O'Connell f537670ce2 Synced net skeleton 2014-05-13 12:28:39 +01:00
Daniel O'Connell 4cb3341a15 Added proxy example, with SSE html page 2014-05-13 11:22:31 +01:00
Daniel O'Connell d52d9a4a6f Added pem files 2014-05-13 11:08:18 +01:00
Daniel O'Connell 4a076c7ea4 Added proxy to the clean target 2014-05-13 10:56:32 +01:00
Sergey Lyubka db6e883c22 Added mg_wakeup_server_ex(), removed mg_wakeup_server() and mg_iterate_over_connections() 2014-05-13 09:33:10 +01:00
Sergey Lyubka 804da054b5 Removed extra line in the comment 2014-05-12 23:24:03 +01:00
Sergey Lyubka fb4e701545 Added mg_wakeup_server_ex() for pushing data 2014-05-12 23:22:57 +01:00
Sergey Lyubka ccff4abf13 Added proxy target 2014-05-12 10:47:08 +01:00
Sergey Lyubka 24a7936907 Squashed warning for non-ssl case in ns_set_ssl_ca_cert() 2014-05-11 16:05:07 +01:00
Sergey Lyubka 0993994139 Merge branch 'master' of ssh://github.com/valenok/mongoose 2014-05-11 13:43:10 +01:00
Sergey Lyubka 8b740536de Added ssl_ca_certificate option 2014-05-11 13:42:59 +01:00
Sergey Lyubka e851aac853 Merge pull request #371 from cry-inc/master
Fixed wrong behavior of mg_set_option() with option "listening_port" caused by SO_REUSEADDR when using Windows
2014-05-07 17:00:36 +01:00
cry-inc a39861b7bf Fixed wrong behavior of mg_set_option() with option "listening_port" caused by SO_REUSEADDR when using Windows 2014-05-07 16:38:23 +02:00
Sergey Lyubka 63490249ba Merge pull request #368 from cry-inc/master
Fixed wrong MIME type for .rar files
2014-04-30 10:45:09 +01:00
cry-inc 704f057384 Fixed wrong MIME type for .rar files 2014-04-30 10:30:35 +02:00
Sergey Lyubka 40968bc496 Moved other products in a different section 2014-04-30 09:18:55 +01:00
Sergey Lyubka 6873f3c5f6 Removed idle_timeout_ms 2014-04-29 18:01:25 +01:00
Sergey Lyubka ba5cd7267a Added MONGOOSE_SEND_NS_EVENTS to the embedding doc 2014-04-28 15:04:39 +01:00
Sergey Lyubka 1bb98e5e8e Exported mg_websocket_printf(), mg_url_encode(). Added unit test for mg_url_encode() 2014-04-25 18:04:24 +01:00
Sergey Lyubka a7774d0f1a Added mg_websocket_printf(). added MONGOOSE_SEND_NS_EVENTS 2014-04-24 14:09:54 +01:00
Sergey Lyubka f52c756fbb Calling SSL_free() in ns_close_conn() 2014-04-16 16:45:31 +01:00
Sergey Lyubka cc586c6ba2 php->basic 2014-04-15 14:13:38 +01:00
Sergey Lyubka 606eab7f4f Passing PUT content to the event handler 2014-04-14 16:14:13 +01:00
Sergey Lyubka 872b85b5f2 more on -access_control_list 2014-04-14 13:03:47 +01:00
Sergey Lyubka 35bd2b6032 Added form.c 2014-04-10 22:18:01 +01:00
Sergey Lyubka c5287b9044 iobuf_append() refactored: allocating exactly as many bytes as needed 2014-04-09 23:52:16 +01:00
Sergey Lyubka 223f6d960e README message changed 2014-04-09 18:10:49 +01:00
Sergey Lyubka 464b895116 Added enum for websocket opcodes 2014-04-09 15:16:03 +01:00
Sergey Lyubka 05d7b7c8bc Added MG_WS_HANDSHAKE 2014-04-09 11:55:36 +01:00
Sergey Lyubka d8b4db37a0 Squashed warnings 2014-04-09 11:37:08 +01:00
Sergey Lyubka 6bb49c780c Updated net skeleton code 2014-04-09 11:32:23 +01:00
Sergey Lyubka 3a60c5764d Unit test target corrected 2014-04-07 19:07:41 +01:00
Sergey Lyubka a8b38e4ab9 mg_set_option() sets NULL if value is empty 2014-03-31 15:02:20 +01:00
Sergey Lyubka 8750f8af1f Added cast in try_parse() 2014-03-31 09:51:47 +01:00
Sergey Lyubka e94a02dc12 Added more in 5.4 release notes 2014-03-31 09:49:42 +01:00
Sergey Lyubka 5680b0fcc5 Removed redundant cast in try_parse() 2014-03-31 09:34:31 +01:00
Sergey Lyubka 33c56b0edc Init local_ip and local_port properly in mg_connection 2014-03-30 22:50:10 +01:00
Sergey Lyubka e62e48397d Keeping absolute path for config file 2014-03-30 16:00:03 +01:00
Sergey Lyubka 8be30350be mg_set_option(): allow NULL as value. Fast success if old_value == new_value. 2014-03-30 15:59:39 +01:00
Sergey Lyubka 2609a2ab72 Fixed comment for mg_template() 2014-03-30 12:47:27 +01:00
Sergey Lyubka 5a04ab2c56 Added mg_template() function 2014-03-30 12:45:48 +01:00
Sergey Lyubka 4739de6c28 Removed DLL interface and Lua conditional 2014-03-30 12:34:32 +01:00
Sergey Lyubka 639d7a2fd8 Fixing MinGW compilation: pid_t -> process_id_t 2014-03-28 09:18:38 +00:00
Sergey Lyubka 8115ce1d82 Handling SSL_write() error 2014-03-27 11:18:20 +00:00
Sergey Lyubka 3558b587b7 Fixed linking problem for -DMONGOOSE_NO_FILESYSTEM 2014-03-27 10:13:34 +00:00
Sergey Lyubka e21ec58ea8 dav fixes: using auth if auth file is set 2014-03-26 23:13:14 +00:00
Sergey Lyubka 74135bca7d link fixed 2014-03-26 18:58:58 +00:00
Sergey Lyubka d369f31608 return 404 for non-existent propfind URIs 2014-03-26 16:34:55 +00:00
Sergey Lyubka d4b14ca3c1 Better API documentation 2014-03-26 14:13:30 +00:00
Sergey Lyubka f0994896d5 FileSharing doc nitpick 2014-03-26 12:27:44 +00:00
Sergey Lyubka cfdd430b98 Added hexdump_file option 2014-03-26 12:20:02 +00:00
Sergey Lyubka a6c05a9e83 changed handle_propfind() to report only dir entry when listing dir 2014-03-24 20:39:32 +00:00
Sergey Lyubka 94f63787bb Restored void * parameter for iterate_over_connections() 2014-03-24 16:01:45 +00:00
Sergey Lyubka 367f5df328 match_prefix -> mg_match_prefix 2014-03-24 16:00:17 +00:00
Sergey Lyubka f096138d6e Added release note 2014-03-23 20:02:41 +00:00
Sergey Lyubka 0d00cd51e6 Fix #356 2014-03-23 19:59:03 +00:00
Sergey Lyubka b216210a13 Moving lua server side to server.c 2014-03-23 15:33:39 +00:00
Sergey Lyubka 166833f330 Added release notes 2014-03-21 11:47:52 +00:00
Sergey Lyubka 4d6bedfd4e Merge branch 'master' of ssh://github.com/valenok/mongoose 2014-03-20 15:01:18 +00:00
Sergey Lyubka ace8c1736c Added mg_load_dll() 2014-03-20 15:01:05 +00:00
Sergey Lyubka c658a54d18 changed set_absolute_path() signature 2014-03-20 14:58:37 +00:00
Sergey Lyubka 781a1dc25e Merge pull request #352 from ranzhengyuan/some-idea
I think that when the socket invalid, the return value should be -1.
2014-03-20 10:34:18 +00:00
冉正源 3ea3b8dfa4 I think that the socket is invalid, the return should be -1. 2014-03-19 22:32:41 +08:00
Sergey Lyubka a514e143ff updated faw and tutorials 2014-03-19 11:41:01 +00:00
Sergey Lyubka e1486a79e3 Merge pull request #350 from solomonhuang/nodav
Remove MONGOOSE_NO_DAV on DAV_AUTH_FILE options
2014-03-19 11:25:15 +00:00
Sergey Lyubka ee615248e3 Merge pull request #351 from da4089/master
Tyop fix.
2014-03-19 09:33:58 +00:00
David Arnold 687e0e2ee8 Tyop fix. 2014-03-19 04:49:47 +00:00
Solomon Huang 19aefcb7dd Remove MONGOOSE_NO_DAV on DAV_AUTH_FILE options
Building with -DMONGOOSE_NO_DAV will fail.
2014-03-19 01:53:02 +08:00
Sergey Lyubka 6a46244a21 embedding guide for MG_POLL fixed 2014-03-14 08:19:54 +00:00
Sergey Lyubka 60674c11c9 API docs regarding MG_POLL changed 2014-03-13 12:23:53 +00:00
Sergey Lyubka 91c9ab807b Forwarding POST data to the CGI process 2014-03-12 22:43:04 +00:00
Sergey Lyubka 9231c7346c match_prefix -> mg_match_prefix 2014-03-12 18:35:36 +00:00
Sergey Lyubka 20cb3a823a Added ecos & qnx 2014-03-12 14:19:36 +00:00
Sergey Lyubka cbd8d69e6d Added hello world for Lua 2014-03-12 12:47:41 +00:00
Sergey Lyubka f7fcfa6a42 Fixed C# example to work with 5.3 2014-03-12 12:31:53 +00:00
Sergey Lyubka 293c5e5852 Moved screenshots down 2014-03-11 16:59:17 +00:00
Sergey Lyubka ceb866b4ee Using img tags for screenshots 2014-03-11 16:57:38 +00:00
Sergey Lyubka 2f9166e96e Added screenshots for mongoose 2014-03-11 16:51:54 +00:00
Sergey Lyubka fe0e0e69e5 File sharing tutorial wording 2014-03-11 15:36:23 +00:00
Sergey Lyubka db96641c10 Added logo 2014-03-11 06:13:59 +00:00
Sergey Lyubka fe83928ca4 Added logo 2014-03-11 06:11:56 +00:00
Sergey Lyubka 014414f17f Docs links made separate 2014-03-11 06:07:06 +00:00
Sergey Lyubka 6ffe2d7f7a Typo fixed in readme 2014-03-11 06:04:44 +00:00
Sergey Lyubka 30c82d7efe Wording in README changed 2014-03-11 06:03:20 +00:00
Sergey Lyubka 999c4ad26c 5.3 -> 5.4 2014-03-10 17:02:00 +00:00
32 changed files with 2280 additions and 1021 deletions

No files matched your search

+52 -29
View File
@@ -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) * [Mailing list](http://groups.google.com/group/mongoose-users)
* [Downloads & Documentation](http://cesanta.com/mongoose.shtml) * [Downloads](http://cesanta.com/mongoose.shtml)
* [How to use Lua Server Pages](http://cesanta.com/docs/Lua.shtml) * [Documentation](http://cesanta.com/docs.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)
# Features # Features
- Works on Windows, Mac, UNIX/Linux, iPhone, Android, and many other platforms - Works on Windows, Mac, UNIX/Linux, iPhone, Android eCos, QNX
- CGI, SSI, SSL, Digest auth, Websocket, WEbDAV, Resumed download, URL rewrite, file blacklist, Custom error pages, Virtual hosts, IP-based ACL, Windows service and many other platforms
- Scripting and database support ([Lua](http://lua.org) + - CGI, SSI, SSL, Digest auth, Websocket, WEbDAV, Resumed download,
[Sqlite](http://sqlite.org), see URL rewrite, file blacklist
[dirscan.lp](https://github.com/cesanta/mongoose/blob/master/examples/lua/dirscan.lp) ), - Custom error pages, Virtual hosts, IP-based ACL, Windows service,
which provides ready to go, powerful web development platform in HTTP/HTTPS client
one single-click executable with no dependencies
- Simple and clean - Simple and clean
[embedding API](https://github.com/cesanta/mongoose/blob/master/mongoose.h). [embedding API](https://github.com/cesanta/mongoose/blob/master/mongoose.h).
The source is in single The source is in single
[mongoose.c](https://github.com/cesanta/mongoose/blob/master/mongoose.c) file [mongoose.c](https://github.com/cesanta/mongoose/blob/master/mongoose.c) file
to make embedding easy to make embedding easy
- Extremely lightweight, has a core of under 40kB and tiny runtime footprint - Extremely lightweight, has a core of under 40kB and tiny runtime footprint
- Asyncronouns, non-blocking core supporting single- or multi-threaded usage - Asynchronous, non-blocking core supporting single- or multi-threaded usage
- On the market since 2004, stable, mature and tested, - On the market since 2004 with over 1 million cumulative downloads
has several man-years invested in continuous improvement and refinement - Stable, mature and tested, has several man-years invested
- Professional support and consultancy available from in continuous improvement and refinement
[Cesanta Software](http://cesanta.com), developer of Mongoose
# Screenshots
Download, double-click to start, run browser -- that's all!
![shot1](http://cesanta.com/images/tut_sharing/tut1.png)
![shot2](http://cesanta.com/images/tut_sharing/tut2.png)
![shot3](http://cesanta.com/images/tut_sharing/tut3.png)
![shot4](http://cesanta.com/images/tut_sharing/tut4.png)
# Acknowledgements # Acknowledgements
@@ -50,14 +64,23 @@ F.Morenius, and 10 others.
# Licensing # Licensing
Mongoose is released under Mongoose is released under commercial and
[GNU GPL v.2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html). [GNU GPL v.2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html) open
Businesses have an option to get non-restrictive, royalty-free commercial source licenses. The GPLv2 open source License does not generally permit
license and professional support from incorporating this software into non-open source programs.
[Cesanta Software](http://cesanta.com). 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), # Other products by Cesanta Software: simple and effective
[Super Light Regular Expression library](https://github.com/cesanta/slre),
[Super Light DNS Resolver](https://github.com/cesanta/sldr) - [SSL Wrapper](https://github.com/cesanta/ssl_wrapper) - application to
are other projects by Cesanta Software, developed with the same philosophy secure network communications
of functionality and simplicity. - [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
View File
@@ -71,23 +71,23 @@ occur. Sequence of events for the accepted connection is this:
certain prefix, and let Mongoose serve all static files. certain prefix, and let Mongoose serve all static files.
If event handler decides to serve the request, but doesn't have 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 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 `mg_connection::connection_param` pointer is a placeholder to keep
user-specific data. For example, handler could decide to open a DB user-specific data. For example, handler could decide to open a DB
connection and store DB connection handle in `connection_param`. connection and store DB connection handle in `connection_param`.
* `MG_POLL` is sent only to those connections which returned `MG_MORE`. * `MG_POLL` is sent to every connection on every iteration of
Event handler should try to complete the reply. If reply is completed, `mg_poll_server()`. Event handler should return `MG_FALSE` to ignore
then event handler should return `MG_TRUE`. Otherwise, it should this event. If event handler returns `MG_TRUE`, then Mongoose assumes
return `MG_FALSE`, and polling will continue until that event handler has finished sending data, and Mongoose will
handler returns `MG_TRUE`. close the connection.
* `MG_HTTP_ERROR` sent when Mongoose is about to send HTTP error back * `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 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 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 * `MG_CLOSE` is sent when the connection is closed. This event is used
to cleanup per-connection state stored in `connection_param` 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: 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, Connection status is held in `mg_connection::status_code`: if zero,
then connection was successful, otherwise connection was not established. then connection was successful, otherwise connection was not established.
User should send a request upon successful connection. 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. * `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. * `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 value is guaranteed to be non-NULL. If parameter is not set, zero-length string
is returned. 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); 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 is an interface primarily designed to push arbitrary data to websocket This function is designed to push data to the connected clients, and
connections at any time. This function could be called from the Mongoose thread can be called from any thread. There is a limitation on the length of
only. When it returns, Mongoose thread calls `func()` for each active the message, currently at 8 kilobytes.
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.
void mg_send_status(struct mg_connection *, int status_code); void mg_send_status(struct mg_connection *, int status_code);
void mg_send_header(struct mg_connection *, const char *name, 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. 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, int mg_websocket_write(struct mg_connection* conn, int opcode,
const char *data, size_t data_len); const char *data, size_t data_len);
+2 -2
View File
@@ -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`: ## 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
![screenshot](http://cesanta.com/images/tut_basic/tut6.png) ![screenshot](http://cesanta.com/images/tut_basic/tut6.png)
## 7. Click on the mongoose icon and choose "Start browser" menu: ## 7. Click on the mongoose icon and choose "Go to my address" menu:
![screenshot](http://cesanta.com/images/tut_basic/tut7.png) ![screenshot](http://cesanta.com/images/tut_basic/tut7.png)
## 8. A browser will popup displaying `index.html` file. Now, you can expand your website by adding more content. ## 8. A browser will popup displaying `index.html` file. Now, you can expand your website by adding more content.
+13 -7
View File
@@ -71,16 +71,20 @@ The sequence of events for every connection is this:
certain prefix, and let Mongoose serve all static files. certain prefix, and let Mongoose serve all static files.
If event handler decides to serve the request, but doesn't have 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 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 `mg_connection::connection_param` pointer is a placeholder to keep
user-specific data. For example, handler could decide to open a DB user-specific data. For example, handler could decide to open a DB
connection and store DB connection handle in `connection_param`. connection and store DB connection handle in `connection_param`.
* `MG_POLL` is sent only to those connections which returned `MG_MORE`. * `MG_POLL` is sent to every connection on every iteration of
Event handler should try to complete the reply. If reply is completed, `mg_poll_server()`. Event handler should return `MG_FALSE` to ignore
then event handler should return `MG_TRUE`. Otherwise, it should this event. If event handler returns `MG_TRUE`, then Mongoose assumes
return `MG_FALSE`, and polling will continue until that event handler has finished sending data, and Mongoose will
handler returns `MG_TRUE`. 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 * `MG_CLOSE` is sent when the connection is closed. This event is used
to cleanup per-connection state stored in `connection_param` to cleanup per-connection state stored in `connection_param`
if it was allocated. 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) * [upload.c](https://github.com/cesanta/mongoose/blob/master/examples/post.c)
shows how to upload files shows how to upload files
* [websocket.c](https://github.com/cesanta/mongoose/blob/master/examples/websocket.c) demonstrates websocket usage * [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 * [mjpg.c](https://github.com/cesanta/mongoose/blob/master/examples/mjpg.c) demonstrates MJPEG streaming implementation
## Compilation flags ## 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_STACK_SIZE=X Sets stack size to X for ns_start_thread()
-DNS_DISABLE_THREADS Disable threads support -DNS_DISABLE_THREADS Disable threads support
-DNS_DISABLE_SOCKETPAIR For systems without loopback interface -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
View File
@@ -1,6 +1,28 @@
# Mongoose FAQ # 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, 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 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 -cgi_interpreter /full/path/to/php-cgi
### Mongoose fails to start ## Mongoose fails to start
If Mongoose exits immediately when run, this If Mongoose exits immediately when run, this
usually indicates a syntax error in the configuration file usually indicates a syntax error in the configuration file
+4 -5
View File
@@ -5,15 +5,14 @@ How To Share Files With Mongoose
![screenshot](http://cesanta.com/images/tut_sharing/tut1.png) ![screenshot](http://cesanta.com/images/tut_sharing/tut1.png)
## 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:
![screenshot](http://cesanta.com/images/tut_sharing/tut2.png) ![screenshot](http://cesanta.com/images/tut_sharing/tut2.png)
## 3. Click on the mongoose icon and choose "Start browser" menu: ## 3. Click on the mongoose icon
![screenshot](http://cesanta.com/images/tut_sharing/tut3.png) ![screenshot](http://cesanta.com/images/tut_sharing/tut3.png)
## 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:
![screenshot](http://cesanta.com/images/tut_sharing/tut4.png) ![screenshot](http://cesanta.com/images/tut_sharing/tut4.png)
## 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
View File
@@ -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 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 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 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
more about subnet masks, see the 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) [Wikipedia page on Subnetwork](http://en.wikipedia.org/wiki/Subnetwork)
Default: not set, all accesses are allowed. 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: `mongoose -hide_files_patterns secret.txt|even_more_secret.txt`. Default:
not set. not set.
### idle\_timeout\_ms
Timeout for idle connections in milliseconds. Default: `30000` (30 seconds)
### index_files ### index_files
Comma-separated list of files to be treated as directory index Comma-separated list of files to be treated as directory index
files. Default: `index.html,index.htm,index.cgi,index.shtml,index.php` files. Default: `index.html,index.htm,index.cgi,index.shtml,index.php`
+1 -1
View File
@@ -40,7 +40,7 @@ How To Create A PHP Website With Mongoose
![screenshot](http://cesanta.com/images/tut_php/tut10.png) ![screenshot](http://cesanta.com/images/tut_php/tut10.png)
## 11. Click on the mongoose icon and choose "Start browser" menu: ## 11. Click on the mongoose icon and choose "Go to my address" menu:
![screenshot](http://cesanta.com/images/tut_php/tut11.png) ![screenshot](http://cesanta.com/images/tut_php/tut11.png)
+168
View File
@@ -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
View File
@@ -12,6 +12,8 @@ ifeq ($(OS),Windows_NT)
CFLAGS += $(CFLAGS_EXTRA) CFLAGS += $(CFLAGS_EXTRA)
else else
UNAME_S := $(shell uname -s) UNAME_S := $(shell uname -s)
CC = g++
CFLAGS += -lssl -g -O0
ifeq ($(UNAME_S),Linux) ifeq ($(UNAME_S),Linux)
CFLAGS += -ldl CFLAGS += -ldl
@@ -48,15 +50,29 @@ upload: upload.c ../mongoose.c
auth: auth.c ../mongoose.c auth: auth.c ../mongoose.c
$(CC) auth.c ../mongoose.c $(OUT) $(CFLAGS) $(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 mjpg: mjpg.c ../mongoose.c
$(CC) mjpg.c ../mongoose.c $(OUT) $(CFLAGS) $(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 websocket_html.c: websocket.html
perl mkdata.pl $< > $@ perl mkdata.pl $< > $@
u: u:
g++ unit_test.c -Wall -W -pedantic -lssl -g -O0 $(CFLAGS_EXTRA) && ./a.out $(CC) unit_test.c $(OUT) $(CFLAGS)
./$@
clean: 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
+88
View File
@@ -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
View File
@@ -2,36 +2,42 @@
// https://github.com/cesanta/mongoose // https://github.com/cesanta/mongoose
using System; using System;
using System.Runtime.InteropServices;
public class Program { public class Program {
static private int EventHandler(MongooseEvent ev) { static private int EventHandler(IntPtr conn_ptr, int ev) {
if (ev.type != 1) { MongooseConnection conn = (MongooseConnection)
return 0; // Mark as unhandled System.Runtime.InteropServices.Marshal.PtrToStructure(
} conn_ptr , typeof(MongooseConnection));
MongooseRequestInfo request_info = (MongooseRequestInfo) if (ev == 102) {
Marshal.PtrToStructure(ev.request_info, typeof(MongooseRequestInfo)); // MG_AUTH
return 1;
if (request_info.uri != "/test") { } else if (ev == 103) {
return 0; // Mark as unhandled // MG_REQUEST
} Mongoose.send_data(conn_ptr, "Hello from C#!\n");
Mongoose.send_data(conn_ptr, "URI: " + conn.uri + "\n");
Mongoose.write(ev.conn, "HTTP/1.1 200 OK\r\n\r\n"); Mongoose.send_data(conn_ptr, "HTTP Headers:\n");
Mongoose.write(ev.conn, "Hello from C#!\n");
for (int i = 0; i < conn.num_headers; i++) {
return 1; // Mark as handled 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() { static void Main() {
Mongoose web_server = new Mongoose(".", "9000", Mongoose web_server = new Mongoose(".", "9001",
new MongooseEventHandler(EventHandler)); new MongooseEventHandler(EventHandler));
Console.WriteLine("Mongoose v." + web_server.version_ + " started."); Console.WriteLine("Mongoose started, press Ctrl-C to exit.");
Console.WriteLine("Press enter to exit program."); for (;;) {
web_server.poll(1000);
// Serve requests until user presses "enter" on a keyboard }
Console.ReadLine();
web_server.stop();
} }
} }
+40 -65
View File
@@ -9,85 +9,60 @@ using System.Runtime.InteropServices;
[MarshalAs(UnmanagedType.LPTStr)] public IntPtr value; [MarshalAs(UnmanagedType.LPTStr)] public IntPtr value;
}; };
// mongoose.h :: struct mg_request_info // mongoose.h :: struct mg_connection
[StructLayout(LayoutKind.Sequential)] public struct MongooseRequestInfo { [StructLayout(LayoutKind.Sequential)] public struct MongooseConnection {
[MarshalAs(UnmanagedType.LPTStr)] public string request_method; [MarshalAs(UnmanagedType.LPTStr)] public string request_method;
[MarshalAs(UnmanagedType.LPTStr)] public string uri; [MarshalAs(UnmanagedType.LPTStr)] public string uri;
[MarshalAs(UnmanagedType.LPTStr)] public string http_version; [MarshalAs(UnmanagedType.LPTStr)] public string http_version;
[MarshalAs(UnmanagedType.LPTStr)] public string query_string; [MarshalAs(UnmanagedType.LPTStr)] public string query_string;
[MarshalAs(UnmanagedType.LPTStr)] public string remote_user;
public int remote_ip; [MarshalAs(UnmanagedType.ByValArray,SizeConst=48)] public char[] remote_ip;
public int remote_port; [MarshalAs(UnmanagedType.LPTStr)] public string local_ip;
public int is_ssl; [MarshalAs(UnmanagedType.U2)] public short remote_port;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=64)] [MarshalAs(UnmanagedType.U2)] public short local_port;
[MarshalAs(UnmanagedType.SysInt)] public int num_headers;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=30)]
public MongooseHeader[] http_headers; 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 delegate int MongooseEventHandler(IntPtr c, int ev);
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 class Mongoose { public class Mongoose {
public const string dll_name_ = "mongoose"; public const string dll_ = "mongoose";
public string version_ = "??"; private IntPtr server_;
// These are here to store a ref to the callbacks [DllImport(dll_)] private static extern IntPtr
// while they are over in unmanaged code, to prevent garbage collection. mg_create_server(IntPtr user_data, MongooseEventHandler eh);
private event MongooseEventHandlerN delegates; [DllImport(dll_)] private static extern int
mg_poll_server(IntPtr server, int milli);
private IntPtr ctx_; [DllImport(dll_)] private static extern IntPtr
mg_set_option(IntPtr server, string name, string value);
[DllImport(dll_name_)] private static extern [DllImport(dll_)] public static extern int
IntPtr mg_start([MarshalAs(UnmanagedType.LPArray, mg_send_data(IntPtr conn, string data, int length);
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);
public Mongoose(string document_root, public Mongoose(string document_root,
string listening_ports, string listening_port,
MongooseEventHandler event_handler) { MongooseEventHandler event_handler) {
version_ = Marshal.PtrToStringAnsi(mg_version()); server_ = mg_create_server(IntPtr.Zero, event_handler);
mg_set_option(server_, "document_root", document_root);
string[] options = { mg_set_option(server_, "listening_port", listening_port);
"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);
} }
public static int write(IntPtr conn, string data) { public static int send_data(IntPtr conn, string data) {
return mg_write(conn, data, data.Length); return mg_send_data(conn, data, data.Length);
} }
public void stop() { public void poll(int milli) {
if (this.ctx_ != IntPtr.Zero) { mg_poll_server(server_, milli);
mg_stop(this.ctx_);
}
this.ctx_ = IntPtr.Zero;
}
~Mongoose() {
stop();
} }
// TODO: add destructor and call mg_destroy_server()
} }
+50
View File
@@ -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-----
+46
View File
@@ -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
View File
@@ -1,47 +1,22 @@
#include <stdio.h>
#include <string.h>
#include "mongoose.h" #include "mongoose.h"
static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
static int index_html(struct mg_connection *conn) { switch (ev) {
FILE *fp = (FILE *) conn->connection_param; case MG_REQUEST:
char buf[200]; mg_send_file(conn, "file.c");
size_t n = 0; return MG_MORE; // It is important to return MG_MORE after mg_send_file!
case MG_AUTH: return MG_TRUE;
if (fp == NULL) { default: return MG_FALSE;
fp = fopen("../mongoose.c", "r");
conn->connection_param = (void *) fp;
} }
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) { int main(void) {
struct mg_server *server; struct mg_server *server = mg_create_server(NULL, ev_handler);
// Create and configure the server
server = mg_create_server(NULL);
mg_set_option(server, "listening_port", "8080"); 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")); printf("Starting on port %s\n", mg_get_option(server, "listening_port"));
for (;;) { for (;;) mg_poll_server(server, 1000);
mg_poll_server(server, 1000);
}
// Cleanup, and free server instance
mg_destroy_server(&server); mg_destroy_server(&server);
return 0; return 0;
} }
+81
View File
@@ -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;
}
+4
View File
@@ -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
View File
@@ -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) { if (stat(path, &st) == 0 && (fp = fopen(path, "rb")) != NULL) {
mg_printf(conn, "--myboundary\r\nContent-Type: image/jpeg\r\n" 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) { while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) {
mg_write(conn, buf, n); mg_write(conn, buf, n);
} }
+199
View File
@@ -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;
}
+23
View File
@@ -0,0 +1,23 @@
<html>
<head>
<title>App1 Index</title>
<style>
img { height: 40px; }
</style>
</head>
<body>
<h1>App1 index page. Served locally from the the proxy server filesystem</h1>
<p>image that references non-existent local resource. Forwarded to
the 'real' proxy target:</p>
<img src="http://cesanta.com/images/logo.png" />
<p>Google logo via HTTPS (external resource, served by remote host):</p>
<img src="https://www.google.ie/images/srpr/logo11w.png" />
<p>Same image via HTTP:</p>
<img src="http://www.google.ie/images/srpr/logo11w.png" />
</body>
</html>
+37
View File
@@ -0,0 +1,37 @@
<html>
<head>
<title>App2 Index</title>
<meta charset="utf-8">
<script>
window.onload = function() {
// Using secure websocket connection, wss://
var ws = new WebSocket('wss://echo.websocket.org');
var div = document.getElementById('events');
ws.onmessage = function(ev) {
var el = document.createElement('div');
el.innerHTML = 'websocket message: ' + ev.data;
div.appendChild(el);
// Keep only last 5 messages in the list
while (div.childNodes.length > 5) div.removeChild(div.firstChild);
};
// Send random stuff to the websocket connection periodically.
// websocket server much echo that stuff back.
window.setInterval(function() {
var d = new Date();
ws.send(d.toString());
}, 1000);
};
</script>
</head>
<body>
<h1>App2 index page. Served locally from the
the proxy's filesystem.</h1>
<p>
Following div shows proxy forwarding of websocket connection, served by
ws://echo.websocket.org:
</p>
<div id="events"></div>
</body>
</html>
+29
View File
@@ -0,0 +1,29 @@
<html>
<head>
<title> proxy index </title>
<script type="text/javascript">
window.onload = function() {
var es = new EventSource("/api/sse");
var div = document.getElementById('events');
es.onmessage = function(ev) {
var el = document.createElement('div');
el.innerHTML = 'sse message: ' + ev.data;
div.appendChild(el);
// Keep only last 5 messages in the list
while (div.childNodes.length > 5) div.removeChild(div.firstChild);
};
};
</script>
</head>
<body>
<h1> proxy index page.</h1>
<ul>
<li><a href="app1">App1</a> - App1 root</li>
<li><a href="app2">App2</a> - App2 root</li>
</ul>
<h2>SSE pushes, done by separate threads at random times:</h2>
<div id="events"></div>
</body>
</html>
+98
View File
@@ -0,0 +1,98 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>WebSocket Test</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type="text/css">
body {
background-color: #cde; margin: 0;
padding: 0; font: 14px Helvetica, Arial, sans-serif;
}
div.content {
width: 800px; margin: 2em auto; padding: 20px 50px;
background-color: #fff; border-radius: 1em;
}
#messages {
border: 2px solid #fec; border-radius: 1em;
height: 10em; overflow: scroll; padding: 0.5em 1em;
}
a:link, a:visited { color: #69c; text-decoration: none; }
@media (max-width: 700px) {
body { background-color: #fff; }
div.content {
width: auto; margin: 0 auto; border-radius: 0;
padding: 1em;
}
}
</style>
<script language="javascript" type="text/javascript">
var rooms = [];
var ws = new WebSocket('ws://' + location.host + '/ws');
if (!window.console) { window.console = { log: function() {} } };
ws.onopen = function(ev) { console.log(ev); };
ws.onerror = function(ev) { console.log(ev); };
ws.onclose = function(ev) { console.log(ev); };
ws.onmessage = function(ev) {
console.log(ev);
var m = (ev.data || '').match(/^(\S+) (.+)/);
if (m[1] == 'id') {
document.getElementById('my_id').innerText = m[2];
} else if (m[1] == 'msg') {
var div = document.createElement('div');
div.innerHTML = m[2];
document.getElementById('messages').appendChild(div);
}
};
window.onload = function() {
document.getElementById('send_button').onclick = function(ev) {
var msg = document.getElementById('send_input').value;
ws.send('msg ' + msg);
};
document.getElementById('room_sel').onchange = function(ev) {
var roomName = this.value || '?';
ws.send('join ' + roomName);
};
};
</script>
</head>
<body>
<div class="content">
<h1>Websocket PubSub Demonstration</h1>
<p>
This page demonstrates how Mongoose web server could be used to implement
<a href="http://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern">
publish–subscribe pattern</a>. Open this page in several browser
windows. Each window initiates persistent
<a href="http://en.wikipedia.org/wiki/WebSocket">WebSocket</a>
connection with Mongoose, making each browser window a websocket client.
Join a room, send messages, and see messages sent by other clients.
</p>
<p>
My ID: <b><span id="my_id"></b></span>
</p>
<p>
Join room: <select id="room_sel">
<option value="">-- select room -- </option>
<option>A</option>
<option>B</option>
</select>
</p>
<div id="messages">
</div>
<p>
<input type="text" id="send_input" />
<button id="send_button">Send Message</button>
</p>
</div>
</body>
</html>
+52 -29
View File
@@ -67,6 +67,11 @@ typedef struct _stat file_stat_t;
typedef struct stat file_stat_t; typedef struct stat file_stat_t;
#include <sys/wait.h> #include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#ifdef IOS
#include <ifaddrs.h>
#endif
#define DIRSEP '/' #define DIRSEP '/'
#define __cdecl #define __cdecl
#define abs_path(rel, abs, abs_size) realpath((rel), (abs)) #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_OPTIONS 100
#define MAX_CONF_FILE_LINE_SIZE (8 * 1024) #define MAX_CONF_FILE_LINE_SIZE (8 * 1024)
#ifndef MVER
#define MVER MONGOOSE_VERSION
#endif
static int exit_flag; static int exit_flag;
static char server_name[50]; // Set by init_server_name() 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 struct mg_server *server; // Set by start_mongoose()
static const char *s_default_document_root = "."; static const char *s_default_document_root = ".";
static const char *s_default_listening_port = "8080"; static const char *s_default_listening_port = "8080";
static char **s_argv = { NULL };
static void set_options(char *argv[]);
#if !defined(CONFIG_FILE) #if !defined(CONFIG_FILE)
#define CONFIG_FILE "mongoose.conf" #define CONFIG_FILE "mongoose.conf"
@@ -131,7 +143,7 @@ static void show_usage_and_exit(void) {
int i; int i;
fprintf(stderr, "Mongoose version %s (c) Sergey Lyubka, built on %s\n", fprintf(stderr, "Mongoose version %s (c) Sergey Lyubka, built on %s\n",
MONGOOSE_VERSION, __DATE__); MVER, __DATE__);
fprintf(stderr, "Usage:\n"); fprintf(stderr, "Usage:\n");
#ifndef MONGOOSE_NO_AUTH #ifndef MONGOOSE_NO_AUTH
fprintf(stderr, " mongoose -A <htpasswd_file> <realm> <user> <passwd>\n"); 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) { 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; FILE *fp = NULL;
size_t i, cmd_line_opts_start = 1, line_no = 0; size_t i, cmd_line_opts_start = 1, line_no = 0;
// Should we use a config file ? // Should we use a config file ?
if (argv[1] != NULL && argv[1][0] != '-') { 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; cmd_line_opts_start = 2;
} else if ((p = strrchr(argv[0], DIRSEP)) == NULL) { } else if ((p = strrchr(argv[0], DIRSEP)) == NULL) {
// No command line flags specified. Look where binary lives // 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 { } 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); (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 config file was set in command line and open failed, die
if (cmd_line_opts_start == 2 && fp == NULL) { 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 // Load config file settings first
if (fp != NULL) { 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 // Loop over the lines in config file
while (fgets(line, sizeof(line), fp) != NULL) { 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) { if (sscanf(line, "%s %[^\r\n#]", opt, val) != 2) {
printf("%s: line %d is invalid, ignoring it:\n %s", printf("%s: line %d is invalid, ignoring it:\n %s",
config_file, (int) line_no, line); s_config_file, (int) line_no, line);
} else { } else {
set_option(options, opt, val); 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) { static void init_server_name(void) {
const char *descr = ""; const char *descr = "";
snprintf(server_name, sizeof(server_name), "Mongoose web server v.%s%s", 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) { static int is_path_absolute(const char *path) {
@@ -269,6 +283,14 @@ static char *get_option(char **options, const char *option_name) {
return NULL; 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) { static int path_exists(const char *path, int is_dir) {
file_stat_t st; file_stat_t st;
return path == NULL || (stat(path, &st) == 0 && 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, static void set_absolute_path(char *options[], const char *option_name) {
const char *path_to_mongoose_exe) {
char path[PATH_MAX], abs[PATH_MAX], *option_value; char path[PATH_MAX], abs[PATH_MAX], *option_value;
const char *p; 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 // Not absolute. Use the directory where mongoose executable lives
// be the relative directory for everything. // be the relative directory for everything.
// Extract mongoose executable directory into path. // 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)); getcwd(path, sizeof(path));
} else { } else {
snprintf(path, sizeof(path), "%.*s", (int) (p - path_to_mongoose_exe), snprintf(path, sizeof(path), "%.*s", (int) (p - s_config_file),
path_to_mongoose_exe); s_config_file);
} }
strncat(path, "/", sizeof(path) - 1); strncat(path, "/", sizeof(path) - 1);
@@ -380,9 +401,7 @@ int modify_passwords_file(const char *fname, const char *domain,
#endif #endif
static void start_mongoose(int argc, char *argv[]) { static void start_mongoose(int argc, char *argv[]) {
char *options[MAX_OPTIONS]; s_argv = argv;
int i;
if ((server = mg_create_server(NULL, EV_HANDLER)) == NULL) { if ((server = mg_create_server(NULL, EV_HANDLER)) == NULL) {
die("%s", "Failed to start Mongoose."); 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"))) { if (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) {
show_usage_and_exit(); show_usage_and_exit();
} }
set_options(argv);
}
static void set_options(char *argv[]) {
char *options[MAX_OPTIONS];
int i;
options[0] = NULL; options[0] = NULL;
set_option(options, "document_root", s_default_document_root); 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 // Make sure we have absolute paths for files and directories
// https://github.com/valenok/mongoose/issues/181 // https://github.com/valenok/mongoose/issues/181
set_absolute_path(options, "document_root", argv[0]); set_absolute_path(options, "document_root");
set_absolute_path(options, "dav_auth_file", argv[0]); set_absolute_path(options, "dav_auth_file");
set_absolute_path(options, "cgi_interpreter", argv[0]); set_absolute_path(options, "cgi_interpreter");
set_absolute_path(options, "access_log_file", argv[0]); set_absolute_path(options, "access_log_file");
set_absolute_path(options, "global_auth_file", argv[0]); set_absolute_path(options, "global_auth_file");
set_absolute_path(options, "ssl_certificate", argv[0]); set_absolute_path(options, "ssl_certificate");
if (!path_exists(get_option(options, "document_root"), 1)) { if (!path_exists(get_option(options, "document_root"), 1)) {
set_option(options, "document_root", s_default_document_root); 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]", notify("Setting document_root to [%s]",
mg_get_option(server, "document_root")); mg_get_option(server, "document_root"));
} }
@@ -472,9 +497,7 @@ int main(int argc, char *argv[]) {
server_name, mg_get_option(server, "document_root"), server_name, mg_get_option(server, "document_root"),
mg_get_option(server, "listening_port")); mg_get_option(server, "listening_port"));
fflush(stdout); // Needed, Windows terminals might not be line-buffered fflush(stdout); // Needed, Windows terminals might not be line-buffered
while (exit_flag == 0) { serving_thread_func(server);
mg_poll_server(server, 1000);
}
printf("Exiting on signal %d ...", exit_flag); printf("Exiting on signal %d ...", exit_flag);
fflush(stdout); fflush(stdout);
mg_destroy_server(&server); mg_destroy_server(&server);
+46
View File
@@ -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
View File
@@ -166,34 +166,34 @@ static const char *test_should_keep_alive(void) {
} }
static const char *test_match_prefix(void) { static const char *test_match_prefix(void) {
ASSERT(match_prefix("/api", 4, "/api") == 4); ASSERT(mg_match_prefix("/api", 4, "/api") == 4);
ASSERT(match_prefix("/a/", 3, "/a/b/c") == 3); ASSERT(mg_match_prefix("/a/", 3, "/a/b/c") == 3);
ASSERT(match_prefix("/a/", 3, "/ab/c") == -1); ASSERT(mg_match_prefix("/a/", 3, "/ab/c") == -1);
ASSERT(match_prefix("/*/", 3, "/ab/c") == 4); ASSERT(mg_match_prefix("/*/", 3, "/ab/c") == 4);
ASSERT(match_prefix("**", 2, "/a/b/c") == 6); ASSERT(mg_match_prefix("**", 2, "/a/b/c") == 6);
ASSERT(match_prefix("/*", 2, "/a/b/c") == 2); ASSERT(mg_match_prefix("/*", 2, "/a/b/c") == 2);
ASSERT(match_prefix("*/*", 3, "/a/b/c") == 2); ASSERT(mg_match_prefix("*/*", 3, "/a/b/c") == 2);
ASSERT(match_prefix("**/", 3, "/a/b/c") == 5); ASSERT(mg_match_prefix("**/", 3, "/a/b/c") == 5);
ASSERT(match_prefix("**.foo|**.bar", 13, "a.bar") == 5); ASSERT(mg_match_prefix("**.foo|**.bar", 13, "a.bar") == 5);
ASSERT(match_prefix("a|b|cd", 6, "cdef") == 2); ASSERT(mg_match_prefix("a|b|cd", 6, "cdef") == 2);
ASSERT(match_prefix("a|b|c?", 6, "cdef") == 2); ASSERT(mg_match_prefix("a|b|c?", 6, "cdef") == 2);
ASSERT(match_prefix("a|?|cd", 6, "cdef") == 1); ASSERT(mg_match_prefix("a|?|cd", 6, "cdef") == 1);
ASSERT(match_prefix("/a/**.cgi", 9, "/foo/bar/x.cgi") == -1); ASSERT(mg_match_prefix("/a/**.cgi", 9, "/foo/bar/x.cgi") == -1);
ASSERT(match_prefix("/a/**.cgi", 9, "/a/bar/x.cgi") == 12); ASSERT(mg_match_prefix("/a/**.cgi", 9, "/a/bar/x.cgi") == 12);
ASSERT(match_prefix("**/", 3, "/a/b/c") == 5); ASSERT(mg_match_prefix("**/", 3, "/a/b/c") == 5);
ASSERT(match_prefix("**/$", 4, "/a/b/c") == -1); ASSERT(mg_match_prefix("**/$", 4, "/a/b/c") == -1);
ASSERT(match_prefix("**/$", 4, "/a/b/") == 5); ASSERT(mg_match_prefix("**/$", 4, "/a/b/") == 5);
ASSERT(match_prefix("$", 1, "") == 0); ASSERT(mg_match_prefix("$", 1, "") == 0);
ASSERT(match_prefix("$", 1, "x") == -1); ASSERT(mg_match_prefix("$", 1, "x") == -1);
ASSERT(match_prefix("*$", 2, "x") == 1); ASSERT(mg_match_prefix("*$", 2, "x") == 1);
ASSERT(match_prefix("/$", 2, "/") == 1); ASSERT(mg_match_prefix("/$", 2, "/") == 1);
ASSERT(match_prefix("**/$", 4, "/a/b/c") == -1); ASSERT(mg_match_prefix("**/$", 4, "/a/b/c") == -1);
ASSERT(match_prefix("**/$", 4, "/a/b/") == 5); ASSERT(mg_match_prefix("**/$", 4, "/a/b/") == 5);
ASSERT(match_prefix("*", 1, "/hello/") == 0); ASSERT(mg_match_prefix("*", 1, "/hello/") == 0);
ASSERT(match_prefix("**.a$|**.b$", 11, "/a/b.b/") == -1); ASSERT(mg_match_prefix("**.a$|**.b$", 11, "/a/b.b/") == -1);
ASSERT(match_prefix("**.a$|**.b$", 11, "/a/b.b") == 6); ASSERT(mg_match_prefix("**.a$|**.b$", 11, "/a/b.b") == 6);
ASSERT(match_prefix("**.a$|**.b$", 11, "/a/B.A") == 6); ASSERT(mg_match_prefix("**.a$|**.b$", 11, "/a/B.A") == 6);
ASSERT(match_prefix("**o$", 4, "HELLO") == 5); ASSERT(mg_match_prefix("**o$", 4, "HELLO") == 5);
return NULL; return NULL;
} }
@@ -271,6 +271,17 @@ static const char *test_url_decode(void) {
return NULL; 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) { static const char *test_to64(void) {
ASSERT(to64("0") == 0); ASSERT(to64("0") == 0);
ASSERT(to64("") == 0); ASSERT(to64("") == 0);
@@ -498,6 +509,7 @@ static const char *run_all_tests(void) {
RUN_TEST(test_parse_http_message); RUN_TEST(test_parse_http_message);
RUN_TEST(test_to64); RUN_TEST(test_to64);
RUN_TEST(test_url_decode); RUN_TEST(test_url_decode);
RUN_TEST(test_url_encode);
RUN_TEST(test_base64_encode); RUN_TEST(test_base64_encode);
RUN_TEST(test_mg_parse_header); RUN_TEST(test_mg_parse_header);
RUN_TEST(test_get_var); RUN_TEST(test_get_var);
+15 -17
View File
@@ -5,9 +5,9 @@
#include <string.h> #include <string.h>
#include "mongoose.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; const char *data;
int data_len; int data_len, ofs = 0;
char var_name[100], file_name[100]; char var_name[100], file_name[100];
mg_printf_data(conn, "%s", 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\" " "<form method=\"POST\" action=\"/handle_post_request\" "
" enctype=\"multipart/form-data\">" " enctype=\"multipart/form-data\">"
"<input type=\"file\" name=\"file\" /> <br/>" "<input type=\"file\" name=\"file\" /> <br/>"
"<input type=\"text\" name=\"input1\" value=hello! /> <br/>"
"<input type=\"submit\" value=\"Upload\" />" "<input type=\"submit\" value=\"Upload\" />"
"</form>"); "</form>");
if (mg_parse_multipart(conn->content, conn->content_len, while ((ofs = mg_parse_multipart(conn->content + ofs, conn->content_len - ofs,
var_name, sizeof(var_name), var_name, sizeof(var_name),
file_name, sizeof(file_name), file_name, sizeof(file_name),
&data, &data_len) > 0) { &data, &data_len)) > 0) {
mg_printf_data(conn, "var: %s, file_name: %s, size: %d bytes<br>",
mg_printf_data(conn, "%s", "Uploaded file:<pre>"); var_name, file_name, data_len);
mg_send_data(conn, data, data_len);
mg_printf_data(conn, "%s", "/pre>");
} }
mg_printf_data(conn, "%s", "</body></html>"); mg_printf_data(conn, "%s", "</body></html>");
return MG_TRUE;
} }
static int ev_handler(struct mg_connection *conn, enum mg_event ev) { static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
if (ev == MG_REQUEST) { switch (ev) {
send_index_page(conn); case MG_AUTH: return MG_TRUE;
return MG_TRUE; case MG_REQUEST: return send_index_page(conn);
} else if (ev == MG_AUTH) { default: return MG_FALSE;
return MG_TRUE;
} else {
return MG_FALSE;
} }
} }
+3 -3
View File
@@ -9,10 +9,10 @@
extern const char *find_embedded_file(const char *, size_t *); extern const char *find_embedded_file(const char *, size_t *);
static int iterate_callback(struct mg_connection *c, enum mg_event ev) { static int iterate_callback(struct mg_connection *c, enum mg_event ev) {
static int counter = 0;
if (ev == MG_POLL && c->is_websocket) { if (ev == MG_POLL && c->is_websocket) {
char buf[20]; 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); mg_websocket_write(c, 1, buf, len);
} }
return MG_TRUE; return MG_TRUE;
@@ -58,7 +58,7 @@ int main(void) {
current_timer = time(NULL); current_timer = time(NULL);
if (current_timer - last_timer > 0) { if (current_timer - last_timer > 0) {
last_timer = current_timer; last_timer = current_timer;
mg_iterate_over_connections(server, iterate_callback); mg_iterate_over_connections(server, iterate_callback, &current_timer);
} }
} }
+80
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff
+40 -22
View File
@@ -20,7 +20,7 @@
#ifndef MONGOOSE_HEADER_INCLUDED #ifndef MONGOOSE_HEADER_INCLUDED
#define MONGOOSE_HEADER_INCLUDED #define MONGOOSE_HEADER_INCLUDED
#define MONGOOSE_VERSION "5.3" #define MONGOOSE_VERSION "5.4"
#include <stdio.h> // required for FILE #include <stdio.h> // required for FILE
#include <stddef.h> // required for size_t #include <stddef.h> // required for size_t
@@ -37,7 +37,7 @@ struct mg_connection {
const char *query_string; // URL part after '?', not including '?', or NULL const char *query_string; // URL part after '?', not including '?', or NULL
char remote_ip[48]; // Max IPv6 string length is 45 characters 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 remote_port; // Client's port
unsigned short local_port; // Local port number unsigned short local_port; // Local port number
@@ -48,13 +48,14 @@ struct mg_connection {
} http_headers[30]; } http_headers[30];
char *content; // POST (or websocket message) data, or NULL 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 is_websocket; // Connection is a websocket connection
int status_code; // HTTP status code for HTTP error handler int status_code; // HTTP status code for HTTP error handler
int wsbits; // First byte of the websocket frame int wsbits; // First byte of the websocket frame
void *server_param; // Parameter passed to mg_add_uri_handler() void *server_param; // Parameter passed to mg_add_uri_handler()
void *connection_param; // Placeholder for connection-specific data 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 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_AUTH, // If callback returns MG_FALSE, authentication fails
MG_REQUEST, // If callback returns MG_FALSE, Mongoose continues with req MG_REQUEST, // If callback returns MG_FALSE, Mongoose continues with req
MG_REPLY, // If callback returns MG_FALSE, Mongoose closes connection MG_REPLY, // If callback returns MG_FALSE, Mongoose closes connection
MG_CLOSE, // Connection is closed MG_CLOSE, // Connection is closed, callback return value is ignored
MG_LUA, // Called before LSP page invoked MG_WS_HANDSHAKE, // New websocket connection, handshake request
MG_WS_CONNECT, // New websocket connection established
MG_HTTP_ERROR // If callback returns MG_FALSE, Mongoose continues with err MG_HTTP_ERROR // If callback returns MG_FALSE, Mongoose continues with err
}; };
typedef int (*mg_handler_t)(struct mg_connection *, enum mg_event); 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 // Server management functions
struct mg_server *mg_create_server(void *server_param, mg_handler_t handler); struct mg_server *mg_create_server(void *server_param, mg_handler_t handler);
void mg_destroy_server(struct mg_server **); void mg_destroy_server(struct mg_server **);
@@ -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); const char *mg_get_option(const struct mg_server *server, const char *name);
void mg_set_listening_socket(struct mg_server *, int sock); void mg_set_listening_socket(struct mg_server *, int sock);
int mg_get_listening_socket(struct mg_server *); 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(struct mg_server *);
void mg_wakeup_server_ex(struct mg_server *, mg_handler_t, const char *, ...);
struct mg_connection *mg_connect(struct mg_server *, const char *, int, int); struct mg_connection *mg_connect(struct mg_server *, const char *, int, int);
// Connection management functions // Connection management functions
void mg_send_status(struct mg_connection *, int status_code); void mg_send_status(struct mg_connection *, int status_code);
void mg_send_header(struct mg_connection *, const char *name, const char *val); void mg_send_header(struct mg_connection *, const char *name, const char *val);
void mg_send_data(struct mg_connection *, const void *data, int data_len); size_t mg_send_data(struct mg_connection *, const void *data, int data_len);
void mg_printf_data(struct mg_connection *, const char *format, ...); size_t mg_printf_data(struct mg_connection *, const char *format, ...);
size_t mg_write(struct mg_connection *, const void *buf, int len);
size_t mg_printf(struct mg_connection *conn, const char *fmt, ...);
int mg_websocket_write(struct mg_connection *, int opcode, size_t mg_websocket_write(struct mg_connection *, int opcode,
const char *data, size_t data_len); const char *data, size_t data_len);
size_t mg_websocket_printf(struct mg_connection* conn, int opcode,
const char *fmt, ...);
// Deprecated in favor of mg_send_* interface void mg_send_file(struct mg_connection *, const char *path);
int mg_write(struct mg_connection *, const void *buf, int len);
int mg_printf(struct mg_connection *conn, const char *fmt, ...);
const char *mg_get_header(const struct mg_connection *, const char *name); const char *mg_get_header(const struct mg_connection *, const char *name);
const char *mg_get_mime_type(const char *name, const char *default_mime_type); const char *mg_get_mime_type(const char *name, const char *default_mime_type);
@@ -111,16 +127,18 @@ int mg_parse_multipart(const char *buf, int buf_len,
void *mg_start_thread(void *(*func)(void *), void *param); void *mg_start_thread(void *(*func)(void *), void *param);
char *mg_md5(char buf[33], ...); char *mg_md5(char buf[33], ...);
int mg_authorize_digest(struct mg_connection *c, FILE *fp); int mg_authorize_digest(struct mg_connection *c, FILE *fp);
int mg_url_encode(const char *src, size_t s_len, char *dst, size_t dst_len);
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 #ifdef __cplusplus
} }