From 8ae0400b0d5804a03452ad39bf3a881f69026813 Mon Sep 17 00:00:00 2001 From: Sergey Lyubka <valenok@gmail.com> Date: Sat, 25 Jan 2014 13:50:57 +0000 Subject: [PATCH] Added ability to set "0" as listening port. Exported local_ip and local_port to the client. --- mongoose.c | 18 +++++++++++++++++- mongoose.h | 2 ++ unit_test.c | 12 +++++++++++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/mongoose.c b/mongoose.c index ed7be4814..e3bf97081 100644 --- a/mongoose.c +++ b/mongoose.c @@ -275,6 +275,7 @@ struct mg_server { mg_handler_t error_handler; mg_handler_t auth_handler; char *config_options[NUM_OPTIONS]; + char local_ip[48]; void *server_data; #ifdef MONGOOSE_USE_SSL SSL_CTX *ssl_ctx; // Server SSL context @@ -1214,6 +1215,7 @@ static void forward_post_data(struct connection *conn) { // 'sa' must be an initialized address to bind to static sock_t open_listening_socket(union socket_address *sa) { + socklen_t len = sizeof(*sa); sock_t on = 1, sock = INVALID_SOCKET; if ((sock = socket(sa->sa.sa_family, SOCK_STREAM, 6)) != INVALID_SOCKET && @@ -1222,6 +1224,8 @@ static sock_t open_listening_socket(union socket_address *sa) { sizeof(sa->sin) : sizeof(sa->sa)) && !listen(sock, SOMAXCONN)) { set_non_blocking_mode(sock); + // In case port was set to 0, get the real port number + (void) getsockname(sock, &sa->sa, &len); } else if (sock != INVALID_SOCKET) { closesocket(sock); sock = INVALID_SOCKET; @@ -1329,6 +1333,8 @@ static struct connection *accept_new_connection(struct mg_server *server) { sizeof(conn->mg_conn.remote_ip), &sa); conn->mg_conn.remote_port = ntohs(sa.sin.sin_port); conn->mg_conn.server_param = server->server_data; + conn->mg_conn.local_ip = server->local_ip; + conn->mg_conn.local_port = ntohs(server->lsa.sin.sin_port); LINKED_LIST_ADD_TO_FRONT(&server->active_connections, &conn->link); DBG(("added conn %p", conn)); } @@ -4067,7 +4073,7 @@ static int parse_port_string(const char *str, union socket_address *sa) { port = 0; // Parsing failure. Make port invalid. } - return port > 0 && port < 0xffff && str[len] == '\0'; + return port <= 0xffff && str[len] == '\0'; } const char *mg_set_option(struct mg_server *server, const char *name, @@ -4092,6 +4098,16 @@ const char *mg_set_option(struct mg_server *server, const char *name, server->listening_sock = open_listening_socket(&server->lsa); if (server->listening_sock == INVALID_SOCKET) { error_msg = "Cannot bind to port"; + } else { + sockaddr_to_string(server->local_ip, sizeof(server->local_ip), + &server->lsa); + if (!strcmp(value, "0")) { + char buf[10]; + mg_snprintf(buf, sizeof(buf), "%d", + (int) ntohs(server->lsa.sin.sin_port)); + free(server->config_options[ind]); + server->config_options[ind] = mg_strdup(buf); + } } #ifndef _WIN32 } else if (ind == RUN_AS_USER) { diff --git a/mongoose.h b/mongoose.h index 459bf73bd..f15543269 100644 --- a/mongoose.h +++ b/mongoose.h @@ -38,6 +38,8 @@ struct mg_connection { char remote_ip[48]; // Max IPv6 string length is 45 characters int remote_port; // Client's port + const char *local_ip; // Local IP address + int local_port; // Local port number int num_headers; // Number of HTTP headers struct mg_header { diff --git a/unit_test.c b/unit_test.c index 171265f8e..53ff20851 100644 --- a/unit_test.c +++ b/unit_test.c @@ -289,7 +289,7 @@ static const char *test_parse_port_string(void) { NULL }; static const char *invalid[] = { - "0", "99999", "1k", "1.2.3", "1.2.3.4:", "1.2.3.4:2p", NULL + "99999", "1k", "1.2.3", "1.2.3.4:", "1.2.3.4:2p", NULL }; union socket_address sa; int i; @@ -301,6 +301,7 @@ static const char *test_parse_port_string(void) { for (i = 0; invalid[i] != NULL; i++) { ASSERT(parse_port_string(invalid[i], &sa) == 0); } + ASSERT(parse_port_string("0", &sa) != 0); return NULL; } @@ -577,6 +578,14 @@ static const char *test_ssl(void) { } #endif +static const char *test_mg_set_option(void) { + struct mg_server *server = mg_create_server(NULL); + ASSERT(mg_set_option(server, "listening_port", "0") == NULL); + ASSERT(mg_get_option(server, "listening_port")[0] != '\0'); + mg_destroy_server(&server); + return NULL; +} + static const char *run_all_tests(void) { RUN_TEST(test_should_keep_alive); RUN_TEST(test_match_prefix); @@ -592,6 +601,7 @@ static const char *run_all_tests(void) { RUN_TEST(test_parse_multipart); RUN_TEST(test_server); RUN_TEST(test_mg_connect); + RUN_TEST(test_mg_set_option); #ifdef MONGOOSE_USE_SSL RUN_TEST(test_ssl); #endif -- GitLab