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 |