⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pconn-banger.c

📁 -
💻 C
字号:
#include "config.h"/* * On some systems, FD_SETSIZE is set to something lower than the * actual number of files which can be opened.  IRIX is one case, * NetBSD is another.  So here we increase FD_SETSIZE to our * configure-discovered maximum *before* any system includes. */#define CHANGE_FD_SETSIZE 1/* Cannot increase FD_SETSIZE on Linux */#if defined(_SQUID_LINUX_)#undef CHANGE_FD_SETSIZE#define CHANGE_FD_SETSIZE 0#endif/* Cannot increase FD_SETSIZE on FreeBSD before 2.2.0, causes select(2) * to return EINVAL. *//* Marian Durkovic <marian@svf.stuba.sk> *//* Peter Wemm <peter@spinner.DIALix.COM> */#if defined(_SQUID_FREEBSD_)#include <osreldate.h>#if __FreeBSD_version < 220000#undef CHANGE_FD_SETSIZE#define CHANGE_FD_SETSIZE 0#endif#endif/* Increase FD_SETSIZE if SQUID_MAXFD is bigger */#if CHANGE_FD_SETSIZE && SQUID_MAXFD > DEFAULT_FD_SETSIZE#define FD_SETSIZE SQUID_MAXFD#endif#if HAVE_UNISTD_H#include <unistd.h>#endif#if HAVE_STDLIB_H#include <stdlib.h>#endif#if HAVE_STDIO_H#include <stdio.h>#endif#if HAVE_FCNTL_H#include <fcntl.h>#endif#ifdef HAVE_STRING_H#include <string.h>#endif#ifdef HAVE_STRINGS_H#include <strings.h>#endif#ifdef HAVE_BSTRING_H#include <bstring.h>#endif#if HAVE_SYS_TYPES_H#include <sys/types.h>#endif#if HAVE_SYS_SELECT_H#include <sys/select.h>#endif#if HAVE_SIGNAL_H#include <signal.h>#endif#if HAVE_TIME_H#include <time.h>#endif#if HAVE_SYS_TIME_H#include <sys/time.h>#endif#if HAVE_SYS_SOCKET_H#include <sys/socket.h>#endif#if HAVE_NETINET_IN_H#include <netinet/in.h>#endif#if HAVE_ARPA_INET_H#include <arpa/inet.h>#endif#if HAVE_ERRNO_H#include <errno.h>#endif#if HAVE_CTYPE_H#include <ctype.h>#endif#if HAVE_ASSERT_H#include <assert.h>#endif#if HAVE_SYS_STAT_H#include <sys/stat.h>#endif#define PROXY_PORT 3128#define PROXY_ADDR "127.0.0.1"#define MAX_FDS 1024#define READ_BUF_SZ 4096#define min(x,y) ((x)<(y)? (x) : (y))static int proxy_port = PROXY_PORT;static char *proxy_addr = PROXY_ADDR;static char *progname;static int noutstanding = 0;static int done_reading_urls = 0;static int opt_ims = 0;static int opt_checksum = 0;static int opt_reopen = 1;static int max_outstanding = 10;static time_t lifetime = 60;static const char *const crlf = "\r\n";static int trace_fd = -1;static int total_bytes_read = 0;#define REPLY_HDR_SZ 8192struct _r {    char url[1024];    int content_length;    int hdr_length;    int hdr_offset;    int bytes_read;    char reply_hdrs[REPLY_HDR_SZ];    struct _r *next;    long sum;    long validsize;    long validsum;};static struct _r *Requests;char *mkrfc850(t)     time_t *t;{    static char buf[128];    struct tm *gmt = gmtime(t);    buf[0] = '\0';    (void) strftime(buf, 127, "%A, %d-%b-%y %H:%M:%S GMT", gmt);    return buf;}char *mime_headers_end(const char *mime){    const char *p1, *p2;    const char *end = NULL;    p1 = strstr(mime, "\n\r\n");    p2 = strstr(mime, "\n\n");    if (p1 && p2)	end = p1 < p2 ? p1 : p2;    else	end = p1 ? p1 : p2;    if (end)	end += (end == p1 ? 3 : 2);    return (char *) end;}voidsig_intr(int sig){    fprintf(stderr, "\rWaiting for open connections to finish...\n");    signal(sig, SIG_DFL);    done_reading_urls = 1;}intopen_http_socket(void){    int s;    struct sockaddr_in S;    if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {	perror("socket");	return -1;    }    memset(&S, '\0', sizeof(struct sockaddr_in));    S.sin_family = AF_INET;    S.sin_port = htons(proxy_port);    S.sin_addr.s_addr = inet_addr(proxy_addr);    if (connect(s, (struct sockaddr *) &S, sizeof(S)) < 0) {	close(s);	perror("connect");	return -1;    }    return s;}intsend_request(int fd, const char *data){    char msg[4096],buf[4096];    int len;    time_t w;    struct _r *r;    struct _r **R;    char *method, *url, *file, *size, *checksum;    char *tmp = strdup(data);    struct stat st;    int file_fd = -1;    method=strtok(tmp, " ");    url=strtok(NULL, " ");    file=strtok(NULL, " ");    size=strtok(NULL, " ");    checksum=strtok(NULL, " ");    if (!url) {      url=method;      method="GET";    }    if (file && strcmp(file,"-")==0)	file=NULL;    if (size && strcmp(size,"-")==0)	size=NULL;    if (checksum && strcmp(checksum,"-")==0)	checksum=NULL;    msg[0] = '\0';    sprintf(buf, "%s %s HTTP/1.0\r\n", method, url);    strcat(msg,buf);    strcat(msg, "Accept: */*\r\n");    strcat(msg, "Proxy-Connection: Keep-Alive\r\n");    if (opt_ims && (lrand48() & 0x03) == 0) {	w = time(NULL) - (lrand48() & 0x3FFFF);	sprintf(buf, "If-Modified-Since: %s\r\n", mkrfc850(&w));	strcat(msg, buf);    }    if (file) {	if ( (file_fd = open(file,O_RDONLY)) < 0) {	    perror("open");	    return -1;	}	if ( fstat(file_fd, &st) ) {	    perror("fstat");	    close(file_fd);	    return -1;	}	sprintf(buf, "Content-length: %d\r\n", st.st_size);	strcat(msg, buf);    }    strcat(msg, "\r\n");    len = strlen(msg);    if (write(fd, msg, len) < 0) {	close(fd);	perror("request write");	close(file_fd);	return -1;    }    if (file) {	while((len=read(file_fd, buf, sizeof buf)) > 0) {	    if (write(fd, buf, len) < 0) {		close(fd);		perror("body write");		close(file_fd);		return -1;	    }	}	if (len < 0) {	    perror("file read");	    close(file_fd);	    return -1;	}	close(file_fd);    }    r = calloc(1, sizeof(struct _r));    strcpy(r->url, url);    if (size)	r->validsize = atoi(size);    else	r->validsize = -1;    if (checksum)	r->validsum = atoi(checksum);    for (R = &Requests; *R; R = &(*R)->next);    *R = r;/*    fprintf(stderr, "REQUESTED %s\n", url); */    noutstanding++;    return 0;}static intget_header_int_value(const char *hdr, const char *buf, const char *end){    const char *t;    for (t = buf; t < end; t += strcspn(t, crlf), t += strspn(t, crlf)) {	if (strncasecmp(t, hdr, strlen(hdr)) == 0) {	    t += strlen(hdr);	    while (isspace(*t))		t++;	    return atoi(t);	}    }    return -1;}static const char *get_header_string_value(const char *hdr, const char *buf, const char *end){    const char *t;    static char result[8192];    for (t = buf; t < end; t += strcspn(t, crlf), t += strspn(t, crlf)) {	if (strncasecmp(t, hdr, strlen(hdr)) == 0) {	    t += strlen(hdr);	    while (isspace(*t))		t++;	    strcpy(result,"");	    strncat(result,t,strcspn(t, crlf));	    return result;	}    }    return NULL;}voidrequest_done(struct _r *r){#if 0    fprintf(stderr, "DONE: %s, (%d+%d)\n",	    r->url,	    r->hdr_length,	    r->content_length);#endif    if (r->content_length != r->bytes_read)	fprintf(stderr, "ERROR! Short reply, expected %d bytes got %d\n",	    r->content_length, r->bytes_read);    else if (r->validsize >= 0) {	if (r->validsize != r->bytes_read)	    fprintf(stderr, "WARNING: %s Object size mismatch, expected %d got %d\n",		    r->url, r->validsize, r->bytes_read);	else if (opt_checksum && r->sum != r->validsum)	    fprintf(stderr, "WARNING: %s Checksum error. Expected %d got %d\n",		    r->url, r->validsum, r->sum);    }}inthandle_read(char *inbuf, int len){    struct _r *r = Requests;    const char *end;    const char *url;    static char buf[READ_BUF_SZ];    int hlen,blen;    if (len < 0 ) {	perror("read");	Requests = r->next;	request_done(r);	free(r);	noutstanding--;	if (trace_fd >= 0)	    write(trace_fd,"\n[CLOSED]\n",10);	return -1;    }    total_bytes_read += len;    xmemcpy(buf,inbuf,len);    if (len == 0) {	fprintf(stderr, "WARNING: %s, server closed socket after %d+%d bytes\n", r->url, r->hdr_offset, r->bytes_read);	/* XXX, If no data was received and it isn't the first request on this	 * connection then the request should be restarted rather than aborted	 * but this is a simple test program an not a full blown HTTP client.	 */	request_done(r);	Requests = r->next;	free(r);	noutstanding--;	return -1;    }    if (trace_fd > 0)	write(trace_fd, buf, len);    while (len > 0) {	/* Build headers */	if (r->hdr_length == 0) {	    hlen = min(len, REPLY_HDR_SZ - r->hdr_offset - 1);	    xmemcpy(r->reply_hdrs + r->hdr_offset, buf, hlen);	    r->hdr_offset += hlen;	    r->reply_hdrs[r->hdr_offset] = '\0';	    len -= hlen;	    /* Save any remaining read data */	    xmemmove(buf, buf + hlen, len);	}	/* Process headers */	if (r->hdr_length == 0 && (end = mime_headers_end(r->reply_hdrs)) != NULL) {#if 0	    fprintf(stderr, "FOUND EOH FOR %s\n", r->url); */#endif	    r->hdr_length = end - r->reply_hdrs;#if 0 	    fprintf(stderr, "HDR_LENGTH = %d\n", r->hdr_length);#endif	    /* "unread" any body contents received */	    blen = r->hdr_offset - r->hdr_length;	    assert(blen >= 0);	    if (blen > 0) {		xmemmove(buf + blen, buf, len);		xmemcpy(buf, r->reply_hdrs + r->hdr_length, blen);		len += blen;	    }	    r->reply_hdrs[r->hdr_length]='\0'; /* Null terminate headers */	    /* Parse headers */	    r->content_length = get_header_int_value("content-length:", r->reply_hdrs, end);/*	    fprintf(stderr, "CONTENT_LENGTH = %d\n", r->content_length); */	    url = get_header_string_value("X-Request-URI:", r->reply_hdrs, end);	    if (url != NULL && strcmp(r->url, url) != 0)		fprintf(stderr, "WARNING: %s got reply %s\n", r->url, url);#if XREQUESTURI || 0	    fprintf(stderr, "LOCATION = %s\n", get_header_string_value("X-Request-URI:", r->reply_hdrs, end));  #endif	}	if ( !(len==0 || r->hdr_length > 0) ) {	    fprintf(stderr, "ERROR!!!\n");	    assert((len==0 || r->hdr_length > 0));	}	/* Process body */	if (r->hdr_length != 0) {	    int i;	    int bytes_left, bytes_used;	    if (r->content_length >= 0) {		bytes_left = r->content_length - r->bytes_read;		assert(bytes_left >= 0);	    	bytes_used = len < bytes_left ? len : bytes_left;	    } else {		bytes_left = len + 1; /* Unknown end... */		bytes_used = len;	    }	    if (opt_checksum) {		for(i=0; i<bytes_used; i++)		    r->sum += (int)buf[i] & 0xFF;	    }	    r->bytes_read += bytes_used;	    len -= bytes_used;	    if (bytes_left == bytes_used) {		request_done(r);		Requests = r->next;		free(r);		noutstanding--;		r = Requests;	    } else if (r->content_length > -1) {		assert(r->bytes_read < r->content_length);	    }	    xmemmove(buf, buf + bytes_used, len);	}    }    return 0;}intread_reply(int fd){    static char buf[READ_BUF_SZ];    int len;    int x;    len = read(fd, buf, READ_BUF_SZ);    x = handle_read(buf, len);    if (x < 0) {	perror("read reply");	close(fd);    }    return x;}voidmain_loop(void){    static int pconn_fd = -1;    static char buf[8192];    struct timeval to;    struct timeval now,last,start;    fd_set R;    struct _r *r;    struct _r *nextr;    int x;    int timeouts;    int nrequests = 0, rrequests = 0, reqpersec = 0;    gettimeofday(&start, NULL);    last = start;    pconn_fd = open_http_socket();    if (pconn_fd < 0) {	perror("socket");	exit(1);    }    while (!done_reading_urls || noutstanding) {	if (!opt_reopen && pconn_fd < 0) {	    fprintf(stderr,"TERMINATED: Connection closed\n");	    break;	}	if (pconn_fd<0) {	    pconn_fd = open_http_socket();	    if (pconn_fd < 0) {		perror("socket");		exit(1);	    }	    nextr = Requests;	    Requests = NULL;	    noutstanding=0;	    while ((r = nextr) != NULL) {		nextr = r->next;		if (send_request(pconn_fd, r->url) != 0) {		    close(pconn_fd);		    pconn_fd=-1;		    nextr = r;		    for (r = Requests; r!=NULL && r->next; r=r->next);		    if (r != NULL)			r->next = nextr;		    else			Requests = nextr;		    break;		}		free(r);	    }	    timeouts = 0;	    if (pconn_fd <0)		continue;	}	if (timeouts == 200) {	    close(pconn_fd);	    pconn_fd = -1;	    r = Requests;	    Requests = Requests->next;	    fprintf(stderr, "ABORT %s\n", Requests->url);	    free(r);	    noutstanding--;	}	if (pconn_fd>=0 && noutstanding < max_outstanding && !done_reading_urls) {	    char *t;	    if (fgets(buf, 8191, stdin) == NULL) {		fprintf(stderr, "Done Reading URLS\n");		done_reading_urls = 1;		continue;	    }	    rrequests++;	    if ((t = strchr(buf, '\n')))		*t = '\0';	    if (send_request(pconn_fd, buf) != 0) {		close(pconn_fd);		pconn_fd=-1;		continue;	    }	    nrequests++;	    reqpersec++;	    timeouts = 0;	}	FD_ZERO(&R);	to.tv_sec = 1;	to.tv_usec = 0;	FD_SET(pconn_fd, &R);	x = select(pconn_fd + 1, &R, NULL, NULL, &to);	if (x < 0) {	    if (errno != EINTR)		perror("select");	    continue;	} else if (x == 0) {	    assert(Requests != NULL);	    fprintf(stderr, "TIMEOUT %s; %d, %d\n", Requests->url,		++timeouts, noutstanding);	    continue;	}	if (FD_ISSET(pconn_fd, &R)) {	    timeouts = 0;	    if (read_reply(pconn_fd) != 0)		pconn_fd = -1;	}	gettimeofday(&now, NULL);        if (now.tv_sec > last.tv_sec) {	    int dt;	    int nreq;	    last = now;	    dt = (int) (now.tv_sec - start.tv_sec);	    nreq=0;	    for (r=Requests; r ; r=r->next) nreq++;	    printf("T+ %6d: %9d req (%+4d), %4d pend, %3d/sec avg, %dmb, %dkb/sec avg\n",		    dt,		    nrequests,		    reqpersec,		    nreq,		    (int) (nrequests / dt),		    (int)total_bytes_read / 1024 / 1024,		    (int)total_bytes_read / 1024 / dt);	    reqpersec = 0;	}    }}voidusage(void){    fprintf(stderr, "usage: %s: -p port -h host -n max -t tracefile -i -c -l lifetime\n", progname);}intmain(argc, argv)     int argc;     char *argv[];{    int c;    setbuf(stdout, NULL);    setbuf(stderr, NULL);    progname = strdup(argv[0]);    while ((c = getopt(argc, argv, "p:h:n:t:icl:r")) != -1) {	switch (c) {	case 'p':	    proxy_port = atoi(optarg);	    break;	case 'h':	    proxy_addr = strdup(optarg);	    break;	case 'n':	    max_outstanding = atoi(optarg);	    break;	case 'i':	    opt_ims = 1;	    break;	case 'c':	    opt_checksum = 1;	    break;	case 'l':	    lifetime = (time_t) atoi(optarg);	    break;	case 't':	    trace_fd = open(optarg,O_WRONLY|O_CREAT|O_TRUNC,0666);	    break;	case 'r':	    opt_reopen = !opt_reopen;	    break;	default:	    usage();	    return 1;	}    }    signal(SIGINT, sig_intr);    signal(SIGPIPE, SIG_IGN);    main_loop();    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -