diff options
author | Robert Adam <dev@robert-adam.de> | 2021-03-03 11:11:13 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-03 11:11:13 +0300 |
commit | e03aa6765bf4c041ee40fb810ee86149fdfd21a3 (patch) | |
tree | 2f996099aa4e7ce7a8eceaafd48f7612bad336bd | |
parent | 6657a6f2a1dc84cc82f1157073727ae1103c79c7 (diff) | |
parent | 0bee65b06746dfb1dd95f62b68891c8a4c2cbb4e (diff) |
Merge pull request #4809: FEAT(server, ice): Ability to broadcast welcome text
This allows server admins to explicitly trigger the broadcast of the
currently set welcome text to a given set of users.
By first setting a new welcome text and then broadcasting it to all
currently connected users, the old behavior of setting the welcome
message (changed in da26386) can be
restored.
Fixes #4805
-rw-r--r-- | docs/dev/ExtendingTheIceInterface.md | 90 | ||||
-rw-r--r-- | src/murmur/Murmur.ice | 5 | ||||
-rw-r--r-- | src/murmur/MurmurI.h | 3 | ||||
-rw-r--r-- | src/murmur/MurmurIce.cpp | 12 | ||||
-rw-r--r-- | src/murmur/MurmurIceWrapper.cpp | 36 | ||||
-rw-r--r-- | src/murmur/RPC.cpp | 7 | ||||
-rw-r--r-- | src/murmur/Server.h | 1 |
7 files changed, 152 insertions, 2 deletions
diff --git a/docs/dev/ExtendingTheIceInterface.md b/docs/dev/ExtendingTheIceInterface.md new file mode 100644 index 000000000..0a20bdfc9 --- /dev/null +++ b/docs/dev/ExtendingTheIceInterface.md @@ -0,0 +1,90 @@ +# Extending the Ice interface + +The server component supports RPC via [ZeroC Ice](https://zeroc.com/products/ice). This document describes how the Ice interface of the server can be +extended. + +Note: If not stated otherwise all referenced files live in `src/murmur/`. + +The files involved in extending the Ice interface are +| **File** | **Description** | +| -------- | --------------- | +| `Murmur.ice` | Contains the formal definition of the interface | +| `Murmur.h` | Contains the C++ interface definition (abstract base classes). This file is automatically generated based on `Murmur.ice` when invoking cmake (via `slice2cpp`). It lives in `<build directory>/src/murmur`. This file is needed to generate `MurmurIceWrapper.cpp` | +| `Murmur.cpp` | Contains some boilerplate and Ice-internal implementation code. This file is generated and lives alongside `Murmur.h` | +| `MurmurI.h` | Contains the definition of the actually implemented API classes (`ServerI` and `MetaI`). These extend the abstract base classes from `Murmur.h` | +| `MurmurIceWrapper.cpp` | Contains wrapper implementation of the `*I` API classes. This file is auto-generated by the `scripts/generateIceWrapper.py` script | +| `MurmurIce.h` | Contains the definition of a statically used helper class | +| `MurmurIce.cpp` | Contains the implementation of that helper class **and** _static_ functions used to actually implement the server-side functionality of the Ice API functions | +| `RPC.cpp` | Contains the implementations of the `Server` (the Mumble server, _not_ the Ice API type) class's member functions that are required to make certain functionality accessible to the static functions in `MurmurIce.cpp` | + + +## Overview + +The steps are +1. Let cmake invoke `slice2cpp` to generate `Murmur.h` and `Murmur.cpp` +2. Invoke `generateIceWrapper.py` to generate `MurmurIceWrapper.cpp` +3. Add new function declarations to `MurmurU.h` +4. Write impl function in `MurmurIce.cpp` +5. Potentially write new public API functions (declare in `Server.h` and define in `RPC.cpp` + +## Detailed instructions + +Before proceeding any further you should run cmake once in order for these files to get generated as they are needed for the next step. Assuming your +build directory lives directly under the repository's root, you can do this by invoking +```bash +cmake .. +``` + +The next step is the generation of the `MurmurIceWrapper.cpp` file by executing the following command (assuming the call is performed from the +repository's root and the build directory is called `build`): +```bash +$ python3 scripts/generateIceWrapper.py --ice-file src/murmur/Murmur.ice --generated-ice-header build/src/murmur/Murmur.h --out-file src/murmur/MurmurIceWrapper.cpp +Using ICE-file at "src/murmur/Murmur.ice" +Using ICE-generated header file at "build/src/murmur/Murmur.h" +``` +The paths that are given in the example may have to be adapted in order for it to work on your machine. + +The `MurmurIceWrapper.cpp` file generates the `*_async` versions of the Ice callbacks that handle the async nature of these callbacks and also +contain the boilerplate for e.g. verification of the caller and things like this. Most importantly though these functions call the `impl_*` functions +defined in `MurmurIce.cpp`. For instance a function called `updateCertificates` inside the `Server` class will call `impl_Server_updateCertificate` +which has to be defined as a `static` function inside `MurmurIce.cpp`. + +The declaration of the async functions generated this way are contained inside `MurmurI.h`. You have to manually add the function's declaration into +there. The easiest way to do this is to let the script generate the implementation as described above and then copy the function signature from there +into the `Murmur.h` file (make the declaration `virtual` though). + +The impl function's signature is always +```cpp +static void impl_<className>_<functionName>(const ::Murmur::AMD_<className>_<functionName>Ptr cb [, int server_id] [, <function arguments>]) { + // Implementation goes here + + cb->ice_response([<function return value>]); +} +``` +- `<className>`: Name of the class the function is declared in (e.g. `Server` or `Meta`) +- `<functionName>`: Name of the function as declared in the `Murmur.ice` file +- `[, int server_id]`: Only needed when extending the `Server` API class (the brackets are not part of what needs to be written in code) +- `[, <function arguments>]`: To be replaced by the list of arguments the function takes +- `[<function return value>]`: To be replaced with the value this function returns or to be removed if the function does not return anything. + + +If you have used non-default types that are declared in `Murmur.ice` (e.g. `IdList`), you can reference them here as `::Murmur::<typeName>` (e.g. +`::Murmur::IdList`). + +Error reporting works via the `cb->ice_exception` function and if everything went well, the function must end by calling `cb->ice_response` +(potentially passing a value to that function that shall be returned to the caller of the function). + +In general it is a good idea to have a look at the existing implementation inside `MurmurIce.cpp` and take inspiration from those. + +Note that the implementations make heavy use of macros (e.g. `NEED_SERVER`, `NEED_CHANNEL`, etc.). These will initialize the corresponding variables +(`server`, `channel`, etc.) based in the parameters fed into the function (In order to obtain the channel, user, etc. you always have to initialize +the `server` variable first). For this to work it is essential that you are using the same parameter names as the existing implementations (e.g. +`server_id` for the server's ID). (For historical reasons the macro to obtain the `user` variable is called `NEED_PLAYER`) + +If the function requires action on the server's side (beyond its public API), you have to declare a new public function in the `Server` class (this +time the Mumble server though; not the Ice server class) defined in `Server.h` (the definitions belong to the group of other RPC functions in there - +section marked by a comment). The implementation of this new function should then be written in `RPC.cpp`. + +An example of when this is needed is for instance if you have to access the list of connected clients (e.g. because you want to send them a message). +While in the current state of the code it would be possible to access this list from the outside (public visibility), you should prefer creating a +public API function in the Mumble `Server` class that has the implementation in `RPC.cpp`. diff --git a/src/murmur/Murmur.ice b/src/murmur/Murmur.ice index 65393e863..1dff7fca3 100644 --- a/src/murmur/Murmur.ice +++ b/src/murmur/Murmur.ice @@ -823,6 +823,11 @@ module Murmur * @returns An ID-list of users listening to the given channel */ idempotent IntList getListeningUsers(int channelid); + + /** + * @param receiverUserIDs list of IDs of the users the message shall be sent to + */ + idempotent void sendWelcomeMessage(IdList receiverUserIDs); }; /** Callback interface for Meta. You can supply an implementation of this to receive notifications diff --git a/src/murmur/MurmurI.h b/src/murmur/MurmurI.h index be17deddc..8dcb23e27 100644 --- a/src/murmur/MurmurI.h +++ b/src/murmur/MurmurI.h @@ -155,6 +155,9 @@ public: virtual void getListeningUsers_async(const ::Murmur::AMD_Server_getListeningUsersPtr &, ::Ice::Int, const Ice::Current &); + virtual void sendWelcomeMessage_async(const ::Murmur::AMD_Server_sendWelcomeMessagePtr &, + const ::Murmur::IdList &p1, const ::Ice::Current ¤t); + virtual void ice_ping(const Ice::Current &) const; }; diff --git a/src/murmur/MurmurIce.cpp b/src/murmur/MurmurIce.cpp index a9525a86b..a3a13751b 100644 --- a/src/murmur/MurmurIce.cpp +++ b/src/murmur/MurmurIce.cpp @@ -1765,6 +1765,18 @@ static void impl_Server_getListeningUsers(const ::Murmur::AMD_Server_getListenin cb->ice_response(userSessions); } +static void impl_Server_sendWelcomeMessage(const ::Murmur::AMD_Server_sendWelcomeMessagePtr cb, int server_id, ::Murmur::IdList receiverUserIDs) { + NEED_SERVER; + + for (unsigned int session : receiverUserIDs) { + NEED_PLAYER; + + server->sendWelcomeMessageTo(user); + } + + cb->ice_response(); +} + static void impl_Server_addUserToGroup(const ::Murmur::AMD_Server_addUserToGroupPtr cb, int server_id, ::Ice::Int channelid, ::Ice::Int session, const ::std::string &group) { NEED_SERVER; diff --git a/src/murmur/MurmurIceWrapper.cpp b/src/murmur/MurmurIceWrapper.cpp index 7d6a5ae3a..94c4abc30 100644 --- a/src/murmur/MurmurIceWrapper.cpp +++ b/src/murmur/MurmurIceWrapper.cpp @@ -3,7 +3,7 @@ // that can be found in the LICENSE file at the root of the // Mumble source tree or at <https://www.mumble.info/LICENSE>. -// This file was auto-generated by scripts/generateIceWrapper.py on 2020-09-12 -- DO NOT EDIT MANUALLY! +// This file was auto-generated by scripts/generateIceWrapper.py on 2021-03-01 -- DO NOT EDIT MANUALLY! #include <boost/bind/bind.hpp> @@ -1767,6 +1767,38 @@ void ::Murmur::ServerI::getListeningUsers_async(const ::Murmur::AMD_Server_getLi QCoreApplication::instance()->postEvent(mi, ie); } +void ::Murmur::ServerI::sendWelcomeMessage_async(const ::Murmur::AMD_Server_sendWelcomeMessagePtr &cb, const IdList& p1, const ::Ice::Current ¤t) { + // qWarning() << "sendWelcomeMessage" << meta->mp.qsIceSecretRead.isNull() << meta->mp.qsIceSecretRead.isEmpty(); +#ifndef ACCESS_Server_sendWelcomeMessage_ALL +# ifdef ACCESS_Server_sendWelcomeMessage_READ + if (!meta->mp.qsIceSecretRead.isNull()) { + bool ok = !meta->mp.qsIceSecretRead.isEmpty(); +# else + if (!meta->mp.qsIceSecretRead.isNull() || !meta->mp.qsIceSecretWrite.isNull()) { + bool ok = !meta->mp.qsIceSecretWrite.isEmpty(); +# endif // ACCESS_Server_sendWelcomeMessage_READ + ::Ice::Context::const_iterator i = current.ctx.find("secret"); + ok = ok && (i != current.ctx.end()); + if (ok) { + const QString &secret = u8((*i).second); +# ifdef ACCESS_Server_sendWelcomeMessage_READ + ok = ((secret == meta->mp.qsIceSecretRead) || (secret == meta->mp.qsIceSecretWrite)); +# else + ok = (secret == meta->mp.qsIceSecretWrite); +# endif // ACCESS_Server_sendWelcomeMessage_READ + } + + if (!ok) { + cb->ice_exception(InvalidSecretException()); + return; + } + } +#endif // ACCESS_Server_sendWelcomeMessage_ALL + + ExecEvent *ie = new ExecEvent(boost::bind(&impl_Server_sendWelcomeMessage, cb, QString::fromStdString(current.id.name).toInt(), p1)); + QCoreApplication::instance()->postEvent(mi, ie); +} + void ::Murmur::MetaI::getServer_async(const ::Murmur::AMD_Meta_getServerPtr &cb, ::Ice::Int p1, const ::Ice::Current ¤t) { // qWarning() << "getServer" << meta->mp.qsIceSecretRead.isNull() << meta->mp.qsIceSecretRead.isEmpty(); #ifndef ACCESS_Meta_getServer_ALL @@ -2088,5 +2120,5 @@ void ::Murmur::MetaI::getSliceChecksums_async(const ::Murmur::AMD_Meta_getSliceC } void ::Murmur::MetaI::getSlice_async(const ::Murmur::AMD_Meta_getSlicePtr &cb, const Ice::Current&) { - cb->ice_response(std::string("\n\n\n\n#include <Ice/SliceChecksumDict.ice>\nmodule Murmur\n{\n\n[\"python:seq:tuple\"] sequence<byte> NetAddress;\n\nstruct User {\nint session;\nint userid;\nbool mute;\nbool deaf;\nbool suppress;\nbool prioritySpeaker;\nbool selfMute;\nbool selfDeaf;\nbool recording;\nint channel;\nstring name;\nint onlinesecs;\nint bytespersec;\nint version;\nstring release;\nstring os;\nstring osversion;\nstring identity;\nstring context;\nstring comment;\nNetAddress address;\nbool tcponly;\nint idlesecs;\nfloat udpPing;\nfloat tcpPing;\n};\nsequence<int> IntList;\n\nstruct TextMessage {\nIntList sessions;\nIntList channels;\nIntList trees;\nstring text;\n};\n\nstruct Channel {\nint id;\nstring name;\nint parent;\nIntList links;\nstring description;\nbool temporary;\nint position;\n};\n\nstruct Group {\nstring name;\nbool inherited;\nbool inherit;\nbool inheritable;\nIntList add;\nIntList remove;\nIntList members;\n};\n\nconst int PermissionWrite = 0x01;\nconst int PermissionTraverse = 0x02;\nconst int PermissionEnter = 0x04;\nconst int PermissionSpeak = 0x08;\nconst int PermissionWhisper = 0x100;\nconst int PermissionMuteDeafen = 0x10;\nconst int PermissionMove = 0x20;\nconst int PermissionMakeChannel = 0x40;\nconst int PermissionMakeTempChannel = 0x400;\nconst int PermissionLinkChannel = 0x80;\nconst int PermissionTextMessage = 0x200;\nconst int PermissionKick = 0x10000;\nconst int PermissionBan = 0x20000;\nconst int PermissionRegister = 0x40000;\nconst int PermissionRegisterSelf = 0x80000;\nconst int ResetUserContent = 0x100000;\n\nstruct ACL {\nbool applyHere;\nbool applySubs;\nbool inherited;\nint userid;\nstring group;\nint allow;\nint deny;\n};\n\nstruct Ban {\nNetAddress address;\nint bits;\nstring name;\nstring hash;\nstring reason;\nint start;\nint duration;\n};\n\nstruct LogEntry {\nint timestamp;\nstring txt;\n};\nclass Tree;\nsequence<Tree> TreeList;\nenum ChannelInfo { ChannelDescription, ChannelPosition };\nenum UserInfo { UserName, UserEmail, UserComment, UserHash, UserPassword, UserLastActive, UserKDFIterations };\ndictionary<int, User> UserMap;\ndictionary<int, Channel> ChannelMap;\nsequence<Channel> ChannelList;\nsequence<User> UserList;\nsequence<Group> GroupList;\nsequence<ACL> ACLList;\nsequence<LogEntry> LogList;\nsequence<Ban> BanList;\nsequence<int> IdList;\nsequence<string> NameList;\ndictionary<int, string> NameMap;\ndictionary<string, int> IdMap;\nsequence<byte> Texture;\ndictionary<string, string> ConfigMap;\nsequence<string> GroupNameList;\nsequence<byte> CertificateDer;\nsequence<CertificateDer> CertificateList;\n\ndictionary<UserInfo, string> UserInfoMap;\n\nclass Tree {\nChannel c;\nTreeList children;\nUserList users;\n};\nexception MurmurException {};\nexception InvalidSessionException extends MurmurException {};\nexception InvalidChannelException extends MurmurException {};\nexception InvalidServerException extends MurmurException {};\nexception ServerBootedException extends MurmurException {};\nexception ServerFailureException extends MurmurException {};\nexception InvalidUserException extends MurmurException {};\nexception InvalidTextureException extends MurmurException {};\nexception InvalidCallbackException extends MurmurException {};\nexception InvalidSecretException extends MurmurException {};\nexception NestingLimitException extends MurmurException {};\nexception WriteOnlyException extends MurmurException {};\nexception InvalidInputDataException extends MurmurException {};\n\ninterface ServerCallback {\nidempotent void userConnected(User state);\nidempotent void userDisconnected(User state);\nidempotent void userStateChanged(User state);\nidempotent void userTextMessage(User state, TextMessage message);\nidempotent void channelCreated(Channel state);\nidempotent void channelRemoved(Channel state);\nidempotent void channelStateChanged(Channel state);\n};\n\nconst int ContextServer = 0x01;\nconst int ContextChannel = 0x02;\nconst int ContextUser = 0x04;\n\ninterface ServerContextCallback {\nidempotent void contextAction(string action, User usr, int session, int channelid);\n};\n\ninterface ServerAuthenticator {\nidempotent int authenticate(string name, string pw, CertificateList certificates, string certhash, bool certstrong, out string newname, out GroupNameList groups);\n\nidempotent bool getInfo(int id, out UserInfoMap info);\n\nidempotent int nameToId(string name);\n\nidempotent string idToName(int id);\n\nidempotent Texture idToTexture(int id);\n};\n\ninterface ServerUpdatingAuthenticator extends ServerAuthenticator {\nint registerUser(UserInfoMap info);\n\nint unregisterUser(int id);\n\nidempotent NameMap getRegisteredUsers(string filter);\n\nidempotent int setInfo(int id, UserInfoMap info);\n\nidempotent int setTexture(int id, Texture tex);\n};\n\n[\"amd\"] interface Server {\nidempotent bool isRunning() throws InvalidSecretException;\n\nvoid start() throws ServerBootedException, ServerFailureException, InvalidSecretException;\n\nvoid stop() throws ServerBootedException, InvalidSecretException;\n\nvoid delete() throws ServerBootedException, InvalidSecretException;\n\nidempotent int id() throws InvalidSecretException;\n\nvoid addCallback(ServerCallback *cb) throws ServerBootedException, InvalidCallbackException, InvalidSecretException;\n\nvoid removeCallback(ServerCallback *cb) throws ServerBootedException, InvalidCallbackException, InvalidSecretException;\n\nvoid setAuthenticator(ServerAuthenticator *auth) throws ServerBootedException, InvalidCallbackException, InvalidSecretException;\n\nidempotent string getConf(string key) throws InvalidSecretException, WriteOnlyException;\n\nidempotent ConfigMap getAllConf() throws InvalidSecretException;\n\nidempotent void setConf(string key, string value) throws InvalidSecretException;\n\nidempotent void setSuperuserPassword(string pw) throws InvalidSecretException;\n\nidempotent LogList getLog(int first, int last) throws InvalidSecretException;\n\nidempotent int getLogLen() throws InvalidSecretException;\n\nidempotent UserMap getUsers() throws ServerBootedException, InvalidSecretException;\n\nidempotent ChannelMap getChannels() throws ServerBootedException, InvalidSecretException;\n\nidempotent CertificateList getCertificateList(int session) throws ServerBootedException, InvalidSessionException, InvalidSecretException;\n\nidempotent Tree getTree() throws ServerBootedException, InvalidSecretException;\n\nidempotent BanList getBans() throws ServerBootedException, InvalidSecretException;\n\nidempotent void setBans(BanList bans) throws ServerBootedException, InvalidSecretException;\n\nvoid kickUser(int session, string reason) throws ServerBootedException, InvalidSessionException, InvalidSecretException;\n\nidempotent User getState(int session) throws ServerBootedException, InvalidSessionException, InvalidSecretException;\n\nidempotent void setState(User state) throws ServerBootedException, InvalidSessionException, InvalidChannelException, InvalidSecretException;\n\nvoid sendMessage(int session, string text) throws ServerBootedException, InvalidSessionException, InvalidSecretException;\n\nbool hasPermission(int session, int channelid, int perm) throws ServerBootedException, InvalidSessionException, InvalidChannelException, InvalidSecretException;\n\nidempotent int effectivePermissions(int session, int channelid) throws ServerBootedException, InvalidSessionException, InvalidChannelException, InvalidSecretException;\n\nvoid addContextCallback(int session, string action, string text, ServerContextCallback *cb, int ctx) throws ServerBootedException, InvalidCallbackException, InvalidSecretException;\n\nvoid removeContextCallback(ServerContextCallback *cb) throws ServerBootedException, InvalidCallbackException, InvalidSecretException;\n\nidempotent Channel getChannelState(int channelid) throws ServerBootedException, InvalidChannelException, InvalidSecretException;\n\nidempotent void setChannelState(Channel state) throws ServerBootedException, InvalidChannelException, InvalidSecretException, NestingLimitException;\n\nvoid removeChannel(int channelid) throws ServerBootedException, InvalidChannelException, InvalidSecretException;\n\nint addChannel(string name, int parent) throws ServerBootedException, InvalidChannelException, InvalidSecretException, NestingLimitException;\n\nvoid sendMessageChannel(int channelid, bool tree, string text) throws ServerBootedException, InvalidChannelException, InvalidSecretException;\n\nidempotent void getACL(int channelid, out ACLList acls, out GroupList groups, out bool inherit) throws ServerBootedException, InvalidChannelException, InvalidSecretException;\n\nidempotent void setACL(int channelid, ACLList acls, GroupList groups, bool inherit) throws ServerBootedException, InvalidChannelException, InvalidSecretException;\n\nidempotent void addUserToGroup(int channelid, int session, string group) throws ServerBootedException, InvalidChannelException, InvalidSessionException, InvalidSecretException;\n\nidempotent void removeUserFromGroup(int channelid, int session, string group) throws ServerBootedException, InvalidChannelException, InvalidSessionException, InvalidSecretException;\n\nidempotent void redirectWhisperGroup(int session, string source, string target) throws ServerBootedException, InvalidSessionException, InvalidSecretException;\n\nidempotent NameMap getUserNames(IdList ids) throws ServerBootedException, InvalidSecretException;\n\nidempotent IdMap getUserIds(NameList names) throws ServerBootedException, InvalidSecretException;\n\nint registerUser(UserInfoMap info) throws ServerBootedException, InvalidUserException, InvalidSecretException;\n\nvoid unregisterUser(int userid) throws ServerBootedException, InvalidUserException, InvalidSecretException;\n\nidempotent void updateRegistration(int userid, UserInfoMap info) throws ServerBootedException, InvalidUserException, InvalidSecretException;\n\nidempotent UserInfoMap getRegistration(int userid) throws ServerBootedException, InvalidUserException, InvalidSecretException;\n\nidempotent NameMap getRegisteredUsers(string filter) throws ServerBootedException, InvalidSecretException;\n\nidempotent int verifyPassword(string name, string pw) throws ServerBootedException, InvalidSecretException;\n\nidempotent Texture getTexture(int userid) throws ServerBootedException, InvalidUserException, InvalidSecretException;\n\nidempotent void setTexture(int userid, Texture tex) throws ServerBootedException, InvalidUserException, InvalidTextureException, InvalidSecretException;\n\nidempotent int getUptime() throws ServerBootedException, InvalidSecretException;\n\n idempotent void updateCertificate(string certificate, string privateKey, string passphrase) throws ServerBootedException, InvalidSecretException, InvalidInputDataException;\n \n idempotent void startListening(int userid, int channelid);\n \n idempotent void stopListening(int userid, int channelid);\n \n idempotent bool isListening(int userid, int channelid);\n \n idempotent IntList getListeningChannels(int userid);\n \n idempotent IntList getListeningUsers(int channelid);\n};\n\ninterface MetaCallback {\nvoid started(Server *srv);\n\nvoid stopped(Server *srv);\n};\nsequence<Server *> ServerList;\n\n[\"amd\"] interface Meta {\nidempotent Server *getServer(int id) throws InvalidSecretException;\n\nServer *newServer() throws InvalidSecretException;\n\nidempotent ServerList getBootedServers() throws InvalidSecretException;\n\nidempotent ServerList getAllServers() throws InvalidSecretException;\n\nidempotent ConfigMap getDefaultConf() throws InvalidSecretException;\n\nidempotent void getVersion(out int major, out int minor, out int patch, out string text);\n\nvoid addCallback(MetaCallback *cb) throws InvalidCallbackException, InvalidSecretException;\n\nvoid removeCallback(MetaCallback *cb) throws InvalidCallbackException, InvalidSecretException;\n\nidempotent int getUptime();\n\nidempotent string getSlice();\n\nidempotent Ice::SliceChecksumDict getSliceChecksums();\n};\n};\n")); + cb->ice_response(std::string("\n\n\n\n#include <Ice/SliceChecksumDict.ice>\nmodule Murmur\n{\n\n[\"python:seq:tuple\"] sequence<byte> NetAddress;\n\nstruct User {\nint session;\nint userid;\nbool mute;\nbool deaf;\nbool suppress;\nbool prioritySpeaker;\nbool selfMute;\nbool selfDeaf;\nbool recording;\nint channel;\nstring name;\nint onlinesecs;\nint bytespersec;\nint version;\nstring release;\nstring os;\nstring osversion;\nstring identity;\nstring context;\nstring comment;\nNetAddress address;\nbool tcponly;\nint idlesecs;\nfloat udpPing;\nfloat tcpPing;\n};\nsequence<int> IntList;\n\nstruct TextMessage {\nIntList sessions;\nIntList channels;\nIntList trees;\nstring text;\n};\n\nstruct Channel {\nint id;\nstring name;\nint parent;\nIntList links;\nstring description;\nbool temporary;\nint position;\n};\n\nstruct Group {\nstring name;\nbool inherited;\nbool inherit;\nbool inheritable;\nIntList add;\nIntList remove;\nIntList members;\n};\n\nconst int PermissionWrite = 0x01;\nconst int PermissionTraverse = 0x02;\nconst int PermissionEnter = 0x04;\nconst int PermissionSpeak = 0x08;\nconst int PermissionWhisper = 0x100;\nconst int PermissionMuteDeafen = 0x10;\nconst int PermissionMove = 0x20;\nconst int PermissionMakeChannel = 0x40;\nconst int PermissionMakeTempChannel = 0x400;\nconst int PermissionLinkChannel = 0x80;\nconst int PermissionTextMessage = 0x200;\nconst int PermissionKick = 0x10000;\nconst int PermissionBan = 0x20000;\nconst int PermissionRegister = 0x40000;\nconst int PermissionRegisterSelf = 0x80000;\nconst int ResetUserContent = 0x100000;\n\nstruct ACL {\nbool applyHere;\nbool applySubs;\nbool inherited;\nint userid;\nstring group;\nint allow;\nint deny;\n};\n\nstruct Ban {\nNetAddress address;\nint bits;\nstring name;\nstring hash;\nstring reason;\nint start;\nint duration;\n};\n\nstruct LogEntry {\nint timestamp;\nstring txt;\n};\nclass Tree;\nsequence<Tree> TreeList;\nenum ChannelInfo { ChannelDescription, ChannelPosition };\nenum UserInfo { UserName, UserEmail, UserComment, UserHash, UserPassword, UserLastActive, UserKDFIterations };\ndictionary<int, User> UserMap;\ndictionary<int, Channel> ChannelMap;\nsequence<Channel> ChannelList;\nsequence<User> UserList;\nsequence<Group> GroupList;\nsequence<ACL> ACLList;\nsequence<LogEntry> LogList;\nsequence<Ban> BanList;\nsequence<int> IdList;\nsequence<string> NameList;\ndictionary<int, string> NameMap;\ndictionary<string, int> IdMap;\nsequence<byte> Texture;\ndictionary<string, string> ConfigMap;\nsequence<string> GroupNameList;\nsequence<byte> CertificateDer;\nsequence<CertificateDer> CertificateList;\n\ndictionary<UserInfo, string> UserInfoMap;\n\nclass Tree {\nChannel c;\nTreeList children;\nUserList users;\n};\nexception MurmurException {};\nexception InvalidSessionException extends MurmurException {};\nexception InvalidChannelException extends MurmurException {};\nexception InvalidServerException extends MurmurException {};\nexception ServerBootedException extends MurmurException {};\nexception ServerFailureException extends MurmurException {};\nexception InvalidUserException extends MurmurException {};\nexception InvalidTextureException extends MurmurException {};\nexception InvalidCallbackException extends MurmurException {};\nexception InvalidSecretException extends MurmurException {};\nexception NestingLimitException extends MurmurException {};\nexception WriteOnlyException extends MurmurException {};\nexception InvalidInputDataException extends MurmurException {};\n\ninterface ServerCallback {\nidempotent void userConnected(User state);\nidempotent void userDisconnected(User state);\nidempotent void userStateChanged(User state);\nidempotent void userTextMessage(User state, TextMessage message);\nidempotent void channelCreated(Channel state);\nidempotent void channelRemoved(Channel state);\nidempotent void channelStateChanged(Channel state);\n};\n\nconst int ContextServer = 0x01;\nconst int ContextChannel = 0x02;\nconst int ContextUser = 0x04;\n\ninterface ServerContextCallback {\nidempotent void contextAction(string action, User usr, int session, int channelid);\n};\n\ninterface ServerAuthenticator {\nidempotent int authenticate(string name, string pw, CertificateList certificates, string certhash, bool certstrong, out string newname, out GroupNameList groups);\n\nidempotent bool getInfo(int id, out UserInfoMap info);\n\nidempotent int nameToId(string name);\n\nidempotent string idToName(int id);\n\nidempotent Texture idToTexture(int id);\n};\n\ninterface ServerUpdatingAuthenticator extends ServerAuthenticator {\nint registerUser(UserInfoMap info);\n\nint unregisterUser(int id);\n\nidempotent NameMap getRegisteredUsers(string filter);\n\nidempotent int setInfo(int id, UserInfoMap info);\n\nidempotent int setTexture(int id, Texture tex);\n};\n\n[\"amd\"] interface Server {\nidempotent bool isRunning() throws InvalidSecretException;\n\nvoid start() throws ServerBootedException, ServerFailureException, InvalidSecretException;\n\nvoid stop() throws ServerBootedException, InvalidSecretException;\n\nvoid delete() throws ServerBootedException, InvalidSecretException;\n\nidempotent int id() throws InvalidSecretException;\n\nvoid addCallback(ServerCallback *cb) throws ServerBootedException, InvalidCallbackException, InvalidSecretException;\n\nvoid removeCallback(ServerCallback *cb) throws ServerBootedException, InvalidCallbackException, InvalidSecretException;\n\nvoid setAuthenticator(ServerAuthenticator *auth) throws ServerBootedException, InvalidCallbackException, InvalidSecretException;\n\nidempotent string getConf(string key) throws InvalidSecretException, WriteOnlyException;\n\nidempotent ConfigMap getAllConf() throws InvalidSecretException;\n\nidempotent void setConf(string key, string value) throws InvalidSecretException;\n\nidempotent void setSuperuserPassword(string pw) throws InvalidSecretException;\n\nidempotent LogList getLog(int first, int last) throws InvalidSecretException;\n\nidempotent int getLogLen() throws InvalidSecretException;\n\nidempotent UserMap getUsers() throws ServerBootedException, InvalidSecretException;\n\nidempotent ChannelMap getChannels() throws ServerBootedException, InvalidSecretException;\n\nidempotent CertificateList getCertificateList(int session) throws ServerBootedException, InvalidSessionException, InvalidSecretException;\n\nidempotent Tree getTree() throws ServerBootedException, InvalidSecretException;\n\nidempotent BanList getBans() throws ServerBootedException, InvalidSecretException;\n\nidempotent void setBans(BanList bans) throws ServerBootedException, InvalidSecretException;\n\nvoid kickUser(int session, string reason) throws ServerBootedException, InvalidSessionException, InvalidSecretException;\n\nidempotent User getState(int session) throws ServerBootedException, InvalidSessionException, InvalidSecretException;\n\nidempotent void setState(User state) throws ServerBootedException, InvalidSessionException, InvalidChannelException, InvalidSecretException;\n\nvoid sendMessage(int session, string text) throws ServerBootedException, InvalidSessionException, InvalidSecretException;\n\nbool hasPermission(int session, int channelid, int perm) throws ServerBootedException, InvalidSessionException, InvalidChannelException, InvalidSecretException;\n\nidempotent int effectivePermissions(int session, int channelid) throws ServerBootedException, InvalidSessionException, InvalidChannelException, InvalidSecretException;\n\nvoid addContextCallback(int session, string action, string text, ServerContextCallback *cb, int ctx) throws ServerBootedException, InvalidCallbackException, InvalidSecretException;\n\nvoid removeContextCallback(ServerContextCallback *cb) throws ServerBootedException, InvalidCallbackException, InvalidSecretException;\n\nidempotent Channel getChannelState(int channelid) throws ServerBootedException, InvalidChannelException, InvalidSecretException;\n\nidempotent void setChannelState(Channel state) throws ServerBootedException, InvalidChannelException, InvalidSecretException, NestingLimitException;\n\nvoid removeChannel(int channelid) throws ServerBootedException, InvalidChannelException, InvalidSecretException;\n\nint addChannel(string name, int parent) throws ServerBootedException, InvalidChannelException, InvalidSecretException, NestingLimitException;\n\nvoid sendMessageChannel(int channelid, bool tree, string text) throws ServerBootedException, InvalidChannelException, InvalidSecretException;\n\nidempotent void getACL(int channelid, out ACLList acls, out GroupList groups, out bool inherit) throws ServerBootedException, InvalidChannelException, InvalidSecretException;\n\nidempotent void setACL(int channelid, ACLList acls, GroupList groups, bool inherit) throws ServerBootedException, InvalidChannelException, InvalidSecretException;\n\nidempotent void addUserToGroup(int channelid, int session, string group) throws ServerBootedException, InvalidChannelException, InvalidSessionException, InvalidSecretException;\n\nidempotent void removeUserFromGroup(int channelid, int session, string group) throws ServerBootedException, InvalidChannelException, InvalidSessionException, InvalidSecretException;\n\nidempotent void redirectWhisperGroup(int session, string source, string target) throws ServerBootedException, InvalidSessionException, InvalidSecretException;\n\nidempotent NameMap getUserNames(IdList ids) throws ServerBootedException, InvalidSecretException;\n\nidempotent IdMap getUserIds(NameList names) throws ServerBootedException, InvalidSecretException;\n\nint registerUser(UserInfoMap info) throws ServerBootedException, InvalidUserException, InvalidSecretException;\n\nvoid unregisterUser(int userid) throws ServerBootedException, InvalidUserException, InvalidSecretException;\n\nidempotent void updateRegistration(int userid, UserInfoMap info) throws ServerBootedException, InvalidUserException, InvalidSecretException;\n\nidempotent UserInfoMap getRegistration(int userid) throws ServerBootedException, InvalidUserException, InvalidSecretException;\n\nidempotent NameMap getRegisteredUsers(string filter) throws ServerBootedException, InvalidSecretException;\n\nidempotent int verifyPassword(string name, string pw) throws ServerBootedException, InvalidSecretException;\n\nidempotent Texture getTexture(int userid) throws ServerBootedException, InvalidUserException, InvalidSecretException;\n\nidempotent void setTexture(int userid, Texture tex) throws ServerBootedException, InvalidUserException, InvalidTextureException, InvalidSecretException;\n\nidempotent int getUptime() throws ServerBootedException, InvalidSecretException;\n\n idempotent void updateCertificate(string certificate, string privateKey, string passphrase) throws ServerBootedException, InvalidSecretException, InvalidInputDataException;\n \n idempotent void startListening(int userid, int channelid);\n \n idempotent void stopListening(int userid, int channelid);\n \n idempotent bool isListening(int userid, int channelid);\n \n idempotent IntList getListeningChannels(int userid);\n \n idempotent IntList getListeningUsers(int channelid);\n \n idempotent void sendWelcomeMessage(IdList receiverUserIDs);\n};\n\ninterface MetaCallback {\nvoid started(Server *srv);\n\nvoid stopped(Server *srv);\n};\nsequence<Server *> ServerList;\n\n[\"amd\"] interface Meta {\nidempotent Server *getServer(int id) throws InvalidSecretException;\n\nServer *newServer() throws InvalidSecretException;\n\nidempotent ServerList getBootedServers() throws InvalidSecretException;\n\nidempotent ServerList getAllServers() throws InvalidSecretException;\n\nidempotent ConfigMap getDefaultConf() throws InvalidSecretException;\n\nidempotent void getVersion(out int major, out int minor, out int patch, out string text);\n\nvoid addCallback(MetaCallback *cb) throws InvalidCallbackException, InvalidSecretException;\n\nvoid removeCallback(MetaCallback *cb) throws InvalidCallbackException, InvalidSecretException;\n\nidempotent int getUptime();\n\nidempotent string getSlice();\n\nidempotent Ice::SliceChecksumDict getSliceChecksums();\n};\n};\n")); } diff --git a/src/murmur/RPC.cpp b/src/murmur/RPC.cpp index d6f9e74ec..cb976c68b 100644 --- a/src/murmur/RPC.cpp +++ b/src/murmur/RPC.cpp @@ -570,6 +570,13 @@ void Server::stopListeningToChannel(ServerUser *user, Channel *cChannel) { sendAll(mpus); } +void Server::sendWelcomeMessageTo(ServerUser *user) { + MumbleProto::ServerConfig mpsc; + mpsc.set_welcome_text(qsWelcomeText.toUtf8().data()); + + sendMessage(user, mpsc); +} + void Meta::connectListener(QObject *obj) { connect(this, SIGNAL(started(Server *)), obj, SLOT(started(Server *))); connect(this, SIGNAL(stopped(Server *)), obj, SLOT(stopped(Server *))); diff --git a/src/murmur/Server.h b/src/murmur/Server.h index 17418fd55..e3cd1daf9 100644 --- a/src/murmur/Server.h +++ b/src/murmur/Server.h @@ -353,6 +353,7 @@ public: void clearTempGroups(User *user, Channel *cChannel = nullptr, bool recurse = true); void startListeningToChannel(ServerUser *user, Channel *cChannel); void stopListeningToChannel(ServerUser *user, Channel *cChannel); + void sendWelcomeMessageTo(ServerUser *user); signals: void registerUserSig(int &, const QMap< int, QString > &); void unregisterUserSig(int &, int); |