(src) add ipv6 support (except D-STAR G3 protocol support)

pull/189/head
SASANO Takayoshi 5 years ago
parent 93e761de8a
commit 6c2e2d32ba

@ -152,7 +152,10 @@ bool CDmridDir::IsValidDmrid(const char *sz)
ok = true; ok = true;
for ( size_t i = 0; (i < n) && ok; i++ ) for ( size_t i = 0; (i < n) && ok; i++ )
{ {
ok &= ::isdigit(sz[i]); if ( !::isdigit(sz[i]) )
{
ok = false;
}
} }
} }
return ok; return ok;

@ -70,9 +70,8 @@ bool CDmrmmdvmProtocol::Init(void)
m_LastKeepaliveTime.Now(); m_LastKeepaliveTime.Now();
// random number generator // random number generator
time_t t; std::random_device rd;
::srand((unsigned) time(&t)); m_uiAuthSeed = rd();
m_uiAuthSeed = (uint32)rand();
// done // done
return ok; return ok;

@ -63,8 +63,9 @@ bool CDmrplusProtocol::Init(void)
m_LastKeepaliveTime.Now(); m_LastKeepaliveTime.Now();
// random number generator // random number generator
time_t t; std::random_device rd;
::srand((unsigned) time(&t)); std::mt19937 mt(rd());
m_Random = mt;
// done // done
return ok; return ok;
@ -88,7 +89,7 @@ void CDmrplusProtocol::Task(void)
if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 ) if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 )
{ {
// crack the packet // crack the packet
if ( IsValidDvFramePacket(Ip, Buffer, Frames) ) if ( IsValidDvFramePacket(Buffer, Frames) )
{ {
//std::cout << "DMRplus DV frame" << std::endl; //std::cout << "DMRplus DV frame" << std::endl;
//Buffer.DebugDump(g_Reflector.m_DebugFile); //Buffer.DebugDump(g_Reflector.m_DebugFile);
@ -108,7 +109,7 @@ void CDmrplusProtocol::Task(void)
}*/ }*/
} }
} }
else if ( IsValidDvHeaderPacket(Ip, Buffer, &Header) ) else if ( IsValidDvHeaderPacket(Buffer, &Header) )
{ {
//std::cout << "DMRplus DV header:" << std::endl; //std::cout << "DMRplus DV header:" << std::endl;
//std::cout << "DMRplus DV header:" << std::endl << *Header << std::endl; //std::cout << "DMRplus DV header:" << std::endl << *Header << std::endl;
@ -444,7 +445,7 @@ bool CDmrplusProtocol::IsValidDisconnectPacket(const CBuffer &Buffer, CCallsign
return valid; return valid;
} }
bool CDmrplusProtocol::IsValidDvHeaderPacket(const CIp &Ip, const CBuffer &Buffer, CDvHeaderPacket **Header) bool CDmrplusProtocol::IsValidDvHeaderPacket(const CBuffer &Buffer, CDvHeaderPacket **Header)
{ {
bool valid = false; bool valid = false;
*Header = NULL; *Header = NULL;
@ -470,7 +471,7 @@ bool CDmrplusProtocol::IsValidDvHeaderPacket(const CIp &Ip, const CBuffer &Buffe
rpt1.SetModule(DMRPLUS_MODULE_ID); rpt1.SetModule(DMRPLUS_MODULE_ID);
CCallsign rpt2 = m_ReflectorCallsign; CCallsign rpt2 = m_ReflectorCallsign;
rpt2.SetModule(DmrDstIdToModule(uiDstId)); rpt2.SetModule(DmrDstIdToModule(uiDstId));
uint32 uiStreamId = IpToStreamId(Ip); uint32 uiStreamId = CreateStreamId();
// and packet // and packet
*Header = new CDvHeaderPacket(uiSrcId, CCallsign("CQCQCQ"), rpt1, rpt2, uiStreamId, 0, 0); *Header = new CDvHeaderPacket(uiSrcId, CCallsign("CQCQCQ"), rpt1, rpt2, uiStreamId, 0, 0);
@ -486,7 +487,7 @@ bool CDmrplusProtocol::IsValidDvHeaderPacket(const CIp &Ip, const CBuffer &Buffe
return valid; return valid;
} }
bool CDmrplusProtocol::IsValidDvFramePacket(const CIp &Ip, const CBuffer &Buffer, CDvFramePacket **frames) bool CDmrplusProtocol::IsValidDvFramePacket(const CBuffer &Buffer, CDvFramePacket **frames)
{ {
bool valid = false; bool valid = false;
frames[0] = NULL; frames[0] = NULL;
@ -528,7 +529,7 @@ bool CDmrplusProtocol::IsValidDvFramePacket(const CIp &Ip, const CBuffer &Buffer
dmrsync[6] = dmrframe[19] & 0xF0; dmrsync[6] = dmrframe[19] & 0xF0;
// and create 3 dv frames // and create 3 dv frames
uint32 uiStreamId = IpToStreamId(Ip); uint32 uiStreamId = CreateStreamId();
// frame1 // frame1
memcpy(dmrambe, &dmr3ambe[0], 9); memcpy(dmrambe, &dmr3ambe[0], 9);
frames[0] = new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 1); frames[0] = new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 1);
@ -840,7 +841,7 @@ void CDmrplusProtocol::ReplaceEMBInBuffer(CBuffer *buffer, uint8 uiDmrPacketId)
// uiStreamId helpers // uiStreamId helpers
uint32 CDmrplusProtocol::IpToStreamId(const CIp &ip) const uint32 CDmrplusProtocol::CreateStreamId(void) const
{ {
return ip.GetAddr() ^ (uint32)(MAKEDWORD(ip.GetPort(), ip.GetPort())); return m_Random();
} }

@ -83,8 +83,8 @@ protected:
// packet decoding helpers // packet decoding helpers
bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, const CIp &); bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, const CIp &);
bool IsValidDisconnectPacket(const CBuffer &, CCallsign *, char *); bool IsValidDisconnectPacket(const CBuffer &, CCallsign *, char *);
bool IsValidDvHeaderPacket(const CIp &, const CBuffer &, CDvHeaderPacket **); bool IsValidDvHeaderPacket(const CBuffer &, CDvHeaderPacket **);
bool IsValidDvFramePacket(const CIp &, const CBuffer &, CDvFramePacket **); bool IsValidDvFramePacket(const CBuffer &, CDvFramePacket **);
// packet encoding helpers // packet encoding helpers
void EncodeConnectAckPacket(CBuffer *); void EncodeConnectAckPacket(CBuffer *);
@ -102,7 +102,7 @@ protected:
uint32 ModuleToDmrDestId(char) const; uint32 ModuleToDmrDestId(char) const;
// uiStreamId helpers // uiStreamId helpers
uint32 IpToStreamId(const CIp &) const; uint32 CreateStreamId(void) const;
// Buffer & LC helpers // Buffer & LC helpers
void AppendVoiceLCToBuffer(CBuffer *, uint32) const; void AppendVoiceLCToBuffer(CBuffer *, uint32) const;
@ -116,6 +116,9 @@ protected:
// for queue header caches // for queue header caches
std::array<CDmrplusStreamCacheItem, NB_OF_MODULES> m_StreamsCache; std::array<CDmrplusStreamCacheItem, NB_OF_MODULES> m_StreamsCache;
// random number generator
mutable std::mt19937 m_Random;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -33,6 +33,9 @@
#include <netinet/ip.h> #include <netinet/ip.h>
#include <netinet/ip_icmp.h> #include <netinet/ip_icmp.h>
#if !defined(ICMP_DEST_UNREACH) && defined(ICMP_UNREACH)
#define ICMP_DEST_UNREACH ICMP_UNREACH
#endif
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// operation // operation
@ -161,7 +164,9 @@ void CG3Protocol::PresenceTask(void)
{ {
CIp Ip(ReqIp); CIp Ip(ReqIp);
Ip.GetSockAddr()->sin_port = htons(G3_DV_PORT); socklen_t len;
struct sockaddr_in *sin = (struct sockaddr_in *)Ip.GetSockAddr(len);
sin->sin_port = htons(G3_DV_PORT);
if (Buffer.size() == 32) if (Buffer.size() == 32)
{ {

@ -33,44 +33,64 @@
CIp::CIp() CIp::CIp()
{ {
::memset(&m_Addr, 0, sizeof(m_Addr)); ::memset(&m_Addr, 0, m_AddrLen = sizeof(struct sockaddr_in));
m_Addr.sin_family = AF_INET; m_Addr.ss_family = AF_INET;
} }
CIp::CIp(const char *sz) CIp::CIp(const char *sz)
{ {
::memset(&m_Addr, 0, sizeof(m_Addr)); struct addrinfo hints, *res;
m_Addr.sin_family = AF_INET;
// try xxx.xxx.xxx.xxxx first ::memset(&m_Addr, 0, m_AddrLen = sizeof(struct sockaddr_in));
m_Addr.sin_addr.s_addr = inet_addr(sz); m_Addr.ss_family = AF_INET;
if ( m_Addr.sin_addr.s_addr == INADDR_NONE )
{ ::memset(&hints, 0, sizeof(hints));
// otherwise try to resolve via dns if ( getaddrinfo(sz, NULL, &hints, &res) == 0 )
hostent *record = gethostbyname(sz);
if( record != NULL )
{ {
m_Addr.sin_addr.s_addr = ((in_addr * )record->h_addr)->s_addr; ::memcpy(&m_Addr, res->ai_addr, m_AddrLen = res->ai_addrlen);
freeaddrinfo(res);
} }
} }
CIp::CIp(const struct sockaddr_storage *ss, socklen_t len)
{
len = ( len < sizeof(m_Addr) ) ? len : sizeof(m_Addr);
::memcpy(&m_Addr, ss, m_AddrLen = len);
} }
CIp::CIp(const struct sockaddr_in *sa) CIp::CIp(const CIp &ip)
{ {
::memcpy(&m_Addr, sa, sizeof(m_Addr)); ::memcpy(&m_Addr, &ip.m_Addr, m_AddrLen = ip.m_AddrLen);
} }
CIp::CIp(const CIp &ip, uint16 port)
{
::memcpy(&m_Addr, &ip.m_Addr, m_AddrLen = ip.m_AddrLen);
CIp::CIp(const CIp &ip) switch (m_Addr.ss_family)
{ {
::memcpy(&m_Addr, &ip.m_Addr, sizeof(m_Addr)); case AF_INET:
((struct sockaddr_in *)&m_Addr)->sin_port = htons(port);
break;
case AF_INET6:
((struct sockaddr_in6 *)&m_Addr)->sin6_port = htons(port);
break;
}
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// set // sockaddr
void CIp::SetSockAddr(struct sockaddr_in *sa) void CIp::SetSockAddr(struct sockaddr_storage *ss, socklen_t len)
{ {
::memcpy(&m_Addr, sa, sizeof(m_Addr)); len = ( len < sizeof(m_Addr) ) ? len : sizeof(m_Addr);
::memcpy(&m_Addr, ss, m_AddrLen = len);
}
struct sockaddr_storage *CIp::GetSockAddr(socklen_t &len)
{
len = m_AddrLen;
return &m_Addr;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -78,14 +98,45 @@ void CIp::SetSockAddr(struct sockaddr_in *sa)
bool CIp::operator ==(const CIp &ip) const bool CIp::operator ==(const CIp &ip) const
{ {
return ( (ip.m_Addr.sin_family == m_Addr.sin_family) && if ( ip.m_Addr.ss_family != m_Addr.ss_family )
(ip.m_Addr.sin_addr.s_addr == m_Addr.sin_addr.s_addr) && {
(ip.m_Addr.sin_port == m_Addr.sin_port)) ; return false;
}
switch (m_Addr.ss_family)
{
case AF_INET:
struct sockaddr_in *pi4, *pm4;
pi4 = (struct sockaddr_in *)&ip.m_Addr;
pm4 = (struct sockaddr_in *)&m_Addr;
return ( (pi4->sin_addr.s_addr == pm4->sin_addr.s_addr) &&
(pi4->sin_port == pm4->sin_port) );
case AF_INET6:
struct sockaddr_in6 *pi6, *pm6;
pi6 = (struct sockaddr_in6 *)&ip.m_Addr;
pm6 = (struct sockaddr_in6 *)&m_Addr;
return ( IN6_ARE_ADDR_EQUAL(&pi6->sin6_addr, &pm6->sin6_addr) &&
(pi6->sin6_port == pm6->sin6_port) );
default:
return false;
}
} }
CIp::operator const char *() const CIp::operator const char *() const
{ {
return ::inet_ntoa(m_Addr.sin_addr); switch (m_Addr.ss_family)
{
case AF_INET:
return ::inet_ntop(m_Addr.ss_family,
&((struct sockaddr_in *)&m_Addr)->sin_addr.s_addr,
m_AddrStr, sizeof(m_AddrStr));
case AF_INET6:
return ::inet_ntop(m_Addr.ss_family,
((struct sockaddr_in6 *)&m_Addr)->sin6_addr.s6_addr,
m_AddrStr, sizeof(m_AddrStr));
default:
return ::strncpy(m_AddrStr, "unknown", sizeof(m_AddrStr));
}
} }

@ -35,20 +35,20 @@ public:
// constructors // constructors
CIp(); CIp();
//CIp(uint8, uint8, uint8, uint8); //CIp(uint8, uint8, uint8, uint8);
CIp(const struct sockaddr_in *); CIp(const struct sockaddr_storage *, socklen_t);
CIp(const char *); CIp(const char *);
CIp(const CIp &); CIp(const CIp &);
CIp(const CIp &, uint16);
// destructor // destructor
virtual ~CIp() {}; virtual ~CIp() {};
// sockaddr // sockaddr
void SetSockAddr(struct sockaddr_in *); void SetSockAddr(struct sockaddr_storage *, socklen_t);
struct sockaddr_in *GetSockAddr(void) { return &m_Addr; } struct sockaddr_storage *GetSockAddr(socklen_t &);
// convertor // converter (IPv6 not supported)
uint32 GetAddr(void) const { return m_Addr.sin_addr.s_addr; } uint32 GetAddr(void) const { return ((struct sockaddr_in *)&m_Addr)->sin_addr.s_addr; }
uint16 GetPort(void) const { return m_Addr.sin_port; }
// operator // operator
bool operator ==(const CIp &) const; bool operator ==(const CIp &) const;
@ -56,7 +56,9 @@ public:
protected: protected:
// data // data
struct sockaddr_in m_Addr; struct sockaddr_storage m_Addr;
socklen_t m_AddrLen;
mutable char m_AddrStr[INET6_ADDRSTRLEN];
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -113,7 +113,7 @@ int CRawSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout)
Buffer->resize(iRecvLen); Buffer->resize(iRecvLen);
// get IP // get IP
Ip->SetSockAddr(&Sin); Ip->SetSockAddr((struct sockaddr_storage *)&Sin, sizeof(Sin));
} }
} }
@ -148,7 +148,7 @@ int CRawSocket::IcmpReceive(CBuffer *Buffer, CIp *Ip, int timeout)
Sin.sin_family = AF_INET; Sin.sin_family = AF_INET;
Sin.sin_addr.s_addr = remote_iph->ip_dst.s_addr; Sin.sin_addr.s_addr = remote_iph->ip_dst.s_addr;
Ip->SetSockAddr(&Sin); Ip->SetSockAddr((struct sockaddr_storage *)&Sin, sizeof(Sin));
} }
} }

@ -31,6 +31,7 @@
#include "cprotocols.h" #include "cprotocols.h"
#include "cpacketstream.h" #include "cpacketstream.h"
#include "cnotificationqueue.h" #include "cnotificationqueue.h"
#include "cudpsocket.h"
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -57,9 +58,10 @@ public:
// settings // settings
void SetCallsign(const CCallsign &callsign) { m_Callsign = callsign; } void SetCallsign(const CCallsign &callsign) { m_Callsign = callsign; }
const CCallsign &GetCallsign(void) const { return m_Callsign; } const CCallsign &GetCallsign(void) const { return m_Callsign; }
void SetListenIp(const CIp &ip) { m_Ip = ip; } void SetListenIp(int i, const CIp &ip) { if (i < UDP_SOCKET_MAX) m_Ip[i] = ip; }
void SetTranscoderIp(const CIp &ip) { m_AmbedIp = ip; } void SetTranscoderIp(const CIp &ip) { m_AmbedIp = ip; }
const CIp &GetListenIp(void) const { return m_Ip; } const CIp &GetListenIp(void) const { return m_Ip[0]; }
const CIp &GetListenIp(int i) const { return m_Ip[i]; }
const CIp &GetTranscoderIp(void) const { return m_AmbedIp; } const CIp &GetTranscoderIp(void) const { return m_AmbedIp; }
// operation // operation
@ -119,7 +121,7 @@ protected:
protected: protected:
// identity // identity
CCallsign m_Callsign; CCallsign m_Callsign;
CIp m_Ip; CIp m_Ip[UDP_SOCKET_MAX];
CIp m_AmbedIp; CIp m_AmbedIp;
// objects // objects

@ -26,17 +26,42 @@
#include <string.h> #include <string.h>
#include "cudpmsgsocket.h" #include "cudpmsgsocket.h"
// neither multiple socket nor IPv6 supported
#define MsgSocket m_Socket[0]
#define MsgIp m_Ip[0]
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// open // open
bool CUdpMsgSocket::Open(uint16 uiPort) bool CUdpMsgSocket::Open(uint16 uiPort)
{ {
bool ret; int on = 1, err = -1;
int on = 1; struct sockaddr_storage *ss;
socklen_t ss_len;
if ( !CUdpSocket::Open(uiPort) )
{
return false;
}
ret = CUdpSocket::Open(uiPort); ss = MsgIp.GetSockAddr(ss_len);
setsockopt(m_Socket, IPPROTO_IP, IP_PKTINFO, (char *)&on, sizeof(on)); if ( ss->ss_family == AF_INET )
{
#if defined(IP_PKTINFO)
err = setsockopt(MsgSocket, IPPROTO_IP, IP_PKTINFO, (char *)&on, sizeof(on));
#elif defined(IP_RECVDSTADDR)
err = setsockopt(MsgSocket, IPPROTO_IP, IP_RECVDSTADDR, (char *)&on, sizeof(on));
#endif
}
return ret; if ( err < 0 )
{
CUdpSocket::Close();
return false;
}
else
{
return true;
}
} }
@ -56,11 +81,15 @@ int CUdpMsgSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout)
union { union {
struct cmsghdr cm; struct cmsghdr cm;
#if defined(IP_PKTINFO)
unsigned char pktinfo_sizer[sizeof(struct cmsghdr) + sizeof(struct in_pktinfo)]; unsigned char pktinfo_sizer[sizeof(struct cmsghdr) + sizeof(struct in_pktinfo)];
#elif defined(IP_RECVDSTADDR)
unsigned char pktinfo_sizer[sizeof(struct cmsghdr) + sizeof(struct sockaddr_in)];
#endif
} Control; } Control;
// socket valid ? // socket valid ?
if ( m_Socket != -1 ) if ( MsgSocket != -1 )
{ {
// allocate buffer // allocate buffer
Buffer->resize(UDP_MSG_BUFFER_LENMAX); Buffer->resize(UDP_MSG_BUFFER_LENMAX);
@ -80,13 +109,13 @@ int CUdpMsgSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout)
// control socket // control socket
FD_ZERO(&FdSet); FD_ZERO(&FdSet);
FD_SET(m_Socket, &FdSet); FD_SET(MsgSocket, &FdSet);
tv.tv_sec = timeout / 1000; tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000; tv.tv_usec = (timeout % 1000) * 1000;
select(m_Socket + 1, &FdSet, 0, 0, &tv); select(MsgSocket + 1, &FdSet, 0, 0, &tv);
// read // read
iRecvLen = (int)recvmsg(m_Socket, &Msg, 0); iRecvLen = (int)recvmsg(MsgSocket, &Msg, 0);
// handle // handle
if ( iRecvLen != -1 ) if ( iRecvLen != -1 )
@ -95,17 +124,25 @@ int CUdpMsgSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout)
Buffer->resize(iRecvLen); Buffer->resize(iRecvLen);
// get IP // get IP
Ip->SetSockAddr(&Sin); Ip->SetSockAddr((struct sockaddr_storage *)&Sin, sizeof(Sin));
// get local IP // get local IP
struct cmsghdr *Cmsg; struct cmsghdr *Cmsg;
for (Cmsg = CMSG_FIRSTHDR(&Msg); Cmsg != NULL; Cmsg = CMSG_NXTHDR(&Msg, Cmsg)) for (Cmsg = CMSG_FIRSTHDR(&Msg); Cmsg != NULL; Cmsg = CMSG_NXTHDR(&Msg, Cmsg))
{ {
#if defined(IP_PKTINFO)
if (Cmsg->cmsg_level == IPPROTO_IP && Cmsg->cmsg_type == IP_PKTINFO) if (Cmsg->cmsg_level == IPPROTO_IP && Cmsg->cmsg_type == IP_PKTINFO)
{ {
struct in_pktinfo *PktInfo = (struct in_pktinfo *)CMSG_DATA(Cmsg); struct in_pktinfo *PktInfo = (struct in_pktinfo *)CMSG_DATA(Cmsg);
m_LocalAddr.s_addr = PktInfo->ipi_spec_dst.s_addr; m_LocalAddr.s_addr = PktInfo->ipi_spec_dst.s_addr;
} }
#elif defined(IP_RECVDSTADDR)
if (Cmsg->cmsg_level == IPPROTO_IP && Cmsg->cmsg_type == IP_RECVDSTADDR)
{
struct sockaddr_in *DestAddr = (struct sockaddr_in *)CMSG_DATA(Cmsg);
m_LocalAddr.s_addr = DestAddr->sin_addr.s_addr;
}
#endif
} }
} }
} }

