Browse Source

[3796] CCSession class removed.

Tomek Mrugalski 10 years ago
parent
commit
4ace5ca475

+ 0 - 1
src/bin/d2/tests/d_test_stubs.h

@@ -18,7 +18,6 @@
 #include <asiolink/io_service.h>
 
 #include <cc/data.h>
-#include <cc/session.h>
 #include <config/ccsession.h>
 
 #include <d2/d_controller.h>

+ 0 - 1
src/bin/dhcp4/ctrl_dhcp4_srv.h

@@ -17,7 +17,6 @@
 
 #include <asiolink/asiolink.h>
 #include <cc/data.h>
-#include <cc/session.h>
 #include <config/ccsession.h>
 #include <dhcp4/dhcp4_srv.h>
 

+ 0 - 1
src/bin/dhcp6/ctrl_dhcp6_srv.h

@@ -17,7 +17,6 @@
 
 #include <asiolink/asiolink.h>
 #include <cc/data.h>
-#include <cc/session.h>
 #include <config/ccsession.h>
 #include <dhcp6/dhcp6_srv.h>
 

+ 1 - 2
src/lib/cc/Makefile.am

@@ -2,7 +2,6 @@ SUBDIRS = . tests
 
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += $(BOOST_INCLUDES)
-AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
 
 AM_CXXFLAGS = $(KEA_CXXFLAGS)
 if USE_GXX
@@ -15,7 +14,7 @@ AM_CXXFLAGS += -fno-strict-aliasing
 endif
 
 lib_LTLIBRARIES = libkea-cc.la
-libkea_cc_la_SOURCES = data.cc data.h session.cc session.h
+libkea_cc_la_SOURCES = data.cc data.h
 libkea_cc_la_SOURCES += logger.cc logger.h
 nodist_libkea_cc_la_SOURCES = cc_messages.cc cc_messages.h
 libkea_cc_la_SOURCES += proto_defs.cc proto_defs.h

+ 12 - 92
src/lib/cc/cc_messages.mes

@@ -14,99 +14,19 @@
 
 $NAMESPACE isc::cc
 
-% CC_ASYNC_READ_FAILED asynchronous read failed (error code = %1)
-This marks a low level error, we tried to read data from the message queue
-daemon asynchronously, but the ASIO library returned an error.
+% CC_RECEIVE Received a message over control channel: %1
+Debug message, noting that a message was received over control channel.
 
-% CC_CONN_ERROR error connecting to message queue (%1)
-It is impossible to reach the message queue daemon for the reason given. It
-is unlikely there'll be reason for whatever program this currently is to
-continue running, as the communication with the rest of Kea is vital
-for the components.
+% CC_SEND Sending message over control channel: '%1'
+Debug message, the code is about to send a message over the control channel.
 
-% CC_DISCONNECT disconnecting from message queue daemon
-The library is disconnecting from the message queue daemon. This debug message
-indicates that the program is trying to shut down gracefully.
+% CC_REGISTER_COMMAND_HANDLER Handler for command '%1' registered
+Command Handler for a given command has been registered. This means that
+the software enabled handling of said command.
 
-% CC_ESTABLISH trying to establish connection with message queue daemon at %1
-This debug message indicates that the command channel library is about to
-connect to the message queue daemon, which should be listening on the UNIX-domain
-socket listed in the output.
+% CC_PROCESS_COMMAND Processing command '%1'
+Debug message, noting that the software is processing received command.
 
