From fb6995db947cd48fc27f3d514ad814a45b7b6edc Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 8 Aug 2020 20:25:26 -0700 Subject: [PATCH] Add network test option to PC context menu --- app/gui/NavigableMessageDialog.qml | 9 ++++ app/gui/PcView.qml | 41 ++++++++++++++++ app/gui/computermodel.cpp | 47 +++++++++++++++++++ app/gui/computermodel.h | 3 ++ .../baseline-check_circle_outline-24px.svg | 1 + app/resources.qrc | 1 + 6 files changed, 102 insertions(+) create mode 100644 app/res/baseline-check_circle_outline-24px.svg diff --git a/app/gui/NavigableMessageDialog.qml b/app/gui/NavigableMessageDialog.qml index 40cfc050..b1e28b10 100644 --- a/app/gui/NavigableMessageDialog.qml +++ b/app/gui/NavigableMessageDialog.qml @@ -6,6 +6,8 @@ NavigableDialog { id: dialog property alias text: dialogLabel.dialogText + property alias showSpinner: dialogSpinner.visible + property alias imageSrc: dialogImage.source property string helpText property string helpUrl : "https://github.com/moonlight-stream/moonlight-docs/wiki/Troubleshooting" @@ -19,7 +21,13 @@ NavigableDialog { RowLayout { spacing: 10 + BusyIndicator { + id: dialogSpinner + visible: false + } + Image { + id: dialogImage source: (standardButtons & Dialog.Yes) ? "qrc:/res/baseline-help_outline-24px.svg" : "qrc:/res/baseline-error_outline-24px.svg" @@ -28,6 +36,7 @@ NavigableDialog { width: 50 height: 50 } + visible: !showSpinner } Label { diff --git a/app/gui/PcView.qml b/app/gui/PcView.qml index e7d381f6..2c17ce83 100644 --- a/app/gui/PcView.qml +++ b/app/gui/PcView.qml @@ -79,6 +79,7 @@ CenteredGridView { var model = Qt.createQmlObject('import ComputerModel 1.0; ComputerModel {}', parent, '') model.initialize(ComputerManager) model.pairingCompleted.connect(pairingComplete) + model.connectionTestCompleted.connect(testConnectionDialog.connectionTestComplete) return model } @@ -184,6 +185,15 @@ CenteredGridView { onTriggered: computerModel.wakeComputer(index) visible: !model.online && model.wakeable } + NavigableMenuItem { + parentMenu: pcContextMenu + text: "Test Network" + onTriggered: { + computerModel.testConnectionForComputer(index) + testConnectionDialog.open() + } + } + NavigableMenuItem { parentMenu: pcContextMenu text: "Rename PC" @@ -302,6 +312,37 @@ CenteredGridView { onAccepted: deletePc() } + NavigableMessageDialog { + id: testConnectionDialog + closePolicy: Popup.CloseOnEscape + standardButtons: Dialog.Ok + + onAboutToShow: { + testConnectionDialog.text = "Moonlight is testing your network connection to determine if NVIDIA GameStream is blocked.\n\nThis may take a few seconds…" + showSpinner = true + } + + function connectionTestComplete(result, blockedPorts) + { + if (result === -1) { + text = "The network test could not be performed because none of Moonlight's connection testing servers were reachable from this PC. Check your Internet connection or try again later." + imageSrc = "qrc:/res/baseline-warning-24px.svg" + } + else if (result === 0) { + text = "This network does not appear to be blocking Moonlight. If you still have trouble connecting, check your PC's firewall settings.\n\nIf you are trying to stream over the Internet, install the Moonlight Internet Hosting Tool on your gaming PC and run the included Internet Streaming Tester to check your gaming PC's Internet connection." + imageSrc = "qrc:/res/baseline-check_circle_outline-24px.svg" + } + else { + text = "Your PC's current network connection seems to be blocking Moonlight. Streaming over the Internet may not work while connected to this network.\n\nThe following network ports were blocked:\n" + text += blockedPorts + imageSrc = "qrc:/res/baseline-error_outline-24px.svg" + } + + // Stop showing the spinner and show the image instead + showSpinner = false + } + } + NavigableDialog { id: renamePcDialog property string label: "Enter the new name for this PC:" diff --git a/app/gui/computermodel.cpp b/app/gui/computermodel.cpp index 6a44e936..87dbdac9 100644 --- a/app/gui/computermodel.cpp +++ b/app/gui/computermodel.cpp @@ -147,6 +147,52 @@ QString ComputerModel::generatePinString() return QString::asprintf("%04u", dist(engine)); } +class DeferredTestConnectionTask : public QObject, public QRunnable +{ + Q_OBJECT +public: + void run() + { + unsigned int portTestResult = LiTestClientConnectivity("qt.conntest.moonlight-stream.org", 443, ML_PORT_FLAG_ALL); + if (portTestResult == ML_TEST_RESULT_INCONCLUSIVE) { + emit connectionTestCompleted(-1, QString()); + } + else { + QString blockedPorts; + + for (int i = 0; i < 32; i++) { + if (portTestResult & (1 << i)) { + if (!blockedPorts.isEmpty()) { + blockedPorts += "\n"; + } + + if (LiGetProtocolFromPortFlagIndex(i) == 17 /* IPPROTO_UDP */) { + blockedPorts += "UDP "; + } + else { + blockedPorts += "TCP "; + } + + blockedPorts += QString::number(LiGetPortFromPortFlagIndex(i)); + } + } + + emit connectionTestCompleted(portTestResult, blockedPorts); + } + } + +signals: + void connectionTestCompleted(int result, QString blockedPorts); +}; + +void ComputerModel::testConnectionForComputer(int) +{ + DeferredTestConnectionTask* testConnectionTask = new DeferredTestConnectionTask(); + QObject::connect(testConnectionTask, &DeferredTestConnectionTask::connectionTestCompleted, + this, &ComputerModel::connectionTestCompleted); + QThreadPool::globalInstance()->start(testConnectionTask); +} + void ComputerModel::pairComputer(int computerIndex, QString pin) { Q_ASSERT(computerIndex < m_Computers.count()); @@ -177,3 +223,4 @@ void ComputerModel::handleComputerStateChanged(NvComputer* computer) } } +#include "computermodel.moc" diff --git a/app/gui/computermodel.h b/app/gui/computermodel.h index 7224d51e..fe743737 100644 --- a/app/gui/computermodel.h +++ b/app/gui/computermodel.h @@ -35,6 +35,8 @@ public: Q_INVOKABLE void pairComputer(int computerIndex, QString pin); + Q_INVOKABLE void testConnectionForComputer(int computerIndex); + Q_INVOKABLE void wakeComputer(int computerIndex); Q_INVOKABLE void renameComputer(int computerIndex, QString name); @@ -43,6 +45,7 @@ public: signals: void pairingCompleted(QVariant error); + void connectionTestCompleted(int result, QString blockedPorts); private slots: void handleComputerStateChanged(NvComputer* computer); diff --git a/app/res/baseline-check_circle_outline-24px.svg b/app/res/baseline-check_circle_outline-24px.svg new file mode 100644 index 00000000..f99e0b75 --- /dev/null +++ b/app/res/baseline-check_circle_outline-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/resources.qrc b/app/resources.qrc index 84fc8c45..97a3ec18 100644 --- a/app/resources.qrc +++ b/app/resources.qrc @@ -15,6 +15,7 @@ res/update.svg res/baseline-help_outline-24px.svg res/baseline-error_outline-24px.svg + res/baseline-check_circle_outline-24px.svg SDL_GameControllerDB/gamecontrollerdb.txt