diff --git a/src/apps/poorman/PoorManLogger.cpp b/src/apps/poorman/PoorManLogger.cpp index 9d47475bac..2f8a5de451 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 @@ poorman_log(const char* msg, bool needTimeHeader, 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 961d5e6e61..ac42d3ee47 100644 --- a/src/apps/poorman/PoorManLogger.h +++ b/src/apps/poorman/PoorManLogger.h @@ -11,20 +11,21 @@ #include #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 faace730e4..0b53dd8104 100644 --- a/src/apps/poorman/PoorManServer.cpp +++ b/src/apps/poorman/PoorManServer.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -85,7 +86,7 @@ PoorManServer::~PoorManServer() 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 @@ status_t PoorManServer::Run() 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 @@ status_t PoorManServer::Run() static_cast(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 @@ int32 PoorManServer::_Listener(void* data) thread_id tid; httpd_conn* hc; PoorManServer* s = static_cast(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(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(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 @@ status_t PoorManServer::_HandleGet(httpd_conn* hc) 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 @@ status_t PoorManServer::_HandleGet(httpd_conn* hc) 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 caa639a029..9bfdc7fd32 100644 --- a/src/apps/poorman/PoorManWindow.cpp +++ b/src/apps/poorman/PoorManWindow.cpp @@ -214,7 +214,7 @@ PoorManWindow::MessageReceived(BMessage* message) break; time_t time; - in_addr_t address; + const char* address; rgb_color color; const void* pointer; ssize_t size; @@ -228,10 +228,8 @@ PoorManWindow::MessageReceived(BMessage* message) else time = *static_cast(pointer); - if (message->FindData("in_addr_t", B_ANY_TYPE, &pointer, &size) != B_OK) - address = INADDR_NONE; - else - address = *static_cast(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 @@ PoorManWindow::MessageReceived(BMessage* message) } } - 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 @@ PoorManWindow::StartServer() 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 ab52cc43b1..11320efa3a 100644 --- a/src/apps/poorman/libhttpd/libhttpd.c +++ b/src/apps/poorman/libhttpd/libhttpd.c @@ -394,7 +394,7 @@ httpd_initialize_listen_socket( httpd_sockaddr* saP ) 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 @@ httpd_initialize_listen_socket( httpd_sockaddr* saP ) { // 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 @@ httpd_initialize_listen_socket( httpd_sockaddr* saP ) 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 @@ ls( httpd_conn* hc ) { 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 @@ ls( httpd_conn* hc ) 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 @@ really_start_request( httpd_conn* hc, struct timeval* nowP ) { 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; }