// 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 "discovery/mdns/mdns_receiver.h" #include #include "discovery/mdns/mdns_reader.h" #include "util/trace_logging.h" namespace openscreen { namespace discovery { MdnsReceiver::ResponseClient::~ResponseClient() = default; MdnsReceiver::MdnsReceiver(Config config) : config_(std::move(config)) {} MdnsReceiver::~MdnsReceiver() { if (state_ == State::kRunning) { Stop(); } OSP_DCHECK(response_clients_.empty()); } void MdnsReceiver::SetQueryCallback( std::function callback) { // This check verifies that either new or stored callback has a target. It // will fail in case multiple objects try to set or clear the callback. OSP_DCHECK(static_cast(query_callback_) != static_cast(callback)); query_callback_ = callback; } void MdnsReceiver::AddResponseCallback(ResponseClient* callback) { auto it = std::find(response_clients_.begin(), response_clients_.end(), callback); OSP_DCHECK(it == response_clients_.end()); response_clients_.push_back(callback); } void MdnsReceiver::RemoveResponseCallback(ResponseClient* callback) { auto it = std::find(response_clients_.begin(), response_clients_.end(), callback); OSP_DCHECK(it != response_clients_.end()); response_clients_.erase(it); } void MdnsReceiver::Start() { state_ = State::kRunning; } void MdnsReceiver::Stop() { state_ = State::kStopped; } void MdnsReceiver::OnRead(UdpSocket* socket, ErrorOr packet_or_error) { if (state_ != State::kRunning || packet_or_error.is_error()) { return; } UdpPacket packet = std::move(packet_or_error.value()); TRACE_SCOPED(TraceCategory::kMdns, "MdnsReceiver::OnRead"); MdnsReader reader(config_, packet.data(), packet.size()); const ErrorOr message = reader.Read(); if (message.is_error()) { if (message.error().code() == Error::Code::kMdnsNonConformingFailure) { OSP_DVLOG << "mDNS message dropped due to invalid rcode or opcode..."; } else { OSP_DVLOG << "mDNS message failed to parse..."; } return; } if (message.value().type() == MessageType::Response) { for (ResponseClient* client : response_clients_) { client->OnMessageReceived(message.value()); } if (response_clients_.empty()) { OSP_DVLOG << "mDNS response message dropped. No response client registered..."; } } else { if (query_callback_) { query_callback_(message.value(), packet.source()); } else { OSP_DVLOG << "mDNS query message dropped. No query client registered..."; } } } } // namespace discovery } // namespace openscreen