@ -33,19 +33,19 @@
CUdpSocket::CUdpSocket() CUdpSocket::CUdpSocket()
{ {
m_Socket = -1; for ( int i = 0; i < UDP_SOCKET_MAX; i++ )
{
m_Socket[i] = -1;
}
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// destructor // destructor
CUdpSocket::~CUdpSocket() CUdpSocket::~CUdpSocket()
{
if ( m_Socket != -1 )
{ {
Close(); Close();
} }
}
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// open & close // open & close
@ -53,26 +53,30 @@ CUdpSocket::~CUdpSocket()
bool CUdpSocket::Open(uint16 uiPort) bool CUdpSocket::Open(uint16 uiPort)
{ {
bool open = false; bool open = false;
struct sockaddr_storage *ss;
socklen_t ss_len;
// create socket for ( int i = 0; i < UDP_SOCKET_MAX; i++ )
m_Socket = socket(PF_INET,SOCK_DGRAM,0);
if ( m_Socket != -1 )
{ {
// initialize sockaddr struct m_Ip[i] = CIp(g_Reflector.GetListenIp(i), uiPort);
::memset(&m_SocketAddr, 0, sizeof(struct sockaddr_in)); ss = m_Ip[i].GetSockAddr(ss_len);
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 ) // create socket
// (avoid INADDR_ANY on secondary and later IP address)
m_Socket[i] = ( i != 0 && m_Ip[i] == CIp() ) ?
-1 : socket(ss->ss_family, SOCK_DGRAM, 0);
if ( m_Socket[i] != -1 )
{
if ( bind(m_Socket[i], (struct sockaddr *)ss, ss_len) == 0 )
{ {
fcntl(m_Socket, F_SETFL, O_NONBLOCK); fcntl(m_Socket[i], F_SETFL, O_NONBLOCK);
open = true; open |= true;
} }
else else
{ {
close(m_Socket); close(m_Socket[i]);
m_Socket = -1; m_Socket[i] = -1;
}
} }
} }
@ -82,39 +86,73 @@ bool CUdpSocket::Open(uint16 uiPort)
void CUdpSocket::Close(void) void CUdpSocket::Close(void)
{ {
if ( m_Socket != -1 ) for ( int i = 0; i < UDP_SOCKET_MAX; i++ )
{
if ( m_Socket[i] != -1 )
{ {
close(m_Socket); close(m_Socket[i]);
m_Socket = -1; m_Socket[i] = -1;
} }
} }
}
int CUdpSocket::GetSocket(const CIp &Ip)
{
CIp temp(Ip);
socklen_t ss_len;
struct sockaddr_storage *ss = temp.GetSockAddr(ss_len);
sa_family_t ss_family = ss->ss_family;
for ( int i = 0; i < UDP_SOCKET_MAX; i++ )
{
ss = m_Ip[i].GetSockAddr(ss_len);
if ( ss_family == ss->ss_family )
{
return m_Socket[i];
}
}
return -1;
}
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// read // read
int CUdpSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout) int CUdpSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout)
{ {
struct sockaddr_in Sin; struct sockaddr_storage Sin;
fd_set FdSet; struct pollfd pfd[UDP_SOCKET_MAX];
unsigned int uiFromLen = sizeof(struct sockaddr_in); socklen_t uiFromLen = sizeof(Sin);
int iRecvLen = -1; int i, socks, index, iRecvLen = -1;
struct timeval tv;
// socket valid ? // socket valid ?
if ( m_Socket != -1 ) for ( i = socks = 0; i < UDP_SOCKET_MAX; i++ )
{
if ( m_Socket[i] != -1 )
{
pfd[socks].fd = m_Socket[i];
pfd[socks].events = POLLIN;
socks++;
}
}
if ( socks != 0 )
{ {
// control socket // control socket
FD_ZERO(&FdSet); poll(pfd, socks, timeout);
FD_SET(m_Socket, &FdSet);
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
select(m_Socket + 1, &FdSet, 0, 0, &tv);
for ( i = 0; i < socks; i++ )
{
// round robin
index = (i + m_Counter) % socks;
if ( pfd[index].revents & POLLIN )
{
// allocate buffer // allocate buffer
Buffer->resize(UDP_BUFFER_LENMAX); Buffer->resize(UDP_BUFFER_LENMAX);
// read // read
iRecvLen = (int)recvfrom(m_Socket, iRecvLen = (int)recvfrom(pfd[index].fd,
(void *)Buffer->data(), UDP_BUFFER_LENMAX, (void *)Buffer->data(), UDP_BUFFER_LENMAX,
0, (struct sockaddr *)&Sin, &uiFromLen); 0, (struct sockaddr *)&Sin, &uiFromLen);
@ -125,7 +163,12 @@ int CUdpSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout)
Buffer->resize(iRecvLen); Buffer->resize(iRecvLen);
// get IP // get IP
Ip->SetSockAddr(&Sin); Ip->SetSockAddr(&Sin, uiFromLen);
m_Counter++;
break;
}
}
} }
} }
@ -139,35 +182,41 @@ int CUdpSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout)
int CUdpSocket::Send(const CBuffer &Buffer, const CIp &Ip) int CUdpSocket::Send(const CBuffer &Buffer, const CIp &Ip)
{ {
CIp temp(Ip); CIp temp(Ip);
return (int)::sendto(m_Socket, socklen_t ss_len;
struct sockaddr_storage *ss = temp.GetSockAddr(ss_len);
return (int)::sendto(GetSocket(Ip),
(void *)Buffer.data(), Buffer.size(), (void *)Buffer.data(), Buffer.size(),
0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in)); 0, (struct sockaddr *)ss, ss_len);
} }
int CUdpSocket::Send(const char *Buffer, const CIp &Ip) int CUdpSocket::Send(const char *Buffer, const CIp &Ip)
{ {
CIp temp(Ip); CIp temp(Ip);
return (int)::sendto(m_Socket, socklen_t ss_len;
struct sockaddr_storage *ss = temp.GetSockAddr(ss_len);
return (int)::sendto(GetSocket(Ip),
(void *)Buffer, ::strlen(Buffer), (void *)Buffer, ::strlen(Buffer),
0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in)); 0, (struct sockaddr *)ss, ss_len);
} }
int CUdpSocket::Send(const CBuffer &Buffer, const CIp &Ip, uint16 destport) int CUdpSocket::Send(const CBuffer &Buffer, const CIp &Ip, uint16 destport)
{ {
CIp temp(Ip); CIp temp(Ip, destport);
temp.GetSockAddr()->sin_port = htons(destport); socklen_t ss_len;
return (int)::sendto(m_Socket, struct sockaddr_storage *ss = temp.GetSockAddr(ss_len);
return (int)::sendto(GetSocket(Ip),
(void *)Buffer.data(), Buffer.size(), (void *)Buffer.data(), Buffer.size(),
0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in)); 0, (struct sockaddr *)ss, ss_len);
} }
int CUdpSocket::Send(const char *Buffer, const CIp &Ip, uint16 destport) int CUdpSocket::Send(const char *Buffer, const CIp &Ip, uint16 destport)
{ {
CIp temp(Ip); CIp temp(Ip, destport);
temp.GetSockAddr()->sin_port = htons(destport); socklen_t ss_len;
return (int)::sendto(m_Socket, struct sockaddr_storage *ss = temp.GetSockAddr(ss_len);
return (int)::sendto(GetSocket(Ip),
(void *)Buffer, ::strlen(Buffer), (void *)Buffer, ::strlen(Buffer),
0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in)); 0, (struct sockaddr *)ss, ss_len);
} }

