Compare commits

..
15 Commits
Author SHA1 Message Date
Deomid Ryabkov 6e50fe4475 Mongoose 6.10
PUBLISHED_FROM=c61fa89018f8cef4f798e094acff8d36c72869f2
2017-10-31 10:01:27 +00:00
Deomid Ryabkov 7942803a75 Fix MQTT SUBSCRIBE parsing
Make sure topic is properly NUL-terminated.
Ignore SUBSCRIBE requests with no topic expressions.

PUBLISHED_FROM=a00f39dda44fe63299e971a91a98f8ee57dd2a64
2017-10-30 15:34:22 +00:00
Deomid Ryabkov a8b74a9021 Fix bug when network conn is closed before CGI
NULL out cgi_nc->user_data so it doesn't touch nc anymore.

PUBLISHED_FROM=de2f76981c377d8951fb8e18e8b3d41dbfcf38b1
2017-10-30 14:20:27 +00:00
Deomid Ryabkov 27a9a62843 Fix SimpleLink listener for SSL
Must set SSL parameters before invoking sl_Listen

PUBLISHED_FROM=9147e7aa945f75e73d5c7cd7987cb5749025a86b
2017-10-24 07:19:45 +00:00
Deomid Ryabkov 9b268b6c77 Fix timer handling
ev_timer_time may remain the same for legit reason, so to prevent looping, instead, reset it before invoking the handler.
To let user know what the initial setting was, pass it as the argument instead of current time (which is kind of pointless).

PUBLISHED_FROM=fa328009f097f9b49b5b0dd13a38ee6d6e6518de
2017-10-21 09:19:42 +00:00
Sergey Lyubka 3b3ac48edd Fix potential leak in socks client
PUBLISHED_FROM=2cb4449d2f36d59db2b0dc37c46b35de6a461810
2017-10-19 13:49:43 +00:00
Sergey Lyubka 598e96a0cc Make amalgam work on windows
PUBLISHED_FROM=92f43c7b0a705ff40c4aea07f2ee0627f8e0e4a1
2017-10-19 13:49:42 +00:00
Бобби b5dd0e8093 Use verbose flags in both socks client and server
PUBLISHED_FROM=d17e96a97e1621e9788844bcd627c3143d37315c
2017-10-19 13:24:30 +00:00
Deomid Ryabkov 9b24fdfd1d Reformat mongoose
PUBLISHED_FROM=5202fa46a6a834bde35168ba566d3dce7c48f453
2017-10-19 13:24:26 +00:00
Бобби 8313896a85 Unbind things from v7
PUBLISHED_FROM=d20f138ae37c99a34cc29e7bfb327d7834404d93
2017-10-18 16:05:25 +00:00
Бобби 8193302162 Initial socks5 client & server implementation
PUBLISHED_FROM=05d3cca6223c963e7ae89dde3628fa8fad46e6bd
2017-10-18 14:05:13 +00:00
Бобби 6e3e5560d0 Move mongoose docs to https://cesanta.com/docs/
PUBLISHED_FROM=ebf5568abe82952ab2751298185a10189098013f
2017-10-16 15:18:24 +00:00
Dmitry Frank f0c6630a16 BREAKING: Sys config API change
Now apps should use getters and setters instead of accessing struct
fields directly, e.g. instead of `get_cfg()->update.timeout` it should
be `mgos_sys_config_get_update_timeout()` to get the current value, and
`mgos_sys_config_set_update_timeout(123)` to update the value.

For now, the config structs are public, but they will be made private
soon, so use accessors to keep your code working.

