#include "Finder.h" #include #include #include #include namespace VStarCam { Finder::Finder(const std::string& sourceAddress) : m_startTime(asio::system_timer::time_point(std::chrono::system_clock::duration::max())), m_timeout(std::chrono::seconds(5)), m_sourceAddress(sourceAddress), m_sourcePort(8600), m_targetPort(9600), m_port(0) { } Finder::~Finder() { } int Finder::GetPort(const std::string& ipAddress) { std::stringstream ss; ss << "Retrieving port for " << ipAddress << std::endl; Logging::Log(Logging::Severity::Debug, ss.str()); { std::unique_lock lock(m_mutex); m_port = 0; m_targetAddress = ipAddress; } Network::BroadcastClient client(m_sourceAddress, m_targetPort, std::bind(&Finder::ProcessMessage, this, std::placeholders::_1)); Network::BroadcastServer server(m_sourceAddress, m_sourcePort, std::function()); m_startTime = std::chrono::system_clock::now(); std::string message("\x44\x48\x01\x01\x0a"); server.Broadcast(message, m_targetPort); while (!PortFound() && !Timeout()) server.Broadcast(message, m_targetPort); std::unique_lock lock(m_mutex); int port = m_port; m_port = 0; ss.str(""); ss << "New port for " << ipAddress << ": " << port << std::endl; Logging::Log(Logging::Severity::Debug, ss.str()); return port; } bool Finder::Timeout() const { return m_startTime + m_timeout <= std::chrono::system_clock::now(); } bool Finder::PortFound() { std::unique_lock lock(m_mutex); return m_condition.wait_for(lock, std::chrono::milliseconds(1000)) == std::cv_status::no_timeout; } void Finder::ProcessMessage(const std::string& message) { std::string::const_iterator it = message.begin(); // Skip Header it += 4; std::string ipAddress = GetString(it); std::string subnetMask = GetString(it); std::string gateway = GetString(it); std::string dns1 = GetString(it); std::string dns2 = GetString(it); // Skip Header it += 6; // Get Port unsigned int port; unsigned char low = *it++; unsigned char high = *it++; std::string hexPort; hexPort += high; hexPort += low; hexPort = StringToHex(hexPort); std::stringstream ss; ss << std::hex << hexPort; ss >> port; std::unique_lock lock(m_mutex); if (ipAddress == m_targetAddress) { m_port = port; lock.unlock(); m_condition.notify_one(); } } std::string Finder::GetString(std::string::const_iterator& it) const { std::string output; while (static_cast(*it) != 0) output += *it++; Advance(it); return output; } void Finder::Advance(std::string::const_iterator& it) const { while (static_cast(*it) == 0) it++; } std::string Finder::StringToHex(const std::string& input) const { static const char* const lut = "0123456789ABCDEF"; size_t len = input.length(); std::string output; output.reserve(2 * len); for (size_t i = 0; i < len; ++i) { const unsigned char c = input[i]; output.push_back(lut[c >> 4]); output.push_back(lut[c & 15]); } return output; } } // namespace VStarCam