123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- // Copyright (C) 2011 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 __ASIOLINK_DNS_SERVER_H
- #define __ASIOLINK_DNS_SERVER_H 1
- #include <asiolink/io_message.h>
- namespace asiolink {
- /// \brief The \c DNSServer class is a wrapper (and base class) for
- /// classes which provide DNS server functionality.
- ///
- /// The classes derived from this one, \c TCPServer and \c UDPServer,
- /// act as the interface layer between clients sending queries, and
- /// functions defined elsewhere that provide answers to those queries.
- /// Those functions are described in more detail below under
- /// \c SimpleCallback, \c DNSLookup, and \c DNSAnswer.
- ///
- /// Notes to developers:
- /// When constructed, this class (and its derived classes) will have its
- /// "self_" member set to point to "this". Objects of this class (as
- /// instantiated through a base class) are sometimes passed by
- /// reference (as this superclass); calls to methods in the base
- /// class are then rerouted via this pointer to methods in the derived
- /// class. This allows code from outside asiolink, with no specific
- /// knowledge of \c TCPServer or \c UDPServer, to access their methods.
- ///
- /// This class is both assignable and copy-constructable. Its subclasses
- /// use the "stackless coroutine" pattern, meaning that it will copy itself
- /// when "forking", and that instances will be posted as ASIO handler
- /// objects, which are always copied.
- ///
- /// Because these objects are frequently copied, it is recommended
- /// that derived classes be kept small to reduce copy overhead.
- class DNSServer {
- protected:
- ///
- /// \name Constructors and destructors
- ///
- /// This is intentionally defined as \c protected, as this base class
- /// should never be instantiated except as part of a derived class.
- //@{
- DNSServer() : self_(this) {}
- public:
- /// \brief The destructor
- virtual ~DNSServer() {}
- //@}
- ///
- /// \name Class methods
- ///
- /// These methods all make their calls indirectly via the "self_"
- /// pointer, ensuring that the functions ultimately invoked will be
- /// the ones in the derived class. This makes it possible to pass
- /// instances of derived classes as references to this base class
- /// without losing access to derived class data.
- ///
- //@{
- /// \brief The funtion operator
- virtual void operator()(asio::error_code ec = asio::error_code(),
- size_t length = 0)
- {
- (*self_)(ec, length);
- }
- /// \brief Stop current running server
- virtual void stop() { self_->stop();}
- /// \brief Resume processing of the server coroutine after an
- /// asynchronous call (e.g., to the DNS Lookup provider) has completed.
- ///
- /// \param done If true, this signals the system there is an answer
- /// to return.
- virtual void resume(const bool done) { self_->resume(done); }
- /// \brief Indicate whether the server is able to send an answer
- /// to a query.
- ///
- /// This is presently used only for testing purposes.
- virtual bool hasAnswer() { return (self_->hasAnswer()); }
- /// \brief Returns the current value of the 'coroutine' object
- ///
- /// This is a temporary method, intended to be used for debugging
- /// purposes during development and removed later. It allows
- /// callers from outside the coroutine object to retrieve information
- /// about its current state.
- ///
- /// \return The value of the 'coroutine' object
- virtual int value() { return (self_->value()); }
- /// \brief Returns a pointer to a clone of this DNSServer object.
- ///
- /// When a \c DNSServer object is copied or assigned, the result will
- /// normally be another \c DNSServer object containing a copy
- /// of the original "self_" pointer. Calling clone() guarantees
- /// that the underlying object is also correctly copied.
- ///
- /// \return A deep copy of this DNSServer object
- virtual DNSServer* clone() { return (self_->clone()); }
- //@}
- protected:
- /// \brief Lookup handler object.
- ///
- /// This is a protected class; it can only be instantiated
- /// from within a derived class of \c DNSServer.
- ///
- /// A server object that has received a query creates an instance
- /// of this class and scheudles it on the ASIO service queue
- /// using asio::io_service::post(). When the handler executes, it
- /// calls the asyncLookup() method in the server object to start a
- /// DNS lookup. When the lookup is complete, the server object is
- /// scheduled to resume, again using io_service::post().
- ///
- /// Note that the calling object is copied into the handler object,
- /// not referenced. This is because, once the calling object yields
- /// control to the handler, it falls out of scope and may disappear
- template <typename T>
- class AsyncLookup {
- public:
- AsyncLookup(T& caller) : caller_(caller) {}
- void operator()() { caller_.asyncLookup(); }
- private:
- T caller_;
- };
- /// \brief Carries out a DNS lookup.
- ///
- /// This function calls the \c DNSLookup object specified by the
- /// DNS server when the \c IOService was created, passing along
- /// the details of the query and a pointer back to the current
- /// server object. It is called asynchronously via the AsyncLookup
- /// handler class.
- virtual void asyncLookup() { self_->asyncLookup(); }
- private:
- DNSServer* self_;
- };
- } // asiolink
- #endif // __ASIOLINK_DNS_SERVER_H
|