| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file |  | 
| 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. |  | 
| 4 |  | 
| 5 #if !defined(DART_IO_DISABLED) |  | 
| 6 |  | 
| 7 #include "platform/globals.h" |  | 
| 8 #if defined(HOST_OS_FUCHSIA) |  | 
| 9 |  | 
| 10 #include "bin/socket_base.h" |  | 
| 11 |  | 
| 12 #include <errno.h>        // NOLINT |  | 
| 13 #include <fcntl.h>        // NOLINT |  | 
| 14 #include <ifaddrs.h>      // NOLINT |  | 
| 15 #include <net/if.h>       // NOLINT |  | 
| 16 #include <netinet/tcp.h>  // NOLINT |  | 
| 17 #include <stdio.h>        // NOLINT |  | 
| 18 #include <stdlib.h>       // NOLINT |  | 
| 19 #include <string.h>       // NOLINT |  | 
| 20 #include <sys/ioctl.h>    // NOLINT |  | 
| 21 #include <sys/stat.h>     // NOLINT |  | 
| 22 #include <unistd.h>       // NOLINT |  | 
| 23 |  | 
| 24 #include "bin/fdutils.h" |  | 
| 25 #include "bin/file.h" |  | 
| 26 #include "bin/socket_base_fuchsia.h" |  | 
| 27 #include "platform/signal_blocker.h" |  | 
| 28 |  | 
| 29 // #define SOCKET_LOG_INFO 1 |  | 
| 30 // #define SOCKET_LOG_ERROR 1 |  | 
| 31 |  | 
| 32 // define SOCKET_LOG_ERROR to get log messages only for errors. |  | 
| 33 // define SOCKET_LOG_INFO to get log messages for both information and errors. |  | 
| 34 #if defined(SOCKET_LOG_INFO) || defined(SOCKET_LOG_ERROR) |  | 
| 35 #define LOG_ERR(msg, ...)                                                      \ |  | 
| 36   {                                                                            \ |  | 
| 37     int err = errno;                                                           \ |  | 
| 38     Log::PrintErr("Dart Socket ERROR: %s:%d: " msg, __FILE__, __LINE__,        \ |  | 
| 39                   ##__VA_ARGS__);                                              \ |  | 
| 40     errno = err;                                                               \ |  | 
| 41   } |  | 
| 42 #if defined(SOCKET_LOG_INFO) |  | 
| 43 #define LOG_INFO(msg, ...)                                                     \ |  | 
| 44   Log::Print("Dart Socket INFO: %s:%d: " msg, __FILE__, __LINE__, ##__VA_ARGS__) |  | 
| 45 #else |  | 
| 46 #define LOG_INFO(msg, ...) |  | 
| 47 #endif  // defined(SOCKET_LOG_INFO) |  | 
| 48 #else |  | 
| 49 #define LOG_ERR(msg, ...) |  | 
| 50 #define LOG_INFO(msg, ...) |  | 
| 51 #endif  // defined(SOCKET_LOG_INFO) || defined(SOCKET_LOG_ERROR) |  | 
| 52 |  | 
| 53 namespace dart { |  | 
| 54 namespace bin { |  | 
| 55 |  | 
| 56 SocketAddress::SocketAddress(struct sockaddr* sa) { |  | 
| 57   ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN); |  | 
| 58   if (!SocketBase::FormatNumericAddress(*reinterpret_cast<RawAddr*>(sa), |  | 
| 59                                         as_string_, INET6_ADDRSTRLEN)) { |  | 
| 60     as_string_[0] = 0; |  | 
| 61   } |  | 
| 62   socklen_t salen = GetAddrLength(*reinterpret_cast<RawAddr*>(sa)); |  | 
| 63   memmove(reinterpret_cast<void*>(&addr_), sa, salen); |  | 
| 64 } |  | 
| 65 |  | 
| 66 |  | 
| 67 bool SocketBase::FormatNumericAddress(const RawAddr& addr, |  | 
| 68                                       char* address, |  | 
| 69                                       int len) { |  | 
| 70   socklen_t salen = SocketAddress::GetAddrLength(addr); |  | 
| 71   LOG_INFO("SocketBase::FormatNumericAddress: calling getnameinfo\n"); |  | 
| 72   return (NO_RETRY_EXPECTED(getnameinfo(&addr.addr, salen, address, len, NULL, |  | 
| 73                                         0, NI_NUMERICHOST) == 0)); |  | 
| 74 } |  | 
| 75 |  | 
| 76 |  | 
| 77 bool SocketBase::IsBindError(intptr_t error_number) { |  | 
| 78   return error_number == EADDRINUSE || error_number == EADDRNOTAVAIL || |  | 
| 79          error_number == EINVAL; |  | 
| 80 } |  | 
| 81 |  | 
| 82 |  | 
| 83 intptr_t SocketBase::Available(intptr_t fd) { |  | 
| 84   intptr_t available = FDUtils::AvailableBytes(fd); |  | 
| 85   LOG_INFO("SocketBase::Available(%ld) = %ld\n", fd, available); |  | 
| 86   return available; |  | 
| 87 } |  | 
| 88 |  | 
| 89 |  | 
| 90 intptr_t SocketBase::Read(intptr_t fd, void* buffer, intptr_t num_bytes) { |  | 
| 91   ASSERT(fd >= 0); |  | 
| 92   LOG_INFO("SocketBase::Read: calling read(%ld, %p, %ld)\n", fd, buffer, |  | 
| 93            num_bytes); |  | 
| 94   ssize_t read_bytes = NO_RETRY_EXPECTED(read(fd, buffer, num_bytes)); |  | 
| 95   ASSERT(EAGAIN == EWOULDBLOCK); |  | 
| 96   if ((read_bytes == -1) && (errno == EWOULDBLOCK)) { |  | 
| 97     // If the read would block we need to retry and therefore return 0 |  | 
| 98     // as the number of bytes written. |  | 
| 99     read_bytes = 0; |  | 
| 100   } else if (read_bytes == -1) { |  | 
| 101     LOG_ERR("SocketBase::Read: read(%ld, %p, %ld) failed\n", fd, buffer, |  | 
| 102             num_bytes); |  | 
| 103   } else { |  | 
| 104     LOG_INFO("SocketBase::Read: read(%ld, %p, %ld) succeeded\n", fd, buffer, |  | 
| 105              num_bytes); |  | 
| 106   } |  | 
| 107   return read_bytes; |  | 
| 108 } |  | 
| 109 |  | 
| 110 |  | 
| 111 intptr_t SocketBase::RecvFrom(intptr_t fd, |  | 
| 112                               void* buffer, |  | 
| 113                               intptr_t num_bytes, |  | 
| 114                               RawAddr* addr) { |  | 
| 115   LOG_ERR("SocketBase::RecvFrom is unimplemented\n"); |  | 
| 116   UNIMPLEMENTED(); |  | 
| 117   return -1; |  | 
| 118 } |  | 
| 119 |  | 
| 120 |  | 
| 121 intptr_t SocketBase::Write(intptr_t fd, |  | 
| 122                            const void* buffer, |  | 
| 123                            intptr_t num_bytes) { |  | 
| 124   ASSERT(fd >= 0); |  | 
| 125   LOG_INFO("SocketBase::Write: calling write(%ld, %p, %ld)\n", fd, buffer, |  | 
| 126            num_bytes); |  | 
| 127   ssize_t written_bytes = NO_RETRY_EXPECTED(write(fd, buffer, num_bytes)); |  | 
| 128   ASSERT(EAGAIN == EWOULDBLOCK); |  | 
| 129   if ((written_bytes == -1) && (errno == EWOULDBLOCK)) { |  | 
| 130     // If the would block we need to retry and therefore return 0 as |  | 
| 131     // the number of bytes written. |  | 
| 132     written_bytes = 0; |  | 
| 133   } else if (written_bytes == -1) { |  | 
| 134     LOG_ERR("SocketBase::Write: write(%ld, %p, %ld) failed\n", fd, buffer, |  | 
| 135             num_bytes); |  | 
| 136   } else { |  | 
| 137     LOG_INFO("SocketBase::Write: write(%ld, %p, %ld) succeeded\n", fd, buffer, |  | 
| 138              num_bytes); |  | 
| 139   } |  | 
| 140   return written_bytes; |  | 
| 141 } |  | 
| 142 |  | 
| 143 |  | 
| 144 intptr_t SocketBase::SendTo(intptr_t fd, |  | 
| 145                             const void* buffer, |  | 
| 146                             intptr_t num_bytes, |  | 
| 147                             const RawAddr& addr) { |  | 
| 148   LOG_ERR("SocketBase::SendTo is unimplemented\n"); |  | 
| 149   UNIMPLEMENTED(); |  | 
| 150   return -1; |  | 
| 151 } |  | 
| 152 |  | 
| 153 |  | 
| 154 intptr_t SocketBase::GetPort(intptr_t fd) { |  | 
| 155   ASSERT(fd >= 0); |  | 
| 156   RawAddr raw; |  | 
| 157   socklen_t size = sizeof(raw); |  | 
| 158   LOG_INFO("SocketBase::GetPort: calling getsockname(%ld)\n", fd); |  | 
| 159   if (NO_RETRY_EXPECTED(getsockname(fd, &raw.addr, &size))) { |  | 
| 160     return 0; |  | 
| 161   } |  | 
| 162   return SocketAddress::GetAddrPort(raw); |  | 
| 163 } |  | 
| 164 |  | 
| 165 |  | 
| 166 SocketAddress* SocketBase::GetRemotePeer(intptr_t fd, intptr_t* port) { |  | 
| 167   ASSERT(fd >= 0); |  | 
| 168   RawAddr raw; |  | 
| 169   socklen_t size = sizeof(raw); |  | 
| 170   if (NO_RETRY_EXPECTED(getpeername(fd, &raw.addr, &size))) { |  | 
| 171     return NULL; |  | 
| 172   } |  | 
| 173   *port = SocketAddress::GetAddrPort(raw); |  | 
| 174   return new SocketAddress(&raw.addr); |  | 
| 175 } |  | 
| 176 |  | 
| 177 |  | 
| 178 void SocketBase::GetError(intptr_t fd, OSError* os_error) { |  | 
| 179   LOG_ERR("SocketBase::GetError is unimplemented\n"); |  | 
| 180   UNIMPLEMENTED(); |  | 
| 181 } |  | 
| 182 |  | 
| 183 |  | 
| 184 int SocketBase::GetType(intptr_t fd) { |  | 
| 185   LOG_ERR("SocketBase::GetType is unimplemented\n"); |  | 
| 186   UNIMPLEMENTED(); |  | 
| 187   return File::kOther; |  | 
| 188 } |  | 
| 189 |  | 
| 190 |  | 
| 191 intptr_t SocketBase::GetStdioHandle(intptr_t num) { |  | 
| 192   LOG_ERR("SocketBase::GetStdioHandle is unimplemented\n"); |  | 
| 193   UNIMPLEMENTED(); |  | 
| 194   return num; |  | 
| 195 } |  | 
| 196 |  | 
| 197 |  | 
| 198 AddressList<SocketAddress>* SocketBase::LookupAddress(const char* host, |  | 
| 199                                                       int type, |  | 
| 200                                                       OSError** os_error) { |  | 
| 201   // Perform a name lookup for a host name. |  | 
| 202   struct addrinfo hints; |  | 
| 203   memset(&hints, 0, sizeof(hints)); |  | 
| 204   hints.ai_family = SocketAddress::FromType(type); |  | 
| 205   hints.ai_socktype = SOCK_STREAM; |  | 
| 206   hints.ai_flags = AI_ADDRCONFIG; |  | 
| 207   hints.ai_protocol = IPPROTO_TCP; |  | 
| 208   struct addrinfo* info = NULL; |  | 
| 209   LOG_INFO("SocketBase::LookupAddress: calling getaddrinfo\n"); |  | 
| 210   int status = NO_RETRY_EXPECTED(getaddrinfo(host, 0, &hints, &info)); |  | 
| 211   if (status != 0) { |  | 
| 212     // We failed, try without AI_ADDRCONFIG. This can happen when looking up |  | 
| 213     // e.g. '::1', when there are no global IPv6 addresses. |  | 
| 214     hints.ai_flags = 0; |  | 
| 215     LOG_INFO("SocketBase::LookupAddress: calling getaddrinfo again\n"); |  | 
| 216     status = NO_RETRY_EXPECTED(getaddrinfo(host, 0, &hints, &info)); |  | 
| 217     if (status != 0) { |  | 
| 218       ASSERT(*os_error == NULL); |  | 
| 219       *os_error = |  | 
| 220           new OSError(status, gai_strerror(status), OSError::kGetAddressInfo); |  | 
| 221       return NULL; |  | 
| 222     } |  | 
| 223   } |  | 
| 224   intptr_t count = 0; |  | 
| 225   for (struct addrinfo* c = info; c != NULL; c = c->ai_next) { |  | 
| 226     if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) { |  | 
| 227       count++; |  | 
| 228     } |  | 
| 229   } |  | 
| 230   intptr_t i = 0; |  | 
| 231   AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count); |  | 
| 232   for (struct addrinfo* c = info; c != NULL; c = c->ai_next) { |  | 
| 233     if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) { |  | 
| 234       addresses->SetAt(i, new SocketAddress(c->ai_addr)); |  | 
| 235       i++; |  | 
| 236     } |  | 
| 237   } |  | 
| 238   freeaddrinfo(info); |  | 
| 239   return addresses; |  | 
| 240 } |  | 
| 241 |  | 
| 242 |  | 
| 243 bool SocketBase::ReverseLookup(const RawAddr& addr, |  | 
| 244                                char* host, |  | 
| 245                                intptr_t host_len, |  | 
| 246                                OSError** os_error) { |  | 
| 247   LOG_ERR("SocketBase::ReverseLookup is unimplemented\n"); |  | 
| 248   UNIMPLEMENTED(); |  | 
| 249   return false; |  | 
| 250 } |  | 
| 251 |  | 
| 252 |  | 
| 253 bool SocketBase::ParseAddress(int type, const char* address, RawAddr* addr) { |  | 
| 254   int result; |  | 
| 255   if (type == SocketAddress::TYPE_IPV4) { |  | 
| 256     result = NO_RETRY_EXPECTED(inet_pton(AF_INET, address, &addr->in.sin_addr)); |  | 
| 257   } else { |  | 
| 258     ASSERT(type == SocketAddress::TYPE_IPV6); |  | 
| 259     result = |  | 
| 260         NO_RETRY_EXPECTED(inet_pton(AF_INET6, address, &addr->in6.sin6_addr)); |  | 
| 261   } |  | 
| 262   return (result == 1); |  | 
| 263 } |  | 
| 264 |  | 
| 265 |  | 
| 266 bool SocketBase::ListInterfacesSupported() { |  | 
| 267   return false; |  | 
| 268 } |  | 
| 269 |  | 
| 270 |  | 
| 271 AddressList<InterfaceSocketAddress>* SocketBase::ListInterfaces( |  | 
| 272     int type, |  | 
| 273     OSError** os_error) { |  | 
| 274   UNIMPLEMENTED(); |  | 
| 275   return NULL; |  | 
| 276 } |  | 
| 277 |  | 
| 278 |  | 
| 279 void SocketBase::Close(intptr_t fd) { |  | 
| 280   ASSERT(fd >= 0); |  | 
| 281   NO_RETRY_EXPECTED(close(fd)); |  | 
| 282 } |  | 
| 283 |  | 
| 284 |  | 
| 285 bool SocketBase::GetNoDelay(intptr_t fd, bool* enabled) { |  | 
| 286   LOG_ERR("SocketBase::GetNoDelay is unimplemented\n"); |  | 
| 287   UNIMPLEMENTED(); |  | 
| 288   return false; |  | 
| 289 } |  | 
| 290 |  | 
| 291 |  | 
| 292 bool SocketBase::SetNoDelay(intptr_t fd, bool enabled) { |  | 
| 293   int on = enabled ? 1 : 0; |  | 
| 294   return NO_RETRY_EXPECTED(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, |  | 
| 295                                       reinterpret_cast<char*>(&on), |  | 
| 296                                       sizeof(on))) == 0; |  | 
| 297 } |  | 
| 298 |  | 
| 299 |  | 
| 300 bool SocketBase::GetMulticastLoop(intptr_t fd, |  | 
| 301                                   intptr_t protocol, |  | 
| 302                                   bool* enabled) { |  | 
| 303   LOG_ERR("SocketBase::GetMulticastLoop is unimplemented\n"); |  | 
| 304   UNIMPLEMENTED(); |  | 
| 305   return false; |  | 
| 306 } |  | 
| 307 |  | 
| 308 |  | 
| 309 bool SocketBase::SetMulticastLoop(intptr_t fd, |  | 
| 310                                   intptr_t protocol, |  | 
| 311                                   bool enabled) { |  | 
| 312   LOG_ERR("SocketBase::SetMulticastLoop is unimplemented\n"); |  | 
| 313   UNIMPLEMENTED(); |  | 
| 314   return false; |  | 
| 315 } |  | 
| 316 |  | 
| 317 |  | 
| 318 bool SocketBase::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) { |  | 
| 319   LOG_ERR("SocketBase::GetMulticastHops is unimplemented\n"); |  | 
| 320   UNIMPLEMENTED(); |  | 
| 321   return false; |  | 
| 322 } |  | 
| 323 |  | 
| 324 |  | 
| 325 bool SocketBase::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) { |  | 
| 326   LOG_ERR("SocketBase::SetMulticastHops is unimplemented\n"); |  | 
| 327   UNIMPLEMENTED(); |  | 
| 328   return false; |  | 
| 329 } |  | 
| 330 |  | 
| 331 |  | 
| 332 bool SocketBase::GetBroadcast(intptr_t fd, bool* enabled) { |  | 
| 333   LOG_ERR("SocketBase::GetBroadcast is unimplemented\n"); |  | 
| 334   UNIMPLEMENTED(); |  | 
| 335   return false; |  | 
| 336 } |  | 
| 337 |  | 
| 338 |  | 
| 339 bool SocketBase::SetBroadcast(intptr_t fd, bool enabled) { |  | 
| 340   LOG_ERR("SocketBase::SetBroadcast is unimplemented\n"); |  | 
| 341   UNIMPLEMENTED(); |  | 
| 342   return false; |  | 
| 343 } |  | 
| 344 |  | 
| 345 |  | 
| 346 bool SocketBase::JoinMulticast(intptr_t fd, |  | 
| 347                                const RawAddr& addr, |  | 
| 348                                const RawAddr&, |  | 
| 349                                int interfaceIndex) { |  | 
| 350   LOG_ERR("SocketBase::JoinMulticast is unimplemented\n"); |  | 
| 351   UNIMPLEMENTED(); |  | 
| 352   return false; |  | 
| 353 } |  | 
| 354 |  | 
| 355 |  | 
| 356 bool SocketBase::LeaveMulticast(intptr_t fd, |  | 
| 357                                 const RawAddr& addr, |  | 
| 358                                 const RawAddr&, |  | 
| 359                                 int interfaceIndex) { |  | 
| 360   LOG_ERR("SocketBase::LeaveMulticast is unimplemented\n"); |  | 
| 361   UNIMPLEMENTED(); |  | 
| 362   return false; |  | 
| 363 } |  | 
| 364 |  | 
| 365 }  // namespace bin |  | 
| 366 }  // namespace dart |  | 
| 367 |  | 
| 368 #endif  // defined(HOST_OS_FUCHSIA) |  | 
| 369 |  | 
| 370 #endif  // !defined(DART_IO_DISABLED) |  | 
| OLD | NEW | 
|---|