mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 09:43:57 +00:00
3c298dbca5
TEST=build Change-Id: I18fc7cfe725dc978d4b23de6191e455ac7cd75e5 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/293800 Reviewed-by: Siva Annamalai <asiva@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
180 lines
5.1 KiB
C++
180 lines
5.1 KiB
C++
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#ifndef RUNTIME_BIN_EVENTHANDLER_FUCHSIA_H_
|
|
#define RUNTIME_BIN_EVENTHANDLER_FUCHSIA_H_
|
|
|
|
#if !defined(RUNTIME_BIN_EVENTHANDLER_H_)
|
|
#error Do not include eventhandler_fuchsia.h directly; use eventhandler.h.
|
|
#endif
|
|
|
|
#include <errno.h>
|
|
#include <lib/fdio/unsafe.h>
|
|
#include <sys/socket.h>
|
|
#include <unistd.h>
|
|
#include <zircon/status.h>
|
|
#include <zircon/syscalls.h>
|
|
#include <zircon/syscalls/object.h>
|
|
#include <zircon/syscalls/port.h>
|
|
|
|
#include "bin/reference_counting.h"
|
|
#include "bin/thread.h"
|
|
#include "platform/signal_blocker.h"
|
|
|
|
namespace dart {
|
|
namespace bin {
|
|
|
|
class DescriptorInfo;
|
|
|
|
class IOHandle : public ReferenceCounted<IOHandle> {
|
|
public:
|
|
explicit IOHandle(intptr_t fd)
|
|
: ReferenceCounted(),
|
|
mutex_(),
|
|
write_events_enabled_(true),
|
|
read_events_enabled_(true),
|
|
close_events_enabled_(true),
|
|
fd_(fd),
|
|
handle_(ZX_HANDLE_INVALID),
|
|
wait_key_(0),
|
|
fdio_(fdio_unsafe_fd_to_io(fd)) {}
|
|
|
|
intptr_t fd() const { return fd_; }
|
|
|
|
// Called from SocketBase::{Read(), Write()} and ServerSocket::Accept() on
|
|
// the Dart thread.
|
|
intptr_t Read(void* buffer, intptr_t num_bytes);
|
|
intptr_t Write(const void* buffer, intptr_t num_bytes);
|
|
intptr_t Accept(struct sockaddr* addr, socklen_t* addrlen);
|
|
intptr_t AvailableBytes();
|
|
|
|
// Called from the EventHandler thread.
|
|
void Close();
|
|
uint32_t MaskToEpollEvents(intptr_t mask);
|
|
// If port is ZX_HANDLE_INVALID, AsyncWait uses the port from the previous
|
|
// call with a valid port handle.
|
|
bool AsyncWait(zx_handle_t port, uint32_t events, uint64_t key);
|
|
void CancelWait(zx_handle_t port, uint64_t key);
|
|
uint32_t WaitEnd(zx_signals_t observed);
|
|
intptr_t ToggleEvents(intptr_t event_mask);
|
|
|
|
static intptr_t EpollEventsToMask(intptr_t events);
|
|
|
|
private:
|
|
~IOHandle() {
|
|
if (fdio_ != nullptr) {
|
|
fdio_unsafe_release(fdio_);
|
|
}
|
|
}
|
|
|
|
bool AsyncWaitLocked(zx_handle_t port, uint32_t events, uint64_t key);
|
|
|
|
// Mutex that protects the state here.
|
|
Mutex mutex_;
|
|
bool write_events_enabled_;
|
|
bool read_events_enabled_;
|
|
bool close_events_enabled_;
|
|
|
|
// Bytes remaining to be read from the socket. Read events should only be
|
|
// re-enabled when this drops to zero.
|
|
intptr_t available_bytes_;
|
|
|
|
// TODO(zra): Add flag to enable/disable peer closed signal?
|
|
intptr_t fd_;
|
|
zx_handle_t handle_;
|
|
zx_handle_t port_;
|
|
uint64_t wait_key_;
|
|
fdio_t* fdio_;
|
|
|
|
friend class ReferenceCounted<IOHandle>;
|
|
DISALLOW_COPY_AND_ASSIGN(IOHandle);
|
|
};
|
|
|
|
class DescriptorInfo : public DescriptorInfoBase {
|
|
public:
|
|
explicit DescriptorInfo(intptr_t fd) : DescriptorInfoBase(fd) {
|
|
IOHandle* handle = reinterpret_cast<IOHandle*>(fd);
|
|
handle->Retain();
|
|
}
|
|
|
|
virtual ~DescriptorInfo() {
|
|
IOHandle* handle = reinterpret_cast<IOHandle*>(fd_);
|
|
handle->Release();
|
|
}
|
|
|
|
virtual void Close() {
|
|
IOHandle* handle = reinterpret_cast<IOHandle*>(fd_);
|
|
handle->Close();
|
|
}
|
|
|
|
IOHandle* io_handle() const { return reinterpret_cast<IOHandle*>(fd_); }
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(DescriptorInfo);
|
|
};
|
|
|
|
class DescriptorInfoSingle : public DescriptorInfoSingleMixin<DescriptorInfo> {
|
|
public:
|
|
explicit DescriptorInfoSingle(intptr_t fd)
|
|
: DescriptorInfoSingleMixin(fd, false) {}
|
|
virtual ~DescriptorInfoSingle() {}
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(DescriptorInfoSingle);
|
|
};
|
|
|
|
class DescriptorInfoMultiple
|
|
: public DescriptorInfoMultipleMixin<DescriptorInfo> {
|
|
public:
|
|
explicit DescriptorInfoMultiple(intptr_t fd)
|
|
: DescriptorInfoMultipleMixin(fd, false) {}
|
|
virtual ~DescriptorInfoMultiple() {}
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(DescriptorInfoMultiple);
|
|
};
|
|
|
|
class EventHandlerImplementation {
|
|
public:
|
|
EventHandlerImplementation();
|
|
~EventHandlerImplementation();
|
|
|
|
void UpdatePort(intptr_t old_mask, DescriptorInfo* di);
|
|
|
|
// Gets the socket data structure for a given file
|
|
// descriptor. Creates a new one if one is not found.
|
|
DescriptorInfo* GetDescriptorInfo(intptr_t fd, bool is_listening);
|
|
void SendData(intptr_t id, Dart_Port dart_port, int64_t data);
|
|
void Start(EventHandler* handler);
|
|
void Shutdown();
|
|
|
|
private:
|
|
static constexpr uint64_t kInterruptPacketKey = 1;
|
|
|
|
static void Poll(uword args);
|
|
static void* GetHashmapKeyFromFd(intptr_t fd);
|
|
static uint32_t GetHashmapHashFromFd(intptr_t fd);
|
|
static void AddToPort(zx_handle_t port_handle, DescriptorInfo* di);
|
|
static void RemoveFromPort(zx_handle_t port_handle, DescriptorInfo* di);
|
|
|
|
int64_t GetTimeout() const;
|
|
void HandlePacket(zx_port_packet_t* pkt);
|
|
void HandleTimeout();
|
|
void WakeupHandler(intptr_t id, Dart_Port dart_port, int64_t data);
|
|
intptr_t GetPollEvents(intptr_t events);
|
|
void HandleInterrupt(InterruptMessage* msg);
|
|
|
|
SimpleHashMap socket_map_;
|
|
TimeoutQueue timeout_queue_;
|
|
bool shutdown_;
|
|
zx_handle_t port_handle_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(EventHandlerImplementation);
|
|
};
|
|
|
|
} // namespace bin
|
|
} // namespace dart
|
|
|
|
#endif // RUNTIME_BIN_EVENTHANDLER_FUCHSIA_H_
|