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 |