-% CC_ESTABLISHED successfully connected to message queue daemon
-This debug message indicates that the connection was successfully made, this
-should follow CC_ESTABLISH.
-
-% CC_GROUP_RECEIVE trying to receive a message with seq %1
-Debug message, noting that a message is expected to come over the command
-channel.
-
-% CC_GROUP_RECEIVED message arrived ('%1', '%2')
-Debug message, noting that we successfully received a message (its envelope and
-payload listed). This follows CC_GROUP_RECEIVE, but might happen some time
-later, depending if we waited for it or just polled.
-
-% CC_GROUP_SEND sending message '%1' to group '%2'
-Debug message, we're about to send a message over the command channel.
-
-% CC_INVALID_LENGTHS invalid length parameters (%1, %2)
-This happens when garbage comes over the command channel or some kind of
-confusion happens in the program. The data received from the socket make no
-sense if we interpret it as lengths of message. The first one is total length
-of the message; the second is the length of the header. The header
-and its length (2 bytes) is counted in the total length.
-
-% CC_LENGTH_NOT_READY length not ready
-There should be data representing the length of message on the socket, but it
-is not there.
-
-% CC_LNAME_RECEIVED received local name: %1
-Debug message: the local module received its unique identifier (name)
-from msgq on completion of establishing the session with msgq.
-
-% CC_NO_MESSAGE no message ready to be received yet
-The program polled for incoming messages, but there was no message waiting.
-This is a debug message which may happen only after CC_GROUP_RECEIVE.
-
-% CC_NO_MSGQ unable to connect to message queue (%1)
-It isn't possible to connect to the message queue daemon, for reason listed.
-It is unlikely any program will be able continue without the communication.
-
-% CC_READ_ERROR error reading data from command channel (%1)
-A low level error happened when the library tried to read data from the
-command channel socket. The reason is listed.
-
-% CC_READ_EXCEPTION error reading data from command channel (%1)
-We received an exception while trying to read data from the command
-channel socket. The reason is listed.
-
-% CC_REPLY replying to message from '%1' with '%2'
-Debug message, noting we're sending a response to the original message
-with the given envelope.
-
-% CC_SET_TIMEOUT setting timeout to %1ms
-Debug message. A timeout for which the program is willing to wait for a reply
-is being set.
-
-% CC_START_READ starting asynchronous read
-Debug message. From now on, when a message (or command) comes, it'll wake the
-program and the library will automatically pass it over to correct place.
-
-% CC_SUBSCRIBE subscribing to communication group %1
-Debug message. The program wants to receive messages addressed to this group.
-
-% CC_TIMEOUT timeout reading data from command channel
-The program waited too long for data from the command channel (usually when it
-sent a query to different program and it didn't answer for whatever reason).
-
-% CC_UNSUBSCRIBE unsubscribing from communication group %1
-Debug message. The program no longer wants to receive messages addressed to
-this group.
-
-% CC_WRITE_ERROR error writing data to command channel (%1)
-A low level error happened when the library tried to write data to the command
-channel socket.
-
-% CC_ZERO_LENGTH invalid message length (0)
-The library received a message length being zero, which makes no sense, since
-all messages must contain at least the envelope.
+% CC_READ_ERROR Received truncated or malformed command (%1)
+A read error indicates that either the communication was interrupted (e.g.
+truncated packet received) or the entity had sent malformed command.

+ 0 - 552
src/lib/cc/session.cc

@@ -1,552 +0,0 @@
-// Copyright (C) 2009  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.
-
-#include <config.h>
-#include <cc/session_config.h>
-#include <cc/logger.h>
-
-#include <stdint.h>
-
-// XXX: there seems to be a strange dependency between ASIO and std library
-// definitions.  On some platforms if we include std headers before ASIO
-// headers unexpected behaviors will happen.
-// A middle term solution is to generalize our local wrapper interface
-// (currently only available for the auth server), where all such portability
-// issues are hidden, and to have other modules use the wrapper.
-#include <unistd.h>             // for some IPC/network system calls
-#include <asio.hpp>
-#include <asio/error_code.hpp>
-#include <asio/deadline_timer.hpp>
-#include <asio/system_error.hpp>
-
-#include <cc/data.h>
-#include <cc/session.h>
-
-#include <cstdio>
-#include <vector>
-#include <iostream>
-#include <sstream>
-
-#include <sys/un.h>
-
-#include <boost/bind.hpp>
-#include <boost/optional.hpp>
-#include <boost/function.hpp>
-#include <boost/date_time/posix_time/posix_time_types.hpp>
-
-#include <exceptions/exceptions.h>
-
-using namespace std;
-using namespace isc::cc;
-using namespace isc::data;
-
-// some of the asio names conflict with socket API system calls
-// (e.g. write(2)) so we don't import the entire asio namespace.
-using asio::io_service;
-
-namespace {
-/// \brief Sets the given Optional 'result' to the given error code
-/// Used as a callback for emulating sync reads with async calls
-/// \param result Pointer to the optional to set
-/// \param err The error code to set it to
-void
-setResult(boost::optional<asio::error_code>* result,
-          const asio::error_code& err)
-{
-    result->reset(err);
-}
-}
-
-namespace isc {
-namespace cc {
-
-class SessionImpl {
-public:
-    SessionImpl(io_service& io_service) :
-        sequence_(-1), queue_(Element::createList()),
-        io_service_(io_service), socket_(io_service_), data_length_(0),
-        timeout_(MSGQ_DEFAULT_TIMEOUT)
-    {}
-    void establish(const char& socket_file);
-    void disconnect();
-    void writeData(const void* data, size_t datalen);
-    size_t readDataLength();
-    // Blocking read. Will throw a SessionTimeout if the timeout value
-    // (in seconds) is thrown. If timeout is 0 it will block forever
-    void readData(void* data, size_t datalen);
-    void startRead(boost::function<void()> user_handler);
-    void setTimeout(size_t seconds) { timeout_ = seconds; };
-    size_t getTimeout() const { return timeout_; };
-    int getSocketDesc();
-
-    long int sequence_; // the next sequence number to use
-    std::string lname_;
-    ElementPtr queue_;
-
-private:
-    void internalRead(const asio::error_code& error,
-                      size_t bytes_transferred);
-
-private:
-    io_service& io_service_;
-    asio::local::stream_protocol::socket socket_;
-    uint32_t data_length_;
-    boost::function<void()> user_handler_;
-    asio::error_code error_;
-    size_t timeout_;
-
-    // By default, unless changed or disabled, blocking reads on
-    // the msgq channel will time out after 4 seconds in this
-    // implementation.
-    // This number is chosen to be low enough so that whatever
-    // component is blocking does not seem to be hanging, but
-    // still gives enough time for other modules to respond if they
-    // are busy. If this choice turns out to be a bad one, we can
-    // change it later.
-    static const size_t MSGQ_DEFAULT_TIMEOUT = 4000;
-};
-
-void
-SessionImpl::establish(const char& socket_file) {
-    try {
-        LOG_DEBUG(logger, DBG_TRACE_BASIC, CC_ESTABLISH).arg(&socket_file);
-        socket_.connect(asio::local::stream_protocol::endpoint(&socket_file),
-                        error_);
-        LOG_DEBUG(logger, DBG_TRACE_BASIC, CC_ESTABLISHED);
-    } catch(const asio::system_error& se) {
-        LOG_FATAL(logger, CC_CONN_ERROR).arg(se.what());
-        isc_throw(SessionError, se.what());
-    }
-    if (error_) {
-        LOG_FATAL(logger, CC_NO_MSGQ).arg(error_.message());
-        isc_throw(SessionError, "Unable to connect to message queue: " <<
-                  error_.message());
-    }
-}
-
-void
-SessionImpl::disconnect() {
-    LOG_DEBUG(logger, DBG_TRACE_BASIC, CC_DISCONNECT);
-    socket_.close();
-    data_length_ = 0;
-}
-
-void
-SessionImpl::writeData(const void* data, size_t datalen) {
-    try {
-        asio::write(socket_, asio::buffer(data, datalen));
-    } catch (const asio::system_error& asio_ex) {
-        LOG_FATAL(logger, CC_WRITE_ERROR).arg(asio_ex.what());
-        isc_throw(SessionError, "ASIO write failed: " << asio_ex.what());
-    }
-}
-
-size_t
-SessionImpl::readDataLength() {
-    size_t ret_len = data_length_;
-    
-    if (ret_len == 0) {
-        readData(&data_length_, sizeof(data_length_));
-        if (data_length_ == 0) {
-            LOG_ERROR(logger, CC_LENGTH_NOT_READY);
-            isc_throw(SessionError, "ASIO read: data length is not ready");
-        }
-        ret_len = ntohl(data_length_);
-    }
-
-    data_length_ = 0;
-    return (ret_len);
-}
-
-void
-SessionImpl::readData(void* data, size_t datalen) {
-    boost::optional<asio::error_code> read_result;
-    boost::optional<asio::error_code> timer_result;
-
-    try {
-        asio::async_read(socket_, asio::buffer(data, datalen),
-                         boost::bind(&setResult, &read_result, _1));
-        asio::deadline_timer timer(socket_.io_service());
-
-        if (getTimeout() != 0) {
-            timer.expires_from_now(boost::posix_time::milliseconds(getTimeout()));
-            timer.async_wait(boost::bind(&setResult, &timer_result, _1));
-        }
-
-        // wait until either we have read the data we want, the
-        // timer expires, or one of the two is triggered with an error.
-        // When one of them has a result, cancel the other, and wait
-        // until the cancel is processed before we continue
-        while (!read_result && !timer_result) {
-            socket_.io_service().run_one();
-
-            // Don't cancel the timer if we haven't set it
-            if (read_result && getTimeout() != 0) {
-                timer.cancel();
-                while (!timer_result) {
-                    socket_.io_service().run_one();
-                }
-            } else if (timer_result) {
-                socket_.cancel();
-                while (!read_result) {
-                    socket_.io_service().run_one();
-                }
-            }
-        }
-
-        // asio::error_code evaluates to false if there was no error
-        if (*read_result) {
-            if (*read_result == asio::error::operation_aborted) {
-                LOG_ERROR(logger, CC_TIMEOUT);
-                isc_throw(SessionTimeout,
-                          "Timeout while reading data from cc session");
-            } else {
-                LOG_ERROR(logger, CC_READ_ERROR).arg(read_result->message());
-                isc_throw(SessionError,
-                          "Error while reading data from cc session: " <<
-                          read_result->message());
-            }
-        }
-    } catch (const asio::system_error& asio_ex) {
-        // to hide ASIO specific exceptions, we catch them explicitly
-        // and convert it to SessionError.
-        LOG_FATAL(logger, CC_READ_EXCEPTION).arg(asio_ex.what());
-        isc_throw(SessionError, "ASIO read failed: " << asio_ex.what());
-    }
-}
-
-void
-SessionImpl::startRead(boost::function<void()> user_handler) {
-    data_length_ = 0;
-    user_handler_ = user_handler;
-    asio::async_read(socket_, asio::buffer(&data_length_,
-                                           sizeof(data_length_)),
-                     boost::bind(&SessionImpl::internalRead, this,
-                                 asio::placeholders::error,
-                                 asio::placeholders::bytes_transferred));
-}
-
-void
-SessionImpl::internalRead(const asio::error_code& error,
-                          size_t bytes_transferred)
-{
-    if (!error) {
-        assert(bytes_transferred == sizeof(data_length_));
-        data_length_ = ntohl(data_length_);
-        if (data_length_ == 0) {
-            LOG_ERROR(logger, CC_ZERO_LENGTH);
-            isc_throw(SessionError, "Invalid message length (0)");
-        }
-        user_handler_();
-    } else {
-        LOG_ERROR(logger, CC_ASYNC_READ_FAILED).arg(error.value());
-        isc_throw(SessionError, "asynchronous read failed");
-    }
-}
-
-int
-SessionImpl::getSocketDesc() {
-    /// @todo boost 1.42 uses native() method, but it is deprecated
-    /// in 1.49 and native_handle() is recommended instead
-    if (!socket_.is_open()) {
-        isc_throw(InvalidOperation, "Can't return socket descriptor: no socket opened.");
-    }
-    return socket_.native();
-}
-
-Session::Session(asio::io_service& io_service) :
-    impl_(new SessionImpl(io_service))
-{}
-
-Session::~Session() {
-    delete impl_;
-}
-
-void
-Session::disconnect() {
-    impl_->disconnect();
-}
-
-void
-Session::startRead(boost::function<void()> read_callback) {
-    LOG_DEBUG(logger, DBG_TRACE_DETAILED, CC_START_READ);
-    impl_->startRead(read_callback);
-}
-
-int
-Session::getSocketDesc() const {
-    return impl_->getSocketDesc();
-}
-
-namespace {                     // maybe unnecessary.
-// This is a helper class to make the establish() method (below) exception-safe
-// with the RAII approach.
-class SessionHolder {
-public:
-    SessionHolder(SessionImpl* obj) : impl_obj_(obj) {}
-    ~SessionHolder()
-    {
-        if (impl_obj_ != NULL) {
-            impl_obj_->disconnect();
-        }
-    }
-    void clear() { impl_obj_ = NULL; }
-    SessionImpl* impl_obj_;
-};
-}
-
-void
-Session::establish(const char* socket_file) {
-    if (socket_file == NULL) {
-        socket_file = getenv("BUNDY_MSGQ_SOCKET_FILE");
-    }
-    if (socket_file == NULL) {
-        socket_file = BUNDY_MSGQ_SOCKET_FILE;
-    }
-
-    impl_->establish(*socket_file);
-
-    // once established, encapsulate the implementation object so that we
-    // can safely release the internal resource when exception happens
-    // below.
-    SessionHolder session_holder(impl_);
-
-    //
-    // send a request for our local name, and wait for a response
-    //
-    ElementPtr get_lname_msg(Element::createMap());
-    get_lname_msg->set(CC_HEADER_TYPE, Element::create(CC_COMMAND_GET_LNAME));
-    sendmsg(get_lname_msg);
-
-    ConstElementPtr routing, msg;
-    recvmsg(routing, msg, false);
-
-    impl_->lname_ = msg->get(CC_PAYLOAD_LNAME)->stringValue();
-    LOG_DEBUG(logger, DBG_TRACE_DETAILED, CC_LNAME_RECEIVED).arg(impl_->lname_);
-
-    // At this point there's no risk of resource leak.
-    session_holder.clear();
-}
-
-//
-// Convert to wire format and send this via the stream socket with its length
-// prefix.
-//
-void
-Session::sendmsg(ConstElementPtr header) {
-    std::string header_wire = header->toWire();
-    unsigned int length = 2 + header_wire.length();
-    unsigned int length_net = htonl(length);
-    unsigned short header_length = header_wire.length();
-    unsigned short header_length_net = htons(header_length);
-
-    impl_->writeData(&length_net, sizeof(length_net));
-    impl_->writeData(&header_length_net, sizeof(header_length_net));
-    impl_->writeData(header_wire.data(), header_length);
-}
-
-void
-Session::sendmsg(ConstElementPtr header, ConstElementPtr payload) {
-    std::string header_wire = header->toWire();
-    std::string body_wire = payload->toWire();
-    unsigned int length = 2 + header_wire.length() + body_wire.length();
-    unsigned int length_net = htonl(length);
-    unsigned short header_length = header_wire.length();
-    unsigned short header_length_net = htons(header_length);
-
-    impl_->writeData(&length_net, sizeof(length_net));
-    impl_->writeData(&header_length_net, sizeof(header_length_net));
-    impl_->writeData(header_wire.data(), header_length);
-    impl_->writeData(body_wire.data(), body_wire.length());
-}
-
-bool
-Session::recvmsg(ConstElementPtr& msg, bool nonblock, int seq) {
-    ConstElementPtr l_env;
-    return (recvmsg(l_env, msg, nonblock, seq));
-}
-
-bool
-Session::recvmsg(ConstElementPtr& env, ConstElementPtr& msg,
-                 bool nonblock, int seq)
-{
-    size_t length = impl_->readDataLength();
-    if (hasQueuedMsgs()) {
-        ConstElementPtr q_el;
-        for (size_t i = 0; i < impl_->queue_->size(); i++) {
-            q_el = impl_->queue_->get(i);
-            if (( seq == -1 &&
-                  !q_el->get(0)->contains(CC_HEADER_REPLY)
-                ) || (
-                  q_el->get(0)->contains(CC_HEADER_REPLY) &&
-                  q_el->get(0)->get(CC_HEADER_REPLY)->intValue() == seq
-                )
-               ) {
-                   env = q_el->get(0);
-                   msg = q_el->get(1);
-                   impl_->queue_->remove(i);
-                   return (true);
-            }
-        }
-    }
-    
-    unsigned short header_length_net;
-    impl_->readData(&header_length_net, sizeof(header_length_net));
-
-    unsigned short header_length = ntohs(header_length_net);
-    if (header_length > length || length < 2) {
-        LOG_ERROR(logger, CC_INVALID_LENGTHS).arg(length).arg(header_length);
-        isc_throw(SessionError, "Length parameters invalid: total=" << length
-                  << ", header=" << header_length);
-    }
-
-    // remove the header-length bytes from the total length
-    length -= 2;
-    std::vector<char> buffer(length);
-    impl_->readData(&buffer[0], length);
-
-    std::string header_wire = std::string(&buffer[0], header_length);
-    std::string body_wire = std::string(&buffer[0] + header_length,
-                                        length - header_length);
-    std::stringstream header_wire_stream;
-    header_wire_stream << header_wire;
-    ConstElementPtr l_env =
-        Element::fromWire(header_wire_stream, header_length);
-    
-    std::stringstream body_wire_stream;
-    body_wire_stream << body_wire;
-    ConstElementPtr l_msg =
-        Element::fromWire(body_wire_stream, length - header_length);
-    if ((seq == -1 &&
-         !l_env->contains(CC_HEADER_REPLY)
-        ) || (
-         l_env->contains(CC_HEADER_REPLY) &&
-         l_env->get(CC_HEADER_REPLY)->intValue() == seq
-        )
-       ) {
-        env = l_env;
-        msg = l_msg;
-        return (true);
-    } else {
-        ElementPtr q_el = Element::createList();
-        q_el->add(l_env);
-        q_el->add(l_msg);
-        impl_->queue_->add(q_el);
-        return (recvmsg(env, msg, nonblock, seq));
-    }
-    // XXXMLG handle non-block here, and return false for short reads
-}
-
-void
-Session::subscribe(std::string group, std::string instance) {
-    LOG_DEBUG(logger, DBG_TRACE_DETAILED, CC_SUBSCRIBE).arg(group);
-    ElementPtr env = Element::createMap();
-
-    env->set(CC_HEADER_TYPE, Element::create(CC_COMMAND_SUBSCRIBE));
-    env->set(CC_HEADER_GROUP, Element::create(group));
-    env->set(CC_HEADER_INSTANCE, Element::create(instance));
-
-    sendmsg(env);
-}
-
-void
-Session::unsubscribe(std::string group, std::string instance) {
-    LOG_DEBUG(logger, DBG_TRACE_DETAILED, CC_UNSUBSCRIBE).arg(group);
-    ElementPtr env = Element::createMap();
-
-    env->set(CC_HEADER_TYPE, Element::create(CC_COMMAND_UNSUBSCRIBE));
-    env->set(CC_HEADER_GROUP, Element::create(group));
-    env->set(CC_HEADER_INSTANCE, Element::create(instance));
-
-    sendmsg(env);
-}
-
-int
-Session::group_sendmsg(ConstElementPtr msg, std::string group,
-                       std::string instance, std::string to, bool want_answer)
-{
-    LOG_DEBUG(logger, DBG_TRACE_DETAILED, CC_GROUP_SEND).arg(msg->str()).
-        arg(group);
-    ElementPtr env = Element::createMap();
-    const long int nseq = ++impl_->sequence_;
-
-    env->set(CC_HEADER_TYPE,
-             Element::create(CC_COMMAND_SEND));
-    env->set(CC_HEADER_FROM, Element::create(impl_->lname_));
-    env->set(CC_HEADER_TO, Element::create(to));
-    env->set(CC_HEADER_GROUP, Element::create(group));
-    env->set(CC_HEADER_INSTANCE, Element::create(instance));
-    env->set(CC_HEADER_SEQ, Element::create(nseq));
-    env->set(CC_HEADER_WANT_ANSWER, Element::create(want_answer));
-
-    sendmsg(env, msg);
-    return (nseq);
-}
-
-bool
-Session::group_recvmsg(ConstElementPtr& envelope, ConstElementPtr& msg,
-                       bool nonblock, int seq)
-{
-    LOG_DEBUG(logger, DBG_TRACE_DETAILED, CC_GROUP_RECEIVE).arg(seq);
-    bool result(recvmsg(envelope, msg, nonblock, seq));
-    if (result) {
-        LOG_DEBUG(logger, DBG_TRACE_DETAILED, CC_GROUP_RECEIVED).
-            arg(envelope->str()).arg(msg->str());
-    } else {
-        LOG_DEBUG(logger, DBG_TRACE_DETAILED, CC_NO_MESSAGE);
-    }
-    return (result);
-}
-
-int
-Session::reply(ConstElementPtr envelope, ConstElementPtr newmsg) {
-    LOG_DEBUG(logger, DBG_TRACE_DETAILED, CC_REPLY).arg(envelope->str()).
-        arg(newmsg->str());
-    ElementPtr env = Element::createMap();
-    long int nseq = ++impl_->sequence_;
-
-    env->set(CC_HEADER_TYPE, Element::create(CC_COMMAND_SEND));
-    env->set(CC_HEADER_FROM, Element::create(impl_->lname_));
-    env->set(CC_HEADER_TO,
-             Element::create(envelope->get(CC_HEADER_FROM)->stringValue()));
-    env->set(CC_HEADER_GROUP,
-             Element::create(envelope->get(CC_HEADER_GROUP)->stringValue()));
-    env->set(CC_HEADER_INSTANCE,
-             Element::create(envelope->get(CC_HEADER_INSTANCE)->stringValue()));
-    env->set(CC_HEADER_SEQ, Element::create(nseq));
-    env->set(CC_HEADER_REPLY,
-             Element::create(envelope->get(CC_HEADER_SEQ)->intValue()));
-
-    sendmsg(env, newmsg);
-
-    return (nseq);
-}
-
-bool
-Session::hasQueuedMsgs() const {
-    return (!impl_->queue_->empty());
-}
-
-void
-Session::setTimeout(size_t milliseconds) {
-    LOG_DEBUG(logger, DBG_TRACE_DETAILED, CC_SET_TIMEOUT).arg(milliseconds);
-    impl_->setTimeout(milliseconds);
-}
-
-size_t
-Session::getTimeout() const {
-    return (impl_->getTimeout());
-}
-}
-}

+ 0 - 192
src/lib/cc/session.h

@@ -1,192 +0,0 @@
-// Copyright (C) 2009  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 ISC_SESSION_H
-#define ISC_SESSION_H 1
-
-#include <cc/data.h>
-#include <cc/session_config.h>
-#include <cc/proto_defs.h>
-
-#include <exceptions/exceptions.h>
-
-#include <string>
-
-#include <boost/function.hpp>
-
-namespace asio {
-class io_service;
-}
-
-namespace isc {
-    namespace cc {
-        class SessionImpl;
-
-        class SessionError : public isc::Exception {
-        public:
-            SessionError(const char* file, size_t line, const char* what) :
-                isc::Exception(file, line, what) {}
-        };
-
-        /// \brief A standard Exception class that is thrown when a
-        /// blocking readData call does not read the given number of
-        /// bytes before the timeout expires
-        class SessionTimeout : public isc::Exception {
-        public:
-            SessionTimeout(const char* file, size_t line, const char* what) :
-                isc::Exception(file, line, what) {}
-        };
-
-        /// \brief The AbstractSession class is an abstract base class that
-        /// defines the interfaces of Session.
-        /// The intended primary usage of abstraction is to allow tests for the
-        /// user class of Session without requiring actual communication
-        /// channels.
-        /// For simplicity we only define the methods that are necessary for
-        /// existing test cases that use this base class.  Eventually we'll
-        /// probably have to extend them.
-        class AbstractSession {
-            ///
-            /// \name Constructors, Assignment Operator and Destructor.
-            ///
-            /// Note: The copy constructor and the assignment operator are
-            /// intentionally defined as private to make it explicit that
-            /// this is a pure base class.
-            //@{
-        private:
-            AbstractSession(const AbstractSession& source);
-            AbstractSession& operator=(const AbstractSession& source);
-        protected:
-            /// \brief The default constructor.
-            ///
-            /// This is intentionally defined as \c protected as this base
-            /// class should never be instantiated (except as part of a
-            /// derived class).
-            AbstractSession() {}
-        public:
-            /// \brief The destructor.
-            virtual ~AbstractSession() {}
-            //@}
-            virtual void establish(const char* socket_file) = 0;
-            virtual void disconnect() = 0;
-            virtual int group_sendmsg(isc::data::ConstElementPtr msg,
-                                      std::string group,
-                                      std::string instance =
-                                          CC_INSTANCE_WILDCARD,
-                                      std::string to = CC_TO_WILDCARD,
-                                      bool want_answer = false) = 0;
-            virtual bool group_recvmsg(isc::data::ConstElementPtr& envelope,
-                                       isc::data::ConstElementPtr& msg,
-                                       bool nonblock = true,
-                                       int seq = -1) = 0;
-            virtual void subscribe(std::string group,
-                                   std::string instance = "*") = 0;
-            virtual void unsubscribe(std::string group,
-                             std::string instance = "*") = 0;
-            virtual void startRead(boost::function<void()> read_callback) = 0;
-            virtual int reply(isc::data::ConstElementPtr envelope,
-                               isc::data::ConstElementPtr newmsg) = 0;
-            virtual bool hasQueuedMsgs() const = 0;
-
-            /// \brief Sets the default timeout for blocking reads
-            ///        in this session to the given number of milliseconds
-            /// \param milliseconds the timeout for blocking reads in
-            ///        milliseconds; if this is set to 0, reads will block
-            ///        forever.
-            virtual void setTimeout(size_t milliseconds) = 0;
-
-            /// \brief Returns the current timeout for blocking reads
-            /// \return The timeout (in milliseconds)
-            virtual size_t getTimeout() const = 0;
-        };
-
-    class Session : public AbstractSession {
-        private:
-            SessionImpl* impl_;
-
-        private:
-            Session(const Session& source);
-            Session& operator=(const Session& source);
-
-        public:
-            Session(asio::io_service& ioservice);
-            virtual ~Session();
-
-            virtual void startRead(boost::function<void()> read_callback);
-
-            virtual void establish(const char* socket_file = NULL);
-            virtual void disconnect();
-            virtual void subscribe(std::string group,
-                                   std::string instance = "*");
-            virtual void unsubscribe(std::string group,
-                             std::string instance = "*");
-
-            /// \brief Send a message to a group.
-            ///
-            /// \todo Can someone explain how the group, instance and to work?
-            ///     What is the desired semantics here?
-            /// \param msg The message to send.
-            /// \param group Part of addressing.
-            /// \param instance Part of addressing.
-            /// \param to Part of addressing.
-            /// \param want_answer Require an answer? If it is true and there's
-            ///     no recipient, the message queue answers by an error
-            ///     instead.
-            /// \return The squence number of the message sent. It can be used
-            ///     to wait for an answer by group_recvmsg.
-            virtual int group_sendmsg(isc::data::ConstElementPtr msg,
-                                      std::string group,
-                                      std::string instance = "*",
-                                      std::string to = "*",
-                                      bool want_answer = false);
-
-            virtual bool group_recvmsg(isc::data::ConstElementPtr& envelope,
-                                       isc::data::ConstElementPtr& msg,
-                                       bool nonblock = true,
-                                       int seq = -1);
-            virtual int reply(isc::data::ConstElementPtr envelope,
-                              isc::data::ConstElementPtr newmsg);
-            virtual bool hasQueuedMsgs() const;
-            virtual void setTimeout(size_t milliseconds);
-            virtual size_t getTimeout() const;
-
-            /// @brief returns socket descriptor from underlying socket connection
-            ///
-            /// @return socket descriptor used for session connection
-            virtual int getSocketDesc() const;
-    private:
-            // The following two methods are virtual to allow tests steal and
-            // replace them. It is not expected to be specialized by a derived
-            // class. Actually, it is not expected to inherit from this class
-            // to begin with.
-            virtual void sendmsg(isc::data::ConstElementPtr header);
-            virtual void sendmsg(isc::data::ConstElementPtr header,
-                                 isc::data::ConstElementPtr payload);
-
-            bool recvmsg(isc::data::ConstElementPtr& msg,
-                         bool nonblock = true,
-                         int seq = -1);
-            bool recvmsg(isc::data::ConstElementPtr& env,
-                         isc::data::ConstElementPtr& msg,
-                         bool nonblock = true,
-                         int seq = -1);
-        };
-    } // namespace cc
-} // namespace isc
-
-#endif // ISC_SESSION_H
-
-// Local Variables:
-// mode: c++
-// End:

+ 1 - 1
src/lib/cc/tests/Makefile.am

@@ -20,7 +20,7 @@ TESTS =
 if HAVE_GTEST
 TESTS += run_unittests
 # (TODO: these need to be completed and moved to tests/)
-run_unittests_SOURCES = data_unittests.cc session_unittests.cc run_unittests.cc
+run_unittests_SOURCES = data_unittests.cc run_unittests.cc
 run_unittests_SOURCES += data_file_unittests.cc
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)

+ 0 - 364
src/lib/cc/tests/session_unittests.cc

@@ -1,364 +0,0 @@
-// Copyright (C) 2009,2015  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.
-
-#include <config.h>
-
-// for some IPC/network system calls in asio/detail/pipe_select_interrupter.hpp 
-#include <unistd.h>
-// XXX: the ASIO header must be included before others.  See session.cc.
-#include <asio.hpp>
-
-#include <cc/session.h>
-#include <cc/data.h>
-#include <cc/tests/session_unittests_config.h>
-
-#include <gtest/gtest.h>
-#include <boost/bind.hpp>
-
-#include <exceptions/exceptions.h>
-
-#include <utility>
-#include <list>
-#include <string>
-#include <iostream>
-
-using namespace isc::cc;
-using std::pair;
-using std::list;
-using std::string;
-using isc::data::ConstElementPtr;
-using isc::data::Element;
-
-namespace {
-
-TEST(AsioSession, establish) {
-    asio::io_service io_service_;
-    Session sess(io_service_);
-
-    // can't return socket descriptor before session is established
-    EXPECT_THROW(sess.getSocketDesc(), isc::InvalidOperation);
-
-    EXPECT_THROW(
-        sess.establish("/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                  ), isc::cc::SessionError
-    );
-}
-
-// This class sets up a domain socket for the session to connect to
-// it will impersonate the msgq a tiny bit (if setSendLname() has
-// been called, it will send an 'answer' to the lname query that is
-// sent in the initialization of Session objects)
-class TestDomainSocket {
-
-public:
-    TestDomainSocket(asio::io_service& io_service, const char* file) :
-        io_service_(io_service),
-        ep_(file),
-        acceptor_(io_service_, ep_),
-        socket_(io_service_),
-        data_buf_(1024)
-    {
-        acceptor_.async_accept(socket_, boost::bind(&TestDomainSocket::acceptHandler,
-                                                    _1));
-    }
-
-    ~TestDomainSocket() {
-        socket_.close();
-        unlink(BUNDY_TEST_SOCKET_FILE);
-    }
-
-    static void acceptHandler(const asio::error_code&) {
-    }
-
-    void sendmsg(isc::data::ElementPtr& env, isc::data::ElementPtr& msg) {
-        const std::string header_wire = env->toWire();
-        const std::string body_wire = msg->toWire();
-        const unsigned int length = 2 + header_wire.length() +
-            body_wire.length();
-        const unsigned int length_net = htonl(length);
-        const unsigned short header_length = header_wire.length();
-        const unsigned short header_length_net = htons(header_length);
-
-        socket_.send(asio::buffer(&length_net, sizeof(length_net)));
-        socket_.send(asio::buffer(&header_length_net,
-                                  sizeof(header_length_net)));
-        socket_.send(asio::buffer(header_wire.data(), header_length));
-        socket_.send(asio::buffer(body_wire.data(), body_wire.length()));
-    }
-
-    void sendLname() {
-        isc::data::ElementPtr lname_answer1 =
-            isc::data::Element::fromJSON("{ \"type\": \"lname\" }");
-        isc::data::ElementPtr lname_answer2 =
-            isc::data::Element::fromJSON("{ \"lname\": \"foobar\" }");
-        sendmsg(lname_answer1, lname_answer2);
-    }
-
-    void setSendLname() {
-        // ignore whatever data we get, send back an lname
-        asio::async_read(socket_,  asio::buffer(&data_buf_[0], 0),
-                         boost::bind(&TestDomainSocket::sendLname, this));
-    }
-
-private:
-    asio::io_service& io_service_;
-    asio::local::stream_protocol::endpoint ep_;
-    asio::local::stream_protocol::acceptor acceptor_;
-    asio::local::stream_protocol::socket socket_;
-    std::vector<char> data_buf_;
-};
-
-/// \brief Pair holding header and data of a message sent over the connection.
-typedef pair<ConstElementPtr, ConstElementPtr> SentMessage;
-
-// We specialize the tested class a little. We replace some low-level
-// methods so we can examine the rest without relying on real network IO
-class TestSession : public Session {
-public:
-    TestSession(asio::io_service& ioservice) :
-        Session(ioservice)
-    {}
-    // Get first message previously sent by sendmsg and remove it from the
-    // buffer. Expects there's at leas one message in the buffer.
-    SentMessage getSentMessage() {
-        assert(!sent_messages_.empty());
-        const SentMessage result(sent_messages_.front());
-        sent_messages_.pop_front();
-        return (result);
-    }
-private:
-    // Override the sendmsg. They are not sent over the real connection, but
-    // stored locally and can be extracted by getSentMessage()
-    virtual void sendmsg(ConstElementPtr header) {
-        sendmsg(header, ConstElementPtr(new isc::data::NullElement));
-    }
-    virtual void sendmsg(ConstElementPtr header, ConstElementPtr payload) {
-        sent_messages_.push_back(SentMessage(header, payload));
-    }
-
-    // The sendmsg stores data here.
-    list<SentMessage> sent_messages_;
-};
-
-class SessionTest : public ::testing::Test {
-protected:
-    SessionTest() : sess(my_io_service), work(my_io_service) {
-        // The TestDomainSocket is held as a 'new'-ed pointer,
-        // so we can call unlink() first.
-        unlink(BUNDY_TEST_SOCKET_FILE);
-        tds = new TestDomainSocket(my_io_service, BUNDY_TEST_SOCKET_FILE);
-    }
-
-    ~SessionTest() {
-        delete tds;
-    }
-
-    // Check the session sent a message with the given header. The
-    // message is hardcoded.
-    void checkSentMessage(const string& expected_hdr, const char* description)
-    {
-        SCOPED_TRACE(description);
-        const SentMessage& msg(sess.getSentMessage());
-        elementsEqual(expected_hdr, msg.first);
-        elementsEqual("{\"test\": 42}", msg.second);
-    }
-
-private:
-    // Check two elements are equal
-    void elementsEqual(const string& expected,
-                       const ConstElementPtr& actual) const
-    {
-        EXPECT_TRUE(Element::fromJSON(expected)->equals(*actual)) <<
-            "Elements differ, expected: " << expected <<
-            ", got: " << actual->toWire();
-    }
-
-public:
-    // used in the handler test
-    // This handler first reads (and ignores) whatever message caused
-    // it to be invoked. Then it calls group_recv for a second message.
-    // If this message is { "command": "stop" } it'll tell the
-    // io_service it is done. Otherwise it'll re-register this handler
-    void someHandler() {
-        isc::data::ConstElementPtr env, msg;
-        sess.group_recvmsg(env, msg, false, -1);
-
-        sess.group_recvmsg(env, msg, false, -1);
-        if (msg && msg->contains("command") &&
-            msg->get("command")->stringValue() == "stop") {
-            my_io_service.stop();
-        } else {
-            sess.startRead(boost::bind(&SessionTest::someHandler, this));
-        }
-    }
-
-protected:
-    asio::io_service my_io_service;
-    TestDomainSocket* tds;
-    TestSession sess;
-    // Keep run() from stopping right away by informing it it has work to do
-    asio::io_service::work work;
-};
-
-TEST_F(SessionTest, timeout_on_connect) {
-    // set to a short timeout so the test doesn't take too long
-    EXPECT_EQ(4000, sess.getTimeout());
-    sess.setTimeout(100);
-    EXPECT_EQ(100, sess.getTimeout());
-    // no answer, should timeout
-    EXPECT_THROW(sess.establish(BUNDY_TEST_SOCKET_FILE), SessionTimeout);
-}
-
-TEST_F(SessionTest, connect_ok) {
-    tds->setSendLname();
-    sess.establish(BUNDY_TEST_SOCKET_FILE);
-}
-
-TEST_F(SessionTest, connect_ok_no_timeout) {
-    tds->setSendLname();
-
-    sess.setTimeout(0);
-    sess.establish(BUNDY_TEST_SOCKET_FILE);
-}
-
-TEST_F(SessionTest, connect_ok_connection_reset) {
-    tds->setSendLname();
-
-    sess.establish(BUNDY_TEST_SOCKET_FILE);
-    // Close the session again, so the next recv() should throw
-    sess.disconnect();
-
-    isc::data::ConstElementPtr env, msg;
-    EXPECT_THROW(sess.group_recvmsg(env, msg, false, -1), SessionError);
-}
-
-TEST_F(SessionTest, run_with_handler) {
-    tds->setSendLname();
-
-    sess.establish(BUNDY_TEST_SOCKET_FILE);
-    sess.startRead(boost::bind(&SessionTest::someHandler, this));
-
-    isc::data::ElementPtr env = isc::data::Element::fromJSON("{ \"to\": \"me\" }");
-    isc::data::ElementPtr msg = isc::data::Element::fromJSON("{ \"some\": \"message\" }");
-    tds->sendmsg(env, msg);
-
-    msg = isc::data::Element::fromJSON("{ \"another\": \"message\" }");
-    tds->sendmsg(env, msg);
-
-    msg = isc::data::Element::fromJSON("{ \"a third\": \"message\" }");
-    tds->sendmsg(env, msg);
-
-    msg = isc::data::Element::fromJSON("{ \"command\": \"stop\" }");
-    tds->sendmsg(env, msg);
-
-
-    size_t count = my_io_service.run();
-    ASSERT_EQ(2, count);
-}
-
-TEST_F(SessionTest, run_with_handler_timeout) {
-    tds->setSendLname();
-
-    sess.establish(BUNDY_TEST_SOCKET_FILE);
-    sess.startRead(boost::bind(&SessionTest::someHandler, this));
-    sess.setTimeout(100);
-
-    isc::data::ElementPtr env = isc::data::Element::fromJSON("{ \"to\": \"me\" }");
-    isc::data::ElementPtr msg = isc::data::Element::fromJSON("{ \"some\": \"message\" }");
-    tds->sendmsg(env, msg);
-
-    msg = isc::data::Element::fromJSON("{ \"another\": \"message\" }");
-    tds->sendmsg(env, msg);
-
-    msg = isc::data::Element::fromJSON("{ \"a third\": \"message\" }");
-    tds->sendmsg(env, msg);
-
-    // No follow-up message, should time out.
-    ASSERT_THROW(my_io_service.run(), SessionTimeout);
-}
-
-TEST_F(SessionTest, get_socket_descr) {
-    tds->setSendLname();
-    sess.establish(BUNDY_TEST_SOCKET_FILE);
-
-    int socket = 0;
-    // session is established, so getSocketDesc() should work
-    EXPECT_NO_THROW(socket = sess.getSocketDesc());
-
-    // expect actual socket handle to be returned, not 0
-    EXPECT_LT(0, socket);
-}
-
-// Test the group_sendmsg sends the correct data.
-TEST_F(SessionTest, group_sendmsg) {
-    // Connect (to set the lname, so we can see it sets the from)
-    tds->setSendLname();
-    sess.establish(BUNDY_TEST_SOCKET_FILE);
-    // Eat the "get_lname" message, so it doesn't confuse the
-    // test below.
-    sess.getSentMessage();
-
-    const ConstElementPtr msg(Element::fromJSON("{\"test\": 42}"));
-    sess.group_sendmsg(msg, "group");
-    checkSentMessage("{"
-                     "   \"from\": \"foobar\","
-                     "   \"group\": \"group\","
-                     "   \"instance\": \"*\","
-                     "   \"seq\": 0,"
-                     "   \"to\": \"*\","
-                     "   \"type\": \"send\","
-                     "   \"want_answer\": False"
-                     "}", "No instance");
-    sess.group_sendmsg(msg, "group", "instance", "recipient");
-    checkSentMessage("{"
-                     "   \"from\": \"foobar\","
-                     "   \"group\": \"group\","
-                     "   \"instance\": \"instance\","
-                     "   \"seq\": 1,"
-                     "   \"to\": \"recipient\","
-                     "   \"type\": \"send\","
-                     "   \"want_answer\": False"
-                     "}", "With instance");
-    sess.group_sendmsg(msg, "group", "*", "*", true);
-    checkSentMessage("{"
-                     "   \"from\": \"foobar\","
-                     "   \"group\": \"group\","
-                     "   \"instance\": \"*\","
-                     "   \"seq\": 2,"
-                     "   \"to\": \"*\","
-                     "   \"type\": \"send\","
-                     "   \"want_answer\": True"
-                     "}", "Want answer");
-    sess.group_sendmsg(msg, "group", "*", "*", false);
-    checkSentMessage("{"
-                     "   \"from\": \"foobar\","
-                     "   \"group\": \"group\","
-                     "   \"instance\": \"*\","
-                     "   \"seq\": 3,"
-                     "   \"to\": \"*\","
-                     "   \"type\": \"send\","
-                     "   \"want_answer\": False"
-                     "}", "Doesn't want answer");
-}
-
-}

+ 0 - 598
src/lib/config/ccsession.cc

@@ -33,7 +33,6 @@
 
 #include <cc/data.h>
 #include <config/module_spec.h>
-#include <cc/session.h>
 #include <exceptions/exceptions.h>
 
 #include <config/config_log.h>
@@ -308,7 +307,6 @@ copyLogger(ConstElementPtr& cur_logger, const std::string& new_name) {
 
 } // end anonymous namespace
 
-
 ConstElementPtr
 getRelatedLoggers(ConstElementPtr loggers) {
     // Keep a list of names for easier lookup later
@@ -394,601 +392,5 @@ default_logconfig_handler(const std::string& module_name,
     logger_manager.process(specs.begin(), specs.end());
 }
 
-
-ModuleSpec
-ModuleCCSession::readModuleSpecification(const std::string& filename) {
-    std::ifstream file;
-    ModuleSpec module_spec;
-
-    // this file should be declared in a @something@ directive
-    file.open(filename.c_str());
-    if (!file) {
-        LOG_ERROR(config_logger, CONFIG_OPEN_FAIL).arg(filename).arg(strerror(errno));
-        isc_throw(CCSessionInitError, strerror(errno));
-    }
-
-    try {
-        module_spec = moduleSpecFromFile(file, true);
-    } catch (const JSONError& pe) {
-        LOG_ERROR(config_logger, CONFIG_JSON_PARSE).arg(filename).arg(pe.what());
-        isc_throw(CCSessionInitError, pe.what());
-    } catch (const ModuleSpecError& dde) {
-        LOG_ERROR(config_logger, CONFIG_MOD_SPEC_FORMAT).arg(filename).arg(dde.what());
-        isc_throw(CCSessionInitError, dde.what());
-    }
-    file.close();
-    return (module_spec);
-}
-
-void
-ModuleCCSession::startCheck() {
-    // data available on the command channel.  process it in the synchronous
-    // mode.
-    checkCommand();
-
-    // start asynchronous read again.
-    session_.startRead(boost::bind(&ModuleCCSession::startCheck, this));
-}
-
-ModuleCCSession::ModuleCCSession(
-    const std::string& spec_file_name,
-    isc::cc::AbstractSession& session,
-    isc::data::ConstElementPtr(*config_handler)(
-        isc::data::ConstElementPtr new_config),
-    isc::data::ConstElementPtr(*command_handler)(
-        const std::string& command, isc::data::ConstElementPtr args),
-    bool start_immediately,
-    bool handle_logging
-    ) :
-    started_(false),
-    session_(session)
-{
-    module_specification_ = readModuleSpecification(spec_file_name);
-    setModuleSpec(module_specification_);
-
-    module_name_ = module_specification_.getFullSpec()->get("module_name")->stringValue();
-    config_handler_ = config_handler;
-    command_handler_ = command_handler;
-
-    session_.establish(NULL);
-    session_.subscribe(module_name_, "*");
-
-    // send the data specification
-    ConstElementPtr spec_msg = createCommand("module_spec",
-                                             module_specification_.getFullSpec());
-    unsigned int seq = session_.group_sendmsg(spec_msg, "ConfigManager");
-
-    ConstElementPtr answer, env;
-    session_.group_recvmsg(env, answer, false, seq);
-    int rcode = -1;
-    ConstElementPtr err = parseAnswer(rcode, answer);
-    if (rcode != 0) {
-        LOG_ERROR(config_logger, CONFIG_MOD_SPEC_REJECT).arg(answer->str());
-        isc_throw(CCSessionInitError, answer->str());
-    }
-
-    setLocalConfig(Element::createMap());
-    // get any stored configuration from the manager
-    if (config_handler_) {
-        ConstElementPtr cmd =
-            createCommand("get_config",
-                          Element::fromJSON("{\"module_name\":\"" +
-                                            module_name_ + "\"}"));
-        seq = session_.group_sendmsg(cmd, "ConfigManager");
-        session_.group_recvmsg(env, answer, false, seq);
-        ConstElementPtr new_config = parseAnswer(rcode, answer);
-        if (rcode == 0) {
-            handleConfigUpdate(new_config);
-        } else {
-            LOG_ERROR(config_logger, CONFIG_GET_FAIL).arg(new_config->str());
-            isc_throw(CCSessionInitError, answer->str());
-        }
-    }
-
-    // Keep track of logging settings automatically
-    if (handle_logging) {
-        addRemoteConfig("Logging", default_logconfig_handler, false);
-    }
-
-    if (start_immediately) {
-        start();
-    }
-
-}
-
-ModuleCCSession::~ModuleCCSession() {
-    try {
-        sendStopping();
-    } catch (const std::exception& exc) {
-        LOG_ERROR(config_logger,
-                  CONFIG_CCSESSION_STOPPING).arg(exc.what());
-    } catch (...) {
-        LOG_ERROR(config_logger,
-                  CONFIG_CCSESSION_STOPPING_UNKNOWN);
-    }
-};
-
-void
-ModuleCCSession::start() {
-    if (started_) {
-        isc_throw(CCSessionError, "Module CC session already started");
-    }
-
-    // register callback for asynchronous read
-    session_.startRead(boost::bind(&ModuleCCSession::startCheck, this));
-
-    started_ = true;
-}
-
-/// Validates the new config values, if they are correct,
-/// call the config handler with the values that have changed
-/// If that results in success, store the new config
-ConstElementPtr
-ModuleCCSession::handleConfigUpdate(ConstElementPtr new_config) {
-    ConstElementPtr answer;
-    ElementPtr errors = Element::createList();
-    if (!config_handler_) {
-        answer = createAnswer(1, module_name_ + " does not have a config handler");
-    } else if (!module_specification_.validateConfig(new_config, false,
-                                                      errors)) {
-        std::stringstream ss;
-        ss << "Error in config validation: ";
-        BOOST_FOREACH(ConstElementPtr error, errors->listValue()) {
-            ss << error->stringValue();
-        }
-        answer = createAnswer(2, ss.str());
-    } else {
-        // remove the values that have not changed
-        ConstElementPtr diff = removeIdentical(new_config, getLocalConfig());
-        // handle config update
-        answer = config_handler_(diff);
-        int rcode = -1;
-        parseAnswer(rcode, answer);
-        if (rcode == 0) {
-            ElementPtr local_config = getLocalConfig();
-            isc::data::merge(local_config, diff);
-            setLocalConfig(local_config);
-        }
-    }
-    return (answer);
-}
-
-bool
-ModuleCCSession::hasQueuedMsgs() const {
-    return (session_.hasQueuedMsgs());
-}
-
-ConstElementPtr
-ModuleCCSession::checkConfigUpdateCommand(const std::string& target_module,
-                                          ConstElementPtr arg)
-{
-    if (target_module == module_name_) {
-        return (handleConfigUpdate(arg));
-    } else {
-        // ok this update is not for us, if we have this module
-        // in our remote config list, update that
-        updateRemoteConfig(target_module, arg);
-        // we're not supposed to answer to this, so return
-        return (ElementPtr());
-    }
-}
-
-ConstElementPtr
-ModuleCCSession::checkModuleCommand(const std::string& cmd_str,
-                                    const std::string& target_module,
-                                    ConstElementPtr arg) const
-{
-    if (target_module == module_name_) {
-        if (command_handler_) {
-            ElementPtr errors = Element::createList();
-            if (module_specification_.validateCommand(cmd_str,
-                                                       arg,
-                                                       errors)) {
-                return (command_handler_(cmd_str, arg));
-            } else {
-                std::stringstream ss;
-                ss << "Error in command validation: ";
-                BOOST_FOREACH(ConstElementPtr error,
-                              errors->listValue()) {
-                    ss << error->stringValue();
-                }
-                return (createAnswer(3, ss.str()));
-            }
-        } else {
-            return (createAnswer(1,
-                                 "Command given but no "
-                                 "command handler for module"));
-        }
-    } else if (unhandled_callback_) {
-        unhandled_callback_(cmd_str, target_module, arg);
-    }
-    return (ElementPtr());
-}
-
-int
-ModuleCCSession::checkCommand() {
-    ConstElementPtr cmd, routing, data;
-    if (session_.group_recvmsg(routing, data, true)) {
-
-        // In case the message is wanted asynchronously, it gets used.
-        if (checkAsyncRecv(routing, data)) {
-            return (0);
-        }
-
-        // In case it is notification, eat it.
-        if (checkNotification(routing, data)) {
-            return (0);
-        }
-
-        /* ignore result messages (in case we're out of sync, to prevent
-         * pingpongs */
-        if (data->getType() != Element::map ||
-            data->contains(isc::cc::CC_PAYLOAD_RESULT)) {
-            return (0);
-        }
-        ConstElementPtr arg;
-        ConstElementPtr answer;
-        try {
-            std::string cmd_str = parseCommand(arg, data);
-            std::string target_module =
-                routing->get(isc::cc::CC_HEADER_GROUP)->stringValue();
-            if (cmd_str == "config_update") {
-                answer = checkConfigUpdateCommand(target_module, arg);
-            } else {
-                answer = checkModuleCommand(cmd_str, target_module, arg);
-            }
-        } catch (const CCSessionError& re) {
-            LOG_ERROR(config_logger, CONFIG_CCSESSION_MSG).arg(re.what());
-        } catch (const std::exception& stde) {
-            // No matter what unexpected error happens, we do not want
-            // to crash because of an incoming event, so we log the
-            // exception and continue to run
-            LOG_ERROR(config_logger, CONFIG_CCSESSION_MSG_INTERNAL).arg(stde.what());
-        }
-        if (!isNull(answer)) {
-            session_.reply(routing, answer);
-        }
-    }
-
-    return (0);
-}
-
-ModuleSpec
-ModuleCCSession::fetchRemoteSpec(const std::string& module, bool is_filename) {
-    if (is_filename) {
-        // It is a filename, simply load it.
-        return (readModuleSpecification(module));
-    } else {
-        // It's module name, request it from config manager
-
-        // Send the command
-        ConstElementPtr cmd(createCommand("get_module_spec",
-                            Element::fromJSON("{\"module_name\": \"" + module +
-                                              "\"}")));
-        unsigned int seq = session_.group_sendmsg(cmd, "ConfigManager");
-        ConstElementPtr env, answer;
-        session_.group_recvmsg(env, answer, false, seq);
-        int rcode = -1;
-        ConstElementPtr spec_data = parseAnswer(rcode, answer);
-        if (rcode == 0 && spec_data) {
-            // received OK, construct the spec out of it
-            ModuleSpec spec = ModuleSpec(spec_data);
-            if (module != spec.getModuleName()) {
-                // It's a different module!
-                isc_throw(CCSessionError, "Module name mismatch");
-            }
-            return (spec);
-        } else {
-            isc_throw(CCSessionError, "Error getting config for " +
-                      module + ": " + answer->str());
-        }
-    }
-}
-
-std::string
-ModuleCCSession::addRemoteConfig(const std::string& spec_name,
-                                 RemoteHandler handler,
-                                 bool spec_is_filename)
-{
-    // First get the module name, specification and default config
-    const ModuleSpec rmod_spec(fetchRemoteSpec(spec_name, spec_is_filename));
-    const std::string module_name(rmod_spec.getModuleName());
-    ConfigData rmod_config(rmod_spec);
-
-    // Get the current configuration values from config manager
-    ConstElementPtr cmd(createCommand("get_config",
-                        Element::fromJSON("{\"module_name\": \"" +
-                                          module_name + "\"}")));
-    const unsigned int seq = session_.group_sendmsg(cmd, "ConfigManager");
-
-    ConstElementPtr env, answer;
-    session_.group_recvmsg(env, answer, false, seq);
-    int rcode = -1;
-    ConstElementPtr new_config = parseAnswer(rcode, answer);
-    ElementPtr local_config;
-    if (rcode == 0 && new_config) {
-        // Merge the received config into existing local config
-        local_config = rmod_config.getLocalConfig();
-        isc::data::merge(local_config, new_config);
-        rmod_config.setLocalConfig(local_config);
-    } else {
-        isc_throw(CCSessionError, "Error getting config for " + module_name + ": " + answer->str());
-    }
-
-    // all ok, add it
-    remote_module_configs_[module_name] = rmod_config;
-    if (handler) {
-        remote_module_handlers_[module_name] = handler;
-        handler(module_name, local_config, rmod_config);
-    }
-
-    // Make sure we get updates in future
-    session_.subscribe(module_name);
-    return (module_name);
-}
-
-void
-ModuleCCSession::removeRemoteConfig(const std::string& module_name) {
-    std::map<std::string, ConfigData>::iterator it;
-
-    it = remote_module_configs_.find(module_name);
-    if (it != remote_module_configs_.end()) {
-        remote_module_configs_.erase(it);
-        remote_module_handlers_.erase(module_name);
-        session_.unsubscribe(module_name);
-    }
-}
-
-ConstElementPtr
-ModuleCCSession::getRemoteConfigValue(const std::string& module_name,
-                                      const std::string& identifier) const
-{
-    std::map<std::string, ConfigData>::const_iterator it =
-        remote_module_configs_.find(module_name);
-
-    if (it != remote_module_configs_.end()) {
-        return ((*it).second.getValue(identifier));
-    } else {
-        isc_throw(CCSessionError,
-                  "Remote module " + module_name + " not found.");
-    }
-}
-
-void
-ModuleCCSession::updateRemoteConfig(const std::string& module_name,
-                                    ConstElementPtr new_config)
-{
-    std::map<std::string, ConfigData>::iterator it;
-
-    it = remote_module_configs_.find(module_name);
-    if (it != remote_module_configs_.end()) {
-        ElementPtr rconf = (*it).second.getLocalConfig();
-        isc::data::merge(rconf, new_config);
-        std::map<std::string, RemoteHandler>::iterator hit =
-            remote_module_handlers_.find(module_name);
-        if (hit != remote_module_handlers_.end()) {
-            hit->second(module_name, new_config, it->second);
-        }
-    }
-}
-
-void
-ModuleCCSession::sendStopping() {
-    // Inform the configuration manager that this module is stopping
-    ConstElementPtr cmd(createCommand("stopping",
-                                      Element::fromJSON(
-                                          "{\"module_name\": \"" +
-                                          module_name_ + "\"}")));
-    // It's just an FYI, configmanager is not expected to respond.
-    session_.group_sendmsg(cmd, "ConfigManager");
-}
-
-class ModuleCCSession::AsyncRecvRequest {
-public: // Everything is public here, as the definition is hidden anyway
-    AsyncRecvRequest(const AsyncRecvCallback& cb, const string& rcp, int sq,
-                     bool reply) :
-        callback(cb),
-        recipient(rcp),
-        seq(sq),
-        is_reply(reply)
-    {}
-    const AsyncRecvCallback callback;
-    const string recipient;
-    const int seq;
-    const bool is_reply;
-};
-
-ModuleCCSession::AsyncRecvRequestID
-ModuleCCSession::groupRecvMsgAsync(const AsyncRecvCallback& callback,
-                                   bool is_reply, int seq,
-                                   const string& recipient) {
-    // This just stores the request, the handling is done in checkCommand()
-
-    // push_back would be simpler, but it does not return the iterator we need
-    return (async_recv_requests_.insert(async_recv_requests_.end(),
-                                        AsyncRecvRequest(callback, recipient,
-                                                         seq, is_reply)));
-}
-
-bool
-ModuleCCSession::checkAsyncRecv(const ConstElementPtr& envelope,
-                                const ConstElementPtr& msg)
-{
-    for (AsyncRecvRequestID request(async_recv_requests_.begin());
-         request != async_recv_requests_.end(); ++request) {
-        // Just go through all the requests and look for a matching one
-        if (requestMatch(*request, envelope)) {
-            // We want the request to be still alive at the time we
-            // call the callback. But we need to remove it on an exception
-            // too, so we use the class. If just C++ had the finally keyword.
-            class RequestDeleter {
-            public:
-                RequestDeleter(AsyncRecvRequests& requests,
-                               AsyncRecvRequestID& request) :
-                    requests_(requests),
-                    request_(request)
-                { }
-                ~RequestDeleter() {
-                    requests_.erase(request_);
-                }
-            private:
-                AsyncRecvRequests& requests_;
-                AsyncRecvRequestID& request_;
-            };
-            RequestDeleter deleter(async_recv_requests_, request);
-            // Call the callback
-            request->callback(envelope, msg, request);
-            return (true);
-        }
-    }
-    return (false);
-}
-
-bool
-ModuleCCSession::requestMatch(const AsyncRecvRequest& request,
-                              const ConstElementPtr& envelope) const
-{
-    if (request.is_reply != envelope->contains(isc::cc::CC_HEADER_REPLY)) {
-        // Wrong type of message
-        return (false);
-    }
-    if (request.is_reply &&
-        (request.seq == -1 ||
-         request.seq == envelope->get(isc::cc::CC_HEADER_REPLY)->intValue())) {
-        // This is the correct reply
-        return (true);
-    }
-    if (!request.is_reply &&
-        (request.recipient.empty() || request.recipient ==
-         envelope->get(isc::cc::CC_HEADER_GROUP)->stringValue())) {
-        // This is the correct command
-        return (true);
-    }
-    // If nothing from the above, we don't want it
-    return (false);
-}
-
-void
-ModuleCCSession::cancelAsyncRecv(const AsyncRecvRequestID& id) {
-    async_recv_requests_.erase(id);
-}
-
-ConstElementPtr
-ModuleCCSession::rpcCall(const std::string &command, const std::string &group,
-                         const std::string &instance, const std::string &to,
-                         const ConstElementPtr &params)
-{
-    ConstElementPtr command_el(createCommand(command, params));
-    const int seq = groupSendMsg(command_el, group, instance, to, true);
-    ConstElementPtr env, answer;
-    LOG_DEBUG(config_logger, DBGLVL_TRACE_DETAIL, CONFIG_RPC_SEQ).arg(command).
-        arg(group).arg(seq);
-    groupRecvMsg(env, answer, true, seq);
-    int rcode;
-    const ConstElementPtr result(parseAnswer(rcode, answer));
-    if (rcode == isc::cc::CC_REPLY_NO_RECPT) {
-        isc_throw(RPCRecipientMissing, result);
-    } else if (rcode != isc::cc::CC_REPLY_SUCCESS) {
-        isc_throw_1(RPCError, result, rcode);
-    } else {
-        return (result);
-    }
-}
-
-void
-ModuleCCSession::notify(const std::string& group, const std::string& name,
-                        const ConstElementPtr& params)
-{
-    const ElementPtr message(Element::createMap());
-    const ElementPtr notification(Element::createList());
-    notification->add(Element::create(name));
-    if (params) {
-        notification->add(params);
-    }
-    message->set(isc::cc::CC_PAYLOAD_NOTIFICATION, notification);
-    groupSendMsg(message, isc::cc::CC_GROUP_NOTIFICATION_PREFIX + group,
-                 isc::cc::CC_INSTANCE_WILDCARD,
-                 isc::cc::CC_TO_WILDCARD, false);
-}
-
-ModuleCCSession::NotificationID
-ModuleCCSession::subscribeNotification(const std::string& notification_group,
-                                       const NotificationCallback& callback)
-{
-    // Either insert a new empty list of callbacks or get an existing one.
-    // Either way, get the iterator for its position.
-    const std::pair<SubscribedNotifications::iterator, bool>& inserted =
-        notifications_.insert(
-            std::pair<std::string, NotificationCallbacks>(notification_group,
-                NotificationCallbacks()));
-    if (inserted.second) {
-        // It was newly inserted. In that case, we need to subscribe to the
-        // group.
-        session_.subscribe(isc::cc::CC_GROUP_NOTIFICATION_PREFIX +
-                           notification_group);
-    }
-    // Insert the callback to the chain
-    NotificationCallbacks& callbacks = inserted.first->second;
-    const NotificationCallbacks::iterator& callback_id =
-        callbacks.insert(callbacks.end(), callback);
-    // Just pack the iterators to form the ID
-    return (NotificationID(inserted.first, callback_id));
-}
-
-void
-ModuleCCSession::unsubscribeNotification(const NotificationID& notification) {
-    NotificationCallbacks& callbacks = notification.first->second;
-    // Remove the callback
-    callbacks.erase(notification.second);
-    // If it became empty, remove it from the map and unsubscribe
-    if (callbacks.empty()) {
-        session_.unsubscribe(isc::cc::CC_GROUP_NOTIFICATION_PREFIX +
-                             notification.first->first);
-        notifications_.erase(notification.first);
-    }
-}
-
-bool
-ModuleCCSession::checkNotification(const data::ConstElementPtr& envelope,
-                                   const data::ConstElementPtr& msg)
-{
-    if (msg->getType() != data::Element::map) {
-        // If it's not a map, then it's not a notification
-        return (false);
-    }
-    if (msg->contains(isc::cc::CC_PAYLOAD_NOTIFICATION)) {
-        // There's a notification inside. Extract its parameters.
-        const std::string& group =
-            envelope->get(isc::cc::CC_HEADER_GROUP)->stringValue();
-        const std::string& notification_group =
-            group.substr(std::string(isc::cc::CC_GROUP_NOTIFICATION_PREFIX).
-                         size());
-        const data::ConstElementPtr& notification =
-            msg->get(isc::cc::CC_PAYLOAD_NOTIFICATION);
-        // The first one is the event that happened
-        const std::string& event = notification->get(0)->stringValue();
-        // Any other params are second. But they may be missing
-        const data::ConstElementPtr params =
-            notification->size() == 1 ? data::ConstElementPtr() :
-            notification->get(1);
-        // Find the chain of notification callbacks
-        const SubscribedNotifications::iterator& chain_iter =
-            notifications_.find(notification_group);
-        if (chain_iter == notifications_.end()) {
-            // This means we no longer have any notifications for this group.
-            // This can happen legally as a race condition - if msgq sends
-            // us a notification, but we unsubscribe before we get to it
-            // in the input stream.
-            return (false);
-        }
-        BOOST_FOREACH(const NotificationCallback& callback,
-                      chain_iter->second) {
-            callback(event, params);
-        }
-        return (true);
-    }
-    return (false); // Not a notification
-}
-
 }
 }

