| Index: runtime/bin/socket.cc
|
| diff --git a/runtime/bin/socket.cc b/runtime/bin/socket.cc
|
| index 745306d0e53aef80dffdde95f79f249bda1bfe4d..1e9d94efc4397f1e72597d90a33ff59b1fcb6cad 100644
|
| --- a/runtime/bin/socket.cc
|
| +++ b/runtime/bin/socket.cc
|
| @@ -23,10 +23,8 @@ namespace bin {
|
|
|
| static const int kSocketIdNativeField = 0;
|
|
|
| -
|
| ListeningSocketRegistry *globalTcpListeningSocketRegistry = NULL;
|
|
|
| -
|
| void ListeningSocketRegistry::Initialize() {
|
| ASSERT(globalTcpListeningSocketRegistry == NULL);
|
| globalTcpListeningSocketRegistry = new ListeningSocketRegistry();
|
| @@ -44,6 +42,60 @@ void ListeningSocketRegistry::Cleanup() {
|
| }
|
|
|
|
|
| +ListeningSocketRegistry::OSSocket* ListeningSocketRegistry::LookupByPort(
|
| + intptr_t port) {
|
| + HashMap::Entry* entry =
|
| + sockets_by_port_.Lookup(GetHashmapKeyFromIntptr(port),
|
| + GetHashmapHashFromIntptr(port), false);
|
| + if (entry == NULL) {
|
| + return NULL;
|
| + }
|
| + return reinterpret_cast<OSSocket*>(entry->value);
|
| +}
|
| +
|
| +
|
| +void ListeningSocketRegistry::InsertByPort(intptr_t port, OSSocket* socket) {
|
| + HashMap::Entry* entry =
|
| + sockets_by_port_.Lookup(GetHashmapKeyFromIntptr(port),
|
| + GetHashmapHashFromIntptr(port), true);
|
| + ASSERT(entry != NULL);
|
| + entry->value = reinterpret_cast<void*>(socket);
|
| +}
|
| +
|
| +
|
| +void ListeningSocketRegistry::RemoveByPort(intptr_t port) {
|
| + sockets_by_port_.Remove(
|
| + GetHashmapKeyFromIntptr(port), GetHashmapHashFromIntptr(port));
|
| +}
|
| +
|
| +
|
| +ListeningSocketRegistry::OSSocket* ListeningSocketRegistry::LookupByFd(
|
| + intptr_t fd) {
|
| + HashMap::Entry* entry =
|
| + sockets_by_fd_.Lookup(GetHashmapKeyFromIntptr(fd),
|
| + GetHashmapHashFromIntptr(fd), false);
|
| + if (entry == NULL) {
|
| + return NULL;
|
| + }
|
| + return reinterpret_cast<OSSocket*>(entry->value);
|
| +}
|
| +
|
| +
|
| +void ListeningSocketRegistry::InsertByFd(intptr_t fd, OSSocket* socket) {
|
| + HashMap::Entry* entry =
|
| + sockets_by_fd_.Lookup(GetHashmapKeyFromIntptr(fd),
|
| + GetHashmapHashFromIntptr(fd), true);
|
| + ASSERT(entry != NULL);
|
| + entry->value = reinterpret_cast<void*>(socket);
|
| +}
|
| +
|
| +
|
| +void ListeningSocketRegistry::RemoveByFd(intptr_t fd) {
|
| + sockets_by_fd_.Remove(
|
| + GetHashmapKeyFromIntptr(fd), GetHashmapHashFromIntptr(fd));
|
| +}
|
| +
|
| +
|
| Dart_Handle ListeningSocketRegistry::CreateBindListen(Dart_Handle socket_object,
|
| RawAddr addr,
|
| intptr_t backlog,
|
| @@ -52,18 +104,12 @@ Dart_Handle ListeningSocketRegistry::CreateBindListen(Dart_Handle socket_object,
|
| MutexLocker ml(ListeningSocketRegistry::mutex_);
|
|
|
| intptr_t port = SocketAddress::GetAddrPort(addr);
|
| -
|
| - SocketsIterator it = sockets_by_port_.find(port);
|
| - OSSocket *first_os_socket = NULL;
|
| - if (it != sockets_by_port_.end()) {
|
| - first_os_socket = it->second;
|
| - }
|
| -
|
| + OSSocket* first_os_socket = LookupByPort(port);
|
| if (first_os_socket != NULL) {
|
| // There is already a socket listening on this port. We need to ensure
|
| // that if there is one also listening on the same address, it was created
|
| // with `shared = true`, ...
|
| - OSSocket *os_socket = it->second;
|
| + OSSocket *os_socket = first_os_socket;
|
| OSSocket *os_socket_same_addr = findOSSocketWithAddress(os_socket, addr);
|
|
|
| if (os_socket_same_addr != NULL) {
|
| @@ -117,8 +163,9 @@ Dart_Handle ListeningSocketRegistry::CreateBindListen(Dart_Handle socket_object,
|
| new OSSocket(addr, allocated_port, v6_only, shared, socketfd);
|
| os_socket->ref_count = 1;
|
| os_socket->next = first_os_socket;
|
| - sockets_by_port_[allocated_port] = os_socket;
|
| - sockets_by_fd_[socketfd] = os_socket;
|
| +
|
| + InsertByPort(allocated_port, os_socket);
|
| + InsertByFd(socketfd, os_socket);
|
|
|
| // We set as a side-effect the port on the dart socket_object.
|
| Socket::SetSocketIdNativeField(socket_object, socketfd);
|
| @@ -127,42 +174,57 @@ Dart_Handle ListeningSocketRegistry::CreateBindListen(Dart_Handle socket_object,
|
| }
|
|
|
|
|
| -bool ListeningSocketRegistry::CloseSafe(intptr_t socketfd) {
|
| +bool ListeningSocketRegistry::CloseOneSafe(OSSocket* os_socket) {
|
| ASSERT(!mutex_->TryLock());
|
| + ASSERT(os_socket != NULL);
|
| + ASSERT(os_socket->ref_count > 0);
|
| + os_socket->ref_count--;
|
| + if (os_socket->ref_count > 0) {
|
| + return false;
|
| + }
|
| + // We free the OS socket by removing it from two datastructures.
|
| + RemoveByFd(os_socket->socketfd);
|
|
|
| - SocketsIterator it = sockets_by_fd_.find(socketfd);
|
| - if (it != sockets_by_fd_.end()) {
|
| - OSSocket *os_socket = it->second;
|
| -
|
| - ASSERT(os_socket->ref_count > 0);
|
| - os_socket->ref_count--;
|
| - if (os_socket->ref_count == 0) {
|
| - // We free the OS socket by removing it from two datastructures.
|
| - sockets_by_fd_.erase(socketfd);
|
| -
|
| - OSSocket *prev = NULL;
|
| - OSSocket *current = sockets_by_port_[os_socket->port];
|
| - while (current != os_socket) {
|
| - ASSERT(current != NULL);
|
| - prev = current;
|
| - current = current->next;
|
| - }
|
| + OSSocket* prev = NULL;
|
| + OSSocket* current = LookupByPort(os_socket->port);
|
| + while (current != os_socket) {
|
| + ASSERT(current != NULL);
|
| + prev = current;
|
| + current = current->next;
|
| + }
|
|
|
| - if ((prev == NULL) && (current->next == NULL)) {
|
| - // Remove last element from the list.
|
| - sockets_by_port_.erase(os_socket->port);
|
| - } else if (prev == NULL) {
|
| - // Remove first element of the list.
|
| - sockets_by_port_[os_socket->port] = current->next;
|
| - } else {
|
| - // Remove element from the list which is not the first one.
|
| - prev->next = os_socket->next;
|
| - }
|
| + if ((prev == NULL) && (current->next == NULL)) {
|
| + // Remove last element from the list.
|
| + RemoveByPort(os_socket->port);
|
| + } else if (prev == NULL) {
|
| + // Remove first element of the list.
|
| + InsertByPort(os_socket->port, current->next);
|
| + } else {
|
| + // Remove element from the list which is not the first one.
|
| + prev->next = os_socket->next;
|
| + }
|
|
|
| - delete os_socket;
|
| - return true;
|
| - }
|
| - return false;
|
| + ASSERT(os_socket->ref_count == 0);
|
| + delete os_socket;
|
| + return true;
|
| +}
|
| +
|
| +
|
| +void ListeningSocketRegistry::CloseAllSafe() {
|
| + MutexLocker ml(mutex_);
|
| + for (HashMap::Entry* p = sockets_by_fd_.Start();
|
| + p != NULL;
|
| + p = sockets_by_fd_.Next(p)) {
|
| + CloseOneSafe(reinterpret_cast<OSSocket*>(p->value));
|
| + }
|
| +}
|
| +
|
| +
|
| +bool ListeningSocketRegistry::CloseSafe(intptr_t socketfd) {
|
| + ASSERT(!mutex_->TryLock());
|
| + OSSocket* os_socket = LookupByFd(socketfd);
|
| + if (os_socket != NULL) {
|
| + return CloseOneSafe(os_socket);
|
| } else {
|
| // It should be impossible for the event handler to close something that
|
| // hasn't been created before.
|
|
|