123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- // 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.
- // $Id$
- #include <config.h>
- #include <unistd.h> // for some IPC/network system calls
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <asio.hpp>
- #include <boost/lexical_cast.hpp>
- #include <boost/bind.hpp>
- #include <boost/shared_ptr.hpp>
- #include <dns/buffer.h>
- #include <dns/message.h>
- #include <asiolink/asiolink.h>
- #include <asiolink/internal/tcpdns.h>
- #include <asiolink/internal/udpdns.h>
- using namespace asio;
- using asio::ip::udp;
- using asio::ip::tcp;
- using namespace std;
- using namespace isc::dns;
- namespace asiolink {
- class IOServiceImpl {
- private:
- IOServiceImpl(const IOService& source);
- IOServiceImpl& operator=(const IOService& source);
- public:
- /// \brief The constructor
- IOServiceImpl() : io_service_() {};
- /// \brief The destructor.
- ~IOServiceImpl() {};
- //@}
- /// \brief Start the underlying event loop.
- ///
- /// This method does not return control to the caller until
- /// the \c stop() method is called via some handler.
- void run() { io_service_.run(); };
- /// \brief Run the underlying event loop for a single event.
- ///
- /// This method return control to the caller as soon as the
- /// first handler has completed. (If no handlers are ready when
- /// it is run, it will block until one is.)
- void run_one() { io_service_.run_one();} ;
- /// \brief Stop the underlying event loop.
- ///
- /// This will return the control to the caller of the \c run() method.
- void stop() { io_service_.stop();} ;
- /// \brief Return the native \c io_service object used in this wrapper.
- ///
- /// This is a short term work around to support other BIND 10 modules
- /// that share the same \c io_service with the authoritative server.
- /// It will eventually be removed once the wrapper interface is
- /// generalized.
- asio::io_service& get_io_service() { return io_service_; };
- private:
- asio::io_service io_service_;
- };
- IOService::IOService() {
- io_impl_ = new IOServiceImpl();
- }
- IOService::~IOService() {
- delete io_impl_;
- }
- void
- IOService::run() {
- io_impl_->run();
- }
- void
- IOService::run_one() {
- io_impl_->run_one();
- }
- void
- IOService::stop() {
- io_impl_->stop();
- }
- asio::io_service&
- IOService::get_io_service() {
- return (io_impl_->get_io_service());
- }
- class DNSServiceImpl {
- public:
- DNSServiceImpl(IOService& io_service, const char& port,
- const ip::address* v4addr, const ip::address* v6addr,
- SimpleCallback* checkin, DNSLookup* lookup,
- DNSAnswer* answer);
- //asio::io_service io_service_;
- void stop();
- typedef boost::shared_ptr<UDPServer> UDPServerPtr;
- typedef boost::shared_ptr<TCPServer> TCPServerPtr;
- UDPServerPtr udp4_server_;
- UDPServerPtr udp6_server_;
- TCPServerPtr tcp4_server_;
- TCPServerPtr tcp6_server_;
- };
- DNSServiceImpl::DNSServiceImpl(IOService& io_service_,
- const char& port,
- const ip::address* const v4addr,
- const ip::address* const v6addr,
- SimpleCallback* checkin,
- DNSLookup* lookup,
- DNSAnswer* answer) :
- udp4_server_(UDPServerPtr()), udp6_server_(UDPServerPtr()),
- tcp4_server_(TCPServerPtr()), tcp6_server_(TCPServerPtr())
- {
- uint16_t portnum;
- try {
- // XXX: SunStudio with stlport4 doesn't reject some invalid
- // representation such as "-1" by lexical_cast<uint16_t>, so
- // we convert it into a signed integer of a larger size and perform
- // range check ourselves.
- const int32_t portnum32 = boost::lexical_cast<int32_t>(&port);
- if (portnum32 < 0 || portnum32 > 65535) {
- isc_throw(IOError, "Invalid port number '" << &port);
- }
- portnum = portnum32;
- } catch (const boost::bad_lexical_cast& ex) {
- isc_throw(IOError, "Invalid port number '" << &port << "': " <<
- ex.what());
- }
- try {
- if (v4addr != NULL) {
- udp4_server_ = UDPServerPtr(new UDPServer(io_service_.get_io_service(),
- *v4addr, portnum,
- checkin, lookup, answer));
- (*udp4_server_)();
- tcp4_server_ = TCPServerPtr(new TCPServer(io_service_.get_io_service(),
- *v4addr, portnum,
- checkin, lookup, answer));
- (*tcp4_server_)();
- }
- if (v6addr != NULL) {
- udp6_server_ = UDPServerPtr(new UDPServer(io_service_.get_io_service(),
- *v6addr, portnum,
- checkin, lookup, answer));
- (*udp6_server_)();
- tcp6_server_ = TCPServerPtr(new TCPServer(io_service_.get_io_service(),
- *v6addr, portnum,
- checkin, lookup, answer));
- (*tcp6_server_)();
- }
- } catch (const asio::system_error& err) {
- // We need to catch and convert any ASIO level exceptions.
- // This can happen for unavailable address, binding a privilege port
- // without the privilege, etc.
- isc_throw(IOError, "Failed to initialize network servers: " <<
- err.what());
- }
- }
- DNSService::DNSService(IOService& io_service,
- const char& port, const char& address,
- SimpleCallback* checkin,
- DNSLookup* lookup,
- DNSAnswer* answer) :
- impl_(NULL), io_service_(io_service)
- {
- error_code err;
- const ip::address addr = ip::address::from_string(&address, err);
- if (err) {
- isc_throw(IOError, "Invalid IP address '" << &address << "': "
- << err.message());
- }
- impl_ = new DNSServiceImpl(io_service, port,
- addr.is_v4() ? &addr : NULL,
- addr.is_v6() ? &addr : NULL,
- checkin, lookup, answer);
- }
- DNSService::DNSService(IOService& io_service,
- const char& port,
- const bool use_ipv4, const bool use_ipv6,
- SimpleCallback* checkin,
- DNSLookup* lookup,
- DNSAnswer* answer) :
- impl_(NULL), io_service_(io_service)
- {
- const ip::address v4addr_any = ip::address(ip::address_v4::any());
- const ip::address* const v4addrp = use_ipv4 ? &v4addr_any : NULL;
- const ip::address v6addr_any = ip::address(ip::address_v6::any());
- const ip::address* const v6addrp = use_ipv6 ? &v6addr_any : NULL;
- impl_ = new DNSServiceImpl(io_service, port, v4addrp, v6addrp, checkin, lookup, answer);
- }
- DNSService::~DNSService() {
- delete impl_;
- }
- RecursiveQuery::RecursiveQuery(DNSService& dns_service, const char& forward,
- uint16_t port) :
- dns_service_(dns_service), ns_addr_(&forward), port_(port)
- {}
- void
- RecursiveQuery::sendQuery(const Question& question, OutputBufferPtr buffer,
- DNSServer* server)
- {
- // XXX: eventually we will need to be able to determine whether
- // the message should be sent via TCP or UDP, or sent initially via
- // UDP and then fall back to TCP on failure, but for the moment
- // we're only going to handle UDP.
- asio::io_service& io = dns_service_.get_io_service();
- UDPQuery q(io, question, ns_addr_, port_, buffer, server);
- io.post(q);
- }
- }
|