mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-26 12:14:56 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e50fe4475 | ||
|
|
7942803a75 | ||
|
|
a8b74a9021 | ||
|
|
27a9a62843 | ||
|
|
9b268b6c77 | ||
|
|
3b3ac48edd | ||
|
|
598e96a0cc | ||
|
|
b5dd0e8093 | ||
|
|
9b24fdfd1d | ||
|
|
8313896a85 | ||
|
|
8193302162 | ||
|
|
6e3e5560d0 | ||
|
|
f0c6630a16 | ||
|
|
1db747da29 | ||
|
|
8065439f96 |
No files matched your search
File renamed without changes.
@@ -1,7 +0,0 @@
|
|||||||
---
|
|
||||||
title: CoAP
|
|
||||||
items:
|
|
||||||
- { name: server_example.md }
|
|
||||||
- { name: client_example.md }
|
|
||||||
- { name: ../c-api/coap.h/ }
|
|
||||||
---
|
|
||||||
File renamed without changes.
@@ -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.
|
||||||
@@ -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/ }
|
|
||||||
---
|
|
||||||
+2
-4
@@ -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.
|
||||||
@@ -32,4 +30,4 @@ Example:
|
|||||||
NOTE: In the CGI handler we don't use explicitly a system call waitpid() for
|
NOTE: In the CGI handler we don't use explicitly a system call waitpid() for
|
||||||
reaping zombie processes. Instead, we set the SIGCHLD handler to SIG_IGN.
|
reaping zombie processes. Instead, we set the SIGCHLD handler to SIG_IGN.
|
||||||
It will cause zombie processes to be reaped automatically.
|
It will cause zombie processes to be reaped automatically.
|
||||||
CAUTION: not all OSes (e.g. QNX) reap zombies if SIGCHLD is ignored.
|
CAUTION: not all OSes (e.g. QNX) reap zombies if SIGCHLD is ignored.
|
||||||
@@ -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
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||||
<form method="POST" action="/upload" enctype="multipart/form-data">
|
<form method="POST" action="/upload" enctype="multipart/form-data">
|
||||||
<input type="file" name="file">
|
<input type="file" name="file">
|
||||||
<input type="submit" value="Upload">
|
<input type="submit" value="Upload">
|
||||||
</form>
|
</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.
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
title: MQTT client example
|
|
||||||
---
|
|
||||||
|
|
||||||
See https://github.com/cesanta/mongoose/tree/master/examples/mqtt_client
|
|
||||||
@@ -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)
|
||||||
|
|
||||||
@@ -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/ }
|
|
||||||
---
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
title: MQTT server example
|
|
||||||
---
|
|
||||||
|
|
||||||
See https://github.com/cesanta/mongoose/tree/master/examples/mqtt_broker
|
|
||||||
@@ -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
|
|
||||||
@@ -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.
|
|
||||||
@@ -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,6 +1,4 @@
|
|||||||
---
|
# Design Concept
|
||||||
title: Design Concept
|
|
||||||
---
|
|
||||||
|
|
||||||
Mongoose has three basic data structures:
|
Mongoose has three basic data structures:
|
||||||
|
|
||||||
|
|||||||
@@ -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,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,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
@@ -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.
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||

|

|
||||||
@@ -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`
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user