| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 #if !defined(DART_IO_DISABLED) | 5 #if !defined(DART_IO_DISABLED) |
| 6 | 6 |
| 7 #include "platform/globals.h" | 7 #include "platform/globals.h" |
| 8 #if defined(TARGET_OS_LINUX) | 8 #if defined(TARGET_OS_LINUX) |
| 9 | 9 |
| 10 #include "bin/socket.h" | 10 #include "bin/socket.h" |
| 11 #include "bin/socket_linux.h" | 11 #include "bin/socket_common_linux.h" |
| 12 | 12 |
| 13 #include <errno.h> // NOLINT | 13 #include <errno.h> // NOLINT |
| 14 #include <ifaddrs.h> // NOLINT | 14 #include <ifaddrs.h> // NOLINT |
| 15 #include <net/if.h> // NOLINT | 15 #include <net/if.h> // NOLINT |
| 16 #include <netinet/tcp.h> // NOLINT | 16 #include <netinet/tcp.h> // NOLINT |
| 17 #include <stdio.h> // NOLINT | 17 #include <stdio.h> // NOLINT |
| 18 #include <stdlib.h> // NOLINT | 18 #include <stdlib.h> // NOLINT |
| 19 #include <string.h> // NOLINT | 19 #include <string.h> // NOLINT |
| 20 #include <sys/stat.h> // NOLINT | 20 #include <sys/stat.h> // NOLINT |
| 21 #include <unistd.h> // NOLINT | 21 #include <unistd.h> // NOLINT |
| (...skipping 10 matching lines...) Expand all Loading... |
| 32 ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN); | 32 ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN); |
| 33 if (!Socket::FormatNumericAddress(*reinterpret_cast<RawAddr*>(sa), as_string_, | 33 if (!Socket::FormatNumericAddress(*reinterpret_cast<RawAddr*>(sa), as_string_, |
| 34 INET6_ADDRSTRLEN)) { | 34 INET6_ADDRSTRLEN)) { |
| 35 as_string_[0] = 0; | 35 as_string_[0] = 0; |
| 36 } | 36 } |
| 37 socklen_t salen = GetAddrLength(*reinterpret_cast<RawAddr*>(sa)); | 37 socklen_t salen = GetAddrLength(*reinterpret_cast<RawAddr*>(sa)); |
| 38 memmove(reinterpret_cast<void*>(&addr_), sa, salen); | 38 memmove(reinterpret_cast<void*>(&addr_), sa, salen); |
| 39 } | 39 } |
| 40 | 40 |
| 41 | 41 |
| 42 bool Socket::FormatNumericAddress(const RawAddr& addr, char* address, int len) { | 42 bool BaseSocket::FormatNumericAddress(const RawAddr& addr, |
| 43 char* address, |
| 44 int len) { |
| 43 socklen_t salen = SocketAddress::GetAddrLength(addr); | 45 socklen_t salen = SocketAddress::GetAddrLength(addr); |
| 44 return (NO_RETRY_EXPECTED(getnameinfo(&addr.addr, salen, address, len, NULL, | 46 return (NO_RETRY_EXPECTED(getnameinfo(&addr.addr, salen, address, len, NULL, |
| 45 0, NI_NUMERICHOST) == 0)); | 47 0, NI_NUMERICHOST) == 0)); |
| 46 } | 48 } |
| 47 | 49 |
| 48 | 50 |
| 49 bool Socket::Initialize() { | 51 bool BaseSocket::Initialize() { |
| 50 // Nothing to do on Linux. | 52 // Nothing to do on Linux. |
| 51 return true; | 53 return true; |
| 52 } | 54 } |
| 53 | 55 |
| 54 | 56 |
| 55 static intptr_t Create(const RawAddr& addr) { | 57 static intptr_t Create(const RawAddr& addr) { |
| 56 intptr_t fd; | 58 intptr_t fd; |
| 57 fd = NO_RETRY_EXPECTED( | 59 intptr_t type = SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC; |
| 58 socket(addr.ss.ss_family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); | 60 fd = NO_RETRY_EXPECTED(socket(addr.ss.ss_family, type, 0)); |
| 59 if (fd < 0) { | 61 if (fd < 0) { |
| 60 return -1; | 62 return -1; |
| 61 } | 63 } |
| 62 return fd; | 64 return fd; |
| 63 } | 65 } |
| 64 | 66 |
| 65 | 67 |
| 66 static intptr_t Connect(intptr_t fd, const RawAddr& addr) { | 68 static intptr_t Connect(intptr_t fd, const RawAddr& addr) { |
| 67 intptr_t result = TEMP_FAILURE_RETRY( | 69 intptr_t result = TEMP_FAILURE_RETRY( |
| 68 connect(fd, &addr.addr, SocketAddress::GetAddrLength(addr))); | 70 connect(fd, &addr.addr, SocketAddress::GetAddrLength(addr))); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 94 bind(fd, &source_addr.addr, SocketAddress::GetAddrLength(source_addr))); | 96 bind(fd, &source_addr.addr, SocketAddress::GetAddrLength(source_addr))); |
| 95 if ((result != 0) && (errno != EINPROGRESS)) { | 97 if ((result != 0) && (errno != EINPROGRESS)) { |
| 96 FDUtils::SaveErrorAndClose(fd); | 98 FDUtils::SaveErrorAndClose(fd); |
| 97 return -1; | 99 return -1; |
| 98 } | 100 } |
| 99 | 101 |
| 100 return Connect(fd, addr); | 102 return Connect(fd, addr); |
| 101 } | 103 } |
| 102 | 104 |
| 103 | 105 |
| 104 bool Socket::IsBindError(intptr_t error_number) { | 106 bool BaseSocket::IsBindError(intptr_t error_number) { |
| 105 return error_number == EADDRINUSE || error_number == EADDRNOTAVAIL || | 107 return error_number == EADDRINUSE || error_number == EADDRNOTAVAIL || |
| 106 error_number == EINVAL; | 108 error_number == EINVAL; |
| 107 } | 109 } |
| 108 | 110 |
| 109 | 111 |
| 110 intptr_t Socket::Available(intptr_t fd) { | 112 intptr_t BaseSocket::Available(intptr_t fd) { |
| 111 return FDUtils::AvailableBytes(fd); | 113 return FDUtils::AvailableBytes(fd); |
| 112 } | 114 } |
| 113 | 115 |
| 114 | 116 |
| 115 intptr_t Socket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) { | 117 intptr_t BaseSocket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) { |
| 116 ASSERT(fd >= 0); | 118 ASSERT(fd >= 0); |
| 117 ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes)); | 119 ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes)); |
| 118 ASSERT(EAGAIN == EWOULDBLOCK); | 120 ASSERT(EAGAIN == EWOULDBLOCK); |
| 119 if ((read_bytes == -1) && (errno == EWOULDBLOCK)) { | 121 if ((read_bytes == -1) && (errno == EWOULDBLOCK)) { |
| 120 // If the read would block we need to retry and therefore return 0 | 122 // If the read would block we need to retry and therefore return 0 |
| 121 // as the number of bytes written. | 123 // as the number of bytes written. |
| 122 read_bytes = 0; | 124 read_bytes = 0; |
| 123 } | 125 } |
| 124 return read_bytes; | 126 return read_bytes; |
| 125 } | 127 } |
| 126 | 128 |
| 127 | 129 |
| 128 intptr_t Socket::RecvFrom(intptr_t fd, | 130 intptr_t BaseSocket::RecvFrom(intptr_t fd, |
| 129 void* buffer, | 131 void* buffer, |
| 130 intptr_t num_bytes, | 132 intptr_t num_bytes, |
| 131 RawAddr* addr) { | 133 RawAddr* addr) { |
| 132 ASSERT(fd >= 0); | 134 ASSERT(fd >= 0); |
| 133 socklen_t addr_len = sizeof(addr->ss); | 135 socklen_t addr_len = sizeof(addr->ss); |
| 134 ssize_t read_bytes = TEMP_FAILURE_RETRY( | 136 ssize_t read_bytes = TEMP_FAILURE_RETRY( |
| 135 recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len)); | 137 recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len)); |
| 136 if ((read_bytes == -1) && (errno == EWOULDBLOCK)) { | 138 if ((read_bytes == -1) && (errno == EWOULDBLOCK)) { |
| 137 // If the read would block we need to retry and therefore return 0 | 139 // If the read would block we need to retry and therefore return 0 |
| 138 // as the number of bytes written. | 140 // as the number of bytes written. |
| 139 read_bytes = 0; | 141 read_bytes = 0; |
| 140 } | 142 } |
| 141 return read_bytes; | 143 return read_bytes; |
| 142 } | 144 } |
| 143 | 145 |
| 144 | 146 |
| 145 intptr_t Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) { | 147 intptr_t BaseSocket::Write(intptr_t fd, |
| 148 const void* buffer, |
| 149 intptr_t num_bytes) { |
| 146 ASSERT(fd >= 0); | 150 ASSERT(fd >= 0); |
| 147 ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes)); | 151 ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes)); |
| 148 ASSERT(EAGAIN == EWOULDBLOCK); | 152 ASSERT(EAGAIN == EWOULDBLOCK); |
| 149 if ((written_bytes == -1) && (errno == EWOULDBLOCK)) { | 153 if ((written_bytes == -1) && (errno == EWOULDBLOCK)) { |
| 150 // If the would block we need to retry and therefore return 0 as | 154 // If the would block we need to retry and therefore return 0 as |
| 151 // the number of bytes written. | 155 // the number of bytes written. |
| 152 written_bytes = 0; | 156 written_bytes = 0; |
| 153 } | 157 } |
| 154 return written_bytes; | 158 return written_bytes; |
| 155 } | 159 } |
| 156 | 160 |
| 157 | 161 |
| 158 intptr_t Socket::SendTo(intptr_t fd, | 162 intptr_t BaseSocket::SendTo(intptr_t fd, |
| 159 const void* buffer, | 163 const void* buffer, |
| 160 intptr_t num_bytes, | 164 intptr_t num_bytes, |
| 161 const RawAddr& addr) { | 165 const RawAddr& addr) { |
| 162 ASSERT(fd >= 0); | 166 ASSERT(fd >= 0); |
| 163 ssize_t written_bytes = | 167 ssize_t written_bytes = |
| 164 TEMP_FAILURE_RETRY(sendto(fd, buffer, num_bytes, 0, &addr.addr, | 168 TEMP_FAILURE_RETRY(sendto(fd, buffer, num_bytes, 0, &addr.addr, |
| 165 SocketAddress::GetAddrLength(addr))); | 169 SocketAddress::GetAddrLength(addr))); |
| 166 ASSERT(EAGAIN == EWOULDBLOCK); | 170 ASSERT(EAGAIN == EWOULDBLOCK); |
| 167 if ((written_bytes == -1) && (errno == EWOULDBLOCK)) { | 171 if ((written_bytes == -1) && (errno == EWOULDBLOCK)) { |
| 168 // If the would block we need to retry and therefore return 0 as | 172 // If the would block we need to retry and therefore return 0 as |
| 169 // the number of bytes written. | 173 // the number of bytes written. |
| 170 written_bytes = 0; | 174 written_bytes = 0; |
| 171 } | 175 } |
| 172 return written_bytes; | 176 return written_bytes; |
| 173 } | 177 } |
| 174 | 178 |
| 175 | 179 |
| 176 intptr_t Socket::GetPort(intptr_t fd) { | 180 intptr_t BaseSocket::GetPort(intptr_t fd) { |
| 177 ASSERT(fd >= 0); | 181 ASSERT(fd >= 0); |
| 178 RawAddr raw; | 182 RawAddr raw; |
| 179 socklen_t size = sizeof(raw); | 183 socklen_t size = sizeof(raw); |
| 180 if (NO_RETRY_EXPECTED(getsockname(fd, &raw.addr, &size))) { | 184 if (NO_RETRY_EXPECTED(getsockname(fd, &raw.addr, &size))) { |
| 181 return 0; | 185 return 0; |
| 182 } | 186 } |
| 183 return SocketAddress::GetAddrPort(raw); | 187 return SocketAddress::GetAddrPort(raw); |
| 184 } | 188 } |
| 185 | 189 |
| 186 | 190 |
| 187 SocketAddress* Socket::GetRemotePeer(intptr_t fd, intptr_t* port) { | 191 SocketAddress* BaseSocket::GetRemotePeer(intptr_t fd, intptr_t* port) { |
| 188 ASSERT(fd >= 0); | 192 ASSERT(fd >= 0); |
| 189 RawAddr raw; | 193 RawAddr raw; |
| 190 socklen_t size = sizeof(raw); | 194 socklen_t size = sizeof(raw); |
| 191 if (NO_RETRY_EXPECTED(getpeername(fd, &raw.addr, &size))) { | 195 if (NO_RETRY_EXPECTED(getpeername(fd, &raw.addr, &size))) { |
| 192 return NULL; | 196 return NULL; |
| 193 } | 197 } |
| 194 *port = SocketAddress::GetAddrPort(raw); | 198 *port = SocketAddress::GetAddrPort(raw); |
| 195 return new SocketAddress(&raw.addr); | 199 return new SocketAddress(&raw.addr); |
| 196 } | 200 } |
| 197 | 201 |
| 198 | 202 |
| 199 void Socket::GetError(intptr_t fd, OSError* os_error) { | 203 void BaseSocket::GetError(intptr_t fd, OSError* os_error) { |
| 200 int len = sizeof(errno); | 204 int len = sizeof(errno); |
| 201 int err = 0; | 205 int err = 0; |
| 202 VOID_NO_RETRY_EXPECTED(getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, | 206 VOID_NO_RETRY_EXPECTED(getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, |
| 203 reinterpret_cast<socklen_t*>(&len))); | 207 reinterpret_cast<socklen_t*>(&len))); |
| 204 errno = err; | 208 errno = err; |
| 205 os_error->SetCodeAndMessage(OSError::kSystem, errno); | 209 os_error->SetCodeAndMessage(OSError::kSystem, errno); |
| 206 } | 210 } |
| 207 | 211 |
| 208 | 212 |
| 209 int Socket::GetType(intptr_t fd) { | 213 int BaseSocket::GetType(intptr_t fd) { |
| 210 struct stat64 buf; | 214 struct stat64 buf; |
| 211 int result = TEMP_FAILURE_RETRY(fstat64(fd, &buf)); | 215 int result = TEMP_FAILURE_RETRY(fstat64(fd, &buf)); |
| 212 if (result == -1) { | 216 if (result == -1) { |
| 213 return -1; | 217 return -1; |
| 214 } | 218 } |
| 215 if (S_ISCHR(buf.st_mode)) { | 219 if (S_ISCHR(buf.st_mode)) { |
| 216 return File::kTerminal; | 220 return File::kTerminal; |
| 217 } | 221 } |
| 218 if (S_ISFIFO(buf.st_mode)) { | 222 if (S_ISFIFO(buf.st_mode)) { |
| 219 return File::kPipe; | 223 return File::kPipe; |
| 220 } | 224 } |
| 221 if (S_ISREG(buf.st_mode)) { | 225 if (S_ISREG(buf.st_mode)) { |
| 222 return File::kFile; | 226 return File::kFile; |
| 223 } | 227 } |
| 224 return File::kOther; | 228 return File::kOther; |
| 225 } | 229 } |
| 226 | 230 |
| 227 | 231 |
| 228 intptr_t Socket::GetStdioHandle(intptr_t num) { | 232 intptr_t BaseSocket::GetStdioHandle(intptr_t num) { |
| 229 return num; | 233 return num; |
| 230 } | 234 } |
| 231 | 235 |
| 232 | 236 |
| 233 AddressList<SocketAddress>* Socket::LookupAddress(const char* host, | 237 AddressList<SocketAddress>* BaseSocket::LookupAddress(const char* host, |
| 234 int type, | 238 int type, |
| 235 OSError** os_error) { | 239 OSError** os_error) { |
| 236 // Perform a name lookup for a host name. | 240 // Perform a name lookup for a host name. |
| 237 struct addrinfo hints; | 241 struct addrinfo hints; |
| 238 memset(&hints, 0, sizeof(hints)); | 242 memset(&hints, 0, sizeof(hints)); |
| 239 hints.ai_family = SocketAddress::FromType(type); | 243 hints.ai_family = SocketAddress::FromType(type); |
| 240 hints.ai_socktype = SOCK_STREAM; | 244 hints.ai_socktype = SOCK_STREAM; |
| 241 hints.ai_flags = AI_ADDRCONFIG; | 245 hints.ai_flags = AI_ADDRCONFIG; |
| 242 hints.ai_protocol = IPPROTO_TCP; | 246 hints.ai_protocol = IPPROTO_TCP; |
| 243 struct addrinfo* info = NULL; | 247 struct addrinfo* info = NULL; |
| 244 int status = NO_RETRY_EXPECTED(getaddrinfo(host, 0, &hints, &info)); | 248 int status = NO_RETRY_EXPECTED(getaddrinfo(host, 0, &hints, &info)); |
| 245 if (status != 0) { | 249 if (status != 0) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 266 if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) { | 270 if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) { |
| 267 addresses->SetAt(i, new SocketAddress(c->ai_addr)); | 271 addresses->SetAt(i, new SocketAddress(c->ai_addr)); |
| 268 i++; | 272 i++; |
| 269 } | 273 } |
| 270 } | 274 } |
| 271 freeaddrinfo(info); | 275 freeaddrinfo(info); |
| 272 return addresses; | 276 return addresses; |
| 273 } | 277 } |
| 274 | 278 |
| 275 | 279 |
| 276 bool Socket::ReverseLookup(const RawAddr& addr, | 280 bool BaseSocket::ReverseLookup(const RawAddr& addr, |
| 277 char* host, | 281 char* host, |
| 278 intptr_t host_len, | 282 intptr_t host_len, |
| 279 OSError** os_error) { | 283 OSError** os_error) { |
| 280 ASSERT(host_len >= NI_MAXHOST); | 284 ASSERT(host_len >= NI_MAXHOST); |
| 281 int status = NO_RETRY_EXPECTED( | 285 int status = NO_RETRY_EXPECTED( |
| 282 getnameinfo(&addr.addr, SocketAddress::GetAddrLength(addr), host, | 286 getnameinfo(&addr.addr, SocketAddress::GetAddrLength(addr), host, |
| 283 host_len, NULL, 0, NI_NAMEREQD)); | 287 host_len, NULL, 0, NI_NAMEREQD)); |
| 284 if (status != 0) { | 288 if (status != 0) { |
| 285 ASSERT(*os_error == NULL); | 289 ASSERT(*os_error == NULL); |
| 286 *os_error = | 290 *os_error = |
| 287 new OSError(status, gai_strerror(status), OSError::kGetAddressInfo); | 291 new OSError(status, gai_strerror(status), OSError::kGetAddressInfo); |
| 288 return false; | 292 return false; |
| 289 } | 293 } |
| 290 return true; | 294 return true; |
| 291 } | 295 } |
| 292 | 296 |
| 293 | 297 |
| 294 bool Socket::ParseAddress(int type, const char* address, RawAddr* addr) { | 298 bool BaseSocket::ParseAddress(int type, const char* address, RawAddr* addr) { |
| 295 int result; | 299 int result; |
| 296 if (type == SocketAddress::TYPE_IPV4) { | 300 if (type == SocketAddress::TYPE_IPV4) { |
| 297 result = NO_RETRY_EXPECTED(inet_pton(AF_INET, address, &addr->in.sin_addr)); | 301 result = NO_RETRY_EXPECTED(inet_pton(AF_INET, address, &addr->in.sin_addr)); |
| 298 } else { | 302 } else { |
| 299 ASSERT(type == SocketAddress::TYPE_IPV6); | 303 ASSERT(type == SocketAddress::TYPE_IPV6); |
| 300 result = | 304 result = |
| 301 NO_RETRY_EXPECTED(inet_pton(AF_INET6, address, &addr->in6.sin6_addr)); | 305 NO_RETRY_EXPECTED(inet_pton(AF_INET6, address, &addr->in6.sin6_addr)); |
| 302 } | 306 } |
| 303 return (result == 1); | 307 return (result == 1); |
| 304 } | 308 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 334 // OpenVPN's virtual device tun0. | 338 // OpenVPN's virtual device tun0. |
| 335 return false; | 339 return false; |
| 336 } | 340 } |
| 337 int family = ifa->ifa_addr->sa_family; | 341 int family = ifa->ifa_addr->sa_family; |
| 338 return ((lookup_family == family) || | 342 return ((lookup_family == family) || |
| 339 (((lookup_family == AF_UNSPEC) && | 343 (((lookup_family == AF_UNSPEC) && |
| 340 ((family == AF_INET) || (family == AF_INET6))))); | 344 ((family == AF_INET) || (family == AF_INET6))))); |
| 341 } | 345 } |
| 342 | 346 |
| 343 | 347 |
| 344 bool Socket::ListInterfacesSupported() { | 348 bool BaseSocket::ListInterfacesSupported() { |
| 345 return true; | 349 return true; |
| 346 } | 350 } |
| 347 | 351 |
| 348 | 352 |
| 349 AddressList<InterfaceSocketAddress>* Socket::ListInterfaces( | 353 AddressList<InterfaceSocketAddress>* BaseSocket::ListInterfaces( |
| 350 int type, | 354 int type, |
| 351 OSError** os_error) { | 355 OSError** os_error) { |
| 352 struct ifaddrs* ifaddr; | 356 struct ifaddrs* ifaddr; |
| 353 | 357 |
| 354 int status = NO_RETRY_EXPECTED(getifaddrs(&ifaddr)); | 358 int status = NO_RETRY_EXPECTED(getifaddrs(&ifaddr)); |
| 355 if (status != 0) { | 359 if (status != 0) { |
| 356 ASSERT(*os_error == NULL); | 360 ASSERT(*os_error == NULL); |
| 357 *os_error = | 361 *os_error = |
| 358 new OSError(status, gai_strerror(status), OSError::kGetAddressInfo); | 362 new OSError(status, gai_strerror(status), OSError::kGetAddressInfo); |
| 359 return NULL; | 363 return NULL; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 } | 471 } |
| 468 if (!FDUtils::SetNonBlocking(socket)) { | 472 if (!FDUtils::SetNonBlocking(socket)) { |
| 469 FDUtils::SaveErrorAndClose(socket); | 473 FDUtils::SaveErrorAndClose(socket); |
| 470 return -1; | 474 return -1; |
| 471 } | 475 } |
| 472 } | 476 } |
| 473 return socket; | 477 return socket; |
| 474 } | 478 } |
| 475 | 479 |
| 476 | 480 |
| 477 void Socket::Close(intptr_t fd) { | 481 void BaseSocket::Close(intptr_t fd) { |
| 478 ASSERT(fd >= 0); | 482 ASSERT(fd >= 0); |
| 479 VOID_TEMP_FAILURE_RETRY(close(fd)); | 483 VOID_TEMP_FAILURE_RETRY(close(fd)); |
| 480 } | 484 } |
| 481 | 485 |
| 482 | 486 |
| 483 bool Socket::GetNoDelay(intptr_t fd, bool* enabled) { | 487 bool BaseSocket::GetNoDelay(intptr_t fd, bool* enabled) { |
| 484 int on; | 488 int on; |
| 485 socklen_t len = sizeof(on); | 489 socklen_t len = sizeof(on); |
| 486 int err = NO_RETRY_EXPECTED(getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, | 490 int err = NO_RETRY_EXPECTED(getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, |
| 487 reinterpret_cast<void*>(&on), &len)); | 491 reinterpret_cast<void*>(&on), &len)); |
| 488 if (err == 0) { | 492 if (err == 0) { |
| 489 *enabled = (on == 1); | 493 *enabled = (on == 1); |
| 490 } | 494 } |
| 491 return (err == 0); | 495 return (err == 0); |
| 492 } | 496 } |
| 493 | 497 |
| 494 | 498 |
| 495 bool Socket::SetNoDelay(intptr_t fd, bool enabled) { | 499 bool BaseSocket::SetNoDelay(intptr_t fd, bool enabled) { |
| 496 int on = enabled ? 1 : 0; | 500 int on = enabled ? 1 : 0; |
| 497 return NO_RETRY_EXPECTED(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, | 501 return NO_RETRY_EXPECTED(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, |
| 498 reinterpret_cast<char*>(&on), | 502 reinterpret_cast<char*>(&on), |
| 499 sizeof(on))) == 0; | 503 sizeof(on))) == 0; |
| 500 } | 504 } |
| 501 | 505 |
| 502 | 506 |
| 503 bool Socket::GetMulticastLoop(intptr_t fd, intptr_t protocol, bool* enabled) { | 507 bool BaseSocket::GetMulticastLoop(intptr_t fd, |
| 508 intptr_t protocol, |
| 509 bool* enabled) { |
| 504 uint8_t on; | 510 uint8_t on; |
| 505 socklen_t len = sizeof(on); | 511 socklen_t len = sizeof(on); |
| 506 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; | 512 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; |
| 507 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP | 513 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP |
| 508 : IPV6_MULTICAST_LOOP; | 514 : IPV6_MULTICAST_LOOP; |
| 509 if (NO_RETRY_EXPECTED(getsockopt(fd, level, optname, | 515 if (NO_RETRY_EXPECTED(getsockopt(fd, level, optname, |
| 510 reinterpret_cast<char*>(&on), &len)) == 0) { | 516 reinterpret_cast<char*>(&on), &len)) == 0) { |
| 511 *enabled = (on == 1); | 517 *enabled = (on == 1); |
| 512 return true; | 518 return true; |
| 513 } | 519 } |
| 514 return false; | 520 return false; |
| 515 } | 521 } |
| 516 | 522 |
| 517 | 523 |
| 518 bool Socket::SetMulticastLoop(intptr_t fd, intptr_t protocol, bool enabled) { | 524 bool BaseSocket::SetMulticastLoop(intptr_t fd, |
| 525 intptr_t protocol, |
| 526 bool enabled) { |
| 519 int on = enabled ? 1 : 0; | 527 int on = enabled ? 1 : 0; |
| 520 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; | 528 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; |
| 521 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP | 529 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP |
| 522 : IPV6_MULTICAST_LOOP; | 530 : IPV6_MULTICAST_LOOP; |
| 523 return NO_RETRY_EXPECTED(setsockopt( | 531 return NO_RETRY_EXPECTED(setsockopt( |
| 524 fd, level, optname, reinterpret_cast<char*>(&on), sizeof(on))) == | 532 fd, level, optname, reinterpret_cast<char*>(&on), sizeof(on))) == |
| 525 0; | 533 0; |
| 526 } | 534 } |
| 527 | 535 |
| 528 | 536 |
| 529 bool Socket::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) { | 537 bool BaseSocket::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) { |
| 530 uint8_t v; | 538 uint8_t v; |
| 531 socklen_t len = sizeof(v); | 539 socklen_t len = sizeof(v); |
| 532 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; | 540 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; |
| 533 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL | 541 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL |
| 534 : IPV6_MULTICAST_HOPS; | 542 : IPV6_MULTICAST_HOPS; |
| 535 if (NO_RETRY_EXPECTED(getsockopt(fd, level, optname, | 543 if (NO_RETRY_EXPECTED(getsockopt(fd, level, optname, |
| 536 reinterpret_cast<char*>(&v), &len)) == 0) { | 544 reinterpret_cast<char*>(&v), &len)) == 0) { |
| 537 *value = v; | 545 *value = v; |
| 538 return true; | 546 return true; |
| 539 } | 547 } |
| 540 return false; | 548 return false; |
| 541 } | 549 } |
| 542 | 550 |
| 543 | 551 |
| 544 bool Socket::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) { | 552 bool BaseSocket::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) { |
| 545 int v = value; | 553 int v = value; |
| 546 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; | 554 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; |
| 547 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL | 555 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL |
| 548 : IPV6_MULTICAST_HOPS; | 556 : IPV6_MULTICAST_HOPS; |
| 549 return NO_RETRY_EXPECTED(setsockopt( | 557 return NO_RETRY_EXPECTED(setsockopt( |
| 550 fd, level, optname, reinterpret_cast<char*>(&v), sizeof(v))) == 0; | 558 fd, level, optname, reinterpret_cast<char*>(&v), sizeof(v))) == 0; |
| 551 } | 559 } |
| 552 | 560 |
| 553 | 561 |
| 554 bool Socket::GetBroadcast(intptr_t fd, bool* enabled) { | 562 bool BaseSocket::GetBroadcast(intptr_t fd, bool* enabled) { |
| 555 int on; | 563 int on; |
| 556 socklen_t len = sizeof(on); | 564 socklen_t len = sizeof(on); |
| 557 int err = NO_RETRY_EXPECTED(getsockopt(fd, SOL_SOCKET, SO_BROADCAST, | 565 int err = NO_RETRY_EXPECTED(getsockopt(fd, SOL_SOCKET, SO_BROADCAST, |
| 558 reinterpret_cast<char*>(&on), &len)); | 566 reinterpret_cast<char*>(&on), &len)); |
| 559 if (err == 0) { | 567 if (err == 0) { |
| 560 *enabled = (on == 1); | 568 *enabled = (on == 1); |
| 561 } | 569 } |
| 562 return (err == 0); | 570 return (err == 0); |
| 563 } | 571 } |
| 564 | 572 |
| 565 | 573 |
| 566 bool Socket::SetBroadcast(intptr_t fd, bool enabled) { | 574 bool BaseSocket::SetBroadcast(intptr_t fd, bool enabled) { |
| 567 int on = enabled ? 1 : 0; | 575 int on = enabled ? 1 : 0; |
| 568 return NO_RETRY_EXPECTED(setsockopt(fd, SOL_SOCKET, SO_BROADCAST, | 576 return NO_RETRY_EXPECTED(setsockopt(fd, SOL_SOCKET, SO_BROADCAST, |
| 569 reinterpret_cast<char*>(&on), | 577 reinterpret_cast<char*>(&on), |
| 570 sizeof(on))) == 0; | 578 sizeof(on))) == 0; |
| 571 } | 579 } |
| 572 | 580 |
| 573 | 581 |
| 574 bool Socket::JoinMulticast(intptr_t fd, | 582 bool BaseSocket::JoinMulticast(intptr_t fd, |
| 575 const RawAddr& addr, | 583 const RawAddr& addr, |
| 576 const RawAddr&, | 584 const RawAddr&, |
| 577 int interfaceIndex) { | 585 int interfaceIndex) { |
| 578 int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; | 586 int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; |
| 579 struct group_req mreq; | 587 struct group_req mreq; |
| 580 mreq.gr_interface = interfaceIndex; | 588 mreq.gr_interface = interfaceIndex; |
| 581 memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr)); | 589 memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr)); |
| 582 return NO_RETRY_EXPECTED( | 590 return NO_RETRY_EXPECTED( |
| 583 setsockopt(fd, proto, MCAST_JOIN_GROUP, &mreq, sizeof(mreq))) == 0; | 591 setsockopt(fd, proto, MCAST_JOIN_GROUP, &mreq, sizeof(mreq))) == 0; |
| 584 } | 592 } |
| 585 | 593 |
| 586 | 594 |
| 587 bool Socket::LeaveMulticast(intptr_t fd, | 595 bool BaseSocket::LeaveMulticast(intptr_t fd, |
| 588 const RawAddr& addr, | 596 const RawAddr& addr, |
| 589 const RawAddr&, | 597 const RawAddr&, |
| 590 int interfaceIndex) { | 598 int interfaceIndex) { |
| 591 int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; | 599 int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; |
| 592 struct group_req mreq; | 600 struct group_req mreq; |
| 593 mreq.gr_interface = interfaceIndex; | 601 mreq.gr_interface = interfaceIndex; |
| 594 memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr)); | 602 memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr)); |
| 595 return NO_RETRY_EXPECTED(setsockopt(fd, proto, MCAST_LEAVE_GROUP, &mreq, | 603 return NO_RETRY_EXPECTED(setsockopt(fd, proto, MCAST_LEAVE_GROUP, &mreq, |
| 596 sizeof(mreq))) == 0; | 604 sizeof(mreq))) == 0; |
| 597 } | 605 } |
| 598 | 606 |
| 599 } // namespace bin | 607 } // namespace bin |
| 600 } // namespace dart | 608 } // namespace dart |
| 601 | 609 |
| 602 #endif // defined(TARGET_OS_LINUX) | 610 #endif // defined(TARGET_OS_LINUX) |
| 603 | 611 |
| 604 #endif // !defined(DART_IO_DISABLED) | 612 #endif // !defined(DART_IO_DISABLED) |
| OLD | NEW |