diff options
author | Thorvald Natvig <slicer@users.sourceforge.net> | 2007-07-31 19:51:34 +0400 |
---|---|---|
committer | Thorvald Natvig <slicer@users.sourceforge.net> | 2007-07-31 19:51:34 +0400 |
commit | 6d6bcff7c7e76b175786bbf245917c1854ee0cf6 (patch) | |
tree | 643f7f9e14080c1a2baa07d4d8f64fbc1b9a9c85 /src | |
parent | 93f186081a806c2472f5b025d122d575b7386899 (diff) |
Global-less server. First step of multiserver support. Completely breaks client
git-svn-id: https://mumble.svn.sourceforge.net/svnroot/mumble/trunk@664 05730e5d-ab1b-0410-a4ac-84af385074fa
Diffstat (limited to 'src')
-rw-r--r-- | src/Channel.cpp | 4 | ||||
-rw-r--r-- | src/Connection.cpp | 2 | ||||
-rw-r--r-- | src/Connection.h | 2 | ||||
-rw-r--r-- | src/Message.cpp | 79 | ||||
-rw-r--r-- | src/Message.h | 82 | ||||
-rw-r--r-- | src/Player.cpp | 37 | ||||
-rw-r--r-- | src/Player.h | 23 | ||||
-rw-r--r-- | src/mumble/GlobalShortcut_win.cpp | 2 | ||||
-rw-r--r-- | src/murmur/DBus.cpp | 74 | ||||
-rw-r--r-- | src/murmur/DBus_real.h | 4 | ||||
-rw-r--r-- | src/murmur/Messages.cpp | 813 | ||||
-rw-r--r-- | src/murmur/Server.cpp | 947 | ||||
-rw-r--r-- | src/murmur/Server.h | 115 | ||||
-rw-r--r-- | src/murmur/ServerDB.cpp | 40 | ||||
-rw-r--r-- | src/murmur/ServerDB.h | 23 | ||||
-rw-r--r-- | src/murmur/Tray.cpp | 3 | ||||
-rw-r--r-- | src/murmur/murmur.cpp | 17 | ||||
-rw-r--r-- | src/murmur/murmur.pro | 2 |
18 files changed, 1232 insertions, 1037 deletions
diff --git a/src/Channel.cpp b/src/Channel.cpp index 8af592b78..20feece87 100644 --- a/src/Channel.cpp +++ b/src/Channel.cpp @@ -178,7 +178,9 @@ void Channel::removeChannel(Channel *c) { void Channel::addPlayer(Player *p) { if (p->cChannel) p->cChannel->removePlayer(p); - p->setParent(this); + ClientPlayer *cp = dynamic_cast<ClientPlayer *>(p); + if (cp) + cp->setParent(this); p->cChannel = this; qlPlayers << p; } diff --git a/src/Connection.cpp b/src/Connection.cpp index 01f9bd294..f77f90b29 100644 --- a/src/Connection.cpp +++ b/src/Connection.cpp @@ -168,7 +168,7 @@ void Connection::forceFlush() { setsockopt(qtsSocket->socketDescriptor(), IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char *>(&nodelay), sizeof(nodelay)); } -void Connection::disconnect() { +void Connection::disconnectSocket() { qtsSocket->disconnectFromHost(); } diff --git a/src/Connection.h b/src/Connection.h index 01588b51e..81bffd799 100644 --- a/src/Connection.h +++ b/src/Connection.h @@ -58,7 +58,7 @@ class Connection : public QObject { ~Connection(); void sendMessage(const Message *mMsg); void sendMessage(const QByteArray &qbaMsg); - void disconnect(); + void disconnectSocket(); void forceFlush(); int activityTime() const; diff --git a/src/Message.cpp b/src/Message.cpp index e290b70e0..08a95d08f 100644 --- a/src/Message.cpp +++ b/src/Message.cpp @@ -163,6 +163,85 @@ Message *Message::networkToMessage(PacketDataStream &qdsIn) { 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::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::PlayerTexture: + msgTexture(cCon, static_cast<MessageTexture *>(msg)); + break; + default: + qFatal("MessageHandler called with unknown message type %d", msg->messageType()); + } +} + bool Message::isValid() const { return true; } diff --git a/src/Message.h b/src/Message.h index 6e79ccc70..d7cb6ad2f 100644 --- a/src/Message.h +++ b/src/Message.h @@ -49,7 +49,7 @@ class Message { Message(); virtual ~Message(); virtual Message::MessageType messageType() const = 0; - virtual void process(Connection *) = 0; +// virtual void process(Connection *) = 0; virtual bool isValid() const; void messageToNetwork(QByteArray &) const; @@ -70,7 +70,7 @@ class MessageSpeex : public Message { Message::MessageType messageType() const { return Speex; }; - void process(Connection *); + //void process(Connection *); bool isValid() const; }; @@ -87,7 +87,7 @@ class MessageServerAuthenticate : public Message { Message::MessageType messageType() const { return ServerAuthenticate; }; - void process(Connection *); + //void process(Connection *); }; class MessagePing : public Message { @@ -99,7 +99,7 @@ class MessagePing : public Message { Message::MessageType messageType() const { return Ping; }; - void process(Connection *); + //void process(Connection *); }; class MessageServerReject : public Message { @@ -113,7 +113,7 @@ class MessageServerReject : public Message { Message::MessageType messageType() const { return ServerReject; }; - void process(Connection *); + //void process(Connection *); }; class MessageServerSync : public Message { @@ -126,7 +126,7 @@ class MessageServerSync : public Message { Message::MessageType messageType() const { return ServerSync; }; - void process(Connection *); + //void process(Connection *); }; class MessageServerJoin : public Message { @@ -139,7 +139,7 @@ class MessageServerJoin : public Message { Message::MessageType messageType() const { return ServerJoin; }; - void process(Connection *); + //void process(Connection *); }; class MessageServerLeave : public Message { @@ -147,7 +147,7 @@ class MessageServerLeave : public Message { Message::MessageType messageType() const { return ServerLeave; }; - void process(Connection *); + //void process(Connection *); }; class MessagePlayerMute : public Message { @@ -160,7 +160,7 @@ class MessagePlayerMute : public Message { Message::MessageType messageType() const { return PlayerMute; }; - void process(Connection *); + //void process(Connection *); }; class MessagePlayerDeaf : public Message { @@ -173,7 +173,7 @@ class MessagePlayerDeaf : public Message { Message::MessageType messageType() const { return PlayerDeaf; }; - void process(Connection *); + //void process(Connection *); }; class MessagePlayerSelfMuteDeaf : public Message { @@ -186,7 +186,7 @@ class MessagePlayerSelfMuteDeaf : public Message { Message::MessageType messageType() const { return PlayerSelfMuteDeaf; }; - void process(Connection *); + //void process(Connection *); }; class MessagePlayerKick : public Message { @@ -199,7 +199,7 @@ class MessagePlayerKick : public Message { Message::MessageType messageType() const { return PlayerKick; }; - void process(Connection *); + //void process(Connection *); }; class MessagePlayerBan : public Message { @@ -212,7 +212,7 @@ class MessagePlayerBan : public Message { Message::MessageType messageType() const { return PlayerBan; }; - void process(Connection *); + //void process(Connection *); }; class MessagePlayerMove : public Message { @@ -225,7 +225,7 @@ class MessagePlayerMove : public Message { Message::MessageType messageType() const { return PlayerMove; }; - void process(Connection *); + //void process(Connection *); }; class MessagePlayerRename : public Message { @@ -237,7 +237,7 @@ class MessagePlayerRename : public Message { Message::MessageType messageType() const { return PlayerRename; }; - void process(Connection *); + //void process(Connection *); }; class MessageChannelAdd : public Message { @@ -251,7 +251,7 @@ class MessageChannelAdd : public Message { Message::MessageType messageType() const { return ChannelAdd; }; - void process(Connection *); + //void process(Connection *); }; class MessageChannelRemove : public Message { @@ -263,7 +263,7 @@ class MessageChannelRemove : public Message { Message::MessageType messageType() const { return ChannelRemove; }; - void process(Connection *); + //void process(Connection *); }; class MessageChannelMove : public Message { @@ -276,7 +276,7 @@ class MessageChannelMove : public Message { Message::MessageType messageType() const { return ChannelMove; }; - void process(Connection *); + //void process(Connection *); }; class MessageChannelLink : public Message { @@ -293,7 +293,7 @@ class MessageChannelLink : public Message { Message::MessageType messageType() const { return ChannelLink; }; - void process(Connection *); + //void process(Connection *); }; class MessageServerBanList : public Message { @@ -306,7 +306,7 @@ class MessageServerBanList : public Message { Message::MessageType messageType() const { return ServerBanList; }; - void process(Connection *); + //void process(Connection *); }; class MessageTextMessage : public Message { @@ -319,7 +319,7 @@ class MessageTextMessage : public Message { Message::MessageType messageType() const { return TextMessage; }; - void process(Connection *); + //void process(Connection *); }; class MessagePermissionDenied : public Message { @@ -331,7 +331,7 @@ class MessagePermissionDenied : public Message { Message::MessageType messageType() const { return PermissionDenied; }; - void process(Connection *); + //void process(Connection *); }; class MessageEditACL : public Message { @@ -367,7 +367,7 @@ class MessageEditACL : public Message { Message::MessageType messageType() const { return EditACL; }; - void process(Connection *); + //void process(Connection *); }; PacketDataStream & operator<< (PacketDataStream & out, const MessageEditACL::GroupStruct &gs); @@ -385,7 +385,7 @@ class MessageQueryUsers : public Message { Message::MessageType messageType() const { return QueryUsers; }; - void process(Connection *); + //void process(Connection *); bool isValid() const; }; @@ -399,9 +399,41 @@ class MessageTexture : public Message { Message::MessageType messageType() const { return PlayerTexture; } - void process(Connection *); + //void process(Connection *); }; +class MessageHandler { + protected: + virtual void msgSpeex(Connection *, MessageSpeex *) = 0; + virtual void msgServerAuthenticate(Connection *, MessageServerAuthenticate *) = 0; + virtual void msgPing(Connection *, MessagePing *) = 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 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; + void dispatch(Connection *, Message *); + public: + virtual ~MessageHandler() { }; +}; + + #else class Message; #endif diff --git a/src/Player.cpp b/src/Player.cpp index a1f612bd1..0746d9824 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -31,11 +31,11 @@ #include "Player.h" #include "Channel.h" -QHash<unsigned int, Player *> Player::c_qmPlayers; -QReadWriteLock Player::c_qrwlPlayers; +QHash<unsigned int, ClientPlayer *> ClientPlayer::c_qmPlayers; +QReadWriteLock ClientPlayer::c_qrwlPlayers; -Player::Player(QObject *p) : QObject(p) { - sState = Player::Connected; +Player::Player() { + sState = ClientPlayer::Connected; uiSession = 0; iId = -1; bMute = bDeaf = false; @@ -46,25 +46,28 @@ Player::Player(QObject *p) : QObject(p) { cChannel = 0; } -Player *Player::get(unsigned int uiSession) { +ClientPlayer::ClientPlayer(QObject *p) : QObject(p) { +} + +ClientPlayer *ClientPlayer::get(unsigned int uiSession) { QReadLocker lock(&c_qrwlPlayers); - Player *p = c_qmPlayers.value(uiSession); + ClientPlayer *p = c_qmPlayers.value(uiSession); return p; } -Player *Player::add(unsigned int uiSession, QObject *po) { +ClientPlayer *ClientPlayer::add(unsigned int uiSession, QObject *po) { QWriteLocker lock(&c_qrwlPlayers); - Player *p = new Player(po); + ClientPlayer *p = new ClientPlayer(po); p->uiSession = uiSession; c_qmPlayers[uiSession] = p; return p; } -Player *Player::match(const Player *other, bool matchname) { +ClientPlayer *ClientPlayer::match(const ClientPlayer *other, bool matchname) { QReadLocker lock(&c_qrwlPlayers); - Player *p; + ClientPlayer *p; foreach(p, c_qmPlayers) { if (p == other) continue; @@ -76,18 +79,18 @@ Player *Player::match(const Player *other, bool matchname) { return NULL; } -void Player::remove(unsigned int uiSession) { +void ClientPlayer::remove(unsigned int uiSession) { QWriteLocker lock(&c_qrwlPlayers); Player *p = c_qmPlayers.take(uiSession); if (p && p->cChannel) p->cChannel->removePlayer(p); } -void Player::remove(Player *p) { +void ClientPlayer::remove(ClientPlayer *p) { remove(p->uiSession); } -void Player::setTalking(bool talking, bool altspeech) { +void ClientPlayer::setTalking(bool talking, bool altspeech) { if ((bTalking == talking) && (bAltSpeak == altspeech)) return; bTalking = talking; @@ -95,7 +98,7 @@ void Player::setTalking(bool talking, bool altspeech) { emit talkingChanged(bTalking); } -void Player::setMute(bool mute) { +void ClientPlayer::setMute(bool mute) { if (bMute == mute) return; bMute = mute; @@ -104,14 +107,14 @@ void Player::setMute(bool mute) { emit muteDeafChanged(); } -void Player::setLocalMute(bool mute) { +void ClientPlayer::setLocalMute(bool mute) { if (bLocalMute == mute) return; bLocalMute = mute; emit muteDeafChanged(); } -void Player::setDeaf(bool deaf) { +void ClientPlayer::setDeaf(bool deaf) { if (bDeaf == deaf) return; bDeaf = deaf; @@ -120,7 +123,7 @@ void Player::setDeaf(bool deaf) { emit muteDeafChanged(); } -void Player::setSelfMuteDeaf(bool mute, bool deaf) { +void ClientPlayer::setSelfMuteDeaf(bool mute, bool deaf) { bSelfDeaf = deaf; bSelfMute = mute; emit muteDeafChanged(); diff --git a/src/Player.h b/src/Player.h index 8f11c812c..fd55c8fce 100644 --- a/src/Player.h +++ b/src/Player.h @@ -35,8 +35,7 @@ class Channel; -class Player : public QObject { - Q_OBJECT +class Player { public: enum State { Connected, Authenticated }; State sState; @@ -49,15 +48,21 @@ class Player : public QObject { bool bTalking, bAltSpeak; Channel *cChannel; - static QHash<unsigned int, Player *> c_qmPlayers; - static QReadWriteLock c_qrwlPlayers; + Player(); + virtual ~Player() {}; +}; - Player(QObject *p = NULL); - static Player *get(unsigned int); - static Player *add(unsigned int, QObject *p = NULL); - static Player *match(const Player *p, bool matchname = false); +class ClientPlayer : public QObject, public Player { + Q_OBJECT + public: + ClientPlayer(QObject *p = NULL); + static QHash<unsigned int, ClientPlayer *> c_qmPlayers; + static QReadWriteLock c_qrwlPlayers; + static ClientPlayer *get(unsigned int); + static ClientPlayer *add(unsigned int, QObject *p = NULL); + static ClientPlayer *match(const ClientPlayer *p, bool matchname = false); static void remove(unsigned int); - static void remove(Player *); + static void remove(ClientPlayer *); public slots: void setTalking(bool talking, bool altspeech); void setMute(bool mute); diff --git a/src/mumble/GlobalShortcut_win.cpp b/src/mumble/GlobalShortcut_win.cpp index 47419caa8..d160c1a4d 100644 --- a/src/mumble/GlobalShortcut_win.cpp +++ b/src/mumble/GlobalShortcut_win.cpp @@ -154,7 +154,7 @@ GlobalShortcutWinConfig::GlobalShortcutWinConfig(QWidget *p) : ConfigWidget(p) { qhKeys[gs]=dikw; i++; } - + lab = new QLabel(tr("Double-click an entry to clear the shortcut.")); l->addWidget(lab,i+1,0,1,2); diff --git a/src/murmur/DBus.cpp b/src/murmur/DBus.cpp index 05380881c..423585935 100644 --- a/src/murmur/DBus.cpp +++ b/src/murmur/DBus.cpp @@ -138,7 +138,8 @@ void MurmurDBus::registerTypes() { qDBusRegisterMetaType<QList<BanInfo> >(); } -MurmurDBus::MurmurDBus(QCoreApplication &app) : QDBusAbstractAdaptor(&app), qdbc(QLatin1String("mainbus")) { +MurmurDBus::MurmurDBus(QCoreApplication &app, Server *srv) : QDBusAbstractAdaptor(&app), qdbc(QLatin1String("mainbus")) { + server = srv; } QString MurmurDBus::mapIdToName(int id) { @@ -223,7 +224,7 @@ int MurmurDBus::authenticate(QString &uname, const QString &pw) { } #define PLAYER_SETUP_VAR(var) \ - Player *pPlayer = Player::get(var); \ + User *pPlayer = server->qhUsers.value(var); \ if (! pPlayer) { \ QDBusConnection::sessionBus().send(msg.createErrorReply("net.sourceforge.mumble.Error.session", "Invalid session id")); \ return; \ @@ -242,8 +243,9 @@ int MurmurDBus::authenticate(QString &uname, const QString &pw) { void MurmurDBus::getPlayers(QList<PlayerInfoExtended> &a) { a.clear(); - foreach(Player *p, g_sServer->qmPlayers) { - a << PlayerInfoExtended(p); + foreach(Player *p, server->qhUsers) { + if (p->sState == Player::Authenticated) + a << PlayerInfoExtended(p); } } @@ -261,7 +263,7 @@ void MurmurDBus::getChannels(QList<ChannelInfo> &a) { void MurmurDBus::kickPlayer(unsigned int session, const QString &reason, const QDBusMessage &msg) { PLAYER_SETUP; - Connection *c = g_sServer->qmConnections.value(session); + Connection *c = server->qhUsers.value(session); if (!c) return; @@ -269,8 +271,8 @@ void MurmurDBus::kickPlayer(unsigned int session, const QString &reason, const Q mpk.uiSession = 0; mpk.uiVictim = session; mpk.qsReason=reason; - g_sServer->sendAll(&mpk); - c->disconnect(); + server->sendAll(&mpk); + c->disconnectSocket(); } void MurmurDBus::getPlayerState(unsigned int session, const QDBusMessage &msg, PlayerInfo &pi) { @@ -299,7 +301,7 @@ void MurmurDBus::setPlayerState(const PlayerInfo &npi, const QDBusMessage &msg) mpd.uiSession = 0; mpd.uiVictim=pPlayer->uiSession; mpd.bDeaf = deaf; - g_sServer->sendAll(&mpd); + server->sendAll(&mpd); changed = true; } else if ((pi.deaf != deaf) || (pi.mute != mute)) { pPlayer->bDeaf = deaf; @@ -309,17 +311,17 @@ void MurmurDBus::setPlayerState(const PlayerInfo &npi, const QDBusMessage &msg) mpm.uiSession = 0; mpm.uiVictim=pPlayer->uiSession; mpm.bMute=mute; - g_sServer->sendAll(&mpm); + server->sendAll(&mpm); changed = true; } if (cChannel->iId != pi.channel) { - g_sServer->playerEnterChannel(pPlayer, cChannel); + server->playerEnterChannel(pPlayer, cChannel); MessagePlayerMove mpm; mpm.uiSession = 0; mpm.uiVictim = pPlayer->uiSession; mpm.iChannelId = cChannel->iId; - g_sServer->sendAll(&mpm); + server->sendAll(&mpm); changed = true; } @@ -330,8 +332,8 @@ void MurmurDBus::setPlayerState(const PlayerInfo &npi, const QDBusMessage &msg) void MurmurDBus::addChannel(const QString &name, int chanparent, const QDBusMessage &msg, int &newid) { CHANNEL_SETUP_VAR(chanparent); - Channel *nc = ServerDB::addChannel(cChannel, name); - ServerDB::updateChannel(nc); + Channel *nc = server->addChannel(cChannel, name); + server->updateChannel(nc); newid = nc->iId; MessageChannelAdd mca; @@ -339,7 +341,7 @@ void MurmurDBus::addChannel(const QString &name, int chanparent, const QDBusMess mca.qsName = name; mca.iParent = chanparent; mca.iId = nc->iId; - g_sServer->sendAll(&mca); + server->sendAll(&mca); } void MurmurDBus::removeChannel(int id, const QDBusMessage &msg) { @@ -348,7 +350,7 @@ void MurmurDBus::removeChannel(int id, const QDBusMessage &msg) { QDBusConnection::sessionBus().send(msg.createErrorReply("net.sourceforge.mumble.Error.channel", "Invalid channel id")); return; } - g_sServer->removeChannel(cChannel, NULL); + server->removeChannel(cChannel, NULL); } void MurmurDBus::setChannelState(const ChannelInfo &nci, const QDBusMessage &msg) { @@ -378,13 +380,13 @@ void MurmurDBus::setChannelState(const ChannelInfo &nci, const QDBusMessage &msg cChannel->cParent->removeChannel(cChannel); cParent->addChannel(cChannel); - ServerDB::updateChannel(cChannel); + server->updateChannel(cChannel); MessageChannelMove mcm; mcm.uiSession = 0; mcm.iId = nci.id; mcm.iParent = nci.parent; - g_sServer->sendAll(&mcm); + server->sendAll(&mcm); changed = true; } @@ -396,28 +398,28 @@ void MurmurDBus::setChannelState(const ChannelInfo &nci, const QDBusMessage &msg foreach(Channel *l, oldset) { if (! newset.contains(l)) { - ServerDB::removeLink(cChannel, l); + server->removeLink(cChannel, l); MessageChannelLink mcl; mcl.uiSession = 0; mcl.iId = nci.id; mcl.qlTargets << l->iId; mcl.ltType = MessageChannelLink::Unlink; - g_sServer->sendAll(&mcl); + server->sendAll(&mcl); } } // Add foreach(Channel *l, newset) { if (! oldset.contains(l)) { - ServerDB::addLink(cChannel, l); + server->addLink(cChannel, l); MessageChannelLink mcl; mcl.uiSession = 0; mcl.iId = nci.id; mcl.qlTargets << l->iId; mcl.ltType = MessageChannelLink::Link; - g_sServer->sendAll(&mcl); + server->sendAll(&mcl); } } @@ -518,47 +520,47 @@ void MurmurDBus::setACL(int id, const QList<ACLInfo> &acls, const QList<GroupInf } ChanACL::clearCache(); - ServerDB::updateChannel(cChannel); + server->updateChannel(cChannel); } void MurmurDBus::getBans(QList<BanInfo> &bi) { bi.clear(); QPair<quint32,int> ban; - foreach(ban, g_sServer->qlBans) { + foreach(ban, server->qlBans) { bi << BanInfo(ban); } } void MurmurDBus::setBans(const QList<BanInfo> &bans, const QDBusMessage &) { - g_sServer->qlBans.clear(); + server->qlBans.clear(); foreach(BanInfo bi, bans) - g_sServer->qlBans << QPair<quint32,int>(bi.address,bi.bits); - ServerDB::setBans(g_sServer->qlBans); + server->qlBans << QPair<quint32,int>(bi.address,bi.bits); + server->setBans(server->qlBans); } void MurmurDBus::getPlayerNames(const QList<int> &ids, const QDBusMessage &, QList<QString> &names) { names.clear(); foreach(int id, ids) { - if (! g_sServer->qhUserNameCache.contains(id)) { - QString name=ServerDB::getUserName(id); + if (! server->qhUserNameCache.contains(id)) { + QString name=server->getUserName(id); if (! name.isEmpty()) { - g_sServer->qhUserNameCache[id]=name; + server->qhUserNameCache[id]=name; } } - names << g_sServer->qhUserNameCache.value(id); + names << server->qhUserNameCache.value(id); } } void MurmurDBus::getPlayerIds(const QList<QString> &names, const QDBusMessage &, QList<int> &ids) { ids.clear(); foreach(QString name, names) { - if (! g_sServer->qhUserIDCache.contains(name)) { - int id=ServerDB::getUserID(name); + if (! server->qhUserIDCache.contains(name)) { + int id=server->getUserID(name); if (id != -1) { - g_sServer->qhUserIDCache[name]=id; + server->qhUserIDCache[name]=id; } } - ids << g_sServer->qhUserIDCache.value(name); + ids << server->qhUserIDCache.value(name); } } @@ -601,8 +603,8 @@ PlayerInfoExtended::PlayerInfoExtended(Player *p) : PlayerInfo(p) { id = p->iId; name = p->qsName; - Connection *c = g_sServer->qmConnections[p->uiSession]; - BandwidthRecord *bw= g_sServer->qmBandwidth[c]; + User *u = static_cast<User *>(p); + BandwidthRecord *bw= & u->bwr; onlinesecs = bw->qtFirst.elapsed() / 1000000LL; bytespersec = 0; diff --git a/src/murmur/DBus_real.h b/src/murmur/DBus_real.h index 4d1838cb1..c76d4876a 100644 --- a/src/murmur/DBus_real.h +++ b/src/murmur/DBus_real.h @@ -37,6 +37,7 @@ #include "Channel.h" #include "Group.h" #include "ACL.h" +#include "Server.h" struct PlayerInfo { unsigned int session; @@ -104,12 +105,13 @@ class MurmurDBus : public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "net.sourceforge.mumble.Murmur"); protected: + Server *server; QString qsAuthService; QString qsAuthPath; public: QDBusConnection qdbc; - MurmurDBus(QCoreApplication &application); + MurmurDBus(QCoreApplication &application, Server *srv); void playerStateChanged(Player *p); void playerConnected(Player *p); diff --git a/src/murmur/Messages.cpp b/src/murmur/Messages.cpp new file mode 100644 index 000000000..3fd83d545 --- /dev/null +++ b/src/murmur/Messages.cpp @@ -0,0 +1,813 @@ +/* Copyright (C) 2005-2007, 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. +*/ + +#include "Player.h" +#include "Channel.h" +#include "ACL.h" +#include "Group.h" +#include "Message.h" +#include "ServerDB.h" +#include "Connection.h" +#include "Server.h" +#include "DBus.h" +#include "PacketDataStream.h" +#include "Cert.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); \ + 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(mpd.qsReason, cCon) +#define PERM_DENIED_TEXT(text) \ + mpd.qsReason = text; \ + sendMessage(cCon, &mpd) + + +void Server::msgServerAuthenticate(Connection *cCon, MessageServerAuthenticate *msg) { + MSG_SETUP(Player::Connected); + + Channel *c; + + uSource->qsName = msg->qsUsername; + + MessageServerReject msr; + bool ok = false; + + QRegExp re("[\\w\\[\\]\\{\\}\\(\\)\\@\\|]+"); + + bool nameok = re.exactMatch(msg->qsUsername); + if (nameok && msg->qsUsername[0] == '@') + nameok = false; + if (nameok && msg->qsUsername[0] == '#') + nameok = false; + + // 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; + + 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) { + msr.qsReason = "Invalid Username"; + msr.rtType = MessageServerReject::InvalidUsername; + } else if (id==-1) { + msr.qsReason = "Wrong password for user"; + msr.rtType = MessageServerReject::WrongUserPW; + } else if (id==-2 && ! g_sp.qsPassword.isEmpty() && g_sp.qsPassword != msg->qsPassword) { + msr.qsReason = "Invalid server password"; + msr.rtType = MessageServerReject::WrongServerPW; + } else { + ok = true; + } + + User *uOld = NULL; + foreach(User *u, qhUsers) { + if (u == uSource) + continue; + if (((u->iId>=0) && (u->iId == uSource->iId)) || + (u->qsName == uSource->qsName)) { + uOld = u; + break; + } + } + + // 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; + ok = false; + } + } + + if (msg->iMaxBandwidth > g_sp.iMaxBandwidth) { + msr.qsReason = QString::fromLatin1("Your maximum bandwidth(%1 kbit/s) above server limit (%2 kbit/s)").arg(msg->iMaxBandwidth/125.0).arg(g_sp.iMaxBandwidth/125.0); + msr.rtType = MessageServerReject::BandwidthExceeded; + ok = false; + } + + if ((id != 0) && (qhUsers.count() > g_sp.iMaxUsers)) { + msr.qsReason = QString::fromLatin1("Server is full (max %1 users)").arg(g_sp.iMaxUsers); + msr.rtType = MessageServerReject::ServerFull; + ok = false; + } + + if (! ok) { + log(QString::fromLatin1("Rejected connection: %1").arg(msr.qsReason), cCon); + sendMessage(cCon, &msr); + cCon->disconnectSocket(); + return; + } + + // Kick ghost + if (uOld) { + log(QString::fromLatin1("Disconnecting ghost"), uOld); + uOld->disconnectSocket(); + } + + int lchan = readLastChannel(uSource); + Channel *lc = Channel::get(lchan); + if (! lc) + lc = Channel::get(0); + else if (! ChanACL::hasPermission(uSource, lc, ChanACL::Enter)) + lc = Channel::get(0); + + playerEnterChannel(uSource, lc, true); + + QQueue<Channel *> q; + QSet<Channel *> chans; + q << Channel::get(0); + 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) + sendMessage(cCon, &mca); + + foreach(c, c->qlChannels) + q.enqueue(c); + } + + foreach(c, chans) { + if (c->qhLinks.count() > 0) { + MessageChannelLink mcl; + mcl.iId = c->iId; + mcl.ltType = MessageChannelLink::Link; + foreach(Channel *l, c->qhLinks.keys()) + mcl.qlTargets << l->iId; + sendMessage(cCon, &mcl); + } + } + + MessageServerJoin msjMsg; + MessagePlayerMove mpm; + + uSource->sState = Player::Authenticated; + msjMsg.uiSession = uSource->uiSession; + msjMsg.iId = uSource->iId; + msjMsg.qsPlayerName = uSource->qsName; + sendExcept(&msjMsg, cCon); + + mpm.uiSession = 0; + mpm.uiVictim = uSource->uiSession; + mpm.iChannelId = uSource->cChannel->iId; + if (mpm.iChannelId != 0) + sendExcept(&mpm, cCon); + + 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 = g_sp.qsWelcomeText; + mssMsg.iMaxBandwidth = g_sp.iMaxBandwidth; + sendMessage(cCon, &mssMsg); + log(QString("Authenticated: %1").arg(msg->qsUsername), cCon); + + dbus->playerConnected(uSource); + playerEnterChannel(uSource, lc, false); +} + +void Server::msgServerBanList(Connection *cCon, MessageServerBanList *msg) { + MSG_SETUP(Player::Authenticated); + + if (! ChanACL::hasPermission(uSource, Channel::get(0), ChanACL::Write)) { + PERM_DENIED(uSource, Channel::get(0), ChanACL::Write); + return; + } + if (msg->bQuery) { + MessageServerBanList msbl; + msbl.uiSession = 0; + msbl.bQuery = false; + msbl.qlBans = qlBans; + sendMessage(cCon, &msbl); + } else { + qlBans = msg->qlBans; + log(QString("Updated banlist"), cCon); + setBans(msg->qlBans); + } +} + +void Server::msgServerLeave(Connection *cCon, MessageServerLeave *) { + cCon->disconnectSocket(); +} + +void Server::msgServerJoin(Connection *cCon, MessageServerJoin *) { + cCon->disconnectSocket(); +} + +void Server::msgServerReject(Connection *cCon, MessageServerReject *) { + cCon->disconnectSocket(); +} + +void Server::msgServerSync(Connection *cCon, MessageServerSync *) { + cCon->disconnectSocket(); +} + +void Server::msgPermissionDenied(Connection *cCon, MessagePermissionDenied *) { + cCon->disconnectSocket(); +} + +void Server::msgPlayerRename(Connection *cCon, MessagePlayerRename *) { + cCon->disconnectSocket(); +} + +void Server::msgSpeex(Connection *cCon, MessageSpeex *msg) { + MSG_SETUP(Player::Authenticated); + fakeUdpPacket(msg, cCon); +} + +void Server::msgPlayerMute(Connection *cCon, MessagePlayerMute *msg) { + MSG_SETUP(Player::Authenticated); + VICTIM_SETUP; + + if (! pDstUser) + return; + + if (! ChanACL::hasPermission(uSource, pDstUser->cChannel, ChanACL::MuteDeafen)) { + PERM_DENIED(uSource, pDstUser->cChannel, ChanACL::MuteDeafen); + return; + } + + if (! msg->bMute && pDstUser->bSuppressed) { + pDstUser->bSuppressed = false; + } else if (pDstUser->bMute == msg->bMute) { + return; + } + + pDstUser->bMute = msg->bMute; + sendAll(msg); + + if (! msg->bMute && pDstUser->bDeaf) { + pDstUser->bDeaf = false; + } + + dbus->playerStateChanged(pDstUser); + + log(QString("Muted %1 (%2)").arg(pDstUser->qsName).arg(msg->bMute), cCon); +} + +void Server::msgPlayerDeaf(Connection *cCon, MessagePlayerDeaf *msg) { + MSG_SETUP(Player::Authenticated); + VICTIM_SETUP; + + if (! pDstUser) + return; + + if (! ChanACL::hasPermission(uSource, pDstUser->cChannel, ChanACL::MuteDeafen)) { + PERM_DENIED(uSource, pDstUser->cChannel, ChanACL::MuteDeafen); + return; + } + + if (pDstUser->bDeaf == msg->bDeaf) + return; + + pDstUser->bDeaf = msg->bDeaf; + sendAll(msg); + + if (msg->bDeaf && ! pDstUser->bMute) { + pDstUser->bMute = true; + } + + dbus->playerStateChanged(pDstUser); + + log(QString("Deafened %1 (%2)").arg(pDstUser->qsName).arg(msg->bDeaf), cCon); +} + +void Server::msgPlayerKick(Connection *cCon, MessagePlayerKick *msg) { + MSG_SETUP(Player::Authenticated); + VICTIM_SETUP; + + if (! pDstUser) + return; + + if (! ChanACL::hasPermission(uSource, pDstUser->cChannel, ChanACL::MoveKick)) { + PERM_DENIED(uSource, pDstUser->cChannel, ChanACL::MoveKick); + return; + } + + sendAll(msg); + log(QString("Kicked %1 (%2)").arg(pDstUser->qsName).arg(msg->qsReason), cCon); + pDstUser->disconnectSocket(); +} + +void Server::msgPlayerBan(Connection *cCon, MessagePlayerBan *msg) { + MSG_SETUP(Player::Authenticated); + VICTIM_SETUP; + + if (! pDstUser) + return; + + if (! ChanACL::hasPermission(uSource, Channel::get(0), ChanACL::MoveKick)) { + PERM_DENIED(uSource, Channel::get(0), ChanACL::MoveKick); + return; + } + + sendAll(msg); + log(QString("Kickbanned %1 (%2)").arg(pDstUser->qsName).arg(msg->qsReason), cCon); + + QHostAddress adr = pDstUser->peerAddress(); + quint32 base = adr.toIPv4Address(); + qlBans << QPair<quint32,int>(base, 32); + setBans(qlBans); + + pDstUser->disconnectSocket(); +} + +void Server::msgPlayerSelfMuteDeaf(Connection *cCon, MessagePlayerSelfMuteDeaf *msg) { + MSG_SETUP(Player::Authenticated); + + uSource->bSelfMute = msg->bMute; + uSource->bSelfDeaf = msg->bDeaf; + sendAll(msg); + dbus->playerStateChanged(uSource); +} + +void Server::msgPlayerMove(Connection *cCon, MessagePlayerMove *msg) { + MSG_SETUP(Player::Authenticated); + VICTIM_SETUP; + + if (! pDstUser) + return; + + Channel *c = Channel::get(msg->iChannelId); + if (!c || (c == pDstUser->cChannel)) + return; + + if ((uSource != pDstUser) && ! ChanACL::hasPermission(uSource, pDstUser->cChannel, ChanACL::MoveKick)) { + PERM_DENIED(uSource, pDstUser->cChannel, ChanACL::MoveKick); + return; + } + + if (! ChanACL::hasPermission(uSource, c, ChanACL::MoveKick) && ! ChanACL::hasPermission(pDstUser, c, ChanACL::Enter)) { + PERM_DENIED(pDstUser, c, ChanACL::Enter); + return; + } + + sendAll(msg); + playerEnterChannel(pDstUser, c); + log(QString("Moved to %1 (%2)").arg(c->qsName).arg(pDstUser->qsName), cCon); +} + +void Server::msgChannelAdd(Connection *cCon, MessageChannelAdd *msg) { + MSG_SETUP(Player::Authenticated); + + Channel *p = Channel::get(msg->iParent); + if (!p) + return; + + if (! ChanACL::hasPermission(uSource, p, ChanACL::MakeChannel)) { + PERM_DENIED(uSource, p, ChanACL::MakeChannel); + return; + } + + QRegExp re("[ \\w\\#\\[\\]\\{\\}\\(\\)\\@\\|]+"); + + if (! re.exactMatch(msg->qsName)) { + PERM_DENIED_TEXT("Illegal channel name"); + return; + } + + QRegExp re2("\\w"); + if (re2.indexIn(msg->qsName) == -1) { + PERM_DENIED_TEXT("Must have alphanumeric in name"); + return; + } + + Channel *c = addChannel(p, msg->qsName); + if (uSource->iId >= 0) { + Group *g = new Group(c, "admin"); + g->qsAdd << uSource->iId; + } + updateChannel(c); + + dbus->channelCreated(c); + + msg->iId = c->iId; + sendAll(msg); + log(QString("Added channel %1 (%2)").arg(c->qsName).arg(p->qsName), cCon); +} + +void Server::msgChannelRemove(Connection *cCon, MessageChannelRemove *msg) { + MSG_SETUP(Player::Authenticated); + + Channel *c = Channel::get(msg->iId); + if (!c) + return; + + if (! ChanACL::hasPermission(uSource, c, ChanACL::Write) || (msg->iId == 0)) { + PERM_DENIED(uSource, c, ChanACL::Write); + return; + } + + log(QString("Removed channel %1").arg(c->qsName), cCon); + + removeChannel(c, uSource); +} + +void Server::msgChannelMove(Connection *cCon, MessageChannelMove *msg) { + MSG_SETUP(Player::Authenticated); + + Channel *c = Channel::get(msg->iId); + Channel *np = Channel::get(msg->iParent); + if (!c || ! np) + return; + + if (np == c->cParent) + return; + + if (! ChanACL::hasPermission(uSource, c, ChanACL::Write)) { + PERM_DENIED(uSource, c, ChanACL::Write); + return; + } + + if (! ChanACL::hasPermission(uSource, np, ChanACL::MakeChannel)) { + PERM_DENIED(uSource, np, ChanACL::MakeChannel); + return; + } + + // Can't move to a subchannel of itself + Channel *p = np; + while (p) { + if (p == c) + return; + p = p->cParent; + } + + log(QString("Moved channel %1 (%2 -> %3)").arg(c->qsName).arg(c->cParent->qsName).arg(np->qsName), cCon); + + c->cParent->removeChannel(c); + np->addChannel(c); + updateChannel(c); + dbus->channelStateChanged(c); + sendAll(msg); +} + +void Server::msgChannelLink(Connection *cCon, MessageChannelLink *msg) { + MSG_SETUP(Player::Authenticated); + + Channel *c = Channel::get(msg->iId); + if (!c) + return; + + if (! ChanACL::hasPermission(uSource, c, ChanACL::LinkChannel)) { + PERM_DENIED(uSource, c, ChanACL::LinkChannel); + return; + } + + Channel *l = (msg->qlTargets.count() == 1) ? Channel::get(msg->qlTargets[0]) : NULL; + + switch (msg->ltType) { + case MessageChannelLink::Link: + if (!l) + return; + if (! ChanACL::hasPermission(uSource, l, ChanACL::LinkChannel)) { + PERM_DENIED(uSource, l, ChanACL::LinkChannel); + return; + } + break; + case MessageChannelLink::Unlink: + if (!l) + return; + break; + case MessageChannelLink::UnlinkAll: + if (msg->qlTargets.count() > 0) + return; + break; + default: + if (msg->qlTargets.count() <= 0) + return; + } + + QSet<Channel *> oldset = c->qhLinks.keys().toSet(); + + switch (msg->ltType) { + case MessageChannelLink::UnlinkAll: + c->unlink(NULL); + removeLink(c, NULL); + dbus->channelStateChanged(c); + log(QString("Unlinked all from channel %1").arg(c->qsName), cCon); + sendAll(msg); + return; + case MessageChannelLink::Link: + c->link(l); + addLink(c, l); + dbus->channelStateChanged(c); + log(QString("Linked channel %1 and %2").arg(c->qsName).arg(l->qsName), cCon); + break; + case MessageChannelLink::Unlink: + c->unlink(l); + removeLink(c, l); + dbus->channelStateChanged(c); + log(QString("Unlinked channel %1 and %2").arg(c->qsName).arg(l->qsName), cCon); + break; + case MessageChannelLink::PushLink: + foreach(int tid, msg->qlTargets) { + l=Channel::get(tid); + if (l && ChanACL::hasPermission(uSource, l, ChanACL::LinkChannel)) + c->playerLink(l, uSource); + } + break; + case MessageChannelLink::PushUnlink: + foreach(int tid, msg->qlTargets) { + l=Channel::get(tid); + if (l) + c->playerUnlink(l, uSource); + } + break; + } + + 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 (newset.count() > oldset.count()) { + mcl.ltType = MessageChannelLink::Link; + changed = newset - oldset; + } else { + mcl.ltType = MessageChannelLink::Unlink; + changed = oldset - newset; + } + foreach(l, changed) + mcl.qlTargets << l->iId; + sendAll(&mcl); +} + +void Server::msgTextMessage(Connection *cCon, MessageTextMessage *msg) { + MSG_SETUP(Player::Authenticated); + VICTIM_SETUP; + sendMessage(pDstUser, msg); +} + +void Server::msgEditACL(Connection *cCon, MessageEditACL *msg) { + MSG_SETUP(Player::Authenticated); + + Channel *c = Channel::get(msg->iId); + if (!c) + return; + + if (! ChanACL::hasPermission(uSource, c, ChanACL::Write)) { + PERM_DENIED(uSource, c, ChanACL::Write); + return; + } + + MessageEditACL mea; + mea.iId = msg->iId; + + if (msg->bQuery) { + QStack<Channel *> chans; + Channel *p; + ChanACL *acl; + + p = c; + while (p) { + chans.push(p); + if ((p==c) || p->bInheritACL) + p = p->cParent; + else + 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; + } + } + } + + p = c->cParent; + QSet<QString> allnames=Group::groupNames(c); + QString name; + 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); + if (g) { + gs.qsAdd = g->qsAdd; + gs.qsRemove = g->qsRemove; + } + if (pg) + gs.qsInheritedMembers = pg->members(); + mea.groups << gs; + } + sendMessage(cCon, &mea); + } else { + Group *g; + ChanACL *a; + MessageEditACL::GroupStruct gs; + MessageEditACL::ACLStruct as; + + QHash<QString, QSet<int> > hOldTemp; + + foreach(g, c->qhGroups) { + hOldTemp.insert(g->qsName, g->qsTemporary); + delete g; + } + + foreach(a, c->qlACL) + delete a; + + 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); + } + + foreach(as, msg->acls) { + 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; + } + + ChanACL::clearCache(); + + if (! ChanACL::hasPermission(uSource, c, ChanACL::Write)) { + a = new ChanACL(c); + a->bApplyHere=true; + a->bApplySubs=false; + a->iPlayerId=uSource->iId; + a->pDeny=ChanACL::None; + a->pAllow=ChanACL::Write | ChanACL::Traverse; + + ChanACL::clearCache(); + } + + updateChannel(c); + log(QString("Updated ACL in channel %1(%2)").arg(c->qsName).arg(c->iId), cCon); + } +} + +void Server::msgQueryUsers(Connection *cCon, MessageQueryUsers *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 == -1) { + id = qhUserIDCache.value(name); + if (! qhUserIDCache.contains(name)) { + id = getUserID(name); + if (id != -1) + qhUserIDCache[name] = id; + } + msg->qlIds[i] = id; + } else { + if (! qhUserNameCache.contains(id)) { + name = getUserName(id); + if (! name.isEmpty()) + qhUserNameCache[id] = name; + } + msg->qlNames[i] = qhUserNameCache.value(id); + } + } + // 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); +} + +void Server::msgTexture(Connection *cCon, MessageTexture *msg) { + MSG_SETUP(Player::Authenticated); + if (! qhUserTextureCache.contains(msg->iPlayerId)) { + QByteArray qba = getUserTexture(msg->iPlayerId); + if (! qba.isEmpty()) { + 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); +} diff --git a/src/murmur/Server.cpp b/src/murmur/Server.cpp index d2983bbd4..686741d66 100644 --- a/src/murmur/Server.cpp +++ b/src/murmur/Server.cpp @@ -48,7 +48,6 @@ #include <errno.h> #endif -Server *g_sServer; ServerParams g_sp; uint qHash(const Peer &p) { @@ -77,6 +76,11 @@ QSslSocket *SslServer::nextPendingSSLConnection() { return qlSockets.takeFirst(); } +User::User(Server *parent, QSslSocket *socket) : Connection(parent, socket), Player() { + uiAddress = 0; + usPort = 0; +} + ServerParams::ServerParams() { qsPassword = QString(); iPort = 64738; @@ -175,7 +179,7 @@ int BandwidthRecord::bytesPerSec() { return (iSum * 1000000LL) / elapsed; } -void UDPThread::run() { +void Server::run() { qDebug("Starting UDP Thread"); qusUdp = new QUdpSocket(); if (! qusUdp->bind(g_sp.qhaBind, g_sp.iPort, QUdpSocket::DontShareAddress)) @@ -186,7 +190,7 @@ void UDPThread::run() { if (setsockopt(qusUdp->socketDescriptor(), SOL_IP, IP_TOS, &val, sizeof(val))) qWarning("Server: Failed to set TOS for UDP Socket"); #endif - connect(this, SIGNAL(tcpTransmit(QByteArray, unsigned int)), g_sServer, SLOT(tcpTransmit(QByteArray, unsigned int)), Qt::QueuedConnection); + connect(this, SIGNAL(tcpTransmit(QByteArray, unsigned int)), this, SLOT(tcpTransmitData(QByteArray, unsigned int)), Qt::QueuedConnection); QHostAddress senderAddr; quint16 senderPort; @@ -199,7 +203,7 @@ void UDPThread::run() { qDebug("Entering UDP event loop"); while (qusUdp->waitForReadyRead(-1)) { - QReadLocker rl(& g_sServer->qrwlConnections); + QReadLocker rl(&qrwlUsers); while (qusUdp->hasPendingDatagrams()) { len=qusUdp->readDatagram(buffer, 65535, &senderAddr, &senderPort); @@ -215,21 +219,21 @@ void UDPThread::run() { Peer p(senderAddr.toIPv4Address(), senderPort); if (p != qhPeers.value(uiSession)) { - Connection *source = g_sServer->qmConnections.value(uiSession); + Connection *source = qhUsers.value(uiSession); if (! source || !(source->peerAddress() == senderAddr)) { continue; } // At any point after this, the connection might go away WHILE we're processing. That is "bad". rl.unlock(); { - QWriteLocker wl(&g_sServer->qrwlConnections); - if (g_sServer->qmConnections.contains(uiSession)) { + QWriteLocker wl(&qrwlUsers); + if (qhUsers.contains(uiSession)) { qhHosts[uiSession] = senderAddr; qhPeers[uiSession] = p; } } rl.relock(); - if (! g_sServer->qmConnections.contains(uiSession)) { + if (! qhUsers.contains(uiSession)) { continue; } } @@ -237,13 +241,13 @@ void UDPThread::run() { if (msgType == Message::Ping) qusUdp->writeDatagram(buffer, len, senderAddr, senderPort); else { - processMsg(pds, g_sServer->qmConnections.value(uiSession)); + processMsg(pds, qhUsers.value(uiSession)); } } } } -void UDPThread::fakeUdpPacket(Message *msg, Connection *source) { +void Server::fakeUdpPacket(Message *msg, Connection *source) { char buffer[65535]; PacketDataStream pds(buffer, 65535); msg->messageToNetwork(pds); @@ -254,11 +258,11 @@ void UDPThread::fakeUdpPacket(Message *msg, Connection *source) { pds >> msgType >> uiSession; - QReadLocker rl(&g_sServer->qrwlConnections); + QReadLocker rl(&qrwlUsers); processMsg(pds, source); } -void UDPThread::sendMessage(unsigned int id, const char *data, int len, QByteArray &cache) { +void Server::sendMessage(unsigned int id, const char *data, int len, QByteArray &cache) { if (qhPeers.contains(id)) { qusUdp->writeDatagram(data, len, qhHosts[id], qhPeers[id].second); } else { @@ -268,18 +272,18 @@ void UDPThread::sendMessage(unsigned int id, const char *data, int len, QByteArr } } -void UDPThread::processMsg(PacketDataStream &pds, Connection *cCon) { - Player *pSrcPlayer = g_sServer->qmPlayers.value(cCon); - if (!pSrcPlayer || (pSrcPlayer->sState != Player::Authenticated)) +void Server::processMsg(PacketDataStream &pds, Connection *cCon) { + User *u = static_cast<User *>(cCon); + if (! u || (u->sState != Player::Authenticated)) return; Player *p; int seq, flags; - if (pSrcPlayer->bMute || pSrcPlayer->bSuppressed) + if (u->bMute || u->bSuppressed) return; - BandwidthRecord *bw = g_sServer->qmBandwidth[cCon]; + BandwidthRecord *bw = & u->bwr; pds >> seq; pds >> flags; @@ -294,7 +298,7 @@ void UDPThread::processMsg(PacketDataStream &pds, Connection *cCon) { return; } - Channel *c = pSrcPlayer->cChannel; + Channel *c = u->cChannel; QByteArray qba; @@ -303,12 +307,12 @@ void UDPThread::processMsg(PacketDataStream &pds, Connection *cCon) { int len = pds.left(); if (flags & MessageSpeex::LoopBack) { - sendMessage(pSrcPlayer->uiSession, data, len, qba); + sendMessage(u->uiSession, data, len, qba); return; } foreach(p, c->qlPlayers) { - if (! p->bDeaf && ! p->bSelfDeaf && (p != pSrcPlayer)) + if (! p->bDeaf && ! p->bSelfDeaf && (p != static_cast<Player *>(u))) sendMessage(p->uiSession, data, len, qba); } @@ -317,7 +321,7 @@ void UDPThread::processMsg(PacketDataStream &pds, Connection *cCon) { chans.remove(c); foreach(Channel *l, chans) { - if (ChanACL::hasPermission(pSrcPlayer, l, (flags & MessageSpeex::AltSpeak) ? ChanACL::AltSpeak : ChanACL::Speak)) { + if (ChanACL::hasPermission(u, l, (flags & MessageSpeex::AltSpeak) ? ChanACL::AltSpeak : ChanACL::Speak)) { foreach(p, l->qlPlayers) { if (! p->bDeaf && ! p->bSelfDeaf) sendMessage(p->uiSession, data, len, qba); @@ -328,7 +332,7 @@ void UDPThread::processMsg(PacketDataStream &pds, Connection *cCon) { } -Server::Server(QObject *p) : QObject(p) { +Server::Server(QObject *p) : QThread(p) { qtsServer = new SslServer(this); connect(qtsServer, SIGNAL(newConnection()), this, SLOT(newClient()), Qt::QueuedConnection); @@ -336,33 +340,28 @@ Server::Server(QObject *p) : QObject(p) { if (! qtsServer->listen(g_sp.qhaBind, g_sp.iPort)) qFatal("Server: TCP Listen on port %d failed",g_sp.iPort); - udp = new UDPThread(); - udp->moveToThread(udp); - log(QString("Server listening on port %1").arg(g_sp.iPort)); - for (int i=1;i<2000;i++) + for (int i=1;i<5000;i++) qqIds.enqueue(i); qtTimeout = new QTimer(this); connect(qtTimeout, SIGNAL(timeout()), this, SLOT(checkTimeout())); qtTimeout->start(5500); - qlBans = ServerDB::getBans(); + qlBans = getBans(); } void Server::log(QString s, Connection *c) { if (c) { - Player *p = qmPlayers.value(c); + User *u = static_cast<User *>(c); int id = 0; int iid = -1; QString name; - if (p) { - id = p->uiSession; - iid = p->iId; - name = p->qsName; - } + id = u->uiSession; + iid = u->iId; + name = u->qsName; qWarning("<%d:%s(%d)> %s", id, qPrintable(name), iid, qPrintable(s)); } else { qWarning("%s", qPrintable(s)); @@ -393,30 +392,24 @@ void Server::newClient() { sock->setPrivateKey(cert.getKey()); sock->setLocalCertificate(cert.getCert()); - Connection *cCon = new Connection(this, sock); - - unsigned int id; - if (qqIds.isEmpty()) { - cCon->disconnect(); + sock->disconnectFromHost(); return; } - id=qqIds.dequeue(); + User *u = new User(this, sock); + u->uiSession = qqIds.dequeue(); - Player *pPlayer = Player::add(id); - qmPlayers[cCon] = pPlayer; { - QWriteLocker wl(&qrwlConnections); - qmBandwidth[cCon] = new BandwidthRecord(); - qmConnections[id] = cCon; + QWriteLocker wl(&qrwlUsers); + qhUsers.insert(u->uiSession, u); } - connect(cCon, SIGNAL(connectionClosed(QString)), this, SLOT(connectionClosed(QString))); - connect(cCon, SIGNAL(message(QByteArray &)), this, SLOT(message(QByteArray &))); - connect(cCon, SIGNAL(handleSslErrors(const QList<QSslError> &)), this, SLOT(sslError(const QList<QSslError> &))); + connect(u, SIGNAL(connectionClosed(QString)), this, SLOT(connectionClosed(QString))); + connect(u, SIGNAL(message(QByteArray &)), this, SLOT(message(QByteArray &))); + connect(u, SIGNAL(handleSslErrors(const QList<QSslError> &)), this, SLOT(sslError(const QList<QSslError> &))); - log(QString("New connection: %1:%2").arg(sock->peerAddress().toString()).arg(sock->peerPort()), cCon); + log(QString("New connection: %1:%2").arg(sock->peerAddress().toString()).arg(sock->peerPort()), u); sock->startServerEncryption(); } @@ -433,82 +426,75 @@ void Server::sslError(const QList<QSslError> &errors) { } } if (ok) { - Connection *c = static_cast<Connection *>(sender()); + Connection *c = dynamic_cast<User *>(sender()); c->proceedAnyway(); } } void Server::connectionClosed(QString reason) { - Connection *c = static_cast<Connection *>(sender()); - Player *pPlayer = qmPlayers.value(c); + Connection *c = dynamic_cast<Connection *>(sender()); + User *u = static_cast<User *>(c); log(QString("Connection closed: %1").arg(reason), c); - if (pPlayer->sState == Player::Authenticated) { + if (u->sState == Player::Authenticated) { MessageServerLeave mslMsg; - mslMsg.uiSession=pPlayer->uiSession; + mslMsg.uiSession=u->uiSession; sendExcept(&mslMsg, c); - dbus->playerDisconnected(pPlayer); + dbus->playerDisconnected(u); } - QWriteLocker wl(&qrwlConnections); - - qmConnections.remove(pPlayer->uiSession); - qmPlayers.remove(c); - - BandwidthRecord *bw = qmBandwidth.take(c); - delete bw; - - Player::remove(pPlayer); + QWriteLocker wl(&qrwlUsers); - qqIds.enqueue(pPlayer->uiSession); + qhUsers.remove(u->uiSession); + if (u->cChannel) + u->cChannel->removePlayer(u); - udp->qhHosts.remove(pPlayer->uiSession); - udp->qhPeers.remove(pPlayer->uiSession); + qqIds.enqueue(u->uiSession); + qhUserTextureCache.remove(u->iId); - qhUserTextureCache.remove(pPlayer->iId); - - delete pPlayer; - c->deleteLater(); + u->deleteLater(); } void Server::message(QByteArray &qbaMsg, Connection *cCon) { - if (cCon == NULL) + if (cCon == NULL) { cCon = static_cast<Connection *>(sender()); + } Message *mMsg = Message::networkToMessage(qbaMsg); // Just leftovers from the buffer and we just kicked // the user off. - if (! qmPlayers.contains(cCon)) - return; + // FIXME :: We don't have anything like this now. + //if (cCon->isDeleted()) + // return; if (mMsg) { - mMsg->process(cCon); + dispatch(cCon, mMsg); delete mMsg; } else { - cCon->disconnect(); + cCon->disconnectSocket(); } } void Server::checkTimeout() { - QList<Connection *> qlClose; + QList<User *> qlClose; - qrwlConnections.lockForRead(); - foreach(Connection *c, qmConnections) { - if (c->activityTime() > (g_sp.iTimeout * 1000)) { - log(QLatin1String("Timeout"), c); - qlClose.append(c); + qrwlUsers.lockForRead(); + foreach(User *u, qhUsers) { + if (u->activityTime() > (g_sp.iTimeout * 1000)) { + log(QLatin1String("Timeout"), u); + qlClose.append(u); } } - qrwlConnections.unlock(); - foreach(Connection *c, qlClose) - c->disconnect(); + qrwlUsers.unlock(); + foreach(User *u, qlClose) + u->disconnectSocket(); } -void Server::tcpTransmit(QByteArray a, unsigned int id) { - Connection *c = qmConnections.value(id); +void Server::tcpTransmitData(QByteArray a, unsigned int id) { + Connection *c = qhUsers.value(id); if (c) { c->sendMessage(a); c->forceFlush(); @@ -516,7 +502,7 @@ void Server::tcpTransmit(QByteArray a, unsigned int id) { } void Server::sendMessage(unsigned int id, Message *mMsg) { - Connection *c = qmConnections.value(id); + Connection *c = qhUsers.value(id); sendMessage(c, mMsg); } @@ -529,11 +515,9 @@ void Server::sendAll(Message *mMsg) { } void Server::sendExcept(Message *mMsg, Connection *cCon) { - QHash<Connection *, Player *>::const_iterator i; - for (i=qmPlayers.constBegin(); i != qmPlayers.constEnd(); ++i) { - if ((i.key() != cCon) && (i.value()->sState == Player::Authenticated)) - sendMessage(i.key(), mMsg); - } + foreach(User *u, qhUsers) + if ((static_cast<Connection *>(u) != cCon) && (u->sState == Player::Authenticated)) + u->sendMessage(mMsg); } void Server::removeChannel(Channel *chan, Player *src, Channel *dest) { @@ -566,11 +550,11 @@ void Server::removeChannel(Channel *chan, Player *src, Channel *dest) { mcr.iId = chan->iId; sendAll(&mcr); - ServerDB::removeChannel(chan); + removeChannel(chan); dbus->channelRemoved(chan); if (chan->cParent) { - QWriteLocker wl(&qrwlConnections); + QWriteLocker wl(&qrwlUsers); chan->cParent->removeChannel(chan); } @@ -582,14 +566,14 @@ void Server::playerEnterChannel(Player *p, Channel *c, bool quiet) { return; { - QWriteLocker wl(&qrwlConnections); + QWriteLocker wl(&qrwlUsers); c->addPlayer(p); } if (quiet) return; - ServerDB::setLastChannel(p); + setLastChannel(p); dbus->playerStateChanged(p); bool mayspeak = ChanACL::hasPermission(p, c, ChanACL::Speak); @@ -604,776 +588,7 @@ void Server::playerEnterChannel(Player *p, Channel *c, bool quiet) { mpm.uiSession = 0; mpm.uiVictim = p->uiSession; mpm.bMute = p->bSuppressed; - g_sServer->sendAll(&mpm); - } - } -} - -#define MSG_SETUP(st) \ - Player *pSrcPlayer = g_sServer->qmPlayers.value(cCon); \ - MessagePermissionDenied mpd; \ - uiSession = pSrcPlayer->uiSession; \ - if (pSrcPlayer->sState != st) \ - return - -#define VICTIM_SETUP \ - Player *pDstPlayer = Player::get(uiVictim); \ - Q_UNUSED(pDstPlayer) \ - Connection *cDst = g_sServer->qmConnections.value(uiVictim); \ - Q_UNUSED(cDst) - -#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); \ - g_sServer->sendMessage(cCon, &mpd); \ - g_sServer->log(mpd.qsReason, cCon) -#define PERM_DENIED_TEXT(text) \ - mpd.qsReason = text; \ - g_sServer->sendMessage(cCon, &mpd) - - -void MessageServerAuthenticate::process(Connection *cCon) { - MSG_SETUP(Player::Connected); - - Channel *c; - - pSrcPlayer->qsName = qsUsername; - - MessageServerReject msr; - bool ok = false; - - QRegExp re("[\\w\\[\\]\\{\\}\\(\\)\\@\\|]+"); - - bool nameok = re.exactMatch(qsUsername); - if (nameok && qsUsername[0] == '@') - nameok = false; - if (nameok && qsUsername[0] == '#') - nameok = false; - - // 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 = ServerDB::authenticate(qsUsername, qsPassword); - - // Did the session go away? - Player *p = Player::get(uiSession); - if (p != pSrcPlayer) - return; - - pSrcPlayer->iId = id >= 0 ? id : -1; - pSrcPlayer->qsName = qsUsername; - - if (iVersion != MESSAGE_STREAM_VERSION) { - msr.qsReason = QString("Wrong version of mumble protocol (client: %1, server: %2)").arg(iVersion).arg(MESSAGE_STREAM_VERSION); - msr.rtType = MessageServerReject::WrongVersion; - } else if (! nameok) { - msr.qsReason = "Invalid Username"; - msr.rtType = MessageServerReject::InvalidUsername; - } else if (id==-1) { - msr.qsReason = "Wrong password for user"; - msr.rtType = MessageServerReject::WrongUserPW; - } else if (id==-2 && ! g_sp.qsPassword.isEmpty() && g_sp.qsPassword != qsPassword) { - msr.qsReason = "Invalid server password"; - msr.rtType = MessageServerReject::WrongServerPW; - } else { - ok = true; - } - - Player *ppOld = Player::match(pSrcPlayer, true); - Connection *cOld = ppOld ? g_sServer->qmConnections.value(ppOld->uiSession) : NULL; - - // Allow reuse of name from same IP - if (ok && ppOld && (pSrcPlayer->iId == -1)) { - if (cOld->peerAddress() != cCon->peerAddress()) { - msr.qsReason = "Playername already in use"; - msr.rtType = MessageServerReject::UsernameInUse; - ok = false; - } - } - - if (iMaxBandwidth > g_sp.iMaxBandwidth) { - msr.qsReason = QString::fromLatin1("Your maximum bandwidth(%1 kbit/s) above server limit (%2 kbit/s)").arg(iMaxBandwidth/125.0).arg(g_sp.iMaxBandwidth/125.0); - msr.rtType = MessageServerReject::BandwidthExceeded; - ok = false; - } - - if ((id != 0) && (g_sServer->qmPlayers.count() > g_sp.iMaxUsers)) { - msr.qsReason = QString::fromLatin1("Server is full (max %1 users)").arg(g_sp.iMaxUsers); - msr.rtType = MessageServerReject::ServerFull; - ok = false; - } - - if (! ok) { - g_sServer->log(QString::fromLatin1("Rejected connection: %1").arg(msr.qsReason), cCon); - g_sServer->sendMessage(cCon, &msr); - cCon->disconnect(); - return; - } - - // Kick ghost - if (ppOld) { - g_sServer->log(QString::fromLatin1("Disconnecting ghost"), cOld); - cOld->disconnect(); - } - - int lchan = ServerDB::readLastChannel(pSrcPlayer); - Channel *lc = Channel::get(lchan); - if (! lc) - lc = Channel::get(0); - else if (! ChanACL::hasPermission(pSrcPlayer, lc, ChanACL::Enter)) - lc = Channel::get(0); - - g_sServer->playerEnterChannel(pSrcPlayer, lc, true); - - QQueue<Channel *> q; - QSet<Channel *> chans; - q << Channel::get(0); - 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) - g_sServer->sendMessage(cCon, &mca); - - foreach(c, c->qlChannels) - q.enqueue(c); - } - - foreach(c, chans) { - if (c->qhLinks.count() > 0) { - MessageChannelLink mcl; - mcl.iId = c->iId; - mcl.ltType = MessageChannelLink::Link; - foreach(Channel *l, c->qhLinks.keys()) - mcl.qlTargets << l->iId; - g_sServer->sendMessage(cCon, &mcl); - } - } - - MessageServerJoin msjMsg; - MessagePlayerMove mpm; - - pSrcPlayer->sState = Player::Authenticated; - msjMsg.uiSession = pSrcPlayer->uiSession; - msjMsg.iId = pSrcPlayer->iId; - msjMsg.qsPlayerName = pSrcPlayer->qsName; - g_sServer->sendExcept(&msjMsg, cCon); - - mpm.uiSession = 0; - mpm.uiVictim = pSrcPlayer->uiSession; - mpm.iChannelId = pSrcPlayer->cChannel->iId; - if (mpm.iChannelId != 0) - g_sServer->sendExcept(&mpm, cCon); - - foreach(Player *pPlayer, g_sServer->qmPlayers) { - if (pPlayer->sState != Player::Authenticated) - continue; - msjMsg.uiSession = pPlayer->uiSession; - msjMsg.iId = pPlayer->iId; - msjMsg.qsPlayerName = pPlayer->qsName; - g_sServer->sendMessage(cCon, &msjMsg); - - if (pPlayer->bDeaf) { - MessagePlayerDeaf mpdMsg; - mpdMsg.uiSession = 0; - mpdMsg.uiVictim = pPlayer->uiSession; - mpdMsg.bDeaf = true; - g_sServer->sendMessage(cCon, &mpdMsg); - } else if (pPlayer->bMute || pPlayer->bSuppressed) { - MessagePlayerMute mpmMsg; - mpmMsg.uiSession = 0; - mpmMsg.uiVictim = pPlayer->uiSession; - mpmMsg.bMute = true; - g_sServer->sendMessage(cCon, &mpmMsg); - } - if (pPlayer->bSelfDeaf || pPlayer->bSelfMute) { - MessagePlayerSelfMuteDeaf mpsmdMsg; - mpsmdMsg.uiSession = pPlayer->uiSession; - mpsmdMsg.bDeaf = pPlayer->bSelfDeaf; - mpsmdMsg.bMute = pPlayer->bSelfMute; - g_sServer->sendMessage(cCon, &mpsmdMsg); + sendAll(&mpm); } - - mpm.uiSession = 0; - mpm.uiVictim = pPlayer->uiSession; - mpm.iChannelId = pPlayer->cChannel->iId; - g_sServer->sendMessage(cCon, &mpm); } - - - MessageServerSync mssMsg; - mssMsg.uiSession = pSrcPlayer->uiSession; - mssMsg.qsWelcomeText = g_sp.qsWelcomeText; - mssMsg.iMaxBandwidth = g_sp.iMaxBandwidth; - g_sServer->sendMessage(cCon, &mssMsg); - g_sServer->log(QString("Authenticated: %1").arg(qsUsername), cCon); - - dbus->playerConnected(pSrcPlayer); - g_sServer->playerEnterChannel(pSrcPlayer, lc, false); -} - -void MessageServerBanList::process(Connection *cCon) { - MSG_SETUP(Player::Authenticated); - - if (! ChanACL::hasPermission(pSrcPlayer, Channel::get(0), ChanACL::Write)) { - PERM_DENIED(pSrcPlayer, Channel::get(0), ChanACL::Write); - return; - } - if (bQuery) { - MessageServerBanList msbl; - msbl.uiSession = 0; - msbl.bQuery = false; - msbl.qlBans = g_sServer->qlBans; - g_sServer->sendMessage(cCon, &msbl); - } else { - g_sServer->qlBans = qlBans; - g_sServer->log(QString("Updated banlist"), cCon); - ServerDB::setBans(qlBans); - } -} - -void MessageServerLeave::process(Connection *cCon) { - cCon->disconnect(); -} - -void MessageServerJoin::process(Connection *cCon) { - cCon->disconnect(); -} - -void MessageServerReject::process(Connection *cCon) { - cCon->disconnect(); -} - -void MessageServerSync::process(Connection *cCon) { - cCon->disconnect(); -} - -void MessagePermissionDenied::process(Connection *cCon) { - cCon->disconnect(); -} - -void MessagePlayerRename::process(Connection *cCon) { - cCon->disconnect(); -} - -void MessageSpeex::process(Connection *cCon) { - MSG_SETUP(Player::Authenticated); - uiSession = pSrcPlayer->uiSession; - g_sServer->udp->fakeUdpPacket(this, cCon); -} - -void MessagePlayerMute::process(Connection *cCon) { - MSG_SETUP(Player::Authenticated); - VICTIM_SETUP; - - if (! pDstPlayer) - return; - - if (! ChanACL::hasPermission(pSrcPlayer, pDstPlayer->cChannel, ChanACL::MuteDeafen)) { - PERM_DENIED(pSrcPlayer, pDstPlayer->cChannel, ChanACL::MuteDeafen); - return; - } - - if (! bMute && pDstPlayer->bSuppressed) { - pDstPlayer->bSuppressed = false; - } else if (pDstPlayer->bMute == bMute) { - return; - } - - pDstPlayer->bMute = bMute; - g_sServer->sendAll(this); - - if (! bMute && pDstPlayer->bDeaf) { - pDstPlayer->bDeaf = false; - } - - dbus->playerStateChanged(pDstPlayer); - - g_sServer->log(QString("Muted %1 (%2)").arg(pDstPlayer->qsName).arg(bMute), cCon); -} - -void MessagePlayerDeaf::process(Connection *cCon) { - MSG_SETUP(Player::Authenticated); - VICTIM_SETUP; - - if (! pDstPlayer) - return; - - if (! ChanACL::hasPermission(pSrcPlayer, pDstPlayer->cChannel, ChanACL::MuteDeafen)) { - PERM_DENIED(pSrcPlayer, pDstPlayer->cChannel, ChanACL::MuteDeafen); - return; - } - - if (pDstPlayer->bDeaf == bDeaf) - return; - - pDstPlayer->bDeaf = bDeaf; - g_sServer->sendAll(this); - - if (bDeaf && ! pDstPlayer->bMute) { - pDstPlayer->bMute = true; - } - - dbus->playerStateChanged(pDstPlayer); - - g_sServer->log(QString("Deafened %1 (%2)").arg(pDstPlayer->qsName).arg(bDeaf), cCon); -} - -void MessagePlayerKick::process(Connection *cCon) { - MSG_SETUP(Player::Authenticated); - VICTIM_SETUP; - - if (! pDstPlayer) - return; - - if (! ChanACL::hasPermission(pSrcPlayer, pDstPlayer->cChannel, ChanACL::MoveKick)) { - PERM_DENIED(pSrcPlayer, pDstPlayer->cChannel, ChanACL::MoveKick); - return; - } - - g_sServer->sendAll(this); - g_sServer->log(QString("Kicked %1 (%2)").arg(pDstPlayer->qsName).arg(qsReason), cCon); - cDst->disconnect(); -} - -void MessagePlayerBan::process(Connection *cCon) { - MSG_SETUP(Player::Authenticated); - VICTIM_SETUP; - - if (! pDstPlayer) - return; - - if (! ChanACL::hasPermission(pSrcPlayer, Channel::get(0), ChanACL::MoveKick)) { - PERM_DENIED(pSrcPlayer, Channel::get(0), ChanACL::MoveKick); - return; - } - - g_sServer->sendAll(this); - g_sServer->log(QString("Kickbanned %1 (%2)").arg(pDstPlayer->qsName).arg(qsReason), cCon); - - - QHostAddress adr = cDst->peerAddress(); - quint32 base = adr.toIPv4Address(); - g_sServer->qlBans << QPair<quint32,int>(base, 32); - ServerDB::setBans(g_sServer->qlBans); - - cDst->disconnect(); -} - -void MessagePlayerSelfMuteDeaf::process(Connection *cCon) { - MSG_SETUP(Player::Authenticated); - - pSrcPlayer->bSelfMute = bMute; - pSrcPlayer->bSelfDeaf = bDeaf; - g_sServer->sendAll(this); - dbus->playerStateChanged(pSrcPlayer); -} - -void MessagePlayerMove::process(Connection *cCon) { - MSG_SETUP(Player::Authenticated); - VICTIM_SETUP; - - if (! pDstPlayer) - return; - - Channel *c = Channel::get(iChannelId); - if (!c || (c == pDstPlayer->cChannel)) - return; - - if ((pSrcPlayer != pDstPlayer) && ! ChanACL::hasPermission(pSrcPlayer, pDstPlayer->cChannel, ChanACL::MoveKick)) { - PERM_DENIED(pSrcPlayer, pDstPlayer->cChannel, ChanACL::MoveKick); - return; - } - - if (! ChanACL::hasPermission(pSrcPlayer, c, ChanACL::MoveKick) && ! ChanACL::hasPermission(pDstPlayer, c, ChanACL::Enter)) { - PERM_DENIED(pDstPlayer, c, ChanACL::Enter); - return; - } - - g_sServer->sendAll(this); - g_sServer->playerEnterChannel(pDstPlayer, c); - g_sServer->log(QString("Moved to %1 (%2)").arg(c->qsName).arg(pDstPlayer->qsName), cCon); -} - -void MessageChannelAdd::process(Connection *cCon) { - MSG_SETUP(Player::Authenticated); - - Channel *p = Channel::get(iParent); - if (!p) - return; - - if (! ChanACL::hasPermission(pSrcPlayer, p, ChanACL::MakeChannel)) { - PERM_DENIED(pSrcPlayer, p, ChanACL::MakeChannel); - return; - } - - QRegExp re("[ \\w\\#\\[\\]\\{\\}\\(\\)\\@\\|]+"); - - if (! re.exactMatch(qsName)) { - PERM_DENIED_TEXT("Illegal channel name"); - return; - } - - QRegExp re2("\\w"); - if (re2.indexIn(qsName) == -1) { - PERM_DENIED_TEXT("Must have alphanumeric in name"); - return; - } - - Channel *c = ServerDB::addChannel(p, qsName); - if (pSrcPlayer->iId >= 0) { - Group *g = new Group(c, "admin"); - g->qsAdd << pSrcPlayer->iId; - } - ServerDB::updateChannel(c); - - dbus->channelCreated(c); - - iId = c->iId; - g_sServer->sendAll(this); - g_sServer->log(QString("Added channel %1 (%2)").arg(qsName).arg(p->qsName), cCon); -} - -void MessageChannelRemove::process(Connection *cCon) { - MSG_SETUP(Player::Authenticated); - - Channel *c = Channel::get(iId); - if (!c) - return; - - if (! ChanACL::hasPermission(pSrcPlayer, c, ChanACL::Write) || (iId == 0)) { - PERM_DENIED(pSrcPlayer, c, ChanACL::Write); - return; - } - - g_sServer->log(QString("Removed channel %1").arg(c->qsName), cCon); - - g_sServer->removeChannel(c, pSrcPlayer); -} - -void MessageChannelMove::process(Connection *cCon) { - MSG_SETUP(Player::Authenticated); - - Channel *c = Channel::get(iId); - Channel *np = Channel::get(iParent); - if (!c || ! np) - return; - - if (np == c->cParent) - return; - - if (! ChanACL::hasPermission(pSrcPlayer, c, ChanACL::Write)) { - PERM_DENIED(pSrcPlayer, c, ChanACL::Write); - return; - } - - if (! ChanACL::hasPermission(pSrcPlayer, np, ChanACL::MakeChannel)) { - PERM_DENIED(pSrcPlayer, np, ChanACL::MakeChannel); - return; - } - - // Can't move to a subchannel of itself - Channel *p = np; - while (p) { - if (p == c) - return; - p = p->cParent; - } - - g_sServer->log(QString("Moved channel %1 (%2 -> %3)").arg(c->qsName).arg(c->cParent->qsName).arg(np->qsName), cCon); - - c->cParent->removeChannel(c); - np->addChannel(c); - ServerDB::updateChannel(c); - dbus->channelStateChanged(c); - g_sServer->sendAll(this); -} - -void MessageChannelLink::process(Connection *cCon) { - MSG_SETUP(Player::Authenticated); - - Channel *c = Channel::get(iId); - if (!c) - return; - - if (! ChanACL::hasPermission(pSrcPlayer, c, ChanACL::LinkChannel)) { - PERM_DENIED(pSrcPlayer, c, ChanACL::LinkChannel); - return; - } - - Channel *l = (qlTargets.count() == 1) ? Channel::get(qlTargets[0]) : NULL; - - switch (ltType) { - case Link: - if (!l) - return; - if (! ChanACL::hasPermission(pSrcPlayer, l, ChanACL::LinkChannel)) { - PERM_DENIED(pSrcPlayer, l, ChanACL::LinkChannel); - return; - } - break; - case Unlink: - if (!l) - return; - break; - case UnlinkAll: - if (qlTargets.count() > 0) - return; - break; - default: - if (qlTargets.count() <= 0) - return; - } - - QSet<Channel *> oldset = c->qhLinks.keys().toSet(); - - switch (ltType) { - case UnlinkAll: - c->unlink(NULL); - ServerDB::removeLink(c, NULL); - dbus->channelStateChanged(c); - g_sServer->log(QString("Unlinked all from channel %1").arg(c->qsName), cCon); - g_sServer->sendAll(this); - return; - case Link: - c->link(l); - ServerDB::addLink(c, l); - dbus->channelStateChanged(c); - g_sServer->log(QString("Linked channel %1 and %2").arg(c->qsName).arg(l->qsName), cCon); - break; - case Unlink: - c->unlink(l); - ServerDB::removeLink(c, l); - dbus->channelStateChanged(c); - g_sServer->log(QString("Unlinked channel %1 and %2").arg(c->qsName).arg(l->qsName), cCon); - break; - case PushLink: - foreach(int tid, qlTargets) { - l=Channel::get(tid); - if (l && ChanACL::hasPermission(pSrcPlayer, l, ChanACL::LinkChannel)) - c->playerLink(l, pSrcPlayer); - } - break; - case PushUnlink: - foreach(int tid, qlTargets) { - l=Channel::get(tid); - if (l) - c->playerUnlink(l, pSrcPlayer); - } - break; - } - - QSet<Channel *> newset = c->qhLinks.keys().toSet(); - QSet<Channel *> changed; - - if (newset.count() == oldset.count()) - return; - - MessageChannelLink mcl; - mcl.iId = iId; - mcl.uiSession=uiSession; - - if (newset.count() > oldset.count()) { - mcl.ltType = Link; - changed = newset - oldset; - } else { - mcl.ltType = Unlink; - changed = oldset - newset; - } - foreach(l, changed) - mcl.qlTargets << l->iId; - g_sServer->sendAll(&mcl); -} - -void MessageTextMessage::process(Connection *cCon) { - MSG_SETUP(Player::Authenticated); - VICTIM_SETUP; - g_sServer->sendMessage(cDst, this); -} - -void MessageEditACL::process(Connection *cCon) { - MSG_SETUP(Player::Authenticated); - - Channel *c = Channel::get(iId); - if (!c) - return; - - if (! ChanACL::hasPermission(pSrcPlayer, c, ChanACL::Write)) { - PERM_DENIED(pSrcPlayer, c, ChanACL::Write); - return; - } - - MessageEditACL mea; - mea.iId = iId; - - if (bQuery) { - QStack<Channel *> chans; - Channel *p; - ChanACL *acl; - - p = c; - while (p) { - chans.push(p); - if ((p==c) || p->bInheritACL) - p = p->cParent; - else - p = NULL; - } - - mea.bQuery = false; - mea.bInheritACL = c->bInheritACL; - - while (! chans.isEmpty()) { - p = chans.pop(); - foreach(acl, p->qlACL) { - if ((p == c) || (acl->bApplySubs)) { - 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; - } - } - } - - p = c->cParent; - QSet<QString> allnames=Group::groupNames(c); - QString name; - foreach(name, allnames) { - Group *g = c->qhGroups.value(name); - Group *pg = p ? Group::getGroup(p, name) : NULL; - GroupStruct gs; - gs.qsName = name; - gs.bInherit = g ? g->bInherit : true; - gs.bInheritable = g ? g->bInheritable : true; - gs.bInherited = ((pg != NULL) && pg->bInheritable); - if (g) { - gs.qsAdd = g->qsAdd; - gs.qsRemove = g->qsRemove; - } - if (pg) - gs.qsInheritedMembers = pg->members(); - mea.groups << gs; - } - g_sServer->sendMessage(cCon, &mea); - } else { - Group *g; - ChanACL *a; - GroupStruct gs; - ACLStruct as; - - QHash<QString, QSet<int> > hOldTemp; - - foreach(g, c->qhGroups) { - hOldTemp.insert(g->qsName, g->qsTemporary); - delete g; - } - - foreach(a, c->qlACL) - delete a; - - c->qhGroups.clear(); - c->qlACL.clear(); - - c->bInheritACL = bInheritACL; - - foreach(gs, 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); - } - - foreach(as, acls) { - 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; - } - - ChanACL::clearCache(); - - if (! ChanACL::hasPermission(pSrcPlayer, c, ChanACL::Write)) { - a = new ChanACL(c); - a->bApplyHere=true; - a->bApplySubs=false; - a->iPlayerId=pSrcPlayer->iId; - a->pDeny=ChanACL::None; - a->pAllow=ChanACL::Write | ChanACL::Traverse; - - ChanACL::clearCache(); - } - - ServerDB::updateChannel(c); - g_sServer->log(QString("Updated ACL in channel %1(%2)").arg(c->qsName).arg(c->iId), cCon); - } -} - -void MessageQueryUsers::process(Connection *cCon) { - MSG_SETUP(Player::Authenticated); - - int i; - for (i=0;i<qlIds.count();i++) { - QString name = qlNames[i]; - int id = qlIds[i]; - if (id == -1) { - id = g_sServer->qhUserIDCache.value(name); - if (! g_sServer->qhUserIDCache.contains(name)) { - id = ServerDB::getUserID(name); - if (id != -1) - g_sServer->qhUserIDCache[name] = id; - } - qlIds[i] = id; - } else { - if (! g_sServer->qhUserNameCache.contains(id)) { - name = ServerDB::getUserName(id); - if (! name.isEmpty()) - g_sServer->qhUserNameCache[id] = name; - } - qlNames[i] = g_sServer->qhUserNameCache.value(id); - } - } - // Check if session is alive. - if (! Player::get(uiSession)) - return; - - g_sServer->sendMessage(cCon, this); -} - -void MessagePing::process(Connection *cCon) { - MSG_SETUP(Player::Authenticated); - g_sServer->sendMessage(cCon, this); -} - -void MessageTexture::process(Connection *cCon) { - MSG_SETUP(Player::Authenticated); - if (! g_sServer->qhUserTextureCache.contains(iPlayerId)) { - QByteArray qba = ServerDB::getUserTexture(iPlayerId); - if (! qba.isEmpty()) { - qba = qCompress(qba); - } - g_sServer->qhUserTextureCache.insert(iPlayerId, qba); - } - - // Check if session is alive. - if (! Player::get(uiSession)) - return; - - qbaTexture = g_sServer->qhUserTextureCache.value(iPlayerId); - if (! qbaTexture.isEmpty()) - g_sServer->sendMessage(cCon, this); } diff --git a/src/murmur/Server.h b/src/murmur/Server.h index e293d6ab4..045ad3f3f 100644 --- a/src/murmur/Server.h +++ b/src/murmur/Server.h @@ -34,9 +34,9 @@ #include "murmur_pch.h" #include "Message.h" #include "Timer.h" +#include "Player.h" +#include "Connection.h" -class Player; -class Connection; class Channel; class PacketDataStream; @@ -69,22 +69,6 @@ class LogEmitter : public QObject { void addLogEntry(const QString &msg); }; -class UDPThread : public QThread { - friend class Server; - Q_OBJECT; - protected: - QUdpSocket *qusUdp; - QHash<unsigned int, Peer> qhPeers; - QHash<unsigned int, QHostAddress> qhHosts; - void processMsg(PacketDataStream &pds, Connection *cCon); - void sendMessage(unsigned int id, const char *data, int len, QByteArray &cache); - signals: - void tcpTransmit(QByteArray, unsigned int id); - public: - void fakeUdpPacket(Message *msg, Connection *source); - void run(); -}; - class SslServer : public QTcpServer { Q_OBJECT; protected: @@ -95,7 +79,27 @@ class SslServer : public QTcpServer { SslServer(QObject *parent = NULL); }; -class Server : public QObject { +class Server; + + +// THIS is a no-go. Can't have multiple inheritance with QObjects. +// Though we don't use any of the signals from "Player"... +// Fug it. + +class User : public Connection, public Player { + Q_OBJECT + protected: + Server *s; + public: + BandwidthRecord bwr; + quint32 uiAddress; + quint16 usPort; + QHostAddress qha; + User(Server *parent, QSslSocket *socket); +}; + + +class Server : public QThread, public MessageHandler { Q_OBJECT; protected: QQueue<int> qqIds; @@ -107,14 +111,10 @@ class Server : public QObject { void sslError(const QList<QSslError> &); void message(QByteArray &, Connection *cCon = NULL); void checkTimeout(); - void tcpTransmit(QByteArray, unsigned int); + void tcpTransmitData(QByteArray, unsigned int); public: - QHash<unsigned int, Connection *> qmConnections; - QHash<Connection *, Player *> qmPlayers; - QHash<Connection *, BandwidthRecord *> qmBandwidth; - QReadWriteLock qrwlConnections; - - UDPThread *udp; + QHash<unsigned int, User *> qhUsers; + QReadWriteLock qrwlUsers; QHash<int, QByteArray> qhUserTextureCache; QHash<int, QString> qhUserNameCache; @@ -134,7 +134,70 @@ class Server : public QObject { void emitPacket(Message *msg); + User *getUser(unsigned int); + Server(QObject *parent = NULL); + + // Database / DBus functions. Implementation in ServerDB.cpp + typedef QPair<quint32, int> qpBan; + int authenticate(QString &name, const QString &pw); + bool hasUsers(); + Channel *addChannel(Channel *c, const QString &name); + void removeChannel(const Channel *c); + void readChannels(Channel *p = NULL); + void updateChannel(const Channel *c); + void readChannelPrivs(Channel *c); + void setLastChannel(const Player *p); + int readLastChannel(Player *p); + void dumpChannel(const Channel *c); + int getUserID(const QString &name); + QString getUserName(int id); + QByteArray getUserTexture(int id); + void setPW(int id, const QString &pw); + void addLink(Channel *c, Channel *l); + void removeLink(Channel *c, Channel *l); + QList<qpBan> getBans(); + void setBans(QList<qpBan> bans); + + + // From msgHandler. Implementation in Messages.cpp + virtual void msgSpeex(Connection *, MessageSpeex *); + virtual void msgServerAuthenticate(Connection *, MessageServerAuthenticate *); + virtual void msgPing(Connection *, MessagePing *); + 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 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 *); + + // UDP Handling + protected: + QUdpSocket *qusUdp; + QHash<unsigned int, Peer> qhPeers; + QHash<unsigned int, QHostAddress> qhHosts; + void processMsg(PacketDataStream &pds, Connection *cCon); + void sendMessage(unsigned int id, const char *data, int len, QByteArray &cache); + signals: + void tcpTransmit(QByteArray, unsigned int id); + public: + void fakeUdpPacket(Message *msg, Connection *source); + void run(); }; struct ServerParams { diff --git a/src/murmur/ServerDB.cpp b/src/murmur/ServerDB.cpp index a93d7df1e..71fab1eca 100644 --- a/src/murmur/ServerDB.cpp +++ b/src/murmur/ServerDB.cpp @@ -184,7 +184,7 @@ ServerDB::ServerDB() { query.exec(QString::fromLatin1("VACUUM")); } -bool ServerDB::hasUsers() { +bool Server::hasUsers() { TransactionHolder th; QSqlQuery query; @@ -200,7 +200,7 @@ bool ServerDB::hasUsers() { // -1 Wrong PW // -2 Anonymous -int ServerDB::authenticate(QString &name, const QString &pw) { +int Server::authenticate(QString &name, const QString &pw) { int res = dbus->authenticate(name, pw); if (res != -2) { @@ -241,7 +241,7 @@ int ServerDB::authenticate(QString &name, const QString &pw) { return res; } -void ServerDB::setPW(int id, const QString &pw) { +void Server::setPW(int id, const QString &pw) { TransactionHolder th; QCryptographicHash hash(QCryptographicHash::Sha1); @@ -255,7 +255,7 @@ void ServerDB::setPW(int id, const QString &pw) { query.exec(); } -QString ServerDB::getUserName(int id) { +QString Server::getUserName(int id) { QString name = dbus->mapIdToName(id); if (! name.isEmpty()) return name; @@ -271,7 +271,7 @@ QString ServerDB::getUserName(int id) { return name; } -int ServerDB::getUserID(const QString &name) { +int Server::getUserID(const QString &name) { int id = dbus->mapNameToId(name); if (id != -2) @@ -288,7 +288,7 @@ int ServerDB::getUserID(const QString &name) { return id; } -QByteArray ServerDB::getUserTexture(int id) { +QByteArray Server::getUserTexture(int id) { QByteArray qba=dbus->mapIdToTexture(id); if (! qba.isNull()) { return qba; @@ -306,7 +306,7 @@ QByteArray ServerDB::getUserTexture(int id) { return qba; } -void ServerDB::addLink(Channel *c, Channel *l) { +void Server::addLink(Channel *c, Channel *l) { TransactionHolder th; QSqlQuery query; @@ -321,7 +321,7 @@ void ServerDB::addLink(Channel *c, Channel *l) { query.exec(); } -void ServerDB::removeLink(Channel *c, Channel *l) { +void Server::removeLink(Channel *c, Channel *l) { TransactionHolder th; QSqlQuery query; @@ -344,19 +344,19 @@ void ServerDB::removeLink(Channel *c, Channel *l) { } } -Channel *ServerDB::addChannel(Channel *parent, const QString &name) { +Channel *Server::addChannel(Channel *p, const QString &name) { TransactionHolder th; QSqlQuery query; query.prepare(QString::fromLatin1("INSERT INTO %1channels (parent_id, name) VALUES (?,?)").arg(g_sp.qsDBPrefix)); - query.addBindValue(parent->iId); + query.addBindValue(p->iId); query.addBindValue(name); query.exec(); int id = query.lastInsertId().toInt(); - return Channel::add(id, name, parent); + return Channel::add(id, name, p); } -void ServerDB::removeChannel(const Channel *c) { +void Server::removeChannel(const Channel *c) { TransactionHolder th; QSqlQuery query; @@ -365,7 +365,7 @@ void ServerDB::removeChannel(const Channel *c) { query.exec(); } -void ServerDB::updateChannel(const Channel *c) { +void Server::updateChannel(const Channel *c) { TransactionHolder th; Group *g; ChanACL *acl; @@ -429,7 +429,7 @@ void ServerDB::updateChannel(const Channel *c) { } } -void ServerDB::readChannelPrivs(Channel *c) { +void Server::readChannelPrivs(Channel *c) { TransactionHolder th; int cid = c->iId; @@ -472,7 +472,7 @@ void ServerDB::readChannelPrivs(Channel *c) { } } -void ServerDB::readChannels(Channel *p) { +void Server::readChannels(Channel *p) { QList<Channel *> kids; Channel *c; QSqlQuery query; @@ -503,7 +503,7 @@ void ServerDB::readChannels(Channel *p) { readChannels(c); } -void ServerDB::setLastChannel(const Player *p) { +void Server::setLastChannel(const Player *p) { if (p->iId < 0) return; @@ -517,7 +517,7 @@ void ServerDB::setLastChannel(const Player *p) { query.exec(); } -int ServerDB::readLastChannel(Player *p) { +int Server::readLastChannel(Player *p) { Channel *c = Channel::get(0); @@ -539,7 +539,7 @@ int ServerDB::readLastChannel(Player *p) { return c->iId; } -void ServerDB::dumpChannel(const Channel *c) { +void Server::dumpChannel(const Channel *c) { Group *g; ChanACL *acl; int pid; @@ -568,7 +568,7 @@ void ServerDB::dumpChannel(const Channel *c) { } } -QList<ServerDB::qpBan> ServerDB::getBans() { +QList<Server::qpBan> Server::getBans() { TransactionHolder th; QList<qpBan> bans; @@ -584,7 +584,7 @@ QList<ServerDB::qpBan> ServerDB::getBans() { return bans; } -void ServerDB::setBans(QList<ServerDB::qpBan> bans) { +void Server::setBans(QList<Server::qpBan> bans) { TransactionHolder th; qpBan ban; diff --git a/src/murmur/ServerDB.h b/src/murmur/ServerDB.h index 39c19f55e..e06ca0c8f 100644 --- a/src/murmur/ServerDB.h +++ b/src/murmur/ServerDB.h @@ -37,30 +37,9 @@ class Channel; class Player; class Connection; -class ServerDB : public QObject { - Q_OBJECT +class ServerDB { public: - typedef QPair<QString, QList<QVariant> > qpCommand; - typedef QPair<quint32, int> qpBan; ServerDB(); - static int authenticate(QString &name, const QString &pw); - static bool hasUsers(); - static Channel *addChannel(Channel *c, const QString &name); - static void removeChannel(const Channel *c); - static void readChannels(Channel *p = NULL); - static void updateChannel(const Channel *c); - static void readChannelPrivs(Channel *c); - static void setLastChannel(const Player *p); - static int readLastChannel(Player *p); - static void dumpChannel(const Channel *c); - static int getUserID(const QString &name); - static QString getUserName(int id); - static QByteArray getUserTexture(int id); - static void setPW(int id, const QString &pw); - static void addLink(Channel *c, Channel *l); - static void removeLink(Channel *c, Channel *l); - static QList<qpBan> getBans(); - static void setBans(QList<qpBan> bans); }; #endif diff --git a/src/murmur/Tray.cpp b/src/murmur/Tray.cpp index 6f0db9ace..acb56e1cd 100644 --- a/src/murmur/Tray.cpp +++ b/src/murmur/Tray.cpp @@ -63,9 +63,8 @@ Tray::Tray(QObject *p, LogEmitter *logger) : QObject(p) { void Tray::on_Tray_activated(QSystemTrayIcon::ActivationReason r) {
if (r == QSystemTrayIcon::Trigger) {
- int numclients = g_sServer->qmConnections.count();
int port = g_sp.iPort;
- qsti->showMessage(tr("Murmur"), tr("Server running on port %1 with %2 conencted clients.").arg(port).arg(numclients), QSystemTrayIcon::Information, 5000);
+ qsti->showMessage(tr("Murmur"), tr("Server running on port %1.").arg(port), QSystemTrayIcon::Information, 5000);
}
}
diff --git a/src/murmur/murmur.cpp b/src/murmur/murmur.cpp index d051ad611..c7ea13c63 100644 --- a/src/murmur/murmur.cpp +++ b/src/murmur/murmur.cpp @@ -48,7 +48,6 @@ #include "Register.h" #include "Cert.h" -extern Server *g_sServer; MurmurDBus *dbus; QFile *logfile; @@ -173,7 +172,9 @@ int main(int argc, char **argv) { cert.initialize(); if (! supw.isEmpty()) { - ServerDB::setPW(0, supw); + // FIXME + + // ServerDB::setPW(0, supw); qFatal("Superuser password set"); } @@ -217,7 +218,11 @@ int main(int argc, char **argv) { MurmurDBus::registerTypes(); #endif - dbus=new MurmurDBus(a); + + Server s; + s.readChannels(); + + dbus=new MurmurDBus(a, &s); #ifdef Q_OS_UNIX if (! g_sp.qsDBus.isEmpty()) { QDBusConnection qdbc("mainbus"); @@ -246,11 +251,7 @@ int main(int argc, char **argv) { } #endif - db.readChannels(); - - Server s; - g_sServer = &s; - g_sServer->udp->start(QThread::HighestPriority); + s.start(QThread::HighestPriority); Register r; diff --git a/src/murmur/murmur.pro b/src/murmur/murmur.pro index f5ca7c219..17eba6e3e 100644 --- a/src/murmur/murmur.pro +++ b/src/murmur/murmur.pro @@ -14,7 +14,7 @@ LANGUAGE = C++ RC_FILE = murmur.rc FORMS = HEADERS = Server.h ServerDB.h Register.h Cert.h -SOURCES = murmur.cpp Server.cpp ServerDB.cpp Register.cpp Cert.cpp +SOURCES = murmur.cpp Server.cpp ServerDB.cpp Register.cpp Cert.cpp Messages.cpp HEADERS += ../ACL.h ../Group.h ../Channel.h ../Connection.h ../Player.h SOURCES += ../ACL.cpp ../Group.cpp ../Channel.cpp ../Message.cpp ../Connection.cpp ../Player.cpp ../Timer.cpp |