Skip to content

Commit

Permalink
Allow disabling network proxies
Browse files Browse the repository at this point in the history
Both manually and automatically. There's now a setting in the network
preferences to toggle between the system-defined proxy and disabling it
altogether. When the system-defined proxy is enabled, Drawpile will
check if it's valid at all and automatically disable it if not, e.g.
because it's a proxy that can't actually tunnel connections.

Relates to #1360.
  • Loading branch information
askmeaboutlo0m committed Aug 17, 2024
1 parent 3fd53fa commit 96b3364
Show file tree
Hide file tree
Showing 16 changed files with 84 additions and 21 deletions.
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Unreleased Version 2.2.2-pre
* Fix: Solve rendering glitches with selection outlines that happen on some systems. Thanks xxxx for reporting.
* Feature: Allow scaling animation exports. Thanks Hopfel for animating across a giant canvas.
* Fix: Allow disabling the application proxy in the network preferences and automatically detect bad proxy configurations that can't actually make connections. Thanks FishEggsThe for reporting.

2024-08-09 Version 2.2.2-beta.3
* Fix: Use more accurate timers for performance profiles if the platform supports it.
Expand Down
9 changes: 9 additions & 0 deletions src/desktop/dialogs/settingsdialog/network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "desktop/widgets/kis_slider_spin_box.h"
#include "libclient/utils/avatarlistmodel.h"
#include "libclient/utils/avatarlistmodeldelegate.h"
#include "libshared/net/proxy.h"
#include <QCheckBox>
#include <QFormLayout>
#include <QHBoxLayout>
Expand Down Expand Up @@ -138,6 +139,14 @@ void Network::initNetwork(
form->addRow(
tr("Network timeout:"), utils::encapsulate(tr("%1 seconds"), timeout));

#ifndef __EMSCRIPTEN__
auto *proxy = utils::addRadioGroup(
form, tr("Network proxy:"), true,
{{tr("System"), int(net::ProxyMode::Default)},
{tr("Disabled"), int(net::ProxyMode::Disabled)}});
settings.bindNetworkProxyMode(proxy);
#endif

auto *messageQueueDrainRate = new KisSliderSpinBox;
messageQueueDrainRate->setRange(
0, net::MessageQueue::MAX_SMOOTH_DRAIN_RATE);
Expand Down
12 changes: 9 additions & 3 deletions src/desktop/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2272,6 +2272,7 @@ void MainWindow::hostSession(
return;
}

// clang-format on
// Start server if hosting locally
const desktop::settings::Settings &settings = dpApp().settings();
if(!useremote) {
Expand All @@ -2283,7 +2284,8 @@ void MainWindow::hostSession(
QString errorMessage;
bool serverStarted = server->start(
settings.serverPort(), settings.serverTimeout(),
settings.serverPrivateUserList(), &errorMessage);
settings.networkProxyMode(), settings.serverPrivateUserList(),
&errorMessage);
if(!serverStarted) {
QMessageBox::warning(this, tr("Host Session"), errorMessage);
delete server;
Expand All @@ -2303,6 +2305,7 @@ void MainWindow::hostSession(
return;
#endif
}
// clang-format off

// Connect to server
net::LoginHandler *login = new net::LoginHandler(
Expand All @@ -2326,7 +2329,8 @@ void MainWindow::hostSession(
shouldShowDialogMaximized());

m_doc->client()->connectToServer(
settings.serverTimeout(), login, !useremote);
settings.serverTimeout(), settings.networkProxyMode(), login,
!useremote);
}

void MainWindow::invite()
Expand Down Expand Up @@ -2551,7 +2555,9 @@ void MainWindow::joinSession(const QUrl& url, const QString &autoRecordFile)

dlg->show();
m_doc->setRecordOnConnect(autoRecordFile);
m_doc->client()->connectToServer(dpApp().settings().serverTimeout(), login, false);
const desktop::settings::Settings &settings = dpApp().settings();
m_doc->client()->connectToServer(
settings.serverTimeout(), settings.networkProxyMode(), login, false);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/libclient/net/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ Client::Client(CommandHandler *commandHandler, QObject *parent)
}

void Client::connectToServer(
int timeoutSecs, LoginHandler *loginhandler, bool builtin)
int timeoutSecs, int proxyMode, LoginHandler *loginhandler, bool builtin)
{
Q_ASSERT(!isConnected());
m_builtin = builtin;

m_server = Server::make(loginhandler->url(), timeoutSecs, this);
m_server = Server::make(loginhandler->url(), timeoutSecs, proxyMode, this);
m_server->setSmoothDrainRate(m_smoothDrainRate);

#ifdef Q_OS_ANDROID
Expand Down
5 changes: 3 additions & 2 deletions src/libclient/net/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ class Client final : public QObject {
* @brief Connect to a remote server
* @param loginhandler the login handler to use
*/
void
connectToServer(int timeoutSecs, LoginHandler *loginhandler, bool builtin);
void connectToServer(
int timeoutSecs, int proxyMode, LoginHandler *loginhandler,
bool builtin);

/**
* @brief Disconnect from the remote server
Expand Down
11 changes: 6 additions & 5 deletions src/libclient/net/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,21 @@

namespace net {

Server *Server::make(const QUrl &url, int timeoutSecs, Client *client)
Server *Server::make(
const QUrl &url, int timeoutSecs, int proxyMode, Client *client)
{
#if defined(HAVE_WEBSOCKETS) && defined(HAVE_TCPSOCKETS)
if(url.scheme().startsWith(QStringLiteral("ws"), Qt::CaseInsensitive)) {
return new WebSocketServer(timeoutSecs, client);
return new WebSocketServer(timeoutSecs, proxyMode, client);
} else {
return new TcpServer(timeoutSecs, client);
return new TcpServer(timeoutSecs, proxyMode, client);
}
#elif defined(HAVE_TCPSOCKETS)
Q_UNUSED(url);
return new TcpServer(timeoutSecs, client);
return new TcpServer(timeoutSecs, proxyMode, client);
#elif defined(HAVE_WEBSOCKETS)
Q_UNUSED(url);
return new WebSocketServer(timeoutSecs, client);
return new WebSocketServer(timeoutSecs, proxyMode, client);
#else
# error "No socket implementation compiled in."
#endif
Expand Down
3 changes: 2 additions & 1 deletion src/libclient/net/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ class Server : public QObject {
TRUSTED_HOST // A host we have explicitly marked as trusted
};

static Server *make(const QUrl &url, int timeoutSecs, Client *client);
static Server *
make(const QUrl &url, int timeoutSecs, int proxyMode, Client *client);

static QString addSchemeToUserSuppliedAddress(const QString &remoteAddress);
static QUrl fixUpAddress(const QUrl &originalUrl, bool join);
Expand Down
7 changes: 6 additions & 1 deletion src/libclient/net/tcpserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,23 @@
#include "libclient/net/tcpserver.h"
#include "cmake-config/config.h"
#include "libclient/net/login.h"
#include "libshared/net/proxy.h"
#include "libshared/net/tcpmessagequeue.h"
#include "libshared/util/qtcompat.h"
#include <QDebug>
#include <QNetworkProxy>
#include <QSslConfiguration>
#include <QSslSocket>

namespace net {

TcpServer::TcpServer(int timeoutSecs, Client *client)
TcpServer::TcpServer(int timeoutSecs, int proxyMode, Client *client)
: Server(client)
{
m_socket = new QSslSocket(this);
if(shouldDisableProxy(proxyMode, m_socket->proxy(), false, false)) {
m_socket->setProxy(QNetworkProxy::NoProxy);
}
m_socket->setSocketOption(QAbstractSocket::LowDelayOption, true);

QSslConfiguration sslconf = m_socket->sslConfiguration();
Expand Down
2 changes: 1 addition & 1 deletion src/libclient/net/tcpserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace net {
class TcpServer final : public Server {
Q_OBJECT
public:
explicit TcpServer(int timeoutSecs, Client *client);
explicit TcpServer(int timeoutSecs, int proxyMode, Client *client);

bool isWebSocket() const override;

Expand Down
13 changes: 12 additions & 1 deletion src/libclient/net/websocketserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
#include "libclient/net/websocketserver.h"
#include "libshared/net/websocketmessagequeue.h"
#include <QWebSocket>
#ifndef __EMSCRIPTEN__
# include "libshared/net/proxy.h"
# include <QNetworkProxy>
#endif

namespace {
#ifdef HAVE_WEBSOCKETS
Expand All @@ -16,10 +20,17 @@ const auto WebSocketError =

namespace net {

WebSocketServer::WebSocketServer(int timeoutSecs, Client *client)
WebSocketServer::WebSocketServer(int timeoutSecs, int proxyMode, Client *client)
: Server(client)
{
m_socket = new QWebSocket(QString(), QWebSocketProtocol::Version13, this);
#ifdef __EMSCRIPTEN__
Q_UNUSED(proxyMode);
#else
if(shouldDisableProxy(proxyMode, m_socket->proxy(), true, false)) {
m_socket->setProxy(QNetworkProxy::NoProxy);
}
#endif

m_msgqueue = new WebSocketMessageQueue(m_socket, true, this);
m_msgqueue->setIdleTimeout(timeoutSecs * 1000);
Expand Down
3 changes: 2 additions & 1 deletion src/libclient/net/websocketserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ class WebSocketMessageQueue;
class WebSocketServer final : public Server {
Q_OBJECT
public:
explicit WebSocketServer(int timeoutSecs, Client *client);
explicit WebSocketServer(
int timeoutSecs, int proxyMode, Client *client);

bool isWebSocket() const override;

Expand Down
9 changes: 7 additions & 2 deletions src/libclient/server/builtinserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
#include "libserver/client.h"
#include "libserver/inmemoryconfig.h"
#include "libserver/loginhandler.h"
#include "libshared/net/proxy.h"
#include <QJsonArray>
#include <QNetworkProxy>
#include <QTcpServer>

namespace server {
Expand Down Expand Up @@ -60,12 +62,15 @@ std::tuple<Session *, QString> BuiltinServer::createSession(
}

bool BuiltinServer::start(
quint16 preferredPort, int clientTimeout, bool privateUserList,
QString *outErrorMessage)
quint16 preferredPort, int clientTimeout, int proxyMode,
bool privateUserList, QString *outErrorMessage)
{
Q_ASSERT(!m_server);

m_server = new QTcpServer{this};
if(net::shouldDisableProxy(proxyMode, m_server->proxy(), false, true)) {
m_server->setProxy(QNetworkProxy::NoProxy);
}
connect(
m_server, &QTcpServer::newConnection, this, &BuiltinServer::newClient);

Expand Down
4 changes: 2 additions & 2 deletions src/libclient/server/builtinserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ class BuiltinServer final : public QObject, public Sessions {
const QString &founder) override;

bool start(
quint16 preferredPort, int clientTimeout, bool privateUserList,
QString *outErrorMessage = nullptr);
quint16 preferredPort, int clientTimeout, int proxyMode,
bool privateUserList, QString *outErrorMessage = nullptr);

public slots:
void stop();
Expand Down
1 change: 1 addition & 0 deletions src/libclient/settings_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ SETTING(checkerColor2 , CheckerColor2 , "settings/ch
SETTING(interpolateInputs , InterpolateInputs , "settings/input/interpolate" , true)
SETTING(messageQueueDrainRate , MessageQueueDrainRate , "settings/messagequeuedrainrate" , net::MessageQueue::DEFAULT_SMOOTH_DRAIN_RATE)
SETTING(mouseSmoothing , MouseSmoothing , "settings/input/mousesmoothing" , false)
SETTING(networkProxyMode , NetworkProxyMode , "settings/networkproxymode" , 0)
SETTING(parentalControlsAutoTag , ParentalControlsAutoTag , "pc/autotag" , true)
SETTING(parentalControlsForceCensor , ParentalControlsForceCensor , "pc/noUncensoring" , false)
SETTING(parentalControlsLevel , ParentalControlsLevel , "pc/level" , parentalcontrols::Level::Unrestricted)
Expand Down
2 changes: 2 additions & 0 deletions src/libshared/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ target_sources(dpshared PRIVATE
net/messagequeue.h
net/protover.cpp
net/protover.h
net/proxy.cpp
net/proxy.h
net/servercmd.cpp
net/servercmd.h
util/database.cpp
Expand Down
19 changes: 19 additions & 0 deletions src/libshared/net/proxy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef LIBSHARED_NET_PROXY_H
#define LIBSHARED_NET_PROXY_H

class QNetworkProxy;

namespace net {

enum class ProxyMode {
Default = 0,
Disabled = 1,
};

bool shouldDisableProxy(
int proxyMode, const QNetworkProxy &proxy, bool allowHttp, bool listen);

}

#endif

0 comments on commit 96b3364

Please sign in to comment.