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 @@
|
||||
---
|
||||
title: DNS server example
|
||||
---
|
||||
# Examples
|
||||
|
||||
|
||||
## DNS server example
|
||||
|
||||
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).
|
||||
|
||||
|
||||
## 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 @@
|
||||
---
|
||||
title: CGI
|
||||
---
|
||||
# CGI
|
||||
|
||||
[CGI](https://en.wikipedia.org/wiki/Common_Gateway_Interface)
|
||||
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
|
||||
reaping zombie processes. Instead, we set the SIGCHLD handler to SIG_IGN.
|
||||
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 @@
|
||||
---
|
||||
title: HTTP client example
|
||||
---
|
||||
# HTTP client example
|
||||
|
||||
To create an HTTP client, follow this pattern:
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
---
|
||||
title: Digest Authentication
|
||||
---
|
||||
# Digest Authentication
|
||||
|
||||
Mongoose has a built-in Digest (MD5) authentication support. In order to
|
||||
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.
|
||||
|
||||
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:
|
||||
|
||||
```
|
||||
+1
-3
@@ -1,6 +1,4 @@
|
||||
---
|
||||
title: HTTP events
|
||||
---
|
||||
#: HTTP events
|
||||
|
||||
As discussed in the overview, `mg_set_protocol_http_websocket()` function
|
||||
parses incoming data, treats it as HTTP or WebSocket, and triggers high-level
|
||||
|
||||
+1
-3
@@ -1,6 +1,4 @@
|
||||
---
|
||||
title: Serving files
|
||||
---
|
||||
# Serving files
|
||||
|
||||
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
|
||||
|
||||
@@ -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 @@
|
||||
---
|
||||
title: HTTP server example
|
||||
---
|
||||
# HTTP server example
|
||||
|
||||
To create an HTTP server, follow this pattern:
|
||||
|
||||
+1
-3
@@ -1,6 +1,4 @@
|
||||
---
|
||||
title: SSI
|
||||
---
|
||||
# SSI
|
||||
|
||||
Server Side Includes (SSI) is a simple interpreted server-side scripting
|
||||
language which is most commonly used to include the contents of a file
|
||||
|
||||
+1
-3
@@ -1,6 +1,4 @@
|
||||
---
|
||||
title: Enabling HTTPS
|
||||
---
|
||||
# Enabling SSL (HTTPS)
|
||||
|
||||
To enable SSL on the server side, please follow these steps:
|
||||
|
||||
|
||||
+5
-7
@@ -1,14 +1,12 @@
|
||||
---
|
||||
title: Handling file uploads
|
||||
---
|
||||
# Handling file uploads
|
||||
|
||||
In order to handle file uploads, use the following HTML snippet:
|
||||
|
||||
```HTML
|
||||
<form method="POST" action="/upload" enctype="multipart/form-data">
|
||||
<input type="file" name="file">
|
||||
<input type="submit" value="Upload">
|
||||
</form>
|
||||
<form method="POST" action="/upload" enctype="multipart/form-data">
|
||||
<input type="file" name="file">
|
||||
<input type="submit" value="Upload">
|
||||
</form>
|
||||
```
|
||||
|
||||
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 @@
|
||||
---
|
||||
title: Design Concept
|
||||
---
|
||||
# Design Concept
|
||||
|
||||
Mongoose has three basic data structures:
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
---
|
||||
title: Connection flags
|
||||
---
|
||||
# Connection flags
|
||||
|
||||
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`
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
---
|
||||
title: Event handler function
|
||||
---
|
||||
# Event handler 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
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
---
|
||||
title: Events
|
||||
---
|
||||
# Events
|
||||
|
||||
Mongoose accepts incoming connections, reads and writes data and calls
|
||||
specified event handlers for each connection when appropriate. A typical event
|
||||
|
||||
+1
-12
@@ -1,15 +1,4 @@
|
||||
---
|
||||
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 }
|
||||
---
|
||||
# Introduction
|
||||
|
||||
Mongoose is a networking library written in C.
|
||||
It is a swiss army knife for embedded network programming.
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
---
|
||||
title: Memory buffers
|
||||
---
|
||||
# Memory buffers
|
||||
|
||||
Each connection has a send and receive buffer, `struct mg_connection::send_mbuf`
|
||||
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
|
||||
is closed, an `MG_EV_CLOSE` event is sent.
|
||||
|
||||

|
||||

|
||||
@@ -1,6 +1,4 @@
|
||||
---
|
||||
title: Example - TCP echo server
|
||||
---
|
||||
# Example - TCP echo server
|
||||
|
||||
- Copy `mongoose.c` and `mongoose.h` to your build tree
|
||||
- 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
|
||||
endif
|
||||
|
||||
ifeq ($(JS), yes)
|
||||
V7_PATH = ../../deps/v7
|
||||
CFLAGS_EXTRA += -DMG_ENABLE_JAVASCRIPT -I $(V7_PATH) $(V7_PATH)/v7.c
|
||||
ifdef ASAN
|
||||
CC = clang
|
||||
CFLAGS += -fsanitize=address
|
||||
endif
|
||||
|
||||
$(PROG): $(SOURCES)
|
||||
|
||||
@@ -75,11 +75,6 @@ int main(int argc, char *argv[]) {
|
||||
s_http_port = argv[++i];
|
||||
} else if (strcmp(argv[i], "-a") == 0 && i + 1 < argc) {
|
||||
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) {
|
||||
s_http_server_opts.global_auth_file = argv[++i];
|
||||
} 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);
|
||||
|
||||
/* 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,
|
||||
const char *filename);
|
||||
@@ -316,8 +316,8 @@ double cs_log_ts WEAK;
|
||||
|
||||
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(char *str) {
|
||||
void cs_log_set_filter(const char *str) WEAK;
|
||||
void cs_log_set_filter(const char *str) {
|
||||
free(s_filter_pattern);
|
||||
if (str != NULL) {
|
||||
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_event_handler_t ev_handler, void *user_data, int ev,
|
||||
void *ev_data) {
|
||||
static int nesting_level = 0;
|
||||
nesting_level++;
|
||||
if (ev_handler == NULL) {
|
||||
/*
|
||||
* 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 & _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);
|
||||
}
|
||||
}
|
||||
@@ -2256,6 +2261,7 @@ MG_INTERNAL void mg_call(struct mg_connection *nc,
|
||||
ev_handler == nc->handler ? "user" : "proto", nc->flags,
|
||||
(int) nc->recv_mbuf.len, (int) nc->send_mbuf.len));
|
||||
}
|
||||
nesting_level--;
|
||||
#if !MG_ENABLE_CALLBACK_USERDATA
|
||||
(void) user_data;
|
||||
#endif
|
||||
@@ -2264,14 +2270,8 @@ MG_INTERNAL void mg_call(struct mg_connection *nc,
|
||||
void mg_if_timer(struct mg_connection *c, double now) {
|
||||
if (c->ev_timer_time > 0 && now >= c->ev_timer_time) {
|
||||
double old_value = c->ev_timer_time;
|
||||
mg_call(c, NULL, c->user_data, MG_EV_TIMER, &now);
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
c->ev_timer_time = 0;
|
||||
mg_call(c, NULL, c->user_data, MG_EV_TIMER, &old_value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
#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"
|
||||
#endif
|
||||
/* 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;
|
||||
|
||||
const struct mg_iface_vtable *mg_ifaces[] = {
|
||||
&mg_default_iface_vtable,
|
||||
#if MG_ENABLE_TUN
|
||||
const struct mg_iface_vtable *mg_ifaces[] = {&mg_default_iface_vtable,
|
||||
&mg_tun_iface_vtable};
|
||||
#else
|
||||
const struct mg_iface_vtable *mg_ifaces[] = {&mg_default_iface_vtable};
|
||||
&mg_tun_iface_vtable,
|
||||
#endif
|
||||
};
|
||||
|
||||
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 */
|
||||
#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"
|
||||
#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"
|
||||
#endif
|
||||
|
||||
#define MG_F_HTTP_CGI_PARSE_HEADERS MG_F_USER_1
|
||||
|
||||
/*
|
||||
* This structure helps to create an environment for the spawned CGI program.
|
||||
* 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;
|
||||
|
||||
if (nc == NULL) {
|
||||
/* The corresponding network connection was closed. */
|
||||
cgi_nc->flags |= MG_F_CLOSE_IMMEDIATELY;
|
||||
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
|
||||
* 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;
|
||||
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");
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
break;
|
||||
case MG_EV_CLOSE:
|
||||
DBG(("%p CLOSE", cgi_nc));
|
||||
mg_http_free_proto_data_cgi(&mg_http_get_proto_data(nc)->cgi);
|
||||
nc->flags |= MG_F_SEND_AND_CLOSE;
|
||||
break;
|
||||
@@ -8688,7 +8929,7 @@ MG_INTERNAL void mg_handle_cgi(struct mg_connection *nc, const char *prog,
|
||||
#if !MG_ENABLE_CALLBACK_USERDATA
|
||||
cgi_pd->cgi.cgi_nc->user_data = nc;
|
||||
#endif
|
||||
nc->flags |= MG_F_USER_1;
|
||||
nc->flags |= MG_F_HTTP_CGI_PARSE_HEADERS;
|
||||
/* Push POST data to the CGI */
|
||||
if (n > 0 && n < nc->recv_mbuf.len) {
|
||||
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) {
|
||||
if (d != NULL) {
|
||||
if (d->cgi_nc != NULL) d->cgi_nc->flags |= MG_F_CLOSE_IMMEDIATELY;
|
||||
memset(d, 0, sizeof(struct mg_http_proto_data_cgi));
|
||||
if (d == NULL) return;
|
||||
if (d->cgi_nc != NULL) {
|
||||
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 */
|
||||
@@ -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) {
|
||||
struct mg_http_proto_data *htd = mg_http_get_proto_data(nc);
|
||||
return (htd != NULL ? &htd->ws_data : NULL);
|
||||
};
|
||||
}
|
||||
|
||||
static int mg_deliver_websocket_data(struct mg_connection *nc) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
te = (struct mg_mqtt_topic_expression *) MG_REALLOC(
|
||||
ss->subscriptions,
|
||||
sizeof(*ss->subscriptions) * (ss->num_subscriptions + num_subs));
|
||||
if (te == NULL) {
|
||||
nc->flags |= MG_F_CLOSE_IMMEDIATELY;
|
||||
return;
|
||||
}
|
||||
ss->subscriptions = te;
|
||||
for (pos = 0;
|
||||
(pos = mg_mqtt_next_subscribe_topic(msg, &topic, &qos, pos)) != -1;
|
||||
ss->num_subscriptions++) {
|
||||
te = &ss->subscriptions[ss->num_subscriptions];
|
||||
te->topic = (char *) MG_MALLOC(topic.len + 1);
|
||||
te->qos = qos;
|
||||
strncpy((char *) te->topic, topic.p, topic.len + 1);
|
||||
if (num_subs > 0) {
|
||||
te = (struct mg_mqtt_topic_expression *) MG_REALLOC(
|
||||
ss->subscriptions,
|
||||
sizeof(*ss->subscriptions) * (ss->num_subscriptions + num_subs));
|
||||
if (te == NULL) {
|
||||
nc->flags |= MG_F_CLOSE_IMMEDIATELY;
|
||||
return;
|
||||
}
|
||||
ss->subscriptions = te;
|
||||
for (pos = 0;
|
||||
pos < (int) msg->payload.len &&
|
||||
(pos = mg_mqtt_next_subscribe_topic(msg, &topic, &qos, pos)) != -1;
|
||||
ss->num_subscriptions++) {
|
||||
te = &ss->subscriptions[ss->num_subscriptions];
|
||||
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,
|
||||
@@ -12553,6 +12805,168 @@ struct mg_connection *mg_sntp_get_time(struct mg_mgr *mgr,
|
||||
|
||||
#endif /* MG_ENABLE_SNTP */
|
||||
#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"
|
||||
#endif
|
||||
/*
|
||||
@@ -13548,11 +13962,10 @@ extern const struct mg_iface_vtable mg_simplelink_iface_vtable;
|
||||
#define MG_TCP_RECV_BUFFER_SIZE 1024
|
||||
#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 sl_set_ssl_opts(struct mg_connection *nc);
|
||||
|
||||
void mg_set_non_blocking_mode(sock_t sock) {
|
||||
SlSockNonblocking_t opt;
|
||||
#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);
|
||||
#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;
|
||||
#endif
|
||||
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 proto = 0;
|
||||
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;
|
||||
mg_sock_set(nc, sock);
|
||||
#if MG_ENABLE_SSL
|
||||
return sl_set_ssl_opts(nc);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
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);
|
||||
mg_sock_set(nc, sock);
|
||||
return 0;
|
||||
@@ -13667,22 +14076,27 @@ static int mg_accept_conn(struct mg_connection *lc) {
|
||||
}
|
||||
|
||||
/* '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 r;
|
||||
socklen_t sa_len =
|
||||
(sa->sa.sa_family == AF_INET) ? sizeof(sa->sin) : sizeof(sa->sin6);
|
||||
sock_t sock = sl_Socket(sa->sa.sa_family, type, proto);
|
||||
if (sock < 0) return sock;
|
||||
if ((r = sl_Bind(sock, &sa->sa, sa_len)) < 0) {
|
||||
sl_Close(sock);
|
||||
return r;
|
||||
}
|
||||
if (type != SOCK_DGRAM && (r = sl_Listen(sock, SOMAXCONN)) < 0) {
|
||||
sl_Close(sock);
|
||||
return r;
|
||||
if ((r = sl_Bind(sock, &sa->sa, sa_len)) < 0) goto clean;
|
||||
if (type != SOCK_DGRAM) {
|
||||
#if MG_ENABLE_SSL
|
||||
if ((r = sl_set_ssl_opts(sock, nc)) < 0) goto clean;
|
||||
#endif
|
||||
if ((r = sl_Listen(sock, SOMAXCONN)) < 0) goto clean;
|
||||
}
|
||||
mg_set_non_blocking_mode(sock);
|
||||
clean:
|
||||
if (r < 0) {
|
||||
sl_Close(sock);
|
||||
sock = r;
|
||||
}
|
||||
return sock;
|
||||
}
|
||||
|
||||
@@ -14167,9 +14581,9 @@ static char *sl_pem2der(const char *pem_file) {
|
||||
}
|
||||
#endif
|
||||
|
||||
int sl_set_ssl_opts(struct mg_connection *nc) {
|
||||
int sl_set_ssl_opts(int sock, struct mg_connection *nc) {
|
||||
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));
|
||||
|
||||
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_key = sl_pem2der(ctx->ssl_key);
|
||||
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,
|
||||
strlen(ssl_cert));
|
||||
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,
|
||||
strlen(ssl_key));
|
||||
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') {
|
||||
char *ssl_ca_cert = sl_pem2der(ctx->ssl_ca_cert);
|
||||
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,
|
||||
strlen(ssl_ca_cert));
|
||||
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) {
|
||||
err = sl_SetSockOpt(nc->sock, SL_SOL_SOCKET,
|
||||
err = sl_SetSockOpt(sock, SL_SOL_SOCKET,
|
||||
SL_SO_SECURE_DOMAIN_NAME_VERIFICATION,
|
||||
ctx->ssl_server_name, strlen(ctx->ssl_server_name));
|
||||
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;
|
||||
for (; q != NULL; q = q->next) pbuf_ref(q);
|
||||
}
|
||||
mgos_lock();
|
||||
if (cs->rx_chain == NULL) {
|
||||
cs->rx_offset = 0;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
mgos_unlock();
|
||||
mg_lwip_recv_common(nc, p);
|
||||
return ERR_OK;
|
||||
}
|
||||
@@ -14929,7 +15345,8 @@ void mg_lwip_if_recved(struct mg_connection *nc, size_t len) {
|
||||
DBG(("%p invalid socket", nc));
|
||||
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};
|
||||
#if MG_ENABLE_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);
|
||||
DBG(("%u %u %u %u", len, cs->rx_chain->len, seg_len, cs->rx_chain->tot_len));
|
||||
mgos_lock();
|
||||
len = MIN(len, seg_len);
|
||||
pbuf_copy_partial(seg, buf, len, cs->rx_offset);
|
||||
cs->rx_offset += len;
|
||||
@@ -15476,6 +15894,7 @@ int ssl_socket_recv(void *ctx, unsigned char *buf, size_t len) {
|
||||
pbuf_free(seg);
|
||||
cs->rx_offset = 0;
|
||||
}
|
||||
mgos_unlock();
|
||||
LOG(LL_DEBUG, ("%p <- %d", nc, (int) len));
|
||||
return len;
|
||||
}
|
||||
|
||||
+75
-2
@@ -23,7 +23,7 @@
|
||||
#ifndef 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. */
|
||||
#ifdef MG_LOCALS
|
||||
@@ -1200,7 +1200,7 @@ int sl_fs_init(void);
|
||||
|
||||
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
|
||||
}
|
||||
@@ -3029,6 +3029,10 @@ struct { \
|
||||
#define MG_ENABLE_MQTT 1
|
||||
#endif
|
||||
|
||||
#ifndef MG_ENABLE_SOCKS
|
||||
#define MG_ENABLE_SOCKS 0
|
||||
#endif
|
||||
|
||||
#ifndef MG_ENABLE_MQTT_BROKER
|
||||
#define MG_ENABLE_MQTT_BROKER 0
|
||||
#endif
|
||||
@@ -6032,3 +6036,72 @@ struct mg_connection *mg_sntp_get_time(struct mg_mgr *mgr,
|
||||
#endif
|
||||
|
||||
#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:
|
||||
p = os.path.join(args.include_path, path)
|
||||
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())
|
||||
return p
|
||||
return p.replace(os.sep, '/')
|
||||
|
||||
def emit_line_directive(out, name, parent_name):
|
||||
print >>out, '''#ifdef %(prefix)s_MODULE_LINES
|
||||
@@ -148,6 +148,10 @@ if args.first:
|
||||
|
||||
# emitting
|
||||
|
||||
if sys.platform == "win32":
|
||||
import os, msvcrt
|
||||
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
|
||||
|
||||
if args.public:
|
||||
print '#include "%s"' % (args.public)
|
||||
|
||||
|
||||
Reference in new issue
Block a user