* Use the address family instead of v6 boolean.
* Check it by exception.
* Documentation.
DNSLookup *lookup_;
DNSAnswer *answer_;
- template<class Ptr, class Server> void addServerFromFD(int fd, bool v6) {
- Ptr server(new Server(io_service_.get_io_service(), fd, v6, checkin_,
+ template<class Ptr, class Server> void addServerFromFD(int fd, int af) {
+ Ptr server(new Server(io_service_.get_io_service(), fd, af, checkin_,
lookup_, answer_));
(*server)();
servers_.push_back(server);
impl_->addServer(port, convertAddr(address));
}
-void DNSService::addServerTCP(int fd, bool v6) {
- impl_->addServerFromFD<DNSServiceImpl::TCPServerPtr, TCPServer>(fd, v6);
+void DNSService::addServerTCPFromFD(int fd, int af) {
+ impl_->addServerFromFD<DNSServiceImpl::TCPServerPtr, TCPServer>(fd, af);
}
-void DNSService::addServerUDP(int fd, bool v6) {
- impl_->addServerFromFD<DNSServiceImpl::UDPServerPtr, UDPServer>(fd, v6);
+void DNSService::addServerUDPFromFD(int fd, int af) {
+ impl_->addServerFromFD<DNSServiceImpl::UDPServerPtr, UDPServer>(fd, af);
}
void
/// \brief Add another server to the service
void addServer(uint16_t port, const std::string &address);
void addServer(const char &port, const std::string &address);
- /// \brief Add another server to the service from already opened file
- /// descriptor
- void addServerTCP(int fd, bool v6);
- void addServerUDP(int fd, bool v6);
+ /// \brief Add another TCP server/listener to the service from already opened
+ /// file descriptor
+ ///
+ /// Adds a new TCP server using an already opened file descriptor (eg. it
+ /// only wraps it so the file descriptor is usable within the event loop).
+ ///
+ /// If you pass bad data (eg. opened UDP socket as fd), this will not detect
+ /// it right away, but successfull operations might fail.
+ ///
+ /// \param fd the file descriptor to be used.
+ /// \param af the address family of the file descriptor. Must be either
+ /// AF_INET or AF_INET6.
+ /// \throw isc::InvalidParameter if af is neither AF_INET nor AF_INET6.
+ void addServerTCPFromFD(int fd, int af);
+ /// \brief Add another UDP server to the service from already opened
+ /// file descriptor
+ ///
+ /// Adds a new UDP server using an already opened file descriptor (eg. it
+ /// only wraps it so the file descriptor is usable within the event loop).
+ ///
+ /// If you pass bad data (eg. opened TCP socket as fd), this will not detect
+ /// it right away, but successfull operations might fail.
+ ///
+ /// \param fd the file descriptor to be used.
+ /// \param af the address family of the file descriptor. Must be either
+ /// AF_INET or AF_INET6.
+ /// \throw isc::InvalidParameter if af is neither AF_INET nor AF_INET6.
+ void addServerUDPFromFD(int fd, int af);
/// \brief Remove all servers from the service
void clearServers();
acceptor_->listen();
}
-TCPServer::TCPServer(io_service& io_service, int fd, bool v6,
+TCPServer::TCPServer(io_service& io_service, int fd, int af,
const SimpleCallback* checkin,
const DNSLookup* lookup,
const DNSAnswer* answer) :
checkin_callback_(checkin), lookup_callback_(lookup),
answer_callback_(answer)
{
+ if (af != AF_INET && af != AF_INET6) {
+ isc_throw(InvalidParameter, "Address family must be either AF_INET "
+ "or AF_INET6, not " << af);
+ }
acceptor_.reset(new tcp::acceptor(io_service));
- acceptor_->assign(v6 ? tcp::v6() : tcp::v4(), fd);
+ acceptor_->assign(af == AF_INET6 ? tcp::v6() : tcp::v4(), fd);
acceptor_->listen();
}
/// \brief Constructor
/// \param io_service the asio::io_service to work with
/// \param fd the file descriptor of opened TCP socket
- /// \param v6 the socket in fd is ipv6 one (if false, it is ipv4)
+ /// \param af address family of the socket, either AF_INET or AF_INET6
/// \param checkin the callbackprovider for non-DNS events
/// \param lookup the callbackprovider for DNS lookup events
/// \param answer the callbackprovider for DNS answer events
- TCPServer(asio::io_service& io_service, int fd, bool v6,
+ /// \throw isc::InvalidParameter if af is neither AF_INET nor AF_INET6
+ TCPServer(asio::io_service& io_service, int fd, int af,
const isc::asiolink::SimpleCallback* checkin = NULL,
const DNSLookup* lookup = NULL, const DNSAnswer* answer = NULL);
// the same.
class DNSServerTestBase : public::testing::Test {
protected:
+ DNSServerTestBase() :
+ udp_server_(NULL),
+ tcp_server_(NULL)
+ { }
void TearDown() {
- udp_server_->stop();
- tcp_server_->stop();
+ if (udp_server_) {
+ udp_server_->stop();
+ }
+ if (tcp_server_) {
+ tcp_server_->stop();
+ }
delete checker_;
delete lookup_;
delete answer_;
answer_ = new SimpleAnswer();
udp_client_ = new UDPClient(service,
ip::udp::endpoint(server_address_,
- server_port));
+ server_port));
tcp_client_ = new TCPClient(service,
ip::tcp::endpoint(server_address_,
server_port));
commonSetup();
int fdUDP(getFd(SOCK_DGRAM));
ASSERT_NE(-1, fdUDP) << strerror(errno);
- udp_server_ = new UDPServer(service, fdUDP, false, checker_, lookup_,
- answer_);
+ udp_server_ = new UDPServer(service, fdUDP, AF_INET6, checker_,
+ lookup_, answer_);
int fdTCP(getFd(SOCK_STREAM));
ASSERT_NE(-1, fdTCP) << strerror(errno);
- tcp_server_ = new TCPServer(service, fdTCP, false, checker_, lookup_,
- answer_);
+ tcp_server_ = new TCPServer(service, fdTCP, AF_INET6, checker_,
+ lookup_, answer_);
}
};
EXPECT_TRUE(this->serverStopSucceed());
}
+// It raises an exception when invalid address family is passed
+TEST_F(DNSServerTestBase, exceptions) {
+ // We abuse DNSServerTestBase for this test, as we don't need the
+ // initialization.
+ commonSetup();
+ // We use the 0 fd as it should not be touched anyway
+ EXPECT_THROW(UDPServer(service, 0, AF_UNIX, checker_, lookup_,
+ answer_), isc::InvalidParameter);
+ EXPECT_THROW(TCPServer(service, 0, AF_UNIX, checker_, lookup_,
+ answer_), isc::InvalidParameter);
+}
+
}
}
socket_->bind(udp::endpoint(addr, port));
}
- Data(io_service& io_service, int fd, bool v6,
- SimpleCallback* checkin, DNSLookup* lookup, DNSAnswer* answer) :
- io_(io_service), done_(false),
- checkin_callback_(checkin),lookup_callback_(lookup),
- answer_callback_(answer)
+ Data(io_service& io_service, int fd, int af, SimpleCallback* checkin,
+ DNSLookup* lookup, DNSAnswer* answer) :
+ io_(io_service), done_(false),
+ checkin_callback_(checkin),lookup_callback_(lookup),
+ answer_callback_(answer)
{
+ if (af != AF_INET && af != AF_INET6) {
+ isc_throw(InvalidParameter, "Address family must be either AF_INET "
+ "or AF_INET6, not " << af);
+ }
// We must use different instantiations for v4 and v6;
// otherwise ASIO will bind to both
- udp proto = v6 ? udp::v6() : udp::v4();
+ udp proto = af == AF_INET6 ? udp::v6() : udp::v4();
socket_.reset(new udp::socket(io_service));
socket_->assign(proto, fd);
}
data_(new Data(io_service, addr, port, checkin, lookup, answer))
{ }
-UDPServer::UDPServer(io_service& io_service, int fd, bool v6,
+UDPServer::UDPServer(io_service& io_service, int fd, int af,
SimpleCallback* checkin, DNSLookup* lookup,
DNSAnswer* answer) :
- data_(new Data(io_service, fd, v6, checkin, lookup, answer))
+ data_(new Data(io_service, fd, af, checkin, lookup, answer))
{ }
/// The function operator is implemented with the "stackless coroutine"
/// \brief Constructor
/// \param io_service the asio::io_service to work with
/// \param fd the file descriptor of opened UDP socket
- /// \param v6 the socket in fd is ipv6 one (if false, it is ipv4)
+ /// \param af address family, either AF_INET or AF_INET6
/// \param checkin the callbackprovider for non-DNS events
/// \param lookup the callbackprovider for DNS lookup events
/// \param answer the callbackprovider for DNS answer events
- UDPServer(asio::io_service& io_service, int fd, bool v6,
+ /// \throw isc::InvalidParameter if af is neither AF_INET nor AF_INET6
+ UDPServer(asio::io_service& io_service, int fd, int af,
isc::asiolink::SimpleCallback* checkin = NULL,
DNSLookup* lookup = NULL, DNSAnswer* answer = NULL);
}
current_sockets.clear();
BOOST_FOREACH(const AddressPair &address, addresses) {
- bool is_v6(IOAddress(address.first).getFamily() == AF_INET6);
+ int af(IOAddress(address.first).getFamily());
// TODO: Support sharing somehow in future.
const SocketRequestor::SocketID
tcp(socketRequestor().requestSocket(SocketRequestor::TCP,
"dummy_app"));
current_sockets.push_back(tcp.second);
if (!test_mode) {
- service.addServerTCP(tcp.first, is_v6);
+ service.addServerTCPFromFD(tcp.first, af);
}
const SocketRequestor::SocketID
udp(socketRequestor().requestSocket(SocketRequestor::UDP,
"dummy_app"));
current_sockets.push_back(udp.second);
if (!test_mode) {
- service.addServerUDP(udp.first, is_v6);
+ service.addServerUDPFromFD(udp.first, af);
}
}
}