[haiku-commits] Change in haiku[master]: PoorMan: Add dual-stack IPv6 support

  • From: Gerrit <review@xxxxxxxxxxxxxxxxxxx>
  • To: waddlesplash <waddlesplash@xxxxxxxxx>, haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 20 Dec 2020 12:08:28 +0000

From Jeremy Visser <jeremyvisser@xxxxxxxxxx>:

Jeremy Visser has uploaded this change for review. ( 
https://review.haiku-os.org/c/haiku/+/3539 ;)


Change subject: PoorMan: Add dual-stack IPv6 support
......................................................................

PoorMan: Add dual-stack IPv6 support

This change adds dual-stack IPv6 support to the PoorMan web server,
which will listen on all available IPv4 and IPv6 addresses and
respond to both.

This change also does some necessary plumbing to support the
output of nicely-formatted IPv6 addresses for request logging.
---
M src/apps/poorman/PoorManLogger.cpp
M src/apps/poorman/PoorManLogger.h
M src/apps/poorman/PoorManServer.cpp
M src/apps/poorman/PoorManWindow.cpp
M src/apps/poorman/libhttpd/libhttpd.c
5 files changed, 103 insertions(+), 75 deletions(-)



  git pull ssh://git.haiku-os.org:22/haiku refs/changes/39/3539/1

diff --git a/src/apps/poorman/PoorManLogger.cpp 
b/src/apps/poorman/PoorManLogger.cpp
index 9d47475..2f8a5de 100644
--- a/src/apps/poorman/PoorManLogger.cpp
+++ b/src/apps/poorman/PoorManLogger.cpp
@@ -17,10 +17,11 @@

 #include "PoorManApplication.h"
 #include "PoorManWindow.h"
+#include "libhttpd.h"

 void
 poorman_log(const char* msg, bool needTimeHeader,
-       in_addr_t addr, rgb_color color)
+       httpd_sockaddr* addr, rgb_color color)
 {
        time_t now = time(NULL);

@@ -38,8 +39,8 @@
                if(message.AddData("time_t", B_TIME_TYPE, &now, sizeof(time_t)) 
!= B_OK)
                        return;
        }
-       if(addr != INADDR_NONE)
-               message.AddData("in_addr_t", B_ANY_TYPE, &addr, 
sizeof(in_addr_t));
+       if(addr != NULL)
+               message.AddString("addr", httpd_ntoa(addr));

        if(color != BLACK)
                message.AddData("rgb_color", B_RGB_COLOR_TYPE, &color, 
sizeof(rgb_color));
diff --git a/src/apps/poorman/PoorManLogger.h b/src/apps/poorman/PoorManLogger.h
index 961d5e6..ac42d3e 100644
--- a/src/apps/poorman/PoorManLogger.h
+++ b/src/apps/poorman/PoorManLogger.h
@@ -11,20 +11,21 @@
 #include <netinet/in.h>

 #include "constants.h" //for rgb_color BLACK
+#include "libhttpd.h" //for httpd_sockaddr

 #ifdef __cplusplus
        extern "C"
        void poorman_log(
                const char* msg,
                bool needTimeHeader = true,
-               in_addr_t addr = INADDR_NONE,
+               httpd_sockaddr* addr = NULL,
                rgb_color color = BLACK
        );
 #else //c version is for libhttpd
        void poorman_log(
                const char* msg,
                bool needTimeHeader,
-               in_addr_t addr,
+               httpd_sockaddr* addr,
                rgb_color color
        );
 #endif
diff --git a/src/apps/poorman/PoorManServer.cpp 
b/src/apps/poorman/PoorManServer.cpp
index faace73..0b53dd8 100644
--- a/src/apps/poorman/PoorManServer.cpp
+++ b/src/apps/poorman/PoorManServer.cpp
@@ -15,6 +15,7 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <poll.h>

 #include <File.h>
 #include <Debug.h>
