]>
Commit | Line | Data |
---|---|---|
c99de607 | 1 | #include "squid.h" |
2 | #include "MsgPipe.h" | |
3 | #include "MsgPipeData.h" | |
4 | #include "MsgPipeSource.h" | |
5 | #include "MsgPipeSink.h" | |
6 | #include "HttpRequest.h" | |
7 | #include "ICAPClientVector.h" | |
8 | #include "ICAPClient.h" | |
9 | ||
10 | ICAPClientVector::ICAPClientVector(ICAPServiceRep::Pointer aService, const char *aPoint): | |
11 | theOwner(0), vPoint(aPoint), | |
12 | service(aService), virgin(NULL), adapted(NULL) | |
13 | { | |
14 | debug(93,3)("%s constructed, this=%p\n", vPoint, this); | |
15 | } | |
16 | ||
17 | ICAPClientVector::~ICAPClientVector() | |
18 | { | |
19 | stop(notifyNone); | |
20 | debug(93,3)("%s destructed, this=%p\n", vPoint, this); | |
21 | } | |
22 | ||
23 | void ICAPClientVector::startMod(void *anOwner, HttpRequest *cause, HttpMsg *header) | |
24 | { | |
25 | debug(93,5)("%s starting, this=%p\n", vPoint, this); | |
26 | ||
27 | theOwner = anOwner; | |
28 | ||
29 | virgin = new MsgPipe("virgin"); // this is the place to create a refcount ptr | |
30 | virgin->source = this; | |
31 | virgin->data = new MsgPipeData; | |
32 | virgin->data->setCause(cause); | |
33 | virgin->data->setHeader(header); | |
34 | virgin->data->body = new MemBuf; | |
35 | virgin->data->body->init(ICAP::MsgPipeBufSizeMin, ICAP::MsgPipeBufSizeMax); | |
36 | ||
37 | adapted = new MsgPipe("adapted"); | |
38 | adapted->sink = this; | |
39 | ||
40 | #if ICAP_ANCHOR_LOOPBACK | |
41 | adapted->data = new MsgPipeData; | |
42 | adapted->data->setCause(request); // should not hurt | |
43 | #else | |
44 | ICAPInitXaction(service, virgin, adapted); | |
45 | #endif | |
46 | ||
47 | virgin->sendSourceStart(); // we may have virgin data to provide | |
48 | adapted->sendSinkNeed(); // we want adapted response, eventially | |
49 | } | |
50 | ||
51 | void ICAPClientVector::sendMoreData(StoreIOBuffer buf) | |
52 | { | |
53 | debug(93,7)("%s::sendMoreData(%p)\n", vPoint, this); | |
54 | //debugs(93,0,HERE << "appending " << buf.length << " bytes"); | |
55 | //debugs(93,0,HERE << "body.contentSize = " << virgin->data->body->contentSize()); | |
56 | //buf.dump(); | |
57 | /* | |
58 | * The caller is responsible for not giving us more data | |
59 | * than will fit in body MemBuf. Caller should use | |
60 | * potentialSpaceSize() to find out how much we can hold. | |
61 | */ | |
62 | virgin->data->body->append(buf.data, buf.length); | |
63 | virgin->sendSourceProgress(); | |
64 | } | |
65 | ||
66 | int | |
67 | ICAPClientVector::potentialSpaceSize() | |
68 | { | |
69 | if (virgin == NULL) | |
70 | return 0; | |
71 | ||
72 | return (int) virgin->data->body->potentialSpaceSize(); | |
73 | } | |
74 | ||
75 | // Owner says we have the entire HTTP message | |
76 | void ICAPClientVector::doneSending() | |
77 | { | |
78 | debug(93,3)("%s::doneSending(%p)\n", vPoint, this); | |
79 | ||
80 | #if ICAP_ANCHOR_LOOPBACK | |
81 | /* simple assignments are not the right way to do this */ | |
82 | adapted->data->setHeader(virgin->data->header); | |
83 | adapted->data->body = virgin->data->body; | |
84 | noteSourceFinish(adapted); | |
85 | // checkDoneAdapting() does not support loopback mode | |
86 | return; | |
87 | #else | |
88 | virgin->sendSourceFinish(); | |
89 | checkDoneAdapting(); // may call the owner back, unfortunately | |
90 | #endif | |
91 | } | |
92 | ||
93 | // Owner tells us to abort | |
94 | void ICAPClientVector::ownerAbort() | |
95 | { | |
96 | debug(93,3)("%s::ownerAbort(%p)\n", vPoint, this); | |
97 | stop(notifyIcap); | |
98 | } | |
99 | ||
100 | // ICAP client needs more virgin response data | |
101 | void ICAPClientVector::noteSinkNeed(MsgPipe *p) | |
102 | { | |
103 | debug(93,3)("%s::noteSinkNeed(%p)\n", vPoint, this); | |
104 | ||
105 | if (virgin->data->body->potentialSpaceSize()) | |
106 | tellSpaceAvailable(); | |
107 | } | |
108 | ||
109 | // ICAP client aborting | |
110 | void ICAPClientVector::noteSinkAbort(MsgPipe *p) | |
111 | { | |
112 | debug(93,3)("%s::noteSinkAbort(%p)\n", vPoint, this); | |
113 | stop(notifyOwner); // deletes us | |
114 | } | |
115 | ||
116 | // ICAP client is done sending adapted response | |
117 | void ICAPClientVector::noteSourceFinish(MsgPipe *p) | |
118 | { | |
119 | debug(93,3)("%s::noteSourceFinish(%p)\n", vPoint, this); | |
120 | checkDoneAdapting(); // may delete us | |
121 | } | |
122 | ||
123 | void ICAPClientVector::checkDoneAdapting() { | |
124 | debug(93,5)("%s::checkDoneAdapting(%p): %d & %d\n", vPoint, this, | |
125 | (int)!virgin->source, (int)!adapted->source); | |
126 | // done if we are not sending and are not receiving | |
127 | if (!virgin->source && !adapted->source) | |
128 | tellDoneAdapting(); // deletes us | |
129 | } | |
130 | ||
131 | // ICAP client is aborting | |
132 | void ICAPClientVector::noteSourceAbort(MsgPipe *p) | |
133 | { | |
134 | debug(93,3)("%s::noteSourceAbort(%p)\n", vPoint, this); | |
135 | stop(notifyOwner); // deletes us | |
136 | } | |
137 | ||
138 | void ICAPClientVector::stop(Notify notify) | |
139 | { | |
140 | debug(93,3)("%s::stop(%p, %d)\n", vPoint, this, (int)notify); | |
141 | clean(notify, true); | |
142 | } | |
143 | ||
144 | void ICAPClientVector::clean(Notify notify, bool cleanAdapted) | |
145 | { | |
146 | if (virgin != NULL) { | |
147 | if (notify == notifyIcap) | |
148 | virgin->sendSourceAbort(); | |
149 | else | |
150 | virgin->source = NULL; | |
151 | virgin = NULL; // refcounted | |
152 | } | |
153 | ||
154 | if (cleanAdapted && adapted != NULL) { | |
155 | if (notify == notifyIcap) | |
156 | adapted->sendSinkAbort(); | |
157 | else | |
158 | adapted->sink = NULL; | |
159 | adapted = NULL; // refcounted | |
160 | } | |
161 | ||
162 | service = NULL; | |
163 | ||
164 | if (theOwner) { | |
165 | if (notify == notifyOwner) | |
166 | tellAbortAdapting(); // deletes us | |
167 | else | |
168 | cbdataReferenceDone(theOwner); | |
169 | } | |
170 | ||
171 | // not safe to do anything here because we may have been deleted. | |
172 | } |