summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authoragayev@chromium.org <agayev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-26 17:55:05 +0000
committeragayev@chromium.org <agayev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-26 17:55:05 +0000
commita506e8f0db3a685046f9163209837b221df0a201 (patch)
tree225836a3386c9783056279dc0e655d76fd4eff2a /net
parentca393c92c74b62915504e717a57e4169d27fdcd5 (diff)
downloadchromium_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.cc109
-rw-r--r--net/base/address_list.h5
-rw-r--r--net/base/address_list_unittest.cc46
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