--------------------- PatchSet 1618 Date: 2005/08/26 20:28:41 Author: dwsquid Branch: squid3-icap Tag: (none) Log: apply /usr/local/bin/astyle -cs4 -O --break-blocks -l Members: src/ChunkedCodingParser.cc:1.1.2.2->1.1.2.3 src/ChunkedCodingParser.h:1.1.2.1->1.1.2.2 src/HttpReply.cc:1.21.4.2->1.21.4.3 src/HttpReply.h:1.8.10.2->1.8.10.3 src/HttpStatusLine.cc:1.3.12.1->1.3.12.2 src/HttpStatusLine.h:1.1.16.1->1.1.16.2 src/ICAPAnchor.cc:1.1.2.18->1.1.2.19 src/ICAPAnchor.h:1.1.2.6->1.1.2.7 src/ICAPClient.cc:1.1.2.5->1.1.2.6 src/ICAPClient.h:1.1.2.4->1.1.2.5 src/ICAPServiceRep.cc:1.1.2.1->1.1.2.2 src/ICAPServiceRep.h:1.1.2.1->1.1.2.2 src/ICAPXaction.cc:1.1.2.12->1.1.2.13 src/ICAPXaction.h:1.1.2.7->1.1.2.8 src/MemBuf.cc:1.6.8.4->1.6.8.5 src/MemBuf.h:1.3.16.5->1.3.16.6 src/MsgPipe.cc:1.1.2.7->1.1.2.8 src/MsgPipe.h:1.1.2.4->1.1.2.5 src/MsgPipeData.h:1.1.2.6->1.1.2.7 src/MsgPipeEnd.h:1.1.2.1->1.1.2.2 src/MsgPipeSink.h:1.1.2.2->1.1.2.3 src/MsgPipeSource.h:1.1.2.2->1.1.2.3 src/Packer.cc:1.2.14.1->1.2.14.2 src/Parsing.cc:1.1.12.1->1.1.12.2 src/StoreIOBuffer.h:1.4.12.2->1.4.12.3 src/TextException.cc:1.1.2.2->1.1.2.3 src/TextException.h:1.1.2.1->1.1.2.2 src/client_side_reply.cc:1.61.2.3->1.61.2.4 src/http.cc:1.49.2.18->1.49.2.19 src/http.h:1.11.4.7->1.11.4.8 src/store.cc:1.27.8.4->1.27.8.5 Index: squid3/src/ChunkedCodingParser.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ChunkedCodingParser.cc,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -u -r1.1.2.2 -r1.1.2.3 --- squid3/src/ChunkedCodingParser.cc 26 Aug 2005 20:24:13 -0000 1.1.2.2 +++ squid3/src/ChunkedCodingParser.cc 26 Aug 2005 20:28:41 -0000 1.1.2.3 @@ -9,195 +9,224 @@ ChunkedCodingParser::Step ChunkedCodingParser::psTrailer = &ChunkedCodingParser::parseTrailer; ChunkedCodingParser::Step ChunkedCodingParser::psMessageEnd = &ChunkedCodingParser::parseMessageEnd; -ChunkedCodingParser::ChunkedCodingParser() { - reset(); +ChunkedCodingParser::ChunkedCodingParser() +{ + reset(); } -void ChunkedCodingParser::reset() { - theStep = psChunkBeg; - theChunkSize = theLeftBodySize = 0; - doNeedMoreData = false; - sawIeof = false; - theIn = theOut = NULL; +void ChunkedCodingParser::reset() +{ + theStep = psChunkBeg; + theChunkSize = theLeftBodySize = 0; + doNeedMoreData = false; + sawIeof = false; + theIn = theOut = NULL; } -bool ChunkedCodingParser::parse(MemBuf *rawData, MemBuf *parsedContent) { - Must(rawData && parsedContent); - theIn = rawData; - theOut = parsedContent; +bool ChunkedCodingParser::parse(MemBuf *rawData, MemBuf *parsedContent) +{ + Must(rawData && parsedContent); + theIn = rawData; + theOut = parsedContent; - doNeedMoreData = !theIn->hasContent(); + doNeedMoreData = !theIn->hasContent(); - while (mayContinue()) { - (this->*theStep)(); - } + while (mayContinue()) { + (this->*theStep)(); + } - return theStep == psMessageEnd; + return theStep == psMessageEnd; } -bool ChunkedCodingParser::needsMoreData() const { - return doNeedMoreData; +bool ChunkedCodingParser::needsMoreData() const +{ + return doNeedMoreData; } -bool ChunkedCodingParser::mayContinue() const { - return !doNeedMoreData && theStep != psMessageEnd; +bool ChunkedCodingParser::mayContinue() const +{ + return !doNeedMoreData && theStep != psMessageEnd; } -void ChunkedCodingParser::parseChunkBeg() { - Must(theChunkSize <= 0); // Should(), really +void ChunkedCodingParser::parseChunkBeg() +{ + Must(theChunkSize <= 0); // Should(), really - size_t crlfBeg = 0; - size_t crlfEnd = 0; - if (findCrlf(crlfBeg, crlfEnd)) { - debugs(99,5, "found chunk-size end: " << crlfBeg << "-" << crlfEnd); - int size = -1; - const char *p = 0; - if (StringToInt(theIn->content(), size, &p, 16)) { - if (size < 0) { - throw TexcHere("negative chunk size"); - return; - } - // check for ieof chunk extension in the last-chunk - if (size == 0 && p && *p++ == ';') { - const char *e = theIn->content() + crlfBeg; // end of extension - while (p < e && isspace(*p)) ++p; // skip space - sawIeof = e - p >= 4 && - strncmp(p, "ieof", 4) == 0 && - isspace(p[4]); - } - theIn->consume(crlfEnd); - theChunkSize = theLeftBodySize = size; - debugs(99,5, "found chunk: " << theChunkSize); - theStep = theChunkSize == 0 ? psTrailer : psChunkBody; - return; - } - throw TexcHere("corrupted chunk size"); - } - doNeedMoreData = true; + size_t crlfBeg = 0; + size_t crlfEnd = 0; + + if (findCrlf(crlfBeg, crlfEnd)) { + debugs(99,5, "found chunk-size end: " << crlfBeg << "-" << crlfEnd); + int size = -1; + const char *p = 0; + + if (StringToInt(theIn->content(), size, &p, 16)) { + if (size < 0) { + throw TexcHere("negative chunk size"); + return; + } + + // check for ieof chunk extension in the last-chunk + if (size == 0 && p && *p++ == ';') { + const char *e = theIn->content() + crlfBeg; // end of extension + + while (p < e && isspace(*p)) + ++p; // skip space + + sawIeof = e - p >= 4 && + strncmp(p, "ieof", 4) == 0 && + isspace(p[4]); + } + + theIn->consume(crlfEnd); + theChunkSize = theLeftBodySize = size; + debugs(99,5, "found chunk: " << theChunkSize); + theStep = theChunkSize == 0 ? psTrailer : psChunkBody; + return; + } + + throw TexcHere("corrupted chunk size"); + } + + doNeedMoreData = true; } -void ChunkedCodingParser::parseChunkBody() { - Must(theLeftBodySize > 0); // Should, really +void ChunkedCodingParser::parseChunkBody() +{ + Must(theLeftBodySize > 0); // Should, really - const size_t parsedSize = XMIN(theLeftBodySize, (size_t)theIn->contentSize()); + const size_t parsedSize = XMIN(theLeftBodySize, (size_t)theIn->contentSize()); - theOut->append(theIn->content(), parsedSize); - theIn->consume(parsedSize); - theLeftBodySize -= parsedSize; + theOut->append(theIn->content(), parsedSize); + theIn->consume(parsedSize); + theLeftBodySize -= parsedSize; - if (theLeftBodySize == 0) - theStep = psChunkEnd; - else - doNeedMoreData = true; + if (theLeftBodySize == 0) + theStep = psChunkEnd; + else + doNeedMoreData = true; } -void ChunkedCodingParser::parseChunkEnd() { - Must(theLeftBodySize == 0); // Should(), really +void ChunkedCodingParser::parseChunkEnd() +{ + Must(theLeftBodySize == 0); // Should(), really + + size_t crlfBeg = 0; + size_t crlfEnd = 0; + + if (findCrlf(crlfBeg, crlfEnd)) { + if (crlfBeg != 0) { + throw TexcHere("found data bewteen chunk end and CRLF"); + return; + } - size_t crlfBeg = 0; - size_t crlfEnd = 0; - if (findCrlf(crlfBeg, crlfEnd)) { - if (crlfBeg != 0) { - throw TexcHere("found data bewteen chunk end and CRLF"); - return; - } - theIn->consume(crlfEnd); - theChunkSize = 0; // done with the current chunk - theStep = psChunkBeg; - return; - } - - doNeedMoreData = true; + theIn->consume(crlfEnd); + theChunkSize = 0; // done with the current chunk + theStep = psChunkBeg; + return; + } + + doNeedMoreData = true; } -void ChunkedCodingParser::parseTrailer() { - Must(theChunkSize == 0); // Should(), really +void ChunkedCodingParser::parseTrailer() +{ + Must(theChunkSize == 0); // Should(), really - while (mayContinue()) - parseTrailerHeader(); + while (mayContinue()) + parseTrailerHeader(); } -void ChunkedCodingParser::parseTrailerHeader() { - size_t crlfBeg = 0; - size_t crlfEnd = 0; - if (findCrlf(crlfBeg, crlfEnd)) { - if (crlfBeg > 0) - ; //theTrailer.append(theIn->content(), crlfEnd); +void ChunkedCodingParser::parseTrailerHeader() +{ + size_t crlfBeg = 0; + size_t crlfEnd = 0; + + if (findCrlf(crlfBeg, crlfEnd)) { + if (crlfBeg > 0) + + ; //theTrailer.append(theIn->content(), crlfEnd); - theIn->consume(crlfEnd); + theIn->consume(crlfEnd); - if (crlfBeg == 0) - theStep = psMessageEnd; + if (crlfBeg == 0) + theStep = psMessageEnd; - return; - } + return; + } - doNeedMoreData = true; + doNeedMoreData = true; } -void ChunkedCodingParser::parseMessageEnd() { - // termination step, should not be called - Must(false); // Should(), really +void ChunkedCodingParser::parseMessageEnd() +{ + // termination step, should not be called + Must(false); // Should(), really } // finds next CRLF -bool ChunkedCodingParser::findCrlf(size_t &crlfBeg, size_t &crlfEnd) { - // XXX: This code was copied, with permission, from another software. - // There is a similar and probably better code inside httpHeaderParse +bool ChunkedCodingParser::findCrlf(size_t &crlfBeg, size_t &crlfEnd) +{ + // XXX: This code was copied, with permission, from another software. + // There is a similar and probably better code inside httpHeaderParse // but it seems difficult to isolate due to parsing-unrelated bloat. - // Such isolation should probably be done before this class is used - // for handling of traffic "more external" than ICAP. + // Such isolation should probably be done before this class is used + // for handling of traffic "more external" than ICAP. const char *buf = theIn->content(); - size_t size = theIn->contentSize(); + size_t size = theIn->contentSize(); - ssize_t crOff = -1; - bool quoted = false; - bool slashed = false; - for (size_t i = 0; i < size; ++i) { - if (slashed) { - slashed = false; - continue; - } - - const char c = buf[i]; - - // handle quoted strings - if (quoted) { - if (c == '\\') - slashed = true; - else - if (c == '"') - quoted = false; - continue; - } else - if (c == '"') { - quoted = true; - crOff = -1; - continue; - } - - if (crOff < 0) { // looking for the first CR or LF - if (c == '\n') { - crlfBeg = i; - crlfEnd = ++i; - return true; - } - - if (c == '\r') - crOff = i; - } else { // skipping CRs, looking for the first LF - if (c == '\n') { - crlfBeg = crOff; - crlfEnd = ++i; - return true; - } - - if (c != '\r') - crOff = -1; - } - } + ssize_t crOff = -1; + bool quoted = false; + bool slashed = false; + + for (size_t i = 0; i < size; ++i) { + if (slashed) { + slashed = false; + continue; + } + + const char c = buf[i]; + + // handle quoted strings + if (quoted) { + if (c == '\\') + slashed = true; + else + if (c == '"') + quoted = false; + + continue; + } else + if (c == '"') { + quoted = true; + crOff = -1; + continue; + } + + if (crOff < 0) { // looking for the first CR or LF + + if (c == '\n') { + crlfBeg = i; + crlfEnd = ++i; + return true; + } + + if (c == '\r') + crOff = i; + } else { // skipping CRs, looking for the first LF + + if (c == '\n') { + crlfBeg = crOff; + crlfEnd = ++i; + return true; + } + + if (c != '\r') + crOff = -1; + } + } - return false; + return false; } Index: squid3/src/ChunkedCodingParser.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ChunkedCodingParser.h,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -u -r1.1.2.1 -r1.1.2.2 --- squid3/src/ChunkedCodingParser.h 24 Aug 2005 05:39:22 -0000 1.1.2.1 +++ squid3/src/ChunkedCodingParser.h 26 Aug 2005 20:28:41 -0000 1.1.2.2 @@ -1,6 +1,6 @@ /* - * $Id: ChunkedCodingParser.h,v 1.1.2.1 2005/08/24 05:39:22 rousskov Exp $ + * $Id: ChunkedCodingParser.h,v 1.1.2.2 2005/08/26 20:28:41 dwsquid Exp $ * * SQUID Web Proxy Cache http://www.squid-cache.org/ * ---------------------------------------------------------- @@ -37,52 +37,53 @@ // ChunkedCodingParser is an incremental parser for chunked transfer coding // used by HTTP and ICAP. The parser shovels content bytes from the raw -// input buffer into the content output buffer, both caller-supplied. -// Ignores chunk extensions except for ICAP's ieof. +// input buffer into the content output buffer, both caller-supplied. +// Ignores chunk extensions except for ICAP's ieof. // Has a trailer-handling placeholder. class ChunkedCodingParser { + public: - ChunkedCodingParser(); + ChunkedCodingParser(); - void reset(); + void reset(); - // true = complete success; false == needs more data - bool parse(MemBuf *rawData, MemBuf *parsedContent); // throws on error + // true = complete success; false == needs more data + bool parse(MemBuf *rawData, MemBuf *parsedContent); // throws on error - bool needsMoreData() const; - bool sawIeof; // saw ieof chunk extension after a 0-size chunk + bool needsMoreData() const; + bool sawIeof; // saw ieof chunk extension after a 0-size chunk private: - typedef void (ChunkedCodingParser::*Step)(); + typedef void (ChunkedCodingParser::*Step)(); private: - bool mayContinue() const; + bool mayContinue() const; - void parseChunkBeg(); - void parseChunkBody(); - void parseChunkEnd(); - void parseTrailer(); - void parseTrailerHeader(); - void parseMessageEnd(); + void parseChunkBeg(); + void parseChunkBody(); + void parseChunkEnd(); + void parseTrailer(); + void parseTrailerHeader(); + void parseMessageEnd(); - bool findCrlf(size_t &crlfBeg, size_t &crlfEnd); + bool findCrlf(size_t &crlfBeg, size_t &crlfEnd); private: - static Step psChunkBeg; - static Step psChunkBody; - static Step psChunkEnd; - static Step psTrailer; - static Step psMessageEnd; - - MemBuf *theIn; - MemBuf *theOut; - - Step theStep; - size_t theChunkSize; - size_t theLeftBodySize; - bool doNeedMoreData; + static Step psChunkBeg; + static Step psChunkBody; + static Step psChunkEnd; + static Step psTrailer; + static Step psMessageEnd; + + MemBuf *theIn; + MemBuf *theOut; + + Step theStep; + size_t theChunkSize; + size_t theLeftBodySize; + bool doNeedMoreData; }; #endif /* SQUID_CHUNKEDCODINGPARSER_H */ Index: squid3/src/HttpReply.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/HttpReply.cc,v retrieving revision 1.21.4.2 retrieving revision 1.21.4.3 diff -u -r1.21.4.2 -r1.21.4.3 --- squid3/src/HttpReply.cc 25 Aug 2005 21:09:55 -0000 1.21.4.2 +++ squid3/src/HttpReply.cc 26 Aug 2005 20:28:41 -0000 1.21.4.3 @@ -1,6 +1,6 @@ /* - * $Id: HttpReply.cc,v 1.21.4.2 2005/08/25 21:09:55 rousskov Exp $ + * $Id: HttpReply.cc,v 1.21.4.3 2005/08/26 20:28:41 dwsquid Exp $ * * DEBUG: section 58 HTTP Reply (Response) * AUTHOR: Alex Rousskov @@ -74,7 +74,7 @@ void httpReplyInitModule(void) { - assert(HTTP_STATUS_NONE == 0); // HttpReply::parse() interface assumes that + assert(HTTP_STATUS_NONE == 0); // HttpReply::parse() interface assumes that httpHeaderMaskInit(&Denied304HeadersMask, 0); httpHeaderCalcMask(&Denied304HeadersMask, (const int *) Denied304HeadersArr, countof(Denied304HeadersArr)); } @@ -117,14 +117,14 @@ void httpReplyReset(HttpReply * rep) { - // reset should not reset the protocol; could have made protoPrefix a - // virtual function instead, but it is not clear whether virtual methods - // are allowed with MEMPROXY_CLASS() and whether some cbdata void* - // conversions are not going to kill virtual tables - const String pfx = rep->protoPrefix; + // reset should not reset the protocol; could have made protoPrefix a + // virtual function instead, but it is not clear whether virtual methods + // are allowed with MEMPROXY_CLASS() and whether some cbdata void* + // conversions are not going to kill virtual tables + const String pfx = rep->protoPrefix; httpReplyClean(rep); *rep = HttpReply(); - rep->protoPrefix = pfx; + rep->protoPrefix = pfx; } /* absorb: copy the contents of a new reply to the old one, destroy new one */ @@ -604,64 +604,71 @@ // negative return is the negated HTTP_ error code // zero return means need more data // positive return is the size of parsed headers -bool HttpReply::parse(MemBuf *buf, bool eof, http_status *error) { - assert(error); - *error = HTTP_STATUS_NONE; - - // httpReplyParseStep() and debugging require 0-termination, unfortunately - buf->terminate(); // does not affect content size - - // quick check that the response starts with HTTP/ or similar - // TODO: Remove? Are we optimizing an unusual case or obscure security? - if (buf->contentSize() >= protoPrefix.size() && - protoPrefix.cmp(buf->content(), protoPrefix.size()) != 0) { - debugs(58, 3, "HttpReply::parse: missing protocol prefix (" << - protoPrefix.buf() << ") in '" << buf->content() << "'"); - *error = HTTP_INVALID_HEADER; - return false; - } - - // find the end of headers - // TODO: Remove? httpReplyParseStep() should do similar checks - const size_t hdr_len = headersEnd(buf->content(), buf->contentSize()); - if (hdr_len <= 0) { - debugs(58, 3, "HttpReply::parse: failed to find end of headers " << - "(eof: " << eof << ") in '" << buf->content() << "'"); - if (eof) // iff we have seen the end, this is an error - *error = HTTP_INVALID_HEADER; - return false; - } +bool HttpReply::parse(MemBuf *buf, bool eof, http_status *error) +{ + assert(error); + *error = HTTP_STATUS_NONE; + + // httpReplyParseStep() and debugging require 0-termination, unfortunately + buf->terminate(); // does not affect content size + + // quick check that the response starts with HTTP/ or similar + // TODO: Remove? Are we optimizing an unusual case or obscure security? + + if (buf->contentSize() >= protoPrefix.size() && + protoPrefix.cmp(buf->content(), protoPrefix.size()) != 0) { + debugs(58, 3, "HttpReply::parse: missing protocol prefix (" << + protoPrefix.buf() << ") in '" << buf->content() << "'"); + *error = HTTP_INVALID_HEADER; + return false; + } + + // find the end of headers + // TODO: Remove? httpReplyParseStep() should do similar checks + const size_t hdr_len = headersEnd(buf->content(), buf->contentSize()); + + if (hdr_len <= 0) { + debugs(58, 3, "HttpReply::parse: failed to find end of headers " << + "(eof: " << eof << ") in '" << buf->content() << "'"); - // TODO: move to httpReplyParseStep() + if (eof) // iff we have seen the end, this is an error + *error = HTTP_INVALID_HEADER; + + return false; + } + + // TODO: move to httpReplyParseStep() if (hdr_len > Config.maxReplyHeaderSize) { - debugs(58, 1, "HttpReply::parse: Too large reply header (" << - hdr_len << " > " << Config.maxReplyHeaderSize); - *error = HTTP_HEADER_TOO_LARGE; - return false; - } - - const int res = httpReplyParseStep(this, buf->content(), eof); - if (res < 0) { // error - debugs(58, 3, "HttpReply::parse: cannot parse isolated headers " << - "in '" << buf->content() << "'"); - *error = HTTP_INVALID_HEADER; - return false; - } - - if (res == 0) { - debugs(58, 2, "HttpReply::parse: strange, need more data near '" << - buf->content() << "'"); - return false; // but this should not happen due to headersEnd() above - } - - assert(res > 0); - debugs(58, 9, "HttpReply::parse success (" << hdr_len << " bytes) " << - "near '" << buf->content() << "'"); - if (hdr_sz != (int)hdr_len) { - debugs(58, 1, "internal HttpReply::parse vs. headersEnd error: " << - hdr_sz << " != " << hdr_len); - hdr_sz = (int)hdr_len; // because old http.cc code used hdr_len - } - - return true; + debugs(58, 1, "HttpReply::parse: Too large reply header (" << + hdr_len << " > " << Config.maxReplyHeaderSize); + *error = HTTP_HEADER_TOO_LARGE; + return false; + } + + const int res = httpReplyParseStep(this, buf->content(), eof); + + if (res < 0) { // error + debugs(58, 3, "HttpReply::parse: cannot parse isolated headers " << + "in '" << buf->content() << "'"); + *error = HTTP_INVALID_HEADER; + return false; + } + + if (res == 0) { + debugs(58, 2, "HttpReply::parse: strange, need more data near '" << + buf->content() << "'"); + return false; // but this should not happen due to headersEnd() above + } + + assert(res > 0); + debugs(58, 9, "HttpReply::parse success (" << hdr_len << " bytes) " << + "near '" << buf->content() << "'"); + + if (hdr_sz != (int)hdr_len) { + debugs(58, 1, "internal HttpReply::parse vs. headersEnd error: " << + hdr_sz << " != " << hdr_len); + hdr_sz = (int)hdr_len; // because old http.cc code used hdr_len + } + + return true; } Index: squid3/src/HttpReply.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/HttpReply.h,v retrieving revision 1.8.10.2 retrieving revision 1.8.10.3 diff -u -r1.8.10.2 -r1.8.10.3 --- squid3/src/HttpReply.h 25 Aug 2005 21:09:55 -0000 1.8.10.2 +++ squid3/src/HttpReply.h 26 Aug 2005 20:28:41 -0000 1.8.10.3 @@ -1,6 +1,6 @@ /* - * $Id: HttpReply.h,v 1.8.10.2 2005/08/25 21:09:55 rousskov Exp $ + * $Id: HttpReply.h,v 1.8.10.3 2005/08/26 20:28:41 dwsquid Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -89,13 +89,13 @@ MEMPROXY_CLASS(HttpReply); HttpReply(); - // returns true on success - // returns false and sets *error to zero when needs more data - // returns false and sets *error to a positive http_status code on error - bool parse(MemBuf *buf, bool eof, http_status *error); + // returns true on success + // returns false and sets *error to zero when needs more data + // returns false and sets *error to a positive http_status code on error + bool parse(MemBuf *buf, bool eof, http_status *error); /* Unsupported, writable, may disappear/change in the future - * Sums _stored_ status-line, headers, and . + * Sums _stored_ status-line, headers, and . * Also used to report parsed header size if parse() is successful */ int hdr_sz; @@ -118,7 +118,7 @@ HttpHeader header; HttpBody body; /* for small constant memory-resident text bodies only */ - String protoPrefix; // e.g., "HTTP/" + String protoPrefix; // e.g., "HTTP/" }; MEMPROXY_CLASS_INLINE(HttpReply) Index: squid3/src/HttpStatusLine.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/HttpStatusLine.cc,v retrieving revision 1.3.12.1 retrieving revision 1.3.12.2 diff -u -r1.3.12.1 -r1.3.12.2 --- squid3/src/HttpStatusLine.cc 24 Aug 2005 06:09:57 -0000 1.3.12.1 +++ squid3/src/HttpStatusLine.cc 26 Aug 2005 20:28:41 -0000 1.3.12.2 @@ -1,6 +1,6 @@ /* - * $Id: HttpStatusLine.cc,v 1.3.12.1 2005/08/24 06:09:57 rousskov Exp $ + * $Id: HttpStatusLine.cc,v 1.3.12.2 2005/08/26 20:28:41 dwsquid Exp $ * * DEBUG: section 57 HTTP Status-line * AUTHOR: Alex Rousskov @@ -84,8 +84,9 @@ assert(sline); sline->status = HTTP_INVALID_HEADER; /* Squid header parsing error */ - // XXX: HttpReply::parse() has a similar check but is using - // casesensitive comparison (which is required by HTTP errata?) + // XXX: HttpReply::parse() has a similar check but is using + // casesensitive comparison (which is required by HTTP errata?) + if (protoPrefix.caseCmp(start, protoPrefix.size()) != 0) return 0; Index: squid3/src/HttpStatusLine.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/HttpStatusLine.h,v retrieving revision 1.1.16.1 retrieving revision 1.1.16.2 diff -u -r1.1.16.1 -r1.1.16.2 --- squid3/src/HttpStatusLine.h 24 Aug 2005 06:09:57 -0000 1.1.16.1 +++ squid3/src/HttpStatusLine.h 26 Aug 2005 20:28:41 -0000 1.1.16.2 @@ -1,6 +1,6 @@ /* - * $Id: HttpStatusLine.h,v 1.1.16.1 2005/08/24 06:09:57 rousskov Exp $ + * $Id: HttpStatusLine.h,v 1.1.16.2 2005/08/26 20:28:41 dwsquid Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -56,8 +56,8 @@ SQUIDCEXTERN const char *httpStatusLineReason(const HttpStatusLine * sline); /* parse/pack */ /* parse a 0-terminating buffer and fill internal structires; returns true on success */ -SQUIDCEXTERN int httpStatusLineParse(HttpStatusLine * sline, const String &protoPrefix, - const char *start, const char *end); +SQUIDCEXTERN int httpStatusLineParse(HttpStatusLine * sline, const String &protoPrefix, + const char *start, const char *end); /* pack fields using Packer */ SQUIDCEXTERN void httpStatusLinePackInto(const HttpStatusLine * sline, Packer * p); Index: squid3/src/ICAPAnchor.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPAnchor.cc,v retrieving revision 1.1.2.18 retrieving revision 1.1.2.19 diff -u -r1.1.2.18 -r1.1.2.19 --- squid3/src/ICAPAnchor.cc 25 Aug 2005 20:51:26 -0000 1.1.2.18 +++ squid3/src/ICAPAnchor.cc 26 Aug 2005 20:28:41 -0000 1.1.2.19 @@ -10,149 +10,173 @@ CBDATA_CLASS_INIT(ICAPAnchor); -ICAPAnchor::ICAPAnchor(): httpState(NULL), virgin(NULL), adapted(NULL) { - debug(93,5)("ICAPAnchor constructed, this=%p\n", this); +ICAPAnchor::ICAPAnchor(): httpState(NULL), virgin(NULL), adapted(NULL) +{ + debug(93,5)("ICAPAnchor constructed, this=%p\n", this); } -ICAPAnchor::~ICAPAnchor() { - stop(notifyNone); - cbdataReferenceDone(httpState); +ICAPAnchor::~ICAPAnchor() +{ + stop(notifyNone); + cbdataReferenceDone(httpState); } -void ICAPAnchor::startRespMod(HttpStateData *anHttpState, HttpRequest *request, HttpReply *reply) { - httpState = cbdataReference(anHttpState); +void ICAPAnchor::startRespMod(HttpStateData *anHttpState, HttpRequest *request, HttpReply *reply) +{ + httpState = cbdataReference(anHttpState); - virgin = new MsgPipe("virgin"); // this is the place to create a refcount ptr - virgin->source = this; - virgin->data = new MsgPipeData; - virgin->data->cause = request; - virgin->data->header = reply; - virgin->data->body = new MemBuf; - memBufInit(virgin->data->body, ICAPMsgPipeBufSizeMin, ICAPMsgPipeBufSizeMax); + virgin = new MsgPipe("virgin"); // this is the place to create a refcount ptr + virgin->source = this; + virgin->data = new MsgPipeData; + virgin->data->cause = request; + virgin->data->header = reply; + virgin->data->body = new MemBuf; + memBufInit(virgin->data->body, ICAPMsgPipeBufSizeMin, ICAPMsgPipeBufSizeMax); - adapted = new MsgPipe("adapted"); - adapted->sink = this; + adapted = new MsgPipe("adapted"); + adapted->sink = this; #if ICAP_ANCHOR_LOOPBACK - adapted->data = new MsgPipeData; - adapted->data->cause = request; // should not hurt + + adapted->data = new MsgPipeData; + adapted->data->cause = request; // should not hurt #endif #if ICAP_ANCHOR_LOOPBACK #else - ICAPInitXaction(virgin, adapted); + + ICAPInitXaction(virgin, adapted); #endif - virgin->sendSourceStart(); // we may have virgin data to provide - adapted->sendSinkNeed(); // we want adapted response, eventially + + virgin->sendSourceStart(); // we may have virgin data to provide + adapted->sendSinkNeed(); // we want adapted response, eventially } -void ICAPAnchor::sendMoreData(StoreIOBuffer buf) { - debug(93,5)("ICAPAnchor::sendMoreData() called\n"); - //buf.dump(); - /* - * The caller is responsible for not giving us more data - * than will fit in body MemBuf. Caller should use - * potentialSpaceSize() to find out how much we can hold. - */ - virgin->data->body->append(buf.data, buf.length); - virgin->sendSourceProgress(); +void ICAPAnchor::sendMoreData(StoreIOBuffer buf) +{ + debug(93,5)("ICAPAnchor::sendMoreData() called\n"); + //buf.dump(); + /* + * The caller is responsible for not giving us more data + * than will fit in body MemBuf. Caller should use + * potentialSpaceSize() to find out how much we can hold. + */ + virgin->data->body->append(buf.data, buf.length); + virgin->sendSourceProgress(); } int ICAPAnchor::potentialSpaceSize() { - return (int) virgin->data->body->potentialSpaceSize(); + return (int) virgin->data->body->potentialSpaceSize(); } // HttpStateData says we have the entire HTTP message -void ICAPAnchor::doneSending() { - debug(93,5)("ICAPAnchor::doneSending() called\n"); +void ICAPAnchor::doneSending() +{ + debug(93,5)("ICAPAnchor::doneSending() called\n"); #if ICAP_ANCHOR_LOOPBACK - /* simple assignments are not the right way to do this */ - adapted->data->header = virgin->data->header; - adapted->data->body = virgin->data->body; - noteSourceFinish(adapted); - return; + /* simple assignments are not the right way to do this */ + adapted->data->header = virgin->data->header; + adapted->data->body = virgin->data->body; + noteSourceFinish(adapted); + return; #else - virgin->sendSourceFinish(); + + virgin->sendSourceFinish(); #endif } // HttpStateData tells us to abort -void ICAPAnchor::ownerAbort() { - debug(93,5)("ICAPAnchor::ownerAbort() called\n"); - stop(notifyIcap); +void ICAPAnchor::ownerAbort() +{ + debug(93,5)("ICAPAnchor::ownerAbort() called\n"); + stop(notifyIcap); } // ICAP client needs more virgin response data -void ICAPAnchor::noteSinkNeed(MsgPipe *p) { - debug(93,5)("ICAPAnchor::noteSinkNeed() called\n"); - if (virgin->data->body->potentialSpaceSize()) - httpState->icapSpaceAvailable(); +void ICAPAnchor::noteSinkNeed(MsgPipe *p) +{ + debug(93,5)("ICAPAnchor::noteSinkNeed() called\n"); + + if (virgin->data->body->potentialSpaceSize()) + httpState->icapSpaceAvailable(); } // ICAP client aborting -void ICAPAnchor::noteSinkAbort(MsgPipe *p) { - debug(93,5)("ICAPAnchor::noteSinkAbort() called\n"); - stop(notifyOwner); +void ICAPAnchor::noteSinkAbort(MsgPipe *p) +{ + debug(93,5)("ICAPAnchor::noteSinkAbort() called\n"); + stop(notifyOwner); } // ICAP client starts sending adapted response // ICAP client has received new HTTP headers (if any) at this point -void ICAPAnchor::noteSourceStart(MsgPipe *p) { - debug(93,5)("ICAPAnchor::noteSourceStart() called\n"); - httpState->takeAdaptedHeaders(adapted->data->header); - noteSourceProgress(p); +void ICAPAnchor::noteSourceStart(MsgPipe *p) +{ + debug(93,5)("ICAPAnchor::noteSourceStart() called\n"); + httpState->takeAdaptedHeaders(adapted->data->header); + noteSourceProgress(p); } // ICAP client sends more data -void ICAPAnchor::noteSourceProgress(MsgPipe *p) { - debug(93,5)("ICAPAnchor::noteSourceProgress() called\n"); - //tell HttpStateData to store a fresh portion of the adapted response - if (p->data->body->hasContent()) { - httpState->takeAdaptedBody(p->data->body); - } +void ICAPAnchor::noteSourceProgress(MsgPipe *p) +{ + debug(93,5)("ICAPAnchor::noteSourceProgress() called\n"); + //tell HttpStateData to store a fresh portion of the adapted response + + if (p->data->body->hasContent()) { + httpState->takeAdaptedBody(p->data->body); + } } // ICAP client is done sending adapted response -void ICAPAnchor::noteSourceFinish(MsgPipe *p) { - debug(93,5)("ICAPAnchor::noteSourceFinish() called\n"); - //tell HttpStateData that we expect no more response data - httpState->doneAdapting(); - stop(notifyNone); +void ICAPAnchor::noteSourceFinish(MsgPipe *p) +{ + debug(93,5)("ICAPAnchor::noteSourceFinish() called\n"); + //tell HttpStateData that we expect no more response data + httpState->doneAdapting(); + stop(notifyNone); } // ICAP client is aborting -void ICAPAnchor::noteSourceAbort(MsgPipe *p) { - debug(93,5)("ICAPAnchor::noteSourceAbort() called\n"); - stop(notifyOwner); +void ICAPAnchor::noteSourceAbort(MsgPipe *p) +{ + debug(93,5)("ICAPAnchor::noteSourceAbort() called\n"); + stop(notifyOwner); } // internal cleanup -void ICAPAnchor::stop(Notify notify) { - if (virgin) { - if (notify == notifyIcap) - virgin->sendSourceAbort(); - else - virgin->source = NULL; - // this is the place to decrement refcount ptr - virgin = NULL; - } - if (adapted) { - if (notify == notifyIcap) - adapted->sendSinkAbort(); - else - adapted->sink = NULL; - // this is the place to decrement refcount ptr - adapted = NULL; - } - - if (httpState) { - if (notify == notifyOwner) - // tell HttpStateData that we are aborting prematurely - httpState->abortAdapting(); - cbdataReferenceDone(httpState); - // httpSTate is now NULL, will not call it any more - } +void ICAPAnchor::stop(Notify notify) +{ + if (virgin) { + if (notify == notifyIcap) + virgin->sendSourceAbort(); + else + virgin->source = NULL; + + // this is the place to decrement refcount ptr + virgin = NULL; + } + + if (adapted) { + if (notify == notifyIcap) + adapted->sendSinkAbort(); + else + adapted->sink = NULL; + + // this is the place to decrement refcount ptr + adapted = NULL; + } + + if (httpState) { + if (notify == notifyOwner) + // tell HttpStateData that we are aborting prematurely + httpState->abortAdapting(); + + cbdataReferenceDone(httpState); + + // httpSTate is now NULL, will not call it any more + } } Index: squid3/src/ICAPAnchor.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPAnchor.h,v retrieving revision 1.1.2.6 retrieving revision 1.1.2.7 diff -u -r1.1.2.6 -r1.1.2.7 --- squid3/src/ICAPAnchor.h 25 Aug 2005 20:51:26 -0000 1.1.2.6 +++ squid3/src/ICAPAnchor.h 26 Aug 2005 20:28:41 -0000 1.1.2.7 @@ -1,6 +1,6 @@ /* - * $Id: ICAPAnchor.h,v 1.1.2.6 2005/08/25 20:51:26 dwsquid Exp $ + * $Id: ICAPAnchor.h,v 1.1.2.7 2005/08/26 20:28:41 dwsquid Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -46,39 +46,42 @@ */ class HttpRequest; + class HttpReply; -class ICAPAnchor: public MsgPipeSource, public MsgPipeSink { +class ICAPAnchor: public MsgPipeSource, public MsgPipeSink +{ + public: - ICAPAnchor(); - virtual ~ICAPAnchor(); + ICAPAnchor(); + virtual ~ICAPAnchor(); - // synchronous calls called by HttpStateData - void startRespMod(HttpStateData *anHttpState, HttpRequest *request, HttpReply *reply); - void sendMoreData(StoreIOBuffer buf); - void doneSending(); - void ownerAbort(); - int potentialSpaceSize(); /* how much data can we accept? */ - - // pipe source methods; called by ICAP while receiving the virgin message - virtual void noteSinkNeed(MsgPipe *p); - virtual void noteSinkAbort(MsgPipe *p); - - // pipe sink methods; called by ICAP while sending the adapted message - virtual void noteSourceStart(MsgPipe *p); - virtual void noteSourceProgress(MsgPipe *p); - virtual void noteSourceFinish(MsgPipe *p); - virtual void noteSourceAbort(MsgPipe *p); + // synchronous calls called by HttpStateData + void startRespMod(HttpStateData *anHttpState, HttpRequest *request, HttpReply *reply); + void sendMoreData(StoreIOBuffer buf); + void doneSending(); + void ownerAbort(); + int potentialSpaceSize(); /* how much data can we accept? */ + + // pipe source methods; called by ICAP while receiving the virgin message + virtual void noteSinkNeed(MsgPipe *p); + virtual void noteSinkAbort(MsgPipe *p); + + // pipe sink methods; called by ICAP while sending the adapted message + virtual void noteSourceStart(MsgPipe *p); + virtual void noteSourceProgress(MsgPipe *p); + virtual void noteSourceFinish(MsgPipe *p); + virtual void noteSourceAbort(MsgPipe *p); public: - HttpStateData *httpState; - MsgPipe *virgin; - MsgPipe *adapted; + HttpStateData *httpState; + MsgPipe *virgin; + MsgPipe *adapted; private: - typedef enum { notifyNone, notifyOwner, notifyIcap } Notify; - void stop(Notify notify); - CBDATA_CLASS2(ICAPAnchor); + typedef enum { notifyNone, notifyOwner, notifyIcap } Notify; + void stop(Notify notify); + CBDATA_CLASS2(ICAPAnchor); }; #endif /* SQUID_ICAPANCHOR_H */ Index: squid3/src/ICAPClient.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPClient.cc,v retrieving revision 1.1.2.5 retrieving revision 1.1.2.6 diff -u -r1.1.2.5 -r1.1.2.6 --- squid3/src/ICAPClient.cc 25 Aug 2005 20:51:26 -0000 1.1.2.5 +++ squid3/src/ICAPClient.cc 26 Aug 2005 20:28:41 -0000 1.1.2.6 @@ -3,32 +3,35 @@ #include "ICAPClient.h" #include "http.h" -void ICAPInitModule() { - /* - * ICAP's MsgPipe buffer needs to be at least as large - * as the HTTP read buffer. Otherwise HTTP may take - * data from the network that won't fit into the MsgPipe, - * which leads to a runtime assertion. - */ - assert(ICAPMsgPipeBufSizeMax >= SQUID_TCP_SO_RCVBUF); +void ICAPInitModule() +{ + /* + * ICAP's MsgPipe buffer needs to be at least as large + * as the HTTP read buffer. Otherwise HTTP may take + * data from the network that won't fit into the MsgPipe, + * which leads to a runtime assertion. + */ + assert(ICAPMsgPipeBufSizeMax >= SQUID_TCP_SO_RCVBUF); } -void ICAPCleanModule() { -} +void ICAPCleanModule() +{} // initialize ICAP-specific ends of message pipes -void ICAPInitXaction(MsgPipe *virgin, MsgPipe *adapted) { - ICAPXaction::Pointer x = new ICAPXaction; - debugs(93,5, "ICAPInitXaction: " << x.getRaw()); - x->init(virgin, adapted, x); - // if we want to do something to the transaction after it is done, - // we need to keep a pointer to it +void ICAPInitXaction(MsgPipe *virgin, MsgPipe *adapted) +{ + ICAPXaction::Pointer x = new ICAPXaction; + debugs(93,5, "ICAPInitXaction: " << x.getRaw()); + x->init(virgin, adapted, x); + // if we want to do something to the transaction after it is done, + // we need to keep a pointer to it } // declared in ICAPXaction.h (ick?) -void ICAPNoteXactionDone(ICAPXaction::Pointer x) { - // nothing to be done here? - // refcounting will delete the transaction - // as soon as the last pointer to it is gone - debugs(93,5, "ICAPNoteXactionDone: " << x.getRaw()); +void ICAPNoteXactionDone(ICAPXaction::Pointer x) +{ + // nothing to be done here? + // refcounting will delete the transaction + // as soon as the last pointer to it is gone + debugs(93,5, "ICAPNoteXactionDone: " << x.getRaw()); } Index: squid3/src/ICAPClient.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPClient.h,v retrieving revision 1.1.2.4 retrieving revision 1.1.2.5 diff -u -r1.1.2.4 -r1.1.2.5 --- squid3/src/ICAPClient.h 25 Aug 2005 20:51:26 -0000 1.1.2.4 +++ squid3/src/ICAPClient.h 26 Aug 2005 20:28:41 -0000 1.1.2.5 @@ -1,6 +1,6 @@ /* - * $Id: ICAPClient.h,v 1.1.2.4 2005/08/25 20:51:26 dwsquid Exp $ + * $Id: ICAPClient.h,v 1.1.2.5 2005/08/26 20:28:41 dwsquid Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -36,13 +36,14 @@ // These are public ICAP interfaces for use by Squid code unaware of -// ICAP internals and treating ICAP as an opaque message adaptation +// ICAP internals and treating ICAP as an opaque message adaptation // protocol. extern void ICAPInitModule(); extern void ICAPCleanModule(); // let ICAP initialize ICAP-specific ends of message pipes + class MsgPipe; extern void ICAPInitXaction(MsgPipe *virgin, MsgPipe *adapted); Index: squid3/src/ICAPServiceRep.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPServiceRep.cc,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -u -r1.1.2.1 -r1.1.2.2 --- squid3/src/ICAPServiceRep.cc 19 Aug 2005 20:13:42 -0000 1.1.2.1 +++ squid3/src/ICAPServiceRep.cc 26 Aug 2005 20:28:41 -0000 1.1.2.2 @@ -1,16 +1,18 @@ #include "squid.h" #include "ICAPServiceRep.h" -ICAPServiceRep::ICAPServiceRep(): port(-1) { - // XXX: these need to be config-driven, and initialized elsewhere - method = xstrdup("RESPMOD"); - uri = xstrdup("icap://127.0.0.1:3214/reqmod"); - host = xstrdup("127.0.0.1"); - port = 3214; +ICAPServiceRep::ICAPServiceRep(): port(-1) +{ + // XXX: these need to be config-driven, and initialized elsewhere + method = xstrdup("RESPMOD"); + uri = xstrdup("icap://127.0.0.1:3214/reqmod"); + host = xstrdup("127.0.0.1"); + port = 3214; } -ICAPServiceRep::~ICAPServiceRep() { - xfree(method); - xfree(uri); - xfree(host); +ICAPServiceRep::~ICAPServiceRep() +{ + xfree(method); + xfree(uri); + xfree(host); } Index: squid3/src/ICAPServiceRep.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPServiceRep.h,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -u -r1.1.2.1 -r1.1.2.2 --- squid3/src/ICAPServiceRep.h 19 Aug 2005 20:13:42 -0000 1.1.2.1 +++ squid3/src/ICAPServiceRep.h 26 Aug 2005 20:28:41 -0000 1.1.2.2 @@ -1,6 +1,6 @@ /* - * $Id: ICAPServiceRep.h,v 1.1.2.1 2005/08/19 20:13:42 rousskov Exp $ + * $Id: ICAPServiceRep.h,v 1.1.2.2 2005/08/26 20:28:41 dwsquid Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -36,21 +36,23 @@ #include -/* The ICAP service representative maintains information about a single +/* The ICAP service representative maintains information about a single ICAP service that Squid communicates with. One ICAP server may host many ICAP services */ -class ICAPServiceRep { +class ICAPServiceRep +{ + public: - ICAPServiceRep(); - ~ICAPServiceRep(); + ICAPServiceRep(); + ~ICAPServiceRep(); public: - char *method; // ICAP method (XXX: should be an enum) - char *uri; // service URI + char *method; // ICAP method (XXX: should be an enum) + char *uri; // service URI - char *host; - int port; + char *host; + int port; }; #endif /* SQUID_ICAPSERVICEREP_H */ Index: squid3/src/ICAPXaction.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPXaction.cc,v retrieving revision 1.1.2.12 retrieving revision 1.1.2.13 diff -u -r1.1.2.12 -r1.1.2.13 --- squid3/src/ICAPXaction.cc 25 Aug 2005 22:09:00 -0000 1.1.2.12 +++ squid3/src/ICAPXaction.cc 26 Aug 2005 20:28:41 -0000 1.1.2.13 @@ -26,46 +26,53 @@ static const char *const crlf = "\r\n"; static -ICAPXaction &ICAPXaction_fromData(void *data) { - ICAPXaction *x = static_cast(data); - assert(x); - return *x; +ICAPXaction &ICAPXaction_fromData(void *data) +{ + ICAPXaction *x = static_cast(data); + assert(x); + return *x; } static -void ICAPXaction_noteCommTimeout(int, void *data) { - ICAPXaction_fromData(data).noteCommTimeout(); +void ICAPXaction_noteCommTimeout(int, void *data) +{ + ICAPXaction_fromData(data).noteCommTimeout(); } static -void ICAPXaction_noteCommClose(int, void *data) { - ICAPXaction_fromData(data).noteCommClose(); +void ICAPXaction_noteCommClose(int, void *data) +{ + ICAPXaction_fromData(data).noteCommClose(); } static -void ICAPXaction_noteCommConnected(int, comm_err_t status, int xerrno, void *data) { - ICAPXaction_fromData(data).noteCommConnected(status); +void ICAPXaction_noteCommConnected(int, comm_err_t status, int xerrno, void *data) +{ + ICAPXaction_fromData(data).noteCommConnected(status); } static -void ICAPXaction_noteCommWroteHeaders(int, char *, size_t size, comm_err_t status, void *data) { - ICAPXaction_fromData(data).noteCommWroteHeaders(status); +void ICAPXaction_noteCommWroteHeaders(int, char *, size_t size, comm_err_t status, void *data) +{ + ICAPXaction_fromData(data).noteCommWroteHeaders(status); } static -void ICAPXaction_noteCommWroteBody(int, char *, size_t size, comm_err_t status, void *data) { - ICAPXaction_fromData(data).noteCommWroteBody(status, size); +void ICAPXaction_noteCommWroteBody(int, char *, size_t size, comm_err_t status, void *data) +{ + ICAPXaction_fromData(data).noteCommWroteBody(status, size); } static -void ICAPXaction_noteCommRead(int, char *, size_t size, comm_err_t status, int xerrno, void *data) { - ICAPXaction_fromData(data).noteCommRead(status, size); +void ICAPXaction_noteCommRead(int, char *, size_t size, comm_err_t status, int xerrno, void *data) +{ + ICAPXaction_fromData(data).noteCommRead(status, size); } -// call guards for all "asynchronous" note*() methods that are being called +// call guards for all "asynchronous" note*() methods that are being called // from message pipes or the comm module -// asynchronous call entry: +// asynchronous call entry: // - remember default notify address (currently hard-coded to notifyAll); // - open the try clause; // - call callStart(). @@ -75,7 +82,7 @@ if (!callStart(#method)) \ return; // ... -// asynchronous call exit: +// asynchronous call exit: // - close the try clause; // - catch exceptions; // - let callEnd() handle transaction termination conditions @@ -87,548 +94,613 @@ callEnd(#method); -ICAPXaction::State::State() { - memset(this, sizeof(*this), 0); +ICAPXaction::State::State() +{ + memset(this, sizeof(*this), 0); } ICAPXaction::ICAPXaction(): self(NULL), virgin(NULL), adapted(NULL), - icapReply(NULL), service(NULL), connection(-1), notify(notifyUnknown) { -} + icapReply(NULL), service(NULL), connection(-1), notify(notifyUnknown) +{} + +ICAPXaction::~ICAPXaction() +{ + notify = notifyNone; + doStop(); -ICAPXaction::~ICAPXaction() { - notify = notifyNone; - doStop(); - if (icapReply) - httpReplyDestroy(icapReply); + if (icapReply) + httpReplyDestroy(icapReply); } -void ICAPXaction::init(MsgPipe *aVirgin, MsgPipe *anAdapted, Pointer &aSelf) { - assert(!self.getRaw() && !virgin && !adapted); - assert(aSelf.getRaw() && aVirgin && anAdapted); +void ICAPXaction::init(MsgPipe *aVirgin, MsgPipe *anAdapted, Pointer &aSelf) +{ + assert(!self.getRaw() && !virgin && !adapted); + assert(aSelf.getRaw() && aVirgin && anAdapted); - self = aSelf; - virgin = aVirgin; - adapted = anAdapted; + self = aSelf; + virgin = aVirgin; + adapted = anAdapted; - // receiving end - virgin->sink = this; // should be 'self' and refcounted - // virgin pipe data is initiated by the source + // receiving end + virgin->sink = this; // should be 'self' and refcounted + // virgin pipe data is initiated by the source - // sending end - adapted->source = this; // should be 'self' and refcounted - adapted->data = new MsgPipeData; - adapted->data->header = httpReplyCreate(); // who is deleting? refcount? - adapted->data->body = new MemBuf; // XXX: make body a non-pointer? - memBufInit(adapted->data->body, ICAPMsgPipeBufSizeMin, ICAPMsgPipeBufSizeMax); - // headers are initialized when we parse them + // sending end + adapted->source = this; // should be 'self' and refcounted + adapted->data = new MsgPipeData; + adapted->data->header = httpReplyCreate(); // who is deleting? refcount? + adapted->data->body = new MemBuf; // XXX: make body a non-pointer? + memBufInit(adapted->data->body, ICAPMsgPipeBufSizeMin, ICAPMsgPipeBufSizeMax); + // headers are initialized when we parse them - // writing end - // nothing to do because we are using temporary write buffers + // writing end + // nothing to do because we are using temporary write buffers - // reading end - memBufDefInit(&readBuf); + // reading end + memBufDefInit(&readBuf); - // encoding - memBufDefInit(&requestBuf); + // encoding + memBufDefInit(&requestBuf); - // parsing - icapReply = httpReplyCreate(); - icapReply->protoPrefix = "ICAP/"; // TODO: make an IcapReply class? + // parsing + icapReply = httpReplyCreate(); + icapReply->protoPrefix = "ICAP/"; // TODO: make an IcapReply class? - // XXX: make sure stop() cleans all buffers + // XXX: make sure stop() cleans all buffers } // HTTP side starts sending virgin data -void ICAPXaction::noteSourceStart(MsgPipe *p) { - ICAPXaction_Enter(noteSourceStart); - - pickService(); - openConnection(); - // put nothing here as openConnection calls commConnectStart - // and that may call us back without waiting for the next select loop - - // XXX: but this has to be here to catch other errors. Thus, if - // commConnectStart fails (see the comment above), we may get here - // _after_ the object got destroyed. Somebody please fix commConnectStart! - ICAPXaction_Exit(noteSourceStart); +void ICAPXaction::noteSourceStart(MsgPipe *p) +{ + ICAPXaction_Enter(noteSourceStart); + + pickService(); + openConnection(); + // put nothing here as openConnection calls commConnectStart + // and that may call us back without waiting for the next select loop + + // XXX: but this has to be here to catch other errors. Thus, if + // commConnectStart fails (see the comment above), we may get here + // _after_ the object got destroyed. Somebody please fix commConnectStart! + ICAPXaction_Exit(noteSourceStart); } // TODO: obey service-specific, OPTIONS-reported connection limit -void ICAPXaction::openConnection() { - // TODO: check whether NULL domain is appropriate here - connection = pconnPop(service->host, service->port, NULL); - - if (connection < 0) { - connection = comm_open(SOCK_STREAM, 0, getOutgoingAddr(NULL), 0, - COMM_NONBLOCKING, service->uri); - if (connection < 0) - throw TexcHere("cannot connect to ICAP service " /* + uri */); - } - - commSetTimeout(connection, Config.Timeout.connect, - &ICAPXaction_noteCommTimeout, this); - state.closer = &ICAPXaction_noteCommClose; - comm_add_close_handler(connection, state.closer, this); - commConnectStart(connection, service->host, service->port, - &ICAPXaction_noteCommConnected, this); -} - -void ICAPXaction::closeConnection() { - if (connection >= 0) { - commSetTimeout(connection, -1, NULL, NULL); - if (state.closer) - comm_remove_close_handler(connection, state.closer, this); - stopReading(); - comm_close(connection); - connection = -1; - } +void ICAPXaction::openConnection() +{ + // TODO: check whether NULL domain is appropriate here + connection = pconnPop(service->host, service->port, NULL); + + if (connection < 0) { + connection = comm_open(SOCK_STREAM, 0, getOutgoingAddr(NULL), 0, + COMM_NONBLOCKING, service->uri); + + if (connection < 0) + throw TexcHere("cannot connect to ICAP service " /* + uri */); + } + + commSetTimeout(connection, Config.Timeout.connect, + &ICAPXaction_noteCommTimeout, this); + state.closer = &ICAPXaction_noteCommClose; + comm_add_close_handler(connection, state.closer, this); + commConnectStart(connection, service->host, service->port, + &ICAPXaction_noteCommConnected, this); +} + +void ICAPXaction::closeConnection() +{ + if (connection >= 0) { + commSetTimeout(connection, -1, NULL, NULL); + + if (state.closer) + comm_remove_close_handler(connection, state.closer, this); + + stopReading(); + + comm_close(connection); + + connection = -1; + } } // connection with the ICAP service established -void ICAPXaction::noteCommConnected(comm_err_t status) { - ICAPXaction_Enter(noteCommConnected); +void ICAPXaction::noteCommConnected(comm_err_t status) +{ + ICAPXaction_Enter(noteCommConnected); - Must(status == COMM_OK); + Must(status == COMM_OK); - startReading(); // wait for early errors from the ICAP server + startReading(); // wait for early errors from the ICAP server - makeRequestHeaders(); - // write headers only; comm module will free the requestBuf - state.isWriting = &ICAPXaction_noteCommWroteHeaders; - comm_old_write_mbuf(connection, requestBuf, state.isWriting, this); + makeRequestHeaders(); + // write headers only; comm module will free the requestBuf + state.isWriting = &ICAPXaction_noteCommWroteHeaders; + comm_old_write_mbuf(connection, requestBuf, state.isWriting, this); - ICAPXaction_Exit(noteCommConnected); + ICAPXaction_Exit(noteCommConnected); } -void ICAPXaction::noteCommWroteHeaders(comm_err_t status) { - ICAPXaction_Enter(noteCommWroteHeaders); +void ICAPXaction::noteCommWroteHeaders(comm_err_t status) +{ + ICAPXaction_Enter(noteCommWroteHeaders); - Must(state.isWriting); - state.isWriting = NULL; + Must(state.isWriting); + state.isWriting = NULL; - Must(status == COMM_OK); - writeMoreBody(); + Must(status == COMM_OK); + writeMoreBody(); - ICAPXaction_Exit(noteCommWroteHeaders); + ICAPXaction_Exit(noteCommWroteHeaders); } -void ICAPXaction::writeMoreBody() { - if (state.isWriting || state.doneWriting) - return; +void ICAPXaction::writeMoreBody() +{ + if (state.isWriting || state.doneWriting) + return; + + MsgPipeData::Body *body = virgin->data->body; + + MemBuf writeBuf; // TODO: suggest a min size based on body and lastChunk + + memBufDefInit(&writeBuf); + + if (body->hasContent()) { + debugs(93, 7, "ICAPXaction will write " << body->contentSize() << + "-byte chunk"); + moveRequestChunk(&writeBuf); + Must(!body->hasContent()); // we should have moved all of it above - MsgPipeData::Body *body = virgin->data->body; - MemBuf writeBuf; // TODO: suggest a min size based on body and lastChunk - memBufDefInit(&writeBuf); + if (!state.doneReceiving) + virgin->sendSinkNeed(); + } - if (body->hasContent()) { - debugs(93, 7, "ICAPXaction will write " << body->contentSize() << - "-byte chunk"); - moveRequestChunk(&writeBuf); - Must(!body->hasContent()); // we should have moved all of it above - if (!state.doneReceiving) - virgin->sendSinkNeed(); - } - - if (state.doneReceiving && !state.doneWriting) { - debugs(93, 7, "ICAPXaction will write last-chunk"); - moveRequestChunk(&writeBuf); // will add zero-size chunk - state.doneWriting = true; - } + if (state.doneReceiving && !state.doneWriting) { + debugs(93, 7, "ICAPXaction will write last-chunk"); + moveRequestChunk(&writeBuf); // will add zero-size chunk + state.doneWriting = true; + } - debugs(93, 7, "ICAPXaction will write " << writeBuf.contentSize() << " bytes"); - if (writeBuf.hasContent()) { - // comm will free the chunk - state.isWriting = &ICAPXaction_noteCommWroteBody; - comm_old_write_mbuf(connection, writeBuf, state.isWriting, this); - } + debugs(93, 7, "ICAPXaction will write " << writeBuf.contentSize() << " bytes"); + + if (writeBuf.hasContent()) { + // comm will free the chunk + state.isWriting = &ICAPXaction_noteCommWroteBody; + comm_old_write_mbuf(connection, writeBuf, state.isWriting, this); + } } -void ICAPXaction::moveRequestChunk(MemBuf *buf) { - MsgPipeData::Body *body = virgin->data->body; - const mb_size_t chunkSize = body->contentSize(); // may be zero - memBufPrintf(buf, "%x\r\n", chunkSize); - if (chunkSize > 0) { - buf->append(body->content(), chunkSize); - body->consume(chunkSize); - } - buf->append(crlf, 2); // chunk-terminating CRLF +void ICAPXaction::moveRequestChunk(MemBuf *buf) +{ + MsgPipeData::Body *body = virgin->data->body; + const mb_size_t chunkSize = body->contentSize(); // may be zero + memBufPrintf(buf, "%x\r\n", chunkSize); + + if (chunkSize > 0) { + buf->append(body->content(), chunkSize); + body->consume(chunkSize); + } + + buf->append(crlf, 2); // chunk-terminating CRLF } -void ICAPXaction::noteCommWroteBody(comm_err_t status, size_t sz) { - ICAPXaction_Enter(noteCommWroteBody); +void ICAPXaction::noteCommWroteBody(comm_err_t status, size_t sz) +{ + ICAPXaction_Enter(noteCommWroteBody); - state.isWriting = NULL; - Must(status == COMM_OK); - writeMoreBody(); + state.isWriting = NULL; + Must(status == COMM_OK); + writeMoreBody(); - ICAPXaction_Exit(noteCommWroteBody); + ICAPXaction_Exit(noteCommWroteBody); } // communication timeout with the ICAP service -void ICAPXaction::noteCommTimeout() { - ICAPXaction_Enter(noteCommTimeout); +void ICAPXaction::noteCommTimeout() +{ + ICAPXaction_Enter(noteCommTimeout); - mustStop(notifyHttp); + mustStop(notifyHttp); - ICAPXaction_Exit(noteCommTimeout); + ICAPXaction_Exit(noteCommTimeout); } // unexpected connection close while talking to the ICAP service -void ICAPXaction::noteCommClose() { - state.closer = NULL; - ICAPXaction_Enter(noteCommClose); +void ICAPXaction::noteCommClose() +{ + state.closer = NULL; + ICAPXaction_Enter(noteCommClose); - mustStop(notifyHttp); + mustStop(notifyHttp); - ICAPXaction_Exit(noteCommClose); + ICAPXaction_Exit(noteCommClose); } -bool ICAPXaction::done() const { - if (notify != notifyUnknown) // mustStop() has been called - return true; +bool ICAPXaction::done() const +{ + if (notify != notifyUnknown) // mustStop() has been called + return true; - return state.doneReceiving && state.doneSending && - state.doneReading && state.doneWriting; + return state.doneReceiving && state.doneSending && + state.doneReading && state.doneWriting; } -void ICAPXaction::startReading() { - Must(connection >= 0 && !state.isReading && - adapted && adapted->data && adapted->data->body); +void ICAPXaction::startReading() +{ + Must(connection >= 0 && !state.isReading && + adapted && adapted->data && adapted->data->body); - readMore(); + readMore(); } -void ICAPXaction::readMore() { - if (state.isReading || state.doneReading) - return; +void ICAPXaction::readMore() +{ + if (state.isReading || state.doneReading) + return; - // do not fill readBuf if we have no space to store the result - if (!adapted->data->body->hasPotentialSpace()) - return; - - // we use the same buffer for headers and body and then consume headers - if (readBuf.hasSpace()) { - state.isReading = &ICAPXaction_noteCommRead; - comm_read(connection, readBuf.space(), readBuf.spaceSize(), - state.isReading, this); - } + // do not fill readBuf if we have no space to store the result + if (!adapted->data->body->hasPotentialSpace()) + return; + + // we use the same buffer for headers and body and then consume headers + if (readBuf.hasSpace()) { + state.isReading = &ICAPXaction_noteCommRead; + comm_read(connection, readBuf.space(), readBuf.spaceSize(), + state.isReading, this); + } } // comm module read a portion of the ICAP response for us -void ICAPXaction::noteCommRead(comm_err_t status, size_t sz) { - ICAPXaction_Enter(noteCommRead); +void ICAPXaction::noteCommRead(comm_err_t status, size_t sz) +{ + ICAPXaction_Enter(noteCommRead); + + Must(state.isReading); + state.isReading = NULL; - Must(state.isReading); - state.isReading = NULL; + Must(!state.doneParsing()); + Must(status == COMM_OK); - Must(!state.doneParsing()); - Must(status == COMM_OK); + debugs(93, 5, "read " << sz << " bytes"); - debugs(93, 5, "read " << sz << " bytes"); + if (sz == 0) + stopReading(); + else + if (sz > 0) + readBuf.appended(sz); - if (sz == 0) - stopReading(); - else - if (sz > 0) - readBuf.appended(sz); + parseMore(); - parseMore(); - readMore(); + readMore(); - ICAPXaction_Exit(noteCommRead); + ICAPXaction_Exit(noteCommRead); } -void ICAPXaction::stopReading() { - if (state.isReading) { - comm_read_cancel(connection, state.isReading, this); - state.isReading = NULL; - } - state.doneReading = true; +void ICAPXaction::stopReading() +{ + if (state.isReading) { + comm_read_cancel(connection, state.isReading, this); + state.isReading = NULL; + } + + state.doneReading = true; } -void ICAPXaction::parseMore() { - debugs(93, 5, "have " << readBuf.contentSize() << " bytes to parse" << - "; state: " << state.parsing); +void ICAPXaction::parseMore() +{ + debugs(93, 5, "have " << readBuf.contentSize() << " bytes to parse" << + "; state: " << state.parsing); - if (state.parsingHeaders()) - parseHeaders(); + if (state.parsingHeaders()) + parseHeaders(); - if (state.parsing == State::psBody) - parseBody(); + if (state.parsing == State::psBody) + parseBody(); } -void ICAPXaction::parseHeaders() { - Must(state.parsingHeaders()); +void ICAPXaction::parseHeaders() +{ + Must(state.parsingHeaders()); - if (state.parsing == State::psIcapHeader) - parseHeader(icapReply); + if (state.parsing == State::psIcapHeader) + parseHeader(icapReply); - if (state.parsing == State::psHttpHeader) { - if (gotEncapsulated("res-hdr")) - parseHeader(adapted->data->header); - else - state.parsing = State::psBody; - } + if (state.parsing == State::psHttpHeader) { + if (gotEncapsulated("res-hdr")) + parseHeader(adapted->data->header); + else + state.parsing = State::psBody; + } - if (state.parsingHeaders()) // need more data - Must(!state.doneReading); - else - adapted->sendSourceStart(); + if (state.parsingHeaders()) // need more data + Must(!state.doneReading); + else + adapted->sendSourceStart(); } -void ICAPXaction::parseHeader(HttpReply *header) { - debugs(93, 5, "have " << readBuf.contentSize() << " hdr bytes to parse" << - "; state: " << state.parsing); +void ICAPXaction::parseHeader(HttpReply *header) +{ + debugs(93, 5, "have " << readBuf.contentSize() << " hdr bytes to parse" << + "; state: " << state.parsing); + + http_status error = HTTP_STATUS_NONE; + const bool parsed = header->parse(&readBuf, state.doneReading, &error); + Must(!error); - http_status error = HTTP_STATUS_NONE; - const bool parsed = header->parse(&readBuf, state.doneReading, &error); - Must(!error); - if (!parsed) { - httpReplyReset(header); - return; - } + if (!parsed) { + httpReplyReset(header); + return; + } - readBuf.consume(header->hdr_sz); - state.parsing = (State::Parsing)(state.parsing + 1); + readBuf.consume(header->hdr_sz); + state.parsing = (State::Parsing)(state.parsing + 1); } -void ICAPXaction::parseBody() { - Must(state.parsing == State::psBody); +void ICAPXaction::parseBody() +{ + Must(state.parsing == State::psBody); - debugs(93, 5, "have " << readBuf.contentSize() << " body bytes to parse"); + debugs(93, 5, "have " << readBuf.contentSize() << " body bytes to parse"); - if (gotEncapsulated("res-body")) { - if (!parsePresentBody()) - return; - } else { - debugs(93, 5, "not expecting a body"); - } - - stopReading(); - state.parsing = State::psDone; - state.doneSending = true; - adapted->sendSourceFinish(); - delete bodyParser; - bodyParser = 0; -} - -bool ICAPXaction::parsePresentBody() { - if (!bodyParser) - bodyParser = new ChunkedCodingParser; - - // the parser will throw on errors - const bool parsed = bodyParser->parse(&readBuf, adapted->data->body); - adapted->sendSourceProgress(); - - debugs(93, 5, "have " << readBuf.contentSize() << " body bytes after " << - "parse; parsed all: " << parsed); - - if (!parsed) { // needs more data - Must(!state.doneReading); // will get more - Must(readBuf.hasSpace()); // have place for more - return false; - } + if (gotEncapsulated("res-body")) { + if (!parsePresentBody()) + return; + } else { + debugs(93, 5, "not expecting a body"); + } - return true; + stopReading(); + state.parsing = State::psDone; + state.doneSending = true; + adapted->sendSourceFinish(); + delete bodyParser; + bodyParser = 0; +} + +bool ICAPXaction::parsePresentBody() +{ + if (!bodyParser) + bodyParser = new ChunkedCodingParser; + + // the parser will throw on errors + const bool parsed = bodyParser->parse(&readBuf, adapted->data->body); + + adapted->sendSourceProgress(); + + debugs(93, 5, "have " << readBuf.contentSize() << " body bytes after " << + "parse; parsed all: " << parsed); + + if (!parsed) { // needs more data + Must(!state.doneReading); // will get more + Must(readBuf.hasSpace()); // have place for more + return false; + } + + return true; } // HTTP side added virgin body data -void ICAPXaction::noteSourceProgress(MsgPipe *p) { - ICAPXaction_Enter(noteSourceProgress); +void ICAPXaction::noteSourceProgress(MsgPipe *p) +{ + ICAPXaction_Enter(noteSourceProgress); - Must(!state.doneReceiving); - writeMoreBody(); + Must(!state.doneReceiving); + writeMoreBody(); - ICAPXaction_Exit(noteSourceProgress); + ICAPXaction_Exit(noteSourceProgress); } // HTTP side sent us all virgin info -void ICAPXaction::noteSourceFinish(MsgPipe *p) { - ICAPXaction_Enter(noteSourceFinish); - - Must(!state.doneReceiving); - state.doneReceiving = true; - writeMoreBody(); // in case we were waiting to send the last-chunk +void ICAPXaction::noteSourceFinish(MsgPipe *p) +{ + ICAPXaction_Enter(noteSourceFinish); + + Must(!state.doneReceiving); + state.doneReceiving = true; + writeMoreBody(); // in case we were waiting to send the last-chunk - ICAPXaction_Exit(noteSourceFinish); + ICAPXaction_Exit(noteSourceFinish); } // HTTP side is aborting -void ICAPXaction::noteSourceAbort(MsgPipe *p) { - ICAPXaction_Enter(noteSourceAbort); +void ICAPXaction::noteSourceAbort(MsgPipe *p) +{ + ICAPXaction_Enter(noteSourceAbort); - Must(!state.doneReceiving); - state.doneReceiving = true; + Must(!state.doneReceiving); + state.doneReceiving = true; - ICAPXaction_Exit(noteSourceAbort); + ICAPXaction_Exit(noteSourceAbort); } // HTTP side wants more adapted data and possibly freed some buffer space -void ICAPXaction::noteSinkNeed(MsgPipe *p) { - ICAPXaction_Enter(noteSinkNeed); +void ICAPXaction::noteSinkNeed(MsgPipe *p) +{ + ICAPXaction_Enter(noteSinkNeed); - Must(!state.doneSending); - parseMore(); + Must(!state.doneSending); + parseMore(); - ICAPXaction_Exit(noteSinkNeed); + ICAPXaction_Exit(noteSinkNeed); } // HTTP side aborted -void ICAPXaction::noteSinkAbort(MsgPipe *p) { - ICAPXaction_Enter(noteSinkAbort); +void ICAPXaction::noteSinkAbort(MsgPipe *p) +{ + ICAPXaction_Enter(noteSinkAbort); - mustStop(notifyService); + mustStop(notifyService); - ICAPXaction_Exit(noteSinkAbort); + ICAPXaction_Exit(noteSinkAbort); } -void ICAPXaction::pickService() { - // TODO: select the service based on config, ACLs, etc. - static ICAPServiceRep TheService; - service = &TheService; +void ICAPXaction::pickService() +{ + // TODO: select the service based on config, ACLs, etc. + static ICAPServiceRep TheService; + service = &TheService; } -void ICAPXaction::mustStop(Notify who) { - Must(state.inCall); // otherwise nobody will call doStop() - Must(notify == notifyUnknown); - notify = who; - debugs(93, 5, "ICAPXaction will stop and notify " << notify); +void ICAPXaction::mustStop(Notify who) +{ + Must(state.inCall); // otherwise nobody will call doStop() + Must(notify == notifyUnknown); + notify = who; + debugs(93, 5, "ICAPXaction will stop and notify " << notify); } // internal cleanup -void ICAPXaction::doStop() { - debugs(93, 5, "ICAPXaction::doStop"); +void ICAPXaction::doStop() +{ + debugs(93, 5, "ICAPXaction::doStop"); + + memBufClean(&readBuf); + memBufClean(&requestBuf); + + closeConnection(); // TODO: pconn support: close unless notifyService ... + + if (virgin) { + if (notify == notifyHttp || notify == notifyAll) + virgin->sendSinkAbort(); + else + virgin->sink = NULL; + + // this is the place to decrement refcount ptr + virgin = NULL; + } + + if (adapted) { + if (notify == notifyHttp || notify == notifyAll) + adapted->sendSourceAbort(); + else + adapted->source = NULL; + + // this is the place to decrement refcount ptr + adapted = NULL; + } + + if (self != NULL) { // even if notify is notifyNone + Pointer s = self; + self = NULL; + ICAPNoteXactionDone(s); + /* this object may be destroyed when 's' is cleared */ + } +} + +void ICAPXaction::makeRequestHeaders() +{ + HttpRequest *&httpReq = virgin->data->cause; + HttpReply *&httpResp = virgin->data->header; + Must(httpReq); // require request headers for now + Must(httpResp); + + MemBuf httpBuf; + memBufDefInit(&httpBuf); + + /* build HTTP request header */ + + // HTTP Request-line + memBufPrintf(&httpBuf, "%s %s HTTP/%d.%d\r\n", + RequestMethodStr[httpReq->method], + httpReq->urlpath.size() ? httpReq->urlpath.buf() : "/", + httpReq->http_ver.major, httpReq->http_ver.minor); + + // HTTP Request header fields + Packer p; + packerToMemInit(&p, &httpBuf); + httpHeaderPackInto(&httpReq->header, &p); + packerClean(&p); + httpBuf.append(crlf, 2); // CRLF terminator + const size_t httpRespOffset = httpBuf.contentSize(); + + // build HTTP response header + packerToMemInit(&p, &httpBuf); + httpStatusLinePackInto(&httpResp->sline, &p); + httpHeaderPackInto(&httpResp->header, &p); + packerClean(&p); + httpBuf.append(crlf, 2); // CRLF terminator + const size_t httpBodyOffset = httpBuf.contentSize(); + + /* ICAP request header */ + MemBuf *buf = &requestBuf; + memBufPrintf(buf, "RESPMOD %s ICAP/1.0\r\n", service->uri); + memBufPrintf(buf, "Host: %s:%d\r\n", service->host, service->port); + memBufPrintf(buf, "Encapsulated: req-hdr=%d,res-hdr=%d,res-body=%d\r\n", + 0, httpRespOffset, httpBodyOffset); + buf->append(crlf, 2); // CRLF terminator + + /* ICAP request body */ + buf->append(httpBuf.content(), httpBuf.contentSize()); +} + +bool ICAPXaction::callStart(const char *method) +{ + debugs(93, 5, "ICAPXaction::" << method << " called " << status()); + + if (state.inCall) { + // this may happen when we have bugs or when arguably buggy + // comm interface calls us while we are closing the connection + debugs(93, 5, "ICAPXaction::" << method << " cancels reentry."); + return false; + } + + state.inCall = true; + return true; +} + +void ICAPXaction::callException(const char *method, const TextException &e, Notify defaultWho) +{ + debugs(93, 4, "ICAPXaction::" << method << " caught an exception: " << + e.message << ' ' << status()); + + if (!done()) + mustStop(defaultWho); +} + +void ICAPXaction::callEnd(const char *method) +{ + if (done()) { + debugs(93, 5, "ICAPXaction::" << method << " ends xaction " << + status()); + doStop(); + return; + } - memBufClean(&readBuf); - memBufClean(&requestBuf); + debugs(93, 6, "ICAPXaction::" << method << " ended " << status()); + state.inCall = false; +} + +// returns a temporary string depicting transaction status, for debugging +const char *ICAPXaction::status() const +{ + static MemBuf status; + memBufReset(&status); + + status.append("[", 1); + + if (notify != notifyUnknown) + memBufPrintf(&status, "N(%d)", notify); - closeConnection(); // TODO: pconn support: close unless notifyService ... + if (state.doneReceiving) + status.append("R", 1); - if (virgin) { - if (notify == notifyHttp || notify == notifyAll) - virgin->sendSinkAbort(); - else - virgin->sink = NULL; - // this is the place to decrement refcount ptr - virgin = NULL; - } - if (adapted) { - if (notify == notifyHttp || notify == notifyAll) - adapted->sendSourceAbort(); - else - adapted->source = NULL; - // this is the place to decrement refcount ptr - adapted = NULL; - } - - if (self != NULL) { // even if notify is notifyNone - Pointer s = self; - self = NULL; - ICAPNoteXactionDone(s); - /* this object may be destroyed when 's' is cleared */ - } -} - -void ICAPXaction::makeRequestHeaders() { - HttpRequest *&httpReq = virgin->data->cause; - HttpReply *&httpResp = virgin->data->header; - Must(httpReq); // require request headers for now - Must(httpResp); - - MemBuf httpBuf; - memBufDefInit(&httpBuf); - - /* build HTTP request header */ - - // HTTP Request-line - memBufPrintf(&httpBuf, "%s %s HTTP/%d.%d\r\n", - RequestMethodStr[httpReq->method], - httpReq->urlpath.size() ? httpReq->urlpath.buf() : "/", - httpReq->http_ver.major, httpReq->http_ver.minor); - - // HTTP Request header fields - Packer p; - packerToMemInit(&p, &httpBuf); - httpHeaderPackInto(&httpReq->header, &p); - packerClean(&p); - httpBuf.append(crlf, 2); // CRLF terminator - const size_t httpRespOffset = httpBuf.contentSize(); - - // build HTTP response header - packerToMemInit(&p, &httpBuf); - httpStatusLinePackInto(&httpResp->sline, &p); - httpHeaderPackInto(&httpResp->header, &p); - packerClean(&p); - httpBuf.append(crlf, 2); // CRLF terminator - const size_t httpBodyOffset = httpBuf.contentSize(); - - /* ICAP request header */ - MemBuf *buf = &requestBuf; - memBufPrintf(buf, "RESPMOD %s ICAP/1.0\r\n", service->uri); - memBufPrintf(buf, "Host: %s:%d\r\n", service->host, service->port); - memBufPrintf(buf, "Encapsulated: req-hdr=%d,res-hdr=%d,res-body=%d\r\n", - 0, httpRespOffset, httpBodyOffset); - buf->append(crlf, 2); // CRLF terminator - - /* ICAP request body */ - buf->append(httpBuf.content(), httpBuf.contentSize()); -} - -bool ICAPXaction::callStart(const char *method) { - debugs(93, 5, "ICAPXaction::" << method << " called " << status()); - if (state.inCall) { - // this may happen when we have bugs or when arguably buggy - // comm interface calls us while we are closing the connection - debugs(93, 5, "ICAPXaction::" << method << " cancels reentry."); - return false; - } - - state.inCall = true; - return true; -} - -void ICAPXaction::callException(const char *method, const TextException &e, Notify defaultWho) { - debugs(93, 4, "ICAPXaction::" << method << " caught an exception: " << - e.message << ' ' << status()); - if (!done()) - mustStop(defaultWho); -} - -void ICAPXaction::callEnd(const char *method) { - if (done()) { - debugs(93, 5, "ICAPXaction::" << method << " ends xaction " << - status()); - doStop(); - return; - } + if (state.doneSending) + status.append("S", 1); - debugs(93, 6, "ICAPXaction::" << method << " ended " << status()); - state.inCall = false; + if (state.doneReading) + status.append("r", 1); + + if (state.doneWriting) + status.append("w", 1); + + status.append("]", 1); + + status.terminate(); + + return status.content(); } -// returns a temporary string depicting transaction status, for debugging -const char *ICAPXaction::status() const { - static MemBuf status; - memBufReset(&status); - - status.append("[", 1); - if (notify != notifyUnknown) - memBufPrintf(&status, "N(%d)", notify); - if (state.doneReceiving) - status.append("R", 1); - if (state.doneSending) - status.append("S", 1); - if (state.doneReading) - status.append("r", 1); - if (state.doneWriting) - status.append("w", 1); - status.append("]", 1); - - status.terminate(); - return status.content(); -} - -bool ICAPXaction::gotEncapsulated(const char *section) const { - return httpHeaderGetByNameListMember(&icapReply->header, "Encapsulated", - section, ',').size() > 0; +bool ICAPXaction::gotEncapsulated(const char *section) const +{ + return httpHeaderGetByNameListMember(&icapReply->header, "Encapsulated", + section, ',').size() > 0; } Index: squid3/src/ICAPXaction.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPXaction.h,v retrieving revision 1.1.2.7 retrieving revision 1.1.2.8 diff -u -r1.1.2.7 -r1.1.2.8 --- squid3/src/ICAPXaction.h 25 Aug 2005 22:09:00 -0000 1.1.2.7 +++ squid3/src/ICAPXaction.h 26 Aug 2005 20:28:41 -0000 1.1.2.8 @@ -1,6 +1,6 @@ /* - * $Id: ICAPXaction.h,v 1.1.2.7 2005/08/25 22:09:00 rousskov Exp $ + * $Id: ICAPXaction.h,v 1.1.2.8 2005/08/26 20:28:41 dwsquid Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -43,114 +43,135 @@ * the adapted messages back. ICAPClient is the "owner" of the ICAPXaction. */ class ICAPServiceRep; + class TextException; + class ChunkedCodingParser; -class ICAPXaction: public MsgPipeSource, public MsgPipeSink { +class ICAPXaction: public MsgPipeSource, public MsgPipeSink +{ + public: - typedef RefCount Pointer; + typedef RefCount Pointer; public: - ICAPXaction(); - virtual ~ICAPXaction(); + ICAPXaction(); + virtual ~ICAPXaction(); - // called by ICAPClient - void init(MsgPipe *aVirgin, MsgPipe *anAdapted, Pointer &aSelf); - void ownerAbort(); - - // pipe source methods; called by Anchor while receiving the adapted msg - virtual void noteSinkNeed(MsgPipe *p); - virtual void noteSinkAbort(MsgPipe *p); - - // pipe sink methods; called by ICAP while sending the virgin message - virtual void noteSourceStart(MsgPipe *p); - virtual void noteSourceProgress(MsgPipe *p); - virtual void noteSourceFinish(MsgPipe *p); - virtual void noteSourceAbort(MsgPipe *p); - - // comm handlers - void noteCommConnected(comm_err_t status); - void noteCommWroteHeaders(comm_err_t status); - void noteCommWroteBody(comm_err_t status, size_t sz); - void noteCommRead(comm_err_t status, size_t sz); - void noteCommTimeout(); - void noteCommClose(); + // called by ICAPClient + void init(MsgPipe *aVirgin, MsgPipe *anAdapted, Pointer &aSelf); + void ownerAbort(); + + // pipe source methods; called by Anchor while receiving the adapted msg + virtual void noteSinkNeed(MsgPipe *p); + virtual void noteSinkAbort(MsgPipe *p); + + // pipe sink methods; called by ICAP while sending the virgin message + virtual void noteSourceStart(MsgPipe *p); + virtual void noteSourceProgress(MsgPipe *p); + virtual void noteSourceFinish(MsgPipe *p); + virtual void noteSourceAbort(MsgPipe *p); + + // comm handlers + void noteCommConnected(comm_err_t status); + void noteCommWroteHeaders(comm_err_t status); + void noteCommWroteBody(comm_err_t status, size_t sz); + void noteCommRead(comm_err_t status, size_t sz); + void noteCommTimeout(); + void noteCommClose(); private: - void openConnection(); - void closeConnection(); - void writeMoreBody(); - void startReading(); - void readMore(); - - void makeRequestHeaders(); - void moveRequestChunk(MemBuf *buf); - - void parseMore(); - void parseHeaders(); - void parseHeader(HttpReply *header); - void parseBody(); - bool parsePresentBody(); - - void pickService(); - - bool done() const; - - typedef enum { notifyUnknown, notifyNone, notifyService, notifyHttp, - notifyAll } Notify; - void mustStop(Notify who); - void doStop(); - void stopReading(); - - bool callStart(const char *method); - void callException(const char *method, const TextException &e, Notify who); - void callEnd(const char *method); + void openConnection(); + void closeConnection(); + void writeMoreBody(); + void startReading(); + void readMore(); + + void makeRequestHeaders(); + void moveRequestChunk(MemBuf *buf); + + void parseMore(); + void parseHeaders(); + void parseHeader(HttpReply *header); + void parseBody(); + bool parsePresentBody(); + + void pickService(); + + bool done() const; + + typedef enum { notifyUnknown, notifyNone, notifyService, notifyHttp, + notifyAll } Notify; + void mustStop(Notify who); + void doStop(); + void stopReading(); + + bool callStart(const char *method); + void callException(const char *method, const TextException &e, Notify who); + void callEnd(const char *method); private: - // returns a temporary string depicting transaction status, for debugging - const char *status() const; - bool gotEncapsulated(const char *section) const; - - Pointer self; - MsgPipe *virgin; - MsgPipe *adapted; - - HttpReply *icapReply; - - ICAPServiceRep *service; - int connection; // FD of the ICAP server connection - - MemBuf requestBuf; - MemBuf readBuf; - ChunkedCodingParser *bodyParser; - - class State { - public: - State(); - - public: - // XXX: document each - unsigned inCall: 1; - - unsigned doneReceiving: 1; - unsigned doneSending: 1; - unsigned doneReading: 1; - unsigned doneWriting: 1; - - bool doneParsing() const { return parsing == psDone; } - bool parsingHeaders() const { return parsing == psIcapHeader || - parsing == psHttpHeader; } - - CWCB *isWriting; - IOCB *isReading; - PF *closer; + // returns a temporary string depicting transaction status, for debugging + const char *status() const; + bool gotEncapsulated(const char *section) const; + + Pointer self; + MsgPipe *virgin; + MsgPipe *adapted; + + HttpReply *icapReply; + + ICAPServiceRep *service; + int connection; // FD of the ICAP server connection + + MemBuf requestBuf; + MemBuf readBuf; + ChunkedCodingParser *bodyParser; + + class State + { + + public: + State(); + + public: + // XXX: document each + + unsigned inCall: + 1; + + unsigned doneReceiving: + 1; + + unsigned doneSending: + 1; + + unsigned doneReading: + 1; + + unsigned doneWriting: + 1; + + bool doneParsing() const { return parsing == psDone; } + + bool parsingHeaders() const + { + return parsing == psIcapHeader || + parsing == psHttpHeader; + } + + CWCB *isWriting; + IOCB *isReading; + PF *closer; + + enum Parsing { psIcapHeader, psHttpHeader, psBody, psDone } parsing; + } - enum Parsing { psIcapHeader, psHttpHeader, psBody, psDone } parsing; - } state; + state; - Notify notify; + Notify notify; - CBDATA_CLASS2(ICAPXaction); + CBDATA_CLASS2(ICAPXaction); }; // destroys (or pools) the transaction; implemented in ICAPClient.cc (ick?) Index: squid3/src/MemBuf.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/MemBuf.cc,v retrieving revision 1.6.8.4 retrieving revision 1.6.8.5 diff -u -r1.6.8.4 -r1.6.8.5 --- squid3/src/MemBuf.cc 24 Aug 2005 21:26:17 -0000 1.6.8.4 +++ squid3/src/MemBuf.cc 26 Aug 2005 20:28:41 -0000 1.6.8.5 @@ -1,6 +1,6 @@ /* - * $Id: MemBuf.cc,v 1.6.8.4 2005/08/24 21:26:17 dwsquid Exp $ + * $Id: MemBuf.cc,v 1.6.8.5 2005/08/26 20:28:41 dwsquid Exp $ * * DEBUG: section 59 auto-growing Memory Buffer with printf * AUTHOR: Alex Rousskov @@ -157,16 +157,16 @@ { assert(mb); - if (memBufIsNull(mb)) { - // nothing to do - } else { - assert(mb->buf); - assert(!mb->stolen); /* not frozen */ - - memFreeBuf(mb->capacity, mb->buf); - mb->buf = NULL; - mb->size = mb->capacity = mb->max_capacity = 0; - } + if (memBufIsNull(mb)) { + // nothing to do + } else { + assert(mb->buf); + assert(!mb->stolen); /* not frozen */ + + memFreeBuf(mb->capacity, mb->buf); + mb->buf = NULL; + mb->size = mb->capacity = mb->max_capacity = 0; + } } /* cleans the buffer without changing its capacity @@ -201,32 +201,39 @@ return 0; } -mb_size_t MemBuf::spaceSize() const { - const mb_size_t terminatedSize = size + 1; - return (terminatedSize < capacity) ? capacity - terminatedSize : 0; +mb_size_t MemBuf::spaceSize() const +{ + const mb_size_t terminatedSize = size + 1; + return (terminatedSize < capacity) ? capacity - terminatedSize : 0; } -mb_size_t MemBuf::potentialSpaceSize() const { - const mb_size_t terminatedSize = size + 1; - return (terminatedSize < max_capacity) ? max_capacity - terminatedSize : 0; +mb_size_t MemBuf::potentialSpaceSize() const +{ + const mb_size_t terminatedSize = size + 1; + return (terminatedSize < max_capacity) ? max_capacity - terminatedSize : 0; } // removes sz bytes and "packs" by moving content left -void MemBuf::consume(mb_size_t shiftSize) { - const mb_size_t cSize = contentSize(); - assert(0 <= shiftSize && shiftSize <= cSize); - assert(!stolen); /* not frozen */ - //assert(valid); - if (shiftSize > 0) { - if (shiftSize < cSize) - xmemmove(buf, buf + shiftSize, cSize - shiftSize); - size -= shiftSize; - terminate(); - } +void MemBuf::consume(mb_size_t shiftSize) +{ + const mb_size_t cSize = contentSize(); + assert(0 <= shiftSize && shiftSize <= cSize); + assert(!stolen); /* not frozen */ + //assert(valid); + + if (shiftSize > 0) { + if (shiftSize < cSize) + xmemmove(buf, buf + shiftSize, cSize - shiftSize); + + size -= shiftSize; + + terminate(); + } } // calls memcpy, appends exactly size bytes, extends buffer if needed -void MemBuf::append(const char *newContent, mb_size_t sz) { +void MemBuf::append(const char *newContent, mb_size_t sz) +{ assert(sz >= 0); assert(buf); assert(!stolen); /* not frozen */ @@ -239,15 +246,17 @@ assert(size + sz <= capacity); /* paranoid */ xmemcpy(space(), newContent, sz); - appended(sz); - } + + appended(sz); + } } // updates content size after external append -void MemBuf::appended(mb_size_t sz) { - assert(size + sz <= capacity); - size += sz; - terminate(); +void MemBuf::appended(mb_size_t sz) +{ + assert(size + sz <= capacity); + size += sz; + terminate(); } // 0-terminate in case we are used as a string. @@ -255,16 +264,17 @@ // XXX: but the extra octet is counted when growth decisions are made! // This will cause the buffer to grow when spaceSize() == 1 on append, // which will assert() if the buffer cannot grow any more. -void MemBuf::terminate() { - assert(size < capacity); - *space() = '\0'; +void MemBuf::terminate() +{ + assert(size < capacity); + *space() = '\0'; } void memBufAppend(MemBuf * mb, const char *buf, mb_size_t sz) { assert(mb); - mb->append(buf, sz); + mb->append(buf, sz); } /* calls memBufVPrintf */ Index: squid3/src/MemBuf.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/MemBuf.h,v retrieving revision 1.3.16.5 retrieving revision 1.3.16.6 diff -u -r1.3.16.5 -r1.3.16.6 --- squid3/src/MemBuf.h 24 Aug 2005 21:26:17 -0000 1.3.16.5 +++ squid3/src/MemBuf.h 26 Aug 2005 20:28:41 -0000 1.3.16.6 @@ -1,6 +1,6 @@ /* - * $Id: MemBuf.h,v 1.3.16.5 2005/08/24 21:26:17 dwsquid Exp $ + * $Id: MemBuf.h,v 1.3.16.6 2005/08/26 20:28:41 dwsquid Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -44,43 +44,48 @@ _SQUID_INLINE_ MemBuf(); _SQUID_INLINE_ ~MemBuf(); - /* use methods instead of deprecated buf and size members */ + /* use methods instead of deprecated buf and size members */ - char *content() { return buf; } // start of the added data - mb_size_t contentSize() const { return size; } // available data size - bool hasContent() const { return size > 0; } - - // these space-related methods assume no growth and allow 0-termination - char *space() { return buf + size; } // space to add data - mb_size_t spaceSize() const; - bool hasSpace() const { return size+1 < capacity; } - - mb_size_t potentialSpaceSize() const; // accounts for possible growth - bool hasPotentialSpace() const { return potentialSpaceSize() > 0; } - // there is currently no stretch() method to grow without appending - - void consume(mb_size_t sz); // removes sz bytes, moving content left - void append(const char *c, mb_size_t sz); // grows if needed and possible - void appended(mb_size_t sz); // updates content size after external append + char *content() { return buf; } // start of the added data - // XXX: convert global memBuf*() functions into methods + mb_size_t contentSize() const { return size; } // available data size - void terminate(); // zero-terminates the buffer w/o increasing contentSize + bool hasContent() const { return size > 0; } + + // these space-related methods assume no growth and allow 0-termination + char *space() { return buf + size; } // space to add data + + mb_size_t spaceSize() const; + bool hasSpace() const { return size+1 < capacity; } + + mb_size_t potentialSpaceSize() const; // accounts for possible growth + bool hasPotentialSpace() const { return potentialSpaceSize() > 0; } + + // there is currently no stretch() method to grow without appending + + void consume(mb_size_t sz); // removes sz bytes, moving content left + void append(const char *c, mb_size_t sz); // grows if needed and possible + void appended(mb_size_t sz); // updates content size after external append + + // XXX: convert global memBuf*() functions into methods + + void terminate(); // zero-terminates the buffer w/o increasing contentSize public: /* public, read-only, depricated in favor of space*() and content*() */ - // XXX: hide these members completely and remove 0-termination - // so that consume() does not need to memmove all the time + // XXX: hide these members completely and remove 0-termination + // so that consume() does not need to memmove all the time char *buf; // available content mb_size_t size; // used space, does not count 0-terminator /* private, stay away; use interface function instead */ - // XXX: make these private after converting memBuf*() functions to methods + // XXX: make these private after converting memBuf*() functions to methods mb_size_t max_capacity; /* when grows: assert(new_capacity <= max_capacity) */ mb_size_t capacity; /* allocated space */ unsigned stolen: 1; /* the buffer has been stolen for use by someone else */ + unsigned valid: 1; /* to be used for debugging only! */ }; Index: squid3/src/MsgPipe.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/MsgPipe.cc,v retrieving revision 1.1.2.7 retrieving revision 1.1.2.8 diff -u -r1.1.2.7 -r1.1.2.8 --- squid3/src/MsgPipe.cc 25 Aug 2005 20:51:26 -0000 1.1.2.7 +++ squid3/src/MsgPipe.cc 26 Aug 2005 20:28:41 -0000 1.1.2.8 @@ -24,64 +24,66 @@ MsgPipe_MAKE_CALLBACK(SinkAbort, source) -MsgPipe::MsgPipe(const char *aName): name(aName), - data(NULL), source(NULL), sink(NULL) { -} +MsgPipe::MsgPipe(const char *aName): name(aName), + data(NULL), source(NULL), sink(NULL) +{} void MsgPipe::sendSourceStart() { - debug(99,5)("MsgPipe::sendSourceStart() called\n"); - sendLater("SourceStart", &MsgPipe_sendSourceStart, sink); + debug(99,5)("MsgPipe::sendSourceStart() called\n"); + sendLater("SourceStart", &MsgPipe_sendSourceStart, sink); } void MsgPipe::sendSourceProgress() { - debug(99,5)("MsgPipe::sendSourceProgress() called\n"); - sendLater("SourceProgress", &MsgPipe_sendSourceProgress, sink); + debug(99,5)("MsgPipe::sendSourceProgress() called\n"); + sendLater("SourceProgress", &MsgPipe_sendSourceProgress, sink); } void MsgPipe::sendSourceFinish() { - debug(99,5)("MsgPipe::sendSourceFinish() called\n"); - sendLater("sendSourceFinish", &MsgPipe_sendSourceFinish, sink); - source = NULL; + debug(99,5)("MsgPipe::sendSourceFinish() called\n"); + sendLater("sendSourceFinish", &MsgPipe_sendSourceFinish, sink); + source = NULL; } void MsgPipe::sendSourceAbort() { - debug(99,5)("MsgPipe::sendSourceAbort() called\n"); - sendLater("SourceAbort", &MsgPipe_sendSourceAbort, sink); - source = NULL; + debug(99,5)("MsgPipe::sendSourceAbort() called\n"); + sendLater("SourceAbort", &MsgPipe_sendSourceAbort, sink); + source = NULL; } void MsgPipe::sendSinkNeed() { - debug(99,5)("MsgPipe::sendSinkNeed() called\n"); - sendLater("SinkNeed", &MsgPipe_sendSinkNeed, source); + debug(99,5)("MsgPipe::sendSinkNeed() called\n"); + sendLater("SinkNeed", &MsgPipe_sendSinkNeed, source); } void MsgPipe::sendSinkAbort() { - debug(99,5)("MsgPipe::sendSinkAbort() called\n"); - sendLater("SinkAbort", &MsgPipe_sendSinkAbort, source); - sink = NULL; -} - -void MsgPipe::sendLater(const char *callName, EVH * handler, MsgPipeEnd *destination) { - if (canSend(destination, callName, true)) - eventAdd(callName, handler, this, 0, true); -} - -bool MsgPipe::canSend(MsgPipeEnd *destination, const char *callName, bool future) { - const bool res = destination != NULL; - const char *verb = future ? - (res ? "will send " : "wont send ") : - (res ? "sends " : "ignores "); - debugs(99,5, "MsgPipe " << name << "(" << this << ") " << - verb << callName << " to the " << - (destination ? destination->kind() : "destination") << "(" << - destination << "); " << - "data: " << data << "; source: " << source << "; sink " << sink); - return res; + debug(99,5)("MsgPipe::sendSinkAbort() called\n"); + sendLater("SinkAbort", &MsgPipe_sendSinkAbort, source); + sink = NULL; +} + +void MsgPipe::sendLater(const char *callName, EVH * handler, MsgPipeEnd *destination) +{ + if (canSend(destination, callName, true)) + eventAdd(callName, handler, this, 0, true); +} + +bool MsgPipe::canSend(MsgPipeEnd *destination, const char *callName, bool future) +{ + const bool res = destination != NULL; + const char *verb = future ? + (res ? "will send " : "wont send ") : + (res ? "sends " : "ignores "); + debugs(99,5, "MsgPipe " << name << "(" << this << ") " << + verb << callName << " to the " << + (destination ? destination->kind() : "destination") << "(" << + destination << "); " << + "data: " << data << "; source: " << source << "; sink " << sink); + return res; } Index: squid3/src/MsgPipe.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/MsgPipe.h,v retrieving revision 1.1.2.4 retrieving revision 1.1.2.5 diff -u -r1.1.2.4 -r1.1.2.5 --- squid3/src/MsgPipe.h 23 Aug 2005 15:36:54 -0000 1.1.2.4 +++ squid3/src/MsgPipe.h 26 Aug 2005 20:28:41 -0000 1.1.2.5 @@ -1,6 +1,6 @@ /* - * $Id: MsgPipe.h,v 1.1.2.4 2005/08/23 15:36:54 rousskov Exp $ + * $Id: MsgPipe.h,v 1.1.2.5 2005/08/26 20:28:41 dwsquid Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -36,44 +36,49 @@ // MsgPipe is a unidirectional communication channel for asynchronously -// transmitting potentially large messages. It aggregates the message -// being piped and pointers to the message sender and recepient. +// transmitting potentially large messages. It aggregates the message +// being piped and pointers to the message sender and recepient. // MsgPipe also provides convenience wrappers for asynchronous calls to // recepient's and sender's note*() methods. class MsgPipeData; + class MsgPipeEnd; + class MsgPipeSource; + class MsgPipeSink; class MsgPipe { + public: - MsgPipe(const char *aName = "anonym"); + MsgPipe(const char *aName = "anonym"); + + // the pipe source calls these to notify the sink + void sendSourceStart(); + void sendSourceProgress(); + void sendSourceFinish(); + void sendSourceAbort(); + + // the pipe sink calls these to notify the source + void sendSinkNeed(); + void sendSinkAbort(); - // the pipe source calls these to notify the sink - void sendSourceStart(); - void sendSourceProgress(); - void sendSourceFinish(); - void sendSourceAbort(); - - // the pipe sink calls these to notify the source - void sendSinkNeed(); - void sendSinkAbort(); + // private method exposed for the event handler only + bool canSend(MsgPipeEnd *destination, const char *callName, bool future); - // private method exposed for the event handler only - bool canSend(MsgPipeEnd *destination, const char *callName, bool future); public: - const char *name; // unmanaged pointer used for debugging only + const char *name; // unmanaged pointer used for debugging only - MsgPipeData *data; - MsgPipeSource *source; - MsgPipeSink *sink; + MsgPipeData *data; + MsgPipeSource *source; + MsgPipeSink *sink; private: - void sendLater(const char *callName, EVH * handler, MsgPipeEnd *destination); + void sendLater(const char *callName, EVH * handler, MsgPipeEnd *destination); - CBDATA_CLASS2(MsgPipe); + CBDATA_CLASS2(MsgPipe); }; #endif /* SQUID_MSGPIPE_H */ Index: squid3/src/MsgPipeData.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/MsgPipeData.h,v retrieving revision 1.1.2.6 retrieving revision 1.1.2.7 diff -u -r1.1.2.6 -r1.1.2.7 --- squid3/src/MsgPipeData.h 25 Aug 2005 16:39:02 -0000 1.1.2.6 +++ squid3/src/MsgPipeData.h 26 Aug 2005 20:28:41 -0000 1.1.2.7 @@ -1,6 +1,6 @@ /* - * $Id: MsgPipeData.h,v 1.1.2.6 2005/08/25 16:39:02 dwsquid Exp $ + * $Id: MsgPipeData.h,v 1.1.2.7 2005/08/26 20:28:41 dwsquid Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -47,20 +47,22 @@ class MsgPipeData { + public: - MsgPipeData(): header(0), body(0), cause(0) {}; - ~MsgPipeData(); + MsgPipeData(): header(0), body(0), cause(0) {}; + + ~MsgPipeData(); public: - typedef HttpReply Header; - typedef MemBuf Body; + typedef HttpReply Header; + typedef MemBuf Body; - // message being piped - Header *header; // parsed HTTP headers - Body *body; // a buffer for decoded HTTP body piping + // message being piped + Header *header; // parsed HTTP headers + Body *body; // a buffer for decoded HTTP body piping - // HTTP request header for piped responses (the cause of the response) - HttpRequest *cause; + // HTTP request header for piped responses (the cause of the response) + HttpRequest *cause; }; #endif /* SQUID_MSGPIPEDATA_H */ Index: squid3/src/MsgPipeEnd.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/MsgPipeEnd.h,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -u -r1.1.2.1 -r1.1.2.2 --- squid3/src/MsgPipeEnd.h 23 Aug 2005 15:42:29 -0000 1.1.2.1 +++ squid3/src/MsgPipeEnd.h 26 Aug 2005 20:28:41 -0000 1.1.2.2 @@ -1,6 +1,6 @@ /* - * $Id: MsgPipeEnd.h,v 1.1.2.1 2005/08/23 15:42:29 rousskov Exp $ + * $Id: MsgPipeEnd.h,v 1.1.2.2 2005/08/26 20:28:41 dwsquid Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -42,10 +42,11 @@ class MsgPipeEnd: public RefCountable { + public: virtual ~MsgPipeEnd() {} - virtual const char *kind() const = 0; // "sink" or "source", for debugging + virtual const char *kind() const = 0; // "sink" or "source", for debugging }; #endif /* SQUID_MSGPIPEEND_H */ Index: squid3/src/MsgPipeSink.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/MsgPipeSink.h,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -u -r1.1.2.2 -r1.1.2.3 --- squid3/src/MsgPipeSink.h 23 Aug 2005 15:42:29 -0000 1.1.2.2 +++ squid3/src/MsgPipeSink.h 26 Aug 2005 20:28:41 -0000 1.1.2.3 @@ -1,6 +1,6 @@ /* - * $Id: MsgPipeSink.h,v 1.1.2.2 2005/08/23 15:42:29 rousskov Exp $ + * $Id: MsgPipeSink.h,v 1.1.2.3 2005/08/26 20:28:41 dwsquid Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -36,20 +36,21 @@ #include "MsgPipeEnd.h" -// MsgPipeSink is an interface for the recepient of a given message +// MsgPipeSink is an interface for the recepient of a given message // over a given message pipe. Use MsgPipe to call sink methods. class MsgPipe; class MsgPipeSink: public MsgPipeEnd { + public: - virtual void noteSourceStart(MsgPipe *p) = 0; - virtual void noteSourceProgress(MsgPipe *p) = 0; - virtual void noteSourceFinish(MsgPipe *p) = 0; - virtual void noteSourceAbort(MsgPipe *p) = 0; + virtual void noteSourceStart(MsgPipe *p) = 0; + virtual void noteSourceProgress(MsgPipe *p) = 0; + virtual void noteSourceFinish(MsgPipe *p) = 0; + virtual void noteSourceAbort(MsgPipe *p) = 0; - virtual const char *kind() const { return "sink"; } + virtual const char *kind() const { return "sink"; } }; #endif /* SQUID_MSGPIPESINK_H */ Index: squid3/src/MsgPipeSource.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/MsgPipeSource.h,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -u -r1.1.2.2 -r1.1.2.3 --- squid3/src/MsgPipeSource.h 23 Aug 2005 15:42:29 -0000 1.1.2.2 +++ squid3/src/MsgPipeSource.h 26 Aug 2005 20:28:41 -0000 1.1.2.3 @@ -1,6 +1,6 @@ /* - * $Id: MsgPipeSource.h,v 1.1.2.2 2005/08/23 15:42:29 rousskov Exp $ + * $Id: MsgPipeSource.h,v 1.1.2.3 2005/08/26 20:28:41 dwsquid Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -36,18 +36,19 @@ #include "MsgPipeEnd.h" -// MsgPipeSource is an interface for the sender of a given message +// MsgPipeSource is an interface for the sender of a given message // over a given message pipe. Use MsgPipe to call source methods. class MsgPipe; class MsgPipeSource: public MsgPipeEnd { + public: - virtual const char *kind() const { return "source"; } + virtual const char *kind() const { return "source"; } - virtual void noteSinkNeed(MsgPipe *p) = 0; - virtual void noteSinkAbort(MsgPipe *p) = 0; + virtual void noteSinkNeed(MsgPipe *p) = 0; + virtual void noteSinkAbort(MsgPipe *p) = 0; }; #endif /* SQUID_MSGPIPESOURCE_H */ Index: squid3/src/Packer.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Packer.cc,v retrieving revision 1.2.14.1 retrieving revision 1.2.14.2 diff -u -r1.2.14.1 -r1.2.14.2 --- squid3/src/Packer.cc 25 Aug 2005 21:16:24 -0000 1.2.14.1 +++ squid3/src/Packer.cc 26 Aug 2005 20:28:41 -0000 1.2.14.2 @@ -1,6 +1,6 @@ /* - * $Id: Packer.cc,v 1.2.14.1 2005/08/25 21:16:24 rousskov Exp $ + * $Id: Packer.cc,v 1.2.14.2 2005/08/26 20:28:41 dwsquid Exp $ * * DEBUG: section 60 Packer: A uniform interface to store-like modules * AUTHOR: Alex Rousskov @@ -111,7 +111,7 @@ p->append = (append_f) store_append; p->vprintf = (vprintf_f) store_vprintf; p->real_handler = e; - storeBuffer(e); + storeBuffer(e); } /* init with this to accumulate data in MemBuf */ @@ -129,8 +129,9 @@ packerClean(Packer * p) { assert(p); - if (p->append == (append_f) store_append && p->real_handler) - storeBufferFlush(static_cast(p->real_handler)); + + if (p->append == (append_f) store_append && p->real_handler) + storeBufferFlush(static_cast(p->real_handler)); /* it is not really necessary to do this, but, just in case... */ p->append = NULL; Index: squid3/src/Parsing.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Parsing.cc,v retrieving revision 1.1.12.1 retrieving revision 1.1.12.2 diff -u -r1.1.12.1 -r1.1.12.2 --- squid3/src/Parsing.cc 24 Aug 2005 05:47:12 -0000 1.1.12.1 +++ squid3/src/Parsing.cc 26 Aug 2005 20:28:41 -0000 1.1.12.2 @@ -1,6 +1,6 @@ /* - * $Id: Parsing.cc,v 1.1.12.1 2005/08/24 05:47:12 rousskov Exp $ + * $Id: Parsing.cc,v 1.1.12.2 2005/08/26 20:28:41 dwsquid Exp $ * * DEBUG: section 3 Configuration File Parsing * AUTHOR: Harvest Derived @@ -73,16 +73,21 @@ } bool -StringToInt(const char *s, int &result, const char **p, int base) { - if (s) { - char *ptr = 0; - const int h = (int) strtol(s, &ptr, base); - if (ptr != s && ptr) { - result = h; - if (p) - *p = ptr; - return true; - } - } - return false; +StringToInt(const char *s, int &result, const char **p, int base) +{ + if (s) { + char *ptr = 0; + const int h = (int) strtol(s, &ptr, base); + + if (ptr != s && ptr) { + result = h; + + if (p) + *p = ptr; + + return true; + } + } + + return false; } Index: squid3/src/StoreIOBuffer.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/StoreIOBuffer.h,v retrieving revision 1.4.12.2 retrieving revision 1.4.12.3 diff -u -r1.4.12.2 -r1.4.12.3 --- squid3/src/StoreIOBuffer.h 19 Aug 2005 21:58:38 -0000 1.4.12.2 +++ squid3/src/StoreIOBuffer.h 26 Aug 2005 20:28:41 -0000 1.4.12.3 @@ -1,6 +1,6 @@ /* - * $Id: StoreIOBuffer.h,v 1.4.12.2 2005/08/19 21:58:38 dwsquid Exp $ + * $Id: StoreIOBuffer.h,v 1.4.12.3 2005/08/26 20:28:41 dwsquid Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -55,11 +55,11 @@ /* Create a StoreIOBuffer from a MemBuf and offset */ /* NOTE that MemBuf still "owns" the pointers, StoreIOBuffer is just borrowing them */ StoreIOBuffer(MemBuf *aMemBuf, off_t anOffset) : - length(aMemBuf->contentSize()), - offset (anOffset), - data(aMemBuf->content()) + length(aMemBuf->contentSize()), + offset (anOffset), + data(aMemBuf->content()) { - flags.error = 0; + flags.error = 0; } Range range() const @@ -69,8 +69,8 @@ void dump() const { - fwrite(data, length, 1, stderr); - fwrite("\n", 1, 1, stderr); + fwrite(data, length, 1, stderr); + fwrite("\n", 1, 1, stderr); } struct Index: squid3/src/TextException.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/TextException.cc,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -u -r1.1.2.2 -r1.1.2.3 --- squid3/src/TextException.cc 20 Aug 2005 06:18:37 -0000 1.1.2.2 +++ squid3/src/TextException.cc 26 Aug 2005 20:28:41 -0000 1.1.2.3 @@ -2,24 +2,26 @@ #include "TextException.h" TextException::TextException(const char *aMsg, const char *aFileName, int aLineNo): - message(xstrdup(aMsg)), theFileName(aFileName), theLineNo(aLineNo) { -} + message(xstrdup(aMsg)), theFileName(aFileName), theLineNo(aLineNo) +{} -TextException::~TextException() { - xfree(message); +TextException::~TextException() +{ + xfree(message); } -void Throw(const char *message, const char *fileName, int lineNo) { +void Throw(const char *message, const char *fileName, int lineNo) +{ + + // or should we let the exception recepient print the exception instead? - // or should we let the exception recepient print the exception instead? + if (fileName) { + debugs(0, 3, fileName << ':' << lineNo << ": exception" << + (message ? ": " : ".") << (message ? message : "")); + } else { + debugs(0, 3, "exception" << + (message ? ": " : ".") << (message ? message : "")); + } - if (fileName) { - debugs(0, 3, fileName << ':' << lineNo << ": exception" << - (message ? ": " : ".") << (message ? message : "")); - } else { - debugs(0, 3, "exception" << - (message ? ": " : ".") << (message ? message : "")); - } - - throw TextException(message, fileName, lineNo); + throw TextException(message, fileName, lineNo); } Index: squid3/src/TextException.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/TextException.h,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -u -r1.1.2.1 -r1.1.2.2 --- squid3/src/TextException.h 19 Aug 2005 20:18:07 -0000 1.1.2.1 +++ squid3/src/TextException.h 26 Aug 2005 20:28:41 -0000 1.1.2.2 @@ -6,20 +6,23 @@ // simple exception to report custom errors // we may want to change the interface to be able to report system errors -class TextException { - public: - TextException(const char *aMessage, const char *aFileName = 0, int aLineNo = -1); - ~TextException(); - - // ostream &print(ostream &os) const; - - public: - char *message; // read-only - - protected: - // optional location information - const char *theFileName; - int theLineNo; + +class TextException +{ + +public: + TextException(const char *aMessage, const char *aFileName = 0, int aLineNo = -1); + ~TextException(); + + // ostream &print(ostream &os) const; + +public: + char *message; // read-only + +protected: + // optional location information + const char *theFileName; + int theLineNo; }; //inline Index: squid3/src/client_side_reply.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/client_side_reply.cc,v retrieving revision 1.61.2.3 retrieving revision 1.61.2.4 diff -u -r1.61.2.3 -r1.61.2.4 --- squid3/src/client_side_reply.cc 26 Aug 2005 19:09:56 -0000 1.61.2.3 +++ squid3/src/client_side_reply.cc 26 Aug 2005 20:28:41 -0000 1.61.2.4 @@ -1,6 +1,6 @@ /* - * $Id: client_side_reply.cc,v 1.61.2.3 2005/08/26 19:09:56 dwsquid Exp $ + * $Id: client_side_reply.cc,v 1.61.2.4 2005/08/26 20:28:41 dwsquid Exp $ * * DEBUG: section 88 Client-side Reply Routines * AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c) @@ -1943,18 +1943,21 @@ clientStreamInsertHead(&http->client_stream, esiStreamRead, esiProcessStream, esiStreamDetach, esiStreamStatus, NULL); } + #endif #if ICAP_CLIENT_RESPMOD_POSTCACHE - debug(88, 0) ("Enabling ICAP processing for %s\n", http->uri); - clientStreamInsertHead(&http->client_stream, icapclientStreamRead, - icapclientProcessStream, - icapclientStreamDetach, - icapclientStreamStatus, - NULL); + debug(88, 0) ("Enabling ICAP processing for %s\n", http->uri); + + clientStreamInsertHead(&http->client_stream, icapclientStreamRead, + icapclientProcessStream, + icapclientStreamDetach, + icapclientStreamStatus, + NULL); #endif + if (http->request->method == METHOD_HEAD) { /* do not forward body for HEAD replies */ body_size = 0; Index: squid3/src/http.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/http.cc,v retrieving revision 1.49.2.18 retrieving revision 1.49.2.19 diff -u -r1.49.2.18 -r1.49.2.19 --- squid3/src/http.cc 26 Aug 2005 20:18:55 -0000 1.49.2.18 +++ squid3/src/http.cc 26 Aug 2005 20:28:41 -0000 1.49.2.19 @@ -1,6 +1,6 @@ /* - * $Id: http.cc,v 1.49.2.18 2005/08/26 20:18:55 dwsquid Exp $ + * $Id: http.cc,v 1.49.2.19 2005/08/26 20:28:41 dwsquid Exp $ * * DEBUG: section 11 Hypertext Transfer Protocol (HTTP) * AUTHOR: Harvest Derived @@ -100,6 +100,7 @@ if (!memBufIsNull(httpState->reply_hdr)) { memBufClean(httpState->reply_hdr); } + delete httpState->reply_hdr; /* why clean? */ requestUnlink(httpState->request); @@ -706,42 +707,50 @@ memBufAppend(reply_hdr, buf, size); - http_status error = HTTP_STATUS_NONE; - const bool parsed = reply->parse(reply_hdr, eof, &error); + http_status error = HTTP_STATUS_NONE; + + const bool parsed = reply->parse(reply_hdr, eof, &error); - if (!parsed && error > 0) { // unrecoverable parsing error + if (!parsed && error > 0) { // unrecoverable parsing error debugs(11, 3, "httpProcessReplyHeader: Non-HTTP-compliant header: '" << reply_hdr->buf << "'"); flags.headers_parsed = 1; memBufClean(reply_hdr); - // negated result yields http_status + // negated result yields http_status failReply (reply, error); ctx_exit(ctx); return; - } + } + + if (!parsed) { // need more data + assert(!error); + assert(!eof); + // XXX: the comment above says this routine is not incremental, yet + // we are returning without destroying "reply" as if we expect to + // be called again. Benign, leak, or worse? + ctx_exit(ctx); + return; + } + + // parsing success + assert(parsed); + + const size_t hdr_size = reply->hdr_sz; + + assert(0 < hdr_size && hdr_size <= (size_t)size); + + reply_hdr->buf[hdr_size] = '\0'; - if (!parsed) { // need more data - assert(!error); - assert(!eof); - // XXX: the comment above says this routine is not incremental, yet - // we are returning without destroying "reply" as if we expect to - // be called again. Benign, leak, or worse? - ctx_exit(ctx); - return; - } - - // parsing success - assert(parsed); - const size_t hdr_size = reply->hdr_sz; - assert(0 < hdr_size && hdr_size <= (size_t)size); - reply_hdr->buf[hdr_size] = '\0'; + flags.headers_parsed = 1; - flags.headers_parsed = 1; debug(11, 9) ("GOT HTTP REPLY HDR:\n---------\n%s\n----------\n", reply_hdr->buf); keepaliveAccounting(reply); + checkDateSkew(reply); + processSurrogateControl (reply); + /* TODO: IF the reply is a 1.0 reply, AND it has a Connection: Header * Parse the header and remove all referenced headers */ @@ -753,10 +762,10 @@ * from the network. */ if (doIcap() < 0) { - /* - * XXX Maybe instead of an error page we should - * handle the reply normally (without ICAP). - */ + /* + * XXX Maybe instead of an error page we should + * handle the reply normally (without ICAP). + */ ErrorState *err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR); err->xerrno = errno; err->request = requestLink(orig_request); @@ -764,6 +773,7 @@ comm_close(fd); return; } + icap->startRespMod(this, request, reply); #else @@ -820,6 +830,7 @@ #if WIP_FWD_LOG fwdStatus(fwd, s); + #endif /* * If its not a reply that we will re-forward, then @@ -1215,8 +1226,8 @@ debug(11,5)("processReplyData: COMPLETE_NONPERSISTENT_MSG\n"); #if REALLY -// hope we can just use transactionComplete() instead of -// this repeated code. + // hope we can just use transactionComplete() instead of + // this repeated code. /* close the connection ourselves */ /* yes - same as for a complete persistent conn here */ commSetTimeout(fd, -1, NULL, NULL); @@ -1245,30 +1256,34 @@ void HttpStateData::maybeReadData() { - int read_sz = SQUID_TCP_SO_RCVBUF; + int read_sz = SQUID_TCP_SO_RCVBUF; #if ICAP_CLIENT + if (icap) { - /* - * Our ICAP message pipes have a finite size limit. We - * should not read more data from the network than will fit - * into the pipe buffer. If totally full, don't register - * the read handler at all. The ICAP side will call our - * icapSpaceAvailable() method when it has free space again. - */ - int icap_space = icap->potentialSpaceSize(); - if (icap_space < read_sz) - read_sz = icap_space; - /* - * why <2? Because delayAwareRead() won't actually read if - * you ask it to read 1 byte. The delayed read request - * just gets re-queued until the client side drains, then - * the I/O thread hangs. Better to not register any read - * handler until we get a notification from ICAP that - * space is available. - */ - if (read_sz < 2) - return; + /* + * Our ICAP message pipes have a finite size limit. We + * should not read more data from the network than will fit + * into the pipe buffer. If totally full, don't register + * the read handler at all. The ICAP side will call our + * icapSpaceAvailable() method when it has free space again. + */ + int icap_space = icap->potentialSpaceSize(); + + if (icap_space < read_sz) + read_sz = icap_space; + + /* + * why <2? Because delayAwareRead() won't actually read if + * you ask it to read 1 byte. The delayed read request + * just gets re-queued until the client side drains, then + * the I/O thread hangs. Better to not register any read + * handler until we get a notification from ICAP that + * space is available. + */ + if (read_sz < 2) + return; } + #endif if (flags.do_next_read) { flags.do_next_read = 0; @@ -2031,19 +2046,21 @@ void HttpStateData::icapSpaceAvailable() { - debug(11,5)("HttpStateData::icapSpaceAvailable() called\n"); - maybeReadData(); + debug(11,5)("HttpStateData::icapSpaceAvailable() called\n"); + maybeReadData(); } void HttpStateData::takeAdaptedHeaders(HttpReply *rep) { debug(11,5)("HttpStateData::takeAdaptedHeaders() called\n"); + if (!entry->isAccepting()) { - debug(11,5)("\toops, entry is not Accepting!\n"); - icap->ownerAbort(); - return; + debug(11,5)("\toops, entry is not Accepting!\n"); + icap->ownerAbort(); + return; } + storeEntryReplaceObject(entry, rep); /* * After calling storeEntryReplaceObject() we give up control @@ -2062,25 +2079,27 @@ debug(11,5)("\t%d is current offset\n", (int)currentOffset); if (!entry->isAccepting()) { - debug(11,5)("\toops, entry is not Accepting!\n"); - icap->ownerAbort(); - return; + debug(11,5)("\toops, entry is not Accepting!\n"); + icap->ownerAbort(); + return; } entry->write(StoreIOBuffer(buf, currentOffset)); // write everything currentOffset += buf->contentSize(); - buf->consume(buf->contentSize()); // consume everything written + buf->consume(buf->contentSize()); // consume everything written } void HttpStateData::doneAdapting() { debug(11,5)("HttpStateData::doneAdapting() called\n"); + if (!entry->isAccepting()) { - debug(11,5)("\toops, entry is not Accepting!\n"); - icap->ownerAbort(); - return; + debug(11,5)("\toops, entry is not Accepting!\n"); + icap->ownerAbort(); + return; } + fwdComplete(fwd); httpStateFree(-1, this); assert(fd == -1); @@ -2090,18 +2109,20 @@ HttpStateData::abortAdapting() { debug(11,5)("HttpStateData::abortAdapting() called\n"); + if (entry->isEmpty()) { - ErrorState *err; - err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR); - err->request = requestLink((HttpRequest *) request); - err->xerrno = errno; - fwdFail(fwd, err); - flags.do_next_read = 0; + ErrorState *err; + err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR); + err->request = requestLink((HttpRequest *) request); + err->xerrno = errno; + fwdFail(fwd, err); + flags.do_next_read = 0; } else { - fwdComplete(fwd); + fwdComplete(fwd); } + if (fd >= 0) - comm_close(fd); + comm_close(fd); else httpStateFree(fd, this); } Index: squid3/src/http.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/http.h,v retrieving revision 1.11.4.7 retrieving revision 1.11.4.8 diff -u -r1.11.4.7 -r1.11.4.8 --- squid3/src/http.h 25 Aug 2005 20:51:27 -0000 1.11.4.7 +++ squid3/src/http.h 26 Aug 2005 20:28:42 -0000 1.11.4.8 @@ -1,6 +1,6 @@ /* - * $Id: http.h,v 1.11.4.7 2005/08/25 20:51:27 dwsquid Exp $ + * $Id: http.h,v 1.11.4.8 2005/08/26 20:28:42 dwsquid Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -51,6 +51,7 @@ void maybeReadData(); int cacheableReply(); #if ICAP_CLIENT + void takeAdaptedHeaders(HttpReply *); void takeAdaptedBody(MemBuf *); void doneAdapting(); @@ -76,6 +77,7 @@ bool surrogateNoStore; void processSurrogateControl(HttpReply *); #if ICAP_CLIENT + ICAPAnchor *icap; #endif @@ -83,7 +85,7 @@ * getReply() public only because it is called from a static function * as httpState->getReply() */ - const HttpReply * getReply() const { return reply ? reply : entry->getReply(); } +const HttpReply * getReply() const { return reply ? reply : entry->getReply(); } private: /* @@ -106,6 +108,7 @@ void haveParsedReplyHeaders(); void transactionComplete(); #if ICAP_CLIENT + int doIcap(); #endif }; Index: squid3/src/store.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/store.cc,v retrieving revision 1.27.8.4 retrieving revision 1.27.8.5 diff -u -r1.27.8.4 -r1.27.8.5 --- squid3/src/store.cc 26 Aug 2005 20:18:55 -0000 1.27.8.4 +++ squid3/src/store.cc 26 Aug 2005 20:28:42 -0000 1.27.8.5 @@ -1,6 +1,6 @@ /* - * $Id: store.cc,v 1.27.8.4 2005/08/26 20:18:55 dwsquid Exp $ + * $Id: store.cc,v 1.27.8.5 2005/08/26 20:28:42 dwsquid Exp $ * * DEBUG: section 20 Storage Manager * AUTHOR: Harvest Derived @@ -1906,11 +1906,13 @@ bool StoreEntry::isAccepting() const { - if (STORE_PENDING != store_status) - return false; - if (EBIT_TEST(flags, ENTRY_ABORTED)) - return false; - return true; + if (STORE_PENDING != store_status) + return false; + + if (EBIT_TEST(flags, ENTRY_ABORTED)) + return false; + + return true; } /* NullStoreEntry */