~ubuntu-branches/ubuntu/oneiric/squid3/oneiric-security

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
/*
 * $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 &params);
    ~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 &params);
};

// 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 Params_>
class CommDialerParamsT
{
public:
    typedef Params_ Params;
    CommDialerParamsT(const Params &io): params(io) {}

public:
    Params params;
};

// Get comm params of an async comm call
template <class Params>
Params &GetCommParams(AsyncCall::Pointer &call)
{
    typedef CommDialerParamsT<Params> DialerParams;
    DialerParams *dp = dynamic_cast<DialerParams*>(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 C, class Params_>
class CommCbMemFunT: public JobDialer<C>, public CommDialerParamsT<Params_>
{
public:
    typedef Params_ Params;
    typedef void (C::*Method)(const Params &io);

    CommCbMemFunT(const CbcPointer<C> &job, Method meth): JobDialer<C>(job),
            CommDialerParamsT<Params_>(job.get()),
            method(meth) {}

    virtual bool canDial(AsyncCall &c) {
        return JobDialer<C>::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<CommAcceptCbParams>
{
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<CommConnectCbParams>
{
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<CommIoCbParams>
{
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<CommCloseCbParams>
{
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<CommTimeoutCbParams>
{
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 Dialer>
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 <class Dialer>
inline
CommCbFunPtrCallT<Dialer> *commCbCall(int debugSection, int debugLevel,
                                      const char *callName, const Dialer &dialer)
{
    return new CommCbFunPtrCallT<Dialer>(debugSection, debugLevel, callName,
                                         dialer);
}

/* inlined implementation of templated methods */

/* CommCbFunPtrCallT */

template <class Dialer>
CommCbFunPtrCallT<Dialer>::CommCbFunPtrCallT(int aDebugSection, int aDebugLevel,
        const char *callName, const Dialer &aDialer):
        AsyncCall(aDebugSection, aDebugLevel, callName),
        dialer(aDialer)
{
}


template <class Dialer>
bool
CommCbFunPtrCallT<Dialer>::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 <class Dialer>
void
CommCbFunPtrCallT<Dialer>::fire()
{
    dialer.dial();
}

#endif /* SQUID_COMMCALLS_H */