tcp-banger3.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2022 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
88struct _thing {
89 int rfd;
90 int wfd;
91 int state;
92 pid_t pid;
94 struct _thing *next;
95};
96typedef struct _thing thing;
97
98static thing *things = NULL;
99static fd_set R1;
100static int maxfd = 0;
101static struct timeval now;
102#if DEBUG
103static int debug = 1;
104#else
105static int debug = 0;
106#endif
107
108int
109tvSubMsec(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
114static int
115get_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 t = strchr(url + 7, '/');
137 strncpy(path, (t ? t : "/"), URL_BUF_SZ);
138 memset(&S, '\0', sizeof(S));
139 h = gethostbyname(host);
140 if (!h)
141 return 0;
142 memcpy(&S.sin_addr.s_addr, h->h_addr_list[0], sizeof(S.sin_addr.s_addr));
143 S.sin_port = htons(port);
144 S.sin_family = AF_INET;
145 if (debug) {
146 char tmp[16];
147 fprintf(stderr, "%s (%s) %d %s\n", host, inet_ntop(AF_INET, &S.sin_addr,tmp,sizeof(tmp)), (int) port, path);
148 }
149 s = socket(PF_INET, SOCK_STREAM, 0);
150 if (s < 0) {
151 perror("socket");
152 return -errno;
153 }
154 x = connect(s, (struct sockaddr *) &S, sizeof(S));
155 if (x < 0) {
156 perror(host);
157 return -errno;
158 }
159 snprintf(request, URL_BUF_SZ,
160 "GET %s HTTP/1.1\r\n"
161 "Accept: */*\r\n"
162 "Host: %s\r\n"
163 "Connection: close\r\n"
164 "\r\n",
165 path,
166 host);
167 x = write(s, request, strlen(request));
168 if (x < 0) {
169 perror("write");
170 return -errno;
171 }
172 do {
173 x = read(s, reply, READ_BUF_SZ);
174 if (x > 0)
175 nr += x;
176 } while (x > 0);
177 close(s);
178 return nr;
179}
180
181static void
183{
184 char buf[URL_BUF_SZ];
185 char *t;
186 int n;
187 struct timeval t1;
188 struct timeval t2;
189 if (debug)
190 fprintf(stderr, "Child PID %d entering child_main_loop\n", (int) getpid());
191 setbuf(stdin, NULL);
192 setbuf(stdout, NULL);
193 setbuf(stderr, NULL);
194 while (fgets(buf, URL_BUF_SZ, stdin)) {
195 t = strchr(buf, '\n');
196 if (t == NULL)
197 continue;
198 *t = '\0';
199 if (strncmp(buf, "http://", 7))
200 continue;
201 gettimeofday(&t1, NULL);
202 n = get_url(buf);
203 gettimeofday(&t2, NULL);
204 printf("%d %d\n", n, tvSubMsec(t1, t2));
205 }
206}
207
208static thing *
209create_a_thing(char *argv[])
210{
211 int p2c[2];
212 int c2p[2];
213 int prfd, pwfd, crfd, cwfd;
214 pid_t pid;
215 thing *t;
216 if (pipe(p2c) < 0)
217 abort();
218 if (pipe(c2p) < 0)
219 abort();
220 prfd = p2c[0];
221 cwfd = p2c[1];
222 crfd = c2p[0];
223 pwfd = c2p[1];
224 if ((pid = fork()) < 0)
225 abort();
226 if (pid > 0) { /* parent */
227 /* close shared socket with child */
228 close(crfd);
229 close(cwfd);
230 t = calloc(1, sizeof(*t));
231 t->wfd = pwfd;
232 t->rfd = prfd;
233 if (pwfd > maxfd)
234 maxfd = pwfd;
235 if (prfd > maxfd)
236 maxfd = prfd;
237 t->pid = pid;
238 return t;
239 }
240 /* child */
241 close(prfd);
242 close(pwfd);
243 dup2(crfd, 0);
244 dup2(cwfd, 1);
245 close(crfd);
246 close(cwfd);
248 exit(0);
249}
250
251static void
252create_children(char *argv[])
253{
254 thing *t;
255 thing **T = &things;
256 int i;
257 for (i = 0; i < 20; i++) {
258 t = create_a_thing(argv);
259 assert(t);
260 if (debug)
261 fprintf(stderr, "Thing #%d on FD %d/%d\n",
262 i, t->rfd, t->wfd);
263 *T = t;
264 T = &t->next;
265 }
266}
267
268char *
270{
271 static char buf[URL_BUF_SZ];
272 while (fgets(buf, URL_BUF_SZ, stdin)) {
273 if (strncmp(buf, "http://", 7))
274 continue;
275 return buf;
276 }
277 return NULL;
278}
279
280static thing *
282{
283 thing *t;
284 thing *n = things;
285 while ((t = n)) {
286 n = t->next;
287 if (t->state == 0)
288 break;
289 }
290 return t;
291}
292
293static void
294dispatch(thing * t, char *url)
295{
296 int x;
297 char *s;
298 assert(t->state == 0);
299 x = write(t->wfd, url, strlen(url));
300 if (x < 0)
301 perror("write");
302 if (debug)
303 fprintf(stderr, "dispatched URL to thing PID %d, %d bytes\n", (int) t->pid, x);
304 strncpy(t->url, url, URL_BUF_SZ);
305 if ((s = strchr(t->url, '\n')))
306 *s = '\0';
307 t->state = 1;
308 FD_SET(t->rfd, &R1);
309}
310
311static void
313{
314 char buf[128];
315 int i;
316 int x;
317 int j;
318 x = read(t->rfd, buf, 128);
319 if (x < 0) {
320 perror("read");
321 } else if (2 == sscanf(buf, "%d %d", &i, &j)) {
322 gettimeofday(&now, NULL);
323 printf("%d.%06d %9d %9d %s\n", (int) now.tv_sec, (int) now.tv_usec, i, j, t->url);
324 }
325 t->state = 0;
326 FD_CLR(t->rfd, &R1);
327}
328
329static void
331{
332 thing *t;
333 char *url;
334 fd_set R2;
335 int x;
336 struct timeval to;
337 FD_ZERO(&R1);
338 for (;;) {
339 while ((t = get_idle_thing()) && (url = parent_read_url()))
340 dispatch(t, url);
341 R2 = R1;
342 to.tv_sec = 60;
343 to.tv_usec = 0;
344 x = select(maxfd + 1, &R2, NULL, NULL, &to);
345 if (x < 0) {
346 perror("select");
347 continue;
348 } else if (x == 0) {
349 return;
350 }
351 for (t = things; t; t = t->next) {
352 if (t->state != 1)
353 continue;
354 if (!FD_ISSET(t->rfd, &R2))
355 continue;
356 read_reply(t);
357 }
358 }
359}
360
361static void
362sig_child(int sig)
363{
364 int status;
365 pid_t pid;
366 do {
367 pid = waitpid(-1, &status, WNOHANG);
368 } while (pid > 0 || (pid < 0 && errno == EINTR));
369 signal(sig, sig_child);
370}
371
372int
373main(int argc, char *argv[])
374{
375 int i;
376 signal(SIGCHLD, sig_child);
377 create_children(argv);
379 for (i = 3; i <= maxfd; i++)
380 close(i);
381 sleep(1);
382}
383
static pid_t pid
Definition: IcmpSquid.cc:34
#define assert(EX)
Definition: assert.h:19
static int port
Definition: ldap_backend.cc:70
#define inet_ntop
Definition: inet_ntop.h:25
struct hostent * gethostbyname()
char url[URL_BUF_SZ]
Definition: tcp-banger3.c:93
int wfd
Definition: tcp-banger3.c:90
pid_t pid
Definition: tcp-banger3.c:92
int state
Definition: tcp-banger3.c:91
struct _thing * next
Definition: tcp-banger3.c:94
int rfd
Definition: tcp-banger3.c:89
char ** h_addr_list
struct _request * request(char *urlin)
Definition: tcp-banger2.c:291
static thing * create_a_thing(char *argv[])
Definition: tcp-banger3.c:209
int main(int argc, char *argv[])
Definition: tcp-banger3.c:373
static void sig_child(int sig)
Definition: tcp-banger3.c:362
static void child_main_loop(void)
Definition: tcp-banger3.c:182
char * parent_read_url(void)
Definition: tcp-banger3.c:269
#define READ_BUF_SZ
Definition: tcp-banger3.c:85
static int maxfd
Definition: tcp-banger3.c:100
static fd_set R1
Definition: tcp-banger3.c:99
static thing * things
Definition: tcp-banger3.c:98
static void read_reply(thing *t)
Definition: tcp-banger3.c:312
static void create_children(char *argv[])
Definition: tcp-banger3.c:252
static void dispatch(thing *t, char *url)
Definition: tcp-banger3.c:294
#define URL_BUF_SZ
Definition: tcp-banger3.c:86
static struct timeval now
Definition: tcp-banger3.c:101
static int debug
Definition: tcp-banger3.c:105
static thing * get_idle_thing(void)
Definition: tcp-banger3.c:281
static void parent_main_loop(void)
Definition: tcp-banger3.c:330
static int get_url(const char *url)
Definition: tcp-banger3.c:115
int tvSubMsec(struct timeval t1, struct timeval t2)
Definition: tcp-banger3.c:109
#define NULL
Definition: types.h:166

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors