--------------------- PatchSet 1658 Date: 2005/09/08 20:14:44 Author: dwsquid Branch: squid3-icap Tag: (none) Log: Beginning to add reqmod support Members: src/ICAPAnchor.cc:1.1.2.25->1.1.2.26 src/ICAPClientSideHook.cc:1.1->1.1.2.1 src/ICAPClientSideHook.h:1.1->1.1.2.1 src/Makefile.am:1.60.4.7->1.60.4.8 src/MsgPipe.cc:1.1.2.10->1.1.2.11 Index: squid3/src/ICAPAnchor.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICAPAnchor.cc,v retrieving revision 1.1.2.25 retrieving revision 1.1.2.26 diff -u -r1.1.2.25 -r1.1.2.26 --- squid3/src/ICAPAnchor.cc 8 Sep 2005 07:32:01 -0000 1.1.2.25 +++ squid3/src/ICAPAnchor.cc 8 Sep 2005 20:14:44 -0000 1.1.2.26 @@ -13,7 +13,7 @@ CBDATA_CLASS_INIT(ICAPAnchor); -LeakFinder *leaky = NULL; // new LeakFinder; +extern LeakFinder *leaky; ICAPAnchor::ICAPAnchor(): httpState(NULL), virgin(NULL), adapted(NULL) { --- /dev/null Wed Feb 14 13:33:00 2007 +++ squid3/src/ICAPClientSideHook.cc Wed Feb 14 13:35:00 2007 @@ -0,0 +1,224 @@ +#include "squid.h" +#include "client_side_request.h" +#include "MsgPipe.h" +#include "MsgPipeData.h" +#include "MsgPipeSource.h" +#include "MsgPipeSink.h" +#include "HttpRequest.h" +#include "ICAPClientSideHook.h" +#include "ICAPClient.h" + +#include "LeakFinder.h" + +#define ICAP_CLIENTSIDEHOOK_LOOPBACK 1 + +extern LeakFinder *leaky; + +CBDATA_CLASS_INIT(ICAPClientSideHook); + +ICAPClientSideHook::ICAPClientSideHook(): chr(NULL), virgin(NULL), adapted(NULL) +{ + debug(93,0)("ICAPClientSideHook constructed, this=%p\n", this); +} + +ICAPClientSideHook::~ICAPClientSideHook() +{ + stop(notifyNone); + cbdataReferenceDone(chr); + debug(93,0)("ICAPClientSideHook destructed, this=%p\n", this); + + if (virgin != NULL) + freeVirgin(); + + if (adapted != NULL) + freeAdapted(); +} + +void ICAPClientSideHook::startReqMod(ClientHttpRequest *anChr, HttpRequest *request) +{ + debug(93,0)("ICAPClientSideHook::startReqMod() called\n"); + chr = cbdataReference(anChr); + + virgin = new MsgPipe("virgin"); // this is the place to create a refcount ptr + leakTouch(virgin.getRaw(), leaky); + virgin->source = this; + virgin->data = new MsgPipeData; + virgin->data->cause = NULL; + virgin->data->header = requestLink(request); + virgin->data->body = new MemBuf; + memBufInit(virgin->data->body, ICAPMsgPipeBufSizeMin, ICAPMsgPipeBufSizeMax); + + adapted = new MsgPipe("adapted"); + leakTouch(adapted.getRaw(), leaky); + adapted->sink = this; +#if ICAP_CLIENTSIDEHOOK_LOOPBACK + + adapted->data = new MsgPipeData; + adapted->data->body = new MemBuf; + memBufInit(adapted->data->body, ICAPMsgPipeBufSizeMin, ICAPMsgPipeBufSizeMax); +#else + + ICAPInitXaction(virgin, adapted); +#endif + + virgin->sendSourceStart(); // we may have virgin data to provide + adapted->sendSinkNeed(); // we want adapted response, eventially +} + +void ICAPClientSideHook::sendMoreData(StoreIOBuffer buf) +{ + debug(93,0)("ICAPClientSideHook::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. + */ + leakTouch(virgin.getRaw(), leaky); + virgin->data->body->append(buf.data, buf.length); + virgin->sendSourceProgress(); +} + +int +ICAPClientSideHook::potentialSpaceSize() +{ + if (virgin == NULL) + return 0; + leakTouch(virgin.getRaw(), leaky); + return (int) virgin->data->body->potentialSpaceSize(); +} + +// ClientHttpRequest says we have the entire HTTP message +void ICAPClientSideHook::doneSending() +{ + debug(93,0)("ICAPClientSideHook::doneSending() called\n"); + leakTouch(virgin.getRaw(), leaky); + +#if ICAP_CLIENTSIDEHOOK_LOOPBACK + /* simple assignments are not the right way to do this */ + adapted->data->header = requestLink(static_cast(virgin->data->header)); + adapted->data->body->append(virgin->data->body->content(), virgin->data->body->contentSize()); + noteSourceFinish(adapted.getRaw()); + return; +#else + + virgin->sendSourceFinish(); +#endif +} + +// ClientHttpRequest tells us to abort +void ICAPClientSideHook::ownerAbort() +{ + debug(93,0)("ICAPClientSideHook::ownerAbort() called\n"); + stop(notifyIcap); +} + +// ICAP client needs more virgin response data +void ICAPClientSideHook::noteSinkNeed(MsgPipe *p) +{ + debug(93,0)("ICAPClientSideHook::noteSinkNeed() called\n"); + + leakTouch(virgin.getRaw(), leaky); + + if (virgin->data->body->potentialSpaceSize()) + chr->icapSpaceAvailable(); +} + +// ICAP client aborting +void ICAPClientSideHook::noteSinkAbort(MsgPipe *p) +{ + debug(93,0)("ICAPClientSideHook::noteSinkAbort() called\n"); + stop(notifyOwner); +} + +// ICAP client starts sending adapted response +// ICAP client has received new HTTP headers (if any) at this point +void ICAPClientSideHook::noteSourceStart(MsgPipe *p) +{ + debug(93,0)("ICAPClientSideHook::noteSourceStart() called\n"); + leakTouch(adapted.getRaw(), leaky); + chr->takeAdaptedHeaders(adapted->data->header); + noteSourceProgress(p); +} + +// ICAP client sends more data +void ICAPClientSideHook::noteSourceProgress(MsgPipe *p) +{ + debug(93,0)("ICAPClientSideHook::noteSourceProgress() called\n"); + //tell ClientHttpRequest to store a fresh portion of the adapted response + + leakTouch(p, leaky); + if (p->data->body->hasContent()) { + chr->takeAdaptedBody(p->data->body); + } +} + +// ICAP client is done sending adapted response +void ICAPClientSideHook::noteSourceFinish(MsgPipe *p) +{ + debug(93,0)("ICAPClientSideHook::noteSourceFinish() called\n"); + //tell ClientHttpRequest that we expect no more response data + leakTouch(p, leaky); + chr->doneAdapting(); + stop(notifyNone); +} + +// ICAP client is aborting +void ICAPClientSideHook::noteSourceAbort(MsgPipe *p) +{ + debug(93,0)("ICAPClientSideHook::noteSourceAbort() called\n"); + leakTouch(p, leaky); + stop(notifyOwner); +} + +// internal cleanup +void ICAPClientSideHook::stop(Notify notify) +{ + if (virgin != NULL) { + leakTouch(virgin.getRaw(), leaky); + + if (notify == notifyIcap) + virgin->sendSourceAbort(); + else + virgin->source = NULL; + + freeVirgin(); + } + + if (adapted != NULL) { + leakTouch(adapted.getRaw(), leaky); + + if (notify == notifyIcap) + adapted->sendSinkAbort(); + else + adapted->sink = NULL; + + freeAdapted(); + } + + if (chr) { + if (notify == notifyOwner) + // tell ClientHttpRequest that we are aborting prematurely + chr->abortAdapting(); + + cbdataReferenceDone(chr); + + // chr is now NULL, will not call it any more + } +} + +void ICAPClientSideHook::freeVirgin() +{ + requestUnlink(virgin->data->cause); + virgin->data->cause = NULL; + virgin->data->header = NULL; + leakTouch(virgin.getRaw(), leaky); + virgin = NULL; // refcounted +} + +void ICAPClientSideHook::freeAdapted() +{ + adapted->data->header = NULL; // we don't own it + leakTouch(adapted.getRaw(), leaky); + adapted = NULL; // refcounted +} --- /dev/null Wed Feb 14 13:33:00 2007 +++ squid3/src/ICAPClientSideHook.h Wed Feb 14 13:35:00 2007 @@ -0,0 +1,90 @@ + +/* + * $Id: ICAPClientSideHook.h,v 1.1.2.1 2005/09/08 20:14:45 dwsquid Exp $ + * + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sinks; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#ifndef SQUID_ICAPCLIENTSIDEHOOK_H +#define SQUID_ICAPCLIENTSIDEHOOK_H + +#include "MsgPipe.h" +#include "MsgPipeSource.h" +#include "MsgPipeSink.h" + +/* The ICAP ClientSideHook implements message pipe sink and source interfaces. It + * helps client-side to marshall the incoming/virgin HTTP message (being + * recieved from the HTTP client) to Squid's ICAP client module, using the + * MsgPipe interface. The same interface is used to get the adapted HTTP + * message back from the ICAP client. client-side is the "owner" of the + * ICAPClientSideHook. + */ + +class HttpRequest; + +//class HttpReply; + +class ICAPClientSideHook: public MsgPipeSource, public MsgPipeSink +{ + +public: + ICAPClientSideHook(); + virtual ~ICAPClientSideHook(); + + // synchronous calls called by ClientHttpRequest + void startReqMod(ClientHttpRequest *, HttpRequest *); + 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: + ClientHttpRequest *chr; + MsgPipe::Pointer virgin; + MsgPipe::Pointer adapted; + +private: + typedef enum { notifyNone, notifyOwner, notifyIcap } Notify; + void stop(Notify notify); + void freeVirgin(); + void freeAdapted(); + CBDATA_CLASS2(ICAPClientSideHook); +}; + +#endif /* SQUID_ICAPCLIENTSIDEHOOK_H */ Index: squid3/src/Makefile.am =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Makefile.am,v retrieving revision 1.60.4.7 retrieving revision 1.60.4.8 diff -u -r1.60.4.7 -r1.60.4.8 --- squid3/src/Makefile.am 8 Sep 2005 07:29:41 -0000 1.60.4.7 +++ squid3/src/Makefile.am 8 Sep 2005 20:14:45 -0000 1.60.4.8 @@ -1,7 +1,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.am,v 1.60.4.7 2005/09/08 07:29:41 rousskov Exp $ +# $Id: Makefile.am,v 1.60.4.8 2005/09/08 20:14:45 dwsquid Exp $ # # Uncomment and customize the following to suit your needs: # @@ -95,6 +95,7 @@ ICAP_CLIENT_ALL_SOURCE = \ ChunkedCodingParser.cc \ ICAPAnchor.cc \ + ICAPClientSideHook.cc \ ICAPClient.cc \ ICAPXaction.cc \ ICAPServiceRep.cc \ Index: squid3/src/MsgPipe.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/MsgPipe.cc,v retrieving revision 1.1.2.10 retrieving revision 1.1.2.11 diff -u -r1.1.2.10 -r1.1.2.11 --- squid3/src/MsgPipe.cc 2 Sep 2005 15:23:56 -0000 1.1.2.10 +++ squid3/src/MsgPipe.cc 8 Sep 2005 20:14:45 -0000 1.1.2.11 @@ -5,7 +5,7 @@ #include "MsgPipeData.h" #include "LeakFinder.h" -extern LeakFinder *leaky; +LeakFinder *leaky = new LeakFinder; CBDATA_CLASS_INIT(MsgPipe);