Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Unified Diff: net/base/address_list.cc

Issue 118100: Avoid doing concurrent DNS resolves of the same hostname (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Get compiling on mac Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/base/address_list.cc
===================================================================
--- net/base/address_list.cc (revision 18213)
+++ net/base/address_list.cc (working copy)
@@ -11,14 +11,128 @@
#include <netdb.h>
#endif
+#include "base/logging.h"
+
namespace net {
+namespace {
+
+// Make a deep copy of |info|. This copy should be deleted using
+// DeleteCopyOfAddrinfo(), and NOT freeaddrinfo().
+struct addrinfo* CreateCopyOfAddrinfo(const struct addrinfo* info) {
+ struct addrinfo* copy = new struct 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) {
+#ifdef OS_WIN
+ copy->ai_canonname = _strdup(info->ai_canonname);
+#else
+ copy->ai_canonname = strdup(info->ai_canonname);
+#endif
+ }
+
+ // 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 (info->ai_next)
+ copy->ai_next = CreateCopyOfAddrinfo(info->ai_next);
+
+ return copy;
+}
+
+// Free an addrinfo that was created by CreateCopyOfAddrinfo().
+void FreeMyAddrinfo(struct addrinfo* 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)
+ FreeMyAddrinfo(next);
+}
+
+// Returns the address to port field in |info|.
+uint16* GetPortField(const struct addrinfo* info) {
+ if (info->ai_family == AF_INET) {
+ DCHECK_EQ(sizeof(sockaddr_in), info->ai_addrlen);
+ struct sockaddr_in* sockaddr =
+ reinterpret_cast<struct sockaddr_in*>(info->ai_addr);
+ return &sockaddr->sin_port;
+ } else if (info->ai_family == AF_INET6) {
+ DCHECK_EQ(sizeof(sockaddr_in6), info->ai_addrlen);
+ struct sockaddr_in6* sockaddr =
+ reinterpret_cast<struct sockaddr_in6*>(info->ai_addr);
+ return &sockaddr->sin6_port;
+ } else {
+ NOTREACHED();
+ return NULL;
+ }
+}
+
+// Assign the port for all addresses in the list.
+void SetPortRecursive(struct addrinfo* info, int port) {
+ uint16* port_field = GetPortField(info);
+ *port_field = htons(port);
+
+ // Assign recursively.
+ if (info->ai_next)
+ SetPortRecursive(info->ai_next, port);
+}
+
+} // namespace
+
void AddressList::Adopt(struct addrinfo* head) {
- data_ = new Data(head);
+ data_ = new Data(head, true /*is_system_created*/);
}
+void AddressList::Copy(const struct addrinfo* head) {
+ data_ = new Data(CreateCopyOfAddrinfo(head), false /*is_system_created*/);
+}
+
+void AddressList::SetPort(int port) {
+ SetPortRecursive(data_->head, port);
+}
+
+int AddressList::GetPort() const {
+ uint16* port_field = GetPortField(data_->head);
+ return ntohs(*port_field);
+}
+
+void AddressList::SetFrom(const AddressList& src, int port) {
+ if (src.GetPort() == port) {
+ // We can reference the data from |src| directly.
+ *this = src;
+ } else {
+ // Otherwise we need to make a copy in order to change the port number.
+ Copy(src.head());
+ SetPort(port);
+ }
+}
+
+void AddressList::Reset() {
+ data_ = NULL;
+}
+
AddressList::Data::~Data() {
- freeaddrinfo(head);
+ // Call either freeaddrinfo(head), or FreeMyAddrinfo(head), depending who
+ // created the data.
+ if (is_system_created)
+ freeaddrinfo(head);
+ else
+ FreeMyAddrinfo(head);
}
} // namespace net

Powered by Google App Engine
This is Rietveld 408576698