Merge branch 'dextrapeer'

pull/1/head
Tom Early 6 years ago
commit 9a6d57921e

@ -2,13 +2,15 @@
# XLXD interlink file # XLXD interlink file
# #
# one line per entry # one line per entry
# each entry specify a remote XLX to peer with # each entry specifies a remote XLX or XRF to peer with
# format: # format:
# <callsign> <ip> <list of module shared> # <XLX callsign> <ip> <list of modules shared>
# <XRF callsign> <ip> <local module><remote module>
# example: # example:
# XLX270 158.64.26.132 ACD # XLX270 158.64.26.132 ACD
# XRF270 158.64.26.132 BB
# #
# note: the remote XLX must list this XLX in it's interlink file # note: the remote XLX must list this XLX in its interlink file
# for the link to be established # for the link to be established
# #
############################################################################# #############################################################################

@ -34,7 +34,7 @@ CBmPeer::CBmPeer()
{ {
} }
CBmPeer::CBmPeer(const CCallsign &callsign, const CIp &ip, char *modules, const CVersion &version) CBmPeer::CBmPeer(const CCallsign &callsign, const CIp &ip, const char *modules, const CVersion &version)
: CPeer(callsign, ip, modules, version) : CPeer(callsign, ip, modules, version)
{ {
std::cout << "Adding BM peer" << std::endl; std::cout << "Adding BM peer" << std::endl;

@ -41,7 +41,7 @@ class CBmPeer : public CPeer
public: public:
// constructors // constructors
CBmPeer(); CBmPeer();
CBmPeer(const CCallsign &, const CIp &, char *, const CVersion &); CBmPeer(const CCallsign &, const CIp &, const char *, const CVersion &);
CBmPeer(const CBmPeer &); CBmPeer(const CBmPeer &);
// destructor // destructor

@ -0,0 +1,99 @@
//
// cdextrapeer.cpp
// xlxd
//
// Created by Antony Chazapis (SV9OAN) on 25/2/2018.
// Copyright © 2016 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of xlxd.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include "main.h"
#include <string.h>
#include "creflector.h"
#include "cdextrapeer.h"
#include "cdextraclient.h"
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CDextraPeer::CDextraPeer()
{
}
CDextraPeer::CDextraPeer(const CCallsign &callsign, const CIp &ip, const char *modules, const CVersion &version)
: CPeer(callsign, ip, modules, version)
{
std::cout << "Adding DExtra peer" << std::endl;
// and construct the DExtra clients
for ( int i = 0; i < ::strlen(modules); i++ )
{
// create
CDextraClient *client = new CDextraClient(callsign, ip, modules[i], version.GetMajor());
// and append to vector
m_Clients.push_back(client);
}
}
CDextraPeer::CDextraPeer(const CDextraPeer &peer)
: CPeer(peer)
{
for ( int i = 0; i < peer.m_Clients.size(); i++ )
{
CDextraClient *client = new CDextraClient((const CDextraClient &)*(peer.m_Clients[i]));
// grow vector capacity if needed
if ( m_Clients.capacity() == m_Clients.size() )
{
m_Clients.reserve(m_Clients.capacity()+10);
}
// and append
m_Clients.push_back(client);
}
}
////////////////////////////////////////////////////////////////////////////////////////
// destructors
CDextraPeer::~CDextraPeer()
{
}
////////////////////////////////////////////////////////////////////////////////////////
// status
bool CDextraPeer::IsAlive(void) const
{
bool alive = true;
for ( int i = 0; (i < m_Clients.size()) && alive ; i++ )
{
alive &= m_Clients[i]->IsAlive();
}
return alive;
}
////////////////////////////////////////////////////////////////////////////////////////
// revision helper
int CDextraPeer::GetProtocolRevision(const CVersion &version)
{
return version.GetMajor();
}

@ -0,0 +1,61 @@
//
// cdextrapeer.h
// xlxd
//
// Created by Antony Chazapis (SV9OAN) on 25/2/2018.
// Copyright © 2016 Jean-Luc Deltombe (LX3JL). All rights reserved.
//
// ----------------------------------------------------------------------------
// This file is part of xlxd.
//
// xlxd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// xlxd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef cdextrapeer_h
#define cdextrapeer_h
#include "cpeer.h"
#include "cdextraclient.h"
////////////////////////////////////////////////////////////////////////////////////////
// define
////////////////////////////////////////////////////////////////////////////////////////
// class
class CDextraPeer : public CPeer
{
public:
// constructors
CDextraPeer();
CDextraPeer(const CCallsign &, const CIp &, const char *, const CVersion &);
CDextraPeer(const CDextraPeer &);
// destructor
~CDextraPeer();
// status
bool IsAlive(void) const;
// identity
int GetProtocol(void) const { return PROTOCOL_DEXTRA; }
const char *GetProtocolName(void) const { return "DExtra"; }
// revision helper
static int GetProtocolRevision(const CVersion &);
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cdextrapeer_h */

@ -24,6 +24,7 @@
#include "main.h" #include "main.h"
#include <string.h> #include <string.h>
#include "cdextrapeer.h"
#include "cdextraclient.h" #include "cdextraclient.h"
#include "cdextraprotocol.h" #include "cdextraprotocol.h"
#include "creflector.h" #include "creflector.h"
@ -52,6 +53,7 @@ bool CDextraProtocol::Init(void)
// update time // update time
m_LastKeepaliveTime.Now(); m_LastKeepaliveTime.Now();
m_LastPeersLinkTime.Now();
// done // done
return ok; return ok;
@ -114,6 +116,29 @@ void CDextraProtocol::Task(void)
{ {
// valid module ? // valid module ?
if ( g_Reflector.IsValidModule(ToLinkModule) ) if ( g_Reflector.IsValidModule(ToLinkModule) )
{
// is this an ack for a link request?
CPeerCallsignList *list = g_GateKeeper.GetPeerList();
CCallsignListItem *item = list->FindListItem(Callsign);
if ( item != NULL && Callsign.GetModule() == item->GetModules()[1] && ToLinkModule == item->GetModules()[0] )
{
std::cout << "DExtra ack packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl;
// already connected ?
CPeers *peers = g_Reflector.GetPeers();
if ( peers->FindPeer(Callsign, Ip, PROTOCOL_DEXTRA) == NULL )
{
// create the new peer
// this also create one client per module
CPeer *peer = new CDextraPeer(Callsign, Ip, std::string(1, ToLinkModule).c_str(), CVersion(2, 0, 0));
// append the peer to reflector peer list
// this also add all new clients to reflector client list
peers->AddPeer(peer);
}
g_Reflector.ReleasePeers();
}
else
{ {
// acknowledge the request // acknowledge the request
EncodeConnectAckPacket(&Buffer, ProtRev); EncodeConnectAckPacket(&Buffer, ProtRev);
@ -126,6 +151,8 @@ void CDextraProtocol::Task(void)
g_Reflector.GetClients()->AddClient(client); g_Reflector.GetClients()->AddClient(client);
g_Reflector.ReleaseClients(); g_Reflector.ReleaseClients();
} }
g_GateKeeper.ReleasePeerList();
}
else else
{ {
std::cout << "DExtra node " << Callsign << " connect attempt on non-existing module" << std::endl; std::cout << "DExtra node " << Callsign << " connect attempt on non-existing module" << std::endl;
@ -193,15 +220,25 @@ void CDextraProtocol::Task(void)
// handle queue from reflector // handle queue from reflector
HandleQueue(); HandleQueue();
// keep client alive // keep alive
if ( m_LastKeepaliveTime.DurationSinceNow() > DEXTRA_KEEPALIVE_PERIOD ) if ( m_LastKeepaliveTime.DurationSinceNow() > DEXTRA_KEEPALIVE_PERIOD )
{ {
// // handle keep alives
HandleKeepalives(); HandleKeepalives();
// update time // update time
m_LastKeepaliveTime.Now(); m_LastKeepaliveTime.Now();
} }
// peer connections
if ( m_LastPeersLinkTime.DurationSinceNow() > DEXTRA_RECONNECT_PERIOD )
{
// handle remote peers connections
HandlePeerLinks();
// update time
m_LastPeersLinkTime.Now();
}
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -275,19 +312,110 @@ void CDextraProtocol::HandleKeepalives(void)
} }
// otherwise check if still with us // otherwise check if still with us
else if ( !client->IsAlive() ) else if ( !client->IsAlive() )
{
CPeers *peers = g_Reflector.GetPeers();
CPeer *peer = peers->FindPeer(client->GetCallsign(), client->GetIp(), PROTOCOL_DEXTRA);
if ( peer != NULL && peer->GetReflectorModules()[0] == client->GetReflectorModule() )
{
// no, but this is a peer client, so it will be handled below
}
else
{ {
// no, disconnect // no, disconnect
CBuffer disconnect; CBuffer disconnect;
EncodeDisconnectPacket(&disconnect); EncodeDisconnectPacket(&disconnect, client->GetReflectorModule());
m_Socket.Send(disconnect, client->GetIp()); m_Socket.Send(disconnect, client->GetIp());
// remove it // remove it
std::cout << "DExtra client " << client->GetCallsign() << " keepalive timeout" << std::endl; std::cout << "DExtra client " << client->GetCallsign() << " keepalive timeout" << std::endl;
clients->RemoveClient(client); clients->RemoveClient(client);
} }
g_Reflector.ReleasePeers();
}
} }
g_Reflector.ReleaseClients(); g_Reflector.ReleaseClients();
// iterate on peers
CPeers *peers = g_Reflector.GetPeers();
index = -1;
CPeer *peer = NULL;
while ( (peer = peers->FindNextPeer(PROTOCOL_DEXTRA, &index)) != NULL )
{
// keepalives are sent between clients
// some client busy or still with us ?
if ( !peer->IsAMaster() && !peer->IsAlive() )
{
// no, disconnect all clients
CBuffer disconnect;
EncodeDisconnectPacket(&disconnect, peer->GetReflectorModules()[0]);
CClients *clients = g_Reflector.GetClients();
for ( int i = 0; i < peer->GetNbClients(); i++ )
{
m_Socket.Send(disconnect, peer->GetClient(i)->GetIp());
}
g_Reflector.ReleaseClients();
// remove it
std::cout << "DExtra peer " << peer->GetCallsign() << " keepalive timeout" << std::endl;
peers->RemovePeer(peer);
}
}
g_Reflector.ReleasePeers();
}
////////////////////////////////////////////////////////////////////////////////////////
// Peers helpers
void CDextraProtocol::HandlePeerLinks(void)
{
CBuffer buffer;
// get the list of peers
CPeerCallsignList *list = g_GateKeeper.GetPeerList();
CPeers *peers = g_Reflector.GetPeers();
// check if all our connected peers are still listed by gatekeeper
// if not, disconnect
int index = -1;
CPeer *peer = NULL;
while ( (peer = peers->FindNextPeer(PROTOCOL_DEXTRA, &index)) != NULL )
{
if ( list->FindListItem(peer->GetCallsign()) == NULL )
{
// send disconnect packet
EncodeDisconnectPacket(&buffer, peer->GetReflectorModules()[0]);
m_Socket.Send(buffer, peer->GetIp());
std::cout << "Sending disconnect packet to XRF peer " << peer->GetCallsign() << std::endl;
// remove client
peers->RemovePeer(peer);
}
}
// check if all ours peers listed by gatekeeper are connected
// if not, connect or reconnect
for ( int i = 0; i < list->size(); i++ )
{
CCallsignListItem *item = &((list->data())[i]);
if ( !item->GetCallsign().HasSameCallsignWithWildcard(CCallsign("XRF*")) )
continue;
if ( strlen(item->GetModules()) != 2 )
continue;
if ( peers->FindPeer(item->GetCallsign(), PROTOCOL_DEXTRA) == NULL )
{
// resolve again peer's IP in case it's a dynamic IP
item->ResolveIp();
// send connect packet to re-initiate peer link
EncodeConnectPacket(&buffer, item->GetModules());
m_Socket.Send(buffer, item->GetIp(), DEXTRA_PORT);
std::cout << "Sending connect packet to XRF peer " << item->GetCallsign() << " @ " << item->GetIp() << " for module " << item->GetModules()[1] << " (module " << item->GetModules()[0] << ")" << std::endl;
}
}
// done
g_Reflector.ReleasePeers();
g_GateKeeper.ReleasePeerList();
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -474,6 +602,16 @@ void CDextraProtocol::EncodeKeepAlivePacket(CBuffer *Buffer)
Buffer->Set(GetReflectorCallsign()); Buffer->Set(GetReflectorCallsign());
} }
void CDextraProtocol::EncodeConnectPacket(CBuffer *Buffer, const char *Modules)
{
uint8 lm = (uint8)Modules[0];
uint8 rm = (uint8)Modules[1];
Buffer->Set((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN);
Buffer->Append(lm);
Buffer->Append(rm);
Buffer->Append((uint8)0);
}
void CDextraProtocol::EncodeConnectAckPacket(CBuffer *Buffer, int ProtRev) void CDextraProtocol::EncodeConnectAckPacket(CBuffer *Buffer, int ProtRev)
{ {
// is it for a XRF or repeater // is it for a XRF or repeater
@ -504,10 +642,12 @@ void CDextraProtocol::EncodeConnectNackPacket(CBuffer *Buffer)
Buffer->Append(tag, sizeof(tag)); Buffer->Append(tag, sizeof(tag));
} }
void CDextraProtocol::EncodeDisconnectPacket(CBuffer *Buffer) void CDextraProtocol::EncodeDisconnectPacket(CBuffer *Buffer, char Module)
{ {
uint8 tag[] = { ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',0 }; uint8 tag[] = { ' ',0 };
Buffer->Set(tag, sizeof(tag)); Buffer->Set((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN);
Buffer->Append((uint8)Module);
Buffer->Append(tag, sizeof(tag));
} }
void CDextraProtocol::EncodeDisconnectedPacket(CBuffer *Buffer) void CDextraProtocol::EncodeDisconnectedPacket(CBuffer *Buffer)

@ -75,6 +75,7 @@ protected:
void HandleQueue(void); void HandleQueue(void);
// keepalive helpers // keepalive helpers
void HandlePeerLinks(void);
void HandleKeepalives(void); void HandleKeepalives(void);
// stream helpers // stream helpers
@ -90,9 +91,10 @@ protected:
// packet encoding helpers // packet encoding helpers
void EncodeKeepAlivePacket(CBuffer *); void EncodeKeepAlivePacket(CBuffer *);
void EncodeConnectPacket(CBuffer *, const char *);
void EncodeConnectAckPacket(CBuffer *, int); void EncodeConnectAckPacket(CBuffer *, int);
void EncodeConnectNackPacket(CBuffer *); void EncodeConnectNackPacket(CBuffer *);
void EncodeDisconnectPacket(CBuffer *); void EncodeDisconnectPacket(CBuffer *, char);
void EncodeDisconnectedPacket(CBuffer *); void EncodeDisconnectedPacket(CBuffer *);
bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const;
bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const; bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const;
@ -101,6 +103,7 @@ protected:
protected: protected:
// time // time
CTimePoint m_LastKeepaliveTime; CTimePoint m_LastKeepaliveTime;
CTimePoint m_LastPeersLinkTime;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -40,7 +40,7 @@ CPeer::CPeer()
m_LastHeardTime = std::time(NULL); m_LastHeardTime = std::time(NULL);
} }
CPeer::CPeer(const CCallsign &callsign, const CIp &ip, char *modules, const CVersion &version) CPeer::CPeer(const CCallsign &callsign, const CIp &ip, const char *modules, const CVersion &version)
{ {
m_Callsign = callsign; m_Callsign = callsign;
m_Ip = ip; m_Ip = ip;

@ -42,7 +42,7 @@ class CPeer
public: public:
// constructors // constructors
CPeer(); CPeer();
CPeer(const CCallsign &, const CIp &, char *, const CVersion &); CPeer(const CCallsign &, const CIp &, const char *, const CVersion &);
CPeer(const CPeer &); CPeer(const CPeer &);
// destructor // destructor
@ -54,7 +54,7 @@ public:
// get // get
const CCallsign &GetCallsign(void) const { return m_Callsign; } const CCallsign &GetCallsign(void) const { return m_Callsign; }
const CIp &GetIp(void) const { return m_Ip; } const CIp &GetIp(void) const { return m_Ip; }
char *GetModulesModules(void) { return m_ReflectorModules; } char *GetReflectorModules(void) { return m_ReflectorModules; }
// set // set

@ -106,7 +106,7 @@ void CPeers::RemovePeer(CPeer *peer)
bool found = false; bool found = false;
for ( int i = 0; (i < m_Peers.size()) && !found; i++ ) for ( int i = 0; (i < m_Peers.size()) && !found; i++ )
{ {
// compare objetc pointers // compare object pointers
if ( (m_Peers[i]) == peer ) if ( (m_Peers[i]) == peer )
{ {
// found it ! // found it !

@ -37,7 +37,7 @@ CXlxPeer::CXlxPeer()
{ {
} }
CXlxPeer::CXlxPeer(const CCallsign &callsign, const CIp &ip, char *modules, const CVersion &version) CXlxPeer::CXlxPeer(const CCallsign &callsign, const CIp &ip, const char *modules, const CVersion &version)
: CPeer(callsign, ip, modules, version) : CPeer(callsign, ip, modules, version)
{ {
// get protocol revision // get protocol revision

@ -40,7 +40,7 @@ class CXlxPeer : public CPeer
public: public:
// constructors // constructors
CXlxPeer(); CXlxPeer();
CXlxPeer(const CCallsign &, const CIp &, char *, const CVersion &); CXlxPeer(const CCallsign &, const CIp &, const char *, const CVersion &);
CXlxPeer(const CXlxPeer &); CXlxPeer(const CXlxPeer &);
// destructor // destructor

@ -384,6 +384,8 @@ void CXlxProtocol::HandlePeerLinks(void)
for ( int i = 0; i < list->size(); i++ ) for ( int i = 0; i < list->size(); i++ )
{ {
CCallsignListItem *item = &((list->data())[i]); CCallsignListItem *item = &((list->data())[i]);
if ( item->GetCallsign().HasSameCallsignWithWildcard(CCallsign("XRF*")) )
continue;
if ( peers->FindPeer(item->GetCallsign(), PROTOCOL_XLX) == NULL ) if ( peers->FindPeer(item->GetCallsign(), PROTOCOL_XLX) == NULL )
{ {
// resolve again peer's IP in case it's a dynamic IP // resolve again peer's IP in case it's a dynamic IP

@ -56,7 +56,7 @@ protected:
// queue helper // queue helper
void HandleQueue(void); void HandleQueue(void);
// keepalive helper // keepalive helpers
void HandlePeerLinks(void); void HandlePeerLinks(void);
void HandleKeepalives(void); void HandleKeepalives(void);

@ -85,6 +85,7 @@
#define DEXTRA_PORT 30001 // UDP port #define DEXTRA_PORT 30001 // UDP port
#define DEXTRA_KEEPALIVE_PERIOD 3 // in seconds #define DEXTRA_KEEPALIVE_PERIOD 3 // in seconds
#define DEXTRA_KEEPALIVE_TIMEOUT (DEXTRA_KEEPALIVE_PERIOD*10) // in seconds #define DEXTRA_KEEPALIVE_TIMEOUT (DEXTRA_KEEPALIVE_PERIOD*10) // in seconds
#define DEXTRA_RECONNECT_PERIOD 5 // in seconds
// DPlus // DPlus
#define DPLUS_PORT 20001 // UDP port #define DPLUS_PORT 20001 // UDP port

Loading…
Cancel
Save

Powered by TurnKey Linux.