aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/server/sockfilt.c106
-rw-r--r--tests/server/util.c75
-rw-r--r--tests/server/util.h4
3 files changed, 113 insertions, 72 deletions
diff --git a/tests/server/sockfilt.c b/tests/server/sockfilt.c
index 7c3404c1f..042b9f531 100644
--- a/tests/server/sockfilt.c
+++ b/tests/server/sockfilt.c
@@ -143,7 +143,7 @@ static void sigpipe_handler(int sig)
}
#endif
-char use_ipv6=FALSE;
+bool use_ipv6=FALSE;
unsigned short port = DEFAULT_PORT;
unsigned short connectport = 0; /* if non-zero, we activate this mode */
@@ -427,25 +427,43 @@ static curl_socket_t sockdaemon(curl_socket_t sock,
#endif /* ENABLE_IPV6 */
int flag = 1;
int rc;
- int maxretr = 12;
- int delay= 10;
-
- rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
- (void *)&flag, sizeof(flag));
- while ((rc < 0) && maxretr) {
- maxretr--;
- go_sleep(delay);
- delay *= 2; /* double the sleep for next attempt */
+ int totdelay = 0;
+ int maxretr = 10;
+ int delay= 20;
+ int attempt = 0;
+ int error = 0;
+
+ do {
+ attempt++;
rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(void *)&flag, sizeof(flag));
- }
- if (rc < 0) {
- perror("setsockopt(SO_REUSEADDR)");
+ if(rc) {
+ error = SOCKERRNO;
+ if(maxretr) {
+ rc = wait_ms(delay);
+ if(rc) {
+ /* should not happen */
+ error = SOCKERRNO;
+ logmsg("wait_ms() failed: (%d) %s", error, strerror(error));
+ 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...");
}
#ifdef ENABLE_IPV6
if(!use_ipv6) {
#endif
+ memset(&me, 0, sizeof(me));
me.sin_family = AF_INET;
me.sin_addr.s_addr = INADDR_ANY;
me.sin_port = htons(*listenport);
@@ -453,16 +471,17 @@ static curl_socket_t sockdaemon(curl_socket_t sock,
#ifdef ENABLE_IPV6
}
else {
- memset(&me6, 0, sizeof(struct sockaddr_in6));
+ memset(&me6, 0, sizeof(me6));
me6.sin6_family = AF_INET6;
me6.sin6_addr = in6addr_any;
me6.sin6_port = htons(*listenport);
rc = bind(sock, (struct sockaddr *) &me6, sizeof(me6));
}
#endif /* ENABLE_IPV6 */
- if(rc < 0) {
- perror("binding stream socket");
- logmsg("Error binding socket");
+ if(rc) {
+ error = SOCKERRNO;
+ logmsg("Error binding socket: (%d) %s", error, strerror(error));
+ sclose(sock);
return CURL_SOCKET_BAD;
}
@@ -475,16 +494,21 @@ static curl_socket_t sockdaemon(curl_socket_t sock,
if(getsockname(sock, (struct sockaddr *) &add,
&socksize)<0) {
- logmsg("getsockname() failed with error: %d", SOCKERRNO);
+ error = SOCKERRNO;
+ logmsg("getsockname() failed with error: (%d) %s",
+ error, strerror(error));
+ sclose(sock);
return CURL_SOCKET_BAD;
}
*listenport = ntohs(add.sin_port);
}
/* start accepting connections */
- rc = listen(sock, 4);
+ rc = listen(sock, 5);
if(0 != rc) {
- logmsg("listen() failed with error: %d", SOCKERRNO);
+ error = SOCKERRNO;
+ logmsg("listen() failed with error: (%d) %s",
+ error, strerror(error));
sclose(sock);
return CURL_SOCKET_BAD;
}
@@ -492,28 +516,6 @@ static curl_socket_t sockdaemon(curl_socket_t sock,
return sock;
}
-static curl_socket_t mksock(bool ipv6)
-{
- curl_socket_t sock;
-#ifdef ENABLE_IPV6
- if(!ipv6)
-#else
- (void)ipv6;
-#endif
- sock = socket(AF_INET, SOCK_STREAM, 0);
-#ifdef ENABLE_IPV6
- else
- sock = socket(AF_INET6, SOCK_STREAM, 0);
-#endif
-
- if (CURL_SOCKET_BAD == sock) {
- perror("opening stream socket");
- logmsg("Error opening socket");
- }
-
- return sock;
-}
-
int main(int argc, char *argv[])
{
@@ -616,10 +618,19 @@ int main(int argc, char *argv[])
#endif
#endif
+#ifdef ENABLE_IPV6
+ if(!use_ipv6)
+#endif
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+#ifdef ENABLE_IPV6
+ else
+ sock = socket(AF_INET6, SOCK_STREAM, 0);
+#endif
- sock = mksock(use_ipv6);
- if (CURL_SOCKET_BAD == sock) {
- logmsg("Error opening socket: %d", SOCKERRNO);
+ if(CURL_SOCKET_BAD == sock) {
+ error = SOCKERRNO;
+ logmsg("Error creating socket: (%d) %s",
+ error, strerror(error));
return 1;
}
@@ -652,8 +663,9 @@ int main(int argc, char *argv[])
}
#endif /* ENABLE_IPV6 */
if(rc) {
- perror("connecting stream socket");
- logmsg("Error connecting to port %d", port);
+ error = SOCKERRNO;
+ logmsg("Error connecting to port %d: (%d) %s",
+ port, error, strerror(error));
sclose(sock);
return 1;
}
diff --git a/tests/server/util.c b/tests/server/util.c
index 95f8c521e..15a4e60e1 100644
--- a/tests/server/util.c
+++ b/tests/server/util.c
@@ -165,31 +165,60 @@ char *test2file(long testno)
return filename;
}
-void go_sleep(long ms)
+/*
+ * Portable function used for waiting a specific amount of ms.
+ * Waiting indefinitely with this function is not allowed, a
+ * zero or negative timeout value will return immediately.
+ *
+ * Return values:
+ * -1 = system call error, or invalid timeout value
+ * 0 = specified timeout has elapsed
+ */
+int wait_ms(int timeout_ms)
{
-#ifdef HAVE_POLL_FINE
- /* portable subsecond "sleep" */
- poll((void *)0, 0, (int)ms);
-#else
- /* systems without poll() need other solutions */
-
-#ifdef WIN32
- /* Windows offers a millisecond sleep */
- Sleep(ms);
-#elif defined(MSDOS)
- delay(ms);
-#else
- /* Other systems must use select() for this */
- struct timeval timeout;
-
- timeout.tv_sec = ms/1000;
- ms = ms%1000;
- timeout.tv_usec = ms * 1000;
-
- select(0, NULL, NULL, NULL, &timeout);
+#if !defined(MSDOS) && !defined(USE_WINSOCK)
+#ifndef HAVE_POLL_FINE
+ struct timeval pending_tv;
#endif
-
+ struct timeval initial_tv;
+ int pending_ms;
+ int error;
#endif
-}
+ int r = 0;
+ if(!timeout_ms)
+ return 0;
+ if(timeout_ms < 0) {
+ SET_SOCKERRNO(EINVAL);
+ return -1;
+ }
+#if defined(MSDOS)
+ delay(timeout_ms);
+#elif defined(USE_WINSOCK)
+ Sleep(timeout_ms);
+#else
+ pending_ms = timeout_ms;
+ initial_tv = curlx_tvnow();
+ do {
+#if defined(HAVE_POLL_FINE)
+ r = poll(NULL, 0, pending_ms);
+#else
+ pending_tv.tv_sec = pending_ms / 1000;
+ pending_tv.tv_usec = (pending_ms % 1000) * 1000;
+ r = select(0, NULL, NULL, NULL, &pending_tv);
+#endif /* HAVE_POLL_FINE */
+ if(r != -1)
+ break;
+ error = SOCKERRNO;
+ if(error == EINVAL)
+ break;
+ pending_ms = timeout_ms - (int)curlx_tvdiff(curlx_tvnow(), initial_tv);
+ if(pending_ms <= 0)
+ break;
+ } while(r == -1);
+#endif /* USE_WINSOCK */
+ if(r)
+ r = -1;
+ return r;
+}
diff --git a/tests/server/util.h b/tests/server/util.h
index c1eccfadb..8c494192b 100644
--- a/tests/server/util.h
+++ b/tests/server/util.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -49,6 +49,6 @@ void win32_cleanup(void);
/* returns the path name to the test case file */
char *test2file(long testno);
-void go_sleep(long ms);
+int wait_ms(int timeout_ms);
#endif /* __SERVER_UTIL_H */