]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - test-suite/tcp-banger2.c
SourceFormat Enforcement
[thirdparty/squid.git] / test-suite / tcp-banger2.c
index 20d8b2b6b5050bb1303ddeb096f660dcde32e44c..b15eea4244c84c5010c096a4a5ed7f8487d2f234 100644 (file)
@@ -1,4 +1,6 @@
-#include "config.h"
+#include "squid.h"
+
+/* $Id$
 
 /*
  * On some systems, FD_SETSIZE is set to something lower than the
@@ -9,7 +11,7 @@
 #define CHANGE_FD_SETSIZE 1
 
 /* Cannot increase FD_SETSIZE on Linux */
-#if defined(_SQUID_LINUX_)
+#if _SQUID_LINUX_
 #undef CHANGE_FD_SETSIZE
 #define CHANGE_FD_SETSIZE 0
 #endif
@@ -18,7 +20,7 @@
  * to return EINVAL. */
 /* Marian Durkovic <marian@svf.stuba.sk> */
 /* Peter Wemm <peter@spinner.DIALix.COM> */
-#if defined(_SQUID_FREEBSD_)
+#if _SQUID_FREEBSD_
 #include <osreldate.h>
 #if __FreeBSD_version < 220000
 #undef CHANGE_FD_SETSIZE
 #if HAVE_UNISTD_H
 #include <unistd.h>
 #endif
-#if HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
 #if HAVE_STDIO_H
 #include <stdio.h>
 #endif
 #if HAVE_FCNTL_H
 #include <fcntl.h>
 #endif
-#ifdef HAVE_STRING_H
+#if HAVE_STRING_H
 #include <string.h>
 #endif
-#ifdef HAVE_STRINGS_H
+#if HAVE_STRINGS_H
 #include <strings.h>
 #endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#if HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
 #if HAVE_SIGNAL_H
 #include <signal.h>
 #endif
 #if HAVE_TIME_H
 #include <time.h>
 #endif
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
 #if HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
 #endif
 #if HAVE_ASSERT_H
 #include <assert.h>
 #endif
+#if HAVE_CTYPE_H
+#include <ctype.h>
+#endif
 
 #define PROXY_PORT 3128
 #define PROXY_ADDR "127.0.0.1"
-#define MAX_FDS 1024
 #define READ_BUF_SZ 4096
 
 static int proxy_port = PROXY_PORT;
@@ -95,12 +87,15 @@ static int reqpersec;
 static int nrequests;
 static int opt_ims = 0;
 static int opt_range = 0;
+static int opt_accel = 0;
 static int max_connections = 64;
 static time_t lifetime = 60;
+static time_t process_lifetime = 86400;
 static struct timeval now;
-static long total_bytes_written = 0;
-static long total_bytes_read = 0;
+static long long total_bytes_written = 0;
+static long long total_bytes_read = 0;
 static int opt_checksum = 0;
+static char *custom_header = NULL;
 FILE *trace_file = NULL;
 
 typedef void (CB) (int, void *);
