From 4576b69e30843e984a3e347d81c2599590ae399e Mon Sep 17 00:00:00 2001
From: Sergey Lyubka <valenok@gmail.com>
Date: Tue, 31 Dec 2013 09:02:24 +0000
Subject: [PATCH] Initializing remote_ip and remote_port properly

---
 build/test/unit_test.c | 15 ++++++--------
 mongoose.c             | 46 ++++++++++++++++++++++++------------------
 2 files changed, 32 insertions(+), 29 deletions(-)

diff --git a/build/test/unit_test.c b/build/test/unit_test.c
index a7ac616ba..b26d49ddb 100644
--- a/build/test/unit_test.c
+++ b/build/test/unit_test.c
@@ -359,14 +359,10 @@ static const char *test_next_option(void) {
 }
 
 static int cb1(struct mg_connection *conn) {
-  char buf[100];
-
   // We're not sending HTTP headers here, to make testing easier
-  snprintf(buf, sizeof(buf), "%s %s",
+  mg_printf(conn, "%s %s %s",
            conn->server_param == NULL ? "?" : (char *) conn->server_param,
-           conn->connection_param == NULL ? "?" : "!");
-  mg_write(conn, buf, strlen(buf));
-
+           conn->connection_param == NULL ? "?" : "!", conn->remote_ip);
   return 1;
 }
 
@@ -401,9 +397,10 @@ static const char *test_server_param(void) {
   reply = wget("127.0.0.1", atoi(HTTP_PORT), &reply_len, "%s",
                "GET /cb1 HTTP/1.0\r\n\r\n");
   ASSERT(reply != NULL);
-  ASSERT(reply_len == 5);
-  ASSERT(memcmp(reply, "foo ?", 5) == 0);  // cb1() does not send HTTP headers
-  printf("%d [%.*s]\n", reply_len, reply_len, reply);
+  ASSERT(reply_len == 15);
+  // cb1() does not send HTTP headers
+  ASSERT(memcmp(reply, "foo ? 127.0.0.1", 5) == 0);
+  //printf("%d [%.*s]\n", reply_len, reply_len, reply);
   free(reply);
 
   return NULL;
diff --git a/mongoose.c b/mongoose.c
index 9ea78be3c..71828fed8 100644
--- a/mongoose.c
+++ b/mongoose.c
@@ -935,6 +935,23 @@ static int check_acl(const char *acl, uint32_t remote_ip) {
   return allowed == '+';
 }
 
+static void sockaddr_to_string(char *buf, size_t len,
+                               const union socket_address *usa) {
+  buf[0] = '\0';
+#if defined(USE_IPV6)
+  inet_ntop(usa->sa.sa_family, usa->sa.sa_family == AF_INET ?
+            (void *) &usa->sin.sin_addr :
+            (void *) &usa->sin6.sin6_addr, buf, len);
+#elif defined(_WIN32)
+  // Only Windoze Vista (and newer) have inet_ntop()
+  strncpy(buf, inet_ntoa(usa->sin.sin_addr), len);
+#else
+  inet_ntop(usa->sa.sa_family, (void *) &usa->sin.sin_addr, buf, len);
+#endif
+}
+
+
+
 static struct connection *accept_new_connection(struct mg_server *server) {
   union socket_address sa;
   socklen_t len = sizeof(sa);
@@ -963,6 +980,10 @@ static struct connection *accept_new_connection(struct mg_server *server) {
     set_non_blocking_mode(sock);
     conn->server = server;
     conn->client_sock = sock;
+    sockaddr_to_string(conn->mg_conn.remote_ip,
+                       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;
     mutex_init(&conn->mutex);
     LINKED_LIST_ADD_TO_FRONT(&server->active_connections, &conn->link);
     DBG(("added conn %p", conn));
@@ -1103,7 +1124,11 @@ static int is_valid_http_method(const char *method) {
 static int parse_http_message(char *buf, int len, struct mg_connection *ri) {
   int is_request, n;
 
-  memset(ri, 0, sizeof(*ri));
+  // Reset the connection. Make sure that we don't touch fields that are
+  // set elsewhere: remote_ip, remote_port, server_param
+  ri->request_method = ri->uri = ri->http_version = ri->query_string = NULL;
+  ri->num_headers = ri->status_code = ri->is_websocket = ri->content_len = 0;
+
   buf[len - 1] = '\0';
 
   // RFC says that all initial whitespaces should be ingored
@@ -1822,10 +1847,6 @@ static void call_uri_handler_if_data_is_buffered(struct connection *conn) {
   struct iobuf *loc = &conn->local_iobuf;
   struct mg_connection *c = &conn->mg_conn;
 
-  // Header parsing does memset() on the whole mg_connection, nullifying
-  // connection_param and server_param. Set them just before calling back.
-  c->server_param = conn->server->server_data;
-
   c->content = loc->buf;
 #ifndef NO_WEBSOCKET
   if (conn->mg_conn.is_websocket) {
@@ -3166,21 +3187,6 @@ static void log_header(const struct mg_connection *conn, const char *header,
   }
 }
 
-static void sockaddr_to_string(char *buf, size_t len,
-                               const union socket_address *usa) {
-  buf[0] = '\0';
-#if defined(USE_IPV6)
-  inet_ntop(usa->sa.sa_family, usa->sa.sa_family == AF_INET ?
-            (void *) &usa->sin.sin_addr :
-            (void *) &usa->sin6.sin6_addr, buf, len);
-#elif defined(_WIN32)
-  // Only Windoze Vista (and newer) have inet_ntop()
-  strncpy(buf, inet_ntoa(usa->sin.sin_addr), len);
-#else
-  inet_ntop(usa->sa.sa_family, (void *) &usa->sin.sin_addr, buf, len);
-#endif
-}
-
 static void log_access(const struct connection *conn, const char *path) {
   const struct mg_connection *c = &conn->mg_conn;
   FILE *fp = (path == NULL) ?  NULL : fopen(path, "a+");
-- 
GitLab