@@ -85,7 +86,7 @@
 status_t PoorManServer::Run()
 {
        if (chdir(fHttpdServer->cwd) == -1) {
-               poorman_log("no web directory, can't start up.\n", false, 
INADDR_NONE, RED);
+               poorman_log("no web directory, can't start up.\n", false, NULL, 
RED);
                return B_ERROR;
        }

@@ -95,7 +96,15 @@
        sa4.sa_in.sin_port = htons(80);
        sa4.sa_in.sin_addr.s_addr = htonl(INADDR_ANY);
        fHttpdServer->listen4_fd = httpd_initialize_listen_socket(&sa4);
-       if (fHttpdServer->listen4_fd == -1)
+
+       httpd_sockaddr sa6;
+       memset(&sa6, 0, sizeof(httpd_sockaddr));
+       sa6.sa_in.sin_family = AF_INET6;
+       sa6.sa_in.sin_port = htons(80);
+       sa6.sa_in.sin_addr.s_addr = htonl(INADDR_ANY);
+       fHttpdServer->listen6_fd = httpd_initialize_listen_socket(&sa6);
+
+       if (fHttpdServer->listen4_fd == -1 && fHttpdServer->listen6_fd == -1)
                return B_ERROR;

        fListenerTid = spawn_thread(
@@ -105,7 +114,7 @@
                static_cast<void*>(this)
        );
        if (fListenerTid < B_OK) {
-               poorman_log("can't create listener thread.\n", false, 
INADDR_NONE, RED);
+               poorman_log("can't create listener thread.\n", false, NULL, 
RED);
                return B_ERROR;
        }
        fIsRunning = true;
@@ -204,55 +213,79 @@
        thread_id tid;
        httpd_conn* hc;
        PoorManServer* s = static_cast<PoorManServer*>(data);
-
+       const int nfds = 2;
+       pollfd fds[nfds];
+
+       // N.B. these fds could be -1, which poll() should skip
+       memset(&fds, 0, sizeof(fds));
+       fds[0].fd = s->fHttpdServer->listen4_fd;
+       fds[0].events = POLLIN;
+       fds[1].fd = s->fHttpdServer->listen6_fd;
+       fds[1].events = POLLIN;
+
        while (s->fIsRunning) {
-               hc = new httpd_conn;
-               hc->initialized = 0;
-               PRINT(("calling httpd_get_conn()\n"));
-               retval = //accept(), blocked here
-                       httpd_get_conn(s->fHttpdServer, 
s->fHttpdServer->listen4_fd, hc);
-               switch (retval) {
-                       case GC_OK:
-                               break;
-                       case GC_FAIL:
-                               httpd_destroy_conn(hc);
-                               delete hc;
-                               s->fIsRunning = false;
-                               return -1;
-                       case GC_NO_MORE:
-                               //should not happen, since we have a blocking 
socket
-                               httpd_destroy_conn(hc);
-                               continue;
-                               break;
-                       default:
-                               //shouldn't happen
-                               continue;
-                               break;
+               // Wait for listen4_fd or listen6_fd (or both!) to become ready:
+               retval = poll(fds, nfds, -1);
+               if (retval < 1) {
+                       return -1; // fds no longer available
                }

-               if (s->fCurConns > s->fMaxConns) {
-                       httpd_send_err(hc, 503,
-                               httpd_err503title, (char *)"", 
httpd_err503form, (char *)"");
-                       httpd_write_response(hc);
-                       continue;
-               }
-
-               tid = spawn_thread(
-                       PoorManServer::_Worker,
-                       "www connection",
-                       B_NORMAL_PRIORITY,
-                       static_cast<void*>(s)
-               );
-               if (tid < B_OK) {
-                       continue;
-               }
-               /*We don't check the return code here.
-                *As we can't kill a thread that doesn't receive the
-                *httpd_conn, we simply let it die itself.
-                */
-               send_data(tid, 512, &hc, sizeof(httpd_conn*));
-               atomic_add(&s->fCurConns, 1);
-               resume_thread(tid);
+               for (int fdi = 0; fdi < nfds; fdi++) {
+                       if (fds[fdi].fd < 0) {
+                               continue; // fd is disabled, e.g. ipv4-only
+                       }
+                       if ((fds[fdi].revents & POLLIN) != POLLIN) {
+                               continue; // fd is unavailable, try next fd
+                       }
+
+                       hc = new httpd_conn;
+                       hc->initialized = 0;
+
+                       PRINT(("calling httpd_get_conn()\n"));
+                       retval = httpd_get_conn(s->fHttpdServer, fds[fdi].fd, 
hc);
+                       switch (retval) {
+                               case GC_OK:
+                                       break;
+                               case GC_FAIL:
+                                       httpd_destroy_conn(hc);
+                                       delete hc;
+                                       s->fIsRunning = false;
+                                       return -1;
+                               case GC_NO_MORE:
+                                       //should not happen, since we have a 
blocking socket
+                                       httpd_destroy_conn(hc);
+                                       continue;
+                                       break;
+                               default:
+                                       //shouldn't happen
+                                       continue;
+                                       break;
+                       }
+
+                       if (s->fCurConns > s->fMaxConns) {
+                               httpd_send_err(hc, 503,
+                                       httpd_err503title, (char *)"", 
httpd_err503form, (char *)"");
+                               httpd_write_response(hc);
+                               continue;
+                       }
+
+                       tid = spawn_thread(
+                               PoorManServer::_Worker,
+                               "www connection",
+                               B_NORMAL_PRIORITY,
+                               static_cast<void*>(s)
+                       );
+                       if (tid < B_OK) {
+                               continue;
+                       }
+                       /*We don't check the return code here.
+                        *As we can't kill a thread that doesn't receive the
+                        *httpd_conn, we simply let it die itself.
+                        */
+                       send_data(tid, 512, &hc, sizeof(httpd_conn*));
+                       atomic_add(&s->fCurConns, 1);
+                       resume_thread(tid);
+               }//for
        }//while
        return 0;
 }
@@ -374,7 +407,7 @@
                pthread_rwlock_unlock(&fWebDirLock);
        }
        log << '/' << hc->expnfilename << '\n';
