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; std::cout << "Initializing controller" << std::endl;
ok &= m_Controller.Init(); if (! m_Controller.Init())
std::cout << std::endl; return false;
// if ok, start threads return true;
if ( ok )
{
//
m_pThread = new std::thread(CAmbeServer::Thread, this);
}
// done
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,39 +34,25 @@
class CAmbeServer class CAmbeServer
{ {
public: public:
// constructors
CAmbeServer();
// destructor
virtual ~CAmbeServer();
// operation // operation
bool Start(void); bool Start(void);
void Stop(void); void Stop(void);
// task // task
static void Thread(CAmbeServer *); static void Thread(CAmbeServer *);
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;
} }
@ -46,18 +46,18 @@ CController::~CController()
{ {
// close socket // close socket
m_Socket.Close(); m_Socket.Close();
// 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();
} }
m_Mutex.unlock(); m_Mutex.unlock();
m_bStopThread = true; m_bStopThread = true;
if ( m_pThread != NULL ) if ( m_pThread != NULL )
@ -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); }
} if (! m_Socket.Open(ip))
else
{ {
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;
// done m_pThread = new std::thread(CController::Thread, this);
return true; return true;
} }
@ -127,18 +126,18 @@ void CController::Task(void)
uint8 CodecOut; uint8 CodecOut;
uint16 StreamId; uint16 StreamId;
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) )
{ {
std::cout << "Stream Open from " << Callsign << std::endl; std::cout << "Stream Open from " << Callsign << std::endl;
// try create the stream // try create the stream
Stream = OpenStream(Callsign, Ip, CodecIn, CodecOut); Stream = OpenStream(Callsign, Ip, CodecIn, CodecOut);
// send back details // send back details
if ( Stream != NULL ) if ( Stream != NULL )
{ {
@ -154,8 +153,8 @@ void CController::Task(void)
{ {
// close the stream // close the stream
CloseStream(StreamId); CloseStream(StreamId);
std::cout << "Stream " << (int)StreamId << " closed" << std::endl; std::cout << "Stream " << (int)StreamId << " closed" << std::endl;
} }
else if ( IsValidKeepAlivePacket(Buffer, &Callsign) ) else if ( IsValidKeepAlivePacket(Buffer, &Callsign) )
{ {
@ -165,38 +164,24 @@ void CController::Task(void)
m_Socket.Send(Buffer, Ip); m_Socket.Send(Buffer, Ip);
} }
} }
// any inactive streams?
// HandleTimout/keepalive Lock();
bool timeout; for ( auto it=m_Streams.begin(); it!=m_Streams.end(); )
do {
{ if ( !(*it)->IsActive() )
// init loop stuffs {
timeout = false; std::cout << "Stream " << (*it)->GetId() << " activity timeout " << std::endl;
CStream *stream = NULL; (*it)->Close();
delete *it;
// any inactive streams? it = m_Streams.erase(it);
Lock(); }
{ else
for ( int i = 0; (i < m_Streams.size()) && !timeout; i++ ) {
{ it++;
if ( !(m_Streams[i]->IsActive()) ) }
{ }
timeout = true; Unlock();
stream = m_Streams[i];
std::cout << "Stream " << (int)m_Streams[i]->GetId() << " activity timeout " << std::endl;
}
}
}
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);
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -205,7 +190,7 @@ void CController::Task(void)
CStream *CController::OpenStream(const CCallsign &Callsign, const CIp &Ip, uint8 CodecIn, uint8 CodecOut) CStream *CController::OpenStream(const CCallsign &Callsign, const CIp &Ip, uint8 CodecIn, uint8 CodecOut)
{ {
CStream *stream = NULL; CStream *stream = NULL;
// create a new stream // create a new stream
m_uiLastStreamId = (m_uiLastStreamId + 1); m_uiLastStreamId = (m_uiLastStreamId + 1);
m_uiLastStreamId = (m_uiLastStreamId == NB_MAX_STREAMS+1) ? 1 : m_uiLastStreamId; m_uiLastStreamId = (m_uiLastStreamId == NB_MAX_STREAMS+1) ? 1 : m_uiLastStreamId;
@ -223,56 +208,50 @@ CStream *CController::OpenStream(const CCallsign &Callsign, const CIp &Ip, uint8
delete stream; delete stream;
stream = NULL; stream = NULL;
} }
// done // done
return stream; return stream;
} }
void CController::CloseStream(CStream *stream) void CController::CloseStream(CStream *stream)
{ {
Lock(); Lock();
{ // look for the stream
// look for the stream for ( auto it=m_Streams.begin(); it!=m_Streams.end(); it++ )
bool found = false; {
for ( int i = 0; (i < m_Streams.size()) && !found; i++ ) // compare object pointers
{ if ( *it == stream )
// compare object pointers {
if ( (m_Streams[i]) == stream ) // close it
{ (*it)->Close();
// close it // remove it
m_Streams[i]->Close(); //std::cout << "Stream " << m_Streams[i]->GetId() << " removed" << std::endl;
// remove it delete *it;
//std::cout << "Stream " << m_Streams[i]->GetId() << " removed" << std::endl; m_Streams.erase(it);
delete m_Streams[i]; break;
m_Streams.erase(m_Streams.begin()+i); }
found = true; }
} Unlock();
}
}
Unlock();
} }
void CController::CloseStream(uint16 StreamId) void CController::CloseStream(uint16 StreamId)
{ {
Lock(); Lock();
{ // look for the stream
// look for the stream for ( auto it=m_Streams.begin(); it!=m_Streams.end(); it++ )
bool found = false; {
for ( int i = 0; (i < m_Streams.size()) && !found; i++ ) // compare object pointers
{ if ( (*it)->GetId() == StreamId )
// compare object pointers {
if ( (m_Streams[i]->GetId()) == StreamId ) // close it
{ (*it)->Close();
// close it // remove it
m_Streams[i]->Close(); //std::cout << "Stream " << m_Streams[i]->GetId() << " removed" << std::endl;
// remove it delete *it;
//std::cout << "Stream " << m_Streams[i]->GetId() << " removed" << std::endl; m_Streams.erase(it);
delete m_Streams[i]; break;
m_Streams.erase(m_Streams.begin()+i); }
found = true; }
}
}
}
Unlock(); Unlock();
} }
@ -282,7 +261,7 @@ void CController::CloseStream(uint16 StreamId)
bool CController::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *Callsign) bool CController::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *Callsign)
{ {
uint8 tag[] = { 'A','M','B','E','D','P','I','N','G' }; uint8 tag[] = { 'A','M','B','E','D','P','I','N','G' };
bool valid = false; bool valid = false;
if ( (Buffer.size() == 17) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) if ( (Buffer.size() == 17) && (Buffer.Compare(tag, sizeof(tag)) == 0) )
{ {
@ -296,7 +275,7 @@ bool CController::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *Calls
bool CController::IsValidOpenstreamPacket(const CBuffer &Buffer, CCallsign *Callsign, uint8 *CodecIn, uint8 *CodecOut) bool CController::IsValidOpenstreamPacket(const CBuffer &Buffer, CCallsign *Callsign, uint8 *CodecIn, uint8 *CodecOut)
{ {
uint8 tag[] = { 'A','M','B','E','D','O','S' }; uint8 tag[] = { 'A','M','B','E','D','O','S' };
bool valid = false; bool valid = false;
if ( (Buffer.size() == 17) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) if ( (Buffer.size() == 17) && (Buffer.Compare(tag, sizeof(tag)) == 0) )
{ {
@ -304,7 +283,7 @@ bool CController::IsValidOpenstreamPacket(const CBuffer &Buffer, CCallsign *Call
Callsign->SetCallsign(&(Buffer.data()[7]), 8); Callsign->SetCallsign(&(Buffer.data()[7]), 8);
*CodecIn = Buffer.data()[15]; *CodecIn = Buffer.data()[15];
*CodecOut = Buffer.data()[16]; *CodecOut = Buffer.data()[16];
// valid ? // valid ?
valid = Callsign->IsValid() && IsValidCodecIn(*CodecIn) && IsValidCodecOut(*CodecOut); valid = Callsign->IsValid() && IsValidCodecIn(*CodecIn) && IsValidCodecOut(*CodecOut);
} }
@ -314,7 +293,7 @@ bool CController::IsValidOpenstreamPacket(const CBuffer &Buffer, CCallsign *Call
bool CController::IsValidClosestreamPacket(const CBuffer &Buffer, uint16 *StreamId) bool CController::IsValidClosestreamPacket(const CBuffer &Buffer, uint16 *StreamId)
{ {
uint8 tag[] = { 'A','M','B','E','D','C','S' }; uint8 tag[] = { 'A','M','B','E','D','C','S' };
bool valid = false; bool valid = false;
if ( /*(Buffer.size() == 16) &&*/ (Buffer.Compare(tag, sizeof(tag)) == 0) ) if ( /*(Buffer.size() == 16) &&*/ (Buffer.Compare(tag, sizeof(tag)) == 0) )
{ {
@ -331,14 +310,14 @@ bool CController::IsValidClosestreamPacket(const CBuffer &Buffer, uint16 *Stream
void CController::EncodeKeepAlivePacket(CBuffer *Buffer) void CController::EncodeKeepAlivePacket(CBuffer *Buffer)
{ {
uint8 tag[] = { 'A','M','B','E','D','P','O','N','G' }; uint8 tag[] = { 'A','M','B','E','D','P','O','N','G' };
Buffer->Set(tag, sizeof(tag)); Buffer->Set(tag, sizeof(tag));
} }
void CController::EncodeStreamDescrPacket(CBuffer *Buffer, const CStream &Stream) void CController::EncodeStreamDescrPacket(CBuffer *Buffer, const CStream &Stream)
{ {
uint8 tag[] = { 'A','M','B','E','D','S','T','D' }; uint8 tag[] = { 'A','M','B','E','D','S','T','D' };
Buffer->Set(tag, sizeof(tag)); Buffer->Set(tag, sizeof(tag));
// id // id
Buffer->Append((uint16)Stream.GetId()); Buffer->Append((uint16)Stream.GetId());
@ -353,7 +332,7 @@ void CController::EncodeStreamDescrPacket(CBuffer *Buffer, const CStream &Stream
void CController::EncodeNoStreamAvailablePacket(CBuffer *Buffer) void CController::EncodeNoStreamAvailablePacket(CBuffer *Buffer)
{ {
uint8 tag[] = { 'A','M','B','E','D','B','U','S','Y' }; uint8 tag[] = { 'A','M','B','E','D','B','U','S','Y' };
Buffer->Set(tag, sizeof(tag)); Buffer->Set(tag, sizeof(tag));
} }
@ -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.
@ -36,10 +37,10 @@ class CController
public: public:
// constructors // constructors
CController(); CController();
// destructor // destructor
virtual ~CController(); virtual ~CController();
// initialization // initialization
bool Init(void); bool Init(void);
void Close(void); void Close(void);
@ -47,28 +48,28 @@ public:
// locks // locks
void Lock(void) { m_Mutex.lock(); } void Lock(void) { m_Mutex.lock(); }
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);
void CloseStream(CStream *); void CloseStream(CStream *);
void CloseStream(uint16); void CloseStream(uint16);
// task // task
static void Thread(CController *); static void Thread(CController *);
void Task(void); void Task(void);
protected: protected:
// packet decoding helpers // packet decoding helpers
bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *); bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *);
bool IsValidOpenstreamPacket(const CBuffer &, CCallsign *, uint8 *, uint8 *); bool IsValidOpenstreamPacket(const CBuffer &, CCallsign *, uint8 *, uint8 *);
bool IsValidClosestreamPacket(const CBuffer &, uint16 *); bool IsValidClosestreamPacket(const CBuffer &, uint16 *);
// packet encoding helpers // packet encoding helpers
void EncodeKeepAlivePacket(CBuffer *); void EncodeKeepAlivePacket(CBuffer *);
void EncodeStreamDescrPacket(CBuffer *, const CStream &); void EncodeStreamDescrPacket(CBuffer *, const CStream &);
@ -77,21 +78,21 @@ protected:
// codec helpers // codec helpers
bool IsValidCodecIn(uint8); bool IsValidCodecIn(uint8);
bool IsValidCodecOut(uint8); bool IsValidCodecOut(uint8);
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;
std::thread *m_pThread; std::thread *m_pThread;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -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.
@ -79,7 +80,7 @@ CStream::~CStream()
delete m_pThread; delete m_pThread;
m_pThread = NULL; m_pThread = NULL;
} }
// then close everything // then close everything
m_Socket.Close(); m_Socket.Close();
if ( m_VocodecChannel != NULL ) if ( m_VocodecChannel != NULL )
@ -93,45 +94,48 @@ 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 {
ok &= ((m_VocodecChannel = g_Vocodecs.OpenChannel(m_uiCodecIn, m_uiCodecOut)) != NULL); std::cerr << "Could not initialize ip address " << s << std::endl;
return false;
if ( ok ) }
{
// store port if (! m_Socket.Open(ip))
m_uiPort = uiPort; {
std::cout << "Error opening stream stream socket on " << ip << std::endl;
// start thread; return false;
m_pThread = new std::thread(CStream::Thread, this); }
// init timeout system // open the vocodecchannel
m_LastActivity.Now(); m_VocodecChannel = g_Vocodecs.OpenChannel(m_uiCodecIn, m_uiCodecOut);
m_iTotalPackets = 0; if (NULL == m_VocodecChannel)
m_iLostPackets = 0; {
std::cerr << "Could not open Vocodec Channel" << std::endl;
} m_Socket.Close();
else return false;
{ }
std::cout << "Error opening stream : no suitable channel available" << std::endl;
} // store port
} m_uiPort = uiPort;
else
{ // start thread;
std::cout << "Error opening socket on port UDP" << uiPort << " on ip " << m_Ip << std::endl; m_pThread = new std::thread(CStream::Thread, this);
}
// init timeout system
m_LastActivity.Now();
m_iTotalPackets = 0;
m_iLostPackets = 0;
// done // done
return ok; return true;
} }
void CStream::Close(void) void CStream::Close(void)
@ -151,8 +155,8 @@ void CStream::Close(void)
{ {
m_VocodecChannel->Close(); m_VocodecChannel->Close();
} }
// report // report
std::cout << m_iLostPackets << " of " << m_iTotalPackets << " packets lost" << std::endl; std::cout << m_iLostPackets << " of " << m_iTotalPackets << " packets lost" << std::endl;
} }
@ -179,9 +183,9 @@ void CStream::Task(void)
uint8 Ambe[AMBE_FRAME_SIZE]; uint8 Ambe[AMBE_FRAME_SIZE];
CAmbePacket *packet; CAmbePacket *packet;
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) )
@ -189,7 +193,7 @@ void CStream::Task(void)
// transcode AMBE here // transcode AMBE here
m_LastActivity.Now(); m_LastActivity.Now();
m_iTotalPackets++; m_iTotalPackets++;
// post packet to VocoderChannel // post packet to VocoderChannel
packet = new CAmbePacket(uiPid, m_uiCodecIn, Ambe); packet = new CAmbePacket(uiPid, m_uiCodecIn, Ambe);
queue = m_VocodecChannel->GetPacketQueueIn(); queue = m_VocodecChannel->GetPacketQueueIn();
@ -197,7 +201,7 @@ void CStream::Task(void)
m_VocodecChannel->ReleasePacketQueueIn(); m_VocodecChannel->ReleasePacketQueueIn();
} }
} }
// anything in our queue ? // anything in our queue ?
queue = m_VocodecChannel->GetPacketQueueOut(); queue = m_VocodecChannel->GetPacketQueueOut();
while ( !queue->empty() ) while ( !queue->empty() )
@ -220,7 +224,7 @@ void CStream::Task(void)
bool CStream::IsValidDvFramePacket(const CBuffer &Buffer, uint8 *pid, uint8 *ambe) bool CStream::IsValidDvFramePacket(const CBuffer &Buffer, uint8 *pid, uint8 *ambe)
{ {
bool valid = false; bool valid = false;
if ( Buffer.size() == 11 ) if ( Buffer.size() == 11 )
{ {
uint8 codec = Buffer.data()[0]; uint8 codec = Buffer.data()[0];
@ -228,7 +232,7 @@ bool CStream::IsValidDvFramePacket(const CBuffer &Buffer, uint8 *pid, uint8 *amb
::memcpy(ambe, &(Buffer.data()[2]), 9); ::memcpy(ambe, &(Buffer.data()[2]), 9);
valid = (codec == GetCodecIn()); valid = (codec == GetCodecIn());
} }
return valid; return valid;
} }
@ -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,65 +27,15 @@
#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 )
{ {
@ -92,40 +43,25 @@ int main(int argc, const char * argv[])
std::cout << "example: ambed 192.168.178.212" << std::endl; std::cout << "example: ambed 192.168.178.212" << std::endl;
return 1; return 1;
} }
// 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>
@ -102,7 +103,7 @@ typedef unsigned int uint;
#define HIWORD(dw) ((uint16)((((uint32)(dw)) >> 16) & 0xFFFF)) #define HIWORD(dw) ((uint16)((((uint32)(dw)) >> 16) & 0xFFFF))
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// FIR Filter coefficients computed to be the closest to the recommended filter in // FIR Filter coefficients computed to be the closest to the recommended filter in
// Documentation // Documentation
// //
// Following GNU Octave script was used // Following GNU Octave script was used
@ -143,6 +144,6 @@ extern CAmbeServer g_AmbeServer;
class CVocodecs; class CVocodecs;
extern CVocodecs g_Vocodecs; extern CVocodecs g_Vocodecs;
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#endif /* main_h */ #endif /* main_h */

@ -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.