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

Side by Side Diff: ppapi/shared_impl/private/net_address_private_impl.cc

Issue 8590006: Pepper: Implement PPB_NetAddress_Private Describe() for IPv6 addresses on Windows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: continue -> else Created 9 years, 1 month 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "ppapi/shared_impl/private/net_address_private_impl.h" 5 #include "ppapi/shared_impl/private/net_address_private_impl.h"
6 6
7 #include <string.h> 7 #include <string.h>
8 8
9 #include <string> 9 #include <string>
10 10
11 #include "base/basictypes.h" 11 #include "base/basictypes.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/stringprintf.h" 13 #include "base/stringprintf.h"
14 #include "build/build_config.h" 14 #include "build/build_config.h"
15 #include "net/base/net_util.h" 15 #include "net/base/net_util.h"
16 #include "net/base/sys_addrinfo.h" 16 #include "net/base/sys_addrinfo.h"
17 #include "net/base/sys_byteorder.h" 17 #include "net/base/sys_byteorder.h"
18 #include "ppapi/c/pp_var.h" 18 #include "ppapi/c/pp_var.h"
19 #include "ppapi/c/private/ppb_net_address_private.h" 19 #include "ppapi/c/private/ppb_net_address_private.h"
20 #include "ppapi/shared_impl/var.h" 20 #include "ppapi/shared_impl/var.h"
21 #include "ppapi/thunk/thunk.h" 21 #include "ppapi/thunk/thunk.h"
22 22
23 #if defined(OS_MACOSX)
24 // This is a bit evil, but it's standard operating procedure for |s6_addr|....
25 #define s6_addr16 __u6_addr.__u6_addr16
26 #endif
27
28 #if defined(OS_WIN)
29 // The type of |sockaddr::sa_family|.
30 typedef ADDRESS_FAMILY sa_family_t;
31
32 #define s6_addr16 u.Word
33 #endif
34
23 // The net address interface doesn't have a normal C -> C++ thunk since it 35 // The net address interface doesn't have a normal C -> C++ thunk since it
24 // doesn't actually have any proxy wrapping or associated objects; it's just a 36 // doesn't actually have any proxy wrapping or associated objects; it's just a
25 // call into base. So we implement the entire interface here, using the thunk 37 // call into base. So we implement the entire interface here, using the thunk
26 // namespace so it magically gets hooked up in the proper places. 38 // namespace so it magically gets hooked up in the proper places.
27 39
28 namespace ppapi { 40 namespace ppapi {
29 41
30 namespace { 42 namespace {
31 43
32 #if defined(OS_WIN)
33 // The type of |sockaddr::sa_family|.
34 typedef ADDRESS_FAMILY sa_family_t;
35 #endif
36
37 inline sa_family_t GetFamily(const PP_NetAddress_Private& addr) { 44 inline sa_family_t GetFamily(const PP_NetAddress_Private& addr) {
38 return reinterpret_cast<const sockaddr*>(addr.data)->sa_family; 45 return reinterpret_cast<const sockaddr*>(addr.data)->sa_family;
39 } 46 }
40 47
41 PP_Bool AreHostsEqual(const PP_NetAddress_Private* addr1, 48 PP_Bool AreHostsEqual(const PP_NetAddress_Private* addr1,
42 const PP_NetAddress_Private* addr2) { 49 const PP_NetAddress_Private* addr2) {
43 if (!NetAddressPrivateImpl::ValidateNetAddress(*addr1) || 50 if (!NetAddressPrivateImpl::ValidateNetAddress(*addr1) ||
44 !NetAddressPrivateImpl::ValidateNetAddress(*addr2)) 51 !NetAddressPrivateImpl::ValidateNetAddress(*addr2))
45 return PP_FALSE; 52 return PP_FALSE;
46 53
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 88
82 if (GetFamily(*addr1) == AF_INET6) { 89 if (GetFamily(*addr1) == AF_INET6) {
83 const sockaddr_in6* a1 = reinterpret_cast<const sockaddr_in6*>(addr1->data); 90 const sockaddr_in6* a1 = reinterpret_cast<const sockaddr_in6*>(addr1->data);
84 const sockaddr_in6* a2 = reinterpret_cast<const sockaddr_in6*>(addr2->data); 91 const sockaddr_in6* a2 = reinterpret_cast<const sockaddr_in6*>(addr2->data);
85 return PP_FromBool(a1->sin6_port == a2->sin6_port); 92 return PP_FromBool(a1->sin6_port == a2->sin6_port);
86 } 93 }
87 94
88 return PP_FALSE; 95 return PP_FALSE;
89 } 96 }
90 97
98 #if defined(OS_WIN) || defined(OS_MACOSX)
yzshen1 2011/11/21 23:55:03 It may be better to use this implementation for al
99 std::string ConvertIPv4AddressToString(const sockaddr_in* a,
100 bool include_port) {
101 unsigned ip = ntohl(a->sin_addr.s_addr);
102 unsigned port = ntohs(a->sin_port);
103 std::string description = base::StringPrintf(
104 "%u.%u.%u.%u",
105 (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
106 if (include_port)
107 base::StringAppendF(&description, ":%u", port);
108 return description;
109 }
110
111 // Format an IPv6 address for human consumption, basically according to RFC
112 // 5952.
113 // - If the scope is nonzero, it is appended to the address as "%<scope>" (this
114 // is not in RFC 5952, but consistent with |getnameinfo()| on Linux and
115 // Windows).
116 // - If |include_port| is true, the address (possibly including the scope) is
117 // enclosed in square brackets and ":<port>" is appended, i.e., the overall
118 // format is "[<address>]:<port>".
119 // - If the address is an IPv4 address embedded IPv6 (per RFC 4291), then the
120 // mixed format is used, e.g., "::ffff:192.168.1.2". This is optional per RFC
121 // 5952, but consistent with |getnameinfo()|.
122 std::string ConvertIPv6AddressToString(const sockaddr_in6* a,
123 bool include_port) {
124 unsigned port = ntohs(a->sin6_port);
125 unsigned scope = a->sin6_scope_id;
126 std::string description(include_port ? "[" : "");
127
128 // IPv4 address embedded in IPv6.
129 if (a->sin6_addr.s6_addr16[0] == 0 && a->sin6_addr.s6_addr16[1] == 0 &&
yzshen1 2011/11/21 23:55:03 [optional] It might be good to define a reference/
130 a->sin6_addr.s6_addr16[2] == 0 && a->sin6_addr.s6_addr16[3] == 0 &&
131 a->sin6_addr.s6_addr16[4] == 0 &&
132 (a->sin6_addr.s6_addr16[5] == 0 || a->sin6_addr.s6_addr16[5] == 0xffff)) {
133 base::StringAppendF(
134 &description,
135 a->sin6_addr.s6_addr16[5] == 0 ? "::%u.%u.%u.%u" : "::ffff:%u.%u.%u.%u",
136 static_cast<unsigned>(a->sin6_addr.s6_addr[12]),
137 static_cast<unsigned>(a->sin6_addr.s6_addr[13]),
138 static_cast<unsigned>(a->sin6_addr.s6_addr[14]),
139 static_cast<unsigned>(a->sin6_addr.s6_addr[15]));
140
141 // "Real" IPv6 addresses.
142 } else {
143 // Find the first longest run of 0s (of length > 1), to collapse to "::".
144 int longest_start = 0;
145 int longest_length = 0;
146 int curr_start = 0;
147 int curr_length = 0;
148 for (int i = 0; i < 8; i++) {
149 if (ntohs(a->sin6_addr.s6_addr16[i]) != 0) {
150 curr_length = 0;
151 } else {
152 if (!curr_length)
153 curr_start = i;
154 curr_length++;
155 if (curr_length > longest_length) {
156 longest_start = curr_start;
157 longest_length = curr_length;
158 }
159 }
160 }
161
162 bool need_sep = false; // Whether the next item needs a ':' to separate.
163 for (int i = 0; i < 8;) {
164 if (longest_length > 1 && i == longest_start) {
165 description.append("::");
166 need_sep = false;
167 i += longest_length;
168 } else {
169 unsigned v = ntohs(a->sin6_addr.s6_addr16[i]);
170 base::StringAppendF(&description, need_sep ? ":%x" : "%x", v);
171 need_sep = true;
172 i++;
173 }
174 }
175 }
176
177 // Nonzero scopes, e.g., 123, are indicated by appending, e.g., "%123".
178 if (scope != 0)
179 base::StringAppendF(&description, "%%%u", scope);
180
181 if (include_port)
182 base::StringAppendF(&description, "]:%u", port);
183
184 return description;
185 }
186 #endif // OS_WIN || OS_MAC
187
91 PP_Var Describe(PP_Module module, 188 PP_Var Describe(PP_Module module,
92 const struct PP_NetAddress_Private* addr, 189 const struct PP_NetAddress_Private* addr,
93 PP_Bool include_port) { 190 PP_Bool include_port) {
94 if (!NetAddressPrivateImpl::ValidateNetAddress(*addr)) 191 if (!NetAddressPrivateImpl::ValidateNetAddress(*addr))
95 return PP_MakeUndefined(); 192 return PP_MakeUndefined();
96 193
97 #if defined(OS_WIN) 194 #if defined(OS_WIN) || defined(OS_MACOSX)
98 // On Windows, |NetAddressToString()| doesn't work in the sandbox. 195 // On Windows, |NetAddressToString()| doesn't work in the sandbox. On Mac,
99 // TODO(viettrungluu): Consider switching to this everywhere once it's fully 196 // the output isn't consistent with RFC 5952, at least on Mac OS 10.6:
100 // implemented. 197 // |getnameinfo()| collapses length-one runs of zeros (and also doesn't
198 // display the scope).
199 // TODO(viettrungluu): Consider switching to this on Linux.
101 switch (GetFamily(*addr)) { 200 switch (GetFamily(*addr)) {
102 case AF_INET: { 201 case AF_INET: {
103 const sockaddr_in* a = reinterpret_cast<const sockaddr_in*>(addr->data); 202 const sockaddr_in* a = reinterpret_cast<const sockaddr_in*>(addr->data);
104 unsigned ip = ntohl(a->sin_addr.s_addr); 203 return StringVar::StringToPPVar(
105 unsigned port = ntohs(a->sin_port); 204 module, ConvertIPv4AddressToString(a, !!include_port));
106 std::string description = base::StringPrintf(
107 "%u.%u.%u.%u",
108 (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
109 if (include_port)
110 description.append(base::StringPrintf(":%u", port));
111 return StringVar::StringToPPVar(module, description);
112 } 205 }
113 case AF_INET6: 206 case AF_INET6: {
114 // TODO(viettrungluu): crbug.com/103969 207 const sockaddr_in6* a = reinterpret_cast<const sockaddr_in6*>(addr->data);
115 NOTIMPLEMENTED(); 208 return StringVar::StringToPPVar(
116 break; 209 module, ConvertIPv6AddressToString(a, !!include_port));
210 }
117 default: 211 default:
118 NOTREACHED(); 212 NOTREACHED();
119 break; 213 break;
120 } 214 }
121 return PP_MakeUndefined(); 215 return PP_MakeUndefined();
122 #else 216 #else
123 const sockaddr* a = reinterpret_cast<const sockaddr*>(addr->data); 217 const sockaddr* a = reinterpret_cast<const sockaddr*>(addr->data);
124 socklen_t l = addr->size; 218 socklen_t l = addr->size;
125 std::string description = 219 std::string description =
126 include_port ? net::NetAddressToStringWithPort(a, l) : 220 include_port ? net::NetAddressToStringWithPort(a, l) :
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 291
198 // Ditto for AF_INET6. 292 // Ditto for AF_INET6.
199 if (GetFamily(addr) == AF_INET6 && addr.size >= sizeof(sockaddr_in6)) 293 if (GetFamily(addr) == AF_INET6 && addr.size >= sizeof(sockaddr_in6))
200 return true; 294 return true;
201 295
202 // Reject everything else. 296 // Reject everything else.
203 return false; 297 return false;
204 } 298 }
205 299
206 } // namespace ppapi 300 } // namespace ppapi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698