Don't do failover for Android, try reconnecting automatically once

Issue: AOTextArea is supposed to have red text for errors, but it's not working
This commit is contained in:
oldmud0 2017-11-04 18:42:28 -05:00
parent d93a558ae7
commit a8ccbe77c1
9 changed files with 132 additions and 79 deletions

2
.gitignore vendored
View File

@ -5,3 +5,5 @@
*.so
base_override.h
base-full/
bass.lib

View File

@ -12,7 +12,8 @@
AOApplication::AOApplication(int &argc, char **argv) : QApplication(argc, argv)
{
net_manager = new NetworkManager(this);
QObject::connect(net_manager, SIGNAL(ms_connect_finished(bool)), SLOT(ms_connect_finished(bool)));
QObject::connect(net_manager, SIGNAL(ms_connect_finished(bool, bool)),
SLOT(ms_connect_finished(bool, bool)));
}
AOApplication::~AOApplication()
@ -136,7 +137,7 @@ void AOApplication::loading_cancelled()
w_lobby->hide_loading_overlay();
}
void AOApplication::ms_connect_finished(bool connected)
void AOApplication::ms_connect_finished(bool connected, bool will_retry)
{
if (connected)
{
@ -144,11 +145,19 @@ void AOApplication::ms_connect_finished(bool connected)
send_ms_packet(f_packet);
}
else
{
if (will_retry)
{
w_lobby->append_error("Error connecting to master server. Will try again in "
+ QString::number(net_manager->ms_reconnect_delay_ms / 1000.f) + " seconds.");
}
else
{
call_error("There was an error connecting to the master server.\n"
"We deploy multiple master servers to mitigate any possible downtime,"
"but the client appears to have exhausted all possible methods of finding"
"We deploy multiple master servers to mitigate any possible downtime, "
"but the client appears to have exhausted all possible methods of finding "
"and connecting to one.\n"
"Please check your Internet connection and firewall, and please try again.");
}
}
}

View File

@ -147,7 +147,7 @@ private:
QVector<server_type> favorite_list;
private slots:
void ms_connect_finished(bool connected);
void ms_connect_finished(bool connected, bool will_retry);
public slots:
void server_disconnected();

View File

@ -7,7 +7,7 @@
AOTextArea::AOTextArea(QWidget *p_parent) : QTextBrowser(p_parent)
{
this->setStyleSheet(".error {color: #0f0}");
}
void AOTextArea::append_chatmessage(QString p_name, QString p_message)
@ -21,81 +21,37 @@ void AOTextArea::append_chatmessage(QString p_name, QString p_message)
this->append("");
this->insertHtml("<b>" + p_name.toHtmlEscaped() + "</b>:&nbsp;");
//QRegExp regExp("((([A-Za-z]{3,9}:(?:\\/\\/)?)(?:[\\-;:&=\\+\\$,\\w]+@)?[A-Za-z0-9\\.\\-]+|(?:www\\.|[\\-;:&=\\+\\$,\\w]+@)[A-Za-z0-9\\.\\-]+)((?:\\/[\\+~%\\/\\.\\w\\-]*)?\\??(?:[\\-\\+=&;%@\\.\\w]*)#?(?:[\\.\\!\\/\\\\\\w]*))?)");
QRegExp omnis_dank_url_regex("\\b(https?://\\S+\\.\\S+)\\b");
//cheap workarounds ahoy
p_message += " ";
QString result = p_message.toHtmlEscaped().replace("\n", "<br>").replace(omnis_dank_url_regex, "<a href='\\1'>\\1</a>" );
this->insertHtml(result);
this->auto_scroll(old_cursor, old_scrollbar_value, is_scrolled_down);
}
/*
QRegExp rx("\\bhttp://\\S+");
void AOTextArea::append_error(QString p_message)
{
const QTextCursor old_cursor = this->textCursor();
const int old_scrollbar_value = this->verticalScrollBar()->value();
const bool is_scrolled_down = old_scrollbar_value == this->verticalScrollBar()->maximum();
int first_index = rx.indexIn(p_message);
this->moveCursor(QTextCursor::End);
qDebug() << "number of rx indices: " << rx.captureCount();
this->append("");
this->insertHtml("<div class='error'>");
if (first_index < 0)
{
this->insertPlainText(p_message);
qDebug() << "NO REGEX MATCHES";
return;
}
p_message += " ";
QString result = p_message.replace("\n", "<br>").replace(omnis_dank_url_regex, "<a href='\\1'>\\1</a>" );
//indices where we found a regex match
QVector<int> rx_indices;
QStringList links = rx.capturedTexts();
this->insertHtml(result);
this->insertHtml("</div>");
qDebug() << "link size" << links.size();
rx_indices.append(first_index);
//start at one because first_index is already appended
for (int n_pos = 1 ; n_pos < rx.captureCount() ; ++n_pos)
rx_indices.append(rx.indexIn(p_message));
for (int msg_pos = 0 ; msg_pos < p_message.size() ; ++msg_pos)
{
int tag_index = rx_indices.indexOf(msg_pos);
if (tag_index < 0)
{
this->insertPlainText(p_message.at(msg_pos));
continue;
}
QString link = links.at(tag_index);
QString html_string = "<a href=\"" + link + "\">" + link + "</a>";
qDebug() << "html: " << html_string;
this->insertHtml(html_string);
msg_pos += link.size() - 1;
}
*/
/*
QStringList word_list = p_message.split(" ");
for (QString i_word : word_list)
{
if (i_word.startsWith("http"))
{
i_word.replace("\n", "").replace("\r", "");
this->insertHtml("<a href=\"" + i_word + "\">" + i_word + "</a> ");
}
else
this->insertPlainText(i_word + " ");
}
*/
this->auto_scroll(old_cursor, old_scrollbar_value, is_scrolled_down);
}
void AOTextArea::auto_scroll(QTextCursor old_cursor, int old_scrollbar_value, bool is_scrolled_down)
{
if (old_cursor.hasSelection() || !is_scrolled_down)
{
// The user has selected text or scrolled away from the bottom: maintain position.

View File

@ -9,6 +9,12 @@ public:
AOTextArea(QWidget *p_parent = nullptr);
void append_chatmessage(QString p_name, QString p_message);
void append_error(QString p_message);
private:
const QRegExp omnis_dank_url_regex = QRegExp("\\b(https?://\\S+\\.\\S+)\\b");
void auto_scroll(QTextCursor old_cursor, int scrollbar_value, bool is_scrolled_down);
};
#endif // AOTEXTAREA_H

View File

@ -262,8 +262,9 @@ void Lobby::on_about_clicked()
call_notice("Attorney Online 2 is built using Qt 5.7\n\n"
"Lead development:\n"
"OmniTroid\n\n"
"Supporting development:\n"
"stonedDiscord\n"
"longbyte1\n"
"Supporting development:\n"
"Fiercy\n\n"
"UI design:\n"
"Ruekasu\n"
@ -357,6 +358,11 @@ void Lobby::append_chatmessage(QString f_name, QString f_message)
ui_chatbox->append_chatmessage(f_name, f_message);
}
void Lobby::append_error(QString f_message)
{
ui_chatbox->append_error(f_message);
}
void Lobby::set_player_count(int players_online, int max_players)
{
QString f_string = "Online: " + QString::number(players_online) + "/" + QString::number(max_players);

View File

@ -27,6 +27,7 @@ public:
void list_servers();
void list_favorites();
void append_chatmessage(QString f_name, QString f_message);
void append_error(QString f_message);
void set_player_count(int players_online, int max_players);
void set_loading_text(QString p_text);
void show_loading_overlay(){ui_loading_background->show();}

View File

@ -12,6 +12,10 @@ NetworkManager::NetworkManager(AOApplication *parent) : QObject(parent)
ms_socket = new QTcpSocket(this);
server_socket = new QTcpSocket(this);
ms_reconnect_timer = new QTimer(this);
ms_reconnect_timer->setSingleShot(true);
QObject::connect(ms_reconnect_timer, SIGNAL(timeout()), this, SLOT(retry_ms_connect()));
QObject::connect(ms_socket, SIGNAL(readyRead()), this, SLOT(handle_ms_packet()));
QObject::connect(server_socket, SIGNAL(readyRead()), this, SLOT(handle_server_packet()));
QObject::connect(server_socket, SIGNAL(disconnected()), ao_app, SLOT(server_disconnected()));
@ -27,7 +31,16 @@ void NetworkManager::connect_to_master()
ms_socket->close();
ms_socket->abort();
#ifdef MS_FAILOVER_SUPPORTED
perform_srv_lookup();
#else
QObject::connect(ms_socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(on_ms_connect_error(QAbstractSocket::SocketError)));
QObject::connect(ms_socket, SIGNAL(connected()),
this, SLOT(on_ms_nosrv_connect_success()));
ms_socket->connectToHost(ms_nosrv_hostname, ms_port);
#endif
}
void NetworkManager::connect_to_server(server_type p_server)
@ -40,7 +53,14 @@ void NetworkManager::connect_to_server(server_type p_server)
void NetworkManager::ship_ms_packet(QString p_packet)
{
if (!ms_socket->isOpen())
{
retry_ms_connect();
}
else
{
ms_socket->write(p_packet.toUtf8());
}
}
void NetworkManager::ship_server_packet(QString p_packet)
@ -82,9 +102,10 @@ void NetworkManager::handle_ms_packet()
}
}
#ifdef MS_FAILOVER_SUPPORTED
void NetworkManager::perform_srv_lookup()
{
ms_dns = new QDnsLookup(QDnsLookup::SRV, ms_hostname, this);
ms_dns = new QDnsLookup(QDnsLookup::SRV, ms_srv_hostname, this);
connect(ms_dns, SIGNAL(finished()), this, SLOT(on_srv_lookup()));
ms_dns->lookup();
@ -127,7 +148,13 @@ void NetworkManager::on_srv_lookup()
break;
}
} while (timer.elapsed() < timeout_milliseconds); // Very expensive spin-wait loop - it will bring CPU to 100%!
if (connected) break;
if (connected)
{
// Connect a one-shot signal in case the master server disconnects randomly
QObject::connect(ms_socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(on_ms_socket_error(QAbstractSocket::SocketError)));
break;
}
else
{
ms_socket->abort();
@ -135,7 +162,37 @@ void NetworkManager::on_srv_lookup()
}
}
}
emit ms_connect_finished(connected);
emit ms_connect_finished(connected, false);
}
#endif
void NetworkManager::on_ms_nosrv_connect_success()
{
emit ms_connect_finished(true, false);
QObject::connect(ms_socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(on_ms_socket_error(QAbstractSocket::SocketError)));
}
void NetworkManager::on_ms_socket_error(QAbstractSocket::SocketError error)
{
qWarning() << "Master server socket error:" << ms_socket->errorString()
<< "(" << error << ")";
// Disconnect the one-shot signal - this way, failover connect attempts
// don't trigger a full retry
QObject::disconnect(ms_socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(on_ms_socket_error(QAbstractSocket::SocketError)));
emit ms_connect_finished(false, true);
ms_reconnect_timer->start(ms_reconnect_delay_ms);
}
void NetworkManager::retry_ms_connect()
{
if (!ms_reconnect_timer->isActive() && ms_socket->state() != QAbstractSocket::ConnectingState)
connect_to_master();
}
void NetworkManager::handle_server_packet()

