// 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 . #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 #include #include 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(); }