Permalink
Browse files

Add wrapper for getaddrinfo

  • Loading branch information...
1 parent 4b1cc05 commit a2db48976932b48f8638dab3f628dfd473ca3df4 @rescrv committed Jun 21, 2012
Showing with 250 additions and 14 deletions.
  1. +14 −12 .gitignore
  2. +5 −2 Makefile.am
  3. +175 −0 po6/net/hostname.h
  4. +56 −0 test/net/hostname.cc
View
26 .gitignore
@@ -1,5 +1,3 @@
-Makefile
-Makefile.in
aclocal.m4
autom4te.cache/
config.h
@@ -9,6 +7,8 @@ configure
depcomp
install-sh
libpo6.pc
+Makefile
+Makefile.in
missing
stamp-h1
test/.deps/
@@ -17,28 +17,30 @@ test/error
test/error.o
test/io/.deps/
test/io/.dirstamp
-test/io/fd.o
test/io_fd
+test/io/fd.o
test/net/.deps/
test/net/.dirstamp
-test/net/ipaddr.o
-test/net/location.o
-test/net/socket.o
+test/net_hostname
+test/net/hostname.o
test/net_ipaddr
+test/net/ipaddr.o
test/net_location
+test/net/location.o
test/net_socket
+test/net/socket.o
test/pathname
test/pathname.o
test/runner.o
+test/threads_cond
+test/threads/cond.o
test/threads/.deps/
test/threads/.dirstamp
-test/threads/cond.o
-test/threads/mutex.o
-test/threads/rwlock.o
-test/threads/spinlock.o
-test/threads/thread.o
-test/threads_cond
test/threads_mutex
+test/threads/mutex.o
test/threads_rwlock
+test/threads/rwlock.o
test/threads_spinlock
+test/threads/spinlock.o
test/threads_thread
+test/threads/thread.o
View
7 Makefile.am
@@ -13,8 +13,8 @@ nobase_include_HEADERS = po6/io/fd.h po6/error.h po6/noncopyable.h \
po6/threads/rwlock.h po6/threads/cond.h \
po6/threads/spinlock.h po6/threads/thread.h \
po6/threads/mutex.h po6/threads/barrier.h \
- po6/pathname.h po6/net/ipaddr.h po6/net/location.h \
- po6/net/socket.h
+ po6/pathname.h po6/net/hostname.h po6/net/ipaddr.h \
+ po6/net/location.h po6/net/socket.h
##################################### Tests ####################################
@@ -26,6 +26,7 @@ TESTS = $(check_PROGRAMS)
check_PROGRAMS = \
test/error \
test/io_fd \
+ test/net_hostname \
test/net_ipaddr \
test/net_location \
test/net_socket \
@@ -40,6 +41,8 @@ test_error_SOURCES = test/runner.cc test/error.cc
test_error_LDADD = $(GTEST_LIBS)
test_io_fd_SOURCES = test/runner.cc test/io/fd.cc
test_io_fd_LDADD = $(GTEST_LIBS)
+test_net_hostname_SOURCES = test/runner.cc test/net/hostname.cc
+test_net_hostname_LDADD = $(GTEST_LIBS)
test_net_ipaddr_SOURCES = test/runner.cc test/net/ipaddr.cc
test_net_ipaddr_LDADD = $(GTEST_LIBS)
test_net_location_SOURCES = test/runner.cc test/net/location.cc
View
175 po6/net/hostname.h
@@ -0,0 +1,175 @@
+// Copyright (c) 2012, Robert Escriva
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of po6 nor the names of its contributors may be used
+// to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef po6_net_hostname_h_
+#define po6_net_hostname_h_
+
+// C
+#include <cstdio>
+
+// POSIX
+#include <netdb.h>
+
+// po6
+#include <po6/net/location.h>
+#include <po6/net/socket.h>
+
+namespace po6
+{
+namespace net
+{
+
+class hostname
+{
+ public:
+ hostname();
+ explicit hostname(const char* _address, in_port_t _port);
+ hostname(const hostname& other);
+ ~hostname() throw ();
+
+ public:
+ location connect(int domain, int type, int protocol, po6::net::socket* sock) const;
+
+ public:
+ bool operator < (const hostname& rhs) const { return compare(rhs) < 0; }
+ bool operator <= (const hostname& rhs) const { return compare(rhs) <= 0; }
+ bool operator == (const hostname& rhs) const { return compare(rhs) == 0; }
+ bool operator != (const hostname& rhs) const { return compare(rhs) != 0; }
+ bool operator >= (const hostname& rhs) const { return compare(rhs) >= 0; }
+ bool operator > (const hostname& rhs) const { return compare(rhs) > 0; }
+
+ public:
+ std::string address;
+ in_port_t port;
+
+ private:
+ class protect_addrinfo;
+
+ private:
+ int compare(const hostname& rhs) const;
+};
+
+class hostname::protect_addrinfo
+{
+ public:
+ protect_addrinfo(addrinfo* ai) : m_ai(ai) {}
+ ~protect_addrinfo() throw () { if (m_ai) { freeaddrinfo(m_ai); } }
+
+ private:
+ addrinfo* m_ai;
+};
+
+inline
+hostname :: hostname()
+ : address()
+ , port()
+{
+}
+
+inline
+hostname :: hostname(const char* _hostname, in_port_t _port)
+ : address(_hostname)
+ , port(_port)
+{
+}
+
+inline
+hostname :: hostname(const hostname& other)
+ : address(other.address)
+ , port(other.port)
+{
+}
+
+inline
+hostname :: ~hostname() throw ()
+{
+}
+
+inline po6::net::location
+hostname :: connect(int domain, int type, int protocol, po6::net::socket* sock) const
+{
+ // Convert the port to a C string
+ char port_cstr[6];
+ snprintf(port_cstr, 6, "%u", port);
+
+ // Setup the hints
+ addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
+ hints.ai_family = domain;
+ hints.ai_socktype = type;
+ hints.ai_protocol = protocol;
+
+ // Make the call
+ addrinfo* res = NULL;
+ int gai_err = getaddrinfo(address.c_str(), port_cstr, &hints, &res);
+
+ if (gai_err)
+ {
+ throw po6::error(gai_err, gai_strerror(gai_err));
+ }
+
+ protect_addrinfo pai(res);
+ location loc;
+
+ for (addrinfo* ai = res; ai; ai = ai->ai_next)
+ {
+ if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
+ {
+ errno = ECONNREFUSED;
+ continue;
+ }
+
+ sock->reset(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+
+ if (sock->get() < 0)
+ {
+ continue;
+ }
+
+ if (::connect(sock->get(), ai->ai_addr, ai->ai_addrlen) < 0)
+ {
+ sock->close();
+ continue;
+ }
+
+ loc = location(ai->ai_addr, ai->ai_addrlen);
+ break;
+ }
+
+ if (sock->get() < 0)
+ {
+ throw po6::error(errno);
+ }
+
+ return loc;
+}
+
+} // namespace net
+} // namespace po6
+
+#endif // po6_net_hostname_h_
View
56 test/net/hostname.cc
@@ -0,0 +1,56 @@
+// Copyright (c) 2012, Robert Escriva
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of po6 nor the names of its contributors may be used
+// to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+// Google Test
+#include <gtest/gtest.h>
+
+// po6
+#include "po6/net/hostname.h"
+#include "po6/net/socket.h"
+
+#pragma GCC diagnostic ignored "-Wswitch-default"
+
+namespace
+{
+
+TEST(HostnameTest, CtorAndDtor)
+{
+ po6::net::hostname hostname1;
+ po6::net::hostname hostname2("hyperdex.org", 80);
+ po6::net::hostname hostname3(hostname2);
+}
+
+TEST(HostnameTest, Comparison)
+{
+ po6::net::hostname hostname("hyperdex.org", 80);
+ po6::net::socket sock;
+ po6::net::location loc;
+
+ loc = hostname.connect(AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, &sock);
+}
+
+} // namespace

0 comments on commit a2db489

Please sign in to comment.