]>
Commit | Line | Data |
---|---|---|
bbc27441 AJ |
1 | /* |
2 | * Copyright (C) 1996-2014 The Squid Software Foundation and contributors | |
3 | * | |
4 | * Squid software is distributed under GPLv2+ license and includes | |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
b0469965 | 9 | #ifndef SQUID_COMMCALLS_H |
10 | #define SQUID_COMMCALLS_H | |
11 | ||
882255af AR |
12 | #include "base/AsyncCall.h" |
13 | #include "base/AsyncJobCalls.h" | |
c8407295 | 14 | #include "comm/Flag.h" |
f9b72e0c | 15 | #include "comm/forward.h" |
94bfd31f | 16 | #include "MasterXaction.h" |
b0469965 | 17 | |
18 | /* CommCalls implement AsyncCall interface for comm_* callbacks. | |
19 | * The classes cover two call dialer kinds: | |
20 | * - A C-style call using a function pointer (depricated); | |
21 | * - A C++-style call to an AsyncJob child. | |
8d77a37c AJ |
22 | * and several comm_* callback kinds: |
23 | * - accept (IOACB) | |
24 | * - connect (CNCB) | |
25 | * - I/O (IOCB) | |
26 | * - timeout (CTCB) | |
575d05c4 | 27 | * - close (CLCB) |
a17bf806 AJ |
28 | * and a special callback kind for passing pipe FD, disk FD or fd_table index 'FD' to the handler: |
29 | * - FD passing callback (FDECB) | |
b0469965 | 30 | */ |
31 | ||
449f0115 AJ |
32 | class CommAcceptCbParams; |
33 | typedef void IOACB(const CommAcceptCbParams ¶ms); | |
34 | ||
c8407295 AJ |
35 | typedef void CNCB(const Comm::ConnectionPointer &conn, Comm::Flag status, int xerrno, void *data); |
36 | typedef void IOCB(const Comm::ConnectionPointer &conn, char *, size_t size, Comm::Flag flag, int xerrno, void *data); | |
f9b72e0c | 37 | |
8d77a37c AJ |
38 | class CommTimeoutCbParams; |
39 | typedef void CTCB(const CommTimeoutCbParams ¶ms); | |
40 | ||
575d05c4 AJ |
41 | class CommCloseCbParams; |
42 | typedef void CLCB(const CommCloseCbParams ¶ms); | |
43 | ||
a17bf806 AJ |
44 | class FdeCbParams; |
45 | typedef void FDECB(const FdeCbParams ¶ms); | |
46 | ||
26ac0430 AJ |
47 | /* |
48 | * TODO: When there are no function-pointer-based callbacks left, all | |
49 | * this complexity can be removed. Jobs that need comm services will just | |
50 | * implement CommReader, CommWriter, etc. interfaces and receive calls | |
51 | * using general (not comm-specific) AsyncCall code. For now, we have to | |
52 | * allow the caller to create a callback that comm can modify to set | |
53 | * parameters, which is not trivial when the caller type/kind is not | |
54 | * known to comm and there are many kinds of parameters. | |
55 | */ | |
b0469965 | 56 | |
b0469965 | 57 | /* Comm*CbParams classes below handle callback parameters */ |
58 | ||
59 | // Maintains parameters common to all comm callbacks | |
26ac0430 AJ |
60 | class CommCommonCbParams |
61 | { | |
b0469965 | 62 | public: |
63 | CommCommonCbParams(void *aData); | |
64 | CommCommonCbParams(const CommCommonCbParams ¶ms); | |
65 | ~CommCommonCbParams(); | |
66 | ||
4c3ba68d AR |
67 | /// adjust using the current Comm state; returns false to cancel the call |
68 | // not virtual because callers know dialer type | |
26ac0430 | 69 | bool syncWithComm() { return true; } |
82ec8dfc | 70 | |
b0469965 | 71 | void print(std::ostream &os) const; |
72 | ||
73 | public: | |
74 | void *data; // cbdata-protected | |
3e4bebf8 AJ |
75 | |
76 | /** The connection which this call pertains to. | |
d6d0eb11 AJ |
77 | * - On accept() calls this is the new client connection. |
78 | * - On connect() finished calls this is the newely opened connection. | |
79 | * - On write calls this is the connection just written to. | |
80 | * - On read calls this is the connection just read from. | |
81 | * - On close calls this describes the connection which is now closed. | |
82 | * - On timeouts this is the connection whose operation timed out. | |
c8407295 | 83 | * + NP: timeouts might also return to the connect/read/write handler with Comm::TIMEOUT. |
3e4bebf8 | 84 | */ |
7957e704 | 85 | Comm::ConnectionPointer conn; |
b0469965 | 86 | |
c8407295 | 87 | Comm::Flag flag; ///< comm layer result status. |
4ee57cbe | 88 | int xerrno; ///< The last errno to occur. non-zero if flag is Comm::COMM_ERROR. |
3e4bebf8 | 89 | |
a17bf806 | 90 | int fd; ///< FD which the call was about. Set by the async call creator. |
b0469965 | 91 | private: |
92 | // should not be needed and not yet implemented | |
26ac0430 | 93 | CommCommonCbParams &operator =(const CommCommonCbParams ¶ms); |
b0469965 | 94 | }; |
95 | ||
96 | // accept parameters | |
26ac0430 AJ |
97 | class CommAcceptCbParams: public CommCommonCbParams |
98 | { | |
b0469965 | 99 | public: |
100 | CommAcceptCbParams(void *aData); | |
94bfd31f AJ |
101 | |
102 | void print(std::ostream &os) const; | |
103 | ||
104 | /// Transaction which this call is part of. | |
105 | MasterXaction::Pointer xaction; | |
b0469965 | 106 | }; |
107 | ||
108 | // connect parameters | |
26ac0430 AJ |
109 | class CommConnectCbParams: public CommCommonCbParams |
110 | { | |
b0469965 | 111 | public: |
112 | CommConnectCbParams(void *aData); | |
4c3ba68d AR |
113 | |
114 | bool syncWithComm(); // see CommCommonCbParams::syncWithComm | |
b0469965 | 115 | }; |
116 | ||
117 | // read/write (I/O) parameters | |
26ac0430 AJ |
118 | class CommIoCbParams: public CommCommonCbParams |
119 | { | |
b0469965 | 120 | public: |
121 | CommIoCbParams(void *aData); | |
122 | ||
123 | void print(std::ostream &os) const; | |
4c3ba68d | 124 | bool syncWithComm(); // see CommCommonCbParams::syncWithComm |
b0469965 | 125 | |
126 | public: | |
127 | char *buf; | |
128 | size_t size; | |
129 | }; | |
130 | ||
131 | // close parameters | |
26ac0430 AJ |
132 | class CommCloseCbParams: public CommCommonCbParams |
133 | { | |
b0469965 | 134 | public: |
135 | CommCloseCbParams(void *aData); | |
136 | }; | |
137 | ||
26ac0430 AJ |
138 | class CommTimeoutCbParams: public CommCommonCbParams |
139 | { | |
b0469965 | 140 | public: |
141 | CommTimeoutCbParams(void *aData); | |
142 | }; | |
143 | ||
a17bf806 AJ |
144 | /// Special Calls parameter, for direct use of an FD without a controlling Comm::Connection |
145 | /// This is used for pipe() FD with helpers, and internally by Comm when handling some special FD actions. | |
146 | class FdeCbParams: public CommCommonCbParams | |
147 | { | |
148 | public: | |
149 | FdeCbParams(void *aData); | |
150 | // TODO make this a standalone object with FD value and pointer to fde table entry. | |
151 | // that requires all the existing Comm handlers to be updated first though | |
152 | }; | |
153 | ||
b0469965 | 154 | // Interface to expose comm callback parameters of all comm dialers. |
155 | // GetCommParams() uses this interface to access comm parameters. | |
156 | template <class Params_> | |
26ac0430 AJ |
157 | class CommDialerParamsT |
158 | { | |
b0469965 | 159 | public: |
160 | typedef Params_ Params; | |
161 | CommDialerParamsT(const Params &io): params(io) {} | |
162 | ||
163 | public: | |
164 | Params params; | |
165 | }; | |
166 | ||
167 | // Get comm params of an async comm call | |
168 | template <class Params> | |
26ac0430 AJ |
169 | Params &GetCommParams(AsyncCall::Pointer &call) |
170 | { | |
171 | typedef CommDialerParamsT<Params> DialerParams; | |
b0469965 | 172 | DialerParams *dp = dynamic_cast<DialerParams*>(call->getDialer()); |
173 | assert(dp); | |
174 | return dp->params; | |
175 | } | |
176 | ||
b0469965 | 177 | // All job dialers with comm parameters are merged into one since they |
178 | // all have exactly one callback argument and differ in Params type only | |
179 | template <class C, class Params_> | |
4299f876 | 180 | class CommCbMemFunT: public JobDialer<C>, public CommDialerParamsT<Params_> |
b0469965 | 181 | { |
182 | public: | |
183 | typedef Params_ Params; | |
184 | typedef void (C::*Method)(const Params &io); | |
185 | ||
5f621cd0 | 186 | CommCbMemFunT(const CbcPointer<C> &aJob, Method aMeth): JobDialer<C>(aJob), |
9fed6779 | 187 | CommDialerParamsT<Params_>(aJob->toCbdata()), |
5f621cd0 | 188 | method(aMeth) {} |
b0469965 | 189 | |
26ac0430 | 190 | virtual bool canDial(AsyncCall &c) { |
4299f876 | 191 | return JobDialer<C>::canDial(c) && |
26ac0430 AJ |
192 | this->params.syncWithComm(); |
193 | } | |
4c3ba68d | 194 | |
b0469965 | 195 | virtual void print(std::ostream &os) const { |
26ac0430 AJ |
196 | os << '('; |
197 | this->params.print(os); | |
198 | os << ')'; | |
199 | } | |
b0469965 | 200 | |
201 | public: | |
b0469965 | 202 | Method method; |
203 | ||
204 | protected: | |
4299f876 | 205 | virtual void doDial() { ((&(*this->job))->*method)(this->params); } |
b0469965 | 206 | }; |
207 | ||
b0469965 | 208 | // accept (IOACB) dialer |
209 | class CommAcceptCbPtrFun: public CallDialer, | |
e1381638 | 210 | public CommDialerParamsT<CommAcceptCbParams> |
b0469965 | 211 | { |
212 | public: | |
213 | typedef CommAcceptCbParams Params; | |
b9ddfca2 | 214 | typedef RefCount<CommAcceptCbPtrFun> Pointer; |
b0469965 | 215 | |
216 | CommAcceptCbPtrFun(IOACB *aHandler, const CommAcceptCbParams &aParams); | |
b9ddfca2 | 217 | CommAcceptCbPtrFun(const CommAcceptCbPtrFun &o); |
b0469965 | 218 | |
b9ddfca2 | 219 | void dial(); |
80463bb4 | 220 | |
b0469965 | 221 | virtual void print(std::ostream &os) const; |
222 | ||
223 | public: | |
224 | IOACB *handler; | |
225 | }; | |
226 | ||
227 | // connect (CNCB) dialer | |
228 | class CommConnectCbPtrFun: public CallDialer, | |
e1381638 | 229 | public CommDialerParamsT<CommConnectCbParams> |
b0469965 | 230 | { |
231 | public: | |
232 | typedef CommConnectCbParams Params; | |
233 | ||
234 | CommConnectCbPtrFun(CNCB *aHandler, const Params &aParams); | |
235 | void dial(); | |
236 | ||
237 | virtual void print(std::ostream &os) const; | |
238 | ||
239 | public: | |
240 | CNCB *handler; | |
241 | }; | |
242 | ||
b0469965 | 243 | // read/write (IOCB) dialer |
244 | class CommIoCbPtrFun: public CallDialer, | |
e1381638 | 245 | public CommDialerParamsT<CommIoCbParams> |
b0469965 | 246 | { |
247 | public: | |
248 | typedef CommIoCbParams Params; | |
249 | ||
250 | CommIoCbPtrFun(IOCB *aHandler, const Params &aParams); | |
251 | void dial(); | |
252 | ||
253 | virtual void print(std::ostream &os) const; | |
254 | ||
255 | public: | |
256 | IOCB *handler; | |
257 | }; | |
258 | ||
575d05c4 | 259 | // close (CLCB) dialer |
b0469965 | 260 | class CommCloseCbPtrFun: public CallDialer, |
e1381638 | 261 | public CommDialerParamsT<CommCloseCbParams> |
b0469965 | 262 | { |
263 | public: | |
264 | typedef CommCloseCbParams Params; | |
265 | ||
575d05c4 | 266 | CommCloseCbPtrFun(CLCB *aHandler, const Params &aParams); |
b0469965 | 267 | void dial(); |
268 | ||
269 | virtual void print(std::ostream &os) const; | |
270 | ||
271 | public: | |
575d05c4 | 272 | CLCB *handler; |
b0469965 | 273 | }; |
274 | ||
275 | class CommTimeoutCbPtrFun:public CallDialer, | |
e1381638 | 276 | public CommDialerParamsT<CommTimeoutCbParams> |
b0469965 | 277 | { |
278 | public: | |
279 | typedef CommTimeoutCbParams Params; | |
280 | ||
8d77a37c | 281 | CommTimeoutCbPtrFun(CTCB *aHandler, const Params &aParams); |
b0469965 | 282 | void dial(); |
283 | ||
284 | virtual void print(std::ostream &os) const; | |
285 | ||
286 | public: | |
8d77a37c | 287 | CTCB *handler; |
b0469965 | 288 | }; |
289 | ||
a17bf806 AJ |
290 | /// FD event (FDECB) dialer |
291 | class FdeCbPtrFun: public CallDialer, | |
292 | public CommDialerParamsT<FdeCbParams> | |
293 | { | |
294 | public: | |
295 | typedef FdeCbParams Params; | |
296 | ||
297 | FdeCbPtrFun(FDECB *aHandler, const Params &aParams); | |
298 | void dial(); | |
299 | virtual void print(std::ostream &os) const; | |
300 | ||
301 | public: | |
302 | FDECB *handler; | |
303 | }; | |
304 | ||
b0469965 | 305 | // AsyncCall to comm handlers implemented as global functions. |
306 | // The dialer is one of the Comm*CbPtrFunT above | |
307 | // TODO: Get rid of this class by moving canFire() to canDial() method | |
308 | // of dialers. | |
309 | template <class Dialer> | |
26ac0430 AJ |
310 | class CommCbFunPtrCallT: public AsyncCall |
311 | { | |
b0469965 | 312 | public: |
b9ddfca2 | 313 | typedef RefCount<CommCbFunPtrCallT<Dialer> > Pointer; |
b0469965 | 314 | typedef typename Dialer::Params Params; |
315 | ||
316 | inline CommCbFunPtrCallT(int debugSection, int debugLevel, | |
26ac0430 | 317 | const char *callName, const Dialer &aDialer); |
b0469965 | 318 | |
cbff89ba AJ |
319 | inline CommCbFunPtrCallT(const CommCbFunPtrCallT &o) : |
320 | AsyncCall(o.debugSection, o.debugLevel, o.name), | |
db98b2bd | 321 | dialer(o.dialer) {} |
cbff89ba AJ |
322 | |
323 | ~CommCbFunPtrCallT() {} | |
b9ddfca2 | 324 | |
b0469965 | 325 | virtual CallDialer* getDialer() { return &dialer; } |
326 | ||
327 | public: | |
328 | Dialer dialer; | |
329 | ||
330 | protected: | |
331 | inline virtual bool canFire(); | |
332 | inline virtual void fire(); | |
cbff89ba AJ |
333 | |
334 | private: | |
335 | CommCbFunPtrCallT & operator=(const CommCbFunPtrCallT &); // not defined. not permitted. | |
b0469965 | 336 | }; |
337 | ||
338 | // Conveninece wrapper: It is often easier to call a templated function than | |
339 | // to create a templated class. | |
340 | template <class Dialer> | |
341 | inline | |
342 | CommCbFunPtrCallT<Dialer> *commCbCall(int debugSection, int debugLevel, | |
26ac0430 | 343 | const char *callName, const Dialer &dialer) |
b0469965 | 344 | { |
345 | return new CommCbFunPtrCallT<Dialer>(debugSection, debugLevel, callName, | |
26ac0430 | 346 | dialer); |
b0469965 | 347 | } |
348 | ||
349 | /* inlined implementation of templated methods */ | |
350 | ||
351 | /* CommCbFunPtrCallT */ | |
352 | ||
353 | template <class Dialer> | |
18ec8500 | 354 | CommCbFunPtrCallT<Dialer>::CommCbFunPtrCallT(int aDebugSection, int aDebugLevel, |
26ac0430 | 355 | const char *callName, const Dialer &aDialer): |
18ec8500 | 356 | AsyncCall(aDebugSection, aDebugLevel, callName), |
b0469965 | 357 | dialer(aDialer) |
358 | { | |
359 | } | |
360 | ||
b0469965 | 361 | template <class Dialer> |
362 | bool | |
363 | CommCbFunPtrCallT<Dialer>::canFire() | |
364 | { | |
365 | if (!AsyncCall::canFire()) | |
366 | return false; | |
367 | ||
368 | if (!cbdataReferenceValid(dialer.params.data)) | |
369 | return cancel("callee gone"); | |
370 | ||
4c3ba68d AR |
371 | if (!dialer.params.syncWithComm()) |
372 | return cancel("out of sync w/comm"); | |
373 | ||
870cec0a AR |
374 | if (!dialer.handler) |
375 | return cancel("no callback requested"); | |
376 | ||
b0469965 | 377 | return true; |
378 | } | |
379 | ||
380 | template <class Dialer> | |
381 | void | |
382 | CommCbFunPtrCallT<Dialer>::fire() | |
383 | { | |
384 | dialer.dial(); | |
385 | } | |
386 | ||
387 | #endif /* SQUID_COMMCALLS_H */ |