summaryrefslogtreecommitdiffstats
path: root/src/lib/asiodns/io_fetch.h
blob: c31ee092c9f806bd4e86963ea307cbeb480bb9f0 (plain)
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
// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

#ifndef IO_FETCH_H
#define IO_FETCH_H 1

#include <config.h>

#include <boost/shared_array.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>

#include <coroutine.h>

#include <asio/error_code.hpp>
#include <asiolink/io_address.h>
#include <asiolink/io_service.h>

#include <util/buffer.h>
#include <dns/question.h>
#include <dns/message.h>

namespace isc {
namespace asiodns {

// Forward declarations
struct IOFetchData;

/// \brief Upstream Fetch Processing
///
/// IOFetch is the class used to send upstream fetches and to handle responses.
///
/// \param E Endpoint type to use.

class IOFetch : public coroutine {
public:
    /// \brief Protocol to use on the fetch
    enum Protocol {
        UDP = 0,
        TCP = 1
    };

    /// \brief Origin of Asynchronous I/O Call
    ///
    /// Indicates what initiated an asynchronous I/O call and used in deciding
    /// what error message to output if the I/O fails.
    enum Origin {
        NONE = 0,           ///< No asynchronous call outstanding
        OPEN = 1,
        SEND = 2,
        RECEIVE = 3,
        CLOSE = 4
    };

    /// \brief Result of Upstream Fetch
    ///
    /// Note that this applies to the status of I/Os in the fetch - a fetch
    /// that resulted in a packet being received from the server is a SUCCESS,
    /// even if the contents of the packet indicate that some error occurred.
    enum Result {
        SUCCESS = 0,        ///< Success, fetch completed
        TIME_OUT = 1,       ///< Failure, fetch timed out
        STOPPED = 2,        ///< Control code, fetch has been stopped
        NOTSET = 3          ///< For testing, indicates value not set
    };

    // The next enum is a "trick" to allow constants to be defined in a class
    // declaration.

    /// \brief Integer Constants
    enum {
        STAGING_LENGTH = 8192   ///< Size of staging buffer
    };

    /// \brief I/O Fetch Callback
    ///
    /// Class of callback object for when the fetch itself has completed - an
    /// object of this class is passed to the IOFetch constructor and its
    /// operator() method called when the fetch completes.
    ///
    /// Note the difference between the two operator() methods:
    /// - IOFetch::operator() callback is called when an asynchronous I/O has
    ///   completed.
    /// - IOFetch::Callback::operator() is called when an upstream fetch - which
    ///   may have involved several asynchronous I/O operations - has completed.
    ///
    /// This is an abstract class.
    class Callback {
    public:
        /// \brief Default Constructor
        Callback()
        {}

        /// \brief Virtual Destructor
        virtual ~Callback()
        {}

        /// \brief Callback method
        ///
        /// This is the method called when the fetch completes.
        ///
        /// \param result Result of the fetch
        virtual void operator()(Result result) = 0;
    };

    /// \brief Constructor.
    ///
    /// Creates the object that will handle the upstream fetch.
    ///
    /// \param protocol Fetch protocol, either IOFetch::TCP or IOFetch::UDP
    /// \param service I/O Service object to handle the asynchronous
    ///        operations.
    /// \param question DNS question to send to the upstream server.
    /// \param address IP address of upstream server
    /// \param port Port to which to connect on the upstream server
    /// \param buff Output buffer into which the response (in wire format)
    ///        is written (if a response is received).
    /// \param cb Callback object containing the callback to be called when we
    ///        terminate.  The caller is responsible for managing this object
    ///        and deleting it if necessary.
    /// \param wait Timeout for the fetch (in ms).  The default value of
    ///        -1 indicates no timeout.
    /// \param edns true if the request should be EDNS. The default value is
    ///        true.
    IOFetch(Protocol protocol, isc::asiolink::IOService& service,
        const isc::dns::Question& question,
        const isc::asiolink::IOAddress& address,
        uint16_t port, isc::util::OutputBufferPtr& buff, Callback* cb,
        int wait = -1,
        bool edns = true);

    /// \brief Constructor
    ///  This constructor has one parameter "query_message", which
    ///  is the shared_ptr to a full query message. It's different
    ///  with above contructor which has only question section. All
    ///  other parameters are same.
    ///
    /// \param query_message the shared_ptr to a full query message
    ///        got from a query client.
    IOFetch(Protocol protocol, isc::asiolink::IOService& service,
        isc::dns::ConstMessagePtr query_message,
        const isc::asiolink::IOAddress& address,
        uint16_t port, isc::util::OutputBufferPtr& buff, Callback* cb,
        int wait = -1);

    /// \brief Constructor.
    ///
    /// Creates the object that will handle the upstream fetch.
    ///
    /// \param protocol Fetch protocol, either IOFetch::TCP or IOFetch::UDP
    /// \param service I/O Service object to handle the asynchronous
    ///     operations.
    /// \param outpkt Packet to send to upstream server.  Note that the
    ///     QID (first two bytes of the packet) may be altered in the sending.
    /// \param buff Output buffer into which the response (in wire format)
    ///     is written (if a response is received).
    /// \param cb Callback object containing the callback to be called
    ///     when we terminate.  The caller is responsible for managing this
    ///     object and deleting it if necessary.
    /// \param address IP address of upstream server
    /// \param port Port to which to connect on the upstream server
    /// (default = 53)
    /// \param wait Timeout for the fetch (in ms).  The default value of
    ///     -1 indicates no timeout.
    IOFetch(Protocol protocol, isc::asiolink::IOService& service,
        isc::util::OutputBufferPtr& outpkt,
        const isc::asiolink::IOAddress& address,
        uint16_t port, isc::util::OutputBufferPtr& buff, Callback* cb,
        int wait = -1);

    /// \brief Return Current Protocol
    ///
    /// \return Protocol associated with this IOFetch object.
    Protocol getProtocol() const;

    /// \brief Coroutine entry point
    ///
    /// The operator() method is the method in which the coroutine code enters
    /// this object when an operation has been completed.
    ///
    /// \param ec Error code, the result of the last asynchronous I/O operation.
    /// \param length Amount of data received on the last asynchronous read
    void operator()(asio::error_code ec = asio::error_code(), size_t length = 0);

    /// \brief Terminate query
    ///
    /// This method can be called at any point.  It terminates the current
    /// query with the specified reason.
    ///
    /// \param reason Reason for terminating the query
    void stop(Result reason = STOPPED);

private:
    /// \brief IOFetch Initialization Function.
    /// All the parameters are same with the constructor, except
    /// parameter "query_message"
    /// \param query_message the message to be sent out.
    void initIOFetch(isc::dns::MessagePtr& query_message, Protocol protocol,
            isc::asiolink::IOService& service, const isc::dns::Question& question,
            const isc::asiolink::IOAddress& address, uint16_t port,
            isc::util::OutputBufferPtr& buff, Callback* cb, int wait,
            bool edns = true);

    /// \brief Log I/O Failure
    ///
    /// Records an I/O failure to the log file
    ///
    /// \param ec ASIO error code
    void logIOFailure(asio::error_code ec);

    // Member variables.  All data is in a structure pointed to by a shared
    // pointer.  The IOFetch object is copied a number of times during its
    // life, and only requiring a pointer to be copied reduces overhead.
    boost::shared_ptr<IOFetchData>  data_;   ///< Private data

};

} // namespace asiodns
} // namespace isc

#endif // IO_FETCH_H