// urfd -- The universal reflector // Copyright © 2024 Thomas A. Early N7TAE // // 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 3 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, see . #include #include #include #include #include #include #include "IP.h" #include "TCTCPSocket.h" void CTCTCPSocket::Close() { for (auto item : m_FD) close(item.second); m_FD.clear(); } void CTCTCPSocket::Close(char mod) { auto item = m_FD.find(mod); if (m_FD.end() == item) return; close(item->second); m_FD.erase(item); } bool CTCTCPSocket::Send(const STCPacket *packet) { int fd = GetFD(packet->module); if (fd < 0) { return true; } long count = 0; auto data = (const unsigned char *)packet; do { auto n = send(fd, data+count, sizeof(STCPacket)-count, 0); if (n <= 0) { if (0 == n) { std::cerr << "CTCTCPSocket::Send: socket on module '" << packet->module << "' has been closed!" << std::endl; } else { perror("CTCTCPSocket::Send"); } Close(packet->module); return true; } count += n; } while (count < sizeof(STCPacket)); return false; } bool CTCTCPSocket::Receive(int fd, STCPacket *packet) { auto data = (unsigned char *)packet; auto n = recv(fd, data, sizeof(STCPacket), MSG_WAITALL); if (n < 0) { perror("CTCTCPSocket::Receive"); return true; } return n == sizeof(STCPacket); } int CTCTCPSocket::GetFD(char module) const { const auto item = m_FD.find(module); if (m_FD.cend() == item) { return -1; } return item->second; } bool CTCTCPServer::Open(const std::string &address, const std::string &tcmodules, uint16_t port) { int fd; CIp ip(address.c_str(), AF_UNSPEC, SOCK_STREAM, port); fd = socket(ip.GetFamily(), SOCK_STREAM, 0); if (fd < 0) { perror("Open socket"); return true; } int yes = 1; int rv = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); if (rv < 0) { close(fd); perror("Open setsockopt"); return true; } rv = bind(fd, ip.GetCPointer(), ip.GetSize()); if (rv < 0) { close(fd); perror("Open bind"); return true; } rv = listen(fd, 3); if (rv < 0) { perror("Open listen"); close(fd); Close(); return true; } std::cout << "Waiting for " << tcmodules.size() << " transcoder connection(s)..." << std::endl; for (unsigned x=0; x