Index: net/base/address_list.cc |
diff --git a/net/base/address_list.cc b/net/base/address_list.cc |
index 93ec009eafd014295c7947c868de61c3eef4d129..d1624be44463cc1df2ee447d97b40c625f4398bf 100644 |
--- a/net/base/address_list.cc |
+++ b/net/base/address_list.cc |
@@ -13,9 +13,12 @@ namespace net { |
namespace { |
-// Make a deep copy of |info|. This copy should be deleted using |
+// Make a copy of |info| (the dynamically-allocated parts are copied as well). |
+// If |recursive| is true, chained entries via ai_next are copied too. |
+// Copy returned by this function should be deleted using |
// DeleteCopyOfAddrinfo(), and NOT freeaddrinfo(). |
-struct addrinfo* CreateCopyOfAddrinfo(const struct addrinfo* info) { |
+struct addrinfo* CreateCopyOfAddrinfo(const struct addrinfo* info, |
+ bool recursive) { |
struct addrinfo* copy = new addrinfo; |
// Copy all the fields (some of these are pointers, we will fix that next). |
@@ -37,8 +40,10 @@ struct addrinfo* CreateCopyOfAddrinfo(const struct addrinfo* info) { |
} |
// Recursive copy. |
- if (info->ai_next) |
- copy->ai_next = CreateCopyOfAddrinfo(info->ai_next); |
+ if (recursive && info->ai_next) |
+ copy->ai_next = CreateCopyOfAddrinfo(info->ai_next, recursive); |
+ else |
+ copy->ai_next = NULL; |
return copy; |
} |
@@ -81,7 +86,8 @@ uint16* GetPortField(const struct addrinfo* info) { |
// 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); |
+ if (port_field) |
+ *port_field = htons(port); |
// Assign recursively. |
if (info->ai_next) |
@@ -94,8 +100,25 @@ void AddressList::Adopt(struct addrinfo* 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::Copy(const struct addrinfo* head, bool recursive) { |
+ data_ = new Data(CreateCopyOfAddrinfo(head, recursive), |
+ false /*is_system_created*/); |
+} |
+ |
+void AddressList::Append(const struct addrinfo* head) { |
+ struct addrinfo* new_head; |
+ if (data_->is_system_created) { |
+ new_head = CreateCopyOfAddrinfo(data_->head, true); |
+ data_ = new Data(new_head, false /*is_system_created*/); |
+ } else { |
+ new_head = data_->head; |
+ } |
+ |
+ // 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); |
} |
void AddressList::SetPort(int port) { |
@@ -104,6 +127,9 @@ void AddressList::SetPort(int port) { |
int AddressList::GetPort() const { |
uint16* port_field = GetPortField(data_->head); |
+ if (!port_field) |
+ return -1; |
+ |
return ntohs(*port_field); |
} |
@@ -113,7 +139,7 @@ void AddressList::SetFrom(const AddressList& src, int port) { |
*this = src; |
} else { |
// Otherwise we need to make a copy in order to change the port number. |
- Copy(src.head()); |
+ Copy(src.head(), true); |
SetPort(port); |
} |
} |