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 | |
32 | namespace dart { |
33 | namespace bin { |
34 | |
35 | union 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 | |
43 | class 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 | |
104 | class 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 | |
127 | template <typename T> |
128 | class 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 | |
151 | class 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 | |