-       poorman_log(log.String(), true, hc->client_addr.sa_in.sin_addr.s_addr);
+       poorman_log(log.String(), true, &hc->client_addr);

        //send mime headers
        if (send(hc->conn_fd, hc->response, hc->responselen, 0) < 0) {
@@ -398,7 +431,7 @@
                                pthread_rwlock_unlock(&fWebDirLock);
                        }
                        log << '/' << hc->expnfilename << '\n';
-                       poorman_log(log.String(), true, 
hc->client_addr.sa_in.sin_addr.s_addr, RED);
+                       poorman_log(log.String(), true, &hc->client_addr, RED);
                        delete [] buf;
                        return B_ERROR;
                }
diff --git a/src/apps/poorman/PoorManWindow.cpp 
b/src/apps/poorman/PoorManWindow.cpp
index caa639a..9bfdc7f 100644
--- a/src/apps/poorman/PoorManWindow.cpp
+++ b/src/apps/poorman/PoorManWindow.cpp
@@ -214,7 +214,7 @@
                                break;

                        time_t time;
-                       in_addr_t address;
+                       const char* address;
                        rgb_color color;
                        const void* pointer;
                        ssize_t size;
@@ -228,10 +228,8 @@
                        else
                                time = *static_cast<const time_t*>(pointer);

-                       if (message->FindData("in_addr_t", B_ANY_TYPE, 
&pointer, &size) != B_OK)
-                               address = INADDR_NONE;
-                       else
-                               address = *static_cast<const 
in_addr_t*>(pointer);
+                       if (message->FindString("addr", &address) != B_OK)
+                               address = NULL;

                        if (message->FindData("rgb_color", B_RGB_COLOR_TYPE, 
&pointer, &size) != B_OK)
                                color = BLACK;
@@ -246,13 +244,8 @@
                                }
                        }

