tcpdns.h 4.29 KB
Newer Older
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
// 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$

#ifndef __TCPDNS_H
#define __TCPDNS_H 1

#include <config.h>


#include <asio.hpp>
#include <boost/shared_ptr.hpp>

#include <dns/buffer.h>
#include <dns/message.h>
#include <dns/messagerenderer.h>

#include <asiolink/asiolink.h>
#include <asiolink/internal/coroutine.h>

namespace asiolink {
// Note: this implementation is optimized for the case where this object
// is created from an ASIO endpoint object in a receiving code path
// by avoiding to make a copy of the base endpoint.  For TCP it may not be
// a big deal, but when we receive UDP packets at a high rate, the copy
// overhead might be significant.
class TCPEndpoint : public IOEndpoint {
public:
    TCPEndpoint(const IOAddress& address, const unsigned short port) :
        asio_endpoint_placeholder_(
            new asio::ip::tcp::endpoint(
                asio::ip::address::from_string(address.toText()), port)),
        asio_endpoint_(*asio_endpoint_placeholder_)
    {}
    TCPEndpoint(const asio::ip::tcp::endpoint& asio_endpoint) :
        asio_endpoint_placeholder_(NULL), asio_endpoint_(asio_endpoint)
    {}
        
    ~TCPEndpoint() { delete asio_endpoint_placeholder_; }
    virtual IOAddress getAddress() const;
    virtual uint16_t getPort() const;
    virtual short getProtocol() const;
    virtual short getFamily() const;
private:
    const asio::ip::tcp::endpoint* asio_endpoint_placeholder_;
    const asio::ip::tcp::endpoint& asio_endpoint_;
};

class TCPSocket : public IOSocket {
private:
    TCPSocket(const TCPSocket& source);
    TCPSocket& operator=(const TCPSocket& source);
public:
    TCPSocket(asio::ip::tcp::socket& socket) : socket_(socket) {}
    virtual int getNative() const;
    virtual int getProtocol() const;
private:
    asio::ip::tcp::socket& socket_;
};

//
// Asynchronous TCP server coroutine
//
class TCPServer : public coroutine {
public:
    explicit TCPServer(asio::io_service& io_service,
                       const asio::ip::address& addr, const uint16_t port, 
                       CheckinProvider* checkin = NULL,
                       DNSProvider* process = NULL);

    void operator()(asio::error_code ec = asio::error_code(),
                    size_t length = 0);

private:
    enum { MAX_LENGTH = 65535 };
    static const size_t TCP_MESSAGE_LENGTHSIZE = 2;

    // Class member variables which are dynamic, and changes to which
    // are expected to be accessible from both sides of a coroutine fork,
    // should be declared here as shared pointers and allocated in the
    // constructor or in the coroutine itself.  (Forking a new coroutine
    // causes class members to be copied, not referenced, so without using
    // this approach, when a variable is changed by a "parent" coroutine
    // the change might not be visible to the "child".  Using shared_ptr<>
    // ensures that when all coroutines using this data are deleted, the
    // memory will be freed.)
    boost::shared_ptr<asio::ip::tcp::acceptor> acceptor_;
    boost::shared_ptr<asio::ip::tcp::socket> socket_;
    boost::shared_ptr<isc::dns::OutputBuffer> response_;
    boost::shared_ptr<isc::dns::OutputBuffer> lenbuf_;
    boost::shared_ptr<isc::dns::MessageRenderer> renderer_;
    boost::shared_ptr<isc::dns::Message> dns_message_;
    boost::shared_ptr<IOMessage> io_message_;
    boost::shared_ptr<TCPSocket> io_socket_;
    boost::shared_ptr<TCPEndpoint> io_endpoint_;
    boost::shared_ptr<char> data_;

    // Callbacks
    const CheckinProvider* checkin_callback_;
    const DNSProvider* dns_callback_;
};

}

#endif // __TCPDNS_H

// Local Variables: 
// mode: c++
// End: