Add support for multicast in PPB_UDPSocket API
[chromium-blink-merge.git] / ppapi / shared_impl / private / net_address_private_impl.cc
blob7515592c006d947c7ed6ba57c2bb24a7126bc3b4
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ppapi/shared_impl/private/net_address_private_impl.h"
7 #if defined(OS_WIN)
8 #include <windows.h>
9 #include <winsock2.h>
10 #include <ws2tcpip.h>
11 #elif defined(OS_POSIX) && !defined(OS_NACL)
12 #include <arpa/inet.h>
13 #include <sys/socket.h>
14 #include <sys/types.h>
15 #endif
17 #include <string.h>
19 #include <string>
21 #include "base/basictypes.h"
22 #include "base/logging.h"
23 #include "base/strings/stringprintf.h"
24 #include "build/build_config.h"
25 #include "ppapi/c/pp_var.h"
26 #include "ppapi/c/private/ppb_net_address_private.h"
27 #include "ppapi/shared_impl/proxy_lock.h"
28 #include "ppapi/shared_impl/var.h"
29 #include "ppapi/thunk/thunk.h"
31 #if defined(OS_MACOSX)
32 // This is a bit evil, but it's standard operating procedure for |s6_addr|....
33 #define s6_addr16 __u6_addr.__u6_addr16
34 #endif
36 #if defined(OS_WIN)
37 // The type of |sockaddr::sa_family|.
38 typedef ADDRESS_FAMILY sa_family_t;
40 #define s6_addr16 u.Word
41 #define ntohs(x) _byteswap_ushort(x)
42 #define htons(x) _byteswap_ushort(x)
43 #endif // defined(OS_WIN)
45 // The net address interface doesn't have a normal C -> C++ thunk since it
46 // doesn't actually have any proxy wrapping or associated objects; it's just a
47 // call into base. So we implement the entire interface here, using the thunk
48 // namespace so it magically gets hooked up in the proper places.
50 namespace ppapi {
52 namespace {
54 // Define our own net-host-net conversion, rather than reuse the one in
55 // base/sys_byteorder.h, to simplify the NaCl port. NaCl has no byte swap
56 // primitives.
57 uint16 ConvertFromNetEndian16(uint16 x) {
58 #if defined(ARCH_CPU_LITTLE_ENDIAN)
59 return (x << 8) | (x >> 8);
60 #else
61 return x;
62 #endif
65 uint16 ConvertToNetEndian16(uint16 x) {
66 #if defined(ARCH_CPU_LITTLE_ENDIAN)
67 return (x << 8) | (x >> 8);
68 #else
69 return x;
70 #endif
73 static const size_t kIPv4AddressSize = 4;
74 static const size_t kIPv6AddressSize = 16;
76 // This structure is a platform-independent representation of a network address.
77 // It is a private format that we embed in PP_NetAddress_Private and is NOT part
78 // of the stable Pepper API.
79 struct NetAddress {
80 bool is_valid;
81 bool is_ipv6; // if true, IPv6, otherwise IPv4.
82 uint16_t port; // host order, not network order.
83 int32_t flow_info; // 0 for IPv4
84 int32_t scope_id; // 0 for IPv4
85 // IPv4 addresses are 4 bytes. IPv6 are 16 bytes. Addresses are stored in net
86 // order (big-endian), which only affects IPv6 addresses, which consist of 8
87 // 16-bit components. These will be byte-swapped on small-endian hosts.
88 uint8_t address[kIPv6AddressSize];
91 // Make sure that sizeof(NetAddress) is the same for all compilers. This ensures
92 // that the alignment is the same on both sides of the NaCl proxy, which is
93 // important because we serialize and deserialize PP_NetAddress_Private by
94 // simply copying the raw bytes.
95 static_assert(sizeof(NetAddress) == 28,
96 "NetAddress different for compiler");
98 // Make sure the storage in |PP_NetAddress_Private| is big enough. (Do it here
99 // since the data is opaque elsewhere.)
100 static_assert(sizeof(reinterpret_cast<PP_NetAddress_Private*>(0)->data) >=
101 sizeof(NetAddress),
102 "PP_NetAddress_Private data too small");
104 size_t GetAddressSize(const NetAddress* net_addr) {
105 return net_addr->is_ipv6 ? kIPv6AddressSize : kIPv4AddressSize;
108 // Convert to embedded struct if it has been initialized.
109 NetAddress* ToNetAddress(PP_NetAddress_Private* addr) {
110 if (!addr || addr->size != sizeof(NetAddress))
111 return NULL;
112 return reinterpret_cast<NetAddress*>(addr->data);
115 const NetAddress* ToNetAddress(const PP_NetAddress_Private* addr) {
116 return ToNetAddress(const_cast<PP_NetAddress_Private*>(addr));
119 // Initializes the NetAddress struct embedded in a PP_NetAddress_Private struct.
120 // Zeroes the memory, so net_addr->is_valid == false.
121 NetAddress* InitNetAddress(PP_NetAddress_Private* addr) {
122 addr->size = sizeof(NetAddress);
123 NetAddress* net_addr = ToNetAddress(addr);
124 DCHECK(net_addr);
125 memset(net_addr, 0, sizeof(NetAddress));
126 return net_addr;
129 bool IsValid(const NetAddress* net_addr) {
130 return net_addr && net_addr->is_valid;
133 PP_NetAddressFamily_Private GetFamily(const PP_NetAddress_Private* addr) {
134 const NetAddress* net_addr = ToNetAddress(addr);
135 if (!IsValid(net_addr))
136 return PP_NETADDRESSFAMILY_PRIVATE_UNSPECIFIED;
137 return net_addr->is_ipv6 ?
138 PP_NETADDRESSFAMILY_PRIVATE_IPV6 : PP_NETADDRESSFAMILY_PRIVATE_IPV4;
141 uint16_t GetPort(const PP_NetAddress_Private* addr) {
142 const NetAddress* net_addr = ToNetAddress(addr);
143 if (!IsValid(net_addr))
144 return 0;
145 return net_addr->port;
148 PP_Bool GetAddress(const PP_NetAddress_Private* addr,
149 void* address,
150 uint16_t address_size) {
151 const NetAddress* net_addr = ToNetAddress(addr);
152 if (!IsValid(net_addr))
153 return PP_FALSE;
154 size_t net_addr_size = GetAddressSize(net_addr);
155 // address_size must be big enough.
156 if (net_addr_size > address_size)
157 return PP_FALSE;
158 memcpy(address, net_addr->address, net_addr_size);
159 return PP_TRUE;
162 uint32_t GetScopeID(const PP_NetAddress_Private* addr) {
163 const NetAddress* net_addr = ToNetAddress(addr);
164 if (!IsValid(net_addr))
165 return 0;
166 return net_addr->scope_id;
169 PP_Bool AreHostsEqual(const PP_NetAddress_Private* addr1,
170 const PP_NetAddress_Private* addr2) {
171 const NetAddress* net_addr1 = ToNetAddress(addr1);
172 const NetAddress* net_addr2 = ToNetAddress(addr2);
173 if (!IsValid(net_addr1) || !IsValid(net_addr2))
174 return PP_FALSE;
176 if ((net_addr1->is_ipv6 != net_addr2->is_ipv6) ||
177 (net_addr1->flow_info != net_addr2->flow_info) ||
178 (net_addr1->scope_id != net_addr2->scope_id))
179 return PP_FALSE;
181 size_t net_addr_size = GetAddressSize(net_addr1);
182 for (size_t i = 0; i < net_addr_size; i++) {
183 if (net_addr1->address[i] != net_addr2->address[i])
184 return PP_FALSE;
187 return PP_TRUE;
190 PP_Bool AreEqual(const PP_NetAddress_Private* addr1,
191 const PP_NetAddress_Private* addr2) {
192 // |AreHostsEqual()| will also validate the addresses and return false if
193 // either is invalid.
194 if (!AreHostsEqual(addr1, addr2))
195 return PP_FALSE;
197 // AreHostsEqual has validated these net addresses.
198 const NetAddress* net_addr1 = ToNetAddress(addr1);
199 const NetAddress* net_addr2 = ToNetAddress(addr2);
200 return PP_FromBool(net_addr1->port == net_addr2->port);
203 std::string ConvertIPv4AddressToString(const NetAddress* net_addr,
204 bool include_port) {
205 std::string description = base::StringPrintf(
206 "%u.%u.%u.%u",
207 net_addr->address[0], net_addr->address[1],
208 net_addr->address[2], net_addr->address[3]);
209 if (include_port)
210 base::StringAppendF(&description, ":%u", net_addr->port);
211 return description;
214 // Format an IPv6 address for human consumption, basically according to RFC
215 // 5952.
216 // - If the scope is nonzero, it is appended to the address as "%<scope>" (this
217 // is not in RFC 5952, but consistent with |getnameinfo()| on Linux and
218 // Windows).
219 // - If |include_port| is true, the address (possibly including the scope) is
220 // enclosed in square brackets and ":<port>" is appended, i.e., the overall
221 // format is "[<address>]:<port>".
222 // - If the address is an IPv4 address embedded IPv6 (per RFC 4291), then the
223 // mixed format is used, e.g., "::ffff:192.168.1.2". This is optional per RFC
224 // 5952, but consistent with |getnameinfo()|.
225 std::string ConvertIPv6AddressToString(const NetAddress* net_addr,
226 bool include_port) {
227 std::string description(include_port ? "[" : "");
229 const uint16_t* address16 =
230 reinterpret_cast<const uint16_t*>(net_addr->address);
231 // IPv4 address embedded in IPv6.
232 if (address16[0] == 0 && address16[1] == 0 &&
233 address16[2] == 0 && address16[3] == 0 &&
234 address16[4] == 0 &&
235 (address16[5] == 0 || address16[5] == 0xffff)) {
236 base::StringAppendF(
237 &description,
238 address16[5] == 0 ? "::%u.%u.%u.%u" : "::ffff:%u.%u.%u.%u",
239 net_addr->address[12],
240 net_addr->address[13],
241 net_addr->address[14],
242 net_addr->address[15]);
244 // "Real" IPv6 addresses.
245 } else {
246 // Find the first longest run of 0s (of length > 1), to collapse to "::".
247 int longest_start = 0;
248 int longest_length = 0;
249 int curr_start = 0;
250 int curr_length = 0;
251 for (int i = 0; i < 8; i++) {
252 if (address16[i] != 0) {
253 curr_length = 0;
254 } else {
255 if (!curr_length)
256 curr_start = i;
257 curr_length++;
258 if (curr_length > longest_length) {
259 longest_start = curr_start;
260 longest_length = curr_length;
265 bool need_sep = false; // Whether the next item needs a ':' to separate.
266 for (int i = 0; i < 8;) {
267 if (longest_length > 1 && i == longest_start) {
268 description.append("::");
269 need_sep = false;
270 i += longest_length;
271 } else {
272 uint16_t v = ConvertFromNetEndian16(address16[i]);
273 base::StringAppendF(&description, need_sep ? ":%x" : "%x", v);
274 need_sep = true;
275 i++;
280 // Nonzero scopes, e.g., 123, are indicated by appending, e.g., "%123".
281 if (net_addr->scope_id != 0)
282 base::StringAppendF(&description, "%%%u", net_addr->scope_id);
284 if (include_port)
285 base::StringAppendF(&description, "]:%u", net_addr->port);
287 return description;
290 PP_Var Describe(PP_Module /*module*/,
291 const struct PP_NetAddress_Private* addr,
292 PP_Bool include_port) {
293 std::string str = NetAddressPrivateImpl::DescribeNetAddress(
294 *addr, PP_ToBool(include_port));
295 if (str.empty())
296 return PP_MakeUndefined();
297 // We must acquire the lock while accessing the VarTracker, which is part of
298 // the critical section of the proxy which may be accessed by other threads.
299 ProxyAutoLock lock;
300 return StringVar::StringToPPVar(str);
303 PP_Bool ReplacePort(const struct PP_NetAddress_Private* src_addr,
304 uint16_t port,
305 struct PP_NetAddress_Private* dest_addr) {
306 const NetAddress* src_net_addr = ToNetAddress(src_addr);
307 if (!IsValid(src_net_addr) || !dest_addr)
308 return PP_FALSE;
309 dest_addr->size = sizeof(NetAddress); // make sure 'size' is valid.
310 NetAddress* dest_net_addr = ToNetAddress(dest_addr);
311 *dest_net_addr = *src_net_addr;
312 dest_net_addr->port = port;
313 return PP_TRUE;
316 void GetAnyAddress(PP_Bool is_ipv6, PP_NetAddress_Private* addr) {
317 if (addr) {
318 NetAddress* net_addr = InitNetAddress(addr);
319 net_addr->is_valid = true;
320 net_addr->is_ipv6 = (is_ipv6 == PP_TRUE);
324 void CreateFromIPv4Address(const uint8_t ip[4],
325 uint16_t port,
326 struct PP_NetAddress_Private* addr) {
327 if (addr) {
328 NetAddress* net_addr = InitNetAddress(addr);
329 net_addr->is_valid = true;
330 net_addr->is_ipv6 = false;
331 net_addr->port = port;
332 memcpy(net_addr->address, ip, kIPv4AddressSize);
336 void CreateFromIPv6Address(const uint8_t ip[16],
337 uint32_t scope_id,
338 uint16_t port,
339 struct PP_NetAddress_Private* addr) {
340 if (addr) {
341 NetAddress* net_addr = InitNetAddress(addr);
342 net_addr->is_valid = true;
343 net_addr->is_ipv6 = true;
344 net_addr->port = port;
345 net_addr->scope_id = scope_id;
346 memcpy(net_addr->address, ip, kIPv6AddressSize);
350 const PPB_NetAddress_Private_0_1 net_address_private_interface_0_1 = {
351 &AreEqual,
352 &AreHostsEqual,
353 &Describe,
354 &ReplacePort,
355 &GetAnyAddress
358 const PPB_NetAddress_Private_1_0 net_address_private_interface_1_0 = {
359 &AreEqual,
360 &AreHostsEqual,
361 &Describe,
362 &ReplacePort,
363 &GetAnyAddress,
364 &GetFamily,
365 &GetPort,
366 &GetAddress
369 const PPB_NetAddress_Private_1_1 net_address_private_interface_1_1 = {
370 &AreEqual,
371 &AreHostsEqual,
372 &Describe,
373 &ReplacePort,
374 &GetAnyAddress,
375 &GetFamily,
376 &GetPort,
377 &GetAddress,
378 &GetScopeID,
379 &CreateFromIPv4Address,
380 &CreateFromIPv6Address
383 } // namespace
385 namespace thunk {
387 PPAPI_THUNK_EXPORT const PPB_NetAddress_Private_0_1*
388 GetPPB_NetAddress_Private_0_1_Thunk() {
389 return &net_address_private_interface_0_1;
392 PPAPI_THUNK_EXPORT const PPB_NetAddress_Private_1_0*
393 GetPPB_NetAddress_Private_1_0_Thunk() {
394 return &net_address_private_interface_1_0;
397 PPAPI_THUNK_EXPORT const PPB_NetAddress_Private_1_1*
398 GetPPB_NetAddress_Private_1_1_Thunk() {
399 return &net_address_private_interface_1_1;
402 } // namespace thunk
404 // For the NaCl target, all we need are the API functions and the thunk.
405 #if !defined(OS_NACL)
407 // static
408 bool NetAddressPrivateImpl::ValidateNetAddress(
409 const PP_NetAddress_Private& addr) {
410 return IsValid(ToNetAddress(&addr));
413 // static
414 bool NetAddressPrivateImpl::SockaddrToNetAddress(
415 const sockaddr* sa,
416 uint32_t sa_length,
417 PP_NetAddress_Private* addr) {
418 if (!sa || sa_length == 0 || !addr)
419 return false;
421 // Our platform neutral format stores ports in host order, not net order,
422 // so convert them here.
423 NetAddress* net_addr = InitNetAddress(addr);
424 switch (sa->sa_family) {
425 case AF_INET: {
426 const struct sockaddr_in* addr4 =
427 reinterpret_cast<const struct sockaddr_in*>(sa);
428 net_addr->is_valid = true;
429 net_addr->is_ipv6 = false;
430 net_addr->port = ConvertFromNetEndian16(addr4->sin_port);
431 memcpy(net_addr->address, &addr4->sin_addr.s_addr, kIPv4AddressSize);
432 break;
434 case AF_INET6: {
435 const struct sockaddr_in6* addr6 =
436 reinterpret_cast<const struct sockaddr_in6*>(sa);
437 net_addr->is_valid = true;
438 net_addr->is_ipv6 = true;
439 net_addr->port = ConvertFromNetEndian16(addr6->sin6_port);
440 net_addr->flow_info = addr6->sin6_flowinfo;
441 net_addr->scope_id = addr6->sin6_scope_id;
442 memcpy(net_addr->address, addr6->sin6_addr.s6_addr, kIPv6AddressSize);
443 break;
445 default:
446 // InitNetAddress sets net_addr->is_valid to false.
447 return false;
449 return true;}
451 // static
452 bool NetAddressPrivateImpl::IPEndPointToNetAddress(
453 const std::vector<unsigned char>& address,
454 uint16 port,
455 PP_NetAddress_Private* addr) {
456 if (!addr)
457 return false;
459 NetAddress* net_addr = InitNetAddress(addr);
460 switch (address.size()) {
461 case kIPv4AddressSize: {
462 net_addr->is_valid = true;
463 net_addr->is_ipv6 = false;
464 net_addr->port = port;
465 std::copy(address.begin(), address.end(), net_addr->address);
466 break;
468 case kIPv6AddressSize: {
469 net_addr->is_valid = true;
470 net_addr->is_ipv6 = true;
471 net_addr->port = port;
472 std::copy(address.begin(), address.end(), net_addr->address);
473 break;
475 default:
476 // InitNetAddress sets net_addr->is_valid to false.
477 return false;
480 return true;
483 // static
484 bool NetAddressPrivateImpl::NetAddressToIPEndPoint(
485 const PP_NetAddress_Private& addr,
486 std::vector<unsigned char>* address,
487 uint16* port) {
488 if (!address || !port)
489 return false;
491 const NetAddress* net_addr = ToNetAddress(&addr);
492 if (!IsValid(net_addr))
493 return false;
495 *port = net_addr->port;
496 size_t address_size = GetAddressSize(net_addr);
497 address->assign(&net_addr->address[0], &net_addr->address[address_size]);
499 return true;
501 #endif // !defined(OS_NACL)
503 // static
504 std::string NetAddressPrivateImpl::DescribeNetAddress(
505 const PP_NetAddress_Private& addr,
506 bool include_port) {
507 const NetAddress* net_addr = ToNetAddress(&addr);
508 if (!IsValid(net_addr))
509 return std::string();
511 // On Windows, |NetAddressToString()| doesn't work in the sandbox. On Mac,
512 // the output isn't consistent with RFC 5952, at least on Mac OS 10.6:
513 // |getnameinfo()| collapses length-one runs of zeros (and also doesn't
514 // display the scope).
515 if (net_addr->is_ipv6)
516 return ConvertIPv6AddressToString(net_addr, include_port);
517 return ConvertIPv4AddressToString(net_addr, include_port);
520 // static
521 void NetAddressPrivateImpl::GetAnyAddress(PP_Bool is_ipv6,
522 PP_NetAddress_Private* addr) {
523 ppapi::GetAnyAddress(is_ipv6, addr);
526 // static
527 void NetAddressPrivateImpl::CreateNetAddressPrivateFromIPv4Address(
528 const PP_NetAddress_IPv4& ipv4_addr,
529 PP_NetAddress_Private* addr) {
530 CreateFromIPv4Address(ipv4_addr.addr, ConvertFromNetEndian16(ipv4_addr.port),
531 addr);
534 // static
535 void NetAddressPrivateImpl::CreateNetAddressPrivateFromIPv6Address(
536 const PP_NetAddress_IPv6& ipv6_addr,
537 PP_NetAddress_Private* addr) {
538 CreateFromIPv6Address(ipv6_addr.addr, 0,
539 ConvertFromNetEndian16(ipv6_addr.port), addr);
542 // static
543 PP_NetAddress_Family NetAddressPrivateImpl::GetFamilyFromNetAddressPrivate(
544 const PP_NetAddress_Private& addr) {
545 const NetAddress* net_addr = ToNetAddress(&addr);
546 if (!IsValid(net_addr))
547 return PP_NETADDRESS_FAMILY_UNSPECIFIED;
548 return net_addr->is_ipv6 ? PP_NETADDRESS_FAMILY_IPV6 :
549 PP_NETADDRESS_FAMILY_IPV4;
552 // static
553 bool NetAddressPrivateImpl::DescribeNetAddressPrivateAsIPv4Address(
554 const PP_NetAddress_Private& addr,
555 PP_NetAddress_IPv4* ipv4_addr) {
556 if (!ipv4_addr)
557 return false;
559 const NetAddress* net_addr = ToNetAddress(&addr);
560 if (!IsValid(net_addr) || net_addr->is_ipv6)
561 return false;
563 ipv4_addr->port = ConvertToNetEndian16(net_addr->port);
565 static_assert(sizeof(ipv4_addr->addr) == kIPv4AddressSize,
566 "mismatched IPv4 address size");
567 memcpy(ipv4_addr->addr, net_addr->address, kIPv4AddressSize);
569 return true;
572 // static
573 bool NetAddressPrivateImpl::DescribeNetAddressPrivateAsIPv6Address(
574 const PP_NetAddress_Private& addr,
575 PP_NetAddress_IPv6* ipv6_addr) {
576 if (!ipv6_addr)
577 return false;
579 const NetAddress* net_addr = ToNetAddress(&addr);
580 if (!IsValid(net_addr) || !net_addr->is_ipv6)
581 return false;
583 ipv6_addr->port = ConvertToNetEndian16(net_addr->port);
585 static_assert(sizeof(ipv6_addr->addr) == kIPv6AddressSize,
586 "mismatched IPv6 address size");
587 memcpy(ipv6_addr->addr, net_addr->address, kIPv6AddressSize);
589 return true;
592 } // namespace ppapi