| 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 |