mirror of
https://github.com/cesanta/mongoose.git
synced 2024-12-28 07:28:13 +08:00
app code moved to qcomm.c
This commit is contained in:
parent
ec22250d9b
commit
2a7e720f12
245
build/src/core.c
245
build/src/core.c
@ -93,7 +93,6 @@ typedef struct stat file_stat_t;
|
||||
#define to64(x) strtoll(x, NULL, 10)
|
||||
#endif
|
||||
|
||||
//#include "mongoose.h"
|
||||
#include "core.h"
|
||||
|
||||
struct linked_list_link { struct linked_list_link *prev, *next; };
|
||||
@ -160,30 +159,6 @@ enum {
|
||||
SSL_CERTIFICATE, SSI_PATTERN, URL_REWRITES, NUM_OPTIONS
|
||||
};
|
||||
|
||||
static const char *static_config_options[] = {
|
||||
"access_control_list", NULL,
|
||||
"access_log_file", NULL,
|
||||
"auth_domain", "mydomain.com",
|
||||
"cgi_interpreter", NULL,
|
||||
"cgi_pattern", "**.cgi$|**.pl$|**.php$",
|
||||
"document_root", NULL,
|
||||
"enable_directory_listing", "yes",
|
||||
"error_log_file", NULL,
|
||||
"extra_mime_types", NULL,
|
||||
"global_auth_file", NULL,
|
||||
"hide_files_patterns", NULL,
|
||||
"idle_timeout_ms", "30000",
|
||||
"index_files","index.html,index.htm,index.cgi,index.shtml,index.php,index.lp",
|
||||
"listening_port", NULL,
|
||||
"num_threads", "50",
|
||||
"put_delete_auth_file", NULL,
|
||||
"run_as_user", NULL,
|
||||
"ssl_certificate", NULL,
|
||||
"ssi_pattern", "**.shtml$|**.shtm$",
|
||||
"url_rewrites", NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct mg_server {
|
||||
sock_t listening_sock;
|
||||
union socket_address lsa; // Listening socket address
|
||||
@ -194,12 +169,14 @@ struct mg_server {
|
||||
sock_t ctl[2]; // Control socketpair. Used to wake up from select() call
|
||||
};
|
||||
|
||||
// Expandable IO buffer
|
||||
struct iobuf {
|
||||
char *buf; // Buffer that holds the data
|
||||
int size; // Buffer size
|
||||
int len; // Number of bytes currently in a buffer
|
||||
};
|
||||
|
||||
// Local endpoint representation
|
||||
union endpoint {
|
||||
int fd; // Opened regular local file
|
||||
sock_t cgi_sock; // CGI socket
|
||||
@ -284,32 +261,35 @@ static const struct {
|
||||
{NULL, 0, NULL}
|
||||
};
|
||||
|
||||
static const char *static_config_options[] = {
|
||||
"access_control_list", NULL,
|
||||
"access_log_file", NULL,
|
||||
"auth_domain", "mydomain.com",
|
||||
"cgi_interpreter", NULL,
|
||||
"cgi_pattern", "**.cgi$|**.pl$|**.php$",
|
||||
"document_root", NULL,
|
||||
"enable_directory_listing", "yes",
|
||||
"error_log_file", NULL,
|
||||
"extra_mime_types", NULL,
|
||||
"global_auth_file", NULL,
|
||||
"hide_files_patterns", NULL,
|
||||
"idle_timeout_ms", "30000",
|
||||
"index_files","index.html,index.htm,index.cgi,index.shtml,index.php,index.lp",
|
||||
"listening_port", NULL,
|
||||
"num_threads", "50",
|
||||
"put_delete_auth_file", NULL,
|
||||
"run_as_user", NULL,
|
||||
"ssl_certificate", NULL,
|
||||
"ssi_pattern", "**.shtml$|**.shtm$",
|
||||
"url_rewrites", NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *static_month_names[] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
||||
const char **mg_get_valid_option_names(void) {
|
||||
return static_config_options;
|
||||
}
|
||||
|
||||
static int get_option_index(const char *name) {
|
||||
int i;
|
||||
|
||||
for (i = 0; static_config_options[i * 2] != NULL; i++) {
|
||||
if (strcmp(static_config_options[i * 2], name) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *mg_get_option(const struct mg_server *srv, const char *name) {
|
||||
int i = get_option_index(name);
|
||||
return i == -1 ? NULL : srv->config_options[i] == NULL ? "" :
|
||||
srv->config_options[i];
|
||||
}
|
||||
|
||||
int mg_start_thread(void *(*f)(void *), void *p) {
|
||||
#ifdef _WIN32
|
||||
return (long)_beginthread((void (__cdecl *)(void *)) f, 0, p) == -1L ? -1 : 0;
|
||||
@ -477,7 +457,7 @@ static pid_t start_process(const char *interp, const char *cmd, const char *env,
|
||||
|
||||
return pid;
|
||||
}
|
||||
#endif
|
||||
#endif // _WIN32
|
||||
|
||||
// This structure helps to create an environment for the spawned CGI program.
|
||||
// Environment is an array of "VARIABLE=VALUE\0" ASCIIZ strings,
|
||||
@ -690,40 +670,6 @@ static char *mg_strdup(const char *str) {
|
||||
return copy;
|
||||
}
|
||||
|
||||
// Valid listening port spec is: [ip_address:]port, e.g. "80", "127.0.0.1:3128"
|
||||
static int parse_port_string(const char *str, union socket_address *sa) {
|
||||
unsigned int a, b, c, d, port;
|
||||
#if defined(USE_IPV6)
|
||||
char buf[100];
|
||||
#endif
|
||||
|
||||
// MacOS needs that. If we do not zero it, subsequent bind() will fail.
|
||||
// Also, all-zeroes in the socket address means binding to all addresses
|
||||
// for both IPv4 and IPv6 (INADDR_ANY and IN6ADDR_ANY_INIT).
|
||||
memset(sa, 0, sizeof(*sa));
|
||||
sa->sin.sin_family = AF_INET;
|
||||
|
||||
if (sscanf(str, "%u.%u.%u.%u:%u", &a, &b, &c, &d, &port) == 5) {
|
||||
// Bind to a specific IPv4 address, e.g. 192.168.1.5:8080
|
||||
sa->sin.sin_addr.s_addr = htonl((a << 24) | (b << 16) | (c << 8) | d);
|
||||
sa->sin.sin_port = htons((uint16_t) port);
|
||||
#if defined(USE_IPV6)
|
||||
} else if (sscanf(str, "[%49[^]]]:%d%n", buf, &port, &len) == 2 &&
|
||||
inet_pton(AF_INET6, buf, &so->lsa.sin6.sin6_addr)) {
|
||||
// IPv6 address, e.g. [3ffe:2a00:100:7031::1]:8080
|
||||
so->lsa.sin6.sin6_family = AF_INET6;
|
||||
so->lsa.sin6.sin6_port = htons((uint16_t) port);
|
||||
#endif
|
||||
} else if (sscanf(str, "%u", &port) == 1) {
|
||||
// If only port is specified, bind to IPv4, INADDR_ANY
|
||||
sa->sin.sin_port = htons((uint16_t) port);
|
||||
} else {
|
||||
port = 0; // Parsing failure. Make port invalid.
|
||||
}
|
||||
|
||||
return port > 0 && port < 0xffff;
|
||||
}
|
||||
|
||||
static int isbyte(int n) {
|
||||
return n >= 0 && n <= 255;
|
||||
}
|
||||
@ -1923,7 +1869,7 @@ void mg_destroy_server(struct mg_server **server) {
|
||||
|
||||
// Apply function to all active connections. Return number of active
|
||||
// connections. Function could be NULL.
|
||||
static int mg_iterate_over_connections(struct mg_server *server,
|
||||
int mg_iterate_over_connections(struct mg_server *server,
|
||||
void (*func)(struct mg_connection *, void *),
|
||||
void *param) {
|
||||
struct linked_list_link *lp, *tmp;
|
||||
@ -1951,6 +1897,67 @@ void mg_add_uri_handler(struct mg_server *server, const char *uri,
|
||||
}
|
||||
}
|
||||
|
||||
const char **mg_get_valid_option_names(void) {
|
||||
return static_config_options;
|
||||
}
|
||||
|
||||
static int get_option_index(const char *name) {
|
||||
int i;
|
||||
|
||||
for (i = 0; static_config_options[i * 2] != NULL; i++) {
|
||||
if (strcmp(static_config_options[i * 2], name) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void set_default_option_values(char **opts) {
|
||||
const char *value, **all_opts = mg_get_valid_option_names();
|
||||
int i;
|
||||
|
||||
for (i = 0; all_opts[i * 2] != NULL; i++) {
|
||||
value = all_opts[i * 2 + 1];
|
||||
if (opts[i] == NULL && value != NULL) {
|
||||
opts[i] = mg_strdup(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Valid listening port spec is: [ip_address:]port, e.g. "80", "127.0.0.1:3128"
|
||||
static int parse_port_string(const char *str, union socket_address *sa) {
|
||||
unsigned int a, b, c, d, port;
|
||||
#if defined(USE_IPV6)
|
||||
char buf[100];
|
||||
#endif
|
||||
|
||||
// MacOS needs that. If we do not zero it, subsequent bind() will fail.
|
||||
// Also, all-zeroes in the socket address means binding to all addresses
|
||||
// for both IPv4 and IPv6 (INADDR_ANY and IN6ADDR_ANY_INIT).
|
||||
memset(sa, 0, sizeof(*sa));
|
||||
sa->sin.sin_family = AF_INET;
|
||||
|
||||
if (sscanf(str, "%u.%u.%u.%u:%u", &a, &b, &c, &d, &port) == 5) {
|
||||
// Bind to a specific IPv4 address, e.g. 192.168.1.5:8080
|
||||
sa->sin.sin_addr.s_addr = htonl((a << 24) | (b << 16) | (c << 8) | d);
|
||||
sa->sin.sin_port = htons((uint16_t) port);
|
||||
#if defined(USE_IPV6)
|
||||
} else if (sscanf(str, "[%49[^]]]:%d%n", buf, &port, &len) == 2 &&
|
||||
inet_pton(AF_INET6, buf, &so->lsa.sin6.sin6_addr)) {
|
||||
// IPv6 address, e.g. [3ffe:2a00:100:7031::1]:8080
|
||||
so->lsa.sin6.sin6_family = AF_INET6;
|
||||
so->lsa.sin6.sin6_port = htons((uint16_t) port);
|
||||
#endif
|
||||
} else if (sscanf(str, "%u", &port) == 1) {
|
||||
// If only port is specified, bind to IPv4, INADDR_ANY
|
||||
sa->sin.sin_port = htons((uint16_t) port);
|
||||
} else {
|
||||
port = 0; // Parsing failure. Make port invalid.
|
||||
}
|
||||
|
||||
return port > 0 && port < 0xffff;
|
||||
}
|
||||
|
||||
const char *mg_set_option(struct mg_server *server, const char *name,
|
||||
const char *value) {
|
||||
int ind = get_option_index(name);
|
||||
@ -1981,10 +1988,14 @@ const char *mg_set_option(struct mg_server *server, const char *name,
|
||||
return error_msg;
|
||||
}
|
||||
|
||||
const char *mg_get_option(const struct mg_server *server, const char *name) {
|
||||
const char *const *opts = server->config_options;
|
||||
int i = get_option_index(name);
|
||||
return i == -1 ? NULL : opts[i] == NULL ? "" : opts[i];
|
||||
}
|
||||
|
||||
struct mg_server *mg_create_server(void *server_data) {
|
||||
struct mg_server *server = (struct mg_server *) calloc(1, sizeof(*server));
|
||||
const char *value;
|
||||
int i;
|
||||
|
||||
#ifdef _WIN32
|
||||
WSADATA data;
|
||||
@ -1996,71 +2007,7 @@ struct mg_server *mg_create_server(void *server_data) {
|
||||
mg_socketpair(server->ctl);
|
||||
server->server_data = server_data;
|
||||
server->listening_sock = INVALID_SOCKET;
|
||||
|
||||
// Set default options values
|
||||
for (i = 0; static_config_options[i * 2] != NULL; i++) {
|
||||
value = static_config_options[i * 2 + 1];
|
||||
if (server->config_options[i] == NULL && value != NULL) {
|
||||
server->config_options[i] = mg_strdup(value);
|
||||
}
|
||||
}
|
||||
set_default_option_values(server->config_options);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
// End of library, start of the application code
|
||||
|
||||
static void iterate_callback(struct mg_connection *c, void *param) {
|
||||
if (c->is_websocket) {
|
||||
char buf[20];
|
||||
int len = snprintf(buf, sizeof(buf), "%d", * (int *) param);
|
||||
mg_websocket_write(c, 1, buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
// This thread sends heartbeats to all websocket connections with 1s interval.
|
||||
// The heartbeat message is simply an iteration counter.
|
||||
static void *timer_thread(void *param) {
|
||||
struct mg_server *server = (struct mg_server *) param;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 9999999; i++) {
|
||||
sleep(1);
|
||||
mg_iterate_over_connections(server, iterate_callback, &i);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// This handler is called for each incoming websocket frame, one or more
|
||||
// times for connection lifetime.
|
||||
static int handler(struct mg_connection *conn) {
|
||||
static const char oops[] = "HTTP/1.0 200 OK\r\n\r\nwebsocket data expected\n";
|
||||
|
||||
if (!conn->is_websocket) {
|
||||
mg_write(conn, oops, sizeof(oops) - 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
mg_websocket_write(conn, 1, conn->content, conn->content_len);
|
||||
|
||||
DBG(("WS msg len: %d", conn->content_len));
|
||||
return conn->content_len == 4 && !memcmp(conn->content, "exit", 4);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct mg_server *server = mg_create_server(NULL);
|
||||
|
||||
mg_set_option(server, "listening_port", "8080");
|
||||
mg_set_option(server, "document_root", argc > 1 ? argv[1] : ".");
|
||||
mg_add_uri_handler(server, "/ws", handler);
|
||||
mg_start_thread(timer_thread, server);
|
||||
|
||||
printf("Started on port %s\n", mg_get_option(server, "listening_port"));
|
||||
for (;;) {
|
||||
mg_poll_server(server, 3000);
|
||||
}
|
||||
|
||||
mg_destroy_server(&server);
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user