uses TCP instead of unix sockets

main
Tom Early 2 years ago
parent 02c6396241
commit 842d2e0a59

20
.gitignore vendored

@ -7,24 +7,8 @@
*.o *.o
*.obj *.obj
# Precompiled Headers # Files
*.gch tcd.*
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Visual Studio # Visual Studio
.vscode .vscode

@ -21,6 +21,7 @@
#include <fstream> #include <fstream>
#include <vector> #include <vector>
#include <sstream> #include <sstream>
#include <regex>
#include "Configure.h" #include "Configure.h"
// ini file keywords // ini file keywords
@ -30,7 +31,9 @@
#define DMRGAINOUT "DmrYsfGainOut" #define DMRGAINOUT "DmrYsfGainOut"
#define DSTARGAININ "DStarGainIn" #define DSTARGAININ "DStarGainIn"
#define DSTARGAINOUT "DStarGainOut" #define DSTARGAINOUT "DStarGainOut"
#define TRANSCODED "Transcoded" #define MODULES "Modules"
#define ADDRESS "Address"
#define PORT "Port"
static inline void split(const std::string &s, char delim, std::vector<std::string> &v) static inline void split(const std::string &s, char delim, std::vector<std::string> &v)
{ {
@ -63,7 +66,10 @@ static inline void trim(std::string &s) {
bool CConfigure::ReadData(const std::string &path) bool CConfigure::ReadData(const std::string &path)
// returns true on failure // returns true on failure
{ {
std::string modstmp; std::regex IPv4RegEx = std::regex("^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3,3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]){1,1}$", std::regex::extended);
std::regex IPv6RegEx = std::regex("^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}(:[0-9a-fA-F]{1,4}){1,1}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|([0-9a-fA-F]{1,4}:){1,1}(:[0-9a-fA-F]{1,4}){1,6}|:((:[0-9a-fA-F]{1,4}){1,7}|:))$", std::regex::extended);
std::string modstmp, porttmp;
std::ifstream cfgfile(path.c_str(), std::ifstream::in); std::ifstream cfgfile(path.c_str(), std::ifstream::in);
if (! cfgfile.is_open()) { if (! cfgfile.is_open()) {
@ -104,7 +110,11 @@ bool CConfigure::ReadData(const std::string &path)
std::cout << "WARNING: missing key or value: '" << line << "'" << std::endl; std::cout << "WARNING: missing key or value: '" << line << "'" << std::endl;
continue; continue;
} }
if (0 == key.compare(TRANSCODED)) if (0 == key.compare(ADDRESS))
address.assign(value);
else if (0 == key.compare(PORT))
porttmp.assign(value);
else if (0 == key.compare(MODULES))
modstmp.assign(value); modstmp.assign(value);
else if (0 == key.compare(DSTARGAININ)) else if (0 == key.compare(DSTARGAININ))
dstar_in = getSigned(key, value); dstar_in = getSigned(key, value);
@ -139,7 +149,22 @@ bool CConfigure::ReadData(const std::string &path)
return true; return true;
} }
std::cout << TRANSCODED << " = " << tcmods << std::endl; if (! std::regex_match(address, IPv4RegEx) && ! std::regex_match(address, IPv6RegEx))
{
std::cerr << "ERROR: '" << address << "' is malformed, Halt." << std::endl;
return true;
}
port = std::strtoul(porttmp.c_str(), nullptr, 10);
if (port < 1025 || port > 49000)
{
std::cerr << "ERROR: Port '" << porttmp << "' must be between >1024 and <49000. Halt." << std::endl;
return true;
}
std::cout << MODULES << " = " << tcmods << std::endl;
std::cout << ADDRESS << " = " << address << std::endl;
std::cout << PORT << " = " << port << std::endl;
std::cout << DSTARGAININ << " = " << dstar_in << std::endl; std::cout << DSTARGAININ << " = " << dstar_in << std::endl;
std::cout << DSTARGAINOUT << " = " << dstar_out << std::endl; std::cout << DSTARGAINOUT << " = " << dstar_out << std::endl;
std::cout << DMRGAININ << " = " << dmr_in << std::endl; std::cout << DMRGAININ << " = " << dmr_in << std::endl;

@ -32,10 +32,13 @@ public:
bool ReadData(const std::string &path); bool ReadData(const std::string &path);
int GetGain(EGainType gt) const; int GetGain(EGainType gt) const;
std::string GetTCMods(void) const { return tcmods; } std::string GetTCMods(void) const { return tcmods; }
std::string GetAddress(void) const { return address; }
unsigned GetPort(void) const { return port; }
private: private:
// CFGDATA data; // CFGDATA data;
std::string tcmods; std::string tcmods, address;
uint16_t port;
int dstar_in, dstar_out, dmr_in, dmr_out, usrp_tx, usrp_rx; int dstar_in, dstar_out, dmr_in, dmr_out, usrp_tx, usrp_rx;
int getSigned(const std::string &key, const std::string &value) const; int getSigned(const std::string &key, const std::string &value) const;

@ -22,6 +22,7 @@
#include <sstream> #include <sstream>
#include <fstream> #include <fstream>
#include <thread> #include <thread>
#include <queue>
#ifdef USE_SW_AMBE2 #ifdef USE_SW_AMBE2
#include <md380_vocoder.h> #include <md380_vocoder.h>
#endif #endif
@ -46,7 +47,7 @@ bool CController::Start()
usrp_rx_num = calcNumerator(g_Conf.GetGain(EGainType::usrprx)); usrp_rx_num = calcNumerator(g_Conf.GetGain(EGainType::usrprx));
usrp_tx_num = calcNumerator(g_Conf.GetGain(EGainType::usrptx)); usrp_tx_num = calcNumerator(g_Conf.GetGain(EGainType::usrptx));
if (InitVocoders() || reader.Open(REF2TC)) if (InitVocoders() || tcClient.Initialize(g_Conf.GetAddress(), g_Conf.GetTCMods(), g_Conf.GetPort()))
{ {
keep_running = false; keep_running = false;
return true; return true;
@ -70,7 +71,7 @@ void CController::Stop()
if (c2Future.valid()) if (c2Future.valid())
c2Future.get(); c2Future.get();
reader.Close(); tcClient.Close();
dstar_device->CloseDevice(); dstar_device->CloseDevice();
dmrsf_device->CloseDevice(); dmrsf_device->CloseDevice();
dstar_device.reset(); dstar_device.reset();
@ -249,39 +250,42 @@ void CController::ReadReflectorThread()
{ {
while (keep_running) while (keep_running)
{ {
STCPacket tcpack; std::queue<std::unique_ptr<STCPacket>> queue;
// wait up to 100 ms to read something on the unix port // wait up to 100 ms to read something on the unix port
if (reader.Receive(&tcpack, 100)) if (tcClient.Receive(queue, 100))
{ {
// create a shared pointer to a new packet while (! queue.empty())
// there is only one CTranscoderPacket created for each new STCPacket received from the reflector
auto packet = std::make_shared<CTranscoderPacket>(tcpack);
switch (packet->GetCodecIn())
{ {
case ECodecType::dstar: // create a shared pointer to a new packet
dstar_device->AddPacket(packet); // there is only one CTranscoderPacket created for each new STCPacket received from the reflector
break; auto packet = std::make_shared<CTranscoderPacket>(*queue.front());
case ECodecType::dmr: queue.pop();
#ifdef USE_SW_AMBE2 switch (packet->GetCodecIn())
swambe2_queue.push(packet); {
#else case ECodecType::dstar:
dmrsf_device->AddPacket(packet); dstar_device->AddPacket(packet);
#endif break;
break; case ECodecType::dmr:
case ECodecType::p25: #ifdef USE_SW_AMBE2
imbe_queue.push(packet); swambe2_queue.push(packet);
break; #else
case ECodecType::usrp: dmrsf_device->AddPacket(packet);
usrp_queue.push(packet); #endif
break; break;
case ECodecType::c2_1600: case ECodecType::p25:
case ECodecType::c2_3200: imbe_queue.push(packet);
codec2_queue.push(packet); break;
break; case ECodecType::usrp:
default: usrp_queue.push(packet);
Dump(packet, "ERROR: Received a reflector packet with unknown Codec:"); break;
break; case ECodecType::c2_1600:
case ECodecType::c2_3200:
codec2_queue.push(packet);
break;
default:
Dump(packet, "ERROR: Received a reflector packet with unknown Codec:");
break;
}
} }
} }
} }
@ -595,14 +599,8 @@ void CController::ProcessUSRPThread()
void CController::SendToReflector(std::shared_ptr<CTranscoderPacket> packet) void CController::SendToReflector(std::shared_ptr<CTranscoderPacket> packet)
{ {
// open a socket to the reflector channel
CUnixDgramWriter socket;
std::string name(TC2REF);
name.append(1, packet->GetModule());
socket.SetUp(name.c_str());
// send the packet over the socket // send the packet over the socket
socket.Send(packet->GetTCPacket()); tcClient.Send(packet->GetTCPacket());
// the socket will automatically close after sending
packet->Sent(); packet->Sent();
} }

@ -29,7 +29,7 @@
#include "codec2.h" #include "codec2.h"
#include "DV3000.h" #include "DV3000.h"
#include "DV3003.h" #include "DV3003.h"
#include "UnixDgramSocket.h" #include "TCSocket.h"
class CController class CController
{ {
@ -48,8 +48,7 @@ protected:
std::future<void> reflectorFuture, c2Future, imbeFuture, usrpFuture; std::future<void> reflectorFuture, c2Future, imbeFuture, usrpFuture;
std::unordered_map<char, int16_t[160]> audio_store; std::unordered_map<char, int16_t[160]> audio_store;
std::unordered_map<char, uint8_t[8]> data_store; std::unordered_map<char, uint8_t[8]> data_store;
CUnixDgramReader reader; CTCClient tcClient;
CUnixDgramWriter writer;
std::unordered_map<char, std::unique_ptr<CCodec2>> c2_16, c2_32; std::unordered_map<char, std::unique_ptr<CCodec2>> c2_16, c2_32;
std::unique_ptr<CDVDevice> dstar_device, dmrsf_device; std::unique_ptr<CDVDevice> dstar_device, dmrsf_device;

@ -0,0 +1 @@
../urfd/reflector/IP.cpp

@ -0,0 +1 @@
../urfd/reflector/IP.h

@ -5,9 +5,9 @@ include tcd.mk
GCC = g++ GCC = g++
ifeq ($(debug), true) ifeq ($(debug), true)
CFLAGS = -ggdb3 -W -Werror -Icodec2 -MMD -MD -std=c++11 CFLAGS = -ggdb3 -W -Werror -Icodec2 -MMD -MD -std=c++17
else else
CFLAGS = -W -Werror -Icodec2 -MMD -MD -std=c++11 CFLAGS = -W -Werror -Icodec2 -MMD -MD -std=c++17
endif endif
ifeq ($(swambe2), true) ifeq ($(swambe2), true)

@ -20,7 +20,7 @@ Currently, this program must be run locally with its paired URF reflector. Remot
Only systemd-based operating systems are supported. Debian or Ubuntu is recommended. If you want to install this on a non-systemd based OS, you are on your own. Also, by default, *tcd* is built without gdb support. Only systemd-based operating systems are supported. Debian or Ubuntu is recommended. If you want to install this on a non-systemd based OS, you are on your own. Also, by default, *tcd* is built without gdb support.
The P25 IMBE software vocoder library is available [here](https://github.com/nostar/imbe_vocoder). See its README.md file for instructions for compiling and installating this library. The P25 IMBE software vocoder library is available [here](https://github.com/nostar/imbe_vocoder). See its README.md file for instructions for compiling and installing this library.
If you are running tcd on an ARM-base processor, you can opt to use a software-based vocoder library available [here](https://github.com/nostar/md380_vocoder) for DMR/YSF vocoding. This library is used for the AMBE+2 (DMR/YSF/NXDN) codec. If you are going to use this library, *tcd* must run on an ARM platform like a RPi. Using this software solution means that you only need one DVSI device to handle D-Star vocoding. If you are running tcd on an ARM-base processor, you can opt to use a software-based vocoder library available [here](https://github.com/nostar/md380_vocoder) for DMR/YSF vocoding. This library is used for the AMBE+2 (DMR/YSF/NXDN) codec. If you are going to use this library, *tcd* must run on an ARM platform like a RPi. Using this software solution means that you only need one DVSI device to handle D-Star vocoding.

@ -0,0 +1 @@
../urfd/reflector/TCSocket.cpp

@ -0,0 +1 @@
../urfd/reflector/TCSocket.h

@ -1 +0,0 @@
../urfd/reflector/UnixDgramSocket.cpp

@ -1 +0,0 @@
../urfd/reflector/UnixDgramSocket.h

@ -2,10 +2,13 @@
# #
# this is a comment # this is a comment
# VERY IMPORTANT: This need to be idential to the same line in the urfd ini file! Port = 10100
ServerAddress = 127.0.0.1
# VERY IMPORTANT: This need to be idential to the same line in [Transcder] section of the urfd ini file!
# This will either be a single module (for DVSI-3000), or # This will either be a single module (for DVSI-3000), or
# up to three modules (for DVSI-3003). # up to three modules (for DVSI-3003).
Transcoded = A Modules = A
# All gain values are in dB. # All gain values are in dB.
# Gain values are limited to -24 to +24. Typical values will usually be less. # Gain values are limited to -24 to +24. Typical values will usually be less.

Loading…
Cancel
Save

Powered by TurnKey Linux.