Flutter Engine
The Flutter Engine
eventhandler_win.h
Go to the documentation of this file.
1// Copyright (c) 2012, 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_EVENTHANDLER_WIN_H_
6#define RUNTIME_BIN_EVENTHANDLER_WIN_H_
7
8#if !defined(RUNTIME_BIN_EVENTHANDLER_H_)
9#error Do not include eventhandler_win.h directly; use eventhandler.h instead.
10#endif
11
12#include <mswsock.h>
13#include <winsock2.h>
14#include <ws2tcpip.h>
15#include <memory>
16#include <utility>
17
18#include "bin/builtin.h"
20#include "bin/socket_base.h"
21#include "bin/thread.h"
22
23namespace dart {
24namespace bin {
25
26// Forward declarations.
27class EventHandlerImplementation;
28class Handle;
29class FileHandle;
30class SocketHandle;
31class ClientSocket;
32class ListenSocket;
33
34// An OverlappedBuffer encapsulates the OVERLAPPED structure and the
35// associated data buffer. For accept it also contains the pre-created
36// socket for the client.
38 public:
39 enum Operation {
47 };
48
57
58 // Find the IO buffer from the OVERLAPPED address.
60
61 // Read data from a buffer which has been received. It will read up
62 // to num_bytes bytes of data returning the actual number of bytes
63 // read. This will update the index of the next byte in the buffer
64 // so calling Read several times will keep returning new data from
65 // the buffer until all data have been read.
66 int Read(void* buffer, int num_bytes);
67
68 // Write data to a buffer before sending it. Returns the number of bytes
69 // actually written to the buffer. Calls to Write will always write to
70 // the buffer from the beginning.
71 int Write(const void* buffer, int num_bytes);
72
73 // Check the amount of data in a read buffer which has not been read yet.
75 bool IsEmpty() { return GetRemainingLength() == 0; }
76
77 Operation operation() const { return operation_; }
78 SOCKET client() const { return client_; }
79 char* GetBufferStart() { return reinterpret_cast<char*>(&buffer_data_); }
80 int GetBufferSize() const { return buflen_; }
81 struct sockaddr* from() const { return from_; }
82 socklen_t* from_len_addr() const { return from_len_addr_; }
83 socklen_t from_len() const { return from_ == nullptr ? 0 : *from_len_addr_; }
84
85 // Returns the address of the OVERLAPPED structure with all fields
86 // initialized to zero.
88 memset(&overlapped_, 0, sizeof(overlapped_));
89 return &overlapped_;
90 }
91
92 // Returns a WASBUF structure initialized with the data in this IO buffer.
93 WSABUF* GetWASBUF() {
94 wbuf_.buf = GetBufferStart();
95 wbuf_.len = GetBufferSize();
96 return &wbuf_;
97 }
98
99 void set_data_length(int data_length) { data_length_ = data_length; }
100
101 void operator delete(void* buffer) { free(buffer); }
102
103 private:
105 : operation_(operation), buflen_(buffer_size) {
106 memset(GetBufferStart(), 0, GetBufferSize());
107 if (operation == kRecvFrom) {
108 // Reserve part of the buffer for the length of source sockaddr
109 // and source sockaddr.
110 const int kAdditionalSize =
111 sizeof(struct sockaddr_storage) + sizeof(socklen_t);
112 ASSERT(buflen_ > kAdditionalSize);
113 buflen_ -= kAdditionalSize;
114 from_len_addr_ =
115 reinterpret_cast<socklen_t*>(GetBufferStart() + GetBufferSize());
116 *from_len_addr_ = sizeof(struct sockaddr_storage);
117 from_ = reinterpret_cast<struct sockaddr*>(from_len_addr_ + 1);
118 } else {
119 from_len_addr_ = nullptr;
120 from_ = nullptr;
121 }
122 index_ = 0;
123 data_length_ = 0;
124 if (operation_ == kAccept) {
125 client_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
126 }
127 }
128
129 void* operator new(size_t size, int buffer_size) {
130 return malloc(size + buffer_size);
131 }
132
133 // Allocate an overlapped buffer for thse specified amount of data and
134 // operation. Some operations need additional buffer space, which is
135 // handled by this method.
136 static OverlappedBuffer* AllocateBuffer(int buffer_size, Operation operation);
137
138 OVERLAPPED overlapped_; // OVERLAPPED structure for overlapped IO.
139 SOCKET client_; // Used for AcceptEx client socket.
140 int buflen_; // Length of the buffer.
141 Operation operation_; // Type of operation issued.
142
143 int index_; // Index for next read from read buffer.
144 int data_length_; // Length of the actual data in the buffer.
145
146 WSABUF wbuf_; // Structure for passing buffer to WSA functions.
147
148 // For the recvfrom operation additional storace is allocated for the
149 // source sockaddr.
150 socklen_t* from_len_addr_; // Pointer to source sockaddr size storage.
151 struct sockaddr* from_; // Pointer to source sockaddr storage.
152
153 // Buffer for recv/send/AcceptEx. This must be at the end of the
154 // object as the object is allocated larger than it's definition
155 // indicate to extend this array.
156 uint8_t buffer_data_[1];
157
158 DISALLOW_COPY_AND_ASSIGN(OverlappedBuffer);
159};
160
161// Abstract super class for holding information on listen and connected
162// sockets.
163class Handle : public ReferenceCounted<Handle>, public DescriptorInfoBase {
164 public:
165 enum Type {
172 };
173
174 // Socket interface exposing normal socket operations.
175 intptr_t Available();
176 bool DataReady();
177 intptr_t Read(void* buffer, intptr_t num_bytes);
178 intptr_t RecvFrom(void* buffer,
179 intptr_t num_bytes,
180 struct sockaddr* sa,
181 socklen_t addr_len);
182 virtual intptr_t Write(const void* buffer, intptr_t num_bytes);
183 virtual intptr_t SendTo(const void* buffer,
184 intptr_t num_bytes,
185 struct sockaddr* sa,
186 socklen_t sa_len);
187
188 // Internal interface used by the event handler.
189 virtual bool IssueRead();
190 virtual bool IssueRecvFrom();
191 virtual bool IssueWrite();
192 virtual bool IssueSendTo(struct sockaddr* sa, socklen_t sa_len);
198
199 bool IsClosing() { return (flags_ & (1 << kClosing)) != 0; }
200 bool IsClosedRead() { return (flags_ & (1 << kCloseRead)) != 0; }
201 bool IsClosedWrite() { return (flags_ & (1 << kCloseWrite)) != 0; }
202 bool IsError() { return (flags_ & (1 << kError)) != 0; }
203 void MarkClosing() { flags_ |= (1 << kClosing); }
204 void MarkClosedRead() { flags_ |= (1 << kCloseRead); }
205 void MarkClosedWrite() { flags_ |= (1 << kCloseWrite); }
206 void MarkError() { flags_ |= (1 << kError); }
207
209
210 HANDLE handle() { return handle_; }
211
212 bool CreateCompletionPort(HANDLE completion_port);
213
214 void Close();
215 virtual void DoClose();
216 virtual bool IsClosed() = 0;
217
218 bool IsHandleClosed() const { return handle_ == INVALID_HANDLE_VALUE; }
219
220 Type type() { return type_; }
221 bool is_file() { return type_ == kFile; }
222 bool is_socket() {
223 return type_ == kListenSocket || type_ == kClientSocket ||
225 }
229
231 flags_ |= (1 << kDoesNotSupportOverlappedIO);
232 }
234 return (flags_ & (1 << kDoesNotSupportOverlappedIO)) == 0;
235 }
236
238
241
242 void set_completion_port(HANDLE completion_port) {
243 completion_port_ = completion_port;
244 }
245
248 }
249
250 protected:
251 // For access to monitor_;
253
254 enum Flags {
259 kError = 4
260 };
261
262 explicit Handle(intptr_t handle);
263 virtual ~Handle();
264
265 virtual void HandleIssueError();
266
272
273 std::unique_ptr<OverlappedBuffer>
274 data_ready_; // Buffer for data ready to be read.
275 OverlappedBuffer* pending_read_; // Buffer for pending read.
276 OverlappedBuffer* pending_write_; // Buffer for pending write
277
279
284
285 private:
286 void WaitForReadThreadStarted();
287 void NotifyReadThreadStarted();
288 void WaitForReadThreadFinished();
289 void NotifyReadThreadFinished();
290
291 int flags_;
292
293 friend class ReferenceCounted<Handle>;
295};
296
297class FileHandle : public DescriptorInfoSingleMixin<Handle> {
298 public:
300 : DescriptorInfoSingleMixin(reinterpret_cast<intptr_t>(handle), true) {
301 type_ = kFile;
302 }
303
305 virtual bool IsClosed();
306
307 private:
308 DISALLOW_COPY_AND_ASSIGN(FileHandle);
309};
310
311class StdHandle : public FileHandle {
312 public:
314
315 virtual void DoClose();
316 virtual intptr_t Write(const void* buffer, intptr_t num_bytes);
317
320
321#if defined(DEBUG)
322 static StdHandle* StdinPtr() { return stdin_; }
323#endif
324
325 private:
326 static Mutex* stdin_mutex_;
327 static StdHandle* stdin_;
328
329 explicit StdHandle(HANDLE handle)
331 thread_id_(Thread::kInvalidThreadId),
332 thread_handle_(nullptr),
333 thread_wrote_(0),
334 write_thread_exists_(false),
335 write_thread_running_(false) {
336 type_ = kStd;
337 }
338
339 ThreadId thread_id_;
340 HANDLE thread_handle_;
341 intptr_t thread_wrote_;
342 bool write_thread_exists_;
343 bool write_thread_running_;
344
345 DISALLOW_COPY_AND_ASSIGN(StdHandle);
346};
347
349 public:
350 DirectoryWatchHandle(HANDLE handle, int events, bool recursive)
351 : DescriptorInfoSingleMixin(reinterpret_cast<intptr_t>(handle), true),
352 events_(events),
353 recursive_(recursive) {
355 }
356
358 virtual bool IsClosed();
359
360 virtual bool IssueRead();
361
362 void Stop();
363
364 private:
365 int events_;
366 bool recursive_;
367
368 DISALLOW_COPY_AND_ASSIGN(DirectoryWatchHandle);
369};
370
371class SocketHandle : public Handle {
372 public:
373 SOCKET socket() const { return socket_; }
374
375 protected:
376 explicit SocketHandle(intptr_t s) : Handle(s), socket_(s) {}
377
378 virtual void HandleIssueError();
379
380 private:
381 const SOCKET socket_;
382
383 DISALLOW_COPY_AND_ASSIGN(SocketHandle);
384};
385
386// Information on listen sockets.
387class ListenSocket : public DescriptorInfoMultipleMixin<SocketHandle> {
388 public:
389 explicit ListenSocket(intptr_t s)
391 AcceptEx_(nullptr),
392 GetAcceptExSockaddrs_(nullptr),
393 pending_accept_count_(0),
394 accepted_head_(nullptr),
395 accepted_tail_(nullptr),
396 accepted_count_(0) {
398 }
399 virtual ~ListenSocket() {
401 ASSERT(accepted_head_ == nullptr);
402 ASSERT(accepted_tail_ == nullptr);
403 }
404
405 // Socket interface exposing normal socket operations.
407 bool CanAccept();
408
409 // Internal interface used by the event handler.
410 bool HasPendingAccept() { return pending_accept_count_ > 0; }
413
415 virtual void DoClose();
416 virtual bool IsClosed();
417
418 int pending_accept_count() { return pending_accept_count_; }
419
420 int accepted_count() { return accepted_count_; }
421
422 private:
423 bool LoadAcceptEx();
424 bool LoadGetAcceptExSockaddrs();
425
426 LPFN_ACCEPTEX AcceptEx_;
427 LPFN_GETACCEPTEXSOCKADDRS GetAcceptExSockaddrs_;
428
429 // The number of asynchronous `IssueAccept` operations which haven't completed
430 // yet.
431 int pending_accept_count_;
432
433 // Linked list of accepted connections provided by completion code. Ready to
434 // be handed over through accept.
435 ClientSocket* accepted_head_;
436 ClientSocket* accepted_tail_;
437
438 // The number of accepted connections which are waiting to be removed from
439 // this queue and processed by dart isolates.
440 int accepted_count_;
441
442 DISALLOW_COPY_AND_ASSIGN(ListenSocket);
443};
444
445// Information on connected sockets.
446class ClientSocket : public DescriptorInfoSingleMixin<SocketHandle> {
447 public:
448 explicit ClientSocket(intptr_t s,
449 std::unique_ptr<RawAddr> remote_addr = nullptr)
451 DisconnectEx_(nullptr),
452 next_(nullptr),
453 connected_(false),
454 closed_(false),
455 remote_addr_(std::move(remote_addr)) {
456 LoadDisconnectEx();
458 }
459
460 virtual ~ClientSocket() {
461 // Don't delete this object until all pending requests have been handled.
464 ASSERT(next_ == nullptr);
465 ASSERT(closed_ == true);
466 }
467
468 void Shutdown(int how);
469
470 // Internal interface used by the event handler.
471 virtual bool IssueRead();
472 virtual bool IssueWrite();
476
478 virtual void DoClose();
479 virtual bool IsClosed();
480
481 // If `ClientSocket` was constructed with a `remote_addr`, populate `addr`
482 // with that value and return `true`. Otherwise leave `addr` untouched and
483 // return `false`.
485
486 ClientSocket* next() { return next_; }
487 void set_next(ClientSocket* next) { next_ = next; }
488
489 void mark_connected() { connected_ = true; }
490 bool is_connected() const { return connected_; }
491
492 void mark_closed() { closed_ = true; }
493
494#if defined(DEBUG)
495 static intptr_t disconnecting() { return disconnecting_; }
496#endif
497
498 private:
499 bool LoadDisconnectEx();
500
501 LPFN_DISCONNECTEX DisconnectEx_;
502 ClientSocket* next_;
503 bool connected_;
504 bool closed_;
505 std::unique_ptr<RawAddr> remote_addr_;
506
507#if defined(DEBUG)
508 static intptr_t disconnecting_;
509#endif
510
511 DISALLOW_COPY_AND_ASSIGN(ClientSocket);
512};
513
514class DatagramSocket : public DescriptorInfoSingleMixin<SocketHandle> {
515 public:
518 }
519
520 virtual ~DatagramSocket() {
521 // Don't delete this object until all pending requests have been handled.
524 }
525
526 // Internal interface used by the event handler.
527 virtual bool IssueRecvFrom();
528 virtual bool IssueSendTo(sockaddr* sa, socklen_t sa_len);
529
531 virtual void DoClose();
532 virtual bool IsClosed();
533
534 private:
535 DISALLOW_COPY_AND_ASSIGN(DatagramSocket);
536};
537
538// Event handler.
540 public:
543
544 void SendData(intptr_t id, Dart_Port dart_port, int64_t data);
545 void Start(EventHandler* handler);
546 void Shutdown();
547
549
550 int64_t GetTimeout();
555 void HandleRead(Handle* handle, int bytes, OverlappedBuffer* buffer);
556 void HandleRecvFrom(Handle* handle, int bytes, OverlappedBuffer* buffer);
557 void HandleWrite(Handle* handle, int bytes, OverlappedBuffer* buffer);
558 void HandleDisconnect(ClientSocket* client_socket,
559 int bytes,
561 void HandleConnect(ClientSocket* client_socket,
562 int bytes,
565
567 DWORD bytes,
569 OVERLAPPED* overlapped);
570
571 HANDLE completion_port() { return completion_port_; }
572
573 private:
574 Monitor startup_monitor_;
575 ThreadId handler_thread_id_;
576 HANDLE handler_thread_handle_;
577
578 TimeoutQueue timeout_queue_; // Time for next timeout.
579 bool shutdown_;
580 HANDLE completion_port_;
581
582 DISALLOW_COPY_AND_ASSIGN(EventHandlerImplementation);
583};
584
585} // namespace bin
586} // namespace dart
587
588#endif // RUNTIME_BIN_EVENTHANDLER_WIN_H_
static uint32_t buffer_size(uint32_t offset, uint32_t maxAlignment)
static bool ok(int result)
virtual bool IssueWrite()
virtual void EnsureInitialized(EventHandlerImplementation *event_handler)
virtual bool IsClosed()
void ConnectComplete(OverlappedBuffer *buffer)
ClientSocket(intptr_t s, std::unique_ptr< RawAddr > remote_addr=nullptr)
void DisconnectComplete(OverlappedBuffer *buffer)
bool PopulateRemoteAddr(RawAddr &addr)
virtual bool IssueRead()
void set_next(ClientSocket *next)
void Shutdown(int how)
virtual void DoClose()
virtual void EnsureInitialized(EventHandlerImplementation *event_handler)
virtual bool IssueRecvFrom()
virtual bool IssueSendTo(sockaddr *sa, socklen_t sa_len)
virtual void EnsureInitialized(EventHandlerImplementation *event_handler)
DirectoryWatchHandle(HANDLE handle, int events, bool recursive)
void HandleWrite(Handle *handle, int bytes, OverlappedBuffer *buffer)
void HandleConnect(ClientSocket *client_socket, int bytes, OverlappedBuffer *buffer)
void SendData(intptr_t id, Dart_Port dart_port, int64_t data)
void HandleRead(Handle *handle, int bytes, OverlappedBuffer *buffer)
void TryDispatchingPendingAccepts(ListenSocket *listen_socket)
void HandleDisconnect(ClientSocket *client_socket, int bytes, OverlappedBuffer *buffer)
void HandleAccept(ListenSocket *listen_socket, OverlappedBuffer *buffer)
void HandleRecvFrom(Handle *handle, int bytes, OverlappedBuffer *buffer)
void Start(EventHandler *handler)
static void EventHandlerEntry(uword args)
void HandleIOCompletion(DWORD bytes, ULONG_PTR key, OVERLAPPED *overlapped)
void HandleInterrupt(InterruptMessage *msg)
void HandleCompletionOrInterrupt(BOOL ok, DWORD bytes, ULONG_PTR key, OVERLAPPED *overlapped)
virtual void EnsureInitialized(EventHandlerImplementation *event_handler)
virtual bool IsClosed()
FileHandle(HANDLE handle)
intptr_t Available()
void MarkDoesNotSupportOverlappedIO()
virtual bool IssueSendTo(struct sockaddr *sa, socklen_t sa_len)
bool IsHandleClosed() const
intptr_t RecvFrom(void *buffer, intptr_t num_bytes, struct sockaddr *sa, socklen_t addr_len)
void ReadSyncCompleteAsync()
virtual intptr_t Write(const void *buffer, intptr_t num_bytes)
virtual void EnsureInitialized(EventHandlerImplementation *event_handler)=0
virtual bool IssueRecvFrom()
void set_event_handler(EventHandlerImplementation *event_handler)
void set_completion_port(HANDLE completion_port)
void set_last_error(DWORD last_error)
virtual bool IsClosed()=0
EventHandlerImplementation * event_handler_
void RecvFromComplete(OverlappedBuffer *buffer)
virtual void DoClose()
virtual bool IssueWrite()
void WriteComplete(OverlappedBuffer *buffer)
OverlappedBuffer * pending_read_
std::unique_ptr< OverlappedBuffer > data_ready_
virtual void HandleIssueError()
bool CreateCompletionPort(HANDLE completion_port)
virtual intptr_t SendTo(const void *buffer, intptr_t num_bytes, struct sockaddr *sa, socklen_t sa_len)
virtual bool IssueRead()
OverlappedBuffer * pending_write_
Handle(intptr_t handle)
intptr_t Read(void *buffer, intptr_t num_bytes)
void ReadComplete(OverlappedBuffer *buffer)
ClientSocket * Accept()
virtual bool IsClosed()
virtual void EnsureInitialized(EventHandlerImplementation *event_handler)
virtual void DoClose()
void AcceptComplete(OverlappedBuffer *buffer, HANDLE completion_port)
int Read(void *buffer, int num_bytes)
void set_data_length(int data_length)
static void DisposeBuffer(OverlappedBuffer *buffer)
static OverlappedBuffer * GetFromOverlapped(OVERLAPPED *overlapped)
static OverlappedBuffer * AllocateRecvFromBuffer(int buffer_size)
static OverlappedBuffer * AllocateAcceptBuffer(int buffer_size)
static OverlappedBuffer * AllocateConnectBuffer()
int Write(const void *buffer, int num_bytes)
socklen_t * from_len_addr() const
static OverlappedBuffer * AllocateDisconnectBuffer()
struct sockaddr * from() const
static OverlappedBuffer * AllocateSendToBuffer(int buffer_size)
static OverlappedBuffer * AllocateReadBuffer(int buffer_size)
static OverlappedBuffer * AllocateWriteBuffer(int buffer_size)
virtual void HandleIssueError()
static StdHandle * Stdin(HANDLE handle)
virtual intptr_t Write(const void *buffer, intptr_t num_bytes)
virtual void DoClose()
int64_t Dart_Port
Definition: dart_api.h:1525
#define ASSERT(E)
struct MyStruct s
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
pthread_t ThreadId
Definition: thread_absl.h:21
static EventHandler * event_handler
Definition: eventhandler.cc:18
Definition: dart_vm.cc:33
void * malloc(size_t size)
Definition: allocation.cc:19
uintptr_t uword
Definition: globals.h:501
static int8_t data[kExtLength]
pthread_t ThreadId
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 The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
Definition: ref_ptr.h:256
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: globals.h:581
int BOOL
Definition: windows_types.h:37
#define INVALID_HANDLE_VALUE
void * HANDLE
Definition: windows_types.h:36
struct _OVERLAPPED OVERLAPPED
__w64 unsigned long ULONG_PTR
Definition: windows_types.h:56
unsigned long DWORD
Definition: windows_types.h:22