ambed single stack

pull/1/head
Tom Early 6 years ago
parent 004cea67a3
commit 1c9ee1b8c1

1
.gitignore vendored

@ -3,5 +3,4 @@
.vscode .vscode
xlxd xlxd
xrfd xrfd
ambed
main.h main.h

@ -0,0 +1,50 @@
#copyright(C) 2020 by Thomas A. Early, N7TAE
# If you are going to change this path, you will
# need to update the systemd service script
BINDIR=/usr/local/bin
GCC=g++
# uncomment the next line to enable gdb debugging help
#DEBUG=true
CFLAGS=-W -MMD -MD -std=c++11
ifdef DEBUG
CFLAGS+=-ggdb3
endif
LDFLAGS=-pthread
SRCS=cagc.cpp cbuffer.cpp cfirfilter.cpp cip.cpp csignalprocessor.cpp cusb3003hrinterface.cpp cvocodecchannel.cpp cvoicepacket.cpp cambepacket.cpp ccallsign.cpp cfixedgain.cpp cpacket.cpp cstream.cpp cusb3000interface.cpp cusb3003interface.cpp cvocodecinterface.cpp main.cpp cambeserver.cpp ccontroller.cpp cftdidevicedescr.cpp cpacketqueue.cpp ctimepoint.cpp cusb3003df2etinterface.cpp cusb3xxxinterface.cpp cvocodecs.cpp cudpsocket.cpp
OBJS=$(SRCS:.cpp=.o)
DEPS=$(SRCS:.cpp=.d)
EXE=ambed
$(EXE) : $(OBJS)
$(GCC) $(LDFLAGS) $(OBJS) -lftd2xx -Wl,-rpath,/usr/local/lib -o $@
%.o : %.cpp
$(GCC) $(CFLAGS) -c $< -o $@
clean :
$(RM) $(EXE) *.o *.d
-include $(DEPS)
# The install and uninstall targets need to be run by root
install : $(EXE) $(EXE).service
cp $(EXE) $(BINDIR)
cp $(EXE).service /etc/systemd/system/
systemctl enable ambed
systemctl daemon-reload
systemctl start ambed
uninstall :
systemctl stop ambed
systemctl disable ambed
systemctl daemon-reload
rm -f /etc/systemd/system/ambed.service
rm -f $(BINDIR)/ambed
systemctl daemon-reload

@ -4,6 +4,7 @@
// //
// Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017. // Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. // Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
// Copyright © 2020 Thomas A. Early, N7TAE
// //
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// This file is part of ambed. // This file is part of ambed.
@ -29,97 +30,30 @@
#include "cambeserver.h" #include "cambeserver.h"
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// globals
CAmbeServer g_AmbeServer; CAmbeServer g_AmbeServer;
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CAmbeServer::CAmbeServer()
{
m_bStopThreads = false;
m_pThread = NULL;
#ifdef DEBUG_DUMPFILE
m_DebugFile.open("/Users/jeanluc/Desktop/ambed.txt");
#endif
}
////////////////////////////////////////////////////////////////////////////////////////
// destructor
CAmbeServer::~CAmbeServer()
{
m_bStopThreads = true;
if ( m_pThread != NULL )
{
m_pThread->join();
delete m_pThread;
}
#ifdef DEBUG_DUMPFILE
m_DebugFile.close();
#endif
}
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// operation // operation
bool CAmbeServer::Start(void) bool CAmbeServer::Start(void)
{ {
bool ok = true;
// init interfaces & controller // init interfaces & controller
std::cout << "Initializing vocodecs:" << std::endl; std::cout << "Initializing vocodecs:" << std::endl;
ok &= g_Vocodecs.Init(); if (! g_Vocodecs.Init())
std::cout << std::endl; return false;
std::cout << "Initializing controller" << std::endl;
ok &= m_Controller.Init();
std::cout << std::endl;
// if ok, start threads std::cout << "Initializing controller" << std::endl;
if ( ok ) if (! m_Controller.Init())
{ return false;
//
m_pThread = new std::thread(CAmbeServer::Thread, this);
}
// done return true;
return ok;
} }
void CAmbeServer::Stop(void) void CAmbeServer::Stop(void)
{ {
// stop controller // stop controller
m_Controller.Close(); m_Controller.Close();
// stop & delete all threads
m_bStopThreads = true;
// stop & delete report threads
if ( m_pThread != NULL )
{
m_pThread->join();
delete m_pThread;
m_pThread = NULL;
}
}
////////////////////////////////////////////////////////////////////////////////////////
// thread
void CAmbeServer::Thread(CAmbeServer *This)
{
while ( !This->m_bStopThreads )
{
This->Task();
}
}
////////////////////////////////////////////////////////////////////////////////////////
// task
void CAmbeServer::Task(void)
{
// and wait a bit
CTimePoint::TaskSleepFor(10000);
} }

