HintsDB: Support transactions with a TDB backend.
[exim.git] / test / src / server.c
index 4bdde65bf7154bfa7679e687c2b2b255ae32f3f9..8fda1d4b00ae62e27945898e0a1543669527ba79 100644 (file)
@@ -26,9 +26,10 @@ on all interfaces, unless the option -noipv6 is given. */
 #include <netinet/in_systm.h>
 #include <netinet/in.h>
 #include <netinet/ip.h>
 #include <netinet/in_systm.h>
 #include <netinet/in.h>
 #include <netinet/ip.h>
+#include <netinet/tcp.h>
 
 #ifdef HAVE_NETINET_IP_VAR_H
 
 #ifdef HAVE_NETINET_IP_VAR_H
-#include <netinet/ip_var.h>
+# include <netinet/ip_var.h>
 #endif
 
 #include <netdb.h>
 #endif
 
 #include <netdb.h>
@@ -52,6 +53,7 @@ on all interfaces, unless the option -noipv6 is given. */
 
 #ifndef CS
 # define CS (char *)
 
 #ifndef CS
 # define CS (char *)
+# define CCS (const char *)
 #endif
 
 
 #endif
 
 
@@ -61,6 +63,10 @@ typedef struct line {
   char line[1];
 } line;
 
   char line[1];
 } line;
 
+typedef unsigned BOOL;
+#define FALSE 0
+#define TRUE  1
+
 
 /*************************************************
 *            SIGALRM handler - crash out         *
 
 /*************************************************
 *            SIGALRM handler - crash out         *
@@ -153,7 +159,8 @@ putchar('\n');
 #define udn 2    /* Unix domain socket number */
 #define skn 2    /* Potential number of sockets */
 
 #define udn 2    /* Unix domain socket number */
 #define skn 2    /* Potential number of sockets */
 
-int main(int argc, char **argv)
+int
+main(int argc, char **argv)
 {
 int i;
 int port = 0;
 {
 int i;
 int port = 0;
@@ -164,7 +171,7 @@ int connection_count = 1;
 int count;
 int on = 1;
 int timeout = 5;
 int count;
 int on = 1;
 int timeout = 5;
-int initial_pause = 0;
+int initial_pause = 0, tfo = 0;
 int use_ipv4 = 1;
 int use_ipv6 = 1;
 int debug = 0;
 int use_ipv4 = 1;
 int use_ipv6 = 1;
 int debug = 0;
@@ -209,6 +216,7 @@ if (argc > 1 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")))
        "\n\t-noipv6  disable ipv6"
        "\n\t-oP file write PID to file"
        "\n\t-t n     n seconds timeout"
        "\n\t-noipv6  disable ipv6"
        "\n\t-oP file write PID to file"
        "\n\t-t n     n seconds timeout"
+       "\n\t-tfo     enable TCP Fast Open"
   );
   exit(0);
   }
   );
   exit(0);
   }
@@ -216,6 +224,7 @@ if (argc > 1 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")))
 while (na < argc && argv[na][0] == '-')
   {
   if (strcmp(argv[na], "-d") == 0) debug = 1;
 while (na < argc && argv[na][0] == '-')
   {
   if (strcmp(argv[na], "-d") == 0) debug = 1;
+  else if (strcmp(argv[na], "-tfo") == 0) tfo = 1;
   else if (strcmp(argv[na], "-t") == 0)
     {
     if (tmo_noerror = ((timeout = atoi(argv[++na])) < 0)) timeout = -timeout;
   else if (strcmp(argv[na], "-t") == 0)
     {
     if (tmo_noerror = ((timeout = atoi(argv[++na])) < 0)) timeout = -timeout;
@@ -259,7 +268,7 @@ if (na < argc) connection_count = atoi(argv[na]);
 if (initial_pause > 0)
   {
   if (debug)
 if (initial_pause > 0)
   {
   if (debug)
-    printf("%d: Inital pause of %d seconds\n", time(NULL), initial_pause);
+    printf("%ld: Inital pause of %d seconds\n", (long)time(NULL), initial_pause);
   else
     printf("Inital pause of %d seconds\n", initial_pause);
   while (initial_pause > 0)
   else
     printf("Inital pause of %d seconds\n", initial_pause);
   while (initial_pause > 0)
@@ -270,7 +279,7 @@ if (initial_pause > 0)
 
 if (port == 0)  /* Unix domain */
   {
 
 if (port == 0)  /* Unix domain */
   {
-  if (debug) printf("%d: Creating Unix domain socket\n", time(NULL));
+  if (debug) printf("%ld: Creating Unix domain socket\n", (long) time(NULL));
   listen_socket[udn] = socket(PF_UNIX, SOCK_STREAM, 0);
   if (listen_socket[udn] < 0)
     {
   listen_socket[udn] = socket(PF_UNIX, SOCK_STREAM, 0);
   if (listen_socket[udn] < 0)
     {
@@ -290,7 +299,15 @@ else
       printf("IPv6 socket creation failed: %s\n", strerror(errno));
       exit(1);
       }
       printf("IPv6 socket creation failed: %s\n", strerror(errno));
       exit(1);
       }
-
+#if defined(TCP_FASTOPEN) && !defined(__APPLE__)
+    if (tfo)
+      {
+      int backlog = 5;
+      if (setsockopt(listen_socket[v6n], IPPROTO_TCP, TCP_FASTOPEN,
+                    &backlog, sizeof(backlog)))
+       if (debug) printf("setsockopt TCP_FASTOPEN: %s\n", strerror(errno));
+      }
+#endif
     /* If this is an IPv6 wildcard socket, set IPV6_V6ONLY if that option is
     available. */
 
     /* If this is an IPv6 wildcard socket, set IPV6_V6ONLY if that option is
     available. */
 
@@ -314,6 +331,15 @@ else
       printf("IPv4 socket creation failed: %s\n", strerror(errno));
       exit(1);
       }
       printf("IPv4 socket creation failed: %s\n", strerror(errno));
       exit(1);
       }
+#if defined(TCP_FASTOPEN) && !defined(__APPLE__)
+    if (tfo)
+      {
+      int backlog = 5;
+      if (setsockopt(listen_socket[v4n], IPPROTO_TCP, TCP_FASTOPEN,
+                    &backlog, sizeof(backlog)))
+       if (debug) printf("setsockopt TCP_FASTOPEN: %s\n", strerror(errno));
+      }
+#endif
     }
   }
 
     }
   }
 
@@ -376,7 +402,7 @@ else
       sin6.sin6_addr = anyaddr6;
       if (bind(listen_socket[i], (struct sockaddr *)&sin6, sizeof(sin6)) < 0)
         {
       sin6.sin6_addr = anyaddr6;
       if (bind(listen_socket[i], (struct sockaddr *)&sin6, sizeof(sin6)) < 0)
         {
-        printf("IPv6 socket bind() failed: %s\n", strerror(errno));
+        printf("IPv6 socket bind(port %d) failed: %s\n", port, strerror(errno));
         exit(1);
         }
       }
         exit(1);
         }
       }
@@ -393,10 +419,9 @@ else
       sin4.sin_addr.s_addr = (S_ADDR_TYPE)INADDR_ANY;
       sin4.sin_port = htons(port);
       if (bind(listen_socket[i], (struct sockaddr *)&sin4, sizeof(sin4)) < 0)
       sin4.sin_addr.s_addr = (S_ADDR_TYPE)INADDR_ANY;
       sin4.sin_port = htons(port);
       if (bind(listen_socket[i], (struct sockaddr *)&sin4, sizeof(sin4)) < 0)
-        {
         if (listen_socket[v6n] < 0 || errno != EADDRINUSE)
           {
         if (listen_socket[v6n] < 0 || errno != EADDRINUSE)
           {
-          printf("IPv4 socket bind() failed: %s\n", strerror(errno));
+          printf("IPv4 socket bind(port %d) failed: %s\n", port, strerror(errno));
           exit(1);
           }
         else
           exit(1);
           }
         else
@@ -404,7 +429,6 @@ else
           close(listen_socket[i]);
           listen_socket[i] = -1;
           }
           close(listen_socket[i]);
           listen_socket[i] = -1;
           }
