xref: /aosp_15_r20/external/openscreen/discovery/mdns/mdns_receiver.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_receiver.h"
6*3f982cf4SFabien Sanglard 
7*3f982cf4SFabien Sanglard #include <utility>
8*3f982cf4SFabien Sanglard 
9*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_reader.h"
10*3f982cf4SFabien Sanglard #include "util/trace_logging.h"
11*3f982cf4SFabien Sanglard 
12*3f982cf4SFabien Sanglard namespace openscreen {
13*3f982cf4SFabien Sanglard namespace discovery {
14*3f982cf4SFabien Sanglard 
15*3f982cf4SFabien Sanglard MdnsReceiver::ResponseClient::~ResponseClient() = default;
16*3f982cf4SFabien Sanglard 
MdnsReceiver(Config config)17*3f982cf4SFabien Sanglard MdnsReceiver::MdnsReceiver(Config config) : config_(std::move(config)) {}
18*3f982cf4SFabien Sanglard 
~MdnsReceiver()19*3f982cf4SFabien Sanglard MdnsReceiver::~MdnsReceiver() {
20*3f982cf4SFabien Sanglard   if (state_ == State::kRunning) {
21*3f982cf4SFabien Sanglard     Stop();
22*3f982cf4SFabien Sanglard   }
23*3f982cf4SFabien Sanglard 
24*3f982cf4SFabien Sanglard   OSP_DCHECK(response_clients_.empty());
25*3f982cf4SFabien Sanglard }
26*3f982cf4SFabien Sanglard 
SetQueryCallback(std::function<void (const MdnsMessage &,const IPEndpoint &)> callback)27*3f982cf4SFabien Sanglard void MdnsReceiver::SetQueryCallback(
28*3f982cf4SFabien Sanglard     std::function<void(const MdnsMessage&, const IPEndpoint&)> callback) {
29*3f982cf4SFabien Sanglard   // This check verifies that either new or stored callback has a target. It
30*3f982cf4SFabien Sanglard   // will fail in case multiple objects try to set or clear the callback.
31*3f982cf4SFabien Sanglard   OSP_DCHECK(static_cast<bool>(query_callback_) != static_cast<bool>(callback));
32*3f982cf4SFabien Sanglard   query_callback_ = callback;
33*3f982cf4SFabien Sanglard }
34*3f982cf4SFabien Sanglard 
AddResponseCallback(ResponseClient * callback)35*3f982cf4SFabien Sanglard void MdnsReceiver::AddResponseCallback(ResponseClient* callback) {
36*3f982cf4SFabien Sanglard   auto it =
37*3f982cf4SFabien Sanglard       std::find(response_clients_.begin(), response_clients_.end(), callback);
38*3f982cf4SFabien Sanglard   OSP_DCHECK(it == response_clients_.end());
39*3f982cf4SFabien Sanglard 
40*3f982cf4SFabien Sanglard   response_clients_.push_back(callback);
41*3f982cf4SFabien Sanglard }
42*3f982cf4SFabien Sanglard 
RemoveResponseCallback(ResponseClient * callback)43*3f982cf4SFabien Sanglard void MdnsReceiver::RemoveResponseCallback(ResponseClient* callback) {
44*3f982cf4SFabien Sanglard   auto it =
45*3f982cf4SFabien Sanglard       std::find(response_clients_.begin(), response_clients_.end(), callback);
46*3f982cf4SFabien Sanglard   OSP_DCHECK(it != response_clients_.end());
47*3f982cf4SFabien Sanglard 
48*3f982cf4SFabien Sanglard   response_clients_.erase(it);
49*3f982cf4SFabien Sanglard }
50*3f982cf4SFabien Sanglard 
Start()51*3f982cf4SFabien Sanglard void MdnsReceiver::Start() {
52*3f982cf4SFabien Sanglard   state_ = State::kRunning;
53*3f982cf4SFabien Sanglard }
54*3f982cf4SFabien Sanglard 
Stop()55*3f982cf4SFabien Sanglard void MdnsReceiver::Stop() {
56*3f982cf4SFabien Sanglard   state_ = State::kStopped;
57*3f982cf4SFabien Sanglard }
58*3f982cf4SFabien Sanglard 
OnRead(UdpSocket * socket,ErrorOr<UdpPacket> packet_or_error)59*3f982cf4SFabien Sanglard void MdnsReceiver::OnRead(UdpSocket* socket,
60*3f982cf4SFabien Sanglard                           ErrorOr<UdpPacket> packet_or_error) {
61*3f982cf4SFabien Sanglard   if (state_ != State::kRunning || packet_or_error.is_error()) {
62*3f982cf4SFabien Sanglard     return;
63*3f982cf4SFabien Sanglard   }
64*3f982cf4SFabien Sanglard 
65*3f982cf4SFabien Sanglard   UdpPacket packet = std::move(packet_or_error.value());
66*3f982cf4SFabien Sanglard 
67*3f982cf4SFabien Sanglard   TRACE_SCOPED(TraceCategory::kMdns, "MdnsReceiver::OnRead");
68*3f982cf4SFabien Sanglard   MdnsReader reader(config_, packet.data(), packet.size());
69*3f982cf4SFabien Sanglard   const ErrorOr<MdnsMessage> message = reader.Read();
70*3f982cf4SFabien Sanglard   if (message.is_error()) {
71*3f982cf4SFabien Sanglard     if (message.error().code() == Error::Code::kMdnsNonConformingFailure) {
72*3f982cf4SFabien Sanglard       OSP_DVLOG << "mDNS message dropped due to invalid rcode or opcode...";
73*3f982cf4SFabien Sanglard     } else {
74*3f982cf4SFabien Sanglard       OSP_DVLOG << "mDNS message failed to parse...";
75*3f982cf4SFabien Sanglard     }
76*3f982cf4SFabien Sanglard     return;
77*3f982cf4SFabien Sanglard   }
78*3f982cf4SFabien Sanglard 
79*3f982cf4SFabien Sanglard   if (message.value().type() == MessageType::Response) {
80*3f982cf4SFabien Sanglard     for (ResponseClient* client : response_clients_) {
81*3f982cf4SFabien Sanglard       client->OnMessageReceived(message.value());
82*3f982cf4SFabien Sanglard     }
83*3f982cf4SFabien Sanglard     if (response_clients_.empty()) {
84*3f982cf4SFabien Sanglard       OSP_DVLOG
85*3f982cf4SFabien Sanglard           << "mDNS response message dropped. No response client registered...";
86*3f982cf4SFabien Sanglard     }
87*3f982cf4SFabien Sanglard   } else {
88*3f982cf4SFabien Sanglard     if (query_callback_) {
89*3f982cf4SFabien Sanglard       query_callback_(message.value(), packet.source());
90*3f982cf4SFabien Sanglard     } else {
91*3f982cf4SFabien Sanglard       OSP_DVLOG << "mDNS query message dropped. No query client registered...";
92*3f982cf4SFabien Sanglard     }
93*3f982cf4SFabien Sanglard   }
94*3f982cf4SFabien Sanglard }
95*3f982cf4SFabien Sanglard 
96*3f982cf4SFabien Sanglard }  // namespace discovery
97*3f982cf4SFabien Sanglard }  // namespace openscreen
98