+ 27 - 574
src/lib/config/ccsession.h

@@ -18,7 +18,6 @@
 #include <config/config_data.h>
 #include <config/module_spec.h>
 
-#include <cc/session.h>
 #include <cc/data.h>
 #include <cc/proto_defs.h>
 
@@ -138,143 +137,6 @@ public:
         isc::Exception(file, line, what) {}
 };
 
-///
-/// \brief This exception is thrown if the constructor fails
-///
-class CCSessionInitError : public isc::Exception {
-public:
-    CCSessionInitError(const char* file, size_t line, const char* what) :
-        isc::Exception(file, line, what) {}
-};
-
-/// \brief Exception thrown when there's a problem with the remote call.
-///
-/// This usually means either the command couldn't be called or the remote
-/// side sent an error as a response.
-class RPCError: public CCSessionError {
-public:
-    RPCError(const char* file, size_t line, const char* what, int rcode) :
-        CCSessionError(file, line, what),
-        rcode_(rcode)
-    {}
-
-    /// \brief The error code for the error.
-    int rcode() const {
-        return (rcode_);
-    }
-private:
-    const int rcode_;
-};
-
-/// \brief Specific version of RPCError for the case the recipient of command
-///     doesn't exist.
-class RPCRecipientMissing: public RPCError {
-public:
-    RPCRecipientMissing(const char* file, size_t line, const char* what) :
-        RPCError(file, line, what, isc::cc::CC_REPLY_NO_RECPT)
-    {}
-};
-
-///
-/// \brief This module keeps a connection to the command channel,
-/// holds configuration information, and handles messages from
-/// the command channel
-///
-class ModuleCCSession : public ConfigData {
-public:
-    /**
-     * Initialize a config/command session
-     *
-     * @param spec_file_name The name of the file containing the
-     *                        module specification.
-     * @param session A Session object over which configuration and command
-     * data are exchanged.
-     * @param config_handler A callback function pointer to be called when
-     * configuration of the local module needs to be updated.
-     * This must refer to a valid object of a concrete derived class of
-     * AbstractSession without establishing the session.
-     *
-     * Note: the design decision on who is responsible for establishing the
-     * session is in flux, and may change in near future.
-     *
-     * \exception CCSessionInitError when the initialization fails,
-     *            either because the file cannot be read or there is
-     *            a communication problem with the config manager.
-     *
-     * @param command_handler A callback function pointer to be called when
-     * a control command from a remote agent needs to be performed on the
-     * local module.
-     * @param start_immediately If true (default), start listening to new commands
-     * and configuration changes asynchronously at the end of the constructor;
-     * if false, it will be delayed until the start() method is explicitly
-     * called. (This is a short term workaround for an initialization trouble.
-     * We'll need to develop a cleaner solution, and then remove this knob)
-     * @param handle_logging If true, the ModuleCCSession will automatically
-     * take care of logging configuration through the virtual Logging config
-     * module. Defaults to true.
-     */
-    ModuleCCSession(const std::string& spec_file_name,
-                    isc::cc::AbstractSession& session,
-                    isc::data::ConstElementPtr(*config_handler)(
-                        isc::data::ConstElementPtr new_config) = NULL,
-                    isc::data::ConstElementPtr(*command_handler)(
-                        const std::string& command,
-                        isc::data::ConstElementPtr args) = NULL,
-                    bool start_immediately = true,
-                    bool handle_logging = true
-                    );
-
-    ///
-    /// Destructor
-    ///
-    /// The destructor automatically calls sendStopping(), which sends
-    /// a message to the ConfigManager that this module is stopping
-    ///
-    virtual ~ModuleCCSession();
-
-    /// Start receiving new commands and configuration changes asynchronously.
-    ///
-    /// This method must be called only once, and only when the ModuleCCSession
-    /// was constructed with start_immediately being false.  Otherwise
-    /// CCSessionError will be thrown.
-    ///
-    /// As noted in the constructor, this method should be considered a short
-    /// term workaround and will be removed in future.
-    void start();
-
-    /**
-     * Optional optimization for checkCommand loop; returns true
-     * if there are unhandled queued messages in the cc session.
-     * (if either this is true or there is data on the socket found
-     * by the select() call on getSocket(), run checkCommand())
-     * 
-     * @return true if there are unhandled queued messages
-     */
-    bool hasQueuedMsgs() const;
-
-    /**
-     * Check if there is a command or config change on the command
-     * session. If so, the appropriate handler is called if set.
-     * If not set, a default answer is returned.
-     * This is a non-blocking read; if there is nothing this function
-     * will return 0.
-     */
-    int checkCommand();
-
-    /**
-     * The config handler function should expect an ElementPtr containing
-     * the full configuration where non-default values have been set.
-     * Later we might want to think about more granular control
-     * (i.e. this does not scale to for instance lists containing
-     * 100000 zones, where the whole list is passed every time a single
-     * thing changes)
-     */
-    void setConfigHandler(isc::data::ConstElementPtr(*config_handler)(
-                              isc::data::ConstElementPtr new_config))
-    {
-        config_handler_ = config_handler;
-    }
-
     /**
      * Set a command handler; the function that is passed takes an
      * ElementPtr, pointing to a list element, containing
@@ -287,10 +149,7 @@ public:
      */
     void setCommandHandler(isc::data::ConstElementPtr(*command_handler)(
                                const std::string& command,
-                               isc::data::ConstElementPtr args))
-    {
-        command_handler_ = command_handler;
-    }
+                               isc::data::ConstElementPtr args));
 
     /**
      * Gives access to the configuration values of a different module
@@ -328,252 +187,6 @@ public:
     typedef boost::function<void(const std::string&,
                                  isc::data::ConstElementPtr,
                                  const ConfigData&)> RemoteHandler;
-    std::string addRemoteConfig(const std::string& spec_name,
-                                RemoteHandler handler = RemoteHandler(),
-                                bool spec_is_filename = true);
-
-    /**
-     * Removes the module with the given name from the remote config
-     * settings. If the module was not added with \c addRemoteConfig(),
-     * nothing happens. If there was a handler for this config, it is
-     * removed as well.
-     */
-    void removeRemoteConfig(const std::string& module_name);
-
-    /**
-     * Returns the current configuration value for the given module
-     * name at the given identifier. See \c ConfigData::getValue() for
-     * more details.
-     * Raises a ModuleCCSessionError if the module name is unknown
-     * Raises a DataNotFoundError if the identifier does not exist
-     * in the specification.
-     *
-     * \param module_name The name of the module to get a config value for
-     * \param identifier The identifier of the config value
-     * \return The configuration setting at the given identifier
-     */
-    isc::data::ConstElementPtr getRemoteConfigValue(
-        const std::string& module_name,
-        const std::string& identifier) const;
-
-    /**
-     * Send a message to the underlying CC session.
-     * This has the same interface as isc::cc::Session::group_sendmsg()
-     *
-     * \param msg see isc::cc::Session::group_sendmsg()
-     * \param group see isc::cc::Session::group_sendmsg()
-     * \param instance see isc::cc::Session::group_sendmsg()
-     * \param to see isc::cc::Session::group_sendmsg()
-     * \param want_answer see isc::cc::Session::group_sendmsg()
-     * \return see isc::cc::Session::group_sendmsg()
-     */
-    int groupSendMsg(isc::data::ConstElementPtr msg,
-                     std::string group,
-                     std::string instance = isc::cc::CC_INSTANCE_WILDCARD,
-                     std::string to = isc::cc::CC_TO_WILDCARD,
-                     bool want_answer = false) {
-        return (session_.group_sendmsg(msg, group, instance, to, want_answer));
-    };
-
-    /// \brief Receive a message from the underlying CC session.
-    /// This has the same interface as isc::cc::Session::group_recvmsg()
-    ///
-    /// NOTE: until #2804 is resolved this method wouldn't work except in
-    /// very limited cases; don't try to use it until then.
-    ///
-    /// \param envelope see isc::cc::Session::group_recvmsg()
-    /// \param msg see isc::cc::Session::group_recvmsg()
-    /// \param nonblock see isc::cc::Session::group_recvmsg()
-    /// \param seq see isc::cc::Session::group_recvmsg()
-    /// \return see isc::cc::Session::group_recvmsg()
-    bool groupRecvMsg(isc::data::ConstElementPtr& envelope,
-                      isc::data::ConstElementPtr& msg,
-                      bool nonblock = true,
-                      int seq = -1) {
-        return (session_.group_recvmsg(envelope, msg, nonblock, seq));
-    }
-
-    /// \brief Send a command message and wait for the answer.
-    ///
-    /// NOTE: until #2804 is resolved this method wouldn't work except in
-    /// very limited cases; don't try to use it until then.
-    ///
-    /// This is mostly a convenience wrapper around groupSendMsg
-    /// and groupRecvMsg, with some error handling.
-    ///
-    /// \param command Name of the command to call.
-    /// \param group Name of the remote module to call the command on.
-    /// \param instance Instance part of recipient address.
-    /// \param to The lname to send it to. Can be used to override the
-    ///     addressing and use a direct recipient.
-    /// \param params Parameters for the command. Can be left NULL if
-    ///     no parameters are needed.
-    /// \return Return value of the successfull remote call. It can be
-    ///     NULL if the remote command is void function (returns nothing).
-    /// \throw RPCError if the call fails (for example when the other
-    ///     side responds with error code).
-    /// \throw RPCRecipientMissing if the recipient doesn't exist.
-    /// \throw CCSessionError if some lower-level error happens (eg.
-    ///     the response was malformed).
-    isc::data::ConstElementPtr rpcCall(const std::string& command,
-                                       const std::string& group,
-                                       const std::string& instance =
-                                           isc::cc::CC_INSTANCE_WILDCARD,
-                                       const std::string& to =
-                                           isc::cc::CC_TO_WILDCARD,
-                                       const isc::data::ConstElementPtr&
-                                           params =
-                                           isc::data::ConstElementPtr());
-
-    /// \brief Send a notification to subscribed users
-    ///
-    /// Send a notification message to all users subscribed to the given
-    /// notification group.
-    ///
-    /// This method does not not block.
-    ///
-    /// See docs/design/ipc-high.txt for details about notifications and
-    /// the format of messages sent.
-    ///
-    /// \throw CCSessionError for low-level communication errors.
-    /// \param notification_group This parameter (indirectly) signifies what
-    ///     users should receive the notification. Only the users that
-    ///     subscribed to notifications on the same group receive it.
-    /// \param name The name of the event to notify about (for example
-    ///     `new_group_member`).
-    /// \param params Other parameters that describe the event. This might
-    ///     be, for example, the ID of the new member and the name of the
-    ///     group. This can be any data element, but it is common for it to be
-    ///     map.
-    void notify(const std::string& notification_group,
-                const std::string& name,
-                const isc::data::ConstElementPtr& params =
-                    isc::data::ConstElementPtr());
-
-    /// \brief Convenience version of rpcCall
-    ///
-    /// This is exactly the same as the previous version of rpcCall, except
-    /// that the instance and to parameters are at their default. This
-    /// allows to sending a command with parameters to a named module
-    /// without long typing of the parameters.
-    isc::data::ConstElementPtr rpcCall(const std::string& command,
-                                       const std::string& group,
-                                       const isc::data::ConstElementPtr&
-                                           params)
-    {
-        return rpcCall(command, group, isc::cc::CC_INSTANCE_WILDCARD,
-                       isc::cc::CC_TO_WILDCARD, params);
-    }
-
-    /// \brief Forward declaration of internal data structure.
-    ///
-    /// This holds information about one asynchronous request to receive
-    /// a message. It is declared as public to allow declaring other derived
-    /// types, but without showing the internal representation.
-    class AsyncRecvRequest;
-
-    /// \brief List of all requests for asynchronous reads.
-    typedef std::list<AsyncRecvRequest> AsyncRecvRequests;
-
-    /// \brief Identifier of single request for asynchronous read.
-    typedef AsyncRecvRequests::iterator AsyncRecvRequestID;
-
-    /// \brief Callback which is called when an asynchronous receive finishes.
-    ///
-    /// This is the callback used by groupRecvMsgAsync() function. It is called
-    /// when a matching message arrives. It receives following parameters when
-    /// called:
-    /// - The envelope of the message
-    /// - The message itself
-    /// - The ID of the request, as returned by corresponding groupRecvMsgAsync
-    ///   call.
-    ///
-    /// It is possible to throw exceptions from the callback, but they will not
-    /// be caught and they will get propagated out through the checkCommand()
-    /// call. This, if not handled on higher level, will likely terminate the
-    /// application. However, the ModuleCCSession internals will be in
-    /// well-defined state after the call (both the callback and the message
-    /// will be removed from the queues as already called).
-    typedef boost::function3<void, const isc::data::ConstElementPtr&,
-                             const isc::data::ConstElementPtr&,
-                             const AsyncRecvRequestID&>
-        AsyncRecvCallback;
-
-    /// \brief Receive a message from the CC session asynchronously.
-    ///
-    /// This registers a callback which is called when a matching message
-    /// is received. This message returns immediately.
-    ///
-    /// Once a matching message arrives, the callback is called with the
-    /// envelope of the message, the message itself and the result of this
-    /// function call (which might be useful for identifying which of many
-    /// events the recipient is waiting for this is). This makes the callback
-    /// used and is not called again even if a message that would match
-    /// arrives later (this is a single-shot callback).
-    ///
-    /// The callback is never called from within this function. Even if there
-    /// are queued messages, the callback would be called once checkCommand()
-    /// is invoked (possibly from start() or the constructor).
-    ///
-    /// The matching is as follows. If is_reply is true, only replies are
-    /// considered. In that case, if seq is -1, any reply is accepted. If
-    /// it is something else than -1, only the reply with matching seq is
-    /// taken. This may be used to receive replies to commands
-    /// asynchronously.
-    ///
-    /// In case the is_reply is false, the function looks for command messages.
-    /// The seq parameter is ignored, but the recipient one is considered. If
-    /// it is an empty string, any command is taken. If it is non-empty, only
-    /// commands addressed to the recipient channel (eg. group - instance is
-    /// ignored for now) are taken. This can be used to receive foreign commands
-    /// or notifications. In such case, it might be desirable to call the
-    /// groupRecvMsgAsync again from within the callback, to receive any future
-    /// commands or events of the same type.
-    ///
-    /// The interaction with other receiving functions is slightly complicated.
-    /// The groupRecvMsg call takes precedence. If the message matches its
-    /// parameters, it steals the message and no callback matching it as well
-    /// is called. Then, all the queued asynchronous receives are considered,
-    /// with the oldest active ones taking precedence (they work as FIFO).
-    /// If none of them matches, generic command and config handling takes
-    /// place. If it is not handled by that, the message is dropped. However,
-    /// it is better if there's just one place that wants to receive each given
-    /// message.
-    ///
-    /// \exception std::bad_alloc if there isn't enough memory to store the
-    ///     callback.
-    /// \param callback is the function to be called when a matching message
-    ///     arrives.
-    /// \param is_reply specifies if the desired message should be a reply or
-    ///     a command.
-    /// \param seq specifies the reply sequence number in case a reply is
-    ///     desired. The default -1 means any reply is OK.
-    /// \param recipient is the CC channel to which the command should be
-    ///     addressed to match (in case is_reply is false). Empty means any
-    ///     command is good one.
-    /// \return An identifier of the request. This will be passed to the
-    ///     callback or can be used to cancel the request by cancelAsyncRecv.
-    /// \todo Decide what to do with instance and what was it meant for anyway.
-    AsyncRecvRequestID groupRecvMsgAsync(const AsyncRecvCallback& callback,
-                                         bool is_reply, int seq = -1,
-                                         const std::string& recipient =
-                                         std::string());
-
-    /// \brief Removes yet unused request for asynchronous receive.
-    ///
-    /// This function cancels a request previously queued by
-    /// groupRecvMsgAsync(). You may use it only before the callback was
-    /// already triggered. If you call it with an ID of callback that
-    /// already happened or was already canceled, the behaviour is undefined
-    /// (but something like a crash is very likely, as the function removes
-    /// an item from a list and this would be removing it from a list that
-    /// does not contain the item).
-    ///
-    /// It is important to cancel requests that are no longer going to happen
-    /// for some reason, as the request would occupy memory forever.
-    ///
-    /// \param id The id of request as returned by groupRecvMsgAsync.
-    void cancelAsyncRecv(const AsyncRecvRequestID& id);
 
     /// \brief Called when a notification comes
     ///
