Skip to content
Permalink
Browse files

Respect maximum channel user limits when joining server

Fixes #1930
  • Loading branch information...
bontibon authored and mkrautz committed Nov 27, 2015
1 parent 4d5d0a8 commit fea39f20089ddc918590e8188cbcc1ac20ff6f77
Showing with 39 additions and 23 deletions.
  1. +22 −23 src/murmur/Messages.cpp
  2. +13 −0 src/murmur/Server.cpp
  3. +4 −0 src/murmur/Server.h
@@ -176,6 +176,25 @@ void Server::msgAuthenticate(ServerUser *uSource, MumbleProto::Authenticate &msg
ok = false;
}

Channel *lc;
if (bRememberChan) {
lc = qhChannels.value(readLastChannel(uSource->iId));
} else {
lc = qhChannels.value(iDefaultChan);
}

if (! lc || ! hasPermission(uSource, lc, ChanACL::Enter) || isChannelFull(lc, uSource)) {
lc = qhChannels.value(iDefaultChan);
if (! lc || ! hasPermission(uSource, lc, ChanACL::Enter) || isChannelFull(lc, uSource)) {
lc = root;
if (isChannelFull(lc, uSource)) {
reason = QString::fromLatin1("Server channels are full");
rtType = MumbleProto::Reject_RejectType_ServerFull;
ok = false;
}
}
}

if (! ok) {
log(uSource, QString("Rejected connection from %1: %2")
.arg(addressToString(uSource->peerAddress(), uSource->peerPort()), reason));
@@ -280,19 +299,6 @@ void Server::msgAuthenticate(ServerUser *uSource, MumbleProto::Authenticate &msg
// Transmit user profile
MumbleProto::UserState mpus;

Channel *lc;
if (bRememberChan)
lc = qhChannels.value(readLastChannel(uSource->iId));
else
lc = qhChannels.value(iDefaultChan);

if (! lc || ! hasPermission(uSource, lc, ChanACL::Enter)) {
lc = qhChannels.value(iDefaultChan);
if (! lc || ! hasPermission(uSource, lc, ChanACL::Enter)) {
lc = root;
}
}

userEnterChannel(uSource, lc, mpus);

uSource->sState = ServerUser::Authenticated;
@@ -520,16 +526,9 @@ void Server::msgUserState(ServerUser *uSource, MumbleProto::UserState &msg) {
PERM_DENIED(pDstServerUser, c, ChanACL::Enter);
return;
}
if (! hasPermission(uSource, c, ChanACL::Write)) {
if (c->uiMaxUsers) {
if (static_cast<unsigned int>(c->qlUsers.count()) >= c->uiMaxUsers) {
PERM_DENIED_FALLBACK(ChannelFull, 0x010201, QLatin1String("Channel is full"));
return;
}
} else if (iMaxUsersPerChannel && (c->qlUsers.count() >= iMaxUsersPerChannel)) {
PERM_DENIED_FALLBACK(ChannelFull, 0x010201, QLatin1String("Channel is full"));
return;
}
if (isChannelFull(c, uSource)) {
PERM_DENIED_FALLBACK(ChannelFull, 0x010201, QLatin1String("Channel is full"));
return;
}
}

@@ -1930,6 +1930,19 @@ bool Server::isTextAllowed(QString &text, bool &changed) {
}
}

bool Server::isChannelFull(Channel *c, ServerUser *u) {
if (u && hasPermission(u, c, ChanACL::Write)) {
return false;
}
if (c->uiMaxUsers) {
return static_cast<unsigned int>(c->qlUsers.count()) >= c->uiMaxUsers;
}
if (iMaxUsersPerChannel) {
return c->qlUsers.count() >= iMaxUsersPerChannel;
}
return false;
}

bool Server::canNest(Channel *newParent, Channel *channel) const {
const int parentLevel = newParent ? static_cast<int>(newParent->getLevel()) : -1;
const int channelDepth = channel ? static_cast<int>(channel->getDepth()) : 0;
@@ -333,6 +333,10 @@ class Server : public QThread {
bool setChannelState(Channel *c, Channel *parent, const QString &qsName, const QSet<Channel *> &links, const QString &desc = QString(), const int position = 0);
void sendTextMessage(Channel *cChannel, ServerUser *pUser, bool tree, const QString &text);

/// Returns true if a channel is full. If a user is provided, false will always
/// be returned if the user has write permission in the channel.
bool isChannelFull(Channel *c, ServerUser *u = 0);

// Database / DBus functions. Implementation in ServerDB.cpp
void initialize();
int authenticate(QString &name, const QString &pw, int sessionId = 0, const QStringList &emails = QStringList(), const QString &certhash = QString(), bool bStrongCert = false, const QList<QSslCertificate> & = QList<QSslCertificate>());

0 comments on commit fea39f2

Please sign in to comment.
You can’t perform that action at this time.