1
0
Fork 0

CPDLC updates from Henning

This commit is contained in:
James Turner 2021-01-04 09:57:38 +00:00
parent 527f58d353
commit af387107a3
6 changed files with 75 additions and 57 deletions

View file

@ -26,6 +26,11 @@
#include "cpdlc.hxx"
#include <Main/fg_props.hxx>
const std::string CPDLC_IRC_SERVER {"mpirc.flightgear.org"};
const std::string CPDLC_MSGPREFIX_CONNECT {"___CPDLC_CONNECT___"};
const std::string CPDLC_MSGPREFIX_MSG {"___CPDLC_MSG___"};
const std::string CPDLC_MSGPREFIX_DISCONNECT {"___CPDLC_DISCONNECT___"};
///////////////////////////////////////////////////////////////////////////////
// CPDLCManager
///////////////////////////////////////////////////////////////////////////////
@ -65,29 +70,30 @@ bool CPDLCManager::connect(const std::string authority = "")
{
// ensure we get an authority on first call but do not accept a change before
// resetting _data_authority in disconnect()
if (!_data_authority.size()) {
if (!authority.size()) {
if (_data_authority.empty()) {
if (authority.empty()) {
SG_LOG(SG_NETWORK, SG_WARN, "cpdlcConnect not possible: empty argument!");
return false;
} else {
_data_authority = authority;
}
}
if (authority.size() && authority != _data_authority) {
if (!authority.empty() && authority != _data_authority) {
SG_LOG(SG_NETWORK, SG_WARN, "cpdlcConnect: cannot change authority now, use disconnect first!");
return false;
}
// launch IRC connection as needed
if (!_irc->isConnected()) {
SG_LOG(SG_NETWORK, SG_DEV_WARN, "Connecting to IRC server...");
SG_LOG(SG_NETWORK, SG_INFO, "Connecting to IRC server...");
if (!_irc->login()) {
SG_LOG(SG_NETWORK, SG_WARN, "IRC login failed.");
return false;
}
_status = CPDLC_WAIT_IRC_READY;
return true;
} else if (_irc->isReady() && _status != CPDLC_ONLINE) {
SG_LOG(SG_NETWORK, SG_DEV_WARN, "CPDLC send connect");
SG_LOG(SG_NETWORK, SG_INFO, "CPDLC sending 'connect'");
_status = CPDLC_CONNECTING;
_pStatus->setIntValue(_status);
return _irc->sendPrivmsg(_data_authority, CPDLC_MSGPREFIX_CONNECT);
@ -97,7 +103,7 @@ bool CPDLCManager::connect(const std::string authority = "")
void CPDLCManager::disconnect()
{
if (_irc && _irc->isConnected() && _data_authority.size()) {
if (_irc && _irc->isConnected() && !_data_authority.empty()) {
_irc->sendPrivmsg(_data_authority, CPDLC_MSGPREFIX_DISCONNECT);
}
_data_authority = "";
@ -137,7 +143,7 @@ void CPDLCManager::update()
if (_irc) {
if (_irc->isConnected()) {
if (_status == CPDLC_WAIT_IRC_READY && _irc->isReady()) {
SG_LOG(SG_NETWORK, SG_DEV_WARN, "CPDLC IRC ready, connecting...");
SG_LOG(SG_NETWORK, SG_INFO, "CPDLC IRC ready, connecting...");
connect();
}
if (_irc->hasMessage()) {
@ -155,9 +161,9 @@ void CPDLCManager::update()
// process incoming message
void CPDLCManager::processMessage(struct IRCMessage message)
{
SG_LOG(SG_NETWORK, SG_INFO, "CPDLC message");
// connection accepted by ATC, or new data authority (been transferred)
if (message.textline.find(CPDLC_MSGPREFIX_CONNECT) == 0) {
SG_LOG(SG_NETWORK, SG_INFO, "CPDLC got connected.");
_data_authority = message.sender;
_pDataAuthority->setStringValue(_data_authority); // make this known to ACFT
_status = CPDLC_ONLINE;
@ -171,11 +177,13 @@ void CPDLCManager::processMessage(struct IRCMessage message)
// connection rejected, or terminated by ATC
if (message.textline.find(CPDLC_MSGPREFIX_DISCONNECT) == 0) {
if (message.sender == _data_authority) {
SG_LOG(SG_NETWORK, SG_INFO, "CPDLC got disconnect.");
disconnect();
}
}
// store valid message in queue for later retrieval by aircraft
else if (message.textline.find(CPDLC_MSGPREFIX_MSG) == 0) {
SG_LOG(SG_NETWORK, SG_INFO, "CPDLC message");
_incoming_messages.push_back(message);
_pNewMessage->setBoolValue(1);
}

View file

@ -35,12 +35,6 @@
#include <simgear/io/sg_socket.hxx>
#include "mpirc.hxx"
const std::string CPDLC_IRC_SERVER {"mpirc.flightgear.org"};
const std::string CPDLC_MSGPREFIX_CONNECT {"___CPDLC_CONNECT___"};
const std::string CPDLC_MSGPREFIX_MSG {"___CPDLC_MSG___"};
const std::string CPDLC_MSGPREFIX_DISCONNECT {"___CPDLC_DISCONNECT___"};
enum CPDLCStatus {
CPDLC_OFFLINE,
CPDLC_CONNECTING,

View file

@ -27,8 +27,16 @@
#include <Main/fg_props.hxx>
const std::string IRC_TEST_CHANNEL{"#mptest"}; // for development
const std::string IRC_MSG_TERMINATOR {"\r\n"};
// https://www.alien.net.au/irc/irc2numerics.html
const std::string IRC_RPL_WELCOME {"001"};
const std::string IRC_RPL_YOURID {"042"};
const std::string IRC_RPL_MOTD {"372"};
const std::string IRC_RPL_MOTDSTART {"375"};
const std::string IRC_RPL_ENDOFMOTD {"376"};
const std::string IRC_ERR_NOSUCHNICK {"401"};
IRCConnection::IRCConnection(const std::string nickname, const std::string servername, const std::string port) : SGSocket(servername, port, "tcp"),
IRCConnection::IRCConnection(const std::string &nickname, const std::string &servername, const std::string &port) : SGSocket(servername, port, "tcp"),
_nickname(nickname)
{
}
@ -50,14 +58,15 @@ void IRCConnection::setupProperties(std::string path)
}
bool IRCConnection::login(const std::string nickname)
bool IRCConnection::login(const std::string &nickname)
{
if (!_connected && !connect()) {
return false;
}
if (nickname.length()) {
if (!nickname.empty()) {
_nickname = nickname;
} else {
SG_LOG(SG_NETWORK, SG_WARN, "IRC login requires nickname argument.");
return false;
}
@ -86,9 +95,12 @@ void IRCConnection::quit()
disconnect();
}
bool IRCConnection::sendPrivmsg(const std::string recipient, const std::string textline)
bool IRCConnection::sendPrivmsg(const std::string &recipient, const std::string &textline)
{
if (!_logged_in) return false;
if (!_logged_in) {
SG_LOG(SG_NETWORK, SG_WARN, "IRC 'privmsg' command unvailable. Login first!");
return false;
}
std::string line("PRIVMSG ");
line += recipient;
line += " :";
@ -99,14 +111,18 @@ bool IRCConnection::sendPrivmsg(const std::string recipient, const std::string t
if (_pIRCReturnCode) _pIRCReturnCode->setStringValue("");
return true;
} else {
SG_LOG(SG_NETWORK, SG_WARN, "IRC send privmsg failed.");
return false;
}
}
// join an IRC channel
bool IRCConnection::join(const std::string channel)
bool IRCConnection::join(const std::string &channel)
{
if (!_logged_in) return false;
if (!_logged_in) {
SG_LOG(SG_NETWORK, SG_WARN, "IRC 'join' command unvailable. Login first!");
return false;
}
std::string lines("JOIN ");
lines += channel;
lines += IRC_MSG_TERMINATOR;
@ -114,9 +130,12 @@ bool IRCConnection::join(const std::string channel)
}
// leave an IRC channel
bool IRCConnection::part(const std::string channel)
bool IRCConnection::part(const std::string &channel)
{
if (!_logged_in) return false;
if (!_logged_in) {
SG_LOG(SG_NETWORK, SG_WARN, "IRC 'part' command unvailable. Login first!");
return false;
}
std::string lines("PART ");
lines += channel;
lines += IRC_MSG_TERMINATOR;
@ -145,7 +164,9 @@ void IRCConnection::update()
// open a connection to IRC server
bool IRCConnection::connect()
{
if (_connected) return false;
if (_connected) {
return true;
}
_connected = open(SG_IO_OUT);
if (_connected) {
@ -168,7 +189,8 @@ void IRCConnection::disconnect()
SG_LOG(SG_NETWORK, SG_INFO, "IRCConnection::disconnect");
}
}
void IRCConnection::pong(const std::string recipient)
void IRCConnection::pong(const std::string &recipient)
{
if (!_connected) return;
std::string line("PONG ");
@ -287,6 +309,7 @@ bool IRCConnection::parseReceivedLine(std::string line)
// TODO: anything sensitive here that we should handle?
// e.g. IRC user has disconnected and username == {current-cpdlc-authority}
return false;
}
return true;
}

View file

@ -35,15 +35,6 @@
#include <simgear/io/sg_socket.hxx>
const std::string IRC_DEFAULT_PORT {"6667"};
const std::string IRC_MSG_TERMINATOR {"\r\n"};
// https://www.alien.net.au/irc/irc2numerics.html
const std::string IRC_RPL_WELCOME {"001"};
const std::string IRC_RPL_YOURID {"042"};
const std::string IRC_RPL_MOTD {"372"};
const std::string IRC_RPL_MOTDSTART {"375"};
const std::string IRC_RPL_ENDOFMOTD {"376"};
const std::string IRC_ERR_NOSUCHNICK {"401"};
const int IRC_BUFFER_SIZE = 1024;
struct IRCMessage {
@ -64,19 +55,19 @@ struct IRCMessage {
class IRCConnection : SGSocket
{
public:
IRCConnection(const std::string nickname, const std::string servername, const std::string port = IRC_DEFAULT_PORT);
IRCConnection(const std::string &nickname, const std::string &servername, const std::string &port = IRC_DEFAULT_PORT);
~IRCConnection();
void setupProperties(const std::string path);
void setupProperties(std::string path);
void update();
bool login(const std::string nickname);
bool login(const std::string &nickname);
bool login();
void quit();
bool sendPrivmsg(const std::string recipient, const std::string textline);
bool join(const std::string channel);
bool part(const std::string channel);
bool sendPrivmsg(const std::string &recipient, const std::string &textline);
bool join(const std::string &channel);
bool part(const std::string &channel);
bool isConnected() const { return _connected; }
@ -87,14 +78,14 @@ public:
private:
bool connect();
void disconnect();
void pong(const std::string recipient);
void pong(const std::string &recipient);
bool parseReceivedLine(std::string irc_line);
bool _connected {false}; // TCP session ok
bool _logged_in {false}; // IRC login completed
std::string _nickname {""};
char _read_buffer[IRC_BUFFER_SIZE];
std::deque<struct IRCMessage> _incoming_private_messages;
std::deque<IRCMessage> _incoming_private_messages;
SGPropertyNode *_pReadyFlag {nullptr};
SGPropertyNode *_pMessageCountIn {nullptr};

View file

@ -54,6 +54,8 @@
#include <FDM/flightProperties.hxx>
#include <Time/TimeManager.hxx>
#include <Main/sentryIntegration.hxx>
#include "mpirc.hxx"
#include "cpdlc.hxx"
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <WS2tcpip.h>
@ -836,7 +838,7 @@ static inline bool IsIncludedInPacket(int filter_base, int property_id)
// rxport: incoming port number (default: 5000)
//////////////////////////////////////////////////////////////////////
static bool do_multiplayer_connect(const SGPropertyNode * arg, SGPropertyNode * root) {
FGMultiplayMgr * self = (FGMultiplayMgr*) globals->get_subsystem("mp");
const auto self = globals->get_subsystem<FGMultiplayMgr>();
if (!self) {
SG_LOG(SG_NETWORK, SG_WARN, "Multiplayer subsystem not available.");
return false;
@ -871,7 +873,7 @@ static bool do_multiplayer_connect(const SGPropertyNode * arg, SGPropertyNode *
// none
//////////////////////////////////////////////////////////////////////
static bool do_multiplayer_disconnect(const SGPropertyNode * arg, SGPropertyNode * root) {
FGMultiplayMgr * self = (FGMultiplayMgr*) globals->get_subsystem("mp");
const auto self = globals->get_subsystem<FGMultiplayMgr>();
if (!self) {
SG_LOG(SG_NETWORK, SG_WARN, "Multiplayer subsystem not available.");
return false;
@ -895,7 +897,7 @@ do_multiplayer_refreshserverlist (const SGPropertyNode * arg, SGPropertyNode * r
{
using namespace simgear;
FGMultiplayMgr * self = (FGMultiplayMgr*) globals->get_subsystem ("mp");
const auto self = globals->get_subsystem<FGMultiplayMgr>();
if (!self) {
SG_LOG(SG_NETWORK, SG_WARN, "Multiplayer subsystem not available.");
return false;
@ -953,7 +955,7 @@ do_multiplayer_refreshserverlist (const SGPropertyNode * arg, SGPropertyNode * r
static bool do_cpdlc_connect(const SGPropertyNode* arg, SGPropertyNode* root)
{
FGMultiplayMgr* self = (FGMultiplayMgr*)globals->get_subsystem("mp");
const auto self = globals->get_subsystem<FGMultiplayMgr>();
if (!self) {
SG_LOG(SG_NETWORK, SG_WARN, "Multiplayer subsystem not available.");
return false;
@ -962,9 +964,9 @@ static bool do_cpdlc_connect(const SGPropertyNode* arg, SGPropertyNode* root)
// check for atc argument
std::string authority = arg->getStringValue("atc");
// otherwise see if we got a property name to read out
if (!authority.size()) {
if (authority.empty()) {
std::string name = arg->getStringValue("property");
if (name.size()) {
if (!name.empty()) {
SGPropertyNode* pNode = globals->get_props()->getNode(name);
if (!pNode) { return false; }
authority = pNode->getStringValue();
@ -979,7 +981,7 @@ static bool do_cpdlc_connect(const SGPropertyNode* arg, SGPropertyNode* root)
static bool do_cpdlc_send_msg(const SGPropertyNode* arg, SGPropertyNode* root)
{
FGMultiplayMgr* self = (FGMultiplayMgr*)globals->get_subsystem("mp");
const auto self = globals->get_subsystem<FGMultiplayMgr>();
if (!self) {
SG_LOG(SG_NETWORK, SG_WARN, "Multiplayer subsystem not available.");
return false;
@ -988,9 +990,9 @@ static bool do_cpdlc_send_msg(const SGPropertyNode* arg, SGPropertyNode* root)
// check for message argument
std::string message = arg->getStringValue("message");
// otherwise see if we got a property name to read out
if (!message.size()) {
if (message.empty()) {
std::string name = arg->getStringValue("property");
if (name.size()) {
if (!name.empty()) {
SGPropertyNode* pNode = globals->get_props()->getNode(name);
if (!pNode) { return false; }
message = pNode->getStringValue();
@ -1004,7 +1006,7 @@ static bool do_cpdlc_send_msg(const SGPropertyNode* arg, SGPropertyNode* root)
static bool do_cpdlc_next_msg(const SGPropertyNode* arg, SGPropertyNode* root)
{
FGMultiplayMgr* self = (FGMultiplayMgr*)globals->get_subsystem("mp");
const auto self = globals->get_subsystem<FGMultiplayMgr>();
if (!self) {
SG_LOG(SG_NETWORK, SG_WARN, "Multiplayer subsystem not available.");
return false;
@ -1015,7 +1017,7 @@ static bool do_cpdlc_next_msg(const SGPropertyNode* arg, SGPropertyNode* root)
static bool do_cpdlc_disconnect(const SGPropertyNode* arg, SGPropertyNode* root)
{
FGMultiplayMgr* self = (FGMultiplayMgr*)globals->get_subsystem("mp");
const auto self = globals->get_subsystem<FGMultiplayMgr>();
if (!self) {
SG_LOG(SG_NETWORK, SG_WARN, "Multiplayer subsystem not available.");
return false;
@ -1178,8 +1180,8 @@ FGMultiplayMgr::init (void)
}
// MP IRC CONNECTION SETUP
std::string host = fgHasNode(MPIRC_SERVER_HOST_PROPERTY) ? fgGetString(MPIRC_SERVER_HOST_PROPERTY) : MPIRC_SERVER_HOST_DEFAULT;
std::string port = fgHasNode(MPIRC_SERVER_PORT_PROPERTY) ? fgGetString(MPIRC_SERVER_PORT_PROPERTY) : IRC_DEFAULT_PORT;
std::string host = fgGetString(MPIRC_SERVER_HOST_PROPERTY, MPIRC_SERVER_HOST_DEFAULT);
std::string port = fgGetString(MPIRC_SERVER_PORT_PROPERTY, IRC_DEFAULT_PORT);
SG_LOG(SG_NETWORK, SG_DEBUG, "Creating socket to MP IRC service " + host + " on port " + port);
_mpirc = std::make_unique<IRCConnection>(MPIRC_NICK_PREFIX + mCallsign, host, port);

View file

@ -44,8 +44,8 @@ const int MAX_MP_PROTOCOL_VERSION = 2;
#include <simgear/io/raw_socket.hxx>
#include <simgear/structure/subsystem_mgr.hxx>
#include "mpirc.hxx"
#include "cpdlc.hxx"
class IRCConnection;
class CPDLCManager;
const std::string MPIRC_SERVER_HOST_DEFAULT {"mpirc.flightgear.org"};
const std::string MPIRC_SERVER_HOST_PROPERTY {"/network/mpirc/server-host"};