Skip to content

Commit

Permalink
Rollback #888
Browse files Browse the repository at this point in the history
  • Loading branch information
zekoz authored and lmoureaux committed Feb 18, 2022
1 parent 38eac2f commit 3b1c3be
Show file tree
Hide file tree
Showing 22 changed files with 167 additions and 304 deletions.
11 changes: 8 additions & 3 deletions client/client_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -474,8 +474,7 @@ int client_main(int argc, char *argv[])
auto positional = parser.positionalArguments();
if (positional.size() == 1) {
url = QUrl(positional.constFirst());
// Supported schemes: fc21://, fc21+local://
if (!url.isValid() || (!url.scheme().startsWith("fc21"))) {
if (!url.isValid() || url.scheme() != QStringLiteral("fc21")) {
// Try with the default protocol
url = QUrl(QStringLiteral("fc21://") + positional.constFirst());
// Still no luck
Expand Down Expand Up @@ -772,7 +771,8 @@ void set_client_state(enum client_states newstate)
qFatal(_("There was an error while auto connecting; aborting."));
exit(EXIT_FAILURE);
} else {
try_to_autoconnect(url);
start_autoconnecting_to_server(url);
auto_connect = false; // Don't try this again.
}
}

Expand Down Expand Up @@ -1078,6 +1078,11 @@ double real_timer_callback()

voteinfo_queue_check_removed();

{
double autoconnect_time = try_to_autoconnect(url);
time_until_next_call = MIN(time_until_next_call, autoconnect_time);
}

if (C_S_RUNNING != client_state()) {
return time_until_next_call;
}
Expand Down
181 changes: 78 additions & 103 deletions client/clinet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@
#endif

// Qt
#include <QLocalSocket>
#include <QString>
#include <QTcpSocket>
#include <QTimer>
#include <QUrl>

// utility
Expand Down Expand Up @@ -58,10 +56,10 @@
#include "clinet.h"

// In autoconnect mode, try to connect to once a second
const int AUTOCONNECT_INTERVAL = 500;
#define AUTOCONNECT_INTERVAL 500

// In autoconnect mode, try to connect 100 times
const int MAX_AUTOCONNECT_ATTEMPTS = 100;
#define MAX_AUTOCONNECT_ATTEMPTS 100

/**
Close socket and cleanup. This one doesn't print a message, so should
Expand Down Expand Up @@ -99,93 +97,63 @@ static void client_conn_close_callback(struct connection *pconn)
qUtf8Printable(reason));
}

namespace {
/// The URL we are presently connecting to.
QUrl connect_to;

/**
* Called when there is an error on the socket.
Try to connect to a server:
- try to create a TCP socket to the given URL (default to
localhost:DEFAULT_SOCK_PORT).
- if successful:
- start monitoring the socket for packets from the server
- send a "login request" packet to the server
and - return 0
- if unable to create the connection, close the socket, put an error
message in ERRBUF and return the Unix error code (ie., errno, which
will be non-zero).
*/
static void error_on_socket()
static int try_to_connect(const QUrl &url, char *errbuf, int errbufsize)
{
if (client.conn.sock != nullptr) {
log_debug("%s", qUtf8Printable(client.conn.sock->errorString()));
real_output_window_append(client.conn.sock->errorString(), NULL);
// Apply defaults
auto url_copy = url;
if (url_copy.host().isEmpty()) {
url_copy.setHost(QStringLiteral("localhost"));
}
if (url_copy.port() <= 0) {
url_copy.setPort(DEFAULT_SOCK_PORT);
}
client.conn.used = false;
}

/**
* Try to connect to a server:
* - try to create a TCP socket to the given URL
* - if successful:
* - start monitoring the socket for packets from the server
* - send a "login request" packet to the server
* and - return 0
* - if unable to create the connection, close the socket, put an error
* message in ERRBUF and return the Unix error code (ie., errno, which
* will be non-zero).
*/
static int try_to_connect(const QUrl &url, char *errbuf, int errbufsize)
{
connections_set_close_callback(client_conn_close_callback);

// connection in progress? wait.
if (client.conn.used) {
if (url != connect_to) {
(void) fc_strlcpy(
errbuf, _("Canceled previous connection, trying new connection."),
errbufsize);
if (auto tcp = qobject_cast<QTcpSocket *>(client.conn.sock)) {
tcp->abort();
} else if (auto local =
qobject_cast<QLocalSocket *>(client.conn.sock)) {
local->abort();
}
connect_to = url;
} else {
(void) fc_strlcpy(errbuf, _("Connection in progress."), errbufsize);
return -1;
}
}

// Reset
if (client.conn.sock) {
client.conn.sock->disconnect(client.conn.sock);
client.conn.sock->deleteLater();
(void) fc_strlcpy(errbuf, _("Connection in progress."), errbufsize);
return -1;
}
client.conn.used = true; // Now there will be a connection :)

// Connect
if (url.scheme() == QStringLiteral("fc21")) {
QTcpSocket *sock = new QTcpSocket;
client.conn.sock = sock;
if (!client.conn.sock) {
client.conn.sock = new QTcpSocket;
QObject::connect(
sock,
client.conn.sock,
QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),
&error_on_socket);
QObject::connect(sock, &QTcpSocket::connected,
[userName = url.userName()] {
make_connection(client.conn.sock, userName);
});
sock->connectToHost(url.host(), url.port());
} else if (url.scheme() == QStringLiteral("fc21+local")) {
QLocalSocket *sock = new QLocalSocket;
client.conn.sock = sock;
QObject::connect(
sock,
QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error),
&error_on_socket);
QObject::connect(sock, &QLocalSocket::connected,
[userName = url.userName()] {
make_connection(client.conn.sock, userName);
});
sock->connectToServer(url.path());
[] {
if (client.conn.sock != nullptr) {
log_debug("%s", qUtf8Printable(client.conn.sock->errorString()));
real_output_window_append(client.conn.sock->errorString(), NULL,
-1);
}
client.conn.used = false;
});
}

client.conn.sock->connectToHost(url.host(), url.port());
if (!client.conn.sock->waitForConnected(-1)) {
errbuf[0] = '\0';
return -1;
}
make_connection(client.conn.sock, url.userName());

return 0;
}
} // namespace

