Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEAT(server): Allow running while DB is in read-only mode #6673

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
22 changes: 19 additions & 3 deletions docs/dev/ExtendingTheIceInterface.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ The files involved in extending the Ice interface are
| `MumbleServer.cpp` | Contains some boilerplate and Ice-internal implementation code. This file is automatically generated. |
| `MumbleServerI.h` | Contains the definition of the actually implemented API classes (`ServerI` and `MetaI`). These extend the abstract base classes from `MumbleServer.h` |
| `MumbleServerWrapper.cpp` | Contains wrapper implementation of the `*I` API classes. This file is automatically generated. |
| `MumbleServere.h` | Contains the definition of a statically used helper class |
| `MumbleServere.cpp` | Contains the implementation of that helper class **and** _static_ functions used to actually implement the server-side functionality of the Ice API functions |
| `MumbleServer.h` | Contains the definition of a statically used helper class |
| `MumbleServer.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 `MumbleServerIce.cpp` |

All auto-generated functions will end up in the corresponding directory inside the `build` directory.
Expand Down Expand Up @@ -62,10 +62,26 @@ Error reporting works via the `cb->ice_exception` function and if everything wen
In general it is a good idea to have a look at the existing implementation inside `MumbleServerIce.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
(`server`, `channel`, etc.) based on 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`)

Furthermore, you might notice the macro definitions like `ACCESS_Server_isListening_READ`. These are used to determine what kind of access privilege
execution of the associated Ice function is required. By default, all functions are assumed to require write-privilege in order to be able to be
executed. The general form of these macros is
```
ACCESS_<className>_<functionName>_<access>
```
where
- `<className>` and `<functionName>` are used as defined above. They define which function this macro will be associated with.
- `<access>` is the required access privilege. Possible values are `READ` and `ALL`, which allow function execution by anyone who has
read-privilege or simply everyone, regardless of their privileges.
The actual implementation of the access privilege checking is performed in the auto-generated `MumbleServerIceWrapper.cpp` based on whether an
associated macro is defined and if so, which one.
Please remember to `#undef` the respective macro at the end of the `MumbleServerIce.cpp` file in order to avoid macro definitions spilling into other
files when using unity builds.


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`.
Expand Down
2 changes: 2 additions & 0 deletions src/Mumble.proto
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ message Reject {
// The user did not provide a certificate but one is required.
NoCertificate = 7;
AuthenticatorFail = 8;
// The server is currently not accepting new connections
NoNewConnections = 9;
}
// Rejection type.
optional RejectType type = 1;
Expand Down
47 changes: 47 additions & 0 deletions src/MumbleProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,53 @@
namespace Mumble {
namespace Protocol {

std::string messageTypeName(TCPMessageType type) {
#define PROCESS_MUMBLE_TCP_MESSAGE(name, value) \
case TCPMessageType::name: \
return #name;

switch (type) { MUMBLE_ALL_TCP_MESSAGES }

#undef PROCESS_MUMBLE_TCP_MESSAGE

// Should be unreachable
assert(false);
return "Unknown";
}

std::string messageTypeName(UDPMessageType type) {
#define PROCESS_MUMBLE_UDP_MESSAGE(name, value) \
case UDPMessageType::name: \
return #name;

switch (type) { MUMBLE_ALL_UDP_MESSAGES }

#undef PROCESS_MUMBLE_UDP_MESSAGE

// Should be unreachable
assert(false);
return "Unknown";
}

std::string messageTypeName(LegacyUDPMessageType type) {
switch (type) {
case LegacyUDPMessageType::VoiceCELTAlpha:
return "VoiceCELTAlpha";
case LegacyUDPMessageType::Ping:
return "Ping";
case LegacyUDPMessageType::VoiceSpeex:
return "VoiceSpeex";
case LegacyUDPMessageType::VoiceCELTBeta:
return "VoiceCELTBeta";
case LegacyUDPMessageType::VoiceOpus:
return "VoiceOpus";
}

// Should be unreachable
assert(false);
return "Unknown";
}

bool protocolVersionsAreCompatible(Version::full_t lhs, Version::full_t rhs) {
// At this point the protocol version only makes a difference between pre-protobuf and post-protobuf
return (lhs < PROTOBUF_INTRODUCTION_VERSION) == (rhs < PROTOBUF_INTRODUCTION_VERSION);
Expand Down
8 changes: 8 additions & 0 deletions src/MumbleProtocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "VolumeAdjustment.h"

#include <cstdint>
#include <string>
#include <vector>

#include <gsl/span>
Expand Down Expand Up @@ -72,15 +73,22 @@ namespace Protocol {
*/
enum class TCPMessageType : byte { MUMBLE_ALL_TCP_MESSAGES };
#undef PROCESS_MUMBLE_TCP_MESSAGE

std::string messageTypeName(TCPMessageType type);

#define PROCESS_MUMBLE_UDP_MESSAGE(name, value) name = value,
/**
* Enum holding all possible UDP message types
*/
enum class UDPMessageType : byte { MUMBLE_ALL_UDP_MESSAGES };
#undef PROCESS_MUMBLE_UDP_MESSAGE

std::string messageTypeName(UDPMessageType type);

enum class LegacyUDPMessageType : byte { VoiceCELTAlpha, Ping, VoiceSpeex, VoiceCELTBeta, VoiceOpus };

std::string messageTypeName(LegacyUDPMessageType type);

enum class AudioCodec {
Opus,
CELT_Alpha, // 0.7.0
Expand Down
17 changes: 17 additions & 0 deletions src/murmur/DBState.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright The Mumble Developers. All rights reserved.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file at the root of the
// Mumble source tree or at <https://www.mumble.info/LICENSE>.

#ifndef MUMBLE_MURMUR_DBSTATE_H_
#define MUMBLE_MURMUR_DBSTATE_H_

/**
* Possible states the database can be in
*/
enum class DBState {
Normal,
ReadOnly,
};

#endif // MUMBLE_MURMUR_DBSTATE_H_
3 changes: 3 additions & 0 deletions src/murmur/Meta.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "Timer.h"

#include "DBState.h"
#include "Version.h"

#ifdef Q_OS_WIN
Expand Down Expand Up @@ -184,6 +185,8 @@ class Meta : public QObject {
QString qsOS, qsOSVersion;
Timer tUptime;

DBState assumedDBState = DBState::Normal;

#ifdef Q_OS_WIN
static HANDLE hQoS;
#endif
Expand Down
Loading
Loading