| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485 |
- #include "IcmpClientImpl.h"
- #include <chrono>
- namespace Network {
- IcmpClientImpl::IcmpClientImpl() :
- m_socket(m_ioContext, asio::ip::icmp::v4()),
- m_done(false)
- {
- StartReceive();
- m_thread = std::thread([&] { m_ioContext.run(); });
- #ifdef __linux__
- pthread_setname_np(m_thread.native_handle(), "IcmpClientImpl");
- #endif
- }
- IcmpClientImpl::~IcmpClientImpl()
- {
- m_ioContext.stop();
- m_thread.join();
- }
- bool IcmpClientImpl::Ping(const std::string& targetAddress)
- {
- m_done = false;
- SendEchoRequest(asio::ip::icmp::endpoint(asio::ip::address::from_string(targetAddress), 0), std::string());
- std::unique_lock<std::mutex> lock(m_mutex);
- if (m_condition.wait_for(lock, std::chrono::seconds(3), [&] { return m_done; }))
- return true;
- return false;
- }
- void IcmpClientImpl::SendEchoRequest(const asio::ip::icmp::endpoint& targetEndpoint, const std::string& data)
- {
- Internal::IcmpHeader echoRequest;
- echoRequest.type(Internal::IcmpHeader::echo_request);
- echoRequest.code(0);
- echoRequest.identifier(GetIdentifier());
- echoRequest.sequence_number(0);
- Internal::ComputeChecksum(echoRequest, data.begin(), data.end());
- asio::streambuf requestBuffer;
- std::ostream os(&requestBuffer);
- os << echoRequest << data;
- m_socket.send_to(requestBuffer.data(), targetEndpoint);
- }
- void IcmpClientImpl::StartReceive()
- {
- m_replyBuffer.consume(m_replyBuffer.size());
- m_socket.async_receive(m_replyBuffer.prepare(65536), std::bind(&IcmpClientImpl::HandleReceive, this, std::placeholders::_1, std::placeholders::_2));
- }
- void IcmpClientImpl::HandleReceive(const asio::error_code& error, std::size_t length)
- {
- m_replyBuffer.commit(length);
- std::istream is(&m_replyBuffer);
- Internal::Ipv4Header ipv4Header;
- Internal::IcmpHeader icmpHeader;
- is >> ipv4Header >> icmpHeader;
- if (is && icmpHeader.type() == Internal::IcmpHeader::echo_reply
- && icmpHeader.identifier() == GetIdentifier()
- && icmpHeader.sequence_number() == 0)
- {
- m_done = true;
- m_condition.notify_all();
- }
- StartReceive();
- }
- unsigned short IcmpClientImpl::GetIdentifier()
- {
- return static_cast<unsigned short>(::getpid());
- }
- } // namespace Network
|