@ -4,6 +4,7 @@
// //
// Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017. // Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. // Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
// Copyright © 2020 Thomas A. Early, N7TAE
// //
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// This file is part of ambed. // This file is part of ambed.
@ -33,11 +34,6 @@
class CAmbeServer class CAmbeServer
{ {
public: public:
// constructors
CAmbeServer();
// destructor
virtual ~CAmbeServer();
// operation // operation
bool Start(void); bool Start(void);
@ -48,24 +44,15 @@ public:
void Task(void); void Task(void);
// get // get
const CIp &GetListenIp(void) const { return m_Controller.GetListenIp(); } const char *GetListenIp(void) const { return m_Controller.GetListenIp(); }
// set // set
void SetListenIp(const CIp &ip) { m_Controller.SetListenIp(ip); } void SetListenIp(const char *ip) { m_Controller.SetListenIp(ip); }
// operator
//bool operator ==(const CIp &) const;
//operator const char *() const;
protected: protected:
// objects // objects
CController m_Controller; CController m_Controller;
// threads
bool m_bStopThreads;
std::thread *m_pThread;
public: public:
#ifdef DEBUG_DUMPFILE #ifdef DEBUG_DUMPFILE
std::ofstream m_DebugFile; std::ofstream m_DebugFile;

@ -1,200 +0,0 @@
//
// cbuffer.cpp
// xlxd
//
// Created by Jean-Luc Deltombe (LX3JL) on 02/11/2015.
// Copyright © 2015 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 "cbuffer.h"
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CBuffer::CBuffer(uint8 *buffer, int len)
{
resize(len);
::memcpy(data(), buffer, len);
}
////////////////////////////////////////////////////////////////////////////////////////
// set
void CBuffer::Set(uint8 *buffer, int len)
{
resize(len);
::memcpy(data(), buffer, len);
}
void CBuffer::Set(const char *sz)
{
resize(::strlen(sz)+1);
::strcpy((char *)data(), sz);
}
void CBuffer::Append(uint8 *buffer, int len)
{
int n = (int)size();
resize(n+len);
::memcpy(&(data()[n]), buffer, len);
}
void CBuffer::Append(uint8 ui, int len)
{
int n = (int)size();
resize(n+len);
::memset(&(data()[n]), ui, len);
}
void CBuffer::Append(uint8 ui)
{
int n = (int)size();
resize(n+sizeof(uint8));
::memcpy(&(data()[n]), &ui, sizeof(uint8));
}
void CBuffer::Append(uint16 ui)
{
int n = (int)size();
resize(n+sizeof(uint16));
::memcpy(&(data()[n]), &ui, sizeof(uint16));
}
void CBuffer::Append(uint32 ui)
{
int n = (int)size();
resize(n+sizeof(uint32));
::memcpy(&(data()[n]), &ui, sizeof(uint32));
}
void CBuffer::Append(const char *sz)
{
Append((uint8 *)sz, (int)strlen(sz));
Append((uint8)0x00);
}
void CBuffer::ReplaceAt(int i, uint8 ui)
{
if ( size() < (i+sizeof(uint8)) )
{
resize(i+sizeof(uint8));
}
*(uint8 *)(&(data()[i])) = ui;
}
void CBuffer::ReplaceAt(int i, uint16 ui)
{
if ( size() < (i+sizeof(uint16)) )
{
resize(i+sizeof(uint16));
}
*(uint16 *)(&(data()[i])) = ui;
}
void CBuffer::ReplaceAt(int i, uint32 ui)
{
if ( size() < (i+sizeof(uint32)) )
{
resize(i+sizeof(uint32));
}
*(uint32 *)(&(data()[i])) = ui;
}
void CBuffer::ReplaceAt(int i, const uint8 *ptr, int len)
{
if ( size() < (i+len) )
{
resize(i+len);
}
::memcpy(&(data()[i]), ptr, len);
}
////////////////////////////////////////////////////////////////////////////////////////
// operation
int CBuffer::Compare(uint8 *buffer, int len) const
{
int result = -1;
if ( size() >= len )
{
result = ::memcmp(data(), buffer, len);
}
return result;
}
int CBuffer::Compare(uint8 *buffer, int off, int len) const
{
int result = -1;
if ( size() >= (off+len) )
{
result = ::memcmp(&(data()[off]), buffer, len);
}
return result;
}
////////////////////////////////////////////////////////////////////////////////////////
// operator
bool CBuffer::operator ==(const CBuffer &Buffer) const
{
if ( size() == Buffer.size() )
{
return (::memcmp((const char *)data(), (const char *)Buffer.data(), size()) == 0);
}
return false;
}
bool CBuffer::operator ==(const char *sz) const
{
if ( size() == ::strlen(sz) )
{
return (::memcmp((const char *)data(), sz, size()) == 0);
}
return false;
}
CBuffer::operator const char *() const
{
return (const char *)data();
}
////////////////////////////////////////////////////////////////////////////////////////
// debug
void CBuffer::DebugDump(std::ofstream &debugout)
{
for ( int i = 0; i < size(); i++ )
{
char sz[16];
sprintf(sz, "%02X", data()[i]);
debugout << sz;
if ( i == size()-1 )
{
debugout << std::endl;
}
else
{
debugout << ',';
}
}
}

@ -0,0 +1 @@
../src/cbuffer.cpp

@ -1,68 +0,0 @@
//
// cbuffer.h
// xlxd
//
// Created by Jean-Luc Deltombe (LX3JL) on 02/11/2015.
// Copyright © 2015 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 cbuffer_h
#define cbuffer_h
////////////////////////////////////////////////////////////////////////////////////////
class CBuffer : public std::vector<uint8>
{
public:
// constructor
CBuffer() {};
CBuffer(uint8 *, int);
// destructor
virtual ~CBuffer() {};
// set
void Set(uint8 *, int);
void Set(const char *);
void Append(uint8 *, int);
void Append(uint8, int);
void Append(uint8);
void Append(uint16);
void Append(uint32);
void Append(const char *);
void ReplaceAt(int, uint8);
void ReplaceAt(int, uint16);
void ReplaceAt(int, uint32);
void ReplaceAt(int, const uint8 *, int);
// operation
int Compare(uint8 *, int) const;
int Compare(uint8 *, int, int) const;
// operator
bool operator ==(const CBuffer &) const;
bool operator ==(const char *) const;
operator const char *() const;
// debug
void DebugDump(std::ofstream &);
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cbuffer_h */

@ -0,0 +1 @@
../src/cbuffer.h

@ -4,6 +4,7 @@
// //
// Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017. // Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. // Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
// Copyright © 2020 Thomas A. Early, N7TAE
// //
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// This file is part of ambed. // This file is part of ambed.
@ -35,7 +36,6 @@ CController::CController()
{ {
m_bStopThread = false; m_bStopThread = false;
m_pThread = NULL; m_pThread = NULL;
m_Ip = CIp("127.0.0.1");
m_uiLastStreamId = 0; m_uiLastStreamId = 0;
} }
@ -50,9 +50,9 @@ CController::~CController()
// close all streams // close all streams
m_Mutex.lock(); m_Mutex.lock();
{ {
for ( int i = 0; i < m_Streams.size(); i++ ) for ( auto it=m_Streams.begin(); it!=m_Streams.end(); it++ )
{ {
delete m_Streams[i]; delete *it;
} }
m_Streams.clear(); m_Streams.clear();
@ -72,24 +72,23 @@ CController::~CController()
bool CController::Init(void) bool CController::Init(void)
{ {
bool ok;
// reset stop flag // reset stop flag
m_bStopThread = false; m_bStopThread = false;
// create our socket // create our socket
ok = m_Socket.Open(m_Ip, TRANSCODER_PORT); CIp ip(strchr(straddress, ':') ? AF_INET6 : AF_INET, TRANSCODER_PORT, straddress);
if ( ok ) if (! ip.IsSet()) {
{ std::cerr << "IP initialization failed for " << straddress << std::endl;
// start thread; return false;
m_pThread = new std::thread(CController::Thread, this);
} }
else if (! m_Socket.Open(ip))
{ {
std::cout << "Error opening socket on port UDP" << TRANSCODER_PORT << " on ip " << m_Ip << std::endl; std::cout << "Error opening socket on port UDP" << TRANSCODER_PORT << " on ip " << ip.GetAddress() << std::endl;
return false;
} }
// start thread;
m_pThread = new std::thread(CController::Thread, this);
// done
return true; return true;
} }
@ -129,7 +128,7 @@ void CController::Task(void)
CStream *Stream; CStream *Stream;
// anything coming in from codec client ? // anything coming in from codec client ?
if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 ) if ( m_Socket.Receive(Buffer, Ip, 20) != -1 )
{ {
// crack packet // crack packet
if ( IsValidOpenstreamPacket(Buffer, &Callsign, &CodecIn, &CodecOut) ) if ( IsValidOpenstreamPacket(Buffer, &Callsign, &CodecIn, &CodecOut) )
@ -166,37 +165,23 @@ void CController::Task(void)
} }
} }
// HandleTimout/keepalive
bool timeout;
do
{
// init loop stuffs
timeout = false;
CStream *stream = NULL;
// any inactive streams? // any inactive streams?
Lock(); Lock();
for ( auto it=m_Streams.begin(); it!=m_Streams.end(); )
{ {
for ( int i = 0; (i < m_Streams.size()) && !timeout; i++ ) if ( !(*it)->IsActive() )
{ {
if ( !(m_Streams[i]->IsActive()) ) std::cout << "Stream " << (*it)->GetId() << " activity timeout " << std::endl;
{ (*it)->Close();
timeout = true; delete *it;
stream = m_Streams[i]; it = m_Streams.erase(it);
std::cout << "Stream " << (int)m_Streams[i]->GetId() << " activity timeout " << std::endl;
} }
else
{
it++;
} }
} }
Unlock(); Unlock();
// if any streams timeout, close it
// this cannot be done in above loop as it suppress it from array
if ( timeout )
{
CloseStream(stream);
}
} while (timeout);
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -231,22 +216,19 @@ CStream *CController::OpenStream(const CCallsign &Callsign, const CIp &Ip, uint8
void CController::CloseStream(CStream *stream) void CController::CloseStream(CStream *stream)
{ {
Lock(); Lock();
{
// look for the stream // look for the stream
bool found = false; for ( auto it=m_Streams.begin(); it!=m_Streams.end(); it++ )
for ( int i = 0; (i < m_Streams.size()) && !found; i++ )
{ {
// compare object pointers // compare object pointers
if ( (m_Streams[i]) == stream ) if ( *it == stream )
{ {
// close it // close it
m_Streams[i]->Close(); (*it)->Close();
// remove it // remove it
//std::cout << "Stream " << m_Streams[i]->GetId() << " removed" << std::endl; //std::cout << "Stream " << m_Streams[i]->GetId() << " removed" << std::endl;
delete m_Streams[i]; delete *it;
m_Streams.erase(m_Streams.begin()+i); m_Streams.erase(it);
found = true; break;
}
} }
} }
Unlock(); Unlock();
@ -255,22 +237,19 @@ void CController::CloseStream(CStream *stream)
void CController::CloseStream(uint16 StreamId) void CController::CloseStream(uint16 StreamId)
{ {
Lock(); Lock();
{
// look for the stream // look for the stream
bool found = false; for ( auto it=m_Streams.begin(); it!=m_Streams.end(); it++ )
for ( int i = 0; (i < m_Streams.size()) && !found; i++ )
{ {
// compare object pointers // compare object pointers
if ( (m_Streams[i]->GetId()) == StreamId ) if ( (*it)->GetId() == StreamId )
{ {
// close it // close it
m_Streams[i]->Close(); (*it)->Close();
// remove it // remove it
//std::cout << "Stream " << m_Streams[i]->GetId() << " removed" << std::endl; //std::cout << "Stream " << m_Streams[i]->GetId() << " removed" << std::endl;
delete m_Streams[i]; delete *it;
m_Streams.erase(m_Streams.begin()+i); m_Streams.erase(it);
found = true; break;
}
} }
} }
Unlock(); Unlock();
@ -370,4 +349,3 @@ bool CController::IsValidCodecOut(uint8 codec)
{ {
return ((codec == CODEC_AMBEPLUS) || (codec == CODEC_AMBE2PLUS) ); return ((codec == CODEC_AMBEPLUS) || (codec == CODEC_AMBE2PLUS) );
} }

@ -4,6 +4,7 @@
// //
// Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017. // Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. // Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
// Copyright © 2020 Thomas A. Early, N7TAE
// //
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// This file is part of ambed. // This file is part of ambed.
@ -49,10 +50,10 @@ public:
void Unlock(void) { m_Mutex.unlock(); } void Unlock(void) { m_Mutex.unlock(); }
// get // get
const CIp &GetListenIp(void) const { return (const CIp &)m_Ip; } const CIp &GetListenIp(void) const { return straddress; }
// set // set
void SetListenIp(const CIp &ip) { m_Ip = ip; } void SetListenIp(const char *str) { straddress = str; }
// streams management // streams management
CStream *OpenStream(const CCallsign &, const CIp &, uint8, uint8); CStream *OpenStream(const CCallsign &, const CIp &, uint8, uint8);
@ -80,13 +81,13 @@ protected:
protected: protected:
// control socket // control socket
CIp m_Ip; const char *straddress;
CUdpSocket m_Socket; CUdpSocket m_Socket;
// streams // streams
uint16 m_uiLastStreamId; uint16 m_uiLastStreamId;
std::mutex m_Mutex; std::mutex m_Mutex;
std::vector<CStream *> m_Streams; std::list<CStream *> m_Streams;
// thread // thread
bool m_bStopThread; bool m_bStopThread;

@ -1,91 +0,0 @@
//
// cip.cpp
// xlxd
//
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
// Copyright © 2015 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 "cip.h"
#include <netdb.h>
////////////////////////////////////////////////////////////////////////////////////////
// constructors
CIp::CIp()
{
::memset(&m_Addr, 0, sizeof(m_Addr));
m_Addr.sin_family = AF_INET;
}
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 )
{
// 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;
}
}
}
CIp::CIp(const struct sockaddr_in *sa)
{
::memcpy(&m_Addr, sa, sizeof(m_Addr));
}
CIp::CIp(const CIp &ip)
{
::memcpy(&m_Addr, &ip.m_Addr, sizeof(m_Addr));
}
////////////////////////////////////////////////////////////////////////////////////////
// set
void CIp::SetSockAddr(struct sockaddr_in *sa)
{
::memcpy(&m_Addr, sa, sizeof(m_Addr));
}
////////////////////////////////////////////////////////////////////////////////////////
// operator
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)) ;
}
CIp::operator const char *() const
{
return ::inet_ntoa(m_Addr.sin_addr);
}

@ -0,0 +1 @@
../src/cip.cpp

@ -1,59 +0,0 @@
//
// cip.h
// xlxd
//
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
// Copyright © 2015 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 cip_h
#define cip_h
////////////////////////////////////////////////////////////////////////////////////////
// class
class CIp
{
public:
// constructors
CIp();
//CIp(uint8, uint8, uint8, uint8);
CIp(const struct sockaddr_in *);
CIp(const char *);
CIp(const CIp &);
// destructor
virtual ~CIp() {};
// sockaddr
void SetSockAddr(struct sockaddr_in *);
struct sockaddr_in *GetSockAddr(void) { return &m_Addr; }
// operator
bool operator ==(const CIp &) const;
operator const char *() const;
protected:
// data
struct sockaddr_in m_Addr;
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cip_h */

@ -0,0 +1 @@
../src/cip.h

@ -4,6 +4,7 @@
// //
// Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017. // Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. // Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
// Copyright © 2020 Thomas A. Early, N7TAE
// //
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// This file is part of ambed. // This file is part of ambed.
@ -93,20 +94,33 @@ CStream::~CStream()
bool CStream::Init(uint16 uiPort) bool CStream::Init(uint16 uiPort)
{ {
bool ok;
// reset stop flag // reset stop flag
m_bStopThread = false; m_bStopThread = false;
// create our socket // create our socket
ok = m_Socket.Open(g_AmbeServer.GetListenIp(), uiPort); auto s = g_AmbeServer.GetListenIp();
if ( ok ) CIp ip(strchr(s, ':') ? AF_INET6 : AF_INET, uiPort, s);
if (! ip.IsSet())
{ {
// open the vocodecchannel std::cerr << "Could not initialize ip address " << s << std::endl;
ok &= ((m_VocodecChannel = g_Vocodecs.OpenChannel(m_uiCodecIn, m_uiCodecOut)) != NULL); return false;
}
if ( ok ) if (! m_Socket.Open(ip))
{ {
std::cout << "Error opening stream stream socket on " << ip << std::endl;
return false;
}
// open the vocodecchannel
m_VocodecChannel = g_Vocodecs.OpenChannel(m_uiCodecIn, m_uiCodecOut);
if (NULL == m_VocodecChannel)
{
std::cerr << "Could not open Vocodec Channel" << std::endl;
m_Socket.Close();
return false;
}
// store port // store port
m_uiPort = uiPort; m_uiPort = uiPort;
@ -118,19 +132,9 @@ bool CStream::Init(uint16 uiPort)
m_iTotalPackets = 0; m_iTotalPackets = 0;
m_iLostPackets = 0; m_iLostPackets = 0;
}
else
{
std::cout << "Error opening stream : no suitable channel available" << std::endl;
}
}
else
{
std::cout << "Error opening socket on port UDP" << uiPort << " on ip " << m_Ip << std::endl;
}
// done // done
return ok; return true;
} }
@ -181,7 +185,7 @@ void CStream::Task(void)
CPacketQueue *queue; CPacketQueue *queue;
// anything coming in from codec client ? // anything coming in from codec client ?
if ( m_Socket.Receive(&Buffer, &Ip, 1) != -1 ) if ( m_Socket.Receive(Buffer, Ip, 1) )
{ {
// crack packet // crack packet
if ( IsValidDvFramePacket(Buffer, &uiPid, Ambe) ) if ( IsValidDvFramePacket(Buffer, &uiPid, Ambe) )
@ -242,4 +246,3 @@ void CStream::EncodeDvFramePacket(CBuffer *Buffer, uint8 Pid, uint8 *Ambe)
Buffer->Append((uint8)Pid); Buffer->Append((uint8)Pid);
Buffer->Append(Ambe, 9); Buffer->Append(Ambe, 9);
} }

@ -1,172 +0,0 @@
//
// cudpsocket.cpp
// xlxd
//
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
// Copyright © 2015 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 "cudpsocket.h"
////////////////////////////////////////////////////////////////////////////////////////
// constructor
CUdpSocket::CUdpSocket()
{
m_Socket = -1;
}
////////////////////////////////////////////////////////////////////////////////////////
// destructor
CUdpSocket::~CUdpSocket()
{
if ( m_Socket != -1 )
{
Close();
}
}
////////////////////////////////////////////////////////////////////////////////////////
// open & close
bool CUdpSocket::Open(const CIp &ListenIp, uint16 uiPort)
{
bool open = false;
// create socket
m_Socket = socket(PF_INET,SOCK_DGRAM,0);
if ( m_Socket != -1 )
{
// 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(ListenIp);
if ( bind(m_Socket, (struct sockaddr *)&m_SocketAddr, sizeof(struct sockaddr_in)) == 0 )
{
fcntl(m_Socket, F_SETFL, O_NONBLOCK);
open = true;
}
else
{
close(m_Socket);
m_Socket = -1;
}
}
// done
return open;
}
void CUdpSocket::Close(void)
{
if ( m_Socket != -1 )
{
close(m_Socket);
m_Socket = -1;
}
}
////////////////////////////////////////////////////////////////////////////////////////
// read
int CUdpSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout)
{
struct sockaddr_in Sin;
fd_set FdSet;
unsigned int uiFromLen = sizeof(struct sockaddr_in);
int iRecvLen = -1;
struct timeval tv;
// socket valid ?
if ( m_Socket != -1 )
{
// 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);
// read
iRecvLen = (int)recvfrom(m_Socket,
(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);
}
}
// done
return iRecvLen;
}
////////////////////////////////////////////////////////////////////////////////////////
// write
int CUdpSocket::Send(const CBuffer &Buffer, const CIp &Ip)
{
CIp temp(Ip);
return (int)::sendto(m_Socket,
(void *)Buffer.data(), Buffer.size(),
0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in));
}
int CUdpSocket::Send(const char *Buffer, const CIp &Ip)
{
CIp temp(Ip);
return (int)::sendto(m_Socket,
(void *)Buffer, ::strlen(Buffer),
0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in));
}
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,
(void *)Buffer.data(), Buffer.size(),
0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in));
}
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,
(void *)Buffer, ::strlen(Buffer),
0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in));
}

