From 80d651541537433e1363f7b4ba7497b08d0fb53f Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 16 Apr 2020 17:52:24 +0200 Subject: [PATCH] tests: run the sws server on "any port" Makes the test servers for HTTP and Gopher pop up on a currently unused port and runtests adapts to that! Closes #5247 --- tests/httpserver.pl | 18 ++++++++++--- tests/runtests.pl | 46 ++++++++++++++++--------------- tests/server/sws.c | 66 +++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 101 insertions(+), 29 deletions(-) diff --git a/tests/httpserver.pl b/tests/httpserver.pl index 05ec80ac77..58ab5d460a 100755 --- a/tests/httpserver.pl +++ b/tests/httpserver.pl @@ -44,8 +44,9 @@ my $unix_socket; # location to place a listening Unix socket my $ipvnum = 4; # default IP version of http server my $idnum = 1; # default http server instance number my $proto = 'http'; # protocol the http server speaks -my $pidfile; # http server pid file -my $logfile; # http server log file +my $pidfile; # pid file +my $portfile; # port number file +my $logfile; # log file my $connect; # IP to connect to on CONNECT my $srcdir; my $gopher = 0; @@ -61,6 +62,12 @@ while(@ARGV) { shift @ARGV; } } + elsif($ARGV[0] eq '--portfile') { + if($ARGV[1]) { + $portfile = $ARGV[1]; + shift @ARGV; + } + } elsif($ARGV[0] eq '--logfile') { if($ARGV[1]) { $logfile = $ARGV[1]; @@ -122,11 +129,16 @@ if(!$srcdir) { if(!$pidfile) { $pidfile = "$path/". server_pidfilename($proto, $ipvnum, $idnum); } +if(!$portfile) { + $portfile = "$path/". server_portfilename($proto, $ipvnum, $idnum); +} if(!$logfile) { $logfile = server_logfilename($logdir, $proto, $ipvnum, $idnum); } -$flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" "; +$flags .= "--pidfile \"$pidfile\" ". + "--logfile \"$logfile\" ". + "--portfile \"$portfile\" "; $flags .= "--gopher " if($gopher); $flags .= "--connect $connect " if($connect); if($ipvnum eq 'unix') { diff --git a/tests/runtests.pl b/tests/runtests.pl index c44b03fb58..549db529fb 100755 --- a/tests/runtests.pl +++ b/tests/runtests.pl @@ -1498,6 +1498,7 @@ sub runhttpserver { $server = servername_id($proto, $ipvnum, $idnum); $pidfile = $serverpidfile{$server}; + my $portfile = $serverportfile{$server}; # don't retry if the server doesn't work if ($doesntrun{$pidfile}) { @@ -1518,11 +1519,12 @@ sub runhttpserver { $flags .= "--connect $HOSTIP " if($alt eq "proxy"); $flags .= $verbose_flag if($debugprotocol); $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" "; + $flags .= "--portfile $portfile "; $flags .= "--id $idnum " if($idnum > 1); if($ipvnum eq "unix") { $flags .= "--unix-socket '$port_or_path' "; } else { - $flags .= "--ipv$ipvnum --port $port_or_path "; + $flags .= "--ipv$ipvnum --port 0 "; } $flags .= "--srcdir \"$srcdir\""; @@ -1538,6 +1540,12 @@ sub runhttpserver { return (0,0); } + # where is it? + my $port; + if(!$port_or_path) { + $port = $port_or_path = pidfromfile($portfile); + } + # Server is up. Verify that we can speak to it. my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port_or_path); if(!$pid3) { @@ -1556,7 +1564,7 @@ sub runhttpserver { sleep(1); - return ($httppid, $pid2); + return ($httppid, $pid2, $port); } ####################################################################### @@ -4611,8 +4619,8 @@ sub startservers { stopserver('gopher'); } if(!$run{'gopher'}) { - ($pid, $pid2) = runhttpserver("gopher", $verbose, 0, - $GOPHERPORT); + ($pid, $pid2, $GOPHERPORT) = + runhttpserver("gopher", $verbose, 0); if($pid <= 0) { return "failed starting GOPHER server"; } @@ -4628,8 +4636,8 @@ sub startservers { stopserver('gopher-ipv6'); } if(!$run{'gopher-ipv6'}) { - ($pid, $pid2) = runhttpserver("gopher", $verbose, "ipv6", - $GOPHER6PORT); + ($pid, $pid2, $GOPHER6PORT) = + runhttpserver("gopher", $verbose, "ipv6"); if($pid <= 0) { return "failed starting GOPHER-IPv6 server"; } @@ -4655,8 +4663,8 @@ sub startservers { stopserver('http'); } if(!$run{'http'}) { - ($pid, $pid2) = runhttpserver("http", $verbose, 0, - $HTTPPORT); + ($pid, $pid2, $HTTPPORT) = + runhttpserver("http", $verbose, 0); if($pid <= 0) { return "failed starting HTTP server"; } @@ -4672,8 +4680,8 @@ sub startservers { stopserver('http-proxy'); } if(!$run{'http-proxy'}) { - ($pid, $pid2) = runhttpserver("http", $verbose, "proxy", - $HTTPPROXYPORT); + ($pid, $pid2, $HTTPPROXYPORT) = + runhttpserver("http", $verbose, "proxy"); if($pid <= 0) { return "failed starting HTTP-proxy server"; } @@ -4688,8 +4696,8 @@ sub startservers { stopserver('http-ipv6'); } if(!$run{'http-ipv6'}) { - ($pid, $pid2) = runhttpserver("http", $verbose, "ipv6", - $HTTP6PORT); + ($pid, $pid2, $HTTP6PORT) = + runhttpserver("http", $verbose, "ipv6"); if($pid <= 0) { return "failed starting HTTP-IPv6 server"; } @@ -4775,8 +4783,8 @@ sub startservers { stopserver('http'); } if(!$run{'http'}) { - ($pid, $pid2) = runhttpserver("http", $verbose, 0, - $HTTPPORT); + ($pid, $pid2, $HTTPPORT) = + runhttpserver("http", $verbose, 0); if($pid <= 0) { return "failed starting HTTP server"; } @@ -4895,8 +4903,9 @@ sub startservers { stopserver('http-unix'); } if(!$run{'http-unix'}) { - ($pid, $pid2) = runhttpserver("http", $verbose, "unix", - $HTTPUNIXPATH); + my $unused; + ($pid, $pid2, $unused) = + runhttpserver("http", $verbose, "unix", $HTTPUNIXPATH); if($pid <= 0) { return "failed starting HTTP-unix server"; } @@ -5427,11 +5436,9 @@ if ($gdbthis) { $minport = $base; # original base port number -$HTTPPORT = $base++; # HTTP server port $HTTPSPORT = $base++; # HTTPS (stunnel) server port $FTPPORT = $base++; # FTP server port $FTPSPORT = $base++; # FTPS (stunnel) server port -$HTTP6PORT = $base++; # HTTP IPv6 server port $FTP2PORT = $base++; # FTP server 2 port $FTP6PORT = $base++; # FTP IPv6 port $TFTPPORT = $base++; # TFTP (UDP) port @@ -5446,11 +5453,8 @@ $SMTPPORT = $base++; # SMTP server port $SMTP6PORT = $base++; # SMTP IPv6 server port $RTSPPORT = $base++; # RTSP server port $RTSP6PORT = $base++; # RTSP IPv6 server port -$GOPHERPORT = $base++; # Gopher IPv4 server port -$GOPHER6PORT = $base++; # Gopher IPv6 server port $HTTPTLSPORT = $base++; # HTTP TLS (non-stunnel) server port $HTTPTLS6PORT = $base++; # HTTP TLS (non-stunnel) IPv6 server port -$HTTPPROXYPORT = $base++; # HTTP proxy port, when using CONNECT $HTTP2PORT = $base++; # HTTP/2 port $DICTPORT = $base++; # DICT port $SMBPORT = $base++; # SMB port diff --git a/tests/server/sws.c b/tests/server/sws.c index 427bd6e8d2..faa1143d96 100644 --- a/tests/server/sws.c +++ b/tests/server/sws.c @@ -1849,6 +1849,7 @@ int main(int argc, char *argv[]) bool unlink_socket = false; #endif const char *pidname = ".http.pid"; + const char *portname = ".http.port"; struct httprequest req; int rc = 0; int error; @@ -1881,6 +1882,11 @@ int main(int argc, char *argv[]) if(argc>arg) pidname = argv[arg++]; } + else if(!strcmp("--portfile", argv[arg])) { + arg++; + if(argc>arg) + portname = argv[arg++]; + } else if(!strcmp("--logfile", argv[arg])) { arg++; if(argc>arg) @@ -1928,7 +1934,7 @@ int main(int argc, char *argv[]) char *endptr; unsigned long ulnum = strtoul(argv[arg], &endptr, 10); if((endptr != argv[arg] + strlen(argv[arg])) || - (ulnum < 1025UL) || (ulnum > 65535UL)) { + (ulnum && ((ulnum < 1025UL) || (ulnum > 65535UL)))) { fprintf(stderr, "sws: invalid --port argument (%s)\n", argv[arg]); return 0; @@ -1961,6 +1967,7 @@ int main(int argc, char *argv[]) " --version\n" " --logfile [file]\n" " --pidfile [file]\n" + " --portfile [file]\n" " --ipv4\n" " --ipv6\n" " --unix-socket [file]\n" @@ -1972,8 +1979,6 @@ int main(int argc, char *argv[]) } } - msnprintf(port_str, sizeof(port_str), "port %hu", port); - #ifdef WIN32 win32_init(); atexit(win32_cleanup); @@ -2080,11 +2085,58 @@ int main(int argc, char *argv[]) } if(0 != rc) { error = SOCKERRNO; - logmsg("Error binding socket on %s: (%d) %s", - location_str, error, strerror(error)); + logmsg("Error binding socket: (%d) %s", error, strerror(error)); goto sws_cleanup; } + if(!port) { + /* The system was supposed to choose a port number, figure out which + port we actually got and update the listener port value with it. */ + curl_socklen_t la_size; + srvr_sockaddr_union_t localaddr; +#ifdef ENABLE_IPV6 + if(socket_domain != AF_INET6) +#endif + la_size = sizeof(localaddr.sa4); +#ifdef ENABLE_IPV6 + else + la_size = sizeof(localaddr.sa6); +#endif + memset(&localaddr.sa, 0, (size_t)la_size); + if(getsockname(sock, &localaddr.sa, &la_size) < 0) { + error = SOCKERRNO; + logmsg("getsockname() failed with error: (%d) %s", + error, strerror(error)); + sclose(sock); + goto sws_cleanup; + } + switch(localaddr.sa.sa_family) { + case AF_INET: + port = ntohs(localaddr.sa4.sin_port); + break; +#ifdef ENABLE_IPV6 + case AF_INET6: + port = ntohs(localaddr.sa6.sin6_port); + break; +#endif + default: + break; + } + if(!port) { + /* Real failure, listener port shall not be zero beyond this point. */ + logmsg("Apparently getsockname() succeeded, with listener port zero."); + logmsg("A valid reason for this failure is a binary built without"); + logmsg("proper network library linkage. This might not be the only"); + logmsg("reason, but double check it before anything else."); + sclose(sock); + goto sws_cleanup; + } + } +#ifdef USE_UNIX_SOCKETS + if(socket_domain != AF_UNIX) +#endif + msnprintf(port_str, sizeof(port_str), "port %hu", port); + logmsg("Running %s %s version on %s", use_gopher?"GOPHER":"HTTP", socket_type, location_str); @@ -2111,6 +2163,10 @@ int main(int argc, char *argv[]) if(!wrotepidfile) goto sws_cleanup; + wrotepidfile = write_portfile(portname, port); + if(!wrotepidfile) + goto sws_cleanup; + /* initialization of httprequest struct is done before get_request(), but the pipelining struct field must be initialized previously to FALSE every time a new connection arrives. */