| 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 #if !defined(DART_IO_DISABLED) | 5 #if !defined(DART_IO_DISABLED) |
| 6 | 6 |
| 7 #include "bin/socket.h" | 7 #include "bin/socket.h" |
| 8 | 8 |
| 9 #include "bin/dartutils.h" | 9 #include "bin/dartutils.h" |
| 10 #include "bin/io_buffer.h" | 10 #include "bin/io_buffer.h" |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 sockets_by_fd_.Remove(GetHashmapKeyFromIntptr(fd), | 94 sockets_by_fd_.Remove(GetHashmapKeyFromIntptr(fd), |
| 95 GetHashmapHashFromIntptr(fd)); | 95 GetHashmapHashFromIntptr(fd)); |
| 96 } | 96 } |
| 97 | 97 |
| 98 | 98 |
| 99 Dart_Handle ListeningSocketRegistry::CreateBindListen(Dart_Handle socket_object, | 99 Dart_Handle ListeningSocketRegistry::CreateBindListen(Dart_Handle socket_object, |
| 100 RawAddr addr, | 100 RawAddr addr, |
| 101 intptr_t backlog, | 101 intptr_t backlog, |
| 102 bool v6_only, | 102 bool v6_only, |
| 103 bool shared) { | 103 bool shared) { |
| 104 MutexLocker ml(ListeningSocketRegistry::mutex_); | 104 MutexLocker ml(mutex_); |
| 105 | 105 |
| 106 OSSocket* first_os_socket = NULL; |
| 106 intptr_t port = SocketAddress::GetAddrPort(addr); | 107 intptr_t port = SocketAddress::GetAddrPort(addr); |
| 107 OSSocket* first_os_socket = LookupByPort(port); | 108 if (port > 0) { |
| 108 if (first_os_socket != NULL) { | 109 first_os_socket = LookupByPort(port); |
| 109 // There is already a socket listening on this port. We need to ensure | 110 if (first_os_socket != NULL) { |
| 110 // that if there is one also listening on the same address, it was created | 111 // There is already a socket listening on this port. We need to ensure |
| 111 // with `shared = true`, ... | 112 // that if there is one also listening on the same address, it was created |
| 112 OSSocket* os_socket = first_os_socket; | 113 // with `shared = true`, ... |
| 113 OSSocket* os_socket_same_addr = findOSSocketWithAddress(os_socket, addr); | 114 OSSocket* os_socket = first_os_socket; |
| 115 OSSocket* os_socket_same_addr = findOSSocketWithAddress(os_socket, addr); |
| 114 | 116 |
| 115 if (os_socket_same_addr != NULL) { | 117 if (os_socket_same_addr != NULL) { |
| 116 if (!os_socket_same_addr->shared || !shared) { | 118 if (!os_socket_same_addr->shared || !shared) { |
| 117 OSError os_error(-1, | 119 OSError os_error(-1, |
| 118 "The shared flag to bind() needs to be `true` if " | 120 "The shared flag to bind() needs to be `true` if " |
| 119 "binding multiple times on the same (address, port) " | 121 "binding multiple times on the same (address, port) " |
| 120 "combination.", | 122 "combination.", |
| 121 OSError::kUnknown); | 123 OSError::kUnknown); |
| 122 return DartUtils::NewDartOSError(&os_error); | 124 return DartUtils::NewDartOSError(&os_error); |
| 125 } |
| 126 if (os_socket_same_addr->v6_only != v6_only) { |
| 127 OSError os_error(-1, |
| 128 "The v6Only flag to bind() needs to be the same if " |
| 129 "binding multiple times on the same (address, port) " |
| 130 "combination.", |
| 131 OSError::kUnknown); |
| 132 return DartUtils::NewDartOSError(&os_error); |
| 133 } |
| 134 |
| 135 // This socket creation is the exact same as the one which originally |
| 136 // created the socket. We therefore increment the refcount and reuse |
| 137 // the file descriptor. |
| 138 os_socket->ref_count++; |
| 139 |
| 140 // We set as a side-effect the file descriptor on the dart |
| 141 // socket_object. |
| 142 Socket::SetSocketIdNativeField(socket_object, os_socket->socketfd); |
| 143 |
| 144 return Dart_True(); |
| 123 } | 145 } |
| 124 if (os_socket_same_addr->v6_only != v6_only) { | |
| 125 OSError os_error(-1, | |
| 126 "The v6Only flag to bind() needs to be the same if " | |
| 127 "binding multiple times on the same (address, port) " | |
| 128 "combination.", | |
| 129 OSError::kUnknown); | |
| 130 return DartUtils::NewDartOSError(&os_error); | |
| 131 } | |
| 132 | |
| 133 // This socket creation is the exact same as the one which originally | |
| 134 // created the socket. We therefore increment the refcount and reuse | |
| 135 // the file descriptor. | |
| 136 os_socket->ref_count++; | |
| 137 | |
| 138 // We set as a side-effect the file descriptor on the dart socket_object. | |
| 139 Socket::SetSocketIdNativeField(socket_object, os_socket->socketfd); | |
| 140 | |
| 141 return Dart_True(); | |
| 142 } | 146 } |
| 143 } | 147 } |
| 144 | 148 |
| 145 // There is no socket listening on that (address, port), so we create new one. | 149 // There is no socket listening on that (address, port), so we create new one. |
| 146 intptr_t socketfd = ServerSocket::CreateBindListen(addr, backlog, v6_only); | 150 intptr_t socketfd = ServerSocket::CreateBindListen(addr, backlog, v6_only); |
| 147 if (socketfd == -5) { | 151 if (socketfd == -5) { |
| 148 OSError os_error(-1, "Invalid host", OSError::kUnknown); | 152 OSError os_error(-1, "Invalid host", OSError::kUnknown); |
| 149 return DartUtils::NewDartOSError(&os_error); | 153 return DartUtils::NewDartOSError(&os_error); |
| 150 } | 154 } |
| 151 if (socketfd < 0) { | 155 if (socketfd < 0) { |
| 152 OSError error; | 156 OSError error; |
| 153 return DartUtils::NewDartOSError(&error); | 157 return DartUtils::NewDartOSError(&error); |
| 154 } | 158 } |
| 155 if (!ServerSocket::StartAccept(socketfd)) { | 159 if (!ServerSocket::StartAccept(socketfd)) { |
| 156 OSError os_error(-1, "Failed to start accept", OSError::kUnknown); | 160 OSError os_error(-1, "Failed to start accept", OSError::kUnknown); |
| 157 return DartUtils::NewDartOSError(&os_error); | 161 return DartUtils::NewDartOSError(&os_error); |
| 158 } | 162 } |
| 159 intptr_t allocated_port = Socket::GetPort(socketfd); | 163 intptr_t allocated_port = Socket::GetPort(socketfd); |
| 160 ASSERT(allocated_port > 0); | 164 ASSERT(allocated_port > 0); |
| 161 | 165 |
| 166 if (allocated_port != port) { |
| 167 // There are two cases to consider: |
| 168 // |
| 169 // a) The user requested (address, port) where port != 0 which means |
| 170 // we re-use an existing socket if available (and it is shared) or we |
| 171 // create a new one. The new socket is guaranteed to have that |
| 172 // selected port. |
| 173 // |
| 174 // b) The user requested (address, 0). This will make us *always* create a |
| 175 // new socket. The OS will assign it a new `allocated_port` and we will |
| 176 // insert into our data structures. *BUT* There might already be an |
| 177 // existing (address2, `allocated_port`) where address != address2. So |
| 178 // we need to do another `LookupByPort(allocated_port)` and link them |
| 179 // via `OSSocket->next`. |
| 180 ASSERT(port == 0); |
| 181 first_os_socket = LookupByPort(allocated_port); |
| 182 } |
| 183 |
| 162 OSSocket* os_socket = | 184 OSSocket* os_socket = |
| 163 new OSSocket(addr, allocated_port, v6_only, shared, socketfd); | 185 new OSSocket(addr, allocated_port, v6_only, shared, socketfd); |
| 164 os_socket->ref_count = 1; | 186 os_socket->ref_count = 1; |
| 165 os_socket->next = first_os_socket; | 187 os_socket->next = first_os_socket; |
| 166 | 188 |
| 167 InsertByPort(allocated_port, os_socket); | 189 InsertByPort(allocated_port, os_socket); |
| 168 InsertByFd(socketfd, os_socket); | 190 InsertByFd(socketfd, os_socket); |
| 169 | 191 |
| 170 // We set as a side-effect the port on the dart socket_object. | 192 // We set as a side-effect the port on the dart socket_object. |
| 171 Socket::SetSocketIdNativeField(socket_object, socketfd); | 193 Socket::SetSocketIdNativeField(socket_object, socketfd); |
| (...skipping 747 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 919 if (Dart_IsError(err)) { | 941 if (Dart_IsError(err)) { |
| 920 Dart_PropagateError(err); | 942 Dart_PropagateError(err); |
| 921 } | 943 } |
| 922 return socket; | 944 return socket; |
| 923 } | 945 } |
| 924 | 946 |
| 925 } // namespace bin | 947 } // namespace bin |
| 926 } // namespace dart | 948 } // namespace dart |
| 927 | 949 |
| 928 #endif // !defined(DART_IO_DISABLED) | 950 #endif // !defined(DART_IO_DISABLED) |
| OLD | NEW |