Branch data Line data Source code
1 : : // Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
2 : : //
3 : : // Permission to use, copy, modify, and/or distribute this software for any
4 : : // purpose with or without fee is hereby granted, provided that the above
5 : : // copyright notice and this permission notice appear in all copies.
6 : : //
7 : : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
8 : : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9 : : // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
10 : : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11 : : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
12 : : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13 : : // PERFORMANCE OF THIS SOFTWARE.
14 : :
15 : : #ifndef __ASIOLINK_DNS_SERVER_H
16 : : #define __ASIOLINK_DNS_SERVER_H 1
17 : :
18 : : #include <asiolink/io_message.h>
19 : :
20 : : namespace isc {
21 : : namespace asiodns {
22 : :
23 : : /// \brief The \c DNSServer class is a wrapper (and base class) for
24 : : /// classes which provide DNS server functionality.
25 : : ///
26 : : /// The classes derived from this one, \c TCPServer and \c UDPServer,
27 : : /// act as the interface layer between clients sending queries, and
28 : : /// functions defined elsewhere that provide answers to those queries.
29 : : /// Those functions are described in more detail below under
30 : : /// \c SimpleCallback, \c DNSLookup, and \c DNSAnswer.
31 : : ///
32 : : /// Notes to developers:
33 : : /// When constructed, this class (and its derived classes) will have its
34 : : /// "self_" member set to point to "this". Objects of this class (as
35 : : /// instantiated through a base class) are sometimes passed by
36 : : /// reference (as this superclass); calls to methods in the base
37 : : /// class are then rerouted via this pointer to methods in the derived
38 : : /// class. This allows code from outside asiodns, with no specific
39 : : /// knowledge of \c TCPServer or \c UDPServer, to access their methods.
40 : : ///
41 : : /// This class is both assignable and copy-constructable. Its subclasses
42 : : /// use the "stackless coroutine" pattern, meaning that it will copy itself
43 : : /// when "forking", and that instances will be posted as ASIO handler
44 : : /// objects, which are always copied.
45 : : ///
46 : : /// Because these objects are frequently copied, it is recommended
47 : : /// that derived classes be kept small to reduce copy overhead.
48 : 0 : class DNSServer {
49 : : protected:
50 : : ///
51 : : /// \name Constructors and destructors
52 : : ///
53 : : /// This is intentionally defined as \c protected, as this base class
54 : : /// should never be instantiated except as part of a derived class.
55 : : //@{
56 : 163 : DNSServer() {
57 : 248 : self_ = this;
58 : : }
59 : : public:
60 : : /// \brief The destructor
61 : 2134 : virtual ~DNSServer() {}
62 : : //@}
63 : :
64 : : ///
65 : : /// \name Class methods
66 : : ///
67 : : /// These methods all make their calls indirectly via the "self_"
68 : : /// pointer, ensuring that the functions ultimately invoked will be
69 : : /// the ones in the derived class. This makes it possible to pass
70 : : /// instances of derived classes as references to this base class
71 : : /// without losing access to derived class data.
72 : : ///
73 : : //@{
74 : : /// \brief The funtion operator
75 : 0 : virtual void operator()(asio::error_code ec = asio::error_code(),
76 : : size_t length = 0)
77 : : {
78 : 0 : (*self_)(ec, length);
79 : 0 : }
80 : :
81 : : /// \brief Stop current running server
82 : 0 : virtual void stop() { self_->stop();}
83 : :
84 : : /// \brief Resume processing of the server coroutine after an
85 : : /// asynchronous call (e.g., to the DNS Lookup provider) has completed.
86 : : ///
87 : : /// \param done If true, this signals the system there is an answer
88 : : /// to return.
89 : 0 : virtual void resume(const bool done) { self_->resume(done); }
90 : :
91 : : /// \brief Returns a pointer to a clone of this DNSServer object.
92 : : ///
93 : : /// When a \c DNSServer object is copied or assigned, the result will
94 : : /// normally be another \c DNSServer object containing a copy
95 : : /// of the original "self_" pointer. Calling clone() guarantees
96 : : /// that the underlying object is also correctly copied.
97 : : ///
98 : : /// \return A deep copy of this DNSServer object
99 : 0 : virtual DNSServer* clone() { return (self_->clone()); }
100 : : //@}
101 : :
102 : : protected:
103 : : /// \brief Lookup handler object.
104 : : ///
105 : : /// This is a protected class; it can only be instantiated
106 : : /// from within a derived class of \c DNSServer.
107 : : ///
108 : : /// A server object that has received a query creates an instance
109 : : /// of this class and scheudles it on the ASIO service queue
110 : : /// using asio::io_service::post(). When the handler executes, it
111 : : /// calls the asyncLookup() method in the server object to start a
112 : : /// DNS lookup. When the lookup is complete, the server object is
113 : : /// scheduled to resume, again using io_service::post().
114 : : ///
115 : : /// Note that the calling object is copied into the handler object,
116 : : /// not referenced. This is because, once the calling object yields
117 : : /// control to the handler, it falls out of scope and may disappear
118 : : template <typename T>
119 [ + - ][ + - ]: 152 : class AsyncLookup {
[ + - ][ + - ]
[ + - ][ + - ]
120 : : public:
121 : 19 : AsyncLookup(T& caller) : caller_(caller) {}
122 [ # # + - ]: 19 : void operator()() { caller_.asyncLookup(); }
123 : : private:
124 : : T caller_;
125 : : };
126 : :
127 : : /// \brief Carries out a DNS lookup.
128 : : ///
129 : : /// This function calls the \c DNSLookup object specified by the
130 : : /// DNS server when the \c IOService was created, passing along
131 : : /// the details of the query and a pointer back to the current
132 : : /// server object. It is called asynchronously via the AsyncLookup
133 : : /// handler class.
134 : 0 : virtual void asyncLookup() { self_->asyncLookup(); }
135 : :
136 : : private:
137 : : DNSServer* self_;
138 : : };
139 : :
140 : :
141 : : } // namespace asiodns
142 : : } // namespace isc
143 : : #endif // __ASIOLINK_DNS_SERVER_H
|