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 bool ListeningSocketRegistry::Initialize() { | |
Søren Gjesse
2015/02/11 08:51:05
Just void return type?
kustermann
2015/02/11 09:56:08
Done.
| |
28 globalTcpListeningSocketRegistry = new ListeningSocketRegistry(); | |
29 return true; | |
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 return | |
86 // the file descriptor. | |
Søren Gjesse
2015/02/11 08:51:05
'return the file descriptor' -> 'reuse the file de
kustermann
2015/02/11 09:56:08
Done.
| |
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) { | |
Søren Gjesse
2015/02/11 08:51:05
Please add a few comments here
1. Removed last el
kustermann
2015/02/11 09:56:08
Done.
| |
150 sockets_by_port_.erase(os_socket->port); | |
151 } else if (prev == NULL) { | |
152 sockets_by_port_[os_socket->port] = current->next; | |
153 } else { | |
154 prev->next = os_socket->next; | |
155 } | |
156 | |
157 delete os_socket; | |
158 return true; | |
159 } | |
160 return false; | |
161 } else { | |
162 // It should be impossible for the event handler to close something that | |
163 // hasn't been created before. | |
164 UNREACHABLE(); | |
165 return false; | |
166 } | |
167 } | |
168 | |
169 | |
170 Dart_Handle ListeningSocketRegistry::MarkSocketFdAsSharableHack( | |
171 intptr_t socketfd) { | |
172 MutexLocker ml(ListeningSocketRegistry::mutex_); | |
173 | |
174 SocketsIterator it = sockets_by_fd_.find(socketfd); | |
175 if (it != sockets_by_fd_.end()) { | |
176 it->second->shared = true; | |
177 return Dart_True(); | |
178 } else { | |
179 return Dart_False(); | |
180 } | |
181 } | |
182 | |
183 | |
22 void FUNCTION_NAME(InternetAddress_Parse)(Dart_NativeArguments args) { | 184 void FUNCTION_NAME(InternetAddress_Parse)(Dart_NativeArguments args) { |
23 const char* address = | 185 const char* address = |
24 DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0)); | 186 DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0)); |
25 ASSERT(address != NULL); | 187 ASSERT(address != NULL); |
26 RawAddr raw; | 188 RawAddr raw; |
27 memset(&raw, 0, sizeof(raw)); | 189 memset(&raw, 0, sizeof(raw)); |
28 int type = strchr(address, ':') == NULL ? SocketAddress::TYPE_IPV4 | 190 int type = strchr(address, ':') == NULL ? SocketAddress::TYPE_IPV4 |
29 : SocketAddress::TYPE_IPV6; | 191 : SocketAddress::TYPE_IPV6; |
30 if (type == SocketAddress::TYPE_IPV4) { | 192 if (type == SocketAddress::TYPE_IPV4) { |
31 raw.addr.sa_family = AF_INET; | 193 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); | 550 SocketAddress::GetSockAddr(Dart_GetNativeArgument(args, 1), &addr); |
389 int64_t port = DartUtils::GetInt64ValueCheckRange( | 551 int64_t port = DartUtils::GetInt64ValueCheckRange( |
390 Dart_GetNativeArgument(args, 2), | 552 Dart_GetNativeArgument(args, 2), |
391 0, | 553 0, |
392 65535); | 554 65535); |
393 int64_t backlog = DartUtils::GetInt64ValueCheckRange( | 555 int64_t backlog = DartUtils::GetInt64ValueCheckRange( |
394 Dart_GetNativeArgument(args, 3), | 556 Dart_GetNativeArgument(args, 3), |
395 0, | 557 0, |
396 65535); | 558 65535); |
397 bool v6_only = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4)); | 559 bool v6_only = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4)); |
398 intptr_t socket = ServerSocket::CreateBindListen( | 560 bool shared = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 5)); |
399 addr, port, backlog, v6_only); | 561 |
400 OSError error; | 562 Dart_Handle socket_object = Dart_GetNativeArgument(args, 0); |
401 if (socket >= 0 && ServerSocket::StartAccept(socket)) { | 563 Dart_Handle result = ListeningSocketRegistry::Instance()->CreateBindListen( |
402 Socket::SetSocketIdNativeField(Dart_GetNativeArgument(args, 0), socket); | 564 socket_object, addr, port, backlog, v6_only, shared); |
403 Dart_SetReturnValue(args, Dart_True()); | 565 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 } | 566 } |
413 | 567 |
414 | 568 |
415 void FUNCTION_NAME(ServerSocket_Accept)(Dart_NativeArguments args) { | 569 void FUNCTION_NAME(ServerSocket_Accept)(Dart_NativeArguments args) { |
416 intptr_t socket = | 570 intptr_t socket = |
417 Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 0)); | 571 Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 0)); |
418 intptr_t new_socket = ServerSocket::Accept(socket); | 572 intptr_t new_socket = ServerSocket::Accept(socket); |
419 if (new_socket >= 0) { | 573 if (new_socket >= 0) { |
420 Socket::SetSocketIdNativeField(Dart_GetNativeArgument(args, 1), new_socket); | 574 Socket::SetSocketIdNativeField(Dart_GetNativeArgument(args, 1), new_socket); |
421 Dart_SetReturnValue(args, Dart_True()); | 575 Dart_SetReturnValue(args, Dart_True()); |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
690 int interfaceIndex = | 844 int interfaceIndex = |
691 DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 3)); | 845 DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 3)); |
692 if (Socket::LeaveMulticast(socket, &addr, &interface, interfaceIndex)) { | 846 if (Socket::LeaveMulticast(socket, &addr, &interface, interfaceIndex)) { |
693 Dart_SetReturnValue(args, Dart_Null()); | 847 Dart_SetReturnValue(args, Dart_Null()); |
694 } else { | 848 } else { |
695 Dart_SetReturnValue(args, DartUtils::NewDartOSError()); | 849 Dart_SetReturnValue(args, DartUtils::NewDartOSError()); |
696 } | 850 } |
697 } | 851 } |
698 | 852 |
699 | 853 |
854 void FUNCTION_NAME(Socket_MarkSocketAsSharedHack)(Dart_NativeArguments args) { | |
855 intptr_t socketfd = | |
856 Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 0)); | |
857 | |
858 ListeningSocketRegistry *registry = ListeningSocketRegistry::Instance(); | |
859 Dart_SetReturnValue(args, registry->MarkSocketFdAsSharableHack(socketfd)); | |
860 } | |
861 | |
862 | |
700 void Socket::SetSocketIdNativeField(Dart_Handle socket, intptr_t id) { | 863 void Socket::SetSocketIdNativeField(Dart_Handle socket, intptr_t id) { |
701 Dart_Handle err = | 864 Dart_Handle err = |
702 Dart_SetNativeInstanceField(socket, kSocketIdNativeField, id); | 865 Dart_SetNativeInstanceField(socket, kSocketIdNativeField, id); |
703 if (Dart_IsError(err)) Dart_PropagateError(err); | 866 if (Dart_IsError(err)) Dart_PropagateError(err); |
704 } | 867 } |
705 | 868 |
706 | 869 |
707 intptr_t Socket::GetSocketIdNativeField(Dart_Handle socket_obj) { | 870 intptr_t Socket::GetSocketIdNativeField(Dart_Handle socket_obj) { |
708 intptr_t socket = 0; | 871 intptr_t socket = 0; |
709 Dart_Handle err = | 872 Dart_Handle err = |
710 Dart_GetNativeInstanceField(socket_obj, kSocketIdNativeField, &socket); | 873 Dart_GetNativeInstanceField(socket_obj, kSocketIdNativeField, &socket); |
711 if (Dart_IsError(err)) Dart_PropagateError(err); | 874 if (Dart_IsError(err)) Dart_PropagateError(err); |
712 return socket; | 875 return socket; |
713 } | 876 } |
714 | 877 |
715 } // namespace bin | 878 } // namespace bin |
716 } // namespace dart | 879 } // namespace dart |
OLD | NEW |