147 lines
3.3 KiB
C++
147 lines
3.3 KiB
C++
#include "MulticastDnsClientImpl.h"
|
|
#include "MalformedPacket.h"
|
|
#include "Packet.h"
|
|
#include <Logging.h>
|
|
|
|
|
|
namespace Network {
|
|
namespace Dns {
|
|
|
|
MulticastDnsClientImpl::MulticastDnsClientImpl(std::function<void(const std::vector<ResourceRecordImpl>&)> callback) :
|
|
m_timer(m_ioService),
|
|
m_responseBuffer(1024),
|
|
m_socket(m_ioService, asio::ip::udp::v4()),
|
|
m_multicastEndpoint(asio::ip::address::from_string("224.0.0.251"), 5353),
|
|
m_callback(callback)
|
|
{
|
|
m_socket.set_option(asio::socket_base::reuse_address(true));
|
|
m_socket.set_option(asio::ip::multicast::join_group(m_multicastEndpoint.address()));
|
|
m_socket.set_option(asio::ip::multicast::hops(255));
|
|
m_socket.bind(asio::ip::udp::endpoint(asio::ip::udp::v4(), 5353));
|
|
|
|
m_thread = std::thread([&] { m_ioService.run(); });
|
|
}
|
|
|
|
MulticastDnsClientImpl::~MulticastDnsClientImpl()
|
|
{
|
|
m_ioService.stop();
|
|
m_thread.join();
|
|
}
|
|
|
|
void MulticastDnsClientImpl::Query(const QueryImpl& query)
|
|
{
|
|
m_query = query;
|
|
m_iterations = 3;
|
|
SendQuery();
|
|
}
|
|
|
|
void MulticastDnsClientImpl::SetTimer(int milliseconds)
|
|
{
|
|
m_timer.cancel();
|
|
m_timer.expires_from_now(std::chrono::milliseconds(milliseconds));
|
|
}
|
|
|
|
void MulticastDnsClientImpl::SendQuery()
|
|
{
|
|
if (m_iterations == 0)
|
|
return;
|
|
m_iterations--;
|
|
|
|
Packet packet;
|
|
packet.AddQuery(m_query);
|
|
|
|
auto data = std::make_shared<Data>(packet.GetData());
|
|
|
|
m_socket.async_send_to(
|
|
asio::buffer(data->GetPtr(), data->GetLength()),
|
|
m_multicastEndpoint,
|
|
std::bind(&MulticastDnsClientImpl::HandleQuerySent, this,
|
|
std::placeholders::_1,
|
|
data
|
|
)
|
|
);
|
|
}
|
|
|
|
void MulticastDnsClientImpl::HandleQuerySent(const asio::error_code & error, std::shared_ptr<Data> data)
|
|
{
|
|
if (error == asio::error::operation_aborted)
|
|
{
|
|
SendQuery();
|
|
}
|
|
else if (error)
|
|
{
|
|
std::stringstream ss;
|
|
ss << "MulticastDnsClientImpl::HandleQuerySent: " << error.message();
|
|
Logging::Log(Logging::Severity::Error, ss.str());
|
|
}
|
|
else
|
|
{
|
|
SetTimer(1000);
|
|
m_timer.async_wait(std::bind(
|
|
&MulticastDnsClientImpl::HandleQueryTimeout, this,
|
|
std::placeholders::_1
|
|
));
|
|
ReceiveQuery();
|
|
}
|
|
}
|
|
|
|
void MulticastDnsClientImpl::ReceiveQuery()
|
|
{
|
|
m_socket.async_receive_from(
|
|
asio::buffer(m_responseBuffer),
|
|
m_receiveEndpoint,
|
|
std::bind(&MulticastDnsClientImpl::HandleQueryResponse, this,
|
|
std::placeholders::_1,
|
|
std::placeholders::_2
|
|
)
|
|
);
|
|
}
|
|
|
|
void MulticastDnsClientImpl::HandleQueryResponse(const asio::error_code & error, std::size_t size)
|
|
{
|
|
if (error == asio::error::operation_aborted)
|
|
{
|
|
SendQuery();
|
|
}
|
|
else if (error)
|
|
{
|
|
std::stringstream ss;
|
|
ss << "MulticastDnsClientImpl::HandleQueryResponse: " << error.message();
|
|
Logging::Log(Logging::Severity::Error, ss.str());
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
Packet packet(DataReader(m_responseBuffer.data(), size), 0);
|
|
if (packet.GetQuery())
|
|
m_callback(packet.GetAnswers());
|
|
}
|
|
catch(MalformedPacket& mp)
|
|
{
|
|
}
|
|
|
|
ReceiveQuery();
|
|
}
|
|
}
|
|
|
|
void MulticastDnsClientImpl::HandleQueryTimeout(const asio::error_code & error)
|
|
{
|
|
if (error == asio::error::operation_aborted)
|
|
{
|
|
}
|
|
else if (error)
|
|
{
|
|
std::stringstream ss;
|
|
ss << "MulticastDnsClientImpl::HandleQueryTimeout: " << error.message();
|
|
Logging::Log(Logging::Severity::Error, ss.str());
|
|
}
|
|
else
|
|
{
|
|
m_socket.cancel();
|
|
}
|
|
}
|
|
|
|
} // namespace Dns
|
|
} // namespace Network
|