Files
sdk/runtime/bin/socket.h
T
Matthew Dempsky 6d5f763952 [vm] Eliminate Mutex/Monitor indirection where possible
In many cases, the Mutexes and Monitors have to be marked "mutable"
because they're used to synchronize const accessor methods.

Small text segment improvement for Product builds:

$ size dart.{arm,x64}.{before,after}
   text	   data	    bss	    dec	    hex	filename
19726069	 409960	 392332	20528361	1393ce9	dart.arm.before
19725525	 409960	 392332	20527817	1393ac9	dart.arm.after
22576021	 600376	1782824	24959221	17cd8f5	dart.x64.before
22574821	 600376	1782824	24958021	17cd445	dart.x64.after

Change-Id: I68f5cd5ad452044df8bfebd160910496036a3e6b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/101745
Commit-Queue: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
2019-05-13 21:17:51 +00:00

264 lines
7.8 KiB
C++

// Copyright (c) 2013, 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_SOCKET_H_
#define RUNTIME_BIN_SOCKET_H_
#include "bin/builtin.h"
#include "bin/dartutils.h"
#include "bin/reference_counting.h"
#include "bin/socket_base.h"
#include "bin/thread.h"
#include "bin/utils.h"
#include "platform/hashmap.h"
namespace dart {
namespace bin {
// TODO(bkonyi): Socket should also inherit from SocketBase once it is
// refactored to use instance methods when possible.
// We write Sockets into the native field of the _NativeSocket object
// on the Dart side. They are allocated in SetSocketIdNativeField(), and are
// deallocated either from the finalizer attached to _NativeSockets there, or
// from the eventhandler, whichever drops the last reference.
class Socket : public ReferenceCounted<Socket> {
public:
enum SocketRequest {
kLookupRequest = 0,
kListInterfacesRequest = 1,
kReverseLookupRequest = 2,
};
enum SocketFinalizer {
kFinalizerNormal,
kFinalizerListening,
kFinalizerStdio,
kFinalizerSignal,
};
// Keep in sync with constants in _NativeSocket in socket_patch.dart.
enum SocketType {
kTcpSocket = 18,
kUdpSocket = 19,
kInternalSocket = 20,
kInternalSignalSocket = 21,
};
explicit Socket(intptr_t fd);
intptr_t fd() const { return fd_; }
void SetClosedFd();
Dart_Port isolate_port() const { return isolate_port_; }
Dart_Port port() const { return port_; }
void set_port(Dart_Port port) { port_ = port; }
uint8_t* udp_receive_buffer() const { return udp_receive_buffer_; }
void set_udp_receive_buffer(uint8_t* buffer) { udp_receive_buffer_ = buffer; }
static bool Initialize();
// Creates a socket which is bound and connected. The port to connect to is
// specified as the port component of the passed RawAddr structure.
static intptr_t CreateConnect(const RawAddr& addr);
// Creates a socket which is bound and connected. The port to connect to is
// specified as the port component of the passed RawAddr structure.
static intptr_t CreateBindConnect(const RawAddr& addr,
const RawAddr& source_addr);
// Creates a datagram socket which is bound. The port to bind
// to is specified as the port component of the RawAddr structure.
static intptr_t CreateBindDatagram(const RawAddr& addr,
bool reuseAddress,
bool reusePort,
int ttl = 1);
static CObject* LookupRequest(const CObjectArray& request);
static CObject* ListInterfacesRequest(const CObjectArray& request);
static CObject* ReverseLookupRequest(const CObjectArray& request);
static Dart_Port GetServicePort();
static void SetSocketIdNativeField(Dart_Handle handle,
intptr_t id,
SocketFinalizer finalizer);
static void ReuseSocketIdNativeField(Dart_Handle handle,
Socket* socket,
SocketFinalizer finalizer);
static Socket* GetSocketIdNativeField(Dart_Handle socket);
static bool short_socket_read() { return short_socket_read_; }
static void set_short_socket_read(bool short_socket_read) {
short_socket_read_ = short_socket_read;
}
static bool short_socket_write() { return short_socket_write_; }
static void set_short_socket_write(bool short_socket_write) {
short_socket_write_ = short_socket_write;
}
static bool IsSignalSocketFlag(intptr_t flag) {
return ((flag & (0x1 << kInternalSignalSocket)) != 0);
}
private:
~Socket() {
ASSERT(fd_ == kClosedFd);
free(udp_receive_buffer_);
udp_receive_buffer_ = NULL;
}
static const int kClosedFd = -1;
static bool short_socket_read_;
static bool short_socket_write_;
intptr_t fd_;
Dart_Port isolate_port_;
Dart_Port port_;
uint8_t* udp_receive_buffer_;
friend class ReferenceCounted<Socket>;
DISALLOW_COPY_AND_ASSIGN(Socket);
};
class ServerSocket {
public:
static const intptr_t kTemporaryFailure = -2;
static intptr_t Accept(intptr_t fd);
// Creates a socket which is bound and listens. The port to listen on is
// specified in the port component of the passed RawAddr structure.
//
// Returns a positive integer if the call is successful. In case of failure
// it returns:
//
// -1: system error (errno set)
// -5: invalid bindAddress
static intptr_t CreateBindListen(const RawAddr& addr,
intptr_t backlog,
bool v6_only = false);
// Start accepting on a newly created listening socket. If it was unable to
// start accepting incoming sockets, the fd is invalidated.
static bool StartAccept(intptr_t fd);
private:
DISALLOW_ALLOCATION();
DISALLOW_IMPLICIT_CONSTRUCTORS(ServerSocket);
};
class ListeningSocketRegistry {
public:
ListeningSocketRegistry()
: sockets_by_port_(SameIntptrValue, kInitialSocketsCount),
sockets_by_fd_(SameIntptrValue, kInitialSocketsCount),
mutex_() {}
~ListeningSocketRegistry() {
CloseAllSafe();
}
static void Initialize();
static ListeningSocketRegistry* Instance();
static void Cleanup();
// This function should be called from a dart runtime call in order to create
// a new (potentially shared) socket.
Dart_Handle CreateBindListen(Dart_Handle socket_object,
RawAddr addr,
intptr_t backlog,
bool v6_only,
bool shared);
// This should be called from the event handler for every kCloseEvent it gets
// on listening sockets.
//
// Returns `true` if the last reference has been dropped and the underlying
// socket can be closed.
//
// The caller is responsible for obtaining the mutex first, before calling
// this function.
bool CloseSafe(Socket* socketfd);
Mutex* mutex() { return &mutex_; }
private:
struct OSSocket {
RawAddr address;
int port;
bool v6_only;
bool shared;
int ref_count;
Socket* socketfd;
// Singly linked lists of OSSocket instances which listen on the same port
// but on different addresses.
OSSocket* next;
OSSocket(RawAddr address,
int port,
bool v6_only,
bool shared,
Socket* socketfd)
: address(address),
port(port),
v6_only(v6_only),
shared(shared),
ref_count(0),
socketfd(socketfd),
next(NULL) {}
};
static const intptr_t kInitialSocketsCount = 8;
OSSocket* FindOSSocketWithAddress(OSSocket* current, const RawAddr& addr) {
while (current != NULL) {
if (SocketAddress::AreAddressesEqual(current->address, addr)) {
return current;
}
current = current->next;
}
return NULL;
}
static bool SameIntptrValue(void* key1, void* key2) {
return reinterpret_cast<intptr_t>(key1) == reinterpret_cast<intptr_t>(key2);
}
static uint32_t GetHashmapHashFromIntptr(intptr_t i) {
return static_cast<uint32_t>((i + 1) & 0xFFFFFFFF);
}
static void* GetHashmapKeyFromIntptr(intptr_t i) {
return reinterpret_cast<void*>(i + 1);
}
OSSocket* LookupByPort(intptr_t port);
void InsertByPort(intptr_t port, OSSocket* socket);
void RemoveByPort(intptr_t port);
OSSocket* LookupByFd(Socket* fd);
void InsertByFd(Socket* fd, OSSocket* socket);
void RemoveByFd(Socket* fd);
bool CloseOneSafe(OSSocket* os_socket, bool update_hash_maps);
void CloseAllSafe();
SimpleHashMap sockets_by_port_;
SimpleHashMap sockets_by_fd_;
Mutex mutex_;
DISALLOW_COPY_AND_ASSIGN(ListeningSocketRegistry);
};
} // namespace bin
} // namespace dart
#endif // RUNTIME_BIN_SOCKET_H_