|
|
@@ -0,0 +1,142 @@
|
|
|
+#include "Finder.h"
|
|
|
+#include <BroadcastClient.h>
|
|
|
+#include <BroadcastServer.h>
|
|
|
+#include <Logging.h>
|
|
|
+#include <chrono>
|
|
|
+
|
|
|
+
|
|
|
+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::Info, ss.str());
|
|
|
+
|
|
|
+ {
|
|
|
+ std::unique_lock<std::mutex> 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<void(const std::string&)>());
|
|
|
+
|
|
|
+ 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<std::mutex> lock(m_mutex);
|
|
|
+ int port = m_port;
|
|
|
+ m_port = 0;
|
|
|
+
|
|
|
+ ss.str("");
|
|
|
+ ss << "New port for " << ipAddress << ": " << port << std::endl;
|
|
|
+ Logging::Log(Logging::Severity::Info, ss.str());
|
|
|
+
|
|
|
+ return port;
|
|
|
+}
|
|
|
+
|
|
|
+bool Finder::Timeout() const
|
|
|
+{
|
|
|
+ return m_startTime + m_timeout <= std::chrono::system_clock::now();
|
|
|
+}
|
|
|
+
|
|
|
+bool Finder::PortFound()
|
|
|
+{
|
|
|
+ std::unique_lock<std::mutex> 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<std::mutex> 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<unsigned char>(*it) != 0)
|
|
|
+ output += *it++;
|
|
|
+
|
|
|
+ Advance(it);
|
|
|
+
|
|
|
+ return output;
|
|
|
+}
|
|
|
+
|
|
|
+void Finder::Advance(std::string::const_iterator& it) const
|
|
|
+{
|
|
|
+ while (static_cast<unsigned char>(*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
|