]> git.ipfire.org Git - thirdparty/squid.git/blob - test-suite/tcp-banger2.c
added connection lifetime and -l secs option
[thirdparty/squid.git] / test-suite / tcp-banger2.c
1
2 #define FD_SETSIZE 1024
3
4 #include <stdio.h>
5 #include <unistd.h>
6 #include <stdlib.h>
7 #include <fcntl.h>
8 #include <string.h>
9 #include <strings.h>
10 #include <sys/types.h>
11 #include <sys/select.h>
12 #include <signal.h>
13 #include <time.h>
14 #include <sys/time.h>
15 #include <sys/socket.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
18 #include <errno.h>
19
20 #define PROXY_PORT 3128
21 #define PROXY_ADDR "127.0.0.1"
22 #define MAX_FDS 1024
23 #define READ_BUF_SZ 4096
24
25 static int proxy_port = PROXY_PORT;
26 static char *proxy_addr = PROXY_ADDR;
27 static char *progname;
28 static int reqpersec;
29 static int nrequests;
30 static int opt_ims = 0;
31 static int max_connections = 64;
32 static time_t lifetime = 60;
33 static struct timeval now;
34
35 typedef void (CB) (int, void *);
36
37 struct _f {
38 CB *cb;
39 void *data;
40 time_t start;
41 };
42
43 struct _f FD[MAX_FDS];
44 int nfds = 0;
45 int maxfd = 0;
46
47
48 char *
49 mkrfc850(t)
50 time_t *t;
51 {
52 static char buf[128];
53 struct tm *gmt = gmtime(t);
54 buf[0] = '\0';
55 (void) strftime(buf, 127, "%A, %d-%b-%y %H:%M:%S GMT", gmt);
56 return buf;
57 }
58
59 void
60 fd_close(int fd)
61 {
62 close(fd);
63 FD[fd].cb = NULL;
64 FD[fd].data = NULL;
65 nfds--;
66 if (fd == maxfd) {
67 while (FD[fd].cb == NULL)
68 fd--;
69 maxfd = fd;
70 }
71 }
72
73 void
74 fd_open(int fd, CB * cb, void *data)
75 {
76 FD[fd].cb = cb;
77 FD[fd].data = data;
78 FD[fd].start = now.tv_sec;
79 if (fd > maxfd)
80 maxfd = fd;
81 nfds++;
82 }
83
84 void
85 sig_intr(int sig)
86 {
87 fd_close(0);
88 printf("\rWaiting for open connections to finish...\n");
89 signal(sig, SIG_DFL);
90 }
91
92 void
93 read_reply(int fd, void *data)
94 {
95 static char buf[READ_BUF_SZ];
96 if (read(fd, buf, READ_BUF_SZ) <= 0) {
97 fd_close(fd);
98 reqpersec++;
99 nrequests++;
100 }
101 }
102
103 int
104 request(url)
105 char *url;
106 {
107 int s;
108 char buf[4096];
109 int len;
110 time_t w;
111 struct sockaddr_in S;
112 if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
113 perror("socket");
114 return -1;
115 }
116 memset(&S, '\0', sizeof(struct sockaddr_in));
117 S.sin_family = AF_INET;
118 S.sin_port = htons(proxy_port);
119 S.sin_addr.s_addr = inet_addr(proxy_addr);
120 if (connect(s, (struct sockaddr *) &S, sizeof(S)) < 0) {
121 close(s);
122 perror("connect");
123 return -1;
124 }
125 buf[0] = '\0';
126 strcat(buf, "GET ");
127 strcat(buf, url);
128 strcat(buf, " HTTP/1.0\r\n");
129 strcat(buf, "Accept: */*\r\n");
130 if (opt_ims && (lrand48() & 0x03) == 0) {
131 w = time(NULL) - (lrand48() & 0x3FFFF);
132 strcat(buf, "If-Modified-Since: ");
133 strcat(buf, mkrfc850(&w));
134 strcat(buf, "\r\n");
135 }
136 strcat(buf, "\r\n");
137 len = strlen(buf);
138 if (write(s, buf, len) < 0) {
139 close(s);
140 perror("write");
141 return -1;
142 }
143 /*
144 * if (fcntl(s, F_SETFL, O_NDELAY) < 0)
145 * perror("fcntl O_NDELAY");
146 */
147 return s;
148 }
149
150 void
151 read_url(int fd, void *junk)
152 {
153 static char buf[8192];
154 char *t;
155 int s;
156 if (fgets(buf, 8191, stdin) == NULL) {
157 printf("Done Reading URLS\n");
158 fd_close(0);
159 return;
160 }
161 if ((t = strchr(buf, '\n')))
162 *t = '\0';
163 s = request(buf);
164 if (s < 0) {
165 max_connections = nfds - 1;
166 printf("NOTE: max_connections set at %d\n", max_connections);
167 }
168 fd_open(s, read_reply, NULL);
169 }
170
171 void
172 usage(void)
173 {
174 fprintf(stderr, "usage: %s: -p port -h host -n max\n", progname);
175 }
176
177 int
178 main(argc, argv)
179 int argc;
180 char *argv[];
181 {
182 int i;
183 int c;
184 int dt;
185 fd_set R;
186 struct timeval start;
187 struct timeval last;
188 struct timeval to;
189 setbuf(stdout, NULL);
190 setbuf(stderr, NULL);
191 progname = strdup(argv[0]);
192 gettimeofday(&start, NULL);
193 last = start;
194 while ((c = getopt(argc, argv, "p:h:n:il:")) != -1) {
195 switch (c) {
196 case 'p':
197 proxy_port = atoi(optarg);
198 break;
199 case 'h':
200 proxy_addr = strdup(optarg);
201 break;
202 case 'n':
203 max_connections = atoi(optarg);
204 break;
205 case 'i':
206 opt_ims = 1;
207 break;
208 case 'l':
209 lifetime = (time_t) atoi(optarg);
210 break;
211 default:
212 usage();
213 return 1;
214 }
215 }
216 fd_open(0, read_url, NULL);
217 signal(SIGINT, sig_intr);
218 while (nfds) {
219 FD_ZERO(&R);
220 to.tv_sec = 0;
221 to.tv_usec = 100000;
222 if (nfds < max_connections && FD[0].cb)
223 FD_SET(0, &R);
224 for (i = 1; i <= maxfd; i++) {
225 if (FD[i].cb == NULL)
226 continue;
227 if (now.tv_sec - FD[i].start > lifetime) {
228 fd_close(i);
229 continue;
230 }
231 FD_SET(i, &R);
232 }
233 if (select(maxfd + 1, &R, NULL, NULL, &to) < 0) {
234 if (errno != EINTR)
235 perror("select");
236 continue;
237 }
238 for (i = 0; i <= maxfd; i++) {
239 if (!FD_ISSET(i, &R))
240 continue;
241 FD[i].cb(i, FD[i].data);
242 }
243 gettimeofday(&now, NULL);
244 if (now.tv_sec > last.tv_sec) {
245 last = now;
246 dt = (int) (now.tv_sec - start.tv_sec);
247 printf("T+ %6d: %9d req (%+4d), %4d conn, %3d/sec avg\n",
248 dt,
249 nrequests,
250 reqpersec,
251 nfds,
252 (int) (nrequests / dt));
253 reqpersec = 0;
254 }
255 }
256 return 0;
257 }