mirror of
https://github.com/LX3JL/xlxd.git
synced 2025-12-06 07:42:01 +01:00
Merge 9a60176fa3 into 129f1257b4
This commit is contained in:
commit
c4354004e0
|
|
@ -64,13 +64,42 @@ for ($i=0;$i<$Reflector->PeerCount();$i++) {
|
||||||
<td>'.$Reflector->Peers[$i]->GetLinkedModule().'</td>';
|
<td>'.$Reflector->Peers[$i]->GetLinkedModule().'</td>';
|
||||||
if ($PageOptions['PeerPage']['IPModus'] != 'HideIP') {
|
if ($PageOptions['PeerPage']['IPModus'] != 'HideIP') {
|
||||||
echo '<td>';
|
echo '<td>';
|
||||||
$Bytes = explode(".", $Reflector->Peers[$i]->GetIP());
|
$IPBinary = inet_pton($Reflector->Peers[$i]->GetIP());
|
||||||
if ($Bytes !== false && count($Bytes) == 4) {
|
$IPLength = strlen($IPBinary);
|
||||||
switch ($PageOptions['PeerPage']['IPModus']) {
|
$Bytes = str_split($IPBinary, 1);
|
||||||
case 'ShowLast1ByteOfIP' : echo $PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$Bytes[3]; break;
|
switch ($PageOptions['PeerPage']['IPModus']) {
|
||||||
case 'ShowLast2ByteOfIP' : echo $PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$Bytes[2].'.'.$Bytes[3]; break;
|
case 'ShowLast1ByteOfIP' : $MasqByte = 3; break;
|
||||||
case 'ShowLast3ByteOfIP' : echo $PageOptions['PeerPage']['MasqueradeCharacter'].'.'.$Bytes[1].'.'.$Bytes[2].'.'.$Bytes[3]; break;
|
case 'ShowLast2ByteOfIP' : $MasqByte = 2; break;
|
||||||
default : echo '<a href="http://'.$Reflector->Peers[$i]->GetIP().'" target="_blank" style="text-decoration:none;color:#000000;">'.$Reflector->Peers[$i]->GetIP().'</a>';
|
case 'ShowLast3ByteOfIP' : $MasqByte = 1; break;
|
||||||
|
default : $MasqByte = 0; break;
|
||||||
|
}
|
||||||
|
if ($MasqByte == 0) {
|
||||||
|
switch ($IPLength) {
|
||||||
|
case 16: $IPAddrBracketL = '['; $IPAddrBracketR = ']'; break;
|
||||||
|
default: $IPAddrBracketL = ''; $IPAddrBracketR = ''; break;
|
||||||
|
}
|
||||||
|
echo '<a href="http://'.$IPAddrBracketL.$Reflector->Peers[$i]->GetIP().$IPAddrBracketR.'" target="_blank" style="text-decoration:none;color:#000000;">'.$Reflector->Peers[$i]->GetIP().'</a>';
|
||||||
|
} 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 '</td>';
|
echo '</td>';
|
||||||
|
|
|
||||||
|
|
@ -60,14 +60,35 @@ for ($i=0;$i<$Reflector->NodeCount();$i++) {
|
||||||
if ($PageOptions['RepeatersPage']['IPModus'] != 'HideIP') {
|
if ($PageOptions['RepeatersPage']['IPModus'] != 'HideIP') {
|
||||||
echo '
|
echo '
|
||||||
<td>';
|
<td>';
|
||||||
$Bytes = explode(".", $Reflector->Nodes[$i]->GetIP());
|
$IPBinary = inet_pton($Reflector->Nodes[$i]->GetIP());
|
||||||
if ($Bytes !== false && count($Bytes) == 4) {
|
$IPLength = strlen($IPBinary);
|
||||||
switch ($PageOptions['RepeatersPage']['IPModus']) {
|
$Bytes = str_split($IPBinary, 1);
|
||||||
case 'ShowLast1ByteOfIP' : echo $PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$Bytes[3]; break;
|
switch ($PageOptions['RepeatersPage']['IPModus']) {
|
||||||
case 'ShowLast2ByteOfIP' : echo $PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$Bytes[2].'.'.$Bytes[3]; break;
|
case 'ShowLast1ByteOfIP' : $MasqByte = 3; break;
|
||||||
case 'ShowLast3ByteOfIP' : echo $PageOptions['RepeatersPage']['MasqueradeCharacter'].'.'.$Bytes[1].'.'.$Bytes[2].'.'.$Bytes[3]; break;
|
case 'ShowLast2ByteOfIP' : $MasqByte = 2; break;
|
||||||
default : echo $Reflector->Nodes[$i]->GetIP();
|
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 '</td>';
|
echo '</td>';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -207,7 +207,7 @@ void CCallsign::SetYsfCallsign(const char *sz)
|
||||||
m_uiDmrid = 0;
|
m_uiDmrid = 0;
|
||||||
|
|
||||||
// set callsign
|
// 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];
|
m_Callsign[i] = sz[i];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,9 +73,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
|
||||||
|
|
@ -46,18 +49,34 @@ bool CG3Protocol::Init(void)
|
||||||
// base class
|
// base class
|
||||||
ok = CProtocol::Init();
|
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
|
// update reflector callsign
|
||||||
m_ReflectorCallsign.PatchCallsign(0, (const uint8 *)"XLX", 3);
|
m_ReflectorCallsign.PatchCallsign(0, (const uint8 *)"XLX", 3);
|
||||||
|
|
||||||
// create our DV socket
|
// create our DV socket
|
||||||
ok &= m_Socket.Open(G3_DV_PORT);
|
ok &= m_Socket.Open(G3_DV_PORT, AF_INET);
|
||||||
if ( !ok )
|
if ( !ok )
|
||||||
{
|
{
|
||||||
std::cout << "Error opening socket on port UDP" << G3_DV_PORT << " on ip " << g_Reflector.GetListenIp() << std::endl;
|
std::cout << "Error opening socket on port UDP" << G3_DV_PORT << " on ip " << g_Reflector.GetListenIp() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
//create helper sockets
|
//create helper sockets
|
||||||
ok &= m_PresenceSocket.Open(G3_PRESENCE_PORT);
|
ok &= m_PresenceSocket.Open(G3_PRESENCE_PORT, AF_INET);
|
||||||
if ( !ok )
|
if ( !ok )
|
||||||
{
|
{
|
||||||
std::cout << "Error opening socket on port UDP" << G3_PRESENCE_PORT << " on ip " << g_Reflector.GetListenIp() << std::endl;
|
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);
|
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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,11 @@ bool CImrsProtocol::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;
|
||||||
}
|
}
|
||||||
|
|
@ -76,10 +81,11 @@ void CImrsProtocol::Task(void)
|
||||||
//CYSFFICH Fich;
|
//CYSFFICH Fich;
|
||||||
CDvHeaderPacket *Header;
|
CDvHeaderPacket *Header;
|
||||||
CDvFramePacket *Frames[5];
|
CDvFramePacket *Frames[5];
|
||||||
|
int sno;
|
||||||
uint32 Version;
|
uint32 Version;
|
||||||
|
|
||||||
// handle incoming packets
|
// handle incoming packets
|
||||||
if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 )
|
if ( m_Socket.Receive(&Buffer, &Ip, 20, &sno) != -1 )
|
||||||
{
|
{
|
||||||
// force port
|
// force port
|
||||||
Ip.SetPort(IMRS_PORT);
|
Ip.SetPort(IMRS_PORT);
|
||||||
|
|
@ -124,7 +130,7 @@ void CImrsProtocol::Task(void)
|
||||||
//std::cout << "IMRS ping packet from " << Ip << std::endl;
|
//std::cout << "IMRS ping packet from " << Ip << std::endl;
|
||||||
|
|
||||||
// acknowledge request
|
// acknowledge request
|
||||||
EncodePongPacket(&Buffer);
|
EncodePongPacket(&Buffer, sno);
|
||||||
m_Socket.Send(Buffer, Ip, IMRS_PORT);
|
m_Socket.Send(Buffer, Ip, IMRS_PORT);
|
||||||
|
|
||||||
// our turn
|
// our turn
|
||||||
|
|
@ -412,7 +418,7 @@ bool CImrsProtocol::IsValidDvHeaderPacket(const CIp &Ip, const CBuffer &Buffer,
|
||||||
if ( (Buffer.size() == 91) && (Buffer.at(1) == 0x4B) )
|
if ( (Buffer.size() == 91) && (Buffer.at(1) == 0x4B) )
|
||||||
{
|
{
|
||||||
// get stream id
|
// get stream id
|
||||||
uint32 uiStreamId = IpToStreamId(Ip);
|
uint32 uiStreamId = CreateStreamId();
|
||||||
|
|
||||||
// and payload
|
// and payload
|
||||||
CBuffer 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) )
|
if ( (Buffer.size() == 181) && (Buffer.at(1) == 0xA5) )
|
||||||
{
|
{
|
||||||
// get stream id
|
// get stream id
|
||||||
uint32 uiStreamId = IpToStreamId(Ip);
|
uint32 uiStreamId = CreateStreamId();
|
||||||
|
|
||||||
// and payload
|
// and payload
|
||||||
CBuffer payload;
|
CBuffer payload;
|
||||||
|
|
@ -584,7 +590,7 @@ bool CImrsProtocol::IsValidDvLastFramePacket(const CIp &Ip, const CBuffer &Buffe
|
||||||
if ( (Buffer.size() == 31) && (Buffer.at(1) == 0x0F) )
|
if ( (Buffer.size() == 31) && (Buffer.at(1) == 0x0F) )
|
||||||
{
|
{
|
||||||
// get stream id
|
// get stream id
|
||||||
uint32 uiStreamId = IpToStreamId(Ip);
|
uint32 uiStreamId = CreateStreamId();
|
||||||
|
|
||||||
// and payload
|
// and payload
|
||||||
CBuffer payload;
|
CBuffer payload;
|
||||||
|
|
@ -647,7 +653,7 @@ void CImrsProtocol::EncodePingPacket(CBuffer *Buffer) const
|
||||||
Buffer->Set(tag, sizeof(tag));
|
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 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' };
|
uint8 radioid[] = { 'G','0','g','B','J' };
|
||||||
|
|
@ -656,7 +662,7 @@ void CImrsProtocol::EncodePongPacket(CBuffer *Buffer) const
|
||||||
// tag
|
// tag
|
||||||
Buffer->Set(tag1, sizeof(tag1));
|
Buffer->Set(tag1, sizeof(tag1));
|
||||||
// mac address
|
// mac address
|
||||||
Buffer->Append(g_Reflector.GetListenMac(), 6);
|
Buffer->Append(g_Reflector.GetListenMac(sno), 6);
|
||||||
// callsign
|
// callsign
|
||||||
::memset(sz, ' ', sizeof(sz));
|
::memset(sz, ' ', sizeof(sz));
|
||||||
g_Reflector.GetCallsign().GetCallsignString(sz);
|
g_Reflector.GetCallsign().GetCallsignString(sz);
|
||||||
|
|
@ -902,9 +908,9 @@ bool CImrsProtocol::EncodeDvLastPacket(const CDvHeaderPacket &Header, const CDvL
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// uiStreamId helpers
|
// 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
||||||
|
|
@ -93,13 +93,13 @@ protected:
|
||||||
|
|
||||||
// DV packet encoding helpers
|
// DV packet encoding helpers
|
||||||
void EncodePingPacket(CBuffer *) const;
|
void EncodePingPacket(CBuffer *) const;
|
||||||
void EncodePongPacket(CBuffer *) const;
|
void EncodePongPacket(CBuffer *, int) const;
|
||||||
bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const;
|
bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const;
|
||||||
bool EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket *, CBuffer *) const;
|
bool EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket *, CBuffer *) const;
|
||||||
bool EncodeDvLastPacket(const CDvHeaderPacket &, const CDvLastFramePacket &, CBuffer *) const;
|
bool EncodeDvLastPacket(const CDvHeaderPacket &, const CDvLastFramePacket &, CBuffer *) const;
|
||||||
|
|
||||||
// uiStreamId helpers
|
// uiStreamId helpers
|
||||||
uint32 IpToStreamId(const CIp &) const;
|
uint32 CreateStreamId(void) const;
|
||||||
|
|
||||||
// DG-ID helper
|
// DG-ID helper
|
||||||
char DgidToModule(uint8 uiDgid) const;
|
char DgidToModule(uint8 uiDgid) const;
|
||||||
|
|
@ -111,6 +111,9 @@ protected:
|
||||||
|
|
||||||
// for queue header caches
|
// for queue header caches
|
||||||
std::array<CImrsStreamCacheItem, NB_OF_MODULES> m_StreamsCache;
|
std::array<CImrsStreamCacheItem, NB_OF_MODULES> m_StreamsCache;
|
||||||
|
|
||||||
|
// random number generator
|
||||||
|
mutable std::mt19937 m_Random;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
||||||
144
src/cip.cpp
144
src/cip.cpp
|
|
@ -31,46 +31,109 @@
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// constructors
|
// constructors
|
||||||
|
|
||||||
CIp::CIp()
|
CIp::CIp(const int af)
|
||||||
{
|
{
|
||||||
::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;
|
||||||
}
|
}
|
||||||
|
|
||||||
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));
|
||||||
|
if ( getaddrinfo(sz, NULL, &hints, &res) == 0 )
|
||||||
{
|
{
|
||||||
// otherwise try to resolve via dns
|
::memcpy(&m_Addr, res->ai_addr, m_AddrLen = res->ai_addrlen);
|
||||||
hostent *record = gethostbyname(sz);
|
freeaddrinfo(res);
|
||||||
if( record != NULL )
|
|
||||||
{
|
|
||||||
m_Addr.sin_addr.s_addr = ((in_addr * )record->h_addr)->s_addr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 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::SetPort(uint16 port)
|
||||||
|
{
|
||||||
|
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
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
19
src/cip.h
19
src/cip.h
|
|
@ -33,25 +33,26 @@ class CIp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// constructors
|
// constructors
|
||||||
CIp();
|
CIp(const int af = AF_INET);
|
||||||
//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 &);
|
||||||
|
|
||||||
// get
|
// get
|
||||||
uint32 GetAddr(void) const { return m_Addr.sin_addr.s_addr; }
|
uint32 GetAddr(void) const;
|
||||||
uint16 GetPort(void) const { return m_Addr.sin_port; }
|
uint16 GetPort(void) const;
|
||||||
|
|
||||||
// set
|
// set
|
||||||
void SetPort(uint16 port) { m_Addr.sin_port = port; }
|
void SetPort(uint16 port);
|
||||||
|
|
||||||
// operator
|
// operator
|
||||||
bool operator ==(const CIp &) const;
|
bool operator ==(const CIp &) const;
|
||||||
|
|
@ -59,7 +60,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,11 @@
|
||||||
#include "ctranscoder.h"
|
#include "ctranscoder.h"
|
||||||
#include "cysfnodedirfile.h"
|
#include "cysfnodedirfile.h"
|
||||||
#include "cysfnodedirhttp.h"
|
#include "cysfnodedirhttp.h"
|
||||||
|
#if defined(AF_PACKET)
|
||||||
|
#include <netpacket/packet.h>
|
||||||
|
#elif defined(AF_LINK)
|
||||||
|
#include <net/if_dl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// constructor
|
// constructor
|
||||||
|
|
@ -774,148 +779,54 @@ void CReflector::SendJsonOffairObject(CUdpSocket &Socket, CIp &Ip, const CCallsi
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// MAC address helpers
|
// MAC address helpers
|
||||||
|
|
||||||
#ifdef __linux__
|
bool CReflector::UpdateListenMac(int i)
|
||||||
#include <netpacket/packet.h>
|
|
||||||
bool CReflector::UpdateListenMac(void)
|
|
||||||
{
|
{
|
||||||
struct ifaddrs *ifap, *ifaptr;
|
struct ifaddrs *ifa_top, *ifa;
|
||||||
char host[NI_MAXHOST];
|
|
||||||
char *ifname = NULL;
|
char *ifname = NULL;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
socklen_t ss_len;
|
||||||
|
|
||||||
// iterate through all our AF_INET interface to find the one
|
if ( getifaddrs(&ifa_top) < 0 || ifa_top == NULL )
|
||||||
// of our listening ip
|
return false;
|
||||||
if ( getifaddrs(&ifap) == 0 )
|
|
||||||
|
m_Ip[i].GetSockAddr(ss_len);
|
||||||
|
|
||||||
|
// get interface name associated with IP address
|
||||||
|
for ( ifa = ifa_top; ifa != NULL; ifa = ifa->ifa_next )
|
||||||
{
|
{
|
||||||
for ( ifaptr = ifap; (ifaptr != NULL) && !found; ifaptr = (ifaptr)->ifa_next )
|
if ( ifa->ifa_addr != NULL &&
|
||||||
{
|
CIp((struct sockaddr_storage *)ifa->ifa_addr, ss_len) == m_Ip[i] ) {
|
||||||
// is it an AF_INET?
|
found = true;
|
||||||
if ( ifaptr->ifa_addr && ifaptr->ifa_addr->sa_family == AF_INET )
|
ifname = new char[strlen(ifa->ifa_name) + 1];
|
||||||
{
|
strcpy(ifname, ifa->ifa_name);
|
||||||
if (ifaptr->ifa_addr == NULL)
|
break;
|
||||||
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 listening interface name found, iterate again
|
// get MAC address from interface name
|
||||||
// to find the corresponding AF_PACKET interface
|
if ( found ) {
|
||||||
if ( found )
|
void *p = NULL;
|
||||||
{
|
|
||||||
found = false;
|
found = false;
|
||||||
if ( getifaddrs(&ifap) == 0 )
|
for ( ifa = ifa_top; ifa != NULL; ifa = ifa->ifa_next )
|
||||||
{
|
{
|
||||||
for ( ifaptr = ifap; (ifaptr != NULL) && !found; ifaptr = (ifaptr)->ifa_next )
|
if ( ifa->ifa_addr == NULL || strcmp(ifa->ifa_name, ifname ) )
|
||||||
{
|
|
||||||
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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
freeifaddrs(ifap);
|
|
||||||
}
|
|
||||||
|
|
||||||
// done
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__APPLE__) && defined(__MACH__)
|
|
||||||
#include <net/if_dl.h>
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (ifa->ifa_addr == NULL)
|
|
||||||
continue;
|
continue;
|
||||||
|
#if defined(AF_PACKET)
|
||||||
// is it an AF_INET?
|
found = ( ifa->ifa_addr->sa_family == AF_PACKET );
|
||||||
if (ifa->ifa_addr->sa_family == AF_INET)
|
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 )
|
||||||
{
|
{
|
||||||
// get IP
|
memcpy(m_Mac[i], p, 6);
|
||||||
s = getnameinfo(ifa->ifa_addr,
|
break;
|
||||||
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 )
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delete [] ifname;
|
delete [] ifname;
|
||||||
}
|
}
|
||||||
return ok;
|
|
||||||
|
freeifaddrs(ifa_top);
|
||||||
|
return found;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
|
||||||
|
|
@ -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,10 +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; UpdateListenMac(); }
|
void SetListenIp(int i, const CIp &ip) { m_Ip[i] = ip; UpdateListenMac(i); }
|
||||||
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(int i = 0) const { return m_Ip[i]; }
|
||||||
const uint8 *GetListenMac(void) const { return (const uint8 *)m_Mac; }
|
const uint8 *GetListenMac(int i) const { return (const uint8 *)m_Mac[i]; }
|
||||||
const CIp &GetTranscoderIp(void) const { return m_AmbedIp; }
|
const CIp &GetTranscoderIp(void) const { return m_AmbedIp; }
|
||||||
|
|
||||||
// operation
|
// operation
|
||||||
|
|
@ -118,13 +119,13 @@ protected:
|
||||||
void SendJsonOffairObject(CUdpSocket &, CIp &, const CCallsign &);
|
void SendJsonOffairObject(CUdpSocket &, CIp &, const CCallsign &);
|
||||||
|
|
||||||
// MAC address helpers
|
// MAC address helpers
|
||||||
bool UpdateListenMac(void);
|
bool UpdateListenMac(int i);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// identity
|
// identity
|
||||||
CCallsign m_Callsign;
|
CCallsign m_Callsign;
|
||||||
CIp m_Ip;
|
CIp m_Ip[UDP_SOCKET_MAX];
|
||||||
uint8 m_Mac[6];
|
uint8 m_Mac[UDP_SOCKET_MAX][6];
|
||||||
CIp m_AmbedIp;
|
CIp m_AmbedIp;
|
||||||
|
|
||||||
// objects
|
// objects
|
||||||
|
|
|
||||||
|
|
@ -30,13 +30,44 @@
|
||||||
// open
|
// open
|
||||||
bool CUdpMsgSocket::Open(uint16 uiPort)
|
bool CUdpMsgSocket::Open(uint16 uiPort)
|
||||||
{
|
{
|
||||||
bool ret;
|
int on = 1, err;
|
||||||
int on = 1;
|
struct sockaddr_storage *ss;
|
||||||
|
socklen_t ss_len;
|
||||||
ret = CUdpSocket::Open(uiPort);
|
|
||||||
setsockopt(m_Socket, IPPROTO_IP, IP_PKTINFO, (char *)&on, sizeof(on));
|
// IPv6 not supported
|
||||||
|
if ( !CUdpSocket::Open(uiPort, AF_INET) )
|
||||||
return ret;
|
{
|
||||||
|
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)
|
int CUdpMsgSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout)
|
||||||
{
|
{
|
||||||
struct sockaddr_in Sin;
|
struct sockaddr_in Sin;
|
||||||
fd_set FdSet;
|
struct pollfd pfd[UDP_SOCKET_MAX];
|
||||||
unsigned int uiFromLen = sizeof(struct sockaddr_in);
|
int i, socks, index, iRecvLen = -1;
|
||||||
int iRecvLen = -1;
|
|
||||||
struct timeval tv;
|
|
||||||
|
|
||||||
struct msghdr Msg;
|
struct msghdr Msg;
|
||||||
struct iovec Iov[1];
|
struct iovec Iov[1];
|
||||||
|
|
||||||
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 )
|
for ( i = socks = 0; i < UDP_SOCKET_MAX; i++ )
|
||||||
{
|
{
|
||||||
// allocate buffer
|
if ( m_Socket[i] != -1 )
|
||||||
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);
|
|
||||||
|
|
||||||
// handle
|
|
||||||
if ( iRecvLen != -1 )
|
|
||||||
{
|
{
|
||||||
// adjust buffer size
|
pfd[socks].fd = m_Socket[i];
|
||||||
Buffer->resize(iRecvLen);
|
pfd[socks].events = POLLIN;
|
||||||
|
socks++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( socks != 0 )
|
||||||
|
{
|
||||||
|
// control socket
|
||||||
|
poll(pfd, socks, timeout);
|
||||||
|
|
||||||
|
for ( i = 0; i < socks; i++ )
|
||||||
|
{
|
||||||
|
// round robin
|
||||||
|
index = (i + m_Counter) % socks;
|
||||||
|
|
||||||
// get IP
|
if ( pfd[index].revents & POLLIN )
|
||||||
Ip->SetSockAddr(&Sin);
|
|
||||||
|
|
||||||
// get local IP
|
|
||||||
struct cmsghdr *Cmsg;
|
|
||||||
for (Cmsg = CMSG_FIRSTHDR(&Msg); Cmsg != NULL; Cmsg = CMSG_NXTHDR(&Msg, Cmsg))
|
|
||||||
{
|
{
|
||||||
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);
|
// adjust buffer size
|
||||||
m_LocalAddr.s_addr = PktInfo->ipi_spec_dst.s_addr;
|
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
|
// done
|
||||||
return iRecvLen;
|
return iRecvLen;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,10 @@
|
||||||
|
|
||||||
CUdpSocket::CUdpSocket()
|
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()
|
CUdpSocket::~CUdpSocket()
|
||||||
{
|
{
|
||||||
if ( m_Socket != -1 )
|
Close();
|
||||||
{
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// open & close
|
// open & close
|
||||||
|
|
||||||
bool CUdpSocket::Open(uint16 uiPort)
|
bool CUdpSocket::Open(uint16 uiPort, int af)
|
||||||
{
|
{
|
||||||
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(AF_UNSPEC);
|
||||||
::memset(&m_SocketAddr, 0, sizeof(struct sockaddr_in));
|
m_Socket[i] = -1;
|
||||||
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 )
|
if ( g_Reflector.GetListenIp(i) != CIp(AF_UNSPEC) )
|
||||||
{
|
{
|
||||||
fcntl(m_Socket, F_SETFL, O_NONBLOCK);
|
m_Ip[i] = CIp(g_Reflector.GetListenIp(i), uiPort);
|
||||||
open = true;
|
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);
|
if ( bind(m_Socket[i], (struct sockaddr *)ss, ss_len) == 0 )
|
||||||
m_Socket = -1;
|
{
|
||||||
|
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)
|
void CUdpSocket::Close(void)
|
||||||
{
|
{
|
||||||
if ( m_Socket != -1 )
|
for ( int i = 0; i < UDP_SOCKET_MAX; i++ )
|
||||||
{
|
{
|
||||||
close(m_Socket);
|
if ( m_Socket[i] != -1 )
|
||||||
m_Socket = -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++ )
|
||||||
|
{
|
||||||
|
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
|
// 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;
|
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;
|
int index2sno[UDP_SOCKET_MAX];
|
||||||
|
|
||||||
// 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;
|
||||||
|
index2sno[socks] = i;
|
||||||
|
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);
|
|
||||||
|
|
||||||
// allocate buffer
|
for ( i = 0; i < socks; i++ )
|
||||||
Buffer->resize(UDP_BUFFER_LENMAX);
|
|
||||||
|
|
||||||
// read
|
|
||||||
iRecvLen = (int)recvfrom(m_Socket,
|
|
||||||
(void *)Buffer->data(), UDP_BUFFER_LENMAX,
|
|
||||||
0, (struct sockaddr *)&Sin, &uiFromLen);
|
|
||||||
|
|
||||||
// handle
|
|
||||||
if ( iRecvLen != -1 )
|
|
||||||
{
|
{
|
||||||
// adjust buffer size
|
// round robin
|
||||||
Buffer->resize(iRecvLen);
|
index = (i + m_Counter) % socks;
|
||||||
|
|
||||||
// get IP
|
if ( pfd[index].revents & POLLIN )
|
||||||
Ip->SetSockAddr(&Sin);
|
{
|
||||||
|
// 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)
|
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
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -55,12 +57,12 @@ public:
|
||||||
~CUdpSocket();
|
~CUdpSocket();
|
||||||
|
|
||||||
// open & close
|
// open & close
|
||||||
bool Open(uint16);
|
bool Open(uint16, int = AF_UNSPEC);
|
||||||
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, int * = NULL);
|
||||||
|
|
||||||
// write
|
// write
|
||||||
int Send(const CBuffer &, const CIp &);
|
int Send(const CBuffer &, const CIp &);
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
@ -459,7 +464,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;
|
||||||
|
|
@ -538,7 +543,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];
|
||||||
|
|
@ -595,7 +600,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
|
||||||
{
|
{
|
||||||
|
|
@ -1016,9 +1021,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;
|
||||||
|
|
|
||||||
21
src/main.cpp
21
src/main.cpp
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include "syslog.h"
|
#include "syslog.h"
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -39,7 +40,7 @@ CReflector g_Reflector;
|
||||||
|
|
||||||
#include "cusers.h"
|
#include "cusers.h"
|
||||||
|
|
||||||
int main(int argc, const char * argv[])
|
int main(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
#ifdef RUN_AS_DAEMON
|
#ifdef RUN_AS_DAEMON
|
||||||
|
|
||||||
|
|
@ -87,7 +88,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,9 +100,21 @@ 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.SetTranscoderIp(CIp(CIp(argv[3])));
|
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
|
// 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>
|
||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -62,6 +65,7 @@
|
||||||
//#define DEBUG_NO_ERROR_ON_XML_OPEN_FAIL
|
//#define DEBUG_NO_ERROR_ON_XML_OPEN_FAIL
|
||||||
//#define DEBUG_DUMPFILE
|
//#define DEBUG_DUMPFILE
|
||||||
//#define DEBUG_NO_G3_ICMP_SOCKET
|
//#define DEBUG_NO_G3_ICMP_SOCKET
|
||||||
|
//#define DEBUG_NO_G3_SUPPORT
|
||||||
|
|
||||||
// reflector ---------------------------------------------------
|
// reflector ---------------------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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…
Reference in a new issue