mirror of
https://github.com/mumble-voip/mumble.git
synced 2025-10-26 11:19:16 +00:00
Serverside comment/texture send-on-demand
This commit is contained in:
parent
ad0f30f6d1
commit
60e71510bf
@ -52,6 +52,7 @@ class Channel : public QObject {
|
||||
Channel *cParent;
|
||||
QString qsName;
|
||||
QString qsDesc;
|
||||
QByteArray qbaDescHash;
|
||||
QList<Channel *> qlChannels;
|
||||
QList<User *> qlUsers;
|
||||
QHash<QString, Group *> qhGroups;
|
||||
|
||||
@ -57,7 +57,8 @@
|
||||
MUMBLE_MH_MSG(VoiceTarget) \
|
||||
MUMBLE_MH_MSG(PermissionQuery) \
|
||||
MUMBLE_MH_MSG(CodecVersion) \
|
||||
MUMBLE_MH_MSG(UserStats)
|
||||
MUMBLE_MH_MSG(UserStats) \
|
||||
MUMBLE_MH_MSG(RequestBlob)
|
||||
|
||||
class MessageHandler {
|
||||
public:
|
||||
@ -83,6 +84,22 @@ inline ::std::string u8(const QString &str) {
|
||||
return ::std::string(qba.constData(), qba.length());
|
||||
}
|
||||
|
||||
inline QByteArray blob(const ::std::string &str) {
|
||||
return QByteArray(str.data(), static_cast<int>(str.length()));
|
||||
}
|
||||
|
||||
inline ::std::string blob(const QByteArray &str) {
|
||||
return ::std::string(str.constData(), str.length());
|
||||
}
|
||||
|
||||
inline QByteArray sha1(const QByteArray &blob) {
|
||||
return QCryptographicHash::hash(blob, QCryptographicHash::Sha1);
|
||||
}
|
||||
|
||||
inline QByteArray sha1(const QString &str) {
|
||||
return QCryptographicHash::hash(str.toUtf8(), QCryptographicHash::Sha1);
|
||||
}
|
||||
|
||||
#else
|
||||
class Message;
|
||||
#endif
|
||||
|
||||
@ -71,6 +71,7 @@ message ChannelState {
|
||||
repeated uint32 links_remove = 7;
|
||||
optional bool temporary = 8 [default = false];
|
||||
optional int32 position = 9 [default = 0];
|
||||
optional bytes description_hash = 10;
|
||||
}
|
||||
|
||||
message UserRemove {
|
||||
@ -96,6 +97,8 @@ message UserState {
|
||||
optional string plugin_identity = 13;
|
||||
optional string comment = 14;
|
||||
optional string hash = 15;
|
||||
optional bytes comment_hash = 16;
|
||||
optional bytes texture_hash = 17;
|
||||
}
|
||||
|
||||
message BanList {
|
||||
@ -256,3 +259,9 @@ message UserStats {
|
||||
optional uint32 idlesecs = 17;
|
||||
optional bool strong_certificate = 18 [default = false];
|
||||
}
|
||||
|
||||
message RequestBlob {
|
||||
repeated uint32 session_texture = 1;
|
||||
repeated uint32 session_comment = 2;
|
||||
repeated uint32 channel_description = 3;
|
||||
}
|
||||
|
||||
@ -43,11 +43,13 @@ class User {
|
||||
int iId;
|
||||
QString qsName;
|
||||
QString qsComment;
|
||||
QByteArray qbaCommentHash;
|
||||
QString qsHash;
|
||||
bool bMute, bDeaf, bSuppress;
|
||||
bool bSelfMute, bSelfDeaf;
|
||||
Channel *cChannel;
|
||||
QByteArray qbaTexture;
|
||||
QByteArray qbaTextureHash;
|
||||
|
||||
User();
|
||||
virtual ~User() {};
|
||||
|
||||
@ -220,7 +220,7 @@ void Server::msgAuthenticate(ServerUser *uSource, MumbleProto::Authenticate &msg
|
||||
uSource->qlCodecs.append(static_cast<qint32>(0x8000000a));
|
||||
}
|
||||
recheckCodecVersions();
|
||||
|
||||
|
||||
MumbleProto::CodecVersion mpcv;
|
||||
mpcv.set_alpha(iCodecAlpha);
|
||||
mpcv.set_beta(iCodecBeta);
|
||||
@ -245,10 +245,14 @@ void Server::msgAuthenticate(ServerUser *uSource, MumbleProto::Authenticate &msg
|
||||
mpcs.set_name(u8(qsRegName.isEmpty() ? QLatin1String("Root") : qsRegName));
|
||||
else
|
||||
mpcs.set_name(u8(c->qsName));
|
||||
if (! c->qsDesc.isEmpty())
|
||||
mpcs.set_description(u8(c->qsDesc));
|
||||
|
||||
mpcs.set_position(c->iPosition);
|
||||
|
||||
if ((uSource->uiVersion >= 0x010202) && ! c->qbaDescHash.isEmpty())
|
||||
mpcs.set_description_hash(blob(c->qbaDescHash));
|
||||
else if (! c->qsDesc.isEmpty())
|
||||
mpcs.set_description(u8(c->qsDesc));
|
||||
|
||||
sendMessage(uSource, mpcs);
|
||||
|
||||
foreach(c, c->qlChannels)
|
||||
@ -281,20 +285,27 @@ void Server::msgAuthenticate(ServerUser *uSource, MumbleProto::Authenticate &msg
|
||||
lc = root;
|
||||
|
||||
userEnterChannel(uSource, lc, mpus);
|
||||
|
||||
|
||||
uSource->sState = ServerUser::Authenticated;
|
||||
mpus.set_session(uSource->uiSession);
|
||||
mpus.set_name(u8(uSource->qsName));
|
||||
if (uSource->iId >= 0) {
|
||||
uSource->qbaTexture = getUserTexture(uSource->iId);
|
||||
mpus.set_user_id(uSource->iId);
|
||||
if (! uSource->qbaTexture.isEmpty())
|
||||
|
||||
hashAssign(uSource->qbaTexture, uSource->qbaTextureHash, getUserTexture(uSource->iId));
|
||||
|
||||
if (! uSource->qbaTextureHash.isEmpty())
|
||||
mpus.set_texture_hash(blob(uSource->qbaTextureHash));
|
||||
else if (! uSource->qbaTexture.isEmpty())
|
||||
mpus.set_texture(std::string(uSource->qbaTexture.constData(), uSource->qbaTexture.size()));
|
||||
|
||||
const QMap<int, QString> &info = getRegistration(uSource->iId);
|
||||
if (info.contains(ServerDB::User_Comment)) {
|
||||
uSource->qsComment = info.value(ServerDB::User_Comment);
|
||||
mpus.set_comment(u8(uSource->qsComment));
|
||||
hashAssign(uSource->qsComment, uSource->qbaCommentHash, info.value(ServerDB::User_Comment));
|
||||
if (! uSource->qbaCommentHash.isEmpty())
|
||||
mpus.set_comment_hash(blob(uSource->qbaCommentHash));
|
||||
else if (! uSource->qsComment.isEmpty())
|
||||
mpus.set_comment(u8(uSource->qsComment));
|
||||
}
|
||||
}
|
||||
if (! uSource->qsHash.isEmpty())
|
||||
@ -302,7 +313,13 @@ void Server::msgAuthenticate(ServerUser *uSource, MumbleProto::Authenticate &msg
|
||||
if (uSource->cChannel->iId != 0)
|
||||
mpus.set_channel_id(uSource->cChannel->iId);
|
||||
|
||||
sendAll(mpus);
|
||||
sendAll(mpus, 0x010202);
|
||||
|
||||
if (! uSource->qbaTexture.isEmpty())
|
||||
mpus.set_texture(blob(uSource->qbaTexture));
|
||||
if (! uSource->qsComment.isEmpty())
|
||||
mpus.set_comment(u8(uSource->qsComment));
|
||||
sendAll(mpus, ~ 0x010202);
|
||||
|
||||
// Transmit other users profiles
|
||||
foreach(ServerUser *u, qhUsers) {
|
||||
@ -333,7 +350,9 @@ void Server::msgAuthenticate(ServerUser *uSource, MumbleProto::Authenticate &msg
|
||||
mpus.set_self_deaf(true);
|
||||
else if (u->bSelfMute)
|
||||
mpus.set_self_mute(true);
|
||||
if (! u->qsComment.isEmpty())
|
||||
if ((uSource->uiVersion >= 0x010202) && ! u->qbaCommentHash.isEmpty())
|
||||
mpus.set_comment_hash(blob(u->qbaCommentHash));
|
||||
else if (! u->qsComment.isEmpty())
|
||||
mpus.set_comment(u8(u->qsComment));
|
||||
if (! u->qsHash.isEmpty())
|
||||
mpus.set_hash(u8(u->qsHash));
|
||||
@ -543,9 +562,11 @@ void Server::msgUserState(ServerUser *uSource, MumbleProto::UserState &msg) {
|
||||
|
||||
if (msg.has_comment()) {
|
||||
pDstServerUser->qsComment = u8(msg.comment());
|
||||
|
||||
if (! bAllowHTML) {
|
||||
pDstServerUser->qsComment = toPlainText(pDstServerUser->qsComment);
|
||||
|
||||
if (bAllowHTML) {
|
||||
hashAssign(pDstServerUser->qsComment, pDstServerUser->qbaCommentHash, u8(msg.comment()));
|
||||
} else {
|
||||
hashAssign(pDstServerUser->qsComment, pDstServerUser->qbaCommentHash, toPlainText(u8(msg.comment())));
|
||||
msg.set_comment(u8(pDstServerUser->qsComment));
|
||||
}
|
||||
|
||||
@ -603,8 +624,18 @@ void Server::msgUserState(ServerUser *uSource, MumbleProto::UserState &msg) {
|
||||
}
|
||||
}
|
||||
|
||||
if (! bNoBroadcast)
|
||||
sendAll(msg);
|
||||
if (! bNoBroadcast) {
|
||||
sendAll(msg, ~ 0x010202);
|
||||
if (msg.has_texture() && ! pDstServerUser->qbaTextureHash.isEmpty()) {
|
||||
msg.clear_texture();
|
||||
msg.set_texture_hash(blob(pDstServerUser->qbaTextureHash));
|
||||
}
|
||||
if (msg.has_comment() && ! pDstServerUser->qbaCommentHash.isEmpty()) {
|
||||
msg.clear_comment();
|
||||
msg.set_comment_hash(blob(pDstServerUser->qbaCommentHash));
|
||||
}
|
||||
sendAll(msg, 0x010202);
|
||||
}
|
||||
|
||||
emit userStateChanged(pDstServerUser);
|
||||
}
|
||||
@ -732,7 +763,7 @@ void Server::msgChannelState(ServerUser *uSource, MumbleProto::ChannelState &msg
|
||||
}
|
||||
|
||||
c = addChannel(p, qsName, msg.temporary(), msg.position());
|
||||
c->qsDesc = qsDesc;
|
||||
hashAssign(c->qsDesc, c->qbaDescHash, qsDesc);
|
||||
|
||||
if (uSource->iId >= 0) {
|
||||
Group *g = new Group(c, "admin");
|
||||
@ -757,7 +788,13 @@ void Server::msgChannelState(ServerUser *uSource, MumbleProto::ChannelState &msg
|
||||
msg.set_channel_id(c->iId);
|
||||
log(uSource, QString("Added channel %1 under %2").arg(QString(*c), QString(*p)));
|
||||
emit channelCreated(c);
|
||||
sendAll(msg);
|
||||
|
||||
sendAll(msg, ~ 0x010202);
|
||||
if (! c->qbaDescHash.isEmpty()) {
|
||||
msg.clear_description();
|
||||
msg.set_description_hash(blob(c->qbaDescHash));
|
||||
}
|
||||
sendAll(msg, 0x010202);
|
||||
|
||||
if (c->bTemporary) {
|
||||
// If a temporary channel has been created move the creator right in there
|
||||
@ -875,7 +912,7 @@ void Server::msgChannelState(ServerUser *uSource, MumbleProto::ChannelState &msg
|
||||
c->qsName = qsName;
|
||||
}
|
||||
if (! qsDesc.isNull())
|
||||
c->qsDesc = qsDesc;
|
||||
hashAssign(c->qsDesc, c->qbaDescHash, qsDesc);
|
||||
|
||||
if (msg.has_position())
|
||||
c->iPosition = msg.position();
|
||||
@ -889,7 +926,13 @@ void Server::msgChannelState(ServerUser *uSource, MumbleProto::ChannelState &msg
|
||||
|
||||
updateChannel(c);
|
||||
emit channelStateChanged(c);
|
||||
sendAll(msg);
|
||||
|
||||
sendAll(msg, ~ 0x010202);
|
||||
if (msg.has_description() && ! c->qbaDescHash.isEmpty()) {
|
||||
msg.clear_description();
|
||||
msg.set_description_hash(blob(c->qbaDescHash));
|
||||
}
|
||||
sendAll(msg, 0x010202);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1444,3 +1487,45 @@ void Server::msgUserStats(ServerUser*uSource, MumbleProto::UserStats &msg) {
|
||||
|
||||
sendMessage(uSource, msg);
|
||||
}
|
||||
|
||||
void Server::msgRequestBlob(ServerUser *uSource, MumbleProto::RequestBlob &msg) {
|
||||
int ntextures = msg.session_texture_size();
|
||||
int ncomments = msg.session_comment_size();
|
||||
int ndescriptions = msg.channel_description_size();
|
||||
|
||||
if (ndescriptions) {
|
||||
MumbleProto::ChannelState mpcs;
|
||||
for(int i=0;i<ndescriptions;++i) {
|
||||
int id = msg.channel_description(i);
|
||||
Channel *c = qhChannels.value(id);
|
||||
if (c && ! c->qsDesc.isEmpty()) {
|
||||
mpcs.set_channel_id(id);
|
||||
mpcs.set_description(u8(c->qsDesc));
|
||||
sendMessage(uSource, mpcs);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ntextures || ncomments) {
|
||||
MumbleProto::UserState mpus;
|
||||
for(int i=0;i<ntextures;++i) {
|
||||
int session = msg.session_texture(i);
|
||||
ServerUser *su = qhUsers.value(session);
|
||||
if (su && ! su->qbaTexture.isEmpty()) {
|
||||
mpus.set_session(session);
|
||||
mpus.set_texture(std::string(su->qbaTexture.constData(), su->qbaTexture.length()));
|
||||
sendMessage(uSource, mpus);
|
||||
}
|
||||
}
|
||||
if (ntextures)
|
||||
mpus.clear_texture();
|
||||
for(int i=0;i<ncomments;++i) {
|
||||
int session = msg.session_comment(i);
|
||||
ServerUser *su = qhUsers.value(session);
|
||||
if (su && ! su->qsComment.isEmpty()) {
|
||||
mpus.set_session(session);
|
||||
mpus.set_comment(u8(su->qsComment));
|
||||
sendMessage(uSource, mpus);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,7 +108,7 @@ Server::Server(int snum, QObject *p) : QThread(p) {
|
||||
|
||||
iCodecAlpha = iCodecBeta = 0;
|
||||
bPreferAlpha = false;
|
||||
|
||||
|
||||
qnamNetwork = NULL;
|
||||
|
||||
readParams();
|
||||
@ -1230,15 +1230,16 @@ void Server::sendProtoMessage(ServerUser *u, const ::google::protobuf::Message &
|
||||
u->sendMessage(msg, msgType, cache);
|
||||
}
|
||||
|
||||
void Server::sendProtoAll(const ::google::protobuf::Message &msg, unsigned int msgType) {
|
||||
sendProtoExcept(NULL, msg, msgType);
|
||||
void Server::sendProtoAll(const ::google::protobuf::Message &msg, unsigned int msgType, unsigned int minversion) {
|
||||
sendProtoExcept(NULL, msg, msgType, minversion);
|
||||
}
|
||||
|
||||
void Server::sendProtoExcept(ServerUser *u, const ::google::protobuf::Message &msg, unsigned int msgType) {
|
||||
void Server::sendProtoExcept(ServerUser *u, const ::google::protobuf::Message &msg, unsigned int msgType, unsigned int minversion) {
|
||||
QByteArray cache;
|
||||
foreach(ServerUser *usr, qhUsers)
|
||||
if ((usr != u) && (usr->sState == ServerUser::Authenticated))
|
||||
usr->sendMessage(msg, msgType, cache);
|
||||
if ((minversion == 0) || (usr->uiVersion >= minversion) || ((minversion & 0x80000000) && (usr->uiVersion < (~minversion))))
|
||||
usr->sendMessage(msg, msgType, cache);
|
||||
}
|
||||
|
||||
void Server::removeChannel(int id) {
|
||||
@ -1501,6 +1502,7 @@ void Server::recheckCodecVersions() {
|
||||
QMap<int, unsigned int> qmCodecUsercount;
|
||||
QMap<int, unsigned int>::const_iterator i;
|
||||
int users = 0;
|
||||
|
||||
// Count how many users use which codec
|
||||
foreach(ServerUser *u, qhUsers) {
|
||||
if (u->qlCodecs.isEmpty())
|
||||
@ -1553,3 +1555,19 @@ void Server::recheckCodecVersions() {
|
||||
|
||||
log(QString::fromLatin1("CELT codec switch %1 %2 (prefer %3)").arg(iCodecAlpha,0,16).arg(iCodecBeta,0,16).arg(bPreferAlpha ? iCodecAlpha : iCodecBeta,0,16));
|
||||
}
|
||||
|
||||
void Server::hashAssign(QString &dest, QByteArray &hash, const QString &src) {
|
||||
dest = src;
|
||||
if (src.length() > 128)
|
||||
hash = sha1(dest);
|
||||
else
|
||||
hash = QByteArray();
|
||||
}
|
||||
|
||||
void Server::hashAssign(QByteArray &dest, QByteArray &hash, const QByteArray &src) {
|
||||
dest = src;
|
||||
if (src.length() > 128)
|
||||
hash = sha1(dest);
|
||||
else
|
||||
hash = QByteArray();
|
||||
}
|
||||
|
||||
@ -294,18 +294,21 @@ class Server : public QThread {
|
||||
void flushClientPermissionCache(ServerUser *u, MumbleProto::PermissionQuery &mpqq);
|
||||
void clearACLCache(User *p = NULL);
|
||||
|
||||
void sendProtoAll(const ::google::protobuf::Message &msg, unsigned int msgType);
|
||||
void sendProtoExcept(ServerUser *, const ::google::protobuf::Message &msg, unsigned int msgType);
|
||||
void sendProtoAll(const ::google::protobuf::Message &msg, unsigned int msgType, unsigned int minversion);
|
||||
void sendProtoExcept(ServerUser *, const ::google::protobuf::Message &msg, unsigned int msgType, unsigned int minversion);
|
||||
void sendProtoMessage(ServerUser *, const ::google::protobuf::Message &msg, unsigned int msgType);
|
||||
|
||||
#define MUMBLE_MH_MSG(x) \
|
||||
void sendAll(const MumbleProto:: x &msg) { sendProtoAll(msg, MessageHandler:: x); } \
|
||||
void sendExcept(ServerUser *u, const MumbleProto:: x &msg) { sendProtoExcept(u, msg, MessageHandler:: x); } \
|
||||
void sendAll(const MumbleProto:: x &msg, unsigned int v = 0) { sendProtoAll(msg, MessageHandler:: x, v); } \
|
||||
void sendExcept(ServerUser *u, const MumbleProto:: x &msg, unsigned int v = 0) { sendProtoExcept(u, msg, MessageHandler:: x, v); } \
|
||||
void sendMessage(ServerUser *u, const MumbleProto:: x &msg) { sendProtoMessage(u, msg, MessageHandler:: x); }
|
||||
|
||||
MUMBLE_MH_ALL
|
||||
#undef MUMBLE_MH_MSG
|
||||
|
||||
static void hashAssign(QString &destination, QByteArray &hash, const QString &str);
|
||||
static void hashAssign(QByteArray &destination, QByteArray &hash, const QByteArray &source);
|
||||
|
||||
void setLiveConf(const QString &key, const QString &value);
|
||||
|
||||
QString addressToString(const QHostAddress &, unsigned short port);
|
||||
|
||||
@ -762,7 +762,7 @@ int Server::authenticate(QString &name, const QString &pw, const QStringList &em
|
||||
if (query.next()) {
|
||||
res = -1;
|
||||
QString storedpw = query.value(2).toString();
|
||||
QString hashedpw = QString::fromLatin1(QCryptographicHash::hash(pw.toUtf8(), QCryptographicHash::Sha1).toHex());
|
||||
QString hashedpw = QString::fromLatin1(sha1(pw).toHex());
|
||||
|
||||
if (! storedpw.isEmpty() && (storedpw == hashedpw)) {
|
||||
name = query.value(1).toString();
|
||||
@ -932,8 +932,8 @@ bool Server::setTexture(int id, const QByteArray &texture) {
|
||||
tex = qCompress(tex);
|
||||
|
||||
ServerUser *u = qhUsers.value(id);
|
||||
if (u)
|
||||
u->qbaTexture = tex;
|
||||
if (u)
|
||||
hashAssign(u->qbaTexture, u->qbaTextureHash, tex);
|
||||
|
||||
int res = -2;
|
||||
emit setTextureSig(res, id, tex);
|
||||
@ -1248,7 +1248,7 @@ void Server::readChannelPrivs(Channel *c) {
|
||||
int key = query.value(0).toInt();
|
||||
const QString &value = query.value(1).toString();
|
||||
if (key == ServerDB::Channel_Description) {
|
||||
c->qsDesc = value;
|
||||
hashAssign(c->qsDesc, c->qbaDescHash, value);
|
||||
} else if (key == ServerDB::Channel_Position) {
|
||||
c->iPosition = QVariant(value).toInt(); // If the conversion fails it'll return the default value 0
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user