-        }
       }
     }
   }
       }
     }
   }
@@ -415,16 +439,21 @@ error because it means that the IPv6 socket will handle IPv4 connections. Don't
 output anything, because it will mess up the test output, which will be
 different for systems that do this and those that don't. */
 
 output anything, because it will mess up the test output, which will be
 different for systems that do this and those that don't. */
 
-for (i = 0; i <= skn; i++)
+for (i = 0; i <= skn; i++) if (listen_socket[i] >= 0)
   {
   {
-  if (listen_socket[i] >= 0 && listen(listen_socket[i], 5) < 0)
-    {
+  if (listen(listen_socket[i], 5) < 0)
     if (i != v4n || listen_socket[v6n] < 0 || errno != EADDRINUSE)
       {
       printf("listen() failed: %s\n", strerror(errno));
       exit(1);
       }
     if (i != v4n || listen_socket[v6n] < 0 || errno != EADDRINUSE)
       {
       printf("listen() failed: %s\n", strerror(errno));
       exit(1);
       }
-    }
+
+#if defined(TCP_FASTOPEN) && defined(__APPLE__)
+  if (  tfo
+     && setsockopt(listen_socket[v4n], IPPROTO_TCP, TCP_FASTOPEN, &on, sizeof(on))
+     && debug)
+      printf("setsockopt TCP_FASTOPEN: %s\n", strerror(errno));
+#endif
   }
 
 
   }
 
 
@@ -496,11 +525,10 @@ s = script;
 
 for (count = 0; count < connection_count; count++)
   {
 
 for (count = 0; count < connection_count; count++)
   {
-
   struct {
     int left;
   struct {
     int left;
-    int in_use;
-  } content_length = { .left = 0, .in_use = 0 };
+    BOOL in_use;
+  } content_length = { 0, FALSE };
 
   alarm(timeout);
   if (port <= 0)
 
   alarm(timeout);
   if (port <= 0)
@@ -527,8 +555,7 @@ for (count = 0; count < connection_count; count++)
       if (listen_socket[i] > max_socket) max_socket = listen_socket[i];
       }
 
       if (listen_socket[i] > max_socket) max_socket = listen_socket[i];
       }
 
-    lcount = select(max_socket + 1, &select_listen, NULL, NULL, NULL);
-    if (lcount < 0)
+    if ((lcount = select(max_socket + 1, &select_listen, NULL, NULL, NULL)) < 0)
       {
       printf("Select failed\n");
       fflush(stdout);
       {
       printf("Select failed\n");
       fflush(stdout);
@@ -537,7 +564,6 @@ for (count = 0; count < connection_count; count++)
 
     accept_socket = -1;
     for (i = 0; i < skn; i++)
 
     accept_socket = -1;
     for (i = 0; i < skn; i++)
-      {
       if (listen_socket[i] > 0 && FD_ISSET(listen_socket[i], &select_listen))
         {
         accept_socket = accept(listen_socket[i],
       if (listen_socket[i] > 0 && FD_ISSET(listen_socket[i], &select_listen))
         {
         accept_socket = accept(listen_socket[i],
@@ -545,7 +571,6 @@ for (count = 0; count < connection_count; count++)
         FD_CLR(listen_socket[i], &select_listen);
         break;
         }
         FD_CLR(listen_socket[i], &select_listen);
         break;
         }
-      }
     }
   alarm(0);
 
     }
   alarm(0);
 
@@ -597,7 +622,7 @@ for (count = 0; count < connection_count; count++)
   doesn't work for other tests (e.g. ident tests) so we have explicit '<' and
   '>' flags for input and output as well as the defaults. */
 
   doesn't work for other tests (e.g. ident tests) so we have explicit '<' and
   '>' flags for input and output as well as the defaults. */
 
-  for (; s != NULL; s = s->next)
+  for (; s; s = s->next)
     {
     char *ss = s->line;
 
     {
     char *ss = s->line;
 
@@ -626,7 +651,7 @@ for (count = 0; count < connection_count; count++)
         { end = "\n"; ss += 3; len -= 3; }
 
       fwrite(ss, 1, len, out);
         { end = "\n"; ss += 3; len -= 3; }
 
       fwrite(ss, 1, len, out);
-      if (*end) fprintf(out, end);
+      if (*end) fputs(end, out);
       }
 
     else if (isdigit((unsigned char)ss[0]))
       }
 
     else if (isdigit((unsigned char)ss[0]))
@@ -662,7 +687,7 @@ for (count = 0; count < connection_count; count++)
          n = dlen < sizeof(buffer) ? dlen : sizeof(buffer);
          if ((n = read(dup_accept_socket, CS buffer, n)) == 0)
            {
          n = dlen < sizeof(buffer) ? dlen : sizeof(buffer);
          if ((n = read(dup_accept_socket, CS buffer, n)) == 0)
            {
-           printf("Unxpected EOF read from client\n");
+           printf("Unexpected EOF read from client\n");
            s = s->next;
            goto END_OFF;
            }
            s = s->next;
            goto END_OFF;
            }
@@ -672,7 +697,7 @@ for (count = 0; count < connection_count; count++)
        while (dlen-- > 0)
          if (fgetc(in) == EOF)
            {
        while (dlen-- > 0)
          if (fgetc(in) == EOF)
            {
-           printf("Unxpected EOF read from client\n");
+           printf("Unexpected EOF read from client\n");
            s = s->next;
            goto END_OFF;
            }
            s = s->next;
            goto END_OFF;
            }
@@ -728,16 +753,14 @@ for (count = 0; count < connection_count; count++)
        alarm(0);
        n += offset;
 
        alarm(0);
        n += offset;
 
-       printit(buffer, n);
+       printit(CS buffer, n);
 
        if (data) do
          {
          n = (read(dup_accept_socket, &c, 1) == 1 && c == '.');
          if (content_length.in_use) content_length.left--;
          while (c != '\n' && read(dup_accept_socket, &c, 1) == 1)
 
        if (data) do
          {
          n = (read(dup_accept_socket, &c, 1) == 1 && c == '.');
          if (content_length.in_use) content_length.left--;
          while (c != '\n' && read(dup_accept_socket, &c, 1) == 1)
-            {
             if (content_length.in_use) content_length.left--;
             if (content_length.in_use) content_length.left--;
-            }
          } while (!n);
        else if (memcmp(ss, buffer, n) != 0)
          {
          } while (!n);
        else if (memcmp(ss, buffer, n) != 0)
          {
@@ -760,7 +783,7 @@ for (count = 0; count < connection_count; count++)
            goto END_OFF;
            }
          alarm(0);
            goto END_OFF;
            }
          alarm(0);
-         n = (int)strlen(CS buffer);
+         n = strlen(CS buffer);
          if (content_length.in_use) content_length.left -= (n - offset);
          while (n > 0 && isspace(buffer[n-1])) n--;
          buffer[n] = 0;
          if (content_length.in_use) content_length.left -= (n - offset);
          while (n > 0 && isspace(buffer[n-1])) n--;
          buffer[n] = 0;
@@ -776,8 +799,10 @@ for (count = 0; count < connection_count; count++)
          }
        }
 
          }
        }
 
-       if (sscanf(buffer, "<Content-length: %d", &content_length.left)) content_length.in_use = 1;
-       if (content_length.in_use && content_length.left <= 0) shutdown(dup_accept_socket, SHUT_RD);
+       if (sscanf(CCS buffer, "<Content-length: %d", &content_length.left))
+                 content_length.in_use = TRUE;
+       if (content_length.in_use && content_length.left <= 0)
+         shutdown(dup_accept_socket, SHUT_RD);
       }
     }
 
       }
     }
 
@@ -788,7 +813,7 @@ for (count = 0; count < connection_count; count++)
 
 if (s == NULL) printf("End of script\n");
 
 
 if (s == NULL) printf("End of script\n");
 
-if (sockname != NULL) unlink(sockname);
+if (sockname) unlink(sockname);
 exit(0);
 }
 
 exit(0);
 }