diff options
author | Thorvald Natvig <slicer@users.sourceforge.net> | 2007-08-11 18:33:20 +0400 |
---|---|---|
committer | Thorvald Natvig <slicer@users.sourceforge.net> | 2007-08-11 18:33:20 +0400 |
commit | 36f625a58371623d24dd3cff6d51725ff71a7cd4 (patch) | |
tree | 9951797c3d4b3e55c14a8f3a664de071c42699f3 /src | |
parent | 467316a9c016cc79e16b7360c6b6cc0bd7695eca (diff) |
Start of proper statistics
git-svn-id: https://mumble.svn.sourceforge.net/svnroot/mumble/trunk@723 05730e5d-ab1b-0410-a4ac-84af385074fa
Diffstat (limited to 'src')
-rw-r--r-- | src/Connection.cpp | 12 | ||||
-rw-r--r-- | src/Connection.h | 9 | ||||
-rw-r--r-- | src/CryptState.cpp | 9 | ||||
-rw-r--r-- | src/CryptState.h | 12 | ||||
-rw-r--r-- | src/Message.cpp | 14 | ||||
-rw-r--r-- | src/Message.h | 24 | ||||
-rw-r--r-- | src/PacketDataStream.h | 18 | ||||
-rw-r--r-- | src/mumble/MainWindow.cpp | 33 | ||||
-rw-r--r-- | src/mumble/MainWindow.h | 1 | ||||
-rw-r--r-- | src/mumble/Messages.cpp | 4 | ||||
-rw-r--r-- | src/mumble/ServerHandler.cpp | 46 | ||||
-rw-r--r-- | src/mumble/ServerHandler.h | 4 | ||||
-rw-r--r-- | src/murmur/Messages.cpp | 26 | ||||
-rw-r--r-- | src/murmur/Server.h | 1 | ||||
-rw-r--r-- | src/tests/TestPacketDataStream.cpp | 26 |
15 files changed, 199 insertions, 40 deletions
diff --git a/src/Connection.cpp b/src/Connection.cpp index 533f143c1..44d1865df 100644 --- a/src/Connection.cpp +++ b/src/Connection.cpp @@ -48,6 +48,11 @@ Connection::Connection(QObject *p, QSslSocket *qtsSock) : QObject(p) { iPacketLength = -1; bDisconnectedEmitted = false; bReentry = false; + + dUDPPingAvg = dUDPPingVar = 0.0L; + dTCPPingAvg = dTCPPingVar = 0.0L; + uiUDPPackets = uiTCPPackets = 0; + connect(qtsSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError))); connect(qtsSocket, SIGNAL(readyRead()), this, SLOT(socketRead())); connect(qtsSocket, SIGNAL(disconnected()), this, SLOT(socketDisconnected())); @@ -168,6 +173,13 @@ void Connection::disconnectSocket() { qtsSocket->disconnectFromHost(); } +void Connection::updatePing(double &avg, double &var, quint32 &samples, quint64 usec) { + samples++; + double x = usec / 1000.0L; + double delta = x - avg; + avg += delta / (samples * 1.0L); + var += delta * (x - avg); +}; QHostAddress Connection::peerAddress() const { return qtsSocket->peerAddress(); diff --git a/src/Connection.h b/src/Connection.h index abcf8f4f9..40635238e 100644 --- a/src/Connection.h +++ b/src/Connection.h @@ -66,6 +66,15 @@ class Connection : public QObject { CryptState csCrypt; + double dUDPPingAvg; + double dUDPPingVar; + quint32 uiUDPPackets; + double dTCPPingAvg; + double dTCPPingVar; + quint32 uiTCPPackets; + + static void updatePing(double &avg, double &var, quint32 &samples, quint64 usec); + QList<QSslCertificate> peerCertificateChain() const; QSslCipher sessionCipher() const; QHostAddress peerAddress() const; diff --git a/src/CryptState.cpp b/src/CryptState.cpp index 73fbd9176..b3b6bdd42 100644 --- a/src/CryptState.cpp +++ b/src/CryptState.cpp @@ -43,7 +43,8 @@ CryptState::CryptState() { for (int i=0;i<0x100;i++) decrypt_history[i] = 0; bInit = false; - stat_good=stat_late=stat_lost = 0; + uiGood=uiLate=uiLost=uiResync=0; + uiRemoteGood=uiRemoteLate=uiRemoteLost=uiRemoteResync=0; } bool CryptState::isValid() const { @@ -174,9 +175,9 @@ bool CryptState::decrypt(const unsigned char *source, unsigned char *dst, unsign if (restore) memcpy(decrypt_iv, saveiv, AES_BLOCK_SIZE); - stat_good++; - stat_late += late; - stat_lost += lost; + uiGood++; + uiLate += late; + uiLost += lost; tLastGood.restart(); return true; diff --git a/src/CryptState.h b/src/CryptState.h index f804a9325..7ad598576 100644 --- a/src/CryptState.h +++ b/src/CryptState.h @@ -41,9 +41,15 @@ class CryptState { unsigned char decrypt_iv[AES_BLOCK_SIZE]; unsigned char decrypt_history[0x100]; - unsigned int stat_good; - unsigned int stat_late; - unsigned int stat_lost; + unsigned int uiGood; + unsigned int uiLate; + unsigned int uiLost; + unsigned int uiResync; + + unsigned int uiRemoteGood; + unsigned int uiRemoteLate; + unsigned int uiRemoteLost; + unsigned int uiRemoteResync; AES_KEY encrypt_key; AES_KEY decrypt_key; diff --git a/src/Message.cpp b/src/Message.cpp index bc0c23960..7162bf2e8 100644 --- a/src/Message.cpp +++ b/src/Message.cpp @@ -139,6 +139,9 @@ Message *Message::networkToMessage(PacketDataStream &qdsIn) { case Ping: mMsg = new MessagePing(); break; + case PingStats: + mMsg = new MessagePingStats(); + break; case PlayerTexture: mMsg = new MessageTexture(); break; @@ -246,6 +249,9 @@ void MessageHandler::dispatch(Connection *cCon, Message *msg) { case Message::Ping: msgPing(cCon, static_cast<MessagePing *>(msg)); break; + case Message::PingStats: + msgPingStats(cCon, static_cast<MessagePingStats *>(msg)); + break; case Message::PlayerTexture: msgTexture(cCon, static_cast<MessageTexture *>(msg)); break; @@ -278,6 +284,14 @@ void MessagePing::restoreStream(PacketDataStream &qdsIn) { qdsIn >> uiTimestamp; } +void MessagePingStats::saveStream(PacketDataStream &qdsOut) const { + qdsOut << uiTimestamp << uiGood << uiLate << uiLost << uiResync << dUDPPingAvg << dUDPPingVar << uiUDPPackets << dTCPPingAvg << dTCPPingVar << uiTCPPackets; +} + +void MessagePingStats::restoreStream(PacketDataStream &qdsIn) { + qdsIn >> uiTimestamp >> uiGood >> uiLate >> uiLost >> uiResync >> dUDPPingAvg >> dUDPPingVar >> uiUDPPackets >> dTCPPingAvg >> dTCPPingVar >> uiTCPPackets; +} + MessageServerAuthenticate::MessageServerAuthenticate() { iVersion = MESSAGE_STREAM_VERSION; iMaxBandwidth = 100000; diff --git a/src/Message.h b/src/Message.h index 87f6e0c01..f618c552e 100644 --- a/src/Message.h +++ b/src/Message.h @@ -43,7 +43,7 @@ class Message { virtual void saveStream(PacketDataStream &) const; virtual void restoreStream(PacketDataStream &); public: - enum MessageType { ServerReject, ServerAuthenticate, Speex, ServerSync, ServerJoin, ServerLeave, ServerBanList, PlayerMute, PlayerDeaf, PlayerKick, PlayerRename, PlayerBan, PlayerMove, PlayerSelfMuteDeaf, ChannelAdd, ChannelRemove, ChannelMove, ChannelLink, ChannelRename, PermissionDenied, EditACL, QueryUsers, Ping, TextMessage, PlayerTexture, CryptSetup, CryptSync }; + enum MessageType { ServerReject, ServerAuthenticate, Speex, ServerSync, ServerJoin, ServerLeave, ServerBanList, PlayerMute, PlayerDeaf, PlayerKick, PlayerRename, PlayerBan, PlayerMove, PlayerSelfMuteDeaf, ChannelAdd, ChannelRemove, ChannelMove, ChannelLink, ChannelRename, PermissionDenied, EditACL, QueryUsers, Ping, TextMessage, PlayerTexture, CryptSetup, CryptSync, PingStats }; unsigned int uiSession; Message(); @@ -98,6 +98,27 @@ class MessagePing : public Message { }; }; +class MessagePingStats : public Message { + protected: + void saveStream(PacketDataStream &) const; + void restoreStream(PacketDataStream &); + public: + quint64 uiTimestamp; + quint32 uiGood; + quint32 uiLate; + quint32 uiLost; + quint32 uiResync; + double dUDPPingAvg; + double dUDPPingVar; + quint32 uiUDPPackets; + double dTCPPingAvg; + double dTCPPingVar; + quint32 uiTCPPackets; + Message::MessageType messageType() const { + return PingStats; + }; +}; + class MessageServerReject : public Message { protected: void saveStream(PacketDataStream &) const; @@ -418,6 +439,7 @@ class MessageHandler { virtual void msgSpeex(Connection *, MessageSpeex *) = 0; virtual void msgServerAuthenticate(Connection *, MessageServerAuthenticate *) = 0; virtual void msgPing(Connection *, MessagePing *) = 0; + virtual void msgPingStats(Connection *, MessagePingStats *) = 0; virtual void msgServerReject(Connection *, MessageServerReject *) = 0; virtual void msgServerSync(Connection *, MessageServerSync *) = 0; virtual void msgServerJoin(Connection *, MessageServerJoin *) = 0; diff --git a/src/PacketDataStream.h b/src/PacketDataStream.h index 6ee6ec34e..07ed08e15 100644 --- a/src/PacketDataStream.h +++ b/src/PacketDataStream.h @@ -293,6 +293,24 @@ class PacketDataStream { INTMAPOPERATOR(char); INTMAPOPERATOR(unsigned char); + union double64u { + quint64 ui; + double d; + }; + + PacketDataStream &operator <<(const double v) { + double64u u; + u.d = v; + return *this << u.ui; + } + + PacketDataStream &operator >>(double &v) { + double64u u; + *this >> u.ui; + v = u.d; + return *this; + } + template <typename T> PacketDataStream &operator <<(const QList<T> &l) { *this << l.size(); diff --git a/src/mumble/MainWindow.cpp b/src/mumble/MainWindow.cpp index 7dbf54769..2f084b1fe 100644 --- a/src/mumble/MainWindow.cpp +++ b/src/mumble/MainWindow.cpp @@ -530,23 +530,32 @@ void MainWindow::on_ServerBanList_triggered() { } void MainWindow::on_ServerInformation_triggered() { + ConnectionPtr c = g.sh->cConnection; + + if (! c) + return; + + CryptState &cs = c->csCrypt; QSslCipher qsc = g.sh->qscCipher; - QMessageBox qmb(QMessageBox::Information, tr("Mumble Server Information"), - tr("Control channel: %1 ms latency, Encrypted with %3 bit %4<br />" - "Voice channel: %2 ms latency, Encrypted with OCB-AES128" - ).arg(g.sh->uiTCPPing / 1000.0, 0, 'f', 2).arg(g.sh->uiUDPPing / 1000.0, 0, 'f', 2).arg(qsc.usedBits()).arg(qsc.name()), QMessageBox::Ok, this); - qmb.setDefaultButton(QMessageBox::Ok); - qmb.setEscapeButton(QMessageBox::Ok); + /*FIXME + QMessageBox qmb(QMessageBox::Information, tr("Mumble Server Information"), + tr("Control channel: %1 ms latency, Encrypted with %3 bit %4<br />" + "Voice channel: %2 ms latency, Encrypted with OCB-AES128" + ).arg(g.sh->uiTCPPing / 1000.0, 0, 'f', 2).arg(g.sh->uiUDPPing / 1000.0, 0, 'f', 2).arg(qsc.usedBits()).arg(qsc.name()), QMessageBox::Ok, this); - QPushButton *qp = qmb.addButton(tr("&View Certificate"), QMessageBox::ActionRole); - int res = qmb.exec(); - if ((res == 0) && (qmb.clickedButton() == qp)) { - ViewCert vc(g.sh->qscCert, this); - vc.exec(); - } + qmb.setDefaultButton(QMessageBox::Ok); + qmb.setEscapeButton(QMessageBox::Ok); + + QPushButton *qp = qmb.addButton(tr("&View Certificate"), QMessageBox::ActionRole); + int res = qmb.exec(); + if ((res == 0) && (qmb.clickedButton() == qp)) { + ViewCert vc(g.sh->qscCert, this); + vc.exec(); + } + */ } void MainWindow::on_PlayerMenu_aboutToShow() { diff --git a/src/mumble/MainWindow.h b/src/mumble/MainWindow.h index 309514846..26adeb608 100644 --- a/src/mumble/MainWindow.h +++ b/src/mumble/MainWindow.h @@ -144,6 +144,7 @@ class MainWindow : public QMainWindow, public MessageHandler { virtual void msgSpeex(Connection *, MessageSpeex *); virtual void msgServerAuthenticate(Connection *, MessageServerAuthenticate *); virtual void msgPing(Connection *, MessagePing *); + virtual void msgPingStats(Connection *, MessagePingStats *); virtual void msgServerReject(Connection *, MessageServerReject *); virtual void msgServerSync(Connection *, MessageServerSync *); virtual void msgServerJoin(Connection *, MessageServerJoin *); diff --git a/src/mumble/Messages.cpp b/src/mumble/Messages.cpp index 019458a5b..e289b89c8 100644 --- a/src/mumble/Messages.cpp +++ b/src/mumble/Messages.cpp @@ -343,6 +343,9 @@ void MainWindow::msgQueryUsers(Connection *, MessageQueryUsers *msg) { void MainWindow::msgPing(Connection *, MessagePing *) { } +void MainWindow::msgPingStats(Connection *, MessagePingStats *) { +} + void MainWindow::msgTexture(Connection *, MessageTexture *msg) { if (! msg->qbaTexture.isEmpty()) g.o->textureResponse(msg->iPlayerId,msg->qbaTexture); @@ -363,6 +366,7 @@ void MainWindow::msgCryptSync(Connection *, MessageCryptSync *msg) { msg->qbaNonce = QByteArray(reinterpret_cast<const char *>(c->csCrypt.encrypt_iv), AES_BLOCK_SIZE); g.sh->sendMessage(msg); } else if (msg->qbaNonce.size() == AES_BLOCK_SIZE) { + c->csCrypt.uiResync++; memcpy(c->csCrypt.decrypt_iv, msg->qbaNonce.constData(), AES_BLOCK_SIZE); } } diff --git a/src/mumble/ServerHandler.cpp b/src/mumble/ServerHandler.cpp index c91180bd5..fb2ee6435 100644 --- a/src/mumble/ServerHandler.cpp +++ b/src/mumble/ServerHandler.cpp @@ -48,8 +48,6 @@ ServerHandler::ServerHandler() { cConnection.reset(); qusUdp = NULL; - uiTCPPing = uiUDPPing = 0LL; - // For some strange reason, on Win32, we have to call supportsSsl before the cipher list is ready. qWarning("OpenSSL Support: %d", QSslSocket::supportsSsl()); @@ -122,7 +120,7 @@ void ServerHandler::udpReady() { if (msgType == Message::Ping) { quint64 t; pds >> t; - uiUDPPing = tTimestamp.elapsed() - t; + Connection::updatePing(cConnection->dUDPPingAvg, cConnection->dUDPPingVar, cConnection->uiUDPPackets, tTimestamp.elapsed() - t); } else if (msgType == Message::Speex) { ClientPlayer *p = ClientPlayer::get(uiSession); AudioOutputPtr ao = g.ao; @@ -142,11 +140,11 @@ void ServerHandler::udpReady() { } } -void ServerHandler::sendMessage(Message *mMsg, bool forceTCP) { +void ServerHandler::sendMessage(Message *mMsg) { bool mayUdp = (mMsg->messageType() == Message::Speex) || (mMsg->messageType() == Message::Ping); mMsg->uiSession = g.uiSession; - if (! forceTCP && mayUdp && ! g.s.bTCPCompat) { + if (mayUdp && ! g.s.bTCPCompat) { QMutexLocker qml(&qmUdp); if (! qusUdp) return; @@ -174,8 +172,6 @@ void ServerHandler::run() { qlErrors.clear(); qscCert.clear(); - uiUDPPing = uiTCPPing = 0LL; - connect(qtsSock, SIGNAL(encrypted()), this, SLOT(serverConnectionConnected())); connect(cConnection.get(), SIGNAL(connectionClosed(QString)), this, SLOT(serverConnectionClosed(QString))); connect(cConnection.get(), SIGNAL(message(QByteArray &)), this, SLOT(message(QByteArray &))); @@ -200,7 +196,6 @@ void ServerHandler::run() { ticker->stop(); cConnection->disconnectSocket(); cConnection.reset(); - } void ServerHandler::setSslErrors(const QList<QSslError> &errors) { @@ -212,12 +207,24 @@ void ServerHandler::setSslErrors(const QList<QSslError> &errors) { } void ServerHandler::sendPing() { - MessagePing mp; - mp.uiTimestamp = tTimestamp.elapsed(); - - sendMessage(&mp, true); - if (! g.s.bTCPCompat) - sendMessage(&mp, false); + CryptState &cs = cConnection->csCrypt; + MessagePingStats mps; + mps.uiTimestamp = tTimestamp.elapsed(); + mps.uiGood = cs.uiGood; + mps.uiLate = cs.uiLate; + mps.uiLost = cs.uiLost; + mps.uiResync = cs.uiResync; + mps.dUDPPingAvg = cConnection->dUDPPingAvg; + mps.dUDPPingVar = cConnection->dUDPPingVar; + mps.dTCPPingAvg = cConnection->dTCPPingAvg; + mps.dTCPPingVar = cConnection->dTCPPingVar; + sendMessage(&mps); + + if (! g.s.bTCPCompat) { + MessagePing mp; + mp.uiTimestamp = mps.uiTimestamp; + sendMessage(&mp); + } } void ServerHandler::message(QByteArray &qbaMsg) { @@ -242,9 +249,14 @@ void ServerHandler::message(QByteArray &qbaMsg) { ao->removeBuffer(p); } } - } else if (mMsg->messageType() == Message::Ping) { - MessagePing *mpMsg = static_cast<MessagePing *>(mMsg); - uiTCPPing = tTimestamp.elapsed() - mpMsg->uiTimestamp; + } else if (mMsg->messageType() == Message::PingStats) { + MessagePingStats *mpsMsg = static_cast<MessagePingStats *>(mMsg); + CryptState &cs = cConnection->csCrypt; + cs.uiRemoteGood = mpsMsg->uiGood; + cs.uiRemoteLate = mpsMsg->uiLate; + cs.uiRemoteLost = mpsMsg->uiLost; + cs.uiRemoteResync = mpsMsg->uiResync; + Connection::updatePing(cConnection->dTCPPingAvg, cConnection->dTCPPingVar, cConnection->uiTCPPackets, tTimestamp.elapsed() - mpsMsg->uiTimestamp); } else { if (mMsg->messageType() == Message::ServerLeave) { if (ao) diff --git a/src/mumble/ServerHandler.h b/src/mumble/ServerHandler.h index aa0e8eb51..9d4737e90 100644 --- a/src/mumble/ServerHandler.h +++ b/src/mumble/ServerHandler.h @@ -66,14 +66,12 @@ class ServerHandler : public QThread { QSslCipher qscCipher; ConnectionPtr cConnection; - quint64 uiUDPPing, uiTCPPing; - ServerHandler(); ~ServerHandler(); void setConnectionInfo(const QString &host, int port, const QString &username, const QString &pw); void getConnectionInfo(QString &host, int &port, QString &username, QString &pw); void customEvent(QEvent *evt); - void sendMessage(Message *m, bool forceTCP=false); + void sendMessage(Message *m); void disconnect(); void run(); signals: diff --git a/src/murmur/Messages.cpp b/src/murmur/Messages.cpp index a7c5f64c6..c51048974 100644 --- a/src/murmur/Messages.cpp +++ b/src/murmur/Messages.cpp @@ -811,6 +811,31 @@ void Server::msgPing(Connection *cCon, MessagePing *msg) { sendMessage(cCon, msg); } +void Server::msgPingStats(Connection *cCon, MessagePingStats *msg) { + MSG_SETUP(Player::Authenticated); + CryptState &cs=uSource->csCrypt; + cs.uiRemoteGood = msg->uiGood; + cs.uiRemoteLate = msg->uiLate; + cs.uiRemoteLost = msg->uiLost; + cs.uiRemoteResync = msg->uiResync; + + uSource->dUDPPingAvg = msg->dUDPPingAvg; + uSource->dUDPPingVar = msg->dUDPPingVar; + uSource->uiUDPPackets = msg->uiUDPPackets; + uSource->dTCPPingAvg = msg->dTCPPingAvg; + uSource->dTCPPingVar = msg->dTCPPingVar; + uSource->uiTCPPackets = msg->uiTCPPackets; + + msg->uiGood = cs.uiGood; + msg->uiLate = cs.uiLate; + msg->uiLost = cs.uiLost; + msg->uiResync = cs.uiResync; + + msg->dUDPPingAvg = msg->dUDPPingVar = msg->dTCPPingAvg = msg->dTCPPingVar = 0.0L; + msg->uiUDPPackets = msg->uiTCPPackets = 0; + sendMessage(cCon, msg); +} + void Server::msgTexture(Connection *cCon, MessageTexture *msg) { MSG_SETUP(Player::Authenticated); if (! qhUserTextureCache.contains(msg->iPlayerId)) { @@ -837,6 +862,7 @@ void Server::msgCryptSync(Connection *cCon, MessageCryptSync *msg) { msg->qbaNonce = QByteArray(reinterpret_cast<const char *>(uSource->csCrypt.encrypt_iv), AES_BLOCK_SIZE); sendMessage(cCon, msg); } else if (msg->qbaNonce.size() == AES_BLOCK_SIZE) { + uSource->csCrypt.uiResync++; memcpy(uSource->csCrypt.decrypt_iv, msg->qbaNonce.constData(), AES_BLOCK_SIZE); } else { cCon->disconnectSocket(); diff --git a/src/murmur/Server.h b/src/murmur/Server.h index 91659876c..d9e6a534b 100644 --- a/src/murmur/Server.h +++ b/src/murmur/Server.h @@ -221,6 +221,7 @@ class Server : public QThread, public MessageHandler { virtual void msgSpeex(Connection *, MessageSpeex *); virtual void msgServerAuthenticate(Connection *, MessageServerAuthenticate *); virtual void msgPing(Connection *, MessagePing *); + virtual void msgPingStats(Connection *, MessagePingStats *); virtual void msgServerReject(Connection *, MessageServerReject *); virtual void msgServerSync(Connection *, MessageServerSync *); virtual void msgServerJoin(Connection *, MessageServerJoin *); diff --git a/src/tests/TestPacketDataStream.cpp b/src/tests/TestPacketDataStream.cpp index 2e72cd90b..7aad73ceb 100644 --- a/src/tests/TestPacketDataStream.cpp +++ b/src/tests/TestPacketDataStream.cpp @@ -13,8 +13,34 @@ class TestPacketDataStream : public QObject { void string(); void string_data(); void space(); + void floating(); + void floating_data(); }; +void TestPacketDataStream::floating_data() { + QTest::addColumn<double>("value"); + for (int i=1;i<256;i++) { + double v = 1.0L / (1.0L * i); + QTest::newRow("Positive") << v; + QTest::newRow("Negative") << -v; + } +} + +void TestPacketDataStream::floating() { + QFETCH(double, value); + + char buff[256]; + double d; + + PacketDataStream out(buff, 256); + out << value; + PacketDataStream in(buff, out.size()); + in >> d; + QCOMPARE(value, d); + QVERIFY(in.isValid()); + QVERIFY(in.left() == 0); +} + void TestPacketDataStream::integer_data() { QTest::addColumn<quint64>("value"); for (int i=0;i<64;i++) { |