@@ -591,198 +204,38 @@ public:
     /// \brief Multiple notification callbacks for the same notification
     typedef std::list<NotificationCallback> NotificationCallbacks;
 
-    /// \brief Mapping from groups to callbacks
-    typedef std::map<std::string, NotificationCallbacks>
-        SubscribedNotifications;
-
-    /// \brief Identification of single callback
-    typedef std::pair<SubscribedNotifications::iterator,
-                      NotificationCallbacks::iterator>
-        NotificationID;
-
-    /// \brief Subscribe to a notification group
+    /// \brief Returns the loggers related to this module
     ///
-    /// From now on, every notification that is sent to the given group
-    /// triggers the passed callback.
+    /// This function does two things;
+    /// - it drops the configuration parts for loggers for other modules.
+    /// - it replaces the '*' in the name of the loggers by the name of
+    ///   this module, but *only* if the expanded name is not configured
+    ///   explicitly.
     ///
-    /// There may be multiple (independent) callbacks for the same channel.
-    /// This one adds a new one, to the end of the chain (the callbacks
-    /// are called in the same order as they were registered).
+    /// Examples: if this is the module b10-resolver,
+    /// For the config names ['*', 'b10-auth']
+    /// The '*' is replaced with 'b10-resolver', and this logger is used.
+    /// 'b10-auth' is ignored (of course, it will not be in the b10-auth
+    /// module).
     ///
