Commit 3aa296cf authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[1539] supported operator<< for IOEndpoint for unified logging format.

the formatEndpoint() function locally defined in auth_srv was essentially
moved there.  also added the test of the operator.
parent 434d67fe
......@@ -17,6 +17,7 @@
#include <util/io/socketsession.h>
#include <asiolink/asiolink.h>
#include <asiolink/io_endpoint.h>
#include <config/ccsession.h>
......@@ -112,8 +113,6 @@ private:
MessageRenderer& renderer_;
};
string formatEndpoint(const IOEndpoint& ep); // forward declaration to keep the diff minimum.
// A helper container of socket session forwarder.
//
// This class provides a simple wrapper interface to SocketSessionForwarder
......@@ -177,8 +176,7 @@ public:
io_message.getData(), io_message.getDataSize());
} catch (const SocketSessionError& ex) {
LOG_ERROR(auth_logger, AUTH_MESSAGE_FORWARD_ERROR).
arg(message_name_).arg(formatEndpoint(remote_ep)).
arg(ex.what());
arg(message_name_).arg(remote_ep).arg(ex.what());
close();
throw;
}
......@@ -215,23 +213,6 @@ private:
}
}
};
// A helper function to log an address/port in the form of IOEndpoint
// in our preferred format: [<ipv6_addr>]:port or <ipv4_addr>:port
string
formatEndpoint(const IOEndpoint& ep) {
string addr_port;
if (ep.getFamily() == AF_INET6) {
addr_port = "[" + ep.getAddress().toText() + "]";
} else if (ep.getFamily() == AF_INET) {
addr_port = ep.getAddress().toText();
} else {
addr_port = "(unknown address)";
}
addr_port += ":" + boost::lexical_cast<string>(ep.getPort());
return (addr_port);
}
}
class AuthSrvImpl {
......
......@@ -14,10 +14,6 @@
#include <config.h>
#include <unistd.h> // for some IPC/network system calls
#include <sys/socket.h>
#include <netinet/in.h>
#include <asio.hpp>
#include <asiolink/io_address.h>
......@@ -26,6 +22,13 @@
#include <asiolink/tcp_endpoint.h>
#include <asiolink/udp_endpoint.h>
#include <boost/lexical_cast.hpp>
#include <cassert>
#include <unistd.h> // for some IPC/network system calls
#include <sys/socket.h>
#include <netinet/in.h>
using namespace std;
namespace isc {
......@@ -58,5 +61,18 @@ IOEndpoint::operator!=(const IOEndpoint& other) const {
return (!operator==(other));
}
ostream&
operator<<(ostream& os, const IOEndpoint& endpoint) {
if (endpoint.getFamily() == AF_INET6) {
os << "[" << endpoint.getAddress().toText() << "]";
} else {
// In practice this should be AF_INET, but it's not guaranteed by
// the interface. We'll use the result of textual address
// representation opaquely.
os << endpoint.getAddress().toText();
}
os << ":" << boost::lexical_cast<string>(endpoint.getPort());
return (os);
}
} // namespace asiolink
} // namespace isc
......@@ -18,9 +18,6 @@
// IMPORTANT NOTE: only very few ASIO headers files can be included in
// this file. In particular, asio.hpp should never be included here.
// See the description of the namespace below.
#include <unistd.h> // for some network system calls
#include <sys/socket.h> // for sockaddr
#include <functional>
#include <string>
......@@ -28,6 +25,12 @@
#include <exceptions/exceptions.h>
#include <asiolink/io_address.h>
# include <ostream>
#include <unistd.h> // for some network system calls
#include <sys/socket.h> // for sockaddr
namespace isc {
namespace asiolink {
......@@ -158,6 +161,27 @@ public:
const unsigned short port);
};
/// \brief Insert the \c IOEndpoint as a string into stream.
///
/// This method converts \c endpoint into a string and inserts it into the
/// output stream \c os.
///
/// This method converts the address and port of the endpoint in the textual
/// format that other BIND 10 modules would use in logging, i.e.,
/// - For IPv6 address: [<address>]:port (e.g., [2001:db8::5300]:53)
/// - For IPv4 address: <address>:port (e.g., 192.0.2.53:5300)
///
/// If it's neither IPv6 nor IPv4, it converts the endpoint into text in the
/// same format as that for IPv4, although in practice such a case is not
/// really expected.
///
/// \param os A \c std::ostream object on which the insertion operation is
/// performed.
/// \param endpoint A reference to an \c IOEndpoint object output by the
/// operation.
/// \return A reference to the same \c std::ostream object referenced by
/// parameter \c os after the insertion operation.
std::ostream& operator<<(std::ostream& os, const IOEndpoint& endpoint);
} // namespace asiolink
} // namespace isc
#endif // __IO_ENDPOINT_H
......
......@@ -13,18 +13,22 @@
// PERFORMANCE OF THIS SOFTWARE.
#include <config.h>
#include <asiolink/io_endpoint.h>
#include <asiolink/io_error.h>
#include <gtest/gtest.h>
#include <boost/shared_ptr.hpp>
#include <sstream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <boost/shared_ptr.hpp>
#include <asiolink/io_endpoint.h>
#include <asiolink/io_error.h>
using namespace isc::asiolink;
namespace {
......@@ -240,4 +244,48 @@ TEST(IOEndpointTest, getSockAddr) {
sockAddrMatch(ep->getSockAddr(), "2001:db8::5300", "35");
}
// A faked IOEndpoint for an uncommon address family. It wouldn't be possible
// to create via the normal factory, so we define a special derived class
// for it.
class TestIOEndpoint : public IOEndpoint {
virtual IOAddress getAddress() const {
return IOAddress("2001:db8::bad:add");
}
virtual uint16_t getPort() const { return (42); }
virtual short getProtocol() const { return (IPPROTO_UDP); }
virtual short getFamily() const { return (AF_UNSPEC); }
virtual const struct sockaddr& getSockAddr() const {
static struct sockaddr sa_placeholder;
return (sa_placeholder);
}
};
void
checkEndpointText(const std::string& expected, const IOEndpoint& ep) {
std::ostringstream oss;
oss << ep;
EXPECT_EQ(expected, oss.str());
}
// test operator<<. We simply confirm it appends the result of toText().
TEST(IOEndpointTest, LeftShiftOperator) {
// UDP/IPv4
ConstIOEndpointPtr ep(IOEndpoint::create(IPPROTO_UDP,
IOAddress("192.0.2.1"), 53210));
checkEndpointText("192.0.2.1:53210", *ep);
// UDP/IPv6
ep.reset(IOEndpoint::create(IPPROTO_UDP, IOAddress("2001:db8::53"), 53));
checkEndpointText("[2001:db8::53]:53", *ep);
// Same for TCP: shouldn't be different
ep.reset(IOEndpoint::create(IPPROTO_TCP, IOAddress("192.0.2.1"), 53210));
checkEndpointText("192.0.2.1:53210", *ep);
ep.reset(IOEndpoint::create(IPPROTO_TCP, IOAddress("2001:db8::53"), 53));
checkEndpointText("[2001:db8::53]:53", *ep);
// Uncommon address family. The actual behavior doesn't matter much
// in practice, but we check such input doesn't make it crash.
checkEndpointText("2001:db8::bad:add:42", TestIOEndpoint());
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment