diff options
author | mbelshe@chromium.org <mbelshe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-02 01:30:16 +0000 |
---|---|---|
committer | mbelshe@chromium.org <mbelshe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-02 01:30:16 +0000 |
commit | 4e5572f5a91691d0112717ee93013f58e36a6d65 (patch) | |
tree | 15966c346e831f9d9c8203e47103aa83f3fb35ed /net/base | |
parent | d062d9636fb69a79942ada2321fe48e9f326cf8c (diff) | |
download | chromium_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.cc | 44 | ||||
-rw-r--r-- | net/base/address_list.h | 10 | ||||
-rw-r--r-- | net/base/address_list_unittest.cc | 41 |
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 |