bool TCPPort::OnSocketEvent(SocketDescriptor _socket, unsigned mask) { assert(listener.IsDefined()); if (_socket == listener) { /* connection should never be defined here */ assert(SocketPort::GetState() == PortState::FAILED); SocketDescriptor s = listener.Accept(); if (!s.IsDefined()) return true; #ifndef HAVE_POSIX /* reset the flag so we can wait for it atomically after SocketPort::Set() */ closed_trigger.Reset(); #endif SocketPort::Set(std::move(s)); #ifdef HAVE_POSIX /* disable the listener socket while the connection socket is active */ return false; #else /* for until the connection SocketThread finishes the connection; meanwhile, incoming connections are ignored */ closed_trigger.Wait(); SocketPort::Close(); /* now continue listening for incoming connections */ return true; #endif } else { /* this event affects the connection socket */ if (!SocketPort::OnSocketEvent(_socket, mask)) { /* the connection was closed; continue listening on incoming connections */ #ifdef HAVE_POSIX /* close the connection, unregister the event, and reinstate the listener socket */ SocketPort::Close(); io_thread->Add(listener.ToFileDescriptor(), Poll::READ, *this); #else /* we must not call SocketPort::Close() here because it may deadlock, waiting forever for this thread to finish; instead, wake up the listener thread, and let it handle the event */ closed_trigger.Signal(); #endif return false; } else /* continue reading from the connection */ return true; } }
gcc_pure bool IsConnected() const { // TODO: what if the socket is broken? return fd.IsDefined(); }
bool IsDefined() const { return socket.IsDefined(); }