--------------------- PatchSet 8163 Date: 2006/06/06 03:35:23 Author: hno Branch: pinning Tag: (none) Log: Fix race conditions and optimize connection usage Members: src/client_side.c:1.47.2.71.2.5->1.47.2.71.2.6 src/forward.c:1.13.6.15.2.3->1.13.6.15.2.4 src/http.c:1.17.6.32.2.3->1.17.6.32.2.4 src/structs.h:1.48.2.43.2.3->1.48.2.43.2.4 Index: squid/src/client_side.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/client_side.c,v retrieving revision 1.47.2.71.2.5 retrieving revision 1.47.2.71.2.6 diff -u -r1.47.2.71.2.5 -r1.47.2.71.2.6 --- squid/src/client_side.c 13 Apr 2006 15:16:58 -0000 1.47.2.71.2.5 +++ squid/src/client_side.c 6 Jun 2006 03:35:23 -0000 1.47.2.71.2.6 @@ -1,6 +1,6 @@ /* - * $Id: client_side.c,v 1.47.2.71.2.5 2006/04/13 15:16:58 hno Exp $ + * $Id: client_side.c,v 1.47.2.71.2.6 2006/06/06 03:35:23 hno Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -964,7 +964,7 @@ safe_free(connState->in.buf); /* XXX account connState->in.buf */ pconnHistCount(0, connState->nrequests); - if (connState->pinning.fd >= 0) + if (connState->pinning.fd >= 0) comm_close(connState->pinning.fd); cbdataFree(connState); #ifdef _SQUID_LINUX_ @@ -980,7 +980,7 @@ clientInterpretRequestHeaders(clientHttpRequest * http) { request_t *request = http->request; - const HttpHeader *req_hdr = &request->header; + HttpHeader *req_hdr = &request->header; int no_cache = 0; const char *str; request->imslen = -1; @@ -1028,36 +1028,44 @@ #endif request->flags.nocache = 1; } + if (Config.onoff.pipeline_prefetch) + request->flags.no_connection_auth = 1; + /* ignore range header in non-GETs */ if (request->method == METHOD_GET) { request->range = httpHeaderGetRange(req_hdr); if (request->range) request->flags.range = 1; } - if (http->conn->pinning.fd != -1) { - request->flags.auth = 1; - request->pinned_connection = http->conn; - cbdataLock(request->pinned_connection); - } else if (httpHeaderHas(req_hdr, HDR_AUTHORIZATION)) { + + if (httpHeaderHas(req_hdr, HDR_AUTHORIZATION) || httpHeaderHas(req_hdr, HDR_PROXY_AUTHORIZATION)) { HttpHeaderPos pos = HttpHeaderInitPos; HttpHeaderEntry *e; request->flags.auth = 1; - if (!Config.onoff.pipeline_prefetch) { - while ((e = httpHeaderGetEntry(req_hdr, &pos))) { - if (e->id == HDR_AUTHORIZATION) { + while ((e = httpHeaderGetEntry(req_hdr, &pos))) { + if (e->id == HDR_AUTHORIZATION || e->id == HDR_PROXY_AUTHORIZATION) { + if (!request->flags.no_connection_auth) { const char *value = strBuf(e->value); - if ((strncasecmp(value, "NTLM", 4) == 0 && - (value[4] == '\0' || value[4] == ' ')) + if (strncasecmp(value, "NTLM ", 5) == 0 + || + strncasecmp(value, "Negotiate ", 10) == 0 || - (strncasecmp(value, "Negotiate", 9) == 0 && - (value[9] == '\0' || value[9] == ' '))) { - request->pinned_connection = http->conn; - cbdataLock(request->pinned_connection); + strncasecmp(value, "Kerberos ", 9) == 0) { + request->flags.connection_auth = 1; + request->flags.must_keepalive = 1; + /* the pinned connection is set below */ break; } + } else { + httpHeaderDelAt(req_hdr, pos); } } } + } + if (request->flags.connection_auth || http->conn->pinning.fd != -1) { + request->flags.auth = 1; + request->pinned_connection = http->conn; + cbdataLock(request->pinned_connection); } else if (request->login[0] != '\0') request->flags.auth = 1; if (httpHeaderHas(req_hdr, HDR_VIA)) { @@ -1456,19 +1464,26 @@ } /* Filter unproxyable authentication types */ if (http->log_type != LOG_TCP_DENIED && - (httpHeaderHas(hdr, HDR_WWW_AUTHENTICATE) || httpHeaderHas(hdr, HDR_PROXY_AUTHENTICATE))) { + (httpHeaderHas(hdr, HDR_WWW_AUTHENTICATE))) { HttpHeaderPos pos = HttpHeaderInitPos; HttpHeaderEntry *e; while ((e = httpHeaderGetEntry(hdr, &pos))) { - if (e->id == HDR_WWW_AUTHENTICATE || e->id == HDR_PROXY_AUTHENTICATE) { + if (e->id == HDR_WWW_AUTHENTICATE) { const char *value = strBuf(e->value); if ((strncasecmp(value, "NTLM", 4) == 0 && (value[4] == '\0' || value[4] == ' ')) || (strncasecmp(value, "Negotiate", 9) == 0 && - (value[9] == '\0' || value[9] == ' '))) { - httpHeaderPutStr(hdr, HDR_PROXY_SUPPORT, "Session-Based-Authentication"); - httpHeaderPutStr(hdr, HDR_CONNECTION, "Proxy-support"); + (value[9] == '\0' || value[9] == ' ')) + || + (strncasecmp(value, "Kerberos", 8) == 0 && + (value[8] == '\0' || value[8] == ' '))) { + if (request->flags.no_connection_auth) { + httpHeaderDelAt(hdr, pos); + } else if (!request->flags.accelerated) { + httpHeaderPutStr(hdr, HDR_PROXY_SUPPORT, "Session-Based-Authentication"); + httpHeaderPutStr(hdr, HDR_CONNECTION, "Proxy-support"); + } break; } } @@ -4001,7 +4016,7 @@ } void -clientPinConnection(ConnStateData *conn, const char *host, int port, int fd) +clientPinConnection(ConnStateData * conn, const char *host, int port, int fd) { if (conn->pinning.fd == fd) return; Index: squid/src/forward.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/forward.c,v retrieving revision 1.13.6.15.2.3 retrieving revision 1.13.6.15.2.4 diff -u -r1.13.6.15.2.3 -r1.13.6.15.2.4 --- squid/src/forward.c 13 Apr 2006 15:16:58 -0000 1.13.6.15.2.3 +++ squid/src/forward.c 6 Jun 2006 03:35:24 -0000 1.13.6.15.2.4 @@ -1,6 +1,6 @@ /* - * $Id: forward.c,v 1.13.6.15.2.3 2006/04/13 15:16:58 hno Exp $ + * $Id: forward.c,v 1.13.6.15.2.4 2006/06/06 03:35:24 hno Exp $ * * DEBUG: section 17 Request Forwarding * AUTHOR: Duane Wessels @@ -343,10 +343,14 @@ { if (conn->pinning.fd < 0) return -1; - if (strcasecmp(conn->pinning.host, request->host) != 0) + if (request && strcasecmp(conn->pinning.host, request->host) != 0) { + comm_close(conn->pinning.fd); return -1; - if (conn->pinning.port != request->port) + } + if (request && conn->pinning.port != request->port) { + comm_close(conn->pinning.fd); return -1; + } return conn->pinning.fd; } @@ -389,16 +393,18 @@ ctimeout = ftimeout; if (fwdState->request->pinned_connection) { fd = getPinnedFD(fwdState->request->pinned_connection, fwdState->request); - if (fd < 0) { - debug(17, 1) ("fwdConnectStart: Pinned connection to %s:%d gone, aborting request\n", fwdState->request->host, fwdState->request->port); - storeAbort(fwdState->entry); + if (fd >= 0) { + fwdState->server_fd = fd; + fwdState->n_tries++; + fwdState->request->flags.must_keepalive = 1; + comm_add_close_handler(fd, fwdServerClosed, fwdState); + fwdConnectDone(fd, COMM_OK, fwdState); return; } - fwdState->server_fd = fd; - fwdState->n_tries++; - comm_add_close_handler(fd, fwdServerClosed, fwdState); - fwdConnectDone(fd, COMM_OK, fwdState); - return; + if (!fwdState->request->flags.connection_auth) { + cbdataUnlock(fwdState->request->pinned_connection); + fwdState->request->pinned_connection = NULL; + } } if ((fd = pconnPop(host, port)) >= 0) { if (fwdCheckRetriable(fwdState)) { Index: squid/src/http.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/http.c,v retrieving revision 1.17.6.32.2.3 retrieving revision 1.17.6.32.2.4 diff -u -r1.17.6.32.2.3 -r1.17.6.32.2.4 --- squid/src/http.c 5 Nov 2005 22:56:42 -0000 1.17.6.32.2.3 +++ squid/src/http.c 6 Jun 2006 03:35:24 -0000 1.17.6.32.2.4 @@ -1,6 +1,6 @@ /* - * $Id: http.c,v 1.17.6.32.2.3 2005/11/05 22:56:42 hno Exp $ + * $Id: http.c,v 1.17.6.32.2.4 2006/06/06 03:35:24 hno Exp $ * * DEBUG: section 11 Hypertext Transfer Protocol (HTTP) * AUTHOR: Harvest Derived @@ -54,6 +54,7 @@ static void httpMakePublic(StoreEntry *); static int httpCachableReply(HttpStateData *); static void httpMaybeRemovePublic(StoreEntry *, http_status); +static int peer_supports_connection_pinning(HttpStateData *httpState); static void httpStateFree(int fd, void *data) @@ -454,6 +455,8 @@ ctx_exit(ctx); return; } + if (!peer_supports_connection_pinning(httpState)) + httpState->orig_request->flags.no_connection_auth = 1; storeTimestampsSet(entry); /* Check if object is cacheable or not based on reply code */ debug(11, 3) ("httpProcessReplyHeader: HTTP CODE: %d\n", reply->sline.status); @@ -557,12 +560,17 @@ { const HttpReply *rep = httpState->entry->mem_obj->reply; const HttpHeader *hdr = &rep->header; + const request_t *req = httpState->orig_request; int rc; String header; if (!httpState->peer) return 1; + if (req->pinned_connection) + if (req->pinned_connection->pinning.fd == httpState->fd) + return 1; + if (!httpHeaderHas(hdr, HDR_PROXY_SUPPORT)) return 0; @@ -584,6 +592,7 @@ LOCAL_ARRAY(char, buf, SQUID_TCP_SO_RCVBUF); StoreEntry *entry = httpState->entry; const request_t *request = httpState->request; + const request_t *orig_request = httpState->orig_request; int len; int bin; int clen; @@ -726,7 +735,7 @@ */ if (!httpState->flags.request_sent) { debug(11, 1) ("httpReadReply: Request not yet fully sent \"%s %s\"\n", - RequestMethodStr[httpState->orig_request->method], + RequestMethodStr[orig_request->method], storeUrl(entry)); keep_alive = 0; } @@ -746,7 +755,7 @@ } else if (len > 0) { debug(11, Config.onoff.relaxed_header_parser <= 0 || keep_alive ? 1 : 2) ("httpReadReply: Excess data from \"%s %s\"\n", - RequestMethodStr[httpState->orig_request->method], + RequestMethodStr[orig_request->method], storeUrl(entry)); storeAppend(entry, buf, len); keep_alive = 0; @@ -762,9 +771,12 @@ #endif comm_remove_close_handler(fd, httpStateFree, httpState); fwdUnregister(fd, httpState->fwd); - if (request->pinned_connection && peer_supports_connection_pinning(httpState)) - clientPinConnection(request->pinned_connection, request->host, request->port, fd); - else if (request->flags.accelerated && Config.Accel.single_host && Config.Accel.host) + if (orig_request->pinned_connection) { + if (peer_supports_connection_pinning(httpState)) + clientPinConnection(orig_request->pinned_connection, orig_request->host, orig_request->port, fd); + else + comm_close(fd); + } else if (orig_request->flags.accelerated && Config.Accel.single_host && Config.Accel.host) pconnPush(fd, Config.Accel.host, Config.Accel.port); else pconnPush(fd, request->host, request->port); @@ -790,7 +802,7 @@ /* Server is nasty on us. Shut down */ debug(11, Config.onoff.relaxed_header_parser <= 0 || entry->mem_obj->reply->keep_alive ? 1 : 2) ("httpReadReply: Excess data from \"%s %s\"\n", - RequestMethodStr[httpState->orig_request->method], + RequestMethodStr[orig_request->method], storeUrl(entry)); fwdComplete(httpState->fwd); comm_close(fd); @@ -1117,7 +1129,9 @@ /* * Is keep-alive okay for all request methods? */ - if (!Config.onoff.server_pconns) + if (httpState->orig_request->flags.must_keepalive) + httpState->flags.keepalive = 1; + else if (!Config.onoff.server_pconns) httpState->flags.keepalive = 0; else if (p == NULL) httpState->flags.keepalive = 1; Index: squid/src/structs.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/structs.h,v retrieving revision 1.48.2.43.2.3 retrieving revision 1.48.2.43.2.4 diff -u -r1.48.2.43.2.3 -r1.48.2.43.2.4 --- squid/src/structs.h 13 Apr 2006 15:16:58 -0000 1.48.2.43.2.3 +++ squid/src/structs.h 6 Jun 2006 03:35:25 -0000 1.48.2.43.2.4 @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.48.2.43.2.3 2006/04/13 15:16:58 hno Exp $ + * $Id: structs.h,v 1.48.2.43.2.4 2006/06/06 03:35:25 hno Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -1636,6 +1636,8 @@ unsigned int body_sent:1; unsigned int reset_tcp:1; unsigned int must_keepalive:1; + unsigned int connection_auth:1; /* Request wants connection oriented auth */ + unsigned int no_connection_auth:1; /* Connection oriented auth can not be supported */ }; struct _link_list {