From 15e738400fc6d322b0caad7a5a7ef1dcaea5065f Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 5 Nov 2008 21:51:59 +0000 Subject: [PATCH] Adjust the default listening address selection for the web server: be prepared to fall back to sensible localhost when MacOS doesn't like silly localhost, and also pick a random port instead of 80 when the user didn't specify one. git-svn-id: svn://svn.tartarus.org/sgt/agedu@8282 cda61777-01e9-0310-a592-d414129be87e --- TODO | 13 ------------- agedu.but | 4 ++-- httpd.c | 34 ++++++++++++++++++++++++---------- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/TODO b/TODO index f34f507..6549737 100644 --- a/TODO +++ b/TODO @@ -1,19 +1,6 @@ TODO list for agedu =================== - - adjust the default web server address selection. - + some systems (e.g. OS X) don't like us binding to random - localhost addresses. So if that fails, try falling back to - 127.0.0.1 proper (and a randomly selected port) before giving - up. - + since binding to port 80 isn't generally feasible, we should - adjust the default behaviour when the user specifies --addr - with no port: it should select port zero, and then print the - port number on standard output. (Possibly also print the URL - as usual, in that situation: translate INADDR_ANY to - INADDR_LOOPBACK and then do the same as when we made the - entire address up ourself.) - - we should munmap in all operating modes where we mmapped, otherwise chaining them will run out of address space diff --git a/agedu.but b/agedu.but index 3eb481a..5bf5d0b 100644 --- a/agedu.but +++ b/agedu.but @@ -481,8 +481,8 @@ three months ago or later. \cw{agedu} should listen when running its web server. If you want \cw{agedu} to listen for connections coming in from any source, you should probably specify the special IP address \cw{0.0.0.0}. If the -port number is omitted, it will be assumed to be 80 (for which -\cw{agedu} will probably need to be running as a privileged user). +port number is omitted, an arbitrary unused port will be chosen for +you and displayed. \lcont{ diff --git a/httpd.c b/httpd.c index 7c3f0f8..bbe82ab 100644 --- a/httpd.c +++ b/httpd.c @@ -403,7 +403,7 @@ static void base64_encode_atom(unsigned char *data, int n, char *out) void run_httpd(const void *t, int authmask, const struct httpd_config *dcfg, const struct html_config *incfg) { - int fd; + int fd, ret; int authtype; char *authstring = NULL; unsigned long ipaddr; @@ -432,12 +432,24 @@ void run_httpd(const void *t, int authmask, const struct httpd_config *dcfg, ipaddr += (1 + rand() % 255); addr.sin_addr.s_addr = htonl(ipaddr); addr.sin_port = htons(0); + } else { addr.sin_addr.s_addr = inet_addr(dcfg->address); - addr.sin_port = dcfg->port ? htons(dcfg->port) : 80; + addr.sin_port = dcfg->port ? htons(dcfg->port) : 0; } addrlen = sizeof(addr); - if (bind(fd, (struct sockaddr *)&addr, addrlen) < 0) { + ret = bind(fd, (const struct sockaddr *)&addr, addrlen); + if (ret < 0 && errno == EADDRNOTAVAIL && !dcfg->address) { + /* + * Some systems don't like us binding to random weird + * localhost-space addresses. Try again with the official + * INADDR_LOOPBACK. + */ + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr.sin_port = htons(0); + ret = bind(fd, (const struct sockaddr *)&addr, addrlen); + } + if (ret < 0) { fprintf(stderr, "bind: %s\n", strerror(errno)); exit(1); } @@ -537,13 +549,13 @@ void run_httpd(const void *t, int authmask, const struct httpd_config *dcfg, fprintf(stderr, PNAME ": authentication method not supported\n"); exit(1); } - if (!dcfg->address) { - if (ntohs(addr.sin_port) == 80) { - printf("URL: http://%s/\n", inet_ntoa(addr.sin_addr)); - } else { - printf("URL: http://%s:%d/\n", - inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); - } + if (ntohs(addr.sin_addr.s_addr) == INADDR_ANY) { + printf("Server port: %d\n", ntohs(addr.sin_port)); + } else if (ntohs(addr.sin_port) == 80) { + printf("URL: http://%s/\n", inet_ntoa(addr.sin_addr)); + } else { + printf("URL: http://%s:%d/\n", + inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); } /* @@ -589,6 +601,8 @@ void run_httpd(const void *t, int authmask, const struct httpd_config *dcfg, switch (fds[i].type) { case FD_CLIENT: + FD_SET_MAX(fds[i].fd, &rfds, maxfd); + break; case FD_LISTENER: FD_SET_MAX(fds[i].fd, &rfds, maxfd); break; -- 2.11.0