-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
23,895 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
CFLAGS = -W -Wall -Wextra -g -I. # Build options | ||
CFLAGS_MONGOOSE += -DMG_ENABLE_LINES=1 -DMG_ENABLE_IPV6=1 | ||
CFLAGS_EXTRA ?= -DMG_TLS=MG_TLS_BUILTIN | ||
|
||
server: main.c patched_mongoose.c mongoose.h Makefile | ||
$(CC) main.c patched_mongoose.c $(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA) -o $@ | ||
|
||
clean: | ||
rm -f server |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
// Copyright (c) 2020 Cesanta Software Limited | ||
// All rights reserved | ||
|
||
#include <signal.h> | ||
#include "mongoose.h" | ||
|
||
static int s_debug_level = MG_LL_INFO; | ||
static const char *s_root_dir = "."; | ||
static const char *s_addr1 = "http://0.0.0.0:8000"; | ||
static const char *s_addr2 = "https://0.0.0.0:8443"; | ||
static const char *s_enable_hexdump = "no"; | ||
static const char *s_ssi_pattern = "#.html"; | ||
static const char *s_upload_dir = NULL; // File uploads disabled by default | ||
|
||
// Self signed certificates, see | ||
// https://github.com/cesanta/mongoose/blob/master/test/certs/generate.sh | ||
#ifdef TLS_TWOWAY | ||
static const char *s_tls_ca = | ||
"-----BEGIN CERTIFICATE-----\n" | ||
"MIIBFTCBvAIJAMNTFtpfcq8NMAoGCCqGSM49BAMCMBMxETAPBgNVBAMMCE1vbmdv\n" | ||
"b3NlMB4XDTI0MDUwNzE0MzczNloXDTM0MDUwNTE0MzczNlowEzERMA8GA1UEAwwI\n" | ||
"TW9uZ29vc2UwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASuP+86T/rOWnGpEVhl\n" | ||
"fxYZ+pjMbCmDZ+vdnP0rjoxudwRMRQCv5slRlDK7Lxue761sdvqxWr0Ma6TFGTNg\n" | ||
"epsRMAoGCCqGSM49BAMCA0gAMEUCIQCwb2CxuAKm51s81S6BIoy1IcandXSohnqs\n" | ||
"us64BAA7QgIgGGtUrpkgFSS0oPBlCUG6YPHFVw42vTfpTC0ySwAS0M4=\n" | ||
"-----END CERTIFICATE-----\n"; | ||
#endif | ||
static const char *s_tls_cert = | ||
"-----BEGIN CERTIFICATE-----\n" | ||
"MIIBMTCB2aADAgECAgkAluqkgeuV/zUwCgYIKoZIzj0EAwIwEzERMA8GA1UEAwwI\n" | ||
"TW9uZ29vc2UwHhcNMjQwNTA3MTQzNzM2WhcNMzQwNTA1MTQzNzM2WjARMQ8wDQYD\n" | ||
"VQQDDAZzZXJ2ZXIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASo3oEiG+BuTt5y\n" | ||
"ZRyfwNr0C+SP+4M0RG2pYkb2v+ivbpfi72NHkmXiF/kbHXtgmSrn/PeTqiA8M+mg\n" | ||
"BhYjDX+zoxgwFjAUBgNVHREEDTALgglsb2NhbGhvc3QwCgYIKoZIzj0EAwIDRwAw\n" | ||
"RAIgTXW9MITQSwzqbNTxUUdt9DcB+8pPUTbWZpiXcA26GMYCIBiYw+DSFMLHmkHF\n" | ||
"+5U3NXW3gVCLN9ntD5DAx8LTG8sB\n" | ||
"-----END CERTIFICATE-----\n"; | ||
|
||
static const char *s_tls_key = | ||
"-----BEGIN EC PRIVATE KEY-----\n" | ||
"MHcCAQEEIAVdo8UAScxG7jiuNY2UZESNX/KPH8qJ0u0gOMMsAzYWoAoGCCqGSM49\n" | ||
"AwEHoUQDQgAEqN6BIhvgbk7ecmUcn8Da9Avkj/uDNERtqWJG9r/or26X4u9jR5Jl\n" | ||
"4hf5Gx17YJkq5/z3k6ogPDPpoAYWIw1/sw==\n" | ||
"-----END EC PRIVATE KEY-----\n"; | ||
|
||
// Handle interrupts, like Ctrl-C | ||
static int s_signo; | ||
static void signal_handler(int signo) { | ||
s_signo = signo; | ||
} | ||
|
||
// Event handler for the listening connection. | ||
// Simply serve static files from `s_root_dir` | ||
static void cb(struct mg_connection *c, int ev, void *ev_data) { | ||
if (ev == MG_EV_ACCEPT && c->fn_data != NULL) { | ||
struct mg_tls_opts opts; | ||
memset(&opts, 0, sizeof(opts)); | ||
#ifdef TLS_TWOWAY | ||
opts.ca = mg_str(s_tls_ca); | ||
#endif | ||
opts.cert = mg_str(s_tls_cert); | ||
opts.key = mg_str(s_tls_key); | ||
mg_tls_init(c, &opts); | ||
} | ||
if (ev == MG_EV_HTTP_MSG) { | ||
struct mg_http_message *hm = ev_data; | ||
|
||
if (mg_match(hm->uri, mg_str("/upload"), NULL)) { | ||
// Serve file upload | ||
if (s_upload_dir == NULL) { | ||
mg_http_reply(c, 403, "", "Denied: file upload directory not set\n"); | ||
} else { | ||
struct mg_http_part part; | ||
size_t pos = 0, total_bytes = 0, num_files = 0; | ||
while ((pos = mg_http_next_multipart(hm->body, pos, &part)) > 0) { | ||
char path[MG_PATH_MAX]; | ||
MG_INFO(("Chunk name: [%.*s] filename: [%.*s] length: %lu bytes", | ||
part.name.len, part.name.buf, part.filename.len, | ||
part.filename.buf, part.body.len)); | ||
mg_snprintf(path, sizeof(path), "%s/%.*s", s_upload_dir, | ||
part.filename.len, part.filename.buf); | ||
if (mg_path_is_sane(mg_str(path))) { | ||
mg_file_write(&mg_fs_posix, path, part.body.buf, part.body.len); | ||
total_bytes += part.body.len; | ||
num_files++; | ||
} else { | ||
MG_ERROR(("Rejecting dangerous path %s", path)); | ||
} | ||
} | ||
mg_http_reply(c, 200, "", "Uploaded %lu files, %lu bytes\n", num_files, | ||
total_bytes); | ||
} | ||
} else { | ||
// Serve web root directory | ||
struct mg_http_serve_opts opts = {0}; | ||
opts.root_dir = s_root_dir; | ||
opts.ssi_pattern = s_ssi_pattern; | ||
mg_http_serve_dir(c, hm, &opts); | ||
} | ||
|
||
// Log request | ||
MG_INFO(("%.*s %.*s %lu -> %.*s %lu", hm->method.len, hm->method.buf, | ||
hm->uri.len, hm->uri.buf, hm->body.len, 3, c->send.buf + 9, | ||
c->send.len)); | ||
} | ||
} | ||
|
||
static void usage(const char *prog) { | ||
fprintf(stderr, | ||
"Mongoose v.%s\n" | ||
"Usage: %s OPTIONS\n" | ||
" -H yes|no - enable traffic hexdump, default: '%s'\n" | ||
" -S PAT - SSI filename pattern, default: '%s'\n" | ||
" -d DIR - directory to serve, default: '%s'\n" | ||
" -l ADDR - listening address, default: '%s'\n" | ||
" -u DIR - file upload directory, default: unset\n" | ||
" -v LEVEL - debug level, from 0 to 4, default: %d\n", | ||
MG_VERSION, prog, s_enable_hexdump, s_ssi_pattern, s_root_dir, | ||
s_addr1, s_debug_level); | ||
exit(EXIT_FAILURE); | ||
} | ||
|
||
int main(int argc, char *argv[]) { | ||
char path[MG_PATH_MAX] = "."; | ||
struct mg_mgr mgr; | ||
struct mg_connection *c; | ||
int i; | ||
|
||
// Parse command-line flags | ||
for (i = 1; i < argc; i++) { | ||
if (strcmp(argv[i], "-d") == 0) { | ||
s_root_dir = argv[++i]; | ||
} else if (strcmp(argv[i], "-H") == 0) { | ||
s_enable_hexdump = argv[++i]; | ||
} else if (strcmp(argv[i], "-S") == 0) { | ||
s_ssi_pattern = argv[++i]; | ||
} else if (strcmp(argv[i], "-l") == 0) { | ||
s_addr1 = argv[++i]; | ||
} else if (strcmp(argv[i], "-l2") == 0) { | ||
s_addr2 = argv[++i]; | ||
} else if (strcmp(argv[i], "-u") == 0) { | ||
s_upload_dir = argv[++i]; | ||
} else if (strcmp(argv[i], "-v") == 0) { | ||
s_debug_level = atoi(argv[++i]); | ||
} else { | ||
usage(argv[0]); | ||
} | ||
} | ||
|
||
// Root directory must not contain double dots. Make it absolute | ||
// Do the conversion only if the root dir spec does not contain overrides | ||
if (strchr(s_root_dir, ',') == NULL) { | ||
realpath(s_root_dir, path); | ||
s_root_dir = path; | ||
} | ||
|
||
// Initialise stuff | ||
signal(SIGINT, signal_handler); | ||
signal(SIGTERM, signal_handler); | ||
mg_log_set(s_debug_level); | ||
mg_mgr_init(&mgr); | ||
if ((c = mg_http_listen(&mgr, s_addr1, cb, NULL)) == NULL) { | ||
MG_ERROR(("Cannot listen on %s. Use http://ADDR:PORT or :PORT", | ||
s_addr1)); | ||
exit(EXIT_FAILURE); | ||
} | ||
if ((c = mg_http_listen(&mgr, s_addr2, cb, (void *) 1)) == NULL) { | ||
MG_ERROR(("Cannot listen on %s. Use http://ADDR:PORT or :PORT", | ||
s_addr2)); | ||
exit(EXIT_FAILURE); | ||
} | ||
if (mg_casecmp(s_enable_hexdump, "yes") == 0) c->is_hexdumping = 1; | ||
|
||
// Start infinite event loop | ||
MG_INFO(("Mongoose version : v%s", MG_VERSION)); | ||
MG_INFO(("HTTP listener : %s", s_addr1)); | ||
MG_INFO(("HTTPS listener : %s", s_addr2)); | ||
MG_INFO(("Web root : [%s]", s_root_dir)); | ||
MG_INFO(("Upload dir : [%s]", s_upload_dir ? s_upload_dir : "unset")); | ||
while (s_signo == 0) mg_mgr_poll(&mgr, 1000); | ||
mg_mgr_free(&mgr); | ||
MG_INFO(("Exiting on signal %d", s_signo)); | ||
return 0; | ||
} |
Oops, something went wrong.