diff options
Diffstat (limited to 'net/base')
-rw-r--r-- | net/base/address_list.cc | 285 | ||||
-rw-r--r-- | net/base/address_list.h | 136 | ||||
-rw-r--r-- | net/base/address_list_net_log_param.cc | 8 | ||||
-rw-r--r-- | net/base/address_list_unittest.cc | 301 | ||||
-rw-r--r-- | net/base/host_port_pair.cc | 10 | ||||
-rw-r--r-- | net/base/host_port_pair.h | 7 | ||||
-rw-r--r-- | net/base/host_resolver_impl.cc | 43 | ||||
-rw-r--r-- | net/base/host_resolver_impl_unittest.cc | 32 | ||||
-rw-r--r-- | net/base/host_resolver_proc.cc | 3 | ||||
-rw-r--r-- | net/base/host_resolver_proc.h | 2 | ||||
-rw-r--r-- | net/base/ip_endpoint.cc | 63 | ||||
-rw-r--r-- | net/base/ip_endpoint.h | 14 | ||||
-rw-r--r-- | net/base/ip_endpoint_unittest.cc | 24 | ||||
-rw-r--r-- | net/base/mapped_host_resolver_unittest.cc | 29 | ||||
-rw-r--r-- | net/base/mock_host_resolver.cc | 29 | ||||
-rw-r--r-- | net/base/net_util.cc | 77 | ||||
-rw-r--r-- | net/base/net_util.h | 38 | ||||
-rw-r--r-- | net/base/net_util_unittest.cc | 73 | ||||
-rw-r--r-- | net/base/single_request_host_resolver_unittest.cc | 5 |
19 files changed, 296 insertions, 883 deletions
diff --git a/net/base/address_list.cc b/net/base/address_list.cc index 4aee12c..e5935c7 100644 --- a/net/base/address_list.cc +++ b/net/base/address_list.cc @@ -4,283 +4,66 @@ #include "net/base/address_list.h" -#include <stdlib.h> - #include "base/logging.h" -#include "base/string_util.h" #include "net/base/net_util.h" #include "net/base/sys_addrinfo.h" namespace net { -namespace { - -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; -#if defined(SIN6_LEN) - addr->sin_len = sockaddr_in_size; -#endif - 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; -#if defined(SIN6_LEN) - addr6->sin6_len = sockaddr_in6_size; -#endif - 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 = base::strdup(name.c_str()); - } - return ai; -} - -} // namespace - -struct AddressList::Data : public base::RefCountedThreadSafe<Data> { - Data(struct addrinfo* ai, bool is_system_created); - - // This variable is const since it should NOT be mutated. Since - // Data is reference counted, this |head| could be shared by multiple - // instances of AddressList, hence we need to be careful not to mutate - // it from any one instance. - const struct addrinfo * const head; - - // Indicates which free function to use for |head|. - bool is_system_created; - - private: - friend class base::RefCountedThreadSafe<Data>; - - ~Data(); -}; +AddressList::AddressList() {} -AddressList::AddressList() { -} - -AddressList::AddressList(const AddressList& addresslist) - : data_(addresslist.data_) { -} +AddressList::~AddressList() {} -AddressList::~AddressList() { +AddressList::AddressList(const IPEndPoint& endpoint) { + push_back(endpoint); } -AddressList& AddressList::operator=(const AddressList& addresslist) { - data_ = addresslist.data_; - return *this; +// static +AddressList AddressList::CreateFromIPAddress(const IPAddressNumber& address, + uint16 port) { + return AddressList(IPEndPoint(address, port)); } // static AddressList AddressList::CreateFromIPAddressList( const IPAddressList& addresses, const std::string& canonical_name) { - DCHECK(!addresses.empty()); - struct addrinfo* head = NULL; - struct addrinfo* next = NULL; - - for (IPAddressList::const_iterator it = addresses.begin(); - it != addresses.end(); ++it) { - if (head == NULL) { - head = next = CreateAddrInfo(*it, false); - if (!canonical_name.empty()) { - head->ai_canonname = base::strdup(canonical_name.c_str()); - } - } else { - next->ai_next = CreateAddrInfo(*it, false); - next = next->ai_next; - } + AddressList list; + list.set_canonical_name(canonical_name); + for (IPAddressList::const_iterator iter = addresses.begin(); + iter != addresses.end(); ++iter) { + list.push_back(IPEndPoint(*iter, 0)); } - - return AddressList(new Data(head, false)); + return list; } // static -AddressList AddressList::CreateFromIPAddress( - const IPAddressNumber& address, - uint16 port) { - return CreateFromIPAddressWithCname(address, port, false); -} - -// static -AddressList AddressList::CreateFromIPAddressWithCname( - const IPAddressNumber& address, - uint16 port, - bool canonicalize_name) { - struct addrinfo* ai = CreateAddrInfo(address, canonicalize_name); - - SetPortForAllAddrinfos(ai, port); - return AddressList(new Data(ai, false /*is_system_created*/)); -} - - -// static -AddressList AddressList::CreateByAdoptingFromSystem(struct addrinfo* head) { - return AddressList(new Data(head, true /*is_system_created*/)); -} - -// static -AddressList AddressList::CreateByCopying(const struct addrinfo* head) { - return AddressList(new Data(CreateCopyOfAddrinfo(head, true /*recursive*/), - false /*is_system_created*/)); -} - -// static -AddressList AddressList::CreateByCopyingFirstAddress( - const struct addrinfo* head) { - return AddressList(new Data(CreateCopyOfAddrinfo(head, false /*recursive*/), - false /*is_system_created*/)); -} - -// static -AddressList AddressList::CreateFromSockaddr( - 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 AddressList(new Data(ai, false /*is_system_created*/)); -} - -void AddressList::Append(const struct addrinfo* head) { +AddressList AddressList::CreateFromAddrinfo(const struct addrinfo* head) { DCHECK(head); - // Always create a copy, since the Data might be shared across instances. - struct addrinfo* new_head = CreateCopyOfAddrinfo(data_->head, true); - data_ = new Data(new_head, false /*is_system_created*/); - - // Find the end of current linked list and append new data there. - struct addrinfo* copy_ptr = new_head; - while (copy_ptr->ai_next) - copy_ptr = copy_ptr->ai_next; - copy_ptr->ai_next = CreateCopyOfAddrinfo(head, true); - - // Only the head of the list should have a canonname. Strip any - // canonical name in the appended data. - copy_ptr = copy_ptr->ai_next; - while (copy_ptr) { - if (copy_ptr->ai_canonname) { - free(copy_ptr->ai_canonname); - copy_ptr->ai_canonname = NULL; - } - copy_ptr = copy_ptr->ai_next; + AddressList list; + if (head->ai_canonname) + list.set_canonical_name(std::string(head->ai_canonname)); + for (const struct addrinfo* ai = head; ai; ai = ai->ai_next) { + IPEndPoint ipe; + // NOTE: Ignoring non-INET* families. + if (ipe.FromSockAddr(ai->ai_addr, ai->ai_addrlen)) + list.push_back(ipe); + else + DLOG(WARNING) << "Unknown family found in addrinfo: " << ai->ai_family; } + return list; } -void AddressList::SetPort(uint16 port) { - // NOTE: we need to be careful not to mutate the reference-counted data, - // since it might be shared by other AddressLists. - struct addrinfo* head = CreateCopyOfAddrinfo(data_->head, true); - SetPortForAllAddrinfos(head, port); - data_ = new Data(head, false /*is_system_created*/); +void AddressList::SetDefaultCanonicalName() { + DCHECK(!empty()); + set_canonical_name(front().ToStringWithoutPort()); } -uint16 AddressList::GetPort() const { - return GetPortFromAddrinfo(data_->head); -} - -bool AddressList::GetCanonicalName(std::string* canonical_name) const { - DCHECK(canonical_name); - if (!data_ || !data_->head->ai_canonname) - return false; - canonical_name->assign(data_->head->ai_canonname); - return true; -} - -const struct addrinfo* AddressList::head() const { - if (!data_) - return NULL; - return data_->head; -} - -AddressList::AddressList(Data* data) : data_(data) {} - -AddressList::Data::Data(struct addrinfo* ai, bool is_system_created) - : head(ai), is_system_created(is_system_created) { - DCHECK(head); -} - -AddressList::Data::~Data() { - // Casting away the const is safe, since upon destruction we know that - // no one holds a reference to the data any more. - struct addrinfo* mutable_head = const_cast<struct addrinfo*>(head); - - // Call either freeaddrinfo(head), or FreeMyAddrinfo(head), depending who - // created the data. - if (is_system_created) - freeaddrinfo(mutable_head); - else - FreeCopyOfAddrinfo(mutable_head); -} - -AddressList CreateAddressListUsingPort(const AddressList& src, int port) { - if (src.GetPort() == port) - return src; - - AddressList out = src; - out.SetPort(port); - return out; +void SetPortOnAddressList(uint16 port, AddressList* list) { + DCHECK(list); + for (AddressList::iterator it = list->begin(); it != list->end(); ++it) { + *it = IPEndPoint(it->address(), port); + } } } // namespace net diff --git a/net/base/address_list.h b/net/base/address_list.h index edcdf09..c76152f 100644 --- a/net/base/address_list.h +++ b/net/base/address_list.h @@ -7,8 +7,10 @@ #pragma once #include <string> +#include <vector> -#include "base/memory/ref_counted.h" +#include "base/basictypes.h" +#include "net/base/ip_endpoint.h" #include "net/base/net_export.h" #include "net/base/net_util.h" @@ -16,106 +18,62 @@ struct addrinfo; namespace net { -// An AddressList object contains a linked list of addrinfo structures. This -// class is designed to be copied around by value. -class NET_EXPORT AddressList { +class NET_EXPORT AddressList : private std::vector<IPEndPoint> { public: - // Constructs an invalid address list. Should not call any methods on this - // other than assignment. AddressList(); - - AddressList(const AddressList& addresslist); ~AddressList(); - AddressList& operator=(const AddressList& addresslist); - // Creates an address list for a list of IP literals. + // Creates an address list for a single IP literal. + explicit AddressList(const IPEndPoint& endpoint); + + static AddressList CreateFromIPAddress(const IPAddressNumber& address, + uint16 port); + static AddressList CreateFromIPAddressList( const IPAddressList& addresses, const std::string& canonical_name); - // Creates an address list for a single IP literal. - static AddressList CreateFromIPAddress( - const IPAddressNumber& address, - uint16 port); - - // Creates an address list for a single IP literal. If - // |canonicalize_name| is true, fill the ai_canonname field with the - // canonicalized IP address. - static AddressList CreateFromIPAddressWithCname( - const IPAddressNumber& address, - uint16 port, - bool canonicalize_name); - - // Adopts the given addrinfo list (assumed to have been created by - // the system, e.g. returned by getaddrinfo()) in place of the - // existing one if any. This hands over responsibility for freeing - // the addrinfo list to the AddressList object. - static AddressList CreateByAdoptingFromSystem(struct addrinfo* head); - - // Creates a new address list with a copy of |head|. This includes the - // entire linked list. - static AddressList CreateByCopying(const struct addrinfo* head); - - // Creates a new address list wich has a single address, |head|. If there - // are other addresses in |head| they will be ignored. - static AddressList CreateByCopyingFirstAddress(const struct addrinfo* head); - - // Creates 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 CreateFromSockaddr( - const struct sockaddr* address, - socklen_t address_length, - int socket_type, - int protocol); - - // Appends a copy of |head| and all its linked addrinfos to the stored - // addrinfo. Note that this will cause a reallocation of the linked list, - // which invalidates the head pointer. - void Append(const struct addrinfo* head); - - // Sets the port of all addresses in the list to |port| (that is the - // sin[6]_port field for the sockaddrs). Note that this will cause a - // reallocation of the linked list, which invalidates the head pointer. - void SetPort(uint16 port); - - // Retrieves the port number of the first sockaddr in the list. (If SetPort() - // was previously used on this list, then all the addresses will have this - // same port number.) - uint16 GetPort() const; - - // Gets the canonical name for the address. - // If the canonical name exists, |*canonical_name| is filled in with the - // value and true is returned. If it does not exist, |*canonical_name| is - // not altered and false is returned. - // |canonical_name| must be a non-null value. - bool GetCanonicalName(std::string* canonical_name) const; - - // Gets access to the head of the addrinfo list. - // - // IMPORTANT: Callers SHOULD NOT mutate the addrinfo chain, since under the - // hood this data might be shared by other AddressLists, which - // might even be running on other threads. - // - // Additionally, non-const methods like SetPort() and Append() can - // cause the head to be reallocated, so do not cache the return - // value of head() across such calls. - const struct addrinfo* head() const; + // Copies the data from |head| and the chained list into an AddressList. + static AddressList CreateFromAddrinfo(const struct addrinfo* head); + + // TODO(szym): Remove all three. http://crbug.com/126134 + const std::string& canonical_name() const { + return canonical_name_; + } + + void set_canonical_name(const std::string& canonical_name) { + canonical_name_ = canonical_name; + } + + // Sets canonical name to the literal of the first IP address on the list. + void SetDefaultCanonicalName(); + + // Exposed methods from std::vector. + using std::vector<IPEndPoint>::size; + using std::vector<IPEndPoint>::empty; + using std::vector<IPEndPoint>::clear; + using std::vector<IPEndPoint>::reserve; + using std::vector<IPEndPoint>::capacity; + using std::vector<IPEndPoint>::operator[]; + using std::vector<IPEndPoint>::front; + using std::vector<IPEndPoint>::back; + using std::vector<IPEndPoint>::push_back; + using std::vector<IPEndPoint>::insert; + using std::vector<IPEndPoint>::erase; + using std::vector<IPEndPoint>::iterator; + using std::vector<IPEndPoint>::const_iterator; + using std::vector<IPEndPoint>::begin; + using std::vector<IPEndPoint>::end; + using std::vector<IPEndPoint>::rbegin; + using std::vector<IPEndPoint>::rend; private: - struct Data; - - explicit AddressList(Data* data); - - scoped_refptr<Data> data_; + // TODO(szym): Remove. http://crbug.com/126134 + std::string canonical_name_; }; -// Helper to create an AddressList that has a particular port. It has an -// optimization to avoid allocating a new address linked list when the -// port is already what we want. -AddressList NET_EXPORT CreateAddressListUsingPort(const AddressList& src, - int port); +// Sets the port on each element in |list| to |port|. +void NET_EXPORT SetPortOnAddressList(uint16 port, AddressList* list); } // namespace net diff --git a/net/base/address_list_net_log_param.cc b/net/base/address_list_net_log_param.cc index 72332ef..78fa660 100644 --- a/net/base/address_list_net_log_param.cc +++ b/net/base/address_list_net_log_param.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,7 +6,6 @@ #include "base/values.h" #include "net/base/net_util.h" -#include "net/base/sys_addrinfo.h" namespace net { @@ -18,9 +17,8 @@ Value* AddressListNetLogParam::ToValue() const { DictionaryValue* dict = new DictionaryValue(); ListValue* list = new ListValue(); - for (const addrinfo* head = address_list_.head(); - head != NULL ; head = head->ai_next) { - list->Append(Value::CreateStringValue(NetAddressToStringWithPort(head))); + for (size_t i = 0; i < address_list_.size() ; ++i) { + list->Append(Value::CreateStringValue(address_list_[i].ToString())); } dict->Set("address_list", list); diff --git a/net/base/address_list_unittest.cc b/net/base/address_list_unittest.cc index 7eda7df..734332e 100644 --- a/net/base/address_list_unittest.cc +++ b/net/base/address_list_unittest.cc @@ -4,155 +4,25 @@ #include "net/base/address_list.h" -#include "base/memory/scoped_ptr.h" #include "base/string_util.h" -#include "net/base/host_resolver_proc.h" +#include "base/sys_byteorder.h" #include "net/base/net_util.h" #include "net/base/sys_addrinfo.h" -#if defined(OS_WIN) -#include "net/base/winsock_init.h" -#endif #include "testing/gtest/include/gtest/gtest.h" namespace net { namespace { -void MutableSetPort(uint16 port, AddressList* addrlist) { - struct addrinfo* mutable_head = - const_cast<struct addrinfo*>(addrlist->head()); - SetPortForAllAddrinfos(mutable_head, port); -} - -// Use getaddrinfo() to allocate an addrinfo structure. -int CreateAddressList(const std::string& hostname, int port, - AddressList* addrlist) { -#if defined(OS_WIN) - EnsureWinsockInit(); -#endif - int rv = SystemHostResolverProc(hostname, - ADDRESS_FAMILY_UNSPECIFIED, - 0, - addrlist, NULL); - if (rv == 0) - MutableSetPort(port, addrlist); - return rv; -} - -void CreateLongAddressList(AddressList* addrlist, int port) { - EXPECT_EQ(0, CreateAddressList("192.168.1.1", port, addrlist)); - AddressList second_list; - EXPECT_EQ(0, CreateAddressList("192.168.1.2", port, &second_list)); - addrlist->Append(second_list.head()); -} - -TEST(AddressListTest, GetPort) { - AddressList addrlist; - EXPECT_EQ(0, CreateAddressList("192.168.1.1", 81, &addrlist)); - EXPECT_EQ(81, addrlist.GetPort()); - - MutableSetPort(83, &addrlist); - EXPECT_EQ(83, addrlist.GetPort()); -} - -TEST(AddressListTest, SetPortMakesCopy) { - AddressList addrlist1; - EXPECT_EQ(0, CreateAddressList("192.168.1.1", 85, &addrlist1)); - EXPECT_EQ(85, addrlist1.GetPort()); - - AddressList addrlist2 = addrlist1; - EXPECT_EQ(85, addrlist2.GetPort()); - - // addrlist1 should not be affected by the assignment to - // addrlist2. - addrlist1.SetPort(80); - EXPECT_EQ(80, addrlist1.GetPort()); - EXPECT_EQ(85, addrlist2.GetPort()); -} - -TEST(AddressListTest, Assignment) { - AddressList addrlist1; - EXPECT_EQ(0, CreateAddressList("192.168.1.1", 85, &addrlist1)); - EXPECT_EQ(85, addrlist1.GetPort()); - - // Should reference the same data as addrlist1 -- so when we change addrlist1 - // both are changed. - AddressList addrlist2 = addrlist1; - EXPECT_EQ(85, addrlist2.GetPort()); - - MutableSetPort(80, &addrlist1); - EXPECT_EQ(80, addrlist1.GetPort()); - EXPECT_EQ(80, addrlist2.GetPort()); -} - -TEST(AddressListTest, CopyRecursive) { - AddressList addrlist1; - CreateLongAddressList(&addrlist1, 85); - EXPECT_EQ(85, addrlist1.GetPort()); - - AddressList addrlist2 = - AddressList::CreateByCopying(addrlist1.head()); - - ASSERT_TRUE(addrlist2.head()->ai_next != NULL); - - // addrlist1 is the same as addrlist2 at this point. - EXPECT_EQ(85, addrlist1.GetPort()); - EXPECT_EQ(85, addrlist2.GetPort()); - - // Changes to addrlist1 are not reflected in addrlist2. - MutableSetPort(70, &addrlist1); - MutableSetPort(90, &addrlist2); - - EXPECT_EQ(70, addrlist1.GetPort()); - EXPECT_EQ(90, addrlist2.GetPort()); -} - -TEST(AddressListTest, CopyNonRecursive) { - AddressList addrlist1; - CreateLongAddressList(&addrlist1, 85); - EXPECT_EQ(85, addrlist1.GetPort()); - - AddressList addrlist2 = - AddressList::CreateByCopyingFirstAddress(addrlist1.head()); - - ASSERT_TRUE(addrlist2.head()->ai_next == NULL); - - // addrlist1 is the same as addrlist2 at this point. - EXPECT_EQ(85, addrlist1.GetPort()); - EXPECT_EQ(85, addrlist2.GetPort()); - - // Changes to addrlist1 are not reflected in addrlist2. - MutableSetPort(70, &addrlist1); - MutableSetPort(90, &addrlist2); - - EXPECT_EQ(70, addrlist1.GetPort()); - EXPECT_EQ(90, addrlist2.GetPort()); -} - -TEST(AddressListTest, Append) { - AddressList addrlist1; - EXPECT_EQ(0, CreateAddressList("192.168.1.1", 11, &addrlist1)); - EXPECT_EQ(11, addrlist1.GetPort()); - AddressList addrlist2; - EXPECT_EQ(0, CreateAddressList("192.168.1.2", 12, &addrlist2)); - EXPECT_EQ(12, addrlist2.GetPort()); - - ASSERT_TRUE(addrlist1.head()->ai_next == NULL); - addrlist1.Append(addrlist2.head()); - ASSERT_TRUE(addrlist1.head()->ai_next != NULL); - - AddressList addrlist3 = - AddressList::CreateByCopyingFirstAddress(addrlist1.head()->ai_next); - EXPECT_EQ(12, addrlist3.GetPort()); -} - static const char* kCanonicalHostname = "canonical.bar.com"; TEST(AddressListTest, Canonical) { // Create an addrinfo with a canonical name. - sockaddr_in address; + struct sockaddr_in address; // The contents of address do not matter for this test, // so just zero-ing them out for consistency. memset(&address, 0x0, sizeof(address)); + // But we need to set the family. + address.sin_family = AF_INET; struct addrinfo ai; memset(&ai, 0x0, sizeof(ai)); ai.ai_family = AF_INET; @@ -163,115 +33,57 @@ TEST(AddressListTest, Canonical) { // Copy the addrinfo struct into an AddressList object and // make sure it seems correct. - AddressList addrlist1 = AddressList::CreateByCopying(&ai); - const struct addrinfo* addrinfo1 = addrlist1.head(); - EXPECT_TRUE(addrinfo1 != NULL); - EXPECT_TRUE(addrinfo1->ai_next == NULL); - std::string canon_name1; - EXPECT_TRUE(addrlist1.GetCanonicalName(&canon_name1)); - EXPECT_EQ("canonical.bar.com", canon_name1); + AddressList addrlist1 = AddressList::CreateFromAddrinfo(&ai); + EXPECT_EQ("canonical.bar.com", addrlist1.canonical_name()); // Copy the AddressList to another one. - AddressList addrlist2 = AddressList::CreateByCopying(addrinfo1); - const struct addrinfo* addrinfo2 = addrlist2.head(); - EXPECT_TRUE(addrinfo2 != NULL); - EXPECT_TRUE(addrinfo2->ai_next == NULL); - EXPECT_TRUE(addrinfo2->ai_canonname != NULL); - EXPECT_NE(addrinfo1, addrinfo2); - EXPECT_NE(addrinfo1->ai_canonname, addrinfo2->ai_canonname); - std::string canon_name2; - EXPECT_TRUE(addrlist2.GetCanonicalName(&canon_name2)); - EXPECT_EQ("canonical.bar.com", canon_name2); - - // Make sure that GetCanonicalName correctly returns false - // when ai_canonname is NULL. - ai.ai_canonname = NULL; - AddressList addrlist_no_canon = AddressList::CreateByCopying(&ai); - std::string canon_name3 = "blah"; - EXPECT_FALSE(addrlist_no_canon.GetCanonicalName(&canon_name3)); - EXPECT_EQ("blah", canon_name3); + AddressList addrlist2 = addrlist1; + EXPECT_EQ("canonical.bar.com", addrlist2.canonical_name()); } -TEST(AddressListTest, IPLiteralConstructor) { - 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++) { - 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(); +TEST(AddressListTest, CreateFromAddrinfo) { + // Create an 4-element addrinfo. + const unsigned kNumElements = 4; + SockaddrStorage storage[kNumElements]; + struct addrinfo ai[kNumElements]; + for (unsigned i = 0; i < kNumElements; ++i) { + struct sockaddr_in* addr = + reinterpret_cast<struct sockaddr_in*>(storage[i].addr); + storage[i].addr_len = sizeof(struct sockaddr_in); + // Populating the address with { i, i, i, i }. + memset(&addr->sin_addr, i, kIPv4AddressSize); + addr->sin_family = AF_INET; + // Set port to i << 2; + addr->sin_port = base::HostToNet16(static_cast<uint16>(i << 2)); + memset(&ai[i], 0x0, sizeof(ai[i])); + ai[i].ai_family = addr->sin_family; + ai[i].ai_socktype = SOCK_STREAM; + ai[i].ai_addrlen = storage[i].addr_len; + ai[i].ai_addr = storage[i].addr; + if (i + 1 < kNumElements) + ai[i].ai_next = &ai[i + 1]; + } - IPAddressNumber ip_number; - ASSERT_TRUE(ParseIPLiteralToNumber(tests[i].ip_address, &ip_number)); - AddressList test_list = AddressList::CreateFromIPAddressWithCname( - ip_number, 80, true); - const struct addrinfo* test_ai = test_list.head(); + AddressList list = AddressList::CreateFromAddrinfo(&ai[0]); - EXPECT_EQ(good_ai->ai_family, test_ai->ai_family); - EXPECT_EQ(good_ai->ai_socktype, test_ai->ai_socktype); - 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); - EXPECT_EQ(strcmp(tests[i].canonical_ip_address.c_str(), - test_ai->ai_canonname), 0); + ASSERT_EQ(kNumElements, list.size()); + for (size_t i = 0; i < list.size(); ++i) { + EXPECT_EQ(AF_INET, list[i].GetFamily()); + // Only check the first byte of the address. + EXPECT_EQ(i, list[i].address()[0]); + EXPECT_EQ(static_cast<int>(i << 2), list[i].port()); } -} - -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++) { - 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(); - AddressList test_list = - AddressList::CreateFromSockaddr(good_ai->ai_addr, - good_ai->ai_addrlen, - SOCK_STREAM, - IPPROTO_TCP); - const struct addrinfo* test_ai = test_list.head(); + // Check if operator= works. + AddressList copy; + copy = list; + ASSERT_EQ(kNumElements, copy.size()); - 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_family == AF_INET ? sizeof(struct sockaddr_in) : - good_ai->ai_family == 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); - } + // Check if copy is independent. + copy[1] = IPEndPoint(copy[2].address(), 0xBEEF); + // Original should be unchanged. + EXPECT_EQ(1u, list[1].address()[0]); + EXPECT_EQ(1 << 2, list[1].port()); } TEST(AddressListTest, CreateFromIPAddressList) { @@ -318,25 +130,8 @@ TEST(AddressListTest, CreateFromIPAddressList) { AddressList test_list = AddressList::CreateFromIPAddressList(ip_list, kCanonicalName); std::string canonical_name; - EXPECT_TRUE(test_list.GetCanonicalName(&canonical_name)); - EXPECT_EQ(kCanonicalName, canonical_name); - - // Make sure that CreateFromIPAddressList has created an addrinfo - // chain of exactly the same length as the |tests| with correct content. - const struct addrinfo* next_ai = test_list.head(); - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { - ASSERT_TRUE(next_ai != NULL); - EXPECT_EQ(tests[i].ai_family, next_ai->ai_family); - EXPECT_EQ(tests[i].ai_addrlen, static_cast<size_t>(next_ai->ai_addrlen)); - - char* ai_addr = reinterpret_cast<char*>(next_ai->ai_addr); - int rv = memcmp(tests[i].in_addr, - ai_addr + tests[i].in_addr_offset, - tests[i].in_addr_size); - EXPECT_EQ(0, rv); - next_ai = next_ai->ai_next; - } - EXPECT_EQ(NULL, next_ai); + EXPECT_EQ(kCanonicalName, test_list.canonical_name()); + EXPECT_EQ(ARRAYSIZE_UNSAFE(tests), test_list.size()); } } // namespace diff --git a/net/base/host_port_pair.cc b/net/base/host_port_pair.cc index 773c7ee..6dbb855 100644 --- a/net/base/host_port_pair.cc +++ b/net/base/host_port_pair.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,8 +9,7 @@ #include "base/string_util.h" #include "base/stringprintf.h" #include "googleurl/src/gurl.h" -#include "net/base/net_util.h" -#include "net/base/sys_addrinfo.h" +#include "net/base/ip_endpoint.h" namespace net { @@ -24,9 +23,8 @@ HostPortPair HostPortPair::FromURL(const GURL& url) { } // static -HostPortPair HostPortPair::FromAddrInfo(const struct addrinfo* ai) { - return HostPortPair(NetAddressToString(ai), - GetPortFromSockaddr(ai->ai_addr, ai->ai_addrlen)); +HostPortPair HostPortPair::FromIPEndPoint(const IPEndPoint& ipe) { + return HostPortPair(ipe.ToStringWithoutPort(), ipe.port()); } HostPortPair HostPortPair::FromString(const std::string& str) { diff --git a/net/base/host_port_pair.h b/net/base/host_port_pair.h index 1288a44..df22768 100644 --- a/net/base/host_port_pair.h +++ b/net/base/host_port_pair.h @@ -10,11 +10,12 @@ #include "base/basictypes.h" #include "net/base/net_export.h" -struct addrinfo; class GURL; namespace net { +class IPEndPoint; + class NET_EXPORT HostPortPair { public: HostPortPair(); @@ -24,8 +25,8 @@ class NET_EXPORT HostPortPair { // Creates a HostPortPair for the origin of |url|. static HostPortPair FromURL(const GURL& url); - // Creates a HostPortPair from an addrinfo struct. - static HostPortPair FromAddrInfo(const struct addrinfo* ai); + // Creates a HostPortPair from an IPEndPoint. + static HostPortPair FromIPEndPoint(const IPEndPoint& ipe); // Creates a HostPortPair from a string formatted in same manner as // ToString(). diff --git a/net/base/host_resolver_impl.cc b/net/base/host_resolver_impl.cc index 541246f..d2d9d5d 100644 --- a/net/base/host_resolver_impl.cc +++ b/net/base/host_resolver_impl.cc @@ -70,18 +70,6 @@ const unsigned kNegativeCacheEntryTTLSeconds = 0; // that limit this to 6, so we're temporarily holding it at that level. static const size_t kDefaultMaxProcTasks = 6u; -// Helper to mutate the linked list contained by AddressList to the given -// port. Note that in general this is dangerous since the AddressList's -// data might be shared (and you should use AddressList::SetPort). -// -// However since we allocated the AddressList ourselves we can safely -// do this optimization and avoid reallocating the list. -void MutableSetPort(int port, AddressList* addr_list) { - struct addrinfo* mutable_head = - const_cast<struct addrinfo*>(addr_list->head()); - SetPortForAllAddrinfos(mutable_head, port); -} - // We use a separate histogram name for each platform to facilitate the // display of error codes by their symbolic name (since each platform has // different mappings). @@ -180,6 +168,13 @@ class CallSystemHostResolverProc : public HostResolverProc { virtual ~CallSystemHostResolverProc() {} }; +void EnsurePortOnAddressList(uint16 port, AddressList* list) { + DCHECK(list); + if (list->empty() || list->front().port() == port) + return; + SetPortOnAddressList(port, list); +} + // Extra parameters to attach to the NetLog when the resolve failed. class ProcTaskFailedParams : public NetLog::EventParameters { public: @@ -534,8 +529,10 @@ class HostResolverImpl::Request { // Prepare final AddressList and call completion callback. void OnComplete(int error, const AddressList& addr_list) { - if (error == OK) - *addresses_ = CreateAddressListUsingPort(addr_list, info_.port()); + if (error == OK) { + *addresses_ = addr_list; + EnsurePortOnAddressList(info_.port(), addresses_); + } CompletionCallback callback = callback_; MarkAsCanceled(); callback.Run(error); @@ -736,7 +733,7 @@ class HostResolverImpl::ProcTask int error, const int os_error) { DCHECK(origin_loop_->BelongsToCurrentThread()); - DCHECK(error || results.head()); + DCHECK(error || !results.empty()); bool was_retry_attempt = attempt_number > 1; @@ -1427,10 +1424,8 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job { DCHECK(!requests_.empty()); - // We are the only consumer of |list|, so we can safely change the port - // without copy-on-write. This pays off, when job has only one request. if (net_error == OK) - MutableSetPort(requests_->front()->info().port(), &list); + SetPortOnAddressList(requests_->front()->info().port(), &list); if ((net_error != ERR_ABORTED) && (net_error != ERR_HOST_RESOLVER_QUEUE_TOO_LARGE)) { @@ -1758,9 +1753,9 @@ bool HostResolverImpl::ResolveAsIP(const Key& key, if ((ip_number.size() == kIPv6AddressSize) && ipv6_disabled) { *net_error = ERR_NAME_NOT_RESOLVED; } else { - *addresses = AddressList::CreateFromIPAddressWithCname( - ip_number, info.port(), - (key.host_resolver_flags & HOST_RESOLVER_CANONNAME)); + *addresses = AddressList::CreateFromIPAddress(ip_number, info.port()); + if (key.host_resolver_flags & HOST_RESOLVER_CANONNAME) + addresses->SetDefaultCanonicalName(); } return true; } @@ -1780,8 +1775,10 @@ bool HostResolverImpl::ServeFromCache(const Key& key, return false; *net_error = cache_entry->error; - if (*net_error == OK) - *addresses = CreateAddressListUsingPort(cache_entry->addrlist, info.port()); + if (*net_error == OK) { + *addresses = cache_entry->addrlist; + EnsurePortOnAddressList(info.port(), addresses); + } return true; } diff --git a/net/base/host_resolver_impl_unittest.cc b/net/base/host_resolver_impl_unittest.cc index d82f6f7..fa88f78 100644 --- a/net/base/host_resolver_impl_unittest.cc +++ b/net/base/host_resolver_impl_unittest.cc @@ -4,6 +4,7 @@ #include "net/base/host_resolver_impl.h" +#include <algorithm> #include <string> #include "base/bind.h" @@ -21,7 +22,6 @@ #include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" #include "net/base/net_util.h" -#include "net/base/sys_addrinfo.h" #include "net/dns/dns_client.h" #include "net/dns/dns_test_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -240,7 +240,7 @@ class Request { result_ = resolver_->Resolve( info_, &list_, base::Bind(&Request::OnComplete, base::Unretained(this)), &handle_, BoundNetLog()); - if (list_.head()) + if (!list_.empty()) EXPECT_EQ(OK, result_); return result_; } @@ -269,28 +269,14 @@ class Request { IPAddressNumber ip; bool rv = ParseIPLiteralToNumber(address, &ip); DCHECK(rv); - IPEndPoint target(ip, port); - for (const struct addrinfo* ai = list_.head(); - ai != NULL; - ai = ai->ai_next) { - IPEndPoint ipe; - rv = ipe.FromSockAddr(ai->ai_addr, ai->ai_addrlen); - DCHECK(rv); - if (target == ipe) - return true; - } - return false; + return std::find(list_.begin(), + list_.end(), + IPEndPoint(ip, port)) != list_.end(); } // Returns the number of addresses in |list_|. unsigned NumberOfAddresses() const { - unsigned count = 0; - for (const struct addrinfo* ai = list_.head(); - ai != NULL; - ai = ai->ai_next) { - ++count; - } - return count; + return list_.size(); } bool HasOneAddress(const std::string& address, int port) const { @@ -323,10 +309,10 @@ class Request { EXPECT_NE(ERR_IO_PENDING, rv); result_ = rv; handle_ = NULL; - if (list_.head()) + if (!list_.empty()) { EXPECT_EQ(OK, result_); - if (OK == rv) - EXPECT_EQ(info_.port(), list_.GetPort()); + EXPECT_EQ(info_.port(), list_.front().port()); + } if (handler_) handler_->Handle(this); if (quit_on_complete_) { diff --git a/net/base/host_resolver_proc.cc b/net/base/host_resolver_proc.cc index c2f2ddd..729079e 100644 --- a/net/base/host_resolver_proc.cc +++ b/net/base/host_resolver_proc.cc @@ -236,7 +236,8 @@ int SystemHostResolverProc(const std::string& host, return ERR_NAME_NOT_RESOLVED; } - *addrlist = AddressList::CreateByAdoptingFromSystem(ai); + *addrlist = AddressList::CreateFromAddrinfo(ai); + freeaddrinfo(ai); return OK; } diff --git a/net/base/host_resolver_proc.h b/net/base/host_resolver_proc.h index 0acb31e..7a54d01 100644 --- a/net/base/host_resolver_proc.h +++ b/net/base/host_resolver_proc.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. diff --git a/net/base/ip_endpoint.cc b/net/base/ip_endpoint.cc index e962d91..b8a161b 100644 --- a/net/base/ip_endpoint.cc +++ b/net/base/ip_endpoint.cc @@ -15,6 +15,12 @@ namespace net { +namespace { +// By definition, socklen_t is large enough to hold both sizes. +const socklen_t kSockaddrInSize = sizeof(struct sockaddr_in); +const socklen_t kSockaddrIn6Size = sizeof(struct sockaddr_in6); +} + IPEndPoint::IPEndPoint() : port_(0) {} IPEndPoint::~IPEndPoint() {} @@ -30,28 +36,25 @@ IPEndPoint::IPEndPoint(const IPEndPoint& endpoint) { int IPEndPoint::GetFamily() const { switch (address_.size()) { - case kIPv4AddressSize: { + case kIPv4AddressSize: return AF_INET; - } - case kIPv6AddressSize: { + case kIPv6AddressSize: return AF_INET6; - } - default: { + default: NOTREACHED() << "Bad IP address"; return AF_UNSPEC; - } } } bool IPEndPoint::ToSockAddr(struct sockaddr* address, - size_t* address_length) const { + socklen_t* address_length) const { DCHECK(address); DCHECK(address_length); switch (address_.size()) { case kIPv4AddressSize: { - if (*address_length < sizeof(struct sockaddr_in)) + if (*address_length < kSockaddrInSize) return false; - *address_length = sizeof(struct sockaddr_in); + *address_length = kSockaddrInSize; struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(address); memset(addr, 0, sizeof(struct sockaddr_in)); addr->sin_family = AF_INET; @@ -60,9 +63,9 @@ bool IPEndPoint::ToSockAddr(struct sockaddr* address, break; } case kIPv6AddressSize: { - if (*address_length < sizeof(struct sockaddr_in6)) + if (*address_length < kSockaddrIn6Size) return false; - *address_length = sizeof(struct sockaddr_in6); + *address_length = kSockaddrIn6Size; struct sockaddr_in6* addr6 = reinterpret_cast<struct sockaddr_in6*>(address); memset(addr6, 0, sizeof(struct sockaddr_in6)); @@ -71,20 +74,18 @@ bool IPEndPoint::ToSockAddr(struct sockaddr* address, memcpy(&addr6->sin6_addr, &address_[0], kIPv6AddressSize); break; } - default: { - NOTREACHED() << "Bad IP address"; - break; - } + default: + return false; } return true; } bool IPEndPoint::FromSockAddr(const struct sockaddr* address, - size_t address_length) { + socklen_t address_length) { DCHECK(address); switch (address->sa_family) { case AF_INET: { - if (address_length < sizeof(struct sockaddr_in)) + if (address_length < kSockaddrInSize) return false; const struct sockaddr_in* addr = reinterpret_cast<const struct sockaddr_in*>(address); @@ -94,7 +95,7 @@ bool IPEndPoint::FromSockAddr(const struct sockaddr* address, break; } case AF_INET6: { - if (address_length < sizeof(struct sockaddr_in6)) + if (address_length < kSockaddrIn6Size) return false; const struct sockaddr_in6* addr = reinterpret_cast<const struct sockaddr_in6*>(address); @@ -103,22 +104,28 @@ bool IPEndPoint::FromSockAddr(const struct sockaddr* address, address_.assign(&bytes[0], &bytes[kIPv6AddressSize]); break; } - default: { - NOTREACHED() << "Bad IP address"; - break; - } + default: + return false; } return true; } std::string IPEndPoint::ToString() const { - struct sockaddr_storage addr_storage; - size_t addr_len = sizeof(addr_storage); - struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); - if (!ToSockAddr(addr, &addr_len)) { - return ""; + SockaddrStorage storage; + if (!ToSockAddr(storage.addr, &storage.addr_len)) { + return std::string(); + } + // TODO(szym): Don't use getnameinfo. http://crbug.com/126212 + return NetAddressToStringWithPort(storage.addr, storage.addr_len); +} + +std::string IPEndPoint::ToStringWithoutPort() const { + SockaddrStorage storage; + if (!ToSockAddr(storage.addr, &storage.addr_len)) { + return std::string(); } - return NetAddressToStringWithPort(addr, addr_len); + // TODO(szym): Don't use getnameinfo. http://crbug.com/126212 + return NetAddressToString(storage.addr, storage.addr_len); } bool IPEndPoint::operator<(const IPEndPoint& that) const { diff --git a/net/base/ip_endpoint.h b/net/base/ip_endpoint.h index 1c8c907..7d59e0d 100644 --- a/net/base/ip_endpoint.h +++ b/net/base/ip_endpoint.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,7 +6,10 @@ #define NET_BASE_IP_ENDPOINT_H_ #pragma once +#include <string> + #include "base/basictypes.h" +#include "base/compiler_specific.h" #include "net/base/net_export.h" #include "net/base/net_util.h" @@ -37,19 +40,24 @@ class NET_EXPORT IPEndPoint { // size of data in |address| available. On output, it is the size of // the address that was copied into |address|. // Returns true on success, false on failure. - bool ToSockAddr(struct sockaddr* address, size_t* address_length) const; + bool ToSockAddr(struct sockaddr* address, socklen_t* address_length) const + WARN_UNUSED_RESULT; // Convert from a sockaddr struct. // |address| is the address. // |address_length| is the length of |address|. // Returns true on success, false on failure. - bool FromSockAddr(const struct sockaddr* address, size_t address_length); + bool FromSockAddr(const struct sockaddr* address, socklen_t address_length) + WARN_UNUSED_RESULT; // Returns value as a string (e.g. "127.0.0.1:80"). Returns empty // string if the address is invalid, and cannot not be converted to a // string. std::string ToString() const; + // As above, but without port. + std::string ToStringWithoutPort() const; + bool operator<(const IPEndPoint& that) const; bool operator==(const IPEndPoint& that) const; diff --git a/net/base/ip_endpoint_unittest.cc b/net/base/ip_endpoint_unittest.cc index b551bb4..f93a08f 100644 --- a/net/base/ip_endpoint_unittest.cc +++ b/net/base/ip_endpoint_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -78,20 +78,19 @@ TEST_F(IPEndPointTest, ToFromSockAddr) { IPEndPoint ip_endpoint(tests[index].ip_address, index); // Convert to a sockaddr. - struct sockaddr_storage addr; - size_t addr_len = sizeof(addr); - struct sockaddr* sockaddr = reinterpret_cast<struct sockaddr*>(&addr); - EXPECT_TRUE(ip_endpoint.ToSockAddr(sockaddr, &addr_len)); + SockaddrStorage storage; + EXPECT_TRUE(ip_endpoint.ToSockAddr(storage.addr, &storage.addr_len)); // Basic verification. - size_t expected_size = tests[index].ipv6 ? + socklen_t expected_size = tests[index].ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in); - EXPECT_EQ(expected_size, addr_len); - EXPECT_EQ(ip_endpoint.port(), GetPortFromSockaddr(sockaddr, addr_len)); + EXPECT_EQ(expected_size, storage.addr_len); + EXPECT_EQ(ip_endpoint.port(), GetPortFromSockaddr(storage.addr, + storage.addr_len)); // And convert back to an IPEndPoint. IPEndPoint ip_endpoint2; - EXPECT_TRUE(ip_endpoint2.FromSockAddr(sockaddr, addr_len)); + EXPECT_TRUE(ip_endpoint2.FromSockAddr(storage.addr, storage.addr_len)); EXPECT_EQ(ip_endpoint.port(), ip_endpoint2.port()); EXPECT_EQ(ip_endpoint.address(), ip_endpoint2.address()); } @@ -101,10 +100,9 @@ TEST_F(IPEndPointTest, ToSockAddrBufTooSmall) { for (int index = 0; index < test_count; ++index) { IPEndPoint ip_endpoint(tests[index].ip_address, index); - struct sockaddr_storage addr; - size_t addr_len = index; // size is too small! - struct sockaddr* sockaddr = reinterpret_cast<struct sockaddr*>(&addr); - EXPECT_FALSE(ip_endpoint.ToSockAddr(sockaddr, &addr_len)); + SockaddrStorage storage; + storage.addr_len = index; // size is too small! + EXPECT_FALSE(ip_endpoint.ToSockAddr(storage.addr, &storage.addr_len)); } } diff --git a/net/base/mapped_host_resolver_unittest.cc b/net/base/mapped_host_resolver_unittest.cc index 7e691be..5ea95c0 100644 --- a/net/base/mapped_host_resolver_unittest.cc +++ b/net/base/mapped_host_resolver_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -16,6 +16,12 @@ namespace net { namespace { +std::string FirstAddress(const AddressList& address_list) { + if (address_list.empty()) + return ""; + return address_list.front().ToString(); +} + TEST(MappedHostResolverTest, Inclusion) { // Create a mock host resolver, with specific hostname to IP mappings. MockHostResolver* resolver_impl(new MockHostResolver()); @@ -53,8 +59,7 @@ TEST(MappedHostResolverTest, Inclusion) { EXPECT_EQ(ERR_IO_PENDING, rv); rv = callback.WaitForResult(); EXPECT_EQ(OK, rv); - EXPECT_EQ("192.168.1.5", NetAddressToString(address_list.head())); - EXPECT_EQ(80, address_list.GetPort()); + EXPECT_EQ("192.168.1.5:80", FirstAddress(address_list)); // Try resolving "foo.com:77". This will NOT be remapped, so result // is "foo.com:77". @@ -64,8 +69,7 @@ TEST(MappedHostResolverTest, Inclusion) { EXPECT_EQ(ERR_IO_PENDING, rv); rv = callback.WaitForResult(); EXPECT_EQ(OK, rv); - EXPECT_EQ("192.168.1.8", NetAddressToString(address_list.head())); - EXPECT_EQ(77, address_list.GetPort()); + EXPECT_EQ("192.168.1.8:77", FirstAddress(address_list)); // Remap "*.org" to "proxy:99". EXPECT_TRUE(resolver->AddRuleFromString("Map *.org proxy:99")); @@ -78,8 +82,7 @@ TEST(MappedHostResolverTest, Inclusion) { EXPECT_EQ(ERR_IO_PENDING, rv); rv = callback.WaitForResult(); EXPECT_EQ(OK, rv); - EXPECT_EQ("192.168.1.11", NetAddressToString(address_list.head())); - EXPECT_EQ(99, address_list.GetPort()); + EXPECT_EQ("192.168.1.11:99", FirstAddress(address_list)); } // Tests that exclusions are respected. @@ -111,8 +114,7 @@ TEST(MappedHostResolverTest, Exclusion) { EXPECT_EQ(ERR_IO_PENDING, rv); rv = callback.WaitForResult(); EXPECT_EQ(OK, rv); - EXPECT_EQ("192.168.1.3", NetAddressToString(address_list.head())); - EXPECT_EQ(80, address_list.GetPort()); + EXPECT_EQ("192.168.1.3:80", FirstAddress(address_list)); // Try resolving "chrome.com:80". Should be remapped to "baz:80". rv = resolver->Resolve(HostResolver::RequestInfo( @@ -122,8 +124,7 @@ TEST(MappedHostResolverTest, Exclusion) { EXPECT_EQ(ERR_IO_PENDING, rv); rv = callback.WaitForResult(); EXPECT_EQ(OK, rv); - EXPECT_EQ("192.168.1.5", NetAddressToString(address_list.head())); - EXPECT_EQ(80, address_list.GetPort()); + EXPECT_EQ("192.168.1.5:80", FirstAddress(address_list)); } TEST(MappedHostResolverTest, SetRulesFromString) { @@ -151,8 +152,7 @@ TEST(MappedHostResolverTest, SetRulesFromString) { EXPECT_EQ(ERR_IO_PENDING, rv); rv = callback.WaitForResult(); EXPECT_EQ(OK, rv); - EXPECT_EQ("192.168.1.7", NetAddressToString(address_list.head())); - EXPECT_EQ(80, address_list.GetPort()); + EXPECT_EQ("192.168.1.7:80", FirstAddress(address_list)); // Try resolving "chrome.net:80". Should be remapped to "bar:60". rv = resolver->Resolve(HostResolver::RequestInfo( @@ -162,8 +162,7 @@ TEST(MappedHostResolverTest, SetRulesFromString) { EXPECT_EQ(ERR_IO_PENDING, rv); rv = callback.WaitForResult(); EXPECT_EQ(OK, rv); - EXPECT_EQ("192.168.1.9", NetAddressToString(address_list.head())); - EXPECT_EQ(60, address_list.GetPort()); + EXPECT_EQ("192.168.1.9:60", FirstAddress(address_list)); } // Parsing bad rules should silently discard the rule (and never crash). diff --git a/net/base/mock_host_resolver.cc b/net/base/mock_host_resolver.cc index 0394451..156ae8c 100644 --- a/net/base/mock_host_resolver.cc +++ b/net/base/mock_host_resolver.cc @@ -17,7 +17,6 @@ #include "net/base/host_cache.h" #include "net/base/net_errors.h" #include "net/base/net_util.h" -#include "net/base/sys_addrinfo.h" #include "net/base/test_completion_callback.h" namespace net { @@ -37,21 +36,14 @@ int ParseAddressList(const std::string& host_list, *addrlist = AddressList(); std::vector<std::string> addresses; base::SplitString(host_list, ',', &addresses); + addrlist->set_canonical_name(canonical_name); for (size_t index = 0; index < addresses.size(); ++index) { IPAddressNumber ip_number; if (!ParseIPLiteralToNumber(addresses[index], &ip_number)) { LOG(WARNING) << "Not a supported IP literal: " << addresses[index]; return ERR_UNEXPECTED; } - - AddressList result = AddressList::CreateFromIPAddress(ip_number, -1); - struct addrinfo* ai = const_cast<struct addrinfo*>(result.head()); - if (index == 0) - ai->ai_canonname = base::strdup(canonical_name.c_str()); - if (!addrlist->head()) - *addrlist = AddressList::CreateByCopyingFirstAddress(result.head()); - else - addrlist->Append(result.head()); + addrlist->push_back(IPEndPoint(ip_number, -1)); } return OK; } @@ -137,8 +129,9 @@ int MockHostResolverBase::ResolveFromIPLiteralOrCache(const RequestInfo& info, AddressList* addresses) { IPAddressNumber ip; if (ParseIPLiteralToNumber(info.hostname(), &ip)) { - *addresses = AddressList::CreateFromIPAddressWithCname( - ip, info.port(), info.host_resolver_flags() & HOST_RESOLVER_CANONNAME); + *addresses = AddressList::CreateFromIPAddress(ip, info.port()); + if (info.host_resolver_flags() & HOST_RESOLVER_CANONNAME) + addresses->SetDefaultCanonicalName(); return OK; } int rv = ERR_DNS_CACHE_MISS; @@ -149,8 +142,10 @@ int MockHostResolverBase::ResolveFromIPLiteralOrCache(const RequestInfo& info, const HostCache::Entry* entry = cache_->Lookup(key, base::TimeTicks::Now()); if (entry) { rv = entry->error; - if (rv == OK) - *addresses = CreateAddressListUsingPort(entry->addrlist, info.port()); + if (rv == OK) { + *addresses = entry->addrlist; + SetPortOnAddressList(info.port(), addresses); + } } } return rv; @@ -175,8 +170,10 @@ int MockHostResolverBase::ResolveProc(size_t id, ttl = base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds); cache_->Set(key, rv, addr, base::TimeTicks::Now(), ttl); } - if (rv == OK) - *addresses = CreateAddressListUsingPort(addr, info.port()); + if (rv == OK) { + *addresses = addr; + SetPortOnAddressList(info.port(), addresses); + } return rv; } diff --git a/net/base/net_util.cc b/net/base/net_util.cc index 6060fd8..b9e7ad1 100644 --- a/net/base/net_util.cc +++ b/net/base/net_util.cc @@ -2265,73 +2265,6 @@ bool IPNumberMatchesPrefix(const IPAddressNumber& ip_number, return true; } -struct addrinfo* CreateCopyOfAddrinfo(const struct addrinfo* info, - bool recursive) { - DCHECK(info); - struct addrinfo* copy = new addrinfo; - - // Copy all the fields (some of these are pointers, we will fix that next). - memcpy(copy, info, sizeof(addrinfo)); - - // ai_canonname is a NULL-terminated string. - if (info->ai_canonname) { - copy->ai_canonname = base::strdup(info->ai_canonname); - } - - // ai_addr is a buffer of length ai_addrlen. - if (info->ai_addr) { - copy->ai_addr = reinterpret_cast<sockaddr *>(new char[info->ai_addrlen]); - memcpy(copy->ai_addr, info->ai_addr, info->ai_addrlen); - } - - // Recursive copy. - if (recursive && info->ai_next) - copy->ai_next = CreateCopyOfAddrinfo(info->ai_next, recursive); - else - copy->ai_next = NULL; - - return copy; -} - -void FreeCopyOfAddrinfo(struct addrinfo* info) { - DCHECK(info); - if (info->ai_canonname) - free(info->ai_canonname); // Allocated by strdup. - - if (info->ai_addr) - delete [] reinterpret_cast<char*>(info->ai_addr); - - struct addrinfo* next = info->ai_next; - - delete info; - - // Recursive free. - if (next) - FreeCopyOfAddrinfo(next); -} - -// Returns the port field of the sockaddr in |info|. -uint16* GetPortFieldFromAddrinfo(struct addrinfo* info) { - const struct addrinfo* const_info = info; - const uint16* port_field = GetPortFieldFromAddrinfo(const_info); - return const_cast<uint16*>(port_field); -} - -const uint16* GetPortFieldFromAddrinfo(const struct addrinfo* info) { - DCHECK(info); - const struct sockaddr* address = info->ai_addr; - DCHECK(address); - DCHECK_EQ(info->ai_family, address->sa_family); - return GetPortFieldFromSockaddr(address, info->ai_addrlen); -} - -uint16 GetPortFromAddrinfo(const struct addrinfo* info) { - const uint16* port_field = GetPortFieldFromAddrinfo(info); - if (!port_field) - return -1; - return base::NetToHost16(*port_field); -} - const uint16* GetPortFieldFromSockaddr(const struct sockaddr* address, socklen_t address_len) { if (address->sa_family == AF_INET) { @@ -2357,16 +2290,6 @@ int GetPortFromSockaddr(const struct sockaddr* address, socklen_t address_len) { return base::NetToHost16(*port_field); } -// Assign |port| to each address in the linked list starting from |head|. -void SetPortForAllAddrinfos(struct addrinfo* head, uint16 port) { - DCHECK(head); - for (struct addrinfo* ai = head; ai; ai = ai->ai_next) { - uint16* port_field = GetPortFieldFromAddrinfo(ai); - if (port_field) - *port_field = base::HostToNet16(port); - } -} - bool IsLocalhost(const std::string& host) { if (host == "localhost" || host == "localhost.localdomain" || diff --git a/net/base/net_util.h b/net/base/net_util.h index 757086a..f63f860 100644 --- a/net/base/net_util.h +++ b/net/base/net_util.h @@ -26,7 +26,6 @@ #include "net/base/escape.h" #include "net/base/net_export.h" -struct addrinfo; class FilePath; class GURL; @@ -100,17 +99,23 @@ NET_EXPORT std::string GetHostAndPort(const GURL& url); // if it is the default for the URL's scheme. NET_EXPORT_PRIVATE std::string GetHostAndOptionalPort(const GURL& url); +// Convenience struct for when you need a |struct sockaddr|. +struct SockaddrStorage { + SockaddrStorage() : addr_len(sizeof(addr_storage)), + addr(reinterpret_cast<struct sockaddr*>(&addr_storage)) {} + struct sockaddr_storage addr_storage; + socklen_t addr_len; + struct sockaddr* const addr; +}; + // Returns the string representation of an address, like "192.168.0.1". // Returns empty string on failure. -NET_EXPORT std::string NetAddressToString(const struct addrinfo* net_address); NET_EXPORT std::string NetAddressToString(const struct sockaddr* net_address, socklen_t address_len); // Same as NetAddressToString, but additionally includes the port number. For // example: "192.168.0.1:99" or "[::1]:80". NET_EXPORT std::string NetAddressToStringWithPort( - const struct addrinfo* net_address); -NET_EXPORT std::string NetAddressToStringWithPort( const struct sockaddr* net_address, socklen_t address_len); @@ -416,34 +421,13 @@ NET_EXPORT_PRIVATE bool IPNumberMatchesPrefix(const IPAddressNumber& ip_number, const IPAddressNumber& ip_prefix, size_t prefix_length_in_bits); -// Makes a copy of |info|. The dynamically-allocated parts are copied as well. -// If |recursive| is true, chained entries via ai_next are copied too. -// The copy returned by this function should be freed using -// FreeCopyOfAddrinfo(), and NOT freeaddrinfo(). -struct addrinfo* CreateCopyOfAddrinfo(const struct addrinfo* info, - bool recursive); - -// Frees an addrinfo that was created by CreateCopyOfAddrinfo(). -void FreeCopyOfAddrinfo(struct addrinfo* info); - -// Returns the port field of the sockaddr in |info|. -const uint16* GetPortFieldFromAddrinfo(const struct addrinfo* info); -uint16* GetPortFieldFromAddrinfo(struct addrinfo* info); - -// Returns the value of |info's| port (in host byte ordering). -uint16 GetPortFromAddrinfo(const struct addrinfo* info); - -// Same except for struct sockaddr. +// Retuns the port field of the |sockaddr|. const uint16* GetPortFieldFromSockaddr(const struct sockaddr* address, socklen_t address_len); +// Returns the value of port in |sockaddr| (in host byte ordering). NET_EXPORT_PRIVATE int GetPortFromSockaddr(const struct sockaddr* address, socklen_t address_len); -// Sets every addrinfo in the linked list |head| as having a port field of -// |port|. -NET_EXPORT_PRIVATE void SetPortForAllAddrinfos(struct addrinfo* head, - uint16 port); - // Returns true if |host| is one of the names (e.g. "localhost") or IP // addresses (IPv4 127.0.0.0/8 or IPv6 ::1) that indicate a loopback. // diff --git a/net/base/net_util_unittest.cc b/net/base/net_util_unittest.cc index caf64b5..6650863 100644 --- a/net/base/net_util_unittest.cc +++ b/net/base/net_util_unittest.cc @@ -19,7 +19,6 @@ #include "base/time.h" #include "base/utf_string_conversions.h" #include "googleurl/src/gurl.h" -#include "net/base/sys_addrinfo.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { @@ -405,52 +404,26 @@ struct UrlTestData { size_t prefix_len; }; -// Returns an addrinfo for the given 32-bit address (IPv4.) -// The result lives in static storage, so don't delete it. +// Fills in sockaddr for the given 32-bit address (IPv4.) // |bytes| should be an array of length 4. -const struct addrinfo* GetIPv4Address(const uint8* bytes, int port) { - static struct addrinfo static_ai; - static struct sockaddr_in static_addr4; - - struct addrinfo* ai = &static_ai; - ai->ai_socktype = SOCK_STREAM; - memset(ai, 0, sizeof(static_ai)); - - ai->ai_family = AF_INET; - ai->ai_addrlen = sizeof(static_addr4); - - struct sockaddr_in* addr4 = &static_addr4; - memset(addr4, 0, sizeof(static_addr4)); +void MakeIPv4Address(const uint8* bytes, int port, SockaddrStorage* storage) { + memset(&storage->addr_storage, 0, sizeof(storage->addr_storage)); + storage->addr_len = sizeof(struct sockaddr_in); + struct sockaddr_in* addr4 = reinterpret_cast<sockaddr_in*>(storage->addr); addr4->sin_port = base::HostToNet16(port); - addr4->sin_family = ai->ai_family; + addr4->sin_family = AF_INET; memcpy(&addr4->sin_addr, bytes, 4); - - ai->ai_addr = (sockaddr*)addr4; - return ai; } -// Returns a addrinfo for the given 128-bit address (IPv6.) -// The result lives in static storage, so don't delete it. +// Fills in sockaddr for the given 128-bit address (IPv6.) // |bytes| should be an array of length 16. -const struct addrinfo* GetIPv6Address(const uint8* bytes, int port) { - static struct addrinfo static_ai; - static struct sockaddr_in6 static_addr6; - - struct addrinfo* ai = &static_ai; - ai->ai_socktype = SOCK_STREAM; - memset(ai, 0, sizeof(static_ai)); - - ai->ai_family = AF_INET6; - ai->ai_addrlen = sizeof(static_addr6); - - struct sockaddr_in6* addr6 = &static_addr6; - memset(addr6, 0, sizeof(static_addr6)); +void MakeIPv6Address(const uint8* bytes, int port, SockaddrStorage* storage) { + memset(&storage->addr_storage, 0, sizeof(storage->addr_storage)); + storage->addr_len = sizeof(struct sockaddr_in6); + struct sockaddr_in6* addr6 = reinterpret_cast<sockaddr_in6*>(storage->addr); addr6->sin6_port = base::HostToNet16(port); - addr6->sin6_family = ai->ai_family; + addr6->sin6_family = AF_INET6; memcpy(&addr6->sin6_addr, bytes, 16); - - ai->ai_addr = (sockaddr*)addr6; - return ai; } // A helper for IDN*{Fast,Slow}. @@ -2270,8 +2243,9 @@ TEST(NetUtilTest, NetAddressToString_IPv4) { }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { - const addrinfo* ai = GetIPv4Address(tests[i].addr, 80); - std::string result = NetAddressToString(ai); + SockaddrStorage storage; + MakeIPv4Address(tests[i].addr, 80, &storage); + std::string result = NetAddressToString(storage.addr, storage.addr_len); EXPECT_EQ(std::string(tests[i].result), result); } } @@ -2287,8 +2261,9 @@ TEST(NetUtilTest, NetAddressToString_IPv6) { }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { - const addrinfo* ai = GetIPv6Address(tests[i].addr, 80); - std::string result = NetAddressToString(ai); + SockaddrStorage storage; + MakeIPv6Address(tests[i].addr, 80, &storage); + std::string result = NetAddressToString(storage.addr, storage.addr_len); // Allow NetAddressToString() to fail, in case the system doesn't // support IPv6. if (!result.empty()) @@ -2298,8 +2273,10 @@ TEST(NetUtilTest, NetAddressToString_IPv6) { TEST(NetUtilTest, NetAddressToStringWithPort_IPv4) { uint8 addr[] = {127, 0, 0, 1}; - const addrinfo* ai = GetIPv4Address(addr, 166); - std::string result = NetAddressToStringWithPort(ai); + SockaddrStorage storage; + MakeIPv4Address(addr, 166, &storage); + std::string result = NetAddressToStringWithPort(storage.addr, + storage.addr_len); EXPECT_EQ("127.0.0.1:166", result); } @@ -2308,8 +2285,10 @@ TEST(NetUtilTest, NetAddressToStringWithPort_IPv6) { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }; - const addrinfo* ai = GetIPv6Address(addr, 361); - std::string result = NetAddressToStringWithPort(ai); + SockaddrStorage storage; + MakeIPv6Address(addr, 361, &storage); + std::string result = NetAddressToStringWithPort(storage.addr, + storage.addr_len); // May fail on systems that don't support IPv6. if (!result.empty()) diff --git a/net/base/single_request_host_resolver_unittest.cc b/net/base/single_request_host_resolver_unittest.cc index 295a318..b23a722 100644 --- a/net/base/single_request_host_resolver_unittest.cc +++ b/net/base/single_request_host_resolver_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -82,7 +82,8 @@ TEST(SingleRequestHostResolverTest, NormalResolve) { EXPECT_EQ(OK, callback.WaitForResult()); // Verify that the result is what we specified in the MockHostResolver. - EXPECT_EQ("199.188.1.166", NetAddressToString(addrlist.head())); + ASSERT_FALSE(addrlist.empty()); + EXPECT_EQ("199.188.1.166", addrlist.front().ToStringWithoutPort()); } // Test that the Cancel() method cancels any outstanding request. |