/**
Connect to a freeciv21-server instance -- or at least try to. On success,
Expand All @@ -212,7 +180,7 @@ int connect_to_server(const QUrl &url, char *errbuf, int errbufsize)
/**
Called after a connection is completed (e.g., in try_to_connect).
*/
void make_connection(QIODevice *sock, const QString &username)
void make_connection(QTcpSocket *sock, const QString &username)
{
struct packet_server_join_req req;

Expand Down Expand Up @@ -280,7 +248,7 @@ void disconnect_from_server()
*/
static int read_from_connection(struct connection *pc, bool block)
{
auto socket = pc->sock;
QTcpSocket *socket = pc->sock;
bool have_data_for_server =
(pc->used && pc->send_buffer && 0 < pc->send_buffer->ndata);

Expand All @@ -296,7 +264,7 @@ static int read_from_connection(struct connection *pc, bool block)

if (block) {
// Wait (and block the main event loop) until we get some data
socket->waitForReadyRead(-1);
socket->waitForReadyRead();
}

// Consume everything
Expand All @@ -321,7 +289,7 @@ static int read_from_connection(struct connection *pc, bool block)
This function is called when the client received a new input from the
server.
*/
void input_from_server(QIODevice *sock)
void input_from_server(QTcpSocket *sock)
{
int nb;

Expand Down Expand Up @@ -358,15 +326,22 @@ void input_from_server(QIODevice *sock)
}
}

static bool autoconnecting = false;
/**
Make an attempt to autoconnect to the server.
It returns number of seconds it should be called again.
*/
void try_to_autoconnect(const QUrl &url)
double try_to_autoconnect(const QUrl &url)
{
char errbuf[512];
static int count = 0;

// Don't repeat autoconnect if not autoconnecting or the user
// established a connection by himself.
if (!autoconnecting || client.conn.established) {
return FC_INFINITY;
}

count++;

if (count >= MAX_AUTOCONNECT_ATTEMPTS) {
Expand All @@ -375,32 +350,32 @@ void try_to_autoconnect(const QUrl &url)
exit(EXIT_FAILURE);
}

if (!client.conn.sock) {
client.conn.sock = new QTcpSocket;
if (try_to_connect(url, errbuf, sizeof(errbuf)) == 0) {
// Success! Don't call me again
autoconnecting = false;
return FC_INFINITY;
} else {
// All errors are fatal
qCritical(_("Error contacting server \"%s\":\n %s\n"),
qUtf8Printable(url.toDisplayString()), errbuf);
exit(EXIT_FAILURE);
}
}

try_to_connect(url, errbuf, sizeof(errbuf));

auto error_handler = [url] {
if (client.conn.sock != nullptr) {
output_window_printf(ftc_client,
_("Failed to autoconnect to %s: %d of %d "
"attempts, retrying..."),
qUtf8Printable(url.toDisplayString()), count,
MAX_AUTOCONNECT_ATTEMPTS);
QTimer::singleShot(AUTOCONNECT_INTERVAL,
[url]() { try_to_autoconnect(url); });
}
};
if (auto tcp = qobject_cast<QTcpSocket *>(client.conn.sock)) {
QObject::connect(
tcp,
QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),
error_handler);
} else if (auto local = qobject_cast<QLocalSocket *>(client.conn.sock)) {
QObject::connect(
local,
QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error),
error_handler);
}
/**
Start trying to autoconnect to freeciv21-server. Calls
get_server_address(), then arranges for try_to_autoconnect(), which
calls try_to_connect(), to be called roughly every
AUTOCONNECT_INTERVAL milliseconds, until success, fatal error or
user intervention.
*/
void start_autoconnecting_to_server(const QUrl &url)
{
output_window_printf(
ftc_client,
_("Auto-connecting to \"%s\" every %f second(s) for %d times"),
qUtf8Printable(url.toDisplayString()), 0.001 * AUTOCONNECT_INTERVAL,
MAX_AUTOCONNECT_ATTEMPTS);

autoconnecting = true;
}
9 changes: 5 additions & 4 deletions client/clinet.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@
#pragma once