@ -29,6 +29,7 @@
//#include <sys/stat.h> //#include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <poll.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <arpa/inet.h> #include <arpa/inet.h>
@ -40,6 +41,7 @@
// define // define
#define UDP_BUFFER_LENMAX 1024 #define UDP_BUFFER_LENMAX 1024
#define UDP_SOCKET_MAX 2
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -57,7 +59,7 @@ public:
// open & close // open & close
bool Open(uint16); bool Open(uint16);
void Close(void); void Close(void);
int GetSocket(void) { return m_Socket; } int GetSocket(const CIp &);
// read // read
int Receive(CBuffer *, CIp *, int); int Receive(CBuffer *, CIp *, int);
@ -70,8 +72,9 @@ public:
protected: protected:
// data // data
int m_Socket; int m_Socket[UDP_SOCKET_MAX];
struct sockaddr_in m_SocketAddr; CIp m_Ip[UDP_SOCKET_MAX];
unsigned int m_Counter;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -67,6 +67,11 @@ bool CYsfProtocol::Init(void)
// update time // update time
m_LastKeepaliveTime.Now(); m_LastKeepaliveTime.Now();
// random number generator
std::random_device rd;
std::mt19937 mt(rd());
m_Random = mt;
// done // done
return ok; return ok;
} }
@ -450,7 +455,7 @@ bool CYsfProtocol::IsValidDvHeaderPacket(const CIp &Ip, const CYSFFICH &Fich, co
if ( Fich.getFI() == YSF_FI_HEADER ) if ( Fich.getFI() == YSF_FI_HEADER )
{ {
// get stream id // get stream id
uint32 uiStreamId = IpToStreamId(Ip); uint32 uiStreamId = CreateStreamId();
// get header data // get header data
CYSFPayload ysfPayload; CYSFPayload ysfPayload;
@ -519,7 +524,7 @@ bool CYsfProtocol::IsValidDvFramePacket(const CIp &Ip, const CYSFFICH &Fich, con
if ( Fich.getFI() == YSF_FI_COMMUNICATIONS ) if ( Fich.getFI() == YSF_FI_COMMUNICATIONS )
{ {
// get stream id // get stream id
uint32 uiStreamId = IpToStreamId(Ip); uint32 uiStreamId = CreateStreamId();
// get DV frames // get DV frames
uint8 ambe0[AMBEPLUS_SIZE]; uint8 ambe0[AMBEPLUS_SIZE];
@ -576,7 +581,7 @@ bool CYsfProtocol::IsValidDvLastFramePacket(const CIp &Ip, const CYSFFICH &Fich,
if ( Fich.getFI() == YSF_FI_TERMINATOR ) if ( Fich.getFI() == YSF_FI_TERMINATOR )
{ {
// get stream id // get stream id
uint32 uiStreamId = IpToStreamId(Ip); uint32 uiStreamId = CreateStreamId();
// get DV frames // get DV frames
{ {
@ -997,9 +1002,9 @@ uint32 CYsfProtocol::CalcHash(const uint8 *buffer, int len) const
// uiStreamId helpers // uiStreamId helpers
uint32 CYsfProtocol::IpToStreamId(const CIp &ip) const uint32 CYsfProtocol::CreateStreamId(void) const
{ {
return ip.GetAddr() ^ (uint32)(MAKEDWORD(ip.GetPort(), ip.GetPort())); return m_Random();
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -120,7 +120,7 @@ protected:
bool EncodeServerStatusPacket(CBuffer *) const; bool EncodeServerStatusPacket(CBuffer *) const;
// uiStreamId helpers // uiStreamId helpers
uint32 IpToStreamId(const CIp &) const; uint32 CreateStreamId(void) const;
// debug // debug
bool DebugTestDecodePacket(const CBuffer &); bool DebugTestDecodePacket(const CBuffer &);
@ -135,6 +135,9 @@ protected:
// for queue header caches // for queue header caches
std::array<CYsfStreamCacheItem, NB_OF_MODULES> m_StreamsCache; std::array<CYsfStreamCacheItem, NB_OF_MODULES> m_StreamsCache;
// random number generator
mutable std::mt19937 m_Random;
// for wires-x // for wires-x
CWiresxCmdHandler m_WiresxCmdHandler; CWiresxCmdHandler m_WiresxCmdHandler;
unsigned char m_seqNo; unsigned char m_seqNo;

@ -87,7 +87,7 @@ int main(int argc, const char * argv[])
#endif #endif
// check arguments // check arguments
if ( argc != 4 ) if ( argc < 4 )
{ {
std::cout << "Usage: xlxd callsign xlxdip ambedip" << std::endl; std::cout << "Usage: xlxd callsign xlxdip ambedip" << std::endl;
std::cout << "example: xlxd XLX999 192.168.178.212 127.0.0.1" << std::endl; std::cout << "example: xlxd XLX999 192.168.178.212 127.0.0.1" << std::endl;
@ -99,8 +99,9 @@ int main(int argc, const char * argv[])
// initialize reflector // initialize reflector
g_Reflector.SetCallsign(argv[1]); g_Reflector.SetCallsign(argv[1]);
g_Reflector.SetListenIp(CIp(argv[2])); g_Reflector.SetListenIp(0, CIp(argv[2]));
g_Reflector.SetTranscoderIp(CIp(CIp(argv[3]))); g_Reflector.SetTranscoderIp(CIp(CIp(argv[3])));
g_Reflector.SetListenIp(1, ( argc >= 5 ) ? CIp(argv[4]) : CIp());
// and let it run // and let it run
if ( !g_Reflector.Start() ) if ( !g_Reflector.Start() )

@ -39,8 +39,11 @@
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <fstream> #include <fstream>
#include <random>
#include <algorithm> #include <algorithm>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// defines // defines

@ -1,4 +1,4 @@
CC=g++ CC=c++
CFLAGS=-c -std=c++11 -pthread CFLAGS=-c -std=c++11 -pthread
LDFLAGS=-std=c++11 -pthread LDFLAGS=-std=c++11 -pthread
SOURCES=$(wildcard *.cpp) SOURCES=$(wildcard *.cpp)

Loading…
Cancel
Save

Powered by TurnKey Linux.