Skip to content

Commit

Permalink
Negotiate and store MSSP data in Lua table (Mudlet#3025)
Browse files Browse the repository at this point in the history
  • Loading branch information
mpconley authored and vadi2 committed Aug 26, 2019
1 parent a8db98e commit b3133ef
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/Host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ Host::Host(int port, const QString& hostname, const QString& login, const QStrin
, mCommandSeparator(QLatin1String(";;"))
, mDisplayFont(QFont("Bitstream Vera Sans Mono", 10, QFont::Normal))
, mEnableGMCP(true)
, mEnableMSSP(true)
, mEnableMSDP(false)
, mServerMXPenabled(true)
, mFORCE_GA_OFF(false)
Expand Down
1 change: 1 addition & 0 deletions src/Host.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ class Host : public QObject
QFont mCommandLineFont;
QString mCommandSeparator;
bool mEnableGMCP;
bool mEnableMSSP;
bool mEnableMSDP;
bool mServerMXPenabled;
QTextStream mErrorLogStream;
Expand Down
79 changes: 79 additions & 0 deletions src/TLuaInterpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13627,6 +13627,23 @@ void TLuaInterpreter::setGMCPTable(QString& key, const QString& string_data)
parseJSON(key, string_data, QLatin1String("gmcp"));
}

// No documentation available in wiki - internal function
void TLuaInterpreter::setMSSPTable(const QString& string_data)
{
lua_State* L = pGlobalLua;
lua_getglobal(L, "mssp"); //defined in Lua init
if (!lua_istable(L, -1)) {
lua_newtable(L);
lua_setglobal(L, "mssp");
lua_getglobal(L, "mssp");
if (!lua_istable(L, -1)) {
qDebug() << "ERROR: mssp table not defined";
return;
}
}
parseMSSP(string_data);
}

// No documentation available in wiki - internal function
void TLuaInterpreter::setMSDPTable(QString& key, const QString& string_data)
{
Expand Down Expand Up @@ -13773,6 +13790,68 @@ void TLuaInterpreter::parseJSON(QString& key, const QString& string_data, const
lua_pop(L, lua_gettop(L));
}

// No documentation available in wiki - internal function
void TLuaInterpreter::parseMSSP(const QString& string_data)
{
lua_State* L = pGlobalLua;

if (!L) {
qDebug() << "LUA CRITICAL ERROR: no suitable Lua execution unit found.";
return;
}

// string_data is in the format of MSSP_VAR "PLAYERS" MSSP_VAL "52" MSSP_VAR "UPTIME" MSSP_VAL "1234567890"
// The quote characters mean that the encased word is a string, the quotes themselves are not sent.
QStringList packageList = string_data.split(MSSP_VAR);

if (packageList.size() > 0) {
Host& host = getHostFromLua(L);
lua_getglobal(L, "mssp");

for (int i = 1; i < packageList.size(); i++) {
QStringList payloadList = packageList[i].split(MSSP_VAL);

if (payloadList.size() != 2) {
return;
}

QString msspVAR;
QString msspVAL;

for (int j = 0; j < payloadList.size(); j++) {
if (j < 1) {
msspVAR = payloadList[j];
lua_pushstring(L, msspVAR.toUtf8().constData());
} else {
msspVAL = payloadList[j];
lua_pushlstring(L, msspVAL.toUtf8().constData(), msspVAL.toUtf8().length());
}
}

lua_rawset(L, -3);

// Raise an event
QString protocol = QStringLiteral("mssp");
QString token = protocol;
token.append(".");
token.append(msspVAR);

TEvent event {};
event.mArgumentList.append(token);
event.mArgumentTypeList.append(ARGUMENT_TYPE_STRING);
event.mArgumentList.append(token);
event.mArgumentTypeList.append(ARGUMENT_TYPE_STRING);
if (mudlet::debugMode) {
QString msg = QStringLiteral("\n%1 event <%2> display(%1) to see the full content\n").arg(protocol, token);
host.mpConsole->printSystemMessage(msg);
}
host.raiseEvent(event);
}

lua_pop(L, lua_gettop(L));
}
}

// No documentation available in wiki - internal function
// src is in Mud Server encoding and may need transcoding
void TLuaInterpreter::msdp2Lua(const char* src)
Expand Down
2 changes: 2 additions & 0 deletions src/TLuaInterpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class TLuaInterpreter : public QThread
~TLuaInterpreter();
void setMSDPTable(QString& key, const QString& string_data);
void parseJSON(QString& key, const QString& string_data, const QString& protocol);
void parseMSSP(const QString& string_data);
void msdp2Lua(const char*);
void initLuaGlobals();
void initIndenterGlobals();
Expand All @@ -91,6 +92,7 @@ class TLuaInterpreter : public QThread
bool compileScript(const QString&);
void setAtcpTable(const QString&, const QString&);
void setGMCPTable(QString&, const QString&);
void setMSSPTable(const QString&);
void setChannel102Table(int& var, int& arg);
bool compileAndExecuteScript(const QString&);
QString formatLuaCode(const QString &);
Expand Down
1 change: 1 addition & 0 deletions src/XMLexport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ void XMLexport::writeHost(Host* pHost, pugi::xml_node mudletPackage)
host.append_attribute("mFORCE_GA_OFF") = pHost->mFORCE_GA_OFF ? "yes" : "no";
host.append_attribute("mFORCE_SAVE_ON_EXIT") = pHost->mFORCE_SAVE_ON_EXIT ? "yes" : "no";
host.append_attribute("mEnableGMCP") = pHost->mEnableGMCP ? "yes" : "no";
host.append_attribute("mEnableMSSP") = pHost->mEnableMSSP ? "yes" : "no";
host.append_attribute("mEnableMSDP") = pHost->mEnableMSDP ? "yes" : "no";
host.append_attribute("mMapStrongHighlight") = pHost->mMapStrongHighlight ? "yes" : "no";
host.append_attribute("mLogStatus") = pHost->mLogStatus ? "yes" : "no";
Expand Down
3 changes: 3 additions & 0 deletions src/XMLimport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,9 @@ void XMLimport::readHostPackage(Host* pHost)
pHost->mFORCE_GA_OFF = (attributes().value("mFORCE_GA_OFF") == "yes");
pHost->mFORCE_SAVE_ON_EXIT = (attributes().value("mFORCE_SAVE_ON_EXIT") == "yes");
pHost->mEnableGMCP = (attributes().value("mEnableGMCP") == "yes");
if (attributes().hasAttribute(QLatin1String("mEnableMSSP"))) {
pHost->mEnableMSSP = (attributes().value(QStringLiteral("mEnableMSSP")) == "yes");
}
pHost->mEnableMSDP = (attributes().value("mEnableMSDP") == "yes");
pHost->mMapStrongHighlight = (attributes().value("mMapStrongHighlight") == "yes");
pHost->mLogStatus = (attributes().value("mLogStatus") == "yes");
Expand Down
70 changes: 70 additions & 0 deletions src/ctelnet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ cTelnet::cTelnet(Host* pH, const QString& profileName)
, lastTimeOffset()
, enableATCP(false)
, enableGMCP(false)
, enableMSSP(false)
, enableChannel102(false)
, mAutoReconnect(false)
, loadingReplay(false)
Expand Down Expand Up @@ -1034,6 +1035,18 @@ void cTelnet::processTelnetCommand(const std::string& command)
break;
}

if (option == OPT_MSSP) {
if (!mpHost->mEnableMSSP) {
break;
}

enableMSSP = true;
sendTelnetOption(TN_DO, OPT_MSSP);
qDebug() << "MSSP enabled";
raiseProtocolEvent("sysProtocolEnabled", "MSSP");
break;
}

if (option == OPT_MXP) {
if (!mpHost->mFORCE_MXP_NEGOTIATION_OFF) {
sendTelnetOption(TN_DO, OPT_MXP);
Expand Down Expand Up @@ -1132,6 +1145,12 @@ void cTelnet::processTelnetCommand(const std::string& command)
raiseProtocolEvent("sysProtocolDisabled", "GMCP");
}

if (option == OPT_MSSP) {
// MSSP got turned off
enableMSSP = false;
raiseProtocolEvent("sysProtocolDisabled", "MSSP");
}

if (option == OPT_MXP) {
// MXP got turned off
mpHost->mServerMXPenabled = false;
Expand Down Expand Up @@ -1198,6 +1217,14 @@ void cTelnet::processTelnetCommand(const std::string& command)
break;
}

if (option == OPT_MSSP && mpHost->mEnableMSSP) {
// MSSP support
enableMSSP = true;
sendTelnetOption(TN_WILL, OPT_MSSP);
raiseProtocolEvent("sysProtocolEnabled", "MSSP");
break;
}

if (option == OPT_MXP && !mpHost->mFORCE_MXP_NEGOTIATION_OFF) {
// MXP support
sendTelnetOption(TN_WILL, OPT_MXP);
Expand Down Expand Up @@ -1271,6 +1298,12 @@ void cTelnet::processTelnetCommand(const std::string& command)
raiseProtocolEvent("sysProtocolDisabled", "GMCP");
}

if (option == OPT_MSSP) {
// MSSP got turned off
enableMSSP = false;
raiseProtocolEvent("sysProtocolDisabled", "MSSP");
}

if (option == OPT_MXP) {
// MXP got turned off
raiseProtocolEvent("sysProtocolDisabled", "MXP");
Expand Down Expand Up @@ -1402,6 +1435,22 @@ void cTelnet::processTelnetCommand(const std::string& command)
return;
}

// MSSP
if (option == OPT_MSSP) {
QByteArray payload = command.c_str();
if (payload.size() < 6) {
return;
}
// payload is in the Mud Server's encoding, trim off the Telnet suboption
// bytes from beginning (3) and end (2):
payload = payload.mid(3, static_cast<int>(payload.size()) - 5);

// strip first 3 characters to get rid of <IAC><SB><201>
// and strip the last 2 characters to get rid of <IAC><TN_SE>
setMSSPVariables(payload);
return;
}

if (option == OPT_102) {
QByteArray payload = command.c_str();
if (payload.size() < 6) {
Expand Down Expand Up @@ -1731,6 +1780,27 @@ void cTelnet::setGMCPVariables(const QByteArray& msg)
mpHost->mLuaInterpreter.setGMCPTable(packageMessage, data);
}

void cTelnet::setMSSPVariables(const QByteArray& msg)
{
QString transcodedMsg;

if (mpOutOfBandDataIncomingCodec) {
// Message is encoded
transcodedMsg = mpOutOfBandDataIncomingCodec->toUnicode(msg);
} else {
// Message is in ASCII (though this can handle Utf-8):
transcodedMsg = QString::fromUtf8(msg);
}

transcodedMsg.remove(QChar::LineFeed);
// replace ANSI escape character with escaped version, to handle improperly passed ANSI codes
transcodedMsg.replace(QLatin1String("\u001B"), QLatin1String("\\u001B"));
// remove \r's from the data, as yajl doesn't like it
transcodedMsg.remove(QChar::CarriageReturn);

mpHost->mLuaInterpreter.setMSSPTable(transcodedMsg);
}

void cTelnet::setChannel102Variables(const QString& msg)
{
// messages consist of 2 bytes only
Expand Down
7 changes: 7 additions & 0 deletions src/ctelnet.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ const char OPT_TERMINAL_TYPE = 24;
const char OPT_EOR = 25;
const char OPT_NAWS = 31;
const char OPT_MSDP = 69; // http://tintin.sourceforge.net/msdp/
const char OPT_MSSP = static_cast<char>(70); // https://tintin.sourceforge.io/protocols/mssp/
const char OPT_COMPRESS = 85;
const char OPT_COMPRESS2 = 86;
const char OPT_MSP = 90;
Expand All @@ -112,6 +113,9 @@ const char OPT_102 = 102;
const char OPT_ATCP = static_cast<char>(200);
const char OPT_GMCP = static_cast<char>(201);

const char MSSP_VAR = 1;
const char MSSP_VAL = 2;

const char MSDP_VAR = 1;
const char MSDP_VAL = 2;
const char MSDP_TABLE_OPEN = 3;
Expand All @@ -135,6 +139,7 @@ class cTelnet : public QObject
bool sendData(QString& data);
void setATCPVariables(const QByteArray&);
void setGMCPVariables(const QByteArray&);
void setMSSPVariables(const QByteArray&);
void atcpComposerCancel();
void atcpComposerSave(QString);
void setDisplayDimensions();
Expand Down Expand Up @@ -165,6 +170,7 @@ class cTelnet : public QObject
std::string encodeAndCookBytes(const std::string&);
bool isATCPEnabled() const { return enableATCP; }
bool isGMCPEnabled() const { return enableGMCP; }
bool isMSSPEnabled() const { return enableMSSP; }
bool isChannel102Enabled() const { return enableChannel102; }
void requestDiscordInfo();
QString decodeOption(const unsigned char) const;
Expand Down Expand Up @@ -281,6 +287,7 @@ public slots:
int lastTimeOffset;
bool enableATCP;
bool enableGMCP;
bool enableMSSP;
bool enableChannel102;
bool mDontReconnect;
bool mAutoReconnect;
Expand Down
5 changes: 5 additions & 0 deletions src/dlgProfilePreferences.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,7 @@ void dlgProfilePreferences::initWithHost(Host* pHost)
//encoding->setCurrentIndex( pHost->mEncoding );
mFORCE_SAVE_ON_EXIT->setChecked(pHost->mFORCE_SAVE_ON_EXIT);
mEnableGMCP->setChecked(pHost->mEnableGMCP);
mEnableMSSP->setChecked(pHost->mEnableMSSP);
mEnableMSDP->setChecked(pHost->mEnableMSDP);

// load profiles into mappers "copy map to profile" combobox
Expand Down Expand Up @@ -977,6 +978,7 @@ void dlgProfilePreferences::initWithHost(Host* pHost)
connect(pushButton_background_color_2, &QAbstractButton::clicked, this, &dlgProfilePreferences::setBgColor2);

connect(mEnableGMCP, &QAbstractButton::clicked, need_reconnect_for_data_protocol, &QWidget::show);
connect(mEnableMSSP, &QAbstractButton::clicked, need_reconnect_for_data_protocol, &QWidget::show);
connect(mEnableMSDP, &QAbstractButton::clicked, need_reconnect_for_data_protocol, &QWidget::show);

connect(mFORCE_MCCP_OFF, &QAbstractButton::clicked, need_reconnect_for_specialoption, &QWidget::show);
Expand Down Expand Up @@ -1057,6 +1059,7 @@ void dlgProfilePreferences::disconnectHostRelatedControls()
disconnect(pushButton_background_color_2, &QAbstractButton::clicked, nullptr, nullptr);

disconnect(mEnableGMCP, &QAbstractButton::clicked, nullptr, nullptr);
disconnect(mEnableMSSP, &QAbstractButton::clicked, nullptr, nullptr);
disconnect(mEnableMSDP, &QAbstractButton::clicked, nullptr, nullptr);

disconnect(mFORCE_MCCP_OFF, &QAbstractButton::clicked, nullptr, nullptr);
Expand Down Expand Up @@ -1134,6 +1137,7 @@ void dlgProfilePreferences::clearHostDetails()
mAlertOnNewData->setChecked(false);
mFORCE_SAVE_ON_EXIT->setChecked(false);
mEnableGMCP->setChecked(false);
mEnableMSSP->setChecked(false);
mEnableMSDP->setChecked(false);

pushButton_chooseProfiles->setEnabled(false);
Expand Down Expand Up @@ -2255,6 +2259,7 @@ void dlgProfilePreferences::slot_save_and_exit()
pHost->mFORCE_GA_OFF = mFORCE_GA_OFF->isChecked();
pHost->mFORCE_SAVE_ON_EXIT = mFORCE_SAVE_ON_EXIT->isChecked();
pHost->mEnableGMCP = mEnableGMCP->isChecked();
pHost->mEnableMSSP = mEnableMSSP->isChecked();
pHost->mEnableMSDP = mEnableMSDP->isChecked();
pHost->mMapperUseAntiAlias = mMapperUseAntiAlias->isChecked();
if (pHost->mpMap && pHost->mpMap->mpMapper) {
Expand Down
1 change: 1 addition & 0 deletions src/mudlet-lua/lua/LuaGlobal.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ end

json_to_value = yajl.to_value
gmcp = {}
mssp = {}

function __gmcp_merge_gmcp_sub_tables( a, key )
local _m = a.__needMerge;
Expand Down
10 changes: 10 additions & 0 deletions src/ui/profile_preferences.ui
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,16 @@
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="mEnableMSSP">
<property name="toolTip">
<string>&lt;p&gt;Enables MSSP - provides Mud Server Status Protocol information upon connection for supported games&lt;/p&gt;</string>
</property>
<property name="text">
<string>Enable MSSP</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="need_reconnect_for_data_protocol">
<property name="enabled">
<bool>true</bool>
Expand Down

0 comments on commit b3133ef

Please sign in to comment.