"Fossies" - the Fresh Open Source Software Archive

Member "httperf-0.9.0/src/core.c" (7 Apr 2007, 29565 Bytes) of package /linux/www/old/httperf-0.9.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "core.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2     httperf -- a tool for measuring web server performance
    3     Copyright 2000-2007 Hewlett-Packard Company and Contributors listed in
    4     AUTHORS file. Originally contributed by David Mosberger-Tang
    5 
    6     This file is part of httperf, a web server performance measurment
    7     tool.
    8 
    9     This program is free software; you can redistribute it and/or
   10     modify it under the terms of the GNU General Public License as
   11     published by the Free Software Foundation; either version 2 of the
   12     License, or (at your option) any later version.
   13     
   14     In addition, as a special exception, the copyright holders give
   15     permission to link the code of this work with the OpenSSL project's
   16     "OpenSSL" library (or with modified versions of it that use the same
   17     license as the "OpenSSL" library), and distribute linked combinations
   18     including the two.  You must obey the GNU General Public License in
   19     all respects for all of the code used other than "OpenSSL".  If you
   20     modify this file, you may extend this exception to your version of the
   21     file, but you are not obligated to do so.  If you do not wish to do
   22     so, delete this exception statement from your version.
   23 
   24     This program is distributed in the hope that it will be useful,
   25     but WITHOUT ANY WARRANTY; without even the implied warranty of
   26     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   27     General Public License for more details.
   28 
   29     You should have received a copy of the GNU General Public License
   30     along with this program; if not, write to the Free Software
   31     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
   32     02110-1301, USA
   33 */
   34 
   35 #include "config.h"
   36 
   37 #include <assert.h>
   38 #include <ctype.h>
   39 #include <errno.h>
   40 #include <fcntl.h>
   41 #include <netdb.h>
   42 #include <signal.h>
   43 #include <stdio.h>
   44 #include <stdlib.h>
   45 #include <string.h>
   46 #include <unistd.h>
   47 
   48 #include <sys/ioctl.h>
   49 #include <sys/socket.h>
   50 #include <sys/time.h>
   51 #include <sys/types.h>
   52 #include <sys/resource.h>   /* grrr, must come after sys/types.h for BSD */
   53 #ifdef HAVE_SYS_SELECT_H
   54 #include <sys/select.h>
   55 #endif
   56 
   57 #include <netinet/in.h>
   58 #include <netinet/tcp.h>
   59 #include <arpa/inet.h>
   60 
   61 #include <httperf.h>
   62 #include <call.h>
   63 #include <core.h>
   64 #include <event.h>
   65 #include <http.h>
   66 #include <conn.h>
   67 
   68 /*if we don't have GNU compatible realloc, fake it*/
   69 #if HAVE_REALLOC == 0
   70 void *rpl_realloc(void *ptr, size_t size)
   71   {
   72     if (ptr == NULL && size == 0)
   73       {
   74         return NULL;
   75       }
   76 
   77     if (size == 0)
   78       {
   79         free(ptr);
   80     return NULL;
   81       }
   82 
   83     if (ptr == NULL)
   84       {
   85         return malloc(size);
   86       }
   87 
   88 #undef realloc
   89     return realloc(ptr, size);
   90 #define realloc rpl_realloc
   91   }
   92 #endif
   93 
   94 #define HASH_TABLE_SIZE 1024    /* can't have more than this many servers */
   95 #define MIN_IP_PORT IPPORT_RESERVED
   96 #define MAX_IP_PORT 65535
   97 #define BITSPERLONG (8*sizeof (u_long))
   98 
   99 static int running = 1;
  100 static int iteration;
  101 static u_long max_burst_len;
  102 static fd_set rdfds, wrfds;
  103 static int min_sd = 0x7fffffff, max_sd = 0, alloced_sd_to_conn = 0;
  104 static struct timeval select_timeout;
  105 static struct sockaddr_in myaddr;
  106 Conn **sd_to_conn;
  107 static u_long port_free_map[((MAX_IP_PORT - MIN_IP_PORT + BITSPERLONG)
  108                  / BITSPERLONG)];
  109 static char http10req[] =
  110   " HTTP/1.0\r\nUser-Agent: httperf/"VERSION \
  111   "\r\nConnection: keep-alive\r\nHost: ";
  112 static char http11req[] =
  113   " HTTP/1.1\r\nUser-Agent: httperf/"VERSION"\r\nHost: ";
  114 
  115 static char http10req_nohost[] =
  116   " HTTP/1.0\r\nUser-Agent: httperf/"VERSION \
  117   "\r\nConnection: keep-alive\r\n";
  118 static char http11req_nohost[] =
  119   " HTTP/1.1\r\nUser-Agent: httperf/"VERSION"\r\n";
  120 
  121 #ifndef SOL_TCP
  122 # define SOL_TCP 6  /* probably ought to do getprotlbyname () */
  123 #endif
  124 
  125 #ifdef TIME_SYSCALLS
  126 # define SYSCALL(n,s)                           \
  127   {                                 \
  128     Time start, stop;                           \
  129     do                                  \
  130       {                                 \
  131     errno = 0;                          \
  132     start = timer_now_forced ();                    \
  133     s;               /* execute the syscall */  \
  134     stop = timer_now_forced ();                 \
  135     syscall_time[SC_##n] += stop - start;               \
  136     ++syscall_count[SC_##n];                    \
  137       }                                 \
  138     while (errno == EINTR);                     \
  139   }
  140 
  141   enum Syscalls
  142     {
  143       SC_BIND, SC_CONNECT, SC_READ, SC_SELECT, SC_SOCKET, SC_WRITEV,
  144       SC_SSL_READ, SC_SSL_WRITEV,
  145       SC_NUM_SYSCALLS
  146     };
  147 
  148   static const char * const syscall_name[SC_NUM_SYSCALLS] =
  149     {
  150       "bind", "connct", "read", "select", "socket", "writev",
  151       "ssl_read", "ssl_writev"
  152     };
  153   static Time syscall_time[SC_NUM_SYSCALLS];
  154   static u_int syscall_count[SC_NUM_SYSCALLS];
  155 #else
  156 # define SYSCALL(n,s)               \
  157   {                     \
  158     do                      \
  159       {                     \
  160     errno = 0;              \
  161     s;                  \
  162       }                     \
  163     while (errno == EINTR);         \
  164   }
  165 #endif
  166 
  167 struct hash_entry
  168   {
  169     const char *hostname;
  170     int port;
  171     struct sockaddr_in sin;
  172   }
  173 hash_table[HASH_TABLE_SIZE];
  174 
  175 static int
  176 hash_code (const char *server, size_t server_len, int port)
  177 {
  178   u_char *cp = (u_char *) server;
  179   u_long h = port;
  180   u_long g;
  181   int ch;
  182 
  183   /* Basically the ELF hash algorithm: */
  184 
  185   while ((ch = *cp++) != '\0')
  186     {
  187       h = (h << 4) + ch;
  188       if ((g = (h & 0xf0000000)) != 0)
  189         {
  190           h ^= g >> 24;
  191           h &= ~g;
  192         }
  193     }
  194   return h;
  195 }
  196 
  197 static struct hash_entry*
  198 hash_enter (const char *server, size_t server_len, int port,
  199         struct sockaddr_in *sin)
  200 {
  201   struct hash_entry *he;
  202 
  203   int index = hash_code (server, server_len, port) % HASH_TABLE_SIZE;
  204 
  205   while (hash_table[index].hostname)
  206     {
  207       ++index;
  208       if (index >= HASH_TABLE_SIZE)
  209     index = 0;
  210     }
  211   he = hash_table + index;
  212   he->hostname = server;
  213   he->port = port;
  214   he->sin = *sin;
  215   return he;
  216 }
  217 
  218 static struct sockaddr_in*
  219 hash_lookup (const char *server, size_t server_len, int port)
  220 {
  221   int index, start_index;
  222 
  223   index = start_index = hash_code (server, server_len, port) % HASH_TABLE_SIZE;
  224   while (hash_table[index].hostname)
  225     {
  226       if (hash_table[index].port == port
  227       && strcmp (hash_table[index].hostname, server) == 0)
  228     return &hash_table[index].sin;
  229 
  230       ++index;
  231       if (index >= HASH_TABLE_SIZE)
  232     index = 0;
  233       if (index == start_index)
  234     break;
  235     }
  236   return 0;
  237 }
  238 
  239 static int
  240 lffs (long w)
  241 {
  242   int r;
  243 
  244   if (sizeof (w) == sizeof (int))
  245     r = ffs (w);
  246   else
  247     {
  248       r = ffs (w);
  249 #if SIZEOF_LONG > 4
  250       if (r == 0)
  251     {
  252       r = ffs (w >> (8*sizeof (int)));
  253       if (r > 0)
  254         r += 8*sizeof (int);
  255     }
  256 #endif
  257     }
  258   return r;
  259 }
  260 
  261 static void
  262 port_put (int port)
  263 {
  264   int i, bit;
  265 
  266   port -= MIN_IP_PORT;
  267   i   = port / BITSPERLONG;
  268   bit = port % BITSPERLONG;
  269   port_free_map[i] |= (1UL << bit);
  270 }
  271 
  272 static int
  273 port_get (void)
  274 {
  275   static u_long mask = ~0UL;
  276   static int previous = 0;
  277   int port, bit, i;
  278 
  279   i = previous;
  280   if ((port_free_map[i] & mask) == 0)
  281     {
  282       do
  283     {
  284       ++i;
  285       if (i >= NELEMS (port_free_map))
  286         i = 0;
  287       if (i == previous)
  288         {
  289           if (DBG > 0)
  290         fprintf (stderr,
  291              "%s.port_get: Yikes! I'm out of port numbers!\n",
  292              prog_name);
  293           return -1;
  294         }
  295     }
  296       while (port_free_map[i] == 0);
  297       mask = ~0UL;
  298     }
  299   previous = i;
  300 
  301   bit = lffs (port_free_map[i] & mask) - 1;
  302   if (bit >= BITSPERLONG - 1)
  303     mask = 0;
  304   else
  305     mask = ~((1UL << (bit + 1)) - 1);
  306   port_free_map[i] &= ~(1UL << bit);
  307   port = bit + i*BITSPERLONG + MIN_IP_PORT;
  308   return port;
  309 }
  310 
  311 static void
  312 conn_failure (Conn *s, int err)
  313 {
  314   Any_Type arg;
  315 
  316   arg.l = err;
  317   event_signal (EV_CONN_FAILED, (Object *) s, arg);
  318 
  319   core_close (s);
  320 }
  321 
  322 static void
  323 conn_timeout (Timer *t, Any_Type arg)
  324 {
  325   Conn *s = arg.vp;
  326   Time now;
  327   Call *c;
  328 
  329   assert (object_is_conn (s));
  330   s->watchdog = 0;
  331 
  332   if (DBG > 0)
  333     {
  334       c = 0;
  335       if (s->sd >= 0)
  336     {
  337       now = timer_now ();
  338       if (FD_ISSET (s->sd, &rdfds)
  339           && s->recvq && now >= s->recvq->timeout)
  340         c = s->recvq;
  341       else if (FD_ISSET (s->sd, &wrfds)
  342            && s->sendq && now >= s->sendq->timeout)
  343         c = s->sendq;
  344     }
  345       if (DBG > 0)
  346     {
  347       fprintf (stderr, "connection_timeout");
  348       if (c)
  349         fprintf (stderr, ".%lu", c->id);
  350       fprintf (stderr, ": t=%p, connection=%p\n", t, s);
  351     }
  352     }
  353 
  354   arg.l = 0;
  355   event_signal (EV_CONN_TIMEOUT, (Object *) s, arg);
  356 
  357   core_close (s);
  358 }
  359 
  360 static void
  361 set_active (Conn *s, fd_set *fdset)
  362 {
  363   int sd = s->sd;
  364   Any_Type arg;
  365   Time timeout;
  366 
  367   FD_SET (sd, fdset);
  368   if (sd < min_sd)
  369     min_sd = sd;
  370   if (sd >= max_sd)
  371     max_sd = sd;
  372 
  373   if (s->watchdog)
  374     return;
  375 
  376   timeout = 0.0;
  377   if (s->sendq)
  378     timeout = s->sendq->timeout;
  379   if (s->recvq && (timeout == 0.0 || timeout > s->recvq->timeout))
  380     timeout = s->recvq->timeout;
  381 
  382   if (timeout > 0.0)
  383     {
  384       arg.vp = s;
  385       s->watchdog = timer_schedule (conn_timeout, arg,
  386                     timeout - timer_now ());
  387     }
  388 }
  389 
  390 static void
  391 do_send (Conn *conn)
  392 {
  393   int async_errno;
  394   socklen_t len;
  395   struct iovec *iovp;
  396   int sd = conn->sd;
  397   ssize_t nsent = 0;
  398   Any_Type arg;
  399   Call *call;
  400 
  401   while (1)
  402     {
  403       call = conn->sendq;
  404       assert (call);
  405 
  406       arg.l = 0;
  407       event_signal (EV_CALL_SEND_RAW_DATA, (Object *) call, arg);
  408 
  409 #ifdef HAVE_SSL
  410       if (param.use_ssl)
  411     {
  412       extern ssize_t SSL_writev (SSL *, const struct iovec *, int);
  413       SYSCALL (SSL_WRITEV,
  414            nsent = SSL_writev(conn->ssl,
  415                       call->req.iov + call->req.iov_index,
  416                       (NELEMS (call->req.iov)
  417                        - call->req.iov_index)));
  418     }
  419       else
  420 #endif
  421     {
  422       SYSCALL (WRITEV,
  423            nsent = writev (sd, call->req.iov + call->req.iov_index,
  424                    (NELEMS (call->req.iov)
  425                     - call->req.iov_index)));
  426     }
  427 
  428       if (DBG > 0)
  429     fprintf (stderr, "do_send.%lu: wrote %ld bytes on %p\n", call->id,
  430          (long) nsent, conn);
  431 
  432       if (nsent < 0)
  433     {
  434       if (errno == EAGAIN)
  435         return;
  436 
  437       len = sizeof (async_errno);
  438       if (getsockopt (sd, SOL_SOCKET, SO_ERROR, &async_errno, &len) == 0
  439           && async_errno != 0)
  440         errno = async_errno;
  441 
  442       if (DBG > 0)
  443         fprintf (stderr, "%s.do_send: writev() failed: %s\n",
  444              prog_name, strerror (errno));
  445 
  446       conn_failure (conn, errno);
  447       return;
  448     }
  449 
  450       call->req.size += nsent;
  451 
  452       iovp = call->req.iov + call->req.iov_index;
  453       while (iovp < call->req.iov + NELEMS (call->req.iov))
  454     {
  455       if (nsent < iovp->iov_len)
  456         {
  457           iovp->iov_len -= nsent;
  458           iovp->iov_base = (caddr_t) ((char *) iovp->iov_base + nsent);
  459           break;
  460         }
  461       else
  462         {
  463           /* we're done with this fragment: */
  464           nsent -= iovp->iov_len;
  465           *iovp = call->req.iov_saved;
  466           ++iovp;
  467           call->req.iov_saved = *iovp;
  468         }
  469     }
  470       call->req.iov_index = iovp - call->req.iov;
  471       if (call->req.iov_index < NELEMS (call->req.iov))
  472     {
  473       /* there are more header bytes to write */
  474       call->timeout = param.timeout ? timer_now () + param.timeout : 0.0;
  475       set_active (conn, &wrfds);
  476       return;
  477     }
  478 
  479       /* we're done with sending this request */
  480       conn->sendq = call->sendq_next;
  481       if (!conn->sendq)
  482     {
  483       conn->sendq_tail = 0;
  484       FD_CLR (sd, &wrfds);
  485     }
  486       arg.l = 0;
  487       event_signal (EV_CALL_SEND_STOP, (Object *) call, arg);
  488       if (conn->state >= S_CLOSING)
  489     {
  490       call_dec_ref (call);
  491       return;
  492     }
  493 
  494       /* get ready to receive matching reply (note that we implicitly
  495          pass on the reference to the call from the sendq to the
  496          recvq): */
  497       call->recvq_next = 0;
  498       if (!conn->recvq)
  499     conn->recvq = conn->recvq_tail = call;
  500       else
  501     {
  502       conn->recvq_tail->recvq_next = call;
  503       conn->recvq_tail = call;
  504     }
  505       call->timeout = param.timeout + param.think_timeout;
  506       if (call->timeout > 0.0)
  507     call->timeout += timer_now ();
  508       set_active (conn, &rdfds);
  509       if (conn->state < S_REPLY_STATUS)
  510     conn->state = S_REPLY_STATUS;   /* expecting reply status */
  511 
  512       if (!conn->sendq)
  513     return;
  514 
  515       arg.l = 0;
  516       event_signal (EV_CALL_SEND_START, (Object *) conn->sendq, arg);
  517       if (conn->state >= S_CLOSING)
  518     return;
  519     }
  520 }
  521 
  522 static void
  523 recv_done (Call *call)
  524 {
  525   Conn *conn = call->conn;
  526   Any_Type arg;
  527 
  528   conn->recvq = call->recvq_next;
  529   if (!conn->recvq)
  530     {
  531       FD_CLR (conn->sd, &rdfds);
  532       conn->recvq_tail = 0;
  533     }
  534   /* we're done with receiving this request */
  535   arg.l = 0;
  536   event_signal (EV_CALL_RECV_STOP, (Object *) call, arg);
  537 
  538   call_dec_ref (call);
  539 }
  540 
  541 static void
  542 do_recv (Conn *s)
  543 {
  544   char *cp, buf[8193];
  545   Call *c = s->recvq;
  546   int i, saved_errno;
  547   ssize_t nread = 0;
  548   size_t buf_len;
  549 
  550   assert (c);
  551 
  552 #ifdef HAVE_SSL
  553   if (param.use_ssl)
  554     {
  555       SYSCALL (SSL_READ,
  556            nread = SSL_read (s->ssl, buf, sizeof (buf) - 1));
  557     }
  558   else
  559 #endif
  560     {
  561       SYSCALL (READ,
  562            nread = read (s->sd, buf, sizeof (buf) - 1));
  563     }
  564   saved_errno = errno;
  565   if (nread <= 0)
  566     {
  567       if (DBG > 0)
  568     {
  569       fprintf (stderr, "do_recv.%lu: received %lu reply bytes on %p\n",
  570            c->id,
  571            (u_long) (c->reply.header_bytes + c->reply.content_bytes),
  572            s);
  573       if (nread < 0)
  574         fprintf (stderr, "%s.do_recv: read() failed: %s\n",
  575              prog_name, strerror (saved_errno));
  576     }
  577       if (nread < 0)
  578     {
  579       if (saved_errno != EAGAIN)
  580         conn_failure (s, saved_errno);
  581     }
  582       else if (s->state != S_REPLY_DATA)
  583     conn_failure (s, ECONNRESET);
  584       else
  585     {
  586       if (s->state < S_CLOSING)
  587         s->state = S_REPLY_DONE;
  588       recv_done (c);
  589     }
  590       return;
  591     }
  592   buf[nread] = '\0';    /* ensure buffer is '\0' terminated */
  593 
  594   if (DBG > 3)
  595     {
  596       /* dump received data in hex & ascii: */
  597 
  598       fprintf (stderr, "do_recv.%lu: received reply data:\n", c->id);
  599       for (cp = buf; cp < buf + nread; )
  600     {
  601       fprintf (stderr, "  %04x:",
  602            (int) (c->reply.header_bytes + c->reply.content_bytes
  603               + (cp - buf)));
  604       for (i = 0; i < 16 && i < buf + nread - cp; ++i)
  605         fprintf (stderr, " %02x", cp[i] & 0xff);
  606       i *= 3;
  607       while (i++ < 50)
  608         fputc (' ', stderr);
  609       for (i = 0; i < 16 && cp < buf + nread; ++i, ++cp)
  610         fprintf (stderr, "%c", isprint (*cp) ? *cp : '.');
  611       fprintf (stderr, "\n");
  612     }
  613     }
  614 
  615   /* process the replies in this buffer: */
  616 
  617   buf_len = nread;
  618   cp = buf;
  619   do
  620     {
  621       c = s->recvq;
  622       assert (c);
  623       /* sets right start time, but doesn't update each packet */
  624       if(s->state == S_REPLY_STATUS)
  625       {
  626         c->timeout = param.timeout + param.think_timeout;
  627         if (c->timeout > 0.0)
  628           c->timeout += timer_now ();
  629       }
  630       
  631       http_process_reply_bytes (c, &cp, &buf_len);
  632       if (s->state == S_REPLY_DONE)
  633     {
  634       recv_done (c);
  635       if (s->state >= S_CLOSING)
  636         return;
  637 
  638       s->state = S_REPLY_STATUS;
  639     }
  640     }
  641   while (buf_len > 0);
  642 
  643   if (s->recvq)
  644     set_active (c->conn, &rdfds);
  645 }
  646 
  647 struct sockaddr_in*
  648 core_addr_intern (const char *server, size_t server_len, int port)
  649 {
  650   struct sockaddr_in sin;
  651   struct hash_entry *h;
  652   struct hostent *he;
  653   Any_Type arg;
  654   
  655   memset (&sin, 0, sizeof (sin));
  656   sin.sin_family = AF_INET;
  657   sin.sin_port = htons (port);
  658 
  659   arg.cvp = server;
  660   event_signal (EV_HOSTNAME_LOOKUP_START, 0, arg);
  661   he = gethostbyname (server);
  662   event_signal (EV_HOSTNAME_LOOKUP_STOP, 0, arg);
  663   if (he)
  664     {
  665       if (he->h_addrtype != AF_INET
  666       || he->h_length != sizeof (sin.sin_addr))
  667     {
  668       fprintf (stderr, "%s: can't deal with addr family %d or size %d\n",
  669            prog_name, he->h_addrtype, he->h_length);
  670       exit (1);
  671     }
  672       memcpy (&sin.sin_addr, he->h_addr_list[0], sizeof (sin.sin_addr));
  673     }
  674   else
  675     {
  676       if (!inet_aton (server, &sin.sin_addr))
  677     {
  678       fprintf (stderr, "%s.core_addr_intern: invalid server address %s\n",
  679            prog_name, server);
  680       exit (1);
  681     }
  682     }
  683   h = hash_enter (server, server_len, port, &sin);
  684   if (!h)
  685     return 0;
  686   return &h->sin;
  687 }
  688 
  689 void
  690 core_init (void)
  691 {
  692   struct rlimit rlimit;
  693 
  694   memset (&hash_table, 0, sizeof (hash_table));
  695   memset (&rdfds, 0, sizeof (rdfds));
  696   memset (&wrfds, 0, sizeof (wrfds));
  697   memset (&myaddr, 0, sizeof (myaddr));
  698   memset (&port_free_map, 0xff, sizeof (port_free_map));
  699 
  700   /* Don't disturb just because a TCP connection closed on us... */
  701   signal (SIGPIPE, SIG_IGN);
  702 
  703 #ifdef DONT_POLL
  704   /* This causes select() to take several milliseconds on both
  705      Linux/x86 and HP-UX 10.20.  */
  706   select_timeout.tv_sec  = (u_long) TIMER_INTERVAL;
  707   select_timeout.tv_usec = (u_long) (TIMER_INTERVAL * 1e6);
  708 #else
  709   /* This causes httperf to become a CPU hog as it polls for
  710      filedescriptors to become readable/writable.  This is OK as long
  711      as httperf is the only (interesting) user-level process that
  712      executes on a machine.  */
  713   select_timeout.tv_sec  = 0;
  714   select_timeout.tv_usec = 0;
  715 #endif
  716 
  717   /* boost open file limit to the max: */
  718   if (getrlimit (RLIMIT_NOFILE, &rlimit) < 0)
  719     {
  720       fprintf (stderr, "%s: failed to get number of open file limit: %s",
  721            prog_name, strerror (errno));
  722       exit (1);
  723     }
  724 
  725   if (rlimit.rlim_max > FD_SETSIZE)
  726     {
  727       fprintf (stderr, "%s: warning: open file limit > FD_SETSIZE; "
  728            "limiting max. # of open files to FD_SETSIZE\n", prog_name);
  729       rlimit.rlim_max = FD_SETSIZE;
  730     }
  731 
  732   rlimit.rlim_cur = rlimit.rlim_max;
  733   if (setrlimit (RLIMIT_NOFILE, &rlimit) < 0)
  734     {
  735       fprintf (stderr, "%s: failed to increase number of open file limit: %s",
  736            prog_name, strerror (errno));
  737       exit (1);
  738     }
  739 
  740   if (verbose)
  741     printf ("%s: maximum number of open descriptors = %ld\n",
  742         prog_name, rlimit.rlim_max);
  743 
  744   if (param.server)
  745     core_addr_intern (param.server, strlen (param.server), param.port);
  746 }
  747 
  748 #ifdef HAVE_SSL
  749 
  750 void
  751 core_ssl_connect (Conn *s)
  752 {
  753   Any_Type arg;
  754   int ssl_err;
  755 
  756   if (DBG > 2)
  757     fprintf (stderr, "core_ssl_connect(conn=%p)\n", (void *) s);
  758 
  759   if (SSL_set_fd (s->ssl, s->sd) == 0)
  760     {
  761       ERR_print_errors_fp (stderr);
  762       exit (-1);
  763     }
  764 
  765   ssl_err = SSL_connect (s->ssl);
  766   if (ssl_err < 0)
  767     {
  768       int reason = SSL_get_error(s->ssl, ssl_err);
  769 
  770       if (reason == SSL_ERROR_WANT_READ || reason == SSL_ERROR_WANT_WRITE)
  771     {
  772       if (DBG > 2)
  773         fprintf (stderr, "core_ssl_connect: want to %s more...\n",
  774              (reason == SSL_ERROR_WANT_READ) ? "read" : "write");
  775       if (reason == SSL_ERROR_WANT_READ && !FD_ISSET (s->sd, &rdfds))
  776         {
  777           FD_CLR (s->sd, &wrfds);
  778           set_active (s, &rdfds);
  779         }
  780       else if (reason == SSL_ERROR_WANT_WRITE && !FD_ISSET (s->sd, &wrfds))
  781         {
  782           FD_CLR (s->sd, &rdfds);
  783           set_active (s, &wrfds);
  784         }
  785       return;
  786     }
  787       fprintf (stderr,
  788            "%s: failed to connect to SSL server (err=%d, reason=%d)\n",
  789            prog_name, ssl_err, reason);
  790       ERR_print_errors_fp (stderr);
  791       exit (-1);
  792     }
  793 
  794   s->state = S_CONNECTED;
  795 
  796   if (DBG > 0)
  797     fprintf (stderr, "core_ssl_connect: SSL is connected!\n");
  798 
  799   if (DBG > 1)
  800     {
  801       SSL_CIPHER *ssl_cipher;
  802 
  803       ssl_cipher = SSL_get_current_cipher (s->ssl);
  804       if (!ssl_cipher)
  805     fprintf (stderr, "core_ssl_connect: server refused all client cipher "
  806          "suites!\n");
  807       else
  808     fprintf (stderr, "core_ssl_connect: cipher=%s, valid=%d, id=%lu\n",
  809          ssl_cipher->name, ssl_cipher->valid, ssl_cipher->id);
  810     }
  811 
  812   arg.l = 0;
  813   event_signal (EV_CONN_CONNECTED, (Object *) s, arg);
  814 }
  815 
  816 #endif /* HAVE_SSL */
  817 
  818 int
  819 core_connect (Conn *s)
  820 {
  821   int sd, result, async_errno;
  822   socklen_t len;
  823   struct sockaddr_in *sin;
  824   struct linger linger;
  825   int myport, optval;
  826   Any_Type arg;
  827   static int prev_iteration = -1;
  828   static u_long burst_len;
  829 
  830   if (iteration == prev_iteration)
  831     ++burst_len;
  832   else
  833     {
  834       if (burst_len > max_burst_len)
  835     max_burst_len = burst_len;
  836       burst_len = 1;
  837       prev_iteration = iteration;
  838     }
  839 
  840   SYSCALL (SOCKET,
  841        sd = socket (AF_INET, SOCK_STREAM, 0));
  842   if (sd < 0)
  843     {
  844       if (DBG > 0)
  845     fprintf (stderr, "%s.core_connect.socket: %s (max_sd=%d)\n",
  846          prog_name, strerror (errno), max_sd);
  847       goto failure;
  848     }
  849 
  850   if (fcntl (sd, F_SETFL, O_NONBLOCK) < 0)
  851     {
  852       fprintf (stderr, "%s.core_connect.fcntl: %s\n",
  853            prog_name, strerror (errno));
  854       goto failure;
  855     }
  856 
  857   if (param.close_with_reset)
  858     {
  859       linger.l_onoff = 1;
  860       linger.l_linger = 0;
  861       if (setsockopt (sd, SOL_SOCKET, SO_LINGER, &linger, sizeof (linger)) < 0)
  862     {
  863       fprintf (stderr, "%s.core_connect.setsockopt(SO_LINGER): %s\n",
  864            prog_name, strerror (errno));
  865       goto failure;
  866     }
  867     }
  868 
  869   /* Disable Nagle algorithm so we don't delay needlessly when
  870      pipelining requests.  */
  871   optval = 1;
  872   if (setsockopt (sd, SOL_TCP, TCP_NODELAY, &optval, sizeof (optval)) < 0)
  873     {
  874       fprintf (stderr, "%s.core_connect.setsockopt(SO_SNDBUF): %s\n",
  875            prog_name, strerror (errno));
  876       goto failure;
  877     }
  878 
  879   optval = param.send_buffer_size;
  880   if (setsockopt (sd, SOL_SOCKET, SO_SNDBUF, &optval, sizeof (optval)) < 0)
  881     {
  882       fprintf (stderr, "%s.core_connect.setsockopt(SO_SNDBUF): %s\n",
  883            prog_name, strerror (errno));
  884       goto failure;
  885     }
  886 
  887   optval = param.recv_buffer_size;
  888   if (setsockopt (sd, SOL_SOCKET, SO_RCVBUF, &optval, sizeof (optval)) < 0)
  889     {
  890       fprintf (stderr, "%s.core_connect.setsockopt(SO_SNDBUF): %s\n",
  891            prog_name, strerror (errno));
  892       goto failure;
  893     }
  894 
  895   s->sd = sd;
  896   if (sd >= alloced_sd_to_conn)
  897     {
  898       size_t size, old_size;
  899 
  900       old_size = alloced_sd_to_conn * sizeof (sd_to_conn[0]);
  901       alloced_sd_to_conn += 2048;
  902       size = alloced_sd_to_conn * sizeof (sd_to_conn[0]);
  903       if (sd_to_conn)
  904     sd_to_conn = realloc (sd_to_conn, size);
  905       else
  906     sd_to_conn = malloc (size);
  907       if (!sd_to_conn)
  908     {
  909       if (DBG > 0)
  910         fprintf (stderr, "%s.core_connect.realloc: %s\n",
  911              prog_name, strerror (errno));
  912       goto failure;
  913     }
  914       memset ((char *) sd_to_conn + old_size, 0, size - old_size);
  915     }
  916   assert (!sd_to_conn[sd]);
  917   sd_to_conn[sd] = s;
  918 
  919   sin = hash_lookup (s->hostname, s->hostname_len, s->port);
  920   if (!sin)
  921     {
  922       if (DBG > 0)
  923     fprintf (stderr, "%s.core_connect: unknown server/port %s:%d\n",
  924          prog_name, s->hostname, s->port);
  925       goto failure;
  926     }
  927 
  928   arg.l = 0;
  929   event_signal (EV_CONN_CONNECTING, (Object *) s, arg);
  930   if (s->state >= S_CLOSING)
  931     goto failure;
  932 
  933   if (param.hog)
  934     {
  935       while (1)
  936     {
  937       myport = port_get ();
  938       if (myport < 0)
  939         goto failure;
  940 
  941       myaddr.sin_port = htons (myport);
  942       SYSCALL (BIND,
  943            result = bind (sd, (struct sockaddr *)&myaddr,
  944                     sizeof (myaddr)));
  945       if (result == 0)
  946         break;
  947 
  948       if (errno != EADDRINUSE && errno == EADDRNOTAVAIL)
  949         {
  950           if (DBG > 0)
  951         fprintf (stderr, "%s.core_connect.bind: %s\n",
  952              prog_name, strerror (errno));
  953           goto failure;
  954         }
  955     }
  956       s->myport = myport;
  957     }
  958 
  959   SYSCALL (CONNECT,
  960        result = connect (sd, (struct sockaddr *)sin, sizeof (*sin)));
  961   if (result == 0)
  962     {
  963 #ifdef HAVE_SSL
  964       if (param.use_ssl)
  965       core_ssl_connect (s);
  966       else
  967 #endif
  968     {
  969       s->state = S_CONNECTED;
  970       arg.l = 0;
  971       event_signal (EV_CONN_CONNECTED, (Object *) s, arg);
  972     }
  973     }
  974   else if (errno == EINPROGRESS)
  975     {
  976       /* The socket becomes writable only after the connection has
  977      been established.  Hence we wait for writability to
  978      detect connection establishment.  */
  979       s->state = S_CONNECTING;
  980       set_active (s, &wrfds);
  981       if (param.timeout > 0.0)
  982     {
  983       arg.vp = s;
  984       assert (!s->watchdog);
  985       s->watchdog = timer_schedule (conn_timeout, arg, param.timeout);
  986     }
  987     }
  988   else
  989     {
  990       len = sizeof (async_errno);
  991       if (getsockopt (sd, SOL_SOCKET, SO_ERROR, &async_errno, &len) == 0
  992       && async_errno != 0)
  993     errno = async_errno;
  994 
  995       if (DBG > 0)
  996     fprintf (stderr, "%s.core_connect.connect: %s (max_sd=%d)\n",
  997          prog_name, strerror (errno), max_sd);
  998       goto failure;
  999     }
 1000   return 0;
 1001 
 1002  failure:
 1003   conn_failure (s, errno);
 1004   return -1;
 1005 }
 1006 
 1007 int
 1008 core_send (Conn *conn, Call *call)
 1009 {
 1010   Any_Type arg;
 1011 
 1012   arg.l = 0;
 1013   event_signal (EV_CALL_ISSUE, (Object *) call, arg);
 1014 
 1015   call->conn = conn;    /* NO refcounting here (see call.h).  */
 1016 
 1017   if (param.no_host_hdr)
 1018     {
 1019       call->req.iov[IE_HOST].iov_base = (caddr_t) "";
 1020       call->req.iov[IE_HOST].iov_len = 0;
 1021     }
 1022   else if (!call->req.iov[IE_HOST].iov_base)
 1023     {
 1024       /* Default call's hostname to connection's hostname: */
 1025       call->req.iov[IE_HOST].iov_base = (caddr_t) conn->fqdname;
 1026       call->req.iov[IE_HOST].iov_len = conn->fqdname_len;
 1027     }
 1028 
 1029   /* NOTE: the protocol version indicates what the _client_ can
 1030      understand.  If we send HTTP/1.1, it doesn't mean that the server
 1031      has to speak HTTP/1.1.  In other words, sending an HTTP/1.1
 1032      header leaves it up to the server whether it wants to reply with
 1033      a 1.0 or 1.1 reply.  */
 1034   switch (call->req.version)
 1035     {
 1036     case 0x10000:
 1037       if (param.no_host_hdr)
 1038     {
 1039       call->req.iov[IE_PROTL].iov_base = (caddr_t) http10req_nohost;
 1040       call->req.iov[IE_PROTL].iov_len = sizeof (http10req_nohost) - 1;
 1041     }
 1042       else
 1043     {
 1044       call->req.iov[IE_PROTL].iov_base = (caddr_t) http10req;
 1045       call->req.iov[IE_PROTL].iov_len = sizeof (http10req) - 1;
 1046     }
 1047       break;
 1048 
 1049     case 0x10001:
 1050       if (param.no_host_hdr)
 1051     {
 1052       call->req.iov[IE_PROTL].iov_base = http11req_nohost;
 1053       call->req.iov[IE_PROTL].iov_len = sizeof (http11req_nohost) - 1;
 1054     }
 1055       else
 1056     {
 1057       call->req.iov[IE_PROTL].iov_base = http11req;
 1058       call->req.iov[IE_PROTL].iov_len = sizeof (http11req) - 1;
 1059     }
 1060       break;
 1061 
 1062     default:
 1063       fprintf (stderr, "%s: unexpected version code %x\n",
 1064            prog_name, call->req.version);
 1065       exit (1);
 1066     }
 1067   call->req.iov_index = 0;
 1068   call->req.iov_saved = call->req.iov[0];
 1069 
 1070   /* insert call into connection's send queue: */
 1071   call_inc_ref (call);
 1072   call->sendq_next = 0;
 1073   if (!conn->sendq)
 1074     {
 1075       conn->sendq = conn->sendq_tail = call;
 1076       arg.l = 0;
 1077       event_signal (EV_CALL_SEND_START, (Object *) call, arg);
 1078       if (conn->state >= S_CLOSING)
 1079     return -1;
 1080       call->timeout = param.timeout ? timer_now () + param.timeout : 0.0;
 1081       set_active (conn, &wrfds);
 1082     }
 1083   else
 1084     {
 1085       conn->sendq_tail->sendq_next = call;
 1086       conn->sendq_tail = call;
 1087     }
 1088   return 0;
 1089 }
 1090 
 1091 void
 1092 core_close (Conn *conn)
 1093 {
 1094   Call *call, *call_next;
 1095   Any_Type arg;
 1096   int sd;
 1097 
 1098   if (conn->state >= S_CLOSING)
 1099     return;         /* guard against recursive calls */
 1100   conn->state = S_CLOSING;
 1101 
 1102   if (DBG >= 10)
 1103     fprintf (stderr, "%s.core_close(conn=%p)\n", prog_name, conn);
 1104 
 1105   if (conn->watchdog)
 1106     {
 1107       timer_cancel (conn->watchdog);
 1108       conn->watchdog = 0;
 1109     }
 1110 
 1111   /* first, get rid of all pending calls: */
 1112   for (call = conn->sendq; call; call = call_next)
 1113     {
 1114       call_next = call->sendq_next;
 1115       call_dec_ref (call);
 1116     }
 1117   conn->sendq = 0;
 1118 
 1119   for (call = conn->recvq; call; call = call_next)
 1120     {
 1121       call_next = call->recvq_next;
 1122       call_dec_ref (call);
 1123     }
 1124   conn->recvq = 0;
 1125 
 1126   sd = conn->sd;
 1127   conn->sd = -1;
 1128 
 1129   arg.l = 0;
 1130   event_signal (EV_CONN_CLOSE, (Object *) conn, arg);
 1131   assert (conn->state == S_CLOSING);
 1132 
 1133 #ifdef HAVE_SSL
 1134   if (param.use_ssl)
 1135     SSL_shutdown (conn->ssl);
 1136 #endif
 1137 
 1138   if (sd >= 0)
 1139     {
 1140       close (sd);
 1141       sd_to_conn[sd] = 0;
 1142       FD_CLR (sd, &wrfds);
 1143       FD_CLR (sd, &rdfds);
 1144     }
 1145   if (conn->myport > 0)
 1146     port_put (conn->myport);
 1147 
 1148   /* A connection that has been closed is not useful anymore, so we
 1149      give up the reference obtained when creating the session.  This
 1150      normally initiates destruction of the connection.  */
 1151   conn_dec_ref (conn);
 1152 }
 1153 
 1154 void
 1155 core_loop (void)
 1156 {
 1157   int is_readable, is_writable, n, sd, bit, min_i, max_i, i = 0;
 1158   fd_set readable, writable;
 1159   fd_mask mask;
 1160   Any_Type arg;
 1161   Conn *conn;
 1162 
 1163   while (running)
 1164     {
 1165       struct timeval tv = select_timeout;
 1166 
 1167       timer_tick ();
 1168 
 1169       readable = rdfds;
 1170       writable = wrfds;
 1171       min_i = min_sd / NFDBITS;
 1172       max_i = max_sd / NFDBITS;
 1173 
 1174       SYSCALL (SELECT,
 1175            n = select (max_sd + 1, &readable, &writable, 0, &tv));
 1176 
 1177       ++iteration;
 1178 
 1179       if (n <= 0)
 1180     {
 1181       if (n < 0)
 1182         {
 1183           fprintf (stderr, "%s.core_loop: select failed: %s\n",
 1184                prog_name, strerror (errno));
 1185           exit (1);
 1186         }
 1187       continue;
 1188     }
 1189 
 1190       while (n > 0)
 1191     {
 1192       /* find the index of the fdmask that has something going on: */
 1193       do
 1194         {
 1195           ++i;
 1196           if (i > max_i)
 1197         i = min_i;
 1198 
 1199           assert (i <= max_i);
 1200           mask = readable.fds_bits[i] | writable.fds_bits[i];
 1201         }
 1202       while (!mask);
 1203       bit = 0;
 1204       sd = i*NFDBITS + bit;
 1205       do
 1206         {
 1207           if (mask & 1)
 1208         {
 1209           --n;
 1210 
 1211           is_readable =
 1212             (FD_ISSET (sd, &readable) && FD_ISSET (sd, &rdfds));
 1213           is_writable =
 1214             (FD_ISSET (sd, &writable) && FD_ISSET (sd, &wrfds));
 1215 
 1216           if (is_readable || is_writable)
 1217             {
 1218               /* only handle sockets that haven't timed out yet */
 1219               conn = sd_to_conn[sd];
 1220 
 1221               conn_inc_ref (conn);
 1222 
 1223               if (conn->watchdog)
 1224             {
 1225               timer_cancel (conn->watchdog);
 1226               conn->watchdog = 0;
 1227             }
 1228               if (conn->state == S_CONNECTING)
 1229             {
 1230 #ifdef HAVE_SSL
 1231               if (param.use_ssl)
 1232                 core_ssl_connect (conn);
 1233               else
 1234 #endif
 1235                 if (is_writable)
 1236                   {
 1237                 FD_CLR (sd, &wrfds);
 1238                 conn->state = S_CONNECTED;
 1239                 arg.l = 0;
 1240                 event_signal (EV_CONN_CONNECTED,
 1241                           (Object *) conn, arg);
 1242                   }
 1243             }
 1244               else
 1245             {
 1246               if (is_writable && conn->sendq)
 1247                 do_send (conn);
 1248               if (is_readable && conn->recvq)
 1249                 do_recv (conn);
 1250             }
 1251 
 1252               conn_dec_ref (conn);
 1253 
 1254               if (n > 0)
 1255             timer_tick ();
 1256             }
 1257         }
 1258           mask = ((u_long) mask) >> 1;
 1259           ++sd;
 1260         }
 1261       while (mask);
 1262     }
 1263     }
 1264 }
 1265 
 1266 void
 1267 core_exit (void)
 1268 {
 1269   running = 0;
 1270 
 1271   printf ("Maximum connect burst length: %lu\n", max_burst_len);
 1272 
 1273 #ifdef TIME_SYSCALLS
 1274   {
 1275     u_int count;
 1276     Time time;
 1277     int i;
 1278 
 1279     printf ("Average syscall execution times:\n");
 1280     for (i = 0; i < NELEMS (syscall_name); ++i)
 1281       {
 1282     count = syscall_count[i];
 1283     time = syscall_time[i];
 1284     printf ("\t%s:\t%.3f ms/call (%.3fs total, %u calls)\n",
 1285         syscall_name[i], count > 0 ? 1e3*time/count : 0, time, count);
 1286         
 1287       }
 1288     putchar ('\n');
 1289   }
 1290 #endif
 1291 }