// Forward declarations
class QIODevice;
class QTcpSocket;
class QString;
class QUrl;

int connect_to_server(const QUrl &url, char *errbuf, int errbufsize);

void make_connection(QIODevice *sock, const QString &username);
void make_connection(QTcpSocket *sock, const QString &username);

void input_from_server(QIODevice *sock);
void input_from_server(QTcpSocket *sock);
void disconnect_from_server();

void try_to_autoconnect(const QUrl &url);
double try_to_autoconnect(const QUrl &url);
void start_autoconnecting_to_server(const QUrl &url);
12 changes: 5 additions & 7 deletions client/connectdlg_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#include <QStandardPaths>
#include <QTcpServer>
#include <QUrl>
#include <QUuid>

#include <cstdio>
#include <cstring>
Expand Down Expand Up @@ -239,17 +238,15 @@ bool client_start_server(const QString &user_name)
return false;
}

// Generate a (random) unique name for the local socket
auto uuid = QUuid::createUuid().toString(QUuid::WithoutBraces);

ruleset = QString::fromUtf8(tileset_what_ruleset(tileset));

// Set up the command-line parameters.
port_buf = QString::number(internal_server_port);
savesdir = QStringLiteral("%1/saves").arg(storage);
scensdir = QStringLiteral("%1/scenarios").arg(storage);

arguments << QStringLiteral("--local") << uuid << QStringLiteral("-q")
arguments << QStringLiteral("-p") << port_buf << QStringLiteral("--bind")
<< QStringLiteral("localhost") << QStringLiteral("-q")
<< QStringLiteral("1") << QStringLiteral("-e")
<< QStringLiteral("--saves") << savesdir
<< QStringLiteral("--scenarios") << scensdir
Expand Down Expand Up @@ -300,9 +297,10 @@ bool client_start_server(const QString &user_name)

// Local server URL
auto url = QUrl();
url.setScheme(QStringLiteral("fc21+local"));
url.setScheme(QStringLiteral("fc21"));
url.setUserName(user_name);
url.setPath(uuid);
url.setHost(QStringLiteral("localhost"));
url.setPort(internal_server_port);

// a reasonable number of tries
while (connect_to_server(
Expand Down
4 changes: 2 additions & 2 deletions client/gui-qt/fc_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ enum client_pages fc_client::current_page() { return page; }
/**
Add notifier for server input
*/
void fc_client::add_server_source(QIODevice *sock)
void fc_client::add_server_source(QTcpSocket *sock)
{
connect(sock, &QIODevice::readyRead, this, &fc_client::server_input);

Expand All @@ -299,7 +299,7 @@ void fc_client::closeEvent(QCloseEvent *event)
*/
void fc_client::server_input()
{
if (auto *socket = dynamic_cast<QIODevice *>(sender())) {
if (auto *socket = dynamic_cast<QTcpSocket *>(sender())) {
input_from_server(socket);
}
}
Expand Down
2 changes: 1 addition & 1 deletion client/gui-qt/fc_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class fc_client : public QMainWindow {
~fc_client() override;
QWidget *pages[static_cast<int>(PAGE_GAME) + 2];
void fc_main(QApplication *);
void add_server_source(QIODevice *socket);
void add_server_source(QTcpSocket *socket);

enum client_pages current_page();

Expand Down
Loading

0 comments on commit 3b1c3be

Please sign in to comment.