1// Copyright (c) 2017, 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_BASE_H_
6#define RUNTIME_BIN_SOCKET_BASE_H_
7
8#include "platform/globals.h"
9// Declare the OS-specific types ahead of defining the generic class.
10#if defined(HOST_OS_ANDROID)
11#include "bin/socket_base_android.h"
12#elif defined(HOST_OS_FUCHSIA)
13#include "bin/socket_base_fuchsia.h"
14#elif defined(HOST_OS_LINUX)
15#include "bin/socket_base_linux.h"
16#elif defined(HOST_OS_MACOS)
17#include "bin/socket_base_macos.h"
18#elif defined(HOST_OS_WINDOWS)
19#include "bin/socket_base_win.h"
20#else
21#error Unknown target os.
22#endif
23
24#include "bin/builtin.h"
25#include "bin/dartutils.h"
26#include "bin/file.h"
27#include "bin/thread.h"
28#include "bin/utils.h"
29#include "platform/allocation.h"
30#include "platform/hashmap.h"
31
32namespace dart {
33namespace bin {
34
35union RawAddr {
36 struct sockaddr_in in;
37 struct sockaddr_in6 in6;
38 struct sockaddr_un un;
39 struct sockaddr_storage ss;
40 struct sockaddr addr;
41};
42
43class SocketAddress {
44 public:
45 enum {
46 TYPE_ANY = -1,
47 TYPE_IPV4,
48 TYPE_IPV6,
49 TYPE_UNIX,
50 };
51
52 enum {
53 ADDRESS_LOOPBACK_IP_V4,
54 ADDRESS_LOOPBACK_IP_V6,
55 ADDRESS_ANY_IP_V4,
56 ADDRESS_ANY_IP_V6,
57 ADDRESS_FIRST = ADDRESS_LOOPBACK_IP_V4,
58 ADDRESS_LAST = ADDRESS_ANY_IP_V6,
59 };
60
61 // Unix domain socket may be unnamed. In this case addr_.un.sun_path contains
62 // garbage and should not be inspected.
63 explicit SocketAddress(struct sockaddr* sa, bool unnamed_unix_socket = false);
64
65 ~SocketAddress() {}
66
67 int GetType();
68
69 const char* as_string() const { return as_string_; }
70 const RawAddr& addr() const { return addr_; }
71
72 static intptr_t GetAddrLength(const RawAddr& addr);
73 static intptr_t GetInAddrLength(const RawAddr& addr);
74 static bool AreAddressesEqual(const RawAddr& a, const RawAddr& b);
75 static void GetSockAddr(Dart_Handle obj, RawAddr* addr);
76 static Dart_Handle GetUnixDomainSockAddr(const char* path,
77 Namespace* namespc,
78 RawAddr* addr);
79 static int16_t FromType(int type);
80 static void SetAddrPort(RawAddr* addr, intptr_t port);
81 static intptr_t GetAddrPort(const RawAddr& addr);
82 static Dart_Handle ToTypedData(const RawAddr& addr);
83 static CObjectUint8Array* ToCObject(const RawAddr& addr);
84 static void SetAddrScope(RawAddr* addr, intptr_t scope_id);
85 static intptr_t GetAddrScope(const RawAddr& addr);
86
87 private:
88#if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || defined(HOST_OS_ANDROID)
89 // Unix domain address is only on Linux, Mac OS and Android now.
90 // unix(7) require sun_path to be 108 bytes on Linux and Android, 104 bytes on
91 // Mac OS.
92 static const intptr_t kMaxUnixPathLength =
93 sizeof(((struct sockaddr_un*)0)->sun_path);
94 char as_string_[kMaxUnixPathLength];
95#else
96 char as_string_[INET6_ADDRSTRLEN];
97#endif // defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || \
98 // defined(HOST_OS_ANDROID)
99 RawAddr addr_;
100
101 DISALLOW_COPY_AND_ASSIGN(SocketAddress);
102};
103
104class InterfaceSocketAddress {
105 public:
106 InterfaceSocketAddress(struct sockaddr* sa,
107 const char* interface_name,
108 intptr_t interface_index)
109 : socket_address_(new SocketAddress(sa)),
110 interface_name_(interface_name),
111 interface_index_(interface_index) {}
112
113 ~InterfaceSocketAddress() { delete socket_address_; }
114
115 SocketAddress* socket_address() const { return socket_address_; }
116 const char* interface_name() const { return interface_name_; }
117 int interface_index() const { return interface_index_; }
118
119 private:
120 SocketAddress* socket_address_;
121 const char* interface_name_;
122 intptr_t interface_index_;
123
124 DISALLOW_COPY_AND_ASSIGN(InterfaceSocketAddress);
125};
126
127template <typename T>
128class AddressList {
129 public:
130 explicit AddressList(intptr_t count)
131 : count_(count), addresses_(new T*[count_]) {}
132
133 ~AddressList() {
134 for (intptr_t i = 0; i < count_; i++) {
135 delete addresses_[i];
136 }
137 delete[] addresses_;
138 }
139
140 intptr_t count() const { return count_; }
141 T* GetAt(intptr_t i) const { return addresses_[i]; }
142 void SetAt(intptr_t i, T* addr) { addresses_[i] = addr; }
143
144 private:
145 const intptr_t count_;
146 T** addresses_;
147
148 DISALLOW_COPY_AND_ASSIGN(AddressList);
149};
150
151class SocketBase : public AllStatic {
152 public:
153 enum SocketRequest {
154 kLookupRequest = 0,
155 kListInterfacesRequest = 1,
156 kReverseLookupRequest = 2,
157 };
158
159 enum SocketOpKind {
160 kSync,
161 kAsync,
162 };
163
164 // TODO(dart:io): Convert these to instance methods where possible.
165 static bool Initialize();
166 static intptr_t Available(intptr_t fd);
167 static intptr_t Read(intptr_t fd,
168 void* buffer,
169 intptr_t num_bytes,
170 SocketOpKind sync);
171 static intptr_t Write(intptr_t fd,
172 const void* buffer,
173 intptr_t num_bytes,
174 SocketOpKind sync);
175 // Send data on a socket. The port to send to is specified in the port
176 // component of the passed RawAddr structure. The RawAddr structure is only
177 // used for datagram sockets.
178 static intptr_t SendTo(intptr_t fd,
179 const void* buffer,
180 intptr_t num_bytes,
181 const RawAddr& addr,
182 SocketOpKind sync);
183 static intptr_t RecvFrom(intptr_t fd,
184 void* buffer,
185 intptr_t num_bytes,
186 RawAddr* addr,
187 SocketOpKind sync);
188 static bool AvailableDatagram(intptr_t fd, void* buffer, intptr_t num_bytes);
189 // Returns true if the given error-number is because the system was not able
190 // to bind the socket to a specific IP.
191 static bool IsBindError(intptr_t error_number);
192 static intptr_t GetPort(intptr_t fd);
193 static SocketAddress* GetRemotePeer(intptr_t fd, intptr_t* port);
194 static void GetError(intptr_t fd, OSError* os_error);
195 static int GetType(intptr_t fd);
196 static intptr_t GetStdioHandle(intptr_t num);
197 static void Close(intptr_t fd);
198 static bool GetNoDelay(intptr_t fd, bool* enabled);
199 static bool SetNoDelay(intptr_t fd, bool enabled);
200 static bool GetMulticastLoop(intptr_t fd, intptr_t protocol, bool* enabled);
201 static bool SetMulticastLoop(intptr_t fd, intptr_t protocol, bool enabled);
202 static bool GetMulticastHops(intptr_t fd, intptr_t protocol, int* value);
203 static bool SetMulticastHops(intptr_t fd, intptr_t protocol, int value);
204 static bool GetBroadcast(intptr_t fd, bool* value);
205 static bool SetBroadcast(intptr_t fd, bool value);
206 static bool GetOption(intptr_t fd,
207 int level,
208 int option,
209 char* data,
210 unsigned int* length);
211 static bool SetOption(intptr_t fd,
212 int level,
213 int option,
214 const char* data,
215 int length);
216 static bool JoinMulticast(intptr_t fd,
217 const RawAddr& addr,
218 const RawAddr& interface,
219 int interfaceIndex);
220 static bool LeaveMulticast(intptr_t fd,
221 const RawAddr& addr,
222 const RawAddr& interface,
223 int interfaceIndex);
224
225 // Perform a hostname lookup. Returns a AddressList of SocketAddress's.
226 static AddressList<SocketAddress>* LookupAddress(const char* host,
227 int type,
228 OSError** os_error);
229
230 static bool ReverseLookup(const RawAddr& addr,
231 char* host,
232 intptr_t host_len,
233 OSError** os_error);
234
235 static bool ParseAddress(int type, const char* address, RawAddr* addr);
236
237 // Convert address from byte representation to human readable string.
238 static bool RawAddrToString(RawAddr* addr, char* str);
239 static bool FormatNumericAddress(const RawAddr& addr, char* address, int len);
240
241 // Whether ListInterfaces is supported.
242 static bool ListInterfacesSupported();
243
244 // List interfaces. Returns a AddressList of InterfaceSocketAddress's.
245 static AddressList<InterfaceSocketAddress>* ListInterfaces(
246 int type,
247 OSError** os_error);
248
249 private:
250 DISALLOW_ALLOCATION();
251 DISALLOW_IMPLICIT_CONSTRUCTORS(SocketBase);
252};
253
254} // namespace bin
255} // namespace dart
256
257#endif // RUNTIME_BIN_SOCKET_BASE_H_
258