/* * $Id$ */ #ifndef SQUID_COMMCALLS_H #define SQUID_COMMCALLS_H #include "comm.h" #include "ConnectionDetail.h" #include "DnsLookupDetails.h" #include "base/AsyncCall.h" #include "base/AsyncJobCalls.h" /* CommCalls implement AsyncCall interface for comm_* callbacks. * The classes cover two call dialer kinds: * - A C-style call using a function pointer (depricated); * - A C++-style call to an AsyncJob child. * and three comm_* callback kinds: * - accept (IOACB), * - connect (CNCB), * - I/O (IOCB). */ /* * TODO: When there are no function-pointer-based callbacks left, all * this complexity can be removed. Jobs that need comm services will just * implement CommReader, CommWriter, etc. interfaces and receive calls * using general (not comm-specific) AsyncCall code. For now, we have to * allow the caller to create a callback that comm can modify to set * parameters, which is not trivial when the caller type/kind is not * known to comm and there are many kinds of parameters. */ /* Comm*CbParams classes below handle callback parameters */ // Maintains parameters common to all comm callbacks class CommCommonCbParams { public: CommCommonCbParams(void *aData); CommCommonCbParams(const CommCommonCbParams ¶ms); ~CommCommonCbParams(); /// adjust using the current Comm state; returns false to cancel the call // not virtual because callers know dialer type bool syncWithComm() { return true; } void print(std::ostream &os) const; public: void *data; // cbdata-protected int fd; int xerrno; comm_err_t flag; private: // should not be needed and not yet implemented CommCommonCbParams &operator =(const CommCommonCbParams ¶ms); }; // accept parameters class CommAcceptCbParams: public CommCommonCbParams { public: CommAcceptCbParams(void *aData); void print(std::ostream &os) const; public: ConnectionDetail details; int nfd; // TODO: rename to fdNew or somesuch }; // connect parameters class CommConnectCbParams: public CommCommonCbParams { public: CommConnectCbParams(void *aData); bool syncWithComm(); // see CommCommonCbParams::syncWithComm void print(std::ostream &os) const; public: DnsLookupDetails dns; }; // read/write (I/O) parameters class CommIoCbParams: public CommCommonCbParams { public: CommIoCbParams(void *aData); void print(std::ostream &os) const; bool syncWithComm(); // see CommCommonCbParams::syncWithComm public: char *buf; size_t size; }; // close parameters class CommCloseCbParams: public CommCommonCbParams { public: CommCloseCbParams(void *aData); }; class CommTimeoutCbParams: public CommCommonCbParams { public: CommTimeoutCbParams(void *aData); }; // Interface to expose comm callback parameters of all comm dialers. // GetCommParams() uses this interface to access comm parameters. template class CommDialerParamsT { public: typedef Params_ Params; CommDialerParamsT(const Params &io): params(io) {} public: Params params; }; // Get comm params of an async comm call template Params &GetCommParams(AsyncCall::Pointer &call) { typedef CommDialerParamsT DialerParams; DialerParams *dp = dynamic_cast(call->getDialer()); assert(dp); return dp->params; } // All job dialers with comm parameters are merged into one since they // all have exactly one callback argument and differ in Params type only template class CommCbMemFunT: public JobDialer, public CommDialerParamsT { public: typedef Params_ Params; typedef void (C::*Method)(const Params &io); CommCbMemFunT(const CbcPointer &job, Method meth): JobDialer(job), CommDialerParamsT(job.get()), method(meth) {} virtual bool canDial(AsyncCall &c) { return JobDialer::canDial(c) && this->params.syncWithComm(); } virtual void print(std::ostream &os) const { os << '('; this->params.print(os); os << ')'; } public: Method method; protected: virtual void doDial() { ((&(*this->job))->*method)(this->params); } }; // accept (IOACB) dialer class CommAcceptCbPtrFun: public CallDialer, public CommDialerParamsT { public: typedef CommAcceptCbParams Params; CommAcceptCbPtrFun(IOACB *aHandler, const CommAcceptCbParams &aParams); void dial(); virtual void print(std::ostream &os) const; public: IOACB *handler; }; // connect (CNCB) dialer class CommConnectCbPtrFun: public CallDialer, public CommDialerParamsT { public: typedef CommConnectCbParams Params; CommConnectCbPtrFun(CNCB *aHandler, const Params &aParams); void dial(); virtual void print(std::ostream &os) const; public: CNCB *handler; }; // read/write (IOCB) dialer class CommIoCbPtrFun: public CallDialer, public CommDialerParamsT { public: typedef CommIoCbParams Params; CommIoCbPtrFun(IOCB *aHandler, const Params &aParams); void dial(); virtual void print(std::ostream &os) const; public: IOCB *handler; }; // close (PF) dialer class CommCloseCbPtrFun: public CallDialer, public CommDialerParamsT { public: typedef CommCloseCbParams Params; CommCloseCbPtrFun(PF *aHandler, const Params &aParams); void dial(); virtual void print(std::ostream &os) const; public: PF *handler; }; class CommTimeoutCbPtrFun:public CallDialer, public CommDialerParamsT { public: typedef CommTimeoutCbParams Params; CommTimeoutCbPtrFun(PF *aHandler, const Params &aParams); void dial(); virtual void print(std::ostream &os) const; public: PF *handler; }; // AsyncCall to comm handlers implemented as global functions. // The dialer is one of the Comm*CbPtrFunT above // TODO: Get rid of this class by moving canFire() to canDial() method // of dialers. template class CommCbFunPtrCallT: public AsyncCall { public: typedef typename Dialer::Params Params; inline CommCbFunPtrCallT(int debugSection, int debugLevel, const char *callName, const Dialer &aDialer); virtual CallDialer* getDialer() { return &dialer; } public: Dialer dialer; protected: inline virtual bool canFire(); inline virtual void fire(); }; // Conveninece wrapper: It is often easier to call a templated function than // to create a templated class. template inline CommCbFunPtrCallT *commCbCall(int debugSection, int debugLevel, const char *callName, const Dialer &dialer) { return new CommCbFunPtrCallT(debugSection, debugLevel, callName, dialer); } /* inlined implementation of templated methods */ /* CommCbFunPtrCallT */ template CommCbFunPtrCallT::CommCbFunPtrCallT(int aDebugSection, int aDebugLevel, const char *callName, const Dialer &aDialer): AsyncCall(aDebugSection, aDebugLevel, callName), dialer(aDialer) { } template bool CommCbFunPtrCallT::canFire() { if (!AsyncCall::canFire()) return false; if (!cbdataReferenceValid(dialer.params.data)) return cancel("callee gone"); if (!dialer.params.syncWithComm()) return cancel("out of sync w/comm"); if (!dialer.handler) return cancel("no callback requested"); return true; } template void CommCbFunPtrCallT::fire() { dialer.dial(); } #endif /* SQUID_COMMCALLS_H */