From be44c26d3430f1b88f2886d42ca034795b165845 Mon Sep 17 00:00:00 2001 From: Dirk-Willem van Gulik Date: Mon, 1 Apr 2002 04:24:48 +0000 Subject: [PATCH] Fixed incompliance of AB when used with a proxy as reported by Taisuke Yamada . Added error trapping to the write function (important on systems with defered errors after a connect). Documented the weakness of the write() function - it assumes the whole RQ can always be fully written to the socket. Fixed a compiler warning which pointed out that 'bad' was both a label and a variable. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x@94354 13f79535-47bb-0310-9956-ffa450edef68 --- src/CHANGES | 3 ++ src/support/ab.c | 103 +++++++++++++++++++++++++++++------------------ 2 files changed, 67 insertions(+), 39 deletions(-) diff --git a/src/CHANGES b/src/CHANGES index 990bd4e7a29..27fce039a69 100644 --- a/src/CHANGES +++ b/src/CHANGES @@ -1,5 +1,8 @@ Changes with Apache 1.3.25 + *) Made AB's use of the Host: header rfc2616 compliant + by Taisuke Yamada [Dirl-Willem van Gulik]. + *) Update the Redhat Layout to match Redhat version 7. PR BZ-7422 [Joe Orton] diff --git a/src/support/ab.c b/src/support/ab.c index 61a682027ac..54acbeaffff 100644 --- a/src/support/ab.c +++ b/src/support/ab.c @@ -255,6 +255,7 @@ char *gnuplot; /* GNUplot file */ char *csvperc; /* CSV Percentile file */ char url[1024]; char fullurl[1024]; +char colonport[1024]; int postlen = 0; /* length of data to be POSTed */ char content_type[1024]; /* content type to put in POST header */ char cookie[1024], /* optional cookie line */ @@ -288,7 +289,7 @@ int err_response = 0; struct timeval start, endtime; /* global request (and its length) */ -char request[512]; +char request[1024]; int reqlen; /* one global throw-away buffer to read stuff into */ @@ -344,7 +345,7 @@ static void write_request(struct connection * c) */ #if !NO_WRITEV && !USE_SSL struct iovec out[2]; - int outcnt = 1; + int outcnt = 1, snd = 0; #endif gettimeofday(&c->connect, 0); #if !NO_WRITEV && !USE_SSL @@ -357,18 +358,28 @@ static void write_request(struct connection * c) outcnt = 2; totalposted += (reqlen + postlen); } - writev(c->fd, out, outcnt); + snd = writev(c->fd, out, outcnt); #else - s_write(c, request, reqlen); + snd = s_write(c, request, reqlen); if (posting > 0) { - s_write(c, postdata, postlen); + snd += s_write(c, postdata, postlen); totalposted += (reqlen + postlen); } #endif - - c->state = STATE_READ; + if (snd < 0) { + bad++; + err_conn++; + close_connection(c); + return; + } else + if (snd != (reqlen + postlen)) { + /* We cannot cope with this. */ + fprintf(stderr,"The entire post RQ could not be transmitted to the socket.\n"); + exit(1); + } FD_SET(c->fd, &readbits); FD_CLR(c->fd, &writebits); + c->state = STATE_READ; gettimeofday(&c->endwrite, 0); } @@ -865,7 +876,7 @@ static void start_connect(struct connection * c) c->fd = socket(AF_INET, SOCK_STREAM, 0); if (c->fd < 0) { what = "SOCKET"; - goto bad; + goto _bad; }; #if USE_SSL @@ -880,18 +891,12 @@ static void start_connect(struct connection * c) again: gettimeofday(&c->start, 0); if (connect(c->fd, (struct sockaddr *) & server, sizeof(server)) < 0) { - if (errno == EINPROGRESS) { - c->state = STATE_CONNECTING; - } - else { + if (errno != EINPROGRESS) { what = "CONNECT"; - goto bad; + goto _bad; }; } - else { - /* connected first time */ - c->state = STATE_CONNECTING; - } + c->state = STATE_CONNECTING; #ifdef USE_SSL /* XX no proper freeing in error's */ @@ -904,18 +909,18 @@ again: if (!(c->ssl = SSL_new(ctx))) { fprintf(stderr, "Failed to set up new SSL context "); ERR_print_errors_fp(stderr); - goto bad; + goto _bad; }; SSL_set_connect_state(c->ssl); if ((e = SSL_set_fd(c->ssl, c->fd)) == -1) { fprintf(stderr, "SSL fd init failed "); ERR_print_errors_fp(stderr); - goto bad; + goto _bad; }; if ((e = SSL_connect(c->ssl)) == -1) { fprintf(stderr, "SSL connect failed "); ERR_print_errors_fp(stderr); - goto bad; + goto _bad; }; if (verbosity >= 1) fprintf(stderr, "SSL connection OK: %s\n", SSL_get_cipher(c->ssl)); @@ -928,10 +933,11 @@ again: FD_SET(c->fd, &writebits); return; -bad: +_bad: ab_close(c->fd); err_conn++; - if (bad++ > 10) { + bad++; + if (bad > 10) { err("\nTest aborted after 10 failures\n\n"); } goto again; @@ -1172,7 +1178,8 @@ static void test(void) fd_set sel_read, sel_except, sel_write; long i; int connectport; - char * url_on_request, * host; + char * connecthost; + char * url_on_request; /* There are four hostname's involved: * The 'hostname' from the URL, the @@ -1182,11 +1189,15 @@ static void test(void) */ if (isproxy) { /* Connect to proxyhost:proxyport - * And set Host: to the hostname of - * the proxy - whistl quoting the - * full URL in the GET/POST line. + * And set Host: to the hostname and + * if not default :port of the URL. + * See RFC2616 - $14.23. But then in + * $5.2.1 it says that the Host: field + * when passed on MUST be ignored. So + * perhaps we should NOT send any + * when we are proxying. */ - host = proxyhost; + connecthost = proxyhost; connectport = proxyport; url_on_request = fullurl; } @@ -1197,11 +1208,11 @@ static void test(void) * header; and do not quote a full * URL in the GET/POST line. */ - host = hostname; + connecthost = hostname; connectport = port; url_on_request = path; } - + if (!use_html) { printf("Benchmarking %s (be patient)%s", hostname, (heartbeatres ? "\n" : "...")); @@ -1210,10 +1221,11 @@ static void test(void) { /* get server information */ struct hostent *he; - he = gethostbyname(host); + he = gethostbyname(connecthost); if (!he) { char theerror[1024]; - sprintf(theerror, "Bad hostname: %s\n", host); + snprintf(theerror, sizeof(theerror), + "Bad hostname: %s\n", connecthost); err(theerror); } server.sin_family = he->h_addrtype; @@ -1231,10 +1243,11 @@ static void test(void) /* setup request */ if (posting <= 0) { - sprintf(request, "%s %s HTTP/1.0\r\n" + snprintf(request, sizeof(request), + "%s %s HTTP/1.0\r\n" "User-Agent: ApacheBench/%s\r\n" "%s" "%s" "%s" - "Host: %s\r\n" + "Host: %s%s\r\n" "Accept: */*\r\n" "%s" "\r\n", (posting == 0) ? "GET" : "HEAD", @@ -1242,10 +1255,11 @@ static void test(void) VERSION, keepalive ? "Connection: Keep-Alive\r\n" : "", cookie, auth, - host, hdrs); + hostname,colonport, hdrs); } else { - sprintf(request, "POST %s HTTP/1.0\r\n" + snprintf(request, sizeof(request), + "POST %s HTTP/1.0\r\n" "User-Agent: ApacheBench/%s\r\n" "%s" "%s" "%s" "Host: %s\r\n" @@ -1258,7 +1272,7 @@ static void test(void) VERSION, keepalive ? "Connection: Keep-Alive\r\n" : "", cookie, auth, - host, postlen, + hostname, colonport, postlen, (content_type[0]) ? content_type : "text/plain", hdrs); } @@ -1332,14 +1346,14 @@ static void test(void) static void copyright(void) { if (!use_html) { - printf("This is ApacheBench, Version %s\n", VERSION " <$Revision: 1.60 $> apache-1.3"); + printf("This is ApacheBench, Version %s\n", VERSION " <$Revision: 1.61 $> apache-1.3"); printf("Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/\n"); printf("Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/\n"); printf("\n"); } else { printf("

\n"); - printf(" This is ApacheBench, Version %s <%s> apache-1.3
\n", VERSION, "$Revision: 1.60 $"); + printf(" This is ApacheBench, Version %s <%s> apache-1.3
\n", VERSION, "$Revision: 1.61 $"); printf(" Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
\n"); printf(" Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/
\n"); printf("

\n

\n"); @@ -1426,7 +1440,18 @@ static int parse_url(char * purl) strcpy(hostname, h); if (p != NULL) port = atoi(p); - return 0; + + if (( +#if USE_SSL + (ssl != 0) && (port != 443)) || ((ssl == 0) && +#endif + (port != 80))) + { + snprintf(colonport,sizeof(colonport),":%d",port); + } else { + colonport[0] = '\0'; + } + return 0; } /* ------------------------------------------------------- */ -- 2.47.2