@@ -113,7 +108,7 @@ struct _f {
 };
 struct _request {
     int fd;
-    char url[8192];
+    char *url;
     char method[16];
     char requestbodyfile[256];
     char buf[READ_BUF_SZ * 2 + 1];
@@ -121,23 +116,33 @@ struct _request {
     int validsize;
     int bodysize;
     int content_length;
+    int status;
     long validsum;
     long sum;
+    int validstatus;
 };
 
-struct _f FD[MAX_FDS];
+struct _f FD[SQUID_MAXFD];
 int nfds = 0;
 int maxfd = 0;
 
+static void
+free_request(struct _request *r)
+{
+    if (r->url)
+        free(r->url);
+    free(r);
+}
 
+#define RFC1123_STRFTIME "%a, %d %b %Y %H:%M:%S GMT"
 char *
-mkrfc850(t)
-     time_t *t;
+mkrfc1123(t)
+time_t *t;
 {
     static char buf[128];
     struct tm *gmt = gmtime(t);
     buf[0] = '\0';
-    (void) strftime(buf, 127, "%A, %d-%b-%y %H:%M:%S GMT", gmt);
+    (void) strftime(buf, 127, RFC1123_STRFTIME, gmt);
     return buf;
 }
 
@@ -146,27 +151,28 @@ fd_close(int fd)
 {
     close(fd);
     if (FD[fd].ccb)
-       FD[fd].ccb(fd, FD[fd].data);
+        FD[fd].ccb(fd, FD[fd].data);
     FD[fd].ccb = NULL;
     FD[fd].cb = NULL;
     FD[fd].data = NULL;
     nfds--;
     if (fd == maxfd) {
-       while (fd > 0 && FD[fd].cb == NULL)
-           fd--;
-       maxfd = fd;
+        while (fd > 0 && FD[fd].cb == NULL)
+            fd--;
+        maxfd = fd;
     }
 }
 
 void
-fd_open(int fd, CB * cb, void *data, CB *ccb)
+fd_open(int fd, CB * cb, void *data, CB * ccb)
 {
+    assert(fd < SQUID_MAXFD);
     FD[fd].cb = cb;
     FD[fd].ccb = ccb;
     FD[fd].data = data;
     FD[fd].start = now.tv_sec;
     if (fd > maxfd)
-       maxfd = fd;
+        maxfd = fd;
     nfds++;
 }
 
@@ -185,60 +191,64 @@ read_reply(int fd, void *data)
     struct _request *r = data;
     static unsigned char buf[READ_BUF_SZ];
     int len;
-    if ((len=read(fd, buf, READ_BUF_SZ)) <= 0) {
-       fd_close(fd);
-       reqpersec++;
-       nrequests++;
-    } else {
-       int used=0;
-       total_bytes_read+=len;
-       if (r->headfound < 2) {
-           char *p,*header = NULL;
-           int oldlen = strlen(r->buf);
-           int newlen = oldlen + len;
-           assert(oldlen <= READ_BUF_SZ);
-           memcpy(r->buf+oldlen, buf, len);
-           r->buf[newlen+1]='\0';
-           for(p=r->buf; r->headfound < 2 && used<newlen; p++,used++) {
-               switch(*p) {
-               case '\n':
-                   r->headfound++;
-                   if (header) {
-                       /* Decode header */
-                       if (strncasecmp(header,"Content-Length:",15)==0)
-                           r->content_length = atoi(header+15);
-                       if (strncasecmp(header,"X-Request-URI:",14)==0) {
-                           /* Check URI */
-                           if (strncmp(r->url, header+15, strcspn(header+15,"\r\n"))) {
-                               char url[8192];
-                               strncpy(url, header+15, strcspn(header+15,"\r\n"));
-                               url[strcspn(header+15, "\r\n")]='\n';
-                               fprintf(stderr,"ERROR: Sent %s received %s\n",
-                                       r->url, url);
-                           }
-                       }
-                       header=NULL;
-                   }
-                   break;
-               case '\r':
-                   break;
-               default:
-                   r->headfound=0;
-                   if (!header)
-                       header = p;
-                   break;
-               }
-           }
-           if (header) {
-               memmove(r->buf, header, newlen - (header - r->buf) + 1);
-           }
-       }
-       r->bodysize+=len-used;
-       if (opt_checksum) {
-           for (; used<len ; used++) {
-               r->sum += buf[used];
-           }
-       }
+    int used = 0;
+    if ((len = read(fd, buf, READ_BUF_SZ)) <= 0) {
+        fd_close(fd);
+        reqpersec++;
+        nrequests++;
+        return;
+    }
+    total_bytes_read += len;
+    if (r->headfound < 2) {
+        char *p, *header = NULL;
+        int oldlen = strlen(r->buf);
+        int newlen = oldlen + len;
+        assert(oldlen <= READ_BUF_SZ);
+        memcpy(r->buf + oldlen, buf, len);
+        r->buf[newlen + 1] = '\0';
+        for (p = r->buf; r->headfound < 2 && used < newlen; p++, used++) {
+            switch (*p) {
+            case '\n':
+                r->headfound++;
+                if (!header)
+                    break;
+                /* Decode header */
+                if (strncmp(header, "HTTP", 4) == 0)
+                    r->status = atoi(header + 8);
+                else if (strncasecmp(header, "Content-Length:", 15) == 0)
+                    r->content_length = atoi(header + 15);
+                else if (strncasecmp(header, "X-Request-URI:", 14) == 0) {
+                    /* Check URI */
+                    if (strncmp(r->url, header + 15, strcspn(header + 15, "\r\n"))) {
+                        char url[8192];
+                        strncpy(url, header + 15, strcspn(header + 15, "\r\n"));
+                        url[strcspn(header + 15, "\r\n")] = '\n';
+                        fprintf(stderr, "ERROR: Sent %s received %s\n",
+                                r->url, url);
+                    }
+                }
+                header = NULL;
+                break;
+            case '\r':
+                break;
+            default:
+                r->headfound = 0;
+                if (!header)
+                    header = p;
+                break;
+            }
+        }
+        if (header) {
+            memmove(r->buf, header, newlen - (header - r->buf) + 1);
+        }
+        assert(used >= oldlen);
+        used -= oldlen;
+    }
+    r->bodysize += len - used;
+    if (opt_checksum) {
+        for (; used < len; used++) {
+            r->sum += buf[used];
+        }
     }
 }
 
@@ -246,152 +256,176 @@ void
 reply_done(int fd, void *data)
 {
     struct _request *r = data;
-    if (opt_range)
-       ; /* skip size checks for now */
+    if (opt_range);            /* skip size checks for now */
+    else if (strcmp(r->method, "HEAD") == 0);
     else if (r->bodysize != r->content_length && r->content_length >= 0)
-       fprintf(stderr,"ERROR: %s got %d of %d bytes\n",
-               r->url, r->bodysize, r->content_length);
+        fprintf(stderr, "ERROR: %s got %d of %d bytes\n",
+                r->url, r->bodysize, r->content_length);
     else if (r->validsize >= 0) {
-       if (r->validsize != r->bodysize)
-           fprintf(stderr,"WARNING: %s size mismatch wanted %d bytes got %d\n",
-                   r->url, r->validsize, r->bodysize);
-       else if (opt_checksum && r->validsum != r->sum)
-           fprintf(stderr,"WARNING: %s invalid checksum wanted 0x%lx got 0x%lx\n",
-                   r->url, r->validsum, r->sum);
+        if (r->validsize != r->bodysize)
+            fprintf(stderr, "WARNING: %s size mismatch wanted %d bytes got %d\n",
+                    r->url, r->validsize, r->bodysize);
+        else if (opt_checksum && r->validsum != r->sum)
+            fprintf(stderr, "WARNING: %s invalid checksum wanted 0x%lx got 0x%lx\n",
+                    r->url, r->validsum, r->sum);
+    }
+    if (r->validstatus && r->status != r->validstatus) {
+        fprintf(stderr, "WARNING: %s status mismatch wanted %d got %d\n",
+                r->url, r->validstatus, r->status);
     }
     if (trace_file) {
-       fprintf(trace_file,"%s %s %s %d 0x%lx\n",
-               r->method, r->url, r->requestbodyfile, r->bodysize, r->sum);
+        if (opt_checksum)
+            fprintf(trace_file, "%s %s %d %s %d 0x%lx\n",
+                    r->method, r->url, r->status, r->requestbodyfile, r->bodysize, r->sum);
+        else
+            fprintf(trace_file, "%s %s %d %s %d\n",
+                    r->method, r->url, r->status, r->requestbodyfile, r->bodysize);
     }
-    free(r);
+    free_request(r);
 }
 
 struct _request *
-request(char *urlin)
-{
-    int s=-1,f=-1;
+request(char *urlin) {
+    int s = -1, f = -1;
     char buf[4096];
     char msg[8192];
-    char *method, *url, *file, *size, *checksum;
+    char *method, *url, *file, *size, *checksum, *status;
+    char *host;
     char urlbuf[8192];
-    int len,len2;
+    int len, len2;
     time_t w;
     struct stat st;
     struct sockaddr_in S;
     struct _request *r;
+    if (*urlin == '\0')
+        return NULL;
     if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
-       perror("socket");
-       return NULL;
+        perror("socket");
+        return NULL;
     }
     memset(&S, '\0', sizeof(struct sockaddr_in));
     S.sin_family = AF_INET;
     S.sin_port = htons(proxy_port);
     S.sin_addr.s_addr = inet_addr(proxy_addr);
     if (connect(s, (struct sockaddr *) &S, sizeof(S)) < 0) {
-       close(s);
-       perror("connect");
-       return NULL;
+        close(s);
+        perror("connect");
+        return NULL;
     }
-    strcpy(urlbuf,urlin);
-    method=strtok(urlbuf," ");
-    url=strtok(NULL," ");
-    file=strtok(NULL," ");
-    size=strtok(NULL," ");
-    checksum=strtok(NULL," ");
+    strcpy(urlbuf, urlin);
+    method = strtok(urlbuf, " ");
+    url = strtok(NULL, " ");
+    status = strtok(NULL, " ");
+    file = strtok(NULL, " ");
+    size = strtok(NULL, " ");
+    checksum = strtok(NULL, " ");
     if (!url) {
-       url=method;
-       method="GET";
+        url = method;
+        method = "GET";
     }
     if (!file)
-       file="-";
+        file = "-";
     if (!size)
-       size="-";
+        size = "-";
     if (!checksum)
-       checksum="-";
-    r=calloc(1,sizeof *r);
-    assert(r!=NULL);
-    strcpy(r->url, url);
+        checksum = "-";
+    r = calloc(1, sizeof *r);
+    assert(r != NULL);
+    r->url = strdup(url);
+    assert(r->url);
     strcpy(r->method, method);
     strcpy(r->requestbodyfile, file);
     r->fd = s;
-    if (size && strcmp(size,"-")!=0)
-       r->validsize=atoi(size);
+    if (size && strcmp(size, "-") != 0)
+        r->validsize = atoi(size);
     else
-       r->validsize=-1; /* Unknown */
-    if (checksum && strcmp(checksum,"-")!=0)
-       r->validsum=strtoul(checksum,NULL,0);
-    r->content_length=-1; /* Unknown */
-    msg[0] = '\0';
-    sprintf(buf,"%s %s HTTP/1.0\r\n", method, url);
-    strcat(msg, buf);
+        r->validsize = -1;     /* Unknown */
+    if (checksum && strcmp(checksum, "-") != 0)
+        r->validsum = strtoul(checksum, NULL, 0);
+    if (status)
+        r->validstatus = atoi(status);
+    r->content_length = -1;    /* Unknown */
+    if (opt_accel) {
+        host = strchr(url, '/') + 2;
+        url = strchr(host, '/');
+    } else {
+        host = NULL;
+    }
+    sprintf(msg, "%s %s HTTP/1.0\r\n", method, url);
+    if (host) {
+        url[0] = '\0';
+        sprintf(buf, "Host: %s\r\n", host);
+        strcat(msg, buf);
+        url[0] = '/';
+    }
     strcat(msg, "Accept: */*\r\n");
     if (opt_ims && (lrand48() & 0x03) == 0) {
-       w = time(NULL) - (lrand48() & 0x3FFFF);
-       sprintf(buf, "If-Modified-Since: %s\r\n", mkrfc850(&w));
-       strcat(msg,buf);
+        w = time(NULL) - (lrand48() & 0x3FFFF);
+        sprintf(buf, "If-Modified-Since: %s\r\n", mkrfc850(&w));
+        strcat(msg, buf);
     }
-    if (file && strcmp(file, "-")!=0) {
-       f = open(file,O_RDONLY);
-       if (f < 0) {
-           perror("open file");
-           exit(1);
-       }
-       fstat(f, &st);
-       sprintf(buf,"Content-Length: %d\r\n", (int)st.st_size);
-       strcat(msg,buf);
+    if (file && strcmp(file, "-") != 0) {
+        f = open(file, O_RDONLY);
+        if (f < 0) {
+            perror("open file");
+            exit(1);
+        }
+        fstat(f, &st);
+        sprintf(buf, "Content-Length: %d\r\n", (int) st.st_size);
+        strcat(msg, buf);
     }
     if (opt_range && (lrand48() & 0x03) == 0) {
-       int len;
-       int count = 0;
-       strcat(msg, "Range: bytes=");
-       while (((len = (int)lrand48()) & 0x03) == 0 || !count) {
-           const int offset = (int) lrand48();
-           if (count)
-               strcat(msg, ",");
-           switch (lrand48() & 0x03) {
-               case 0:
-                   sprintf(buf, "-%d", len);
-                   break;
-               case 1:
-                   sprintf(buf, "%d-", offset);
-                   break;
-               default:
-                   sprintf(buf, "%d-%d", offset, offset+len);
-                   break;
-           }
-           strcat(msg,buf);
-           count++;
-       }
-       strcat(msg,"\r\n");
+        int len;
+        int count = 0;
+        strcat(msg, "Range: bytes=");
+        while (((len = (int) lrand48()) & 0x03) == 0 || !count) {
+            const int offset = (int) lrand48();
+            if (count)
+                strcat(msg, ",");
+            switch (lrand48() & 0x03) {
+            case 0:
+                sprintf(buf, "-%d", len);
+                break;
+            case 1:
+                sprintf(buf, "%d-", offset);
+                break;
+            default:
+                sprintf(buf, "%d-%d", offset, offset + len);
+                break;
+            }
+            strcat(msg, buf);
+            count++;
+        }
+        strcat(msg, "\r\n");
     }
+    strcat(msg, custom_header);
     strcat(msg, "\r\n");
     len = strlen(msg);
-    if ((len2=write(s, msg, len)) != len) {
-       close(s);
-       perror("write request");
-       free(r);
-       return NULL;
+    if ((len2 = write(s, msg, len)) != len) {
+        close(s);
+        perror("write request");
+        free_request(r);
+        return NULL;
     } else
-       total_bytes_written += len2;
-    if (f>=0) {
-       while ((len = read(f, buf, sizeof(buf)))>0) {
-           len2 = write(s, buf, len);
-           if (len2 < 0) {
-               perror("write body");
-               close(s);
-               free(r);
-           }
-       }
-       if (len < 0) {
-           perror("read body");
-           exit(1);
-       }
+        total_bytes_written += len2;
+    if (f >= 0) {
+        while ((len = read(f, buf, sizeof(buf))) > 0) {
+            len2 = write(s, buf, len);
+            if (len2 < 0) {
+                perror("write body");
+                close(s);
+                free_request(r);
+            }
+        }
+        if (len < 0) {
+            perror("read body");
+            exit(1);
+        }
     }
-
-/*
- * if (fcntl(s, F_SETFL, O_NDELAY) < 0)
- * perror("fcntl O_NDELAY");
- */
+    /*
+     * if (fcntl(s, F_SETFL, O_NDELAY) < 0)
+     * perror("fcntl O_NDELAY");
+     */
     return r;
 }
 
@@ -401,20 +435,23 @@ read_url(int fd, void *junk)
     struct _request *r;
     static char buf[8192];
     char *t;
+    buf[0] = '\0';
     if (fgets(buf, 8191, stdin) == NULL) {
-       printf("Done Reading URLS\n");
-       fd_close(0);
-       nfds++;
-       return;
+        printf("Done Reading URLS\n");
+        fd_close(0);
+        nfds++;
+        return;
     }
+    if (buf[0] == '\0')
+        return;
     if ((t = strchr(buf, '\n')))
-       *t = '\0';
+        *t = '\0';
     r = request(buf);
     if (!r) {
-       max_connections = nfds - 1;
-       printf("NOTE: max_connections set at %d\n", max_connections);
+        max_connections = nfds - 1;
+        printf("NOTE: max_connections set at %d\n", max_connections);
     } else {
-       fd_open(r->fd, read_reply, r, reply_done);
+        fd_open(r->fd, read_reply, r, reply_done);
     }
 }
 
@@ -426,18 +463,20 @@ usage(void)
     fprintf(stderr, " -c              Check checksum agains trace\n");
     fprintf(stderr, " -i              Send random If-Modified-Since times\n");
     fprintf(stderr, " -l <seconds>    Connection lifetime timeout (default 60)\n");
+    fprintf(stderr, " -a              Accelerator mode\n");
+    fprintf(stderr, " -H <string>     Custom header\n");
 }
 
 int
 main(argc, argv)
-     int argc;
-     char *argv[];
+int argc;
+char *argv[];
 {
     int i;
     int c;
     int dt;
     int j;
-    fd_set R,R2;
+    fd_set R, R2;
     struct timeval start;
     struct timeval last;
     struct timeval to;
@@ -446,38 +485,50 @@ main(argc, argv)
     progname = strdup(argv[0]);
     gettimeofday(&now, NULL);
     start = last = now;
-    while ((c = getopt(argc, argv, "p:h:n:icrl:t:")) != -1) {
-       switch (c) {
-       case 'p':
-           proxy_port = atoi(optarg);
-           break;
-       case 'h':
-           proxy_addr = strdup(optarg);
-           break;
-       case 'n':
-           max_connections = atoi(optarg);
-           break;
-       case 'i':
-           opt_ims = 1;
-           break;
-       case 'l':
-           lifetime = (time_t) atoi(optarg);
-           break;
-       case 'c':
-           opt_checksum = 1;
-           break;
-       case 't':
-           opt_checksum = 1; /* Tracing requires checksums */
-           trace_file = fopen(optarg,"w");
-           assert(trace_file);
-           break;
-       case 'r':
-           opt_range = 1;
-           break;
-       default:
-           usage();
-           return 1;
-       }
+    custom_header = strdup("");
+    while ((c = getopt(argc, argv, "ap:h:H:n:icrl:L:t:")) != -1) {
+        switch (c) {
+        case 'a':
+            opt_accel = 1;
+            break;
+        case 'p':
+            proxy_port = atoi(optarg);
+            break;
+        case 'h':
+            proxy_addr = strdup(optarg);
+            break;
+        case 'n':
+            max_connections = atoi(optarg);
+            break;
+        case 'i':
+            opt_ims = 1;
+            break;
+        case 'l':
+            lifetime = (time_t) atoi(optarg);
+            break;
+        case 'L':
+            process_lifetime = (time_t) atoi(optarg);
+            break;
+        case 'c':
+            opt_checksum = 1;
+            break;
+        case 't':
+            trace_file = fopen(optarg, "a");
+            assert(trace_file);
+            setbuf(trace_file, NULL);
+            break;
+        case 'r':
+            opt_range = 1;
+            break;
+        case 'H':
+            custom_header = realloc(custom_header, strlen(custom_header) + strlen(optarg) + 2 + 1);
+            strcat(custom_header, optarg);
+            strcat(custom_header, "\r\n");
+            break;
+        default:
+            usage();
+            return 1;
+        }
     }
     fd_open(0, read_url, NULL, NULL);
     nfds--;
@@ -485,54 +536,59 @@ main(argc, argv)
     signal(SIGPIPE, SIG_IGN);
     FD_ZERO(&R2);
     while (nfds || FD[0].cb) {
-       FD_ZERO(&R);
-       to.tv_sec = 0;
-       to.tv_usec = 100000;
-       if (nfds < max_connections && FD[0].cb)
-           FD_SET(0, &R);
-       for (i = 1; i <= maxfd; i++) {
-           if (FD[i].cb == NULL)
-               continue;
-           if (now.tv_sec - FD[i].start > lifetime) {
-               fprintf(stderr, "WARNING: fd %d lifetime timeout\n", i);
-               fd_close(i);
-               continue;
-           }
-           FD_SET(i, &R);
-       }
-       if (select(maxfd + 1, &R, NULL, NULL, &to) < 0) {
-           fprintf(stderr, "maxfd=%d\n", maxfd);
-           if (errno != EINTR)
-               perror("select");
-           continue;
-       }
-       gettimeofday(&now, NULL);
-       for (i = 0; i <= maxfd; i++) {
-           if (!FD_ISSET(i, &R))
-               continue;
-           FD[i].cb(i, FD[i].data);
+        FD_ZERO(&R);
+        to.tv_sec = 0;
+        to.tv_usec = 100000;
+        if (nfds < max_connections && FD[0].cb)
+            FD_SET(0, &R);
+        for (i = 1; i <= maxfd; i++) {
+            if (FD[i].cb == NULL)
+                continue;
+            if (now.tv_sec - FD[i].start > lifetime) {
+                fprintf(stderr, "WARNING: fd %d lifetime timeout\n", i);
+                fd_close(i);
+                continue;
+            }
+            FD_SET(i, &R);
+        }
+        if (select(maxfd + 1, &R, NULL, NULL, &to) < 0) {
+            fprintf(stderr, "maxfd=%d\n", maxfd);
+            if (errno != EINTR)
+                perror("select");
+            continue;
+        }
+        gettimeofday(&now, NULL);
+        for (i = 0; i <= maxfd; i++) {
+            if (!FD_ISSET(i, &R))
+                continue;
+            FD[i].cb(i, FD[i].data);
             if (nfds < max_connections && FD[0].cb) {
-               j=0;
-               FD_SET(0,&R2);
-               to.tv_sec=0;
-               to.tv_usec=0;
-               if(select(1,&R2,NULL,NULL,&to) == 1)
-                   FD[0].cb(0, FD[0].data);
-           }
-       }
-       if (now.tv_sec > last.tv_sec) {
-           last = now;
-           dt = (int) (now.tv_sec - start.tv_sec);
-           printf("T+ %6d: %9d req (%+4d), %4d conn, %3d/sec avg, %dmb, %dkb/sec avg\n",
-               dt,
-               nrequests,
-               reqpersec,
-               nfds,
-               (int) (nrequests / dt),
-               (int)total_bytes_read / 1024 / 1024,
-               (int)total_bytes_read / 1024 / dt);
-           reqpersec = 0;
-       }
+                j = 0;
+                FD_SET(0, &R2);
+                to.tv_sec = 0;
+                to.tv_usec = 0;
+                if (select(1, &R2, NULL, NULL, &to) == 1)
+                    FD[0].cb(0, FD[0].data);
+            }
+        }
+        if (now.tv_sec > last.tv_sec) {
+            last = now;
+            dt = (int) (now.tv_sec - start.tv_sec);
+            printf("T+ %6d: %9d req (%+4d), %4d conn, %3d/sec avg, %dmb, %dkb/sec avg\n",
+                   dt,
+                   nrequests,
+                   reqpersec,
+                   nfds,
+                   (int) (nrequests / dt),
+                   (int) (total_bytes_read / 1024 / 1024),
+                   (int) (total_bytes_read / 1024 / dt));
+            reqpersec = 0;
+            /*
+             * if (dt > process_lifetime)
+             *     exit(0);
+             */
+        }
     }
+    printf("Exiting normally\n");
     return 0;
 }