-    /// \param notification_group The channel of notifications.
-    /// \param callback The callback to be added.
-    /// \return ID of the notification callback. It is an opaque ID and can
-    ///     be used to remove this callback.
-    NotificationID subscribeNotification(const std::string& notification_group,
-                                         const NotificationCallback& callback);
-
-    /// \brief Unsubscribe the callback from its notification group.
+    /// For ['*', 'b10-resolver']
+    /// The '*' is ignored, and only 'b10-resolver' is used.
     ///
-    /// Express that the desire for this callback to be executed is no longer
-    /// relevant. All the other callbacks (even for the same notification
-    /// group) are left intact.
+    /// For ['*.reslib', 'b10-resolver']
+    /// Or ['b10-resolver.reslib', '*']
+    /// Both are used, where the * will be expanded to b10-resolver
     ///
-    /// \param notification The ID of notification callback returned by
-    ///     subscribeNotification.
-    void unsubscribeNotification(const NotificationID& notification);
-
-    /// \brief Subscribe to a group
+    /// \note This is a public function at this time, but mostly for
+    /// the purposes of testing. Once we can directly test what loggers
+    /// are running, this function may be moved to the unnamed namespace
     ///
-    /// Wrapper around the CCSession::subscribe.
-    void subscribe(const std::string& group) {
-        session_.subscribe(group, isc::cc::CC_INSTANCE_WILDCARD);
-    }
+    /// \param loggers the original 'loggers' config list
+    /// \return ListElement containing only loggers relevant for this
+    ///         module, where * is replaced by the root logger name
+    isc::data::ConstElementPtr
+    getRelatedLoggers(isc::data::ConstElementPtr loggers);
 
