summaryrefslogtreecommitdiffstats
path: root/net/base
diff options
context:
space:
mode:
authormbelshe@chromium.org <mbelshe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-02 01:30:16 +0000
committermbelshe@chromium.org <mbelshe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-02 01:30:16 +0000
commit4e5572f5a91691d0112717ee93013f58e36a6d65 (patch)
tree15966c346e831f9d9c8203e47103aa83f3fb35ed /net/base
parentd062d9636fb69a79942ada2321fe48e9f326cf8c (diff)
downloadchromium_src-4e5572f5a91691d0112717ee93013f58e36a6d65.zip
chromium_src-4e5572f5a91691d0112717ee93013f58e36a6d65.tar.gz
chromium_src-4e5572f5a91691d0112717ee93013f58e36a6d65.tar.bz2
Add constructor for creating an AddressList from a struct sockaddr. This is
preliminary work for using UDP, where we're going to use recvfrom(), which receives a sockaddr from the network call, and we want to turn that into an AddressList which is more usable for the app. BUG=none TEST=AddressFromAddressInfo Review URL: http://codereview.chromium.org/6598040 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76489 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base')
-rw-r--r--net/base/address_list.cc44
-rw-r--r--net/base/address_list.h10
-rw-r--r--net/base/address_list_unittest.cc41
3 files changed, 95 insertions, 0 deletions
diff --git a/net/base/address_list.cc b/net/base/address_list.cc
index 14ee0d6..d2f1974 100644
--- a/net/base/address_list.cc
+++ b/net/base/address_list.cc
@@ -219,11 +219,55 @@ void AddressList::Reset() {
}
const struct addrinfo* AddressList::head() const {
+ if (!data_)
+ return NULL;
return data_->head;
}
AddressList::AddressList(Data* data) : data_(data) {}
+// static
+AddressList* AddressList::CreateAddressListFromSockaddr(
+ const struct sockaddr* address,
+ socklen_t address_length,
+ int socket_type,
+ int protocol) {
+ // Do sanity checking on socket_type and protocol.
+ DCHECK(socket_type == SOCK_DGRAM || socket_type == SOCK_STREAM);
+ DCHECK(protocol == IPPROTO_TCP || protocol == IPPROTO_UDP);
+
+ struct addrinfo* ai = new addrinfo;
+ memset(ai, 0, sizeof(addrinfo));
+ switch (address_length) {
+ case sizeof(struct sockaddr_in):
+ {
+ const struct sockaddr_in* sin =
+ reinterpret_cast<const struct sockaddr_in*>(address);
+ ai->ai_family = sin->sin_family;
+ DCHECK_EQ(AF_INET, ai->ai_family);
+ }
+ break;
+ case sizeof(struct sockaddr_in6):
+ {
+ const struct sockaddr_in6* sin6 =
+ reinterpret_cast<const struct sockaddr_in6*>(address);
+ ai->ai_family = sin6->sin6_family;
+ DCHECK_EQ(AF_INET6, ai->ai_family);
+ }
+ break;
+ default:
+ NOTREACHED() << "Bad IP address";
+ break;
+ }
+ ai->ai_socktype = socket_type;
+ ai->ai_protocol = protocol;
+ ai->ai_addrlen = address_length;
+ ai->ai_addr = reinterpret_cast<struct sockaddr*>(new char[address_length]);
+ memcpy(ai->ai_addr, address, address_length);
+ return new AddressList(new Data(ai, false /*is_system_created*/));
+}
+
+
AddressList::Data::Data(struct addrinfo* ai, bool is_system_created)
: head(ai), is_system_created(is_system_created) {
DCHECK(head);
diff --git a/net/base/address_list.h b/net/base/address_list.h
index 9406a8c..2993528 100644
--- a/net/base/address_list.h
+++ b/net/base/address_list.h
@@ -74,6 +74,16 @@ class AddressList {
// Get access to the head of the addrinfo list.
const struct addrinfo* head() const;
+ // Constructs an address list for a single socket address.
+ // |address| the sockaddr to copy.
+ // |socket_type| is either SOCK_STREAM or SOCK_DGRAM.
+ // |protocol| is either IPPROTO_TCP or IPPROTO_UDP.
+ static AddressList* CreateAddressListFromSockaddr(
+ const struct sockaddr* address,
+ socklen_t address_length,
+ int socket_type,
+ int protocol);
+
private:
struct Data;
diff --git a/net/base/address_list_unittest.cc b/net/base/address_list_unittest.cc
index 65d0f5c..2a13f45 100644
--- a/net/base/address_list_unittest.cc
+++ b/net/base/address_list_unittest.cc
@@ -4,6 +4,7 @@
#include "net/base/address_list.h"
+#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "net/base/host_resolver_proc.h"
#include "net/base/net_util.h"
@@ -213,4 +214,44 @@ TEST(AddressListTest, IPLiteralConstructor) {
}
}
+TEST(AddressListTest, AddressFromAddrInfo) {
+ struct TestData {
+ std::string ip_address;
+ std::string canonical_ip_address;
+ bool is_ipv6;
+ } tests[] = {
+ { "127.0.00.1", "127.0.0.1", false },
+ { "192.168.1.1", "192.168.1.1", false },
+ { "::1", "::1", true },
+ { "2001:db8:0::42", "2001:db8::42", true },
+ };
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); i++) {
+ net::AddressList expected_list;
+ int rv = CreateAddressList(tests[i].canonical_ip_address, 80,
+ &expected_list);
+ if (tests[i].is_ipv6 && rv != 0) {
+ LOG(WARNING) << "Unable to resolve ip literal '" << tests[i].ip_address
+ << "' test skipped.";
+ continue;
+ }
+ ASSERT_EQ(0, rv);
+ const struct addrinfo* good_ai = expected_list.head();
+
+ scoped_ptr<net::AddressList> test_list(
+ net::AddressList::CreateAddressListFromSockaddr(good_ai->ai_addr,
+ good_ai->ai_addrlen,
+ SOCK_STREAM,
+ IPPROTO_TCP));
+ const struct addrinfo* test_ai = test_list->head();
+
+ EXPECT_EQ(good_ai->ai_family, test_ai->ai_family);
+ EXPECT_EQ(good_ai->ai_addrlen, test_ai->ai_addrlen);
+ size_t sockaddr_size =
+ good_ai->ai_socktype == AF_INET ? sizeof(struct sockaddr_in) :
+ good_ai->ai_socktype == AF_INET6 ? sizeof(struct sockaddr_in6) : 0;
+ EXPECT_EQ(memcmp(good_ai->ai_addr, test_ai->ai_addr, sockaddr_size), 0);
+ EXPECT_EQ(good_ai->ai_next, test_ai->ai_next);
+ }
+}
+
} // namespace