3
Fork 0

svxlink-17.12.2

This commit is contained in:
Alexey Bazhin 2018-03-14 14:16:33 +03:00
parent 444d3ba29d
commit d2d6e3d273
3 changed files with 213 additions and 39 deletions

View file

@ -1,7 +1,7 @@
#!/bin/bash
PREFIX=/opt/SVXLink
sudo apt-get install libsigc++-2.0-dev libpopt-dev libgcrypt11-dev libasound2-dev libgsm1-dev
sudo apt-get install libsigc++-2.0-dev libpopt-dev libgcrypt11-dev libasound2-dev libgsm1-dev tcl-dev libspeex-dev libopus-dev
sudo adduser svxlink --system --home $PREFIX --shell /bin/false --disabled-login --disabled-password
sudo addgroup svxlink

View file

@ -39,6 +39,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include <cstdlib>
#include <vector>
#include <string.h>
/****************************************************************************
*
@ -58,6 +59,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include <common.h>
#include <AsyncPty.h>
#include <AsyncPtyStreamBuf.h>
/****************************************************************************
*
* Local Includes
@ -133,7 +137,7 @@ using namespace EchoLink;
extern "C" {
Module *module_init(void *dl_handle, Logic *logic, const char *cfg_name)
{
{
return new ModuleEchoLink(dl_handle, logic, cfg_name);
}
} /* extern "C" */
@ -158,7 +162,7 @@ ModuleEchoLink::ModuleEchoLink(void *dl_handle, Logic *logic,
listen_only_valve(0), selector(0), num_con_max(0), num_con_ttl(5*60),
num_con_block_time(120*60), num_con_update_timer(0), reject_conf(false),
autocon_echolink_id(0), autocon_time(DEFAULT_AUTOCON_TIME),
autocon_timer(0), proxy(0)
autocon_timer(0), proxy(0), pty(0)
{
cout << "\tModule EchoLink v" MODULE_ECHOLINK_VERSION " starting...\n";
@ -470,6 +474,21 @@ bool ModuleEchoLink::initialize(void)
mem_fun(*this, &ModuleEchoLink::checkAutoCon));
}
string pty_path;
if(cfg().getValue(cfgName(), "COMMAND_PTY", pty_path))
{
pty = new Pty(pty_path);
if (!pty->open())
{
cerr << "*** ERROR: Could not open echolink PTY "
<< pty_path << " as specified in configuration variable "
<< name() << "/" << "COMMAND_PTY" << endl;
return false;
}
pty->dataReceived.connect(
sigc::mem_fun(*this, &ModuleEchoLink::onCommandPtyInput));
}
return true;
} /* ModuleEchoLink::initialize */
@ -510,6 +529,85 @@ void ModuleEchoLink::logicIdleStateChanged(bool is_idle)
*
****************************************************************************/
void ModuleEchoLink::handlePtyCommand(const std::string &full_command)
{
istringstream is(full_command);
string command;
if (!(is >> command))
{
return;
}
if (command == "KILL") // Disconnect active talker
{
if (talker == 0)
{
cout << "EchoLink: Trying to KILL, but no active talker" << endl;
}
else
{
cout << "EchoLink: Killing talker: " << talker->remoteCallsign() << endl;
talker->disconnect();
}
}
else if (command == "DISC") // Disconnect client by callsign
{
string callsign;
if (!(is >> callsign))
{
cerr << "*** WARNING: Malformed EchoLink PTY disconnect command: \""
<< full_command << "\"" << endl;
return;
}
vector<QsoImpl *>::iterator it;
for (it = qsos.begin(); it != qsos.end(); ++it)
{
if ((*it)->remoteCallsign() == callsign)
{
cout << "EchoLink: Disconnecting user "
<< (*it)->remoteCallsign() << endl;
(*it)->disconnect();
return;
}
}
cerr << "*** WARNING: Could not find EchoLink user \"" << callsign
<< "\" in PTY command \"DISC\"" << endl;
}
else
{
cerr << "*** WARNING: Unknown EchoLink PTY command received: \""
<< full_command << "\"" << endl;
}
} /* ModuleEchoLink::handlePtyCommand */
void ModuleEchoLink::onCommandPtyInput(const void *buf, size_t count)
{
const char *buffer = reinterpret_cast<const char*>(buf);
for (size_t i=0; i<count; ++i)
{
char ch = buffer[i];
switch (ch)
{
case '\n': // Execute command on NL
handlePtyCommand(command_buf);
command_buf.clear();
break;
case '\r': // Ignore CR
break;
default: // Append character to command buffer
if (command_buf.size() >= 256) // Prevent cmd buffer growing too big
{
command_buf.clear();
}
command_buf += ch;
break;
}
}
} /* ModuleEchoLink::onCommandPtyInput */
void ModuleEchoLink::moduleCleanup(void)
{
@ -584,8 +682,8 @@ void ModuleEchoLink::moduleCleanup(void)
* Output: None
* Author: Tobias Blomberg / SM0SVX
* Created: 2004-03-07
* Remarks:
* Bugs:
* Remarks:
* Bugs:
*----------------------------------------------------------------------------
*/
void ModuleEchoLink::activateInit(void)
@ -606,7 +704,7 @@ void ModuleEchoLink::activateInit(void)
* Created: 2004-03-07
* Remarks: Do NOT call this function directly unless you really know what
* you are doing. Use Module::deactivate() instead.
* Bugs:
* Bugs:
*----------------------------------------------------------------------------
*/
void ModuleEchoLink::deactivateCleanup(void)
@ -643,8 +741,8 @@ void ModuleEchoLink::deactivateCleanup(void)
* Output: Return true if the digit is handled or false if not
* Author: Tobias Blomberg / SM0SVX
* Created: 2004-03-07
* Remarks:
* Bugs:
* Remarks:
* Bugs:
*----------------------------------------------------------------------------
*/
#if 0
@ -669,8 +767,8 @@ bool ModuleEchoLink::dtmfDigitReceived(char digit, int duration)
* Output: None
* Author: Tobias Blomberg / SM0SVX
* Created: 2004-03-07
* Remarks:
* Bugs:
* Remarks:
* Bugs:
*----------------------------------------------------------------------------
*/
void ModuleEchoLink::dtmfCmdReceived(const string& cmd)
@ -746,8 +844,8 @@ void ModuleEchoLink::dtmfCmdReceivedWhenIdle(const std::string &cmd)
* Output: None
* Author: Tobias Blomberg / SM0SVX
* Created: 2004-03-07
* Remarks:
* Bugs:
* Remarks:
* Bugs:
*----------------------------------------------------------------------------
*/
void ModuleEchoLink::squelchOpen(bool is_open)
@ -757,7 +855,7 @@ void ModuleEchoLink::squelchOpen(bool is_open)
squelch_is_open = is_open;
if (listen_only_valve->isOpen())
{
broadcastTalkerStatus();
broadcastTalkerStatus();
}
for (vector<QsoImpl*>::iterator it=qsos.begin(); it!=qsos.end(); ++it)
@ -776,8 +874,8 @@ void ModuleEchoLink::squelchOpen(bool is_open)
* Output: None
* Author: Tobias Blomberg / SM0SVX
* Created: 2004-05-22
* Remarks:
* Bugs:
* Remarks:
* Bugs:
*----------------------------------------------------------------------------
*/
void ModuleEchoLink::allMsgsWritten(void)
@ -806,8 +904,8 @@ void ModuleEchoLink::allMsgsWritten(void)
* Output: None
* Author: Tobias Blomberg / SM0SVX
* Created: 2004-03-07
* Remarks:
* Bugs:
* Remarks:
* Bugs:
*----------------------------------------------------------------------------
*/
void ModuleEchoLink::onStatusChanged(StationData::Status status)
@ -847,8 +945,8 @@ void ModuleEchoLink::onStatusChanged(StationData::Status status)
* Output: None
* Author: Tobias Blomberg / SM0SVX
* Created: 2004-03-07
* Remarks:
* Bugs:
* Remarks:
* Bugs:
*----------------------------------------------------------------------------
*/
void ModuleEchoLink::onStationListUpdated(void)
@ -889,8 +987,8 @@ void ModuleEchoLink::onStationListUpdated(void)
* Output: None
* Author: Tobias Blomberg / SM0SVX
* Created: 2004-03-07
* Remarks:
* Bugs:
* Remarks:
* Bugs:
*----------------------------------------------------------------------------
*/
void ModuleEchoLink::onError(const string& msg)
@ -907,6 +1005,34 @@ void ModuleEchoLink::onError(const string& msg)
} /* onError */
/*
*----------------------------------------------------------------------------
* Method: clientListChanged
* Purpose: Called on connect or disconnect of a remote client to send an
* event to list the connected stations.
* Input: None
* Output: None
* Author: Wim Fournier / PH7WIM
* Created: 2016-01-11
* Remarks:
* Bugs:
*----------------------------------------------------------------------------
*/
void ModuleEchoLink::clientListChanged(void)
{
stringstream ss;
ss << "client_list_changed [list";
for (vector<QsoImpl *>::iterator it = qsos.begin(); it != qsos.end(); ++it)
{
if ((*it)->currentState() != Qso::STATE_DISCONNECTED)
{
ss << " " << (*it)->remoteCallsign();
}
}
ss << "]";
processEvent(ss.str());
} /* clientListChanged */
/*
*----------------------------------------------------------------------------
@ -919,8 +1045,8 @@ void ModuleEchoLink::onError(const string& msg)
* Output: None
* Author: Tobias Blomberg / SM0SVX
* Created: 2004-03-07
* Remarks:
* Bugs:
* Remarks:
* Bugs:
*----------------------------------------------------------------------------
*/
void ModuleEchoLink::onIncomingConnection(const IpAddress& ip,
@ -990,6 +1116,8 @@ void ModuleEchoLink::onIncomingConnection(const IpAddress& ip,
qso->stateChange.connect(mem_fun(*this, &ModuleEchoLink::onStateChange));
qso->chatMsgReceived.connect(
mem_fun(*this, &ModuleEchoLink::onChatMsgReceived));
qso->infoMsgReceived.connect(
mem_fun(*this, &ModuleEchoLink::onInfoMsgReceived));
qso->isReceiving.connect(mem_fun(*this, &ModuleEchoLink::onIsReceiving));
qso->audioReceivedRaw.connect(
mem_fun(*this, &ModuleEchoLink::audioFromRemoteRaw));
@ -1062,8 +1190,8 @@ void ModuleEchoLink::onIncomingConnection(const IpAddress& ip,
* Output: None
* Author: Tobias Blomberg / SM0SVX
* Created: 2006-03-12
* Remarks:
* Bugs:
* Remarks:
* Bugs:
*----------------------------------------------------------------------------
*/
void ModuleEchoLink::onStateChange(QsoImpl *qso, Qso::State qso_state)
@ -1097,13 +1225,19 @@ void ModuleEchoLink::onStateChange(QsoImpl *qso, Qso::State qso_state)
broadcastTalkerStatus();
updateDescription();
clientListChanged();
break;
}
case Qso::STATE_CONNECTED:
updateEventVariables();
clientListChanged();
break;
default:
updateEventVariables();
break;
}
}
} /* ModuleEchoLink::onStateChange */
@ -1117,8 +1251,8 @@ void ModuleEchoLink::onStateChange(QsoImpl *qso, Qso::State qso_state)
* Output: None
* Author: Tobias Blomberg / SM0SVX
* Created: 2004-05-04
* Remarks:
* Bugs:
* Remarks:
* Bugs:
*----------------------------------------------------------------------------
*/
void ModuleEchoLink::onChatMsgReceived(QsoImpl *qso, const string& msg)
@ -1151,6 +1285,37 @@ void ModuleEchoLink::onChatMsgReceived(QsoImpl *qso, const string& msg)
} /* onChatMsgReceived */
/*
*----------------------------------------------------------------------------
* Method: onInfoMsgReceived
* Purpose: Called by the EchoLink::Qso object when a info message has been
* received from the remote station.
* Input: qso - The QSO object
* msg - The received message
* Output: None
* Author: Tobias Blomberg / SM0SVX
* Created: 2017-05-13
* Remarks:
* Bugs:
*----------------------------------------------------------------------------
*/
void ModuleEchoLink::onInfoMsgReceived(QsoImpl *qso, const string& msg)
{
// Escape TCL control characters
string escaped(msg);
replaceAll(escaped, "\\", "\\\\");
replaceAll(escaped, "{", "\\{");
replaceAll(escaped, "}", "\\}");
stringstream ss;
// FIXME: This TCL specific code should not be here
ss << "info_received \"" << qso->remoteCallsign()
<< "\" [subst -nocommands -novariables {";
ss << escaped;
ss << "}]";
processEvent(ss.str());
} /* onInfoMsgReceived */
/*
*----------------------------------------------------------------------------
* Method: onIsReceiving
@ -1162,8 +1327,8 @@ void ModuleEchoLink::onChatMsgReceived(QsoImpl *qso, const string& msg)
* Output: None
* Author: Tobias Blomberg / SM0SVX
* Created: 2004-03-07
* Remarks:
* Bugs:
* Remarks:
* Bugs:
*----------------------------------------------------------------------------
*/
void ModuleEchoLink::onIsReceiving(bool is_receiving, QsoImpl *qso)
@ -1172,7 +1337,8 @@ void ModuleEchoLink::onIsReceiving(bool is_receiving, QsoImpl *qso)
// << (is_receiving ? "TRUE" : "FALSE") << endl;
stringstream ss;
ss << "is_receiving " << (is_receiving ? "1" : "0");
ss << "is_receiving " << (is_receiving ? "1" : "0")
<< " " << qso->remoteCallsign();
processEvent(ss.str());
if ((talker == 0) && is_receiving)
@ -1260,8 +1426,8 @@ void ModuleEchoLink::destroyQsoObject(QsoImpl *qso)
* Output: None
* Author: Tobias Blomberg / SM0SVX
* Created: 2004-03-07
* Remarks:
* Bugs:
* Remarks:
* Bugs:
*----------------------------------------------------------------------------
*/
void ModuleEchoLink::getDirectoryList(Timer *timer)
@ -1350,12 +1516,14 @@ void ModuleEchoLink::createOutgoingConnection(const StationData &station)
return;
}
qsos.push_back(qso);
updateEventVariables();
updateEventVariables();
qso->setRemoteCallsign(station.callsign());
qso->setListenOnly(!listen_only_valve->isOpen());
qso->stateChange.connect(mem_fun(*this, &ModuleEchoLink::onStateChange));
qso->chatMsgReceived.connect(
mem_fun(*this, &ModuleEchoLink::onChatMsgReceived));
qso->infoMsgReceived.connect(
mem_fun(*this, &ModuleEchoLink::onInfoMsgReceived));
qso->isReceiving.connect(mem_fun(*this, &ModuleEchoLink::onIsReceiving));
qso->audioReceivedRaw.connect(
mem_fun(*this, &ModuleEchoLink::audioFromRemoteRaw));
@ -1955,7 +2123,7 @@ void ModuleEchoLink::checkIdle(void)
* Bugs:
*----------------------------------------------------------------------------
*/
void ModuleEchoLink::checkAutoCon(Timer *)
void ModuleEchoLink::checkAutoCon(Timer *)
{
// Only try to activate the link if we are online and not
// currently connected to any station. A connection will only be attempted
@ -2008,8 +2176,8 @@ bool ModuleEchoLink::numConCheck(const std::string &callsign)
char time_str[64];
strftime(time_str, sizeof(time_str), "%c", localtime(&next));
cerr << "*** WARNING: Ingnoring incoming connection because "
<< "the station (" << callsign << ") has connected "
<< "to often (" << stn.num_con << " times). "
<< "the station (" << callsign << ") has connected "
<< "to often (" << stn.num_con << " times). "
<< "Next connect is possible after " << time_str << ".\n";
return false;
}

View file

@ -62,6 +62,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "version/SVXLINK.h"
#include "BrandMeisterBridge.h"
/****************************************************************************
*
* Forward declarations
@ -74,6 +75,7 @@ namespace Async
class AudioSplitter;
class AudioValve;
class AudioSelector;
class Pty;
};
namespace EchoLink
{
@ -152,9 +154,7 @@ class ModuleEchoLink : public Module
private:
BrandMeisterBridge bridge;
typedef enum
{
STATE_NORMAL,
@ -212,6 +212,8 @@ class ModuleEchoLink : public Module
int autocon_time;
Async::Timer *autocon_timer;
EchoLink::Proxy *proxy;
Async::Pty *pty;
std::string command_buf;
void moduleCleanup(void);
void activateInit(void);
@ -222,15 +224,19 @@ class ModuleEchoLink : public Module
void squelchOpen(bool is_open);
int audioFromRx(float *samples, int count);
void allMsgsWritten(void);
void handlePtyCommand(const std::string &full_command);
void onCommandPtyInput(const void *buf, size_t count);
void onStatusChanged(EchoLink::StationData::Status status);
void onStationListUpdated(void);
void onError(const std::string& msg);
void clientListChanged(void);
void onIncomingConnection(const Async::IpAddress& ip,
const std::string& callsign, const std::string& name,
const std::string& priv);
void onStateChange(QsoImpl *qso, EchoLink::Qso::State qso_state);
void onChatMsgReceived(QsoImpl *qso, const std::string& msg);
void onInfoMsgReceived(QsoImpl *qso, const std::string& msg);
void onIsReceiving(bool is_receiving, QsoImpl *qso);
void destroyQsoObject(QsoImpl *qso);