diff options
Diffstat (limited to 'src/mumble/ServerInformation.cpp')
-rw-r--r-- | src/mumble/ServerInformation.cpp | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/src/mumble/ServerInformation.cpp b/src/mumble/ServerInformation.cpp new file mode 100644 index 000000000..dd8e41278 --- /dev/null +++ b/src/mumble/ServerInformation.cpp @@ -0,0 +1,199 @@ +// Copyright 2021 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at <https://www.mumble.info/LICENSE>. + +#include "ServerInformation.h" +#include "CELTCodec.h" +#include "Connection.h" +#include "MainWindow.h" +#include "NetworkConfig.h" +#include "SSL.h" +#include "SSLCipherInfo.h" +#include "ServerHandler.h" +#include "UserModel.h" +#include "Version.h" +#include "ViewCert.h" +#include "Global.h" + +#include <QTableWidgetItem> + +#include <boost/accumulators/accumulators.hpp> + +#include <cmath> + +QString ServerInformation::m_unknownStr = tr("Unknown"); + +ServerInformation::ServerInformation(QWidget *parent) : QDialog(parent) { + setupUi(this); + + updateFields(); +} + +void ServerInformation::updateFields() { + updateServerInformation(); + updateAudioBandwidth(); + updateConnectionDetails(); +} + +void ServerInformation::on_okButton_clicked() { + accept(); +} + +void ServerInformation::on_viewCertButton_clicked() { + hide(); + + ViewCert certViewer(Global::get().sh->qscCert, this); + certViewer.exec(); + + accept(); +} + +void ServerInformation::updateServerInformation() { + QString host, userName, password; + unsigned short port; + + Global::get().sh->getConnectionInfo(host, port, userName, password); + + const int userCount = ModelItem::c_qhUsers.count(); + const unsigned int maxUserCount = Global::get().uiMaxUsers; + + QString release = Global::get().sh->qsRelease; + if (release.isEmpty()) { + release = m_unknownStr; + } + QString os = Global::get().sh->qsOS; + if (os.isEmpty()) { + os = m_unknownStr; + } else if (!Global::get().sh->qsOSVersion.isEmpty()) { + os += QString::fromLatin1(" (%1)").arg(Global::get().sh->qsOSVersion); + } + + serverInfo_host->setText(host); + serverInfo_port->setText(QString::number(port)); + serverInfo_users->setText(QString::fromLatin1("%1 / %2").arg(userCount).arg(maxUserCount)); + serverInfo_protocol->setText(MumbleVersion::toString(Global::get().sh->uiVersion)); + serverInfo_release->setText(release); + serverInfo_os->setText(os); +} + +static const QString currentCodec() { + if (Global::get().bOpus) + return QLatin1String("Opus"); + + int v = Global::get().bPreferAlpha ? Global::get().iCodecAlpha : Global::get().iCodecBeta; + CELTCodec *cc = Global::get().qmCodecs.value(v); + if (cc) + return QString::fromLatin1("CELT %1").arg(cc->version()); + else + return QString::fromLatin1("CELT %1").arg(QString::number(v, 16)); +} + +void ServerInformation::updateAudioBandwidth() { + // The bandwidths are in bit/s, so we divide by 1000 to get kBit/s + const float maxBandwidthAllowed = Global::get().iMaxBandwidth / 1000.0f; + const float currentBandwidth = Global::get().iAudioBandwidth / 1000.0f; + + audio_current->setText(QString::fromLatin1("%1 kBit/s").arg(currentBandwidth, 0, 'f', 1)); + audio_allowed->setText(QString::fromLatin1("%1 kBit/s").arg(maxBandwidthAllowed, 0, 'f', 1)); + audio_codec->setText(currentCodec()); +} + +QString getCipherID(const QSslCipher &cipher, const SSLCipherInfo *cipherInfo) { + if (cipherInfo && cipherInfo->rfc_name) { + return QString::fromUtf8(cipherInfo->rfc_name); + } + + return cipher.name(); +} + +void ServerInformation::updateConnectionDetails() { + QString latencyString = QString::fromUtf8("%1 ms (σ = %2 ms)"); + const ConnectionPtr connection = Global::get().sh->cConnection; + + if (!connection) { + return; + } + + // UDP + if (NetworkConfig::TcpModeEnabled()) { + connection_udp_infoMessage->show(); + + connection_udp_encryption->hide(); + connection_udp_encryptionLabel->hide(); + connection_udp_latency->hide(); + connection_udp_latencyLabel->hide(); + connection_udp_statisticsGroup->hide(); + } else { + connection_udp_infoMessage->hide(); + + connection_udp_encryption->show(); + connection_udp_encryptionLabel->show(); + connection_udp_latency->show(); + connection_udp_latencyLabel->show(); + connection_udp_statisticsGroup->show(); + + // Actually fill in data + const float latency = boost::accumulators::mean(Global::get().sh->accUDP); + const float deviation = std::sqrt(boost::accumulators::variance(Global::get().sh->accUDP)); + + connection_udp_encryption->setText("128 bit OCB-AES128"); + connection_udp_latency->setText(latencyString.arg(latency, 0, 'f', 1).arg(deviation, 0, 'f', 1)); + + populateUDPStatistics(*connection); + } + + + // TCP + const float latency = boost::accumulators::mean(Global::get().sh->accTCP); + const float deviation = std::sqrt(boost::accumulators::variance(Global::get().sh->accTCP)); + + QSslCipher cipher = Global::get().sh->qscCipher; + const SSLCipherInfo *cipherInfo = SSLCipherInfoLookupByOpenSSLName(cipher.name().toLatin1().constData()); + + const QString cipherID = getCipherID(cipher, cipherInfo); + + connection_tcp_tls->setText(MumbleSSL::protocolToString(connection->sessionProtocol()).toHtmlEscaped()); + connection_tcp_latency->setText(latencyString.arg(latency, 0, 'f', 1).arg(deviation, 0, 'f', 1)); + connection_tcp_cipher->setText(cipherID.isEmpty() ? m_unknownStr : cipherID); + + if (cipherInfo) { + if (cipherInfo->forward_secret) { + connection_tcp_forwardSecrecy->setText(tr("The connection provides perfect forward secrecy.")); + } else { + connection_tcp_forwardSecrecy->setText(tr("The connection does NOT provide perfect forward secrecy.")); + } + } else { + connection_tcp_forwardSecrecy->setText(tr("No information about forward secrecy available.")); + } +} + +void ServerInformation::populateUDPStatistics(const Connection &connection) { + // statistics + constexpr int toServerCol = 0; + constexpr int fromServerCol = 1; + constexpr int goodRow = 0; + constexpr int lateRow = 1; + constexpr int lostRow = 2; + constexpr int resyncRow = 3; + + QTableWidgetItem *toGoodItem = new QTableWidgetItem(QString::number(connection.csCrypt->uiRemoteGood)); + QTableWidgetItem *fromGoodItem = new QTableWidgetItem(QString::number(connection.csCrypt->uiGood)); + QTableWidgetItem *toLateItem = new QTableWidgetItem(QString::number(connection.csCrypt->uiRemoteLate)); + QTableWidgetItem *fromLateItem = new QTableWidgetItem(QString::number(connection.csCrypt->uiLate)); + QTableWidgetItem *toLostItem = new QTableWidgetItem(QString::number(connection.csCrypt->uiRemoteLost)); + QTableWidgetItem *fromLostItem = new QTableWidgetItem(QString::number(connection.csCrypt->uiLost)); + QTableWidgetItem *toResyncItem = new QTableWidgetItem(QString::number(connection.csCrypt->uiRemoteResync)); + QTableWidgetItem *fromResyncItem = new QTableWidgetItem(QString::number(connection.csCrypt->uiResync)); + + connection_udp_statisticsTable->setItem(goodRow, toServerCol, toGoodItem); + connection_udp_statisticsTable->setItem(goodRow, fromServerCol, fromGoodItem); + connection_udp_statisticsTable->setItem(lateRow, toServerCol, toLateItem); + connection_udp_statisticsTable->setItem(lateRow, fromServerCol, fromLateItem); + connection_udp_statisticsTable->setItem(lostRow, toServerCol, toLostItem); + connection_udp_statisticsTable->setItem(lostRow, fromServerCol, fromLostItem); + connection_udp_statisticsTable->setItem(resyncRow, toServerCol, toResyncItem); + connection_udp_statisticsTable->setItem(resyncRow, fromServerCol, fromResyncItem); + + connection_udp_statisticsTable->adjustSize(); +} |