Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
socket_base.cc
Go to the documentation of this file.
1// Copyright (c) 2017, 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 "bin/socket_base.h"
6
7#include <errno.h> // NOLINT
8
9#include "bin/dartutils.h"
10#include "bin/io_buffer.h"
11#include "bin/isolate_data.h"
12#include "bin/lockers.h"
13#include "bin/thread.h"
15#include "bin/utils.h"
16
17#include "include/dart_api.h"
18
19#include "platform/globals.h"
20#include "platform/utils.h"
21
22namespace dart {
23namespace bin {
24
26 switch (addr_.ss.ss_family) {
27 case AF_INET6:
28 return TYPE_IPV6;
29 case AF_INET:
30 return TYPE_IPV4;
31 case AF_UNIX:
32 return TYPE_UNIX;
33 default:
35 return TYPE_ANY;
36 }
37}
38
40 bool unnamed_unix_socket) {
41 ASSERT((addr.ss.ss_family == AF_INET) || (addr.ss.ss_family == AF_INET6) ||
42 (addr.ss.ss_family == AF_UNIX));
43 switch (addr.ss.ss_family) {
44 case AF_INET6:
45 return sizeof(struct sockaddr_in6);
46 case AF_INET:
47 return sizeof(struct sockaddr_in);
48 case AF_UNIX: {
49 // For an abstract UNIX socket, trailing null bytes in the name are
50 // meaningful. That is, the bytes '\0/tmp/dbus-xxxx' are a different name
51 // than '\0/tmp/dbus-xxxx\0\0\0...'. The length of the address structure
52 // passed to connect() etc. tells those calls how many bytes of the name
53 // to look at. Therefore, when computing the length of the address in
54 // this case, any trailing null bytes are trimmed.
55 // TODO(dart:io): Support abstract UNIX socket addresses that have
56 // trailing null bytes on purpose.
57 // https://github.com/dart-lang/sdk/issues/46158
58 intptr_t nulls = 0;
59 if (!unnamed_unix_socket && addr.un.sun_path[0] == '\0') {
60 intptr_t i = sizeof(addr.un.sun_path) - 1;
61 while (addr.un.sun_path[i] == '\0') {
62 nulls++;
63 i--;
64 }
65 }
66 return sizeof(struct sockaddr_un) - nulls;
67 }
68 default:
70 return 0;
71 }
72}
73
75 ASSERT((addr.ss.ss_family == AF_INET) || (addr.ss.ss_family == AF_INET6));
76 return (addr.ss.ss_family == AF_INET6) ? sizeof(struct in6_addr)
77 : sizeof(struct in_addr);
78}
79
80bool SocketAddress::AreAddressesEqual(const RawAddr& a, const RawAddr& b) {
81 if (a.ss.ss_family != b.ss.ss_family) {
82 return false;
83 }
84 if (a.ss.ss_family == AF_INET) {
85 return memcmp(&a.in.sin_addr, &b.in.sin_addr, sizeof(a.in.sin_addr)) == 0;
86 } else if (a.ss.ss_family == AF_INET6) {
87 return memcmp(&a.in6.sin6_addr, &b.in6.sin6_addr,
88 sizeof(a.in6.sin6_addr)) == 0 &&
89 a.in6.sin6_scope_id == b.in6.sin6_scope_id;
90 } else if (a.ss.ss_family == AF_UNIX) {
91 // This is not used anywhere. The comparison of file path is done via
92 // File::AreIdentical().
93 int len = sizeof(a.un.sun_path);
94 for (int i = 0; i < len; i++) {
95 if (a.un.sun_path[i] != b.un.sun_path[i]) return false;
96 if (a.un.sun_path[i] == '\0') return true;
97 }
98 return true;
99 } else {
100 UNREACHABLE();
101 return false;
102 }
103}
104
106 Dart_TypedData_Type data_type;
107 uint8_t* data = nullptr;
108 intptr_t len;
110 obj, &data_type, reinterpret_cast<void**>(&data), &len);
111 if (Dart_IsError(result)) {
113 }
114 if ((data_type != Dart_TypedData_kUint8) ||
115 ((len != sizeof(in_addr)) && (len != sizeof(in6_addr)))) {
116 Dart_PropagateError(Dart_NewApiError("Unexpected type for socket address"));
117 }
118 memset(reinterpret_cast<void*>(addr), 0, sizeof(RawAddr));
119 if (len == sizeof(in_addr)) {
120 addr->in.sin_family = AF_INET;
121 memmove(reinterpret_cast<void*>(&addr->in.sin_addr), data, len);
122 } else {
123 ASSERT(len == sizeof(in6_addr));
124 addr->in6.sin6_family = AF_INET6;
125 memmove(reinterpret_cast<void*>(&addr->in6.sin6_addr), data, len);
126 }
128}
129
131 Namespace* namespc,
132 RawAddr* addr) {
133#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
134 NamespaceScope ns(namespc, path);
135 path = ns.path();
136 bool is_abstract = (path[0] == '@');
137 if (is_abstract) {
138 // The following 107 bytes after the leading null byte represents the name
139 // of unix domain socket. Without reseting, even users provide the same path
140 // for bind and connect, they actually represent two different address and
141 // connection will be rejected.
142 bzero(addr->un.sun_path, sizeof(addr->un.sun_path));
143 }
144#endif // defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
145 if (sizeof(path) > sizeof(addr->un.sun_path)) {
146 OSError os_error(-1,
147 "The length of path exceeds the limit. "
148 "Check out man 7 unix page",
150 return DartUtils::NewDartOSError(&os_error);
151 }
152 addr->un.sun_family = AF_UNIX;
153 Utils::SNPrint(addr->un.sun_path, sizeof(addr->un.sun_path), "%s", path);
154#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
155 // In case of abstract namespace, transfer the leading '@' into a null byte.
156 if (is_abstract) {
157 addr->un.sun_path[0] = '\0';
158 }
159#endif // defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
160 return Dart_Null();
161}
162
164 if (type == TYPE_ANY) {
165 return AF_UNSPEC;
166 }
167 if (type == TYPE_IPV4) {
168 return AF_INET;
169 }
170 if (type == TYPE_UNIX) {
171 return AF_UNIX;
172 }
173 ASSERT((type == TYPE_IPV6) && "Invalid type");
174 return AF_INET6;
175}
176
178 if (addr->ss.ss_family == AF_INET) {
179 addr->in.sin_port = htons(port);
180 } else if (addr->ss.ss_family == AF_INET6) {
181 addr->in6.sin6_port = htons(port);
182 } else {
183 UNREACHABLE();
184 }
185}
186
188 if (addr.ss.ss_family == AF_INET) {
189 return ntohs(addr.in.sin_port);
190 } else if (addr.ss.ss_family == AF_INET6) {
191 return ntohs(addr.in6.sin6_port);
192 } else if (addr.ss.ss_family == AF_UNIX) {
193 return 0;
194 } else {
195 UNREACHABLE();
196 return -1;
197 }
198}
199
201 int len = GetInAddrLength(addr);
203 if (Dart_IsError(result)) {
205 }
206 Dart_Handle err;
207 if (addr.addr.sa_family == AF_INET6) {
209 result, 0, reinterpret_cast<const uint8_t*>(&addr.in6.sin6_addr), len);
210 } else {
212 result, 0, reinterpret_cast<const uint8_t*>(&addr.in.sin_addr), len);
213 }
214 if (Dart_IsError(err)) {
216 }
217 return result;
218}
219
221 int in_addr_len = SocketAddress::GetInAddrLength(addr);
222 const void* in_addr;
223 if (addr.addr.sa_family == AF_INET6) {
224 in_addr = reinterpret_cast<const void*>(&addr.in6.sin6_addr);
225 } else {
226 in_addr = reinterpret_cast<const void*>(&addr.in.sin_addr);
227 }
229 new CObjectUint8Array(CObject::NewUint8Array(in_addr, in_addr_len));
230 return data;
231}
232void SocketAddress::SetAddrScope(RawAddr* addr, intptr_t scope_id) {
233 if (addr->addr.sa_family != AF_INET6) return;
234 addr->in6.sin6_scope_id = scope_id;
235}
236
238 if (addr.addr.sa_family == AF_INET6) {
239 return addr.in6.sin6_scope_id;
240 } else {
241 return 0;
242 }
243}
244
246 const char* address =
248 ASSERT(address != nullptr);
249 RawAddr raw;
250 memset(&raw, 0, sizeof(raw));
251 int type = strchr(address, ':') == nullptr ? SocketAddress::TYPE_IPV4
254 raw.addr.sa_family = AF_INET;
255 } else {
256 raw.addr.sa_family = AF_INET6;
257 }
258 bool ok = SocketBase::ParseAddress(type, address, &raw);
259 if (!ok) {
261 } else {
263 }
264}
265
268 const char* address =
270 // This must be an IPv6 address.
271 intptr_t type = 1;
272 ASSERT(address != nullptr);
273 OSError* os_error = nullptr;
274 AddressList<SocketAddress>* addresses =
275 SocketBase::LookupAddress(address, type, &os_error);
276 if (addresses != nullptr) {
277 SocketAddress* addr = addresses->GetAt(0);
280 delete addresses;
281 } else {
283 delete os_error;
284 }
285}
286
290 // INET6_ADDRSTRLEN is larger than INET_ADDRSTRLEN
291 char str[INET6_ADDRSTRLEN];
292 bool ok = SocketBase::RawAddrToString(&addr, str);
293 if (!ok) {
294 str[0] = '\0';
295 }
297}
298
300 intptr_t error_number =
302 bool is_bind_error = SocketBase::IsBindError(error_number);
303 Dart_SetBooleanReturnValue(args, is_bind_error ? true : false);
304}
305
306bool SocketBase::IsValidAddress(const char* address) {
307 ASSERT(address != nullptr);
308 RawAddr raw;
309 memset(&raw, 0, sizeof(raw));
310 int type = strchr(address, ':') == nullptr ? SocketAddress::TYPE_IPV4
313 raw.addr.sa_family = AF_INET;
314 } else {
315 raw.addr.sa_family = AF_INET6;
316 }
317 return SocketBase::ParseAddress(type, address, &raw);
318}
319
320#if !defined(DART_HOST_OS_WINDOWS)
321intptr_t SocketBase::Write(intptr_t fd,
322 const void* buffer,
323 intptr_t num_bytes,
324 SocketOpKind sync) {
325 // For non-blocking sockets we must write as many bytes as possible into
326 // the output to trigger EAGAIN otherwise we are not guaranteed to
327 // receive an event from epoll which we are using in edge-triggering
328 // (EPOLLET) mode. See man epoll for more information and guidelines.
329 ssize_t num_bytes_left = num_bytes;
330 while (num_bytes_left > 0) {
331 ssize_t written_bytes = WriteImpl(fd, buffer, num_bytes_left, sync);
332 static_assert(EAGAIN == EWOULDBLOCK);
333 if (written_bytes == -1) {
334 if ((sync == kAsync) && (errno == EWOULDBLOCK)) {
335 break;
336 }
337
338 return -1; // Error occurred.
339 }
340
341 num_bytes_left -= written_bytes;
342 buffer = static_cast<const char*>(buffer) + written_bytes;
343 }
344
345 return num_bytes - num_bytes_left;
346}
347#endif
348
349} // namespace bin
350} // namespace dart
static bool ok(int result)
#define UNREACHABLE()
Definition assert.h:248
#define FUNCTION_NAME(name)
Definition builtin.h:19
static int SNPrint(char *str, size_t size, const char *format,...) PRINTF_ATTRIBUTE(3
T * GetAt(intptr_t i) const
static Dart_CObject * NewUint8Array(const void *data, intptr_t length)
Definition dartutils.cc:951
static Dart_Handle NewDartOSError()
Definition dartutils.cc:706
static const char * GetStringValue(Dart_Handle str_obj)
Definition dartutils.cc:132
static Dart_Handle NewString(const char *str)
Definition dartutils.h:214
static intptr_t GetIntptrValue(Dart_Handle value_obj)
Definition dartutils.cc:104
const char * path() const
Definition namespace.h:83
static void SetAddrScope(RawAddr *addr, intptr_t scope_id)
static void GetSockAddr(Dart_Handle obj, RawAddr *addr)
static int16_t FromType(int type)
static intptr_t GetAddrScope(const RawAddr &addr)
static void SetAddrPort(RawAddr *addr, intptr_t port)
static CObjectUint8Array * ToCObject(const RawAddr &addr)
static bool AreAddressesEqual(const RawAddr &a, const RawAddr &b)
static intptr_t GetAddrLength(const RawAddr &addr, bool unnamed_unix_socket=false)
static Dart_Handle GetUnixDomainSockAddr(const char *path, Namespace *namespc, RawAddr *addr)
static Dart_Handle ToTypedData(const RawAddr &addr)
static intptr_t GetAddrPort(const RawAddr &addr)
static intptr_t GetInAddrLength(const RawAddr &addr)
const RawAddr & addr() const
Definition socket_base.h:68
static AddressList< SocketAddress > * LookupAddress(const char *host, int type, OSError **os_error)
static bool ParseAddress(int type, const char *address, RawAddr *addr)
static bool IsBindError(intptr_t error_number)
static bool IsValidAddress(const char *address)
static bool RawAddrToString(RawAddr *addr, char *str)
static intptr_t Write(intptr_t fd, const void *buffer, intptr_t num_bytes, SocketOpKind sync)
struct _Dart_Handle * Dart_Handle
Definition dart_api.h:258
struct _Dart_NativeArguments * Dart_NativeArguments
Definition dart_api.h:3010
Dart_TypedData_Type
Definition dart_api.h:2603
@ Dart_TypedData_kUint8
Definition dart_api.h:2606
#define ASSERT(E)
static bool b
struct MyStruct a[10]
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static const uint8_t buffer[]
GAsyncResult * result
static Dart_Handle ThrowIfError(Dart_Handle handle)
Definition dartutils.h:31
void FUNCTION_NAME() InternetAddress_RawAddrToString(Dart_NativeArguments args)
void FUNCTION_NAME() SocketBase_IsBindError(Dart_NativeArguments args)
void FUNCTION_NAME() InternetAddress_ParseScopedLinkLocalAddress(Dart_NativeArguments args)
void FUNCTION_NAME() InternetAddress_Parse(Dart_NativeArguments args)
DART_EXPORT void Dart_SetBooleanReturnValue(Dart_NativeArguments args, bool retval)
DART_EXPORT Dart_Handle Dart_NewInteger(int64_t value)
DART_EXPORT void Dart_PropagateError(Dart_Handle handle)
DART_EXPORT Dart_Handle Dart_NewTypedData(Dart_TypedData_Type type, intptr_t length)
DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args, Dart_Handle retval)
DART_EXPORT Dart_Handle Dart_TypedDataAcquireData(Dart_Handle object, Dart_TypedData_Type *type, void **data, intptr_t *len)
DART_EXPORT bool Dart_IsError(Dart_Handle handle)
DART_EXPORT Dart_Handle Dart_ListSetAsBytes(Dart_Handle list, intptr_t offset, const uint8_t *native_array, intptr_t length)
DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args, int index)
DART_EXPORT Dart_Handle Dart_TypedDataReleaseData(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_NewApiError(const char *error)
DART_EXPORT Dart_Handle Dart_Null()
static int8_t data[kExtLength]
struct sockaddr_storage ss
Definition socket_base.h:37
struct sockaddr addr
Definition socket_base.h:38
struct sockaddr_un un
Definition socket_base.h:36
struct sockaddr_in in
Definition socket_base.h:34
struct sockaddr_in6 in6
Definition socket_base.h:35