1 /* http_load - multiprocessing http test client
2 **
3 ** Copyright � 1998,1999,2001 by Jef Poskanzer <jef@mail.acme.com>.
4 ** All rights reserved.
5 **
6 ** Redistribution and use in source and binary forms, with or without
7 ** modification, are permitted provided that the following conditions
8 ** are met:
9 ** 1. Redistributions of source code must retain the above copyright
10 **    notice, this list of conditions and the following disclaimer.
11 ** 2. Redistributions in binary form must reproduce the above copyright
12 **    notice, this list of conditions and the following disclaimer in the
13 **    documentation and/or other materials provided with the distribution.
14 **
15 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 ** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 ** SUCH DAMAGE.
26 */
27 
28 #include "tscore/ink_config.h"
29 
30 #include <sys/epoll.h>
31 #include <unistd.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <fcntl.h>
36 #include <sys/types.h>
37 #include <sys/time.h>
38 #include <time.h>
39 #include <sys/resource.h>
40 #include <sys/socket.h>
41 #include <netinet/in.h>
42 #include <arpa/inet.h>
43 #include <netdb.h>
44 #include <errno.h>
45 #include <signal.h>
46 
47 #include <openssl/ssl.h>
48 #include <openssl/rand.h>
49 #include <openssl/err.h>
50 
51 #include "port.h"
52 #include "timers.h"
53 
54 #if defined(AF_INET6) && defined(IN6_IS_ADDR_V4MAPPED)
55 #define USE_IPV6
56 #endif
57 
58 #define max(a, b) ((a) >= (b) ? (a) : (b))
59 #define min(a, b) ((a) <= (b) ? (a) : (b))
60 
61 /* How long a connection can stay idle before we give up on it. */
62 #define IDLE_SECS 60
63 
64 /* Default max bytes/second in throttle mode. */
65 #define THROTTLE 3360
66 
67 /* How often to show progress reports. */
68 #define PROGRESS_SECS 60
69 
70 /* How many file descriptors to not use. */
71 #define RESERVED_FDS 3
72 
73 typedef struct {
74   char *url_str;
75   int protocol;
76   char *hostname;
77   unsigned short port;
78 #ifdef USE_IPV6
79   struct sockaddr_in6 sa;
80 #else  /* USE_IPV6 */
81   struct sockaddr_in sa;
82 #endif /* USE_IPV6 */
83   int sa_len, sock_family, sock_type, sock_protocol;
84   char *filename;
85   int got_bytes;
86   long bytes;
87   int got_checksum;
88   long checksum;
89   char *buf;
90   int buf_bytes;
91   int unique_id_offset;
92   struct {
93     int completed;
94     int max_response;
95     int min_response;
96   } stats;
97 
98 } url;
99 static url *urls;
100 static int num_urls, max_urls, cur_url;
101 
102 typedef struct {
103   char *str;
104   struct sockaddr_in sa;
105 } sip;
106 static sip *sips;
107 static int num_sips, max_sips;
108 
109 /* Protocol symbols. */
110 #define PROTO_HTTP 0
111 #define PROTO_HTTPS 1
112 
113 /* Connection states */
114 typedef enum {
115   CNST_FREE = 0,
116   CNST_CONNECTING,
117   CNST_HEADERS,
118   CNST_READING,
119   CNST_PAUSING,
120 } connection_states;
121 
122 /* States for the Header State Machine */
123 typedef enum {
124   /* SM basic states */
125   HDST_LINE1_PROTOCOL = 0,
126   HDST_LINE1_WS,
127   HDST_LINE1_STATUS,
128   HDST_BOL,
129   HDST_TEXT,
130   HDST_LF,
131   HDST_CR,
132   HDST_CRLF,
133   HDST_CRLFCR,
134   /* SM states for Content-Length header */
135   HDST_C,
136   HDST_CO,
137   HDST_CON,
138   HDST_CONT,
139   HDST_CONTE,
140   HDST_CONTEN,
141   HDST_CONTENT,
142   HDST_CONTENT_,
143   HDST_CONTENT_L,
144   HDST_CONTENT_LE,
145   HDST_CONTENT_LEN,
146   HDST_CONTENT_LENG,
147   HDST_CONTENT_LENGT,
148   HDST_CONTENT_LENGTH,
149   HDST_CONTENT_LENGTH_COLON,
150   HDST_CONTENT_LENGTH_COLON_WS,
151   HDST_CONTENT_LENGTH_COLON_WS_NUM,
152   /* SM states for Connection: close */
153   HDST_CONN,
154   HDST_CONNE,
155   HDST_CONNEC,
156   HDST_CONNECT,
157   HDST_CONNECTI,
158   HDST_CONNECTIO,
159   HDST_CONNECTION,
160   HDST_CONNECTION_COLON,
161   HDST_CONNECTION_COLON_WS,
162   HDST_CONNECTION_COLON_WS_C,
163   HDST_CONNECTION_COLON_WS_CL,
164   HDST_CONNECTION_COLON_WS_CLO,
165   HDST_CONNECTION_COLON_WS_CLOS,
166   HDST_CONNECTION_COLON_WS_CLOSE,
167   /* SM states for Connection: keep-alive */
168   HDST_CONNECTION_COLON_WS_K,
169   HDST_CONNECTION_COLON_WS_KE,
170   HDST_CONNECTION_COLON_WS_KEE,
171   HDST_CONNECTION_COLON_WS_KEEP,
172   HDST_CONNECTION_COLON_WS_KEEP_,
173   HDST_CONNECTION_COLON_WS_KEEP_A,
174   HDST_CONNECTION_COLON_WS_KEEP_AL,
175   HDST_CONNECTION_COLON_WS_KEEP_ALI,
176   HDST_CONNECTION_COLON_WS_KEEP_ALIV,
177   HDST_CONNECTION_COLON_WS_KEEP_ALIVE,
178   /* SM states for Transfer-Encoding: chunked */
179   HDST_T,
180   HDST_TR,
181   HDST_TRA,
182   HDST_TRAN,
183   HDST_TRANS,
184   HDST_TRANSF,
185   HDST_TRANSFE,
186   HDST_TRANSFER,
187   HDST_TRANSFER_DASH,
188   HDST_TRANSFER_DASH_E,
189   HDST_TRANSFER_DASH_EN,
190   HDST_TRANSFER_DASH_ENC,
191   HDST_TRANSFER_DASH_ENCO,
192   HDST_TRANSFER_DASH_ENCOD,
193   HDST_TRANSFER_DASH_ENCODI,
194   HDST_TRANSFER_DASH_ENCODIN,
195   HDST_TRANSFER_DASH_ENCODING,
196   HDST_TRANSFER_DASH_ENCODING_COLON,
197   HDST_TRANSFER_DASH_ENCODING_COLON_WS,
198   HDST_TRANSFER_DASH_ENCODING_COLON_WS_C,
199   HDST_TRANSFER_DASH_ENCODING_COLON_WS_CH,
200   HDST_TRANSFER_DASH_ENCODING_COLON_WS_CHU,
201   HDST_TRANSFER_DASH_ENCODING_COLON_WS_CHUN,
202   HDST_TRANSFER_DASH_ENCODING_COLON_WS_CHUNK,
203   HDST_TRANSFER_DASH_ENCODING_COLON_WS_CHUNKE,
204   HDST_TRANSFER_DASH_ENCODING_COLON_WS_CHUNKED
205 } header_states;
206 
207 typedef struct {
208   int url_num;
209   struct sockaddr_in sa;
210   int sa_len;
211   int conn_fd;
212   SSL *ssl;
213   connection_states conn_state;
214   header_states header_state;
215   int did_connect, did_response;
216   struct timeval started_at;
217   struct timeval connect_at;
218   struct timeval request_at;
219   struct timeval response_at;
220   Timer *idle_timer;
221   Timer *wakeup_timer;
222   long content_length;
223   long bytes;
224   long checksum;
225   int http_status;
226   int reusable;
227   int keep_alive;
228   int chunked;
229   unsigned int unique_id;
230   struct {
231     int connections;
232     int requests;
233     int responses;
234     int requests_per_connection;
235   } stats;
236 } connection;
237 
238 static connection *connections;
239 static int max_connections, num_connections, max_parallel, num_ka_conns;
240 
241 static int http_status_counts[1000]; /* room for all three-digit statuses */
242 static char *argv0;
243 static int do_checksum, do_throttle, do_verbose, do_jitter, do_proxy;
244 static int do_accept_gzip, do_sequential;
245 static float throttle;
246 static int idle_secs;
247 static char *proxy_hostname;
248 static unsigned short proxy_port;
249 static char *user_agent;
250 static char *cookie;
251 static char *http_version;
252 static int is_http_1_1;
253 static int ignore_bytes;
254 static int keep_alive;
255 static char *extra_headers;
256 static unsigned int unique_id_counter;
257 static int unique_id = 0;
258 static int socket_pool;
259 static int epfd;
260 static int max_connect_failures = 0;
261 
262 static struct timeval start_at;
263 static int fetches_started, connects_completed, responses_completed, fetches_completed;
264 static long long total_bytes;
265 static long long total_connect_usecs, max_connect_usecs, min_connect_usecs;
266 static long long total_response_usecs, max_response_usecs, min_response_usecs;
267 int total_timeouts, total_badbytes, total_badchecksums;
268 
269 static long start_interval, low_interval, high_interval, range_interval;
270 
271 static SSL_CTX *ssl_ctx = (SSL_CTX *)0;
272 static char *cipher     = (char *)0;
273 
274 /* Forwards. */
275 static void usage(void);
276 static void read_url_file(char *url_file);
277 static void lookup_address(int url_num);
278 static void read_sip_file(char *sip_file);
279 static void start_connection(struct timeval *nowP);
280 static void start_socket(int url_num, int cnum, struct timeval *nowP);
281 static void handle_connect(int cnum, struct timeval *nowP, int double_check);
282 static void handle_read(int cnum, struct timeval *nowP);
283 static void idle_connection(ClientData client_data, struct timeval *nowP);
284 static void wakeup_connection(ClientData client_data, struct timeval *nowP);
285 static void close_connection(int cnum);
286 static void progress_report(ClientData client_data, struct timeval *nowP);
287 static void start_timer(ClientData client_data, struct timeval *nowP);
288 static void end_timer(ClientData client_data, struct timeval *nowP);
289 static void finish(struct timeval *nowP);
290 static long long delta_timeval(struct timeval *start, struct timeval *finish);
291 static void *malloc_check(size_t size);
292 static void *realloc_check(void *ptr, size_t size);
293 static char *strdup_check(char *str);
294 static void check(void *ptr);
295 
296 int
main(int argc,char ** argv)297 main(int argc, char **argv)
298 {
299   int argn;
300   int start;
301 #define START_NONE 0
302 #define START_PARALLEL 1
303 #define START_RATE 2
304   int start_parallel = -1, start_rate = -1;
305   int end;
306 #define END_NONE 0
307 #define END_FETCHES 1
308 #define END_SECONDS 2
309   int end_fetches = -1, end_seconds = -1;
310   int cnum;
311   char *url_file;
312   char *sip_file;
313 #ifdef RLIMIT_NOFILE
314   struct rlimit limits;
315 #endif /* RLIMIT_NOFILE */
316   struct epoll_event *events;
317   struct timeval now;
318   int i, r, periodic_tmr;
319 
320   max_connections = 64 - RESERVED_FDS; /* a guess */
321 #ifdef RLIMIT_NOFILE
322   /* Try and increase the limit on # of files to the maximum. */
323   if (getrlimit(RLIMIT_NOFILE, &limits) == 0) {
324     if (limits.rlim_cur != limits.rlim_max) {
325       if (limits.rlim_max == RLIM_INFINITY)
326         limits.rlim_cur = 8192; /* arbitrary */
327       else if (limits.rlim_max > limits.rlim_cur)
328         limits.rlim_cur = limits.rlim_max;
329       (void)setrlimit(RLIMIT_NOFILE, &limits);
330     }
331     max_connections = limits.rlim_cur - RESERVED_FDS;
332   }
333 #endif /* RLIMIT_NOFILE */
334 
335   /* Parse args. */
336   argv0       = argv[0];
337   argn        = 1;
338   do_checksum = do_throttle = do_verbose = do_jitter = do_proxy = 0;
339   do_accept_gzip = do_sequential = 0;
340   throttle                       = THROTTLE;
341   sip_file                       = (char *)0;
342   user_agent                     = VERSION;
343   cookie                         = NULL;
344   http_version                   = "1.1";
345   is_http_1_1                    = 1;
346   idle_secs                      = IDLE_SECS;
347   start                          = START_NONE;
348   end                            = END_NONE;
349   keep_alive                     = 0;
350   socket_pool                    = 0;
351   extra_headers                  = NULL;
352   while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') {
353     if (strncmp(argv[argn], "-checksum", strlen(argv[argn])) == 0)
354       do_checksum = 1;
355     else if (strncmp(argv[argn], "-sequential", strlen(argv[argn])) == 0)
356       do_sequential = 1;
357     else if (strncmp(argv[argn], "-throttle", strlen(argv[argn])) == 0)
358       do_throttle = 1;
359     else if (strncmp(argv[argn], "-Throttle", strlen(argv[argn])) == 0 && argn + 1 < argc) {
360       do_throttle = 1;
361       throttle    = atoi(argv[++argn]) / 10.0;
362     } else if (strncmp(argv[argn], "-verbose", strlen(argv[argn])) == 0)
363       do_verbose = 1;
364     else if (strncmp(argv[argn], "-timeout", strlen(argv[argn])) == 0 && argn + 1 < argc)
365       idle_secs = atoi(argv[++argn]);
366     else if (strncmp(argv[argn], "-jitter", strlen(argv[argn])) == 0)
367       do_jitter = 1;
368     else if (strncmp(argv[argn], "-accept_gzip", strlen(argv[argn])) == 0)
369       do_accept_gzip = 1;
370     else if (strncmp(argv[argn], "-parallel", strlen(argv[argn])) == 0 && argn + 1 < argc) {
371       start          = START_PARALLEL;
372       start_parallel = atoi(argv[++argn]);
373       if (start_parallel < 1) {
374         (void)fprintf(stderr, "%s: parallel must be at least 1\n", argv0);
375         exit(1);
376       }
377       if (start_parallel > max_connections) {
378         (void)fprintf(stderr, "%s: parallel may be at most %d\n", argv0, max_connections);
379         exit(1);
380       }
381     } else if (strncmp(argv[argn], "-rate", strlen(argv[argn])) == 0 && argn + 1 < argc) {
382       start      = START_RATE;
383       start_rate = atoi(argv[++argn]);
384       if (start_rate < 1) {
385         (void)fprintf(stderr, "%s: rate must be at least 1\n", argv0);
386         exit(1);
387       }
388       if (start_rate > 1000) {
389         (void)fprintf(stderr, "%s: rate may be at most 1000\n", argv0);
390         exit(1);
391       }
392     } else if (strncmp(argv[argn], "-sockets", strlen(argv[argn])) == 0 && argn + 1 < argc) {
393       socket_pool = atoi(argv[++argn]) - 1;
394       if (socket_pool < 0) {
395         (void)fprintf(stderr, "%s: sockets must be at least 1\n", argv0);
396         exit(1);
397       }
398     } else if (strncmp(argv[argn], "-fetches", strlen(argv[argn])) == 0 && argn + 1 < argc) {
399       end         = END_FETCHES;
400       end_fetches = atoi(argv[++argn]);
401       if (end_fetches < 1) {
402         (void)fprintf(stderr, "%s: fetches must be at least 1\n", argv0);
403         exit(1);
404       }
405     } else if (strncmp(argv[argn], "-seconds", strlen(argv[argn])) == 0 && argn + 1 < argc) {
406       end         = END_SECONDS;
407       end_seconds = atoi(argv[++argn]);
408       if (end_seconds < 1) {
409         (void)fprintf(stderr, "%s: seconds must be at least 1\n", argv0);
410         exit(1);
411       }
412     } else if (strncmp(argv[argn], "-keep_alive", strlen(argv[argn])) == 0 && argn + 1 < argc) {
413       keep_alive = atoi(argv[++argn]);
414       if (keep_alive < 1) {
415         (void)fprintf(stderr, "%s: keep_alive must be at least 1\n", argv0);
416         exit(1);
417       }
418     } else if (strncmp(argv[argn], "-unique_id", strlen(argv[argn])) == 0) {
419       unique_id = 1;
420     } else if (strncmp(argv[argn], "-sip", strlen(argv[argn])) == 0 && argn + 1 < argc)
421       sip_file = argv[++argn];
422     else if (strncmp(argv[argn], "-agent", strlen(argv[argn])) == 0 && argn + 1 < argc)
423       user_agent = argv[++argn];
424     else if (strncmp(argv[argn], "-cookie", strlen(argv[argn])) == 0 && argn + 1 < argc)
425       cookie = argv[++argn];
426     else if (strncmp(argv[argn], "-ignore_bytes", strlen(argv[argn])) == 0)
427       ignore_bytes = 1;
428     else if (strncmp(argv[argn], "-max_connect_failures", strlen(argv[argn])) == 0) {
429       max_connect_failures = atoi(argv[++argn]);
430       if (max_connect_failures < 1) {
431         (void)fprintf(stderr, "%s: max_connection failures should be 1 or higher\n", argv0);
432         exit(1);
433       }
434     } else if (strncmp(argv[argn], "-header", strlen(argv[argn])) == 0 && argn + 1 < argc) {
435       if (extra_headers) {
436         strcat(extra_headers, "\r\n");
437         strcat(extra_headers, argv[++argn]);
438       } else {
439         extra_headers = malloc_check(65536);
440         strncpy(extra_headers, argv[++argn], 65536 - 1);
441         extra_headers[65536] = '\0';
442       }
443     } else if (strncmp(argv[argn], "-http_version", strlen(argv[argn])) == 0 && argn + 1 < argc) {
444       http_version = argv[++argn];
445       is_http_1_1  = (strcmp(http_version, "1.1") == 0);
446     } else if (strncmp(argv[argn], "-cipher", strlen(argv[argn])) == 0 && argn + 1 < argc) {
447       cipher = argv[++argn];
448       if (strcasecmp(cipher, "fastsec") == 0)
449         cipher = "RC4-MD5";
450       else if (strcasecmp(cipher, "highsec") == 0)
451         cipher = "DES-CBC3-SHA";
452       else if (strcasecmp(cipher, "paranoid") == 0)
453         cipher = "AES256-SHA";
454     } else if (strncmp(argv[argn], "-proxy", strlen(argv[argn])) == 0 && argn + 1 < argc) {
455       char *colon;
456       do_proxy       = 1;
457       proxy_hostname = argv[++argn];
458       colon          = strchr(proxy_hostname, ':');
459       if (colon == (char *)0)
460         proxy_port = 80;
461       else {
462         proxy_port = (unsigned short)atoi(colon + 1);
463         *colon     = '\0';
464       }
465     } else
466       usage();
467     ++argn;
468   }
469   if (argn + 1 != argc)
470     usage();
471   if (start == START_NONE || end == END_NONE)
472     usage();
473   if (do_jitter && start != START_RATE)
474     usage();
475   url_file = argv[argn];
476 
477   /* Read in and parse the URLs. */
478   read_url_file(url_file);
479 
480   /* Read in the source IP file, if specified. */
481   if (sip_file != (char *)0)
482     read_sip_file(sip_file);
483 
484   /* Initialize the connections table. */
485   if (start == START_PARALLEL)
486     max_connections = start_parallel;
487   connections = (connection *)malloc_check(max_connections * sizeof(connection));
488   for (cnum = 0; cnum < max_connections; ++cnum) {
489     connections[cnum].conn_state        = CNST_FREE;
490     connections[cnum].reusable          = 0;
491     connections[cnum].stats.requests    = 0;
492     connections[cnum].stats.responses   = 0;
493     connections[cnum].stats.connections = 0;
494   }
495   num_connections = max_parallel = num_ka_conns = 0;
496 
497   /* Initialize the HTTP status-code histogram. */
498   for (i = 0; i < 1000; ++i)
499     http_status_counts[i] = 0;
500 
501   /* Initialize the statistics. */
502   fetches_started      = 0;
503   connects_completed   = 0;
504   responses_completed  = 0;
505   fetches_completed    = 0;
506   total_bytes          = 0;
507   total_connect_usecs  = 0;
508   max_connect_usecs    = 0;
509   min_connect_usecs    = 1000000000L;
510   total_response_usecs = 0;
511   max_response_usecs   = 0;
512   min_response_usecs   = 1000000000L;
513   total_timeouts       = 0;
514   total_badbytes       = 0;
515   total_badchecksums   = 0;
516 
517   /* Initialize epoll() and kqueue() etc. */
518   epfd = epoll_create(max_connections);
519   if (epfd == -1) {
520     perror("epoll_create");
521     exit(1);
522   }
523   events = malloc(sizeof(struct epoll_event) * max_connections);
524 
525 /* Initialize the random number generator. */
526 #ifdef HAVE_SRANDOMDEV
527   srandomdev();
528 #else
529   srandom((int)time((time_t *)0) ^ getpid());
530 #endif
531 
532   /* Initialize the rest. */
533   tmr_init();
534   (void)gettimeofday(&now, (struct timezone *)0);
535   start_at = now;
536   if (do_verbose)
537     (void)tmr_create(&now, progress_report, JunkClientData, PROGRESS_SECS * 1000L, 1);
538   if (start == START_RATE) {
539     start_interval = 1000L / start_rate;
540     if (do_jitter) {
541       low_interval   = start_interval * 9 / 10;
542       high_interval  = start_interval * 11 / 10;
543       range_interval = high_interval - low_interval + 1;
544     }
545     (void)tmr_create(&now, start_timer, JunkClientData, start_interval, !do_jitter);
546   }
547   if (end == END_SECONDS)
548     (void)tmr_create(&now, end_timer, JunkClientData, end_seconds * 1000L, 0);
549   (void)signal(SIGPIPE, SIG_IGN);
550 
551   /* Main loop. */
552   for (;;) {
553     if (end == END_FETCHES && fetches_completed >= end_fetches)
554       finish(&now);
555 
556     if (start == START_PARALLEL) {
557       /* See if we need to start any new connections; but at most 10. */
558       for (i = 0; i < 10 && num_connections < start_parallel && (end != END_FETCHES || fetches_started < end_fetches); ++i) {
559         start_connection(&now);
560         (void)gettimeofday(&now, (struct timezone *)0);
561         tmr_run(&now);
562       }
563     }
564 
565     r = epoll_wait(epfd, events, max_connections, tmr_mstimeout(&now));
566 #ifdef DEBUG
567     fprintf(stderr, "epoll_wait() got %d events\n", r);
568 #endif
569     if (r < 0) {
570       perror("epoll_wait");
571       exit(1);
572     }
573     (void)gettimeofday(&now, (struct timezone *)0);
574 
575     /* Service them. */
576     periodic_tmr = 50;
577     while (r-- > 0) {
578       if (--periodic_tmr == 0) {
579         periodic_tmr = 50;
580         tmr_run(&now);
581       }
582       cnum = events[r].data.u32;
583 #ifdef DEBUG
584       fprintf(stderr, "processing event %d (%d), for CNUM %d\n", r + 1, events[r].events, cnum);
585 #endif
586       switch (connections[cnum].conn_state) {
587       case CNST_CONNECTING:
588         handle_connect(cnum, &now, 1);
589         break;
590       case CNST_HEADERS:
591       case CNST_READING:
592         handle_read(cnum, &now);
593         break;
594       default:
595         /* Nothing */
596         break;
597       }
598     }
599     /* And run the timers. */
600     tmr_run(&now);
601   }
602 
603   /* NOT_REACHED */
604 }
605 
606 static void
usage(void)607 usage(void)
608 {
609   (void)fprintf(stderr,
610                 "usage:	%s [-checksum] [-throttle] [-sequential] [-proxy host:port]\n"
611                 "		[-verbose] [-timeout secs] [-sip sip_file] [-agent user_agent]\n"
612                 "		[-cookie http_cookie] [-accept_gzip] [-http_version version_str]\n"
613                 "		[-keep_alive num_reqs_per_conn] [-unique_id]\n"
614                 "		[-max_connect_failures N] [-ignore_bytes] [ [-header str] ... ]\n",
615                 argv0);
616   (void)fprintf(stderr, "	[-cipher str]\n");
617   (void)fprintf(stderr, "	-parallel N | -rate N [-jitter]\n");
618   (void)fprintf(stderr, "	-fetches N | -seconds N\n");
619   (void)fprintf(stderr, "	url_file\n");
620   (void)fprintf(stderr, "One start specifier, either -parallel or -rate, is required.\n");
621   (void)fprintf(stderr, "One end specifier, either -fetches or -seconds, is required.\n");
622   exit(1);
623 }
624 
625 static void
read_url_file(char * url_file)626 read_url_file(char *url_file)
627 {
628   char line[5000], hostname[5000];
629   char *http    = "http://";
630   int http_len  = strlen(http);
631   char *https   = "https://";
632   int https_len = strlen(https);
633   int proto_len, host_len;
634   char *cp;
635 
636   FILE *fp = fopen(url_file, "r");
637   if (fp == NULL) {
638     perror(url_file);
639     exit(1);
640   }
641 
642   max_urls = 100;
643   urls     = (url *)malloc_check(max_urls * sizeof(url));
644   num_urls = 0;
645   cur_url  = 0;
646 
647   /* The Host: header can either be user provided (via -header), or
648      constructed by the URL host and possibly port (if not port 80) */
649 
650   char hdr_buf[2048];
651   int hdr_bytes = 0;
652   hdr_bytes += snprintf(&hdr_buf[hdr_bytes], sizeof(hdr_buf) - hdr_bytes, "User-Agent: %s\r\n", user_agent);
653   if (cookie)
654     hdr_bytes += snprintf(&hdr_buf[hdr_bytes], sizeof(hdr_buf) - hdr_bytes, "Cookie: %s\r\n", cookie);
655   if (do_accept_gzip)
656     hdr_bytes += snprintf(&hdr_buf[hdr_bytes], sizeof(hdr_buf) - hdr_bytes, "Accept-Encoding: gzip\r\n");
657   /* Add Connection: keep-alive header if keep_alive requested, and version != "1.1" */
658   if ((keep_alive > 0) && !is_http_1_1)
659     hdr_bytes += snprintf(&hdr_buf[hdr_bytes], sizeof(hdr_buf) - hdr_bytes, "Connection: keep-alive\r\n");
660   if (extra_headers != NULL) {
661     hdr_bytes += snprintf(&hdr_buf[hdr_bytes], sizeof(hdr_buf) - hdr_bytes, "%s\r\n", extra_headers);
662   }
663   snprintf(&hdr_buf[hdr_bytes], sizeof(hdr_buf) - hdr_bytes, "\r\n");
664 
665   while (fgets(line, sizeof(line), fp) != (char *)0) {
666     char req_buf[2048];
667     int req_bytes = 0;
668 
669     /* Nuke trailing newline. */
670     if (line[strlen(line) - 1] == '\n')
671       line[strlen(line) - 1] = '\0';
672 
673     /* Check for room in urls. */
674     if (num_urls >= max_urls) {
675       max_urls *= 2;
676       urls = (url *)realloc_check((void *)urls, max_urls * sizeof(url));
677     }
678 
679     /* Add to table. */
680     urls[num_urls].url_str = strdup_check(line);
681 
682     /* Parse it. */
683     if (strncmp(http, line, http_len) == 0) {
684       proto_len               = http_len;
685       urls[num_urls].protocol = PROTO_HTTP;
686     } else if (strncmp(https, line, https_len) == 0) {
687       proto_len               = https_len;
688       urls[num_urls].protocol = PROTO_HTTPS;
689     } else {
690       fprintf(stderr, "%s: unknown protocol - %s\n", argv0, line);
691       exit(1);
692     }
693     for (cp = line + proto_len; *cp != '\0' && *cp != ':' && *cp != '/'; ++cp)
694       ;
695     host_len = cp - line;
696     host_len -= proto_len;
697     strncpy(hostname, line + proto_len, host_len);
698     hostname[host_len]      = '\0';
699     urls[num_urls].hostname = strdup_check(hostname);
700     if (*cp == ':') {
701       urls[num_urls].port = (unsigned short)atoi(++cp);
702       while (*cp != '\0' && *cp != '/')
703         ++cp;
704     } else if (urls[num_urls].protocol == PROTO_HTTPS)
705       urls[num_urls].port = 443;
706     else
707       urls[num_urls].port = 80;
708     if (*cp == '\0')
709       urls[num_urls].filename = strdup_check("/");
710     else
711       urls[num_urls].filename = strdup_check(cp);
712 
713     lookup_address(num_urls);
714 
715     urls[num_urls].got_bytes        = 0;
716     urls[num_urls].got_checksum     = 0;
717     urls[num_urls].unique_id_offset = 0;
718 
719     /* Pre-generate the request string, major performance improvement. */
720     if (do_proxy) {
721       req_bytes = snprintf(req_buf, sizeof(req_buf), "GET %s://%.500s:%d%.500s HTTP/%s\r\n",
722                            urls[num_urls].protocol == PROTO_HTTPS ? "https" : "http", urls[num_urls].hostname,
723                            (int)urls[num_urls].port, urls[num_urls].filename, http_version);
724     } else
725       req_bytes = snprintf(req_buf, sizeof(req_buf), "GET %.500s HTTP/%s\r\n", urls[num_urls].filename, http_version);
726 
727     if (extra_headers == NULL || !strstr(extra_headers, "Host:")) {
728       if (urls[num_urls].port != 80)
729         req_bytes += snprintf(&req_buf[req_bytes], sizeof(req_buf) - req_bytes, "Host: %s:%d\r\n", urls[num_urls].hostname,
730                               urls[num_urls].port);
731       else
732         req_bytes += snprintf(&req_buf[req_bytes], sizeof(req_buf) - req_bytes, "Host: %s\r\n", urls[num_urls].hostname);
733     }
734     if (unique_id == 1) {
735       req_bytes += snprintf(&req_buf[req_bytes], sizeof(req_buf) - req_bytes, "X-ID: ");
736       urls[num_urls].unique_id_offset = req_bytes;
737       req_bytes += snprintf(&req_buf[req_bytes], sizeof(req_buf) - req_bytes, "%09u\r\n", 0);
738     }
739 
740     // add the common hdr here
741     req_bytes += snprintf(&req_buf[req_bytes], sizeof(req_buf) - req_bytes, hdr_buf, 0);
742 
743     urls[num_urls].buf_bytes = req_bytes;
744     urls[num_urls].buf       = strdup_check(req_buf);
745 
746     ++num_urls;
747   }
748   fclose(fp);
749 }
750 
751 static void
lookup_address(int url_num)752 lookup_address(int url_num)
753 {
754   if (do_proxy && url_num > 0) {
755     urls[url_num].sock_family   = urls[url_num - 1].sock_family;
756     urls[url_num].sock_type     = urls[url_num - 1].sock_type;
757     urls[url_num].sock_protocol = urls[url_num - 1].sock_protocol;
758     urls[url_num].sa_len        = urls[url_num - 1].sa_len;
759     urls[url_num].sa            = urls[url_num - 1].sa;
760     return;
761   }
762   int i;
763   char *hostname;
764   unsigned short port;
765 #ifdef USE_IPV6
766   struct addrinfo hints;
767   char portstr[10];
768   int gaierr;
769   struct addrinfo *ai;
770   struct addrinfo *ai2;
771   struct addrinfo *aiv4;
772   struct addrinfo *aiv6;
773 #else  /* USE_IPV6 */
774   struct hostent *he;
775 #endif /* USE_IPV6 */
776 
777   urls[url_num].sa_len = sizeof(urls[url_num].sa);
778   (void)memset((void *)&urls[url_num].sa, 0, urls[url_num].sa_len);
779 
780   if (do_proxy)
781     hostname = proxy_hostname;
782   else
783     hostname = urls[url_num].hostname;
784   if (do_proxy)
785     port = proxy_port;
786   else
787     port = urls[url_num].port;
788 
789   /* Try to do this using existing information  */
790   for (i = 0; i < url_num; i++) {
791     if ((strcmp(hostname, urls[i].hostname) == 0) && (port == urls[i].port)) {
792       urls[url_num].sock_family   = urls[i].sock_family;
793       urls[url_num].sock_type     = urls[i].sock_type;
794       urls[url_num].sock_protocol = urls[i].sock_protocol;
795       urls[url_num].sa            = urls[i].sa;
796       urls[url_num].sa_len        = urls[i].sa_len;
797       return;
798     }
799   }
800 
801 #ifdef USE_IPV6
802 
803   (void)memset(&hints, 0, sizeof(hints));
804   hints.ai_family   = PF_UNSPEC;
805   hints.ai_socktype = SOCK_STREAM;
806   (void)snprintf(portstr, sizeof(portstr), "%d", (int)port);
807   if ((gaierr = getaddrinfo(hostname, portstr, &hints, &ai)) != 0) {
808     (void)fprintf(stderr, "%s: getaddrinfo %s - %s\n", argv0, hostname, gai_strerror(gaierr));
809     exit(1);
810   }
811 
812   /* Find the first IPv4 and IPv6 entries. */
813   aiv4 = (struct addrinfo *)0;
814   aiv6 = (struct addrinfo *)0;
815   for (ai2 = ai; ai2 != (struct addrinfo *)0; ai2 = ai2->ai_next) {
816     switch (ai2->ai_family) {
817     case AF_INET:
818       if (aiv4 == (struct addrinfo *)0)
819         aiv4 = ai2;
820       break;
821     case AF_INET6:
822       if (aiv6 == (struct addrinfo *)0)
823         aiv6 = ai2;
824       break;
825     }
826   }
827 
828   /* If there's an IPv4 address, use that, otherwise try IPv6. */
829   if (aiv4 != (struct addrinfo *)0) {
830     if (sizeof(urls[url_num].sa) < aiv4->ai_addrlen) {
831       (void)fprintf(stderr, "%s - sockaddr too small (%lu < %lu)\n", hostname, (unsigned long)sizeof(urls[url_num].sa),
832                     (unsigned long)aiv4->ai_addrlen);
833       exit(1);
834     }
835     urls[url_num].sock_family   = aiv4->ai_family;
836     urls[url_num].sock_type     = aiv4->ai_socktype;
837     urls[url_num].sock_protocol = aiv4->ai_protocol;
838     urls[url_num].sa_len        = aiv4->ai_addrlen;
839     (void)memmove(&urls[url_num].sa, aiv4->ai_addr, aiv4->ai_addrlen);
840     freeaddrinfo(ai);
841     return;
842   }
843   if (aiv6 != (struct addrinfo *)0) {
844     if (sizeof(urls[url_num].sa) < aiv6->ai_addrlen) {
845       (void)fprintf(stderr, "%s - sockaddr too small (%lu < %lu)\n", hostname, (unsigned long)sizeof(urls[url_num].sa),
846                     (unsigned long)aiv6->ai_addrlen);
847       exit(1);
848     }
849     urls[url_num].sock_family   = aiv6->ai_family;
850     urls[url_num].sock_type     = aiv6->ai_socktype;
851     urls[url_num].sock_protocol = aiv6->ai_protocol;
852     urls[url_num].sa_len        = aiv6->ai_addrlen;
853     (void)memmove(&urls[url_num].sa, aiv6->ai_addr, aiv6->ai_addrlen);
854     freeaddrinfo(ai);
855     return;
856   }
857 
858   (void)fprintf(stderr, "%s: no valid address found for host %s\n", argv0, hostname);
859   exit(1);
860 
861 #else /* USE_IPV6 */
862 
863   /* No match in previous lookups */
864   he = gethostbyname(hostname);
865   if (he == (struct hostent *)0) {
866     (void)fprintf(stderr, "%s: unknown host - %s\n", argv0, hostname);
867     exit(1);
868   }
869   urls[url_num].sock_family = urls[url_num].sa.sin_family = he->h_addrtype;
870   urls[url_num].sock_type                                 = SOCK_STREAM;
871   urls[url_num].sock_protocol                             = 0;
872   urls[url_num].sa_len                                    = sizeof(urls[url_num].sa);
873   (void)memmove(&urls[url_num].sa.sin_addr, he->h_addr, he->h_length);
874   urls[url_num].sa.sin_port = htons(port);
875 
876 #endif /* USE_IPV6 */
877 }
878 
879 static void
read_sip_file(char * sip_file)880 read_sip_file(char *sip_file)
881 {
882   FILE *fp;
883   char line[5000];
884 
885   fp = fopen(sip_file, "r");
886   if (fp == (FILE *)0) {
887     perror(sip_file);
888     exit(1);
889   }
890 
891   max_sips = 100;
892   sips     = (sip *)malloc_check(max_sips * sizeof(sip));
893   num_sips = 0;
894   while (fgets(line, sizeof(line), fp) != (char *)0) {
895     /* Nuke trailing newline. */
896     if (line[strlen(line) - 1] == '\n')
897       line[strlen(line) - 1] = '\0';
898 
899     /* Check for room in sips. */
900     if (num_sips >= max_sips) {
901       max_sips *= 2;
902       sips = (sip *)realloc_check((void *)sips, max_sips * sizeof(sip));
903     }
904 
905     /* Add to table. */
906     sips[num_sips].str = strdup_check(line);
907     (void)memset((void *)&sips[num_sips].sa, 0, sizeof(sips[num_sips].sa));
908     if (!inet_aton(sips[num_sips].str, &sips[num_sips].sa.sin_addr)) {
909       (void)fprintf(stderr, "%s: cannot convert source IP address %s\n", argv0, sips[num_sips].str);
910       exit(1);
911     }
912     ++num_sips;
913   }
914   fclose(fp);
915 }
916 
917 static void
start_connection(struct timeval * nowP)918 start_connection(struct timeval *nowP)
919 {
920   int cnum, url_num;
921   static int cycle_slot = 0;
922 
923   /* Find an empty connection slot. */
924   if (socket_pool > 0) {
925     int prev_cycle_slot = cycle_slot;
926 
927     while (1) {
928       ++cycle_slot;
929       if (cycle_slot > socket_pool)
930         cycle_slot = 0;
931       if (prev_cycle_slot == cycle_slot) {
932         return;
933 #if 0
934         /* Unused right now, not sure why */
935         printf("Warning: cycling through all socket slots\n");
936         tmr_run(nowP);
937 #endif
938       }
939       if (connections[cycle_slot].conn_state == CNST_FREE) {
940         /* Choose a URL. */
941         if (do_sequential) {
942           url_num = cur_url++;
943           if (cur_url >= num_urls)
944             cur_url = 0;
945         } else {
946           url_num = ((unsigned long)random()) % ((unsigned int)num_urls);
947         }
948 
949         /* Start the socket. */
950         start_socket(url_num, cycle_slot, nowP);
951         if (connections[cycle_slot].conn_state != CNST_FREE) {
952           ++num_connections;
953           /*
954              if ( num_connections > max_parallel )
955              max_parallel = num_connections;
956            */
957         }
958         ++fetches_started;
959         return;
960       }
961     }
962   } else {
963     for (cnum = 0; cnum < max_connections; ++cnum)
964       if (connections[cnum].conn_state == CNST_FREE) {
965         /* Choose a URL. */
966         if (do_sequential) {
967           url_num = cur_url++;
968           if (cur_url >= num_urls)
969             cur_url = 0;
970         } else {
971           url_num = ((unsigned long)random()) % ((unsigned int)num_urls);
972         }
973         /* Start the socket. */
974         start_socket(url_num, cnum, nowP);
975         if (connections[cnum].conn_state != CNST_FREE) {
976           ++num_connections;
977           /*
978              if ( num_connections > max_parallel )
979              max_parallel = num_connections;
980            */
981         }
982         ++fetches_started;
983         return;
984       }
985   }
986   /* No slots left. */
987   (void)fprintf(stderr, "%s: ran out of connection slots\n", argv0);
988   finish(nowP);
989 }
990 
991 static void
start_socket(int url_num,int cnum,struct timeval * nowP)992 start_socket(int url_num, int cnum, struct timeval *nowP)
993 {
994   ClientData client_data;
995   int flags;
996   int sip_num;
997   int reusable = connections[cnum].reusable;
998 
999   /* Start filling in the connection slot. */
1000   connections[cnum].url_num        = url_num;
1001   connections[cnum].started_at     = *nowP;
1002   client_data.i                    = cnum;
1003   connections[cnum].did_connect    = 0;
1004   connections[cnum].did_response   = 0;
1005   connections[cnum].idle_timer     = tmr_create(nowP, idle_connection, client_data, idle_secs * 1000L, 0);
1006   connections[cnum].wakeup_timer   = (Timer *)0;
1007   connections[cnum].content_length = -1;
1008   connections[cnum].bytes          = 0;
1009   connections[cnum].checksum       = 0;
1010   connections[cnum].http_status    = -1;
1011   connections[cnum].reusable       = 0;
1012   connections[cnum].chunked        = 0;
1013   connections[cnum].unique_id      = 0;
1014 
1015   // set unique id
1016   if (unique_id == 1 && urls[url_num].unique_id_offset > 0) {
1017     char buffer[10];
1018     snprintf(buffer, 10, "%09u", ++unique_id_counter);
1019     //      fprintf(stderr, "%s %s\n", buffer, &urls[url_num].buf[unique_id_offset]);
1020     memcpy((void *)&urls[url_num].buf[urls[url_num].unique_id_offset], (void *)buffer, 9);
1021     connections[cnum].unique_id = unique_id_counter;
1022   }
1023 
1024   /* Make a socket. */
1025   if (!reusable) {
1026     struct epoll_event ev;
1027 
1028     connections[cnum].keep_alive = keep_alive;
1029     connections[cnum].conn_fd    = socket(urls[url_num].sock_family, urls[url_num].sock_type, urls[url_num].sock_protocol);
1030     if (connections[cnum].conn_fd < 0) {
1031       perror(urls[url_num].url_str);
1032       return;
1033     }
1034     connections[cnum].stats.connections++;
1035 
1036     /* Set the file descriptor to no-delay mode. */
1037     flags = fcntl(connections[cnum].conn_fd, F_GETFL, 0);
1038     if (flags == -1) {
1039       perror(urls[url_num].url_str);
1040       (void)close(connections[cnum].conn_fd);
1041       return;
1042     }
1043     if (fcntl(connections[cnum].conn_fd, F_SETFL, flags | O_NDELAY) < 0) {
1044       perror(urls[url_num].url_str);
1045       (void)close(connections[cnum].conn_fd);
1046       return;
1047     }
1048 
1049     if (num_sips > 0) {
1050       /* Try a random source IP address. */
1051       sip_num = ((unsigned long)random()) % ((unsigned int)num_sips);
1052       if (bind(connections[cnum].conn_fd, (struct sockaddr *)&sips[sip_num].sa, sizeof(sips[sip_num].sa)) < 0) {
1053         perror("binding local address");
1054         (void)close(connections[cnum].conn_fd);
1055         return;
1056       }
1057     }
1058     ev.events   = EPOLLOUT;
1059     ev.data.u32 = cnum;
1060 #ifdef DEBUG
1061     fprintf(stderr, "Adding FD %d for CNUM %d\n", connections[cnum].conn_fd, cnum);
1062 #endif
1063     if (epoll_ctl(epfd, EPOLL_CTL_ADD, connections[cnum].conn_fd, &ev)) {
1064       perror("epoll add fd");
1065       (void)close(connections[cnum].conn_fd);
1066       return;
1067     }
1068     /* Connect to the host. */
1069     connections[cnum].sa_len = urls[url_num].sa_len;
1070     (void)memmove((void *)&connections[cnum].sa, (void *)&urls[url_num].sa, urls[url_num].sa_len);
1071     connections[cnum].connect_at = *nowP;
1072     if (connect(connections[cnum].conn_fd, (struct sockaddr *)&connections[cnum].sa, connections[cnum].sa_len) < 0) {
1073       if (errno == EINPROGRESS) {
1074         connections[cnum].conn_state = CNST_CONNECTING;
1075         return;
1076       } else {
1077         /* remove the FD from the epoll descriptor */
1078         if (epoll_ctl(epfd, EPOLL_CTL_DEL, connections[cnum].conn_fd, &ev) < 0)
1079           perror("epoll delete fd");
1080         perror(urls[url_num].url_str);
1081         (void)close(connections[cnum].conn_fd);
1082         return;
1083       }
1084     }
1085 
1086     /* Connect succeeded instantly, so handle it now. */
1087     (void)gettimeofday(nowP, (struct timezone *)0);
1088     handle_connect(cnum, nowP, 0);
1089   } else {
1090     /* Send the request on a reused connection */
1091     int r;
1092 
1093     connections[cnum].stats.requests++;
1094     connections[cnum].stats.requests_per_connection++;
1095     connections[cnum].request_at = *nowP;
1096 
1097     if (urls[url_num].protocol == PROTO_HTTPS)
1098       r = SSL_write(connections[cnum].ssl, urls[url_num].buf, urls[url_num].buf_bytes);
1099     else
1100       r = write(connections[cnum].conn_fd, urls[url_num].buf, urls[url_num].buf_bytes);
1101     if (r <= 0) {
1102       perror(urls[url_num].url_str);
1103       connections[cnum].reusable = 0;
1104       close_connection(cnum);
1105       return;
1106     }
1107     connections[cnum].conn_state   = CNST_HEADERS;
1108     connections[cnum].header_state = HDST_LINE1_PROTOCOL;
1109   }
1110 }
1111 
1112 static int
cert_verify_callback(int ok,X509_STORE_CTX * ctx)1113 cert_verify_callback(int ok __attribute__((unused)), X509_STORE_CTX *ctx __attribute__((unused)))
1114 {
1115   return 1;
1116 }
1117 
1118 static void
handle_connect(int cnum,struct timeval * nowP,int double_check)1119 handle_connect(int cnum, struct timeval *nowP, int double_check)
1120 {
1121   static int connect_failures = 0;
1122   int url_num;
1123   int r;
1124   struct epoll_event ev;
1125 
1126 #ifdef DEBUG
1127   fprintf(stderr, "Entering handle_connect() for CNUM %d\n", cnum);
1128 #endif
1129 
1130   url_num                                         = connections[cnum].url_num;
1131   connections[cnum].stats.requests_per_connection = 0;
1132   if (double_check) {
1133     /* Check to make sure the non-blocking connect succeeded. */
1134     int err, errlen;
1135 
1136     if (connect(connections[cnum].conn_fd, (struct sockaddr *)&connections[cnum].sa, connections[cnum].sa_len) < 0) {
1137       if (max_connect_failures && (++connect_failures > max_connect_failures))
1138         exit(0);
1139       switch (errno) {
1140       case EISCONN:
1141         /* Ok! */
1142         break;
1143       case EINVAL:
1144         errlen = sizeof(err);
1145         if (getsockopt(connections[cnum].conn_fd, SOL_SOCKET, SO_ERROR, (void *)&err, (socklen_t *)&errlen) < 0)
1146           (void)fprintf(stderr, "%s: unknown connect error\n", urls[url_num].url_str);
1147         else
1148           (void)fprintf(stderr, "%s: %s\n", urls[url_num].url_str, strerror(err));
1149         close_connection(cnum);
1150         return;
1151       default:
1152         perror(urls[url_num].url_str);
1153         close_connection(cnum);
1154         return;
1155       }
1156     }
1157   }
1158 
1159   if (urls[url_num].protocol == PROTO_HTTPS) {
1160     int flags;
1161 
1162     /* Make SSL connection. */
1163     if (ssl_ctx == (SSL_CTX *)0) {
1164       SSL_load_error_strings();
1165       SSL_library_init();
1166       ssl_ctx = SSL_CTX_new(SSLv23_client_method());
1167       /* For some reason this does not seem to work, but indications are that it should...
1168          Maybe something with how we create connections? TODO: Fix it... */
1169       SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, cert_verify_callback);
1170       if (cipher != (char *)0) {
1171         if (!SSL_CTX_set_cipher_list(ssl_ctx, cipher)) {
1172           (void)fprintf(stderr, "%s: cannot set cipher list\n", argv0);
1173           ERR_print_errors_fp(stderr);
1174           close_connection(cnum);
1175           return;
1176         }
1177       }
1178     }
1179 
1180     if (!RAND_status()) {
1181       unsigned char bytes[1024];
1182       for (size_t i = 0; i < sizeof(bytes); ++i)
1183         bytes[i] = random() % 0xff;
1184       RAND_seed(bytes, sizeof(bytes));
1185     }
1186     flags = fcntl(connections[cnum].conn_fd, F_GETFL, 0);
1187     if (flags != -1)
1188       (void)fcntl(connections[cnum].conn_fd, F_SETFL, flags & ~(int)O_NDELAY);
1189     connections[cnum].ssl = SSL_new(ssl_ctx);
1190     SSL_set_fd(connections[cnum].ssl, connections[cnum].conn_fd);
1191     r = SSL_connect(connections[cnum].ssl);
1192     if (r <= 0) {
1193       (void)fprintf(stderr, "%s: SSL connection failed - %d\n", argv0, r);
1194       ERR_print_errors_fp(stderr);
1195       close_connection(cnum);
1196       return;
1197     }
1198   }
1199 
1200   ev.events   = EPOLLIN;
1201   ev.data.u32 = cnum;
1202 
1203 #ifdef DEBUG
1204   fprintf(stderr, "Mod FD %d to read for CNUM %d\n", connections[cnum].conn_fd, cnum);
1205 #endif
1206   if (epoll_ctl(epfd, EPOLL_CTL_MOD, connections[cnum].conn_fd, &ev)) {
1207     perror("epoll mod fd");
1208     (void)close(connections[cnum].conn_fd);
1209     return;
1210   }
1211   /* Send the request. */
1212   connections[cnum].did_connect = 1;
1213   connections[cnum].request_at  = *nowP;
1214   connections[cnum].stats.requests++;
1215   if (urls[url_num].protocol == PROTO_HTTPS)
1216     r = SSL_write(connections[cnum].ssl, urls[url_num].buf, urls[url_num].buf_bytes);
1217   else
1218     r = write(connections[cnum].conn_fd, urls[url_num].buf, urls[url_num].buf_bytes);
1219   if (r <= 0) {
1220     perror(urls[url_num].url_str);
1221     connections[cnum].reusable = 0;
1222     close_connection(cnum);
1223     return;
1224   }
1225   connections[cnum].conn_state   = CNST_HEADERS;
1226   connections[cnum].header_state = HDST_LINE1_PROTOCOL;
1227 }
1228 
1229 static void
handle_read(int cnum,struct timeval * nowP)1230 handle_read(int cnum, struct timeval *nowP)
1231 {
1232   char buf[30000]; /* must be larger than throttle / 2 */
1233   int bytes_to_read, bytes_read, bytes_handled;
1234   float elapsed;
1235   ClientData client_data;
1236   long checksum;
1237 
1238   tmr_reset(nowP, connections[cnum].idle_timer);
1239 
1240   if (do_throttle)
1241     bytes_to_read = throttle / 2.0;
1242   else
1243     bytes_to_read = sizeof(buf);
1244   if (!connections[cnum].did_response) {
1245     connections[cnum].did_response = 1;
1246     connections[cnum].response_at  = *nowP;
1247     if (connections[cnum].did_connect) {
1248       if (connections[cnum].keep_alive == keep_alive) {
1249         num_ka_conns++;
1250         if (num_ka_conns > max_parallel) {
1251           max_parallel = num_ka_conns;
1252         }
1253       }
1254     }
1255     if (connections[cnum].keep_alive == 0) {
1256       num_ka_conns--;
1257     }
1258   }
1259   if (urls[connections[cnum].url_num].protocol == PROTO_HTTPS)
1260     bytes_read = SSL_read(connections[cnum].ssl, buf, bytes_to_read - 1);
1261   else
1262     bytes_read = read(connections[cnum].conn_fd, buf, bytes_to_read - 1);
1263   if (bytes_read <= 0) {
1264     connections[cnum].reusable = 0;
1265     close_connection(cnum);
1266     return;
1267   }
1268 
1269   buf[bytes_read] = 0;
1270   for (bytes_handled = 0; bytes_handled < bytes_read;) {
1271     switch (connections[cnum].conn_state) {
1272     case CNST_HEADERS:
1273       /* State machine to read until we reach the file part.  Looks for
1274        ** Content-Length header too.
1275        */
1276       for (; bytes_handled < bytes_read && connections[cnum].conn_state == CNST_HEADERS; ++bytes_handled) {
1277         switch (connections[cnum].header_state) {
1278         case HDST_LINE1_PROTOCOL:
1279           switch (buf[bytes_handled]) {
1280           case ' ':
1281           case '\t':
1282             connections[cnum].header_state = HDST_LINE1_WS;
1283             break;
1284           case '\n':
1285             connections[cnum].header_state = HDST_LF;
1286             break;
1287           case '\r':
1288             connections[cnum].header_state = HDST_CR;
1289             break;
1290           }
1291           break;
1292 
1293         case HDST_LINE1_WS:
1294           switch (buf[bytes_handled]) {
1295           case ' ':
1296           case '\t':
1297             break;
1298           case '0':
1299           case '1':
1300           case '2':
1301           case '3':
1302           case '4':
1303           case '5':
1304           case '6':
1305           case '7':
1306           case '8':
1307           case '9':
1308             connections[cnum].http_status  = buf[bytes_handled] - '0';
1309             connections[cnum].header_state = HDST_LINE1_STATUS;
1310             break;
1311           case '\n':
1312             connections[cnum].header_state = HDST_LF;
1313             break;
1314           case '\r':
1315             connections[cnum].header_state = HDST_CR;
1316             break;
1317           default:
1318             connections[cnum].header_state = HDST_TEXT;
1319             break;
1320           }
1321           break;
1322 
1323         case HDST_LINE1_STATUS:
1324           switch (buf[bytes_handled]) {
1325           case '0':
1326           case '1':
1327           case '2':
1328           case '3':
1329           case '4':
1330           case '5':
1331           case '6':
1332           case '7':
1333           case '8':
1334           case '9':
1335             connections[cnum].http_status = connections[cnum].http_status * 10 + buf[bytes_handled] - '0';
1336             break;
1337           case '\n':
1338             connections[cnum].header_state = HDST_LF;
1339             break;
1340           case '\r':
1341             connections[cnum].header_state = HDST_CR;
1342             break;
1343           default:
1344             connections[cnum].header_state = HDST_TEXT;
1345             break;
1346           }
1347           break;
1348 
1349         case HDST_BOL:
1350           switch (buf[bytes_handled]) {
1351           case '\n':
1352             connections[cnum].header_state = HDST_LF;
1353             break;
1354           case '\r':
1355             connections[cnum].header_state = HDST_CR;
1356             break;
1357           case 'C':
1358           case 'c':
1359             connections[cnum].header_state = HDST_C;
1360             break;
1361           case 'T':
1362           case 't':
1363             connections[cnum].header_state = HDST_T;
1364             break;
1365           default:
1366             connections[cnum].header_state = HDST_TEXT;
1367             break;
1368           }
1369           break;
1370 
1371         case HDST_TEXT:
1372           switch (buf[bytes_handled]) {
1373           case '\n':
1374             connections[cnum].header_state = HDST_LF;
1375             break;
1376           case '\r':
1377             connections[cnum].header_state = HDST_CR;
1378             break;
1379           default:
1380             break;
1381           }
1382           break;
1383 
1384         case HDST_LF:
1385           switch (buf[bytes_handled]) {
1386           case '\n':
1387             connections[cnum].conn_state = CNST_READING;
1388             break;
1389           case '\r':
1390             connections[cnum].header_state = HDST_CR;
1391             break;
1392           case 'C':
1393           case 'c':
1394             connections[cnum].header_state = HDST_C;
1395             break;
1396           case 'T':
1397           case 't':
1398             connections[cnum].header_state = HDST_T;
1399             break;
1400           default:
1401             connections[cnum].header_state = HDST_TEXT;
1402             break;
1403           }
1404           break;
1405 
1406         case HDST_CR:
1407           switch (buf[bytes_handled]) {
1408           case '\n':
1409             connections[cnum].header_state = HDST_CRLF;
1410             break;
1411           case '\r':
1412             connections[cnum].conn_state = CNST_READING;
1413             break;
1414           case 'C':
1415           case 'c':
1416             connections[cnum].header_state = HDST_C;
1417             break;
1418           case 'T':
1419           case 't':
1420             connections[cnum].header_state = HDST_T;
1421             break;
1422           default:
1423             connections[cnum].header_state = HDST_TEXT;
1424             break;
1425           }
1426           break;
1427 
1428         case HDST_CRLF:
1429           switch (buf[bytes_handled]) {
1430           case '\n':
1431             connections[cnum].conn_state = CNST_READING;
1432             break;
1433           case '\r':
1434             connections[cnum].header_state = HDST_CRLFCR;
1435             break;
1436           case 'C':
1437           case 'c':
1438             connections[cnum].header_state = HDST_C;
1439             break;
1440           case 'T':
1441           case 't':
1442             connections[cnum].header_state = HDST_T;
1443             break;
1444           default:
1445             connections[cnum].header_state = HDST_TEXT;
1446             break;
1447           }
1448           break;
1449 
1450         case HDST_CRLFCR:
1451           switch (buf[bytes_handled]) {
1452           case '\n':
1453           case '\r':
1454             connections[cnum].conn_state = CNST_READING;
1455             break;
1456           case 'C':
1457           case 'c':
1458             connections[cnum].header_state = HDST_C;
1459             break;
1460           case 'T':
1461           case 't':
1462             connections[cnum].header_state = HDST_T;
1463             break;
1464           default:
1465             connections[cnum].header_state = HDST_TEXT;
1466             break;
1467           }
1468           break;
1469 
1470         case HDST_C:
1471           switch (buf[bytes_handled]) {
1472           case 'O':
1473           case 'o':
1474             connections[cnum].header_state = HDST_CO;
1475             break;
1476           case '\n':
1477             connections[cnum].header_state = HDST_LF;
1478             break;
1479           case '\r':
1480             connections[cnum].header_state = HDST_CR;
1481             break;
1482           default:
1483             connections[cnum].header_state = HDST_TEXT;
1484             break;
1485           }
1486           break;
1487 
1488         case HDST_CO:
1489           switch (buf[bytes_handled]) {
1490           case 'N':
1491           case 'n':
1492             connections[cnum].header_state = HDST_CON;
1493             break;
1494           case '\n':
1495             connections[cnum].header_state = HDST_LF;
1496             break;
1497           case '\r':
1498             connections[cnum].header_state = HDST_CR;
1499             break;
1500           default:
1501             connections[cnum].header_state = HDST_TEXT;
1502             break;
1503           }
1504           break;
1505 
1506         case HDST_CON:
1507           switch (buf[bytes_handled]) {
1508           case 'T':
1509           case 't':
1510             connections[cnum].header_state = HDST_CONT;
1511             break;
1512           case 'N':
1513           case 'n':
1514             connections[cnum].header_state = HDST_CONN;
1515             break;
1516           case '\n':
1517             connections[cnum].header_state = HDST_LF;
1518             break;
1519           case '\r':
1520             connections[cnum].header_state = HDST_CR;
1521             break;
1522           default:
1523             connections[cnum].header_state = HDST_TEXT;
1524             break;
1525           }
1526           break;
1527 
1528         case HDST_CONT:
1529           switch (buf[bytes_handled]) {
1530           case 'E':
1531           case 'e':
1532             connections[cnum].header_state = HDST_CONTE;
1533             break;
1534           case '\n':
1535             connections[cnum].header_state = HDST_LF;
1536             break;
1537           case '\r':
1538             connections[cnum].header_state = HDST_CR;
1539             break;
1540           default:
1541             connections[cnum].header_state = HDST_TEXT;
1542             break;
1543           }
1544           break;
1545 
1546         case HDST_CONTE:
1547           switch (buf[bytes_handled]) {
1548           case 'N':
1549           case 'n':
1550             connections[cnum].header_state = HDST_CONTEN;
1551             break;
1552           case '\n':
1553             connections[cnum].header_state = HDST_LF;
1554             break;
1555           case '\r':
1556             connections[cnum].header_state = HDST_CR;
1557             break;
1558           default:
1559             connections[cnum].header_state = HDST_TEXT;
1560             break;
1561           }
1562           break;
1563 
1564         case HDST_CONTEN:
1565           switch (buf[bytes_handled]) {
1566           case 'T':
1567           case 't':
1568             connections[cnum].header_state = HDST_CONTENT;
1569             break;
1570           case '\n':
1571             connections[cnum].header_state = HDST_LF;
1572             break;
1573           case '\r':
1574             connections[cnum].header_state = HDST_CR;
1575             break;
1576           default:
1577             connections[cnum].header_state = HDST_TEXT;
1578             break;
1579           }
1580           break;
1581 
1582         case HDST_CONTENT:
1583           switch (buf[bytes_handled]) {
1584           case '-':
1585             connections[cnum].header_state = HDST_CONTENT_;
1586             break;
1587           case '\n':
1588             connections[cnum].header_state = HDST_LF;
1589             break;
1590           case '\r':
1591             connections[cnum].header_state = HDST_CR;
1592             break;
1593           default:
1594             connections[cnum].header_state = HDST_TEXT;
1595             break;
1596           }
1597           break;
1598 
1599         case HDST_CONTENT_:
1600           switch (buf[bytes_handled]) {
1601           case 'L':
1602           case 'l':
1603             connections[cnum].header_state = HDST_CONTENT_L;
1604             break;
1605           case '\n':
1606             connections[cnum].header_state = HDST_LF;
1607             break;
1608           case '\r':
1609             connections[cnum].header_state = HDST_CR;
1610             break;
1611           default:
1612             connections[cnum].header_state = HDST_TEXT;
1613             break;
1614           }
1615           break;
1616 
1617         case HDST_CONTENT_L:
1618           switch (buf[bytes_handled]) {
1619           case 'E':
1620           case 'e':
1621             connections[cnum].header_state = HDST_CONTENT_LE;
1622             break;
1623           case '\n':
1624             connections[cnum].header_state = HDST_LF;
1625             break;
1626           case '\r':
1627             connections[cnum].header_state = HDST_CR;
1628             break;
1629           default:
1630             connections[cnum].header_state = HDST_TEXT;
1631             break;
1632           }
1633           break;
1634 
1635         case HDST_CONTENT_LE:
1636           switch (buf[bytes_handled]) {
1637           case 'N':
1638           case 'n':
1639             connections[cnum].header_state = HDST_CONTENT_LEN;
1640             break;
1641           case '\n':
1642             connections[cnum].header_state = HDST_LF;
1643             break;
1644           case '\r':
1645             connections[cnum].header_state = HDST_CR;
1646             break;
1647           default:
1648             connections[cnum].header_state = HDST_TEXT;
1649             break;
1650           }
1651           break;
1652 
1653         case HDST_CONTENT_LEN:
1654           switch (buf[bytes_handled]) {
1655           case 'G':
1656           case 'g':
1657             connections[cnum].header_state = HDST_CONTENT_LENG;
1658             break;
1659           case '\n':
1660             connections[cnum].header_state = HDST_LF;
1661             break;
1662           case '\r':
1663             connections[cnum].header_state = HDST_CR;
1664             break;
1665           default:
1666             connections[cnum].header_state = HDST_TEXT;
1667             break;
1668           }
1669           break;
1670 
1671         case HDST_CONTENT_LENG:
1672           switch (buf[bytes_handled]) {
1673           case 'T':
1674           case 't':
1675             connections[cnum].header_state = HDST_CONTENT_LENGT;
1676             break;
1677           case '\n':
1678             connections[cnum].header_state = HDST_LF;
1679             break;
1680           case '\r':
1681             connections[cnum].header_state = HDST_CR;
1682             break;
1683           default:
1684             connections[cnum].header_state = HDST_TEXT;
1685             break;
1686           }
1687           break;
1688 
1689         case HDST_CONTENT_LENGT:
1690           switch (buf[bytes_handled]) {
1691           case 'H':
1692           case 'h':
1693             connections[cnum].header_state = HDST_CONTENT_LENGTH;
1694             break;
1695           case '\n':
1696             connections[cnum].header_state = HDST_LF;
1697             break;
1698           case '\r':
1699             connections[cnum].header_state = HDST_CR;
1700             break;
1701           default:
1702             connections[cnum].header_state = HDST_TEXT;
1703             break;
1704           }
1705           break;
1706 
1707         case HDST_CONTENT_LENGTH:
1708           switch (buf[bytes_handled]) {
1709           case ':':
1710             connections[cnum].header_state = HDST_CONTENT_LENGTH_COLON;
1711             break;
1712           case '\n':
1713             connections[cnum].header_state = HDST_LF;
1714             break;
1715           case '\r':
1716             connections[cnum].header_state = HDST_CR;
1717             break;
1718           default:
1719             connections[cnum].header_state = HDST_TEXT;
1720             break;
1721           }
1722           break;
1723 
1724         case HDST_CONTENT_LENGTH_COLON:
1725           switch (buf[bytes_handled]) {
1726           case ' ':
1727           case '\t':
1728             connections[cnum].header_state = HDST_CONTENT_LENGTH_COLON_WS;
1729             break;
1730           case '\n':
1731             connections[cnum].header_state = HDST_LF;
1732             break;
1733           case '\r':
1734             connections[cnum].header_state = HDST_CR;
1735             break;
1736           default:
1737             connections[cnum].header_state = HDST_TEXT;
1738             break;
1739           }
1740           break;
1741 
1742         case HDST_CONTENT_LENGTH_COLON_WS:
1743           switch (buf[bytes_handled]) {
1744           case ' ':
1745           case '\t':
1746             break;
1747           case '0':
1748           case '1':
1749           case '2':
1750           case '3':
1751           case '4':
1752           case '5':
1753           case '6':
1754           case '7':
1755           case '8':
1756           case '9':
1757             connections[cnum].content_length = buf[bytes_handled] - '0';
1758             connections[cnum].header_state   = HDST_CONTENT_LENGTH_COLON_WS_NUM;
1759             break;
1760           case '\n':
1761             connections[cnum].header_state = HDST_LF;
1762             break;
1763           case '\r':
1764             connections[cnum].header_state = HDST_CR;
1765             break;
1766           default:
1767             connections[cnum].header_state = HDST_TEXT;
1768             break;
1769           }
1770           break;
1771 
1772         case HDST_CONTENT_LENGTH_COLON_WS_NUM:
1773           switch (buf[bytes_handled]) {
1774           case '0':
1775           case '1':
1776           case '2':
1777           case '3':
1778           case '4':
1779           case '5':
1780           case '6':
1781           case '7':
1782           case '8':
1783           case '9':
1784             connections[cnum].content_length = connections[cnum].content_length * 10 + buf[bytes_handled] - '0';
1785             break;
1786           case '\n':
1787             connections[cnum].header_state = HDST_LF;
1788             break;
1789           case '\r':
1790             connections[cnum].header_state = HDST_CR;
1791             break;
1792           default:
1793             connections[cnum].header_state = HDST_TEXT;
1794             break;
1795           }
1796           break;
1797 
1798         /* Stuff for Connection: close */
1799         case HDST_CONN:
1800           switch (buf[bytes_handled]) {
1801           case 'E':
1802           case 'e':
1803             connections[cnum].header_state = HDST_CONNE;
1804             break;
1805           case '\n':
1806             connections[cnum].header_state = HDST_LF;
1807             break;
1808           case '\r':
1809             connections[cnum].header_state = HDST_CR;
1810             break;
1811           default:
1812             connections[cnum].header_state = HDST_TEXT;
1813             break;
1814           }
1815           break;
1816 
1817         case HDST_CONNE:
1818           switch (buf[bytes_handled]) {
1819           case 'C':
1820           case 'c':
1821             connections[cnum].header_state = HDST_CONNEC;
1822             break;
1823           case '\n':
1824             connections[cnum].header_state = HDST_LF;
1825             break;
1826           case '\r':
1827             connections[cnum].header_state = HDST_CR;
1828             break;
1829           default:
1830             connections[cnum].header_state = HDST_TEXT;
1831             break;
1832           }
1833           break;
1834 
1835         case HDST_CONNEC:
1836           switch (buf[bytes_handled]) {
1837           case 'T':
1838           case 't':
1839             connections[cnum].header_state = HDST_CONNECT;
1840             break;
1841           case '\n':
1842             connections[cnum].header_state = HDST_LF;
1843             break;
1844           case '\r':
1845             connections[cnum].header_state = HDST_CR;
1846             break;
1847           default:
1848             connections[cnum].header_state = HDST_TEXT;
1849             break;
1850           }
1851           break;
1852 
1853         case HDST_CONNECT:
1854           switch (buf[bytes_handled]) {
1855           case 'I':
1856           case 'i':
1857             connections[cnum].header_state = HDST_CONNECTI;
1858             break;
1859           case '\n':
1860             connections[cnum].header_state = HDST_LF;
1861             break;
1862           case '\r':
1863             connections[cnum].header_state = HDST_CR;
1864             break;
1865           default:
1866             connections[cnum].header_state = HDST_TEXT;
1867             break;
1868           }
1869           break;
1870 
1871         case HDST_CONNECTI:
1872           switch (buf[bytes_handled]) {
1873           case 'O':
1874           case 'o':
1875             connections[cnum].header_state = HDST_CONNECTIO;
1876             break;
1877           case '\n':
1878             connections[cnum].header_state = HDST_LF;
1879             break;
1880           case '\r':
1881             connections[cnum].header_state = HDST_CR;
1882             break;
1883           default:
1884             connections[cnum].header_state = HDST_TEXT;
1885             break;
1886           }
1887           break;
1888 
1889         case HDST_CONNECTIO:
1890           switch (buf[bytes_handled]) {
1891           case 'N':
1892           case 'n':
1893             connections[cnum].header_state = HDST_CONNECTION;
1894             break;
1895           case '\n':
1896             connections[cnum].header_state = HDST_LF;
1897             break;
1898           case '\r':
1899             connections[cnum].header_state = HDST_CR;
1900             break;
1901           default:
1902             connections[cnum].header_state = HDST_TEXT;
1903             break;
1904           }
1905           break;
1906 
1907         case HDST_CONNECTION:
1908           switch (buf[bytes_handled]) {
1909           case ':':
1910             connections[cnum].header_state = HDST_CONNECTION_COLON;
1911             break;
1912           case '\n':
1913             connections[cnum].header_state = HDST_LF;
1914             break;
1915           case '\r':
1916             connections[cnum].header_state = HDST_CR;
1917             break;
1918           default:
1919             connections[cnum].header_state = HDST_TEXT;
1920             break;
1921           }
1922           break;
1923 
1924         case HDST_CONNECTION_COLON:
1925           switch (buf[bytes_handled]) {
1926           case ' ':
1927           case '\t':
1928             connections[cnum].header_state = HDST_CONNECTION_COLON_WS;
1929             break;
1930           case '\n':
1931             connections[cnum].header_state = HDST_LF;
1932             break;
1933           case '\r':
1934             connections[cnum].header_state = HDST_CR;
1935             break;
1936           default:
1937             connections[cnum].header_state = HDST_TEXT;
1938             break;
1939           }
1940           break;
1941 
1942         case HDST_CONNECTION_COLON_WS:
1943           switch (buf[bytes_handled]) {
1944           case 'C':
1945           case 'c':
1946             connections[cnum].header_state = HDST_CONNECTION_COLON_WS_C;
1947             break;
1948           case 'K':
1949           case 'k':
1950             connections[cnum].header_state = HDST_CONNECTION_COLON_WS_K;
1951             break;
1952           case '\n':
1953             connections[cnum].header_state = HDST_LF;
1954             break;
1955           case '\r':
1956             connections[cnum].header_state = HDST_CR;
1957             break;
1958           default:
1959             connections[cnum].header_state = HDST_TEXT;
1960             break;
1961           }
1962           break;
1963 
1964         case HDST_CONNECTION_COLON_WS_C:
1965           switch (buf[bytes_handled]) {
1966           case 'L':
1967           case 'l':
1968             connections[cnum].header_state = HDST_CONNECTION_COLON_WS_CL;
1969             break;
1970           case '\n':
1971             connections[cnum].header_state = HDST_LF;
1972             break;
1973           case '\r':
1974             connections[cnum].header_state = HDST_CR;
1975             break;
1976           default:
1977             connections[cnum].header_state = HDST_TEXT;
1978             break;
1979           }
1980           break;
1981 
1982         case HDST_CONNECTION_COLON_WS_CL:
1983           switch (buf[bytes_handled]) {
1984           case 'O':
1985           case 'o':
1986             connections[cnum].header_state = HDST_CONNECTION_COLON_WS_CLO;
1987             break;
1988           case '\n':
1989             connections[cnum].header_state = HDST_LF;
1990             break;
1991           case '\r':
1992             connections[cnum].header_state = HDST_CR;
1993             break;
1994           default:
1995             connections[cnum].header_state = HDST_TEXT;
1996             break;
1997           }
1998           break;
1999 
2000         case HDST_CONNECTION_COLON_WS_CLO:
2001           switch (buf[bytes_handled]) {
2002           case 'S':
2003           case 's':
2004             connections[cnum].header_state = HDST_CONNECTION_COLON_WS_CLOS;
2005             break;
2006           case '\n':
2007             connections[cnum].header_state = HDST_LF;
2008             break;
2009           case '\r':
2010             connections[cnum].header_state = HDST_CR;
2011             break;
2012           default:
2013             connections[cnum].header_state = HDST_TEXT;
2014             break;
2015           }
2016           break;
2017 
2018         case HDST_CONNECTION_COLON_WS_CLOS:
2019           switch (buf[bytes_handled]) {
2020           case 'E':
2021           case 'e':
2022             connections[cnum].header_state = HDST_CONNECTION_COLON_WS_CLOSE;
2023             break;
2024           case '\n':
2025             connections[cnum].header_state = HDST_LF;
2026             break;
2027           case '\r':
2028             connections[cnum].header_state = HDST_CR;
2029             break;
2030           default:
2031             connections[cnum].header_state = HDST_TEXT;
2032             break;
2033           }
2034           break;
2035 
2036         case HDST_CONNECTION_COLON_WS_CLOSE:
2037           /* Got the complete HTTP/1.1 "Connection: close" header, make sure this
2038              is the last request on this connection. */
2039           /* Close ToDo: Fix this */
2040           switch (buf[bytes_handled]) {
2041           case '\n':
2042             connections[cnum].header_state = HDST_LF;
2043             break;
2044           case '\r':
2045             connections[cnum].header_state = HDST_CR;
2046             break;
2047           default:
2048             connections[cnum].header_state = HDST_TEXT;
2049             break;
2050           }
2051           break;
2052 
2053         case HDST_CONNECTION_COLON_WS_K:
2054           switch (buf[bytes_handled]) {
2055           case 'E':
2056           case 'e':
2057             connections[cnum].header_state = HDST_CONNECTION_COLON_WS_KE;
2058             break;
2059           case '\n':
2060             connections[cnum].header_state = HDST_LF;
2061             break;
2062           case '\r':
2063             connections[cnum].header_state = HDST_CR;
2064             break;
2065           default:
2066             connections[cnum].header_state = HDST_TEXT;
2067             break;
2068           }
2069           break;
2070 
2071         case HDST_CONNECTION_COLON_WS_KE:
2072           switch (buf[bytes_handled]) {
2073           case 'E':
2074           case 'e':
2075             connections[cnum].header_state = HDST_CONNECTION_COLON_WS_KEE;
2076             break;
2077           case '\n':
2078             connections[cnum].header_state = HDST_LF;
2079             break;
2080           case '\r':
2081             connections[cnum].header_state = HDST_CR;
2082             break;
2083           default:
2084             connections[cnum].header_state = HDST_TEXT;
2085             break;
2086           }
2087           break;
2088 
2089         case HDST_CONNECTION_COLON_WS_KEE:
2090           switch (buf[bytes_handled]) {
2091           case 'P':
2092           case 'p':
2093             connections[cnum].header_state = HDST_CONNECTION_COLON_WS_KEEP;
2094             break;
2095           case '\n':
2096             connections[cnum].header_state = HDST_LF;
2097             break;
2098           case '\r':
2099             connections[cnum].header_state = HDST_CR;
2100             break;
2101           default:
2102             connections[cnum].header_state = HDST_TEXT;
2103             break;
2104           }
2105           break;
2106 
2107         case HDST_CONNECTION_COLON_WS_KEEP:
2108           switch (buf[bytes_handled]) {
2109           case '-':
2110             connections[cnum].header_state = HDST_CONNECTION_COLON_WS_KEEP_;
2111             break;
2112           case '\n':
2113             connections[cnum].header_state = HDST_LF;
2114             break;
2115           case '\r':
2116             connections[cnum].header_state = HDST_CR;
2117             break;
2118           default:
2119             connections[cnum].header_state = HDST_TEXT;
2120             break;
2121           }
2122           break;
2123 
2124         case HDST_CONNECTION_COLON_WS_KEEP_:
2125           switch (buf[bytes_handled]) {
2126           case 'A':
2127           case 'a':
2128             connections[cnum].header_state = HDST_CONNECTION_COLON_WS_KEEP_A;
2129             break;
2130           case '\n':
2131             connections[cnum].header_state = HDST_LF;
2132             break;
2133           case '\r':
2134             connections[cnum].header_state = HDST_CR;
2135             break;
2136           default:
2137             connections[cnum].header_state = HDST_TEXT;
2138             break;
2139           }
2140           break;
2141 
2142         case HDST_CONNECTION_COLON_WS_KEEP_A:
2143           switch (buf[bytes_handled]) {
2144           case 'L':
2145           case 'l':
2146             connections[cnum].header_state = HDST_CONNECTION_COLON_WS_KEEP_AL;
2147             break;
2148           case '\n':
2149             connections[cnum].header_state = HDST_LF;
2150             break;
2151           case '\r':
2152             connections[cnum].header_state = HDST_CR;
2153             break;
2154           default:
2155             connections[cnum].header_state = HDST_TEXT;
2156             break;
2157           }
2158           break;
2159 
2160         case HDST_CONNECTION_COLON_WS_KEEP_AL:
2161           switch (buf[bytes_handled]) {
2162           case 'I':
2163           case 'i':
2164             connections[cnum].header_state = HDST_CONNECTION_COLON_WS_KEEP_ALI;
2165             break;
2166           case '\n':
2167             connections[cnum].header_state = HDST_LF;
2168             break;
2169           case '\r':
2170             connections[cnum].header_state = HDST_CR;
2171             break;
2172           default:
2173             connections[cnum].header_state = HDST_TEXT;
2174             break;
2175           }
2176           break;
2177 
2178         case HDST_CONNECTION_COLON_WS_KEEP_ALI:
2179           switch (buf[bytes_handled]) {
2180           case 'V':
2181           case 'v':
2182             connections[cnum].header_state = HDST_CONNECTION_COLON_WS_KEEP_ALIV;
2183             break;
2184           case '\n':
2185             connections[cnum].header_state = HDST_LF;
2186             break;
2187           case '\r':
2188             connections[cnum].header_state = HDST_CR;
2189             break;
2190           default:
2191             connections[cnum].header_state = HDST_TEXT;
2192             break;
2193           }
2194           break;
2195 
2196         case HDST_CONNECTION_COLON_WS_KEEP_ALIV:
2197           switch (buf[bytes_handled]) {
2198           case 'E':
2199           case 'e':
2200             connections[cnum].header_state = HDST_CONNECTION_COLON_WS_KEEP_ALIVE;
2201             break;
2202           case '\n':
2203             connections[cnum].header_state = HDST_LF;
2204             break;
2205           case '\r':
2206             connections[cnum].header_state = HDST_CR;
2207             break;
2208           default:
2209             connections[cnum].header_state = HDST_TEXT;
2210             break;
2211           }
2212           break;
2213 
2214         case HDST_CONNECTION_COLON_WS_KEEP_ALIVE:
2215           /* Handle Connection: keep-alive response header, make the
2216              connection reusable if we have some keep_alive quota left. */
2217           /* ToDo: Fix this */
2218           switch (buf[bytes_handled]) {
2219           case '\n':
2220             connections[cnum].header_state = HDST_LF;
2221             break;
2222           case '\r':
2223             connections[cnum].header_state = HDST_CR;
2224             break;
2225           default:
2226             connections[cnum].header_state = HDST_TEXT;
2227             break;
2228           }
2229           break;
2230 
2231         /* States for Transfer-Encoding: chunked */
2232         case HDST_T:
2233           switch (buf[bytes_handled]) {
2234           case 'R':
2235           case 'r':
2236             connections[cnum].header_state = HDST_TR;
2237             break;
2238           case '\n':
2239             connections[cnum].header_state = HDST_LF;
2240             break;
2241           case '\r':
2242             connections[cnum].header_state = HDST_CR;
2243             break;
2244           default:
2245             connections[cnum].header_state = HDST_TEXT;
2246             break;
2247           }
2248           break;
2249 
2250         case HDST_TR:
2251           switch (buf[bytes_handled]) {
2252           case 'A':
2253           case 'a':
2254             connections[cnum].header_state = HDST_TRA;
2255             break;
2256           case '\n':
2257             connections[cnum].header_state = HDST_LF;
2258             break;
2259           case '\r':
2260             connections[cnum].header_state = HDST_CR;
2261             break;
2262           default:
2263             connections[cnum].header_state = HDST_TEXT;
2264             break;
2265           }
2266           break;
2267 
2268         case HDST_TRA:
2269           switch (buf[bytes_handled]) {
2270           case 'N':
2271           case 'n':
2272             connections[cnum].header_state = HDST_TRAN;
2273             break;
2274           case '\n':
2275             connections[cnum].header_state = HDST_LF;
2276             break;
2277           case '\r':
2278             connections[cnum].header_state = HDST_CR;
2279             break;
2280           default:
2281             connections[cnum].header_state = HDST_TEXT;
2282             break;
2283           }
2284           break;
2285 
2286         case HDST_TRAN:
2287           switch (buf[bytes_handled]) {
2288           case 'S':
2289           case 's':
2290             connections[cnum].header_state = HDST_TRANS;
2291             break;
2292           case '\n':
2293             connections[cnum].header_state = HDST_LF;
2294             break;
2295           case '\r':
2296             connections[cnum].header_state = HDST_CR;
2297             break;
2298           default:
2299             connections[cnum].header_state = HDST_TEXT;
2300             break;
2301           }
2302           break;
2303 
2304         case HDST_TRANS:
2305           switch (buf[bytes_handled]) {
2306           case 'F':
2307           case 'f':
2308             connections[cnum].header_state = HDST_TRANSF;
2309             break;
2310           case '\n':
2311             connections[cnum].header_state = HDST_LF;
2312             break;
2313           case '\r':
2314             connections[cnum].header_state = HDST_CR;
2315             break;
2316           default:
2317             connections[cnum].header_state = HDST_TEXT;
2318             break;
2319           }
2320           break;
2321 
2322         case HDST_TRANSF:
2323           switch (buf[bytes_handled]) {
2324           case 'E':
2325           case 'e':
2326             connections[cnum].header_state = HDST_TRANSFE;
2327             break;
2328           case '\n':
2329             connections[cnum].header_state = HDST_LF;
2330             break;
2331           case '\r':
2332             connections[cnum].header_state = HDST_CR;
2333             break;
2334           default:
2335             connections[cnum].header_state = HDST_TEXT;
2336             break;
2337           }
2338           break;
2339 
2340         case HDST_TRANSFE:
2341           switch (buf[bytes_handled]) {
2342           case 'R':
2343           case 'r':
2344             connections[cnum].header_state = HDST_TRANSFER;
2345             break;
2346           case '\n':
2347             connections[cnum].header_state = HDST_LF;
2348             break;
2349           case '\r':
2350             connections[cnum].header_state = HDST_CR;
2351             break;
2352           default:
2353             connections[cnum].header_state = HDST_TEXT;
2354             break;
2355           }
2356           break;
2357 
2358         case HDST_TRANSFER:
2359           switch (buf[bytes_handled]) {
2360           case '-':
2361             connections[cnum].header_state = HDST_TRANSFER_DASH;
2362             break;
2363           case '\n':
2364             connections[cnum].header_state = HDST_LF;
2365             break;
2366           case '\r':
2367             connections[cnum].header_state = HDST_CR;
2368             break;
2369           default:
2370             connections[cnum].header_state = HDST_TEXT;
2371             break;
2372           }
2373           break;
2374 
2375         case HDST_TRANSFER_DASH:
2376           switch (buf[bytes_handled]) {
2377           case 'E':
2378           case 'e':
2379             connections[cnum].header_state = HDST_TRANSFER_DASH_E;
2380             break;
2381           case '\n':
2382             connections[cnum].header_state = HDST_LF;
2383             break;
2384           case '\r':
2385             connections[cnum].header_state = HDST_CR;
2386             break;
2387           default:
2388             connections[cnum].header_state = HDST_TEXT;
2389             break;
2390           }
2391           break;
2392 
2393         case HDST_TRANSFER_DASH_E:
2394           switch (buf[bytes_handled]) {
2395           case 'N':
2396           case 'n':
2397             connections[cnum].header_state = HDST_TRANSFER_DASH_EN;
2398             break;
2399           case '\n':
2400             connections[cnum].header_state = HDST_LF;
2401             break;
2402           case '\r':
2403             connections[cnum].header_state = HDST_CR;
2404             break;
2405           default:
2406             connections[cnum].header_state = HDST_TEXT;
2407             break;
2408           }
2409           break;
2410 
2411         case HDST_TRANSFER_DASH_EN:
2412           switch (buf[bytes_handled]) {
2413           case 'C':
2414           case 'c':
2415             connections[cnum].header_state = HDST_TRANSFER_DASH_ENC;
2416             break;
2417           case '\n':
2418             connections[cnum].header_state = HDST_LF;
2419             break;
2420           case '\r':
2421             connections[cnum].header_state = HDST_CR;
2422             break;
2423           default:
2424             connections[cnum].header_state = HDST_TEXT;
2425             break;
2426           }
2427           break;
2428 
2429         case HDST_TRANSFER_DASH_ENC:
2430           switch (buf[bytes_handled]) {
2431           case 'O':
2432           case 'o':
2433             connections[cnum].header_state = HDST_TRANSFER_DASH_ENCO;
2434             break;
2435           case '\n':
2436             connections[cnum].header_state = HDST_LF;
2437             break;
2438           case '\r':
2439             connections[cnum].header_state = HDST_CR;
2440             break;
2441           default:
2442             connections[cnum].header_state = HDST_TEXT;
2443             break;
2444           }
2445           break;
2446 
2447         case HDST_TRANSFER_DASH_ENCO:
2448           switch (buf[bytes_handled]) {
2449           case 'D':
2450           case 'd':
2451             connections[cnum].header_state = HDST_TRANSFER_DASH_ENCOD;
2452             break;
2453           case '\n':
2454             connections[cnum].header_state = HDST_LF;
2455             break;
2456           case '\r':
2457             connections[cnum].header_state = HDST_CR;
2458             break;
2459           default:
2460             connections[cnum].header_state = HDST_TEXT;
2461             break;
2462           }
2463           break;
2464 
2465         case HDST_TRANSFER_DASH_ENCOD:
2466           switch (buf[bytes_handled]) {
2467           case 'I':
2468           case 'i':
2469             connections[cnum].header_state = HDST_TRANSFER_DASH_ENCODI;
2470             break;
2471           case '\n':
2472             connections[cnum].header_state = HDST_LF;
2473             break;
2474           case '\r':
2475             connections[cnum].header_state = HDST_CR;
2476             break;
2477           default:
2478             connections[cnum].header_state = HDST_TEXT;
2479             break;
2480           }
2481           break;
2482 
2483         case HDST_TRANSFER_DASH_ENCODI:
2484           switch (buf[bytes_handled]) {
2485           case 'N':
2486           case 'n':
2487             connections[cnum].header_state = HDST_TRANSFER_DASH_ENCODIN;
2488             break;
2489           case '\n':
2490             connections[cnum].header_state = HDST_LF;
2491             break;
2492           case '\r':
2493             connections[cnum].header_state = HDST_CR;
2494             break;
2495           default:
2496             connections[cnum].header_state = HDST_TEXT;
2497             break;
2498           }
2499           break;
2500 
2501         case HDST_TRANSFER_DASH_ENCODIN:
2502           switch (buf[bytes_handled]) {
2503           case 'G':
2504           case 'g':
2505             connections[cnum].header_state = HDST_TRANSFER_DASH_ENCODING;
2506             break;
2507           case '\n':
2508             connections[cnum].header_state = HDST_LF;
2509             break;
2510           case '\r':
2511             connections[cnum].header_state = HDST_CR;
2512             break;
2513           default:
2514             connections[cnum].header_state = HDST_TEXT;
2515             break;
2516           }
2517           break;
2518 
2519         case HDST_TRANSFER_DASH_ENCODING:
2520           switch (buf[bytes_handled]) {
2521           case ':':
2522             connections[cnum].header_state = HDST_TRANSFER_DASH_ENCODING_COLON;
2523             break;
2524           case '\n':
2525             connections[cnum].header_state = HDST_LF;
2526             break;
2527           case '\r':
2528             connections[cnum].header_state = HDST_CR;
2529             break;
2530           default:
2531             connections[cnum].header_state = HDST_TEXT;
2532             break;
2533           }
2534           break;
2535 
2536         case HDST_TRANSFER_DASH_ENCODING_COLON:
2537           switch (buf[bytes_handled]) {
2538           case ' ':
2539             connections[cnum].header_state = HDST_TRANSFER_DASH_ENCODING_COLON_WS;
2540             break;
2541           case '\n':
2542             connections[cnum].header_state = HDST_LF;
2543             break;
2544           case '\r':
2545             connections[cnum].header_state = HDST_CR;
2546             break;
2547           default:
2548             connections[cnum].header_state = HDST_TEXT;
2549             break;
2550           }
2551           break;
2552 
2553         case HDST_TRANSFER_DASH_ENCODING_COLON_WS:
2554           switch (buf[bytes_handled]) {
2555           case 'C':
2556           case 'c':
2557             connections[cnum].header_state = HDST_TRANSFER_DASH_ENCODING_COLON_WS_C;
2558             break;
2559           case '\n':
2560             connections[cnum].header_state = HDST_LF;
2561             break;
2562           case '\r':
2563             connections[cnum].header_state = HDST_CR;
2564             break;
2565           default:
2566             connections[cnum].header_state = HDST_TEXT;
2567             break;
2568           }
2569           break;
2570 
2571         case HDST_TRANSFER_DASH_ENCODING_COLON_WS_C:
2572           switch (buf[bytes_handled]) {
2573           case 'H':
2574           case 'h':
2575             connections[cnum].header_state = HDST_TRANSFER_DASH_ENCODING_COLON_WS_CH;
2576             break;
2577           case '\n':
2578             connections[cnum].header_state = HDST_LF;
2579             break;
2580           case '\r':
2581             connections[cnum].header_state = HDST_CR;
2582             break;
2583           default:
2584             connections[cnum].header_state = HDST_TEXT;
2585             break;
2586           }
2587           break;
2588 
2589         case HDST_TRANSFER_DASH_ENCODING_COLON_WS_CH:
2590           switch (buf[bytes_handled]) {
2591           case 'U':
2592           case 'u':
2593             connections[cnum].header_state = HDST_TRANSFER_DASH_ENCODING_COLON_WS_CHU;
2594             break;
2595           case '\n':
2596             connections[cnum].header_state = HDST_LF;
2597             break;
2598           case '\r':
2599             connections[cnum].header_state = HDST_CR;
2600             break;
2601           default:
2602             connections[cnum].header_state = HDST_TEXT;
2603             break;
2604           }
2605           break;
2606 
2607         case HDST_TRANSFER_DASH_ENCODING_COLON_WS_CHU:
2608           switch (buf[bytes_handled]) {
2609           case 'N':
2610           case 'n':
2611             connections[cnum].header_state = HDST_TRANSFER_DASH_ENCODING_COLON_WS_CHUN;
2612             break;
2613           case '\n':
2614             connections[cnum].header_state = HDST_LF;
2615             break;
2616           case '\r':
2617             connections[cnum].header_state = HDST_CR;
2618             break;
2619           default:
2620             connections[cnum].header_state = HDST_TEXT;
2621             break;
2622           }
2623           break;
2624 
2625         case HDST_TRANSFER_DASH_ENCODING_COLON_WS_CHUN:
2626           switch (buf[bytes_handled]) {
2627           case 'K':
2628           case 'k':
2629             connections[cnum].header_state = HDST_TRANSFER_DASH_ENCODING_COLON_WS_CHUNK;
2630             break;
2631           case '\n':
2632             connections[cnum].header_state = HDST_LF;
2633             break;
2634           case '\r':
2635             connections[cnum].header_state = HDST_CR;
2636             break;
2637           default:
2638             connections[cnum].header_state = HDST_TEXT;
2639             break;
2640           }
2641           break;
2642 
2643         case HDST_TRANSFER_DASH_ENCODING_COLON_WS_CHUNK:
2644           switch (buf[bytes_handled]) {
2645           case 'E':
2646           case 'e':
2647             connections[cnum].header_state = HDST_TRANSFER_DASH_ENCODING_COLON_WS_CHUNKE;
2648             break;
2649           case '\n':
2650             connections[cnum].header_state = HDST_LF;
2651             break;
2652           case '\r':
2653             connections[cnum].header_state = HDST_CR;
2654             break;
2655           default:
2656             connections[cnum].header_state = HDST_TEXT;
2657             break;
2658           }
2659           break;
2660 
2661         case HDST_TRANSFER_DASH_ENCODING_COLON_WS_CHUNKE:
2662           switch (buf[bytes_handled]) {
2663           case 'D':
2664           case 'd':
2665             connections[cnum].header_state = HDST_TRANSFER_DASH_ENCODING_COLON_WS_CHUNKED;
2666             break;
2667           case '\n':
2668             connections[cnum].header_state = HDST_LF;
2669             break;
2670           case '\r':
2671             connections[cnum].header_state = HDST_CR;
2672             break;
2673           default:
2674             connections[cnum].header_state = HDST_TEXT;
2675             break;
2676           }
2677           break;
2678 
2679         case HDST_TRANSFER_DASH_ENCODING_COLON_WS_CHUNKED:
2680           /* ToDo: what to do here? */
2681           connections[cnum].chunked = 1;
2682           switch (buf[bytes_handled]) {
2683           case '\n':
2684             connections[cnum].header_state = HDST_LF;
2685             break;
2686           case '\r':
2687             connections[cnum].header_state = HDST_CR;
2688             break;
2689           default:
2690             connections[cnum].header_state = HDST_TEXT;
2691             break;
2692           }
2693           break;
2694         }
2695       }
2696 
2697       if (connections[cnum].conn_state == CNST_READING && connections[cnum].content_length == 0) {
2698 #ifdef DEBUG
2699         fprintf(stderr, "[handle_read] content_length is 0, close connection\n");
2700 #endif
2701         if (connections[cnum].keep_alive > 0)
2702           connections[cnum].reusable = 1;
2703 
2704         close_connection(cnum);
2705 
2706         return;
2707       }
2708 
2709       break;
2710 
2711     case CNST_READING:
2712       connections[cnum].bytes += bytes_read - bytes_handled;
2713       if (do_throttle) {
2714         /* Check if we're reading too fast. */
2715         elapsed = delta_timeval(&connections[cnum].started_at, nowP) / 1000000.0;
2716         if (elapsed > 0.01 && connections[cnum].bytes / elapsed > throttle) {
2717           connections[cnum].conn_state   = CNST_PAUSING;
2718           client_data.i                  = cnum;
2719           connections[cnum].wakeup_timer = tmr_create(nowP, wakeup_connection, client_data, 1000L, 0);
2720         }
2721       }
2722       if (do_checksum) {
2723         checksum = connections[cnum].checksum;
2724         for (; bytes_handled < bytes_read; ++bytes_handled) {
2725           if (checksum & 1)
2726             checksum = (checksum >> 1) + 0x8000;
2727           else
2728             checksum >>= 1;
2729           checksum += buf[bytes_handled];
2730           checksum &= 0xffff;
2731         }
2732         connections[cnum].checksum = checksum;
2733       } else
2734         bytes_handled = bytes_read;
2735 
2736       /* This is an utter hack, to try to support chunked encodings... I only
2737          examine the "footer", to see if it looks like a chunked "end".
2738          ToDo: We should properly parse the body, and find the chunked sizes. */
2739       if (connections[cnum].chunked && !strncmp(buf + bytes_read - 5, "0\r\n\r\n", 5))
2740         connections[cnum].content_length = connections[cnum].bytes;
2741 
2742       if (connections[cnum].content_length != -1 && connections[cnum].bytes >= connections[cnum].content_length) {
2743         if (connections[cnum].keep_alive > 0)
2744           connections[cnum].reusable = 1;
2745         close_connection(cnum);
2746         return;
2747       }
2748 
2749       break;
2750     default:
2751       /* Nothing */
2752       break;
2753     }
2754   }
2755 }
2756 
2757 static void
idle_connection(ClientData client_data,struct timeval * nowP)2758 idle_connection(ClientData client_data, struct timeval *nowP __attribute__((unused)))
2759 {
2760   int cnum;
2761   struct timeval tv;
2762   char strTime[32];
2763   struct tm localtv;
2764   gettimeofday(&tv, NULL);
2765   strftime(strTime, 32, "%T", localtime_r(&tv.tv_sec, &localtv));
2766 
2767   cnum                         = client_data.i;
2768   connections[cnum].idle_timer = (Timer *)0;
2769   if (unique_id) {
2770     (void)fprintf(stderr, "[%s.%lld] %s: timed out (%d sec) in state %d, requests %d, unique id: %u\n", strTime,
2771                   (long long)tv.tv_usec, urls[connections[cnum].url_num].url_str, idle_secs, connections[cnum].conn_state,
2772                   connections[cnum].stats.requests_per_connection, connections[cnum].unique_id);
2773   } else {
2774     (void)fprintf(stderr, "[%s.%lld] %s: timed out (%d sec) in state %d, requests %d\n", strTime, (long long)tv.tv_usec,
2775                   urls[connections[cnum].url_num].url_str, idle_secs, connections[cnum].conn_state,
2776                   connections[cnum].stats.requests_per_connection);
2777   }
2778   connections[cnum].reusable = 0;
2779   close_connection(cnum);
2780   ++total_timeouts;
2781 }
2782 
2783 static void
wakeup_connection(ClientData client_data,struct timeval * nowP)2784 wakeup_connection(ClientData client_data, struct timeval *nowP __attribute__((unused)))
2785 {
2786   int cnum;
2787 
2788   cnum                           = client_data.i;
2789   connections[cnum].wakeup_timer = (Timer *)0;
2790   connections[cnum].conn_state   = CNST_READING;
2791 }
2792 
2793 static void
close_connection(int cnum)2794 close_connection(int cnum)
2795 {
2796   int url_num;
2797 
2798   if (!connections[cnum].reusable) {
2799     struct epoll_event ev;
2800 
2801     ev.events   = EPOLLIN | EPOLLOUT;
2802     ev.data.u32 = cnum;
2803     if (epoll_ctl(epfd, EPOLL_CTL_DEL, connections[cnum].conn_fd, &ev) < 0)
2804       perror("epoll delete fd");
2805     if (urls[connections[cnum].url_num].protocol == PROTO_HTTPS)
2806       SSL_free(connections[cnum].ssl);
2807     (void)close(connections[cnum].conn_fd);
2808   } else {
2809     --connections[cnum].keep_alive;
2810   }
2811   connections[cnum].conn_state = CNST_FREE;
2812   if (connections[cnum].idle_timer != (Timer *)0)
2813     tmr_cancel(connections[cnum].idle_timer);
2814   if (connections[cnum].wakeup_timer != (Timer *)0)
2815     tmr_cancel(connections[cnum].wakeup_timer);
2816   --num_connections;
2817   ++fetches_completed;
2818   total_bytes += connections[cnum].bytes;
2819   if (connections[cnum].did_connect) {
2820     long long connect_usecs = delta_timeval(&connections[cnum].connect_at, &connections[cnum].request_at);
2821     /*
2822             if ( connect_usecs > ( max_connect_usecs << 3 ) && max_connect_usecs )
2823                 connect_usecs = max_connect_usecs;
2824     */
2825     total_connect_usecs += connect_usecs;
2826     max_connect_usecs = max(max_connect_usecs, connect_usecs);
2827     min_connect_usecs = min(min_connect_usecs, connect_usecs);
2828     ++connects_completed;
2829   }
2830   if (connections[cnum].did_response) {
2831     long long response_usecs = delta_timeval(&connections[cnum].request_at, &connections[cnum].response_at);
2832     /*
2833             if ( response_usecs > ( max_response_usecs << 1 ) && max_response_usecs )
2834                 response_usecs = max_response_usecs;
2835     */
2836     total_response_usecs += response_usecs;
2837     max_response_usecs = max(max_response_usecs, response_usecs);
2838     min_response_usecs = min(min_response_usecs, response_usecs);
2839     ++responses_completed;
2840   }
2841   if (connections[cnum].http_status >= 0 && connections[cnum].http_status <= 999) {
2842     ++http_status_counts[connections[cnum].http_status];
2843     connections[cnum].stats.responses++;
2844   }
2845 
2846   url_num = connections[cnum].url_num;
2847 
2848   /* Only check to update got_bytes, byte count errors and/or checksums
2849      if the request was successful (i.e. no HTTP error). */
2850   if (connections[cnum].http_status >= 0 && connections[cnum].http_status < 400) {
2851     if (do_checksum) {
2852       if (!urls[url_num].got_checksum) {
2853         urls[url_num].checksum     = connections[cnum].checksum;
2854         urls[url_num].got_checksum = 1;
2855       } else {
2856         if (connections[cnum].checksum != urls[url_num].checksum) {
2857           (void)fprintf(stderr, "%s: checksum wrong\n", urls[url_num].url_str);
2858           ++total_badchecksums;
2859         }
2860       }
2861     } else {
2862       if (!urls[url_num].got_bytes) {
2863         urls[url_num].bytes     = connections[cnum].bytes;
2864         urls[url_num].got_bytes = 1;
2865       } else {
2866         if (connections[cnum].bytes != urls[url_num].bytes) {
2867           if (!ignore_bytes)
2868             (void)fprintf(stderr, "%s: byte count wrong (expected %ld, got %ld)\n", urls[url_num].url_str, urls[url_num].bytes,
2869                           connections[cnum].bytes);
2870           ++total_badbytes;
2871         }
2872       }
2873     }
2874   }
2875 }
2876 
2877 static void
progress_report(ClientData client_data,struct timeval * nowP)2878 progress_report(ClientData client_data __attribute__((unused)), struct timeval *nowP __attribute__((unused)))
2879 {
2880   float elapsed;
2881 
2882   elapsed = delta_timeval(&start_at, nowP) / 1000000.0;
2883   (void)fprintf(stderr, "--- %g secs, %d fetches started, %d completed, %d current\n", elapsed, fetches_started, fetches_completed,
2884                 num_connections);
2885 }
2886 
2887 static void
start_timer(ClientData client_data,struct timeval * nowP)2888 start_timer(ClientData client_data __attribute__((unused)), struct timeval *nowP __attribute__((unused)))
2889 {
2890   start_connection(nowP);
2891   if (do_jitter)
2892     (void)tmr_create(nowP, start_timer, JunkClientData, (long)(random() % range_interval) + low_interval, 0);
2893 }
2894 
2895 static void
end_timer(ClientData client_data,struct timeval * nowP)2896 end_timer(ClientData client_data __attribute__((unused)), struct timeval *nowP __attribute__((unused)))
2897 {
2898   finish(nowP);
2899 }
2900 
2901 static void
finish(struct timeval * nowP)2902 finish(struct timeval *nowP)
2903 {
2904   float elapsed;
2905   int i;
2906 
2907   /* Report statistics. */
2908   elapsed = delta_timeval(&start_at, nowP) / 1000000.0;
2909   (void)printf("%d fetches on %d conns, %d max parallel, %g bytes, in %g seconds\n", fetches_completed, connects_completed,
2910                max_parallel, (float)total_bytes, elapsed);
2911   if (fetches_completed > 0)
2912     (void)printf("%g mean bytes/fetch\n", (float)total_bytes / (float)fetches_completed);
2913   if (elapsed > 0.01) {
2914     (void)printf("%g fetches/sec, %g bytes/sec\n", (float)fetches_completed / elapsed, (float)total_bytes / elapsed);
2915   }
2916   if (connects_completed > 0)
2917     (void)printf("msecs/connect: %g mean, %g max, %g min\n", (float)total_connect_usecs / (float)connects_completed / 1000.0,
2918                  (float)max_connect_usecs / 1000.0, (float)min_connect_usecs / 1000.0);
2919   if (responses_completed > 0)
2920     (void)printf("msecs/first-response: %g mean, %g max, %g min\n",
2921                  (float)total_response_usecs / (float)responses_completed / 1000.0, (float)max_response_usecs / 1000.0,
2922                  (float)min_response_usecs / 1000.0);
2923   if (total_timeouts != 0)
2924     (void)printf("%d timeouts\n", total_timeouts);
2925   if (do_checksum) {
2926     if (total_badchecksums != 0)
2927       (void)printf("%d bad checksums\n", total_badchecksums);
2928   } else {
2929     if (total_badbytes != 0)
2930       (void)printf("%d bad byte counts\n", total_badbytes);
2931   }
2932 
2933   (void)printf("HTTP response codes:\n");
2934   for (i = 0; i < 1000; ++i)
2935     if (http_status_counts[i] > 0)
2936       (void)printf("  code %03d -- %d\n", i, http_status_counts[i]);
2937   if (do_verbose) {
2938     (void)printf("Socket slot stats:\n");
2939     for (i = 0; i < max_connections; i++)
2940       if (connections[i].stats.connections > 0)
2941         (void)printf("  slot %04d -- %d connections, %d requests, %d responses\n", i, connections[i].stats.connections,
2942                      connections[i].stats.requests, connections[i].stats.responses);
2943   }
2944 
2945   tmr_destroy();
2946   if (ssl_ctx != (SSL_CTX *)0)
2947     SSL_CTX_free(ssl_ctx);
2948   exit(0);
2949 }
2950 
2951 static long long
delta_timeval(struct timeval * start,struct timeval * finish)2952 delta_timeval(struct timeval *start, struct timeval *finish)
2953 {
2954   long long delta_secs  = finish->tv_sec - start->tv_sec;
2955   long long delta_usecs = finish->tv_usec - start->tv_usec;
2956   return delta_secs * (long long)1000000L + delta_usecs;
2957 }
2958 
2959 static void *
malloc_check(size_t size)2960 malloc_check(size_t size)
2961 {
2962   void *ptr = malloc(size);
2963   check(ptr);
2964   return ptr;
2965 }
2966 
2967 static void *
realloc_check(void * ptr,size_t size)2968 realloc_check(void *ptr, size_t size)
2969 {
2970   ptr = realloc(ptr, size);
2971   check(ptr);
2972   return ptr;
2973 }
2974 
2975 static char *
strdup_check(char * str)2976 strdup_check(char *str)
2977 {
2978   str = strdup(str);
2979   check((void *)str);
2980   return str;
2981 }
2982 
2983 static void
check(void * ptr)2984 check(void *ptr)
2985 {
2986   if (ptr == (void *)0) {
2987     (void)fprintf(stderr, "%s: out of memory\n", argv0);
2988     exit(1);
2989   }
2990 }
2991