-    /// \brief Unsubscribe from a group.
-    ///
-    /// Wrapper around the CCSession::unsubscribe.
-    void unsubscribe(const std::string& group) {
-        session_.unsubscribe(group, isc::cc::CC_INSTANCE_WILDCARD);
-    }
+}; // end of namespace isc::config
+}; // end of namespace isc
 
-    /// \brief Callback type for unhandled commands
-    ///
-    /// The type of functions that are not handled by the ModuleCCSession
-    /// because they are not aimed at the module.
-    ///
-    /// The parameters are:
-    /// - Name of the command.
-    /// - The module it was aimed for (may be empty).
-    /// - The parameters of the command.
-    typedef boost::function<void (const std::string&, const std::string&,
-                                  const isc::data::ConstElementPtr&)>
-        UnhandledCallback;
-
-    /// \brief Register a callback for messages sent to foreign modules.
-    ///
-    /// Usually, a command aimed at foreign module (or sent directly)
-    /// is discarded. By registering a callback here, these can be
-    /// examined.
-    ///
-    /// \note A callback overwrites the previous one set.
-    /// \todo This is a temporary, unclean, solution. A more generic
-    ///     one needs to be designed. Also, a solution that is able
-    ///     to send an answer would be great.
-    ///
-    /// \param callback The new callback to use. It may be an empty
-    ///     function.
-    void setUnhandledCallback(const UnhandledCallback& callback) {
-        unhandled_callback_ = callback;
-    }
-
-private:
-    ModuleSpec readModuleSpecification(const std::string& filename);
-    void startCheck();
-    void sendStopping();
-    /// \brief Check if the message is wanted by asynchronous read
-    ///
-    /// It checks if any of the previously queued requests match
-    /// the message. If so, the callback is dispatched and removed.
-    ///
-    /// \param envelope The envelope of the message.
-    /// \param msg The actual message data.
-    /// \return True if the message was used for a callback, false
-    ///     otherwise.
-    bool checkAsyncRecv(const data::ConstElementPtr& envelope,
-                        const data::ConstElementPtr& msg);
-    bool checkNotification(const data::ConstElementPtr& envelope,
-                           const data::ConstElementPtr& msg);
-    /// \brief Checks if a message with this envelope matches the request
-    bool requestMatch(const AsyncRecvRequest& request,
-                      const data::ConstElementPtr& envelope) const;
-
-    bool started_;
-    std::string module_name_;
-    isc::cc::AbstractSession& session_;
-    ModuleSpec module_specification_;
-    AsyncRecvRequests async_recv_requests_;
-    SubscribedNotifications notifications_;
-
-    isc::data::ConstElementPtr handleConfigUpdate(
-        isc::data::ConstElementPtr new_config);
-
-    isc::data::ConstElementPtr checkConfigUpdateCommand(
-        const std::string& target_module,
-        isc::data::ConstElementPtr arg);
-
-    isc::data::ConstElementPtr checkModuleCommand(
-        const std::string& cmd_str,
-        const std::string& target_module,
-        isc::data::ConstElementPtr arg) const;
-
-    isc::data::ConstElementPtr(*config_handler_)(
-        isc::data::ConstElementPtr new_config);
-    isc::data::ConstElementPtr(*command_handler_)(
-        const std::string& command,
-        isc::data::ConstElementPtr args);
-
-    std::map<std::string, ConfigData> remote_module_configs_;
-    std::map<std::string, RemoteHandler> remote_module_handlers_;
-
-    void updateRemoteConfig(const std::string& module_name,
-                            isc::data::ConstElementPtr new_config);
-
-    ModuleSpec fetchRemoteSpec(const std::string& module, bool is_filename);
-
-    UnhandledCallback unhandled_callback_;
-};
-
-/// \brief Default handler for logging config updates
-///
-/// When CCSession is initialized with handle_logging set to true,
-/// this callback will be used to update the logger when a configuration
-/// change comes in.
-///
-/// This function updates the (global) loggers by initializing a
-/// LoggerManager and passing the settings as specified in the given
-/// configuration update.
-///
-/// \param module_name The name of the module
-/// \param new_config The modified configuration values
-/// \param config_data The full config data for the (remote) logging
-///                    module.
-void
-default_logconfig_handler(const std::string& module_name,
-                          isc::data::ConstElementPtr new_config,
-                          const ConfigData& config_data);
-
-
-/// \brief Returns the loggers related to this module
-///
-/// This function does two things;
-/// - it drops the configuration parts for loggers for other modules.
-/// - it replaces the '*' in the name of the loggers by the name of
-///   this module, but *only* if the expanded name is not configured
-///   explicitly.
-///
-/// Examples: if this is the module b10-resolver,
-/// For the config names ['*', 'b10-auth']
-/// The '*' is replaced with 'b10-resolver', and this logger is used.
-/// 'b10-auth' is ignored (of course, it will not be in the b10-auth
-/// module).
-///
-/// For ['*', 'b10-resolver']
-/// The '*' is ignored, and only 'b10-resolver' is used.
-///
-/// For ['*.reslib', 'b10-resolver']
-/// Or ['b10-resolver.reslib', '*']
-/// Both are used, where the * will be expanded to b10-resolver
-///
-/// \note This is a public function at this time, but mostly for
-/// the purposes of testing. Once we can directly test what loggers
-/// are running, this function may be moved to the unnamed namespace
-///
-/// \param loggers the original 'loggers' config list
-/// \return ListElement containing only loggers relevant for this
-///         module, where * is replaced by the root logger name
-isc::data::ConstElementPtr
-getRelatedLoggers(isc::data::ConstElementPtr loggers);
-
-} // namespace config
-
-} // namespace isc
 #endif // CCSESSION_H
-
-// Local Variables:
-// mode: c++
-// End:

+ 0 - 4
src/lib/config/tests/Makefile.am

@@ -11,9 +11,6 @@ endif
 
 CLEANFILES = *.gcno *.gcda
 
-noinst_LTLIBRARIES = libfake_session.la
-libfake_session_la_SOURCES = fake_session.h fake_session.cc
-
 TESTS_ENVIRONMENT = \
 	$(LIBTOOL) --mode=execute $(VALGRIND_COMMAND)
 
@@ -25,7 +22,6 @@ run_unittests_SOURCES = ccsession_unittests.cc module_spec_unittests.cc config_d
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
 run_unittests_LDADD =  $(GTEST_LDADD)
-run_unittests_LDADD += libfake_session.la
 run_unittests_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la
 run_unittests_LDADD += $(top_builddir)/src/lib/config/libkea-cfgclient.la
 run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la

File diff suppressed because it is too large
+ 2 - 1018
src/lib/config/tests/ccsession_unittests.cc


+ 0 - 274
src/lib/config/tests/fake_session.cc

