Skip to content

Commit 80d74e9

Browse files
committed
Merge branch 'dev'
2 parents 359060a + 43a0b50 commit 80d74e9

File tree

12 files changed

+335
-181
lines changed

12 files changed

+335
-181
lines changed

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,11 @@ the functionality:
6161

6262
# Contributions
6363

64-
To submit contributions, sign [Cesanta CLA](https://cesanta.com/cla.html)
65-
and send GitHub pull request.
64+
Contributions are welcome! Please follow the guidelines below:
65+
66+
- Sign [Cesanta CLA](https://cesanta.com/cla.html) and send GitHub pull request
67+
- When making pull requests, please make sure that it has only one commit,
68+
and imlements/fixes only one piece of functionality
6669

6770
# Looking for a pre-compiled Mongoose web server Windows or Mac binary?
6871
- [Download pre-compiled Mongoose web server binary.](https://www.cesanta.com/binary.html)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
PROG = http_proxy_client
2+
#SSL_LIB=openssl
3+
CFLAGS_EXTRA = -DMG_ENABLE_CALLBACK_USERDATA=1
4+
include ../examples.mk
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* Copyright (c) 2014 Cesanta Software Limited
3+
* All rights reserved
4+
*
5+
* This program fetches HTTP URLs.
6+
*/
7+
8+
#define MG_ENABLE_CALLBACK_USERDATA 1
9+
#include "mongoose.h"
10+
11+
static int s_exit_flag = 0;
12+
static int s_show_headers = 0;
13+
14+
static void ev_handler(struct mg_connection *c, int ev, void *ev_data,
15+
void *userdata) {
16+
struct http_message *hm = (struct http_message *) ev_data;
17+
18+
switch (ev) {
19+
case MG_EV_CONNECT:
20+
if (*(int *) ev_data != 0) {
21+
fprintf(stderr, "connect() failed: %s\n", strerror(*(int *) ev_data));
22+
s_exit_flag = 1;
23+
} else {
24+
// Stage 2. Connection to the HTTP proxy is established.
25+
// Write CONNECT request, and turn this connection to HTTP.
26+
// NOTE: target URL is passed to us as userdata.
27+
unsigned port = 80;
28+
struct mg_str scheme, host;
29+
mg_parse_uri(mg_mk_str((char *) userdata), &scheme, NULL, &host, &port,
30+
NULL, NULL, NULL);
31+
if (port == 0) port = (scheme.len == 5) ? 443 : 80;
32+
mg_printf(c, "CONNECT %.*s:%u HTTP/1.1\r\n\r\n", (int) host.len, host.p,
33+
port);
34+
// Now set the flag and wait for the connection establishment
35+
c->flags |= MG_F_USER_1;
36+
}
37+
break;
38+
case MG_EV_RECV:
39+
// Stage 3. Check if proxy replied. Here, we don't parse the reply
40+
// for simplicity. Assume success, and write HTTP request.
41+
if (c->flags & MG_F_USER_1) {
42+
struct mg_str host, path;
43+
c->flags &= ~MG_F_USER_1;
44+
mg_parse_uri(mg_mk_str((char *) userdata), NULL, NULL, &host, NULL,
45+
&path, NULL, NULL);
46+
if (path.len == 0) path = mg_mk_str("/");
47+
mg_printf(c, "GET %.*s HTTP/1.0\r\nHost: %.*s\r\n\r\n", (int) path.len,
48+
path.p, (int) host.len, host.p);
49+
mg_set_protocol_http_websocket(c);
50+
}
51+
break;
52+
case MG_EV_HTTP_REPLY:
53+
c->flags |= MG_F_CLOSE_IMMEDIATELY;
54+
if (s_show_headers) {
55+
fwrite(hm->message.p, 1, hm->message.len, stdout);
56+
} else {
57+
fwrite(hm->body.p, 1, hm->body.len, stdout);
58+
}
59+
putchar('\n');
60+
s_exit_flag = 1;
61+
break;
62+
case MG_EV_CLOSE:
63+
if (s_exit_flag == 0) {
64+
printf("Server closed connection\n");
65+
s_exit_flag = 1;
66+
}
67+
break;
68+
default:
69+
break;
70+
}
71+
}
72+
73+
int main(int argc, char *argv[]) {
74+
struct mg_mgr mgr;
75+
int i;
76+
77+
mg_mgr_init(&mgr, NULL);
78+
79+
/* Process command line arguments */
80+
for (i = 1; i < argc; i++) {
81+
if (strcmp(argv[i], "--show-headers") == 0) {
82+
s_show_headers = 1;
83+
} else if (strcmp(argv[i], "--hexdump") == 0 && i + 1 < argc) {
84+
mgr.hexdump_file = argv[++i];
85+
} else {
86+
break;
87+
}
88+
}
89+
90+
if (i + 2 != argc) {
91+
fprintf(stderr,
92+
"Usage: %s [--hexdump <file>] "
93+
"[--show-headers] PROXY_HOST:PROXY_PORT URL\n",
94+
argv[0]);
95+
exit(EXIT_FAILURE);
96+
}
97+
98+
// Stage 1. Connect to the HTTP proxy as to a plain TCP server.
99+
// Pass URL as a callback argument
100+
mg_connect(&mgr, argv[i], ev_handler, argv[i + 1]);
101+
102+
while (s_exit_flag == 0) {
103+
mg_mgr_poll(&mgr, 1000);
104+
}
105+
mg_mgr_free(&mgr);
106+
107+
return 0;
108+
}

mongoose.c

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4469,10 +4469,13 @@ struct mg_iface *mg_socks_mk_iface(struct mg_mgr *mgr, const char *proxy_addr) {
44694469
#endif
44704470

44714471
#include <openssl/ssl.h>
4472+
#include <openssl/err.h>
44724473
#ifndef KR_VERSION
44734474
#include <openssl/tls1.h>
44744475
#endif
44754476

4477+
static const char *mg_default_session_id_context = "mongoose";
4478+
44764479
struct mg_ssl_if_ctx {
44774480
SSL *ssl;
44784481
SSL_CTX *ssl_ctx;
@@ -4534,6 +4537,9 @@ enum mg_ssl_if_result mg_ssl_if_conn_init(
45344537
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_SSLv2);
45354538
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_SSLv3);
45364539
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_TLSv1);
4540+
SSL_CTX_set_session_id_context(ctx->ssl_ctx,
4541+
(void *) mg_default_session_id_context,
4542+
strlen(mg_default_session_id_context));
45374543
#ifdef MG_SSL_OPENSSL_NO_COMPRESSION
45384544
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_COMPRESSION);
45394545
#endif
@@ -4591,6 +4597,17 @@ static enum mg_ssl_if_result mg_ssl_if_ssl_err(struct mg_connection *nc,
45914597
int res) {
45924598
struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data;
45934599
int err = SSL_get_error(ctx->ssl, res);
4600+
/*
4601+
* We've just fetched the last error from the queue.
4602+
* Now we need to clear the error queue. If we do not, then the following
4603+
* can happen (actually reported):
4604+
* - A new connection is accept()-ed with cert error (e.g. self-signed cert)
4605+
* - Since all accept()-ed connections share listener's context,
4606+
* - *ALL* SSL accepted connection report read error on the next poll cycle.
4607+
* Thus a single errored connection can close all the rest, unrelated ones.
4608+
* Clearing the error keeps the shared SSL_CTX in an OK state.
4609+
*/
4610+
ERR_clear_error();
45944611
if (err == SSL_ERROR_WANT_READ) return MG_SSL_WANT_READ;
45954612
if (err == SSL_ERROR_WANT_WRITE) return MG_SSL_WANT_WRITE;
45964613
DBG(("%p %p SSL error: %d %d", nc, ctx->ssl_ctx, res, err));
@@ -5865,7 +5882,7 @@ static void mg_http_free_proto_data_endpoints(struct mg_http_endpoint **ep) {
58655882
current = tmp;
58665883
}
58675884

5868-
ep = NULL;
5885+
*ep = NULL;
58695886
}
58705887

58715888
static void mg_http_free_reverse_proxy_data(struct mg_reverse_proxy_data *rpd) {
@@ -7731,7 +7748,7 @@ static void mg_print_dir_entry(struct mg_connection *nc, const char *file_name,
77317748
href = mg_url_encode(mg_mk_str(file_name));
77327749
mg_printf_http_chunk(nc,
77337750
"<tr><td><a href=\"%s%s\">%s%s</a></td>"
7734-
"<td>%s</td><td name=%" INT64_FMT ">%s</td></tr>\n",
7751+
"<td>%s</td><td name=\"%" INT64_FMT "\">%s</td></tr>",
77357752
href.p, slash, path, slash, mod, is_dir ? -1 : fsize,
77367753
size);
77377754
free((void *) href.p);
@@ -7797,23 +7814,24 @@ static void mg_send_directory_listing(struct mg_connection *nc, const char *dir,
77977814

77987815
mg_printf_http_chunk(
77997816
nc,
7800-
"<html><head><title>Index of %.*s</title>%s%s"
7817+
"<!DOCTYPE html><html><head><title>Index of %.*s</title>%s%s"
78017818
"<style>th,td {text-align: left; padding-right: 1em; "
7802-
"font-family: monospace; }</style></head>\n"
7803-
"<body><h1>Index of %.*s</h1>\n<table cellpadding=0><thead>"
7804-
"<tr><th><a href=# rel=0>Name</a></th><th>"
7805-
"<a href=# rel=1>Modified</a</th>"
7806-
"<th><a href=# rel=2>Size</a></th></tr>"
7807-
"<tr><td colspan=3><hr></td></tr>\n"
7808-
"</thead>\n"
7809-
"<tbody id=tb>",
7819+
"font-family: monospace; }</style></head>"
7820+
"<body><h1>Index of %.*s</h1><table cellpadding=\"0\"><thead>"
7821+
"<tr><th><a href=\"#\" rel=\"0\">Name</a></th><th>"
7822+
"<a href=\"#\" rel=\"1\">Modified</a></th>"
7823+
"<th><a href=\"#\" rel=\"2\">Size</a></th></tr>"
7824+
"<tr><td colspan=\"3\"><hr></td></tr>"
7825+
"</thead>"
7826+
"<tbody id=\"tb\">",
78107827
(int) hm->uri.len, hm->uri.p, sort_js_code, sort_js_code2,
78117828
(int) hm->uri.len, hm->uri.p);
78127829
mg_scan_directory(nc, dir, opts, mg_print_dir_entry);
78137830
mg_printf_http_chunk(nc,
7814-
"</tbody><tr><td colspan=3><hr></td></tr>\n"
7815-
"</table>\n"
7816-
"<address>%s</address>\n"
7831+
"</tbody>"
7832+
"<tfoot><tr><td colspan=\"3\"><hr></td></tr></tfoot>"
7833+
"</table>"
7834+
"<address>%s</address>"
78177835
"</body></html>",
78187836
mg_version_header);
78197837
mg_send_http_chunk(nc, "", 0);

mongoose.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#ifndef CS_MONGOOSE_SRC_COMMON_H_
2424
#define CS_MONGOOSE_SRC_COMMON_H_
2525

26-
#define MG_VERSION "6.17"
26+
#define MG_VERSION "6.18"
2727

2828
/* Local tweaks, applied before any of Mongoose's own headers. */
2929
#ifdef MG_LOCALS
@@ -228,7 +228,7 @@
228228
#include <windows.h>
229229
#include <process.h>
230230

231-
#if _MSC_VER < 1700
231+
#if defined(_MSC_VER) && (_MSC_VER < 1700)
232232
typedef int bool;
233233
#else
234234
#include <stdbool.h>

src/common/platforms/platform_windows.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
#include <windows.h>
5151
#include <process.h>
5252

53-
#if _MSC_VER < 1700
53+
#if defined(_MSC_VER) && (_MSC_VER < 1700)
5454
typedef int bool;
5555
#else
5656
#include <stdbool.h>

src/mg_http.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ static void mg_http_free_proto_data_endpoints(struct mg_http_endpoint **ep) {
236236
current = tmp;
237237
}
238238

239-
ep = NULL;
239+
*ep = NULL;
240240
}
241241

242242
static void mg_http_free_reverse_proxy_data(struct mg_reverse_proxy_data *rpd) {
@@ -2102,7 +2102,7 @@ static void mg_print_dir_entry(struct mg_connection *nc, const char *file_name,
21022102
href = mg_url_encode(mg_mk_str(file_name));
21032103
mg_printf_http_chunk(nc,
21042104
"<tr><td><a href=\"%s%s\">%s%s</a></td>"
2105-
"<td>%s</td><td name=%" INT64_FMT ">%s</td></tr>\n",
2105+
"<td>%s</td><td name=\"%" INT64_FMT "\">%s</td></tr>",
21062106
href.p, slash, path, slash, mod, is_dir ? -1 : fsize,
21072107
size);
21082108
free((void *) href.p);
@@ -2168,23 +2168,24 @@ static void mg_send_directory_listing(struct mg_connection *nc, const char *dir,
21682168

21692169
mg_printf_http_chunk(
21702170
nc,
2171-
"<html><head><title>Index of %.*s</title>%s%s"
2171+
"<!DOCTYPE html><html><head><title>Index of %.*s</title>%s%s"
21722172
"<style>th,td {text-align: left; padding-right: 1em; "
2173-
"font-family: monospace; }</style></head>\n"
2174-
"<body><h1>Index of %.*s</h1>\n<table cellpadding=0><thead>"
2175-
"<tr><th><a href=# rel=0>Name</a></th><th>"
2176-
"<a href=# rel=1>Modified</a</th>"
2177-
"<th><a href=# rel=2>Size</a></th></tr>"
2178-
"<tr><td colspan=3><hr></td></tr>\n"
2179-
"</thead>\n"
2180-
"<tbody id=tb>",
2173+
"font-family: monospace; }</style></head>"
2174+
"<body><h1>Index of %.*s</h1><table cellpadding=\"0\"><thead>"
2175+
"<tr><th><a href=\"#\" rel=\"0\">Name</a></th><th>"
2176+
"<a href=\"#\" rel=\"1\">Modified</a></th>"
2177+
"<th><a href=\"#\" rel=\"2\">Size</a></th></tr>"
2178+
"<tr><td colspan=\"3\"><hr></td></tr>"
2179+
"</thead>"
2180+
"<tbody id=\"tb\">",
21812181
(int) hm->uri.len, hm->uri.p, sort_js_code, sort_js_code2,
21822182
(int) hm->uri.len, hm->uri.p);
21832183
mg_scan_directory(nc, dir, opts, mg_print_dir_entry);
21842184
mg_printf_http_chunk(nc,
2185-
"</tbody><tr><td colspan=3><hr></td></tr>\n"
2186-
"</table>\n"
2187-
"<address>%s</address>\n"
2185+
"</tbody>"
2186+
"<tfoot><tr><td colspan=\"3\"><hr></td></tr></tfoot>"
2187+
"</table>"
2188+
"<address>%s</address>"
21882189
"</body></html>",
21892190
mg_version_header);
21902191
mg_send_http_chunk(nc, "", 0);

src/mg_ssl_if_openssl.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@
1010
#endif
1111

1212
#include <openssl/ssl.h>
13+
#include <openssl/err.h>
1314
#ifndef KR_VERSION
1415
#include <openssl/tls1.h>
1516
#endif
1617

18+
static const char *mg_default_session_id_context = "mongoose";
19+
1720
struct mg_ssl_if_ctx {
1821
SSL *ssl;
1922
SSL_CTX *ssl_ctx;
@@ -75,6 +78,9 @@ enum mg_ssl_if_result mg_ssl_if_conn_init(
7578
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_SSLv2);
7679
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_SSLv3);
7780
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_TLSv1);
81+
SSL_CTX_set_session_id_context(ctx->ssl_ctx,
82+
(void *) mg_default_session_id_context,
83+
strlen(mg_default_session_id_context));
7884
#ifdef MG_SSL_OPENSSL_NO_COMPRESSION
7985
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_COMPRESSION);
8086
#endif
@@ -132,6 +138,17 @@ static enum mg_ssl_if_result mg_ssl_if_ssl_err(struct mg_connection *nc,
132138
int res) {
133139
struct mg_ssl_if_ctx *ctx = (struct mg_ssl_if_ctx *) nc->ssl_if_data;
134140
int err = SSL_get_error(ctx->ssl, res);
141+
/*
142+
* We've just fetched the last error from the queue.
143+
* Now we need to clear the error queue. If we do not, then the following
144+
* can happen (actually reported):
145+
* - A new connection is accept()-ed with cert error (e.g. self-signed cert)
146+
* - Since all accept()-ed connections share listener's context,
147+
* - *ALL* SSL accepted connection report read error on the next poll cycle.
148+
* Thus a single errored connection can close all the rest, unrelated ones.
149+
* Clearing the error keeps the shared SSL_CTX in an OK state.
150+
*/
151+
ERR_clear_error();
135152
if (err == SSL_ERROR_WANT_READ) return MG_SSL_WANT_READ;
136153
if (err == SSL_ERROR_WANT_WRITE) return MG_SSL_WANT_WRITE;
137154
DBG(("%p %p SSL error: %d %d", nc, ctx->ssl_ctx, res, err));

0 commit comments

Comments
 (0)