summaryrefslogtreecommitdiff
path: root/Source/Core/DolphinQt/Debugger/NetworkWidget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/DolphinQt/Debugger/NetworkWidget.cpp')
-rw-r--r--Source/Core/DolphinQt/Debugger/NetworkWidget.cpp301
1 files changed, 301 insertions, 0 deletions
diff --git a/Source/Core/DolphinQt/Debugger/NetworkWidget.cpp b/Source/Core/DolphinQt/Debugger/NetworkWidget.cpp
new file mode 100644
index 0000000000..8adee91ca2
--- /dev/null
+++ b/Source/Core/DolphinQt/Debugger/NetworkWidget.cpp
@@ -0,0 +1,301 @@
+// Copyright 2020 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include "DolphinQt/Debugger/NetworkWidget.h"
+
+#include <QCheckBox>
+#include <QGridLayout>
+#include <QGroupBox>
+#include <QHeaderView>
+#include <QTableWidget>
+#include <QVBoxLayout>
+
+#ifdef _WIN32
+#include <winsock2.h>
+#else
+#include <sys/socket.h>
+#include <sys/types.h>
+#endif
+
+#include "Core/ConfigManager.h"
+#include "Core/IOS/Network/SSL.h"
+#include "Core/IOS/Network/Socket.h"
+#include "DolphinQt/Host.h"
+#include "DolphinQt/Settings.h"
+
+namespace
+{
+QTableWidgetItem* GetSocketDomain(s32 host_fd)
+{
+ if (host_fd < 0)
+ return new QTableWidgetItem();
+
+ sockaddr sa;
+ socklen_t sa_len = sizeof(sa);
+ const int ret = getsockname(host_fd, &sa, &sa_len);
+ if (ret != 0)
+ return new QTableWidgetItem(QTableWidget::tr("Unknown"));
+
+ switch (sa.sa_family)
+ {
+ case 2:
+ return new QTableWidgetItem(QLatin1Literal("AF_INET"));
+ case 23:
+ return new QTableWidgetItem(QLatin1Literal("AF_INET6"));
+ default:
+ return new QTableWidgetItem(QString::number(sa.sa_family));
+ }
+}
+
+QTableWidgetItem* GetSocketType(s32 host_fd)
+{
+ if (host_fd < 0)
+ return new QTableWidgetItem();
+
+ int so_type;
+ socklen_t opt_len = sizeof(so_type);
+ const int ret =
+ getsockopt(host_fd, SOL_SOCKET, SO_TYPE, reinterpret_cast<char*>(&so_type), &opt_len);
+ if (ret != 0)
+ return new QTableWidgetItem(QTableWidget::tr("Unknown"));
+
+ switch (so_type)
+ {
+ case 1:
+ return new QTableWidgetItem(QLatin1Literal("SOCK_STREAM"));
+ case 2:
+ return new QTableWidgetItem(QLatin1Literal("SOCK_DGRAM"));
+ default:
+ return new QTableWidgetItem(QString::number(so_type));
+ }
+}
+
+QTableWidgetItem* GetSocketState(s32 host_fd)
+{
+ if (host_fd < 0)
+ return new QTableWidgetItem();
+
+ sockaddr_in peer_addr;
+ socklen_t peer_addr_len = sizeof(sockaddr_in);
+ if (getpeername(host_fd, reinterpret_cast<sockaddr*>(&peer_addr), &peer_addr_len) == 0)
+ return new QTableWidgetItem(QTableWidget::tr("Connected"));
+
+ int so_accept = 0;
+ socklen_t opt_len = sizeof(so_accept);
+ const int ret =
+ getsockopt(host_fd, SOL_SOCKET, SO_ACCEPTCONN, reinterpret_cast<char*>(&so_accept), &opt_len);
+ if (ret == 0 && so_accept > 0)
+ return new QTableWidgetItem(QTableWidget::tr("Listening"));
+ return new QTableWidgetItem(QTableWidget::tr("Unbound"));
+}
+
+QTableWidgetItem* GetSocketName(s32 host_fd)
+{
+ if (host_fd < 0)
+ return new QTableWidgetItem();
+
+ sockaddr_in sock_addr;
+ socklen_t sock_addr_len = sizeof(sockaddr_in);
+ if (getsockname(host_fd, reinterpret_cast<sockaddr*>(&sock_addr), &sock_addr_len) != 0)
+ return new QTableWidgetItem(QTableWidget::tr("Unknown"));
+
+ const QString sock_name = QStringLiteral("%1:%2")
+ .arg(QString::fromLatin1(inet_ntoa(sock_addr.sin_addr)))
+ .arg(ntohs(sock_addr.sin_port));
+
+ sockaddr_in peer_addr;
+ socklen_t peer_addr_len = sizeof(sockaddr_in);
+ if (getpeername(host_fd, reinterpret_cast<sockaddr*>(&peer_addr), &peer_addr_len) != 0)
+ return new QTableWidgetItem(sock_name);
+
+ const QString peer_name = QStringLiteral("%1:%2")
+ .arg(QString::fromLatin1(inet_ntoa(peer_addr.sin_addr)))
+ .arg(ntohs(peer_addr.sin_port));
+ return new QTableWidgetItem(QStringLiteral("%1->%2").arg(sock_name).arg(peer_name));
+}
+} // namespace
+
+NetworkWidget::NetworkWidget(QWidget* parent) : QDockWidget(parent)
+{
+ setWindowTitle(tr("Network"));
+ setObjectName(QStringLiteral("network"));
+
+ setHidden(!Settings::Instance().IsNetworkVisible() || !Settings::Instance().IsDebugModeEnabled());
+
+ setAllowedAreas(Qt::AllDockWidgetAreas);
+
+ CreateWidgets();
+
+ auto& settings = Settings::GetQSettings();
+
+ restoreGeometry(settings.value(QStringLiteral("networkwidget/geometry")).toByteArray());
+ // macOS: setHidden() needs to be evaluated before setFloating() for proper window presentation
+ // according to Settings
+ setFloating(settings.value(QStringLiteral("networkwidget/floating")).toBool());
+
+ ConnectWidgets();
+
+ connect(Host::GetInstance(), &Host::UpdateDisasmDialog, this, &NetworkWidget::Update);
+
+ connect(&Settings::Instance(), &Settings::NetworkVisibilityChanged,
+ [this](bool visible) { setHidden(!visible); });
+
+ connect(&Settings::Instance(), &Settings::DebugModeToggled, [this](bool enabled) {
+ setHidden(!enabled || !Settings::Instance().IsNetworkVisible());
+ });
+}
+
+NetworkWidget::~NetworkWidget()
+{
+ auto& settings = Settings::GetQSettings();
+
+ settings.setValue(QStringLiteral("networkwidget/geometry"), saveGeometry());
+ settings.setValue(QStringLiteral("networkwidget/floating"), isFloating());
+}
+
+void NetworkWidget::closeEvent(QCloseEvent*)
+{
+ Settings::Instance().SetNetworkVisible(false);
+}
+
+void NetworkWidget::showEvent(QShowEvent* event)
+{
+ Update();
+}
+
+void NetworkWidget::CreateWidgets()
+{
+ auto* widget = new QWidget;
+ auto* layout = new QVBoxLayout;
+ widget->setLayout(layout);
+ layout->addWidget(CreateSocketTableGroup());
+ layout->addWidget(CreateSSLContextGroup());
+ layout->addWidget(CreateSSLOptionsGroup());
+ layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding));
+ setWidget(widget);
+
+ Update();
+}
+
+void NetworkWidget::ConnectWidgets()
+{
+ connect(m_dump_ssl_read_checkbox, &QCheckBox::stateChanged,
+ [](int state) { SConfig::GetInstance().m_SSLDumpRead = state == Qt::Checked; });
+ connect(m_dump_ssl_write_checkbox, &QCheckBox::stateChanged,
+ [](int state) { SConfig::GetInstance().m_SSLDumpWrite = state == Qt::Checked; });
+ connect(m_dump_root_ca_checkbox, &QCheckBox::stateChanged,
+ [](int state) { SConfig::GetInstance().m_SSLDumpRootCA = state == Qt::Checked; });
+ connect(m_dump_peer_cert_checkbox, &QCheckBox::stateChanged,
+ [](int state) { SConfig::GetInstance().m_SSLDumpPeerCert = state == Qt::Checked; });
+ connect(m_verify_certificates_checkbox, &QCheckBox::stateChanged,
+ [](int state) { SConfig::GetInstance().m_SSLVerifyCert = state == Qt::Checked; });
+}
+
+void NetworkWidget::Update()
+{
+ m_socket_table->setRowCount(0);
+ for (u32 wii_fd = 0; wii_fd < IOS::HLE::WII_SOCKET_FD_MAX; wii_fd++)
+ {
+ m_socket_table->insertRow(wii_fd);
+ const s32 host_fd = IOS::HLE::WiiSockMan::GetInstance().GetHostSocket(wii_fd);
+ m_socket_table->setItem(wii_fd, 0, new QTableWidgetItem(QString::number(wii_fd)));
+ m_socket_table->setItem(wii_fd, 1, GetSocketDomain(host_fd));
+ m_socket_table->setItem(wii_fd, 2, GetSocketType(host_fd));
+ m_socket_table->setItem(wii_fd, 3, GetSocketState(host_fd));
+ m_socket_table->setItem(wii_fd, 4, GetSocketName(host_fd));
+ }
+ m_socket_table->resizeColumnsToContents();
+
+ m_ssl_table->setRowCount(0);
+ for (u32 ssl_id = 0; ssl_id < IOS::HLE::NET_SSL_MAXINSTANCES; ssl_id++)
+ {
+ m_ssl_table->insertRow(ssl_id);
+ s32 host_fd = -1;
+ if (IOS::HLE::Device::IsSSLIDValid(ssl_id) &&
+ IOS::HLE::Device::NetSSL::_SSL[ssl_id].ctx.p_bio != nullptr)
+ {
+ host_fd =
+ static_cast<mbedtls_net_context*>(IOS::HLE::Device::NetSSL::_SSL[ssl_id].ctx.p_bio)->fd;
+ }
+ m_ssl_table->setItem(ssl_id, 0, new QTableWidgetItem(QString::number(ssl_id)));
+ m_ssl_table->setItem(ssl_id, 1, GetSocketDomain(host_fd));
+ m_ssl_table->setItem(ssl_id, 2, GetSocketType(host_fd));
+ m_ssl_table->setItem(ssl_id, 3, GetSocketState(host_fd));
+ m_ssl_table->setItem(ssl_id, 4, GetSocketName(host_fd));
+ }
+ m_ssl_table->resizeColumnsToContents();
+
+ const auto& config = SConfig::GetInstance();
+ m_dump_ssl_read_checkbox->setChecked(config.m_SSLDumpRead);
+ m_dump_ssl_write_checkbox->setChecked(config.m_SSLDumpWrite);
+ m_dump_root_ca_checkbox->setChecked(config.m_SSLDumpRootCA);
+ m_dump_peer_cert_checkbox->setChecked(config.m_SSLDumpPeerCert);
+ m_verify_certificates_checkbox->setChecked(config.m_SSLVerifyCert);
+}
+
+QGroupBox* NetworkWidget::CreateSocketTableGroup()
+{
+ QGroupBox* socket_table_group = new QGroupBox(tr("Socket table"));
+ QGridLayout* socket_table_layout = new QGridLayout;
+ socket_table_group->setLayout(socket_table_layout);
+
+ m_socket_table = new QTableWidget();
+ QStringList header{tr("FD"), tr("Domain"), tr("Type"), tr("State"), tr("Name")};
+ m_socket_table->setColumnCount(header.size());
+
+ m_socket_table->setHorizontalHeaderLabels(header);
+ m_socket_table->setTabKeyNavigation(false);
+ m_socket_table->verticalHeader()->setVisible(false);
+ m_socket_table->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ m_socket_table->setSelectionMode(QAbstractItemView::NoSelection);
+ m_socket_table->setWordWrap(false);
+
+ socket_table_layout->addWidget(m_socket_table, 0, 0);
+ socket_table_layout->setSpacing(1);
+ return socket_table_group;
+}
+
+QGroupBox* NetworkWidget::CreateSSLContextGroup()
+{
+ QGroupBox* ssl_context_group = new QGroupBox(tr("SSL context"));
+ QGridLayout* ssl_context_layout = new QGridLayout;
+ ssl_context_group->setLayout(ssl_context_layout);
+
+ m_ssl_table = new QTableWidget();
+ QStringList header{tr("ID"), tr("Domain"), tr("Type"), tr("State"), tr("Name")};
+ m_ssl_table->setColumnCount(header.size());
+
+ m_ssl_table->setHorizontalHeaderLabels(header);
+ m_ssl_table->setTabKeyNavigation(false);
+ m_ssl_table->verticalHeader()->setVisible(false);
+ m_ssl_table->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ m_ssl_table->setSelectionMode(QAbstractItemView::NoSelection);
+ m_ssl_table->setWordWrap(false);
+
+ ssl_context_layout->addWidget(m_ssl_table, 0, 0);
+ ssl_context_layout->setSpacing(1);
+ return ssl_context_group;
+}
+
+QGroupBox* NetworkWidget::CreateSSLOptionsGroup()
+{
+ QGroupBox* ssl_options_group = new QGroupBox(tr("SSL options"));
+ QGridLayout* ssl_options_layout = new QGridLayout;
+ ssl_options_group->setLayout(ssl_options_layout);
+
+ m_dump_ssl_read_checkbox = new QCheckBox(tr("Dump SSL read"));
+ m_dump_ssl_write_checkbox = new QCheckBox(tr("Dump SSL write"));
+ m_dump_root_ca_checkbox = new QCheckBox(tr("Dump root CA"));
+ m_dump_peer_cert_checkbox = new QCheckBox(tr("Dump peer certificates"));
+ m_verify_certificates_checkbox = new QCheckBox(tr("Verify certificates"));
+
+ ssl_options_layout->addWidget(m_dump_ssl_read_checkbox, 0, 0);
+ ssl_options_layout->addWidget(m_dump_ssl_write_checkbox, 1, 0);
+ ssl_options_layout->addWidget(m_verify_certificates_checkbox, 2, 0);
+ ssl_options_layout->addWidget(m_dump_root_ca_checkbox, 0, 1);
+ ssl_options_layout->addWidget(m_dump_peer_cert_checkbox, 1, 1);
+
+ ssl_options_layout->setSpacing(1);
+ return ssl_options_group;
+}