mirror of
https://github.com/curl/curl.git
synced 2026-04-14 22:01:41 +03:00
tests/server: de-dupe/merge three sockdaemon() clones into one
Also: tidy up `if()` expressions here and there.
Follow-up to f4f25505df #15000
Closes #17719
This commit is contained in:
parent
1a70977a83
commit
bb50dee510
9 changed files with 212 additions and 500 deletions
|
|
@ -504,7 +504,7 @@ static int test_dnsd(int argc, char **argv)
|
|||
rc = bind(sock, &me.sa, sizeof(me.sa6));
|
||||
}
|
||||
#endif /* USE_IPV6 */
|
||||
if(0 != rc) {
|
||||
if(rc) {
|
||||
error = SOCKERRNO;
|
||||
logmsg("Error binding socket on port %hu (%d) %s", port, error,
|
||||
sstrerror(error));
|
||||
|
|
|
|||
|
|
@ -135,6 +135,10 @@ extern int bind_unix_socket(curl_socket_t sock, const char *unix_socket,
|
|||
struct sockaddr_un *sau);
|
||||
#endif
|
||||
extern unsigned short util_ultous(unsigned long ulnum);
|
||||
extern curl_socket_t sockdaemon(curl_socket_t sock,
|
||||
unsigned short *listenport,
|
||||
const char *unix_socket,
|
||||
bool bind_only);
|
||||
|
||||
/* global variables */
|
||||
static const char *srcpath = "."; /* pointing to the test dir */
|
||||
|
|
|
|||
|
|
@ -715,149 +715,6 @@ static bool mqttd_incoming(curl_socket_t listenfd)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static curl_socket_t mqttd_sockdaemon(curl_socket_t sock,
|
||||
unsigned short *listenport,
|
||||
bool bind_only)
|
||||
{
|
||||
/* passive daemon style */
|
||||
srvr_sockaddr_union_t listener;
|
||||
int flag;
|
||||
int rc;
|
||||
int totdelay = 0;
|
||||
int maxretr = 10;
|
||||
int delay = 20;
|
||||
int attempt = 0;
|
||||
int error = 0;
|
||||
|
||||
do {
|
||||
attempt++;
|
||||
flag = 1;
|
||||
rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
(void *)&flag, sizeof(flag));
|
||||
if(rc) {
|
||||
error = SOCKERRNO;
|
||||
logmsg("setsockopt(SO_REUSEADDR) failed with error (%d) %s",
|
||||
error, sstrerror(error));
|
||||
if(maxretr) {
|
||||
rc = curlx_wait_ms(delay);
|
||||
if(rc) {
|
||||
/* should not happen */
|
||||
error = SOCKERRNO;
|
||||
logmsg("curlx_wait_ms() failed with error (%d) %s",
|
||||
error, sstrerror(error));
|
||||
sclose(sock);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
if(got_exit_signal) {
|
||||
logmsg("signalled to die, exiting...");
|
||||
sclose(sock);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
totdelay += delay;
|
||||
delay *= 2; /* double the sleep for next attempt */
|
||||
}
|
||||
}
|
||||
} while(rc && maxretr--);
|
||||
|
||||
if(rc) {
|
||||
logmsg("setsockopt(SO_REUSEADDR) failed %d times in %d ms. Error (%d) %s",
|
||||
attempt, totdelay, error, strerror(error));
|
||||
logmsg("Continuing anyway...");
|
||||
}
|
||||
|
||||
/* When the specified listener port is zero, it is actually a
|
||||
request to let the system choose a non-zero available port. */
|
||||
|
||||
#ifdef USE_IPV6
|
||||
if(!use_ipv6) {
|
||||
#endif
|
||||
memset(&listener.sa4, 0, sizeof(listener.sa4));
|
||||
listener.sa4.sin_family = AF_INET;
|
||||
listener.sa4.sin_addr.s_addr = INADDR_ANY;
|
||||
listener.sa4.sin_port = htons(*listenport);
|
||||
rc = bind(sock, &listener.sa, sizeof(listener.sa4));
|
||||
#ifdef USE_IPV6
|
||||
}
|
||||
else {
|
||||
memset(&listener.sa6, 0, sizeof(listener.sa6));
|
||||
listener.sa6.sin6_family = AF_INET6;
|
||||
listener.sa6.sin6_addr = in6addr_any;
|
||||
listener.sa6.sin6_port = htons(*listenport);
|
||||
rc = bind(sock, &listener.sa, sizeof(listener.sa6));
|
||||
}
|
||||
#endif /* USE_IPV6 */
|
||||
if(rc) {
|
||||
error = SOCKERRNO;
|
||||
logmsg("Error binding socket on port %hu (%d) %s",
|
||||
*listenport, error, sstrerror(error));
|
||||
sclose(sock);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
|
||||
if(!*listenport) {
|
||||
/* 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 USE_IPV6
|
||||
if(!use_ipv6)
|
||||
#endif
|
||||
la_size = sizeof(localaddr.sa4);
|
||||
#ifdef USE_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, sstrerror(error));
|
||||
sclose(sock);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
switch(localaddr.sa.sa_family) {
|
||||
case AF_INET:
|
||||
*listenport = ntohs(localaddr.sa4.sin_port);
|
||||
break;
|
||||
#ifdef USE_IPV6
|
||||
case AF_INET6:
|
||||
*listenport = ntohs(localaddr.sa6.sin6_port);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(!*listenport) {
|
||||
/* 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);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
}
|
||||
|
||||
/* bindonly option forces no listening */
|
||||
if(bind_only) {
|
||||
logmsg("instructed to bind port without listening");
|
||||
return sock;
|
||||
}
|
||||
|
||||
/* start accepting connections */
|
||||
rc = listen(sock, 5);
|
||||
if(0 != rc) {
|
||||
error = SOCKERRNO;
|
||||
logmsg("listen(%ld, 5) failed with error (%d) %s",
|
||||
(long)sock, error, sstrerror(error));
|
||||
sclose(sock);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
|
||||
static int test_mqttd(int argc, char *argv[])
|
||||
{
|
||||
curl_socket_t sock = CURL_SOCKET_BAD;
|
||||
|
|
@ -912,16 +769,16 @@ static int test_mqttd(int argc, char *argv[])
|
|||
}
|
||||
else if(!strcmp("--ipv6", argv[arg])) {
|
||||
#ifdef USE_IPV6
|
||||
socket_domain = AF_INET6;
|
||||
ipv_inuse = "IPv6";
|
||||
use_ipv6 = TRUE;
|
||||
#endif
|
||||
arg++;
|
||||
}
|
||||
else if(!strcmp("--ipv4", argv[arg])) {
|
||||
/* for completeness, we support this option as well */
|
||||
#ifdef USE_IPV6
|
||||
socket_domain = AF_INET;
|
||||
ipv_inuse = "IPv4";
|
||||
use_ipv6 = FALSE;
|
||||
#endif
|
||||
arg++;
|
||||
}
|
||||
|
|
@ -969,14 +826,7 @@ static int test_mqttd(int argc, char *argv[])
|
|||
|
||||
install_signal_handlers(FALSE);
|
||||
|
||||
#ifdef USE_IPV6
|
||||
if(!use_ipv6)
|
||||
#endif
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
#ifdef USE_IPV6
|
||||
else
|
||||
sock = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
#endif
|
||||
sock = socket(socket_domain, SOCK_STREAM, 0);
|
||||
|
||||
if(CURL_SOCKET_BAD == sock) {
|
||||
error = SOCKERRNO;
|
||||
|
|
@ -986,7 +836,7 @@ static int test_mqttd(int argc, char *argv[])
|
|||
|
||||
{
|
||||
/* passive daemon style */
|
||||
sock = mqttd_sockdaemon(sock, &server_port, FALSE);
|
||||
sock = sockdaemon(sock, &server_port, NULL, FALSE);
|
||||
if(CURL_SOCKET_BAD == sock) {
|
||||
goto mqttd_cleanup;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1127,7 +1127,7 @@ static int test_rtspd(int argc, char *argv[])
|
|||
rc = bind(sock, &me.sa, sizeof(me.sa6));
|
||||
}
|
||||
#endif /* USE_IPV6 */
|
||||
if(0 != rc) {
|
||||
if(rc) {
|
||||
error = SOCKERRNO;
|
||||
logmsg("Error binding socket on port %hu (%d) %s",
|
||||
port, error, sstrerror(error));
|
||||
|
|
@ -1181,7 +1181,7 @@ static int test_rtspd(int argc, char *argv[])
|
|||
|
||||
/* start accepting connections */
|
||||
rc = listen(sock, 5);
|
||||
if(0 != rc) {
|
||||
if(rc) {
|
||||
error = SOCKERRNO;
|
||||
logmsg("listen() failed with error (%d) %s",
|
||||
error, sstrerror(error));
|
||||
|
|
|
|||
|
|
@ -554,6 +554,7 @@ static unsigned int WINAPI select_ws_wait_thread(void *lpParameter)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static HANDLE select_ws_wait(HANDLE handle, HANDLE signal, HANDLE abort)
|
||||
{
|
||||
typedef uintptr_t curl_win_thread_handle_t;
|
||||
|
|
@ -578,6 +579,7 @@ static HANDLE select_ws_wait(HANDLE handle, HANDLE signal, HANDLE abort)
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct select_ws_data {
|
||||
int fd; /* provided file descriptor (indexed by nfd) */
|
||||
long wsastate; /* internal pre-select state (indexed by nfd) */
|
||||
|
|
@ -586,6 +588,7 @@ struct select_ws_data {
|
|||
HANDLE signal; /* internal thread signal (indexed by nth) */
|
||||
HANDLE thread; /* internal thread handle (indexed by nth) */
|
||||
};
|
||||
|
||||
static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
|
||||
fd_set *exceptfds, struct timeval *tv)
|
||||
{
|
||||
|
|
@ -1206,149 +1209,6 @@ static bool juggle(curl_socket_t *sockfdp,
|
|||
#endif
|
||||
}
|
||||
|
||||
static curl_socket_t sockfilt_sockdaemon(curl_socket_t sock,
|
||||
unsigned short *listenport,
|
||||
bool bind_only)
|
||||
{
|
||||
/* passive daemon style */
|
||||
srvr_sockaddr_union_t listener;
|
||||
int flag;
|
||||
int rc;
|
||||
int totdelay = 0;
|
||||
int maxretr = 10;
|
||||
int delay = 20;
|
||||
int attempt = 0;
|
||||
int error = 0;
|
||||
|
||||
do {
|
||||
attempt++;
|
||||
flag = 1;
|
||||
rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
(void *)&flag, sizeof(flag));
|
||||
if(rc) {
|
||||
error = SOCKERRNO;
|
||||
logmsg("setsockopt(SO_REUSEADDR) failed with error (%d) %s",
|
||||
error, sstrerror(error));
|
||||
if(maxretr) {
|
||||
rc = curlx_wait_ms(delay);
|
||||
if(rc) {
|
||||
/* should not happen */
|
||||
error = SOCKERRNO;
|
||||
logmsg("curlx_wait_ms() failed with error (%d) %s",
|
||||
error, sstrerror(error));
|
||||
sclose(sock);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
if(got_exit_signal) {
|
||||
logmsg("signalled to die, exiting...");
|
||||
sclose(sock);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
totdelay += delay;
|
||||
delay *= 2; /* double the sleep for next attempt */
|
||||
}
|
||||
}
|
||||
} while(rc && maxretr--);
|
||||
|
||||
if(rc) {
|
||||
logmsg("setsockopt(SO_REUSEADDR) failed %d times in %d ms. Error (%d) %s",
|
||||
attempt, totdelay, error, strerror(error));
|
||||
logmsg("Continuing anyway...");
|
||||
}
|
||||
|
||||
/* When the specified listener port is zero, it is actually a
|
||||
request to let the system choose a non-zero available port. */
|
||||
|
||||
#ifdef USE_IPV6
|
||||
if(!use_ipv6) {
|
||||
#endif
|
||||
memset(&listener.sa4, 0, sizeof(listener.sa4));
|
||||
listener.sa4.sin_family = AF_INET;
|
||||
listener.sa4.sin_addr.s_addr = INADDR_ANY;
|
||||
listener.sa4.sin_port = htons(*listenport);
|
||||
rc = bind(sock, &listener.sa, sizeof(listener.sa4));
|
||||
#ifdef USE_IPV6
|
||||
}
|
||||
else {
|
||||
memset(&listener.sa6, 0, sizeof(listener.sa6));
|
||||
listener.sa6.sin6_family = AF_INET6;
|
||||
listener.sa6.sin6_addr = in6addr_any;
|
||||
listener.sa6.sin6_port = htons(*listenport);
|
||||
rc = bind(sock, &listener.sa, sizeof(listener.sa6));
|
||||
}
|
||||
#endif /* USE_IPV6 */
|
||||
if(rc) {
|
||||
error = SOCKERRNO;
|
||||
logmsg("Error binding socket on port %hu (%d) %s",
|
||||
*listenport, error, sstrerror(error));
|
||||
sclose(sock);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
|
||||
if(!*listenport) {
|
||||
/* 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 USE_IPV6
|
||||
if(!use_ipv6)
|
||||
#endif
|
||||
la_size = sizeof(localaddr.sa4);
|
||||
#ifdef USE_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, sstrerror(error));
|
||||
sclose(sock);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
switch(localaddr.sa.sa_family) {
|
||||
case AF_INET:
|
||||
*listenport = ntohs(localaddr.sa4.sin_port);
|
||||
break;
|
||||
#ifdef USE_IPV6
|
||||
case AF_INET6:
|
||||
*listenport = ntohs(localaddr.sa6.sin6_port);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(!*listenport) {
|
||||
/* 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);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
}
|
||||
|
||||
/* bindonly option forces no listening */
|
||||
if(bind_only) {
|
||||
logmsg("instructed to bind port without listening");
|
||||
return sock;
|
||||
}
|
||||
|
||||
/* start accepting connections */
|
||||
rc = listen(sock, 5);
|
||||
if(0 != rc) {
|
||||
error = SOCKERRNO;
|
||||
logmsg("listen() failed with error (%d) %s",
|
||||
error, sstrerror(error));
|
||||
sclose(sock);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
|
||||
static int test_sockfilt(int argc, char *argv[])
|
||||
{
|
||||
srvr_sockaddr_union_t me;
|
||||
|
|
@ -1399,16 +1259,16 @@ static int test_sockfilt(int argc, char *argv[])
|
|||
}
|
||||
else if(!strcmp("--ipv6", argv[arg])) {
|
||||
#ifdef USE_IPV6
|
||||
socket_domain = AF_INET6;
|
||||
ipv_inuse = "IPv6";
|
||||
use_ipv6 = TRUE;
|
||||
#endif
|
||||
arg++;
|
||||
}
|
||||
else if(!strcmp("--ipv4", argv[arg])) {
|
||||
/* for completeness, we support this option as well */
|
||||
#ifdef USE_IPV6
|
||||
socket_domain = AF_INET;
|
||||
ipv_inuse = "IPv4";
|
||||
use_ipv6 = FALSE;
|
||||
#endif
|
||||
arg++;
|
||||
}
|
||||
|
|
@ -1478,14 +1338,7 @@ static int test_sockfilt(int argc, char *argv[])
|
|||
|
||||
install_signal_handlers(false);
|
||||
|
||||
#ifdef USE_IPV6
|
||||
if(!use_ipv6)
|
||||
#endif
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
#ifdef USE_IPV6
|
||||
else
|
||||
sock = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
#endif
|
||||
sock = socket(socket_domain, SOCK_STREAM, 0);
|
||||
|
||||
if(CURL_SOCKET_BAD == sock) {
|
||||
error = SOCKERRNO;
|
||||
|
|
@ -1497,31 +1350,33 @@ static int test_sockfilt(int argc, char *argv[])
|
|||
if(server_connectport) {
|
||||
/* Active mode, we should connect to the given port number */
|
||||
mode = ACTIVE;
|
||||
#ifdef USE_IPV6
|
||||
if(!use_ipv6) {
|
||||
#endif
|
||||
memset(&me.sa4, 0, sizeof(me.sa4));
|
||||
me.sa4.sin_family = AF_INET;
|
||||
me.sa4.sin_port = htons(server_connectport);
|
||||
me.sa4.sin_addr.s_addr = INADDR_ANY;
|
||||
if(!addr)
|
||||
addr = "127.0.0.1";
|
||||
curlx_inet_pton(AF_INET, addr, &me.sa4.sin_addr);
|
||||
switch(socket_domain) {
|
||||
case AF_INET:
|
||||
memset(&me.sa4, 0, sizeof(me.sa4));
|
||||
me.sa4.sin_family = AF_INET;
|
||||
me.sa4.sin_port = htons(server_connectport);
|
||||
me.sa4.sin_addr.s_addr = INADDR_ANY;
|
||||
if(!addr)
|
||||
addr = "127.0.0.1";
|
||||
curlx_inet_pton(AF_INET, addr, &me.sa4.sin_addr);
|
||||
|
||||
rc = connect(sock, &me.sa, sizeof(me.sa4));
|
||||
rc = connect(sock, &me.sa, sizeof(me.sa4));
|
||||
break;
|
||||
#ifdef USE_IPV6
|
||||
}
|
||||
else {
|
||||
memset(&me.sa6, 0, sizeof(me.sa6));
|
||||
me.sa6.sin6_family = AF_INET6;
|
||||
me.sa6.sin6_port = htons(server_connectport);
|
||||
if(!addr)
|
||||
addr = "::1";
|
||||
curlx_inet_pton(AF_INET6, addr, &me.sa6.sin6_addr);
|
||||
case AF_INET6:
|
||||
memset(&me.sa6, 0, sizeof(me.sa6));
|
||||
me.sa6.sin6_family = AF_INET6;
|
||||
me.sa6.sin6_port = htons(server_connectport);
|
||||
if(!addr)
|
||||
addr = "::1";
|
||||
curlx_inet_pton(AF_INET6, addr, &me.sa6.sin6_addr);
|
||||
|
||||
rc = connect(sock, &me.sa, sizeof(me.sa6));
|
||||
}
|
||||
rc = connect(sock, &me.sa, sizeof(me.sa6));
|
||||
break;
|
||||
#endif /* USE_IPV6 */
|
||||
default:
|
||||
rc = 1;
|
||||
}
|
||||
if(rc) {
|
||||
error = SOCKERRNO;
|
||||
logmsg("Error connecting to port %hu (%d) %s",
|
||||
|
|
@ -1534,7 +1389,7 @@ static int test_sockfilt(int argc, char *argv[])
|
|||
}
|
||||
else {
|
||||
/* passive daemon style */
|
||||
sock = sockfilt_sockdaemon(sock, &server_port, s_bind_only);
|
||||
sock = sockdaemon(sock, &server_port, NULL, s_bind_only);
|
||||
if(CURL_SOCKET_BAD == sock) {
|
||||
write_stdout("FAIL\n", 5);
|
||||
goto sockfilt_cleanup;
|
||||
|
|
|
|||
|
|
@ -730,166 +730,6 @@ static bool socksd_incoming(curl_socket_t listenfd)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static curl_socket_t socksd_sockdaemon(curl_socket_t sock,
|
||||
unsigned short *listenport,
|
||||
const char *unix_socket,
|
||||
bool bind_only)
|
||||
{
|
||||
/* passive daemon style */
|
||||
srvr_sockaddr_union_t listener;
|
||||
int flag;
|
||||
int rc;
|
||||
int totdelay = 0;
|
||||
int maxretr = 10;
|
||||
int delay = 20;
|
||||
int attempt = 0;
|
||||
int error = 0;
|
||||
|
||||
#ifndef USE_UNIX_SOCKETS
|
||||
(void)unix_socket;
|
||||
#endif
|
||||
|
||||
do {
|
||||
attempt++;
|
||||
flag = 1;
|
||||
rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
(void *)&flag, sizeof(flag));
|
||||
if(rc) {
|
||||
error = SOCKERRNO;
|
||||
logmsg("setsockopt(SO_REUSEADDR) failed with error (%d) %s",
|
||||
error, sstrerror(error));
|
||||
if(maxretr) {
|
||||
rc = curlx_wait_ms(delay);
|
||||
if(rc) {
|
||||
/* should not happen */
|
||||
error = SOCKERRNO;
|
||||
logmsg("curlx_wait_ms() failed with error (%d) %s",
|
||||
error, sstrerror(error));
|
||||
sclose(sock);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
if(got_exit_signal) {
|
||||
logmsg("signalled to die, exiting...");
|
||||
sclose(sock);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
totdelay += delay;
|
||||
delay *= 2; /* double the sleep for next attempt */
|
||||
}
|
||||
}
|
||||
} while(rc && maxretr--);
|
||||
|
||||
if(rc) {
|
||||
logmsg("setsockopt(SO_REUSEADDR) failed %d times in %d ms. Error (%d) %s",
|
||||
attempt, totdelay, error, strerror(error));
|
||||
logmsg("Continuing anyway...");
|
||||
}
|
||||
|
||||
/* When the specified listener port is zero, it is actually a
|
||||
request to let the system choose a non-zero available port. */
|
||||
|
||||
switch(socket_domain) {
|
||||
case AF_INET:
|
||||
memset(&listener.sa4, 0, sizeof(listener.sa4));
|
||||
listener.sa4.sin_family = AF_INET;
|
||||
listener.sa4.sin_addr.s_addr = INADDR_ANY;
|
||||
listener.sa4.sin_port = htons(*listenport);
|
||||
rc = bind(sock, &listener.sa, sizeof(listener.sa4));
|
||||
break;
|
||||
#ifdef USE_IPV6
|
||||
case AF_INET6:
|
||||
memset(&listener.sa6, 0, sizeof(listener.sa6));
|
||||
listener.sa6.sin6_family = AF_INET6;
|
||||
listener.sa6.sin6_addr = in6addr_any;
|
||||
listener.sa6.sin6_port = htons(*listenport);
|
||||
rc = bind(sock, &listener.sa, sizeof(listener.sa6));
|
||||
break;
|
||||
#endif /* USE_IPV6 */
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
case AF_UNIX:
|
||||
rc = bind_unix_socket(sock, unix_socket, &listener.sau);
|
||||
#endif
|
||||
}
|
||||
|
||||
if(rc) {
|
||||
error = SOCKERRNO;
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
if(socket_domain == AF_UNIX)
|
||||
logmsg("Error binding socket on path %s (%d) %s",
|
||||
unix_socket, error, sstrerror(error));
|
||||
else
|
||||
#endif
|
||||
logmsg("Error binding socket on port %hu (%d) %s",
|
||||
*listenport, error, sstrerror(error));
|
||||
sclose(sock);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
|
||||
if(!*listenport
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
&& !unix_socket
|
||||
#endif
|
||||
) {
|
||||
/* 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 USE_IPV6
|
||||
if(socket_domain == AF_INET6)
|
||||
la_size = sizeof(localaddr.sa6);
|
||||
else
|
||||
#endif
|
||||
la_size = sizeof(localaddr.sa4);
|
||||
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, sstrerror(error));
|
||||
sclose(sock);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
switch(localaddr.sa.sa_family) {
|
||||
case AF_INET:
|
||||
*listenport = ntohs(localaddr.sa4.sin_port);
|
||||
break;
|
||||
#ifdef USE_IPV6
|
||||
case AF_INET6:
|
||||
*listenport = ntohs(localaddr.sa6.sin6_port);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(!*listenport) {
|
||||
/* 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);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
}
|
||||
|
||||
/* bindonly option forces no listening */
|
||||
if(bind_only) {
|
||||
logmsg("instructed to bind port without listening");
|
||||
return sock;
|
||||
}
|
||||
|
||||
/* start accepting connections */
|
||||
rc = listen(sock, 5);
|
||||
if(0 != rc) {
|
||||
error = SOCKERRNO;
|
||||
logmsg("listen() failed with error (%d) %s", error, sstrerror(error));
|
||||
sclose(sock);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
|
||||
static int test_socksd(int argc, char *argv[])
|
||||
{
|
||||
curl_socket_t sock = CURL_SOCKET_BAD;
|
||||
|
|
@ -1038,7 +878,7 @@ static int test_socksd(int argc, char *argv[])
|
|||
|
||||
{
|
||||
/* passive daemon style */
|
||||
sock = socksd_sockdaemon(sock, &server_port, unix_socket, FALSE);
|
||||
sock = sockdaemon(sock, &server_port, unix_socket, FALSE);
|
||||
if(CURL_SOCKET_BAD == sock) {
|
||||
goto socks5_cleanup;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2200,7 +2200,7 @@ static int test_sws(int argc, char *argv[])
|
|||
rc = bind_unix_socket(sock, unix_socket, &me.sau);
|
||||
#endif /* USE_UNIX_SOCKETS */
|
||||
}
|
||||
if(0 != rc) {
|
||||
if(rc) {
|
||||
error = SOCKERRNO;
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
if(socket_domain == AF_UNIX)
|
||||
|
|
@ -2266,7 +2266,7 @@ static int test_sws(int argc, char *argv[])
|
|||
|
||||
/* start accepting connections */
|
||||
rc = listen(sock, 50);
|
||||
if(0 != rc) {
|
||||
if(rc) {
|
||||
error = SOCKERRNO;
|
||||
logmsg("listen() failed with error (%d) %s", error, sstrerror(error));
|
||||
goto sws_cleanup;
|
||||
|
|
|
|||
|
|
@ -689,7 +689,7 @@ static int test_tftpd(int argc, char **argv)
|
|||
rc = bind(sock, &me.sa, sizeof(me.sa6));
|
||||
}
|
||||
#endif /* USE_IPV6 */
|
||||
if(0 != rc) {
|
||||
if(rc) {
|
||||
error = SOCKERRNO;
|
||||
logmsg("Error binding socket on port %hu (%d) %s", port, error,
|
||||
sstrerror(error));
|
||||
|
|
|
|||
|
|
@ -707,7 +707,7 @@ int bind_unix_socket(curl_socket_t sock, const char *unix_socket,
|
|||
}
|
||||
strcpy(sau->sun_path, unix_socket);
|
||||
rc = bind(sock, (struct sockaddr*)sau, sizeof(struct sockaddr_un));
|
||||
if(0 != rc && SOCKERRNO == SOCKEADDRINUSE) {
|
||||
if(rc && SOCKERRNO == SOCKEADDRINUSE) {
|
||||
struct_stat statbuf;
|
||||
/* socket already exists. Perhaps it is stale? */
|
||||
curl_socket_t unixfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
|
@ -720,7 +720,7 @@ int bind_unix_socket(curl_socket_t sock, const char *unix_socket,
|
|||
rc = connect(unixfd, (struct sockaddr*)sau, sizeof(struct sockaddr_un));
|
||||
error = SOCKERRNO;
|
||||
sclose(unixfd);
|
||||
if(0 != rc && SOCKECONNREFUSED != error) {
|
||||
if(rc && error != SOCKECONNREFUSED) {
|
||||
logmsg("Failed to connect to %s (%d) %s",
|
||||
unix_socket, error, sstrerror(error));
|
||||
return rc;
|
||||
|
|
@ -732,7 +732,7 @@ int bind_unix_socket(curl_socket_t sock, const char *unix_socket,
|
|||
#else
|
||||
rc = lstat(unix_socket, &statbuf);
|
||||
#endif
|
||||
if(0 != rc) {
|
||||
if(rc) {
|
||||
logmsg("Error binding socket, failed to stat %s (%d) %s",
|
||||
unix_socket, errno, strerror(errno));
|
||||
return rc;
|
||||
|
|
@ -745,7 +745,7 @@ int bind_unix_socket(curl_socket_t sock, const char *unix_socket,
|
|||
#endif
|
||||
/* dead socket, cleanup and retry bind */
|
||||
rc = unlink(unix_socket);
|
||||
if(0 != rc) {
|
||||
if(rc) {
|
||||
logmsg("Error binding socket, failed to unlink %s (%d) %s",
|
||||
unix_socket, errno, strerror(errno));
|
||||
return rc;
|
||||
|
|
@ -777,3 +777,166 @@ unsigned short util_ultous(unsigned long ulnum)
|
|||
# pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
curl_socket_t sockdaemon(curl_socket_t sock,
|
||||
unsigned short *listenport,
|
||||
const char *unix_socket,
|
||||
bool bind_only)
|
||||
{
|
||||
/* passive daemon style */
|
||||
srvr_sockaddr_union_t listener;
|
||||
int flag;
|
||||
int rc;
|
||||
int totdelay = 0;
|
||||
int maxretr = 10;
|
||||
int delay = 20;
|
||||
int attempt = 0;
|
||||
int error = 0;
|
||||
|
||||
#ifndef USE_UNIX_SOCKETS
|
||||
(void)unix_socket;
|
||||
#endif
|
||||
|
||||
do {
|
||||
attempt++;
|
||||
flag = 1;
|
||||
rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
(void *)&flag, sizeof(flag));
|
||||
if(rc) {
|
||||
error = SOCKERRNO;
|
||||
logmsg("setsockopt(SO_REUSEADDR) failed with error (%d) %s",
|
||||
error, sstrerror(error));
|
||||
if(maxretr) {
|
||||
rc = curlx_wait_ms(delay);
|
||||
if(rc) {
|
||||
/* should not happen */
|
||||
error = SOCKERRNO;
|
||||
logmsg("curlx_wait_ms() failed with error (%d) %s",
|
||||
error, sstrerror(error));
|
||||
sclose(sock);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
if(got_exit_signal) {
|
||||
logmsg("signalled to die, exiting...");
|
||||
sclose(sock);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
totdelay += delay;
|
||||
delay *= 2; /* double the sleep for next attempt */
|
||||
}
|
||||
}
|
||||
} while(rc && maxretr--);
|
||||
|
||||
if(rc) {
|
||||
logmsg("setsockopt(SO_REUSEADDR) failed %d times in %d ms. Error (%d) %s",
|
||||
attempt, totdelay, error, strerror(error));
|
||||
logmsg("Continuing anyway...");
|
||||
}
|
||||
|
||||
/* When the specified listener port is zero, it is actually a
|
||||
request to let the system choose a non-zero available port. */
|
||||
|
||||
switch(socket_domain) {
|
||||
case AF_INET:
|
||||
memset(&listener.sa4, 0, sizeof(listener.sa4));
|
||||
listener.sa4.sin_family = AF_INET;
|
||||
listener.sa4.sin_addr.s_addr = INADDR_ANY;
|
||||
listener.sa4.sin_port = htons(*listenport);
|
||||
rc = bind(sock, &listener.sa, sizeof(listener.sa4));
|
||||
break;
|
||||
#ifdef USE_IPV6
|
||||
case AF_INET6:
|
||||
memset(&listener.sa6, 0, sizeof(listener.sa6));
|
||||
listener.sa6.sin6_family = AF_INET6;
|
||||
listener.sa6.sin6_addr = in6addr_any;
|
||||
listener.sa6.sin6_port = htons(*listenport);
|
||||
rc = bind(sock, &listener.sa, sizeof(listener.sa6));
|
||||
break;
|
||||
#endif /* USE_IPV6 */
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
case AF_UNIX:
|
||||
rc = bind_unix_socket(sock, unix_socket, &listener.sau);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
if(rc) {
|
||||
error = SOCKERRNO;
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
if(socket_domain == AF_UNIX)
|
||||
logmsg("Error binding socket on path %s (%d) %s",
|
||||
unix_socket, error, sstrerror(error));
|
||||
else
|
||||
#endif
|
||||
logmsg("Error binding socket on port %hu (%d) %s",
|
||||
*listenport, error, sstrerror(error));
|
||||
sclose(sock);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
|
||||
if(!*listenport
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
&& !unix_socket
|
||||
#endif
|
||||
) {
|
||||
/* 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 USE_IPV6
|
||||
if(socket_domain == AF_INET6)
|
||||
la_size = sizeof(localaddr.sa6);
|
||||
else
|
||||
#endif
|
||||
la_size = sizeof(localaddr.sa4);
|
||||
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, sstrerror(error));
|
||||
sclose(sock);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
switch(localaddr.sa.sa_family) {
|
||||
case AF_INET:
|
||||
*listenport = ntohs(localaddr.sa4.sin_port);
|
||||
break;
|
||||
#ifdef USE_IPV6
|
||||
case AF_INET6:
|
||||
*listenport = ntohs(localaddr.sa6.sin6_port);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(!*listenport) {
|
||||
/* 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);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
}
|
||||
|
||||
/* bindonly option forces no listening */
|
||||
if(bind_only) {
|
||||
logmsg("instructed to bind port without listening");
|
||||
return sock;
|
||||
}
|
||||
|
||||
/* start accepting connections */
|
||||
rc = listen(sock, 5);
|
||||
if(rc) {
|
||||
error = SOCKERRNO;
|
||||
logmsg("listen(%ld, 5) failed with error (%d) %s",
|
||||
(long)sock, error, sstrerror(error));
|
||||
sclose(sock);
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue