Re: Body processing patch [pconn-banger patch]

From: Henrik Nordstrom <hno@dont-contact.us>
Date: Fri, 01 May 1998 14:32:46 +0200

This is a multi-part message in MIME format.

--------------744066D03CE61966E2180F2
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Henrik Nordstrom wrote:

> My Squid also seems to have severe problems with pipelined
> connections. Not sure if this is caused by my patch or not.

False alarm. It was pconn-banger that had severe problems with pipelined
connections, not Squid or my patch. [fixed].

This pconn-banger patch
* Fixes some bugs
* Adds -t <tracefile> to save a trace of all read data
* Adds the possibility to send generic HTTP requests by using the syntax
"[Method] URL [Body-File]".

It does not handle "no-body" replies (HEAD).

/Henrik

--------------744066D03CE61966E2180F2
Content-Type: text/plain; charset=us-ascii; name="squid-1.2.beta20-1.pconn-banger.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="squid-1.2.beta20-1.pconn-banger.patch"

Index: squid/test-suite/pconn-banger.c
diff -u squid/test-suite/pconn-banger.c:1.1.1.5 squid/test-suite/pconn-banger.c:1.1.1.5.16.1
--- squid/test-suite/pconn-banger.c:1.1.1.5 Thu Feb 5 22:45:12 1998
+++ squid/test-suite/pconn-banger.c Fri May 1 14:10:52 1998
@@ -86,6 +86,9 @@
 #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"
@@ -99,9 +102,10 @@
 static int noutstanding = 0;
 static int done_reading_urls = 0;
 static int opt_ims = 0;
-static int max_connections = 64;
+static int max_outstanding = 10;
 static time_t lifetime = 60;
 static const char *const crlf = "\r\n";
+static int trace_fd = -1;
 
 #define REPLY_HDR_SZ 8192
 
@@ -153,6 +157,7 @@
 {
     printf("\rWaiting for open connections to finish...\n");
     signal(sig, SIG_DFL);
+ done_reading_urls = 1;
 }
 
 int
@@ -177,34 +182,75 @@
 }
 
 int
-send_request(int fd, const char *url)
+send_request(int fd, const char *data)
 {
- char buf[4096];
+ char msg[4096],buf[4096];
     int len;
     time_t w;
     struct _r *r;
     struct _r **R;
- buf[0] = '\0';
- strcat(buf, "GET ");
- strcat(buf, url);
- strcat(buf, " HTTP/1.0\r\n");
- strcat(buf, "Accept: */*\r\n");
- strcat(buf, "Proxy-Connection: Keep-Alive\r\n");
+ char *method;
+ char *url;
+ char *file;
+ char *tmp = strdup(data);
+ struct stat st;
+ int file_fd = -1;
+ method=strtok(tmp, " ");
+ url=strtok(NULL, " ");
+ file=strtok(NULL, " ");
+ if (!url) {
+ url=method;
+ method="GET";
+ }
+ 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);
- strcat(buf, "If-Modified-Since: ");
- strcat(buf, mkrfc850(&w));
- strcat(buf, "\r\n");
- }
- strcat(buf, "\r\n");
- len = strlen(buf);
- if (write(fd, buf, len) < 0) {
+ 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("write");
+ 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));
- r->url = strdup(url);
+ r->url = strdup(data);
     for (R = &Requests; *R; R = &(*R)->next);
     *R = r;
     fprintf(stderr, "REQUESTED %s\n", url);
@@ -224,63 +270,117 @@
             return atoi(t);
         }
     }
- return 0;
+ 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;
 }
 
 int
-handle_read(char *buf, int len)
+handle_read(char *inbuf, int len)
 {
     struct _r *r = Requests;
     const char *end;
- int hlen;
- if (len < 0) {
+ static char buf[READ_BUF_SZ];
+ int hlen,blen;
+ if (len < 0 ) {
         perror("read");
         Requests = r->next;
         free(r);
         noutstanding--;
         return -1;
     }
+ xmemcpy(buf,inbuf,len);
     if (len == 0) {
- fprintf(stderr, "DONE: %s, server closed socket, read %d bytes\n", r->url, r->bytes_read);
+ fprintf(stderr, "DONE: %s, server closed socket, read %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.
+ */
         Requests = r->next;
         free(r);
         noutstanding--;
         return -1;
     }
- if (r->hdr_length == 0) {
- hlen = min(len, REPLY_HDR_SZ - r->hdr_length);
- strncpy(r->reply_hdrs + r->hdr_length, buf, hlen);
- r->hdr_offset += hlen;
- *(r->reply_hdrs + REPLY_HDR_SZ - 1) = '\0';
- }
- if (r->hdr_length == 0 && (end = mime_headers_end(r->reply_hdrs)) != NULL) {
- fprintf(stderr, "FOUND EOH FOR %s\n", r->url);
- r->hdr_length = end - r->reply_hdrs;
- fprintf(stderr, "HDR_LENGTH = %d\n", r->hdr_length);
- r->content_length = get_header_int_value("content-length:", r->reply_hdrs, end);
- fprintf(stderr, "CONTENT_LENGTH = %d\n", r->content_length);
- }
- if (r->content_length && r->hdr_length) {
- int bytes_left = r->content_length + r->hdr_length - r->bytes_read;
- int bytes_used = len > bytes_left ? bytes_left : len;
- r->bytes_read += bytes_used;
- len -= bytes_used;
- if (r->bytes_read == r->content_length + r->hdr_length) {
- fprintf(stderr, "DONE: %s, (%d == %d+%d)\n",
- r->url,
- r->bytes_read,
- r->hdr_length,
- r->content_length);
- Requests = r->next;
- free(r);
- noutstanding--;
- } else {
- assert(r->bytes_read < r->content_length + r->hdr_length);
+ 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);
         }
- if (len) {
- assert(bytes_used > 0);
+ /* Process headers */
+ if (r->hdr_length == 0 && (end = mime_headers_end(r->reply_hdrs)) != NULL) {
+ fprintf(stderr, "FOUND EOH FOR %s\n", r->url);
+ r->hdr_length = end - r->reply_hdrs;
+ fprintf(stderr, "HDR_LENGTH = %d\n", r->hdr_length);
+ /* "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);
+#if XREQESTURI
+ 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 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;
+ }
+ r->bytes_read += bytes_used;
+ len -= bytes_used;
+ if (bytes_left == 0) {
+ fprintf(stderr, "DONE: %s, (%d+%d)\n",
+ r->url,
+ r->hdr_length,
+ r->content_length);
+ Requests = r->next;
+ free(r);
+ noutstanding--;
+ r = Requests;
+ } else {
+ assert(r->bytes_read < r->content_length);
+ }
             xmemmove(buf, buf + bytes_used, len);
- return handle_read(buf, len);
         }
     }
     return 0;
@@ -294,8 +394,10 @@
     int x;
     len = read(fd, buf, READ_BUF_SZ);
     x = handle_read(buf, len);
- if (x < 0)
+ if (x < 0) {
+ perror("read reply");
         close(fd);
+ }
     return x;
 }
 
@@ -316,6 +418,7 @@
             pconn_fd = -1;
             r = Requests;
             Requests = Requests->next;
+ fprintf(stderr, "ABORT %s\n", Requests->url);
             free(r);
             noutstanding--;
         }
@@ -335,12 +438,12 @@
             }
             timeouts = 0;
         }
- if (noutstanding < 10 && !done_reading_urls) {
+ if (noutstanding < max_outstanding && !done_reading_urls) {
             char *t;
             if (fgets(buf, 8191, stdin) == NULL) {
                 printf("Done Reading URLS\n");
                 done_reading_urls = 1;
- break;
+ continue;
             }
             if ((t = strchr(buf, '\n')))
                 *t = '\0';
@@ -373,7 +476,7 @@
 void
 usage(void)
 {
- fprintf(stderr, "usage: %s: -p port -h host -n max\n", progname);
+ fprintf(stderr, "usage: %s: -p port -h host -n max -t tracefile -i -l lifetime\n", progname);
 }
 
 int
@@ -385,7 +488,7 @@
     setbuf(stdout, NULL);
     setbuf(stderr, NULL);
     progname = strdup(argv[0]);
- while ((c = getopt(argc, argv, "p:h:n:il:")) != -1) {
+ while ((c = getopt(argc, argv, "p:h:n:t:il:")) != -1) {
         switch (c) {
         case 'p':
             proxy_port = atoi(optarg);
@@ -394,13 +497,16 @@
             proxy_addr = strdup(optarg);
             break;
         case 'n':
- max_connections = atoi(optarg);
+ max_outstanding = atoi(optarg);
             break;
         case 'i':
             opt_ims = 1;
             break;
         case 'l':
             lifetime = (time_t) atoi(optarg);
+ break;
+ case 't':
+ trace_fd = open(optarg,O_WRONLY|O_CREAT|O_TRUNC,0666);
             break;
         default:
             usage();

--------------744066D03CE61966E2180F2--
Received on Tue Jul 29 2003 - 13:15:48 MDT

This archive was generated by hypermail pre-2.1.9 : Tue Dec 09 2003 - 16:11:46 MST