From 30a47e1bd3759ab5938cba6117fe2a06a5236817 Mon Sep 17 00:00:00 2001 From: Tom Early Date: Sat, 4 Jul 2020 17:07:22 -0700 Subject: [PATCH] new CIp & CUdpSocket --- src/ccodecstream.cpp | 36 ++--- src/cdcsprotocol.cpp | 2 +- src/cdextraprotocol.cpp | 2 +- src/cdmrmmdvmprotocol.cpp | 2 +- src/cdmrplusprotocol.cpp | 2 +- src/cdplusprotocol.cpp | 2 +- src/cg3protocol.cpp | 6 +- src/cip.cpp | 274 +++++++++++++++++++++++++++++--------- src/cip.h | 124 +++++++++-------- src/crawsocket.cpp | 10 +- src/creflector.cpp | 2 +- src/ctranscoder.cpp | 2 +- src/cudpmsgsocket.cpp | 24 ++-- src/cudpsocket.cpp | 212 +++++++++++++++-------------- src/cudpsocket.h | 54 ++++---- src/cxlxprotocol.cpp | 2 +- src/cysfprotocol.cpp | 2 +- 17 files changed, 466 insertions(+), 292 deletions(-) diff --git a/src/ccodecstream.cpp b/src/ccodecstream.cpp index 7d8e0c8..2a6e1dc 100644 --- a/src/ccodecstream.cpp +++ b/src/ccodecstream.cpp @@ -61,7 +61,7 @@ CCodecStream::~CCodecStream() { // close socket m_Socket.Close(); - + // kill threads m_bStopThread = true; if ( m_pThread != NULL ) @@ -69,7 +69,7 @@ CCodecStream::~CCodecStream() m_pThread->join(); delete m_pThread; } - + // empty local queue while ( !m_LocalQueue.empty() ) { @@ -90,14 +90,14 @@ CCodecStream::~CCodecStream() bool CCodecStream::Init(uint16 uiPort) { bool ok; - + // reset stop flag m_bStopThread = false; - + // create server's IP m_Ip = g_Reflector.GetTranscoderIp(); m_uiPort = uiPort; - + // create our socket ok = m_Socket.Open(uiPort); if ( ok ) @@ -111,7 +111,7 @@ bool CCodecStream::Init(uint16 uiPort) std::cout << "Error opening socket on port UDP" << uiPort << " on ip " << g_Reflector.GetListenIp() << std::endl; m_bConnected = false; } - + // done return ok; } @@ -121,7 +121,7 @@ void CCodecStream::Close(void) // close socket m_bConnected = false; m_Socket.Close(); - + // kill threads m_bStopThread = true; if ( m_pThread != NULL ) @@ -157,33 +157,33 @@ void CCodecStream::Task(void) CIp Ip; uint8 Ambe[AMBE_SIZE]; uint8 DStarSync[] = { 0x55,0x2D,0x16 }; - + // any packet from transcoder - if ( m_Socket.Receive(&Buffer, &Ip, 5) != -1 ) + if ( m_Socket.Receive(Buffer, Ip, 5) ) { // crack if ( IsValidAmbePacket(Buffer, Ambe) ) { // tickle m_TimeoutTimer.Now(); - + // update statistics double ping = m_StatsTimer.DurationSinceNow(); if ( m_fPingMin == -1 ) { m_fPingMin = ping; m_fPingMax = ping; - + } else { m_fPingMin = MIN(m_fPingMin, ping); m_fPingMax = MAX(m_fPingMax, ping); - + } m_fPingSum += ping; m_fPingCount += 1; - + // pop the original packet if ( !m_LocalQueue.empty() ) { @@ -208,14 +208,14 @@ void CCodecStream::Task(void) } } } - + // anything in our queue while ( !empty() ) { // yes, pop it from queue CPacket *Packet = front(); pop(); - + // yes, send to ambed // this assume that thread pushing the Packet // have verified that the CodecStream is connected @@ -224,11 +224,11 @@ void CCodecStream::Task(void) m_uiTotalPackets++; EncodeAmbePacket(&Buffer, ((CDvFramePacket *)Packet)->GetAmbe(m_uiCodecIn)); m_Socket.Send(Buffer, m_Ip, m_uiPort); - + // and push to our local queue m_LocalQueue.push(Packet); } - + // handle timeout if ( !m_LocalQueue.empty() && (m_TimeoutTimer.DurationSinceNow() >= (TRANSCODER_AMBEPACKET_TIMEOUT/1000.0f)) ) { @@ -243,7 +243,7 @@ void CCodecStream::Task(void) bool CCodecStream::IsValidAmbePacket(const CBuffer &Buffer, uint8 *Ambe) { bool valid = false; - + if ( (Buffer.size() == 11) && (Buffer.data()[0] == m_uiCodecOut) ) { ::memcpy(Ambe, &(Buffer.data()[2]), 9); diff --git a/src/cdcsprotocol.cpp b/src/cdcsprotocol.cpp index f4f7b27..536e0a2 100644 --- a/src/cdcsprotocol.cpp +++ b/src/cdcsprotocol.cpp @@ -72,7 +72,7 @@ void CDcsProtocol::Task(void) CDvFramePacket *Frame; // handle incoming packets - if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 ) + if ( m_Socket.Receive(Buffer, Ip, 20) ) { // crack the packet if ( IsValidDvPacket(Buffer, &Header, &Frame) ) diff --git a/src/cdextraprotocol.cpp b/src/cdextraprotocol.cpp index be1a31d..568f7cb 100644 --- a/src/cdextraprotocol.cpp +++ b/src/cdextraprotocol.cpp @@ -75,7 +75,7 @@ void CDextraProtocol::Task(void) CDvLastFramePacket *LastFrame; // any incoming packet ? - if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 ) + if ( m_Socket.Receive(Buffer, Ip, 20) ) { // crack the packet if ( (Frame = IsValidDvFramePacket(Buffer)) != NULL ) diff --git a/src/cdmrmmdvmprotocol.cpp b/src/cdmrmmdvmprotocol.cpp index 41468b3..8e05bb2 100644 --- a/src/cdmrmmdvmprotocol.cpp +++ b/src/cdmrmmdvmprotocol.cpp @@ -97,7 +97,7 @@ void CDmrmmdvmProtocol::Task(void) CDvLastFramePacket *LastFrame; // handle incoming packets - if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 ) + if ( m_Socket.Receive(Buffer, Ip, 20) ) { //Buffer.DebugDump(g_Reflector.m_DebugFile); // crack the packet diff --git a/src/cdmrplusprotocol.cpp b/src/cdmrplusprotocol.cpp index cb9b19f..2323732 100644 --- a/src/cdmrplusprotocol.cpp +++ b/src/cdmrplusprotocol.cpp @@ -86,7 +86,7 @@ void CDmrplusProtocol::Task(void) CDvFramePacket *Frames[3]; // handle incoming packets - if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 ) + if ( m_Socket.Receive(Buffer, Ip, 20) ) { // crack the packet if ( IsValidDvFramePacket(Ip, Buffer, Frames) ) diff --git a/src/cdplusprotocol.cpp b/src/cdplusprotocol.cpp index 95e93ac..7d59c41 100644 --- a/src/cdplusprotocol.cpp +++ b/src/cdplusprotocol.cpp @@ -73,7 +73,7 @@ void CDplusProtocol::Task(void) CDvLastFramePacket *LastFrame; // handle incoming packets - if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 ) + if ( m_Socket.Receive(Buffer, Ip, 20) ) { // crack the packet if ( (Frame = IsValidDvFramePacket(Buffer)) != NULL ) diff --git a/src/cg3protocol.cpp b/src/cg3protocol.cpp index 72b6f8f..6f75be3 100644 --- a/src/cg3protocol.cpp +++ b/src/cg3protocol.cpp @@ -156,11 +156,11 @@ void CG3Protocol::PresenceTask(void) CCallsign Terminal; - if ( m_PresenceSocket.Receive(&Buffer, &ReqIp, 20) != -1 ) + if ( m_PresenceSocket.Receive(Buffer, ReqIp, 20) ) { CIp Ip(ReqIp); - Ip.GetSockAddr()->sin_port = htons(G3_DV_PORT); + Ip.SetPort(G3_DV_PORT); if (Buffer.size() == 32) { @@ -390,7 +390,7 @@ void CG3Protocol::Task(void) CDvLastFramePacket *LastFrame; // any incoming packet ? - if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 ) + if ( m_Socket.Receive(Buffer, Ip, 20) != -1 ) { CIp ClIp; CIp *BaseIp = NULL; diff --git a/src/cip.cpp b/src/cip.cpp index 5cec9b5..3c5c2ae 100644 --- a/src/cip.cpp +++ b/src/cip.cpp @@ -1,91 +1,241 @@ -// -// cip.cpp -// xlxd -// -// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015. -// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. -// -// ---------------------------------------------------------------------------- -// This file is part of xlxd. -// -// xlxd 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. -// -// xlxd 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 Foobar. If not, see . -// ---------------------------------------------------------------------------- - -#include "main.h" -#include -#include "cip.h" +/* +* Copyright (C) 2020 by Thomas 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 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 +#include +#include #include - -//////////////////////////////////////////////////////////////////////////////////////// -// constructors +#include "cip.h" CIp::CIp() { - ::memset(&m_Addr, 0, sizeof(m_Addr)); - m_Addr.sin_family = AF_INET; + Clear(); } -CIp::CIp(const char *sz) +CIp::CIp(const char *address, int family, int type, uint16_t port) +{ + Clear(); + struct addrinfo hints, *result; + bzero(&hints, sizeof(struct addrinfo)); + hints.ai_family = family; + hints.ai_socktype = type; + if (0 == getaddrinfo(address, (port ? std::to_string(port).c_str() : NULL), &hints, &result)) { + memcpy(&addr, result->ai_addr, result->ai_addrlen); + addr.ss_family = result->ai_family; + freeaddrinfo(result); + } + SetPort(port); +} +CIp::CIp(const int family, const uint16_t port, const char *address) { - ::memset(&m_Addr, 0, sizeof(m_Addr)); - m_Addr.sin_family = AF_INET; - // try xxx.xxx.xxx.xxxx first - m_Addr.sin_addr.s_addr = inet_addr(sz); - if ( m_Addr.sin_addr.s_addr == INADDR_NONE ) - { - // otherwise try to resolve via dns - hostent *record = gethostbyname(sz); - if( record != NULL ) - { - m_Addr.sin_addr.s_addr = ((in_addr * )record->h_addr)->s_addr; - } - } + Initialize(family, port, address); } -CIp::CIp(const struct sockaddr_in *sa) +void CIp::Initialize(const int family, const uint16_t port, const char *address) { - ::memcpy(&m_Addr, sa, sizeof(m_Addr)); + Clear(); + addr.ss_family = family; + if (AF_INET == family) { + auto addr4 = (struct sockaddr_in *)&addr; + addr4->sin_port = htons(port); + if (address) { + if (0 == strncasecmp(address, "loc", 3)) + inet_pton(AF_INET, "127.0.0.1", &(addr4->sin_addr)); + else if (0 == strncasecmp(address, "any", 3)) + inet_pton(AF_INET, "0.0.0.0", &(addr4->sin_addr)); + else if (0 == strncasecmp(address, "none", 4)) + addr.ss_family = AF_UNSPEC; + else { + if (1 > inet_pton(AF_INET, address, &(addr4->sin_addr))) + std::cerr << "Address Initialization Error: '" << address << "' is not a valdid IPV4 address!" << std::endl; + } + } + } else if (AF_INET6 == family) { + auto addr6 = (struct sockaddr_in6 *)&addr; + addr6->sin6_port = htons(port); + if (address) { + if (0 == strncasecmp(address, "loc", 3)) + inet_pton(AF_INET6, "::1", &(addr6->sin6_addr)); + else if (0 == strncasecmp(address, "any", 3)) + inet_pton(AF_INET6, "::", &(addr6->sin6_addr)); + else if (0 == strncasecmp(address, "none", 4)) + addr.ss_family = AF_UNSPEC; + else { + if (1 > inet_pton(AF_INET6, address, &(addr6->sin6_addr))) + std::cerr << "Address Initialization Error: '" << address << "' is not a valid IPV6 address!" << std::endl; + } + } + } else + std::cerr << "Error: Wrong address family type:" << family << " for [" << (address ? address : "NULL") << "]:" << port << std::endl; } +bool CIp::operator==(const CIp &rhs) const // doesn't compare ports, only addresses and families +{ + if (addr.ss_family != rhs.addr.ss_family) + return false; + if (AF_INET == addr.ss_family) { + auto l = (struct sockaddr_in *)&addr; + auto r = (struct sockaddr_in *)&rhs.addr; + return (l->sin_addr.s_addr == r->sin_addr.s_addr); + } else if (AF_INET6 == addr.ss_family) { + auto l = (struct sockaddr_in6 *)&addr; + auto r = (struct sockaddr_in6 *)&rhs.addr; + return (0 == memcmp(&(l->sin6_addr), &(r->sin6_addr), sizeof(struct in6_addr))); + } + return false; +} -CIp::CIp(const CIp &ip) +bool CIp::operator!=(const CIp &rhs) const // doesn't compare ports, only addresses and families { - ::memcpy(&m_Addr, &ip.m_Addr, sizeof(m_Addr)); + if (addr.ss_family != rhs.addr.ss_family) + return true; + if (AF_INET == addr.ss_family) { + auto l = (struct sockaddr_in *)&addr; + auto r = (struct sockaddr_in *)&rhs.addr; + return (l->sin_addr.s_addr != r->sin_addr.s_addr); + } else if (AF_INET6 == addr.ss_family) { + auto l = (struct sockaddr_in6 *)&addr; + auto r = (struct sockaddr_in6 *)&rhs.addr; + return (0 != memcmp(&(l->sin6_addr), &(r->sin6_addr), sizeof(struct in6_addr))); + } + return true; } -//////////////////////////////////////////////////////////////////////////////////////// -// set +bool CIp::AddressIsZero() const +{ + if (AF_INET == addr.ss_family) { + auto addr4 = (struct sockaddr_in *)&addr; + return (addr4->sin_addr.s_addr == 0U); + } else { + auto addr6 = (struct sockaddr_in6 *)&addr; + for (unsigned int i=0; i<16; i++) { + if (addr6->sin6_addr.s6_addr[i]) + return false; + } + return true; + } +} -void CIp::SetSockAddr(struct sockaddr_in *sa) +void CIp::ClearAddress() { - ::memcpy(&m_Addr, sa, sizeof(m_Addr)); + if (AF_INET == addr.ss_family) { + auto addr4 = (struct sockaddr_in *)&addr; + addr4->sin_addr.s_addr = 0U; + strcpy(straddr, "0.0.0.0"); + } else { + auto addr6 = (struct sockaddr_in6 *)&addr; + memset(&(addr6->sin6_addr.s6_addr), 0, 16); + strcpy(straddr, "::"); + } } -//////////////////////////////////////////////////////////////////////////////////////// -// operator +const char *CIp::GetAddress() const +{ + if (straddr[0]) + return straddr; + + if (AF_INET == addr.ss_family) { + auto addr4 = (struct sockaddr_in *)&addr; + inet_ntop(AF_INET, &(addr4->sin_addr), straddr, INET6_ADDRSTRLEN); + } else if (AF_INET6 == addr.ss_family) { + auto addr6 = (struct sockaddr_in6 *)&addr; + inet_ntop(AF_INET6, &(addr6->sin6_addr), straddr, INET6_ADDRSTRLEN); + } else { + std::cerr << "CIp::GetAddress: unknown socket family=" << addr.ss_family << std::endl; + } + return straddr; +} -bool CIp::operator ==(const CIp &ip) const +std::ostream &operator<<(std::ostream &stream, const CIp &Ip) { - return ( (ip.m_Addr.sin_family == m_Addr.sin_family) && - (ip.m_Addr.sin_addr.s_addr == m_Addr.sin_addr.s_addr) && - (ip.m_Addr.sin_port == m_Addr.sin_port)) ; + const char *sz = Ip; + if (AF_INET6 == Ip.GetFamily()) + stream << "[" << sz << "]"; + else + stream << sz; + const uint16_t port = Ip.GetPort(); + if (port) + stream << ":" << port; + return stream; } -CIp::operator const char *() const +uint32_t CIp::GetAddr() const { - return ::inet_ntoa(m_Addr.sin_addr); + if (AF_INET6 == addr.ss_family) { + auto addr6 = (struct sockaddr_in6 *)&addr; + // hash the results + auto *a = (const uint32_t *)&(addr6->sin6_addr.s6_addr); + return a[0] ^ a[1] ^ a[2] ^ a[3]; + } else { + auto addr4 = (struct sockaddr_in *)&addr; + return addr4->sin_addr.s_addr; + } } +int CIp::GetFamily() const +{ + return addr.ss_family; +} +uint16_t CIp::GetPort() const +{ + if (AF_INET == addr.ss_family) { + auto addr4 = (struct sockaddr_in *)&addr; + return ntohs(addr4->sin_port); + } else if (AF_INET6 == addr.ss_family) { + auto addr6 = (struct sockaddr_in6 *)&addr; + return ntohs(addr6->sin6_port); + } else + return 0; +} + +void CIp::SetPort(const uint16_t newport) +{ + if (AF_INET == addr.ss_family) { + auto addr4 = (struct sockaddr_in *)&addr; + addr4->sin_port = htons(newport); + } else if (AF_INET6 == addr.ss_family) { + auto addr6 = (struct sockaddr_in6 *)&addr; + addr6->sin6_port = htons(newport); + } +} + +struct sockaddr *CIp::GetPointer() +{ + memset(straddr, 0, INET6_ADDRSTRLEN); // things might change + return (struct sockaddr *)&addr; +} + +const struct sockaddr *CIp::GetCPointer() const +{ + return (const struct sockaddr *)&addr; +} + +size_t CIp::GetSize() const +{ + if (AF_INET == addr.ss_family) + return sizeof(struct sockaddr_in); + else + return sizeof(struct sockaddr_in6); +} + +void CIp::Clear() +{ + memset(&addr, 0, sizeof(struct sockaddr_storage)); + memset(straddr, 0, INET6_ADDRSTRLEN); +} diff --git a/src/cip.h b/src/cip.h index 6c43288..78fc05d 100644 --- a/src/cip.h +++ b/src/cip.h @@ -1,63 +1,73 @@ -// -// cip.h -// xlxd -// -// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015. -// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. -// -// ---------------------------------------------------------------------------- -// This file is part of xlxd. -// -// xlxd 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. -// -// xlxd 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 Foobar. If not, see . -// ---------------------------------------------------------------------------- - -#ifndef cip_h -#define cip_h - - -//////////////////////////////////////////////////////////////////////////////////////// -// class +#pragma once + +/* + * Copyright (C) 2020 by Thomas 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 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include class CIp { public: - // constructors - CIp(); - //CIp(uint8, uint8, uint8, uint8); - CIp(const struct sockaddr_in *); - CIp(const char *); - CIp(const CIp &); - - // destructor - virtual ~CIp() {}; - - // sockaddr - void SetSockAddr(struct sockaddr_in *); - struct sockaddr_in *GetSockAddr(void) { return &m_Addr; } - - // convertor - uint32 GetAddr(void) const { return m_Addr.sin_addr.s_addr; } - uint16 GetPort(void) const { return m_Addr.sin_port; } - - // operator - bool operator ==(const CIp &) const; - operator const char *() const; - -protected: - // data - struct sockaddr_in m_Addr; + // constructors + CIp(); + CIp(const char *address, int family = AF_UNSPEC, int type = SOCK_DGRAM, uint16_t port = 0U); + CIp(const int family, const uint16_t port = 0U, const char *address = NULL); + + // initializer for empty constructor + void Initialize(const int family, const uint16_t port = 0U, const char *address = NULL); + + // comparison operators + bool operator==(const CIp &rhs) const; + bool operator!=(const CIp &rhs) const; + + // state methods + bool AddressIsZero() const; + void ClearAddress(); + const char *GetAddress() const; + operator const char *() const { return GetAddress(); } + friend std::ostream &operator<<(std::ostream &stream, const CIp &Ip); + int GetFamily() const; + uint16_t GetPort() const; + size_t GetSize() const; + uint32_t GetAddr() const; + + // modifiers + void SetPort(const uint16_t newport); + + // for i/o + struct sockaddr *GetPointer(); + const struct sockaddr *GetCPointer() const; + + void Clear(); + +private: + struct sockaddr_storage addr; + mutable char straddr[INET6_ADDRSTRLEN]; }; -//////////////////////////////////////////////////////////////////////////////////////// -#endif /* cip_h */ +std::ostream &operator<<(std::ostream &stream, const CIp &Ip); diff --git a/src/crawsocket.cpp b/src/crawsocket.cpp index a30908d..de8514b 100644 --- a/src/crawsocket.cpp +++ b/src/crawsocket.cpp @@ -19,7 +19,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Foobar. If not, see . // ---------------------------------------------------------------------------- #include "main.h" @@ -54,7 +54,7 @@ bool CRawSocket::Open(uint16 uiProto) { bool open = false; int on = 1; - + // create socket m_Socket = socket(AF_INET,SOCK_RAW,uiProto); if ( m_Socket != -1 ) @@ -63,7 +63,7 @@ bool CRawSocket::Open(uint16 uiProto) open = true; m_Proto = uiProto; } - + // done return open; } @@ -113,7 +113,7 @@ int CRawSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout) Buffer->resize(iRecvLen); // get IP - Ip->SetSockAddr(&Sin); + memcpy(Ip->GetPointer(), &Sin, sizeof(struct sockaddr_in)); } } @@ -148,7 +148,7 @@ int CRawSocket::IcmpReceive(CBuffer *Buffer, CIp *Ip, int timeout) Sin.sin_family = AF_INET; Sin.sin_addr.s_addr = remote_iph->ip_dst.s_addr; - Ip->SetSockAddr(&Sin); + memcpy(Ip->GetPointer(), &Sin, sizeof(struct sockaddr_in)); } } diff --git a/src/creflector.cpp b/src/creflector.cpp index a5cb278..41e5b7c 100644 --- a/src/creflector.cpp +++ b/src/creflector.cpp @@ -429,7 +429,7 @@ void CReflector::JsonReportThread(CReflector *This) while ( !This->m_bStopThreads ) { // any command ? - if ( Socket.Receive(&Buffer, &Ip, 50) != -1 ) + if ( Socket.Receive(Buffer, Ip, 50) ) { // check verb if ( Buffer.Compare((uint8 *)"hello", 5) == 0 ) diff --git a/src/ctranscoder.cpp b/src/ctranscoder.cpp index 6e48ccc..e4d91b3 100644 --- a/src/ctranscoder.cpp +++ b/src/ctranscoder.cpp @@ -140,7 +140,7 @@ void CTranscoder::Task(void) // anything coming in from codec server ? //if ( (m_Socket.Receive(&Buffer, &Ip, 20) != -1) && (Ip == m_Ip) ) - if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 ) + if ( m_Socket.Receive(Buffer, Ip, 20) ) { m_LastActivityTime.Now(); diff --git a/src/cudpmsgsocket.cpp b/src/cudpmsgsocket.cpp index 45d438d..b90f702 100644 --- a/src/cudpmsgsocket.cpp +++ b/src/cudpmsgsocket.cpp @@ -19,7 +19,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Foobar. If not, see . // ---------------------------------------------------------------------------- #include "main.h" @@ -34,7 +34,7 @@ bool CUdpMsgSocket::Open(uint16 uiPort) int on = 1; ret = CUdpSocket::Open(uiPort); - setsockopt(m_Socket, IPPROTO_IP, IP_PKTINFO, (char *)&on, sizeof(on)); + setsockopt(m_fd, IPPROTO_IP, IP_PKTINFO, (char *)&on, sizeof(on)); return ret; } @@ -60,7 +60,7 @@ int CUdpMsgSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout) } Control; // socket valid ? - if ( m_Socket != -1 ) + if ( m_fd != -1 ) { // allocate buffer Buffer->resize(UDP_MSG_BUFFER_LENMAX); @@ -80,22 +80,23 @@ int CUdpMsgSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout) // control socket FD_ZERO(&FdSet); - FD_SET(m_Socket, &FdSet); + FD_SET(m_fd, &FdSet); tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; - select(m_Socket + 1, &FdSet, 0, 0, &tv); - + select(m_fd + 1, &FdSet, 0, 0, &tv); + // read - iRecvLen = (int)recvmsg(m_Socket, &Msg, 0); - + iRecvLen = (int)recvmsg(m_fd, &Msg, 0); + // handle if ( iRecvLen != -1 ) { // adjust buffer size Buffer->resize(iRecvLen); - + // get IP - Ip->SetSockAddr(&Sin); + if (AF_INET == m_addr.GetFamily()) + memcpy(Ip->GetPointer(), &Sin, sizeof(struct sockaddr_in)); // get local IP struct cmsghdr *Cmsg; @@ -109,8 +110,7 @@ int CUdpMsgSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout) } } } - + // done return iRecvLen; } - diff --git a/src/cudpsocket.cpp b/src/cudpsocket.cpp index 5caa074..9b7fa8a 100644 --- a/src/cudpsocket.cpp +++ b/src/cudpsocket.cpp @@ -4,6 +4,7 @@ // // Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015. // Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// Copyright © 2020 Thomas A. Early, N7TAE // // ---------------------------------------------------------------------------- // This file is part of xlxd. @@ -19,11 +20,11 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Foobar. If not, see . // ---------------------------------------------------------------------------- -#include "main.h" #include +#include "main.h" #include "creflector.h" #include "cudpsocket.h" @@ -33,7 +34,7 @@ CUdpSocket::CUdpSocket() { - m_Socket = -1; + m_fd = -1; } //////////////////////////////////////////////////////////////////////////////////////// @@ -41,133 +42,142 @@ CUdpSocket::CUdpSocket() CUdpSocket::~CUdpSocket() { - if ( m_Socket != -1 ) - { - Close(); - } + Close(); } //////////////////////////////////////////////////////////////////////////////////////// // open & close -bool CUdpSocket::Open(uint16 uiPort) +// returns true on error +bool CUdpSocket::Open(const CIp &Ip) { - bool open = false; - - // create socket - m_Socket = socket(PF_INET,SOCK_DGRAM,0); - if ( m_Socket != -1 ) - { - // initialize sockaddr struct - ::memset(&m_SocketAddr, 0, sizeof(struct sockaddr_in)); - m_SocketAddr.sin_family = AF_INET; - m_SocketAddr.sin_port = htons(uiPort); - m_SocketAddr.sin_addr.s_addr = inet_addr(g_Reflector.GetListenIp()); - - if ( bind(m_Socket, (struct sockaddr *)&m_SocketAddr, sizeof(struct sockaddr_in)) == 0 ) - { - fcntl(m_Socket, F_SETFL, O_NONBLOCK); - open = true; - } - else - { - close(m_Socket); - m_Socket = -1; - } - } - - // done - return open; + // check for a vaild family + if (AF_UNSPEC == Ip.GetFamily()) + return true; + + // create socket + m_fd = socket(Ip.GetFamily(), SOCK_DGRAM, 0); + if ( m_fd < 0 ) + { + std::cerr << "Unable to open socket on " << Ip << ", " << strerror(errno) << std::endl; + return false; + } + // initialize sockaddr struct + m_addr = Ip; + + int reuse = 1; + if ( 0 > setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int))) + { + std::cerr << "Cannot set the UDP socket option on " << m_addr << ", " << strerror(errno) << std::endl; + Close(); + return false; + } + + if (fcntl(m_fd, F_SETFL, O_NONBLOCK)) + { + std::cerr << "fcntl set non-blocking failed on " << m_addr << ", " << strerror(errno) << std::endl; + Close(); + return false; + } + + if ( bind(m_fd, m_addr.GetCPointer(), m_addr.GetSize()) ) + { + std::cerr << "bind failed on " << m_addr << ", " << strerror(errno) << std::endl; + Close(); + return false; + } + + if (0 == m_addr.GetPort()) { // get the assigned port for an ephemeral port request + CIp a; + socklen_t len = sizeof(struct sockaddr_storage); + if (getsockname(m_fd, a.GetPointer(), &len)) + { + std::cerr << "getsockname error " << m_addr << ", " << strerror(errno) << std::endl; + Close(); + return false; + } + if (a != m_addr) + std::cout << "getsockname didn't return the same address as set: returned " << a << ", should have been " << m_addr << std::endl; + + m_addr.SetPort(a.GetPort()); + } + + // done + return true; } void CUdpSocket::Close(void) { - if ( m_Socket != -1 ) - { - close(m_Socket); - m_Socket = -1; - } + if ( m_fd >= 0 ) + { + close(m_fd); + m_fd = -1; + } } //////////////////////////////////////////////////////////////////////////////////////// // read -int CUdpSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout) +bool CUdpSocket::Receive(CBuffer &Buffer, CIp &Ip, int timeout) { - struct sockaddr_in Sin; - fd_set FdSet; - unsigned int uiFromLen = sizeof(struct sockaddr_in); - int iRecvLen = -1; - struct timeval tv; - - // socket valid ? - if ( m_Socket != -1 ) - { - // control socket - FD_ZERO(&FdSet); - FD_SET(m_Socket, &FdSet); - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - select(m_Socket + 1, &FdSet, 0, 0, &tv); - - // allocate buffer - Buffer->resize(UDP_BUFFER_LENMAX); - - // read - iRecvLen = (int)recvfrom(m_Socket, - (void *)Buffer->data(), UDP_BUFFER_LENMAX, - 0, (struct sockaddr *)&Sin, &uiFromLen); - - // handle - if ( iRecvLen != -1 ) - { - // adjust buffer size - Buffer->resize(iRecvLen); - - // get IP - Ip->SetSockAddr(&Sin); - } - } - - // done - return iRecvLen; + // socket valid ? + if ( 0 > m_fd ) + return false; + + // control socket + fd_set FdSet; + FD_ZERO(&FdSet); + FD_SET(m_fd, &FdSet); + struct timeval tv; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + auto rval = select(m_fd + 1, &FdSet, 0, 0, &tv); + if (0 > rval) + { + std::cerr << "select error on UPD port " << m_addr << ": " << strerror(errno) << std::endl; + return false; + } + else if (0 == rval) + return false; + + // read + uint8_t buf[UDP_BUFFER_LENMAX]; + unsigned int fromsize = sizeof(struct sockaddr_storage); + auto iRecvLen = recvfrom(m_fd, buf, UDP_BUFFER_LENMAX, 0, Ip.GetPointer(), &fromsize); + + // handle + if (0 >= iRecvLen) + return false; + + Buffer.Set(buf, iRecvLen); + + // done + return true; } //////////////////////////////////////////////////////////////////////////////////////// // write -int CUdpSocket::Send(const CBuffer &Buffer, const CIp &Ip) +void CUdpSocket::Send(const CBuffer &Buffer, const CIp &Ip) const { - CIp temp(Ip); - return (int)::sendto(m_Socket, - (void *)Buffer.data(), Buffer.size(), - 0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in)); + sendto(m_fd, Buffer.data(), Buffer.size(), 0, Ip.GetCPointer(), Ip.GetSize()); } -int CUdpSocket::Send(const char *Buffer, const CIp &Ip) +void CUdpSocket::Send(const char *Buffer, const CIp &Ip) const { - CIp temp(Ip); - return (int)::sendto(m_Socket, - (void *)Buffer, ::strlen(Buffer), - 0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in)); + sendto(m_fd, Buffer, ::strlen(Buffer), 0, Ip.GetCPointer(), Ip.GetSize()); } -int CUdpSocket::Send(const CBuffer &Buffer, const CIp &Ip, uint16 destport) +void CUdpSocket::Send(const CBuffer &Buffer, const CIp &Ip, uint16_t destport) const { - CIp temp(Ip); - temp.GetSockAddr()->sin_port = htons(destport); - return (int)::sendto(m_Socket, - (void *)Buffer.data(), Buffer.size(), - 0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in)); + CIp temp(Ip); + temp.SetPort(destport); + sendto(m_fd, Buffer.data(), Buffer.size(), 0, temp.GetCPointer(), temp.GetSize()); } -int CUdpSocket::Send(const char *Buffer, const CIp &Ip, uint16 destport) +void CUdpSocket::Send(const char *Buffer, const CIp &Ip, uint16_t destport) const { - CIp temp(Ip); - temp.GetSockAddr()->sin_port = htons(destport); - return (int)::sendto(m_Socket, - (void *)Buffer, ::strlen(Buffer), - 0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in)); + CIp temp(Ip); + temp.SetPort(destport); + sendto(m_fd, Buffer, ::strlen(Buffer), 0, temp.GetCPointer(), temp.GetSize()); } - - diff --git a/src/cudpsocket.h b/src/cudpsocket.h index e91ed80..5f42e9f 100644 --- a/src/cudpsocket.h +++ b/src/cudpsocket.h @@ -4,6 +4,7 @@ // // Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015. // Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// Copyright © 2020 Thomas A. Early, N7TAE // // ---------------------------------------------------------------------------- // This file is part of xlxd. @@ -19,14 +20,14 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Foobar. If not, see . // ---------------------------------------------------------------------------- #ifndef cudpsocket_h #define cudpsocket_h +#include #include -//#include #include #include #include @@ -48,30 +49,33 @@ class CUdpSocket { public: - // constructor - CUdpSocket(); - - // destructor - ~CUdpSocket(); - - // open & close - bool Open(uint16); - void Close(void); - int GetSocket(void) { return m_Socket; } - - // read - int Receive(CBuffer *, CIp *, int); - - // write - int Send(const CBuffer &, const CIp &); - int Send(const CBuffer &, const CIp &, uint16); - int Send(const char *, const CIp &); - int Send(const char *, const CIp &, uint16); - + // constructor + CUdpSocket(); + + // destructor + ~CUdpSocket(); + + // open & close + bool Open(const CIp &Ip); + void Close(void); + int GetSocket(void) + { + return m_fd; + } + + // read + bool Receive(CBuffer &, CIp &, int); + + // write + void Send(const CBuffer &, const CIp &) const; + void Send(const char *, const CIp &) const; + void Send(const CBuffer &, const CIp &, uint16_t) const; + void Send(const char *, const CIp &, uint16_t) const; + protected: - // data - int m_Socket; - struct sockaddr_in m_SocketAddr; + // data + int m_fd; + CIp m_addr; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cxlxprotocol.cpp b/src/cxlxprotocol.cpp index 26a022f..d237aa4 100644 --- a/src/cxlxprotocol.cpp +++ b/src/cxlxprotocol.cpp @@ -75,7 +75,7 @@ void CXlxProtocol::Task(void) CDvLastFramePacket *LastFrame; // any incoming packet ? - if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 ) + if ( m_Socket.Receive(Buffer, Ip, 20) ) { // crack the packet if ( (Frame = IsValidDvFramePacket(Buffer)) != NULL ) diff --git a/src/cysfprotocol.cpp b/src/cysfprotocol.cpp index 208fbe4..968fcb8 100644 --- a/src/cysfprotocol.cpp +++ b/src/cysfprotocol.cpp @@ -111,7 +111,7 @@ void CYsfProtocol::Task(void) } // handle incoming packets - if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 ) + if ( m_Socket.Receive(Buffer, Ip, 20) ) { // crack the packet if ( IsValidDvPacket(Buffer, &Fich) )