Flutter Engine
The Flutter Engine
socket_base_linux.cc
Go to the documentation of this 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
3// BSD-style license that can be found in the LICENSE file.
4
5#include "platform/globals.h"
6#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
7
8#include "bin/socket_base.h"
9
10#include <errno.h> // NOLINT
11#include <ifaddrs.h> // NOLINT
12#include <net/if.h> // NOLINT
13#include <netinet/tcp.h> // NOLINT
14#include <stdio.h> // NOLINT
15#include <stdlib.h> // NOLINT
16#include <string.h> // NOLINT
17#include <sys/stat.h> // NOLINT
18#include <unistd.h> // NOLINT
19
20#include "bin/fdutils.h"
21#include "bin/file.h"
23#include "bin/thread.h"
25
26namespace dart {
27namespace bin {
28
29void SocketBase::GetError(intptr_t fd, OSError* os_error) {
30 int len = sizeof(errno);
31 int err = 0;
32 VOID_NO_RETRY_EXPECTED(getsockopt(fd, SOL_SOCKET, SO_ERROR, &err,
33 reinterpret_cast<socklen_t*>(&len)));
34 errno = err;
35 os_error->SetCodeAndMessage(OSError::kSystem, errno);
36}
37
38int SocketBase::GetType(intptr_t fd) {
39 struct stat64 buf;
40 int result = TEMP_FAILURE_RETRY(fstat64(fd, &buf));
41 if (result == -1) {
42 return -1;
43 }
44 if (S_ISCHR(buf.st_mode)) {
45 return File::kTerminal;
46 }
47 if (S_ISFIFO(buf.st_mode)) {
48 return File::kPipe;
49 }
50 if (S_ISREG(buf.st_mode)) {
51 return File::kFile;
52 }
53 return File::kOther;
54}
55
56AddressList<SocketAddress>* SocketBase::LookupAddress(const char* host,
57 int type,
58 OSError** os_error) {
59 // Perform a name lookup for a host name.
60 struct addrinfo hints;
61 memset(&hints, 0, sizeof(hints));
62 hints.ai_family = SocketAddress::FromType(type);
63 hints.ai_socktype = SOCK_STREAM;
64 hints.ai_flags = AI_ADDRCONFIG;
65 hints.ai_protocol = IPPROTO_TCP;
66 struct addrinfo* info = nullptr;
67 int status = NO_RETRY_EXPECTED(getaddrinfo(host, nullptr, &hints, &info));
68 if (status != 0) {
69 // We failed, try without AI_ADDRCONFIG. This can happen when looking up
70 // e.g. '::1', when there are no global IPv6 addresses.
71 hints.ai_flags = 0;
72 status = NO_RETRY_EXPECTED(getaddrinfo(host, nullptr, &hints, &info));
73 if (status != 0) {
74 ASSERT(*os_error == nullptr);
75 *os_error =
76 new OSError(status, gai_strerror(status), OSError::kGetAddressInfo);
77 return nullptr;
78 }
79 }
80 intptr_t count = 0;
81 for (struct addrinfo* c = info; c != nullptr; c = c->ai_next) {
82 if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
83 count++;
84 }
85 }
86 intptr_t i = 0;
87 AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
88 for (struct addrinfo* c = info; c != nullptr; c = c->ai_next) {
89 if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
90 addresses->SetAt(i, new SocketAddress(c->ai_addr));
91 i++;
92 }
93 }
94 freeaddrinfo(info);
95 return addresses;
96}
97
98bool SocketBase::SetMulticastLoop(intptr_t fd,
99 intptr_t protocol,
100 bool enabled) {
101 int on = enabled ? 1 : 0;
102 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
103 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP
104 : IPV6_MULTICAST_LOOP;
105 return NO_RETRY_EXPECTED(setsockopt(
106 fd, level, optname, reinterpret_cast<char*>(&on), sizeof(on))) ==
107 0;
108}
109
110bool SocketBase::GetOption(intptr_t fd,
111 int level,
112 int option,
113 char* data,
114 unsigned int* length) {
115 socklen_t optlen = static_cast<socklen_t>(*length);
116 auto result = NO_RETRY_EXPECTED(getsockopt(fd, level, option, data, &optlen));
117 *length = static_cast<unsigned int>(optlen);
118 return result == 0;
119}
120
121bool SocketBase::JoinMulticast(intptr_t fd,
122 const RawAddr& addr,
123 const RawAddr&,
124 int interfaceIndex) {
125 int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
126 struct group_req mreq;
127 mreq.gr_interface = interfaceIndex;
128 memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr));
129 return NO_RETRY_EXPECTED(
130 setsockopt(fd, proto, MCAST_JOIN_GROUP, &mreq, sizeof(mreq))) == 0;
131}
132
133bool SocketBase::LeaveMulticast(intptr_t fd,
134 const RawAddr& addr,
135 const RawAddr&,
136 int interfaceIndex) {
137 int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
138 struct group_req mreq;
139 mreq.gr_interface = interfaceIndex;
140 memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr));
141 return NO_RETRY_EXPECTED(setsockopt(fd, proto, MCAST_LEAVE_GROUP, &mreq,
142 sizeof(mreq))) == 0;
143}
144
145} // namespace bin
146} // namespace dart
147
148#endif // defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
int count
Definition: FontMgrTest.cpp:50
GLenum type
static int16_t FromType(int type)
Definition: socket_base.cc:163
static intptr_t GetAddrLength(const RawAddr &addr, bool unnamed_unix_socket=false)
Definition: socket_base.cc:39
static bool LeaveMulticast(intptr_t fd, const RawAddr &addr, const RawAddr &interface, int interfaceIndex)
static int GetType(intptr_t fd)
static AddressList< SocketAddress > * LookupAddress(const char *host, int type, OSError **os_error)
static void GetError(intptr_t fd, OSError *os_error)
static bool SetMulticastLoop(intptr_t fd, intptr_t protocol, bool enabled)
static bool GetOption(intptr_t fd, int level, int option, char *data, unsigned int *length)
static bool JoinMulticast(intptr_t fd, const RawAddr &addr, const RawAddr &interface, int interfaceIndex)
#define ASSERT(E)
GAsyncResult * result
size_t length
Definition: dart_vm.cc:33
static int8_t data[kExtLength]
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service host
Definition: switches.h:74
#define NO_RETRY_EXPECTED(expression)
#define VOID_NO_RETRY_EXPECTED(expression)
#define TEMP_FAILURE_RETRY(expression)