diff --git a/dashboard2/pgs/peers.php b/dashboard2/pgs/peers.php
index 1f45c136..efebafa9 100644
--- a/dashboard2/pgs/peers.php
+++ b/dashboard2/pgs/peers.php
@@ -64,13 +64,42 @@
'.$Reflector->Peers[$i]->GetLinkedModule().' | ';
if ($PageOptions['PeerPage']['IPModus'] != 'HideIP') {
echo '';
- $Bytes = explode(".", $Reflector->Peers[$i]->GetIP());
- if ($Bytes !== false && count($Bytes) == 4) {
- switch ($PageOptions['PeerPage']['IPModus']) {
- case 'ShowLast1ByteOfIP' : echo $PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$Bytes[3]; break;
- case 'ShowLast2ByteOfIP' : echo $PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$Bytes[2].'.'.$Bytes[3]; break;
- case 'ShowLast3ByteOfIP' : echo $PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$Bytes[1].'.'.$Bytes[2].'.'.$Bytes[3]; break;
- default : echo ''.$Reflector->Peers[$i]->GetIP().'';
+ $IPBinary = inet_pton($Reflector->Peers[$i]->GetIP());
+ $IPLength = strlen($IPBinary);
+ $Bytes = str_split($IPBinary, 1);
+ switch ($PageOptions['PeerPage']['IPModus']) {
+ case 'ShowLast1ByteOfIP' : $MasqByte = 3; break;
+ case 'ShowLast2ByteOfIP' : $MasqByte = 2; break;
+ case 'ShowLast3ByteOfIP' : $MasqByte = 1; break;
+ default : $MasqByte = 0; break;
+ }
+ if ($MasqByte == 0) {
+ switch ($IPLength) {
+ case 16: $IPAddrBracketL = '['; $IPAddrBracketR = ']'; break;
+ default: $IPAddrBracketL = ''; $IPAddrBracketR = ''; break;
+ }
+ echo ''.$Reflector->Peers[$i]->GetIP().'';
+ } else {
+ switch ($IPLength) {
+ case 4:
+ for ($pos = 0; $pos < $IPLength; $pos++) {
+ if ($pos) echo '.';
+ if ($pos < $MasqByte) echo $PageOptions['PeerPage']['MasqueradeCharacter'];
+ else echo ord($Bytes[$pos]);
+ }
+ break;
+ case 16:
+ for ($pos = 0; $pos < $IPLength; $pos += 2) {
+ if ($pos) echo ':';
+ if ($pos < ($MasqByte * 4)) echo $PageOptions['PeerPage']['MasqueradeCharacter'];
+ else {
+ echo bin2hex($Bytes[$pos]);
+ echo bin2hex($Bytes[$pos + 1]);
+ }
+ }
+ break;
+ default:
+ break;
}
}
echo ' | ';
diff --git a/dashboard2/pgs/repeaters.php b/dashboard2/pgs/repeaters.php
index a7562b90..ef0a31a8 100644
--- a/dashboard2/pgs/repeaters.php
+++ b/dashboard2/pgs/repeaters.php
@@ -60,14 +60,35 @@
if ($PageOptions['RepeatersPage']['IPModus'] != 'HideIP') {
echo '
';
- $Bytes = explode(".", $Reflector->Nodes[$i]->GetIP());
- if ($Bytes !== false && count($Bytes) == 4) {
- switch ($PageOptions['RepeatersPage']['IPModus']) {
- case 'ShowLast1ByteOfIP' : echo $PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$Bytes[3]; break;
- case 'ShowLast2ByteOfIP' : echo $PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$Bytes[2].'.'.$Bytes[3]; break;
- case 'ShowLast3ByteOfIP' : echo $PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$Bytes[1].'.'.$Bytes[2].'.'.$Bytes[3]; break;
- default : echo $Reflector->Nodes[$i]->GetIP();
- }
+ $IPBinary = inet_pton($Reflector->Nodes[$i]->GetIP());
+ $IPLength = strlen($IPBinary);
+ $Bytes = str_split($IPBinary, 1);
+ switch ($PageOptions['RepeatersPage']['IPModus']) {
+ case 'ShowLast1ByteOfIP' : $MasqByte = 3; break;
+ case 'ShowLast2ByteOfIP' : $MasqByte = 2; break;
+ case 'ShowLast3ByteOfIP' : $MasqByte = 1; break;
+ default : $MasqByte = 0; break;
+ }
+ switch ($IPLength) {
+ case 4:
+ for ($pos = 0; $pos < $IPLength; $pos++) {
+ if ($pos) echo '.';
+ if ($pos < $MasqByte) echo $PageOptions['RepeatersPage']['MasqueradeCharacter'];
+ else echo ord($Bytes[$pos]);
+ }
+ break;
+ case 16:
+ for ($pos = 0; $pos < $IPLength; $pos += 2) {
+ if ($pos) echo ':';
+ if ($pos < ($MasqByte * 4)) echo $PageOptions['RepeatersPage']['MasqueradeCharacter'];
+ else {
+ echo bin2hex($Bytes[$pos]);
+ echo bin2hex($Bytes[$pos + 1]);
+ }
+ }
+ break;
+ default:
+ break;
}
echo ' | ';
}
diff --git a/src/cdmriddir.cpp b/src/cdmriddir.cpp
index 5d62db3a..9887d2fc 100644
--- a/src/cdmriddir.cpp
+++ b/src/cdmriddir.cpp
@@ -152,7 +152,10 @@ bool CDmridDir::IsValidDmrid(const char *sz)
ok = true;
for ( size_t i = 0; (i < n) && ok; i++ )
{
- ok &= ::isdigit(sz[i]);
+ if ( !::isdigit(sz[i]) )
+ {
+ ok = false;
+ }
}
}
return ok;
diff --git a/src/cdmrmmdvmprotocol.cpp b/src/cdmrmmdvmprotocol.cpp
index 2398fd14..3357580f 100644
--- a/src/cdmrmmdvmprotocol.cpp
+++ b/src/cdmrmmdvmprotocol.cpp
@@ -70,9 +70,8 @@ bool CDmrmmdvmProtocol::Init(void)
m_LastKeepaliveTime.Now();
// random number generator
- time_t t;
- ::srand((unsigned) time(&t));
- m_uiAuthSeed = (uint32)rand();
+ std::random_device rd;
+ m_uiAuthSeed = rd();
// done
return ok;
diff --git a/src/cdmrplusprotocol.cpp b/src/cdmrplusprotocol.cpp
index 1d1180f1..273e8c00 100644
--- a/src/cdmrplusprotocol.cpp
+++ b/src/cdmrplusprotocol.cpp
@@ -63,8 +63,9 @@ bool CDmrplusProtocol::Init(void)
m_LastKeepaliveTime.Now();
// random number generator
- time_t t;
- ::srand((unsigned) time(&t));
+ std::random_device rd;
+ std::mt19937 mt(rd());
+ m_Random = mt;
// done
return ok;
@@ -88,7 +89,7 @@ void CDmrplusProtocol::Task(void)
if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 )
{
// crack the packet
- if ( IsValidDvFramePacket(Ip, Buffer, Frames) )
+ if ( IsValidDvFramePacket(Buffer, Frames) )
{
//std::cout << "DMRplus DV frame" << std::endl;
//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 << *Header << std::endl;
@@ -444,7 +445,7 @@ bool CDmrplusProtocol::IsValidDisconnectPacket(const CBuffer &Buffer, CCallsign
return valid;
}
-bool CDmrplusProtocol::IsValidDvHeaderPacket(const CIp &Ip, const CBuffer &Buffer, CDvHeaderPacket **Header)
+bool CDmrplusProtocol::IsValidDvHeaderPacket(const CBuffer &Buffer, CDvHeaderPacket **Header)
{
bool valid = false;
*Header = NULL;
@@ -470,7 +471,7 @@ bool CDmrplusProtocol::IsValidDvHeaderPacket(const CIp &Ip, const CBuffer &Buffe
rpt1.SetModule(DMRPLUS_MODULE_ID);
CCallsign rpt2 = m_ReflectorCallsign;
rpt2.SetModule(DmrDstIdToModule(uiDstId));
- uint32 uiStreamId = IpToStreamId(Ip);
+ uint32 uiStreamId = CreateStreamId();
// and packet
*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;
}
-bool CDmrplusProtocol::IsValidDvFramePacket(const CIp &Ip, const CBuffer &Buffer, CDvFramePacket **frames)
+bool CDmrplusProtocol::IsValidDvFramePacket(const CBuffer &Buffer, CDvFramePacket **frames)
{
bool valid = false;
frames[0] = NULL;
@@ -528,7 +529,7 @@ bool CDmrplusProtocol::IsValidDvFramePacket(const CIp &Ip, const CBuffer &Buffer
dmrsync[6] = dmrframe[19] & 0xF0;
// and create 3 dv frames
- uint32 uiStreamId = IpToStreamId(Ip);
+ uint32 uiStreamId = CreateStreamId();
// frame1
memcpy(dmrambe, &dmr3ambe[0], 9);
frames[0] = new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 1);
@@ -840,7 +841,7 @@ void CDmrplusProtocol::ReplaceEMBInBuffer(CBuffer *buffer, uint8 uiDmrPacketId)
// 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();
}
diff --git a/src/cdmrplusprotocol.h b/src/cdmrplusprotocol.h
index e9d4c1e6..73ea7a42 100644
--- a/src/cdmrplusprotocol.h
+++ b/src/cdmrplusprotocol.h
@@ -83,8 +83,8 @@ class CDmrplusProtocol : public CProtocol
// packet decoding helpers
bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, const CIp &);
bool IsValidDisconnectPacket(const CBuffer &, CCallsign *, char *);
- bool IsValidDvHeaderPacket(const CIp &, const CBuffer &, CDvHeaderPacket **);
- bool IsValidDvFramePacket(const CIp &, const CBuffer &, CDvFramePacket **);
+ bool IsValidDvHeaderPacket(const CBuffer &, CDvHeaderPacket **);
+ bool IsValidDvFramePacket(const CBuffer &, CDvFramePacket **);
// packet encoding helpers
void EncodeConnectAckPacket(CBuffer *);
@@ -102,7 +102,7 @@ class CDmrplusProtocol : public CProtocol
uint32 ModuleToDmrDestId(char) const;
// uiStreamId helpers
- uint32 IpToStreamId(const CIp &) const;
+ uint32 CreateStreamId(void) const;
// Buffer & LC helpers
void AppendVoiceLCToBuffer(CBuffer *, uint32) const;
@@ -116,6 +116,9 @@ class CDmrplusProtocol : public CProtocol
// for queue header caches
std::array m_StreamsCache;
+
+ // random number generator
+ mutable std::mt19937 m_Random;
};
////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/cg3protocol.cpp b/src/cg3protocol.cpp
index 9f854204..f08b57cc 100755
--- a/src/cg3protocol.cpp
+++ b/src/cg3protocol.cpp
@@ -33,6 +33,9 @@
#include
#include
+#if !defined(ICMP_DEST_UNREACH) && defined(ICMP_UNREACH)
+#define ICMP_DEST_UNREACH ICMP_UNREACH
+#endif
////////////////////////////////////////////////////////////////////////////////////////
// operation
@@ -46,18 +49,34 @@ bool CG3Protocol::Init(void)
// base class
ok = CProtocol::Init();
+ // G3 needs IPv4 address
+ bool ipv4 = false;
+#if !defined(DEBUG_NO_G3_SUPPORT)
+ for ( int i = 0; i < UDP_SOCKET_MAX; i++ )
+ {
+ CIp ip = g_Reflector.GetListenIp(i);
+ socklen_t ss_len;
+ ipv4 |= ( ip.GetSockAddr(ss_len)->ss_family == AF_INET );
+ }
+#endif
+ if ( !ipv4 ) {
+ std::cout << "No IPv4 address, G3 support is disabled" << std::endl;
+ m_bStopThread = true;
+ return true;
+ }
+
// update reflector callsign
m_ReflectorCallsign.PatchCallsign(0, (const uint8 *)"XLX", 3);
// create our DV socket
- ok &= m_Socket.Open(G3_DV_PORT);
+ ok &= m_Socket.Open(G3_DV_PORT, AF_INET);
if ( !ok )
{
std::cout << "Error opening socket on port UDP" << G3_DV_PORT << " on ip " << g_Reflector.GetListenIp() << std::endl;
}
//create helper sockets
- ok &= m_PresenceSocket.Open(G3_PRESENCE_PORT);
+ ok &= m_PresenceSocket.Open(G3_PRESENCE_PORT, AF_INET);
if ( !ok )
{
std::cout << "Error opening socket on port UDP" << G3_PRESENCE_PORT << " on ip " << g_Reflector.GetListenIp() << std::endl;
@@ -161,7 +180,9 @@ void CG3Protocol::PresenceTask(void)
{
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)
{
diff --git a/src/cip.cpp b/src/cip.cpp
index 5cec9b53..dfd5ec1f 100644
--- a/src/cip.cpp
+++ b/src/cip.cpp
@@ -31,46 +31,66 @@
////////////////////////////////////////////////////////////////////////////////////////
// constructors
-CIp::CIp()
+CIp::CIp(const int af)
{
- ::memset(&m_Addr, 0, sizeof(m_Addr));
- m_Addr.sin_family = AF_INET;
+ ::memset(&m_Addr, 0, m_AddrLen = sizeof(struct sockaddr_in));
+ m_Addr.ss_family = af;
}
CIp::CIp(const char *sz)
{
- ::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 )
+ struct addrinfo hints, *res;
+
+ ::memset(&m_Addr, 0, m_AddrLen = sizeof(struct sockaddr_in));
+ m_Addr.ss_family = AF_INET;
+
+ ::memset(&hints, 0, sizeof(hints));
+ if ( getaddrinfo(sz, NULL, &hints, &res) == 0 )
{
- // 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;
- }
+ ::memcpy(&m_Addr, res->ai_addr, m_AddrLen = res->ai_addrlen);
+ freeaddrinfo(res);
}
}
-CIp::CIp(const struct sockaddr_in *sa)
+CIp::CIp(const 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);
}
-
CIp::CIp(const CIp &ip)
{
- ::memcpy(&m_Addr, &ip.m_Addr, 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);
+
+ switch (m_Addr.ss_family)
+ {
+ 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
{
- 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)) ;
+ if ( ip.m_Addr.ss_family != m_Addr.ss_family )
+ {
+ 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
{
- 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));
+ }
}
diff --git a/src/cip.h b/src/cip.h
index 6c432886..83563785 100644
--- a/src/cip.h
+++ b/src/cip.h
@@ -33,22 +33,22 @@ class CIp
{
public:
// constructors
- CIp();
+ CIp(const int af = AF_INET);
//CIp(uint8, uint8, uint8, uint8);
- CIp(const struct sockaddr_in *);
+ CIp(const struct sockaddr_storage *, socklen_t);
CIp(const char *);
CIp(const CIp &);
+ CIp(const CIp &, uint16);
// destructor
virtual ~CIp() {};
// sockaddr
- void SetSockAddr(struct sockaddr_in *);
- struct sockaddr_in *GetSockAddr(void) { return &m_Addr; }
+ void SetSockAddr(struct sockaddr_storage *, socklen_t);
+ struct sockaddr_storage *GetSockAddr(socklen_t &);
- // convertor
- uint32 GetAddr(void) const { return m_Addr.sin_addr.s_addr; }
- uint16 GetPort(void) const { return m_Addr.sin_port; }
+ // converter (IPv6 not supported)
+ uint32 GetAddr(void) const { return ((struct sockaddr_in *)&m_Addr)->sin_addr.s_addr; }
// operator
bool operator ==(const CIp &) const;
@@ -56,7 +56,9 @@ class CIp
protected:
// data
- struct sockaddr_in m_Addr;
+ struct sockaddr_storage m_Addr;
+ socklen_t m_AddrLen;
+ mutable char m_AddrStr[INET6_ADDRSTRLEN];
};
////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/crawsocket.cpp b/src/crawsocket.cpp
index 119dbb10..b81e006a 100644
--- a/src/crawsocket.cpp
+++ b/src/crawsocket.cpp
@@ -113,7 +113,7 @@ int CRawSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout)
Buffer->resize(iRecvLen);
// 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_addr.s_addr = remote_iph->ip_dst.s_addr;
- Ip->SetSockAddr(&Sin);
+ Ip->SetSockAddr((struct sockaddr_storage *)&Sin, sizeof(Sin));
}
}
diff --git a/src/creflector.h b/src/creflector.h
index 14244539..8f36acb5 100644
--- a/src/creflector.h
+++ b/src/creflector.h
@@ -31,6 +31,7 @@
#include "cprotocols.h"
#include "cpacketstream.h"
#include "cnotificationqueue.h"
+#include "cudpsocket.h"
////////////////////////////////////////////////////////////////////////////////////////
@@ -57,9 +58,10 @@ class CReflector
// settings
void SetCallsign(const CCallsign &callsign) { m_Callsign = callsign; }
const CCallsign &GetCallsign(void) const { return m_Callsign; }
- void SetListenIp(const CIp &ip) { m_Ip = ip; }
+ void SetListenIp(int i, const CIp &ip) { m_Ip[i] = 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; }
// operation
@@ -119,7 +121,7 @@ class CReflector
protected:
// identity
CCallsign m_Callsign;
- CIp m_Ip;
+ CIp m_Ip[UDP_SOCKET_MAX];
CIp m_AmbedIp;
// objects
diff --git a/src/cudpmsgsocket.cpp b/src/cudpmsgsocket.cpp
index 45d438dd..374a6635 100644
--- a/src/cudpmsgsocket.cpp
+++ b/src/cudpmsgsocket.cpp
@@ -26,17 +26,42 @@
#include
#include "cudpmsgsocket.h"
+// neither multiple socket nor IPv6 supported
+#define MsgSocket m_Socket[0]
+#define MsgIp m_Ip[0]
+
////////////////////////////////////////////////////////////////////////////////////////
// open
bool CUdpMsgSocket::Open(uint16 uiPort)
{
- bool ret;
- int on = 1;
-
- ret = CUdpSocket::Open(uiPort);
- setsockopt(m_Socket, IPPROTO_IP, IP_PKTINFO, (char *)&on, sizeof(on));
-
- return ret;
+ int on = 1, err = -1;
+ struct sockaddr_storage *ss;
+ socklen_t ss_len;
+
+ if ( !CUdpSocket::Open(uiPort, AF_INET) )
+ {
+ return false;
+ }
+
+ ss = MsgIp.GetSockAddr(ss_len);
+ 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
+ }
+
+ if ( err < 0 )
+ {
+ CUdpSocket::Close();
+ return false;
+ }
+ else
+ {
+ return true;
+ }
}
@@ -56,11 +81,15 @@ int CUdpMsgSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout)
union {
struct cmsghdr cm;
+#if defined(IP_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;
// socket valid ?
- if ( m_Socket != -1 )
+ if ( MsgSocket != -1 )
{
// allocate buffer
Buffer->resize(UDP_MSG_BUFFER_LENMAX);
@@ -80,13 +109,13 @@ int CUdpMsgSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout)
// control socket
FD_ZERO(&FdSet);
- FD_SET(m_Socket, &FdSet);
+ FD_SET(MsgSocket, &FdSet);
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
- select(m_Socket + 1, &FdSet, 0, 0, &tv);
+ select(MsgSocket + 1, &FdSet, 0, 0, &tv);
// read
- iRecvLen = (int)recvmsg(m_Socket, &Msg, 0);
+ iRecvLen = (int)recvmsg(MsgSocket, &Msg, 0);
// handle
if ( iRecvLen != -1 )
@@ -95,17 +124,25 @@ int CUdpMsgSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout)
Buffer->resize(iRecvLen);
// get IP
- Ip->SetSockAddr(&Sin);
+ Ip->SetSockAddr((struct sockaddr_storage *)&Sin, sizeof(Sin));
// get local IP
struct cmsghdr *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)
{
struct in_pktinfo *PktInfo = (struct in_pktinfo *)CMSG_DATA(Cmsg);
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
}
}
}
diff --git a/src/cudpsocket.cpp b/src/cudpsocket.cpp
index 5caa0741..4499c861 100755
--- a/src/cudpsocket.cpp
+++ b/src/cudpsocket.cpp
@@ -33,7 +33,10 @@
CUdpSocket::CUdpSocket()
{
- m_Socket = -1;
+ for ( int i = 0; i < UDP_SOCKET_MAX; i++ )
+ {
+ m_Socket[i] = -1;
+ }
}
////////////////////////////////////////////////////////////////////////////////////////
@@ -41,38 +44,43 @@ CUdpSocket::CUdpSocket()
CUdpSocket::~CUdpSocket()
{
- if ( m_Socket != -1 )
- {
- Close();
- }
+ Close();
}
////////////////////////////////////////////////////////////////////////////////////////
// open & close
-bool CUdpSocket::Open(uint16 uiPort)
+bool CUdpSocket::Open(uint16 uiPort, int af)
{
bool open = false;
+ struct sockaddr_storage *ss;
+ socklen_t ss_len;
- // create socket
- m_Socket = socket(PF_INET,SOCK_DGRAM,0);
- if ( m_Socket != -1 )
+ for ( int i = 0; i < UDP_SOCKET_MAX; i++ )
{
- // 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());
+ m_Ip[i] = CIp(AF_UNSPEC);
+ m_Socket[i] = -1;
- if ( bind(m_Socket, (struct sockaddr *)&m_SocketAddr, sizeof(struct sockaddr_in)) == 0 )
+ if ( g_Reflector.GetListenIp(i) != CIp(AF_UNSPEC) )
{
- fcntl(m_Socket, F_SETFL, O_NONBLOCK);
- open = true;
+ m_Ip[i] = CIp(g_Reflector.GetListenIp(i), uiPort);
+ ss = m_Ip[i].GetSockAddr(ss_len);
+ m_Socket[i] = ( af != AF_UNSPEC && af != ss->ss_family ) ?
+ -1 : socket(ss->ss_family, SOCK_DGRAM, 0);
}
- else
+
+ if ( m_Socket[i] != -1 )
{
- close(m_Socket);
- m_Socket = -1;
+ if ( bind(m_Socket[i], (struct sockaddr *)ss, ss_len) == 0 )
+ {
+ fcntl(m_Socket[i], F_SETFL, O_NONBLOCK);
+ open |= true;
+ }
+ else
+ {
+ close(m_Socket[i]);
+ m_Socket[i] = -1;
+ }
}
}
@@ -82,11 +90,34 @@ bool CUdpSocket::Open(uint16 uiPort)
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[i]);
+ 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++ )
{
- close(m_Socket);
- m_Socket = -1;
+ ss = m_Ip[i].GetSockAddr(ss_len);
+ if ( ss_family == ss->ss_family )
+ {
+ // if ss->ss_family == AF_UNSPEC, m_Socket[i] = -1
+ return m_Socket[i];
+ }
}
+
+ return -1;
}
////////////////////////////////////////////////////////////////////////////////////////
@@ -94,38 +125,55 @@ void CUdpSocket::Close(void)
int 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;
+ struct sockaddr_storage Sin;
+ struct pollfd pfd[UDP_SOCKET_MAX];
+ socklen_t uiFromLen = sizeof(Sin);
+ int i, socks, index, iRecvLen = -1;
// 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
- 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);
+ poll(pfd, socks, timeout);
- // read
- iRecvLen = (int)recvfrom(m_Socket,
- (void *)Buffer->data(), UDP_BUFFER_LENMAX,
- 0, (struct sockaddr *)&Sin, &uiFromLen);
-
- // handle
- if ( iRecvLen != -1 )
+ for ( i = 0; i < socks; i++ )
{
- // adjust buffer size
- Buffer->resize(iRecvLen);
+ // round robin
+ index = (i + m_Counter) % socks;
- // get IP
- Ip->SetSockAddr(&Sin);
+ if ( pfd[index].revents & POLLIN )
+ {
+ // allocate buffer
+ Buffer->resize(UDP_BUFFER_LENMAX);
+
+ // read
+ iRecvLen = (int)recvfrom(pfd[index].fd,
+ (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, uiFromLen);
+
+ m_Counter++;
+ break;
+ }
+ }
}
}
@@ -139,35 +187,41 @@ int CUdpSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout)
int CUdpSocket::Send(const CBuffer &Buffer, const CIp &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(),
- 0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in));
+ 0, (struct sockaddr *)ss, ss_len);
}
int CUdpSocket::Send(const char *Buffer, const CIp &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),
- 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)
{
- CIp temp(Ip);
- temp.GetSockAddr()->sin_port = htons(destport);
- return (int)::sendto(m_Socket,
+ CIp temp(Ip, destport);
+ socklen_t ss_len;
+ struct sockaddr_storage *ss = temp.GetSockAddr(ss_len);
+ return (int)::sendto(GetSocket(Ip),
(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)
{
- CIp temp(Ip);
- temp.GetSockAddr()->sin_port = htons(destport);
- return (int)::sendto(m_Socket,
+ CIp temp(Ip, destport);
+ socklen_t ss_len;
+ struct sockaddr_storage *ss = temp.GetSockAddr(ss_len);
+ return (int)::sendto(GetSocket(Ip),
(void *)Buffer, ::strlen(Buffer),
- 0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in));
+ 0, (struct sockaddr *)ss, ss_len);
}
diff --git a/src/cudpsocket.h b/src/cudpsocket.h
index e91ed80f..ae8418cc 100755
--- a/src/cudpsocket.h
+++ b/src/cudpsocket.h
@@ -29,6 +29,7 @@
//#include
#include
#include
+#include
#include
#include
#include
@@ -40,6 +41,7 @@
// define
#define UDP_BUFFER_LENMAX 1024
+#define UDP_SOCKET_MAX 2
////////////////////////////////////////////////////////////////////////////////////////
@@ -55,9 +57,9 @@ class CUdpSocket
~CUdpSocket();
// open & close
- bool Open(uint16);
+ bool Open(uint16, int = AF_UNSPEC);
void Close(void);
- int GetSocket(void) { return m_Socket; }
+ int GetSocket(const CIp &);
// read
int Receive(CBuffer *, CIp *, int);
@@ -70,8 +72,9 @@ class CUdpSocket
protected:
// data
- int m_Socket;
- struct sockaddr_in m_SocketAddr;
+ int m_Socket[UDP_SOCKET_MAX];
+ CIp m_Ip[UDP_SOCKET_MAX];
+ unsigned int m_Counter;
};
////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/cysfprotocol.cpp b/src/cysfprotocol.cpp
index f0573a38..8df84ca6 100644
--- a/src/cysfprotocol.cpp
+++ b/src/cysfprotocol.cpp
@@ -67,6 +67,11 @@ bool CYsfProtocol::Init(void)
// update time
m_LastKeepaliveTime.Now();
+ // random number generator
+ std::random_device rd;
+ std::mt19937 mt(rd());
+ m_Random = mt;
+
// done
return ok;
}
@@ -450,7 +455,7 @@ bool CYsfProtocol::IsValidDvHeaderPacket(const CIp &Ip, const CYSFFICH &Fich, co
if ( Fich.getFI() == YSF_FI_HEADER )
{
// get stream id
- uint32 uiStreamId = IpToStreamId(Ip);
+ uint32 uiStreamId = CreateStreamId();
// get header data
CYSFPayload ysfPayload;
@@ -519,7 +524,7 @@ bool CYsfProtocol::IsValidDvFramePacket(const CIp &Ip, const CYSFFICH &Fich, con
if ( Fich.getFI() == YSF_FI_COMMUNICATIONS )
{
// get stream id
- uint32 uiStreamId = IpToStreamId(Ip);
+ uint32 uiStreamId = CreateStreamId();
// get DV frames
uint8 ambe0[AMBEPLUS_SIZE];
@@ -576,7 +581,7 @@ bool CYsfProtocol::IsValidDvLastFramePacket(const CIp &Ip, const CYSFFICH &Fich,
if ( Fich.getFI() == YSF_FI_TERMINATOR )
{
// get stream id
- uint32 uiStreamId = IpToStreamId(Ip);
+ uint32 uiStreamId = CreateStreamId();
// get DV frames
{
@@ -997,9 +1002,9 @@ uint32 CYsfProtocol::CalcHash(const uint8 *buffer, int len) const
// 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();
}
////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/cysfprotocol.h b/src/cysfprotocol.h
index 77725e9a..6dab89be 100644
--- a/src/cysfprotocol.h
+++ b/src/cysfprotocol.h
@@ -120,7 +120,7 @@ class CYsfProtocol : public CProtocol
bool EncodeServerStatusPacket(CBuffer *) const;
// uiStreamId helpers
- uint32 IpToStreamId(const CIp &) const;
+ uint32 CreateStreamId(void) const;
// debug
bool DebugTestDecodePacket(const CBuffer &);
@@ -135,6 +135,9 @@ class CYsfProtocol : public CProtocol
// for queue header caches
std::array m_StreamsCache;
+ // random number generator
+ mutable std::mt19937 m_Random;
+
// for wires-x
CWiresxCmdHandler m_WiresxCmdHandler;
unsigned char m_seqNo;
diff --git a/src/main.cpp b/src/main.cpp
index 723ab5be..5b751880 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -27,6 +27,7 @@
#include "syslog.h"
#include
+#include
////////////////////////////////////////////////////////////////////////////////////////
@@ -39,7 +40,7 @@ CReflector g_Reflector;
#include "cusers.h"
-int main(int argc, const char * argv[])
+int main(int argc, char * argv[])
{
#ifdef RUN_AS_DAEMON
@@ -87,7 +88,7 @@ int main(int argc, const char * argv[])
#endif
// check arguments
- if ( argc != 4 )
+ if ( argc < 4 )
{
std::cout << "Usage: xlxd callsign xlxdip ambedip" << std::endl;
std::cout << "example: xlxd XLX999 192.168.178.212 127.0.0.1" << std::endl;
@@ -99,9 +100,21 @@ int main(int argc, const char * argv[])
// initialize reflector
g_Reflector.SetCallsign(argv[1]);
- g_Reflector.SetListenIp(CIp(argv[2]));
g_Reflector.SetTranscoderIp(CIp(CIp(argv[3])));
-
+
+ int ip;
+ char *p, *last;
+ for ( ip = 0, (p = strtok_r(argv[2], ",", &last));
+ ip < UDP_SOCKET_MAX && p != NULL;
+ ip++, (p = strtok_r(NULL, ",", &last)) )
+ {
+ g_Reflector.SetListenIp(ip, CIp(p));
+ }
+ for ( ; ip < UDP_SOCKET_MAX; ip++ )
+ {
+ g_Reflector.SetListenIp(ip, CIp(AF_UNSPEC));
+ }
+
// and let it run
if ( !g_Reflector.Start() )
{
diff --git a/src/main.h b/src/main.h
index 7127e39b..abf7b6d6 100755
--- a/src/main.h
+++ b/src/main.h
@@ -39,8 +39,11 @@
#include
#include
#include
+#include
#include
#include
+#include
+#include
////////////////////////////////////////////////////////////////////////////////////////
// defines
@@ -61,6 +64,7 @@
//#define DEBUG_NO_ERROR_ON_XML_OPEN_FAIL
//#define DEBUG_DUMPFILE
//#define DEBUG_NO_G3_ICMP_SOCKET
+//#define DEBUG_NO_G3_SUPPORT
// reflector ---------------------------------------------------
diff --git a/src/makefile b/src/makefile
index 2d7b5875..bbf7a7ce 100644
--- a/src/makefile
+++ b/src/makefile
@@ -1,4 +1,4 @@
-CC=g++
+CC=c++
CFLAGS=-c -std=c++11 -pthread
LDFLAGS=-std=c++11 -pthread
SOURCES=$(wildcard *.cpp)