From bae87dc0d93d8e56bd1038d4a46477992eaa1bdd Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 20 Apr 2020 14:53:50 +0200 Subject: [PATCH] tests: run the RTSP test server on a dynamic port number To avoid port collisions. Closes #5272 --- tests/rtspserver.pl | 11 +++++++- tests/runtests.pl | 25 ++++++++---------- tests/server/rtspd.c | 62 +++++++++++++++++++++++++++++++++++++++----- 3 files changed, 77 insertions(+), 21 deletions(-) diff --git a/tests/rtspserver.pl b/tests/rtspserver.pl index 00a48b078..315526a93 100755 --- a/tests/rtspserver.pl +++ b/tests/rtspserver.pl @@ -44,6 +44,7 @@ my $ipvnum = 4; # default IP version of rtsp server my $idnum = 1; # default rtsp server instance number my $proto = 'rtsp'; # protocol the rtsp server speaks my $pidfile; # rtsp server pid file +my $portfile; my $logfile; # rtsp server log file my $srcdir; @@ -58,6 +59,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]; @@ -107,7 +114,9 @@ if(!$logfile) { $logfile = server_logfilename($logdir, $proto, $ipvnum, $idnum); } -$flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" "; +$flags .= "--pidfile \"$pidfile\" ". + "--portfile \"$portfile\" ". + "--logfile \"$logfile\" "; $flags .= "--ipv$ipvnum --port $port --srcdir \"$srcdir\""; exec("server/rtspd".exe_ext('SRV')." $flags"); diff --git a/tests/runtests.pl b/tests/runtests.pl index cfc2c8694..1c6a028b9 100755 --- a/tests/runtests.pl +++ b/tests/runtests.pl @@ -2025,7 +2025,6 @@ sub runtftpserver { # sub runrtspserver { my ($verbose, $ipv6) = @_; - my $port = $RTSPPORT; my $ip = $HOSTIP; my $proto = 'rtsp'; my $ipvnum = 4; @@ -2039,13 +2038,13 @@ sub runrtspserver { if($ipv6) { # if IPv6, use a different setup $ipvnum = 6; - $port = $RTSP6PORT; $ip = $HOST6IP; } $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}) { @@ -2063,9 +2062,11 @@ sub runrtspserver { $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum); $flags .= "--verbose " if($debugprotocol); - $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" "; + $flags .= "--pidfile \"$pidfile\" ". + "--portfile \"$portfile\" ". + "--logfile \"$logfile\" "; $flags .= "--id $idnum " if($idnum > 1); - $flags .= "--ipv$ipvnum --port $port --srcdir \"$srcdir\""; + $flags .= "--ipv$ipvnum --port 0 --srcdir \"$srcdir\""; my $cmd = "$perl $srcdir/rtspserver.pl $flags"; my ($rtsppid, $pid2) = startnew($cmd, $pidfile, 15, 0); @@ -2079,6 +2080,8 @@ sub runrtspserver { return (0,0); } + my $port = pidfromfile($portfile); + # Server is up. Verify that we can speak to it. my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port); if(!$pid3) { @@ -2092,12 +2095,12 @@ sub runrtspserver { $pid2 = $pid3; if($verbose) { - logmsg "RUN: $srvrname server is now running PID $rtsppid\n"; + logmsg "RUN: $srvrname server PID $rtsppid port $port\n"; } sleep(1); - return ($rtsppid, $pid2); + return ($rtsppid, $pid2, $port); } @@ -3154,14 +3157,10 @@ sub checksystem { if($verbose) { logmsg "* Ports: "; - logmsg sprintf("RTSP/%d ", $RTSPPORT); if($stunnel) { logmsg sprintf("FTPS/%d ", $FTPSPORT); logmsg sprintf("HTTPS/%d ", $HTTPSPORT); } - if($http_ipv6) { - logmsg sprintf("RTSP-IPv6/%d ", $RTSP6PORT); - } logmsg sprintf("\n* SSH/%d ", $SSHPORT); if($httptlssrv) { logmsg sprintf("HTTPTLS/%d ", $HTTPTLSPORT); @@ -4718,7 +4717,7 @@ sub startservers { stopserver('rtsp'); } if(!$run{'rtsp'}) { - ($pid, $pid2) = runrtspserver($verbose); + ($pid, $pid2, $RTSPPORT) = runrtspserver($verbose); if($pid <= 0) { return "failed starting RTSP server"; } @@ -4732,7 +4731,7 @@ sub startservers { stopserver('rtsp-ipv6'); } if(!$run{'rtsp-ipv6'}) { - ($pid, $pid2) = runrtspserver($verbose, "ipv6"); + ($pid, $pid2, $RTSP6PORT) = runrtspserver($verbose, "ipv6"); if($pid <= 0) { return "failed starting RTSP-IPv6 server"; } @@ -5446,8 +5445,6 @@ $minport = $base; # original base port number $HTTPSPORT = $base++; # HTTPS (stunnel) server port $FTPSPORT = $base++; # FTPS (stunnel) server port $SSHPORT = $base++; # SSH (SCP/SFTP) port -$RTSPPORT = $base++; # RTSP server port -$RTSP6PORT = $base++; # RTSP IPv6 server port $HTTPTLSPORT = $base++; # HTTP TLS (non-stunnel) server port $HTTPTLS6PORT = $base++; # HTTP TLS (non-stunnel) IPv6 server port $HTTP2PORT = $base++; # HTTP/2 port diff --git a/tests/server/rtspd.c b/tests/server/rtspd.c index 2d95d8359..6ee7787b1 100644 --- a/tests/server/rtspd.c +++ b/tests/server/rtspd.c @@ -1049,6 +1049,7 @@ int main(int argc, char *argv[]) int flag; unsigned short port = DEFAULT_PORT; const char *pidname = ".rtsp.pid"; + const char *portfile = NULL; struct httprequest req; int rc; int error; @@ -1075,6 +1076,11 @@ int main(int argc, char *argv[]) if(argc>arg) pidname = argv[arg++]; } + else if(!strcmp("--portfile", argv[arg])) { + arg++; + if(argc>arg) + portfile = argv[arg++]; + } else if(!strcmp("--logfile", argv[arg])) { arg++; if(argc>arg) @@ -1099,12 +1105,6 @@ int main(int argc, char *argv[]) if(argc>arg) { char *endptr; unsigned long ulnum = strtoul(argv[arg], &endptr, 10); - if((endptr != argv[arg] + strlen(argv[arg])) || - (ulnum < 1025UL) || (ulnum > 65535UL)) { - fprintf(stderr, "rtspd: invalid --port argument (%s)\n", - argv[arg]); - return 0; - } port = curlx_ultous(ulnum); arg++; } @@ -1121,6 +1121,7 @@ int main(int argc, char *argv[]) " --version\n" " --logfile [file]\n" " --pidfile [file]\n" + " --portfile [file]\n" " --ipv4\n" " --ipv6\n" " --port [port]\n" @@ -1188,6 +1189,49 @@ int main(int argc, char *argv[]) goto server_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(!use_ipv6) +#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 server_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 server_cleanup; + } + } logmsg("Running %s version on port %d", ipv_inuse, (int)port); /* start accepting connections */ @@ -1208,6 +1252,12 @@ int main(int argc, char *argv[]) if(!wrotepidfile) goto server_cleanup; + if(portfile) { + wrotepidfile = write_portfile(portfile, port); + if(!wrotepidfile) + goto server_cleanup; + } + for(;;) { msgsock = accept(sock, NULL, NULL);