/* * Copyright (C) 2016 by Jonathan Naylor G4KLX * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "YSFReflector.h" #include "StopWatch.h" #include "Network.h" #include #include int main(int argc, char** argv) { if (argc == 1) { ::fprintf(stderr, "Usage: YSFReflector \n"); return 1; } unsigned int port = ::atoi(argv[1]); if (port == 0U) { ::fprintf(stderr, "YSFReflector: invalid port number\n"); return 1; } CYSFReflector Reflector(port); Reflector.run(); return 0; } CYSFReflector::CYSFReflector(unsigned int port) : m_port(port), m_repeaters() { } CYSFReflector::~CYSFReflector() { } void CYSFReflector::run() { CNetwork network(m_port, false); bool ret = network.open(); if (!ret) return; CStopWatch stopWatch; stopWatch.start(); CTimer pollTimer(1000U, 60U); pollTimer.start(); for (;;) { unsigned char buffer[200U]; unsigned int len = network.readData(buffer); if (len > 0U) { std::string callsign = std::string((char*)(buffer + 4U), YSF_CALLSIGN_LENGTH); CYSFRepeater* rpt = findRepeater(callsign); if (rpt != NULL) { for (auto it = m_repeaters.begin(); it != m_repeaters.end(); ++it) { if ((*it)->m_callsign != callsign) network.writeData(buffer, (*it)->m_address, (*it)->m_port); } } else { ::fprintf(stdout, "Data received from an unknown repeater - %s\n", callsign.c_str()); } } // Refresh/add repeaters based on their polls std::string callsign; in_addr address; unsigned int port; bool ret = network.readPoll(callsign, address, port); if (ret) { CYSFRepeater* rpt = findRepeater(callsign); if (rpt == NULL) { ::fprintf(stdout, "Adding %s\n", callsign.c_str()); rpt = new CYSFRepeater; rpt->m_timer.start(); rpt->m_callsign = callsign; rpt->m_address = address; rpt->m_port = port; m_repeaters.push_back(rpt); } else { rpt->m_timer.start(); rpt->m_address = address; rpt->m_port = port; } } unsigned int ms = stopWatch.elapsed(); stopWatch.start(); network.clock(ms); pollTimer.clock(ms); if (pollTimer.hasExpired()) { for (auto it = m_repeaters.begin(); it != m_repeaters.end(); ++it) network.writePoll((*it)->m_address, (*it)->m_port); pollTimer.start(); } // Remove any repeaters that haven't reported for a while for (auto it = m_repeaters.begin(); it != m_repeaters.end(); ++it) { (*it)->m_timer.clock(ms); if ((*it)->m_timer.hasExpired()) { ::fprintf(stdout, "Removing %s\n", (*it)->m_callsign.c_str()); m_repeaters.erase(it); break; } } if (ms < 5U) { #if defined(_WIN32) || defined(_WIN64) ::Sleep(5UL); // 5ms #else ::usleep(5000); // 5ms #endif } } network.close(); } CYSFRepeater* CYSFReflector::findRepeater(const std::string& callsign) const { for (auto it = m_repeaters.begin(); it != m_repeaters.end(); ++it) { if ((*it)->m_callsign == callsign) return *it; } return NULL; }