OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 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 | 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_BASE_H_ |
6 #define RUNTIME_BIN_SOCKET_H_ | 6 #define RUNTIME_BIN_SOCKET_BASE_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_base.h can only be included on builds with IO enabled" |
10 #endif | 10 #endif |
11 | 11 |
12 #include "platform/globals.h" | 12 #include "platform/globals.h" |
13 // Declare the OS-specific types ahead of defining the generic class. | 13 // Declare the OS-specific types ahead of defining the generic class. |
14 #if defined(HOST_OS_ANDROID) | 14 #if defined(HOST_OS_ANDROID) |
15 #include "bin/socket_android.h" | 15 #include "bin/socket_base_android.h" |
16 #elif defined(HOST_OS_FUCHSIA) | 16 #elif defined(HOST_OS_FUCHSIA) |
17 #include "bin/socket_fuchsia.h" | 17 #include "bin/socket_base_fuchsia.h" |
18 #elif defined(HOST_OS_LINUX) | 18 #elif defined(HOST_OS_LINUX) |
19 #include "bin/socket_linux.h" | 19 #include "bin/socket_base_linux.h" |
20 #elif defined(HOST_OS_MACOS) | 20 #elif defined(HOST_OS_MACOS) |
21 #include "bin/socket_macos.h" | 21 #include "bin/socket_base_macos.h" |
22 #elif defined(HOST_OS_WINDOWS) | 22 #elif defined(HOST_OS_WINDOWS) |
23 #include "bin/socket_win.h" | 23 #include "bin/socket_base_win.h" |
24 #else | 24 #else |
25 #error Unknown target os. | 25 #error Unknown target os. |
26 #endif | 26 #endif |
27 | 27 |
28 #include "bin/builtin.h" | 28 #include "bin/builtin.h" |
29 #include "bin/dartutils.h" | 29 #include "bin/dartutils.h" |
30 #include "bin/reference_counting.h" | |
31 #include "bin/thread.h" | 30 #include "bin/thread.h" |
32 #include "bin/utils.h" | 31 #include "bin/utils.h" |
| 32 #include "platform/allocation.h" |
33 #include "platform/hashmap.h" | 33 #include "platform/hashmap.h" |
34 | 34 |
35 namespace dart { | 35 namespace dart { |
36 namespace bin { | 36 namespace bin { |
37 | 37 |
38 union RawAddr { | 38 union RawAddr { |
39 struct sockaddr_in in; | 39 struct sockaddr_in in; |
40 struct sockaddr_in6 in6; | 40 struct sockaddr_in6 in6; |
41 struct sockaddr_storage ss; | 41 struct sockaddr_storage ss; |
42 struct sockaddr addr; | 42 struct sockaddr addr; |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 T* GetAt(intptr_t i) const { return addresses_[i]; } | 240 T* GetAt(intptr_t i) const { return addresses_[i]; } |
241 void SetAt(intptr_t i, T* addr) { addresses_[i] = addr; } | 241 void SetAt(intptr_t i, T* addr) { addresses_[i] = addr; } |
242 | 242 |
243 private: | 243 private: |
244 const intptr_t count_; | 244 const intptr_t count_; |
245 T** addresses_; | 245 T** addresses_; |
246 | 246 |
247 DISALLOW_COPY_AND_ASSIGN(AddressList); | 247 DISALLOW_COPY_AND_ASSIGN(AddressList); |
248 }; | 248 }; |
249 | 249 |
250 | 250 class SocketBase : public AllStatic { |
251 // We write Sockets into the native field of the _NativeSocket object | |
252 // on the Dart side. They are allocated in SetSocketIdNativeField(), and are | |
253 // deallocated either from the finalizer attached to _NativeSockets there, or | |
254 // from the eventhandler, whichever drops the last reference. | |
255 class Socket : public ReferenceCounted<Socket> { | |
256 public: | 251 public: |
257 enum SocketRequest { | 252 enum SocketRequest { |
258 kLookupRequest = 0, | 253 kLookupRequest = 0, |
259 kListInterfacesRequest = 1, | 254 kListInterfacesRequest = 1, |
260 kReverseLookupRequest = 2, | 255 kReverseLookupRequest = 2, |
261 }; | 256 }; |
262 | 257 |
263 enum SocketFinalizer { | |
264 kFinalizerNormal, | |
265 kFinalizerListening, | |
266 kFinalizerStdio, | |
267 }; | |
268 | |
269 explicit Socket(intptr_t fd); | |
270 | |
271 intptr_t fd() const { return fd_; } | |
272 void SetClosedFd(); | |
273 | |
274 Dart_Port port() const { return port_; } | |
275 void set_port(Dart_Port port) { port_ = port; } | |
276 | |
277 // TODO(dart:io): Convert these to instance methods where possible. | 258 // TODO(dart:io): Convert these to instance methods where possible. |
278 static bool Initialize(); | 259 static bool Initialize(); |
279 static intptr_t Available(intptr_t fd); | 260 static intptr_t Available(intptr_t fd); |
280 static intptr_t Read(intptr_t fd, void* buffer, intptr_t num_bytes); | 261 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); | 262 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 | 263 // 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 | 264 // component of the passed RawAddr structure. The RawAddr structure is only |
284 // used for datagram sockets. | 265 // used for datagram sockets. |
285 static intptr_t SendTo(intptr_t fd, | 266 static intptr_t SendTo(intptr_t fd, |
286 const void* buffer, | 267 const void* buffer, |
287 intptr_t num_bytes, | 268 intptr_t num_bytes, |
288 const RawAddr& addr); | 269 const RawAddr& addr); |
289 static intptr_t RecvFrom(intptr_t fd, | 270 static intptr_t RecvFrom(intptr_t fd, |
290 void* buffer, | 271 void* buffer, |
291 intptr_t num_bytes, | 272 intptr_t num_bytes, |
292 RawAddr* addr); | 273 RawAddr* addr); |
293 // 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. | |
295 static intptr_t CreateConnect(const RawAddr& addr); | |
296 // 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. | |
298 static intptr_t CreateBindConnect(const RawAddr& addr, | |
299 const RawAddr& source_addr); | |
300 // Returns true if the given error-number is because the system was not able | 274 // Returns true if the given error-number is because the system was not able |
301 // to bind the socket to a specific IP. | 275 // to bind the socket to a specific IP. |
302 static bool IsBindError(intptr_t error_number); | 276 static bool IsBindError(intptr_t error_number); |
303 // Creates a datagram socket which is bound. The port to bind | |
304 // to is specified as the port component of the RawAddr structure. | |
305 static intptr_t CreateBindDatagram(const RawAddr& addr, bool reuseAddress); | |
306 static intptr_t GetPort(intptr_t fd); | 277 static intptr_t GetPort(intptr_t fd); |
307 static SocketAddress* GetRemotePeer(intptr_t fd, intptr_t* port); | 278 static SocketAddress* GetRemotePeer(intptr_t fd, intptr_t* port); |
308 static void GetError(intptr_t fd, OSError* os_error); | 279 static void GetError(intptr_t fd, OSError* os_error); |
309 static int GetType(intptr_t fd); | 280 static int GetType(intptr_t fd); |
310 static intptr_t GetStdioHandle(intptr_t num); | 281 static intptr_t GetStdioHandle(intptr_t num); |
311 static void Close(intptr_t fd); | 282 static void Close(intptr_t fd); |
312 static bool GetNoDelay(intptr_t fd, bool* enabled); | 283 static bool GetNoDelay(intptr_t fd, bool* enabled); |
313 static bool SetNoDelay(intptr_t fd, bool enabled); | 284 static bool SetNoDelay(intptr_t fd, bool enabled); |
314 static bool GetMulticastLoop(intptr_t fd, intptr_t protocol, bool* enabled); | 285 static bool GetMulticastLoop(intptr_t fd, intptr_t protocol, bool* enabled); |
315 static bool SetMulticastLoop(intptr_t fd, intptr_t protocol, bool enabled); | 286 static bool SetMulticastLoop(intptr_t fd, intptr_t protocol, bool enabled); |
(...skipping 24 matching lines...) Expand all Loading... |
340 static bool FormatNumericAddress(const RawAddr& addr, char* address, int len); | 311 static bool FormatNumericAddress(const RawAddr& addr, char* address, int len); |
341 | 312 |
342 // Whether ListInterfaces is supported. | 313 // Whether ListInterfaces is supported. |
343 static bool ListInterfacesSupported(); | 314 static bool ListInterfacesSupported(); |
344 | 315 |
345 // List interfaces. Returns a AddressList of InterfaceSocketAddress's. | 316 // List interfaces. Returns a AddressList of InterfaceSocketAddress's. |
346 static AddressList<InterfaceSocketAddress>* ListInterfaces( | 317 static AddressList<InterfaceSocketAddress>* ListInterfaces( |
347 int type, | 318 int type, |
348 OSError** os_error); | 319 OSError** os_error); |
349 | 320 |
350 static CObject* LookupRequest(const CObjectArray& request); | |
351 static CObject* ListInterfacesRequest(const CObjectArray& request); | |
352 static CObject* ReverseLookupRequest(const CObjectArray& request); | |
353 | |
354 static Dart_Port GetServicePort(); | |
355 | |
356 static void SetSocketIdNativeField(Dart_Handle handle, | |
357 intptr_t id, | |
358 SocketFinalizer finalizer); | |
359 static void ReuseSocketIdNativeField(Dart_Handle handle, | |
360 Socket* socket, | |
361 SocketFinalizer finalizer); | |
362 static Socket* GetSocketIdNativeField(Dart_Handle socket); | |
363 | |
364 private: | |
365 ~Socket() { ASSERT(fd_ == kClosedFd); } | |
366 | |
367 static const int kClosedFd = -1; | |
368 | |
369 intptr_t fd_; | |
370 Dart_Port port_; | |
371 | |
372 friend class ReferenceCounted<Socket>; | |
373 DISALLOW_COPY_AND_ASSIGN(Socket); | |
374 }; | |
375 | |
376 | |
377 class ServerSocket { | |
378 public: | |
379 static const intptr_t kTemporaryFailure = -2; | |
380 | |
381 static intptr_t Accept(intptr_t fd); | |
382 | |
383 // Creates a socket which is bound and listens. The port to listen on is | |
384 // specified in the port component of the passed RawAddr structure. | |
385 // | |
386 // Returns a positive integer if the call is successful. In case of failure | |
387 // it returns: | |
388 // | |
389 // -1: system error (errno set) | |
390 // -5: invalid bindAddress | |
391 static intptr_t CreateBindListen(const RawAddr& addr, | |
392 intptr_t backlog, | |
393 bool v6_only = false); | |
394 | |
395 // Start accepting on a newly created listening socket. If it was unable to | |
396 // start accepting incoming sockets, the fd is invalidated. | |
397 static bool StartAccept(intptr_t fd); | |
398 | |
399 private: | 321 private: |
400 DISALLOW_ALLOCATION(); | 322 DISALLOW_ALLOCATION(); |
401 DISALLOW_IMPLICIT_CONSTRUCTORS(ServerSocket); | 323 DISALLOW_IMPLICIT_CONSTRUCTORS(SocketBase); |
402 }; | |
403 | |
404 | |
405 class ListeningSocketRegistry { | |
406 public: | |
407 ListeningSocketRegistry() | |
408 : sockets_by_port_(SameIntptrValue, kInitialSocketsCount), | |
409 sockets_by_fd_(SameIntptrValue, kInitialSocketsCount), | |
410 mutex_(new Mutex()) {} | |
411 | |
412 ~ListeningSocketRegistry() { | |
413 CloseAllSafe(); | |
414 delete mutex_; | |
415 mutex_ = NULL; | |
416 } | |
417 | |
418 static void Initialize(); | |
419 | |
420 static ListeningSocketRegistry* Instance(); | |
421 | |
422 static void Cleanup(); | |
423 | |
424 // This function should be called from a dart runtime call in order to create | |
425 // a new (potentially shared) socket. | |
426 Dart_Handle CreateBindListen(Dart_Handle socket_object, | |
427 RawAddr addr, | |
428 intptr_t backlog, | |
429 bool v6_only, | |
430 bool shared); | |
431 | |
432 // This should be called from the event handler for every kCloseEvent it gets | |
433 // on listening sockets. | |
434 // | |
435 // Returns `true` if the last reference has been dropped and the underlying | |
436 // socket can be closed. | |
437 // | |
438 // The caller is responsible for obtaining the mutex first, before calling | |
439 // this function. | |
440 bool CloseSafe(Socket* socketfd); | |
441 | |
442 Mutex* mutex() { return mutex_; } | |
443 | |
444 private: | |
445 struct OSSocket { | |
446 RawAddr address; | |
447 int port; | |
448 bool v6_only; | |
449 bool shared; | |
450 int ref_count; | |
451 Socket* socketfd; | |
452 | |
453 // Singly linked lists of OSSocket instances which listen on the same port | |
454 // but on different addresses. | |
455 OSSocket* next; | |
456 | |
457 OSSocket(RawAddr address, | |
458 int port, | |
459 bool v6_only, | |
460 bool shared, | |
461 Socket* socketfd) | |
462 : address(address), | |
463 port(port), | |
464 v6_only(v6_only), | |
465 shared(shared), | |
466 ref_count(0), | |
467 socketfd(socketfd), | |
468 next(NULL) {} | |
469 }; | |
470 | |
471 static const intptr_t kInitialSocketsCount = 8; | |
472 | |
473 OSSocket* FindOSSocketWithAddress(OSSocket* current, const RawAddr& addr) { | |
474 while (current != NULL) { | |
475 if (SocketAddress::AreAddressesEqual(current->address, addr)) { | |
476 return current; | |
477 } | |
478 current = current->next; | |
479 } | |
480 return NULL; | |
481 } | |
482 | |
483 static bool SameIntptrValue(void* key1, void* key2) { | |
484 return reinterpret_cast<intptr_t>(key1) == reinterpret_cast<intptr_t>(key2); | |
485 } | |
486 | |
487 static uint32_t GetHashmapHashFromIntptr(intptr_t i) { | |
488 return static_cast<uint32_t>((i + 1) & 0xFFFFFFFF); | |
489 } | |
490 | |
491 | |
492 static void* GetHashmapKeyFromIntptr(intptr_t i) { | |
493 return reinterpret_cast<void*>(i + 1); | |
494 } | |
495 | |
496 OSSocket* LookupByPort(intptr_t port); | |
497 void InsertByPort(intptr_t port, OSSocket* socket); | |
498 void RemoveByPort(intptr_t port); | |
499 | |
500 OSSocket* LookupByFd(Socket* fd); | |
501 void InsertByFd(Socket* fd, OSSocket* socket); | |
502 void RemoveByFd(Socket* fd); | |
503 | |
504 bool CloseOneSafe(OSSocket* os_socket, bool update_hash_maps); | |
505 void CloseAllSafe(); | |
506 | |
507 HashMap sockets_by_port_; | |
508 HashMap sockets_by_fd_; | |
509 | |
510 Mutex* mutex_; | |
511 | |
512 DISALLOW_COPY_AND_ASSIGN(ListeningSocketRegistry); | |
513 }; | 324 }; |
514 | 325 |
515 } // namespace bin | 326 } // namespace bin |
516 } // namespace dart | 327 } // namespace dart |
517 | 328 |
518 #endif // RUNTIME_BIN_SOCKET_H_ | 329 #endif // RUNTIME_BIN_SOCKET_BASE_H_ |
OLD | NEW |