diff --git a/dashboard2/pgs/peers.php b/dashboard2/pgs/peers.php index 1f45c13..efebafa 100644 --- a/dashboard2/pgs/peers.php +++ b/dashboard2/pgs/peers.php @@ -64,13 +64,42 @@ for ($i=0;$i<$Reflector->PeerCount();$i++) { '.$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 a7562b9..ef0a31a 100644 --- a/dashboard2/pgs/repeaters.php +++ b/dashboard2/pgs/repeaters.php @@ -60,14 +60,35 @@ for ($i=0;$i<$Reflector->NodeCount();$i++) { 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/ccallsign.cpp b/src/ccallsign.cpp index 930ad58..6206f65 100644 --- a/src/ccallsign.cpp +++ b/src/ccallsign.cpp @@ -207,7 +207,7 @@ void CCallsign::SetYsfCallsign(const char *sz) m_uiDmrid = 0; // set callsign - for ( i = 0; (i < sizeof(m_Callsign)) && (sz[i] != '/') && (sz[i] != '-') && (sz[i] != 0x00); i++ ) + for ( i = 0; (i < sizeof(m_Callsign)) && (sz[i] != '/') && (sz[i] != '-'); i++ ) { m_Callsign[i] = sz[i]; } diff --git a/src/cdmrmmdvmprotocol.cpp b/src/cdmrmmdvmprotocol.cpp index c8a0fad..e6972f9 100644 --- a/src/cdmrmmdvmprotocol.cpp +++ b/src/cdmrmmdvmprotocol.cpp @@ -73,9 +73,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 4f755dc..514f550 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 e9d4c1e..73ea7a4 100644 --- a/src/cdmrplusprotocol.h +++ b/src/cdmrplusprotocol.h @@ -83,8 +83,8 @@ protected: // 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 @@ protected: 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 @@ protected: // 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 770259f..6f499df 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; @@ -169,7 +188,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/cimrsprotocol.cpp b/src/cimrsprotocol.cpp index e82c852..f11508b 100644 --- a/src/cimrsprotocol.cpp +++ b/src/cimrsprotocol.cpp @@ -55,6 +55,11 @@ bool CImrsProtocol::Init(void) // update time m_LastKeepaliveTime.Now(); + // random number generator + std::random_device rd; + std::mt19937 mt(rd()); + m_Random = mt; + // done return ok; } @@ -76,10 +81,11 @@ void CImrsProtocol::Task(void) //CYSFFICH Fich; CDvHeaderPacket *Header; CDvFramePacket *Frames[5]; + int sno; uint32 Version; // handle incoming packets - if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 ) + if ( m_Socket.Receive(&Buffer, &Ip, 20, &sno) != -1 ) { // force port Ip.SetPort(IMRS_PORT); @@ -124,7 +130,7 @@ void CImrsProtocol::Task(void) //std::cout << "IMRS ping packet from " << Ip << std::endl; // acknowledge request - EncodePongPacket(&Buffer); + EncodePongPacket(&Buffer, sno); m_Socket.Send(Buffer, Ip, IMRS_PORT); // our turn @@ -412,7 +418,7 @@ bool CImrsProtocol::IsValidDvHeaderPacket(const CIp &Ip, const CBuffer &Buffer, if ( (Buffer.size() == 91) && (Buffer.at(1) == 0x4B) ) { // get stream id - uint32 uiStreamId = IpToStreamId(Ip); + uint32 uiStreamId = CreateStreamId(); // and payload CBuffer payload; @@ -491,7 +497,7 @@ bool CImrsProtocol::IsValidDvFramePacket(const CIp &Ip, const CBuffer &Buffer, C if ( (Buffer.size() == 181) && (Buffer.at(1) == 0xA5) ) { // get stream id - uint32 uiStreamId = IpToStreamId(Ip); + uint32 uiStreamId = CreateStreamId(); // and payload CBuffer payload; @@ -584,7 +590,7 @@ bool CImrsProtocol::IsValidDvLastFramePacket(const CIp &Ip, const CBuffer &Buffe if ( (Buffer.size() == 31) && (Buffer.at(1) == 0x0F) ) { // get stream id - uint32 uiStreamId = IpToStreamId(Ip); + uint32 uiStreamId = CreateStreamId(); // and payload CBuffer payload; @@ -647,7 +653,7 @@ void CImrsProtocol::EncodePingPacket(CBuffer *Buffer) const Buffer->Set(tag, sizeof(tag)); } -void CImrsProtocol::EncodePongPacket(CBuffer *Buffer) const +void CImrsProtocol::EncodePongPacket(CBuffer *Buffer, int sno) const { uint8 tag1[] = { 0x00,0x2C,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x04,0x00,0x00 }; uint8 radioid[] = { 'G','0','g','B','J' }; @@ -656,7 +662,7 @@ void CImrsProtocol::EncodePongPacket(CBuffer *Buffer) const // tag Buffer->Set(tag1, sizeof(tag1)); // mac address - Buffer->Append(g_Reflector.GetListenMac(), 6); + Buffer->Append(g_Reflector.GetListenMac(sno), 6); // callsign ::memset(sz, ' ', sizeof(sz)); g_Reflector.GetCallsign().GetCallsignString(sz); @@ -902,9 +908,9 @@ bool CImrsProtocol::EncodeDvLastPacket(const CDvHeaderPacket &Header, const CDvL //////////////////////////////////////////////////////////////////////////////////////// // uiStreamId helpers -uint32 CImrsProtocol::IpToStreamId(const CIp &ip) const +uint32 CImrsProtocol::CreateStreamId(void) const { - return ip.GetAddr() ^ (uint32)(MAKEDWORD(ip.GetPort(), ip.GetPort())); + return m_Random(); } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cimrsprotocol.h b/src/cimrsprotocol.h index 8d8f77e..7de655e 100644 --- a/src/cimrsprotocol.h +++ b/src/cimrsprotocol.h @@ -93,13 +93,13 @@ protected: // DV packet encoding helpers void EncodePingPacket(CBuffer *) const; - void EncodePongPacket(CBuffer *) const; + void EncodePongPacket(CBuffer *, int) const; bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; bool EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket *, CBuffer *) const; bool EncodeDvLastPacket(const CDvHeaderPacket &, const CDvLastFramePacket &, CBuffer *) const; // uiStreamId helpers - uint32 IpToStreamId(const CIp &) const; + uint32 CreateStreamId(void) const; // DG-ID helper char DgidToModule(uint8 uiDgid) const; @@ -111,6 +111,9 @@ protected: // for queue header caches std::array m_StreamsCache; + + // random number generator + mutable std::mt19937 m_Random; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cip.cpp b/src/cip.cpp index 5cec9b5..bd4c469 100644 --- a/src/cip.cpp +++ b/src/cip.cpp @@ -31,46 +31,109 @@ //////////////////////////////////////////////////////////////////////////////////////// // 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; + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// sockaddr + +void CIp::SetSockAddr(struct sockaddr_storage *ss, socklen_t len) +{ + 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; } //////////////////////////////////////////////////////////////////////////////////////// -// set +// get and set + +uint32 CIp::GetAddr(void) const +{ + switch (m_Addr.ss_family) + { + case AF_INET: + return ((struct sockaddr_in *)&m_Addr)->sin_addr.s_addr; + default: + return 0; /* not supported */ + } +} + +uint16 CIp::GetPort(void) const +{ + switch (m_Addr.ss_family) + { + case AF_INET: + return ((struct sockaddr_in *)&m_Addr)->sin_port; + case AF_INET6: + return ((struct sockaddr_in6 *)&m_Addr)->sin6_port; + default: + return 0; /* not supported */ + } +} -void CIp::SetSockAddr(struct sockaddr_in *sa) +void CIp::SetPort(uint16 port) { - ::memcpy(&m_Addr, sa, sizeof(m_Addr)); + switch (m_Addr.ss_family) + { + case AF_INET: + ((struct sockaddr_in *)&m_Addr)->sin_port = port; + break; + case AF_INET6: + ((struct sockaddr_in6 *)&m_Addr)->sin6_port = port; + break; + default: + /* not supported, do nothing */ + break; + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -78,14 +141,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 8d52cde..d916aac 100644 --- a/src/cip.h +++ b/src/cip.h @@ -33,25 +33,26 @@ 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 &); // get - uint32 GetAddr(void) const { return m_Addr.sin_addr.s_addr; } - uint16 GetPort(void) const { return m_Addr.sin_port; } + uint32 GetAddr(void) const; + uint16 GetPort(void) const; // set - void SetPort(uint16 port) { m_Addr.sin_port = port; } + void SetPort(uint16 port); // operator bool operator ==(const CIp &) const; @@ -59,7 +60,9 @@ public: 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 119dbb1..b81e006 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.cpp b/src/creflector.cpp index a813df9..625a6c2 100644 --- a/src/creflector.cpp +++ b/src/creflector.cpp @@ -31,6 +31,11 @@ #include "ctranscoder.h" #include "cysfnodedirfile.h" #include "cysfnodedirhttp.h" +#if defined(AF_PACKET) +#include +#elif defined(AF_LINK) +#include +#endif //////////////////////////////////////////////////////////////////////////////////////// // constructor @@ -774,148 +779,54 @@ void CReflector::SendJsonOffairObject(CUdpSocket &Socket, CIp &Ip, const CCallsi //////////////////////////////////////////////////////////////////////////////////////// // MAC address helpers -#ifdef __linux__ -#include -bool CReflector::UpdateListenMac(void) +bool CReflector::UpdateListenMac(int i) { - struct ifaddrs *ifap, *ifaptr; - char host[NI_MAXHOST]; + struct ifaddrs *ifa_top, *ifa; char *ifname = NULL; bool found = false; + socklen_t ss_len; - // iterate through all our AF_INET interface to find the one - // of our listening ip - if ( getifaddrs(&ifap) == 0 ) - { - for ( ifaptr = ifap; (ifaptr != NULL) && !found; ifaptr = (ifaptr)->ifa_next ) - { - // is it an AF_INET? - if ( ifaptr->ifa_addr && ifaptr->ifa_addr->sa_family == AF_INET ) - { - if (ifaptr->ifa_addr == NULL) - continue; - - // get the IP - if ( getnameinfo(ifaptr->ifa_addr, - sizeof(struct sockaddr_in), - host, NI_MAXHOST, - NULL, 0, NI_NUMERICHOST) == 0 ) - { - if ( CIp(host) == m_Ip ) - { - // yes, found it - found = true; - ifname = new char[strlen(ifaptr->ifa_name)+1]; - strcpy(ifname, ifaptr->ifa_name); - } - } - } - - } - freeifaddrs(ifap); - } + if ( getifaddrs(&ifa_top) < 0 || ifa_top == NULL ) + return false; - // if listening interface name found, iterate again - // to find the corresponding AF_PACKET interface - if ( found ) + m_Ip[i].GetSockAddr(ss_len); + + // get interface name associated with IP address + for ( ifa = ifa_top; ifa != NULL; ifa = ifa->ifa_next ) { - found = false; - if ( getifaddrs(&ifap) == 0 ) - { - for ( ifaptr = ifap; (ifaptr != NULL) && !found; ifaptr = (ifaptr)->ifa_next ) - { - if ( !strcmp((ifaptr)->ifa_name, ifname) && (ifaptr->ifa_addr->sa_family == AF_PACKET) ) - { - found = true; - struct sockaddr_ll *s = (struct sockaddr_ll *)(ifaptr->ifa_addr); - for ( int i = 0; i < 6; i++ ) - { - m_Mac[i] = s->sll_addr[i]; - } - } - } + if ( ifa->ifa_addr != NULL && + CIp((struct sockaddr_storage *)ifa->ifa_addr, ss_len) == m_Ip[i] ) { + found = true; + ifname = new char[strlen(ifa->ifa_name) + 1]; + strcpy(ifname, ifa->ifa_name); + break; } - freeifaddrs(ifap); } - // done - return found; -} -#endif - -#if defined(__APPLE__) && defined(__MACH__) -#include -bool CReflector::UpdateListenMac(void) -{ - struct ifaddrs *ifaddr; - int s; - char host[NI_MAXHOST]; - char *ifname = NULL; - bool found = false; - bool ok = false; - - if ( getifaddrs(&ifaddr) != -1) - { - // Walk through linked list, maintaining head pointer so we can free list later. - // until finding our listening AF_INET interface - for (struct ifaddrs *ifa = ifaddr; (ifa != NULL) && !found; ifa = ifa->ifa_next) + // get MAC address from interface name + if ( found ) { + void *p = NULL; + found = false; + for ( ifa = ifa_top; ifa != NULL; ifa = ifa->ifa_next ) { - if (ifa->ifa_addr == NULL) + if ( ifa->ifa_addr == NULL || strcmp(ifa->ifa_name, ifname ) ) continue; - - // is it an AF_INET? - if (ifa->ifa_addr->sa_family == AF_INET) - { - // get IP - s = getnameinfo(ifa->ifa_addr, - sizeof(struct sockaddr_in), - host, NI_MAXHOST, - NULL, 0, NI_NUMERICHOST); - if (s != 0) - { - return false; - } - // is it our listening ip ? - if ( CIp(host) == m_Ip ) - { - // yes, found it - found = true; - ifname = new char[strlen(ifa->ifa_name)+1]; - strcpy(ifname, ifa->ifa_name); - } - } - } - freeifaddrs(ifaddr); - - // found our interface ? - if ( found ) - { - // yes - //std::cout << ifname << " : " << host << std::endl; - - // Walk again through linked list - // until finding our listening AF_LINK interface - if ( getifaddrs(&ifaddr) != -1 ) +#if defined(AF_PACKET) + found = ( ifa->ifa_addr->sa_family == AF_PACKET ); + p = ((struct sockaddr_ll *)ifa->ifa_addr)->sll_addr; +#elif defined(AF_LINK) + found = ( ifa->ifa_addr->sa_family == AF_LINK ); + p = LLADDR((struct sockaddr_dl *)ifa->ifa_addr); +#endif + if ( found ) { - found = false; - for (struct ifaddrs *ifa = ifaddr; (ifa != NULL) && !found; ifa = ifa->ifa_next) - { - if (ifa->ifa_addr == NULL) - continue; - - if ( !strcmp(ifa->ifa_name, ifname) && (ifa->ifa_addr->sa_family == AF_LINK)) - { - ::memcpy((void *)m_Mac, (void *)LLADDR((struct sockaddr_dl *)(ifa)->ifa_addr), sizeof(m_Mac)); - ok = true; - found = true; - } - } - freeifaddrs(ifaddr); + memcpy(m_Mac[i], p, 6); + break; } } - delete [] ifname; } - return ok; + + freeifaddrs(ifa_top); + return found; } -#endif diff --git a/src/creflector.h b/src/creflector.h index ece983e..ea2967e 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,10 +58,10 @@ public: // 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; UpdateListenMac(); } + void SetListenIp(int i, const CIp &ip) { m_Ip[i] = ip; UpdateListenMac(i); } void SetTranscoderIp(const CIp &ip) { m_AmbedIp = ip; } - const CIp &GetListenIp(void) const { return m_Ip; } - const uint8 *GetListenMac(void) const { return (const uint8 *)m_Mac; } + const CIp &GetListenIp(int i = 0) const { return m_Ip[i]; } + const uint8 *GetListenMac(int i) const { return (const uint8 *)m_Mac[i]; } const CIp &GetTranscoderIp(void) const { return m_AmbedIp; } // operation @@ -118,13 +119,13 @@ protected: void SendJsonOffairObject(CUdpSocket &, CIp &, const CCallsign &); // MAC address helpers - bool UpdateListenMac(void); + bool UpdateListenMac(int i); protected: // identity CCallsign m_Callsign; - CIp m_Ip; - uint8 m_Mac[6]; + CIp m_Ip[UDP_SOCKET_MAX]; + uint8 m_Mac[UDP_SOCKET_MAX][6]; CIp m_AmbedIp; // objects diff --git a/src/cudpmsgsocket.cpp b/src/cudpmsgsocket.cpp index 45d438d..8a3fb9a 100644 --- a/src/cudpmsgsocket.cpp +++ b/src/cudpmsgsocket.cpp @@ -30,13 +30,44 @@ // 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; + struct sockaddr_storage *ss; + socklen_t ss_len; + + // IPv6 not supported + if ( !CUdpSocket::Open(uiPort, AF_INET) ) + { + return false; + } + + for ( int i = 0; i < UDP_SOCKET_MAX; i++ ) + { + if ( m_Socket[i] != -1 ) + { + ss = m_Ip[i].GetSockAddr(ss_len); + switch ( ss->ss_family ) + { + case AF_INET: +#if defined(IP_PKTINFO) + err = setsockopt(m_Socket[i], IPPROTO_IP, IP_PKTINFO, (char *)&on, sizeof(on)); +#elif defined(IP_RECVDSTADDR) + err = setsockopt(m_Socket[i], IPPROTO_IP, IP_RECVDSTADDR, (char *)&on, sizeof(on)); +#endif + break; + default: + err = -1; + break; + } + + if ( err < 0 ) + { + CUdpSocket::Close(); + return false; + } + } + } + + return true; } @@ -46,70 +77,98 @@ bool CUdpMsgSocket::Open(uint16 uiPort) int CUdpMsgSocket::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 pollfd pfd[UDP_SOCKET_MAX]; + int i, socks, index, iRecvLen = -1; + struct msghdr Msg; struct iovec Iov[1]; - + 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 ) + 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 ) { - // allocate buffer - Buffer->resize(UDP_MSG_BUFFER_LENMAX); - - //prepare msghdr - bzero(&Msg, sizeof(Msg)); - Iov[0].iov_base = Buffer->data(); - Iov[0].iov_len = UDP_MSG_BUFFER_LENMAX; - - bzero(&Sin, sizeof(Sin)); - Msg.msg_name = &Sin; - Msg.msg_namelen = sizeof(Sin); - Msg.msg_iov = Iov; - Msg.msg_iovlen = 1; - Msg.msg_control = &Control; - Msg.msg_controllen = sizeof(Control); - // 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); - - // read - iRecvLen = (int)recvmsg(m_Socket, &Msg, 0); + poll(pfd, socks, timeout); - // 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); - - // get local IP - struct cmsghdr *Cmsg; - for (Cmsg = CMSG_FIRSTHDR(&Msg); Cmsg != NULL; Cmsg = CMSG_NXTHDR(&Msg, Cmsg)) + if ( pfd[index].revents & POLLIN ) { - if (Cmsg->cmsg_level == IPPROTO_IP && Cmsg->cmsg_type == IP_PKTINFO) + // allocate buffer + Buffer->resize(UDP_MSG_BUFFER_LENMAX); + + // prepare msghdr + bzero(&Msg, sizeof(Msg)); + Iov[0].iov_base = Buffer->data(); + Iov[0].iov_len = UDP_MSG_BUFFER_LENMAX; + + bzero(&Sin, sizeof(Sin)); + Msg.msg_name = &Sin; + Msg.msg_namelen = sizeof(Sin); + Msg.msg_iov = Iov; + Msg.msg_iovlen = 1; + Msg.msg_control = &Control; + Msg.msg_controllen = sizeof(Control); + + // read + iRecvLen = (int)recvmsg(pfd[index].fd, &Msg, 0); + + // handle + if ( iRecvLen != -1 ) { - struct in_pktinfo *PktInfo = (struct in_pktinfo *)CMSG_DATA(Cmsg); - m_LocalAddr.s_addr = PktInfo->ipi_spec_dst.s_addr; + // adjust buffer size + Buffer->resize(iRecvLen); + + // get IP + 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 + } + + m_Counter++; + break; } } } } - + // done return iRecvLen; } diff --git a/src/cudpsocket.cpp b/src/cudpsocket.cpp index 5caa074..f1b6e03 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,50 +90,98 @@ 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; } //////////////////////////////////////////////////////////////////////////////////////// // read -int CUdpSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout) +int CUdpSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout, int *sno) { - 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; + int index2sno[UDP_SOCKET_MAX]; // 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; + index2sno[socks] = i; + 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); + + // record the number of incoming socket + if ( sno != NULL ) + { + *sno = index2sno[index]; + } + + m_Counter++; + break; + } + } } } @@ -139,35 +195,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 e91ed80..7d5b40f 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,12 +57,12 @@ public: ~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); + int Receive(CBuffer *, CIp *, int, int * = NULL); // write int Send(const CBuffer &, const CIp &); @@ -70,8 +72,9 @@ public: 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 38e11c7..73bc378 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; } @@ -459,7 +464,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; @@ -538,7 +543,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]; @@ -595,7 +600,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 { @@ -1016,9 +1021,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 77725e9..6dab89b 100644 --- a/src/cysfprotocol.h +++ b/src/cysfprotocol.h @@ -120,7 +120,7 @@ protected: bool EncodeServerStatusPacket(CBuffer *) const; // uiStreamId helpers - uint32 IpToStreamId(const CIp &) const; + uint32 CreateStreamId(void) const; // debug bool DebugTestDecodePacket(const CBuffer &); @@ -135,6 +135,9 @@ protected: // 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 723ab5b..5b75188 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 26b5ba2..0a81eda 100644 --- a/src/main.h +++ b/src/main.h @@ -39,8 +39,11 @@ #include #include #include +#include #include #include +#include +#include #include //////////////////////////////////////////////////////////////////////////////////////// @@ -62,6 +65,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 2d7b587..bbf7a7c 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)