@ -0,0 +1 @@
../src/cudpsocket.cpp

@ -1,78 +0,0 @@
//
// cudpsocket.h
// xlxd
//
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
// Copyright © 2015 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 cudpsocket_h
#define cudpsocket_h
#include <sys/types.h>
//#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include "cip.h"
#include "cbuffer.h"
////////////////////////////////////////////////////////////////////////////////////////
// define
#define UDP_BUFFER_LENMAX 1024
////////////////////////////////////////////////////////////////////////////////////////
// class
class CUdpSocket
{
public:
// constructor
CUdpSocket();
// destructor
~CUdpSocket();
// open & close
bool Open(const CIp &, uint16);
void Close(void);
int GetSocket(void) { return m_Socket; }
// read
int Receive(CBuffer *, CIp *, int);
// write
int Send(const CBuffer &, const CIp &);
int Send(const CBuffer &, const CIp &, uint16);
int Send(const char *, const CIp &);
int Send(const char *, const CIp &, uint16);
protected:
// data
int m_Socket;
struct sockaddr_in m_SocketAddr;
};
////////////////////////////////////////////////////////////////////////////////////////
#endif /* cudpsocket_h */

@ -0,0 +1 @@
../src/cudpsocket.h

@ -4,6 +4,7 @@
// //
// Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017. // Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017.
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. // Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
// Copyright © 2020 Thomas A. Early, N7TAE
// //
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// This file is part of ambed. // This file is part of ambed.
@ -26,64 +27,14 @@
#include "ctimepoint.h" #include "ctimepoint.h"
#include "cambeserver.h" #include "cambeserver.h"
#include "syslog.h"
#include <sys/stat.h> #include <sys/stat.h>
////////////////////////////////////////////////////////////////////////////////////////
// global objects
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// function declaration // function declaration
int main(int argc, const char * argv[]) int main(int argc, const char * argv[])
{ {
#ifdef RUN_AS_DAEMON
// redirect cout, cerr and clog to syslog
syslog::redirect cout_redir(std::cout);
syslog::redirect cerr_redir(std::cerr);
syslog::redirect clog_redir(std::clog);
//Fork the Parent Process
pid_t pid, sid;
pid = ::fork();
//pid = ::vfork();
if ( pid < 0 )
{
exit(EXIT_FAILURE);
}
// We got a good pid, Close the Parent Process
if (pid > 0)
{
exit(EXIT_SUCCESS);
}
// Change File Mask
::umask(0);
//Create a new Signature Id for our child
sid = ::setsid();
if (sid < 0)
{
exit(EXIT_FAILURE);
}
// Change Directory
// If we cant find the directory we exit with failure.
if ( (::chdir("/")) < 0)
{
exit(EXIT_FAILURE);
}
// Close Standard File Descriptors
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
#endif
// check arguments // check arguments
if ( argc != 2 ) if ( argc != 2 )
@ -94,38 +45,23 @@ int main(int argc, const char * argv[])
} }
// initialize ambeserver // initialize ambeserver
g_AmbeServer.SetListenIp(CIp(argv[1])); g_AmbeServer.SetListenIp(argv[1]);
// and let it run // and let it run
std::cout << "Starting AMBEd " << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_REVISION << std::endl << std::endl; std::cout << "Starting AMBEd " << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_REVISION << std::endl << std::endl;
if ( !g_AmbeServer.Start() ) if ( ! g_AmbeServer.Start() )
{ {
std::cout << "Error starting AMBEd" << std::endl; std::cout << "Error starting AMBEd" << std::endl;
exit(EXIT_FAILURE); return EXIT_FAILURE;
} }
std::cout << "AMBEd started and listening on " << g_AmbeServer.GetListenIp() << std::endl; std::cout << "AMBEd started and listening on " << g_AmbeServer.GetListenIp() << std::endl;
#ifdef RUN_AS_DAEMON pause(); // wait for any signal
// run forever
while ( true )
{
// sleep 60 seconds
CTimePoint::TaskSleepFor(60000);
}
#else
// wait any key
for (;;)
{
// sleep 60 seconds
CTimePoint::TaskSleepFor(60000);
//std::cin.get();
}
#endif
// and wait for end // and wait for end
g_AmbeServer.Stop(); g_AmbeServer.Stop();
std::cout << "AMBEd stopped" << std::endl; std::cout << "AMBEd stopped" << std::endl;
// done // done
exit(EXIT_SUCCESS); return EXIT_SUCCESS;
} }

