diff options
author | Robert Adam <dev@robert-adam.de> | 2021-04-14 20:47:00 +0300 |
---|---|---|
committer | Robert Adam <dev@robert-adam.de> | 2021-04-16 21:15:44 +0300 |
commit | 27dbee8e620877f9a1668b1d58c7269a48c7e229 (patch) | |
tree | 0d445574449cb224a2d4cc8043520ca66c6afe11 /src/murmur | |
parent | c10d636cef79b07784318671df97dba6c1af2b83 (diff) |
FEAT(client): Plugin framework
This commit introduces a new plugin framework into the codebase of the
Mumble client. Note that "plugin" here really refers to a (more or less)
general purpose plugin and is therefore not to be confused with the
previously available positional data plugins (only responsible for
fetching positional data from a running game and passing that to
Mumble).
The plugin interface is written in C, removing the compiler-dependence
the old "plugins" had. Instead plugins can now be written in an
arbitrary language as long as that language is capable of being compiled
into a shared library and also being capable of being C-compatible.
As already indicated a plugin is essentially a shared library that
provides certain functions that allow Mumble to interface with it.
Inside Mumble the so-called PluginManager is responsible for managing
the plugins and relaying events to the respective callbacks. Plugins
themselves can also interact with Mumble on their own initiative by
using the provided API functions.
Fixes #2455
Fixes #2148
Fixes #1594
Fixes #2051
Fixes #3742
Fixes #4575
Fixes #4751
Diffstat (limited to 'src/murmur')
-rw-r--r-- | src/murmur/Messages.cpp | 56 | ||||
-rw-r--r-- | src/murmur/Meta.cpp | 6 | ||||
-rw-r--r-- | src/murmur/Meta.h | 3 | ||||
-rw-r--r-- | src/murmur/Server.cpp | 11 | ||||
-rw-r--r-- | src/murmur/Server.h | 3 | ||||
-rw-r--r-- | src/murmur/ServerUser.cpp | 3 | ||||
-rw-r--r-- | src/murmur/ServerUser.h | 1 |
7 files changed, 82 insertions, 1 deletions
diff --git a/src/murmur/Messages.cpp b/src/murmur/Messages.cpp index cfde87e2a..6fb23e141 100644 --- a/src/murmur/Messages.cpp +++ b/src/murmur/Messages.cpp @@ -10,6 +10,7 @@ #include "Group.h" #include "Message.h" #include "Meta.h" +#include "MumbleConstants.h" #include "Server.h" #include "ServerDB.h" #include "ServerUser.h" @@ -2165,6 +2166,61 @@ void Server::msgServerConfig(ServerUser *, MumbleProto::ServerConfig &) { void Server::msgSuggestConfig(ServerUser *, MumbleProto::SuggestConfig &) { } +void Server::msgPluginDataTransmission(ServerUser *sender, MumbleProto::PluginDataTransmission &msg) { + // A client's plugin has sent us a message that we shall delegate to its receivers + + if (sender->m_pluginMessageBucket.ratelimit(1)) { + qWarning("Dropping plugin message sent from \"%s\" (%d)", qUtf8Printable(sender->qsName), sender->uiSession); + return; + } + + if (!msg.has_data() || !msg.has_dataid()) { + // Messages without data and/or without a data ID can't be used by the clients. Thus we don't even have to send them + return; + } + + if (msg.data().size() > Mumble::Plugins::PluginMessage::MAX_DATA_LENGTH) { + qWarning("Dropping plugin message sent from \"%s\" (%d) - data too large", qUtf8Printable(sender->qsName), sender->uiSession); + return; + } + if (msg.dataid().size() > Mumble::Plugins::PluginMessage::MAX_DATA_ID_LENGTH) { + qWarning("Dropping plugin message sent from \"%s\" (%d) - data ID too long", qUtf8Printable(sender->qsName), sender->uiSession); + return; + } + + // Always set the sender's session and don't rely on it being set correctly (would + // allow spoofing the sender's session) + msg.set_sendersession(sender->uiSession); + + // Copy needed data from message in order to be able to remove info about receivers from the message as this doesn't + // matter for the client + size_t receiverAmount = msg.receiversessions_size(); + const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 > receiverSessions = msg.receiversessions(); + + msg.clear_receiversessions(); + + QSet<uint32_t> uniqueReceivers; + uniqueReceivers.reserve(receiverSessions.size()); + + for(int i = 0; static_cast<size_t>(i) < receiverAmount; i++) { + uint32_t userSession = receiverSessions.Get(i); + + if (!uniqueReceivers.contains(userSession)) { + uniqueReceivers.insert(userSession); + } else { + // Duplicate entry -> ignore + continue; + } + + ServerUser *receiver = qhUsers.value(receiverSessions.Get(i)); + + if (receiver) { + // We can simply redirect the message we have received to the clients + sendMessage(receiver, msg); + } + } +} + #undef RATELIMIT #undef MSG_SETUP #undef MSG_SETUP_NO_UNIDLE diff --git a/src/murmur/Meta.cpp b/src/murmur/Meta.cpp index 6ebaeb18d..5e1456167 100644 --- a/src/murmur/Meta.cpp +++ b/src/murmur/Meta.cpp @@ -104,6 +104,9 @@ MetaParams::MetaParams() { iMessageLimit = 1; iMessageBurst = 5; + iPluginMessageLimit = 4; + iPluginMessageBurst = 15; + qsCiphers = MumbleSSL::defaultOpenSSLCipherString(); bLogGroupChanges = false; @@ -402,6 +405,9 @@ void MetaParams::read(QString fname) { iMessageLimit = typeCheckedFromSettings("messagelimit", 1); iMessageBurst = typeCheckedFromSettings("messageburst", 5); + iPluginMessageLimit = typeCheckedFromSettings("pluginmessagelimit", 4); + iPluginMessageBurst = typeCheckedFromSettings("pluginmessageburst", 15); + bool bObfuscate = typeCheckedFromSettings("obfuscate", false); if (bObfuscate) { qWarning("IP address obfuscation enabled."); diff --git a/src/murmur/Meta.h b/src/murmur/Meta.h index bac90df5b..91b48f535 100644 --- a/src/murmur/Meta.h +++ b/src/murmur/Meta.h @@ -104,6 +104,9 @@ public: unsigned int iMessageLimit; unsigned int iMessageBurst; + unsigned int iPluginMessageLimit; + unsigned int iPluginMessageBurst; + QSslCertificate qscCert; QSslKey qskKey; diff --git a/src/murmur/Server.cpp b/src/murmur/Server.cpp index 4c8dd0939..c0c979814 100644 --- a/src/murmur/Server.cpp +++ b/src/murmur/Server.cpp @@ -418,6 +418,8 @@ void Server::readParams() { qrChannelName = Meta::mp.qrChannelName; iMessageLimit = Meta::mp.iMessageLimit; iMessageBurst = Meta::mp.iMessageBurst; + iPluginMessageLimit = Meta::mp.iPluginMessageLimit; + iPluginMessageBurst = Meta::mp.iPluginMessageBurst; qvSuggestVersion = Meta::mp.qvSuggestVersion; qvSuggestPositional = Meta::mp.qvSuggestPositional; qvSuggestPushToTalk = Meta::mp.qvSuggestPushToTalk; @@ -526,6 +528,15 @@ void Server::readParams() { if (iMessageBurst < 1) { // Prevent disabling messages entirely iMessageBurst = 1; } + + iPluginMessageLimit = getConf("mpluginessagelimit", iPluginMessageLimit).toUInt(); + if (iPluginMessageLimit < 1) { // Prevent disabling messages entirely + iPluginMessageLimit = 1; + } + iPluginMessageBurst = getConf("pluginmessageburst", iPluginMessageBurst).toUInt(); + if (iPluginMessageBurst < 1) { // Prevent disabling messages entirely + iPluginMessageBurst = 1; + } } void Server::setLiveConf(const QString &key, const QString &value) { diff --git a/src/murmur/Server.h b/src/murmur/Server.h index abebd0ffe..ac854cea6 100644 --- a/src/murmur/Server.h +++ b/src/murmur/Server.h @@ -140,6 +140,9 @@ public: unsigned int iMessageLimit; unsigned int iMessageBurst; + unsigned int iPluginMessageLimit; + unsigned int iPluginMessageBurst; + QVariant qvSuggestVersion; QVariant qvSuggestPositional; QVariant qvSuggestPushToTalk; diff --git a/src/murmur/ServerUser.cpp b/src/murmur/ServerUser.cpp index f2dac8abb..367889bee 100644 --- a/src/murmur/ServerUser.cpp +++ b/src/murmur/ServerUser.cpp @@ -13,7 +13,8 @@ #endif ServerUser::ServerUser(Server *p, QSslSocket *socket) - : Connection(p, socket), User(), s(nullptr), leakyBucket(p->iMessageLimit, p->iMessageBurst) { + : Connection(p, socket), User(), s(nullptr), + leakyBucket(p->iMessageLimit, p->iMessageBurst), m_pluginMessageBucket(5, 20) { sState = ServerUser::Connected; sUdpSocket = INVALID_SOCKET; diff --git a/src/murmur/ServerUser.h b/src/murmur/ServerUser.h index fd40071ca..c34ebeaf7 100644 --- a/src/murmur/ServerUser.h +++ b/src/murmur/ServerUser.h @@ -147,6 +147,7 @@ public: QMap< QString, QString > qmWhisperRedirect; LeakyBucket leakyBucket; + LeakyBucket m_pluginMessageBucket; int iLastPermissionCheck; QMap< int, unsigned int > qmPermissionSent; |