| // 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 BIN_SOCKET_H_ |
| #define BIN_SOCKET_H_ |
| |
| #include "bin/builtin.h" |
| #include "bin/utils.h" |
| |
| #include "platform/globals.h" |
| #include "platform/thread.h" |
| // Declare the OS-specific types ahead of defining the generic class. |
| #if defined(TARGET_OS_ANDROID) |
| #include "bin/socket_android.h" |
| #elif defined(TARGET_OS_LINUX) |
| #include "bin/socket_linux.h" |
| #elif defined(TARGET_OS_MACOS) |
| #include "bin/socket_macos.h" |
| #elif defined(TARGET_OS_WINDOWS) |
| #include "bin/socket_win.h" |
| #else |
| #error Unknown target os. |
| #endif |
| |
| |
| namespace dart { |
| namespace bin { |
| |
| union RawAddr { |
| struct sockaddr_in in; |
| struct sockaddr_in6 in6; |
| struct sockaddr_storage ss; |
| struct sockaddr addr; |
| }; |
| |
| class SocketAddress { |
| public: |
| enum { |
| TYPE_ANY = -1, |
| TYPE_IPV4, |
| TYPE_IPV6, |
| }; |
| |
| enum { |
| ADDRESS_LOOPBACK_IP_V4, |
| ADDRESS_LOOPBACK_IP_V6, |
| ADDRESS_ANY_IP_V4, |
| ADDRESS_ANY_IP_V6, |
| ADDRESS_FIRST = ADDRESS_LOOPBACK_IP_V4, |
| ADDRESS_LAST = ADDRESS_ANY_IP_V6, |
| }; |
| |
| explicit SocketAddress(struct addrinfo* addrinfo); |
| |
| int GetType() { |
| if (addr_.ss.ss_family == AF_INET6) return TYPE_IPV6; |
| return TYPE_IPV4; |
| } |
| |
| const char* as_string() const { return as_string_; } |
| const RawAddr& addr() const { return addr_; } |
| |
| static intptr_t GetAddrLength(const RawAddr& addr) { |
| return addr.ss.ss_family == AF_INET6 ? |
| sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in); |
| } |
| |
| static int16_t FromType(int type) { |
| if (type == TYPE_ANY) return AF_UNSPEC; |
| if (type == TYPE_IPV4) return AF_INET; |
| ASSERT(type == TYPE_IPV6 && "Invalid type"); |
| return AF_INET6; |
| } |
| |
| static void SetAddrPort(RawAddr* addr, intptr_t port) { |
| if (addr->ss.ss_family == AF_INET) { |
| addr->in.sin_port = htons(port); |
| } else { |
| addr->in6.sin6_port = htons(port); |
| } |
| } |
| |
| static intptr_t GetAddrPort(RawAddr* addr) { |
| if (addr->ss.ss_family == AF_INET) { |
| return ntohs(addr->in.sin_port); |
| } else { |
| return ntohs(addr->in6.sin6_port); |
| } |
| } |
| |
| private: |
| char as_string_[INET6_ADDRSTRLEN]; |
| RawAddr addr_; |
| |
| DISALLOW_COPY_AND_ASSIGN(SocketAddress); |
| }; |
| |
| class SocketAddresses { |
| public: |
| explicit SocketAddresses(intptr_t count) |
| : count_(count), |
| addresses_(new SocketAddress*[count_]) {} |
| |
| ~SocketAddresses() { |
| for (intptr_t i = 0; i < count_; i++) { |
| delete addresses_[i]; |
| } |
| delete[] addresses_; |
| } |
| |
| intptr_t count() const { return count_; } |
| SocketAddress* GetAt(intptr_t i) const { return addresses_[i]; } |
| void SetAt(intptr_t i, SocketAddress* addr) { addresses_[i] = addr; } |
| |
| private: |
| const intptr_t count_; |
| SocketAddress** addresses_; |
| |
| DISALLOW_COPY_AND_ASSIGN(SocketAddresses); |
| }; |
| |
| class Socket { |
| public: |
| enum SocketRequest { |
| kLookupRequest = 0, |
| }; |
| |
| static bool Initialize(); |
| static intptr_t Available(intptr_t fd); |
| static int Read(intptr_t fd, void* buffer, intptr_t num_bytes); |
| static int Write(intptr_t fd, const void* buffer, intptr_t num_bytes); |
| static intptr_t CreateConnect(RawAddr addr, |
| const intptr_t port); |
| static intptr_t GetPort(intptr_t fd); |
| static bool GetRemotePeer(intptr_t fd, char* host, intptr_t* port); |
| static void GetError(intptr_t fd, OSError* os_error); |
| static int GetType(intptr_t fd); |
| static intptr_t GetStdioHandle(int num); |
| static void Close(intptr_t fd); |
| static bool SetNonBlocking(intptr_t fd); |
| static bool SetBlocking(intptr_t fd); |
| static bool SetNoDelay(intptr_t fd, bool enabled); |
| |
| // Perform a hostname lookup. Returns the SocketAddresses. |
| static SocketAddresses* LookupAddress(const char* host, |
| int type, |
| OSError** os_error); |
| |
| static Dart_Port GetServicePort(); |
| |
| static Dart_Handle SetSocketIdNativeField(Dart_Handle socket, intptr_t id); |
| static Dart_Handle GetSocketIdNativeField(Dart_Handle socket, intptr_t* id); |
| |
| private: |
| static dart::Mutex mutex_; |
| static int service_ports_size_; |
| static Dart_Port* service_ports_; |
| static int service_ports_index_; |
| |
| DISALLOW_ALLOCATION(); |
| DISALLOW_IMPLICIT_CONSTRUCTORS(Socket); |
| }; |
| |
| |
| class ServerSocket { |
| public: |
| static const intptr_t kTemporaryFailure = -2; |
| |
| static intptr_t Accept(intptr_t fd); |
| |
| // 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(RawAddr addr, |
| intptr_t port, |
| intptr_t backlog); |
| |
| DISALLOW_ALLOCATION(); |
| DISALLOW_IMPLICIT_CONSTRUCTORS(ServerSocket); |
| }; |
| |
| } // namespace bin |
| } // namespace dart |
| |
| #endif // BIN_SOCKET_H_ |