@ -27,6 +27,7 @@
#include <vector> #include <vector>
#include <array> #include <array>
#include <list>
#include <map> #include <map>
#include <queue> #include <queue>
#include <chrono> #include <chrono>

@ -1,22 +0,0 @@
CC=g++
CFLAGS=-c -std=c++11 -pthread
LDFLAGS=-std=c++11 -pthread
SOURCES=$(wildcard *.cpp)
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=ambed
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -lftd2xx -Wl,-rpath,/usr/local/lib -o $@
.cpp.o:
$(CC) $(CFLAGS) $< -o $@
clean:
$(RM) $(EXECUTABLE) *.o
install:
mkdir -p /ambed
cp $(EXECUTABLE) /ambed/
cp ./run /ambed/

@ -1,6 +0,0 @@
#!/bin/bash
# start ambed server
sudo rmmod ftdi_sio
sudo rmmod usbserial
sudo /ambed/ambed 127.0.0.1 &

@ -1,96 +0,0 @@
/*************************************************************************
** Copyright (C) 2014 Jan Pedersen <jp@jp-embedded.com>
**
** This program 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.
**
** This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*************************************************************************/
#ifndef __syslog
#define __syslog
#include <iostream>
#include <streambuf>
#include <string>
namespace csyslog {
#include <syslog.h>
}
namespace syslog
{
struct level {
enum pri {
emerg = LOG_EMERG, // A panic condition
alert = LOG_ALERT, // A condition that should be corrected
critical= LOG_CRIT, // Critical condition, e.g, hard device error
error = LOG_ERR, // Errors
warning = LOG_WARNING, // Warning messages
notice = LOG_NOTICE, // Possibly be handled specially
info = LOG_INFO, // Informational
debug = LOG_DEBUG // For debugging program
};
};
class streambuf : public std::streambuf
{
std::string _buf;
int _level;
public:
streambuf() : _level(level::debug) { }
void level(int level) { _level = level; }
protected:
int sync()
{
if (_buf.size()) {
csyslog::syslog(_level, "%s", _buf.c_str());
_buf.erase();
}
return 0;
}
int_type overflow(int_type c)
{
if(c == traits_type::eof()) sync();
else _buf += static_cast<char>(c);
return c;
}
};
class ostream : public std::ostream
{
streambuf _logbuf;
public:
ostream() : std::ostream(&_logbuf) {}
ostream& operator<<(const level::pri lev) { _logbuf.level(lev); return *this; }
};
class redirect
{
ostream dst;
std::ostream &src;
std::streambuf * const sbuf;
public:
redirect(std::ostream & src) : src(src), sbuf(src.rdbuf(dst.rdbuf())) { dst << (&src == &std::cout ? level::info : level::error); }
~redirect() { src.rdbuf(sbuf); }
};
}
#endif

@ -25,7 +25,6 @@
#include <string.h> #include <string.h>
#include "main.h" #include "main.h"
#include "creflector.h"
#include "cudpsocket.h" #include "cudpsocket.h"

Loading…
Cancel
Save

Powered by TurnKey Linux.