#include <util/io/socketsession.h>
#include <asiolink/asiolink.h>
+#include <asiolink/io_endpoint.h>
#include <config/ccsession.h>
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
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;
}
}
}
};
-
-// 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 {
#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>
#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 {
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
// 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>
#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 {
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
// 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 {
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());
+}
}