| // Copyright 2019 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "platform/impl/tls_data_router_posix.h" |
| |
| #include <memory> |
| #include <utility> |
| |
| #include "platform/impl/stream_socket_posix.h" |
| #include "platform/impl/tls_connection_posix.h" |
| #include "util/osp_logging.h" |
| |
| namespace openscreen { |
| |
| TlsDataRouterPosix::TlsDataRouterPosix( |
| SocketHandleWaiter* waiter, |
| std::function<Clock::time_point()> now_function) |
| : waiter_(waiter), now_function_(now_function) {} |
| |
| TlsDataRouterPosix::~TlsDataRouterPosix() { |
| waiter_->UnsubscribeAll(this); |
| } |
| |
| void TlsDataRouterPosix::RegisterConnection(TlsConnectionPosix* connection) { |
| { |
| std::lock_guard<std::mutex> lock(connections_mutex_); |
| OSP_DCHECK(std::find(connections_.begin(), connections_.end(), |
| connection) == connections_.end()); |
| connections_.push_back(connection); |
| } |
| |
| waiter_->Subscribe(this, connection->socket_handle()); |
| } |
| |
| void TlsDataRouterPosix::DeregisterConnection(TlsConnectionPosix* connection) { |
| { |
| std::lock_guard<std::mutex> lock(connections_mutex_); |
| auto it = std::remove_if( |
| connections_.begin(), connections_.end(), |
| [connection](TlsConnectionPosix* conn) { return conn == connection; }); |
| if (it == connections_.end()) { |
| return; |
| } |
| connections_.erase(it, connections_.end()); |
| } |
| |
| waiter_->OnHandleDeletion(this, connection->socket_handle(), |
| disable_locking_for_testing_); |
| } |
| |
| void TlsDataRouterPosix::RegisterAcceptObserver( |
| std::unique_ptr<StreamSocketPosix> socket, |
| SocketObserver* observer) { |
| OSP_DCHECK(observer); |
| StreamSocketPosix* socket_ptr = socket.get(); |
| { |
| std::unique_lock<std::mutex> lock(accept_socket_mutex_); |
| accept_stream_sockets_.push_back(std::move(socket)); |
| accept_socket_mappings_[socket_ptr] = observer; |
| } |
| |
| waiter_->Subscribe(this, socket_ptr->socket_handle()); |
| } |
| |
| void TlsDataRouterPosix::DeregisterAcceptObserver(SocketObserver* observer) { |
| std::vector<std::unique_ptr<StreamSocketPosix>> sockets_to_delete; |
| { |
| std::unique_lock<std::mutex> lock(accept_socket_mutex_); |
| for (auto it = accept_stream_sockets_.begin(); |
| it != accept_stream_sockets_.end();) { |
| auto map_entry = accept_socket_mappings_.find(it->get()); |
| OSP_DCHECK(map_entry != accept_socket_mappings_.end()); |
| if (map_entry->second == observer) { |
| sockets_to_delete.push_back(std::move(*it)); |
| accept_socket_mappings_.erase(map_entry); |
| it = accept_stream_sockets_.erase(it); |
| } else { |
| ++it; |
| } |
| } |
| } |
| |
| for (auto& socket : sockets_to_delete) { |
| waiter_->OnHandleDeletion(this, socket->socket_handle(), |
| disable_locking_for_testing_); |
| } |
| } |
| |
| void TlsDataRouterPosix::ProcessReadyHandle( |
| SocketHandleWaiter::SocketHandleRef handle, |
| uint32_t flags) { |
| if (flags & SocketHandleWaiter::Flags::kReadable) { |
| std::unique_lock<std::mutex> lock(accept_socket_mutex_); |
| for (const auto& pair : accept_socket_mappings_) { |
| if (pair.first->socket_handle() == handle) { |
| pair.second->OnConnectionPending(pair.first); |
| return; |
| } |
| } |
| } |
| { |
| std::lock_guard<std::mutex> lock(connections_mutex_); |
| for (TlsConnectionPosix* connection : connections_) { |
| if (connection->socket_handle() == handle) { |
| if (flags & SocketHandleWaiter::Flags::kReadable) { |
| connection->TryReceiveMessage(); |
| } |
| if (flags & SocketHandleWaiter::Flags::kWriteable) { |
| connection->SendAvailableBytes(); |
| } |
| return; |
| } |
| } |
| } |
| } |
| |
| bool TlsDataRouterPosix::HasTimedOut(Clock::time_point start_time, |
| Clock::duration timeout) { |
| return now_function_() - start_time > timeout; |
| } |
| |
| bool TlsDataRouterPosix::IsSocketWatched(StreamSocketPosix* socket) const { |
| std::unique_lock<std::mutex> lock(accept_socket_mutex_); |
| return accept_socket_mappings_.find(socket) != accept_socket_mappings_.end(); |
| } |
| |
| } // namespace openscreen |