View File

@ -1,12 +1,20 @@
#ifndef NETWORKMANAGER_H
#define NETWORKMANAGER_H
// Qt for Android has stubbed QDnsLookup. This is not documented in any part of their wiki.
// This prevents SRV lookup/failover behavior from functioning.
// https://bugreports.qt.io/browse/QTBUG-56143
#ifndef ANDROID
#define MS_FAILOVER_SUPPORTED
#endif
#include "aopacket.h"
#include "aoapplication.h"
#include <QTcpSocket>
#include <QDnsLookup>
#include <QTime>
#include <QTimer>
class NetworkManager : public QObject
{
@ -20,11 +28,16 @@ public:
QTcpSocket *ms_socket;
QTcpSocket *server_socket;
QDnsLookup *ms_dns;
QTimer *ms_reconnect_timer;
QString ms_hostname = "_aoms._tcp.aceattorneyonline.com";
int ms_port = 27016;
const QString ms_srv_hostname = "_aoms._tcp.aceattorneyonline.com";
const QString ms_nosrv_hostname = "master.aceattorneyonline.com";
const int ms_port = 27016;
const int timeout_milliseconds = 2000;
const int ms_reconnect_delay_ms = 5000;
bool ms_partial_packet = false;
QString ms_temp_packet = "";
@ -41,7 +54,7 @@ public slots:
void ship_server_packet(QString p_packet);
signals:
void ms_connect_finished(bool success);
void ms_connect_finished(bool success, bool will_retry);
private:
void perform_srv_lookup();
@ -50,6 +63,9 @@ private slots:
void on_srv_lookup();
void handle_ms_packet();
void handle_server_packet();
void on_ms_nosrv_connect_success();
void on_ms_socket_error(QAbstractSocket::SocketError error);
void retry_ms_connect();
};
#endif // NETWORKMANAGER_H