Added ability to set "0" as listening port. Exported local_ip and local_port to the client.

This commit is contained in:
Sergey Lyubka 2014-01-25 13:50:57 +00:00
parent 037fdbcccb
commit 8ae0400b0d
3 changed files with 30 additions and 2 deletions

View File

@ -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) {

View File

@ -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 {

View File

@ -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