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 __TCP_SERVER_H
16 : : #define __TCP_SERVER_H 1
17 : :
18 : : #ifndef ASIO_HPP
19 : : #error "asio.hpp must be included before including this, see asiolink.h as to why"
20 : : #endif
21 : :
22 : : #include <boost/shared_array.hpp>
23 : : #include <boost/shared_ptr.hpp>
24 : :
25 : : #include <asiolink/asiolink.h>
26 : : #include <coroutine.h>
27 : : #include "dns_server.h"
28 : : #include "dns_lookup.h"
29 : : #include "dns_answer.h"
30 : :
31 : : namespace isc {
32 : : namespace asiodns {
33 : :
34 : : /// \brief A TCP-specific \c DNSServer object.
35 : : ///
36 : : /// This class inherits from both \c DNSServer and from \c coroutine,
37 : : /// defined in coroutine.h.
38 : 2570 : class TCPServer : public virtual DNSServer, public virtual coroutine {
39 : : public:
40 : : /// \brief Constructor
41 : : /// \param io_service the asio::io_service to work with
42 : : /// \param fd the file descriptor of opened TCP socket
43 : : /// \param af address family of the socket, either AF_INET or AF_INET6
44 : : /// \param checkin the callbackprovider for non-DNS events
45 : : /// \param lookup the callbackprovider for DNS lookup events
46 : : /// \param answer the callbackprovider for DNS answer events
47 : : /// \throw isc::InvalidParameter if af is neither AF_INET nor AF_INET6
48 : : /// \throw isc::asiolink::IOError when a low-level error happens, like the
49 : : /// fd is not a valid descriptor or it can't be listened on.
50 : : TCPServer(asio::io_service& io_service, int fd, int af,
51 : : const isc::asiolink::SimpleCallback* checkin = NULL,
52 : : const DNSLookup* lookup = NULL, const DNSAnswer* answer = NULL);
53 : :
54 : : void operator()(asio::error_code ec = asio::error_code(),
55 : : size_t length = 0);
56 : : void asyncLookup();
57 : : void stop();
58 : : void resume(const bool done);
59 : 0 : DNSServer* clone() {
60 : 0 : TCPServer* s = new TCPServer(*this);
61 [ # # ][ # # ]: 0 : return (s);
62 : : }
63 : :
64 : : private:
65 : : enum { MAX_LENGTH = 65535 };
66 : : static const size_t TCP_MESSAGE_LENGTHSIZE = 2;
67 : :
68 : : // The ASIO service object
69 : : asio::io_service& io_;
70 : :
71 : : // Class member variables which are dynamic, and changes to which
72 : : // need to accessible from both sides of a coroutine fork or from
73 : : // outside of the coroutine (i.e., from an asynchronous I/O call),
74 : : // should be declared here as pointers and allocated in the
75 : : // constructor or in the coroutine. This allows state information
76 : : // to persist when an individual copy of the coroutine falls out
77 : : // scope while waiting for an event, *so long as* there is another
78 : : // object that is referencing the same data. As a side-benefit, using
79 : : // pointers also reduces copy overhead for coroutine objects.
80 : : //
81 : : // Note: Currently these objects are allocated by "new" in the
82 : : // constructor, or in the function operator while processing a query.
83 : : // Repeated allocations from the heap for every incoming query is
84 : : // clearly a performance issue; this must be optimized in the future.
85 : : // The plan is to have a structure pre-allocate several "server state"
86 : : // objects which can be pulled off a free list and placed on an in-use
87 : : // list whenever a query comes in. This will serve the dual purpose
88 : : // of improving performance and guaranteeing that state information
89 : : // will *not* be destroyed when any one instance of the coroutine
90 : : // falls out of scope while waiting for an event.
91 : : //
92 : : // An ASIO acceptor object to handle new connections. Created in
93 : : // the constructor.
94 : : boost::shared_ptr<asio::ip::tcp::acceptor> acceptor_;
95 : :
96 : : // Socket used to for listen for queries. Created in the
97 : : // constructor and stored in a shared_ptr because socket objects
98 : : // are not copyable.
99 : : boost::shared_ptr<asio::ip::tcp::socket> socket_;
100 : :
101 : : // The buffer into which the response is written
102 : : boost::shared_ptr<isc::util::OutputBuffer> respbuf_;
103 : :
104 : : // \c IOMessage and \c Message objects to be passed to the
105 : : // DNS lookup and answer providers
106 : : boost::shared_ptr<isc::asiolink::IOMessage> io_message_;
107 : : isc::dns::MessagePtr query_message_;
108 : : isc::dns::MessagePtr answer_message_;
109 : :
110 : : // The buffer into which the query packet is written
111 : : boost::shared_array<char>data_;
112 : :
113 : : // State information that is entirely internal to a given instance
114 : : // of the coroutine can be declared here.
115 : : size_t bytes_;
116 : : bool done_;
117 : :
118 : : // Callback functions provided by the caller
119 : : const isc::asiolink::SimpleCallback* checkin_callback_;
120 : : const DNSLookup* lookup_callback_;
121 : : const DNSAnswer* answer_callback_;
122 : :
123 : : boost::shared_ptr<isc::asiolink::IOEndpoint> peer_;
124 : : boost::shared_ptr<isc::asiolink::IOSocket> iosock_;
125 : : };
126 : :
127 : : } // namespace asiodns
128 : : } // namespace isc
129 : : #endif // __TCP_SERVER_H
|