// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. #include "platform/globals.h" #if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID) #include "bin/socket_base.h" #include // NOLINT #include // NOLINT #include // NOLINT #include // NOLINT #include // NOLINT #include // NOLINT #include // NOLINT #include // NOLINT #include // NOLINT #include "bin/fdutils.h" #include "bin/file.h" #include "bin/socket_base_linux.h" #include "bin/thread.h" #include "platform/signal_blocker.h" namespace dart { namespace bin { void SocketBase::GetError(intptr_t fd, OSError* os_error) { int len = sizeof(errno); int err = 0; VOID_NO_RETRY_EXPECTED(getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, reinterpret_cast(&len))); errno = err; os_error->SetCodeAndMessage(OSError::kSystem, errno); } int SocketBase::GetType(intptr_t fd) { struct stat64 buf; int result = TEMP_FAILURE_RETRY(fstat64(fd, &buf)); if (result == -1) { return -1; } if (S_ISCHR(buf.st_mode)) { return File::kTerminal; } if (S_ISFIFO(buf.st_mode)) { return File::kPipe; } if (S_ISREG(buf.st_mode)) { return File::kFile; } return File::kOther; } AddressList* SocketBase::LookupAddress(const char* host, int type, OSError** os_error) { // Perform a name lookup for a host name. struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = SocketAddress::FromType(type); hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_ADDRCONFIG; hints.ai_protocol = IPPROTO_TCP; struct addrinfo* info = nullptr; int status = NO_RETRY_EXPECTED(getaddrinfo(host, nullptr, &hints, &info)); if (status != 0) { // We failed, try without AI_ADDRCONFIG. This can happen when looking up // e.g. '::1', when there are no global IPv6 addresses. hints.ai_flags = 0; status = NO_RETRY_EXPECTED(getaddrinfo(host, nullptr, &hints, &info)); if (status != 0) { ASSERT(*os_error == nullptr); *os_error = new OSError(status, gai_strerror(status), OSError::kGetAddressInfo); return nullptr; } } intptr_t count = 0; for (struct addrinfo* c = info; c != nullptr; c = c->ai_next) { if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) { count++; } } intptr_t i = 0; AddressList* addresses = new AddressList(count); for (struct addrinfo* c = info; c != nullptr; c = c->ai_next) { if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) { addresses->SetAt(i, new SocketAddress(c->ai_addr)); i++; } } freeaddrinfo(info); return addresses; } bool SocketBase::SetMulticastLoop(intptr_t fd, intptr_t protocol, bool enabled) { int on = enabled ? 1 : 0; int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP : IPV6_MULTICAST_LOOP; return NO_RETRY_EXPECTED(setsockopt( fd, level, optname, reinterpret_cast(&on), sizeof(on))) == 0; } bool SocketBase::GetOption(intptr_t fd, int level, int option, char* data, unsigned int* length) { socklen_t optlen = static_cast(*length); auto result = NO_RETRY_EXPECTED(getsockopt(fd, level, option, data, &optlen)); *length = static_cast(optlen); return result == 0; } bool SocketBase::JoinMulticast(intptr_t fd, const RawAddr& addr, const RawAddr&, int interfaceIndex) { int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; struct group_req mreq; mreq.gr_interface = interfaceIndex; memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr)); return NO_RETRY_EXPECTED( setsockopt(fd, proto, MCAST_JOIN_GROUP, &mreq, sizeof(mreq))) == 0; } bool SocketBase::LeaveMulticast(intptr_t fd, const RawAddr& addr, const RawAddr&, int interfaceIndex) { int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; struct group_req mreq; mreq.gr_interface = interfaceIndex; memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr)); return NO_RETRY_EXPECTED(setsockopt(fd, proto, MCAST_LEAVE_GROUP, &mreq, sizeof(mreq))) == 0; } } // namespace bin } // namespace dart #endif // defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)