1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "platform/impl/udp_socket_reader_posix.h"
6
7 #include <chrono>
8 #include <functional>
9
10 #include "platform/impl/socket_handle_posix.h"
11 #include "platform/impl/udp_socket_posix.h"
12 #include "util/osp_logging.h"
13
14 namespace openscreen {
15
UdpSocketReaderPosix(SocketHandleWaiter * waiter)16 UdpSocketReaderPosix::UdpSocketReaderPosix(SocketHandleWaiter* waiter)
17 : waiter_(waiter) {}
18
~UdpSocketReaderPosix()19 UdpSocketReaderPosix::~UdpSocketReaderPosix() {
20 waiter_->UnsubscribeAll(this);
21 }
22
ProcessReadyHandle(SocketHandleRef handle,uint32_t flags)23 void UdpSocketReaderPosix::ProcessReadyHandle(SocketHandleRef handle,
24 uint32_t flags) {
25 if (flags & SocketHandleWaiter::Flags::kReadable) {
26 std::lock_guard<std::mutex> lock(mutex_);
27 // NOTE: Because sockets_ is expected to remain small, the performance here
28 // is better than using an unordered_set.
29 for (UdpSocketPosix* socket : sockets_) {
30 if (socket->GetHandle() == handle) {
31 socket->ReceiveMessage();
32 break;
33 }
34 }
35 }
36 }
37
OnCreate(UdpSocket * socket)38 void UdpSocketReaderPosix::OnCreate(UdpSocket* socket) {
39 UdpSocketPosix* read_socket = static_cast<UdpSocketPosix*>(socket);
40 {
41 std::lock_guard<std::mutex> lock(mutex_);
42 sockets_.push_back(read_socket);
43 }
44 waiter_->Subscribe(this, std::cref(read_socket->GetHandle()));
45 }
46
OnDestroy(UdpSocket * socket)47 void UdpSocketReaderPosix::OnDestroy(UdpSocket* socket) {
48 UdpSocketPosix* destroyed_socket = static_cast<UdpSocketPosix*>(socket);
49 OnDelete(destroyed_socket);
50 }
51
OnDelete(UdpSocketPosix * socket,bool disable_locking_for_testing)52 void UdpSocketReaderPosix::OnDelete(UdpSocketPosix* socket,
53 bool disable_locking_for_testing) {
54 {
55 std::unique_lock<std::mutex> lock(mutex_);
56 auto it = std::find(sockets_.begin(), sockets_.end(), socket);
57 if (it != sockets_.end()) {
58 sockets_.erase(it);
59 }
60 }
61
62 waiter_->OnHandleDeletion(this, std::cref(socket->GetHandle()),
63 disable_locking_for_testing);
64 }
65
IsMappedReadForTesting(UdpSocketPosix * socket) const66 bool UdpSocketReaderPosix::IsMappedReadForTesting(
67 UdpSocketPosix* socket) const {
68 return std::find(sockets_.begin(), sockets_.end(), socket) != sockets_.end();
69 }
70
71 } // namespace openscreen
72