-                       if (address != INADDR_NONE) {
-                               char addr[INET_ADDRSTRLEN];
-                               struct in_addr sin_addr;
-                               sin_addr.s_addr = address;
-                               if (inet_ntop(AF_INET, &sin_addr, addr, 
sizeof(addr)) != NULL) {
-                                       line << '(' << addr << ") ";
-                               }
+                       if (address != NULL) {
+                               line << '(' << address << ") ";
                        }

                        line << msg;
@@ -711,7 +704,7 @@

        fStatus = true;
        UpdateStatusLabelAndMenuItem();
-       poorman_log(B_TRANSLATE("done.\n"), false, INADDR_NONE, GREEN);
+       poorman_log(B_TRANSLATE("done.\n"), false, NULL, GREEN);

        return B_OK;
 }
diff --git a/src/apps/poorman/libhttpd/libhttpd.c 
b/src/apps/poorman/libhttpd/libhttpd.c
index ab52cc4..11320ef 100644
--- a/src/apps/poorman/libhttpd/libhttpd.c
+++ b/src/apps/poorman/libhttpd/libhttpd.c
@@ -394,7 +394,7 @@
        if ( listen_fd < 0 )
        {
 //     syslog( LOG_CRIT, "socket %.80s - %m", httpd_ntoa( saP ) );
-               poorman_log("can't create socket.\n", false, INADDR_NONE, RED);
+               poorman_log("can't create socket.\n", false, NULL, RED);
                return -1;
        }
        (void) fcntl( listen_fd, F_SETFD, 1 );
@@ -411,7 +411,7 @@
        {
                //      syslog(
                //          LOG_CRIT, "bind %.80s - %m", httpd_ntoa( saP ) );
-               poorman_log("can't bind to socket.\n", false, INADDR_NONE, RED);
+               poorman_log("can't bind to socket.\n", false, NULL, RED);
                (void) close( listen_fd );
                return -1;
        }
@@ -420,7 +420,7 @@
        if ( listen( listen_fd, LISTEN_BACKLOG ) < 0 )
        {
                //      syslog( LOG_CRIT, "listen - %m" );
-               poorman_log("can't listen to socket.\n", false, INADDR_NONE, 
RED);
+               poorman_log("can't listen to socket.\n", false, NULL, RED);
                (void) close( listen_fd );
                return -1;
        }
@@ -2695,7 +2695,7 @@
        {
        char logString[27+B_PATH_NAME_LENGTH+1];
        sprintf(logString, "Error 404 File not found: %s\n", hc->decodedurl+1);
-       poorman_log(logString, true, hc->client_addr.sa_in.sin_addr.s_addr, 
RED);
+       poorman_log(logString, true, &hc->client_addr, RED);
 //     syslog( LOG_ERR, "opendir %.80s - %m", hc->expnfilename );
        httpd_send_err( hc, 404, err404title, "", err404form, hc->encodedurl );
        free(de);
@@ -2735,7 +2735,7 @@
                                strcat(logString, "index file");

                        strcat(logString, ".  Sending directory listing.\n");
-                       poorman_log(logString, true, 
hc->client_addr.sa_in.sin_addr.s_addr, BLACK);
+                       poorman_log(logString, true, &hc->client_addr, BLACK);
                }

            send_mime(
@@ -3049,7 +3049,7 @@
            {
            char logString[27+B_PATH_NAME_LENGTH+1];
                sprintf(logString, "Error 404 File not found: %s\n", 
hc->decodedurl+1);
-               poorman_log(logString, true, 
hc->client_addr.sa_in.sin_addr.s_addr, RED);
+               poorman_log(logString, true, &hc->client_addr, RED);
            httpd_send_err( hc, 404, err404title, "", err404form, 
hc->encodedurl );
            return -1;
            }

--
To view, visit https://review.haiku-os.org/c/haiku/+/3539
To unsubscribe, or for help writing mail filters, visit 
https://review.haiku-os.org/settings

Gerrit-Project: haiku
Gerrit-Branch: master
Gerrit-Change-Id: I0ce7691222f0233e2e098d67e6293b9e58d7486d
Gerrit-Change-Number: 3539
Gerrit-PatchSet: 1
Gerrit-Owner: Jeremy Visser <jeremyvisser@xxxxxxxxxx>
Gerrit-MessageType: newchange

Other related posts:

  • » [haiku-commits] Change in haiku[master]: PoorMan: Add dual-stack IPv6 support - Gerrit