}
bool
-AuthSrvImpl::processUpdate(const IOMessage& /*io_message*/,
+AuthSrvImpl::processUpdate(const IOMessage& io_message,
Message& /*message*/,
OutputBuffer& /*buffer*/,
std::auto_ptr<TSIGContext> /*tsig_context*/)
// hardcode for initial test
ddns_forwarder_.connect();
+ const IOEndpoint& remote_ep = io_message.getRemoteEndpoint();
+ const int protocol = remote_ep.getProtocol();
+ const int sock_type = (protocol == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
+ ddns_forwarder_.forwarder_.push(io_message.getSocket().getNative(),
+ remote_ep.getFamily(), sock_type, protocol,
+ // XXX: no I/F to get local
+ remote_ep.getSockAddr(),
+ remote_ep.getSockAddr(),
+ io_message.getData(),
+ io_message.getDataSize());
+
return (false);
}
#include <log/logger_support.h>
#include <xfr/xfrout_client.h>
-#include <testutils/mockups.h>
+#include <util/unittests/mock_socketsession.h>
#include <auth/auth_srv.h>
#include <auth/auth_config.h>
using namespace isc::dns;
using namespace isc::log;
using namespace isc::util;
+using namespace isc::util::unittests;
using namespace isc::xfr;
using namespace isc::bench;
using namespace isc::asiodns;
using namespace isc::asiolink;
-using namespace isc::testutils;
namespace {
// Commonly used constant:
#include <auth/common.h>
#include <auth/statistics.h>
+#include <util/unittests/mock_socketsession.h>
#include <dns/tests/unittest_util.h>
#include <testutils/dnsmessage_test.h>
#include <testutils/srv_test.h>
#include <testutils/portconfig.h>
#include <testutils/socket_request.h>
+#include <boost/lexical_cast.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>
#include <vector>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
using namespace std;
using namespace isc::cc;
using namespace isc::dns;
using namespace isc::util;
+using namespace isc::util::unittests;
using namespace isc::dns::rdata;
using namespace isc::data;
using namespace isc::xfr;
//
// DDNS related tests
//
+
+// Helper subroutine to check if the given socket address has the expected
+// address and port. It depends on specific output of getnameinfo() (while
+// there can be multiple textual representation of the same address) but
+// in practice it should be reliable.
+void
+checkAddrPort(const struct sockaddr& actual_sa,
+ const string& expected_addr, const string& expected_port)
+{
+ char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
+ const int error = getnameinfo(&actual_sa, actual_sa.sa_len, hbuf,
+ sizeof(hbuf), sbuf, sizeof(sbuf),
+ NI_NUMERICHOST | NI_NUMERICSERV);
+ if (error != 0) {
+ isc_throw(isc::Unexpected, "getnameinfo failed: " <<
+ gai_strerror(error));
+ }
+ EXPECT_EQ(expected_addr, hbuf);
+ EXPECT_EQ(expected_port, sbuf);
+}
+
TEST_F(AuthSrvTest, DDNSForward) {
EXPECT_FALSE(ddns_forwarder.isConnected());
// confirm the forwarder connection will be established exactly once,
// and kept established.
for (size_t i = 0; i < 2; ++i) {
- createAndSendRequest(RRType::SOA(), Opcode::UPDATE());
+ // Use different names for each iteration
+ const Name zone_name = Name(i == 0 ? "example.com" : "example.org");
+ createAndSendRequest(RRType::SOA(), Opcode::UPDATE(), zone_name);
EXPECT_FALSE(dnsserv.hasAnswer());
EXPECT_TRUE(ddns_forwarder.isConnected());
+
+ // Examine the pushed data
+ EXPECT_EQ(AF_INET, ddns_forwarder.getPushedFamily());
+ EXPECT_EQ(SOCK_DGRAM, ddns_forwarder.getPushedType());
+ EXPECT_EQ(IPPROTO_UDP, ddns_forwarder.getPushedProtocol());
+ checkAddrPort(ddns_forwarder.getPushedRemoteend(),
+ DEFAULT_REMOTE_ADDRESS, "53210");
+ EXPECT_EQ(io_message->getDataSize(),
+ ddns_forwarder.getPushedData().size());
+ EXPECT_EQ(0, memcmp(io_message->getData(),
+ &ddns_forwarder.getPushedData()[0],
+ ddns_forwarder.getPushedData().size()));
}
}
#include <asiolink/asiolink.h>
+#include <util/unittests/mock_socketsession.h>
#include <testutils/mockups.h>
#include <cassert>
using namespace isc::data;
using namespace isc::datasrc;
using namespace isc::config;
+using namespace isc::util::unittests;
using namespace isc::testutils;
using namespace isc::auth::unittest;
#include "datasrc_util.h"
+#include <util/unittests/mock_socketsession.h>
#include <testutils/mockups.h>
#include <testutils/portconfig.h>
#include <testutils/socket_request.h>
using namespace isc::datasrc;
using namespace isc::asiodns;
using namespace isc::auth::unittest;
+using namespace isc::util::unittests;
using namespace isc::testutils;
namespace {
bool disconnect_ok_;
};
-// Mock socket session forwarder
-class MockSocketSessionForwarder :
- public isc::util::io::BaseSocketSessionForwarder
-{
-public:
- MockSocketSessionForwarder() :
- is_connected_(false), connect_ok_(true), push_ok_(true),
- close_ok_(true)
- {}
-
- virtual void connectToReceiver() {
- if (!connect_ok_) {
- isc_throw(isc::util::io::SocketSessionError, "socket session "
- "forwarding connection disabled for test");
- }
- if (is_connected_) {
- isc_throw(isc::util::io::SocketSessionError, "duplicate connect");
- }
- is_connected_ = true;
- }
- virtual void close() {
- is_connected_ = false;
- }
-#if 0
- virtual void push(int sock, int family, int type, int protocol,
- const struct sockaddr& local_end,
- const struct sockaddr& remote_end,
- const void* data, size_t data_len)
-#endif
- virtual void push(int, int, int, int,
- const struct sockaddr&,
- const struct sockaddr&,
- const void*, size_t)
- {
- if (!push_ok_) {
- isc_throw(isc::util::io::SocketSessionError,
- "socket session forwarding is disabled for test");
- }
- }
- bool isConnected() const { return (is_connected_); }
- void disableConnect() { connect_ok_ = false; }
- void enableConnect() { connect_ok_ = true; }
- void disableClose() { close_ok_ = false; }
- void enableClose() { close_ok_ = true; }
- void disablePush() { push_ok_ = false; }
-
-private:
- bool is_connected_;
- bool connect_ok_;
- bool push_ok_;
- bool close_ok_;
-};
-
} // end of testutils
} // end of isc
#endif // __ISC_TESTUTILS_MOCKUPS_H
libutil_unittests_la_SOURCES += textdata.h
endif
+# For now, this isn't needed for libutil_unittests
+EXTRA_DIST = mock_socketsession.h
+
libutil_unittests_la_CPPFLAGS = $(AM_CPPFLAGS)
if HAVE_GTEST
libutil_unittests_la_CPPFLAGS += $(GTEST_INCLUDES)
--- /dev/null
+// Copyright (C) 2012 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 __UTIL_UNITTESTS_MOCKSOCKETSESSION_H
+#define __UTIL_UNITTESTS_MOCKSOCKETSESSION_H 1
+
+#include <exceptions/exceptions.h>
+
+#include <util/io/socketsession.h>
+#include <util/io/sockaddr_util.h>
+
+#include <cassert>
+#include <cstring>
+#include <vector>
+
+#include <sys/socket.h>
+
+namespace isc {
+namespace util {
+namespace unittests {
+
+// Mock socket session forwarder
+class MockSocketSessionForwarder :
+ public isc::util::io::BaseSocketSessionForwarder
+{
+public:
+ MockSocketSessionForwarder() :
+ is_connected_(false), connect_ok_(true), push_ok_(true),
+ close_ok_(true)
+ {}
+
+ virtual void connectToReceiver() {
+ if (!connect_ok_) {
+ isc_throw(isc::util::io::SocketSessionError, "socket session "
+ "forwarding connection disabled for test");
+ }
+ if (is_connected_) {
+ isc_throw(isc::util::io::SocketSessionError, "duplicate connect");
+ }
+ is_connected_ = true;
+ }
+ virtual void close() {
+ is_connected_ = false;
+ }
+ virtual void push(int sock, int family, int type, int protocol,
+ const struct sockaddr& local_end,
+ const struct sockaddr& remote_end,
+ const void* data, size_t data_len)
+ {
+ if (!push_ok_) {
+ isc_throw(isc::util::io::SocketSessionError,
+ "socket session forwarding is disabled for test");
+ }
+
+ // Copy parameters for later checks
+ pushed_sock_ = sock;
+ pushed_family_ = family;
+ pushed_type_ = type;
+ pushed_protocol_ = protocol;
+ assert(remote_end.sa_family == AF_INET);
+ assert(io::internal::getSALength(local_end) <=
+ sizeof(pushed_local_end_ss_));
+ std::memcpy(&pushed_local_end_ss_, &local_end,
+ io::internal::getSALength(local_end));
+ assert(io::internal::getSALength(remote_end) <=
+ sizeof(pushed_remote_end_ss_));
+ std::memcpy(&pushed_remote_end_ss_, &remote_end,
+ io::internal::getSALength(remote_end));
+ pushed_data_.resize(data_len);
+ std::memcpy(&pushed_data_[0], data, data_len);
+ }
+ bool isConnected() const { return (is_connected_); }
+ void disableConnect() { connect_ok_ = false; }
+ void enableConnect() { connect_ok_ = true; }
+ void disableClose() { close_ok_ = false; }
+ void enableClose() { close_ok_ = true; }
+ void disablePush() { push_ok_ = false; }
+
+ // Read-only accessors to recorded parameters to the previous successful
+ // call to push(). Return values are undefined if there has been no
+ // successful call to push().
+ int getPushedSock() const { return (pushed_sock_); }
+ int getPushedFamily() const { return (pushed_family_); }
+ int getPushedType() const { return (pushed_type_); }
+ int getPushedProtocol() const { return (pushed_protocol_); }
+ const struct sockaddr& getPushedLocalend() const {
+ return (*io::internal::convertSockAddr(&pushed_local_end_ss_));
+ }
+ const struct sockaddr& getPushedRemoteend() const {
+ return (*io::internal::convertSockAddr(&pushed_remote_end_ss_));
+ }
+ const std::vector<uint8_t> getPushedData() const { return (pushed_data_); }
+
+private:
+ bool is_connected_;
+ bool connect_ok_;
+ bool push_ok_;
+ bool close_ok_;
+ int pushed_sock_;
+ int pushed_family_;
+ int pushed_type_;
+ int pushed_protocol_;
+ struct sockaddr_storage pushed_local_end_ss_;
+ struct sockaddr_storage pushed_remote_end_ss_;
+ std::vector<uint8_t> pushed_data_;
+};
+
+} // end of unittests
+} // end of util
+} // end of isc
+#endif // __UTIL_UNITTESTS_MOCKSOCKETSESSION_H
+
+// Local Variables:
+// mode: c++
+// End: