Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mumble-voip/mumble.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Message.h3
-rw-r--r--src/Mumble.proto6
-rw-r--r--src/murmur/Messages.cpp10
-rw-r--r--src/murmur/Server.cpp80
-rw-r--r--src/murmur/Server.h7
5 files changed, 103 insertions, 3 deletions
diff --git a/src/Message.h b/src/Message.h
index 4eee97d69..1a9572fe9 100644
--- a/src/Message.h
+++ b/src/Message.h
@@ -54,7 +54,8 @@
MUMBLE_MH_MSG(ContextActionAdd) \
MUMBLE_MH_MSG(ContextAction) \
MUMBLE_MH_MSG(UserList) \
- MUMBLE_MH_MSG(VoiceTarget)
+ MUMBLE_MH_MSG(VoiceTarget) \
+ MUMBLE_MH_MSG(PermissionQuery)
class MessageHandler {
public:
diff --git a/src/Mumble.proto b/src/Mumble.proto
index eb81c589c..511db13a3 100644
--- a/src/Mumble.proto
+++ b/src/Mumble.proto
@@ -208,3 +208,9 @@ message VoiceTarget {
optional uint32 id = 1;
repeated Target targets = 2;
}
+
+message PermissionQuery {
+ optional uint32 channel_id = 1;
+ optional uint32 permissions = 2;
+ optional bool flush = 3 [default = false];
+}
diff --git a/src/murmur/Messages.cpp b/src/murmur/Messages.cpp
index d1c233728..153636844 100644
--- a/src/murmur/Messages.cpp
+++ b/src/murmur/Messages.cpp
@@ -1275,3 +1275,13 @@ void Server::msgVoiceTarget(ServerUser *uSource, MumbleProto::VoiceTarget &msg)
uSource->qmTargets.insert(target, wt);
}
}
+
+void Server::msgPermissionQuery(ServerUser *uSource, MumbleProto::PermissionQuery &msg) {
+ MSG_SETUP(ServerUser::Authenticated);
+
+ Channel *c = qhChannels.value(msg.channel_id());
+ if (!c)
+ return;
+
+ sendClientPermission(uSource, c, true);
+}
diff --git a/src/murmur/Server.cpp b/src/murmur/Server.cpp
index dbc649a3f..bf30f6f77 100644
--- a/src/murmur/Server.cpp
+++ b/src/murmur/Server.cpp
@@ -80,6 +80,7 @@ ServerUser::ServerUser(Server *p, QSslSocket *socket) : Connection(p, socket), U
bUdp = true;
uiVersion = 0;
bVerified = true;
+ iLastPermissionCheck = -1;
}
@@ -1304,6 +1305,8 @@ void Server::userEnterChannel(User *p, Channel *c, bool quiet, bool ignoretemp)
if (old && old->bTemporary && old->qlUsers.isEmpty() && ! ignoretemp) {
QCoreApplication::instance()->postEvent(this, new ExecEvent(boost::bind(&Server::removeChannel, this, old->iId)));
}
+
+ sendClientPermission(static_cast<ServerUser *>(p), c);
}
bool Server::hasPermission(ServerUser *p, Channel *c, QFlags<ChanACL::Perm> perm) {
@@ -1311,7 +1314,78 @@ bool Server::hasPermission(ServerUser *p, Channel *c, QFlags<ChanACL::Perm> perm
return ChanACL::hasPermission(p, c, perm, acCache);
}
+void Server::sendClientPermission(ServerUser *u, Channel *c, bool forceupdate) {
+ unsigned int perm;
+
+ {
+ QMutexLocker qml(&qmCache);
+ ChanACL::hasPermission(u, c, ChanACL::Enter, acCache);
+ perm = acCache.value(u)->value(c);
+ }
+
+ if (forceupdate)
+ u->iLastPermissionCheck = c->iId;
+
+ if (u->qmPermissionSent.value(c->iId) != perm) {
+ u->qmPermissionSent.insert(c->iId, perm);
+
+ MumbleProto::PermissionQuery mppq;
+ mppq.set_channel_id(c->iId);
+ mppq.set_permissions(perm);
+
+ sendMessage(u, mppq);
+ }
+}
+
+/* This function is a helper for clearACLCache and assumes qmCache is held.
+ * First, check if anything actually changed, or if the list is getting awfully large,
+ * because this function is potentially quite expensive.
+ * If all the items are still valid; great. If they aren't, send off the last channel
+ * the client expliticly asked for -- this may not be what it wants, but it's our best
+ * guess.
+ */
+
+void Server::flushClientPermissionCache(ServerUser *u, MumbleProto::PermissionQuery &mppq) {
+ QMap<int, unsigned int>::const_iterator i;
+ bool match = (u->qmPermissionSent.count() < 20);
+ for(i = u->qmPermissionSent.constBegin(); (match && (i != u->qmPermissionSent.constEnd())); ++i) {
+ Channel *c = qhChannels.value(i.key());
+ if (! c) {
+ match = false;
+ } else {
+ ChanACL::hasPermission(u, c, ChanACL::Enter, acCache);
+ unsigned int perm = acCache.value(u)->value(c);
+ if (perm != i.value())
+ match = false;
+ }
+ }
+
+ if (match)
+ return;
+
+ u->qmPermissionSent.clear();
+
+ Channel *c = qhChannels.value(u->iLastPermissionCheck);
+ if (! c) {
+ c = u->cChannel;
+ u->iLastPermissionCheck = c->iId;
+ }
+
+ ChanACL::hasPermission(u, c, ChanACL::Enter, acCache);
+ unsigned int perm = acCache.value(u)->value(c);
+ u->qmPermissionSent.insert(c->iId, perm);
+
+ mppq.Clear();
+ mppq.set_channel_id(c->iId);
+ mppq.set_permissions(perm);
+ mppq.set_flush(true);
+
+ sendMessage(u, mppq);
+}
+
void Server::clearACLCache(User *p) {
+ MumbleProto::PermissionQuery mppq;
+
{
QMutexLocker qml(&qmCache);
@@ -1319,10 +1393,16 @@ void Server::clearACLCache(User *p) {
ChanACL::ChanCache *h = acCache.take(p);
if (h)
delete h;
+
+ flushClientPermissionCache(static_cast<ServerUser *>(p), mppq);
} else {
foreach(ChanACL::ChanCache *h, acCache)
delete h;
acCache.clear();
+
+ foreach(ServerUser *u, qhUsers)
+ if (u->sState == ServerUser::Authenticated)
+ flushClientPermissionCache(u, mppq);
}
}
diff --git a/src/murmur/Server.h b/src/murmur/Server.h
index 6bb273719..90ea9227d 100644
--- a/src/murmur/Server.h
+++ b/src/murmur/Server.h
@@ -153,13 +153,14 @@ class ServerUser : public Connection, public User {
typedef QPair<QSet<ServerUser *>, QSet<ServerUser *> > TargetCache;
QMap<int, TargetCache> qmTargetCache;
QMap<QString, QString> qmWhisperRedirect;
-
+
+ int iLastPermissionCheck;
+ QMap<int, unsigned int> qmPermissionSent;
#ifdef Q_OS_UNIX
int sUdpSocket;
#else
SOCKET sUdpSocket;
#endif
-
BandwidthRecord bwr;
struct sockaddr_storage saiUdpAddress;
ServerUser(Server *parent, QSslSocket *socket);
@@ -282,6 +283,8 @@ class Server : public QThread {
bool checkDecrypt(ServerUser *u, const char *encrypted, char *plain, unsigned int cryptlen);
bool hasPermission(ServerUser *p, Channel *c, QFlags<ChanACL::Perm> perm);
+ void sendClientPermission(ServerUser *u, Channel *c, bool updatelast = false);
+ void flushClientPermissionCache(ServerUser *u, MumbleProto::PermissionQuery &mpqq);
void clearACLCache(User *p = NULL);
void sendProtoAll(const ::google::protobuf::Message &msg, unsigned int msgType);