Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ISC Open Source Projects
Kea
Commits
a5014970
Commit
a5014970
authored
Jul 02, 2013
by
Marcin Siodelski
Browse files
[2975] Stub implementation of the DNSClient class.
parent
0fc40f16
Changes
6
Hide whitespace changes
Inline
Side-by-side
src/bin/d2/Makefile.am
View file @
a5014970
...
...
@@ -54,6 +54,7 @@ b10_dhcp_ddns_SOURCES += d_controller.cc d_controller.h
b10_dhcp_ddns_SOURCES
+=
d2_controller.cc d2_controller.h
b10_dhcp_ddns_SOURCES
+=
d2_update_message.cc d2_update_message.h
b10_dhcp_ddns_SOURCES
+=
d2_zone.cc d2_zone.h
b10_dhcp_ddns_SOURCES
+=
dns_client.cc dns_client.h
nodist_b10_dhcp_ddns_SOURCES
=
d2_messages.h d2_messages.cc
EXTRA_DIST
+=
d2_messages.mes
...
...
@@ -61,6 +62,7 @@ EXTRA_DIST += d2_messages.mes
b10_dhcp_ddns_LDADD
=
$(top_builddir)
/src/lib/log/libb10-log.la
b10_dhcp_ddns_LDADD
+=
$(top_builddir)
/src/lib/exceptions/libb10-exceptions.la
b10_dhcp_ddns_LDADD
+=
$(top_builddir)
/src/lib/cc/libb10-cc.la
b10_dhcp_ddns_LDADD
+=
$(top_builddir)
/src/lib/asiodns/libb10-asiodns.la
b10_dhcp_ddns_LDADD
+=
$(top_builddir)
/src/lib/asiolink/libb10-asiolink.la
b10_dhcp_ddns_LDADD
+=
$(top_builddir)
/src/lib/config/libb10-cfgclient.la
b10_dhcp_ddns_LDADD
+=
$(top_builddir)
/src/lib/dns/libb10-dns++.la
...
...
src/bin/d2/d2_update_message.h
View file @
a5014970
...
...
@@ -63,6 +63,10 @@ public:
isc
::
Exception
(
file
,
line
,
what
)
{}
};
class
D2UpdateMessage
;
/// @brief Pointer to the DNS Update Message.
typedef
boost
::
shared_ptr
<
D2UpdateMessage
>
D2UpdateMessagePtr
;
/// @brief The @c D2UpdateMessage encapsulates a DNS Update message.
///
...
...
src/bin/d2/dns_client.cc
0 → 100644
View file @
a5014970
// Copyright (C) 2013 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 <d2/dns_client.h>
#include <dns/messagerenderer.h>
namespace
isc
{
namespace
d2
{
namespace
{
// OutputBuffer objects are pre-allocated before data is written to them.
// This is a default number of bytes for the buffers we create within
// DNSClient class.
const
size_t
DEFAULT_BUFFER_SIZE
=
128
;
}
using
namespace
isc
::
util
;
using
namespace
isc
::
asiolink
;
using
namespace
isc
::
asiodns
;
DNSClient
::
DNSClient
(
D2UpdateMessagePtr
&
response_placeholder
,
Callback
*
callback
)
:
in_buf_
(
new
OutputBuffer
(
DEFAULT_BUFFER_SIZE
)),
response_
(
response_placeholder
),
callback_
(
callback
)
{
if
(
!
response_
)
{
isc_throw
(
BadValue
,
"a pointer to an object to encapsulate the DNS"
" server must be provided; found NULL value"
);
}
}
void
DNSClient
::
operator
()(
IOFetch
::
Result
result
)
{
// @todo Do something useful here. One of the useful things will be to parse
// incoming message if the result is SUCCESS.
// Once we are done with internal business, let's call a callback supplied
// by a caller.
if
(
callback_
!=
NULL
)
{
(
*
callback_
)(
result
);
}
}
void
DNSClient
::
doUpdate
(
IOService
&
io_service
,
const
IOAddress
&
ns_addr
,
const
uint16_t
ns_port
,
D2UpdateMessage
&
update
,
const
int
wait
)
{
// A renderer is used by the toWire function which creates the on-wire data
// from the DNS Update message. A renderer has its internal buffer where it
// renders data by default. However, this buffer can't be directly accessed.
// Fortunately, the renderer's API accepts user-supplied buffers. So, let's
// create our own buffer and pass it to the renderer so as the message is
// rendered to this buffer. Finally, we pass this buffer to IOFetch.
dns
::
MessageRenderer
renderer
;
OutputBufferPtr
msg_buf
(
new
OutputBuffer
(
DEFAULT_BUFFER_SIZE
));
renderer
.
setBuffer
(
msg_buf
.
get
());
// Render DNS Update message. This may throw a bunch of exceptions if
// invalid message object is given.
update
.
toWire
(
renderer
);
// IOFetch has all the mechanisms that we need to perform asynchronous
// communication with the DNS server. The last but one argument points to
// this object as a completion callback for the message exchange. As a
// result operator()(IOFetch::Result) will be called.
IOFetch
io_fetch
(
IOFetch
::
UDP
,
io_service
,
msg_buf
,
ns_addr
,
ns_port
,
in_buf_
,
this
,
wait
);
// Post the task to the task queue in the IO service. Caller will actually
// run these tasks by executing IOService::run.
io_service
.
post
(
io_fetch
);
}
}
// namespace d2
}
// namespace isc
src/bin/d2/dns_client.h
0 → 100644
View file @
a5014970
// Copyright (C) 2013 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 DNS_CLIENT_H
#define DNS_CLIENT_H
#include <d2/d2_update_message.h>
#include <asiolink/io_service.h>
#include <util/buffer.h>
#include <asiodns/io_fetch.h>
namespace
isc
{
namespace
d2
{
/// @brief The @c DNSClient class handles communication with the DNS server.
///
/// Communication with the DNS server is asynchronous. Caller must provide a
/// callback, which will be invoked when the response from the DNS server is
/// received, a timeout has occured or IO service has been stopped for any
/// reason. The caller-supplied callback is called by the internal callback
/// operator implemented by @c DNSClient. This callback is responsible for
/// initializing the @c D2UpdateMessage instance which encapsulates the response
/// from the DNS. This initialization does not take place if the response from
/// DNS is not received.
///
/// Caller must supply a pointer to the @c D2UpdateMessage object, which will
/// encapsulate DNS response, through class constructor. An exception will be
/// thrown if the pointer is not initialized by the caller.
///
/// @todo Currently, only the stub implementation is available for this class.
/// The major missing piece is to create @c D2UpdateMessage object which will
/// encapsulate the response from the DNS server.
class
DNSClient
:
public
asiodns
::
IOFetch
::
Callback
{
public:
/// @brief Callback for the @c DNSClient class.
///
/// This is is abstract class which represents the external callback for the
/// @c DNSClient. Caller must implement this class and supply its instance
/// in the @c DNSClient constructor to get callbacks when the DNS Update
/// exchange is complete (@see @c DNSClient).
class
Callback
{
public:
/// @brief Virtual destructor.
virtual
~
Callback
()
{
}
/// @brief Function operator implementing a callback.
///
/// @param result an @c asiodns::IOFetch::Result object representing
/// IO status code.
virtual
void
operator
()(
asiodns
::
IOFetch
::
Result
result
)
=
0
;
};
/// @brief Constructor.
///
/// @param response_placeholder Pointer to an object which will hold a
/// DNS server's response. Caller is responsible for allocating this object.
/// @param callback Pointer to an object implementing @c DNSClient::Callback
/// class. This object will be called when DNS message exchange completes or
/// if an error occurs. NULL value disables callback invocation.
DNSClient
(
D2UpdateMessagePtr
&
response_placeholder
,
Callback
*
callback
);
/// @brief Virtual destructor, does nothing.
virtual
~
DNSClient
()
{
}
///
/// @name Copy constructor and assignment operator
///
/// Copy constructor and assignment operator are private because
/// @c DNSClient is a singleton class and its instance should not be copied.
//@{
private:
DNSClient
(
const
DNSClient
&
source
);
DNSClient
&
operator
=
(
const
DNSClient
&
source
);
//@}
public:
/// @brief Function operator, implementing an internal callback.
///
/// This internal callback is called when the DNS update message exchange is
/// complete. It further invokes the external callback provided by a caller.
/// Before external callback is invoked, an object of the @c D2UpdateMessage
/// type, representing a response from the server is set.
///
/// @param result An @c asiodns::IOFetch::Result object representing status
/// code returned by the IO.
virtual
void
operator
()(
asiodns
::
IOFetch
::
Result
result
);
/// @brief Start asynchronous DNS Update.
///
/// This function starts asynchronous DNS Update and returns. The DNS Update
/// will be executed by the specified IO service. Once the message exchange
/// with a DNS server is complete, timeout occurs or IO operation is
/// interrupted, the caller-supplied callback function will be invoked.
///
/// An address and port of the DNS server is specified through the function
/// arguments so as the same instance of the @c DNSClient can be used to
/// initiate multiple message exchanges.
///
/// @param io_service IO service to be used to run the message exchange.
/// @param ns_addr DNS server address.
/// @param ns_port DNS server port.
/// @param update A DNS Update message to be sent to the server.
/// @param wait A timeout (in seconds) for the response. If a response is
/// not received within the timeout, exchange is interrupted. A negative
/// value disables timeout.
void
doUpdate
(
asiolink
::
IOService
&
io_service
,
const
asiolink
::
IOAddress
&
ns_addr
,
const
uint16_t
ns_port
,
D2UpdateMessage
&
update
,
const
int
wait
=
-
1
);
private:
/// A buffer holding server's response in the wire format.
util
::
OutputBufferPtr
in_buf_
;
/// A pointer to the caller-supplied object, encapsuating a response
/// from DNS.
D2UpdateMessagePtr
response_
;
/// A pointer to the external callback.
Callback
*
callback_
;
};
}
// namespace d2
}
// namespace isc
#endif // DNS_CLIENT_H
src/bin/d2/tests/Makefile.am
View file @
a5014970
...
...
@@ -58,6 +58,7 @@ d2_unittests_SOURCES += ../d2_process.cc ../d2_process.h
d2_unittests_SOURCES
+=
../d2_controller.cc ../d2_controller.h
d2_unittests_SOURCES
+=
../d2_update_message.cc ../d2_update_message.h
d2_unittests_SOURCES
+=
../d2_zone.cc ../d2_zone.h
d2_unittests_SOURCES
+=
../dns_client.cc ../dns_client.h
d2_unittests_SOURCES
+=
d_test_stubs.cc d_test_stubs.h
d2_unittests_SOURCES
+=
d2_unittests.cc
d2_unittests_SOURCES
+=
d2_process_unittests.cc
...
...
@@ -65,6 +66,7 @@ d2_unittests_SOURCES += d_controller_unittests.cc
d2_unittests_SOURCES
+=
d2_controller_unittests.cc
d2_unittests_SOURCES
+=
d2_update_message_unittests.cc
d2_unittests_SOURCES
+=
d2_zone_unittests.cc
d2_unittests_SOURCES
+=
dns_client_unittests.cc
nodist_d2_unittests_SOURCES
=
../d2_messages.h ../d2_messages.cc
d2_unittests_CPPFLAGS
=
$(AM_CPPFLAGS)
$(GTEST_INCLUDES)
...
...
@@ -72,6 +74,7 @@ d2_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
d2_unittests_LDADD
=
$(GTEST_LDADD)
d2_unittests_LDADD
+=
$(top_builddir)
/src/lib/exceptions/libb10-exceptions.la
d2_unittests_LDADD
+=
$(top_builddir)
/src/lib/log/libb10-log.la
d2_unittests_LDADD
+=
$(top_builddir)
/src/lib/asiodns/libb10-asiodns.la
d2_unittests_LDADD
+=
$(top_builddir)
/src/lib/asiolink/libb10-asiolink.la
d2_unittests_LDADD
+=
$(top_builddir)
/src/lib/cc/libb10-cc.la
d2_unittests_LDADD
+=
$(top_builddir)
/src/lib/config/libb10-cfgclient.la
...
...
src/bin/d2/tests/dns_client_unittests.cc
0 → 100644
View file @
a5014970
// Copyright (C) 2013 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 <d2/dns_client.h>
#include <asiodns/io_fetch.h>
#include <asiodns/logger.h>
#include <dns/rcode.h>
#include <dns/rrclass.h>
#include <boost/scoped_ptr.hpp>
#include <gtest/gtest.h>
using
namespace
std
;
using
namespace
isc
;
using
namespace
isc
::
asiolink
;
using
namespace
isc
::
asiodns
;
using
namespace
isc
::
d2
;
using
namespace
isc
;
using
namespace
isc
::
dns
;
namespace
{
const
char
*
TEST_ADDRESS
=
"127.0.0.1"
;
const
uint16_t
TEST_PORT
=
5301
;
// @brief Test Fixture class.
//
// This test fixture class implements DNSClient::Callback so as it can be
// installed as a completion callback for tests it implements. This callback
// is called when a DDNS transaction (send and receive) completes. This allows
// for the callback function to direcetly access class members. In particular,
// the callback function can access IOService on which run() was called and
// call stop() on it.
class
DNSClientTest
:
public
virtual
::
testing
::
Test
,
DNSClient
::
Callback
{
public:
IOService
service_
;
D2UpdateMessagePtr
response_
;
IOFetch
::
Result
result_
;
// @brief Constructor.
//
// This constructor overrides the default logging level of asiodns logger to
// prevent it from emitting debug messages from IOFetch class. Such an error
// message can be emitted if timeout occurs when DNSClient class is
// waiting for a response. Some of the tests are checking DNSClient behavior
// in case when response from the server is not received. Tests output would
// become messy if such errors were logged.
DNSClientTest
()
:
service_
(),
result_
(
IOFetch
::
SUCCESS
)
{
asiodns
::
logger
.
setSeverity
(
log
::
INFO
);
response_
.
reset
(
new
D2UpdateMessage
(
D2UpdateMessage
::
INBOUND
));
}
// @brief Destructor.
//
// Sets the asiodns logging level back to DEBUG.
virtual
~
DNSClientTest
()
{
asiodns
::
logger
.
setSeverity
(
log
::
DEBUG
);
};
// @brief Exchange completion calback.
//
// This callback is called when the exchange with the DNS server is
// complete or an error occured. This includes the occurence of a timeout.
//
// @param result An error code returned by an IO.
virtual
void
operator
()(
IOFetch
::
Result
result
)
{
result_
=
result
;
service_
.
stop
();
}
// This test verifies that when invalid response placeholder object is
// passed to a constructor, constructor throws the appropriate exception.
// It also verifies that the constructor will not throw if the supplied
// callback object is NULL.
void
runConstructorTest
()
{
D2UpdateMessagePtr
null_response
;
EXPECT_THROW
(
DNSClient
(
null_response
,
this
),
isc
::
BadValue
);
EXPECT_NO_THROW
(
DNSClient
(
response_
,
NULL
));
}
// This test verifies the DNSClient behavior when a server does not respond
// do the DNS Update message. In such case, the callback function is
// expected to be called and the TIME_OUT error code should be returned.
void
runSendNoReceiveTest
()
{
// Create outgoing message. Simply set the required message fields:
// error code and Zone section. This is enough to create on-wire format
// of this message and send it.
D2UpdateMessage
message
(
D2UpdateMessage
::
OUTBOUND
);
ASSERT_NO_THROW
(
message
.
setRcode
(
Rcode
(
Rcode
::
NOERROR_CODE
)));
ASSERT_NO_THROW
(
message
.
setZone
(
Name
(
"example.com"
),
RRClass
::
IN
()));
// Use scoped pointer so as we can declare dns_client in the function
// scope.
boost
::
scoped_ptr
<
DNSClient
>
dns_client
;
// Constructor may throw if the response placehoder is NULL.
EXPECT_NO_THROW
(
dns_client
.
reset
(
new
DNSClient
(
response_
,
this
)));
IOService
io_service
;
// Set the response wait time to 0 so as our test is not hanging. This
// should cause instant timeout.
const
int
timeout
=
0
;
// The doUpdate() function starts asynchronous message exchange with DNS
// server. When message exchange is done or timeout occurs, the
// completion callback will be triggered. The doUpdate function returns
// immediately.
EXPECT_NO_THROW
(
dns_client
->
doUpdate
(
service_
,
IOAddress
(
TEST_ADDRESS
),
TEST_PORT
,
message
,
timeout
));
// This starts the execution of tasks posted to IOService. run() blocks
// until stop() is called in the completion callback function.
service_
.
run
();
// If callback function was called it should have modified the default
// value of result_ with the TIME_OUT error code.
EXPECT_EQ
(
IOFetch
::
TIME_OUT
,
result_
);
}
};
TEST_F
(
DNSClientTest
,
constructor
)
{
runConstructorTest
();
}
TEST_F
(
DNSClientTest
,
timeout
)
{
runSendNoReceiveTest
();
}
}
// End of anonymous namespace
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment