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

github.com/mumble-voip/mumble.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThorvald Natvig <slicer@users.sourceforge.net>2007-07-31 19:51:34 +0400
committerThorvald Natvig <slicer@users.sourceforge.net>2007-07-31 19:51:34 +0400
commit6d6bcff7c7e76b175786bbf245917c1854ee0cf6 (patch)
tree643f7f9e14080c1a2baa07d4d8f64fbc1b9a9c85 /src
parent93f186081a806c2472f5b025d122d575b7386899 (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.cpp4
-rw-r--r--src/Connection.cpp2
-rw-r--r--src/Connection.h2
-rw-r--r--src/Message.cpp79
-rw-r--r--src/Message.h82
-rw-r--r--src/Player.cpp37
-rw-r--r--src/Player.h23
-rw-r--r--src/mumble/GlobalShortcut_win.cpp2
-rw-r--r--src/murmur/DBus.cpp74
-rw-r--r--src/murmur/DBus_real.h4
-rw-r--r--src/murmur/Messages.cpp813
-rw-r--r--src/murmur/Server.cpp947
-rw-r--r--src/murmur/Server.h115
-rw-r--r--src/murmur/ServerDB.cpp40
-rw-r--r--src/murmur/ServerDB.h23
-rw-r--r--src/murmur/Tray.cpp3
-rw-r--r--src/murmur/murmur.cpp17
-rw-r--r--src/murmur/murmur.pro2
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