@@ -1,274 +0,0 @@
-// Copyright (C) 2009  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.
-
-#include <config.h>
-
-#include <stdint.h>
-
-#include <cstdio>
-#include <vector>
-#include <iostream>
-#include <sstream>
-
-#include <boost/foreach.hpp>
-
-#include <exceptions/exceptions.h>
-
-#include <cc/data.h>
-#include <config/tests/fake_session.h>
-
-using namespace std;
-using namespace isc::cc;
-using namespace isc::data;
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-// ok i want these in cc/data 
-bool
-listContains(ConstElementPtr list, ConstElementPtr el) {
-    if (!list) {
-        return (false);
-    }
-    BOOST_FOREACH(ConstElementPtr l_el, list->listValue()) {
-        if (*l_el == *el) {
-            return (true);
-        }
-    }
-    return (false);
-}
-
-void
-listRemove(ElementPtr list, ConstElementPtr el) {
-    int i = 0;
-    BOOST_FOREACH(ConstElementPtr s_el, list->listValue()) {
-        if (*el == *s_el) {
-            list->remove(i);
-            return;
-        }
-        i++;
-    }
-}
-// endwant
-
-namespace isc {
-namespace cc {
-
-FakeSession::FakeSession(isc::data::ElementPtr initial_messages,
-                         isc::data::ElementPtr subscriptions,
-                         isc::data::ElementPtr msg_queue) :
-    messages_(initial_messages),
-    subscriptions_(subscriptions),
-    msg_queue_(msg_queue),
-    started_(false),
-    throw_on_send_(false)
-{
-}
-
-FakeSession::~FakeSession() {
-}
-
-void
-FakeSession::disconnect() {
-}
-
-void
-FakeSession::startRead(boost::function<void()>) {
-    started_ = true;
-}
-
-void
-FakeSession::establish(const char*) {
-}
-
-bool
-FakeSession::recvmsg(ConstElementPtr& msg, bool nonblock, int) {
-    if (started_ && !nonblock) {
-        // This would schedule another read for length, leading to
-        // corrupted data
-        isc_throw(DoubleRead, "Second read scheduled from recvmsg");
-    }
-
-    //cout << "[XX] client asks for message " << endl;
-    if (messages_ &&
-        messages_->getType() == Element::list &&
-        !messages_->empty()) {
-        msg = messages_->get(0);
-        messages_->remove(0);
-    } else {
-        msg = ElementPtr();
-    }
-    return (true);
-}
-
-bool
-FakeSession::recvmsg(ConstElementPtr& env, ConstElementPtr& msg, bool nonblock,
-                     int)
-{
-    if (started_ && !nonblock) {
-        // This would schedule another read for length, leading to
-        // corrupted data
-        isc_throw(DoubleRead, "Second read scheduled from recvmsg");
-    }
-
-    //cout << "[XX] client asks for message and env" << endl;
-    env = ElementPtr();
-    if (messages_ &&
-        messages_->getType() == Element::list &&
-        !messages_->empty()) {
-        // do we need initial message to have env[group] and [to] too?
-        msg = messages_->get(0);
-        messages_->remove(0);
-        return (true);
-    } else if (msg_queue_) {
-        BOOST_FOREACH(ConstElementPtr c_m, msg_queue_->listValue()) {
-            ConstElementPtr to_remove = ElementPtr();
-            if (haveSubscription(c_m->get(0), c_m->get(1))) {
-                ElementPtr new_env = Element::createMap();
-                new_env->set("group", c_m->get(0));
-                new_env->set("to", c_m->get(1));
-                if (c_m->get(3)->intValue() != -1) {
-                    new_env->set("reply", c_m->get(3));
-                }
-                env = new_env;
-                msg = c_m->get(2);
-                to_remove = c_m;
-            }
-            if (to_remove) {
-                listRemove(msg_queue_, to_remove);
-                return (true);
-            }
-        }
-    }
-    msg = ElementPtr();
-    env = ElementPtr();
-    return (false);
-}
-
-void
-FakeSession::subscribe(std::string group, std::string instance) {
-    //cout << "[XX] client subscribes to " << group << " . " << instance << endl;
-    ElementPtr s_el = Element::createList();
-    s_el->add(Element::create(group));
-    s_el->add(Element::create(instance));
-    if (!subscriptions_) {
-        subscriptions_ = Element::createList();
-    }
-    subscriptions_->add(s_el);
-}
-
-void
-FakeSession::unsubscribe(std::string group, std::string instance) {
-    //cout << "[XX] client unsubscribes from " << group << " . " << instance << endl;
-    ElementPtr s_el = Element::createList();
-    s_el->add(Element::create(group));
-    s_el->add(Element::create(instance));
-    if (!subscriptions_) {
-        return;
-    }
-    listRemove(subscriptions_, s_el);
-}
-
-int
-FakeSession::group_sendmsg(ConstElementPtr msg, std::string group,
-                           std::string to, std::string, bool want_answer)
-{
-    if (throw_on_send_) {
-        isc_throw(Exception, "Throw on send is set in FakeSession");
-    }
-    addMessage(msg, group, to, -1, want_answer);
-    return (1);
-}
-
-bool
-FakeSession::group_recvmsg(ConstElementPtr& envelope, ConstElementPtr& msg,
-                           bool nonblock, int seq)
-{
-    return (recvmsg(envelope, msg, nonblock, seq));
-}
-
-int
-FakeSession::reply(ConstElementPtr envelope, ConstElementPtr newmsg) {
-    //cout << "[XX] client sends reply: " << newmsg << endl;
-    //cout << "[XX] env: " << envelope << endl;
-    addMessage(newmsg, envelope->get("group")->stringValue(),
-               envelope->get("to")->stringValue());
-    return (1);
-}
-
-bool
-FakeSession::hasQueuedMsgs() const {
-    return (msg_queue_ && !msg_queue_->empty());
-}
-
-ConstElementPtr
-FakeSession::getFirstMessage(std::string& group, std::string& to) const {
-    ConstElementPtr el;
-    if (msg_queue_ && !msg_queue_->empty()) {
-        el = msg_queue_->get(0);
-        msg_queue_->remove(0);
-        group = el->get(0)->stringValue();
-        to = el->get(1)->stringValue();
-        return (el->get(2));
-    } else {
-        group = "";
-        to = "";
-        return (ElementPtr());
-    }
-}
-
-void
-FakeSession::addMessage(ConstElementPtr msg, const std::string& group,
-                        const std::string& to, int seq, bool want_answer)
-{
-    ElementPtr m_el = Element::createList();
-    m_el->add(Element::create(group));
-    m_el->add(Element::create(to));
-    m_el->add(msg);
-    m_el->add(Element::create(seq));
-    if (want_answer) {
-        m_el->add(Element::create(want_answer));
-    }
-    if (!msg_queue_) {
-        msg_queue_ = Element::createList();
-    }
-    msg_queue_->add(m_el);
-}
-
-bool
-FakeSession::haveSubscription(const std::string& group,
-                              const std::string& instance)
-{
-    if (!subscriptions_) {
-        return (false);
-    }
-    ElementPtr s1 = Element::createList();
-    ElementPtr s2 = Element::createList();
-    s1->add(Element::create(group));
-    s1->add(Element::create(instance));
-    s2->add(Element::create(group));
-    s2->add(Element::create("*"));
-    bool result = (listContains(subscriptions_, s1) ||
-                   listContains(subscriptions_, s2));
-    return (result);
-}
-
-bool
-FakeSession::haveSubscription(ConstElementPtr group, ConstElementPtr instance)
-{
-    return (haveSubscription(group->stringValue(), instance->stringValue()));
-}
-}
-}

+ 0 - 120
src/lib/config/tests/fake_session.h

@@ -1,120 +0,0 @@
-// Copyright (C) 2009  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 ISC_FAKESESSION_H
-#define ISC_FAKESESSION_H 1
-
-#include <string>
-
-#include <boost/function.hpp>
-
-#include <exceptions/exceptions.h>
-
-#include <cc/data.h>
-#include <cc/session.h>
-
-namespace isc {
-namespace cc {
-class FakeSession : public AbstractSession {
-private:
-    FakeSession(const Session& source);
-    FakeSession& operator=(const Session& source);
-
-public:
-    // if initial_messages contains a list of messages,
-    // these are sent when recv_msg or group_recvmsg is called
-    // instead of whatever is in the msg queue.
-    // The test can also add data to a copy of the message later to tweak
-    // the group_recvmsg() behavior.  See getMessages() below.
-    FakeSession(isc::data::ElementPtr initial_messages,
-                isc::data::ElementPtr subscriptions,
-                isc::data::ElementPtr msg_queue);
-    virtual ~FakeSession();
-
-    // This is thrown if two reads for length at once are scheduled at once.
-    // Such thing does bad things currently (see discussion in ticket #931).
-    class DoubleRead : public Exception {
-    public:
-        DoubleRead(const char* file, size_t line, const char* what) :
-            Exception(file, line, what) {}
-    };
-
-    virtual void startRead(boost::function<void()> read_callback);
-
-    virtual void establish(const char* socket_file = NULL);
-    virtual void disconnect();
-    virtual void subscribe(std::string group,
-                           std::string instance = "*");
-    virtual void unsubscribe(std::string group,
-                             std::string instance = "*");
-    virtual int group_sendmsg(isc::data::ConstElementPtr msg,
-                              std::string group,
-                              std::string instance = "*",
-                              std::string to = "*",
-                              bool want_answer = false);
-    virtual bool group_recvmsg(isc::data::ConstElementPtr& envelope,
-                               isc::data::ConstElementPtr& msg,
-                               bool nonblock = true,
-                               int seq = -1);
-    virtual int reply(isc::data::ConstElementPtr envelope,
-                      isc::data::ConstElementPtr newmsg);
-    virtual bool hasQueuedMsgs() const;
-    virtual void setTimeout(size_t) {}
-    virtual size_t getTimeout() const { return (0); }
-    isc::data::ConstElementPtr getFirstMessage(std::string& group,
-                                               std::string& to) const;
-    void addMessage(isc::data::ConstElementPtr, const std::string& group,
-                    const std::string& to, int seq = -1,
-                    bool want_answer = false);
-    bool haveSubscription(const std::string& group,
-                          const std::string& instance);
-    bool haveSubscription(const isc::data::ConstElementPtr group,
-                          const isc::data::ConstElementPtr instance);
-
-    // For the convenience of tests, we share these internal members
-    // with the tester.  The test code may insert update and check,
-    // before (via the constructor parameters), during and after the actual
-    // session object was created/destroyed.
-    isc::data::ElementPtr getMessages() { return (messages_); }
-    isc::data::ElementPtr getMsgQueue() { return (msg_queue_); }
-
-    /// Throw exception on sendmsg()
-    ///
-    /// When set to true, and sendmsg() is later called, this
-    /// will throw isc::Exception
-    ///
-    /// \param value If true, enable throw. If false, disable it
-    void setThrowOnSend(bool value) { throw_on_send_ = value; }
-
-private:
-    bool recvmsg(isc::data::ConstElementPtr& msg,
-                 bool nonblock = true, int seq = -1);
-    bool recvmsg(isc::data::ConstElementPtr& env,
-                 isc::data::ConstElementPtr& msg,
-                 bool nonblock = true, int seq = -1);
-
-    const isc::data::ElementPtr messages_;
-    isc::data::ElementPtr subscriptions_;
-    isc::data::ElementPtr msg_queue_;
-    bool started_;
-    bool throw_on_send_;
-};
-} // namespace cc
-} // namespace isc
-
-#endif // ISC_FAKESESSION_H
-
-// Local Variables:
-// mode: c++
-// End:

+ 0 - 82
src/lib/testutils/mockups.h

@@ -18,9 +18,6 @@
 #include <exceptions/exceptions.h>
 
 #include <cc/data.h>
-#include <cc/session.h>
-
-//#include <xfr/xfrout_client.h>
 
 #include <asiodns/asiodns.h>
 
@@ -30,85 +27,6 @@
 namespace isc {
 namespace testutils {
 
-// A minimal mock configuration session.  Most the methods are
-// stubbed out, except for a very basic group_sendmsg() and
-// group_recvmsg().  hasQueuedMessages() always returns false.
-class MockSession : public isc::cc::AbstractSession {
-public:
-    MockSession() :
-        // by default we return a simple "success" message.
-        msg_(isc::data::Element::fromJSON("{\"result\": [0, \"SUCCESS\"]}")),
-        send_ok_(true), receive_ok_(true), answer_wanted_(false)
-    {}
-
-
-    virtual void establish(const char*) {}
-    virtual void disconnect() {}
-
-    virtual int group_sendmsg(isc::data::ConstElementPtr msg,
-                              std::string group,
-                              std::string, std::string, bool want_answer)
-    {
-        if (!send_ok_) {
-            isc_throw(isc::cc::SessionError,
-                      "mock session send is disabled for test");
-        }
-
-        sent_msg_ = msg;
-        msg_dest_ = group;
-        answer_wanted_ = want_answer;
-        return (0);
-    }
-
-    virtual bool group_recvmsg(isc::data::ConstElementPtr&,
-                               isc::data::ConstElementPtr& msg, bool, int)
-    {
-        if (!receive_ok_) {
-            isc_throw(isc::cc::SessionError,
-                      "mock session receive is disabled for test");
-        }
-
-        msg = msg_;
-        return (true);
-    }
-
-    virtual void subscribe(std::string, std::string) {}
-    virtual void unsubscribe(std::string, std::string) {}
-
-    virtual void startRead(boost::function<void()>) {}
-
-    virtual int reply(isc::data::ConstElementPtr, isc::data::ConstElementPtr) {
-        return (-1);
-    }
-
-    virtual bool hasQueuedMsgs() const {
-        return (false);
-    }
-
-    virtual void setTimeout(size_t) {};
-    virtual size_t getTimeout() const { return 0; };
-
-    // The following methods extent AbstractSession to allow testing:
-    void setMessage(isc::data::ConstElementPtr msg) { msg_ = msg; }
-    void disableSend() { send_ok_ = false; }
-    void disableReceive() { receive_ok_ = false; }
-
-    isc::data::ConstElementPtr getSentMessage() const { return (sent_msg_); }
-    std::string getMessageDest() const { return (msg_dest_); }
-
-    /// \brief Return the value of want_answer parameter of the previous call
-    /// to group_sendmsg().
-    bool wasAnswerWanted() const { return (answer_wanted_); }
-
-private:
-    isc::data::ConstElementPtr sent_msg_;
-    std::string msg_dest_;
-    isc::data::ConstElementPtr msg_;
-    bool send_ok_;
-    bool receive_ok_;
-    bool answer_wanted_;
-};
-
 // This mock object does nothing except for recording passed parameters
 // to addServerXXX methods so the test code subsequently checks the parameters.
 class MockDNSService : public isc::asiodns::DNSServiceBase {

+ 0 - 1
src/lib/testutils/srv_test.h

@@ -93,7 +93,6 @@ protected:
                              const char* const address = DEFAULT_REMOTE_ADDRESS,
                              uint16_t port = DEFAULT_REMOTE_PORT);
 
-    MockSession notify_session;
     MockServer dnsserv;
     isc::dns::Message request_message;
     isc::dns::MessagePtr parse_message;