diff options
-rw-r--r-- | src/Connection.cpp | 22 | ||||
-rw-r--r-- | src/Connection.h | 5 | ||||
-rw-r--r-- | src/Message.cpp | 683 | ||||
-rw-r--r-- | src/Message.h | 510 | ||||
-rw-r--r-- | src/Mumble.proto | 53 | ||||
-rw-r--r-- | src/PacketDataStream.h | 406 | ||||
-rw-r--r-- | src/murmur/Messages.cpp | 1123 | ||||
-rw-r--r-- | src/murmur/RPC.cpp | 108 | ||||
-rw-r--r-- | src/murmur/Server.cpp | 168 | ||||
-rw-r--r-- | src/murmur/Server.h | 62 | ||||
-rw-r--r-- | src/murmur/ServerDB.cpp | 3 |
11 files changed, 747 insertions, 2396 deletions
diff --git a/src/Connection.cpp b/src/Connection.cpp index 96219321c..5a62996f4 100644 --- a/src/Connection.cpp +++ b/src/Connection.cpp @@ -30,7 +30,6 @@ #include "Message.h" #include "Connection.h" -#include "PacketDataStream.h" #ifdef Q_OS_UNIX #include <sys/socket.h> @@ -87,7 +86,7 @@ void Connection::setToS() { #elif defined(Q_OS_UNIX) int val = 0xa0; if (setsockopt(qtsSocket->socketDescriptor(), IPPROTO_IP, IP_TOS, &val, sizeof(val))) { - int val = 0x60; + val = 0x60; if (setsockopt(qtsSocket->socketDescriptor(), IPPROTO_IP, IP_TOS, &val, sizeof(val))) qWarning("Connection: Failed to set TOS for TCP Socket"); } @@ -204,11 +203,22 @@ void Connection::socketDisconnected() { } } -void Connection::sendMessage(const Message *mMsg) { - QByteArray qbaBuffer; - mMsg->messageToNetwork(qbaBuffer); +void Connection::sendMessage(const ::google::protobuf::Message &msg, unsigned int msgType, QByteArray &cache) { + if (cache.isEmpty()) { + int len = msg.ByteSize(); + if (len > 0x7fffff) + return; + cache.resize(len + 4); + unsigned char *uc = reinterpret_cast<unsigned char *>(cache.data()); + uc[0] = msgType; + uc[1] = (len >> 16) & 0xFF; + uc[2] = (len >> 8) & 0xFF; + uc[3] = len & 0xFF; + + msg.SerializeToArray(uc + 4, len); + } - sendMessage(qbaBuffer); + sendMessage(cache); } void Connection::sendMessage(const QByteArray &qbaMsg) { diff --git a/src/Connection.h b/src/Connection.h index 8955b406a..18b0cfc89 100644 --- a/src/Connection.h +++ b/src/Connection.h @@ -33,8 +33,7 @@ #include "murmur_pch.h" #include "CryptState.h" - -class Message; +#include "Mumble.pb.h" class Connection : public QObject { private: @@ -68,7 +67,7 @@ class Connection : public QObject { public: Connection(QObject *parent, QSslSocket *qtsSocket); ~Connection(); - void sendMessage(const Message *mMsg); + void sendMessage(const ::google::protobuf::Message &msg, unsigned int msgType, QByteArray &cache); void sendMessage(const QByteArray &qbaMsg); void disconnectSocket(bool force=false); void forceFlush(); diff --git a/src/Message.cpp b/src/Message.cpp index bd31b68a8..48e0d081a 100644 --- a/src/Message.cpp +++ b/src/Message.cpp @@ -29,681 +29,18 @@ */ #include "Message.h" -#include "PacketDataStream.h" #include "murmur_pch.h" -Message::Message() { - uiSession = 0; -} - -Message::~Message() { -} - -void Message::messageToNetwork(QByteArray &qbaOut) const { - char buffer[8192]; - PacketDataStream qdsOut(buffer, 8192); - qdsOut << messageType(); - qdsOut << uiSession; - saveStream(qdsOut); - - if (qdsOut.undersize() == 0) { - qbaOut = QByteArray(buffer, qdsOut.size()); - return; - } - - unsigned int size = 8192 + qdsOut.undersize(); - STACKVAR(char, b, size); - PacketDataStream pdsResized(b, size); - pdsResized << messageType(); - pdsResized << uiSession; - saveStream(pdsResized); - qbaOut = QByteArray(b, pdsResized.size()); -} - -void Message::messageToNetwork(PacketDataStream &pds) const { - pds << messageType(); - pds << uiSession; - saveStream(pds); - pds.truncate(); -} - -Message *Message::networkToMessage(QByteArray &qbaIn) { - PacketDataStream qdsIn(qbaIn.constData(), qbaIn.size()); - return networkToMessage(qdsIn); -} - -Message *Message::networkToMessage(PacketDataStream &qdsIn) { - Message *mMsg = NULL; - unsigned char iMessageType; - short uiSession; - qdsIn >> iMessageType; - qdsIn >> uiSession; - switch (iMessageType) { - case Speex: - mMsg = new MessageSpeex(); - break; - case ServerAuthenticate: - mMsg = new MessageServerAuthenticate(); - break; - case ServerReject: - mMsg = new MessageServerReject(); - break; - case ServerSync: - mMsg = new MessageServerSync(); - break; - case ServerJoin: - mMsg = new MessageServerJoin(); - break; - case ServerLeave: - mMsg = new MessageServerLeave(); - break; - case ServerBanList: - mMsg = new MessageServerBanList(); - break; - case PlayerMute: - mMsg = new MessagePlayerMute(); - break; - case PlayerDeaf: - mMsg = new MessagePlayerDeaf(); - break; - case PlayerSelfMuteDeaf: - mMsg = new MessagePlayerSelfMuteDeaf(); - break; - case PlayerKick: - mMsg = new MessagePlayerKick(); - break; - case PlayerBan: - mMsg = new MessagePlayerBan(); - break; - case PlayerMove: - mMsg = new MessagePlayerMove(); - break; - case PlayerRename: - mMsg = new MessagePlayerRename(); - break; - case ChannelAdd: - mMsg = new MessageChannelAdd(); - break; - case ChannelRemove: - mMsg = new MessageChannelRemove(); - break; - case ChannelMove: - mMsg = new MessageChannelMove(); - break; - case ChannelLink: - mMsg = new MessageChannelLink(); - break; - case ChannelRename: - mMsg = new MessageChannelRename(); - break; - case ChannelDescUpdate: - mMsg = new MessageChannelDescUpdate(); - break; - case TextMessage: - mMsg = new MessageTextMessage(); - break; - case PermissionDenied: - mMsg = new MessagePermissionDenied(); - break; - case EditACL: - mMsg = new MessageEditACL(); - break; - case QueryUsers: - mMsg = new MessageQueryUsers(); - break; - case Ping: - mMsg = new MessagePing(); - break; - case PingStats: - mMsg = new MessagePingStats(); - break; - case PlayerTexture: - mMsg = new MessageTexture(); - break; - case CryptSetup: - mMsg = new MessageCryptSetup(); - break; - case CryptSync: - mMsg = new MessageCryptSync(); - break; - case ContextAction: - mMsg = new MessageContextAction(); - break; - case ContextAddAction: - mMsg = new MessageContextAddAction(); - break; - default: - qWarning("Message: Type %d (session %d, size %d) is unknown type", iMessageType, uiSession, qdsIn.capacity()); - } - if (mMsg) { - mMsg->uiSession=uiSession; - mMsg->restoreStream(qdsIn); - if (! qdsIn.isValid()) { - delete mMsg; - mMsg = NULL; - qWarning("Message: Type %d (session %d, size %d) corrupt or short packet", iMessageType, uiSession, qdsIn.capacity()); - } else if (qdsIn.left() != 0) { - delete mMsg; - mMsg = NULL; - qWarning("Message: Type %d (session %d) Long packet: %d/%d leftover bytes", iMessageType, uiSession, qdsIn.left(), qdsIn.size()); - } else if (! mMsg->isValid()) { - delete mMsg; - mMsg = NULL; - qWarning("Message: Type %d (session %d, size %d) failed to validate", iMessageType, uiSession, qdsIn.capacity()); - } - } - - return mMsg; -} - -void MessageHandler::dispatch(Connection *cCon, Message *msg) { - switch (msg->messageType()) { - case Message::Speex: - msgSpeex(cCon, static_cast<MessageSpeex *>(msg)); - break; - case Message::ServerAuthenticate: - msgServerAuthenticate(cCon, static_cast<MessageServerAuthenticate *>(msg)); - break; - case Message::ServerReject: - msgServerReject(cCon, static_cast<MessageServerReject *>(msg)); - break; - case Message::ServerSync: - msgServerSync(cCon, static_cast<MessageServerSync *>(msg)); - break; - case Message::ServerJoin: - msgServerJoin(cCon, static_cast<MessageServerJoin *>(msg)); - break; - case Message::ServerLeave: - msgServerLeave(cCon, static_cast<MessageServerLeave *>(msg)); - break; - case Message::ServerBanList: - msgServerBanList(cCon, static_cast<MessageServerBanList *>(msg)); - break; - case Message::PlayerMute: - msgPlayerMute(cCon, static_cast<MessagePlayerMute *>(msg)); - break; - case Message::PlayerDeaf: - msgPlayerDeaf(cCon, static_cast<MessagePlayerDeaf *>(msg)); - break; - case Message::PlayerSelfMuteDeaf: - msgPlayerSelfMuteDeaf(cCon, static_cast<MessagePlayerSelfMuteDeaf *>(msg)); - break; - case Message::PlayerKick: - msgPlayerKick(cCon, static_cast<MessagePlayerKick *>(msg)); - break; - case Message::PlayerBan: - msgPlayerBan(cCon, static_cast<MessagePlayerBan *>(msg)); - break; - case Message::PlayerMove: - msgPlayerMove(cCon, static_cast<MessagePlayerMove *>(msg)); - break; - case Message::PlayerRename: - msgPlayerRename(cCon, static_cast<MessagePlayerRename *>(msg)); - break; - case Message::ChannelAdd: - msgChannelAdd(cCon, static_cast<MessageChannelAdd *>(msg)); - break; - case Message::ChannelRemove: - msgChannelRemove(cCon, static_cast<MessageChannelRemove *>(msg)); - break; - case Message::ChannelMove: - msgChannelMove(cCon, static_cast<MessageChannelMove *>(msg)); - break; - case Message::ChannelLink: - msgChannelLink(cCon, static_cast<MessageChannelLink *>(msg)); - break; - case Message::ChannelRename: - msgChannelRename(cCon, static_cast<MessageChannelRename *>(msg)); - break; - case Message::ChannelDescUpdate: - msgChannelDescUpdate(cCon, static_cast<MessageChannelDescUpdate *>(msg)); - break; - case Message::TextMessage: - msgTextMessage(cCon, static_cast<MessageTextMessage *>(msg)); - break; - case Message::PermissionDenied: - msgPermissionDenied(cCon, static_cast<MessagePermissionDenied *>(msg)); - break; - case Message::EditACL: - msgEditACL(cCon, static_cast<MessageEditACL *>(msg)); - break; - case Message::QueryUsers: - msgQueryUsers(cCon, static_cast<MessageQueryUsers *>(msg)); - break; - case Message::Ping: - msgPing(cCon, static_cast<MessagePing *>(msg)); - break; - case Message::PingStats: - msgPingStats(cCon, static_cast<MessagePingStats *>(msg)); - break; - case Message::PlayerTexture: - msgTexture(cCon, static_cast<MessageTexture *>(msg)); - break; - case Message::CryptSetup: - msgCryptSetup(cCon, static_cast<MessageCryptSetup *>(msg)); - break; - case Message::CryptSync: - msgCryptSync(cCon, static_cast<MessageCryptSync *>(msg)); - break; - case Message::ContextAction: - msgContextAction(cCon, static_cast<MessageContextAction *>(msg)); - break; - case Message::ContextAddAction: - msgContextAddAction(cCon, static_cast<MessageContextAddAction *>(msg)); +void MessageHandler::dispatch(Connection *cCon, int type, const QByteArray &msg) { + switch (type) { + case MessageHandler::Version: + { + MumbleProto::Version mpv; + mpv.ParseFromArray(msg.constData(), msg.size()); + msgVersion(cCon, &mpv); + } break; default: - qFatal("MessageHandler called with unknown message type %d", msg->messageType()); - } -} - -bool Message::isValid() const { - return true; -} - -void Message::saveStream(PacketDataStream &) const { -} - -void Message::restoreStream(PacketDataStream &) { -} - -void MessagePing::saveStream(PacketDataStream &qdsOut) const { - qdsOut << uiTimestamp; -} - -void MessagePing::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> uiTimestamp; -} - -void MessagePingStats::saveStream(PacketDataStream &qdsOut) const { - qdsOut << uiTimestamp << uiGood << uiLate << uiLost << uiResync << dUDPPingAvg << dUDPPingVar << uiUDPPackets << dTCPPingAvg << dTCPPingVar << uiTCPPackets; -} - -void MessagePingStats::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> uiTimestamp >> uiGood >> uiLate >> uiLost >> uiResync >> dUDPPingAvg >> dUDPPingVar >> uiUDPPackets >> dTCPPingAvg >> dTCPPingVar >> uiTCPPackets; -} - -MessageServerAuthenticate::MessageServerAuthenticate() { - iVersion = MESSAGE_STREAM_VERSION; -} - -void MessageServerAuthenticate::saveStream(PacketDataStream &qdsOut) const { - qdsOut << iVersion; - qdsOut << qsUsername; - qdsOut << qsPassword; -} - -void MessageServerAuthenticate::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> iVersion; - qdsIn >> qsUsername; - qdsIn >> qsPassword; -} - - -void MessageServerReject::saveStream(PacketDataStream &qdsOut) const { - qdsOut << qsReason; - qdsOut << static_cast<int>(rtType); -} - -void MessageServerReject::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> qsReason; - int v; - qdsIn >> v; - rtType = static_cast<RejectType>(v); -} - -void MessageServerSync::saveStream(PacketDataStream &qdsOut) const { - qdsOut << iMaxBandwidth; - qdsOut << qsWelcomeText; -} - -void MessageServerSync::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> iMaxBandwidth; - qdsIn >> qsWelcomeText; -} - -void MessageServerJoin::saveStream(PacketDataStream &qdsOut) const { - qdsOut << qsPlayerName; - qdsOut << iId; -} - -void MessageServerJoin::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> qsPlayerName; - qdsIn >> iId; -} - -void MessageServerBanList::saveStream(PacketDataStream &qdsOut) const { - qdsOut << bQuery; - qdsOut << qlBans; -} - -void MessageServerBanList::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> bQuery; - qdsIn >> qlBans; -} - -void MessagePermissionDenied::saveStream(PacketDataStream &qdsOut) const { - qdsOut << qsReason; -} - -void MessagePermissionDenied::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> qsReason; -} - -void MessageSpeex::saveStream(PacketDataStream &qdsOut) const { - qdsOut << static_cast<unsigned short>(iSeq); - qdsOut.append(qbaSpeexPacket.constData(), qbaSpeexPacket.size()); -} - -void MessageSpeex::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> iSeq; - qbaSpeexPacket = qdsIn.dataBlock(qdsIn.left()); -} - -bool MessageSpeex::isValid() const { - return ! qbaSpeexPacket.isEmpty(); -} - -void MessagePlayerMute::saveStream(PacketDataStream &qdsOut) const { - qdsOut << uiVictim; - qdsOut << bMute; -} - -void MessagePlayerMute::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> uiVictim; - qdsIn >> bMute; -} - -void MessagePlayerDeaf::saveStream(PacketDataStream &qdsOut) const { - qdsOut << uiVictim; - qdsOut << bDeaf; -} - -void MessagePlayerDeaf::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> uiVictim; - qdsIn >> bDeaf; -} - -void MessagePlayerKick::saveStream(PacketDataStream &qdsOut) const { - qdsOut << uiVictim; - qdsOut << qsReason; -} - -void MessagePlayerKick::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> uiVictim; - qdsIn >> qsReason; -} - -void MessagePlayerBan::saveStream(PacketDataStream &qdsOut) const { - qdsOut << uiVictim; - qdsOut << qsReason; -} - -void MessagePlayerBan::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> uiVictim; - qdsIn >> qsReason; -} - -void MessagePlayerMove::saveStream(PacketDataStream &qdsOut) const { - qdsOut << uiVictim; - qdsOut << iChannelId; -} - -void MessagePlayerMove::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> uiVictim; - qdsIn >> iChannelId; -} - -void MessagePlayerRename::saveStream(PacketDataStream &qdsOut) const { - qdsOut << qsName; -} - -void MessagePlayerRename::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> qsName; -} - -void MessagePlayerSelfMuteDeaf::saveStream(PacketDataStream &qdsOut) const { - qdsOut << bMute; - qdsOut << bDeaf; -} - -void MessagePlayerSelfMuteDeaf::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> bMute; - qdsIn >> bDeaf; -} - -void MessageChannelAdd::saveStream(PacketDataStream &qdsOut) const { - qdsOut << iId; - qdsOut << iParent; - qdsOut << qsName; -} - -void MessageChannelAdd::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> iId; - qdsIn >> iParent; - qdsIn >> qsName; -} - -void MessageChannelRemove::saveStream(PacketDataStream &qdsOut) const { - qdsOut << iId; -} - -void MessageChannelRemove::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> iId; -} - -void MessageChannelLink::saveStream(PacketDataStream &qdsOut) const { - qdsOut << iId; - qdsOut << static_cast<int>(ltType); - qdsOut << qlTargets; -} - -void MessageChannelLink::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> iId; - int v; - qdsIn >> v; - ltType = static_cast<LinkType>(v); - qdsIn >> qlTargets; -} - -void MessageChannelMove::saveStream(PacketDataStream &qdsOut) const { - qdsOut << iId; - qdsOut << iParent; -} - -void MessageChannelMove::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> iId; - qdsIn >> iParent; -} - -void MessageChannelRename::saveStream(PacketDataStream &qdsOut) const { - qdsOut << iId << qsName; -} - -void MessageChannelRename::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> iId >> qsName; -} - -void MessageChannelDescUpdate::saveStream(PacketDataStream &qdsOut) const { - qdsOut << iId << qsDesc; -} - -void MessageChannelDescUpdate::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> iId >> qsDesc; -} - -void MessageTextMessage::saveStream(PacketDataStream &qdsOut) const { - qdsOut << uiVictim; - qdsOut << iChannel; - qdsOut << bTree; - qdsOut << qsMessage; -} - -void MessageTextMessage::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> uiVictim; - qdsIn >> iChannel; - qdsIn >> bTree; - qdsIn >> qsMessage; -} - -void MessageEditACL::saveStream(PacketDataStream &qdsOut) const { - qdsOut << iId; - qdsOut << bQuery; - if (bQuery) - return; - - qdsOut << bInheritACL; - qdsOut << groups; - qdsOut << acls; -} - -void MessageEditACL::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> iId; - qdsIn >> bQuery; - if (bQuery) - return; - - qdsIn >> bInheritACL; - qdsIn >> groups; - qdsIn >> acls; -} - -void MessageQueryUsers::saveStream(PacketDataStream &qdsOut) const { - qdsOut << qlIds; - qdsOut << qlNames; -} - -void MessageQueryUsers::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> qlIds; - qdsIn >> qlNames; -} - -bool MessageQueryUsers::isValid() const { - if (qlIds.count() != qlNames.count()) - return false; - - int i; - for (i=0;i<qlIds.count();i++) { - if ((qlIds[i] == -1) && (qlNames[i].isEmpty())) - return false; - } - return true; -} - -void MessageTexture::saveStream(PacketDataStream &qdsOut) const { - qdsOut << iPlayerId; - qdsOut << qbaTexture; -} - -void MessageTexture::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> iPlayerId; - qdsIn >> qbaTexture; -} - -void MessageCryptSetup::saveStream(PacketDataStream &qdsOut) const { - qdsOut << qbaKey << qbaServerNonce << qbaClientNonce; -} - -void MessageCryptSetup::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> qbaKey >> qbaServerNonce >> qbaClientNonce; -} - -bool MessageCryptSetup::isValid() const { - return ((qbaKey.size() == AES_BLOCK_SIZE) && - (qbaClientNonce.size() == AES_BLOCK_SIZE) && - (qbaServerNonce.size() == AES_BLOCK_SIZE)); -} - - -void MessageCryptSync::saveStream(PacketDataStream &qdsOut) const { - qdsOut << qbaNonce; -} - -void MessageCryptSync::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> qbaNonce; -} - -bool MessageCryptSync::isValid() const { - return (qbaNonce.isEmpty() || (qbaNonce.size() == AES_BLOCK_SIZE)); -} - -void MessageContextAddAction::saveStream(PacketDataStream &qdsOut) const { - qdsOut << qsAction; - qdsOut << qsText; - qdsOut << static_cast<int>(ctx); -} - -void MessageContextAddAction::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> qsAction; - qdsIn >> qsText; - int c; - qdsIn >> c; - ctx = static_cast<Context>(c); -} - -bool MessageContextAddAction::isValid() const { - return (! qsAction.isEmpty() && (ctx & (CtxServer | CtxPlayer | CtxChannel))); -} - -void MessageContextAction::saveStream(PacketDataStream &qdsOut) const { - qdsOut << qsAction; - qdsOut << uiVictim; - qdsOut << iChannel; -} - -void MessageContextAction::restoreStream(PacketDataStream &qdsIn) { - qdsIn >> qsAction; - qdsIn >> uiVictim; - qdsIn >> iChannel; -} - -bool MessageContextAction::isValid() const { - return (! qsAction.isEmpty()); -} - -PacketDataStream & operator<< (PacketDataStream & out, const MessageEditACL::GroupStruct &gs) { - out << gs.qsName; - out << gs.bInherited; - out << gs.bInherit; - out << gs.bInheritable; - out << gs.qsAdd; - out << gs.qsRemove; - out << gs.qsInheritedMembers; - return out; -} - -PacketDataStream & operator>> (PacketDataStream & in, MessageEditACL::GroupStruct &gs) { - in >> gs.qsName; - in >> gs.bInherited; - in >> gs.bInherit; - in >> gs.bInheritable; - in >> gs.qsAdd; - in >> gs.qsRemove; - in >> gs.qsInheritedMembers; - return in; -} - -PacketDataStream & operator<< (PacketDataStream & out, const MessageEditACL::ACLStruct &as) { - out << as.bApplyHere; - out << as.bApplySubs; - out << as.bInherited; - out << as.iPlayerId; - out << as.qsGroup; - out << static_cast<int>(as.pAllow); - out << static_cast<int>(as.pDeny); - return out; -} - -PacketDataStream & operator>> (PacketDataStream & in, MessageEditACL::ACLStruct &as) { - int v; - - in >> as.bApplyHere; - in >> as.bApplySubs; - in >> as.bInherited; - in >> as.iPlayerId; - in >> as.qsGroup; - in >> v; - as.pAllow = static_cast<ChanACL::Permissions>(v); - in >> v; - as.pDeny = static_cast<ChanACL::Permissions>(v); - return in; + break; + } } diff --git a/src/Message.h b/src/Message.h index 303cf59f8..7e02c366f 100644 --- a/src/Message.h +++ b/src/Message.h @@ -31,489 +31,45 @@ #ifndef _MESSAGE_H #define _MESSAGE_H -#define MESSAGE_STREAM_VERSION 4 - -#include "ACL.h" - -class Connection; -class PacketDataStream; - -class Message { - protected: - virtual void saveStream(PacketDataStream &) const; - virtual void restoreStream(PacketDataStream &); - public: - enum MessageType { ServerReject, ServerAuthenticate, Speex, ServerSync, ServerJoin, ServerLeave, ServerBanList, PlayerMute, PlayerDeaf, PlayerKick, PlayerRename, PlayerBan, PlayerMove, PlayerSelfMuteDeaf, ChannelAdd, ChannelRemove, ChannelMove, ChannelLink, ChannelRename, PermissionDenied, EditACL, QueryUsers, Ping, TextMessage, PlayerTexture, CryptSetup, CryptSync, PingStats, ContextAction, ContextAddAction, ChannelDescUpdate }; - unsigned int uiSession; - - Message(); - virtual ~Message(); - virtual Message::MessageType messageType() const = 0; - virtual bool isValid() const; - - void messageToNetwork(QByteArray &) const; - void messageToNetwork(PacketDataStream &) const; - static Message *networkToMessage(QByteArray &); - static Message *networkToMessage(PacketDataStream &); -}; - -class MessageSpeex : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - enum { AltSpeak = 0x01, LoopBack = 0x02, EndSpeech = 0x04, FrameCountMask = 0x30 }; - unsigned int iSeq; - // Flags is in first byte of packet. - QByteArray qbaSpeexPacket; - Message::MessageType messageType() const { - return Speex; - }; - bool isValid() const; -}; - -class MessageServerAuthenticate : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - int iVersion; - QString qsUsername; - QString qsPassword; - MessageServerAuthenticate(); - Message::MessageType messageType() const { - return ServerAuthenticate; - }; -}; - -class MessagePing : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - quint64 uiTimestamp; - Message::MessageType messageType() const { - return Ping; - }; -}; - -class MessagePingStats : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - quint64 uiTimestamp; - quint32 uiGood; - quint32 uiLate; - quint32 uiLost; - quint32 uiResync; - double dUDPPingAvg; - double dUDPPingVar; - quint32 uiUDPPackets; - double dTCPPingAvg; - double dTCPPingVar; - quint32 uiTCPPackets; - Message::MessageType messageType() const { - return PingStats; - }; -}; - -class MessageServerReject : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - enum RejectType { None, WrongVersion, InvalidUsername, WrongUserPW, WrongServerPW, UsernameInUse, ServerFull }; - QString qsReason; - RejectType rtType; - Message::MessageType messageType() const { - return ServerReject; - }; -}; - -class MessageServerSync : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - int iMaxBandwidth; - QString qsWelcomeText; - Message::MessageType messageType() const { - return ServerSync; - }; -}; - -class MessageServerJoin : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - QString qsPlayerName; - int iId; - Message::MessageType messageType() const { - return ServerJoin; - }; -}; - -class MessageServerLeave : public Message { - public: - Message::MessageType messageType() const { - return ServerLeave; - }; -}; - -class MessagePlayerMute : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - unsigned int uiVictim; - bool bMute; - Message::MessageType messageType() const { - return PlayerMute; - }; -}; - -class MessagePlayerDeaf : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - unsigned int uiVictim; - bool bDeaf; - Message::MessageType messageType() const { - return PlayerDeaf; - }; -}; - -class MessagePlayerSelfMuteDeaf : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - bool bMute; - bool bDeaf; - Message::MessageType messageType() const { - return PlayerSelfMuteDeaf; - }; -}; - -class MessagePlayerKick : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - unsigned int uiVictim; - QString qsReason; - Message::MessageType messageType() const { - return PlayerKick; - }; -}; - -class MessagePlayerBan : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - unsigned int uiVictim; - QString qsReason; - Message::MessageType messageType() const { - return PlayerBan; - }; -}; - -class MessagePlayerMove : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - unsigned int uiVictim; - int iChannelId; - Message::MessageType messageType() const { - return PlayerMove; - }; -}; - -class MessagePlayerRename : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - QString qsName; - Message::MessageType messageType() const { - return PlayerRename; - }; -}; - -class MessageChannelAdd : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - int iId; - int iParent; - QString qsName; - Message::MessageType messageType() const { - return ChannelAdd; - }; -}; - -class MessageChannelRemove : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - int iId; - Message::MessageType messageType() const { - return ChannelRemove; - }; -}; - -class MessageChannelMove : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - int iId; - int iParent; - Message::MessageType messageType() const { - return ChannelMove; - }; -}; - -class MessageChannelLink : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - enum LinkType { - Link, Unlink, UnlinkAll, PushLink, PushUnlink - }; - int iId; - LinkType ltType; - QList<int> qlTargets; - Message::MessageType messageType() const { - return ChannelLink; - }; -}; - -class MessageChannelRename : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - int iId; - QString qsName; - Message::MessageType messageType() const { - return ChannelRename; - }; -}; - -class MessageChannelDescUpdate : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - int iId; - QString qsDesc; - Message::MessageType messageType() const { - return ChannelDescUpdate; - }; -}; - -class MessageServerBanList : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - bool bQuery; - QList<QPair<quint32, int> > qlBans; - Message::MessageType messageType() const { - return ServerBanList; - }; -}; - -class MessageTextMessage : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - unsigned int uiVictim; - int iChannel; - bool bTree; - QString qsMessage; - Message::MessageType messageType() const { - return TextMessage; - }; -}; - -class MessagePermissionDenied : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - QString qsReason; - Message::MessageType messageType() const { - return PermissionDenied; - }; -}; - -class MessageEditACL : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - struct GroupStruct { - QString qsName; - bool bInherited; - bool bInherit; - bool bInheritable; - QSet<int> qsAdd; - QSet<int> qsRemove; - QSet<int> qsInheritedMembers; - }; - - struct ACLStruct { - bool bApplyHere; - bool bApplySubs; - bool bInherited; - int iPlayerId; - QString qsGroup; - ChanACL::Permissions pAllow; - ChanACL::Permissions pDeny; - }; - - int iId; - bool bQuery; - bool bInheritACL; - QList<GroupStruct> groups; - QList<ACLStruct> acls; - Message::MessageType messageType() const { - return EditACL; - }; -}; - -PacketDataStream & operator<< (PacketDataStream & out, const MessageEditACL::GroupStruct &gs); -PacketDataStream & operator>> (PacketDataStream & in, MessageEditACL::GroupStruct &gs); -PacketDataStream & operator<< (PacketDataStream & out, const MessageEditACL::ACLStruct &gs); -PacketDataStream & operator>> (PacketDataStream & in, MessageEditACL::ACLStruct &gs); - -class MessageQueryUsers : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - QList<int> qlIds; - QList<QString> qlNames; - Message::MessageType messageType() const { - return QueryUsers; - }; - bool isValid() const; -}; - -class MessageTexture : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - int iPlayerId; - QByteArray qbaTexture; - Message::MessageType messageType() const { - return PlayerTexture; - } -}; - -class MessageCryptSetup : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - QByteArray qbaKey, qbaClientNonce, qbaServerNonce; - Message::MessageType messageType() const { - return CryptSetup; - } - bool isValid() const; -}; - -class MessageCryptSync : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - QByteArray qbaNonce; - Message::MessageType messageType() const { - return CryptSync; - } - bool isValid() const; -}; - -class MessageContextAddAction : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - enum Context { CtxServer = 0x01, CtxChannel = 0x02, CtxPlayer = 0x04 }; - QString qsAction; - QString qsText; - Context ctx; - Message::MessageType messageType() const { - return ContextAddAction; - } - bool isValid() const; -}; - -class MessageContextAction : public Message { - protected: - void saveStream(PacketDataStream &) const; - void restoreStream(PacketDataStream &); - public: - QString qsAction; - unsigned int uiVictim; - int iChannel; - Message::MessageType messageType() const { - return ContextAction; - } - bool isValid() const; -}; +#include "Connection.h" +#include "Mumble.pb.h" class MessageHandler { - protected: - virtual void msgSpeex(Connection *, MessageSpeex *) = 0; - virtual void msgServerAuthenticate(Connection *, MessageServerAuthenticate *) = 0; - virtual void msgPing(Connection *, MessagePing *) = 0; - virtual void msgPingStats(Connection *, MessagePingStats *) = 0; - virtual void msgServerReject(Connection *, MessageServerReject *) = 0; - virtual void msgServerSync(Connection *, MessageServerSync *) = 0; - virtual void msgServerJoin(Connection *, MessageServerJoin *) = 0; - virtual void msgServerLeave(Connection *, MessageServerLeave *) = 0; - virtual void msgPlayerMute(Connection *, MessagePlayerMute *) = 0; - virtual void msgPlayerDeaf(Connection *, MessagePlayerDeaf *) = 0; - virtual void msgPlayerSelfMuteDeaf(Connection *, MessagePlayerSelfMuteDeaf *) = 0; - virtual void msgPlayerKick(Connection *, MessagePlayerKick *) = 0; - virtual void msgPlayerBan(Connection *, MessagePlayerBan *) = 0; - virtual void msgPlayerMove(Connection *, MessagePlayerMove *) = 0; - virtual void msgPlayerRename(Connection *, MessagePlayerRename *) = 0; - virtual void msgChannelAdd(Connection *, MessageChannelAdd *) = 0; - virtual void msgChannelRemove(Connection *, MessageChannelRemove *) = 0; - virtual void msgChannelMove(Connection *, MessageChannelMove *) = 0; - virtual void msgChannelLink(Connection *, MessageChannelLink *) = 0; - virtual void msgChannelRename(Connection *, MessageChannelRename *) = 0; - virtual void msgChannelDescUpdate(Connection *, MessageChannelDescUpdate *) = 0; - virtual void msgServerBanList(Connection *, MessageServerBanList *) = 0; - virtual void msgTextMessage(Connection *, MessageTextMessage *) = 0; - virtual void msgPermissionDenied(Connection *, MessagePermissionDenied *) = 0; - virtual void msgEditACL(Connection *, MessageEditACL *) = 0; - virtual void msgQueryUsers(Connection *, MessageQueryUsers *) = 0; - virtual void msgTexture(Connection *, MessageTexture *) = 0; - virtual void msgCryptSetup(Connection *, MessageCryptSetup *) = 0; - virtual void msgCryptSync(Connection *, MessageCryptSync *) = 0; - virtual void msgContextAddAction(Connection *, MessageContextAddAction *) = 0; - virtual void msgContextAction(Connection *, MessageContextAction *) = 0; - void dispatch(Connection *, Message *); public: + enum UDPMessageType { UDPVoice, UDPPing }; + enum MessageType { Version, UDPTunnel, Authenticate, Ping, Reject, ServerSync, ChannelRemove, ChannelState, UserRemove, UserState, BanList, TextMessage, PermissionDenied, ACL, QueryUsers, CryptSetup, ContextActionAdd, ContextAction }; + protected: + virtual void msgVersion(Connection *, MumbleProto::Version *) = 0; + virtual void msgUDPTunnel(Connection *, MumbleProto::UDPTunnel *) = 0; + virtual void msgAuthenticate(Connection *, MumbleProto::Authenticate *) = 0; + virtual void msgPing(Connection *, MumbleProto::Ping *) = 0; + virtual void msgReject(Connection *, MumbleProto::Reject *) = 0; + virtual void msgServerSync(Connection *, MumbleProto::ServerSync *) = 0; + virtual void msgChannelRemove(Connection *, MumbleProto::ChannelRemove *) = 0; + virtual void msgChannelState(Connection *, MumbleProto::ChannelState *) = 0; + virtual void msgUserRemove(Connection *, MumbleProto::UserRemove *) = 0; + virtual void msgUserState(Connection *, MumbleProto::UserState *) = 0; + virtual void msgBanList(Connection *, MumbleProto::BanList *) = 0; + virtual void msgTextMessage(Connection *, MumbleProto::TextMessage *) = 0; + virtual void msgPermissionDenied(Connection *, MumbleProto::PermissionDenied *) = 0; + virtual void msgACL(Connection *, MumbleProto::ACL *) = 0; + virtual void msgQueryUsers(Connection *, MumbleProto::QueryUsers *) = 0; + virtual void msgCryptSetup(Connection *, MumbleProto::CryptSetup *) = 0; + virtual void msgContextActionAdd(Connection *, MumbleProto::ContextActionAdd *) = 0; + virtual void msgContextAction(Connection *, MumbleProto::ContextAction *) = 0; + void dispatch(Connection *, int type, const QByteArray &); virtual ~MessageHandler() { }; }; +inline QString u8(const ::std::string &str) { + return QString::fromUtf8(str.data(), str.length()); +} + +inline ::std::string u8(const QString &str) { + const QByteArray &qba = str.toUtf8(); + return ::std::string(qba.constData(), qba.length()); +} + #else class Message; #endif diff --git a/src/Mumble.proto b/src/Mumble.proto index 62b6abf53..85f56ca80 100644 --- a/src/Mumble.proto +++ b/src/Mumble.proto @@ -12,23 +12,19 @@ message UDPTunnel { } message Authenticate { - required string username = 1; + optional string username = 1; optional string password = 2; optional bool want_textures = 3 [default = true]; } message Ping { optional uint64 timestamp = 1; -} - -message PingStats { - optional uint64 timestamp = 1; - required uint32 good = 2; - required uint32 late = 3; - required uint32 lost = 4; - required uint32 resync = 5; - required uint32 udp_packets = 6; - required uint32 tcp_packets = 7; + optional uint32 good = 2; + optional uint32 late = 3; + optional uint32 lost = 4; + optional uint32 resync = 5; + optional uint32 udp_packets = 6; + optional uint32 tcp_packets = 7; optional float udp_ping_avg = 8; optional float udp_ping_var = 9; optional float tcp_ping_avg = 10; @@ -50,8 +46,9 @@ message Reject { } message ServerSync { - optional uint32 maxbandwidth = 1; - optional string welcometext = 2; + optional uint32 session = 1; + optional uint32 max_bandwidth = 2; + optional string welcome_text = 3; } message ChannelRemove { @@ -64,10 +61,15 @@ message ChannelState { optional string name = 3; repeated uint32 links = 4; optional string description = 5; + repeated uint32 links_add = 6; + repeated uint32 links_remove = 7; } message UserRemove { required uint32 session = 1; + optional uint32 actor = 2; + optional string reason = 3; + optional bool ban = 4; } message UserState { @@ -75,22 +77,15 @@ message UserState { optional uint32 actor = 2; optional string name = 3; optional uint32 user_id = 4; - optional uint32 channel = 5; + optional uint32 channel_id = 5; optional bool mute = 6; optional bool deaf = 7; optional bool suppressed = 8; - optional bool selfmute = 9; - optional bool selfdeaf = 10; + optional bool self_mute = 9; + optional bool self_deaf = 10; optional bytes texture = 11; } -message Kick { - required uint32 session = 1; - optional uint32 actor = 2; - optional string reason = 3; - optional bool ban = 4; -} - message BanList { message BanEntry { required bytes address = 1; @@ -101,10 +96,11 @@ message BanList { } message TextMessage { - required uint32 actor = 1; + optional uint32 actor = 1; repeated uint32 session = 2; repeated uint32 channel_id = 3; - required string message = 4; + repeated uint32 tree_id = 4; + required string message = 5; } message PermissionDenied { @@ -128,8 +124,8 @@ message ACL { optional bool inherited = 3 [default = true]; optional uint32 user_id = 4; optional string group = 5; - required uint32 grant = 6; - required uint32 deny = 7; + optional uint32 grant = 6; + optional uint32 deny = 7; } required uint32 channel_id = 1; optional bool inherit_acls = 2 [default = true]; @@ -145,7 +141,8 @@ message QueryUsers { message CryptSetup { optional bytes key = 1; - optional bytes nonce = 2; + optional bytes client_nonce = 2; + optional bytes server_nonce = 3; } message ContextActionAdd { diff --git a/src/PacketDataStream.h b/src/PacketDataStream.h deleted file mode 100644 index 948cb03dd..000000000 --- a/src/PacketDataStream.h +++ /dev/null @@ -1,406 +0,0 @@ -/* Copyright (C) 2005-2009, Thorvald Natvig <thorvald@natvig.com> - - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - Neither the name of the Mumble Developers nor the names of its - contributors may be used to endorse or promote products derived from this - software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef _PACKETDATASTREAM_H -#define _PACKETDATASTREAM_H - -/* - * GCC doesn't yet do inter-object-file inlining, so unfortunately, this all has to be defined here. - */ - -class PacketDataStream { - private: - Q_DISABLE_COPY(PacketDataStream) - private: - unsigned char *data; - quint32 maxsize; - quint32 offset; - quint32 overshoot; - bool ok; - public: - quint32 size() const { - return offset; - } - - quint32 capacity() const { - return maxsize; - } - - bool isValid() const { - return ok; - } - - quint32 left() const { - return maxsize - offset; - } - - quint32 undersize() const { - return overshoot; - } - - void append(const quint64 v) { -#ifndef QT_NO_DEBUG - Q_ASSERT(v <= 0xff); -#endif - if (offset < maxsize) - data[offset++] = static_cast<unsigned char>(v); - else { - ok = false; - overshoot++; - } - }; - - void append(const char *d, quint32 len) { - if (left() >= len) { - memcpy(& data[offset], d, len); - offset += len; - } else { - int l = left(); - memset(& data[offset], 0, l); - offset += l; - overshoot += len - l; - ok = false; - } - } - - void skip(quint32 len) { - if (left() >= len) - offset += len; - else - ok = false; - } - - quint64 next() { - if (offset < maxsize) - return data[offset++]; - else { - ok = false; - return 0; - } - }; - - void rewind() { - offset = 0; - } - - void truncate() { - maxsize = offset; - } - - const unsigned char *dataPtr() const { - return reinterpret_cast<const unsigned char *>(& data[offset]); - } - - const char *charPtr() const { - return reinterpret_cast<const char *>(& data[offset]); - } - - QByteArray dataBlock(quint32 len) { - if (len <= left()) { - QByteArray a(charPtr(), len); - offset +=len; - return a; - } else { - ok = false; - return QByteArray(); - } - } - - protected: - void setup(unsigned char *d, int msize) { - data = d; - offset = 0; - overshoot = 0; - maxsize = msize; - ok = true; - } - public: - PacketDataStream(const char *d, int msize) { - setup(const_cast<unsigned char *>(reinterpret_cast<const unsigned char *>(d)), msize); - }; - - PacketDataStream(char *d, int msize) { - setup(reinterpret_cast<unsigned char *>(d), msize); - }; - - PacketDataStream(unsigned char *d, int msize) { - setup(d, msize); - }; - - PacketDataStream &operator <<(const quint64 value) { - quint64 i = value; - - if ((i & 0x8000000000000000LL) && (~i < 0x100000000LL)) { - // Signed number. - i = ~i; - if (i <= 0x3) { - // Shortcase for -1 to -4 - append(0xFC | i); - return *this; - } else { - append(0xF8); - } - } - if (i < 0x80) { - // Need top bit clear - append(i); - } else if (i < 0x4000) { - // Need top two bits clear - append((i >> 8) | 0x80); - append(i & 0xFF); - } else if (i < 0x200000) { - // Need top three bits clear - append((i >> 16) | 0xC0); - append((i >> 8) & 0xFF); - append(i & 0xFF); - } else if (i < 0x10000000) { - // Need top four bits clear - append((i >> 24) | 0xE0); - append((i >> 16) & 0xFF); - append((i >> 8) & 0xFF); - append(i & 0xFF); - } else if (i < 0x100000000LL) { - // It's a full 32-bit integer. - append(0xF0); - append((i >> 24) & 0xFF); - append((i >> 16) & 0xFF); - append((i >> 8) & 0xFF); - append(i & 0xFF); - } else { - // It's a 64-bit value. - append(0xF4); - append((i >> 56) & 0xFF); - append((i >> 48) & 0xFF); - append((i >> 40) & 0xFF); - append((i >> 32) & 0xFF); - append((i >> 24) & 0xFF); - append((i >> 16) & 0xFF); - append((i >> 8) & 0xFF); - append(i & 0xFF); - } - return *this; - } - - PacketDataStream &operator >>(quint64 &i) { - quint64 v = next(); - - if ((v & 0x80) == 0x00) { - i=(v & 0x7F); - } else if ((v & 0xC0) == 0x80) { - i=(v & 0x3F) << 8 | next(); - } else if ((v & 0xF0) == 0xF0) { - switch (v & 0xFC) { - case 0xF0: - i=next() << 24 | next() << 16 | next() << 8 | next(); - break; - case 0xF4: - i=next() << 56 | next() << 48 | next() << 40 | next() << 32 | next() << 24 | next() << 16 | next() << 8 | next(); - break; - case 0xF8: - *this >> i; - i = ~i; - break; - case 0xFC: - i=v & 0x03; - i = ~i; - break; - default: - ok = false; - i = 0; - break; - } - } else if ((v & 0xF0) == 0xE0) { - i=(v & 0x0F) << 24 | next() << 16 | next() << 8 | next(); - } else if ((v & 0xE0) == 0xC0) { - i=(v & 0x1F) << 16 | next() << 8 | next(); - } - return *this; - } - - PacketDataStream &operator <<(const QByteArray &a) { - *this << a.size(); - append(a.constData(), a.size()); - return *this; - } - - PacketDataStream &operator >>(QByteArray &a) { - quint32 len; - *this >> len; - if (len > left()) { - len = left(); - ok = false; - } - a = QByteArray(reinterpret_cast<const char *>(& data[offset]), len); - offset+=len; - return *this; - } - - PacketDataStream &operator <<(const QString &s) { - return *this << s.toUtf8(); - } - - // Using the data directly instead of through qbuff avoids a copy. - PacketDataStream &operator >>(QString &s) { - quint32 len; - *this >> len; - if (len > left()) { - len = left(); - ok = false; - } - s = QString::fromUtf8(reinterpret_cast<const char *>(& data[offset]), len); - offset+=len; - return *this; - } - - PacketDataStream &operator <<(const bool b) { - quint32 v = b ? 1 : 0; - return *this << v; - } - - PacketDataStream &operator >>(bool &b) { - quint32 v; - *this >> v; - b = v ? true : false; - return *this; - } - -#define INTMAPOPERATOR(type) \ - PacketDataStream &operator <<(const type v) { \ - return *this << static_cast<quint64>(v); \ - } \ - PacketDataStream &operator >>(type &v) { \ - quint64 vv; \ - *this >> vv; \ - v = static_cast<type>(vv); \ - return *this; \ - } - - - INTMAPOPERATOR(int); - INTMAPOPERATOR(unsigned int); - INTMAPOPERATOR(short); - INTMAPOPERATOR(unsigned short); - INTMAPOPERATOR(char); - INTMAPOPERATOR(unsigned char); - - union double64u { - quint64 ui; - double d; - }; - - PacketDataStream &operator <<(const double v) { - double64u u; - u.d = v; - return *this << u.ui; - } - - PacketDataStream &operator >>(double &v) { - double64u u; - *this >> u.ui; - v = u.d; - return *this; - } - - template <typename T> - PacketDataStream &operator <<(const QList<T> &l) { - *this << l.size(); - for (int i=0;i < l.size();i++) - *this << l.at(i); - return *this; - } - - template <typename T> - PacketDataStream &operator >>(QList<T> &l) { - l.clear(); - quint32 len; - *this >> len; - if (len > left()) { - len = left(); - ok = false; - } - for (quint32 i=0;i<len;i++) { - if (left() == 0) { - ok = false; - break; - } - - T t; - *this >> t; - l.append(t); - } - return *this; - } - - - template <typename T> - PacketDataStream &operator <<(const QSet<T> &s) { - *this << s.size(); - for (typename QSet<T>::const_iterator i=s.constBegin();i!=s.constEnd();++i) - *this << *i; - return *this; - } - - template <typename T> - PacketDataStream &operator >>(QSet<T> &s) { - s.clear(); - quint32 len; - *this >> len; - if (len > left()) { - len = left(); - ok = false; - } - for (quint32 i=0;i<len;i++) { - if (left() == 0) { - ok = false; - break; - } - - T t; - *this >> t; - s.insert(t); - } - return *this; - } - - template <typename T,typename U> - PacketDataStream &operator <<(const QPair<T,U> &p) { - return *this << p.first << p.second; - } - - template <typename T,typename U> - PacketDataStream &operator >>(QPair<T,U> &p) { - return *this >> p.first >> p.second; - } - -}; - -#else -class PacketDataStream; -#endif diff --git a/src/murmur/Messages.cpp b/src/murmur/Messages.cpp index 44aafe0ab..41c81be8c 100644 --- a/src/murmur/Messages.cpp +++ b/src/murmur/Messages.cpp @@ -37,66 +37,66 @@ #include "Connection.h" #include "Server.h" #include "DBus.h" -#include "PacketDataStream.h" #define MSG_SETUP(st) \ User *uSource = static_cast<User *>(cCon); \ - MessagePermissionDenied mpd; \ - msg->uiSession = uSource->uiSession; \ if (uSource->sState != st) \ return #define VICTIM_SETUP \ - User *pDstUser = qhUsers.value(msg->uiVictim); \ + User *pDstUser = uSource; \ + if (msg->has_session()) \ + pDstUser = qhUsers.value(msg->session()); \ if (! pDstUser) \ return; \ Q_UNUSED(pDstUser) #define PERM_DENIED(who, where, what) \ - mpd.qsReason = QString("%1 not allowed to %2 in %3").arg(who->qsName).arg(ChanACL::permName(what)).arg(where->qsName); \ - sendMessage(cCon, &mpd); \ - log(uSource, mpd.qsReason) + { \ + MumbleProto::PermissionDenied mppd; \ + QString reason = QString("%1 not allowed to %2 in %3").arg(who->qsName).arg(ChanACL::permName(what)).arg(where->qsName); \ + mppd.set_reason(u8(reason)); \ + sendMessage(uSource, mppd, MessageHandler::PermissionDenied); \ + log(uSource, reason); \ + } #define PERM_DENIED_TEXT(text) \ - mpd.qsReason = text; \ - sendMessage(cCon, &mpd) + { \ + MumbleProto::PermissionDenied mppd; \ + mppd.set_reason(std::string(text)); \ + sendMessage(uSource, mppd, MessageHandler::PermissionDenied); \ + } -void Server::msgServerAuthenticate(Connection *cCon, MessageServerAuthenticate *msg) { +void Server::msgAuthenticate(Connection *cCon, MumbleProto::Authenticate *msg) { MSG_SETUP(Player::Connected); Channel *c; - uSource->qsName = msg->qsUsername; + uSource->qsName = u8(msg->username()); - MessageServerReject msr; bool ok = false; - bool nameok = validatePlayerName(msg->qsUsername); + bool nameok = validatePlayerName(uSource->qsName); + QString pw = u8(msg->password()); // Fetch ID and stored username. // Since this may call DBus, which may recall our dbus messages, this function needs // to support re-entrancy, and also to support the fact that sessions may go away. - int id = authenticate(msg->qsUsername, msg->qsPassword); - - // Did the session go away? - Player *p = qhUsers.value(msg->uiSession); - if (p != uSource) - return; + int id = authenticate(uSource->qsName, pw); uSource->iId = id >= 0 ? id : -1; - uSource->qsName = msg->qsUsername; - - if (msg->iVersion != MESSAGE_STREAM_VERSION) { - msr.qsReason = QString("Wrong version of mumble protocol (client: %1, server: %2)").arg(msg->iVersion).arg(MESSAGE_STREAM_VERSION); - msr.rtType = MessageServerReject::WrongVersion; - } else if (! nameok && (uSource->iId == -1)) { - msr.qsReason = "Invalid Username"; - msr.rtType = MessageServerReject::InvalidUsername; + + QString reason; + MumbleProto::Reject_RejectType rtType = MumbleProto::Reject_RejectType_None; + + if (! nameok && (uSource->iId == -1)) { + reason = "Invalid Username"; + rtType = MumbleProto::Reject_RejectType_InvalidUsername; } else if (id==-1) { - msr.qsReason = "Wrong password for user"; - msr.rtType = MessageServerReject::WrongUserPW; - } else if (id==-2 && ! qsPassword.isEmpty() && qsPassword != msg->qsPassword) { - msr.qsReason = "Invalid server password"; - msr.rtType = MessageServerReject::WrongServerPW; + reason = "Wrong password for user"; + rtType = MumbleProto::Reject_RejectType_WrongUserPW; + } else if (id==-2 && ! qsPassword.isEmpty() && qsPassword != pw) { + reason = "Invalid server password"; + rtType = MumbleProto::Reject_RejectType_WrongServerPW; } else { ok = true; } @@ -115,39 +115,42 @@ void Server::msgServerAuthenticate(Connection *cCon, MessageServerAuthenticate * // Allow reuse of name from same IP if (ok && uOld && (uSource->iId == -1)) { if (uOld->peerAddress() != cCon->peerAddress()) { - msr.qsReason = "Playername already in use"; - msr.rtType = MessageServerReject::UsernameInUse; + reason = "Playername already in use"; + rtType = MumbleProto::Reject_RejectType_UsernameInUse; ok = false; } } if ((id != 0) && (qhUsers.count() > iMaxUsers)) { - msr.qsReason = QString::fromLatin1("Server is full (max %1 users)").arg(iMaxUsers); - msr.rtType = MessageServerReject::ServerFull; + reason = QString::fromLatin1("Server is full (max %1 users)").arg(iMaxUsers); + rtType = MumbleProto::Reject_RejectType_ServerFull; ok = false; } if (! ok) { - log(uSource, QString("Rejected connection: %1").arg(msr.qsReason)); - sendMessage(cCon, &msr); - cCon->disconnectSocket(); + log(uSource, QString("Rejected connection: %1").arg(reason)); + MumbleProto::Reject mpr; + mpr.set_reason(u8(reason)); + mpr.set_type(rtType); + sendMessage(uSource, mpr, MessageHandler::Reject); + cCon->disconnectSocket(true); return; } // Kick ghost if (uOld) { log(uSource, "Disconnecting ghost"); - uOld->disconnectSocket(); + uOld->disconnectSocket(true); } // Setup UDP encryption uSource->csCrypt.genKey(); - MessageCryptSetup mcs; - mcs.uiSession = uSource->uiSession; - mcs.qbaKey = QByteArray(reinterpret_cast<const char *>(uSource->csCrypt.raw_key), AES_BLOCK_SIZE); - mcs.qbaServerNonce = QByteArray(reinterpret_cast<const char *>(uSource->csCrypt.encrypt_iv), AES_BLOCK_SIZE); - mcs.qbaClientNonce = QByteArray(reinterpret_cast<const char *>(uSource->csCrypt.decrypt_iv), AES_BLOCK_SIZE); - sendMessage(cCon, &mcs); + + MumbleProto::CryptSetup mpcrypt; + mpcrypt.set_key(std::string(reinterpret_cast<const char *>(uSource->csCrypt.raw_key), AES_BLOCK_SIZE)); + mpcrypt.set_server_nonce(std::string(reinterpret_cast<const char *>(uSource->csCrypt.encrypt_iv), AES_BLOCK_SIZE)); + mpcrypt.set_client_nonce(std::string(reinterpret_cast<const char *>(uSource->csCrypt.decrypt_iv), AES_BLOCK_SIZE)); + sendMessage(uSource, mpcrypt, MessageHandler::CryptSetup); int lchan = readLastChannel(uSource->iId); if (lchan == 0) @@ -163,27 +166,24 @@ void Server::msgServerAuthenticate(Connection *cCon, MessageServerAuthenticate * QQueue<Channel *> q; QSet<Channel *> chans; q << qhChannels.value(0); + MumbleProto::ChannelState mpcs; while (! q.isEmpty()) { c = q.dequeue(); - chans.insert(c); - MessageChannelAdd mca; - mca.uiSession = 0; - mca.iId = c->iId; - mca.iParent = (c->cParent) ? c->cParent->iId : -1; - mca.qsName = c->qsName; - if (c->iId == 0) - mca.qsName = qsRegName.isEmpty() ? QLatin1String("Root") : qsRegName; + mpcs.Clear(); - sendMessage(cCon, &mca); - - MessageChannelDescUpdate mcdu; - - mcdu.iId = c->iId; - mcdu.qsDesc = c->qsDesc; + mpcs.set_channel_id(c->iId); + if (c->cParent) + mpcs.set_parent(c->cParent->iId); + if (c->iId == 0) + 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)); - sendMessage(static_cast<User *>(p), &mcdu); + sendMessage(uSource, mpcs, MessageHandler::ChannelState); foreach(c, c->qlChannels) q.enqueue(c); @@ -191,513 +191,472 @@ void Server::msgServerAuthenticate(Connection *cCon, MessageServerAuthenticate * foreach(c, chans) { if (c->qhLinks.count() > 0) { - MessageChannelLink mcl; - mcl.iId = c->iId; - mcl.ltType = MessageChannelLink::Link; + mpcs.Clear(); + mpcs.set_channel_id(c->iId); + foreach(Channel *l, c->qhLinks.keys()) - mcl.qlTargets << l->iId; - sendMessage(cCon, &mcl); + mpcs.add_links(l->iId); + sendMessage(uSource, mpcs, MessageHandler::ChannelState); } } - MessageServerJoin msjMsg; - MessagePlayerMove mpm; + MumbleProto::UserState mpus; uSource->sState = Player::Authenticated; - msjMsg.uiSession = uSource->uiSession; - msjMsg.iId = uSource->iId; - msjMsg.qsPlayerName = uSource->qsName; - sendExcept(&msjMsg, cCon); + mpus.set_session(uSource->uiSession); + mpus.set_name(u8(uSource->qsName)); + if (uSource->iId >= 0) + mpus.set_user_id(uSource->iId); + if (uSource->cChannel->iId != 0) + mpus.set_channel_id(uSource->cChannel->iId); - mpm.uiSession = 0; - mpm.uiVictim = uSource->uiSession; - mpm.iChannelId = uSource->cChannel->iId; - if (mpm.iChannelId != 0) - sendExcept(&mpm, cCon); + sendExcept(uSource, mpus, MessageHandler::UserState); foreach(User *u, qhUsers) { if (u->sState != Player::Authenticated) continue; - msjMsg.uiSession = u->uiSession; - msjMsg.iId = u->iId; - msjMsg.qsPlayerName = u->qsName; - sendMessage(cCon, &msjMsg); - - if (u->bDeaf) { - MessagePlayerDeaf mpdMsg; - mpdMsg.uiSession = 0; - mpdMsg.uiVictim = u->uiSession; - mpdMsg.bDeaf = true; - sendMessage(cCon, &mpdMsg); - } else if (u->bMute || u->bSuppressed) { - MessagePlayerMute mpmMsg; - mpmMsg.uiSession = 0; - mpmMsg.uiVictim = u->uiSession; - mpmMsg.bMute = true; - sendMessage(cCon, &mpmMsg); - } - if (u->bSelfDeaf || u->bSelfMute) { - MessagePlayerSelfMuteDeaf mpsmdMsg; - mpsmdMsg.uiSession = u->uiSession; - mpsmdMsg.bDeaf = u->bSelfDeaf; - mpsmdMsg.bMute = u->bSelfMute; - sendMessage(cCon, &mpsmdMsg); - } - - mpm.uiSession = 0; - mpm.uiVictim = u->uiSession; - mpm.iChannelId = u->cChannel->iId; - sendMessage(cCon, &mpm); - } - - MessageServerSync mssMsg; - mssMsg.uiSession = uSource->uiSession; - mssMsg.qsWelcomeText = qsWelcomeText; - mssMsg.iMaxBandwidth = iMaxBandwidth; - sendMessage(cCon, &mssMsg); + + mpus.Clear(); + mpus.set_session(u->uiSession); + mpus.set_name(u8(u->qsName)); + if (u->iId >= 0) + mpus.set_user_id(u->iId); + if (u->cChannel->iId != 0) + mpus.set_channel_id(u->cChannel->iId); + if (u->bDeaf) + mpus.set_deaf(true); + else if (u->bMute) + mpus.set_mute(true); + if (u->bSuppressed) + mpus.set_suppressed(true); + if (u->bSelfDeaf) + mpus.set_self_deaf(true); + else if (u->bSelfMute) + mpus.set_self_mute(true); + + if (! qhUserTextureCache.contains(u->iId)) { + QByteArray qba = getUserTexture(u->iId); + qhUserTextureCache.insert(u->iId, qba); + } + QByteArray texture = qhUserTextureCache.value(u->iId); + if (! texture.isEmpty()) + mpus.set_texture(std::string(texture.constData(), texture.size())); + + sendMessage(uSource, mpus, MessageHandler::UserState); + } + + MumbleProto::ServerSync mpss; + mpss.set_session(uSource->uiSession); + if (! qsWelcomeText.isEmpty()) + mpss.set_welcome_text(u8(qsWelcomeText)); + mpss.set_max_bandwidth(iMaxBandwidth); + + sendMessage(uSource, mpss, MessageHandler::ServerSync); log(uSource, "Authenticated"); emit playerConnected(uSource); playerEnterChannel(uSource, lc, false); - - while (lc && lc->qsDesc.isEmpty()) - lc = lc->cParent; - if (lc) - sendChannelDescription(uSource, lc); } -void Server::msgServerBanList(Connection *cCon, MessageServerBanList *msg) { +void Server::msgBanList(Connection *cCon, MumbleProto::BanList *msg) { MSG_SETUP(Player::Authenticated); + typedef QPair<quint32, int> ban; if (! hasPermission(uSource, qhChannels.value(0), ChanACL::Write)) { PERM_DENIED(uSource, qhChannels.value(0), ChanACL::Write); return; } - if (msg->bQuery) { - MessageServerBanList msbl; - msbl.uiSession = 0; - msbl.bQuery = false; - msbl.qlBans = qlBans; - sendMessage(cCon, &msbl); + if (msg->query()) { + msg->clear_query(); + msg->clear_bans(); + foreach(const ban &b, qlBans) { + MumbleProto::BanList_BanEntry *be = msg->add_bans(); + char buff[4]; + buff[0] = (b.first >> 24) & 0xFF; + buff[1] = (b.first >> 16) & 0xFF; + buff[2] = (b.first >> 8) & 0xFF; + buff[3] = (b.first >> 0) & 0xFF; + be->set_address(std::string(buff, 4)); + be->set_mask(b.second); + } + sendMessage(uSource, *msg, MessageHandler::BanList); } else { - qlBans = msg->qlBans; + qlBans.clear(); + for(int i=0;i < msg->bans_size(); ++i) { + const MumbleProto::BanList_BanEntry &be = msg->bans(i); + quint32 v = 0; + std::string s = be.address(); + if (s.length() == 4) { + const char *data = s.data(); + v += (data[0] << 24); + v += (data[1] << 16); + v += (data[2] << 8); + v += (data[3] << 0); + qlBans << ban(v, be.mask()); + } + } saveBans(); log(uSource, "Updated banlist"); } } -void Server::msgServerLeave(Connection *cCon, MessageServerLeave *) { - cCon->disconnectSocket(); -} - -void Server::msgServerJoin(Connection *cCon, MessageServerJoin *) { - cCon->disconnectSocket(); +void Server::msgReject(Connection *, MumbleProto::Reject *) { } -void Server::msgServerReject(Connection *cCon, MessageServerReject *) { - cCon->disconnectSocket(); +void Server::msgServerSync(Connection *, MumbleProto::ServerSync *) { } -void Server::msgServerSync(Connection *cCon, MessageServerSync *) { - cCon->disconnectSocket(); +void Server::msgPermissionDenied(Connection *, MumbleProto::PermissionDenied *) { } -void Server::msgPermissionDenied(Connection *cCon, MessagePermissionDenied *) { - cCon->disconnectSocket(); -} - -void Server::msgPlayerRename(Connection *cCon, MessagePlayerRename *) { - cCon->disconnectSocket(); -} - -void Server::msgCryptSetup(Connection *cCon, MessageCryptSetup *) { - cCon->disconnectSocket(); -} - -void Server::msgSpeex(Connection *cCon, MessageSpeex *msg) { +void Server::msgUDPTunnel(Connection *cCon, MumbleProto::UDPTunnel *msg) { MSG_SETUP(Player::Authenticated); - fakeUdpPacket(msg, cCon); + + const std::string &str = msg->packet(); + int len = str.length(); + if (len < 1) + return; + QReadLocker rl(&qrwlUsers); + processMsg(uSource, str.data(), len); } -void Server::msgPlayerMute(Connection *cCon, MessagePlayerMute *msg) { +void Server::msgUserState(Connection *cCon, MumbleProto::UserState *msg) { MSG_SETUP(Player::Authenticated); VICTIM_SETUP; - if ((pDstUser->iId ==0) || ! hasPermission(uSource, pDstUser->cChannel, ChanACL::MuteDeafen)) { - PERM_DENIED(uSource, pDstUser->cChannel, ChanACL::MuteDeafen); + if (pDstUser->iId == 0) { + PERM_DENIED_TEXT("Can't modify SuperUser"); return; } - if (! msg->bMute && pDstUser->bSuppressed) { - pDstUser->bSuppressed = false; - } else if (pDstUser->bMute == msg->bMute) { - return; - } + msg->set_session(pDstUser->uiSession); + msg->set_actor(uSource->uiSession); - pDstUser->bMute = msg->bMute; - sendAll(msg); - - if (! msg->bMute && pDstUser->bDeaf) { - pDstUser->bDeaf = false; - } + if (msg->has_channel_id()) { + Channel *c = qhChannels.value(msg->channel_id()); + if (!c || (c == pDstUser->cChannel)) + return; - log(uSource, QString("Muted %1 (%2)").arg(*pDstUser).arg(msg->bMute)); - emit playerStateChanged(pDstUser); -} + if ((uSource != pDstUser) && (! hasPermission(uSource, pDstUser->cChannel, ChanACL::MoveKick))) { + PERM_DENIED(uSource, pDstUser->cChannel, ChanACL::MoveKick); + return; + } -void Server::msgPlayerDeaf(Connection *cCon, MessagePlayerDeaf *msg) { - MSG_SETUP(Player::Authenticated); - VICTIM_SETUP; + if (! hasPermission(uSource, c, ChanACL::MoveKick) && ! hasPermission(pDstUser, c, ChanACL::Enter)) { + PERM_DENIED(pDstUser, c, ChanACL::Enter); + return; + } + } - if ((pDstUser->iId ==0) || ! hasPermission(uSource, pDstUser->cChannel, ChanACL::MuteDeafen)) { - PERM_DENIED(uSource, pDstUser->cChannel, ChanACL::MuteDeafen); - return; + if (msg->has_mute() || msg->has_deaf() || msg->has_suppressed()) { + if (! hasPermission(uSource, pDstUser->cChannel, ChanACL::MuteDeafen) || msg->suppressed()) { + PERM_DENIED(uSource, pDstUser->cChannel, ChanACL::MuteDeafen); + return; + } } - if (pDstUser->bDeaf == msg->bDeaf) + if ((pDstUser != uSource) && (msg->has_self_deaf() || msg->has_self_mute() || msg->has_texture())) return; - pDstUser->bDeaf = msg->bDeaf; - sendAll(msg); + // Permission checks done. Now enact this. - if (msg->bDeaf && ! pDstUser->bMute) { - pDstUser->bMute = true; + if (msg->has_self_deaf()) { + uSource->bSelfDeaf = msg->self_deaf(); + if (uSource->bSelfDeaf) + msg->set_self_mute(true); } - log(uSource, QString("Deafened %1 (%2)").arg(*pDstUser).arg(msg->bDeaf)); - - emit playerStateChanged(pDstUser); -} - -void Server::msgPlayerKick(Connection *cCon, MessagePlayerKick *msg) { - MSG_SETUP(Player::Authenticated); - VICTIM_SETUP; - - if ((pDstUser->iId ==0) || ! hasPermission(uSource, pDstUser->cChannel, ChanACL::MoveKick)) { - PERM_DENIED(uSource, pDstUser->cChannel, ChanACL::MoveKick); - return; + if (msg->has_self_mute()) { + uSource->bSelfMute = msg->self_mute(); + if (! uSource->bSelfMute) { + msg->set_self_deaf(false); + uSource->bSelfDeaf = false; + } } - sendAll(msg); - log(uSource, QString("Kicked %1 (%2)").arg(*pDstUser).arg(msg->qsReason)); - pDstUser->disconnectSocket(); -} -void Server::msgPlayerBan(Connection *cCon, MessagePlayerBan *msg) { - MSG_SETUP(Player::Authenticated); - VICTIM_SETUP; + if (msg->has_channel_id()) { + Channel *c = qhChannels.value(msg->channel_id()); - if ((pDstUser->iId ==0) || ! hasPermission(uSource, qhChannels.value(0), ChanACL::MoveKick)) { - PERM_DENIED(uSource, qhChannels.value(0), ChanACL::MoveKick); - return; + playerEnterChannel(pDstUser, c); + log(uSource, QString("Moved %1 to %2").arg(*pDstUser).arg(*c)); } - sendAll(msg); - log(uSource, QString("Kickbanned %1 (%2)").arg(*pDstUser).arg(msg->qsReason)); - - QHostAddress adr = pDstUser->peerAddress(); - quint32 base = adr.toIPv4Address(); - qlBans << QPair<quint32,int>(base, 32); - saveBans(); - pDstUser->disconnectSocket(); -} + if (msg->has_mute() || msg->has_deaf() || msg->has_suppressed()) { + if (msg->has_deaf()) { + pDstUser->bDeaf = msg->deaf(); + if (pDstUser->bDeaf) + msg->set_mute(true); + } + if (msg->has_mute()) { + pDstUser->bMute = msg->mute(); + if (! pDstUser->bMute) { + msg->set_deaf(false); + pDstUser->bDeaf = false; + } + } + if (msg->has_suppressed()) + pDstUser->bSuppressed = msg->suppressed(); -void Server::msgPlayerSelfMuteDeaf(Connection *cCon, MessagePlayerSelfMuteDeaf *msg) { - MSG_SETUP(Player::Authenticated); + log(uSource, QString("Changed speak-state of %1 (%2 %3 %4)").arg(*pDstUser).arg(pDstUser->bMute).arg(pDstUser->bDeaf).arg(pDstUser->bSuppressed)); + } - uSource->bSelfMute = msg->bMute; - uSource->bSelfDeaf = msg->bDeaf; - sendAll(msg); + sendAll(*msg, MessageHandler::UserState); - emit playerStateChanged(uSource); + emit playerStateChanged(pDstUser); } -void Server::msgPlayerMove(Connection *cCon, MessagePlayerMove *msg) { +void Server::msgUserRemove(Connection *cCon, MumbleProto::UserRemove *msg) { MSG_SETUP(Player::Authenticated); VICTIM_SETUP; + + msg->set_actor(uSource->uiSession); - Channel *c = qhChannels.value(msg->iChannelId); - if (!c || (c == pDstUser->cChannel)) - return; + bool ban = msg->has_ban() && msg->ban(); + + Channel *c = ban ? qhChannels.value(0) : pDstUser->cChannel; - if ((uSource != pDstUser) && ((pDstUser->iId ==0) || ! hasPermission(uSource, pDstUser->cChannel, ChanACL::MoveKick))) { - PERM_DENIED(uSource, pDstUser->cChannel, ChanACL::MoveKick); + if ((pDstUser->iId ==0) || ! hasPermission(uSource, c, ChanACL::MoveKick)) { + PERM_DENIED(uSource, c, ChanACL::MoveKick); return; } - if (! hasPermission(uSource, c, ChanACL::MoveKick) && ! hasPermission(pDstUser, c, ChanACL::Enter)) { - PERM_DENIED(pDstUser, c, ChanACL::Enter); - return; + if (ban) { + QHostAddress adr = pDstUser->peerAddress(); + quint32 base = adr.toIPv4Address(); + qlBans << QPair<quint32,int>(base, 32); + saveBans(); } - sendAll(msg); - playerEnterChannel(pDstUser, c); - log(uSource, QString("Moved %1 to %2").arg(*pDstUser).arg(*c)); + sendAll(*msg, MessageHandler::UserRemove); + if (ban) + log(uSource, QString("Kickbanned %1 (%2)").arg(*pDstUser).arg(u8(msg->reason()))); + else + log(uSource, QString("Kicked %1 (%2)").arg(*pDstUser).arg(u8(msg->reason()))); + pDstUser->disconnectSocket(); } -void Server::msgChannelAdd(Connection *cCon, MessageChannelAdd *msg) { +void Server::msgChannelState(Connection *cCon, MumbleProto::ChannelState *msg) { MSG_SETUP(Player::Authenticated); - Channel *p = qhChannels.value(msg->iParent); - if (!p) - return; + Channel *c = NULL; + Channel *p = NULL; - if (! hasPermission(uSource, p, ChanACL::MakeChannel)) { - PERM_DENIED(uSource, p, ChanACL::MakeChannel); - return; + if (msg->has_channel_id()) { + c = qhChannels.value(msg->channel_id()); + if (! c) + return; } - if (! validateChannelName(msg->qsName)) { - PERM_DENIED_TEXT("Illegal channel name"); + if (msg->has_parent()) { + p = qhChannels.value(msg->parent()); + if (! p); return; } - QRegExp re2("\\w"); - if (re2.indexIn(msg->qsName) == -1) { - PERM_DENIED_TEXT("Must have alphanumeric in name"); - return; - } + msg->clear_links(); - foreach(Channel *sibling, p->qlChannels) { - if (sibling->qsName == msg->qsName) { - PERM_DENIED_TEXT("Duplicate channel name"); + QString qsName; + QString qsDesc; + if (msg->has_description()) + qsDesc = u8(msg->description()); + if (msg->has_name()) { + qsName = u8(msg->name()); + + if (! validateChannelName(qsName)) { + PERM_DENIED_TEXT("Illegal channel name"); return; } - } - - Channel *c = addChannel(p, msg->qsName, QString()); - if (uSource->iId >= 0) { - Group *g = new Group(c, "admin"); - g->qsAdd << uSource->iId; - } - updateChannel(c); - - msg->iId = c->iId; - sendAll(msg); - log(uSource, QString("Added channel %1 under %2").arg(*c).arg(*p)); - - emit channelCreated(c); -} - -void Server::msgChannelRemove(Connection *cCon, MessageChannelRemove *msg) { - MSG_SETUP(Player::Authenticated); - Channel *c = qhChannels.value(msg->iId); - if (!c) - return; + QRegExp re2("\\w"); + if (re2.indexIn(qsName) == -1) { + PERM_DENIED_TEXT("Must have alphanumeric in name"); + return; + } - if (! hasPermission(uSource, c, ChanACL::Write) || (c->iId == 0)) { - PERM_DENIED(uSource, c, ChanACL::Write); - return; + if (p || c) { + Channel *cp = p ? p : c->cParent; + foreach(Channel *sibling, cp->qlChannels) { + if (sibling->qsName == qsName) { + PERM_DENIED_TEXT("Duplicate channel name"); + return; + } + } + } } - log(uSource, QString("Removed channel %1").arg(*c)); + if (! c) { + if (! p || qsName.isNull()) + return; + if (! hasPermission(uSource, p, ChanACL::MakeChannel)) { + PERM_DENIED(uSource, p, ChanACL::MakeChannel); + return; + } - removeChannel(c, uSource); -} + c = addChannel(p, qsName, qsDesc); + if (uSource->iId >= 0) { + Group *g = new Group(c, "admin"); + g->qsAdd << uSource->iId; + } + updateChannel(c); -void Server::msgChannelRename(Connection *cCon, MessageChannelRename *msg) { - MSG_SETUP(Player::Authenticated); - Channel *c = qhChannels.value(msg->iId); + msg->set_channel_id(c->iId); + log(uSource, QString("Added channel %1 under %2").arg(*c).arg(*p)); + emit channelCreated(c); + } else { + if (! qsName.isNull()) { + if (! hasPermission(uSource, c, ChanACL::Write) || (c->iId == 0)) { + PERM_DENIED(uSource, c, ChanACL::Write); + return; + } + } + if (! qsDesc.isNull()) { + if (! hasPermission(uSource, c, ChanACL::Write)) { + PERM_DENIED(uSource, c, ChanACL::Write); + return; + } + } + if (p) { + if (p == c->cParent) + return; - if (!c) - return; + Channel *ip = p; + while (ip) { + if (ip == c) + return; + ip = ip->cParent; + } - if (! hasPermission(uSource, c, ChanACL::Write) || (c->iId == 0)) { - PERM_DENIED(uSource, c, ChanACL::Write); - return; - } + if (! hasPermission(uSource, c, ChanACL::Write)) { + PERM_DENIED(uSource, c, ChanACL::Write); + return; + } - if (! validateChannelName(msg->qsName)) { - PERM_DENIED_TEXT("Illegal channel name"); - return; - } + if (! hasPermission(uSource, p, ChanACL::MakeChannel)) { + PERM_DENIED(uSource, p, ChanACL::MakeChannel); + return; + } - QRegExp re2("\\w"); - if (re2.indexIn(msg->qsName) == -1) { - PERM_DENIED_TEXT("Must have alphanumeric in name"); - return; - } + QString name = qsName.isNull() ? c->qsName : qsName; - foreach(Channel *sibling, c->cParent->qlChannels) { - if (sibling->qsName == msg->qsName) { - PERM_DENIED_TEXT("Duplicate channel name"); - return; + foreach(Channel *sibling, p->qlChannels) { + if (sibling->qsName == name) { + PERM_DENIED_TEXT("Duplicate channel name"); + return; + } + } + } + QList<Channel *> qlAdd; + QList<Channel *> qlRemove; + + if (msg->links_add_size() || msg->links_remove_size()) { + if (! hasPermission(uSource, c, ChanACL::LinkChannel)) { + PERM_DENIED(uSource, c, ChanACL::LinkChannel); + return; + } + if (msg->links_remove_size()) { + for(int i=0;i < msg->links_remove_size(); ++i) { + unsigned int link = msg->links_remove(i); + Channel *l = qhChannels.value(link); + if (! l) + return; + qlRemove << l; + } + } + if (msg->links_add_size()) { + for(int i=0;i < msg->links_add_size(); ++i) { + unsigned int link = msg->links_add(i); + Channel *l = qhChannels.value(link); + if (! l) + return; + if (! hasPermission(uSource, l, ChanACL::LinkChannel)) { + PERM_DENIED(uSource, l, ChanACL::LinkChannel); + return; + } + qlAdd << l; + } + } } - } - log(uSource, QString("Renamed channel %1 to %2").arg(*c).arg(msg->qsName)); - c->qsName = msg->qsName; - updateChannel(c); - sendAll(msg); + // All permission checks done -- the update is good. - emit channelStateChanged(c); -} + if (p) { + log(uSource, QString("Moved channel %1 from %2 to %3").arg(*c).arg(* c->cParent).arg(*p)); -void Server::msgChannelDescUpdate(Connection *cCon, MessageChannelDescUpdate *msg) { - MSG_SETUP(Player::Authenticated); - Channel *c = qhChannels.value(msg->iId); + c->cParent->removeChannel(c); + p->addChannel(c); + } + if (! qsName.isNull()) { + log(uSource, QString("Renamed channel %1 to %2").arg(*c).arg(qsName)); + c->qsName = qsName; + } + if (! qsDesc.isNull()) + c->qsDesc = qsDesc; - if (!c) - return; + foreach(Channel *l, qlAdd) { + c->link(l); + addLink(c, l); + } + foreach(Channel *l, qlRemove) { + c->unlink(l); + removeLink(c, l); + } - if (! hasPermission(uSource, c, ChanACL::Write)) { - PERM_DENIED(uSource, c, ChanACL::Write); - return; + updateChannel(c); + emit channelStateChanged(c); } - log(uSource, QString("Changed description for channel %1 to: %2").arg(*c).arg(msg->qsDesc)); - c->qsDesc = msg->qsDesc; - updateChannel(c); - sendAll(msg); - sendChannelDescriptionUpdate(c); + sendAll(*msg, MessageHandler::ChannelState); } -void Server::msgChannelMove(Connection *cCon, MessageChannelMove *msg) { +void Server::msgChannelRemove(Connection *cCon, MumbleProto::ChannelRemove *msg) { MSG_SETUP(Player::Authenticated); - Channel *c = qhChannels.value(msg->iId); - Channel *np = qhChannels.value(msg->iParent); - if (!c || ! np) - return; - - if (np == c->cParent) + Channel *c = qhChannels.value(msg->channel_id()); + if (!c) return; - if (! hasPermission(uSource, c, ChanACL::Write)) { + if (! hasPermission(uSource, c, ChanACL::Write) || (c->iId == 0)) { PERM_DENIED(uSource, c, ChanACL::Write); return; } - if (! hasPermission(uSource, np, ChanACL::MakeChannel)) { - PERM_DENIED(uSource, np, ChanACL::MakeChannel); - return; - } - - foreach(Channel *sibling, np->qlChannels) { - if (sibling->qsName == c->qsName) { - PERM_DENIED_TEXT("Duplicate channel name"); - return; - } - } - - // Can't move to a subchannel of itself - Channel *p = np; - while (p) { - if (p == c) - return; - p = p->cParent; - } - - log(uSource, QString("Moved channel %1 from %2 to %3").arg(*c).arg(* c->cParent).arg(*np)); - - c->cParent->removeChannel(c); - np->addChannel(c); - updateChannel(c); - sendAll(msg); + log(uSource, QString("Removed channel %1").arg(*c)); - emit channelStateChanged(c); + removeChannel(c, uSource); } -void Server::msgChannelLink(Connection *cCon, MessageChannelLink *msg) { +void Server::msgTextMessage(Connection *cCon, MumbleProto::TextMessage *msg) { MSG_SETUP(Player::Authenticated); + QMutexLocker qml(&qmCache); - Channel *c = qhChannels.value(msg->iId); - if (!c) - return; - - if (! hasPermission(uSource, c, ChanACL::LinkChannel)) { - PERM_DENIED(uSource, c, ChanACL::LinkChannel); - return; - } + QSet<User *> users; + QQueue<Channel *> q; - Channel *l = (msg->qlTargets.count() == 1) ? qhChannels.value(msg->qlTargets[0]) : NULL; + msg->set_actor(uSource->uiSession); - QSet<Channel *> oldset = c->qhLinks.keys().toSet(); + for(int i=0;i<msg->channel_id_size(); ++i) { + unsigned int id = msg->channel_id(i); - switch (msg->ltType) { - case MessageChannelLink::Link: - if (!l) - return; - if (! hasPermission(uSource, l, ChanACL::LinkChannel)) { - PERM_DENIED(uSource, l, ChanACL::LinkChannel); - return; - } - c->link(l); - addLink(c, l); - log(uSource, QString("Linked channel %1 to %2").arg(*c).arg(*l)); - emit channelStateChanged(c); - break; - case MessageChannelLink::Unlink: - if (!l) - return; - c->unlink(l); - removeLink(c, l); - log(uSource, QString("Unlinked channel %1 to %2").arg(*c).arg(*l)); - emit channelStateChanged(c); - break; - case MessageChannelLink::UnlinkAll: - if (msg->qlTargets.count() > 0) - return; - c->unlink(NULL); - removeLink(c, NULL); - log(uSource, QString("Unlinked all from channel %1").arg(*c)); - sendAll(msg); - emit channelStateChanged(c); + Channel *c = qhChannels.value(id); + if (! c) return; - case MessageChannelLink::PushLink: - if (msg->qlTargets.count() <= 0) - return; - foreach(int tid, msg->qlTargets) { - l=qhChannels.value(tid); - if (l && hasPermission(uSource, l, ChanACL::LinkChannel)) - c->playerLink(l, uSource); - } - break; - case MessageChannelLink::PushUnlink: - if (msg->qlTargets.count() <= 0) - return; - foreach(int tid, msg->qlTargets) { - l=qhChannels.value(tid); - if (l) - c->playerUnlink(l, uSource); - } - break; - default: - if (msg->qlTargets.count() <= 0) - return; - } - - QSet<Channel *> newset = c->qhLinks.keys().toSet(); - QSet<Channel *> changed; - if (newset.count() == oldset.count()) - return; - - MessageChannelLink mcl; - mcl.iId = msg->iId; - mcl.uiSession=msg->uiSession; + if (! ChanACL::hasPermission(uSource, c, ChanACL::Speak | ChanACL::AltSpeak, acCache)) { + PERM_DENIED(uSource, c, ChanACL::Speak); + return; + } - if (newset.count() > oldset.count()) { - mcl.ltType = MessageChannelLink::Link; - changed = newset - oldset; - } else { - mcl.ltType = MessageChannelLink::Unlink; - changed = oldset - newset; + foreach(Player *p, c->qlPlayers) + users.insert(static_cast<User *>(p)); } - foreach(l, changed) - mcl.qlTargets << l->iId; - sendAll(&mcl); -} + + for(int i=0;i<msg->tree_id_size(); ++i) { + unsigned int id = msg->tree_id(i); -void Server::msgTextMessage(Connection *cCon, MessageTextMessage *msg) { - MSG_SETUP(Player::Authenticated); - QMutexLocker qml(&qmCache); - - if (msg->iChannel != -1) { - Channel *c = qhChannels.value(msg->iChannel); - if (!c) + Channel *c = qhChannels.value(id); + if (! c) return; if (! ChanACL::hasPermission(uSource, c, ChanACL::Speak | ChanACL::AltSpeak, acCache)) { @@ -705,42 +664,37 @@ void Server::msgTextMessage(Connection *cCon, MessageTextMessage *msg) { return; } - QSet<Channel *> chans; - QQueue<Channel *> q; - q << c; - chans.insert(c); + q.enqueue(c); + } - if (msg->bTree) { - while (! q.isEmpty()) { - c = q.dequeue(); - chans.insert(c); - foreach(c, c->qlChannels) - q.enqueue(c); - } - } - foreach(c, chans) { - if (ChanACL::hasPermission(uSource, c, ChanACL::Speak | ChanACL::AltSpeak, acCache)) { - foreach(Player *p, c->qlPlayers) { - if (p != static_cast<Player *>(uSource)) - sendMessage(static_cast<User *>(p), msg); - } - } + while (! q.isEmpty()) { + Channel *c = q.dequeue(); + if (ChanACL::hasPermission(uSource, c, ChanACL::Speak | ChanACL::AltSpeak, acCache)) { + foreach(c, c->qlChannels) + q.enqueue(c); + foreach(Player *p, c->qlPlayers) + users.insert(static_cast<User *>(p)); } + } - } else { - VICTIM_SETUP; - if (! ChanACL::hasPermission(uSource, pDstUser->cChannel, ChanACL::Speak | ChanACL::AltSpeak, acCache)) { - PERM_DENIED(uSource, pDstUser->cChannel, ChanACL::Speak); + for(int i=0;i < msg->session_size(); ++i) { + unsigned int session = msg->session(i); + User *u = qhUsers.value(session); + if (! ChanACL::hasPermission(uSource, u->cChannel, ChanACL::Speak | ChanACL::AltSpeak, acCache)) { + PERM_DENIED(uSource, u->cChannel, ChanACL::Speak); return; } - sendMessage(pDstUser, msg); + users.insert(u); } + + foreach(User *u, users) + sendMessage(u, *msg, MessageHandler::TextMessage); } -void Server::msgEditACL(Connection *cCon, MessageEditACL *msg) { +void Server::msgACL(Connection *cCon, MumbleProto::ACL *msg) { MSG_SETUP(Player::Authenticated); - Channel *c = qhChannels.value(msg->iId); + Channel *c = qhChannels.value(msg->channel_id()); if (!c) return; @@ -748,15 +702,17 @@ void Server::msgEditACL(Connection *cCon, MessageEditACL *msg) { PERM_DENIED(uSource, c, ChanACL::Write); return; } - - MessageEditACL mea; - mea.iId = msg->iId; - - if (msg->bQuery) { + + if (msg->has_query() && msg->query()) { QStack<Channel *> chans; Channel *p; ChanACL *acl; - + + msg->clear_groups(); + msg->clear_acls(); + msg->clear_query(); + msg->set_inherit_acls(c->bInheritACL); + p = c; while (p) { chans.push(p); @@ -766,22 +722,21 @@ void Server::msgEditACL(Connection *cCon, MessageEditACL *msg) { p = NULL; } - mea.bQuery = false; - mea.bInheritACL = c->bInheritACL; - while (! chans.isEmpty()) { p = chans.pop(); foreach(acl, p->qlACL) { if ((p == c) || (acl->bApplySubs)) { - MessageEditACL::ACLStruct as; - as.bInherited = (p != c); - as.bApplyHere = acl->bApplyHere; - as.bApplySubs = acl->bApplySubs; - as.iPlayerId = acl->iPlayerId; - as.qsGroup = acl->qsGroup; - as.pDeny = acl->pDeny; - as.pAllow = acl->pAllow; - mea.acls << as; + MumbleProto::ACL_ChanACL *mpacl = msg->add_acls(); + + mpacl->set_inherited(p != c); + mpacl->set_apply_here(acl->bApplyHere); + mpacl->set_apply_subs(acl->bApplySubs); + if (acl->iPlayerId >= 0) + mpacl->set_user_id(acl->iPlayerId); + else + mpacl->set_group(u8(acl->qsGroup)); + mpacl->set_grant(acl->pAllow); + mpacl->set_deny(acl->pDeny); } } } @@ -792,25 +747,26 @@ void Server::msgEditACL(Connection *cCon, MessageEditACL *msg) { foreach(name, allnames) { Group *g = c->qhGroups.value(name); Group *pg = p ? Group::getGroup(p, name) : NULL; - MessageEditACL::GroupStruct gs; - gs.qsName = name; - gs.bInherit = g ? g->bInherit : true; - gs.bInheritable = g ? g->bInheritable : true; - gs.bInherited = ((pg != NULL) && pg->bInheritable); + + MumbleProto::ACL_ChanGroup *group = msg->add_groups(); + group->set_name(u8(name)); + group->set_inherit(g ? g->bInherit : true); + group->set_inheritable(g ? g->bInheritable : true); + group->set_inherited((pg != NULL) && pg->bInheritable); if (g) { - gs.qsAdd = g->qsAdd; - gs.qsRemove = g->qsRemove; + foreach(int id, g->qsAdd) + group->add_add(id); + foreach(int id, g->qsRemove) + group->add_remove(id); } if (pg) - gs.qsInheritedMembers = pg->members(); - mea.groups << gs; + foreach(int id, pg->members()) + group->add_inherited_members(id); } - sendMessage(cCon, &mea); + sendMessage(uSource, *msg, MessageHandler::ACL); } else { Group *g; ChanACL *a; - MessageEditACL::GroupStruct gs; - MessageEditACL::ACLStruct as; QHash<QString, QSet<int> > hOldTemp; @@ -825,25 +781,31 @@ void Server::msgEditACL(Connection *cCon, MessageEditACL *msg) { c->qhGroups.clear(); c->qlACL.clear(); - c->bInheritACL = msg->bInheritACL; - - foreach(gs, msg->groups) { - g = new Group(c, gs.qsName); - g->bInherit = gs.bInherit; - g->bInheritable = gs.bInheritable; - g->qsAdd = gs.qsAdd; - g->qsRemove = gs.qsRemove; - g->qsTemporary = hOldTemp.value(gs.qsName); + c->bInheritACL = msg->inherit_acls(); + + for(int i=0;i<msg->groups_size(); ++i) { + const MumbleProto::ACL_ChanGroup &group = msg->groups(i); + g = new Group(c, u8(group.name())); + g->bInherit = group.inherit(); + g->bInheritable = group.inheritable(); + for(int j=0;j<group.add_size();++j) + g->qsAdd << group.add(j); + for(int j=0;j<group.remove_size();++j) + g->qsRemove << group.remove(j); + g->qsTemporary = hOldTemp.value(g->qsName); } - foreach(as, msg->acls) { + for(int i=0;i<msg->acls_size(); ++i) { + const MumbleProto::ACL_ChanACL &mpacl = msg->acls(i); a = new ChanACL(c); - a->bApplyHere=as.bApplyHere; - a->bApplySubs=as.bApplySubs; - a->iPlayerId=as.iPlayerId; - a->qsGroup=as.qsGroup; - a->pDeny=as.pDeny; - a->pAllow=as.pAllow; + a->bApplyHere=mpacl.apply_here(); + a->bApplySubs=mpacl.apply_subs(); + if (mpacl.has_user_id()) + a->iPlayerId=mpacl.user_id(); + else + a->qsGroup=u8(mpacl.group()); + a->pDeny=static_cast<ChanACL::Permissions>(mpacl.deny()); + a->pAllow=static_cast<ChanACL::Permissions>(mpacl.grant()); } clearACLCache(); @@ -864,111 +826,96 @@ void Server::msgEditACL(Connection *cCon, MessageEditACL *msg) { } } -void Server::msgQueryUsers(Connection *cCon, MessageQueryUsers *msg) { +void Server::msgQueryUsers(Connection *cCon, MumbleProto::QueryUsers *msg) { MSG_SETUP(Player::Authenticated); - int i; - for (i=0;i<msg->qlIds.count();i++) { - QString name = msg->qlNames[i]; - int id = msg->qlIds[i]; - if (id < 0) { - id = qhUserIDCache.value(name); + if (msg->ids_size()) { + msg->clear_names(); + for(int i=0;i<msg->ids_size();++i) { + int id = msg->ids(i); + if (! qhUserNameCache.contains(id)) { + QString name = getUserName(id); + if (! name.isEmpty()) + qhUserNameCache[id] = name; + } + msg->add_names(u8(qhUserNameCache.value(id))); + } + } else { + msg->clear_ids(); + for(int i=0;i<msg->names_size();++i) { + QString name = u8(msg->names(i)); + int id = qhUserIDCache.value(name); if (! qhUserIDCache.contains(name)) { id = getUserID(name); if (id >= 0) qhUserIDCache[name] = id; } - msg->qlIds[i] = (id >= 0) ? id : -1; - } else { - if (! qhUserNameCache.contains(id)) { - name = getUserName(id); - if (! name.isEmpty()) - qhUserNameCache[id] = name; - } - msg->qlNames[i] = qhUserNameCache.value(id); + msg->add_ids((id >= 0) ? id : -1); } } - // Check if session is alive. - if (! qhUsers.contains(msg->uiSession)) - return; - - sendMessage(cCon, msg); -} -void Server::msgPing(Connection *cCon, MessagePing *msg) { - MSG_SETUP(Player::Authenticated); - sendMessage(cCon, msg); + sendMessage(uSource, *msg, MessageHandler::QueryUsers); } -void Server::msgPingStats(Connection *cCon, MessagePingStats *msg) { +void Server::msgPing(Connection *cCon, MumbleProto::Ping *msg) { MSG_SETUP(Player::Authenticated); CryptState &cs=uSource->csCrypt; - cs.uiRemoteGood = msg->uiGood; - cs.uiRemoteLate = msg->uiLate; - cs.uiRemoteLost = msg->uiLost; - cs.uiRemoteResync = msg->uiResync; - - uSource->dUDPPingAvg = msg->dUDPPingAvg; - uSource->dUDPPingVar = msg->dUDPPingVar; - uSource->uiUDPPackets = msg->uiUDPPackets; - uSource->dTCPPingAvg = msg->dTCPPingAvg; - uSource->dTCPPingVar = msg->dTCPPingVar; - uSource->uiTCPPackets = msg->uiTCPPackets; - - msg->uiGood = cs.uiGood; - msg->uiLate = cs.uiLate; - msg->uiLost = cs.uiLost; - msg->uiResync = cs.uiResync; - - msg->dUDPPingAvg = msg->dUDPPingVar = msg->dTCPPingAvg = msg->dTCPPingVar = 0.0L; - msg->uiUDPPackets = msg->uiTCPPackets = 0; - sendMessage(cCon, msg); -} - -void Server::msgTexture(Connection *cCon, MessageTexture *msg) { - MSG_SETUP(Player::Authenticated); - if (! qhUserTextureCache.contains(msg->iPlayerId)) { - QByteArray qba = getUserTexture(msg->iPlayerId); - if (! qba.isEmpty()) { - // Check for uncompressed image - if (qba.size() == 600 * 60 * 4) - qba = qCompress(qba); - } - qhUserTextureCache.insert(msg->iPlayerId, qba); - } - - // Check if session is alive. - if (! qhUsers.contains(msg->uiSession)) - return; - msg->qbaTexture = qhUserTextureCache.value(msg->iPlayerId); - if (! msg->qbaTexture.isEmpty()) - sendMessage(cCon, msg); + cs.uiRemoteGood = msg->good(); + cs.uiRemoteLate = msg->late(); + cs.uiRemoteLost = msg->lost(); + cs.uiRemoteResync = msg->resync(); + + uSource->dUDPPingAvg = msg->udp_ping_avg(); + uSource->dUDPPingVar = msg->udp_ping_var(); + uSource->uiUDPPackets = msg->udp_packets(); + uSource->dTCPPingAvg = msg->tcp_ping_avg(); + uSource->dTCPPingVar = msg->tcp_ping_var(); + uSource->uiTCPPackets = msg->tcp_packets(); + + quint64 ts = msg->timestamp(); + + msg->Clear(); + msg->set_timestamp(ts); + msg->set_good(cs.uiGood); + msg->set_late(cs.uiLate); + msg->set_lost(cs.uiLost); + msg->set_resync(cs.uiResync); + + sendMessage(uSource, *msg, MessageHandler::Ping); } -void Server::msgCryptSync(Connection *cCon, MessageCryptSync *msg) { +void Server::msgCryptSetup(Connection *cCon, MumbleProto::CryptSetup *msg) { MSG_SETUP(Player::Authenticated); - if (msg->qbaNonce.isEmpty()) { + if (! msg->has_client_nonce()) { log(uSource, "Requested crypt-nonce resync"); - msg->qbaNonce = QByteArray(reinterpret_cast<const char *>(uSource->csCrypt.encrypt_iv), AES_BLOCK_SIZE); - sendMessage(cCon, msg); - } else if (msg->qbaNonce.size() == AES_BLOCK_SIZE) { - uSource->csCrypt.uiResync++; - memcpy(uSource->csCrypt.decrypt_iv, msg->qbaNonce.constData(), AES_BLOCK_SIZE); + msg->set_server_nonce(std::string(reinterpret_cast<const char *>(uSource->csCrypt.encrypt_iv), AES_BLOCK_SIZE)); + sendMessage(uSource, *msg, MessageHandler::CryptSetup); } else { - cCon->disconnectSocket(); + const std::string &str = msg->client_nonce(); + if (str.size() == AES_BLOCK_SIZE) { + uSource->csCrypt.uiResync++; + memcpy(uSource->csCrypt.decrypt_iv, str.data(), AES_BLOCK_SIZE); + } } } -void Server::msgContextAddAction(Connection *cCon, MessageContextAddAction *) { - cCon->disconnectSocket(); +void Server::msgContextActionAdd(Connection *, MumbleProto::ContextActionAdd *) { } -void Server::msgContextAction(Connection *cCon, MessageContextAction *msg) { +void Server::msgContextAction(Connection *cCon, MumbleProto::ContextAction *msg) { MSG_SETUP(Player::Authenticated); - if ((msg->uiVictim > 0) && ! qhUsers.contains(msg->uiVictim)) + + unsigned int session = msg->has_session() ? msg->session() : 0; + int id = msg->has_channel_id() ? static_cast<int>(msg->channel_id()) : -1; + + if (session && ! qhUsers.contains(session)) return; - if ((msg->iChannel >= 0) && ! qhChannels.contains(msg->iChannel)) + if ((id >= 0) && ! qhChannels.contains(id)) return; - emit contextAction(uSource, msg->qsAction, msg->uiVictim, msg->iChannel); + emit contextAction(uSource, u8(msg->action()), session, id); +} + +void Server::msgVersion(Connection *, MumbleProto::Version *) { } + diff --git a/src/murmur/RPC.cpp b/src/murmur/RPC.cpp index 7c008eaec..0de7cb06d 100644 --- a/src/murmur/RPC.cpp +++ b/src/murmur/RPC.cpp @@ -36,58 +36,45 @@ #include "Version.h" void Server::setPlayerState(Player *pPlayer, Channel *cChannel, bool mute, bool deaf, bool suppressed) { - bool changed = false; + // FIXME: What if nothing changed? Then don't emit and don't sendAll. if (deaf) mute = true; if (! mute) deaf = false; - - if ((pPlayer->bDeaf != deaf) && (deaf || (!deaf && mute))) { - pPlayer->bDeaf = deaf; - pPlayer->bMute = mute; - MessagePlayerDeaf mpd; - mpd.uiSession = 0; - mpd.uiVictim=pPlayer->uiSession; - mpd.bDeaf = deaf; - sendAll(&mpd); - changed = true; - } else if ((pPlayer->bDeaf != deaf) || (pPlayer->bMute != mute)) { - pPlayer->bDeaf = deaf; - pPlayer->bMute = mute; - - MessagePlayerMute mpm; - mpm.uiSession = 0; - mpm.uiVictim=pPlayer->uiSession; - mpm.bMute=mute; - sendAll(&mpm); - changed = true; - } - + + MumbleProto::UserState mpus; + mpus.set_session(pPlayer->uiSession); + if (mute != pPlayer->bMute) + mpus.set_mute(mute); + if (deaf != pPlayer->bDeaf) + mpus.set_deaf(deaf); + if (suppressed != pPlayer->bSuppressed) + mpus.set_suppressed(suppressed); + + pPlayer->bDeaf = deaf; + pPlayer->bMute = mute; + pPlayer->bSuppressed = suppressed; + if (cChannel != pPlayer->cChannel) { + mpus.set_channel_id(cChannel->iId); playerEnterChannel(pPlayer, cChannel); - MessagePlayerMove mpm; - mpm.uiSession = 0; - mpm.uiVictim = pPlayer->uiSession; - mpm.iChannelId = cChannel->iId; - sendAll(&mpm); - changed = true; } - + + sendAll(mpus, MessageHandler::UserState); emit playerStateChanged(pPlayer); } bool Server::setChannelState(Channel *cChannel, Channel *cParent, const QString &qsName, const QSet<Channel *> &links) { bool changed = false; bool updated = false; - + + MumbleProto::ChannelState mpcs; + mpcs.set_channel_id(cChannel->iId); + if (cChannel->qsName != qsName) { cChannel->qsName = qsName; - MessageChannelRename mcr; - mcr.uiSession = 0; - mcr.iId = cChannel->iId; - mcr.qsName = cChannel->qsName; - sendAll(&mcr); + mpcs.set_name(u8(qsName)); updated = true; changed = true; } @@ -102,12 +89,8 @@ bool Server::setChannelState(Channel *cChannel, Channel *cParent, const QString cChannel->cParent->removeChannel(cChannel); cParent->addChannel(cChannel); - - MessageChannelMove mcm; - mcm.uiSession = 0; - mcm.iId = cChannel->iId; - mcm.iParent = cParent->iId; - sendAll(&mcm); + + mpcs.set_parent(cParent->iId); updated = true; changed = true; @@ -120,13 +103,7 @@ bool Server::setChannelState(Channel *cChannel, Channel *cParent, const QString foreach(Channel *l, links) { if (! links.contains(l)) { removeLink(cChannel, l); - - MessageChannelLink mcl; - mcl.uiSession = 0; - mcl.iId = cChannel->iId; - mcl.qlTargets << l->iId; - mcl.ltType = MessageChannelLink::Unlink; - sendAll(&mcl); + mpcs.add_links_remove(l->iId); } } @@ -134,13 +111,7 @@ bool Server::setChannelState(Channel *cChannel, Channel *cParent, const QString foreach(Channel *l, links) { if (! oldset.contains(l)) { addLink(cChannel, l); - - MessageChannelLink mcl; - mcl.uiSession = 0; - mcl.iId = cChannel->iId; - mcl.qlTargets << l->iId; - mcl.ltType = MessageChannelLink::Link; - sendAll(&mcl); + mpcs.add_links_add(l->iId); } } @@ -149,25 +120,26 @@ bool Server::setChannelState(Channel *cChannel, Channel *cParent, const QString if (updated) updateChannel(cChannel); - if (changed) + if (changed) { + sendAll(mpcs, MessageHandler::ChannelState); emit channelStateChanged(cChannel); + } return true; } void Server::sendTextMessage(Channel *cChannel, User *pPlayer, bool tree, const QString &text) { - MessageTextMessage mtm; - mtm.uiSession = 0; - mtm.qsMessage = text; + MumbleProto::TextMessage mptm; + mptm.set_message(u8(text)); + if (pPlayer) { - mtm.uiVictim = pPlayer->uiSession; - mtm.iChannel = -1; - mtm.bTree = false; - sendMessage(pPlayer, &mtm); + mptm.add_session(pPlayer->uiSession); + sendMessage(pPlayer, mptm, MessageHandler::TextMessage); } else { - mtm.uiVictim = 0; - mtm.iChannel = cChannel->iId; - mtm.bTree = tree; + if (tree) + mptm.add_tree_id(cChannel->iId); + else + mptm.add_channel_id(cChannel->iId); QSet<Channel *> chans; QQueue<Channel *> q; @@ -185,7 +157,7 @@ void Server::sendTextMessage(Channel *cChannel, User *pPlayer, bool tree, const } foreach(c, chans) { foreach(Player *p, c->qlPlayers) - sendMessage(static_cast<User *>(p), &mtm); + sendMessage(static_cast<User *>(p), mptm, MessageHandler::TextMessage); } } } diff --git a/src/murmur/Server.cpp b/src/murmur/Server.cpp index e5c5b5cb6..b7a1c357e 100644 --- a/src/murmur/Server.cpp +++ b/src/murmur/Server.cpp @@ -39,7 +39,6 @@ #include "Connection.h" #include "Server.h" #include "DBus.h" -#include "PacketDataStream.h" #include "Meta.h" uint qHash(const Peer &p) { @@ -327,9 +326,6 @@ void Server::run() { #endif char buffer[512]; - quint32 msgType = 0; - unsigned int uiSession = 0; - sockaddr_in from; #ifdef Q_OS_UNIX socklen_t fromlen; @@ -372,7 +368,7 @@ void Server::run() { break; } else if (len == SOCKET_ERROR) { break; - } else if (len < 6) { + } else if (len < 5) { // 4 bytes crypt header + type + session continue; } else if (len > 512) { @@ -382,80 +378,51 @@ void Server::run() { QReadLocker rl(&qrwlUsers); quint64 key = (static_cast<unsigned long long>(from.sin_addr.s_addr) << 16) ^ from.sin_port; - PacketDataStream pds(buffer, len - 4); User *u = qhPeerUsers.value(key); if (u) { if (! checkDecrypt(u, encrypted, buffer, len)) { continue; } - pds >> msgType >> uiSession; - if (u->uiSession != uiSession) { - continue; - } } else { // Unknown peer foreach(User *usr, qhHostUsers.value(from.sin_addr.s_addr)) { - pds.rewind(); if (usr->csCrypt.isValid() && checkDecrypt(usr, encrypted, buffer, len)) { - pds >> msgType >> uiSession; - if (usr->uiSession == uiSession) { - // Every time we relock, reverify users' existance. - // The main thread might delete the user while the lock isn't held. - rl.unlock(); - qrwlUsers.lockForWrite(); - if (qhUsers.contains(uiSession)) { - u = usr; - qhHostUsers[from.sin_addr.s_addr].remove(u); - qhPeerUsers.insert(key, u); - u->saiUdpAddress.sin_port = from.sin_port; - qrwlUsers.unlock(); - rl.relock(); - if (! qhUsers.contains(uiSession)) - u = NULL; - } + // Every time we relock, reverify users' existance. + // The main thread might delete the user while the lock isn't held. + unsigned int uiSession = usr->uiSession; + rl.unlock(); + qrwlUsers.lockForWrite(); + if (qhUsers.contains(uiSession)) { + u = usr; + qhHostUsers[from.sin_addr.s_addr].remove(u); + qhPeerUsers.insert(key, u); + u->saiUdpAddress.sin_port = from.sin_port; + qrwlUsers.unlock(); + rl.relock(); + if (! qhUsers.contains(uiSession)) + u = NULL; } - + break; } } if (! u) { continue; } - len -= 4; } + len -= 4; - if ((msgType != Message::Speex) && (msgType != Message::Ping)) - continue; - if (! pds.isValid()) - continue; - - if (msgType == Message::Ping) { + unsigned int msgType = (buffer[0] >> 5) & 0x7; + + if (msgType == MessageHandler::UDPPing) { QByteArray qba; sendMessage(u, buffer, len, qba); - } else { - processMsg(pds, qhUsers.value(uiSession)); + } else if (msgType == MessageHandler::UDPVoice) { + processMsg(u, buffer, len); } } } -void Server::fakeUdpPacket(Message *msg, Connection *source) { - char buffer[512]; - PacketDataStream pds(buffer, 512); - msg->messageToNetwork(pds); - if (! pds.isValid()) - return; - - pds.rewind(); - - quint32 msgType; - int uiSession; - - pds >> msgType >> uiSession; - - QReadLocker rl(&qrwlUsers); - processMsg(pds, source); -} - bool Server::checkDecrypt(User *u, const char *encrypted, char *plain, unsigned int len) { if (u->csCrypt.isValid() && u->csCrypt.decrypt(reinterpret_cast<const unsigned char *>(encrypted), reinterpret_cast<unsigned char *>(plain), len)) return true; @@ -497,24 +464,16 @@ void Server::sendMessage(User *u, const char *data, int len, QByteArray &cache) } } -void Server::processMsg(PacketDataStream &pds, Connection *cCon) { - User *u = static_cast<User *>(cCon); - if (! u || (u->sState != Player::Authenticated)) +void Server::processMsg(User *u, const char *data, int len) { + if (u->sState != Player::Authenticated || u->bMute || u->bSuppressed) return; Player *p; - int seq, flags; - - if (u->bMute || u->bSuppressed) - return; BandwidthRecord *bw = & u->bwr; - pds >> seq; - pds >> flags; - // IP + UDP + Crypt + Data - int packetsize = 20 + 8 + 4 + pds.capacity(); + int packetsize = 20 + 8 + 4 + len; bw->addFrame(packetsize); if (bw->bytesPerSec() > iMaxBandwidth) { @@ -526,11 +485,9 @@ void Server::processMsg(PacketDataStream &pds, Connection *cCon) { QByteArray qba; - pds.rewind(); - const char *data = pds.charPtr(); - int len = pds.left(); + unsigned int target = data[0] & 0x1f; - if (flags & MessageSpeex::LoopBack) { + if (target == 0x1f) { sendMessage(u, data, len, qba); return; } @@ -547,7 +504,7 @@ void Server::processMsg(PacketDataStream &pds, Connection *cCon) { QMutexLocker qml(&qmCache); foreach(Channel *l, chans) { - if (ChanACL::hasPermission(u, l, (flags & MessageSpeex::AltSpeak) ? ChanACL::AltSpeak : ChanACL::Speak, acCache)) { + if (ChanACL::hasPermission(u, l, (target == 1) ? ChanACL::AltSpeak : ChanACL::Speak, acCache)) { foreach(p, l->qlPlayers) { if (! p->bDeaf && ! p->bSelfDeaf) sendMessage(static_cast<User *>(p), data, len, qba); @@ -658,9 +615,9 @@ void Server::connectionClosed(QString reason) { log(u, QString("Connection closed: %1").arg(reason)); if (u->sState == Player::Authenticated) { - MessageServerLeave mslMsg; - mslMsg.uiSession=u->uiSession; - sendExcept(&mslMsg, c); + MumbleProto::UserRemove mpur; + mpur.set_session(u->uiSession); + sendExcept(u, mpur, MessageHandler::UserRemove); emit playerDisconnected(u); } @@ -689,21 +646,13 @@ void Server::connectionClosed(QString reason) { stopThread(); } -void Server::message(QByteArray &qbaMsg, Connection *cCon) { +void Server::message(const QByteArray &qbaMsg, unsigned int msgType, Connection *cCon) { if (cCon == NULL) { cCon = static_cast<Connection *>(sender()); } - Message *mMsg = Message::networkToMessage(qbaMsg); - - if (mMsg) { - dispatch(cCon, mMsg); - delete mMsg; - } else { - cCon->disconnectSocket(); - } + dispatch(cCon, msgType, qbaMsg); } - void Server::checkTimeout() { QList<User *> qlClose; @@ -731,23 +680,25 @@ void Server::doSync(unsigned int id) { User *u = qhUsers.value(id); if (u) { log(u, "Requesting crypt-nonce resync"); - MessageCryptSync mcs; - u->sendMessage(&mcs); + MumbleProto::CryptSetup mpcs; + sendMessage(u, mpcs, MessageHandler::CryptSetup); } } -void Server::sendMessage(Connection *c, Message *mMsg) { - c->sendMessage(mMsg); +void Server::sendMessage(User *u, const ::google::protobuf::Message &msg, unsigned int msgType) { + QByteArray cache; + u->sendMessage(msg, msgType, cache); } -void Server::sendAll(Message *mMsg) { - sendExcept(mMsg, NULL); +void Server::sendAll(const ::google::protobuf::Message &msg, unsigned int msgType) { + sendExcept(NULL, msg, msgType); } -void Server::sendExcept(Message *mMsg, Connection *cCon) { - foreach(User *u, qhUsers) - if ((static_cast<Connection *>(u) != cCon) && (u->sState == Player::Authenticated)) - u->sendMessage(mMsg); +void Server::sendExcept(User *u, const ::google::protobuf::Message &msg, unsigned int msgType) { + QByteArray cache; + foreach(User *usr, qhUsers) + if ((usr != u) && (usr->sState == Player::Authenticated)) + usr->sendMessage(msg, msgType, cache); } void Server::sendChannelDescription(Player *p, const Channel *c) { @@ -783,20 +734,18 @@ void Server::removeChannel(Channel *chan, Player *src, Channel *dest) { foreach(p, chan->qlPlayers) { chan->removePlayer(p); - - MessagePlayerMove mpm; - mpm.uiSession = 0; - mpm.uiVictim = p->uiSession; - mpm.iChannelId = dest->iId; - sendAll(&mpm); + + MumbleProto::UserState mpus; + mpus.set_session(p->uiSession); + mpus.set_channel_id(dest->iId); + sendAll(mpus, MessageHandler::UserState); playerEnterChannel(p, dest); } - - MessageChannelRemove mcr; - mcr.uiSession = src ? src->uiSession : 0; - mcr.iId = chan->iId; - sendAll(&mcr); + + MumbleProto::ChannelRemove mpcr; + mpcr.set_channel_id(chan->iId); + sendAll(mpcr, MessageHandler::ChannelRemove); removeChannel(chan); emit channelRemoved(chan); @@ -851,11 +800,10 @@ void Server::playerEnterChannel(Player *p, Channel *c, bool quiet) { // Ok, he can speak and was suppressed, or vice versa p->bSuppressed = ! mayspeak; - MessagePlayerMute mpm; - mpm.uiSession = 0; - mpm.uiVictim = p->uiSession; - mpm.bMute = p->bSuppressed; - sendAll(&mpm); + MumbleProto::UserState mpus; + mpus.set_session(p->uiSession); + mpus.set_suppressed(p->bSuppressed); + sendAll(mpus, MessageHandler::UserState); } } emit playerStateChanged(p); diff --git a/src/murmur/Server.h b/src/murmur/Server.h index a4f4def95..2a210ea7c 100644 --- a/src/murmur/Server.h +++ b/src/murmur/Server.h @@ -36,6 +36,7 @@ #include "Timer.h" #include "Player.h" #include "Connection.h" +#include "ACL.h" #include "DBus.h" class Channel; @@ -157,7 +158,7 @@ class Server : public QThread, public MessageHandler { void newClient(); void connectionClosed(QString); void sslError(const QList<QSslError> &); - void message(QByteArray &, Connection *cCon = NULL); + void message(const QByteArray &, unsigned int, Connection *cCon = NULL); void checkTimeout(); void tcpTransmitData(QByteArray, unsigned int); void doSync(unsigned int); @@ -189,9 +190,8 @@ class Server : public QThread, public MessageHandler { QList<QPair<quint32, int> > qlBans; - void processMsg(PacketDataStream &pds, Connection *cCon); + void processMsg(User *u, const char *data, int len); void sendMessage(User *u, const char *data, int len, QByteArray &cache); - void fakeUdpPacket(Message *msg, Connection *source); void run(); bool validateChannelName(const QString &name); @@ -202,9 +202,10 @@ class Server : public QThread, public MessageHandler { bool hasPermission(Player *p, Channel *c, ChanACL::Perm perm); void clearACLCache(Player *p = NULL); - void sendAll(Message *); - void sendExcept(Message *, Connection *); - void sendMessage(Connection *, Message *); + void sendAll(const ::google::protobuf::Message &msg, unsigned int msgType); + void sendExcept(User *, const ::google::protobuf::Message &msg, unsigned int msgType); + void sendMessage(User *, const ::google::protobuf::Message &msg, unsigned int msgType); + void sendChannelDescription(Player *, const Channel *); void sendChannelDescriptionUpdate(const Channel *changed, const Channel *current=NULL); @@ -288,37 +289,24 @@ class Server : public QThread, public MessageHandler { void dblog(const QString &str); // From msgHandler. Implementation in Messages.cpp - virtual void msgSpeex(Connection *, MessageSpeex *); - virtual void msgServerAuthenticate(Connection *, MessageServerAuthenticate *); - virtual void msgPing(Connection *, MessagePing *); - virtual void msgPingStats(Connection *, MessagePingStats *); - virtual void msgServerReject(Connection *, MessageServerReject *); - virtual void msgServerSync(Connection *, MessageServerSync *); - virtual void msgServerJoin(Connection *, MessageServerJoin *); - virtual void msgServerLeave(Connection *, MessageServerLeave *); - virtual void msgPlayerMute(Connection *, MessagePlayerMute *); - virtual void msgPlayerDeaf(Connection *, MessagePlayerDeaf *); - virtual void msgPlayerSelfMuteDeaf(Connection *, MessagePlayerSelfMuteDeaf *); - virtual void msgPlayerKick(Connection *, MessagePlayerKick *); - virtual void msgPlayerBan(Connection *, MessagePlayerBan *); - virtual void msgPlayerMove(Connection *, MessagePlayerMove *); - virtual void msgPlayerRename(Connection *, MessagePlayerRename *); - virtual void msgChannelAdd(Connection *, MessageChannelAdd *); - virtual void msgChannelRemove(Connection *, MessageChannelRemove *); - virtual void msgChannelMove(Connection *, MessageChannelMove *); - virtual void msgChannelLink(Connection *, MessageChannelLink *); - virtual void msgChannelRename(Connection *, MessageChannelRename *); - virtual void msgChannelDescUpdate(Connection *, MessageChannelDescUpdate *); - virtual void msgServerBanList(Connection *, MessageServerBanList *); - virtual void msgTextMessage(Connection *, MessageTextMessage *); - virtual void msgPermissionDenied(Connection *, MessagePermissionDenied *); - virtual void msgEditACL(Connection *, MessageEditACL *); - virtual void msgQueryUsers(Connection *, MessageQueryUsers *); - virtual void msgTexture(Connection *, MessageTexture *); - virtual void msgCryptSetup(Connection *, MessageCryptSetup *); - virtual void msgCryptSync(Connection *, MessageCryptSync *); - virtual void msgContextAddAction(Connection *, MessageContextAddAction *); - virtual void msgContextAction(Connection *, MessageContextAction *); + virtual void msgVersion(Connection *, MumbleProto::Version *); + virtual void msgUDPTunnel(Connection *, MumbleProto::UDPTunnel *); + virtual void msgAuthenticate(Connection *, MumbleProto::Authenticate *); + virtual void msgPing(Connection *, MumbleProto::Ping *); + virtual void msgReject(Connection *, MumbleProto::Reject *); + virtual void msgServerSync(Connection *, MumbleProto::ServerSync *); + virtual void msgChannelRemove(Connection *, MumbleProto::ChannelRemove *); + virtual void msgChannelState(Connection *, MumbleProto::ChannelState *); + virtual void msgUserRemove(Connection *, MumbleProto::UserRemove *); + virtual void msgUserState(Connection *, MumbleProto::UserState *); + virtual void msgBanList(Connection *, MumbleProto::BanList *); + virtual void msgTextMessage(Connection *, MumbleProto::TextMessage *); + virtual void msgPermissionDenied(Connection *, MumbleProto::PermissionDenied *); + virtual void msgACL(Connection *, MumbleProto::ACL *); + virtual void msgQueryUsers(Connection *, MumbleProto::QueryUsers *); + virtual void msgCryptSetup(Connection *, MumbleProto::CryptSetup *); + virtual void msgContextActionAdd(Connection *, MumbleProto::ContextActionAdd *); + virtual void msgContextAction(Connection *, MumbleProto::ContextAction *); }; diff --git a/src/murmur/ServerDB.cpp b/src/murmur/ServerDB.cpp index 3ccf84571..7e9fea792 100644 --- a/src/murmur/ServerDB.cpp +++ b/src/murmur/ServerDB.cpp @@ -844,6 +844,9 @@ QByteArray Server::getUserTexture(int id) { SQLEXEC(); if (query.next()) { qba = query.value(0).toByteArray(); + if (! qba.isEmpty()) + if (qba.size() == 600 * 60 * 4) + qba = qCompress(qba); } return qba; } |