fix issue with logger not allowing strings >500 characters; refactor RCON to support returning data to a RCON client; enhance network support to allow enabling RCON while networking itself is disabled; add version and help commands to RCON;

2.0-maint
Bryan Biedenkapp 3 years ago
parent 4afaf6400d
commit 7159c8297a

@ -55,6 +55,9 @@
#define EOL "\r\n"
#endif
const uint32_t ACT_LOG_BUFFER_LEN = 501U;
const uint32_t LOG_BUFFER_LEN = 4096U;
// ---------------------------------------------------------------------------
// Global Variables
// ---------------------------------------------------------------------------
@ -194,7 +197,7 @@ void ActivityLog(const char *mode, const bool sourceRf, const char* msg, ...)
assert(mode != NULL);
assert(msg != NULL);
char buffer[501U];
char buffer[ACT_LOG_BUFFER_LEN];
#if defined(_WIN32) || defined(_WIN64)
SYSTEMTIME st;
::GetSystemTime(&st);
@ -212,7 +215,7 @@ void ActivityLog(const char *mode, const bool sourceRf, const char* msg, ...)
va_list vl;
va_start(vl, msg);
::vsnprintf(buffer + ::strlen(buffer), 500, msg, vl);
::vsnprintf(buffer + ::strlen(buffer), ACT_LOG_BUFFER_LEN - 1U, msg, vl);
va_end(vl);
@ -279,7 +282,7 @@ void Log(uint32_t level, const char *module, const char* fmt, ...)
{
assert(fmt != NULL);
char buffer[501U];
char buffer[LOG_BUFFER_LEN];
#if defined(_WIN32) || defined(_WIN64)
if (!m_disableTimeDisplay) {
SYSTEMTIME st;
@ -327,7 +330,7 @@ void Log(uint32_t level, const char *module, const char* fmt, ...)
va_list vl;
va_start(vl, fmt);
::vsnprintf(buffer + ::strlen(buffer), 500, fmt, vl);
::vsnprintf(buffer + ::strlen(buffer), LOG_BUFFER_LEN - 1U, fmt, vl);
va_end(vl);

@ -131,7 +131,9 @@ CMD_OBJECTS = \
remote/RemoteCommand.cmd.o \
edac/SHA256.cmd.o \
network/UDPSocket.cmd.o \
Log.cmd.o
Thread.cmd.o \
Log.cmd.o \
Utils.cmd.o
.PHONY: dvmhost dvmcmd all strip clean install dpkg tarball

@ -40,22 +40,6 @@ const uint8_t BITS_TABLE[] = {
B6(0), B6(1), B6(1), B6(2)
};
#if defined(ENABLE_DMR)
#define DESCR_DMR "DMR, "
#else
#define DESCR_DMR ""
#endif
#if defined(ENABLE_P25)
#define DESCR_P25 "P25, "
#else
#define DESCR_P25 ""
#endif
#if defined(ENABLE_NXDN)
#define DESCR_NXDN "NXDN, "
#else
#define DESCR_NXDN ""
#endif
// ---------------------------------------------------------------------------
// Global Functions
// ---------------------------------------------------------------------------

@ -30,6 +30,26 @@
#include <string>
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
#if defined(ENABLE_DMR)
#define DESCR_DMR "DMR, "
#else
#define DESCR_DMR ""
#endif
#if defined(ENABLE_P25)
#define DESCR_P25 "P25, "
#else
#define DESCR_P25 ""
#endif
#if defined(ENABLE_NXDN)
#define DESCR_NXDN "NXDN, "
#else
#define DESCR_NXDN ""
#endif
// ---------------------------------------------------------------------------
// Externs
// ---------------------------------------------------------------------------

@ -10,11 +10,6 @@ network:
id: 100000
address: 127.0.0.1
port: 62031
rconEnable: false
rconAddress: 127.0.0.1
rconPort: 9990
rconPassword: "PASSWORD"
rconDebug: false
jitter: 360
password: "PASSWORD"
slot1: true
@ -24,6 +19,11 @@ network:
allowDiagnosticTransfer: true
handleChGrants: false
debug: false
rconEnable: false
rconAddress: 127.0.0.1
rconPort: 9990
rconPassword: "PASSWORD"
rconDebug: false
protocols:
dmr:
enable: true

@ -317,11 +317,9 @@ int Host::run()
m_tidLookup->read();
// initialize networking
if (m_conf["network"]["enable"].as<bool>(false)) {
ret = createNetwork();
if (!ret)
return EXIT_FAILURE;
}
// set CW parameters
if (systemConf["cwId"]["enable"].as<bool>(false)) {
@ -2236,7 +2234,13 @@ bool Host::createModem()
/// </summary>
bool Host::createNetwork()
{
// dump out if both networking and RCON are disabled
if (m_conf["network"]["enable"].as<bool>(false) && m_conf["network"]["rconEnable"].as<bool>(false)) {
return true;
}
yaml::Node networkConf = m_conf["network"];
bool netEnable = networkConf["enable"].as<bool>(false);
std::string address = networkConf["address"].as<std::string>();
uint16_t port = (uint16_t)networkConf["port"].as<uint32_t>(TRAFFIC_DEFAULT_PORT);
uint16_t local = (uint16_t)networkConf["local"].as<uint32_t>(0U);
@ -2266,6 +2270,8 @@ bool Host::createNetwork()
IdenTable entry = m_idenTable->find(m_channelId);
LogInfo("Network Parameters");
LogInfo(" Enabled: %s", netEnable ? "yes" : "no");
if (netEnable) {
LogInfo(" Peer Id: %u", id);
LogInfo(" Address: %s", address.c_str());
LogInfo(" Port: %u", port);
@ -2273,15 +2279,6 @@ bool Host::createNetwork()
LogInfo(" Local: %u", local);
else
LogInfo(" Local: random");
LogInfo(" RCON Enabled: %s", rconEnable ? "yes" : "no");
if (rconEnable) {
LogInfo(" RCON Address: %s", rconAddress.c_str());
LogInfo(" RCON Port: %u", rconPort);
}
if (rconDebug) {
LogInfo(" RCON Debug: yes");
}
LogInfo(" DMR Jitter: %ums", jitter);
LogInfo(" Slot 1: %s", slot1 ? "enabled" : "disabled");
LogInfo(" Slot 2: %s", slot2 ? "enabled" : "disabled");
@ -2293,7 +2290,19 @@ bool Host::createNetwork()
if (debug) {
LogInfo(" Debug: yes");
}
}
LogInfo(" RCON Enabled: %s", rconEnable ? "yes" : "no");
if (rconEnable) {
LogInfo(" RCON Address: %s", rconAddress.c_str());
LogInfo(" RCON Port: %u", rconPort);
if (rconDebug) {
LogInfo(" RCON Debug: yes");
}
}
// initialize networking
if (netEnable) {
m_network = new Network(address, port, local, id, password, m_duplex, debug, m_dmrEnabled, m_p25Enabled, m_nxdnEnabled, slot1, slot2, allowActivityTransfer, allowDiagnosticTransfer, updateLookup, handleChGrants);
m_network->setLookups(m_ridLookup, m_tidLookup);
@ -2313,12 +2322,13 @@ bool Host::createNetwork()
m_network->enable(true);
::LogSetNetwork(m_network);
}
// initialize network remote command
if (rconEnable) {
m_remoteControl = new RemoteControl(rconAddress, rconPort, rconPassword, rconDebug);
m_remoteControl->setLookups(m_ridLookup, m_tidLookup);
ret = m_remoteControl->open();
bool ret = m_remoteControl->open();
if (!ret) {
delete m_remoteControl;
m_remoteControl = NULL;

File diff suppressed because it is too large Load Diff

@ -83,6 +83,12 @@ private:
::lookups::RadioIdLookup* m_ridLookup;
::lookups::TalkgroupIdLookup* m_tidLookup;
/// <summary>Helper to send response to client.</summary>
void writeResponse(std::string reply, sockaddr_storage address, uint32_t addrLen);
/// <summary>Helper to print the remote control help.</summary>
std::string displayHelp();
/// <summary></summary>
std::string getArgString(std::vector<std::string> args, uint32_t n) const;

@ -169,7 +169,7 @@ bool UDPSocket::open(const uint32_t index, const uint32_t af, const std::string&
return false;
}
LogInfo("Opening UDP port on %u", port);
LogInfoEx(LOG_NET, "Opening UDP port on %u", port);
}
return true;
@ -394,7 +394,7 @@ int UDPSocket::lookup(const std::string& hostname, uint16_t port, sockaddr_stora
paddr->sin_family = AF_INET;
paddr->sin_port = htons(port);
paddr->sin_addr.s_addr = htonl(INADDR_NONE);
LogError("Cannot find address for host %s", hostname.c_str());
LogError(LOG_NET, "Cannot find address for host %s", hostname.c_str());
return err;
}

@ -32,7 +32,9 @@
#include "edac/SHA256.h"
#include "network/UDPSocket.h"
#include "RemoteCommand.h"
#include "Thread.h"
#include "Log.h"
#include "Utils.h"
using namespace network;
@ -55,10 +57,14 @@ using namespace network;
#define ERRNO_ADDR_LOOKUP 97
#define ERRNO_FAILED_TO_SEND 96
const uint32_t START_OF_TEXT = 0x02;
const uint32_t REC_SEPARATOR = 0x1E;
const uint8_t RCON_FRAME_START = 0xFEU;
const uint8_t START_OF_TEXT = 0x02U;
const uint8_t END_OF_TEXT = 0x03U;
const uint8_t END_OF_BLOCK = 0x17U;
const uint8_t REC_SEPARATOR = 0x1EU;
const uint32_t RC_BUFFER_LENGTH = 140U;
const uint32_t RC_BUFFER_LENGTH = 250U;
const uint32_t RESPONSE_BUFFER_LEN = 4095U;
// ---------------------------------------------------------------------------
// Macros
@ -74,6 +80,7 @@ static std::string g_progExe = std::string(__EXE_NAME__);
static std::string g_remoteAddress = std::string("127.0.0.1");
static uint32_t g_remotePort = RCON_DEFAULT_PORT;
static std::string g_remotePassword = std::string();
static bool g_debug = false;
// ---------------------------------------------------------------------------
// Global Functions
@ -101,6 +108,7 @@ void usage(const char* message, const char* arg)
" -p remote modem command port\n"
" -P remote modem authentication password\n"
"\n"
" -d enable debug\n"
" -v show version information\n"
" -h show this screen\n"
" -- stop handling options\n",
@ -156,6 +164,10 @@ int checkArgs(int argc, char* argv[])
p += 2;
}
else if (IS("-d")) {
++p;
g_debug = true;
}
else if (IS("-v")) {
::fprintf(stdout, __PROG_NAME__ " %s (built %s)\r\n", __VER__, __BUILD__);
::fprintf(stdout, "Copyright (c) 2017-2022 Bryan Biedenkapp, N2PLL and DVMProject (https://github.com/dvmproject) Authors.\r\n");
@ -215,13 +227,13 @@ int main(int argc, char** argv)
}
// initialize system logging
bool ret = ::LogInitialise("", "", 0U, 1U);
bool ret = ::LogInitialise("", "", 0U, 1U, true);
if (!ret) {
::fprintf(stderr, "unable to open the log file\n");
return 1;
}
CRemoteCommand* command = new CRemoteCommand(g_remoteAddress, g_remotePort, g_remotePassword);
RemoteCommand* command = new RemoteCommand(g_remoteAddress, g_remotePort, g_remotePassword);
int retCode = command->send(cmd);
::LogFinalise();
@ -233,12 +245,12 @@ int main(int argc, char** argv)
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CRemoteCommand class.
/// Initializes a new instance of the RemoteCommand class.
/// </summary>
/// <param name="address">Network Hostname/IP address to connect to.</param>
/// <param name="port">Network port number.</param>
/// <param name="password">Authentication password.</param>
CRemoteCommand::CRemoteCommand(const std::string& address, uint32_t port, const std::string& password) :
RemoteCommand::RemoteCommand(const std::string& address, uint32_t port, const std::string& password) :
m_address(address),
m_port(port),
m_password(password)
@ -248,9 +260,9 @@ CRemoteCommand::CRemoteCommand(const std::string& address, uint32_t port, const
}
/// <summary>
/// Finalizes a instance of the CRemoteCommand class.
/// Finalizes a instance of the RemoteCommand class.
/// </summary>
CRemoteCommand::~CRemoteCommand()
RemoteCommand::~RemoteCommand()
{
/* stub */
}
@ -260,7 +272,7 @@ CRemoteCommand::~CRemoteCommand()
/// </summary>
/// <param name="command">Command string to send to remote modem.</param>
/// <returns>EXIT_SUCCESS, if command was sent, otherwise EXIT_FAILURE.</returns>
int CRemoteCommand::send(const std::string& command)
int RemoteCommand::send(const std::string& command)
{
UDPSocket socket(0U);
@ -279,10 +291,11 @@ int CRemoteCommand::send(const std::string& command)
return ERRNO_ADDR_LOOKUP;
}
::LogInfoEx(LOG_HOST, "%s: sending command \"%s\" to %s:%u\r\n", g_progExe.c_str(), command.c_str(),
::LogInfoEx(LOG_HOST, "%s: sending command \"%s\" to %s:%u", g_progExe.c_str(), command.c_str(),
m_address.c_str(), m_port);
buffer[0U] = START_OF_TEXT;
buffer[0U] = RCON_FRAME_START;
buffer[1U] = START_OF_TEXT;
if (!m_password.empty()) {
size_t size = m_password.size();
@ -297,19 +310,70 @@ int CRemoteCommand::send(const std::string& command)
edac::SHA256 sha256;
sha256.buffer(in, (uint32_t)(size), out);
::memcpy(buffer + 1U, out, 32U);
::memcpy(buffer + 2U, out, 32U);
}
buffer[33U] = REC_SEPARATOR;
::memcpy(buffer + 34U, command.c_str(), command.size());
buffer[34U] = REC_SEPARATOR;
::memcpy(buffer + 35U, command.c_str(), command.size());
buffer[35U + command.size()] = END_OF_TEXT;
ret = socket.write((uint8_t *)buffer, 34U + command.size(), addr, addrLen);
if (g_debug)
Utils::dump(1U, "RCON Sent", (uint8_t*)buffer, 36U + command.size());
ret = socket.write((uint8_t *)buffer, 36U + command.size(), addr, addrLen);
if (!ret) {
socket.close();
::LogError(LOG_HOST, "Failed to send command: \"%s\"\r\n", command.c_str());
::LogError(LOG_HOST, "Failed to send command: \"%s\"", command.c_str());
return ERRNO_FAILED_TO_SEND;
}
Thread::sleep(100);
uint8_t response[RESPONSE_BUFFER_LEN];
::memset(response, 0x00U, RESPONSE_BUFFER_LEN);
int len = 1;
uint32_t offs = 0U;
do
{
::memset(buffer, 0x00U, RC_BUFFER_LENGTH);
int len = socket.read((uint8_t *)buffer, RC_BUFFER_LENGTH, addr, addrLen);
if (len <= 1)
break;
if (offs + len > RESPONSE_BUFFER_LEN)
break;
if (g_debug)
::LogDebug(LOG_RCON, "RemoteCommand::send() block len = %u, offs = %u", len - 3, offs);
buffer[len] = '\0';
if (g_debug)
Utils::dump(1U, "RCON Received", (uint8_t*)buffer, len);
// make sure this is an RCON response
if (buffer[0U] != RCON_FRAME_START) {
::LogError(LOG_HOST, "Invalid response from host %s:%u", m_address.c_str(), m_port);
socket.close();
return EXIT_FAILURE;
}
if (buffer[1U] != START_OF_TEXT) {
::LogError(LOG_HOST, "Invalid response from host %s:%u", m_address.c_str(), m_port);
socket.close();
return EXIT_FAILURE;
}
::memcpy(response + offs, buffer + 2U, len - 3U);
offs += len - 3U;
Thread::sleep(100);
} while (buffer[len - 1U] != END_OF_TEXT);
::LogInfoEx(LOG_HOST, ">> %s", response);
socket.close();
return EXIT_SUCCESS;
}

@ -40,13 +40,13 @@
// This class implements the core remote command logic.
// ---------------------------------------------------------------------------
class HOST_SW_API CRemoteCommand
class HOST_SW_API RemoteCommand
{
public:
/// <summary>Initializes a new instance of the CRemoteCommand class.</summary>
CRemoteCommand(const std::string& address, uint32_t port, const std::string& password);
/// <summary>Finalizes a instance of the CRemoteCommand class.</summary>
~CRemoteCommand();
/// <summary>Initializes a new instance of the RemoteCommand class.</summary>
RemoteCommand(const std::string& address, uint32_t port, const std::string& password);
/// <summary>Finalizes a instance of the RemoteCommand class.</summary>
~RemoteCommand();
/// <summary>Sends remote control command to the specified modem.</summary>
int send(const std::string& command);

Loading…
Cancel
Save

Powered by TurnKey Linux.