| 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(HOST_OS_LINUX) | 8 #if defined(HOST_OS_LINUX) |
| 9 | 9 |
| 10 #include "bin/socket_base.h" | 10 #include "bin/socket_base.h" |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 SocketAddress::SocketAddress(struct sockaddr* sa) { | 31 SocketAddress::SocketAddress(struct sockaddr* sa) { |
| 32 ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN); | 32 ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN); |
| 33 if (!SocketBase::FormatNumericAddress(*reinterpret_cast<RawAddr*>(sa), | 33 if (!SocketBase::FormatNumericAddress(*reinterpret_cast<RawAddr*>(sa), |
| 34 as_string_, INET6_ADDRSTRLEN)) { | 34 as_string_, 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 | |
| 42 bool SocketBase::Initialize() { | 41 bool SocketBase::Initialize() { |
| 43 // Nothing to do on Linux. | 42 // Nothing to do on Linux. |
| 44 return true; | 43 return true; |
| 45 } | 44 } |
| 46 | 45 |
| 47 | |
| 48 bool SocketBase::FormatNumericAddress(const RawAddr& addr, | 46 bool SocketBase::FormatNumericAddress(const RawAddr& addr, |
| 49 char* address, | 47 char* address, |
| 50 int len) { | 48 int len) { |
| 51 socklen_t salen = SocketAddress::GetAddrLength(addr); | 49 socklen_t salen = SocketAddress::GetAddrLength(addr); |
| 52 return (NO_RETRY_EXPECTED(getnameinfo(&addr.addr, salen, address, len, NULL, | 50 return (NO_RETRY_EXPECTED(getnameinfo(&addr.addr, salen, address, len, NULL, |
| 53 0, NI_NUMERICHOST) == 0)); | 51 0, NI_NUMERICHOST) == 0)); |
| 54 } | 52 } |
| 55 | 53 |
| 56 | |
| 57 bool SocketBase::IsBindError(intptr_t error_number) { | 54 bool SocketBase::IsBindError(intptr_t error_number) { |
| 58 return error_number == EADDRINUSE || error_number == EADDRNOTAVAIL || | 55 return error_number == EADDRINUSE || error_number == EADDRNOTAVAIL || |
| 59 error_number == EINVAL; | 56 error_number == EINVAL; |
| 60 } | 57 } |
| 61 | 58 |
| 62 | |
| 63 intptr_t SocketBase::Available(intptr_t fd) { | 59 intptr_t SocketBase::Available(intptr_t fd) { |
| 64 return FDUtils::AvailableBytes(fd); | 60 return FDUtils::AvailableBytes(fd); |
| 65 } | 61 } |
| 66 | 62 |
| 67 | |
| 68 intptr_t SocketBase::Read(intptr_t fd, | 63 intptr_t SocketBase::Read(intptr_t fd, |
| 69 void* buffer, | 64 void* buffer, |
| 70 intptr_t num_bytes, | 65 intptr_t num_bytes, |
| 71 SocketOpKind sync) { | 66 SocketOpKind sync) { |
| 72 ASSERT(fd >= 0); | 67 ASSERT(fd >= 0); |
| 73 ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes)); | 68 ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes)); |
| 74 ASSERT(EAGAIN == EWOULDBLOCK); | 69 ASSERT(EAGAIN == EWOULDBLOCK); |
| 75 if ((sync == kAsync) && (read_bytes == -1) && (errno == EWOULDBLOCK)) { | 70 if ((sync == kAsync) && (read_bytes == -1) && (errno == EWOULDBLOCK)) { |
| 76 // If the read would block we need to retry and therefore return 0 | 71 // If the read would block we need to retry and therefore return 0 |
| 77 // as the number of bytes written. | 72 // as the number of bytes written. |
| 78 read_bytes = 0; | 73 read_bytes = 0; |
| 79 } | 74 } |
| 80 return read_bytes; | 75 return read_bytes; |
| 81 } | 76 } |
| 82 | 77 |
| 83 | |
| 84 intptr_t SocketBase::RecvFrom(intptr_t fd, | 78 intptr_t SocketBase::RecvFrom(intptr_t fd, |
| 85 void* buffer, | 79 void* buffer, |
| 86 intptr_t num_bytes, | 80 intptr_t num_bytes, |
| 87 RawAddr* addr, | 81 RawAddr* addr, |
| 88 SocketOpKind sync) { | 82 SocketOpKind sync) { |
| 89 ASSERT(fd >= 0); | 83 ASSERT(fd >= 0); |
| 90 socklen_t addr_len = sizeof(addr->ss); | 84 socklen_t addr_len = sizeof(addr->ss); |
| 91 ssize_t read_bytes = TEMP_FAILURE_RETRY( | 85 ssize_t read_bytes = TEMP_FAILURE_RETRY( |
| 92 recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len)); | 86 recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len)); |
| 93 if ((sync == kAsync) && (read_bytes == -1) && (errno == EWOULDBLOCK)) { | 87 if ((sync == kAsync) && (read_bytes == -1) && (errno == EWOULDBLOCK)) { |
| 94 // If the read would block we need to retry and therefore return 0 | 88 // If the read would block we need to retry and therefore return 0 |
| 95 // as the number of bytes written. | 89 // as the number of bytes written. |
| 96 read_bytes = 0; | 90 read_bytes = 0; |
| 97 } | 91 } |
| 98 return read_bytes; | 92 return read_bytes; |
| 99 } | 93 } |
| 100 | 94 |
| 101 | |
| 102 intptr_t SocketBase::Write(intptr_t fd, | 95 intptr_t SocketBase::Write(intptr_t fd, |
| 103 const void* buffer, | 96 const void* buffer, |
| 104 intptr_t num_bytes, | 97 intptr_t num_bytes, |
| 105 SocketOpKind sync) { | 98 SocketOpKind sync) { |
| 106 ASSERT(fd >= 0); | 99 ASSERT(fd >= 0); |
| 107 ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes)); | 100 ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes)); |
| 108 ASSERT(EAGAIN == EWOULDBLOCK); | 101 ASSERT(EAGAIN == EWOULDBLOCK); |
| 109 if ((sync == kAsync) && (written_bytes == -1) && (errno == EWOULDBLOCK)) { | 102 if ((sync == kAsync) && (written_bytes == -1) && (errno == EWOULDBLOCK)) { |
| 110 // If the would block we need to retry and therefore return 0 as | 103 // If the would block we need to retry and therefore return 0 as |
| 111 // the number of bytes written. | 104 // the number of bytes written. |
| 112 written_bytes = 0; | 105 written_bytes = 0; |
| 113 } | 106 } |
| 114 return written_bytes; | 107 return written_bytes; |
| 115 } | 108 } |
| 116 | 109 |
| 117 | |
| 118 intptr_t SocketBase::SendTo(intptr_t fd, | 110 intptr_t SocketBase::SendTo(intptr_t fd, |
| 119 const void* buffer, | 111 const void* buffer, |
| 120 intptr_t num_bytes, | 112 intptr_t num_bytes, |
| 121 const RawAddr& addr, | 113 const RawAddr& addr, |
| 122 SocketOpKind sync) { | 114 SocketOpKind sync) { |
| 123 ASSERT(fd >= 0); | 115 ASSERT(fd >= 0); |
| 124 ssize_t written_bytes = | 116 ssize_t written_bytes = |
| 125 TEMP_FAILURE_RETRY(sendto(fd, buffer, num_bytes, 0, &addr.addr, | 117 TEMP_FAILURE_RETRY(sendto(fd, buffer, num_bytes, 0, &addr.addr, |
| 126 SocketAddress::GetAddrLength(addr))); | 118 SocketAddress::GetAddrLength(addr))); |
| 127 ASSERT(EAGAIN == EWOULDBLOCK); | 119 ASSERT(EAGAIN == EWOULDBLOCK); |
| 128 if ((sync == kAsync) && (written_bytes == -1) && (errno == EWOULDBLOCK)) { | 120 if ((sync == kAsync) && (written_bytes == -1) && (errno == EWOULDBLOCK)) { |
| 129 // If the would block we need to retry and therefore return 0 as | 121 // If the would block we need to retry and therefore return 0 as |
| 130 // the number of bytes written. | 122 // the number of bytes written. |
| 131 written_bytes = 0; | 123 written_bytes = 0; |
| 132 } | 124 } |
| 133 return written_bytes; | 125 return written_bytes; |
| 134 } | 126 } |
| 135 | 127 |
| 136 | |
| 137 intptr_t SocketBase::GetPort(intptr_t fd) { | 128 intptr_t SocketBase::GetPort(intptr_t fd) { |
| 138 ASSERT(fd >= 0); | 129 ASSERT(fd >= 0); |
| 139 RawAddr raw; | 130 RawAddr raw; |
| 140 socklen_t size = sizeof(raw); | 131 socklen_t size = sizeof(raw); |
| 141 if (NO_RETRY_EXPECTED(getsockname(fd, &raw.addr, &size))) { | 132 if (NO_RETRY_EXPECTED(getsockname(fd, &raw.addr, &size))) { |
| 142 return 0; | 133 return 0; |
| 143 } | 134 } |
| 144 return SocketAddress::GetAddrPort(raw); | 135 return SocketAddress::GetAddrPort(raw); |
| 145 } | 136 } |
| 146 | 137 |
| 147 | |
| 148 SocketAddress* SocketBase::GetRemotePeer(intptr_t fd, intptr_t* port) { | 138 SocketAddress* SocketBase::GetRemotePeer(intptr_t fd, intptr_t* port) { |
| 149 ASSERT(fd >= 0); | 139 ASSERT(fd >= 0); |
| 150 RawAddr raw; | 140 RawAddr raw; |
| 151 socklen_t size = sizeof(raw); | 141 socklen_t size = sizeof(raw); |
| 152 if (NO_RETRY_EXPECTED(getpeername(fd, &raw.addr, &size))) { | 142 if (NO_RETRY_EXPECTED(getpeername(fd, &raw.addr, &size))) { |
| 153 return NULL; | 143 return NULL; |
| 154 } | 144 } |
| 155 *port = SocketAddress::GetAddrPort(raw); | 145 *port = SocketAddress::GetAddrPort(raw); |
| 156 return new SocketAddress(&raw.addr); | 146 return new SocketAddress(&raw.addr); |
| 157 } | 147 } |
| 158 | 148 |
| 159 | |
| 160 void SocketBase::GetError(intptr_t fd, OSError* os_error) { | 149 void SocketBase::GetError(intptr_t fd, OSError* os_error) { |
| 161 int len = sizeof(errno); | 150 int len = sizeof(errno); |
| 162 int err = 0; | 151 int err = 0; |
| 163 VOID_NO_RETRY_EXPECTED(getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, | 152 VOID_NO_RETRY_EXPECTED(getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, |
| 164 reinterpret_cast<socklen_t*>(&len))); | 153 reinterpret_cast<socklen_t*>(&len))); |
| 165 errno = err; | 154 errno = err; |
| 166 os_error->SetCodeAndMessage(OSError::kSystem, errno); | 155 os_error->SetCodeAndMessage(OSError::kSystem, errno); |
| 167 } | 156 } |
| 168 | 157 |
| 169 | |
| 170 int SocketBase::GetType(intptr_t fd) { | 158 int SocketBase::GetType(intptr_t fd) { |
| 171 struct stat64 buf; | 159 struct stat64 buf; |
| 172 int result = TEMP_FAILURE_RETRY(fstat64(fd, &buf)); | 160 int result = TEMP_FAILURE_RETRY(fstat64(fd, &buf)); |
| 173 if (result == -1) { | 161 if (result == -1) { |
| 174 return -1; | 162 return -1; |
| 175 } | 163 } |
| 176 if (S_ISCHR(buf.st_mode)) { | 164 if (S_ISCHR(buf.st_mode)) { |
| 177 return File::kTerminal; | 165 return File::kTerminal; |
| 178 } | 166 } |
| 179 if (S_ISFIFO(buf.st_mode)) { | 167 if (S_ISFIFO(buf.st_mode)) { |
| 180 return File::kPipe; | 168 return File::kPipe; |
| 181 } | 169 } |
| 182 if (S_ISREG(buf.st_mode)) { | 170 if (S_ISREG(buf.st_mode)) { |
| 183 return File::kFile; | 171 return File::kFile; |
| 184 } | 172 } |
| 185 return File::kOther; | 173 return File::kOther; |
| 186 } | 174 } |
| 187 | 175 |
| 188 | |
| 189 intptr_t SocketBase::GetStdioHandle(intptr_t num) { | 176 intptr_t SocketBase::GetStdioHandle(intptr_t num) { |
| 190 return num; | 177 return num; |
| 191 } | 178 } |
| 192 | 179 |
| 193 | |
| 194 AddressList<SocketAddress>* SocketBase::LookupAddress(const char* host, | 180 AddressList<SocketAddress>* SocketBase::LookupAddress(const char* host, |
| 195 int type, | 181 int type, |
| 196 OSError** os_error) { | 182 OSError** os_error) { |
| 197 // Perform a name lookup for a host name. | 183 // Perform a name lookup for a host name. |
| 198 struct addrinfo hints; | 184 struct addrinfo hints; |
| 199 memset(&hints, 0, sizeof(hints)); | 185 memset(&hints, 0, sizeof(hints)); |
| 200 hints.ai_family = SocketAddress::FromType(type); | 186 hints.ai_family = SocketAddress::FromType(type); |
| 201 hints.ai_socktype = SOCK_STREAM; | 187 hints.ai_socktype = SOCK_STREAM; |
| 202 hints.ai_flags = AI_ADDRCONFIG; | 188 hints.ai_flags = AI_ADDRCONFIG; |
| 203 hints.ai_protocol = IPPROTO_TCP; | 189 hints.ai_protocol = IPPROTO_TCP; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 226 for (struct addrinfo* c = info; c != NULL; c = c->ai_next) { | 212 for (struct addrinfo* c = info; c != NULL; c = c->ai_next) { |
| 227 if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) { | 213 if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) { |
| 228 addresses->SetAt(i, new SocketAddress(c->ai_addr)); | 214 addresses->SetAt(i, new SocketAddress(c->ai_addr)); |
| 229 i++; | 215 i++; |
| 230 } | 216 } |
| 231 } | 217 } |
| 232 freeaddrinfo(info); | 218 freeaddrinfo(info); |
| 233 return addresses; | 219 return addresses; |
| 234 } | 220 } |
| 235 | 221 |
| 236 | |
| 237 bool SocketBase::ReverseLookup(const RawAddr& addr, | 222 bool SocketBase::ReverseLookup(const RawAddr& addr, |
| 238 char* host, | 223 char* host, |
| 239 intptr_t host_len, | 224 intptr_t host_len, |
| 240 OSError** os_error) { | 225 OSError** os_error) { |
| 241 ASSERT(host_len >= NI_MAXHOST); | 226 ASSERT(host_len >= NI_MAXHOST); |
| 242 int status = NO_RETRY_EXPECTED( | 227 int status = NO_RETRY_EXPECTED( |
| 243 getnameinfo(&addr.addr, SocketAddress::GetAddrLength(addr), host, | 228 getnameinfo(&addr.addr, SocketAddress::GetAddrLength(addr), host, |
| 244 host_len, NULL, 0, NI_NAMEREQD)); | 229 host_len, NULL, 0, NI_NAMEREQD)); |
| 245 if (status != 0) { | 230 if (status != 0) { |
| 246 ASSERT(*os_error == NULL); | 231 ASSERT(*os_error == NULL); |
| 247 *os_error = | 232 *os_error = |
| 248 new OSError(status, gai_strerror(status), OSError::kGetAddressInfo); | 233 new OSError(status, gai_strerror(status), OSError::kGetAddressInfo); |
| 249 return false; | 234 return false; |
| 250 } | 235 } |
| 251 return true; | 236 return true; |
| 252 } | 237 } |
| 253 | 238 |
| 254 | |
| 255 bool SocketBase::ParseAddress(int type, const char* address, RawAddr* addr) { | 239 bool SocketBase::ParseAddress(int type, const char* address, RawAddr* addr) { |
| 256 int result; | 240 int result; |
| 257 if (type == SocketAddress::TYPE_IPV4) { | 241 if (type == SocketAddress::TYPE_IPV4) { |
| 258 result = NO_RETRY_EXPECTED(inet_pton(AF_INET, address, &addr->in.sin_addr)); | 242 result = NO_RETRY_EXPECTED(inet_pton(AF_INET, address, &addr->in.sin_addr)); |
| 259 } else { | 243 } else { |
| 260 ASSERT(type == SocketAddress::TYPE_IPV6); | 244 ASSERT(type == SocketAddress::TYPE_IPV6); |
| 261 result = | 245 result = |
| 262 NO_RETRY_EXPECTED(inet_pton(AF_INET6, address, &addr->in6.sin6_addr)); | 246 NO_RETRY_EXPECTED(inet_pton(AF_INET6, address, &addr->in6.sin6_addr)); |
| 263 } | 247 } |
| 264 return (result == 1); | 248 return (result == 1); |
| 265 } | 249 } |
| 266 | 250 |
| 267 | |
| 268 static bool ShouldIncludeIfaAddrs(struct ifaddrs* ifa, int lookup_family) { | 251 static bool ShouldIncludeIfaAddrs(struct ifaddrs* ifa, int lookup_family) { |
| 269 if (ifa->ifa_addr == NULL) { | 252 if (ifa->ifa_addr == NULL) { |
| 270 // OpenVPN's virtual device tun0. | 253 // OpenVPN's virtual device tun0. |
| 271 return false; | 254 return false; |
| 272 } | 255 } |
| 273 int family = ifa->ifa_addr->sa_family; | 256 int family = ifa->ifa_addr->sa_family; |
| 274 return ((lookup_family == family) || | 257 return ((lookup_family == family) || |
| 275 (((lookup_family == AF_UNSPEC) && | 258 (((lookup_family == AF_UNSPEC) && |
| 276 ((family == AF_INET) || (family == AF_INET6))))); | 259 ((family == AF_INET) || (family == AF_INET6))))); |
| 277 } | 260 } |
| 278 | 261 |
| 279 | |
| 280 bool SocketBase::ListInterfacesSupported() { | 262 bool SocketBase::ListInterfacesSupported() { |
| 281 return true; | 263 return true; |
| 282 } | 264 } |
| 283 | 265 |
| 284 | |
| 285 AddressList<InterfaceSocketAddress>* SocketBase::ListInterfaces( | 266 AddressList<InterfaceSocketAddress>* SocketBase::ListInterfaces( |
| 286 int type, | 267 int type, |
| 287 OSError** os_error) { | 268 OSError** os_error) { |
| 288 struct ifaddrs* ifaddr; | 269 struct ifaddrs* ifaddr; |
| 289 | 270 |
| 290 int status = NO_RETRY_EXPECTED(getifaddrs(&ifaddr)); | 271 int status = NO_RETRY_EXPECTED(getifaddrs(&ifaddr)); |
| 291 if (status != 0) { | 272 if (status != 0) { |
| 292 ASSERT(*os_error == NULL); | 273 ASSERT(*os_error == NULL); |
| 293 *os_error = | 274 *os_error = |
| 294 new OSError(status, gai_strerror(status), OSError::kGetAddressInfo); | 275 new OSError(status, gai_strerror(status), OSError::kGetAddressInfo); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 313 addresses->SetAt( | 294 addresses->SetAt( |
| 314 i, new InterfaceSocketAddress(ifa->ifa_addr, ifa_name, | 295 i, new InterfaceSocketAddress(ifa->ifa_addr, ifa_name, |
| 315 if_nametoindex(ifa->ifa_name))); | 296 if_nametoindex(ifa->ifa_name))); |
| 316 i++; | 297 i++; |
| 317 } | 298 } |
| 318 } | 299 } |
| 319 freeifaddrs(ifaddr); | 300 freeifaddrs(ifaddr); |
| 320 return addresses; | 301 return addresses; |
| 321 } | 302 } |
| 322 | 303 |
| 323 | |
| 324 void SocketBase::Close(intptr_t fd) { | 304 void SocketBase::Close(intptr_t fd) { |
| 325 ASSERT(fd >= 0); | 305 ASSERT(fd >= 0); |
| 326 VOID_TEMP_FAILURE_RETRY(close(fd)); | 306 VOID_TEMP_FAILURE_RETRY(close(fd)); |
| 327 } | 307 } |
| 328 | 308 |
| 329 | |
| 330 bool SocketBase::GetNoDelay(intptr_t fd, bool* enabled) { | 309 bool SocketBase::GetNoDelay(intptr_t fd, bool* enabled) { |
| 331 int on; | 310 int on; |
| 332 socklen_t len = sizeof(on); | 311 socklen_t len = sizeof(on); |
| 333 int err = NO_RETRY_EXPECTED(getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, | 312 int err = NO_RETRY_EXPECTED(getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, |
| 334 reinterpret_cast<void*>(&on), &len)); | 313 reinterpret_cast<void*>(&on), &len)); |
| 335 if (err == 0) { | 314 if (err == 0) { |
| 336 *enabled = (on == 1); | 315 *enabled = (on == 1); |
| 337 } | 316 } |
| 338 return (err == 0); | 317 return (err == 0); |
| 339 } | 318 } |
| 340 | 319 |
| 341 | |
| 342 bool SocketBase::SetNoDelay(intptr_t fd, bool enabled) { | 320 bool SocketBase::SetNoDelay(intptr_t fd, bool enabled) { |
| 343 int on = enabled ? 1 : 0; | 321 int on = enabled ? 1 : 0; |
| 344 return NO_RETRY_EXPECTED(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, | 322 return NO_RETRY_EXPECTED(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, |
| 345 reinterpret_cast<char*>(&on), | 323 reinterpret_cast<char*>(&on), |
| 346 sizeof(on))) == 0; | 324 sizeof(on))) == 0; |
| 347 } | 325 } |
| 348 | 326 |
| 349 | |
| 350 bool SocketBase::GetMulticastLoop(intptr_t fd, | 327 bool SocketBase::GetMulticastLoop(intptr_t fd, |
| 351 intptr_t protocol, | 328 intptr_t protocol, |
| 352 bool* enabled) { | 329 bool* enabled) { |
| 353 uint8_t on; | 330 uint8_t on; |
| 354 socklen_t len = sizeof(on); | 331 socklen_t len = sizeof(on); |
| 355 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; | 332 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; |
| 356 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP | 333 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP |
| 357 : IPV6_MULTICAST_LOOP; | 334 : IPV6_MULTICAST_LOOP; |
| 358 if (NO_RETRY_EXPECTED(getsockopt(fd, level, optname, | 335 if (NO_RETRY_EXPECTED(getsockopt(fd, level, optname, |
| 359 reinterpret_cast<char*>(&on), &len)) == 0) { | 336 reinterpret_cast<char*>(&on), &len)) == 0) { |
| 360 *enabled = (on == 1); | 337 *enabled = (on == 1); |
| 361 return true; | 338 return true; |
| 362 } | 339 } |
| 363 return false; | 340 return false; |
| 364 } | 341 } |
| 365 | 342 |
| 366 | |
| 367 bool SocketBase::SetMulticastLoop(intptr_t fd, | 343 bool SocketBase::SetMulticastLoop(intptr_t fd, |
| 368 intptr_t protocol, | 344 intptr_t protocol, |
| 369 bool enabled) { | 345 bool enabled) { |
| 370 int on = enabled ? 1 : 0; | 346 int on = enabled ? 1 : 0; |
| 371 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; | 347 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; |
| 372 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP | 348 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP |
| 373 : IPV6_MULTICAST_LOOP; | 349 : IPV6_MULTICAST_LOOP; |
| 374 return NO_RETRY_EXPECTED(setsockopt( | 350 return NO_RETRY_EXPECTED(setsockopt( |
| 375 fd, level, optname, reinterpret_cast<char*>(&on), sizeof(on))) == | 351 fd, level, optname, reinterpret_cast<char*>(&on), sizeof(on))) == |
| 376 0; | 352 0; |
| 377 } | 353 } |
| 378 | 354 |
| 379 | |
| 380 bool SocketBase::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) { | 355 bool SocketBase::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) { |
| 381 uint8_t v; | 356 uint8_t v; |
| 382 socklen_t len = sizeof(v); | 357 socklen_t len = sizeof(v); |
| 383 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; | 358 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; |
| 384 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL | 359 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL |
| 385 : IPV6_MULTICAST_HOPS; | 360 : IPV6_MULTICAST_HOPS; |
| 386 if (NO_RETRY_EXPECTED(getsockopt(fd, level, optname, | 361 if (NO_RETRY_EXPECTED(getsockopt(fd, level, optname, |
| 387 reinterpret_cast<char*>(&v), &len)) == 0) { | 362 reinterpret_cast<char*>(&v), &len)) == 0) { |
| 388 *value = v; | 363 *value = v; |
| 389 return true; | 364 return true; |
| 390 } | 365 } |
| 391 return false; | 366 return false; |
| 392 } | 367 } |
| 393 | 368 |
| 394 | |
| 395 bool SocketBase::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) { | 369 bool SocketBase::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) { |
| 396 int v = value; | 370 int v = value; |
| 397 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; | 371 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; |
| 398 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL | 372 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL |
| 399 : IPV6_MULTICAST_HOPS; | 373 : IPV6_MULTICAST_HOPS; |
| 400 return NO_RETRY_EXPECTED(setsockopt( | 374 return NO_RETRY_EXPECTED(setsockopt( |
| 401 fd, level, optname, reinterpret_cast<char*>(&v), sizeof(v))) == 0; | 375 fd, level, optname, reinterpret_cast<char*>(&v), sizeof(v))) == 0; |
| 402 } | 376 } |
| 403 | 377 |
| 404 | |
| 405 bool SocketBase::GetBroadcast(intptr_t fd, bool* enabled) { | 378 bool SocketBase::GetBroadcast(intptr_t fd, bool* enabled) { |
| 406 int on; | 379 int on; |
| 407 socklen_t len = sizeof(on); | 380 socklen_t len = sizeof(on); |
| 408 int err = NO_RETRY_EXPECTED(getsockopt(fd, SOL_SOCKET, SO_BROADCAST, | 381 int err = NO_RETRY_EXPECTED(getsockopt(fd, SOL_SOCKET, SO_BROADCAST, |
| 409 reinterpret_cast<char*>(&on), &len)); | 382 reinterpret_cast<char*>(&on), &len)); |
| 410 if (err == 0) { | 383 if (err == 0) { |
| 411 *enabled = (on == 1); | 384 *enabled = (on == 1); |
| 412 } | 385 } |
| 413 return (err == 0); | 386 return (err == 0); |
| 414 } | 387 } |
| 415 | 388 |
| 416 | |
| 417 bool SocketBase::SetBroadcast(intptr_t fd, bool enabled) { | 389 bool SocketBase::SetBroadcast(intptr_t fd, bool enabled) { |
| 418 int on = enabled ? 1 : 0; | 390 int on = enabled ? 1 : 0; |
| 419 return NO_RETRY_EXPECTED(setsockopt(fd, SOL_SOCKET, SO_BROADCAST, | 391 return NO_RETRY_EXPECTED(setsockopt(fd, SOL_SOCKET, SO_BROADCAST, |
| 420 reinterpret_cast<char*>(&on), | 392 reinterpret_cast<char*>(&on), |
| 421 sizeof(on))) == 0; | 393 sizeof(on))) == 0; |
| 422 } | 394 } |
| 423 | 395 |
| 424 | |
| 425 bool SocketBase::JoinMulticast(intptr_t fd, | 396 bool SocketBase::JoinMulticast(intptr_t fd, |
| 426 const RawAddr& addr, | 397 const RawAddr& addr, |
| 427 const RawAddr&, | 398 const RawAddr&, |
| 428 int interfaceIndex) { | 399 int interfaceIndex) { |
| 429 int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; | 400 int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; |
| 430 struct group_req mreq; | 401 struct group_req mreq; |
| 431 mreq.gr_interface = interfaceIndex; | 402 mreq.gr_interface = interfaceIndex; |
| 432 memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr)); | 403 memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr)); |
| 433 return NO_RETRY_EXPECTED( | 404 return NO_RETRY_EXPECTED( |
| 434 setsockopt(fd, proto, MCAST_JOIN_GROUP, &mreq, sizeof(mreq))) == 0; | 405 setsockopt(fd, proto, MCAST_JOIN_GROUP, &mreq, sizeof(mreq))) == 0; |
| 435 } | 406 } |
| 436 | 407 |
| 437 | |
| 438 bool SocketBase::LeaveMulticast(intptr_t fd, | 408 bool SocketBase::LeaveMulticast(intptr_t fd, |
| 439 const RawAddr& addr, | 409 const RawAddr& addr, |
| 440 const RawAddr&, | 410 const RawAddr&, |
| 441 int interfaceIndex) { | 411 int interfaceIndex) { |
| 442 int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; | 412 int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; |
| 443 struct group_req mreq; | 413 struct group_req mreq; |
| 444 mreq.gr_interface = interfaceIndex; | 414 mreq.gr_interface = interfaceIndex; |
| 445 memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr)); | 415 memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr)); |
| 446 return NO_RETRY_EXPECTED(setsockopt(fd, proto, MCAST_LEAVE_GROUP, &mreq, | 416 return NO_RETRY_EXPECTED(setsockopt(fd, proto, MCAST_LEAVE_GROUP, &mreq, |
| 447 sizeof(mreq))) == 0; | 417 sizeof(mreq))) == 0; |
| 448 } | 418 } |
| 449 | 419 |
| 450 } // namespace bin | 420 } // namespace bin |
| 451 } // namespace dart | 421 } // namespace dart |
| 452 | 422 |
| 453 #endif // defined(HOST_OS_LINUX) | 423 #endif // defined(HOST_OS_LINUX) |
| 454 | 424 |
| 455 #endif // !defined(DART_IO_DISABLED) | 425 #endif // !defined(DART_IO_DISABLED) |
| OLD | NEW |