OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "platform/globals.h" | 5 #include "platform/globals.h" |
6 #if defined(TARGET_OS_ANDROID) | 6 #if defined(TARGET_OS_ANDROID) |
7 | 7 |
8 #include <errno.h> // NOLINT | 8 #include <errno.h> // NOLINT |
9 #include <stdio.h> // NOLINT | 9 #include <stdio.h> // NOLINT |
10 #include <stdlib.h> // NOLINT | 10 #include <stdlib.h> // NOLINT |
11 #include <string.h> // NOLINT | 11 #include <string.h> // NOLINT |
12 #include <sys/stat.h> // NOLINT | 12 #include <sys/stat.h> // NOLINT |
13 #include <unistd.h> // NOLINT | 13 #include <unistd.h> // NOLINT |
14 #include <netinet/tcp.h> // NOLINT | 14 #include <netinet/tcp.h> // NOLINT |
15 | 15 |
16 #include "bin/fdutils.h" | 16 #include "bin/fdutils.h" |
17 #include "bin/file.h" | 17 #include "bin/file.h" |
18 #include "bin/log.h" | 18 #include "bin/log.h" |
19 #include "bin/socket.h" | 19 #include "bin/socket.h" |
20 | 20 |
21 | 21 |
22 namespace dart { | 22 namespace dart { |
23 namespace bin { | 23 namespace bin { |
24 | 24 |
25 SocketAddress::SocketAddress(struct sockaddr* sa) { | 25 SocketAddress::SocketAddress(struct sockaddr* sa) { |
26 ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN); | 26 ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN); |
27 socklen_t salen = GetAddrLength(reinterpret_cast<RawAddr*>(sa)); | 27 if (!Socket::FormatNumericAddress( |
28 if (TEMP_FAILURE_RETRY(getnameinfo(sa, | 28 reinterpret_cast<RawAddr*>(sa), as_string_, INET6_ADDRSTRLEN)) { |
29 salen, | |
30 as_string_, | |
31 INET6_ADDRSTRLEN, | |
32 NULL, | |
33 0, | |
34 NI_NUMERICHOST)) != 0) { | |
35 as_string_[0] = 0; | 29 as_string_[0] = 0; |
36 } | 30 } |
| 31 socklen_t salen = GetAddrLength(reinterpret_cast<RawAddr*>(sa)); |
37 memmove(reinterpret_cast<void *>(&addr_), sa, salen); | 32 memmove(reinterpret_cast<void *>(&addr_), sa, salen); |
38 } | 33 } |
39 | 34 |
40 | 35 |
| 36 bool Socket::FormatNumericAddress(RawAddr* addr, char* address, int len) { |
| 37 socklen_t salen = SocketAddress::GetAddrLength(addr); |
| 38 if (TEMP_FAILURE_RETRY(getnameinfo(&addr->addr, |
| 39 salen, |
| 40 address, |
| 41 len, |
| 42 NULL, |
| 43 0, |
| 44 NI_NUMERICHOST)) != 0) { |
| 45 return false; |
| 46 } |
| 47 return true; |
| 48 } |
| 49 |
| 50 |
41 bool Socket::Initialize() { | 51 bool Socket::Initialize() { |
42 // Nothing to do on Android. | 52 // Nothing to do on Android. |
43 return true; | 53 return true; |
44 } | 54 } |
45 | 55 |
46 | 56 |
47 intptr_t Socket::Create(RawAddr addr) { | 57 intptr_t Socket::Create(RawAddr addr) { |
48 intptr_t fd; | 58 intptr_t fd; |
49 | 59 |
50 fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0)); | 60 fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0)); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 ASSERT(EAGAIN == EWOULDBLOCK); | 108 ASSERT(EAGAIN == EWOULDBLOCK); |
99 if (read_bytes == -1 && errno == EWOULDBLOCK) { | 109 if (read_bytes == -1 && errno == EWOULDBLOCK) { |
100 // If the read would block we need to retry and therefore return 0 | 110 // If the read would block we need to retry and therefore return 0 |
101 // as the number of bytes written. | 111 // as the number of bytes written. |
102 read_bytes = 0; | 112 read_bytes = 0; |
103 } | 113 } |
104 return read_bytes; | 114 return read_bytes; |
105 } | 115 } |
106 | 116 |
107 | 117 |
| 118 int Socket::RecvFrom(intptr_t fd, void* buffer, intptr_t num_bytes, |
| 119 RawAddr* addr) { |
| 120 ASSERT(fd >= 0); |
| 121 socklen_t addr_len = sizeof(addr->ss); |
| 122 ssize_t read_bytes = |
| 123 TEMP_FAILURE_RETRY( |
| 124 recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len)); |
| 125 if (read_bytes == -1 && errno == EWOULDBLOCK) { |
| 126 // If the read would block we need to retry and therefore return 0 |
| 127 // as the number of bytes written. |
| 128 read_bytes = 0; |
| 129 } |
| 130 return read_bytes; |
| 131 } |
| 132 |
| 133 |
108 int Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) { | 134 int Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) { |
109 ASSERT(fd >= 0); | 135 ASSERT(fd >= 0); |
110 ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes)); | 136 ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes)); |
111 ASSERT(EAGAIN == EWOULDBLOCK); | 137 ASSERT(EAGAIN == EWOULDBLOCK); |
112 if (written_bytes == -1 && errno == EWOULDBLOCK) { | 138 if (written_bytes == -1 && errno == EWOULDBLOCK) { |
113 // If the would block we need to retry and therefore return 0 as | 139 // If the would block we need to retry and therefore return 0 as |
114 // the number of bytes written. | 140 // the number of bytes written. |
115 written_bytes = 0; | 141 written_bytes = 0; |
116 } | 142 } |
117 return written_bytes; | 143 return written_bytes; |
118 } | 144 } |
119 | 145 |
120 | 146 |
| 147 int Socket::SendTo(intptr_t fd, const void* buffer, intptr_t num_bytes, |
| 148 RawAddr addr) { |
| 149 ASSERT(fd >= 0); |
| 150 ssize_t written_bytes = |
| 151 TEMP_FAILURE_RETRY( |
| 152 sendto(fd, buffer, num_bytes, 0, |
| 153 &addr.addr, SocketAddress::GetAddrLength(&addr))); |
| 154 ASSERT(EAGAIN == EWOULDBLOCK); |
| 155 if (written_bytes == -1 && errno == EWOULDBLOCK) { |
| 156 // If the would block we need to retry and therefore return 0 as |
| 157 // the number of bytes written. |
| 158 written_bytes = 0; |
| 159 } |
| 160 return written_bytes; |
| 161 } |
| 162 |
| 163 |
121 intptr_t Socket::GetPort(intptr_t fd) { | 164 intptr_t Socket::GetPort(intptr_t fd) { |
122 ASSERT(fd >= 0); | 165 ASSERT(fd >= 0); |
123 RawAddr raw; | 166 RawAddr raw; |
124 socklen_t size = sizeof(raw); | 167 socklen_t size = sizeof(raw); |
125 if (TEMP_FAILURE_RETRY( | 168 if (TEMP_FAILURE_RETRY( |
126 getsockname(fd, | 169 getsockname(fd, |
127 &raw.addr, | 170 &raw.addr, |
128 &size))) { | 171 &size))) { |
129 const int kBufferSize = 1024; | 172 const int kBufferSize = 1024; |
130 char error_message[kBufferSize]; | 173 char error_message[kBufferSize]; |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 if (type == SocketAddress::TYPE_IPV4) { | 292 if (type == SocketAddress::TYPE_IPV4) { |
250 result = inet_pton(AF_INET, address, &addr->in.sin_addr); | 293 result = inet_pton(AF_INET, address, &addr->in.sin_addr); |
251 } else { | 294 } else { |
252 ASSERT(type == SocketAddress::TYPE_IPV6); | 295 ASSERT(type == SocketAddress::TYPE_IPV6); |
253 result = inet_pton(AF_INET6, address, &addr->in6.sin6_addr); | 296 result = inet_pton(AF_INET6, address, &addr->in6.sin6_addr); |
254 } | 297 } |
255 return result == 1; | 298 return result == 1; |
256 } | 299 } |
257 | 300 |
258 | 301 |
| 302 intptr_t Socket::CreateBindDatagram( |
| 303 RawAddr* addr, intptr_t port, bool reuseAddress) { |
| 304 intptr_t fd; |
| 305 |
| 306 fd = TEMP_FAILURE_RETRY( |
| 307 socket(addr->addr.sa_family, SOCK_DGRAM, IPPROTO_UDP)); |
| 308 if (fd < 0) return -1; |
| 309 |
| 310 FDUtils::SetCloseOnExec(fd); |
| 311 |
| 312 if (reuseAddress) { |
| 313 int optval = 1; |
| 314 TEMP_FAILURE_RETRY( |
| 315 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))); |
| 316 } |
| 317 |
| 318 SocketAddress::SetAddrPort(addr, port); |
| 319 if (TEMP_FAILURE_RETRY( |
| 320 bind(fd, |
| 321 &addr->addr, |
| 322 SocketAddress::GetAddrLength(addr))) < 0) { |
| 323 TEMP_FAILURE_RETRY(close(fd)); |
| 324 return -1; |
| 325 } |
| 326 |
| 327 Socket::SetNonBlocking(fd); |
| 328 return fd; |
| 329 } |
| 330 |
| 331 |
259 AddressList<InterfaceSocketAddress>* Socket::ListInterfaces( | 332 AddressList<InterfaceSocketAddress>* Socket::ListInterfaces( |
260 int type, | 333 int type, |
261 OSError** os_error) { | 334 OSError** os_error) { |
262 // The ifaddrs.h header is not provided on Android. An Android | 335 // The ifaddrs.h header is not provided on Android. An Android |
263 // implementation would have to use IOCTL or netlink. | 336 // implementation would have to use IOCTL or netlink. |
264 return NULL; | 337 return NULL; |
265 } | 338 } |
266 | 339 |
267 | 340 |
268 intptr_t ServerSocket::CreateBindListen(RawAddr addr, | 341 intptr_t ServerSocket::CreateBindListen(RawAddr addr, |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 bool Socket::SetNonBlocking(intptr_t fd) { | 434 bool Socket::SetNonBlocking(intptr_t fd) { |
362 return FDUtils::SetNonBlocking(fd); | 435 return FDUtils::SetNonBlocking(fd); |
363 } | 436 } |
364 | 437 |
365 | 438 |
366 bool Socket::SetBlocking(intptr_t fd) { | 439 bool Socket::SetBlocking(intptr_t fd) { |
367 return FDUtils::SetBlocking(fd); | 440 return FDUtils::SetBlocking(fd); |
368 } | 441 } |
369 | 442 |
370 | 443 |
| 444 bool Socket::GetNoDelay(intptr_t fd, bool* enabled) { |
| 445 int on; |
| 446 socklen_t len = sizeof(on); |
| 447 int err = TEMP_FAILURE_RETRY(getsockopt(fd, |
| 448 IPPROTO_TCP, |
| 449 TCP_NODELAY, |
| 450 reinterpret_cast<void *>(&on), |
| 451 &len)); |
| 452 if (err == 0) { |
| 453 *enabled = on == 1; |
| 454 } |
| 455 return err == 0; |
| 456 } |
| 457 |
| 458 |
371 bool Socket::SetNoDelay(intptr_t fd, bool enabled) { | 459 bool Socket::SetNoDelay(intptr_t fd, bool enabled) { |
372 int on = enabled ? 1 : 0; | 460 int on = enabled ? 1 : 0; |
373 return TEMP_FAILURE_RETRY(setsockopt(fd, | 461 return TEMP_FAILURE_RETRY(setsockopt(fd, |
374 IPPROTO_TCP, | 462 IPPROTO_TCP, |
375 TCP_NODELAY, | 463 TCP_NODELAY, |
376 reinterpret_cast<char *>(&on), | 464 reinterpret_cast<char *>(&on), |
377 sizeof(on))) == 0; | 465 sizeof(on))) == 0; |
378 } | 466 } |
379 | 467 |
| 468 |
| 469 bool Socket::GetMulticastLoop(intptr_t fd, intptr_t protocol, bool* enabled) { |
| 470 uint8_t on; |
| 471 socklen_t len = sizeof(on); |
| 472 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; |
| 473 int optname = protocol == SocketAddress::TYPE_IPV4 |
| 474 ? IP_MULTICAST_LOOP : IPV6_MULTICAST_LOOP; |
| 475 if (TEMP_FAILURE_RETRY(getsockopt(fd, |
| 476 level, |
| 477 optname, |
| 478 reinterpret_cast<char *>(&on), |
| 479 &len)) == 0) { |
| 480 *enabled = (on == 1); |
| 481 return true; |
| 482 } |
| 483 return false; |
| 484 } |
| 485 |
| 486 |
| 487 bool Socket::SetMulticastLoop(intptr_t fd, intptr_t protocol, bool enabled) { |
| 488 int on = enabled ? 1 : 0; |
| 489 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; |
| 490 int optname = protocol == SocketAddress::TYPE_IPV4 |
| 491 ? IP_MULTICAST_LOOP : IPV6_MULTICAST_LOOP; |
| 492 return TEMP_FAILURE_RETRY(setsockopt(fd, |
| 493 level, |
| 494 optname, |
| 495 reinterpret_cast<char *>(&on), |
| 496 sizeof(on))) == 0; |
| 497 } |
| 498 |
| 499 |
| 500 bool Socket::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) { |
| 501 uint8_t v; |
| 502 socklen_t len = sizeof(v); |
| 503 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; |
| 504 int optname = protocol == SocketAddress::TYPE_IPV4 |
| 505 ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS; |
| 506 if (TEMP_FAILURE_RETRY(getsockopt(fd, |
| 507 level, |
| 508 optname, |
| 509 reinterpret_cast<char *>(&v), |
| 510 &len)) == 0) { |
| 511 *value = v; |
| 512 return true; |
| 513 } |
| 514 return false; |
| 515 } |
| 516 |
| 517 |
| 518 bool Socket::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) { |
| 519 int v = value; |
| 520 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; |
| 521 int optname = protocol == SocketAddress::TYPE_IPV4 |
| 522 ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS; |
| 523 return TEMP_FAILURE_RETRY(setsockopt(fd, |
| 524 level, |
| 525 optname, |
| 526 reinterpret_cast<char *>(&v), |
| 527 sizeof(v))) == 0; |
| 528 } |
| 529 |
| 530 |
| 531 bool Socket::GetBroadcast(intptr_t fd, bool* enabled) { |
| 532 int on; |
| 533 socklen_t len = sizeof(on); |
| 534 int err = TEMP_FAILURE_RETRY(getsockopt(fd, |
| 535 SOL_SOCKET, |
| 536 SO_BROADCAST, |
| 537 reinterpret_cast<char *>(&on), |
| 538 &len)); |
| 539 if (err == 0) { |
| 540 *enabled = on == 1; |
| 541 } |
| 542 return err == 0; |
| 543 } |
| 544 |
| 545 |
| 546 bool Socket::SetBroadcast(intptr_t fd, bool enabled) { |
| 547 int on = enabled ? 1 : 0; |
| 548 return TEMP_FAILURE_RETRY(setsockopt(fd, |
| 549 SOL_SOCKET, |
| 550 SO_BROADCAST, |
| 551 reinterpret_cast<char *>(&on), |
| 552 sizeof(on))) == 0; |
| 553 } |
| 554 |
| 555 |
| 556 bool Socket::JoinMulticast(intptr_t fd, RawAddr* addr, int interfaceIndex) { |
| 557 int proto = addr->addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; |
| 558 struct group_req mreq; |
| 559 mreq.gr_interface = interfaceIndex; |
| 560 memmove(&mreq.gr_group, &addr->ss, SocketAddress::GetAddrLength(addr)); |
| 561 return TEMP_FAILURE_RETRY(setsockopt( |
| 562 fd, proto, MCAST_JOIN_GROUP, &mreq, sizeof(mreq))) == 0; |
| 563 } |
| 564 |
| 565 |
| 566 bool Socket::LeaveMulticast(intptr_t fd, RawAddr* addr, int interfaceIndex) { |
| 567 int proto = addr->addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; |
| 568 struct group_req mreq; |
| 569 mreq.gr_interface = interfaceIndex; |
| 570 memmove(&mreq.gr_group, &addr->ss, SocketAddress::GetAddrLength(addr)); |
| 571 return TEMP_FAILURE_RETRY(setsockopt( |
| 572 fd, proto, MCAST_LEAVE_GROUP, &mreq, sizeof(mreq))) == 0; |
| 573 } |
| 574 |
380 } // namespace bin | 575 } // namespace bin |
381 } // namespace dart | 576 } // namespace dart |
382 | 577 |
383 #endif // defined(TARGET_OS_ANDROID) | 578 #endif // defined(TARGET_OS_ANDROID) |
OLD | NEW |