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 #include "bin/io_buffer.h" | 5 #include "bin/io_buffer.h" |
6 #include "bin/isolate_data.h" | 6 #include "bin/isolate_data.h" |
7 #include "bin/dartutils.h" | 7 #include "bin/dartutils.h" |
8 #include "bin/socket.h" | 8 #include "bin/socket.h" |
9 #include "bin/thread.h" | 9 #include "bin/thread.h" |
| 10 #include "bin/lockers.h" |
10 #include "bin/utils.h" | 11 #include "bin/utils.h" |
11 | 12 |
12 #include "platform/globals.h" | 13 #include "platform/globals.h" |
13 #include "platform/utils.h" | 14 #include "platform/utils.h" |
14 | 15 |
15 #include "include/dart_api.h" | 16 #include "include/dart_api.h" |
16 | 17 |
17 namespace dart { | 18 namespace dart { |
18 namespace bin { | 19 namespace bin { |
19 | 20 |
20 static const int kSocketIdNativeField = 0; | 21 static const int kSocketIdNativeField = 0; |
21 | 22 |
| 23 |
| 24 ListeningSocketRegistry *globalTcpListeningSocketRegistry = NULL; |
| 25 |
| 26 |
| 27 void ListeningSocketRegistry::Initialize() { |
| 28 ASSERT(globalTcpListeningSocketRegistry == NULL); |
| 29 globalTcpListeningSocketRegistry = new ListeningSocketRegistry(); |
| 30 } |
| 31 |
| 32 |
| 33 ListeningSocketRegistry *ListeningSocketRegistry::Instance() { |
| 34 return globalTcpListeningSocketRegistry; |
| 35 } |
| 36 |
| 37 |
| 38 void ListeningSocketRegistry::Cleanup() { |
| 39 delete globalTcpListeningSocketRegistry; |
| 40 globalTcpListeningSocketRegistry = NULL; |
| 41 } |
| 42 |
| 43 |
| 44 Dart_Handle ListeningSocketRegistry::CreateBindListen(Dart_Handle socket_object, |
| 45 RawAddr addr, |
| 46 intptr_t port, |
| 47 intptr_t backlog, |
| 48 bool v6_only, |
| 49 bool shared) { |
| 50 MutexLocker ml(ListeningSocketRegistry::mutex_); |
| 51 |
| 52 SocketsIterator it = sockets_by_port_.find(port); |
| 53 OSSocket *first_os_socket = NULL; |
| 54 if (it != sockets_by_port_.end()) { |
| 55 first_os_socket = it->second; |
| 56 } |
| 57 |
| 58 if (first_os_socket != NULL) { |
| 59 // There is already a socket listening on this port. We need to ensure |
| 60 // that if there is one also listening on the same address, it was created |
| 61 // with `shared = true`, ... |
| 62 |
| 63 OSSocket *os_socket = it->second; |
| 64 OSSocket *os_socket_same_addr = findOSSocketWithAddress(os_socket, addr); |
| 65 |
| 66 if (os_socket_same_addr != NULL) { |
| 67 if (!os_socket_same_addr->shared || !shared) { |
| 68 OSError os_error(-1, |
| 69 "The shared flag to bind() needs to be `true` if " |
| 70 "binding multiple times on the same (address, port) " |
| 71 "combination.", |
| 72 OSError::kUnknown); |
| 73 return DartUtils::NewDartOSError(&os_error); |
| 74 } |
| 75 if (os_socket_same_addr->v6_only != v6_only) { |
| 76 OSError os_error(-1, |
| 77 "The v6Only flag to bind() needs to be the same if " |
| 78 "binding multiple times on the same (address, port) " |
| 79 "combination.", |
| 80 OSError::kUnknown); |
| 81 return DartUtils::NewDartOSError(&os_error); |
| 82 } |
| 83 |
| 84 // This socket creation is the exact same as the one which originally |
| 85 // created the socket. We therefore increment the refcount and reuse |
| 86 // the file descriptor. |
| 87 os_socket->ref_count++; |
| 88 |
| 89 // We set as a side-effect the file descriptor on the dart socket_object. |
| 90 Socket::SetSocketIdNativeField(socket_object, os_socket->socketfd); |
| 91 |
| 92 return Dart_True(); |
| 93 } |
| 94 } |
| 95 |
| 96 // There is no socket listening on that (address, port), so we create new one. |
| 97 intptr_t socketfd = ServerSocket::CreateBindListen( |
| 98 addr, port, backlog, v6_only); |
| 99 if (socketfd == -5) { |
| 100 OSError os_error(-1, "Invalid host", OSError::kUnknown); |
| 101 return DartUtils::NewDartOSError(&os_error); |
| 102 } |
| 103 if (socketfd < 0) { |
| 104 OSError error; |
| 105 return DartUtils::NewDartOSError(&error); |
| 106 } |
| 107 if (!ServerSocket::StartAccept(socketfd)) { |
| 108 OSError os_error(-1, "Failed to start accept", OSError::kUnknown); |
| 109 return DartUtils::NewDartOSError(&os_error); |
| 110 } |
| 111 intptr_t allocated_port = Socket::GetPort(socketfd); |
| 112 ASSERT(allocated_port > 0); |
| 113 |
| 114 OSSocket *os_socket = |
| 115 new OSSocket(addr, allocated_port, v6_only, shared, socketfd); |
| 116 os_socket->ref_count = 1; |
| 117 os_socket->next = first_os_socket; |
| 118 sockets_by_port_[allocated_port] = os_socket; |
| 119 sockets_by_fd_[socketfd] = os_socket; |
| 120 |
| 121 // We set as a side-effect the port on the dart socket_object. |
| 122 Socket::SetSocketIdNativeField(socket_object, socketfd); |
| 123 |
| 124 return Dart_True(); |
| 125 } |
| 126 |
| 127 |
| 128 bool ListeningSocketRegistry::CloseSafe(intptr_t socketfd) { |
| 129 ASSERT(!mutex_->TryLock()); |
| 130 |
| 131 SocketsIterator it = sockets_by_fd_.find(socketfd); |
| 132 if (it != sockets_by_fd_.end()) { |
| 133 OSSocket *os_socket = it->second; |
| 134 |
| 135 ASSERT(os_socket->ref_count > 0); |
| 136 os_socket->ref_count--; |
| 137 if (os_socket->ref_count == 0) { |
| 138 // We free the OS socket by removing it from two datastructures. |
| 139 sockets_by_fd_.erase(socketfd); |
| 140 |
| 141 OSSocket *prev = NULL; |
| 142 OSSocket *current = sockets_by_port_[os_socket->port]; |
| 143 while (current != os_socket) { |
| 144 ASSERT(current != NULL); |
| 145 prev = current; |
| 146 current = current->next; |
| 147 } |
| 148 |
| 149 if (prev == NULL && current->next == NULL) { |
| 150 // Remove last element from the list. |
| 151 sockets_by_port_.erase(os_socket->port); |
| 152 } else if (prev == NULL) { |
| 153 // Remove first element of the list. |
| 154 sockets_by_port_[os_socket->port] = current->next; |
| 155 } else { |
| 156 // Remove element from the list which is not the first one. |
| 157 prev->next = os_socket->next; |
| 158 } |
| 159 |
| 160 delete os_socket; |
| 161 return true; |
| 162 } |
| 163 return false; |
| 164 } else { |
| 165 // It should be impossible for the event handler to close something that |
| 166 // hasn't been created before. |
| 167 UNREACHABLE(); |
| 168 return false; |
| 169 } |
| 170 } |
| 171 |
| 172 |
| 173 Dart_Handle ListeningSocketRegistry::MarkSocketFdAsSharableHack( |
| 174 intptr_t socketfd) { |
| 175 MutexLocker ml(ListeningSocketRegistry::mutex_); |
| 176 |
| 177 SocketsIterator it = sockets_by_fd_.find(socketfd); |
| 178 if (it != sockets_by_fd_.end()) { |
| 179 it->second->shared = true; |
| 180 return Dart_True(); |
| 181 } else { |
| 182 return Dart_False(); |
| 183 } |
| 184 } |
| 185 |
| 186 |
22 void FUNCTION_NAME(InternetAddress_Parse)(Dart_NativeArguments args) { | 187 void FUNCTION_NAME(InternetAddress_Parse)(Dart_NativeArguments args) { |
23 const char* address = | 188 const char* address = |
24 DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0)); | 189 DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0)); |
25 ASSERT(address != NULL); | 190 ASSERT(address != NULL); |
26 RawAddr raw; | 191 RawAddr raw; |
27 memset(&raw, 0, sizeof(raw)); | 192 memset(&raw, 0, sizeof(raw)); |
28 int type = strchr(address, ':') == NULL ? SocketAddress::TYPE_IPV4 | 193 int type = strchr(address, ':') == NULL ? SocketAddress::TYPE_IPV4 |
29 : SocketAddress::TYPE_IPV6; | 194 : SocketAddress::TYPE_IPV6; |
30 if (type == SocketAddress::TYPE_IPV4) { | 195 if (type == SocketAddress::TYPE_IPV4) { |
31 raw.addr.sa_family = AF_INET; | 196 raw.addr.sa_family = AF_INET; |
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
388 SocketAddress::GetSockAddr(Dart_GetNativeArgument(args, 1), &addr); | 553 SocketAddress::GetSockAddr(Dart_GetNativeArgument(args, 1), &addr); |
389 int64_t port = DartUtils::GetInt64ValueCheckRange( | 554 int64_t port = DartUtils::GetInt64ValueCheckRange( |
390 Dart_GetNativeArgument(args, 2), | 555 Dart_GetNativeArgument(args, 2), |
391 0, | 556 0, |
392 65535); | 557 65535); |
393 int64_t backlog = DartUtils::GetInt64ValueCheckRange( | 558 int64_t backlog = DartUtils::GetInt64ValueCheckRange( |
394 Dart_GetNativeArgument(args, 3), | 559 Dart_GetNativeArgument(args, 3), |
395 0, | 560 0, |
396 65535); | 561 65535); |
397 bool v6_only = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4)); | 562 bool v6_only = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4)); |
398 intptr_t socket = ServerSocket::CreateBindListen( | 563 bool shared = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 5)); |
399 addr, port, backlog, v6_only); | 564 |
400 OSError error; | 565 Dart_Handle socket_object = Dart_GetNativeArgument(args, 0); |
401 if (socket >= 0 && ServerSocket::StartAccept(socket)) { | 566 Dart_Handle result = ListeningSocketRegistry::Instance()->CreateBindListen( |
402 Socket::SetSocketIdNativeField(Dart_GetNativeArgument(args, 0), socket); | 567 socket_object, addr, port, backlog, v6_only, shared); |
403 Dart_SetReturnValue(args, Dart_True()); | 568 Dart_SetReturnValue(args, result); |
404 } else { | |
405 if (socket == -5) { | |
406 OSError os_error(-1, "Invalid host", OSError::kUnknown); | |
407 Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error)); | |
408 } else { | |
409 Dart_SetReturnValue(args, DartUtils::NewDartOSError(&error)); | |
410 } | |
411 } | |
412 } | 569 } |
413 | 570 |
414 | 571 |
415 void FUNCTION_NAME(ServerSocket_Accept)(Dart_NativeArguments args) { | 572 void FUNCTION_NAME(ServerSocket_Accept)(Dart_NativeArguments args) { |
416 intptr_t socket = | 573 intptr_t socket = |
417 Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 0)); | 574 Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 0)); |
418 intptr_t new_socket = ServerSocket::Accept(socket); | 575 intptr_t new_socket = ServerSocket::Accept(socket); |
419 if (new_socket >= 0) { | 576 if (new_socket >= 0) { |
420 Socket::SetSocketIdNativeField(Dart_GetNativeArgument(args, 1), new_socket); | 577 Socket::SetSocketIdNativeField(Dart_GetNativeArgument(args, 1), new_socket); |
421 Dart_SetReturnValue(args, Dart_True()); | 578 Dart_SetReturnValue(args, Dart_True()); |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
690 int interfaceIndex = | 847 int interfaceIndex = |
691 DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 3)); | 848 DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 3)); |
692 if (Socket::LeaveMulticast(socket, &addr, &interface, interfaceIndex)) { | 849 if (Socket::LeaveMulticast(socket, &addr, &interface, interfaceIndex)) { |
693 Dart_SetReturnValue(args, Dart_Null()); | 850 Dart_SetReturnValue(args, Dart_Null()); |
694 } else { | 851 } else { |
695 Dart_SetReturnValue(args, DartUtils::NewDartOSError()); | 852 Dart_SetReturnValue(args, DartUtils::NewDartOSError()); |
696 } | 853 } |
697 } | 854 } |
698 | 855 |
699 | 856 |
| 857 void FUNCTION_NAME(Socket_MarkSocketAsSharedHack)(Dart_NativeArguments args) { |
| 858 intptr_t socketfd = |
| 859 Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 0)); |
| 860 |
| 861 ListeningSocketRegistry *registry = ListeningSocketRegistry::Instance(); |
| 862 Dart_SetReturnValue(args, registry->MarkSocketFdAsSharableHack(socketfd)); |
| 863 } |
| 864 |
| 865 |
700 void Socket::SetSocketIdNativeField(Dart_Handle socket, intptr_t id) { | 866 void Socket::SetSocketIdNativeField(Dart_Handle socket, intptr_t id) { |
701 Dart_Handle err = | 867 Dart_Handle err = |
702 Dart_SetNativeInstanceField(socket, kSocketIdNativeField, id); | 868 Dart_SetNativeInstanceField(socket, kSocketIdNativeField, id); |
703 if (Dart_IsError(err)) Dart_PropagateError(err); | 869 if (Dart_IsError(err)) Dart_PropagateError(err); |
704 } | 870 } |
705 | 871 |
706 | 872 |
707 intptr_t Socket::GetSocketIdNativeField(Dart_Handle socket_obj) { | 873 intptr_t Socket::GetSocketIdNativeField(Dart_Handle socket_obj) { |
708 intptr_t socket = 0; | 874 intptr_t socket = 0; |
709 Dart_Handle err = | 875 Dart_Handle err = |
710 Dart_GetNativeInstanceField(socket_obj, kSocketIdNativeField, &socket); | 876 Dart_GetNativeInstanceField(socket_obj, kSocketIdNativeField, &socket); |
711 if (Dart_IsError(err)) Dart_PropagateError(err); | 877 if (Dart_IsError(err)) Dart_PropagateError(err); |
712 return socket; | 878 return socket; |
713 } | 879 } |
714 | 880 |
715 } // namespace bin | 881 } // namespace bin |
716 } // namespace dart | 882 } // namespace dart |
OLD | NEW |