diff options
author | agayev@chromium.org <agayev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-26 17:55:05 +0000 |
---|---|---|
committer | agayev@chromium.org <agayev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-26 17:55:05 +0000 |
commit | a506e8f0db3a685046f9163209837b221df0a201 (patch) | |
tree | 225836a3386c9783056279dc0e655d76fd4eff2a /net | |
parent | ca393c92c74b62915504e717a57e4169d27fdcd5 (diff) | |
download | chromium_src-a506e8f0db3a685046f9163209837b221df0a201.zip chromium_src-a506e8f0db3a685046f9163209837b221df0a201.tar.gz chromium_src-a506e8f0db3a685046f9163209837b221df0a201.tar.bz2 |
Added static method that allows creation of an AddressList from a list of IP addresses
BUG=None
TEST=net_unittests
Review URL: http://codereview.chromium.org/6987023
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@86852 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/base/address_list.cc | 109 | ||||
-rw-r--r-- | net/base/address_list.h | 5 | ||||
-rw-r--r-- | net/base/address_list_unittest.cc | 46 |
3 files changed, 120 insertions, 40 deletions
diff --git a/net/base/address_list.cc b/net/base/address_list.cc index 8cda64f..5763a9a 100644 --- a/net/base/address_list.cc +++ b/net/base/address_list.cc @@ -22,6 +22,52 @@ char* do_strdup(const char* src) { #endif } +struct addrinfo* CreateAddrInfo(const IPAddressNumber& address, + bool canonicalize_name) { + struct addrinfo* ai = new addrinfo; + memset(ai, 0, sizeof(addrinfo)); + ai->ai_socktype = SOCK_STREAM; + + switch (address.size()) { + case kIPv4AddressSize: { + ai->ai_family = AF_INET; + const size_t sockaddr_in_size = sizeof(struct sockaddr_in); + ai->ai_addrlen = sockaddr_in_size; + + struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>( + new char[sockaddr_in_size]); + memset(addr, 0, sockaddr_in_size); + addr->sin_family = AF_INET; + memcpy(&addr->sin_addr, &address[0], kIPv4AddressSize); + ai->ai_addr = reinterpret_cast<struct sockaddr*>(addr); + break; + } + case kIPv6AddressSize: { + ai->ai_family = AF_INET6; + const size_t sockaddr_in6_size = sizeof(struct sockaddr_in6); + ai->ai_addrlen = sockaddr_in6_size; + + struct sockaddr_in6* addr6 = reinterpret_cast<struct sockaddr_in6*>( + new char[sockaddr_in6_size]); + memset(addr6, 0, sockaddr_in6_size); + addr6->sin6_family = AF_INET6; + memcpy(&addr6->sin6_addr, &address[0], kIPv6AddressSize); + ai->ai_addr = reinterpret_cast<struct sockaddr*>(addr6); + break; + } + default: { + NOTREACHED() << "Bad IP address"; + break; + } + } + + if (canonicalize_name) { + std::string name = NetAddressToString(ai); + ai->ai_canonname = do_strdup(name.c_str()); + } + return ai; +} + } // namespace struct AddressList::Data : public base::RefCountedThreadSafe<Data> { @@ -58,6 +104,28 @@ AddressList& AddressList::operator=(const AddressList& addresslist) { } // static +AddressList AddressList::CreateFromIPAddressList( + const std::vector<IPAddressNumber>& addresses, + uint16 port) { + DCHECK(!addresses.empty()); + struct addrinfo* head = NULL; + struct addrinfo* next = NULL; + + for (std::vector<IPAddressNumber>::const_iterator it = addresses.begin(); + it != addresses.end(); ++it) { + if (head == NULL) { + head = next = CreateAddrInfo(*it, false); + } else { + next->ai_next = CreateAddrInfo(*it, false); + next = next->ai_next; + } + } + + SetPortForAllAddrinfos(head, port); + return AddressList(new Data(head, false)); +} + +// static AddressList AddressList::CreateFromIPAddress( const IPAddressNumber& address, uint16 port) { @@ -69,47 +137,8 @@ AddressList AddressList::CreateFromIPAddressWithCname( const IPAddressNumber& address, uint16 port, bool canonicalize_name) { - struct addrinfo* ai = new addrinfo; - memset(ai, 0, sizeof(addrinfo)); - ai->ai_socktype = SOCK_STREAM; + struct addrinfo* ai = CreateAddrInfo(address, canonicalize_name); - switch (address.size()) { - case 4: { - ai->ai_family = AF_INET; - const size_t sockaddr_in_size = sizeof(struct sockaddr_in); - ai->ai_addrlen = sockaddr_in_size; - - struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>( - new char[sockaddr_in_size]); - memset(addr, 0, sockaddr_in_size); - addr->sin_family = AF_INET; - memcpy(&addr->sin_addr, &address[0], 4); - ai->ai_addr = reinterpret_cast<struct sockaddr*>(addr); - break; - } - case 16: { - ai->ai_family = AF_INET6; - const size_t sockaddr_in6_size = sizeof(struct sockaddr_in6); - ai->ai_addrlen = sockaddr_in6_size; - - struct sockaddr_in6* addr6 = reinterpret_cast<struct sockaddr_in6*>( - new char[sockaddr_in6_size]); - memset(addr6, 0, sockaddr_in6_size); - addr6->sin6_family = AF_INET6; - memcpy(&addr6->sin6_addr, &address[0], 16); - ai->ai_addr = reinterpret_cast<struct sockaddr*>(addr6); - break; - } - default: { - NOTREACHED() << "Bad IP address"; - break; - } - } - - if (canonicalize_name) { - std::string name = NetAddressToString(ai); - ai->ai_canonname = do_strdup(name.c_str()); - } SetPortForAllAddrinfos(ai, port); return AddressList(new Data(ai, false /*is_system_created*/)); } diff --git a/net/base/address_list.h b/net/base/address_list.h index e29e34b..840bc51 100644 --- a/net/base/address_list.h +++ b/net/base/address_list.h @@ -28,6 +28,11 @@ class NET_API AddressList { ~AddressList(); AddressList& operator=(const AddressList& addresslist); + // Creates an address list for a list of IP literals. + static AddressList CreateFromIPAddressList( + const std::vector<IPAddressNumber>& addresses, + uint16 port); + // Creates an address list for a single IP literal. static AddressList CreateFromIPAddress( const IPAddressNumber& address, diff --git a/net/base/address_list_unittest.cc b/net/base/address_list_unittest.cc index 1409258..202a8b7 100644 --- a/net/base/address_list_unittest.cc +++ b/net/base/address_list_unittest.cc @@ -274,5 +274,51 @@ TEST(AddressListTest, AddressFromAddrInfo) { } } +TEST(AddressListTest, CreateFromIPAddressList) { + struct TestData { + std::string ip_address; + bool is_ipv6; + } tests[] = { + { "127.0.0.1", false }, + { "2001:db8:0::42", true }, + { "192.168.1.1", false }, + }; + + // Construct a list of ip addresses. + std::vector<IPAddressNumber> ip_list; + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + IPAddressNumber ip_number; + ParseIPLiteralToNumber(tests[i].ip_address, &ip_number); + ip_list.push_back(ip_number); + } + + AddressList test_list = AddressList::CreateFromIPAddressList(ip_list, 80); + EXPECT_EQ(80, test_list.GetPort()); + + // Make sure that CreateFromIPAddressList has created an addrinfo + // chain of exactly the same length as the |tests| with correct content. + struct addrinfo* next_ai = const_cast<struct addrinfo*>(test_list.head()); + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { + ASSERT_TRUE(next_ai != NULL); + AddressList expected_list; + int rv = CreateAddressList(tests[i].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."; + } else { + ASSERT_EQ(0, rv); + const struct addrinfo* good_ai = expected_list.head(); + EXPECT_EQ(good_ai->ai_family, next_ai->ai_family); + EXPECT_EQ(good_ai->ai_addrlen, next_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, next_ai->ai_addr, sockaddr_size), 0); + } + next_ai = next_ai->ai_next; + } + EXPECT_EQ(NULL, next_ai); +} + } // namespace } // namespace net |