| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/base/address_list.h" | 5 #include "net/base/address_list.h" |
| 6 | 6 |
| 7 #include <stdlib.h> | 7 #include <stdlib.h> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "net/base/sys_addrinfo.h" | 10 #include "net/base/sys_addrinfo.h" |
| 11 | 11 |
| 12 namespace net { | 12 namespace net { |
| 13 | 13 |
| 14 namespace { | 14 namespace { |
| 15 | 15 |
| 16 // Make a deep copy of |info|. This copy should be deleted using | 16 // Make a copy of |info| (the dynamically-allocated parts are copied as well). |
| 17 // If |recursive| is true, chained entries via ai_next are copied too. |
| 18 // Copy returned by this function should be deleted using |
| 17 // DeleteCopyOfAddrinfo(), and NOT freeaddrinfo(). | 19 // DeleteCopyOfAddrinfo(), and NOT freeaddrinfo(). |
| 18 struct addrinfo* CreateCopyOfAddrinfo(const struct addrinfo* info) { | 20 struct addrinfo* CreateCopyOfAddrinfo(const struct addrinfo* info, |
| 21 bool recursive) { |
| 19 struct addrinfo* copy = new addrinfo; | 22 struct addrinfo* copy = new addrinfo; |
| 20 | 23 |
| 21 // Copy all the fields (some of these are pointers, we will fix that next). | 24 // Copy all the fields (some of these are pointers, we will fix that next). |
| 22 memcpy(copy, info, sizeof(addrinfo)); | 25 memcpy(copy, info, sizeof(addrinfo)); |
| 23 | 26 |
| 24 // ai_canonname is a NULL-terminated string. | 27 // ai_canonname is a NULL-terminated string. |
| 25 if (info->ai_canonname) { | 28 if (info->ai_canonname) { |
| 26 #ifdef OS_WIN | 29 #ifdef OS_WIN |
| 27 copy->ai_canonname = _strdup(info->ai_canonname); | 30 copy->ai_canonname = _strdup(info->ai_canonname); |
| 28 #else | 31 #else |
| 29 copy->ai_canonname = strdup(info->ai_canonname); | 32 copy->ai_canonname = strdup(info->ai_canonname); |
| 30 #endif | 33 #endif |
| 31 } | 34 } |
| 32 | 35 |
| 33 // ai_addr is a buffer of length ai_addrlen. | 36 // ai_addr is a buffer of length ai_addrlen. |
| 34 if (info->ai_addr) { | 37 if (info->ai_addr) { |
| 35 copy->ai_addr = reinterpret_cast<sockaddr *>(new char[info->ai_addrlen]); | 38 copy->ai_addr = reinterpret_cast<sockaddr *>(new char[info->ai_addrlen]); |
| 36 memcpy(copy->ai_addr, info->ai_addr, info->ai_addrlen); | 39 memcpy(copy->ai_addr, info->ai_addr, info->ai_addrlen); |
| 37 } | 40 } |
| 38 | 41 |
| 39 // Recursive copy. | 42 // Recursive copy. |
| 40 if (info->ai_next) | 43 if (recursive && info->ai_next) |
| 41 copy->ai_next = CreateCopyOfAddrinfo(info->ai_next); | 44 copy->ai_next = CreateCopyOfAddrinfo(info->ai_next, recursive); |
| 45 else |
| 46 copy->ai_next = NULL; |
| 42 | 47 |
| 43 return copy; | 48 return copy; |
| 44 } | 49 } |
| 45 | 50 |
| 46 // Free an addrinfo that was created by CreateCopyOfAddrinfo(). | 51 // Free an addrinfo that was created by CreateCopyOfAddrinfo(). |
| 47 void FreeMyAddrinfo(struct addrinfo* info) { | 52 void FreeMyAddrinfo(struct addrinfo* info) { |
| 48 if (info->ai_canonname) | 53 if (info->ai_canonname) |
| 49 free(info->ai_canonname); // Allocated by strdup. | 54 free(info->ai_canonname); // Allocated by strdup. |
| 50 | 55 |
| 51 if (info->ai_addr) | 56 if (info->ai_addr) |
| (...skipping 22 matching lines...) Expand all Loading... |
| 74 return &sockaddr->sin6_port; | 79 return &sockaddr->sin6_port; |
| 75 } else { | 80 } else { |
| 76 NOTREACHED(); | 81 NOTREACHED(); |
| 77 return NULL; | 82 return NULL; |
| 78 } | 83 } |
| 79 } | 84 } |
| 80 | 85 |
| 81 // Assign the port for all addresses in the list. | 86 // Assign the port for all addresses in the list. |
| 82 void SetPortRecursive(struct addrinfo* info, int port) { | 87 void SetPortRecursive(struct addrinfo* info, int port) { |
| 83 uint16* port_field = GetPortField(info); | 88 uint16* port_field = GetPortField(info); |
| 84 *port_field = htons(port); | 89 if (port_field) |
| 90 *port_field = htons(port); |
| 85 | 91 |
| 86 // Assign recursively. | 92 // Assign recursively. |
| 87 if (info->ai_next) | 93 if (info->ai_next) |
| 88 SetPortRecursive(info->ai_next, port); | 94 SetPortRecursive(info->ai_next, port); |
| 89 } | 95 } |
| 90 | 96 |
| 91 } // namespace | 97 } // namespace |
| 92 | 98 |
| 93 void AddressList::Adopt(struct addrinfo* head) { | 99 void AddressList::Adopt(struct addrinfo* head) { |
| 94 data_ = new Data(head, true /*is_system_created*/); | 100 data_ = new Data(head, true /*is_system_created*/); |
| 95 } | 101 } |
| 96 | 102 |
| 97 void AddressList::Copy(const struct addrinfo* head) { | 103 void AddressList::Copy(const struct addrinfo* head, bool recursive) { |
| 98 data_ = new Data(CreateCopyOfAddrinfo(head), false /*is_system_created*/); | 104 data_ = new Data(CreateCopyOfAddrinfo(head, recursive), |
| 105 false /*is_system_created*/); |
| 106 } |
| 107 |
| 108 void AddressList::Append(const struct addrinfo* head) { |
| 109 struct addrinfo* new_head; |
| 110 if (data_->is_system_created) { |
| 111 new_head = CreateCopyOfAddrinfo(data_->head, true); |
| 112 data_ = new Data(new_head, false /*is_system_created*/); |
| 113 } else { |
| 114 new_head = data_->head; |
| 115 } |
| 116 |
| 117 // Find the end of current linked list and append new data there. |
| 118 struct addrinfo* copy_ptr = new_head; |
| 119 while (copy_ptr->ai_next) |
| 120 copy_ptr = copy_ptr->ai_next; |
| 121 copy_ptr->ai_next = CreateCopyOfAddrinfo(head, true); |
| 99 } | 122 } |
| 100 | 123 |
| 101 void AddressList::SetPort(int port) { | 124 void AddressList::SetPort(int port) { |
| 102 SetPortRecursive(data_->head, port); | 125 SetPortRecursive(data_->head, port); |
| 103 } | 126 } |
| 104 | 127 |
| 105 int AddressList::GetPort() const { | 128 int AddressList::GetPort() const { |
| 106 uint16* port_field = GetPortField(data_->head); | 129 uint16* port_field = GetPortField(data_->head); |
| 130 if (!port_field) |
| 131 return -1; |
| 132 |
| 107 return ntohs(*port_field); | 133 return ntohs(*port_field); |
| 108 } | 134 } |
| 109 | 135 |
| 110 void AddressList::SetFrom(const AddressList& src, int port) { | 136 void AddressList::SetFrom(const AddressList& src, int port) { |
| 111 if (src.GetPort() == port) { | 137 if (src.GetPort() == port) { |
| 112 // We can reference the data from |src| directly. | 138 // We can reference the data from |src| directly. |
| 113 *this = src; | 139 *this = src; |
| 114 } else { | 140 } else { |
| 115 // Otherwise we need to make a copy in order to change the port number. | 141 // Otherwise we need to make a copy in order to change the port number. |
| 116 Copy(src.head()); | 142 Copy(src.head(), true); |
| 117 SetPort(port); | 143 SetPort(port); |
| 118 } | 144 } |
| 119 } | 145 } |
| 120 | 146 |
| 121 void AddressList::Reset() { | 147 void AddressList::Reset() { |
| 122 data_ = NULL; | 148 data_ = NULL; |
| 123 } | 149 } |
| 124 | 150 |
| 125 // static | 151 // static |
| 126 AddressList AddressList::CreateIPv6Address(unsigned char data[16]) { | 152 AddressList AddressList::CreateIPv6Address(unsigned char data[16]) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 145 AddressList::Data::~Data() { | 171 AddressList::Data::~Data() { |
| 146 // Call either freeaddrinfo(head), or FreeMyAddrinfo(head), depending who | 172 // Call either freeaddrinfo(head), or FreeMyAddrinfo(head), depending who |
| 147 // created the data. | 173 // created the data. |
| 148 if (is_system_created) | 174 if (is_system_created) |
| 149 freeaddrinfo(head); | 175 freeaddrinfo(head); |
| 150 else | 176 else |
| 151 FreeMyAddrinfo(head); | 177 FreeMyAddrinfo(head); |
| 152 } | 178 } |
| 153 | 179 |
| 154 } // namespace net | 180 } // namespace net |
| OLD | NEW |