Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
socket.h
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#ifndef RUNTIME_BIN_SOCKET_H_
6#define RUNTIME_BIN_SOCKET_H_
7
8#include "bin/builtin.h"
9#include "bin/dartutils.h"
10#include "bin/file.h"
12#include "bin/socket_base.h"
13#include "bin/thread.h"
14#include "bin/utils.h"
15#include "platform/hashmap.h"
16
17namespace dart {
18namespace bin {
19
20// TODO(bkonyi): Socket should also inherit from SocketBase once it is
21// refactored to use instance methods when possible.
22
23// We write Sockets into the native field of the _NativeSocket object
24// on the Dart side. They are allocated in SetSocketIdNativeField(), and are
25// deallocated either from the finalizer attached to _NativeSockets there, or
26// from the eventhandler, whichever drops the last reference.
27class Socket : public ReferenceCounted<Socket> {
28 public:
34
41
42 // Keep in sync with constants in _NativeSocket in socket_patch.dart.
49
50 explicit Socket(intptr_t fd);
51
52 intptr_t fd() const { return fd_; }
53
54 // Close fd and may need to decrement the count of handle by calling
55 // release().
56 void CloseFd();
57 // Set fd_ to closed. On fuchsia and win, shared socket should not
58 // release handle but only SetClosedFd().
60
61 Dart_Port isolate_port() const { return isolate_port_; }
62
63 Dart_Port port() const { return port_; }
64 void set_port(Dart_Port port) { port_ = port; }
65
66 uint8_t* udp_receive_buffer() const { return udp_receive_buffer_; }
67 void set_udp_receive_buffer(uint8_t* buffer) { udp_receive_buffer_ = buffer; }
68
69 static bool Initialize();
70
71 // Creates a socket which is bound and connected. The port to connect to is
72 // specified as the port component of the passed RawAddr structure.
73 static intptr_t CreateConnect(const RawAddr& addr);
74 static intptr_t CreateUnixDomainConnect(const RawAddr& addr);
75 // Creates a socket which is bound and connected. The port to connect to is
76 // specified as the port component of the passed RawAddr structure.
77 static intptr_t CreateBindConnect(const RawAddr& addr,
78 const RawAddr& source_addr);
79 static intptr_t CreateUnixDomainBindConnect(const RawAddr& addr,
80 const RawAddr& source_addr);
81 // Creates a datagram socket which is bound. The port to bind
82 // to is specified as the port component of the RawAddr structure.
83 static intptr_t CreateBindDatagram(const RawAddr& addr,
84 bool reuseAddress,
85 bool reusePort,
86 int ttl = 1);
87
88 static CObject* LookupRequest(const CObjectArray& request);
89 static CObject* ListInterfacesRequest(const CObjectArray& request);
90 static CObject* ReverseLookupRequest(const CObjectArray& request);
91
93
94 static void SetSocketIdNativeField(Dart_Handle handle,
95 intptr_t id,
96 SocketFinalizer finalizer);
97 static void ReuseSocketIdNativeField(Dart_Handle handle,
98 Socket* socket,
99 SocketFinalizer finalizer);
101
102 static bool short_socket_read() { return short_socket_read_; }
104 short_socket_read_ = short_socket_read;
105 }
106 static bool short_socket_write() { return short_socket_write_; }
108 short_socket_write_ = short_socket_write;
109 }
110
111 static bool IsSignalSocketFlag(intptr_t flag) {
112 return ((flag & (0x1 << kInternalSignalSocket)) != 0);
113 }
114
115 private:
116 ~Socket() {
117 ASSERT(fd_ == kClosedFd);
118 free(udp_receive_buffer_);
119 udp_receive_buffer_ = nullptr;
120 }
121
122 static constexpr int kClosedFd = -1;
123
124 static bool short_socket_read_;
125 static bool short_socket_write_;
126
127 intptr_t fd_;
128 Dart_Port isolate_port_;
129 Dart_Port port_;
130 uint8_t* udp_receive_buffer_;
131
132 friend class ReferenceCounted<Socket>;
134};
135
137 public:
138 static constexpr intptr_t kTemporaryFailure = -2;
139
140 static intptr_t Accept(intptr_t fd);
141
142 // Creates a socket which is bound and listens. The port to listen on is
143 // specified in the port component of the passed RawAddr structure.
144 //
145 // Returns a positive integer if the call is successful. In case of failure
146 // it returns:
147 //
148 // -1: system error (errno set)
149 // -5: invalid bindAddress
150 static intptr_t CreateBindListen(const RawAddr& addr,
151 intptr_t backlog,
152 bool v6_only = false);
153 static intptr_t CreateUnixDomainBindListen(const RawAddr& addr,
154 intptr_t backlog);
155
156 // Start accepting on a newly created listening socket. If it was unable to
157 // start accepting incoming sockets, the fd is invalidated.
158 static bool StartAccept(intptr_t fd);
159
160 private:
161 DISALLOW_ALLOCATION();
163};
164
166 public:
168 : sockets_by_port_(SameIntptrValue, kInitialSocketsCount),
169 sockets_by_fd_(SameIntptrValue, kInitialSocketsCount),
170 unix_domain_sockets_(nullptr),
171 mutex_() {}
172
173 ~ListeningSocketRegistry() { CloseAllSafe(); }
174
175 static void Initialize();
176
178
179 static void Cleanup();
180
181 // Bind `socket_object` to `addr`.
182 // Return Dart_True() if succeed.
183 // This function should be called from a dart runtime call in order to create
184 // a new (potentially shared) socket.
186 RawAddr addr,
187 intptr_t backlog,
188 bool v6_only,
189 bool shared);
190 // Bind unix domain socket`socket_object` to `path`.
191 // Return Dart_True() if succeed.
192 // This function should be called from a dart runtime call in order to create
193 // a new socket.
195 Namespace* namespc,
196 const char* path,
197 intptr_t backlog,
198 bool shared);
199
200 // This should be called from the event handler for every kCloseEvent it gets
201 // on listening sockets.
202 //
203 // Returns `true` if the last reference has been dropped and the underlying
204 // socket can be closed.
205 //
206 // The caller is responsible for obtaining the mutex first, before calling
207 // this function.
208 bool CloseSafe(Socket* socketfd);
209
210 Mutex* mutex() { return &mutex_; }
211
212 private:
213 struct OSSocket {
214 RawAddr address;
215 int port;
216 bool v6_only;
217 bool shared;
218 int ref_count;
219 intptr_t fd;
220
221 // Only applicable to Unix domain socket, where address.addr.sa_family
222 // == AF_UNIX.
223 Namespace* namespc;
224
225 // Singly linked lists of OSSocket instances which listen on the same port
226 // but on different addresses.
227 OSSocket* next;
228
229 OSSocket(RawAddr address,
230 int port,
231 bool v6_only,
232 bool shared,
233 Socket* socketfd,
234 Namespace* namespc)
235 : address(address),
236 port(port),
237 v6_only(v6_only),
238 shared(shared),
239 ref_count(0),
240 namespc(namespc),
241 next(nullptr) {
242 fd = socketfd->fd();
243 }
244 };
245
246 static constexpr intptr_t kInitialSocketsCount = 8;
247
248 OSSocket* FindOSSocketWithAddress(OSSocket* current, const RawAddr& addr) {
249 while (current != nullptr) {
250 if (SocketAddress::AreAddressesEqual(current->address, addr)) {
251 return current;
252 }
253 current = current->next;
254 }
255 return nullptr;
256 }
257
258 OSSocket* FindOSSocketWithPath(OSSocket* current,
259 Namespace* namespc,
260 const char* path) {
261 while (current != nullptr) {
262 ASSERT(current->address.addr.sa_family == AF_UNIX);
263#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
264 bool condition;
265 if (path[0] == '\0') {
266 condition = current->address.un.sun_path[0] == '\0' &&
267 strcmp(&(current->address.un.sun_path[1]), path + 1) == 0;
268 } else {
269 condition =
270 File::AreIdentical(current->namespc, current->address.un.sun_path,
271 namespc, path) == File::kIdentical;
272 }
273 if (condition) {
274 return current;
275 }
276#else
277 if (File::AreIdentical(current->namespc, current->address.un.sun_path,
278 namespc, path) == File::kIdentical) {
279 return current;
280 }
281#endif // defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
282 current = current->next;
283 }
284 return nullptr;
285 }
286
287 static bool SameIntptrValue(void* key1, void* key2) {
288 return reinterpret_cast<intptr_t>(key1) == reinterpret_cast<intptr_t>(key2);
289 }
290
291 static uint32_t GetHashmapHashFromIntptr(intptr_t i) {
292 return static_cast<uint32_t>((i + 1) & 0xFFFFFFFF);
293 }
294
295 static void* GetHashmapKeyFromIntptr(intptr_t i) {
296 return reinterpret_cast<void*>(i + 1);
297 }
298
299 OSSocket* LookupByPort(intptr_t port);
300 void InsertByPort(intptr_t port, OSSocket* socket);
301 void RemoveByPort(intptr_t port);
302
303 OSSocket* LookupByFd(Socket* fd);
304 void InsertByFd(Socket* fd, OSSocket* socket);
305 void RemoveByFd(Socket* fd);
306
307 bool CloseOneSafe(OSSocket* os_socket, Socket* socket);
308 void CloseAllSafe();
309
310 SimpleHashMap sockets_by_port_;
311 SimpleHashMap sockets_by_fd_;
312
313 OSSocket* unix_domain_sockets_;
314
315 Mutex mutex_;
316
318};
319
320} // namespace bin
321} // namespace dart
322
323#endif // RUNTIME_BIN_SOCKET_H_
static Identical AreIdentical(Namespace *namespc_1, const char *file_1, Namespace *namespc_2, const char *file_2)
Dart_Handle CreateBindListen(Dart_Handle socket_object, RawAddr addr, intptr_t backlog, bool v6_only, bool shared)
Definition socket.cc:94
bool CloseSafe(Socket *socketfd)
Definition socket.cc:350
Dart_Handle CreateUnixDomainBindListen(Dart_Handle socket_object, Namespace *namespc, const char *path, intptr_t backlog, bool shared)
Definition socket.cc:197
static ListeningSocketRegistry * Instance()
Definition socket.cc:38
static intptr_t CreateBindListen(const RawAddr &addr, intptr_t backlog, bool v6_only=false)
static intptr_t Accept(intptr_t fd)
static constexpr intptr_t kTemporaryFailure
Definition socket.h:138
static bool StartAccept(intptr_t fd)
static intptr_t CreateUnixDomainBindListen(const RawAddr &addr, intptr_t backlog)
static bool AreAddressesEqual(const RawAddr &a, const RawAddr &b)
@ kReverseLookupRequest
Definition socket.h:32
@ kListInterfacesRequest
Definition socket.h:31
static bool IsSignalSocketFlag(intptr_t flag)
Definition socket.h:111
static CObject * ListInterfacesRequest(const CObjectArray &request)
Definition socket.cc:1134
intptr_t fd() const
Definition socket.h:52
static bool short_socket_read()
Definition socket.h:102
Dart_Port isolate_port() const
Definition socket.h:61
static void set_short_socket_read(bool short_socket_read)
Definition socket.h:103
static Dart_Port GetServicePort()
void set_udp_receive_buffer(uint8_t *buffer)
Definition socket.h:67
@ kInternalSignalSocket
Definition socket.h:47
static CObject * ReverseLookupRequest(const CObjectArray &request)
Definition socket.cc:1103
static bool short_socket_write()
Definition socket.h:106
static intptr_t CreateUnixDomainConnect(const RawAddr &addr)
uint8_t * udp_receive_buffer() const
Definition socket.h:66
static void SetSocketIdNativeField(Dart_Handle handle, intptr_t id, SocketFinalizer finalizer)
Definition socket.cc:1489
Dart_Port port() const
Definition socket.h:63
static Socket * GetSocketIdNativeField(Dart_Handle socket)
Definition socket.cc:1496
static intptr_t CreateConnect(const RawAddr &addr)
void set_port(Dart_Port port)
Definition socket.h:64
static intptr_t CreateBindDatagram(const RawAddr &addr, bool reuseAddress, bool reusePort, int ttl=1)
static void ReuseSocketIdNativeField(Dart_Handle handle, Socket *socket, SocketFinalizer finalizer)
Definition socket.cc:1456
Socket(intptr_t fd)
static CObject * LookupRequest(const CObjectArray &request)
Definition socket.cc:1057
static bool Initialize()
static intptr_t CreateBindConnect(const RawAddr &addr, const RawAddr &source_addr)
static intptr_t CreateUnixDomainBindConnect(const RawAddr &addr, const RawAddr &source_addr)
static void set_short_socket_write(bool short_socket_write)
Definition socket.h:107
int64_t Dart_Port
Definition dart_api.h:1524
struct _Dart_Handle * Dart_Handle
Definition dart_api.h:258
#define ASSERT(E)
FlutterSemanticsFlag flag
static const uint8_t buffer[]
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName)
Definition globals.h:593
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition globals.h:581