PUBLISHED_FROM=f7d582421a8d7e4d1ed50a280f2670d8b62f8d45
2017-10-11 11:15:48 +00:00
Deomid Ryabkov 1db747da29 Do not double-count recved bytes
Mongoose would report consumed bytes twice if mg_call is invoked recursively (e.g. proto_handler uses mg_call to invoke user's handler).
Reporting twice as much recved as was delivered effectively disables LwIP's TCP throttling and causes buffers to grow too big.

PUBLISHED_FROM=4ad5cd5db4dd54623bd6de2d50d32ddcc9e2b08a
2017-09-14 13:51:03 +00:00
Deomid Ryabkov 8065439f96 Acquire lock when manipulating rx in SSL recv path
PUBLISHED_FROM=a34cfa3ebc12daf75d7f24c8d3f3707dcc33d9a2
2017-09-14 11:06:24 +00:00
40 changed files with 702 additions and 269 deletions

No files matched your search

File renamed without changes.
-7
View File
@@ -1,7 +0,0 @@
---
title: CoAP
items:
- { name: server_example.md }
- { name: client_example.md }
- { name: ../c-api/coap.h/ }
---
File renamed without changes.
-7
View File
@@ -1,7 +0,0 @@
---
title: DNS client example
---
See https://github.com/cesanta/mongoose/blob/master/mongoose.c and search
for the `mg_resolve_async_eh()` function - that is the core of
built-in Mongoose async DNS resolver.
@@ -1,6 +1,7 @@
--- # Examples
title: DNS server example
---
## DNS server example
To create a DNS server, follow this pattern: To create a DNS server, follow this pattern:
@@ -71,3 +72,10 @@ int main(int argc, char *argv[]) {
``` ```
See full [Captive DNS server example](https://github.com/cesanta/mongoose/tree/master/examples/captive_dns_server). See full [Captive DNS server example](https://github.com/cesanta/mongoose/tree/master/examples/captive_dns_server).
## DNS client example
See https://github.com/cesanta/mongoose/blob/master/mongoose.c and search
for the `mg_resolve_async_eh()` function - that is the core of
built-in Mongoose async DNS resolver.
-8
View File
@@ -1,8 +0,0 @@
---
title: DNS
items:
- { name: server_example.md }
- { name: client_example.md }
- { name: ../c-api/dns.h/ }
- { name: ../c-api/dns_server.h/ }
---
+1 -3
View File
@@ -1,6 +1,4 @@
--- # CGI
title: CGI
---
[CGI](https://en.wikipedia.org/wiki/Common_Gateway_Interface) [CGI](https://en.wikipedia.org/wiki/Common_Gateway_Interface)
is a simple mechanism to generate dynamic content. is a simple mechanism to generate dynamic content.
@@ -1,6 +1,4 @@
--- # HTTP client example
title: HTTP client example
---
To create an HTTP client, follow this pattern: To create an HTTP client, follow this pattern:
@@ -1,6 +1,4 @@
--- # Digest Authentication
title: Digest Authentication
---
Mongoose has a built-in Digest (MD5) authentication support. In order to Mongoose has a built-in Digest (MD5) authentication support. In order to
enable Digest authentication, create a file `.htpasswd` in the directory enable Digest authentication, create a file `.htpasswd` in the directory
@@ -8,7 +6,7 @@ you would like to protect. That file should be in the format that Apache's
`htdigest` utility. `htdigest` utility.
You can use either Apache `htdigest` utility, or You can use either Apache `htdigest` utility, or
Mongoose pre-build binary (https://www.cesanta.com/products/binary) Mongoose pre-build binary at https://www.cesanta.com/binary.html
to add new users into that file: to add new users into that file:
``` ```
+1 -3
View File
@@ -1,6 +1,4 @@
--- #: HTTP events
title: HTTP events
---
As discussed in the overview, `mg_set_protocol_http_websocket()` function As discussed in the overview, `mg_set_protocol_http_websocket()` function
parses incoming data, treats it as HTTP or WebSocket, and triggers high-level parses incoming data, treats it as HTTP or WebSocket, and triggers high-level
+1 -3
View File
@@ -1,6 +1,4 @@
--- # Serving files
title: Serving files
---
API function `mg_serve_http()` makes it easy to serve files from a filesystem. API function `mg_serve_http()` makes it easy to serve files from a filesystem.
Generally speaking, that function is an implementation of the HTTP server Generally speaking, that function is an implementation of the HTTP server
-16
View File
@@ -1,16 +0,0 @@
---
title: HTTP
items:
- { name: server_example.md }
- { name: client_example.md }
- { name: events.md }
- { name: files.md }
- { name: cgi.md }
- { name: ssi.md }
- { name: upload.md }
- { name: ssl.md }
- { name: digest_auth.md }
- { name: ../c-api/http.h/ }
- { name: ../c-api/http_server.h/ }
- { name: ../c-api/http_client.h/ }
---
@@ -1,6 +1,4 @@
--- # HTTP server example
title: HTTP server example
---
To create an HTTP server, follow this pattern: To create an HTTP server, follow this pattern:
+1 -3
View File
@@ -1,6 +1,4 @@
--- # SSI
title: SSI
---
Server Side Includes (SSI) is a simple interpreted server-side scripting Server Side Includes (SSI) is a simple interpreted server-side scripting
language which is most commonly used to include the contents of a file language which is most commonly used to include the contents of a file
+1 -3
View File
@@ -1,6 +1,4 @@
--- # Enabling SSL (HTTPS)
title: Enabling HTTPS
---
To enable SSL on the server side, please follow these steps: To enable SSL on the server side, please follow these steps:
+5 -7
View File
@@ -1,14 +1,12 @@
--- # Handling file uploads
title: Handling file uploads
---
In order to handle file uploads, use the following HTML snippet: In order to handle file uploads, use the following HTML snippet:
```HTML ```HTML
&lt;form method="POST" action="/upload" enctype="multipart/form-data"&gt; <form method="POST" action="/upload" enctype="multipart/form-data">
&lt;input type="file" name="file"&gt; <input type="file" name="file">
&lt;input type="submit" value="Upload"&gt; <input type="submit" value="Upload">
&lt;/form&gt; </form>
``` ```
Uploaded files will be sent to the `/upload` endpoint via the `POST` request. Uploaded files will be sent to the `/upload` endpoint via the `POST` request.
-5
View File
@@ -1,5 +0,0 @@
---
title: MQTT client example
---
See https://github.com/cesanta/mongoose/tree/master/examples/mqtt_client
+5
View File
@@ -0,0 +1,5 @@
# Examples
- [Client example](https://github.com/cesanta/mongoose/tree/master/examples/mqtt_client)
- [Server example](https://github.com/cesanta/mongoose/tree/master/examples/mqtt_broker)
-8
View File
@@ -1,8 +0,0 @@
---
title: MQTT
items:
- { name: server_example.md }
- { name: client_example.md }
- { name: ../c-api/mqtt.h/ }
- { name: ../c-api/mqtt_server.h/ }
---
-5
View File
@@ -1,5 +0,0 @@
---
title: MQTT server example
---
See https://github.com/cesanta/mongoose/tree/master/examples/mqtt_broker
+59
View File
@@ -0,0 +1,59 @@
# Build options
Mongoose source code ships in a single .c file that contains functionality
for all supported protocols (modules). Modules can be disabled at compile
time which reduces the executable's size. That can be done by setting preprocessor
flags. Also, some preprocessor flags can be used to tune internal Mongoose
parameters.
To set a preprocessor flag during compile time, use the `-D <PREPROCESSOR_FLAG>`
compiler option. For example, to disable both MQTT and CoAP,
compile the application `my_app.c` like this (assumed UNIX system):
```
$ cc my_app.c mongoose.c -D MG_DISABLE_MQTT -D MG_DISABLE_COAP
```
## Enabling flags
- `MG_ENABLE_SSL` Enable [SSL/TLS support](https://docs.cesanta.com/mongoose/master/#/http/ssl.md/) (OpenSSL API)
- `MG_ENABLE_IPV6` Enable IPv6 support
- `MG_ENABLE_MQTT` enable [MQTT client](https://docs.cesanta.com/mongoose/master/#/mqtt/client_example.md/) (on by default, set to 0 to disable)
- `MG_ENABLE_MQTT_BROKER` enable [MQTT broker](https://docs.cesanta.com/mongoose/master/#/mqtt/server_example.md/)
- `MG_ENABLE_DNS_SERVER` enable DNS server
- `MG_ENABLE_COAP` enable CoAP protocol
- `MG_ENABLE_HTTP` Enable HTTP protocol support (on by default, set to 0 to disable)
- `MG_ENABLE_HTTP_CGI` Enable [CGI](https://docs.cesanta.com/mongoose/master/#/http/cgi.md/) support
- `MG_ENABLE_HTTP_SSI` Enable [Server Side Includes](https://docs.cesanta.com/mongoose/master/#/http/ssi.md/) support
- `MG_ENABLE_HTTP_SSI_EXEC` Enable SSI `exec` operator
- `MG_ENABLE_HTTP_WEBDAV` enable WebDAV extensions to HTTP
- `MG_ENABLE_HTTP_WEBSOCKET` enable WebSocket extension to HTTP (on by default, =0 to disable)
- `MG_ENABLE_BROADCAST` enable `mg_broadcast()` API
- `MG_ENABLE_GETADDRINFO` enable `getaddrinfo()` in `mg_resolve2()`
- `MG_ENABLE_THREADS` enable `mg_start_thread()` API
## Disabling flags
- `MG_DISABLE_HTTP_DIGEST_AUTH` disable HTTP Digest (MD5) authorisation support
- `CS_DISABLE_SHA1` disable SHA1 support (used by WebSocket)
- `CS_DISABLE_MD5` disable MD5 support (used by HTTP auth)
- `MG_DISABLE_HTTP_KEEP_ALIVE` useful for embedded systems to save resources
## Platform specific
Mongoose tries to detect the target platform whenever possible, but in some cases you have
to explicitly declare some peculiarities of your target, such as:
- `MG_CC3200`: enable workarounds for the TI CC3200 target.
- `MG_ESP8266`: enable workarounds for the ESP8266 target, add `RTOS_SDK` to specify the RTOS SDK flavour.
## Tunables
- `MG_MALLOC`, `MG_CALLOC`, `MG_REALLOC`, `MG_FREE` allow you to a use custom
memory allocator, e.g. `-DMG_MALLOC=my_malloc`
- `MG_USE_READ_WRITE` when set replaces calls to `recv` with `read` and `send` with `write`,
thus enabling to add any kind of file descriptor (files, serial devices) to an event manager.
- `MG_SSL_CRYPTO_MODERN`, `MG_SSL_CRYPTO_OLD` - choose either "Modern" or "Old" ciphers
instead of the default "Intermediate" setting.
See [this article](https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations) for details.
- `MG_USER_FILE_FUNCTIONS` allow you to use custom file operation, by defining you own `mg_stat`, `mg_fopen`, `mg_open`, `mg_fread` and `mg_fwrite` functions
@@ -1,8 +0,0 @@
---
title: Disabling flags
---
- `MG_DISABLE_HTTP_DIGEST_AUTH` disable HTTP Digest (MD5) authorisation support
- `CS_DISABLE_SHA1` disable SHA1 support (used by WebSocket)
- `CS_DISABLE_MD5` disable MD5 support (used by HTTP auth)
- `MG_DISABLE_HTTP_KEEP_ALIVE` useful for embedded systems to save resources
@@ -1,19 +0,0 @@
---
title: Enabling flags
---
- `MG_ENABLE_SSL` Enable [SSL/TLS support](https://docs.cesanta.com/mongoose/master/#/http/ssl.md/) (OpenSSL API)
- `MG_ENABLE_IPV6` Enable IPv6 support
- `MG_ENABLE_MQTT` enable [MQTT client](https://docs.cesanta.com/mongoose/master/#/mqtt/client_example.md/) (on by default, set to 0 to disable)
- `MG_ENABLE_MQTT_BROKER` enable [MQTT broker](https://docs.cesanta.com/mongoose/master/#/mqtt/server_example.md/)
- `MG_ENABLE_DNS_SERVER` enable DNS server
- `MG_ENABLE_COAP` enable CoAP protocol
- `MG_ENABLE_HTTP` Enable HTTP protocol support (on by default, set to 0 to disable)
- `MG_ENABLE_HTTP_CGI` Enable [CGI](https://docs.cesanta.com/mongoose/master/#/http/cgi.md/) support
- `MG_ENABLE_HTTP_SSI` Enable [Server Side Includes](https://docs.cesanta.com/mongoose/master/#/http/ssi.md/) support
- `MG_ENABLE_HTTP_SSI_EXEC` Enable SSI `exec` operator
- `MG_ENABLE_HTTP_WEBDAV` enable WebDAV extensions to HTTP
- `MG_ENABLE_HTTP_WEBSOCKET` enable WebSocket extension to HTTP (on by default, =0 to disable)
- `MG_ENABLE_BROADCAST` enable `mg_broadcast()` API
- `MG_ENABLE_GETADDRINFO` enable `getaddrinfo()` in `mg_resolve2()`
- `MG_ENABLE_THREADS` enable `mg_start_thread()` API
-22
View File
@@ -1,22 +0,0 @@
---
title: Build Options
items:
- { type: file, name: enabling-flags.md }
- { type: file, name: disabling-flags.md }
- { type: file, name: platform-spec.md }
- { type: file, name: tunables.md }
---
Mongoose source code ships in a single .c file that contains functionality
for all supported protocols (modules). Modules can be disabled at compile
time which reduces the executable's size. That can be done by setting preprocessor
flags. Also, some preprocessor flags can be used to tune internal Mongoose
parameters.
To set a preprocessor flag during compile time, use the `-D <PREPROCESSOR_FLAG>`
compiler option. For example, to disable both MQTT and CoAP,
compile the application `my_app.c` like this (assumed UNIX system):
```
$ cc my_app.c mongoose.c -D MG_DISABLE_MQTT -D MG_DISABLE_COAP
```
@@ -1,9 +0,0 @@
---
title: Platform specific
---
Mongoose tries to detect the target platform whenever possible, but in some cases you have
to explicitly declare some peculiarities of your target, such as:
- `MG_CC3200`: enable workarounds for the TI CC3200 target.
- `MG_ESP8266`: enable workarounds for the ESP8266 target, add `RTOS_SDK` to specify the RTOS SDK flavour.
-12
View File
@@ -1,12 +0,0 @@
---
title: Tunables
---
- `MG_MALLOC`, `MG_CALLOC`, `MG_REALLOC`, `MG_FREE` allow you to a use custom
memory allocator, e.g. `-DMG_MALLOC=my_malloc`
- `MG_USE_READ_WRITE` when set replaces calls to `recv` with `read` and `send` with `write`,
thus enabling to add any kind of file descriptor (files, serial devices) to an event manager.
- `MG_SSL_CRYPTO_MODERN`, `MG_SSL_CRYPTO_OLD` - choose either "Modern" or "Old" ciphers
instead of the default "Intermediate" setting.
See [this article](https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations) for details.
- `MG_USER_FILE_FUNCTIONS` allow you to use custom file operation, by defining you own `mg_stat`, `mg_fopen`, `mg_open`, `mg_fread` and `mg_fwrite` functions
+1 -3
View File
@@ -1,6 +1,4 @@
--- # Design Concept
title: Design Concept
---
Mongoose has three basic data structures: Mongoose has three basic data structures:
+1 -3
View File
@@ -1,6 +1,4 @@
--- # Connection flags
title: Connection flags
---
Each connection has a `flags` bit field. Some flags are set by Mongoose, for Each connection has a `flags` bit field. Some flags are set by Mongoose, for
example if a user creates an outbound UDP connection using a `udp://1.2.3.4:5678` example if a user creates an outbound UDP connection using a `udp://1.2.3.4:5678`
+1 -3
View File
@@ -1,6 +1,4 @@
--- # Event handler function
title: Event handler function
---
Each connection has an event handler function associated with it. That function Each connection has an event handler function associated with it. That function
must be implemented by the user. Event handler is the key element of the Mongoose must be implemented by the user. Event handler is the key element of the Mongoose
+1 -3
View File
@@ -1,6 +1,4 @@
--- # Events
title: Events
---
Mongoose accepts incoming connections, reads and writes data and calls Mongoose accepts incoming connections, reads and writes data and calls
specified event handlers for each connection when appropriate. A typical event specified event handlers for each connection when appropriate. A typical event
+1 -12
View File
@@ -1,15 +1,4 @@
--- # Introduction
title: Overview
items:
# - { name: usage-example.md }
- { name: concept.md }
- { name: mbufs.md }
- { name: event-handler.md }
- { name: events.md }
- { name: conn-flags.md }
- { name: build-options }
- { name: usage-example.md }
---
Mongoose is a networking library written in C. Mongoose is a networking library written in C.
It is a swiss army knife for embedded network programming. It is a swiss army knife for embedded network programming.
+2 -4
View File
@@ -1,6 +1,4 @@
--- # Memory buffers
title: Memory buffers
---
Each connection has a send and receive buffer, `struct mg_connection::send_mbuf` Each connection has a send and receive buffer, `struct mg_connection::send_mbuf`
and `struct mg_connection::recv_mbuf` respectively. When data arrives, and `struct mg_connection::recv_mbuf` respectively. When data arrives,
@@ -11,4 +9,4 @@ When Mongoose successfully writes data to the socket, it discards data from
`struct mg_connection::send_mbuf` and sends an `MG_EV_SEND` event. When the connection `struct mg_connection::send_mbuf` and sends an `MG_EV_SEND` event. When the connection
is closed, an `MG_EV_CLOSE` event is sent. is closed, an `MG_EV_CLOSE` event is sent.
![](media/mbuf.png) ![](/docs/media/mbuf.png)
+1 -3
View File
@@ -1,6 +1,4 @@
--- # Example - TCP echo server
title: Example - TCP echo server
---
- Copy `mongoose.c` and `mongoose.h` to your build tree - Copy `mongoose.c` and `mongoose.h` to your build tree
- Write code that uses the Mongoose API, e.g. in `my_app.c` - Write code that uses the Mongoose API, e.g. in `my_app.c`
+3 -3
View File
@@ -21,9 +21,9 @@ ifeq ($(SSL_LIB),mbedtls)
CFLAGS += -DMG_ENABLE_SSL -DMG_SSL_IF=MG_SSL_IF_MBEDTLS -DMG_SSL_MBED_DUMMY_RANDOM -lmbedcrypto -lmbedtls -lmbedx509 CFLAGS += -DMG_ENABLE_SSL -DMG_SSL_IF=MG_SSL_IF_MBEDTLS -DMG_SSL_MBED_DUMMY_RANDOM -lmbedcrypto -lmbedtls -lmbedx509
endif endif
ifeq ($(JS), yes) ifdef ASAN
V7_PATH = ../../deps/v7 CC = clang
CFLAGS_EXTRA += -DMG_ENABLE_JAVASCRIPT -I $(V7_PATH) $(V7_PATH)/v7.c CFLAGS += -fsanitize=address
endif endif
$(PROG): $(SOURCES) $(PROG): $(SOURCES)
-5
View File
@@ -75,11 +75,6 @@ int main(int argc, char *argv[]) {
s_http_port = argv[++i]; s_http_port = argv[++i];
} else if (strcmp(argv[i], "-a") == 0 && i + 1 < argc) { } else if (strcmp(argv[i], "-a") == 0 && i + 1 < argc) {
s_http_server_opts.auth_domain = argv[++i]; s_http_server_opts.auth_domain = argv[++i];
#if MG_ENABLE_JAVASCRIPT
} else if (strcmp(argv[i], "-j") == 0 && i + 1 < argc) {
const char *init_file = argv[++i];
mg_enable_javascript(&mgr, v7_create(), init_file);
#endif
} else if (strcmp(argv[i], "-P") == 0 && i + 1 < argc) { } else if (strcmp(argv[i], "-P") == 0 && i + 1 < argc) {
s_http_server_opts.global_auth_file = argv[++i]; s_http_server_opts.global_auth_file = argv[++i];
} else if (strcmp(argv[i], "-A") == 0 && i + 1 < argc) { } else if (strcmp(argv[i], "-A") == 0 && i + 1 < argc) {
+5
View File
@@ -0,0 +1,5 @@
PROG = socks_server
# NOTE(lsm): -DMG_ENABLE_IPV6 won't work for the mingw build
MODULE_CFLAGS = -DMG_ENABLE_SOCKS=1 # -DMG_ENABLE_DEBUG=1
#SSL_LIB=openssl
include ../examples.mk
+32
View File
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2017 Cesanta Software Limited
* All rights reserved
*
* Use curl to test, e.g.
* curl -i --socks5 127.0.0.1:1080 www.met.ie
*/
#include "mongoose.h"
static const char *s_listening_addr = "1080";
int main(void) {
struct mg_mgr mgr;
struct mg_connection *c;
mg_mgr_init(&mgr, NULL);
if ((c = mg_bind(&mgr, s_listening_addr, NULL)) == NULL) {
fprintf(stderr, "mg_bind(%s) failed\n", s_listening_addr);
exit(EXIT_FAILURE);
}
mg_set_protocol_socks(c);
printf("Starting socks5 proxy server on %s\n", s_listening_addr);
for (;;) {
mg_mgr_poll(&mgr, 1000);
}
mg_mgr_free(&mgr);
return 0;
}
+484 -65
View File
@@ -236,7 +236,7 @@ enum cs_log_level {
void cs_log_set_level(enum cs_log_level level); void cs_log_set_level(enum cs_log_level level);
/* Set log filter. NULL (a default) logs everything. */ /* Set log filter. NULL (a default) logs everything. */
void cs_log_set_filter(char *source_file_name); void cs_log_set_filter(const char *source_file_name);
int cs_log_print_prefix(enum cs_log_level level, const char *func, int cs_log_print_prefix(enum cs_log_level level, const char *func,
const char *filename); const char *filename);
@@ -316,8 +316,8 @@ double cs_log_ts WEAK;
enum cs_log_level cs_log_cur_msg_level WEAK = LL_NONE; enum cs_log_level cs_log_cur_msg_level WEAK = LL_NONE;
void cs_log_set_filter(char *str) WEAK; void cs_log_set_filter(const char *str) WEAK;
void cs_log_set_filter(char *str) { void cs_log_set_filter(const char *str) {
free(s_filter_pattern); free(s_filter_pattern);
if (str != NULL) { if (str != NULL) {
s_filter_pattern = strdup(str); s_filter_pattern = strdup(str);
@@ -2218,6 +2218,8 @@ MG_INTERNAL void mg_remove_conn(struct mg_connection *conn) {
MG_INTERNAL void mg_call(struct mg_connection *nc, MG_INTERNAL void mg_call(struct mg_connection *nc,
mg_event_handler_t ev_handler, void *user_data, int ev, mg_event_handler_t ev_handler, void *user_data, int ev,
void *ev_data) { void *ev_data) {
static int nesting_level = 0;
nesting_level++;
if (ev_handler == NULL) { if (ev_handler == NULL) {
/* /*
* If protocol handler is specified, call it. Otherwise, call user-specified * If protocol handler is specified, call it. Otherwise, call user-specified
@@ -2247,7 +2249,10 @@ MG_INTERNAL void mg_call(struct mg_connection *nc,
nc->flags = (flags_before & ~_MG_CALLBACK_MODIFIABLE_FLAGS_MASK) | nc->flags = (flags_before & ~_MG_CALLBACK_MODIFIABLE_FLAGS_MASK) |
(nc->flags & _MG_CALLBACK_MODIFIABLE_FLAGS_MASK); (nc->flags & _MG_CALLBACK_MODIFIABLE_FLAGS_MASK);
} }
if (recved > 0 && !(nc->flags & MG_F_UDP)) { /* It's important to not double-count recved bytes, and since mg_call can be
* called recursively (e.g. proto_handler invokes user handler), we keep
* track of recursion and only report received bytes at the top level. */
if (nesting_level == 1 && recved > 0 && !(nc->flags & MG_F_UDP)) {
nc->iface->vtable->recved(nc, recved); nc->iface->vtable->recved(nc, recved);
} }
} }
@@ -2256,6 +2261,7 @@ MG_INTERNAL void mg_call(struct mg_connection *nc,
ev_handler == nc->handler ? "user" : "proto", nc->flags, ev_handler == nc->handler ? "user" : "proto", nc->flags,
(int) nc->recv_mbuf.len, (int) nc->send_mbuf.len)); (int) nc->recv_mbuf.len, (int) nc->send_mbuf.len));
} }
nesting_level--;
#if !MG_ENABLE_CALLBACK_USERDATA #if !MG_ENABLE_CALLBACK_USERDATA
(void) user_data; (void) user_data;
#endif #endif
@@ -2264,14 +2270,8 @@ MG_INTERNAL void mg_call(struct mg_connection *nc,
void mg_if_timer(struct mg_connection *c, double now) { void mg_if_timer(struct mg_connection *c, double now) {
if (c->ev_timer_time > 0 && now >= c->ev_timer_time) { if (c->ev_timer_time > 0 && now >= c->ev_timer_time) {
double old_value = c->ev_timer_time; double old_value = c->ev_timer_time;
mg_call(c, NULL, c->user_data, MG_EV_TIMER, &now); c->ev_timer_time = 0;
/* mg_call(c, NULL, c->user_data, MG_EV_TIMER, &old_value);
* To prevent timer firing all the time, reset the timer after delivery.
* However, in case user sets it to new value, do not reset.
*/
if (c->ev_timer_time == old_value) {
c->ev_timer_time = 0;
}
} }
} }
@@ -3225,6 +3225,31 @@ struct mg_connection *mg_tun_if_find_conn(struct mg_tun_client *client,
#endif /* CS_MONGOOSE_SRC_NET_IF_TUN_H_ */ #endif /* CS_MONGOOSE_SRC_NET_IF_TUN_H_ */
#ifdef MG_MODULE_LINES #ifdef MG_MODULE_LINES
#line 1 "mongoose/src/net_if_socks.h"
#endif
/*
* Copyright (c) 2014-2017 Cesanta Software Limited
* All rights reserved
*/
#ifndef CS_MONGOOSE_SRC_NET_IF_SOCKS_H_
#define CS_MONGOOSE_SRC_NET_IF_SOCKS_H_
#if MG_ENABLE_SOCKS
/* Amalgamated: #include "mongoose/src/net_if.h" */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
extern const struct mg_iface_vtable mg_socks_iface_vtable;
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* MG_ENABLE_SOCKS */
#endif /* CS_MONGOOSE_SRC_NET_IF_SOCKS_H_ */
#ifdef MG_MODULE_LINES
#line 1 "mongoose/src/net_if.c" #line 1 "mongoose/src/net_if.c"
#endif #endif
/* Amalgamated: #include "mongoose/src/net_if.h" */ /* Amalgamated: #include "mongoose/src/net_if.h" */
@@ -3234,12 +3259,12 @@ struct mg_connection *mg_tun_if_find_conn(struct mg_tun_client *client,
extern const struct mg_iface_vtable mg_default_iface_vtable; extern const struct mg_iface_vtable mg_default_iface_vtable;
const struct mg_iface_vtable *mg_ifaces[] = {
&mg_default_iface_vtable,
#if MG_ENABLE_TUN #if MG_ENABLE_TUN
const struct mg_iface_vtable *mg_ifaces[] = {&mg_default_iface_vtable, &mg_tun_iface_vtable,
&mg_tun_iface_vtable};
#else
const struct mg_iface_vtable *mg_ifaces[] = {&mg_default_iface_vtable};
#endif #endif
};
int mg_num_ifaces = (int) (sizeof(mg_ifaces) / sizeof(mg_ifaces[0])); int mg_num_ifaces = (int) (sizeof(mg_ifaces) / sizeof(mg_ifaces[0]));
@@ -4016,6 +4041,218 @@ const struct mg_iface_vtable mg_default_iface_vtable = MG_SOCKET_IFACE_VTABLE;
#endif /* MG_ENABLE_NET_IF_SOCKET */ #endif /* MG_ENABLE_NET_IF_SOCKET */
#ifdef MG_MODULE_LINES #ifdef MG_MODULE_LINES
#line 1 "mongoose/src/net_if_socks.c"
#endif
/*
* Copyright (c) 2014-2016 Cesanta Software Limited
* All rights reserved
*/
#if MG_ENABLE_SOCKS
struct socksdata {
char *proxy_addr; /* HOST:PORT of the socks5 proxy server */
struct mg_connection *s; /* Respective connection to the server */
struct mg_connection *c; /* Connection to the client */
struct mbuf tmp; /* Temporary buffer for sent data */
};
static void socks_if_disband(struct socksdata *d) {
LOG(LL_DEBUG, ("disbanding proxy %p %p", d->c, d->s));
if (d->c) d->c->flags |= MG_F_SEND_AND_CLOSE;
if (d->s) d->s->flags |= MG_F_SEND_AND_CLOSE;
d->c = d->s = NULL;
}
static void socks_if_handler(struct mg_connection *c, int ev, void *ev_data) {
struct socksdata *d = (struct socksdata *) c->user_data;
if (ev == MG_EV_CONNECT) {
int res = *(int *) ev_data;
if (res == 0) {
/* Send handshake to the proxy server */
unsigned char buf[] = {MG_SOCKS_VERSION, 1, MG_SOCKS_HANDSHAKE_NOAUTH};
mg_send(d->s, buf, sizeof(buf));
LOG(LL_DEBUG, ("Sent handshake to %s", d->proxy_addr));
} else {
LOG(LL_ERROR, ("Cannot connect to %s: %d", d->proxy_addr, res));
d->c->flags |= MG_F_CLOSE_IMMEDIATELY;
}
} else if (ev == MG_EV_CLOSE) {
socks_if_disband(d);
} else if (ev == MG_EV_RECV) {
/* Handle handshake reply */
if (!(c->flags & MG_SOCKS_HANDSHAKE_DONE)) {
/* TODO(lsm): process IPv6 too */
unsigned char buf[10] = {MG_SOCKS_VERSION, MG_SOCKS_CMD_CONNECT, 0,
MG_SOCKS_ADDR_IPV4};
if (c->recv_mbuf.len < 2) return;
if ((unsigned char) c->recv_mbuf.buf[1] == MG_SOCKS_HANDSHAKE_FAILURE) {
LOG(LL_ERROR, ("Server kicked us out"));
socks_if_disband(d);
return;
}
mbuf_remove(&c->recv_mbuf, 2);
c->flags |= MG_SOCKS_HANDSHAKE_DONE;
/* Send connect request */
memcpy(buf + 4, &d->c->sa.sin.sin_addr, 4);
memcpy(buf + 8, &d->c->sa.sin.sin_port, 2);
mg_send(c, buf, sizeof(buf));
}
/* Process connect request */
if ((c->flags & MG_SOCKS_HANDSHAKE_DONE) &&
!(c->flags & MG_SOCKS_CONNECT_DONE)) {
if (c->recv_mbuf.len < 10) return;
if (c->recv_mbuf.buf[1] != MG_SOCKS_SUCCESS) {
LOG(LL_ERROR, ("Socks connection error: %d", c->recv_mbuf.buf[1]));
socks_if_disband(d);
return;
}
mbuf_remove(&c->recv_mbuf, 10);
c->flags |= MG_SOCKS_CONNECT_DONE;
/* Connected. Move sent data from client, if any, to server */
if (d->s && d->c) {
mbuf_append(&d->s->send_mbuf, d->tmp.buf, d->tmp.len);
mbuf_free(&d->tmp);
}
}
/* All flags are set, we're in relay mode */
if ((c->flags & MG_SOCKS_CONNECT_DONE) && d->c && d->s) {
mbuf_append(&d->c->recv_mbuf, d->s->recv_mbuf.buf, d->s->recv_mbuf.len);
mbuf_remove(&d->s->recv_mbuf, d->s->recv_mbuf.len);
}
}
}
static void mg_socks_if_connect_tcp(struct mg_connection *c,
const union socket_address *sa) {
struct socksdata *d = (struct socksdata *) c->iface->data;
d->c = c;
d->s = mg_connect(c->mgr, d->proxy_addr, socks_if_handler);
d->s->user_data = d;
LOG(LL_DEBUG, ("%p %s", c, d->proxy_addr));
(void) sa;
}
static void mg_socks_if_connect_udp(struct mg_connection *c) {
(void) c;
}
static int mg_socks_if_listen_tcp(struct mg_connection *c,
union socket_address *sa) {
(void) c;
(void) sa;
return 0;
}
static int mg_socks_if_listen_udp(struct mg_connection *c,
union socket_address *sa) {
(void) c;
(void) sa;
return -1;
}
static void mg_socks_if_tcp_send(struct mg_connection *c, const void *buf,
size_t len) {
struct socksdata *d = (struct socksdata *) c->iface->data;
LOG(LL_DEBUG, ("%p -> %p %d %d", c, buf, (int) len, (int) c->send_mbuf.len));
if (d && d->s && d->s->flags & MG_SOCKS_CONNECT_DONE) {
mbuf_append(&d->s->send_mbuf, d->tmp.buf, d->tmp.len);
mbuf_append(&d->s->send_mbuf, buf, len);
mbuf_free(&d->tmp);
} else {
mbuf_append(&d->tmp, buf, len);
}
}
static void mg_socks_if_udp_send(struct mg_connection *c, const void *buf,
size_t len) {
(void) c;
(void) buf;
(void) len;
}
static void mg_socks_if_recved(struct mg_connection *c, size_t len) {
(void) c;
(void) len;
}
static int mg_socks_if_create_conn(struct mg_connection *c) {
(void) c;
return 1;
}
static void mg_socks_if_destroy_conn(struct mg_connection *c) {
c->iface->vtable->free(c->iface);
MG_FREE(c->iface);
c->iface = NULL;
LOG(LL_DEBUG, ("%p", c));
}
static void mg_socks_if_sock_set(struct mg_connection *c, sock_t sock) {
(void) c;
(void) sock;
}
static void mg_socks_if_init(struct mg_iface *iface) {
(void) iface;
}
static void mg_socks_if_free(struct mg_iface *iface) {
struct socksdata *d = (struct socksdata *) iface->data;
LOG(LL_DEBUG, ("%p", iface));
if (d != NULL) {
socks_if_disband(d);
mbuf_free(&d->tmp);
MG_FREE(d->proxy_addr);
MG_FREE(d);
iface->data = NULL;
}
}
static void mg_socks_if_add_conn(struct mg_connection *c) {
c->sock = INVALID_SOCKET;
}
static void mg_socks_if_remove_conn(struct mg_connection *c) {
(void) c;
}
static time_t mg_socks_if_poll(struct mg_iface *iface, int timeout_ms) {
LOG(LL_DEBUG, ("%p", iface));
(void) iface;
(void) timeout_ms;
return (time_t) cs_time();
}
static void mg_socks_if_get_conn_addr(struct mg_connection *c, int remote,
union socket_address *sa) {
LOG(LL_DEBUG, ("%p", c));
(void) c;
(void) remote;
(void) sa;
}
const struct mg_iface_vtable mg_socks_iface_vtable = {
mg_socks_if_init, mg_socks_if_free,
mg_socks_if_add_conn, mg_socks_if_remove_conn,
mg_socks_if_poll, mg_socks_if_listen_tcp,
mg_socks_if_listen_udp, mg_socks_if_connect_tcp,
mg_socks_if_connect_udp, mg_socks_if_tcp_send,
mg_socks_if_udp_send, mg_socks_if_recved,
mg_socks_if_create_conn, mg_socks_if_destroy_conn,
mg_socks_if_sock_set, mg_socks_if_get_conn_addr,
};
struct mg_iface *mg_socks_mk_iface(struct mg_mgr *mgr, const char *proxy_addr) {
struct mg_iface *iface = mg_if_create_iface(&mg_socks_iface_vtable, mgr);
iface->data = MG_CALLOC(1, sizeof(struct socksdata));
((struct socksdata *) iface->data)->proxy_addr = strdup(proxy_addr);
return iface;
}
#endif
#ifdef MG_MODULE_LINES
#line 1 "mongoose/src/net_if_tun.c" #line 1 "mongoose/src/net_if_tun.c"
#endif #endif
/* /*
@@ -8224,6 +8461,8 @@ void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path,
#define MG_ENV_EXPORT_TO_CGI "MONGOOSE_CGI" #define MG_ENV_EXPORT_TO_CGI "MONGOOSE_CGI"
#endif #endif
#define MG_F_HTTP_CGI_PARSE_HEADERS MG_F_USER_1
/* /*
* This structure helps to create an environment for the spawned CGI program. * This structure helps to create an environment for the spawned CGI program.
* Environment is an array of "VARIABLE=VALUE\0" ASCIIZ strings, * Environment is an array of "VARIABLE=VALUE\0" ASCIIZ strings,
@@ -8589,6 +8828,7 @@ static void mg_cgi_ev_handler(struct mg_connection *cgi_nc, int ev,
(void) ev_data; (void) ev_data;
if (nc == NULL) { if (nc == NULL) {
/* The corresponding network connection was closed. */
cgi_nc->flags |= MG_F_CLOSE_IMMEDIATELY; cgi_nc->flags |= MG_F_CLOSE_IMMEDIATELY;
return; return;
} }
@@ -8608,7 +8848,7 @@ static void mg_cgi_ev_handler(struct mg_connection *cgi_nc, int ev,
* been received, send appropriate reply line, and forward all * been received, send appropriate reply line, and forward all
* received headers to the client. * received headers to the client.
*/ */
if (nc->flags & MG_F_USER_1) { if (nc->flags & MG_F_HTTP_CGI_PARSE_HEADERS) {
struct mbuf *io = &cgi_nc->recv_mbuf; struct mbuf *io = &cgi_nc->recv_mbuf;
int len = mg_http_get_request_len(io->buf, io->len); int len = mg_http_get_request_len(io->buf, io->len);
@@ -8628,13 +8868,14 @@ static void mg_cgi_ev_handler(struct mg_connection *cgi_nc, int ev,
mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\n"); mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\n");
} }
} }
nc->flags &= ~MG_F_USER_1; nc->flags &= ~MG_F_HTTP_CGI_PARSE_HEADERS;
} }
if (!(nc->flags & MG_F_USER_1)) { if (!(nc->flags & MG_F_HTTP_CGI_PARSE_HEADERS)) {
mg_forward(cgi_nc, nc); mg_forward(cgi_nc, nc);
} }
break; break;
case MG_EV_CLOSE: case MG_EV_CLOSE:
DBG(("%p CLOSE", cgi_nc));
mg_http_free_proto_data_cgi(&mg_http_get_proto_data(nc)->cgi); mg_http_free_proto_data_cgi(&mg_http_get_proto_data(nc)->cgi);
nc->flags |= MG_F_SEND_AND_CLOSE; nc->flags |= MG_F_SEND_AND_CLOSE;
break; break;
@@ -8688,7 +8929,7 @@ MG_INTERNAL void mg_handle_cgi(struct mg_connection *nc, const char *prog,
#if !MG_ENABLE_CALLBACK_USERDATA #if !MG_ENABLE_CALLBACK_USERDATA
cgi_pd->cgi.cgi_nc->user_data = nc; cgi_pd->cgi.cgi_nc->user_data = nc;
#endif #endif
nc->flags |= MG_F_USER_1; nc->flags |= MG_F_HTTP_CGI_PARSE_HEADERS;
/* Push POST data to the CGI */ /* Push POST data to the CGI */
if (n > 0 && n < nc->recv_mbuf.len) { if (n > 0 && n < nc->recv_mbuf.len) {
mg_send(cgi_pd->cgi.cgi_nc, hm->body.p, n); mg_send(cgi_pd->cgi.cgi_nc, hm->body.p, n);
@@ -8705,10 +8946,12 @@ MG_INTERNAL void mg_handle_cgi(struct mg_connection *nc, const char *prog,
} }
MG_INTERNAL void mg_http_free_proto_data_cgi(struct mg_http_proto_data_cgi *d) { MG_INTERNAL void mg_http_free_proto_data_cgi(struct mg_http_proto_data_cgi *d) {
if (d != NULL) { if (d == NULL) return;
if (d->cgi_nc != NULL) d->cgi_nc->flags |= MG_F_CLOSE_IMMEDIATELY; if (d->cgi_nc != NULL) {
memset(d, 0, sizeof(struct mg_http_proto_data_cgi)); d->cgi_nc->flags |= MG_F_CLOSE_IMMEDIATELY;
d->cgi_nc->user_data = NULL;
} }
memset(d, 0, sizeof(*d));
} }
#endif /* MG_ENABLE_HTTP && MG_ENABLE_HTTP_CGI */ #endif /* MG_ENABLE_HTTP && MG_ENABLE_HTTP_CGI */
@@ -9216,7 +9459,7 @@ static void mg_handle_incoming_websocket_frame(struct mg_connection *nc,
static struct mg_ws_proto_data *mg_ws_get_proto_data(struct mg_connection *nc) { static struct mg_ws_proto_data *mg_ws_get_proto_data(struct mg_connection *nc) {
struct mg_http_proto_data *htd = mg_http_get_proto_data(nc); struct mg_http_proto_data *htd = mg_http_get_proto_data(nc);
return (htd != NULL ? &htd->ws_data : NULL); return (htd != NULL ? &htd->ws_data : NULL);
}; }
static int mg_deliver_websocket_data(struct mg_connection *nc) { static int mg_deliver_websocket_data(struct mg_connection *nc) {
/* Using unsigned char *, cause of integer arithmetic below */ /* Using unsigned char *, cause of integer arithmetic below */
@@ -10498,24 +10741,33 @@ static void mg_mqtt_broker_handle_subscribe(struct mg_connection *nc,
qoss[num_subs++] = qos; qoss[num_subs++] = qos;
} }
te = (struct mg_mqtt_topic_expression *) MG_REALLOC( if (num_subs > 0) {
ss->subscriptions, te = (struct mg_mqtt_topic_expression *) MG_REALLOC(
sizeof(*ss->subscriptions) * (ss->num_subscriptions + num_subs)); ss->subscriptions,
if (te == NULL) { sizeof(*ss->subscriptions) * (ss->num_subscriptions + num_subs));
nc->flags |= MG_F_CLOSE_IMMEDIATELY; if (te == NULL) {
return; nc->flags |= MG_F_CLOSE_IMMEDIATELY;
} return;
ss->subscriptions = te; }
for (pos = 0; ss->subscriptions = te;
(pos = mg_mqtt_next_subscribe_topic(msg, &topic, &qos, pos)) != -1; for (pos = 0;
ss->num_subscriptions++) { pos < (int) msg->payload.len &&
te = &ss->subscriptions[ss->num_subscriptions]; (pos = mg_mqtt_next_subscribe_topic(msg, &topic, &qos, pos)) != -1;
te->topic = (char *) MG_MALLOC(topic.len + 1); ss->num_subscriptions++) {
te->qos = qos; te = &ss->subscriptions[ss->num_subscriptions];
strncpy((char *) te->topic, topic.p, topic.len + 1); te->topic = (char *) MG_MALLOC(topic.len + 1);
te->qos = qos;
memcpy((char *) te->topic, topic.p, topic.len);
((char *) te->topic)[topic.len] = '\0';
}
} }
mg_mqtt_suback(nc, qoss, num_subs, msg->message_id); if (pos == (int) msg->payload.len) {
mg_mqtt_suback(nc, qoss, num_subs, msg->message_id);
} else {
/* We did not fully parse the payload, something must be wrong. */
nc->flags |= MG_F_CLOSE_IMMEDIATELY;
}
} }
static void mg_mqtt_broker_handle_publish(struct mg_mqtt_broker *brk, static void mg_mqtt_broker_handle_publish(struct mg_mqtt_broker *brk,
@@ -12553,6 +12805,168 @@ struct mg_connection *mg_sntp_get_time(struct mg_mgr *mgr,
#endif /* MG_ENABLE_SNTP */ #endif /* MG_ENABLE_SNTP */
#ifdef MG_MODULE_LINES #ifdef MG_MODULE_LINES
#line 1 "mongoose/src/socks.c"
#endif
/*
* Copyright (c) 2017 Cesanta Software Limited
* All rights reserved
*/
#if MG_ENABLE_SOCKS
/* Amalgamated: #include "mongoose/src/socks.h" */
/* Amalgamated: #include "mongoose/src/internal.h" */
/*
* https://www.ietf.org/rfc/rfc1928.txt paragraph 3, handle client handshake
*
* +----+----------+----------+
* |VER | NMETHODS | METHODS |
* +----+----------+----------+
* | 1 | 1 | 1 to 255 |
* +----+----------+----------+
*/
static void mg_socks5_handshake(struct mg_connection *c) {
struct mbuf *r = &c->recv_mbuf;
if (r->buf[0] != MG_SOCKS_VERSION) {
c->flags |= MG_F_CLOSE_IMMEDIATELY;
} else if (r->len > 2 && (size_t) r->buf[1] + 2 <= r->len) {
/* https://www.ietf.org/rfc/rfc1928.txt paragraph 3 */
unsigned char reply[2] = {MG_SOCKS_VERSION, MG_SOCKS_HANDSHAKE_FAILURE};
int i;
for (i = 2; i < r->buf[1] + 2; i++) {
/* TODO(lsm): support other auth methods */
if (r->buf[i] == MG_SOCKS_HANDSHAKE_NOAUTH) reply[1] = r->buf[i];
}
mbuf_remove(r, 2 + r->buf[1]);
mg_send(c, reply, sizeof(reply));
c->flags |= MG_SOCKS_HANDSHAKE_DONE; /* Mark handshake done */
}
}
static void disband(struct mg_connection *c) {
struct mg_connection *c2 = (struct mg_connection *) c->user_data;
if (c2 != NULL) {
c2->flags |= MG_F_SEND_AND_CLOSE;
c2->user_data = NULL;
}
c->flags |= MG_F_SEND_AND_CLOSE;
c->user_data = NULL;
}
static void relay_data(struct mg_connection *c) {
struct mg_connection *c2 = (struct mg_connection *) c->user_data;
if (c2 != NULL) {
mg_send(c2, c->recv_mbuf.buf, c->recv_mbuf.len);
mbuf_remove(&c->recv_mbuf, c->recv_mbuf.len);
} else {
c->flags |= MG_F_SEND_AND_CLOSE;
}
}
static void serv_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_CLOSE) {
disband(c);
} else if (ev == MG_EV_RECV) {
relay_data(c);
} else if (ev == MG_EV_CONNECT) {
int res = *(int *) ev_data;
if (res != 0) LOG(LL_ERROR, ("connect error: %d", res));
}
}
static void mg_socks5_connect(struct mg_connection *c, const char *addr) {
struct mg_connection *serv = mg_connect(c->mgr, addr, serv_ev_handler);
serv->user_data = c;
c->user_data = serv;
}
/*
* Request, https://www.ietf.org/rfc/rfc1928.txt paragraph 4
*
* +----+-----+-------+------+----------+----------+
* |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
* +----+-----+-------+------+----------+----------+
* | 1 | 1 | X'00' | 1 | Variable | 2 |
* +----+-----+-------+------+----------+----------+
*/
static void mg_socks5_handle_request(struct mg_connection *c) {
struct mbuf *r = &c->recv_mbuf;
unsigned char *p = (unsigned char *) r->buf;
unsigned char addr_len = 4, reply = MG_SOCKS_SUCCESS;
int ver, cmd, atyp;
char addr[300];
if (r->len < 8) return; /* return if not fully buffered. min DST.ADDR is 2 */
ver = p[0];
cmd = p[1];
atyp = p[3];
/* TODO(lsm): support other commands */
if (ver != MG_SOCKS_VERSION || cmd != MG_SOCKS_CMD_CONNECT) {
reply = MG_SOCKS_CMD_NOT_SUPPORTED;
} else if (atyp == MG_SOCKS_ADDR_IPV4) {
addr_len = 4;
if (r->len < (size_t) addr_len + 6) return; /* return if not buffered */
snprintf(addr, sizeof(addr), "%d.%d.%d.%d:%d", p[4], p[5], p[6], p[7],
p[8] << 8 | p[9]);
mg_socks5_connect(c, addr);
} else if (atyp == MG_SOCKS_ADDR_IPV6) {
addr_len = 16;
if (r->len < (size_t) addr_len + 6) return; /* return if not buffered */
snprintf(addr, sizeof(addr), "[%x:%x:%x:%x:%x:%x:%x:%x]:%d",
p[4] << 8 | p[5], p[6] << 8 | p[7], p[8] << 8 | p[9],
p[10] << 8 | p[11], p[12] << 8 | p[13], p[14] << 8 | p[15],
p[16] << 8 | p[17], p[18] << 8 | p[19], p[20] << 8 | p[21]);
mg_socks5_connect(c, addr);
} else if (atyp == MG_SOCKS_ADDR_DOMAIN) {
addr_len = p[4] + 1;
if (r->len < (size_t) addr_len + 6) return; /* return if not buffered */
snprintf(addr, sizeof(addr), "%.*s:%d", p[4], p + 5,
p[4 + addr_len] << 8 | p[4 + addr_len + 1]);
mg_socks5_connect(c, addr);
} else {
reply = MG_SOCKS_ADDR_NOT_SUPPORTED;
}
/*
* Reply, https://www.ietf.org/rfc/rfc1928.txt paragraph 5
*
* +----+-----+-------+------+----------+----------+
* |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
* +----+-----+-------+------+----------+----------+
* | 1 | 1 | X'00' | 1 | Variable | 2 |
* +----+-----+-------+------+----------+----------+
*/
{
unsigned char buf[] = {MG_SOCKS_VERSION, reply, 0};
mg_send(c, buf, sizeof(buf));
}
mg_send(c, r->buf + 3, addr_len + 1 + 2);
mbuf_remove(r, 6 + addr_len); /* Remove request from the input stream */
c->flags |= MG_SOCKS_CONNECT_DONE; /* Mark ourselves as connected */
}
static void socks_handler(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_RECV) {
if (!(c->flags & MG_SOCKS_HANDSHAKE_DONE)) mg_socks5_handshake(c);
if (c->flags & MG_SOCKS_HANDSHAKE_DONE &&
!(c->flags & MG_SOCKS_CONNECT_DONE)) {
mg_socks5_handle_request(c);
}
if (c->flags & MG_SOCKS_CONNECT_DONE) relay_data(c);
} else if (ev == MG_EV_CLOSE) {
disband(c);
}
(void) ev_data;
}
void mg_set_protocol_socks(struct mg_connection *c) {
c->proto_handler = socks_handler;
}
#endif
#ifdef MG_MODULE_LINES
#line 1 "common/platforms/cc3200/cc3200_libc.c" #line 1 "common/platforms/cc3200/cc3200_libc.c"
#endif #endif
/* /*
@@ -13548,11 +13962,10 @@ extern const struct mg_iface_vtable mg_simplelink_iface_vtable;
#define MG_TCP_RECV_BUFFER_SIZE 1024 #define MG_TCP_RECV_BUFFER_SIZE 1024
#define MG_UDP_RECV_BUFFER_SIZE 1500 #define MG_UDP_RECV_BUFFER_SIZE 1500
static sock_t mg_open_listening_socket(union socket_address *sa, int type, static sock_t mg_open_listening_socket(struct mg_connection *nc,
union socket_address *sa, int type,
int proto); int proto);
int sl_set_ssl_opts(struct mg_connection *nc);
void mg_set_non_blocking_mode(sock_t sock) { void mg_set_non_blocking_mode(sock_t sock) {
SlSockNonblocking_t opt; SlSockNonblocking_t opt;
#if SL_MAJOR_VERSION_NUM < 2 #if SL_MAJOR_VERSION_NUM < 2
@@ -13578,7 +13991,7 @@ void mg_sl_if_connect_tcp(struct mg_connection *nc,
} }
mg_sock_set(nc, sock); mg_sock_set(nc, sock);
#if MG_ENABLE_SSL #if MG_ENABLE_SSL
nc->err = sl_set_ssl_opts(nc); nc->err = sl_set_ssl_opts(sock, nc);
if (nc->err != 0) goto out; if (nc->err != 0) goto out;
#endif #endif
nc->err = sl_Connect(sock, &sa->sa, sizeof(sa->sin)); nc->err = sl_Connect(sock, &sa->sa, sizeof(sa->sin));
@@ -13600,18 +14013,14 @@ void mg_sl_if_connect_udp(struct mg_connection *nc) {
int mg_sl_if_listen_tcp(struct mg_connection *nc, union socket_address *sa) { int mg_sl_if_listen_tcp(struct mg_connection *nc, union socket_address *sa) {
int proto = 0; int proto = 0;
if (nc->flags & MG_F_SSL) proto = SL_SEC_SOCKET; if (nc->flags & MG_F_SSL) proto = SL_SEC_SOCKET;
sock_t sock = mg_open_listening_socket(sa, SOCK_STREAM, proto); sock_t sock = mg_open_listening_socket(nc, sa, SOCK_STREAM, proto);
if (sock < 0) return sock; if (sock < 0) return sock;
mg_sock_set(nc, sock); mg_sock_set(nc, sock);
#if MG_ENABLE_SSL
return sl_set_ssl_opts(nc);
#else
return 0; return 0;
#endif
} }
int mg_sl_if_listen_udp(struct mg_connection *nc, union socket_address *sa) { int mg_sl_if_listen_udp(struct mg_connection *nc, union socket_address *sa) {
sock_t sock = mg_open_listening_socket(sa, SOCK_DGRAM, 0); sock_t sock = mg_open_listening_socket(nc, sa, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET) return (errno ? errno : 1); if (sock == INVALID_SOCKET) return (errno ? errno : 1);
mg_sock_set(nc, sock); mg_sock_set(nc, sock);
return 0; return 0;
@@ -13667,22 +14076,27 @@ static int mg_accept_conn(struct mg_connection *lc) {
} }
/* 'sa' must be an initialized address to bind to */ /* 'sa' must be an initialized address to bind to */
static sock_t mg_open_listening_socket(union socket_address *sa, int type, static sock_t mg_open_listening_socket(struct mg_connection *nc,
union socket_address *sa, int type,
int proto) { int proto) {
int r; int r;
socklen_t sa_len = socklen_t sa_len =
(sa->sa.sa_family == AF_INET) ? sizeof(sa->sin) : sizeof(sa->sin6); (sa->sa.sa_family == AF_INET) ? sizeof(sa->sin) : sizeof(sa->sin6);
sock_t sock = sl_Socket(sa->sa.sa_family, type, proto); sock_t sock = sl_Socket(sa->sa.sa_family, type, proto);
if (sock < 0) return sock; if (sock < 0) return sock;
if ((r = sl_Bind(sock, &sa->sa, sa_len)) < 0) { if ((r = sl_Bind(sock, &sa->sa, sa_len)) < 0) goto clean;
sl_Close(sock); if (type != SOCK_DGRAM) {
return r; #if MG_ENABLE_SSL
} if ((r = sl_set_ssl_opts(sock, nc)) < 0) goto clean;
if (type != SOCK_DGRAM && (r = sl_Listen(sock, SOMAXCONN)) < 0) { #endif
sl_Close(sock); if ((r = sl_Listen(sock, SOMAXCONN)) < 0) goto clean;
return r;
} }
mg_set_non_blocking_mode(sock); mg_set_non_blocking_mode(sock);
clean:
if (r < 0) {
sl_Close(sock);
sock = r;
}
return sock; return sock;
} }
@@ -14167,9 +14581,9 @@ static char *sl_pem2der(const char *pem_file) {
} }
#endif #endif
int sl_set_ssl_opts(struct mg_connection *nc) { int sl_set_ssl_opts(int sock, struct mg_connection *nc) {
int err; int err;
struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data; const struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data;
DBG(("%p ssl ctx: %p", nc, ctx)); DBG(("%p ssl ctx: %p", nc, ctx));
if (ctx != NULL) { if (ctx != NULL) {
@@ -14181,11 +14595,11 @@ int sl_set_ssl_opts(struct mg_connection *nc) {
char *ssl_cert = sl_pem2der(ctx->ssl_cert); char *ssl_cert = sl_pem2der(ctx->ssl_cert);
char *ssl_key = sl_pem2der(ctx->ssl_key); char *ssl_key = sl_pem2der(ctx->ssl_key);
if (ssl_cert != NULL && ssl_key != NULL) { if (ssl_cert != NULL && ssl_key != NULL) {
err = sl_SetSockOpt(nc->sock, SL_SOL_SOCKET, err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME, ssl_cert, SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME, ssl_cert,
strlen(ssl_cert)); strlen(ssl_cert));
LOG(LL_INFO, ("CERTIFICATE_FILE_NAME %s -> %d", ssl_cert, err)); LOG(LL_INFO, ("CERTIFICATE_FILE_NAME %s -> %d", ssl_cert, err));
err = sl_SetSockOpt(nc->sock, SL_SOL_SOCKET, err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME, ssl_key, SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME, ssl_key,
strlen(ssl_key)); strlen(ssl_key));
LOG(LL_INFO, ("PRIVATE_KEY_FILE_NAME %s -> %d", ssl_key, err)); LOG(LL_INFO, ("PRIVATE_KEY_FILE_NAME %s -> %d", ssl_key, err));
@@ -14200,7 +14614,7 @@ int sl_set_ssl_opts(struct mg_connection *nc) {
if (ctx->ssl_ca_cert[0] != '\0') { if (ctx->ssl_ca_cert[0] != '\0') {
char *ssl_ca_cert = sl_pem2der(ctx->ssl_ca_cert); char *ssl_ca_cert = sl_pem2der(ctx->ssl_ca_cert);
if (ssl_ca_cert != NULL) { if (ssl_ca_cert != NULL) {
err = sl_SetSockOpt(nc->sock, SL_SOL_SOCKET, err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
SL_SO_SECURE_FILES_CA_FILE_NAME, ssl_ca_cert, SL_SO_SECURE_FILES_CA_FILE_NAME, ssl_ca_cert,
strlen(ssl_ca_cert)); strlen(ssl_ca_cert));
LOG(LL_INFO, ("CA_FILE_NAME %s -> %d", ssl_ca_cert, err)); LOG(LL_INFO, ("CA_FILE_NAME %s -> %d", ssl_ca_cert, err));
@@ -14212,7 +14626,7 @@ int sl_set_ssl_opts(struct mg_connection *nc) {
} }
} }
if (ctx->ssl_server_name != NULL) { if (ctx->ssl_server_name != NULL) {
err = sl_SetSockOpt(nc->sock, SL_SOL_SOCKET, err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
SL_SO_SECURE_DOMAIN_NAME_VERIFICATION, SL_SO_SECURE_DOMAIN_NAME_VERIFICATION,
ctx->ssl_server_name, strlen(ctx->ssl_server_name)); ctx->ssl_server_name, strlen(ctx->ssl_server_name));
DBG(("DOMAIN_NAME_VERIFICATION %s -> %d", ctx->ssl_server_name, err)); DBG(("DOMAIN_NAME_VERIFICATION %s -> %d", ctx->ssl_server_name, err));
@@ -14439,6 +14853,7 @@ static err_t mg_lwip_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb,
struct pbuf *q = p->next; struct pbuf *q = p->next;
for (; q != NULL; q = q->next) pbuf_ref(q); for (; q != NULL; q = q->next) pbuf_ref(q);
} }
mgos_lock();
if (cs->rx_chain == NULL) { if (cs->rx_chain == NULL) {
cs->rx_offset = 0; cs->rx_offset = 0;
} else if (pbuf_clen(cs->rx_chain) >= 4) { } else if (pbuf_clen(cs->rx_chain) >= 4) {
@@ -14452,6 +14867,7 @@ static err_t mg_lwip_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb,
p = np; p = np;
} }
} }
mgos_unlock();
mg_lwip_recv_common(nc, p); mg_lwip_recv_common(nc, p);
return ERR_OK; return ERR_OK;
} }
@@ -14929,7 +15345,8 @@ void mg_lwip_if_recved(struct mg_connection *nc, size_t len) {
DBG(("%p invalid socket", nc)); DBG(("%p invalid socket", nc));
return; return;
} }
DBG(("%p %p %u", nc, cs->pcb.tcp, len)); DBG(("%p %p %u %u", nc, cs->pcb.tcp, len,
(cs->rx_chain ? cs->rx_chain->tot_len : 0)));
struct tcp_recved_ctx ctx = {.tpcb = cs->pcb.tcp, .len = len}; struct tcp_recved_ctx ctx = {.tpcb = cs->pcb.tcp, .len = len};
#if MG_ENABLE_SSL #if MG_ENABLE_SSL
if (!(nc->flags & MG_F_SSL)) { if (!(nc->flags & MG_F_SSL)) {
@@ -15465,6 +15882,7 @@ int ssl_socket_recv(void *ctx, unsigned char *buf, size_t len) {
} }
size_t seg_len = (seg->len - cs->rx_offset); size_t seg_len = (seg->len - cs->rx_offset);
DBG(("%u %u %u %u", len, cs->rx_chain->len, seg_len, cs->rx_chain->tot_len)); DBG(("%u %u %u %u", len, cs->rx_chain->len, seg_len, cs->rx_chain->tot_len));
mgos_lock();
len = MIN(len, seg_len); len = MIN(len, seg_len);
pbuf_copy_partial(seg, buf, len, cs->rx_offset); pbuf_copy_partial(seg, buf, len, cs->rx_offset);
cs->rx_offset += len; cs->rx_offset += len;
@@ -15476,6 +15894,7 @@ int ssl_socket_recv(void *ctx, unsigned char *buf, size_t len) {
pbuf_free(seg); pbuf_free(seg);
cs->rx_offset = 0; cs->rx_offset = 0;
} }
mgos_unlock();
LOG(LL_DEBUG, ("%p <- %d", nc, (int) len)); LOG(LL_DEBUG, ("%p <- %d", nc, (int) len));
return len; return len;
} }
+75 -2
View File
@@ -23,7 +23,7 @@
#ifndef CS_MONGOOSE_SRC_COMMON_H_ #ifndef CS_MONGOOSE_SRC_COMMON_H_
#define CS_MONGOOSE_SRC_COMMON_H_ #define CS_MONGOOSE_SRC_COMMON_H_
#define MG_VERSION "6.9" #define MG_VERSION "6.10"
/* Local tweaks, applied before any of Mongoose's own headers. */ /* Local tweaks, applied before any of Mongoose's own headers. */
#ifdef MG_LOCALS #ifdef MG_LOCALS
@@ -1200,7 +1200,7 @@ int sl_fs_init(void);
void sl_restart_cb(struct mg_mgr *mgr); void sl_restart_cb(struct mg_mgr *mgr);
int sl_set_ssl_opts(struct mg_connection *nc); int sl_set_ssl_opts(int sock, struct mg_connection *nc);
#ifdef __cplusplus #ifdef __cplusplus
} }
@@ -3029,6 +3029,10 @@ struct { \
#define MG_ENABLE_MQTT 1 #define MG_ENABLE_MQTT 1
#endif #endif
#ifndef MG_ENABLE_SOCKS
#define MG_ENABLE_SOCKS 0
#endif
#ifndef MG_ENABLE_MQTT_BROKER #ifndef MG_ENABLE_MQTT_BROKER
#define MG_ENABLE_MQTT_BROKER 0 #define MG_ENABLE_MQTT_BROKER 0
#endif #endif
@@ -6032,3 +6036,72 @@ struct mg_connection *mg_sntp_get_time(struct mg_mgr *mgr,
#endif #endif
#endif /* CS_MONGOOSE_SRC_SNTP_H_ */ #endif /* CS_MONGOOSE_SRC_SNTP_H_ */
#ifdef MG_MODULE_LINES
#line 1 "mongoose/src/socks.h"
#endif
/*
* Copyright (c) 2017 Cesanta Software Limited
* All rights reserved
*/
#ifndef CS_MONGOOSE_SRC_SOCKS_H_
#define CS_MONGOOSE_SRC_SOCKS_H_
#if MG_ENABLE_SOCKS
#define MG_SOCKS_VERSION 5
#define MG_SOCKS_HANDSHAKE_DONE MG_F_USER_1
#define MG_SOCKS_CONNECT_DONE MG_F_USER_2
/* SOCKS5 handshake methods */
enum mg_socks_handshake_method {
MG_SOCKS_HANDSHAKE_NOAUTH = 0, /* Handshake method - no authentication */
MG_SOCKS_HANDSHAKE_GSSAPI = 1, /* Handshake method - GSSAPI auth */
MG_SOCKS_HANDSHAKE_USERPASS = 2, /* Handshake method - user/password auth */
MG_SOCKS_HANDSHAKE_FAILURE = 0xff, /* Handshake method - failure */
};
/* SOCKS5 commands */
enum mg_socks_command {
MG_SOCKS_CMD_CONNECT = 1, /* Command: CONNECT */
MG_SOCKS_CMD_BIND = 2, /* Command: BIND */
MG_SOCKS_CMD_UDP_ASSOCIATE = 3, /* Command: UDP ASSOCIATE */
};
/* SOCKS5 address types */
enum mg_socks_address_type {
MG_SOCKS_ADDR_IPV4 = 1, /* Address type: IPv4 */
MG_SOCKS_ADDR_DOMAIN = 3, /* Address type: Domain name */
MG_SOCKS_ADDR_IPV6 = 4, /* Address type: IPv6 */
};
/* SOCKS5 response codes */
enum mg_socks_response {
MG_SOCKS_SUCCESS = 0, /* Response: success */
MG_SOCKS_FAILURE = 1, /* Response: failure */
MG_SOCKS_NOT_ALLOWED = 2, /* Response: connection not allowed */
MG_SOCKS_NET_UNREACHABLE = 3, /* Response: network unreachable */
MG_SOCKS_HOST_UNREACHABLE = 4, /* Response: network unreachable */
MG_SOCKS_CONN_REFUSED = 5, /* Response: network unreachable */
MG_SOCKS_TTL_EXPIRED = 6, /* Response: network unreachable */
MG_SOCKS_CMD_NOT_SUPPORTED = 7, /* Response: network unreachable */
MG_SOCKS_ADDR_NOT_SUPPORTED = 8, /* Response: network unreachable */
};
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Turn the connection into the SOCKS server */
void mg_set_protocol_socks(struct mg_connection *c);
/* Create socks tunnel for the client connection */
struct mg_iface *mg_socks_mk_iface(struct mg_mgr *, const char *proxy_addr);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
#endif
+6 -2
View File
@@ -99,9 +99,9 @@ def resolve(path, parent_name):
else: else:
p = os.path.join(args.include_path, path) p = os.path.join(args.include_path, path)
if os.path.exists(p) and not args.norel: if os.path.exists(p) and not args.norel:
p = os.path.realpath(p).replace('%s/' % os.getcwd(), '') p = os.path.realpath(p).replace('%s%s' % (os.getcwd(), os.sep), '')
# print >>sys.stderr, '%s -> %s (cwd %s)' % (path, p, os.getcwd()) # print >>sys.stderr, '%s -> %s (cwd %s)' % (path, p, os.getcwd())
return p return p.replace(os.sep, '/')
def emit_line_directive(out, name, parent_name): def emit_line_directive(out, name, parent_name):
print >>out, '''#ifdef %(prefix)s_MODULE_LINES print >>out, '''#ifdef %(prefix)s_MODULE_LINES
@@ -148,6 +148,10 @@ if args.first:
# emitting # emitting
if sys.platform == "win32":
import os, msvcrt
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
if args.public: if args.public:
print '#include "%s"' % (args.public) print '#include "%s"' % (args.public)