tcp-banger3.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2019 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 #include "squid.h"
10 
11 /*
12  * On some systems, FD_SETSIZE is set to something lower than the
13  * actual number of files which can be opened. IRIX is one case,
14  * NetBSD is another. So here we increase FD_SETSIZE to our
15  * configure-discovered maximum *before* any system includes.
16  */
17 #define CHANGE_FD_SETSIZE 1
18 
19 /* Cannot increase FD_SETSIZE on Linux */
20 #if _SQUID_LINUX_
21 #undef CHANGE_FD_SETSIZE
22 #define CHANGE_FD_SETSIZE 0
23 #endif
24 
25 /* Cannot increase FD_SETSIZE on FreeBSD before 2.2.0, causes select(2)
26  * to return EINVAL. */
27 /* Marian Durkovic <marian@svf.stuba.sk> */
28 /* Peter Wemm <peter@spinner.DIALix.COM> */
29 #if _SQUID_FREEBSD_
30 #include <osreldate.h>
31 #if __FreeBSD_version < 220000
32 #undef CHANGE_FD_SETSIZE
33 #define CHANGE_FD_SETSIZE 0
34 #endif
35 #endif
36 
37 /* Increase FD_SETSIZE if SQUID_MAXFD is bigger */
38 #if CHANGE_FD_SETSIZE && SQUID_MAXFD > DEFAULT_FD_SETSIZE
39 #define FD_SETSIZE SQUID_MAXFD
40 #endif
41 
42 #if HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif
45 #if HAVE_FCNTL_H
46 #include <fcntl.h>
47 #endif
48 #if HAVE_STRING_H
49 #include <string.h>
50 #endif
51 #if HAVE_STRINGS_H
52 #include <strings.h>
53 #endif
54 #if HAVE_SIGNAL_H
55 #include <signal.h>
56 #endif
57 #if HAVE_TIME_H
58 #include <time.h>
59 #endif
60 #if HAVE_SYS_SOCKET_H
61 #include <sys/socket.h>
62 #endif
63 #if HAVE_NETINET_IN_H
64 #include <netinet/in.h>
65 #endif
66 #if HAVE_ARPA_INET_H
67 #include <arpa/inet.h>
68 #endif
69 #if HAVE_ERRNO_H
70 #include <errno.h>
71 #endif
72 #if HAVE_SYS_STAT_H
73 #include <sys/stat.h>
74 #endif
75 #if HAVE_ASSERT_H
76 #include <assert.h>
77 #endif
78 #if HAVE_NETDB_H
79 #include <netdb.h>
80 #endif
81 #if HAVE_SYS_WAIT_H
82 #include <sys/wait.h>
83 #endif
84 
85 #define READ_BUF_SZ 4096
86 #define URL_BUF_SZ 4096
87 
88 struct _thing {
89  int rfd;
90  int wfd;
91  int state;
92  pid_t pid;
93  char url[URL_BUF_SZ];
94  struct _thing *next;
95 };
96 typedef struct _thing thing;
97 
98 static thing *things = NULL;
99 static fd_set R1;
100 static int maxfd = 0;
101 static struct timeval now;
102 #if DEBUG
103 static int debug = 1;
104 #else
105 static int debug = 0;
106 #endif
107 
108 int
109 tvSubMsec(struct timeval t1, struct timeval t2)
110 {
111  return (t2.tv_sec - t1.tv_sec) * 1000 + (t2.tv_usec - t1.tv_usec) / 1000;
112 }
113 
114 static int
115 get_url(const char *url)
116 {
117  char host[URL_BUF_SZ];
118  char path[URL_BUF_SZ];
119  char request[URL_BUF_SZ];
120  char reply[READ_BUF_SZ];
121  char *t;
122  int x;
123  int s;
124  int nr = 0;
125  struct hostent *h;
126  struct sockaddr_in S;
127  unsigned short port = 80;
128  assert(!strncmp(url, "http://", 7));
129  strncpy(host, url + 7, URL_BUF_SZ);
130  if ((t = strchr(host, '/')))
131  *t = '\0';
132  if ((t = strchr(host, ':'))) {
133  *t = '\0';
134  port = (unsigned short) atoi(t + 1);
135  }
136 #if 0
137  if ((int) port != 80)
138  return 0;
139 #endif
140  t = strchr(url + 7, '/');
141  strncpy(path, (t ? t : "/"), URL_BUF_SZ);
142  memset(&S, '\0', sizeof(S));
143  h = gethostbyname(host);
144  if (!h)
145  return 0;
146  memcpy(&S.sin_addr.s_addr, h->h_addr_list[0], sizeof(S.sin_addr.s_addr));
147  S.sin_port = htons(port);
148  S.sin_family = AF_INET;
149  if (debug) {
150  char tmp[16];
151  fprintf(stderr, "%s (%s) %d %s\n", host, inet_ntop(AF_INET, &S.sin_addr,tmp,sizeof(tmp)), (int) port, path);
152  }
153  s = socket(PF_INET, SOCK_STREAM, 0);
154  if (s < 0) {
155  perror("socket");
156  return -errno;
157  }
158  x = connect(s, (struct sockaddr *) &S, sizeof(S));
159  if (x < 0) {
160  perror(host);
161  return -errno;
162  }
163  snprintf(request, URL_BUF_SZ,
164  "GET %s HTTP/1.1\r\n"
165  "Accept: */*\r\n"
166  "Host: %s\r\n"
167  "Connection: close\r\n"
168  "\r\n",
169  path,
170  host);
171  x = write(s, request, strlen(request));
172  if (x < 0) {
173  perror("write");
174  return -errno;
175  }
176  do {
177  x = read(s, reply, READ_BUF_SZ);
178  if (x > 0)
179  nr += x;
180  } while (x > 0);
181  close(s);
182  return nr;
183 }
184 
185 static void
187 {
188  char buf[URL_BUF_SZ];
189  char *t;
190  int n;
191  struct timeval t1;
192  struct timeval t2;
193  if (debug)
194  fprintf(stderr, "Child PID %d entering child_main_loop\n", (int) getpid());
195  setbuf(stdin, NULL);
196  setbuf(stdout, NULL);
197  setbuf(stderr, NULL);
198  while (fgets(buf, URL_BUF_SZ, stdin)) {
199  t = strchr(buf, '\n');
200  if (t == NULL)
201  continue;
202  *t = '\0';
203  if (strncmp(buf, "http://", 7))
204  continue;
205  gettimeofday(&t1, NULL);
206  n = get_url(buf);
207  gettimeofday(&t2, NULL);
208  printf("%d %d\n", n, tvSubMsec(t1, t2));
209  }
210 }
211 
212 static thing *
213 create_a_thing(char *argv[])
214 {
215  int p2c[2];
216  int c2p[2];
217  int prfd, pwfd, crfd, cwfd;
218  pid_t pid;
219  thing *t;
220  if (pipe(p2c) < 0)
221  abort();
222  if (pipe(c2p) < 0)
223  abort();
224  prfd = p2c[0];
225  cwfd = p2c[1];
226  crfd = c2p[0];
227  pwfd = c2p[1];
228  if ((pid = fork()) < 0)
229  abort();
230  if (pid > 0) { /* parent */
231  /* close shared socket with child */
232  close(crfd);
233  close(cwfd);
234  t = calloc(1, sizeof(*t));
235  t->wfd = pwfd;
236  t->rfd = prfd;
237  if (pwfd > maxfd)
238  maxfd = pwfd;
239  if (prfd > maxfd)
240  maxfd = prfd;
241  t->pid = pid;
242  return t;
243  }
244  /* child */
245  close(prfd);
246  close(pwfd);
247  dup2(crfd, 0);
248  dup2(cwfd, 1);
249  close(crfd);
250  close(cwfd);
251  child_main_loop();
252  exit(0);
253 }
254 
255 static void
256 create_children(char *argv[])
257 {
258  thing *t;
259  thing **T = &things;
260  int i;
261  for (i = 0; i < 20; i++) {
262  t = create_a_thing(argv);
263  assert(t);
264  if (debug)
265  fprintf(stderr, "Thing #%d on FD %d/%d\n",
266  i, t->rfd, t->wfd);
267  *T = t;
268  T = &t->next;
269  }
270 }
271 
272 char *
274 {
275  static char buf[URL_BUF_SZ];
276  while (fgets(buf, URL_BUF_SZ, stdin)) {
277  if (strncmp(buf, "http://", 7))
278  continue;
279  return buf;
280  }
281  return NULL;
282 }
283 
284 static thing *
286 {
287  thing *t;
288  thing *n = things;
289  while ((t = n)) {
290  n = t->next;
291  if (t->state == 0)
292  break;
293  }
294  return t;
295 }
296 
297 static void
298 dispatch(thing * t, char *url)
299 {
300  int x;
301  char *s;
302  assert(t->state == 0);
303  x = write(t->wfd, url, strlen(url));
304  if (x < 0)
305  perror("write");
306  if (debug)
307  fprintf(stderr, "dispatched URL to thing PID %d, %d bytes\n", (int) t->pid, x);
308  strncpy(t->url, url, URL_BUF_SZ);
309  if ((s = strchr(t->url, '\n')))
310  *s = '\0';
311  t->state = 1;
312  FD_SET(t->rfd, &R1);
313 }
314 
315 static void
317 {
318  char buf[128];
319  int i;
320  int x;
321  int j;
322  x = read(t->rfd, buf, 128);
323  if (x < 0) {
324  perror("read");
325  } else if (2 == sscanf(buf, "%d %d", &i, &j)) {
326  gettimeofday(&now, NULL);
327  printf("%d.%06d %9d %9d %s\n", (int) now.tv_sec, (int) now.tv_usec, i, j, t->url);
328  }
329  t->state = 0;
330  FD_CLR(t->rfd, &R1);
331 }
332 
333 static void
335 {
336  thing *t;
337  char *url;
338  fd_set R2;
339  int x;
340  struct timeval to;
341  FD_ZERO(&R1);
342  for (;;) {
343  while ((t = get_idle_thing()) && (url = parent_read_url()))
344  dispatch(t, url);
345  R2 = R1;
346  to.tv_sec = 60;
347  to.tv_usec = 0;
348  x = select(maxfd + 1, &R2, NULL, NULL, &to);
349  if (x < 0) {
350  perror("select");
351  continue;
352  } else if (x == 0) {
353  return;
354  }
355  for (t = things; t; t = t->next) {
356  if (t->state != 1)
357  continue;
358  if (!FD_ISSET(t->rfd, &R2))
359  continue;
360  read_reply(t);
361  }
362  }
363 }
364 
365 static void
366 sig_child(int sig)
367 {
368  int status;
369  pid_t pid;
370  do {
371  pid = waitpid(-1, &status, WNOHANG);
372  } while (pid > 0 || (pid < 0 && errno == EINTR));
373  signal(sig, sig_child);
374 }
375 
376 int
377 main(int argc, char *argv[])
378 {
379  int i;
380  signal(SIGCHLD, sig_child);
381  create_children(argv);
383  for (i = 3; i <= maxfd; i++)
384  close(i);
385  sleep(1);
386 }
387 
struct _thing * next
Definition: tcp-banger3.c:94
int state
Definition: tcp-banger3.c:91
static struct timeval now
Definition: tcp-banger3.c:101
#define assert(EX)
Definition: assert.h:17
static void create_children(char *argv[])
Definition: tcp-banger3.c:256
static void dispatch(thing *t, char *url)
Definition: tcp-banger3.c:298
int main(int argc, char *argv[])
Definition: tcp-banger3.c:377
static void parent_main_loop(void)
Definition: tcp-banger3.c:334
static void child_main_loop(void)
Definition: tcp-banger3.c:186
struct _request * request(char *urlin)
Definition: tcp-banger2.c:291
int i
Definition: membanger.c:49
static void sig_child(int sig)
Definition: tcp-banger3.c:366
int tvSubMsec(struct timeval t1, struct timeval t2)
Definition: tcp-banger3.c:109
char ** h_addr_list
int wfd
Definition: tcp-banger3.c:90
char * parent_read_url(void)
Definition: tcp-banger3.c:273
char url[URL_BUF_SZ]
Definition: tcp-banger3.c:93
static thing * things
Definition: tcp-banger3.c:98
#define inet_ntop
Definition: inet_ntop.h:25
int rfd
Definition: tcp-banger3.c:89
static int debug
Definition: tcp-banger3.c:105
static void read_reply(thing *t)
Definition: tcp-banger3.c:316
static int port
Definition: ldap_backend.cc:69
static thing * get_idle_thing(void)
Definition: tcp-banger3.c:285
void const char * buf
Definition: stub_helper.cc:16
#define READ_BUF_SZ
Definition: tcp-banger3.c:85
static int maxfd
Definition: tcp-banger3.c:100
struct hostent * gethostbyname()
static thing * create_a_thing(char *argv[])
Definition: tcp-banger3.c:213
#define URL_BUF_SZ
Definition: tcp-banger3.c:86
static fd_set R1
Definition: tcp-banger3.c:99
static int get_url(const char *url)
Definition: tcp-banger3.c:115
#define NULL
Definition: types.h:166
pid_t pid
Definition: tcp-banger3.c:92

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors