diff --git a/src/MultiPlayer/cpdlc.cxx b/src/MultiPlayer/cpdlc.cxx index 6a534ea23..f9f93e664 100644 --- a/src/MultiPlayer/cpdlc.cxx +++ b/src/MultiPlayer/cpdlc.cxx @@ -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); } diff --git a/src/MultiPlayer/cpdlc.hxx b/src/MultiPlayer/cpdlc.hxx index 8a26011cf..335993dcd 100644 --- a/src/MultiPlayer/cpdlc.hxx +++ b/src/MultiPlayer/cpdlc.hxx @@ -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, diff --git a/src/MultiPlayer/mpirc.cxx b/src/MultiPlayer/mpirc.cxx index 20506b05c..182a55b1e 100644 --- a/src/MultiPlayer/mpirc.cxx +++ b/src/MultiPlayer/mpirc.cxx @@ -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; } diff --git a/src/MultiPlayer/mpirc.hxx b/src/MultiPlayer/mpirc.hxx index d3b2f5fca..28e9e8e3b 100644 --- a/src/MultiPlayer/mpirc.hxx +++ b/src/MultiPlayer/mpirc.hxx @@ -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}; diff --git a/src/MultiPlayer/multiplaymgr.cxx b/src/MultiPlayer/multiplaymgr.cxx index 84b8b9273..8ac674fc6 100644 --- a/src/MultiPlayer/multiplaymgr.cxx +++ b/src/MultiPlayer/multiplaymgr.cxx @@ -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); diff --git a/src/MultiPlayer/multiplaymgr.hxx b/src/MultiPlayer/multiplaymgr.hxx index 6b2a36ef0..651a4bbc7 100644 --- a/src/MultiPlayer/multiplaymgr.hxx +++ b/src/MultiPlayer/multiplaymgr.hxx @@ -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"};