Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
static int16_t FromType(int type)
static intptr_t GetAddrLength(const RawAddr &addr, bool unnamed_unix_socket=false)
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
static int8_t data[kExtLength]
#define NO_RETRY_EXPECTED(expression)
#define VOID_NO_RETRY_EXPECTED(expression)
#define TEMP_FAILURE_RETRY(expression)