OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #ifndef RUNTIME_BIN_SOCKET_H_ | 5 #ifndef RUNTIME_BIN_SOCKET_H_ |
6 #define RUNTIME_BIN_SOCKET_H_ | 6 #define RUNTIME_BIN_SOCKET_H_ |
7 | 7 |
8 #if defined(DART_IO_DISABLED) | 8 #if defined(DART_IO_DISABLED) |
9 #error "socket.h can only be included on builds with IO enabled" | 9 #error "socket.h can only be included on builds with IO enabled" |
10 #endif | 10 #endif |
11 | 11 |
12 #include "platform/globals.h" | |
13 // Declare the OS-specific types ahead of defining the generic class. | |
14 #if defined(HOST_OS_ANDROID) | |
15 #include "bin/socket_android.h" | |
16 #elif defined(HOST_OS_FUCHSIA) | |
17 #include "bin/socket_fuchsia.h" | |
18 #elif defined(HOST_OS_LINUX) | |
19 #include "bin/socket_linux.h" | |
20 #elif defined(HOST_OS_MACOS) | |
21 #include "bin/socket_macos.h" | |
22 #elif defined(HOST_OS_WINDOWS) | |
23 #include "bin/socket_win.h" | |
24 #else | |
25 #error Unknown target os. | |
26 #endif | |
27 | |
28 #include "bin/builtin.h" | 12 #include "bin/builtin.h" |
29 #include "bin/dartutils.h" | 13 #include "bin/dartutils.h" |
30 #include "bin/reference_counting.h" | 14 #include "bin/reference_counting.h" |
| 15 #include "bin/socket_base.h" |
31 #include "bin/thread.h" | 16 #include "bin/thread.h" |
32 #include "bin/utils.h" | 17 #include "bin/utils.h" |
33 #include "platform/hashmap.h" | 18 #include "platform/hashmap.h" |
34 | 19 |
35 namespace dart { | 20 namespace dart { |
36 namespace bin { | 21 namespace bin { |
37 | 22 |
38 union RawAddr { | 23 // TODO(bkonyi): Socket should also inherit from SocketBase once it is |
39 struct sockaddr_in in; | 24 // refactored to use instance methods when possible. |
40 struct sockaddr_in6 in6; | |
41 struct sockaddr_storage ss; | |
42 struct sockaddr addr; | |
43 }; | |
44 | |
45 class SocketAddress { | |
46 public: | |
47 enum { | |
48 TYPE_ANY = -1, | |
49 TYPE_IPV4, | |
50 TYPE_IPV6, | |
51 }; | |
52 | |
53 enum { | |
54 ADDRESS_LOOPBACK_IP_V4, | |
55 ADDRESS_LOOPBACK_IP_V6, | |
56 ADDRESS_ANY_IP_V4, | |
57 ADDRESS_ANY_IP_V6, | |
58 ADDRESS_FIRST = ADDRESS_LOOPBACK_IP_V4, | |
59 ADDRESS_LAST = ADDRESS_ANY_IP_V6, | |
60 }; | |
61 | |
62 explicit SocketAddress(struct sockaddr* sa); | |
63 | |
64 ~SocketAddress() {} | |
65 | |
66 int GetType() { | |
67 if (addr_.ss.ss_family == AF_INET6) { | |
68 return TYPE_IPV6; | |
69 } | |
70 return TYPE_IPV4; | |
71 } | |
72 | |
73 const char* as_string() const { return as_string_; } | |
74 const RawAddr& addr() const { return addr_; } | |
75 | |
76 static intptr_t GetAddrLength(const RawAddr& addr) { | |
77 ASSERT((addr.ss.ss_family == AF_INET) || (addr.ss.ss_family == AF_INET6)); | |
78 return (addr.ss.ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) | |
79 : sizeof(struct sockaddr_in); | |
80 } | |
81 | |
82 static intptr_t GetInAddrLength(const RawAddr& addr) { | |
83 ASSERT((addr.ss.ss_family == AF_INET) || (addr.ss.ss_family == AF_INET6)); | |
84 return (addr.ss.ss_family == AF_INET6) ? sizeof(struct in6_addr) | |
85 : sizeof(struct in_addr); | |
86 } | |
87 | |
88 static bool AreAddressesEqual(const RawAddr& a, const RawAddr& b) { | |
89 if (a.ss.ss_family == AF_INET) { | |
90 if (b.ss.ss_family != AF_INET) { | |
91 return false; | |
92 } | |
93 return memcmp(&a.in.sin_addr, &b.in.sin_addr, sizeof(a.in.sin_addr)) == 0; | |
94 } else if (a.ss.ss_family == AF_INET6) { | |
95 if (b.ss.ss_family != AF_INET6) { | |
96 return false; | |
97 } | |
98 return memcmp(&a.in6.sin6_addr, &b.in6.sin6_addr, | |
99 sizeof(a.in6.sin6_addr)) == 0; | |
100 } else { | |
101 UNREACHABLE(); | |
102 return false; | |
103 } | |
104 } | |
105 | |
106 static void GetSockAddr(Dart_Handle obj, RawAddr* addr) { | |
107 Dart_TypedData_Type data_type; | |
108 uint8_t* data = NULL; | |
109 intptr_t len; | |
110 Dart_Handle result = Dart_TypedDataAcquireData( | |
111 obj, &data_type, reinterpret_cast<void**>(&data), &len); | |
112 if (Dart_IsError(result)) { | |
113 Dart_PropagateError(result); | |
114 } | |
115 if ((data_type != Dart_TypedData_kUint8) || | |
116 ((len != sizeof(in_addr)) && (len != sizeof(in6_addr)))) { | |
117 Dart_PropagateError( | |
118 Dart_NewApiError("Unexpected type for socket address")); | |
119 } | |
120 memset(reinterpret_cast<void*>(addr), 0, sizeof(RawAddr)); | |
121 if (len == sizeof(in_addr)) { | |
122 addr->in.sin_family = AF_INET; | |
123 memmove(reinterpret_cast<void*>(&addr->in.sin_addr), data, len); | |
124 } else { | |
125 ASSERT(len == sizeof(in6_addr)); | |
126 addr->in6.sin6_family = AF_INET6; | |
127 memmove(reinterpret_cast<void*>(&addr->in6.sin6_addr), data, len); | |
128 } | |
129 Dart_TypedDataReleaseData(obj); | |
130 } | |
131 | |
132 static int16_t FromType(int type) { | |
133 if (type == TYPE_ANY) { | |
134 return AF_UNSPEC; | |
135 } | |
136 if (type == TYPE_IPV4) { | |
137 return AF_INET; | |
138 } | |
139 ASSERT((type == TYPE_IPV6) && "Invalid type"); | |
140 return AF_INET6; | |
141 } | |
142 | |
143 static void SetAddrPort(RawAddr* addr, intptr_t port) { | |
144 if (addr->ss.ss_family == AF_INET) { | |
145 addr->in.sin_port = htons(port); | |
146 } else { | |
147 addr->in6.sin6_port = htons(port); | |
148 } | |
149 } | |
150 | |
151 static intptr_t GetAddrPort(const RawAddr& addr) { | |
152 if (addr.ss.ss_family == AF_INET) { | |
153 return ntohs(addr.in.sin_port); | |
154 } else { | |
155 return ntohs(addr.in6.sin6_port); | |
156 } | |
157 } | |
158 | |
159 static Dart_Handle ToTypedData(const RawAddr& addr) { | |
160 int len = GetInAddrLength(addr); | |
161 Dart_Handle result = Dart_NewTypedData(Dart_TypedData_kUint8, len); | |
162 if (Dart_IsError(result)) { | |
163 Dart_PropagateError(result); | |
164 } | |
165 Dart_Handle err; | |
166 if (addr.addr.sa_family == AF_INET6) { | |
167 err = Dart_ListSetAsBytes( | |
168 result, 0, reinterpret_cast<const uint8_t*>(&addr.in6.sin6_addr), | |
169 len); | |
170 } else { | |
171 err = Dart_ListSetAsBytes( | |
172 result, 0, reinterpret_cast<const uint8_t*>(&addr.in.sin_addr), len); | |
173 } | |
174 if (Dart_IsError(err)) { | |
175 Dart_PropagateError(err); | |
176 } | |
177 return result; | |
178 } | |
179 | |
180 static CObjectUint8Array* ToCObject(const RawAddr& addr) { | |
181 int in_addr_len = SocketAddress::GetInAddrLength(addr); | |
182 const void* in_addr; | |
183 CObjectUint8Array* data = | |
184 new CObjectUint8Array(CObject::NewUint8Array(in_addr_len)); | |
185 if (addr.addr.sa_family == AF_INET6) { | |
186 in_addr = reinterpret_cast<const void*>(&addr.in6.sin6_addr); | |
187 } else { | |
188 in_addr = reinterpret_cast<const void*>(&addr.in.sin_addr); | |
189 } | |
190 memmove(data->Buffer(), in_addr, in_addr_len); | |
191 return data; | |
192 } | |
193 | |
194 private: | |
195 char as_string_[INET6_ADDRSTRLEN]; | |
196 RawAddr addr_; | |
197 | |
198 DISALLOW_COPY_AND_ASSIGN(SocketAddress); | |
199 }; | |
200 | |
201 | |
202 class InterfaceSocketAddress { | |
203 public: | |
204 InterfaceSocketAddress(struct sockaddr* sa, | |
205 const char* interface_name, | |
206 intptr_t interface_index) | |
207 : socket_address_(new SocketAddress(sa)), | |
208 interface_name_(interface_name), | |
209 interface_index_(interface_index) {} | |
210 | |
211 ~InterfaceSocketAddress() { delete socket_address_; } | |
212 | |
213 SocketAddress* socket_address() const { return socket_address_; } | |
214 const char* interface_name() const { return interface_name_; } | |
215 int interface_index() const { return interface_index_; } | |
216 | |
217 private: | |
218 SocketAddress* socket_address_; | |
219 const char* interface_name_; | |
220 intptr_t interface_index_; | |
221 | |
222 DISALLOW_COPY_AND_ASSIGN(InterfaceSocketAddress); | |
223 }; | |
224 | |
225 | |
226 template <typename T> | |
227 class AddressList { | |
228 public: | |
229 explicit AddressList(intptr_t count) | |
230 : count_(count), addresses_(new T*[count_]) {} | |
231 | |
232 ~AddressList() { | |
233 for (intptr_t i = 0; i < count_; i++) { | |
234 delete addresses_[i]; | |
235 } | |
236 delete[] addresses_; | |
237 } | |
238 | |
239 intptr_t count() const { return count_; } | |
240 T* GetAt(intptr_t i) const { return addresses_[i]; } | |
241 void SetAt(intptr_t i, T* addr) { addresses_[i] = addr; } | |
242 | |
243 private: | |
244 const intptr_t count_; | |
245 T** addresses_; | |
246 | |
247 DISALLOW_COPY_AND_ASSIGN(AddressList); | |
248 }; | |
249 | |
250 | 25 |
251 // We write Sockets into the native field of the _NativeSocket object | 26 // We write Sockets into the native field of the _NativeSocket object |
252 // on the Dart side. They are allocated in SetSocketIdNativeField(), and are | 27 // on the Dart side. They are allocated in SetSocketIdNativeField(), and are |
253 // deallocated either from the finalizer attached to _NativeSockets there, or | 28 // deallocated either from the finalizer attached to _NativeSockets there, or |
254 // from the eventhandler, whichever drops the last reference. | 29 // from the eventhandler, whichever drops the last reference. |
255 class Socket : public ReferenceCounted<Socket> { | 30 class Socket : public ReferenceCounted<Socket> { |
256 public: | 31 public: |
257 enum SocketRequest { | 32 enum SocketRequest { |
258 kLookupRequest = 0, | 33 kLookupRequest = 0, |
259 kListInterfacesRequest = 1, | 34 kListInterfacesRequest = 1, |
260 kReverseLookupRequest = 2, | 35 kReverseLookupRequest = 2, |
261 }; | 36 }; |
262 | 37 |
263 enum SocketFinalizer { | 38 enum SocketFinalizer { |
264 kFinalizerNormal, | 39 kFinalizerNormal, |
265 kFinalizerListening, | 40 kFinalizerListening, |
266 kFinalizerStdio, | 41 kFinalizerStdio, |
267 }; | 42 }; |
268 | 43 |
269 explicit Socket(intptr_t fd); | 44 explicit Socket(intptr_t fd); |
270 | 45 |
271 intptr_t fd() const { return fd_; } | 46 intptr_t fd() const { return fd_; } |
272 void SetClosedFd(); | 47 void SetClosedFd(); |
273 | 48 |
274 Dart_Port port() const { return port_; } | 49 Dart_Port port() const { return port_; } |
275 void set_port(Dart_Port port) { port_ = port; } | 50 void set_port(Dart_Port port) { port_ = port; } |
276 | 51 |
277 // TODO(dart:io): Convert these to instance methods where possible. | |
278 static bool Initialize(); | 52 static bool Initialize(); |
279 static intptr_t Available(intptr_t fd); | 53 |
280 static intptr_t Read(intptr_t fd, void* buffer, intptr_t num_bytes); | |
281 static intptr_t Write(intptr_t fd, const void* buffer, intptr_t num_bytes); | |
282 // Send data on a socket. The port to send to is specified in the port | |
283 // component of the passed RawAddr structure. The RawAddr structure is only | |
284 // used for datagram sockets. | |
285 static intptr_t SendTo(intptr_t fd, | |
286 const void* buffer, | |
287 intptr_t num_bytes, | |
288 const RawAddr& addr); | |
289 static intptr_t RecvFrom(intptr_t fd, | |
290 void* buffer, | |
291 intptr_t num_bytes, | |
292 RawAddr* addr); | |
293 // Creates a socket which is bound and connected. The port to connect to is | 54 // Creates a socket which is bound and connected. The port to connect to is |
294 // specified as the port component of the passed RawAddr structure. | 55 // specified as the port component of the passed RawAddr structure. |
295 static intptr_t CreateConnect(const RawAddr& addr); | 56 static intptr_t CreateConnect(const RawAddr& addr); |
296 // Creates a socket which is bound and connected. The port to connect to is | 57 // Creates a socket which is bound and connected. The port to connect to is |
297 // specified as the port component of the passed RawAddr structure. | 58 // specified as the port component of the passed RawAddr structure. |
298 static intptr_t CreateBindConnect(const RawAddr& addr, | 59 static intptr_t CreateBindConnect(const RawAddr& addr, |
299 const RawAddr& source_addr); | 60 const RawAddr& source_addr); |
300 // Returns true if the given error-number is because the system was not able | |
301 // to bind the socket to a specific IP. | |
302 static bool IsBindError(intptr_t error_number); | |
303 // Creates a datagram socket which is bound. The port to bind | 61 // Creates a datagram socket which is bound. The port to bind |
304 // to is specified as the port component of the RawAddr structure. | 62 // to is specified as the port component of the RawAddr structure. |
305 static intptr_t CreateBindDatagram(const RawAddr& addr, bool reuseAddress); | 63 static intptr_t CreateBindDatagram(const RawAddr& addr, bool reuseAddress); |
306 static intptr_t GetPort(intptr_t fd); | |
307 static SocketAddress* GetRemotePeer(intptr_t fd, intptr_t* port); | |
308 static void GetError(intptr_t fd, OSError* os_error); | |
309 static int GetType(intptr_t fd); | |
310 static intptr_t GetStdioHandle(intptr_t num); | |
311 static void Close(intptr_t fd); | |
312 static bool GetNoDelay(intptr_t fd, bool* enabled); | |
313 static bool SetNoDelay(intptr_t fd, bool enabled); | |
314 static bool GetMulticastLoop(intptr_t fd, intptr_t protocol, bool* enabled); | |
315 static bool SetMulticastLoop(intptr_t fd, intptr_t protocol, bool enabled); | |
316 static bool GetMulticastHops(intptr_t fd, intptr_t protocol, int* value); | |
317 static bool SetMulticastHops(intptr_t fd, intptr_t protocol, int value); | |
318 static bool GetBroadcast(intptr_t fd, bool* value); | |
319 static bool SetBroadcast(intptr_t fd, bool value); | |
320 static bool JoinMulticast(intptr_t fd, | |
321 const RawAddr& addr, | |
322 const RawAddr& interface, | |
323 int interfaceIndex); | |
324 static bool LeaveMulticast(intptr_t fd, | |
325 const RawAddr& addr, | |
326 const RawAddr& interface, | |
327 int interfaceIndex); | |
328 | |
329 // Perform a hostname lookup. Returns a AddressList of SocketAddress's. | |
330 static AddressList<SocketAddress>* LookupAddress(const char* host, | |
331 int type, | |
332 OSError** os_error); | |
333 | |
334 static bool ReverseLookup(const RawAddr& addr, | |
335 char* host, | |
336 intptr_t host_len, | |
337 OSError** os_error); | |
338 | |
339 static bool ParseAddress(int type, const char* address, RawAddr* addr); | |
340 static bool FormatNumericAddress(const RawAddr& addr, char* address, int len); | |
341 | |
342 // Whether ListInterfaces is supported. | |
343 static bool ListInterfacesSupported(); | |
344 | |
345 // List interfaces. Returns a AddressList of InterfaceSocketAddress's. | |
346 static AddressList<InterfaceSocketAddress>* ListInterfaces( | |
347 int type, | |
348 OSError** os_error); | |
349 | 64 |
350 static CObject* LookupRequest(const CObjectArray& request); | 65 static CObject* LookupRequest(const CObjectArray& request); |
351 static CObject* ListInterfacesRequest(const CObjectArray& request); | 66 static CObject* ListInterfacesRequest(const CObjectArray& request); |
352 static CObject* ReverseLookupRequest(const CObjectArray& request); | 67 static CObject* ReverseLookupRequest(const CObjectArray& request); |
353 | 68 |
354 static Dart_Port GetServicePort(); | 69 static Dart_Port GetServicePort(); |
355 | 70 |
356 static void SetSocketIdNativeField(Dart_Handle handle, | 71 static void SetSocketIdNativeField(Dart_Handle handle, |
357 intptr_t id, | 72 intptr_t id, |
358 SocketFinalizer finalizer); | 73 SocketFinalizer finalizer); |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
509 | 224 |
510 Mutex* mutex_; | 225 Mutex* mutex_; |
511 | 226 |
512 DISALLOW_COPY_AND_ASSIGN(ListeningSocketRegistry); | 227 DISALLOW_COPY_AND_ASSIGN(ListeningSocketRegistry); |
513 }; | 228 }; |
514 | 229 |
515 } // namespace bin | 230 } // namespace bin |
516 } // namespace dart | 231 } // namespace dart |
517 | 232 |
518 #endif // RUNTIME_BIN_SOCKET_H_ | 233 #endif // RUNTIME_BIN_SOCKET_H_ |
OLD | NEW |