Remove TCP entry point (#1007)
* Remove TCP entry point Resolve #987 * Remove TCP entry point * Servers that do not support WebSocket will be marked as `Legacy` * Removal of TCP connection from the master will follow later. * Tweaked error message
This commit is contained in:
		
							parent
							
								
									662d4781d2
								
							
						
					
					
						commit
						efd2571459
					
				@ -78,12 +78,8 @@ add_executable(Attorney_Online
 | 
				
			|||||||
  src/lobby.cpp
 | 
					  src/lobby.cpp
 | 
				
			||||||
  src/lobby.h
 | 
					  src/lobby.h
 | 
				
			||||||
  src/main.cpp
 | 
					  src/main.cpp
 | 
				
			||||||
  src/net/netconnection.cpp
 | 
					  src/network/websocketconnection.cpp
 | 
				
			||||||
  src/net/netconnection.h
 | 
					  src/network/websocketconnection.h
 | 
				
			||||||
  src/net/nettcpconnection.cpp
 | 
					 | 
				
			||||||
  src/net/nettcpconnection.h
 | 
					 | 
				
			||||||
  src/net/netwebsocketconnection.cpp
 | 
					 | 
				
			||||||
  src/net/netwebsocketconnection.h
 | 
					 | 
				
			||||||
  src/networkmanager.cpp
 | 
					  src/networkmanager.cpp
 | 
				
			||||||
  src/networkmanager.h
 | 
					  src/networkmanager.h
 | 
				
			||||||
  src/options.cpp
 | 
					  src/options.cpp
 | 
				
			||||||
@ -103,6 +99,7 @@ add_executable(Attorney_Online
 | 
				
			|||||||
  src/widgets/server_editor_dialog.h
 | 
					  src/widgets/server_editor_dialog.h
 | 
				
			||||||
  data.qrc
 | 
					  data.qrc
 | 
				
			||||||
  src/screenslidetimer.h src/screenslidetimer.cpp
 | 
					  src/screenslidetimer.h src/screenslidetimer.cpp
 | 
				
			||||||
 | 
					  src/network/serverinfo.h src/network/serverinfo.cpp
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set_target_properties(Attorney_Online PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin")
 | 
					set_target_properties(Attorney_Online PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin")
 | 
				
			||||||
 | 
				
			|||||||
@ -78,34 +78,13 @@
 | 
				
			|||||||
      </widget>
 | 
					      </widget>
 | 
				
			||||||
     </item>
 | 
					     </item>
 | 
				
			||||||
     <item row="3" column="0">
 | 
					     <item row="3" column="0">
 | 
				
			||||||
      <widget class="QLabel" name="label_6">
 | 
					 | 
				
			||||||
       <property name="text">
 | 
					 | 
				
			||||||
        <string>Protocol:</string>
 | 
					 | 
				
			||||||
       </property>
 | 
					 | 
				
			||||||
      </widget>
 | 
					 | 
				
			||||||
     </item>
 | 
					 | 
				
			||||||
     <item row="3" column="1">
 | 
					 | 
				
			||||||
      <widget class="QComboBox" name="protocol">
 | 
					 | 
				
			||||||
       <item>
 | 
					 | 
				
			||||||
        <property name="text">
 | 
					 | 
				
			||||||
         <string>TCP</string>
 | 
					 | 
				
			||||||
        </property>
 | 
					 | 
				
			||||||
       </item>
 | 
					 | 
				
			||||||
       <item>
 | 
					 | 
				
			||||||
        <property name="text">
 | 
					 | 
				
			||||||
         <string>WEBSOCKET</string>
 | 
					 | 
				
			||||||
        </property>
 | 
					 | 
				
			||||||
       </item>
 | 
					 | 
				
			||||||
      </widget>
 | 
					 | 
				
			||||||
     </item>
 | 
					 | 
				
			||||||
     <item row="4" column="0">
 | 
					 | 
				
			||||||
      <widget class="QLabel" name="label_2">
 | 
					      <widget class="QLabel" name="label_2">
 | 
				
			||||||
       <property name="text">
 | 
					       <property name="text">
 | 
				
			||||||
        <string>Description:</string>
 | 
					        <string>Description:</string>
 | 
				
			||||||
       </property>
 | 
					       </property>
 | 
				
			||||||
      </widget>
 | 
					      </widget>
 | 
				
			||||||
     </item>
 | 
					     </item>
 | 
				
			||||||
     <item row="4" column="1">
 | 
					     <item row="3" column="1">
 | 
				
			||||||
      <widget class="QPlainTextEdit" name="description">
 | 
					      <widget class="QPlainTextEdit" name="description">
 | 
				
			||||||
       <property name="sizePolicy">
 | 
					       <property name="sizePolicy">
 | 
				
			||||||
        <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
 | 
					        <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
 | 
				
			||||||
 | 
				
			|||||||
@ -316,8 +316,14 @@ QScrollBar:horizontall {
 | 
				
			|||||||
             <item row="1" column="0">
 | 
					             <item row="1" column="0">
 | 
				
			||||||
              <widget class="QTreeWidget" name="serverlist_tree">
 | 
					              <widget class="QTreeWidget" name="serverlist_tree">
 | 
				
			||||||
               <property name="styleSheet">
 | 
					               <property name="styleSheet">
 | 
				
			||||||
                <string notr="true">background-color: rgba(140, 140, 140, 255);
 | 
					                <string notr="true">QHeaderView, QTreeView {
 | 
				
			||||||
color: rgb(255, 255, 255);</string>
 | 
					background-color: rgba(140, 140, 140, 255);
 | 
				
			||||||
 | 
					color: rgb(255, 255, 255);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QToolTip {
 | 
				
			||||||
 | 
					color: black;
 | 
				
			||||||
 | 
					}</string>
 | 
				
			||||||
               </property>
 | 
					               </property>
 | 
				
			||||||
               <property name="textElideMode">
 | 
					               <property name="textElideMode">
 | 
				
			||||||
                <enum>Qt::ElideNone</enum>
 | 
					                <enum>Qt::ElideNone</enum>
 | 
				
			||||||
@ -330,7 +336,7 @@ color: rgb(255, 255, 255);</string>
 | 
				
			|||||||
                 <string>#</string>
 | 
					                 <string>#</string>
 | 
				
			||||||
                </property>
 | 
					                </property>
 | 
				
			||||||
                <property name="textAlignment">
 | 
					                <property name="textAlignment">
 | 
				
			||||||
                 <set>AlignTrailing|AlignVCenter</set>
 | 
					                 <set>AlignLeading|AlignVCenter</set>
 | 
				
			||||||
                </property>
 | 
					                </property>
 | 
				
			||||||
               </column>
 | 
					               </column>
 | 
				
			||||||
               <column>
 | 
					               <column>
 | 
				
			||||||
@ -369,7 +375,11 @@ color: rgb(255, 255, 255);</string>
 | 
				
			|||||||
               </property>
 | 
					               </property>
 | 
				
			||||||
               <property name="styleSheet">
 | 
					               <property name="styleSheet">
 | 
				
			||||||
                <string notr="true">background-color: rgba(140, 140, 140, 255);
 | 
					                <string notr="true">background-color: rgba(140, 140, 140, 255);
 | 
				
			||||||
color: rgb(255, 255, 255);</string>
 | 
					color: rgb(255, 255, 255);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QToolTip {
 | 
				
			||||||
 | 
						color: black;
 | 
				
			||||||
 | 
					};</string>
 | 
				
			||||||
               </property>
 | 
					               </property>
 | 
				
			||||||
               <property name="textElideMode">
 | 
					               <property name="textElideMode">
 | 
				
			||||||
                <enum>Qt::ElideNone</enum>
 | 
					                <enum>Qt::ElideNone</enum>
 | 
				
			||||||
 | 
				
			|||||||
@ -5,25 +5,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <optional>
 | 
					#include <optional>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum ServerConnectionType
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  TcpServerConnection,
 | 
					 | 
				
			||||||
  WebSocketServerConnection,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const QMap<QString, ServerConnectionType> SERVER_CONNECTION_TYPE_STRING_MAP = {{"tcp", ServerConnectionType::TcpServerConnection}, {"ws", ServerConnectionType::WebSocketServerConnection}};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct ServerInfo
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  QString name;
 | 
					 | 
				
			||||||
  QString description;
 | 
					 | 
				
			||||||
  QString ip;
 | 
					 | 
				
			||||||
  int port;
 | 
					 | 
				
			||||||
  ServerConnectionType socket_type;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  inline QString toString() { return QString("%1 (<%2>%3:%4)").arg(name, SERVER_CONNECTION_TYPE_STRING_MAP.key(socket_type), ip, QString::number(port)); }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct CharacterSlot
 | 
					struct CharacterSlot
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  QString name;
 | 
					  QString name;
 | 
				
			||||||
 | 
				
			|||||||
@ -9,8 +9,8 @@ DemoServer::DemoServer(QObject *parent)
 | 
				
			|||||||
  timer->setTimerType(Qt::PreciseTimer);
 | 
					  timer->setTimerType(Qt::PreciseTimer);
 | 
				
			||||||
  timer->setSingleShot(true);
 | 
					  timer->setSingleShot(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  tcp_server = new QTcpServer(this);
 | 
					  server = new QWebSocketServer(tr("DemoServer"), QWebSocketServer::NonSecureMode, this);
 | 
				
			||||||
  connect(tcp_server, &QTcpServer::newConnection, this, &DemoServer::accept_connection);
 | 
					  connect(server, &QWebSocketServer::newConnection, this, &DemoServer::accept_connection);
 | 
				
			||||||
  connect(timer, &QTimer::timeout, this, &DemoServer::playback);
 | 
					  connect(timer, &QTimer::timeout, this, &DemoServer::playback);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -30,22 +30,22 @@ void DemoServer::start_server()
 | 
				
			|||||||
  {
 | 
					  {
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (!tcp_server->listen(QHostAddress::LocalHost, 0))
 | 
					  if (!server->listen(QHostAddress::LocalHost, 0))
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    qCritical() << "Could not start demo playback server...";
 | 
					    qCritical() << "Could not start demo playback server...";
 | 
				
			||||||
    qDebug() << tcp_server->errorString();
 | 
					    qDebug() << server->errorString();
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  this->m_port = tcp_server->serverPort();
 | 
					  this->m_port = server->serverPort();
 | 
				
			||||||
  qInfo() << "Demo server started at port" << m_port;
 | 
					  qInfo() << "Demo server started at port" << m_port;
 | 
				
			||||||
  m_server_started = true;
 | 
					  m_server_started = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void DemoServer::destroy_connection()
 | 
					void DemoServer::destroy_connection()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  QTcpSocket *temp_socket = tcp_server->nextPendingConnection();
 | 
					  QWebSocket *temp_socket = server->nextPendingConnection();
 | 
				
			||||||
  connect(temp_socket, &QAbstractSocket::disconnected, temp_socket, &QObject::deleteLater);
 | 
					  temp_socket->close();
 | 
				
			||||||
  temp_socket->disconnectFromHost();
 | 
					  temp_socket->deleteLater();
 | 
				
			||||||
  return;
 | 
					  return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -80,22 +80,20 @@ void DemoServer::accept_connection()
 | 
				
			|||||||
  {
 | 
					  {
 | 
				
			||||||
    // Client is already connected...
 | 
					    // Client is already connected...
 | 
				
			||||||
    qWarning() << "Multiple connections to demo server disallowed.";
 | 
					    qWarning() << "Multiple connections to demo server disallowed.";
 | 
				
			||||||
    QTcpSocket *temp_socket = tcp_server->nextPendingConnection();
 | 
					    QWebSocket *temp_socket = server->nextPendingConnection();
 | 
				
			||||||
    connect(temp_socket, &QAbstractSocket::disconnected, temp_socket, &QObject::deleteLater);
 | 
					    temp_socket->close();
 | 
				
			||||||
    temp_socket->disconnectFromHost();
 | 
					    temp_socket->deleteLater();
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  client_sock = tcp_server->nextPendingConnection();
 | 
					  client_sock = server->nextPendingConnection();
 | 
				
			||||||
  connect(client_sock, &QAbstractSocket::disconnected, this, &DemoServer::client_disconnect);
 | 
					  connect(client_sock, &QWebSocket::disconnected, this, &DemoServer::client_disconnect);
 | 
				
			||||||
  connect(client_sock, &QAbstractSocket::readyRead, this, &DemoServer::recv_data);
 | 
					  connect(client_sock, &QWebSocket::textMessageReceived, this, &DemoServer::recv_data);
 | 
				
			||||||
  client_sock->write("decryptor#NOENCRYPT#%");
 | 
					  client_sock->sendTextMessage("decryptor#NOENCRYPT#%");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void DemoServer::recv_data()
 | 
					void DemoServer::recv_data(const QString &message)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  QString in_data = QString::fromUtf8(client_sock->readAll());
 | 
					  const QStringList packet_list = message.split("%", Qt::SkipEmptyParts);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  const QStringList packet_list = in_data.split("%", Qt::SkipEmptyParts);
 | 
					 | 
				
			||||||
  for (const QString &packet : packet_list)
 | 
					  for (const QString &packet : packet_list)
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    QStringList f_contents;
 | 
					    QStringList f_contents;
 | 
				
			||||||
@ -145,39 +143,35 @@ void DemoServer::handle_packet(AOPacket p_packet)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  if (header == "HI")
 | 
					  if (header == "HI")
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    client_sock->write("ID#0#DEMOINTERNAL#0#%");
 | 
					    client_sock->sendTextMessage("ID#0#DEMOINTERNAL#0#%");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else if (header == "ID")
 | 
					  else if (header == "ID")
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    QStringList feature_list = {"noencryption", "yellowtext", "prezoom", "flipping", "customobjections", "fastloading", "deskmod", "evidence", "cccc_ic_support", "arup", "casing_alerts", "modcall_reason", "looping_sfx", "additive", "effects", "y_offset", "expanded_desk_mods"};
 | 
					    QStringList feature_list = {"noencryption", "yellowtext", "prezoom", "flipping", "customobjections", "fastloading", "deskmod", "evidence", "cccc_ic_support", "arup", "casing_alerts", "modcall_reason", "looping_sfx", "additive", "effects", "y_offset", "expanded_desk_mods"};
 | 
				
			||||||
    client_sock->write("PN#0#1#%");
 | 
					    client_sock->sendTextMessage("PN#0#1#%");
 | 
				
			||||||
    client_sock->write("FL#");
 | 
					    client_sock->sendTextMessage("FL#" + feature_list.join('#') + "#%");
 | 
				
			||||||
    client_sock->write(feature_list.join('#').toUtf8());
 | 
					 | 
				
			||||||
    client_sock->write("#%");
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else if (header == "askchaa")
 | 
					  else if (header == "askchaa")
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    client_sock->write("SI#");
 | 
					    client_sock->sendTextMessage("SI#" + QString::number(num_chars) + "#0#1#%");
 | 
				
			||||||
    client_sock->write(QString::number(num_chars).toUtf8());
 | 
					 | 
				
			||||||
    client_sock->write("#0#1#%");
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else if (header == "RC")
 | 
					  else if (header == "RC")
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    client_sock->write(sc_packet.toUtf8());
 | 
					    client_sock->sendTextMessage(sc_packet.toUtf8());
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else if (header == "RM")
 | 
					  else if (header == "RM")
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    client_sock->write("SM#%");
 | 
					    client_sock->sendTextMessage("SM#%");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else if (header == "RD")
 | 
					  else if (header == "RD")
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    client_sock->write("DONE#%");
 | 
					    client_sock->sendTextMessage("DONE#%");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else if (header == "CC")
 | 
					  else if (header == "CC")
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    client_sock->write("PV#0#CID#-1#%");
 | 
					    client_sock->sendTextMessage("PV#0#CID#-1#%");
 | 
				
			||||||
    QString packet = "CT#DEMO#" + tr("Demo file loaded. Send /play or > in OOC to begin playback.") + "#1#%";
 | 
					    QString packet = "CT#DEMO#" + tr("Demo file loaded. Send /play or > in OOC to begin playback.") + "#1#%";
 | 
				
			||||||
    client_sock->write(packet.toUtf8());
 | 
					    client_sock->sendTextMessage(packet.toUtf8());
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else if (header == "CT")
 | 
					  else if (header == "CT")
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
@ -190,7 +184,7 @@ void DemoServer::handle_packet(AOPacket p_packet)
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      load_demo(path);
 | 
					      load_demo(path);
 | 
				
			||||||
      QString packet = "CT#DEMO#" + tr("Demo file loaded. Send /play or > in OOC to begin playback.") + "#1#%";
 | 
					      QString packet = "CT#DEMO#" + tr("Demo file loaded. Send /play or > in OOC to begin playback.") + "#1#%";
 | 
				
			||||||
      client_sock->write(packet.toUtf8());
 | 
					      client_sock->sendTextMessage(packet.toUtf8());
 | 
				
			||||||
      reset_state();
 | 
					      reset_state();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (contents[1].startsWith("/play") || contents[1] == ">")
 | 
					    else if (contents[1].startsWith("/play") || contents[1] == ">")
 | 
				
			||||||
@ -199,7 +193,7 @@ void DemoServer::handle_packet(AOPacket p_packet)
 | 
				
			|||||||
      {
 | 
					      {
 | 
				
			||||||
        timer->start();
 | 
					        timer->start();
 | 
				
			||||||
        QString packet = "CT#DEMO#" + tr("Resuming playback.") + "#1#%";
 | 
					        QString packet = "CT#DEMO#" + tr("Resuming playback.") + "#1#%";
 | 
				
			||||||
        client_sock->write(packet.toUtf8());
 | 
					        client_sock->sendTextMessage(packet.toUtf8());
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      else
 | 
					      else
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
@ -216,7 +210,7 @@ void DemoServer::handle_packet(AOPacket p_packet)
 | 
				
			|||||||
      timer->stop();
 | 
					      timer->stop();
 | 
				
			||||||
      timer->setInterval(timeleft);
 | 
					      timer->setInterval(timeleft);
 | 
				
			||||||
      QString packet = "CT#DEMO#" + tr("Pausing playback.") + "#1#%";
 | 
					      QString packet = "CT#DEMO#" + tr("Pausing playback.") + "#1#%";
 | 
				
			||||||
      client_sock->write(packet.toUtf8());
 | 
					      client_sock->sendTextMessage(packet.toUtf8());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (contents[1].startsWith("/max_wait"))
 | 
					    else if (contents[1].startsWith("/max_wait"))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -232,38 +226,32 @@ void DemoServer::handle_packet(AOPacket p_packet)
 | 
				
			|||||||
            p_max_wait = -1;
 | 
					            p_max_wait = -1;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          m_max_wait = p_max_wait;
 | 
					          m_max_wait = p_max_wait;
 | 
				
			||||||
          QString packet = "CT#DEMO#" + tr("Setting max_wait to") + " ";
 | 
					          QString packet = "CT#DEMO#" + tr("Setting max_wait to") + " " + QString::number(m_max_wait) + " " + tr("milliseconds.") + "#1#%";
 | 
				
			||||||
          client_sock->write(packet.toUtf8());
 | 
					          client_sock->sendTextMessage(packet);
 | 
				
			||||||
          client_sock->write(QString::number(m_max_wait).toUtf8());
 | 
					 | 
				
			||||||
          packet = " " + tr("milliseconds.") + "#1#%";
 | 
					 | 
				
			||||||
          client_sock->write(packet.toUtf8());
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          QString packet = "CT#DEMO#" + tr("Not a valid integer!") + "#1#%";
 | 
					          QString packet = "CT#DEMO#" + tr("Not a valid integer!") + "#1#%";
 | 
				
			||||||
          client_sock->write(packet.toUtf8());
 | 
					          client_sock->sendTextMessage(packet.toUtf8());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      else
 | 
					      else
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        QString packet = "CT#DEMO#" + tr("Current max_wait is") + " ";
 | 
					        QString packet = "CT#DEMO#" + tr("Current max_wait is") + " " + QString::number(m_max_wait) + tr("milliseconds.") + "#1#%";
 | 
				
			||||||
        client_sock->write(packet.toUtf8());
 | 
					        client_sock->sendTextMessage(packet.toUtf8());
 | 
				
			||||||
        client_sock->write(QString::number(m_max_wait).toUtf8());
 | 
					 | 
				
			||||||
        packet = " " + tr("milliseconds.") + "#1#%";
 | 
					 | 
				
			||||||
        client_sock->write(packet.toUtf8());
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (contents[1].startsWith("/reload"))
 | 
					    else if (contents[1].startsWith("/reload"))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      load_demo(p_path);
 | 
					      load_demo(p_path);
 | 
				
			||||||
      QString packet = "CT#DEMO#" + tr("Current demo file reloaded. Send /play or > in OOC to begin playback.") + "#1#%";
 | 
					      QString packet = "CT#DEMO#" + tr("Current demo file reloaded. Send /play or > in OOC to begin playback.") + "#1#%";
 | 
				
			||||||
      client_sock->write(packet.toUtf8());
 | 
					      client_sock->sendTextMessage(packet.toUtf8());
 | 
				
			||||||
      reset_state();
 | 
					      reset_state();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (contents[1].startsWith("/min_wait"))
 | 
					    else if (contents[1].startsWith("/min_wait"))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      QString packet = "CT#DEMO#" + tr("min_wait is deprecated. Use the client Settings for minimum wait instead!") + "#1#%";
 | 
					      QString packet = "CT#DEMO#" + tr("min_wait is deprecated. Use the client Settings for minimum wait instead!") + "#1#%";
 | 
				
			||||||
      client_sock->write(packet.toUtf8());
 | 
					      client_sock->sendTextMessage(packet.toUtf8());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (contents[1].startsWith("/debug"))
 | 
					    else if (contents[1].startsWith("/debug"))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -276,31 +264,31 @@ void DemoServer::handle_packet(AOPacket p_packet)
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
          debug_mode = toggle == 1;
 | 
					          debug_mode = toggle == 1;
 | 
				
			||||||
          QString packet = "CT#DEMO#" + tr("Setting debug mode to %1").arg(static_cast<int>(debug_mode)) + "#1#%";
 | 
					          QString packet = "CT#DEMO#" + tr("Setting debug mode to %1").arg(static_cast<int>(debug_mode)) + "#1#%";
 | 
				
			||||||
          client_sock->write(packet.toUtf8());
 | 
					          client_sock->sendTextMessage(packet.toUtf8());
 | 
				
			||||||
          // Debug mode disabled?
 | 
					          // Debug mode disabled?
 | 
				
			||||||
          if (!debug_mode)
 | 
					          if (!debug_mode)
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
            // Reset the timer
 | 
					            // Reset the timer
 | 
				
			||||||
            client_sock->write("TI#4#1#0#%");
 | 
					            client_sock->sendTextMessage("TI#4#1#0#%");
 | 
				
			||||||
            client_sock->write("TI#4#3#0#%");
 | 
					            client_sock->sendTextMessage("TI#4#3#0#%");
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          QString packet = "CT#DEMO#" + tr("Valid values are 1 or 0!") + "#1#%";
 | 
					          QString packet = "CT#DEMO#" + tr("Valid values are 1 or 0!") + "#1#%";
 | 
				
			||||||
          client_sock->write(packet.toUtf8());
 | 
					          client_sock->sendTextMessage(packet.toUtf8());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      else
 | 
					      else
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        QString packet = "CT#DEMO#" + tr("Set debug mode using /debug 1 to enable, and /debug 0 to disable, which will use the fifth timer (TI#4) to show the remaining time until next demo line.") + "#1#%";
 | 
					        QString packet = "CT#DEMO#" + tr("Set debug mode using /debug 1 to enable, and /debug 0 to disable, which will use the fifth timer (TI#4) to show the remaining time until next demo line.") + "#1#%";
 | 
				
			||||||
        client_sock->write(packet.toUtf8());
 | 
					        client_sock->sendTextMessage(packet.toUtf8());
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (contents[1].startsWith("/help"))
 | 
					    else if (contents[1].startsWith("/help"))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      QString packet = "CT#DEMO#" + tr("Available commands:\nload, reload, play, pause, max_wait, debug, help") + "#1#%";
 | 
					      QString packet = "CT#DEMO#" + tr("Available commands:\nload, reload, play, pause, max_wait, debug, help") + "#1#%";
 | 
				
			||||||
      client_sock->write(packet.toUtf8());
 | 
					      client_sock->sendTextMessage(packet.toUtf8());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -395,22 +383,22 @@ void DemoServer::load_demo(QString filename)
 | 
				
			|||||||
void DemoServer::reset_state()
 | 
					void DemoServer::reset_state()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  // Reset evidence list
 | 
					  // Reset evidence list
 | 
				
			||||||
  client_sock->write("LE##%");
 | 
					  client_sock->sendTextMessage("LE##%");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Reset timers
 | 
					  // Reset timers
 | 
				
			||||||
  client_sock->write("TI#0#1#0#%");
 | 
					  client_sock->sendTextMessage("TI#0#1#0#%");
 | 
				
			||||||
  client_sock->write("TI#0#3#0#%");
 | 
					  client_sock->sendTextMessage("TI#0#3#0#%");
 | 
				
			||||||
  client_sock->write("TI#1#1#0#%");
 | 
					  client_sock->sendTextMessage("TI#1#1#0#%");
 | 
				
			||||||
  client_sock->write("TI#1#3#0#%");
 | 
					  client_sock->sendTextMessage("TI#1#3#0#%");
 | 
				
			||||||
  client_sock->write("TI#2#1#0#%");
 | 
					  client_sock->sendTextMessage("TI#2#1#0#%");
 | 
				
			||||||
  client_sock->write("TI#2#3#0#%");
 | 
					  client_sock->sendTextMessage("TI#2#3#0#%");
 | 
				
			||||||
  client_sock->write("TI#3#1#0#%");
 | 
					  client_sock->sendTextMessage("TI#3#1#0#%");
 | 
				
			||||||
  client_sock->write("TI#3#3#0#%");
 | 
					  client_sock->sendTextMessage("TI#3#3#0#%");
 | 
				
			||||||
  client_sock->write("TI#4#1#0#%");
 | 
					  client_sock->sendTextMessage("TI#4#1#0#%");
 | 
				
			||||||
  client_sock->write("TI#4#3#0#%");
 | 
					  client_sock->sendTextMessage("TI#4#3#0#%");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Set the BG to default (also breaks up the message queue)
 | 
					  // Set the BG to default (also breaks up the message queue)
 | 
				
			||||||
  client_sock->write("BN#default#wit#%");
 | 
					  client_sock->sendTextMessage("BN#default#wit#%");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Stop the wait packet timer
 | 
					  // Stop the wait packet timer
 | 
				
			||||||
  timer->stop();
 | 
					  timer->stop();
 | 
				
			||||||
@ -432,7 +420,7 @@ void DemoServer::playback()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  while (!current_packet.startsWith("wait#"))
 | 
					  while (!current_packet.startsWith("wait#"))
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    client_sock->write(current_packet.toUtf8());
 | 
					    client_sock->sendTextMessage(current_packet.toUtf8());
 | 
				
			||||||
    if (demo_data.isEmpty())
 | 
					    if (demo_data.isEmpty())
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
@ -478,15 +466,15 @@ void DemoServer::playback()
 | 
				
			|||||||
    timer->start(duration);
 | 
					    timer->start(duration);
 | 
				
			||||||
    if (debug_mode)
 | 
					    if (debug_mode)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      client_sock->write("TI#4#2#%");
 | 
					      client_sock->sendTextMessage("TI#4#2#%");
 | 
				
			||||||
      QString debug_timer = "TI#4#0#" + QString::number(duration) + "#%";
 | 
					      QString debug_timer = "TI#4#0#" + QString::number(duration) + "#%";
 | 
				
			||||||
      client_sock->write(debug_timer.toUtf8());
 | 
					      client_sock->sendTextMessage(debug_timer.toUtf8());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    QString end_packet = "CT#DEMO#" + tr("Reached the end of the demo file. Send /play or > in OOC to restart, or /load to open a new file.") + "#1#%";
 | 
					    QString end_packet = "CT#DEMO#" + tr("Reached the end of the demo file. Send /play or > in OOC to restart, or /load to open a new file.") + "#1#%";
 | 
				
			||||||
    client_sock->write(end_packet.toUtf8());
 | 
					    client_sock->sendTextMessage(end_packet.toUtf8());
 | 
				
			||||||
    timer->setInterval(0);
 | 
					    timer->setInterval(0);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -7,9 +7,9 @@
 | 
				
			|||||||
#include <QMessageBox>
 | 
					#include <QMessageBox>
 | 
				
			||||||
#include <QObject>
 | 
					#include <QObject>
 | 
				
			||||||
#include <QQueue>
 | 
					#include <QQueue>
 | 
				
			||||||
#include <QTcpServer>
 | 
					 | 
				
			||||||
#include <QTcpSocket>
 | 
					 | 
				
			||||||
#include <QTimer>
 | 
					#include <QTimer>
 | 
				
			||||||
 | 
					#include <QWebSocket>
 | 
				
			||||||
 | 
					#include <QWebSocketServer>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DemoServer : public QObject
 | 
					class DemoServer : public QObject
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -27,8 +27,8 @@ private:
 | 
				
			|||||||
  int m_port = 0;
 | 
					  int m_port = 0;
 | 
				
			||||||
  int m_max_wait = -1;
 | 
					  int m_max_wait = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QTcpServer *tcp_server;
 | 
					  QWebSocketServer *server;
 | 
				
			||||||
  QTcpSocket *client_sock = nullptr;
 | 
					  QWebSocket *client_sock = nullptr;
 | 
				
			||||||
  bool client_connected = false;
 | 
					  bool client_connected = false;
 | 
				
			||||||
  bool partial_packet = false;
 | 
					  bool partial_packet = false;
 | 
				
			||||||
  bool debug_mode = false;
 | 
					  bool debug_mode = false;
 | 
				
			||||||
@ -48,7 +48,7 @@ private:
 | 
				
			|||||||
private Q_SLOTS:
 | 
					private Q_SLOTS:
 | 
				
			||||||
  void accept_connection();
 | 
					  void accept_connection();
 | 
				
			||||||
  void destroy_connection();
 | 
					  void destroy_connection();
 | 
				
			||||||
  void recv_data();
 | 
					  void recv_data(const QString &in_data);
 | 
				
			||||||
  void client_disconnect();
 | 
					  void client_disconnect();
 | 
				
			||||||
  void playback();
 | 
					  void playback();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -238,8 +238,7 @@ void Lobby::on_add_server_to_fave_released()
 | 
				
			|||||||
void Lobby::on_edit_favorite_released()
 | 
					void Lobby::on_edit_favorite_released()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  const int index = get_selected_server();
 | 
					  const int index = get_selected_server();
 | 
				
			||||||
  ServerEditorDialog dialog;
 | 
					  ServerEditorDialog dialog(Options::getInstance().favorites().at(index));
 | 
				
			||||||
  dialog.loadServerInfo(Options::getInstance().favorites().at(index));
 | 
					 | 
				
			||||||
  if (dialog.exec())
 | 
					  if (dialog.exec())
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    Options::getInstance().updateFavorite(dialog.currentServerInfo(), index);
 | 
					    Options::getInstance().updateFavorite(dialog.currentServerInfo(), index);
 | 
				
			||||||
@ -428,7 +427,7 @@ void Lobby::on_demo_clicked(QTreeWidgetItem *item, int column)
 | 
				
			|||||||
  QString l_filepath = (get_app_path() + "/logs/%1/%2").arg(item->data(0, Qt::DisplayRole).toString(), item->data(1, Qt::DisplayRole).toString());
 | 
					  QString l_filepath = (get_app_path() + "/logs/%1/%2").arg(item->data(0, Qt::DisplayRole).toString(), item->data(1, Qt::DisplayRole).toString());
 | 
				
			||||||
  ao_app->demo_server->start_server();
 | 
					  ao_app->demo_server->start_server();
 | 
				
			||||||
  ServerInfo demo_server;
 | 
					  ServerInfo demo_server;
 | 
				
			||||||
  demo_server.ip = "127.0.0.1";
 | 
					  demo_server.address = "127.0.0.1";
 | 
				
			||||||
  demo_server.port = ao_app->demo_server->port();
 | 
					  demo_server.port = ao_app->demo_server->port();
 | 
				
			||||||
  ao_app->demo_server->set_demo_file(l_filepath);
 | 
					  ao_app->demo_server->set_demo_file(l_filepath);
 | 
				
			||||||
  net_manager->connect_to_server(demo_server);
 | 
					  net_manager->connect_to_server(demo_server);
 | 
				
			||||||
@ -462,7 +461,22 @@ void Lobby::list_servers()
 | 
				
			|||||||
  {
 | 
					  {
 | 
				
			||||||
    QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui_serverlist_tree);
 | 
					    QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui_serverlist_tree);
 | 
				
			||||||
    treeItem->setData(0, Qt::DisplayRole, i);
 | 
					    treeItem->setData(0, Qt::DisplayRole, i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (i_server.legacy)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      treeItem->setText(1, "(Legacy) " + i_server.name);
 | 
				
			||||||
 | 
					      treeItem->setBackground(0, Qt::darkRed);
 | 
				
			||||||
 | 
					      treeItem->setBackground(1, Qt::darkRed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      QString tooltip = tr("Unable to connect to server. Server is missing WebSocket support.");
 | 
				
			||||||
 | 
					      treeItem->setToolTip(0, tooltip);
 | 
				
			||||||
 | 
					      treeItem->setToolTip(1, tooltip);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
      treeItem->setText(1, i_server.name);
 | 
					      treeItem->setText(1, i_server.name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    i++;
 | 
					    i++;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  ui_serverlist_tree->setSortingEnabled(true);
 | 
					  ui_serverlist_tree->setSortingEnabled(true);
 | 
				
			||||||
@ -480,7 +494,22 @@ void Lobby::list_favorites()
 | 
				
			|||||||
  {
 | 
					  {
 | 
				
			||||||
    QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui_favorites_tree);
 | 
					    QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui_favorites_tree);
 | 
				
			||||||
    treeItem->setData(0, Qt::DisplayRole, i);
 | 
					    treeItem->setData(0, Qt::DisplayRole, i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (i_server.legacy)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      treeItem->setText(1, "(Legacy) " + i_server.name);
 | 
				
			||||||
 | 
					      treeItem->setBackground(0, Qt::darkRed);
 | 
				
			||||||
 | 
					      treeItem->setBackground(1, Qt::darkRed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      QString tooltip = tr("Unable to connect to server. Server is missing WebSocket support.");
 | 
				
			||||||
 | 
					      treeItem->setToolTip(0, tooltip);
 | 
				
			||||||
 | 
					      treeItem->setToolTip(1, tooltip);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
      treeItem->setText(1, i_server.name);
 | 
					      treeItem->setText(1, i_server.name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    i++;
 | 
					    i++;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  ui_favorites_tree->setSortingEnabled(true);
 | 
					  ui_favorites_tree->setSortingEnabled(true);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +0,0 @@
 | 
				
			|||||||
#include "netconnection.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NetConnection::NetConnection(QObject *parent)
 | 
					 | 
				
			||||||
    : QObject(parent)
 | 
					 | 
				
			||||||
{}
 | 
					 | 
				
			||||||
@ -1,28 +0,0 @@
 | 
				
			|||||||
#pragma once
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "aopacket.h"
 | 
					 | 
				
			||||||
#include "datatypes.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <QObject>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class NetConnection : public QObject
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  Q_OBJECT
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
  explicit NetConnection(QObject *parent = nullptr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  virtual bool isConnected() = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  virtual void connectToServer(ServerInfo &server) = 0;
 | 
					 | 
				
			||||||
  virtual void disconnectFromServer() = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  virtual void sendPacket(AOPacket packet) = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Q_SIGNALS:
 | 
					 | 
				
			||||||
  void connectedToServer();
 | 
					 | 
				
			||||||
  void disconnectedFromServer();
 | 
					 | 
				
			||||||
  void errorOccurred(QString error);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  void receivedPacket(AOPacket packet);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
@ -1,102 +0,0 @@
 | 
				
			|||||||
#include "nettcpconnection.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NetTcpConnection::NetTcpConnection(QObject *parent)
 | 
					 | 
				
			||||||
    : NetConnection(parent)
 | 
					 | 
				
			||||||
    , m_socket(new QTcpSocket(this))
 | 
					 | 
				
			||||||
    , m_last_state(QAbstractSocket::UnconnectedState)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
 | 
					 | 
				
			||||||
  connect(m_socket, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error), this, &NetTcpConnection::onErrorOccurred);
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
  connect(m_socket, &QTcpSocket::errorOccurred, this, &NetTcpConnection::onErrorOccurred);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
  connect(m_socket, &QTcpSocket::stateChanged, this, &NetTcpConnection::onStateChanged);
 | 
					 | 
				
			||||||
  connect(m_socket, &QTcpSocket::readyRead, this, &NetTcpConnection::onReadyRead);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NetTcpConnection::~NetTcpConnection()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  m_socket->disconnect(this);
 | 
					 | 
				
			||||||
  disconnectFromServer();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool NetTcpConnection::isConnected()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  return m_last_state == QAbstractSocket::ConnectedState;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void NetTcpConnection::connectToServer(ServerInfo &server)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  disconnectedFromServer();
 | 
					 | 
				
			||||||
  m_socket->connectToHost(server.ip, server.port);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void NetTcpConnection::disconnectFromServer()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  m_socket->abort();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void NetTcpConnection::sendPacket(AOPacket packet)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if (!isConnected())
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    qWarning().noquote() << QObject::tr("Cannot send packet, not connected to server");
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  m_socket->write(packet.toString(true).toUtf8());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void NetTcpConnection::onErrorOccurred()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  Q_EMIT errorOccurred(m_socket->errorString());
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void NetTcpConnection::onStateChanged(QAbstractSocket::SocketState state)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  m_last_state = state;
 | 
					 | 
				
			||||||
  switch (state)
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
  default:
 | 
					 | 
				
			||||||
    break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  case QAbstractSocket::ConnectedState:
 | 
					 | 
				
			||||||
    m_cached_data.clear();
 | 
					 | 
				
			||||||
    Q_EMIT connectedToServer();
 | 
					 | 
				
			||||||
    break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  case QAbstractSocket::UnconnectedState:
 | 
					 | 
				
			||||||
    Q_EMIT disconnectFromServer();
 | 
					 | 
				
			||||||
    break;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void NetTcpConnection::onReadyRead()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  m_cached_data += QString::fromUtf8(m_socket->readAll());
 | 
					 | 
				
			||||||
  if (!m_cached_data.endsWith('%'))
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  QStringList raw_packet_list = m_cached_data.split('%', Qt::SkipEmptyParts);
 | 
					 | 
				
			||||||
  m_cached_data.clear();
 | 
					 | 
				
			||||||
  for (QString raw_packet : raw_packet_list)
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    if (!raw_packet.endsWith('#'))
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      Q_EMIT errorOccurred(QObject::tr("Malformed packet received %1").arg(raw_packet));
 | 
					 | 
				
			||||||
      continue;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    raw_packet.chop(1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    QStringList raw_content = raw_packet.split('#');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const QString header = raw_content.takeFirst();
 | 
					 | 
				
			||||||
    for (QString &data : raw_content)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      data = AOPacket::decode(data);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Q_EMIT receivedPacket(AOPacket(header, raw_content));
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,31 +0,0 @@
 | 
				
			|||||||
#pragma once
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "aopacket.h"
 | 
					 | 
				
			||||||
#include "datatypes.h"
 | 
					 | 
				
			||||||
#include "netconnection.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <QTcpSocket>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class NetTcpConnection : public NetConnection
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
  NetTcpConnection(QObject *parent = nullptr);
 | 
					 | 
				
			||||||
  virtual ~NetTcpConnection();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool isConnected() override;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  void connectToServer(ServerInfo &server) override;
 | 
					 | 
				
			||||||
  void disconnectFromServer() override;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  void sendPacket(AOPacket packet) override;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
  QTcpSocket *m_socket;
 | 
					 | 
				
			||||||
  QAbstractSocket::SocketState m_last_state;
 | 
					 | 
				
			||||||
  QString m_cached_data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
private Q_SLOTS:
 | 
					 | 
				
			||||||
  void onErrorOccurred();
 | 
					 | 
				
			||||||
  void onStateChanged(QAbstractSocket::SocketState state);
 | 
					 | 
				
			||||||
  void onReadyRead();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
@ -1,32 +0,0 @@
 | 
				
			|||||||
#pragma once
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "netconnection.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class NetworkManager;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <QWebSocket>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class NetWebSocketConnection : public NetConnection
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
  NetWebSocketConnection(NetworkManager *networkManager);
 | 
					 | 
				
			||||||
  virtual ~NetWebSocketConnection();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bool isConnected() override;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  void connectToServer(ServerInfo &server) override;
 | 
					 | 
				
			||||||
  void disconnectFromServer() override;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  void sendPacket(AOPacket packet) override;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
  NetworkManager *m_network_manager;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  QWebSocket *m_socket;
 | 
					 | 
				
			||||||
  QAbstractSocket::SocketState m_last_state;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
private Q_SLOTS:
 | 
					 | 
				
			||||||
  void onError();
 | 
					 | 
				
			||||||
  void onStateChanged(QAbstractSocket::SocketState state);
 | 
					 | 
				
			||||||
  void onTextMessageReceived(QString message);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
							
								
								
									
										6
									
								
								src/network/serverinfo.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/network/serverinfo.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					#include "serverinfo.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QString ServerInfo::toString() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return QString("%1 (%2:%3)").arg(name.isEmpty() ? QStringLiteral("Unnamed Server") : name).arg(address).arg(port);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										15
									
								
								src/network/serverinfo.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/network/serverinfo.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <QString>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ServerInfo
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  QString name;
 | 
				
			||||||
 | 
					  QString description;
 | 
				
			||||||
 | 
					  QString address;
 | 
				
			||||||
 | 
					  quint16 port = 0;
 | 
				
			||||||
 | 
					  bool legacy = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  QString toString() const;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -1,48 +1,48 @@
 | 
				
			|||||||
#include "netwebsocketconnection.h"
 | 
					#include "websocketconnection.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "networkmanager.h"
 | 
					#include "aoapplication.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <QNetworkRequest>
 | 
					#include <QNetworkRequest>
 | 
				
			||||||
#include <QUrl>
 | 
					#include <QUrl>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NetWebSocketConnection::NetWebSocketConnection(NetworkManager *networkManager)
 | 
					WebSocketConnection::WebSocketConnection(AOApplication *ao_app, QObject *parent)
 | 
				
			||||||
    : NetConnection(networkManager)
 | 
					    : QObject(parent)
 | 
				
			||||||
    , m_network_manager(networkManager)
 | 
					    , ao_app(ao_app)
 | 
				
			||||||
    , m_socket(new QWebSocket(QString(), QWebSocketProtocol::VersionLatest, this))
 | 
					    , m_socket(new QWebSocket(QString(), QWebSocketProtocol::VersionLatest, this))
 | 
				
			||||||
    , m_last_state(QAbstractSocket::UnconnectedState)
 | 
					    , m_last_state(QAbstractSocket::UnconnectedState)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  connect(m_socket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error), this, &NetWebSocketConnection::onError);
 | 
					  connect(m_socket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error), this, &WebSocketConnection::onError);
 | 
				
			||||||
  connect(m_socket, &QWebSocket::stateChanged, this, &NetWebSocketConnection::onStateChanged);
 | 
					  connect(m_socket, &QWebSocket::stateChanged, this, &WebSocketConnection::onStateChanged);
 | 
				
			||||||
  connect(m_socket, &QWebSocket::textMessageReceived, this, &NetWebSocketConnection::onTextMessageReceived);
 | 
					  connect(m_socket, &QWebSocket::textMessageReceived, this, &WebSocketConnection::onTextMessageReceived);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NetWebSocketConnection::~NetWebSocketConnection()
 | 
					WebSocketConnection::~WebSocketConnection()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  m_socket->disconnect(this);
 | 
					  m_socket->disconnect(this);
 | 
				
			||||||
  disconnectFromServer();
 | 
					  disconnectFromServer();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool NetWebSocketConnection::isConnected()
 | 
					bool WebSocketConnection::isConnected()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  return m_last_state == QAbstractSocket::ConnectedState;
 | 
					  return m_last_state == QAbstractSocket::ConnectedState;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void NetWebSocketConnection::connectToServer(ServerInfo &server)
 | 
					void WebSocketConnection::connectToServer(const ServerInfo &server)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  disconnectFromServer();
 | 
					  disconnectFromServer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QUrl url;
 | 
					  QUrl url;
 | 
				
			||||||
  url.setScheme("ws");
 | 
					  url.setScheme("ws");
 | 
				
			||||||
  url.setHost(server.ip);
 | 
					  url.setHost(server.address);
 | 
				
			||||||
  url.setPort(server.port);
 | 
					  url.setPort(server.port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QNetworkRequest req(url);
 | 
					  QNetworkRequest req(url);
 | 
				
			||||||
  req.setHeader(QNetworkRequest::UserAgentHeader, m_network_manager->get_user_agent());
 | 
					  req.setHeader(QNetworkRequest::UserAgentHeader, QStringLiteral("AttorneyOnline/%1 (Desktop)").arg(ao_app->get_version_string()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  m_socket->open(req);
 | 
					  m_socket->open(req);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void NetWebSocketConnection::disconnectFromServer()
 | 
					void WebSocketConnection::disconnectFromServer()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  if (isConnected())
 | 
					  if (isConnected())
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
@ -50,17 +50,17 @@ void NetWebSocketConnection::disconnectFromServer()
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void NetWebSocketConnection::sendPacket(AOPacket packet)
 | 
					void WebSocketConnection::sendPacket(AOPacket packet)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  m_socket->sendTextMessage(packet.toString(true));
 | 
					  m_socket->sendTextMessage(packet.toString(true));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void NetWebSocketConnection::onError()
 | 
					void WebSocketConnection::onError()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  Q_EMIT errorOccurred(m_socket->errorString());
 | 
					  Q_EMIT errorOccurred(m_socket->errorString());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void NetWebSocketConnection::onStateChanged(QAbstractSocket::SocketState state)
 | 
					void WebSocketConnection::onStateChanged(QAbstractSocket::SocketState state)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  m_last_state = state;
 | 
					  m_last_state = state;
 | 
				
			||||||
  switch (state)
 | 
					  switch (state)
 | 
				
			||||||
@ -78,7 +78,7 @@ void NetWebSocketConnection::onStateChanged(QAbstractSocket::SocketState state)
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void NetWebSocketConnection::onTextMessageReceived(QString message)
 | 
					void WebSocketConnection::onTextMessageReceived(QString message)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  if (!message.endsWith("#%"))
 | 
					  if (!message.endsWith("#%"))
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
							
								
								
									
										43
									
								
								src/network/websocketconnection.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/network/websocketconnection.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "aopacket.h"
 | 
				
			||||||
 | 
					#include "serverinfo.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <QObject>
 | 
				
			||||||
 | 
					#include <QWebSocket>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AOApplication;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class WebSocketConnection : public QObject
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Q_OBJECT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  explicit WebSocketConnection(AOApplication *ao_app, QObject *parent = nullptr);
 | 
				
			||||||
 | 
					  virtual ~WebSocketConnection();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool isConnected();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void connectToServer(const ServerInfo &server);
 | 
				
			||||||
 | 
					  void disconnectFromServer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void sendPacket(AOPacket packet);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Q_SIGNALS:
 | 
				
			||||||
 | 
					  void connectedToServer();
 | 
				
			||||||
 | 
					  void disconnectedFromServer();
 | 
				
			||||||
 | 
					  void errorOccurred(QString error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void receivedPacket(AOPacket packet);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  AOApplication *ao_app;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  QWebSocket *m_socket;
 | 
				
			||||||
 | 
					  QAbstractSocket::SocketState m_last_state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private Q_SLOTS:
 | 
				
			||||||
 | 
					  void onError();
 | 
				
			||||||
 | 
					  void onStateChanged(QAbstractSocket::SocketState state);
 | 
				
			||||||
 | 
					  void onTextMessageReceived(QString message);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -3,8 +3,6 @@
 | 
				
			|||||||
#include "datatypes.h"
 | 
					#include "datatypes.h"
 | 
				
			||||||
#include "debug_functions.h"
 | 
					#include "debug_functions.h"
 | 
				
			||||||
#include "lobby.h"
 | 
					#include "lobby.h"
 | 
				
			||||||
#include "net/nettcpconnection.h"
 | 
					 | 
				
			||||||
#include "net/netwebsocketconnection.h"
 | 
					 | 
				
			||||||
#include "options.h"
 | 
					#include "options.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <QAbstractSocket>
 | 
					#include <QAbstractSocket>
 | 
				
			||||||
@ -59,19 +57,19 @@ void NetworkManager::ms_request_finished(QNetworkReply *reply)
 | 
				
			|||||||
  {
 | 
					  {
 | 
				
			||||||
    const auto entry = entryRef.toObject();
 | 
					    const auto entry = entryRef.toObject();
 | 
				
			||||||
    ServerInfo server;
 | 
					    ServerInfo server;
 | 
				
			||||||
    server.ip = entry["ip"].toString();
 | 
					    server.address = entry["ip"].toString();
 | 
				
			||||||
    server.name = entry["name"].toString();
 | 
					    server.name = entry["name"].toString();
 | 
				
			||||||
    server.description = entry["description"].toString(tr("No description provided."));
 | 
					    server.description = entry["description"].toString(tr("No description provided."));
 | 
				
			||||||
    if (entry["ws_port"].isDouble())
 | 
					    if (entry.contains("ws_port"))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      server.socket_type = WebSocketServerConnection;
 | 
					 | 
				
			||||||
      server.port = entry["ws_port"].toInt();
 | 
					      server.port = entry["ws_port"].toInt();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      server.socket_type = TcpServerConnection;
 | 
					 | 
				
			||||||
      server.port = entry["port"].toInt();
 | 
					      server.port = entry["port"].toInt();
 | 
				
			||||||
 | 
					      server.legacy = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (server.port != 0)
 | 
					    if (server.port != 0)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      server_list.append(server);
 | 
					      server_list.append(server);
 | 
				
			||||||
@ -149,27 +147,12 @@ void NetworkManager::connect_to_server(ServerInfo server)
 | 
				
			|||||||
  disconnect_from_server();
 | 
					  disconnect_from_server();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  qInfo().noquote() << QObject::tr("Connecting to %1").arg(server.toString());
 | 
					  qInfo().noquote() << QObject::tr("Connecting to %1").arg(server.toString());
 | 
				
			||||||
  switch (server.socket_type)
 | 
					  m_connection = new WebSocketConnection(ao_app, this);
 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
  default:
 | 
					 | 
				
			||||||
    server.socket_type = TcpServerConnection;
 | 
					 | 
				
			||||||
    [[fallthrough]];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  case TcpServerConnection:
 | 
					  connect(m_connection, &WebSocketConnection::connectedToServer, this, [] { qInfo() << "Established connection to server."; });
 | 
				
			||||||
    qInfo() << "Using TCP backend.";
 | 
					  connect(m_connection, &WebSocketConnection::disconnectedFromServer, ao_app, &AOApplication::server_disconnected);
 | 
				
			||||||
    m_connection = new NetTcpConnection(this);
 | 
					  connect(m_connection, &WebSocketConnection::errorOccurred, this, [](QString error) { qCritical() << "Connection error:" << error; });
 | 
				
			||||||
    break;
 | 
					  connect(m_connection, &WebSocketConnection::receivedPacket, this, &NetworkManager::handle_server_packet);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  case WebSocketServerConnection:
 | 
					 | 
				
			||||||
    qInfo() << "Using WebSockets backend.";
 | 
					 | 
				
			||||||
    m_connection = new NetWebSocketConnection(this);
 | 
					 | 
				
			||||||
    break;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  connect(m_connection, &NetConnection::connectedToServer, this, [] { qInfo() << "Established connection to server."; });
 | 
					 | 
				
			||||||
  connect(m_connection, &NetConnection::disconnectedFromServer, ao_app, &AOApplication::server_disconnected);
 | 
					 | 
				
			||||||
  connect(m_connection, &NetConnection::errorOccurred, this, [](QString error) { qCritical() << "Connection error:" << error; });
 | 
					 | 
				
			||||||
  connect(m_connection, &NetConnection::receivedPacket, this, &NetworkManager::handle_server_packet);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  m_connection->connectToServer(server);
 | 
					  m_connection->connectToServer(server);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "aoapplication.h"
 | 
					#include "aoapplication.h"
 | 
				
			||||||
#include "aopacket.h"
 | 
					#include "aopacket.h"
 | 
				
			||||||
#include "net/netconnection.h"
 | 
					#include "network/websocketconnection.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <QDnsLookup>
 | 
					#include <QDnsLookup>
 | 
				
			||||||
#include <QNetworkAccessManager>
 | 
					#include <QNetworkAccessManager>
 | 
				
			||||||
@ -50,7 +50,7 @@ private:
 | 
				
			|||||||
  AOApplication *ao_app;
 | 
					  AOApplication *ao_app;
 | 
				
			||||||
  QNetworkAccessManager *http;
 | 
					  QNetworkAccessManager *http;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  NetConnection *m_connection = nullptr;
 | 
					  WebSocketConnection *m_connection = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QTimer *heartbeat_timer;
 | 
					  QTimer *heartbeat_timer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -668,11 +668,19 @@ QVector<ServerInfo> Options::favorites()
 | 
				
			|||||||
  {
 | 
					  {
 | 
				
			||||||
    ServerInfo f_server;
 | 
					    ServerInfo f_server;
 | 
				
			||||||
    favorite.beginGroup(group);
 | 
					    favorite.beginGroup(group);
 | 
				
			||||||
    f_server.ip = favorite.value("address", "127.0.0.1").toString();
 | 
					    f_server.address = favorite.value("address", "127.0.0.1").toString();
 | 
				
			||||||
    f_server.port = favorite.value("port", 27016).toInt();
 | 
					    f_server.port = favorite.value("port", 27016).toInt();
 | 
				
			||||||
    f_server.name = favorite.value("name", "Missing Name").toString();
 | 
					    f_server.name = favorite.value("name", "Missing Name").toString();
 | 
				
			||||||
    f_server.description = favorite.value("desc", "No description").toString();
 | 
					    f_server.description = favorite.value("desc", "No description").toString();
 | 
				
			||||||
    f_server.socket_type = SERVER_CONNECTION_TYPE_STRING_MAP.value(favorite.value("protocol", "tcp").toString());
 | 
					    if (favorite.contains("protocol"))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      f_server.legacy = favorite.value("protocol").toString() == "tcp";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      f_server.legacy = favorite.value("legacy", false).toBool();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    serverlist.append(std::move(f_server));
 | 
					    serverlist.append(std::move(f_server));
 | 
				
			||||||
    favorite.endGroup();
 | 
					    favorite.endGroup();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -688,18 +696,10 @@ void Options::setFavorites(QVector<ServerInfo> value)
 | 
				
			|||||||
    auto fav_server = value.at(i);
 | 
					    auto fav_server = value.at(i);
 | 
				
			||||||
    favorite.beginGroup(QString::number(i));
 | 
					    favorite.beginGroup(QString::number(i));
 | 
				
			||||||
    favorite.setValue("name", fav_server.name);
 | 
					    favorite.setValue("name", fav_server.name);
 | 
				
			||||||
    favorite.setValue("address", fav_server.ip);
 | 
					    favorite.setValue("address", fav_server.address);
 | 
				
			||||||
    favorite.setValue("port", fav_server.port);
 | 
					    favorite.setValue("port", fav_server.port);
 | 
				
			||||||
    favorite.setValue("desc", fav_server.description);
 | 
					    favorite.setValue("desc", fav_server.description);
 | 
				
			||||||
 | 
					    favorite.setValue("legacy", fav_server.legacy);
 | 
				
			||||||
    if (fav_server.socket_type == TcpServerConnection)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      favorite.setValue("protocol", "tcp");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      favorite.setValue("protocol", "ws");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    favorite.endGroup();
 | 
					    favorite.endGroup();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  favorite.sync();
 | 
					  favorite.sync();
 | 
				
			||||||
@ -717,17 +717,10 @@ void Options::addFavorite(ServerInfo server)
 | 
				
			|||||||
  int index = favorites().size();
 | 
					  int index = favorites().size();
 | 
				
			||||||
  favorite.beginGroup(QString::number(index));
 | 
					  favorite.beginGroup(QString::number(index));
 | 
				
			||||||
  favorite.setValue("name", server.name);
 | 
					  favorite.setValue("name", server.name);
 | 
				
			||||||
  favorite.setValue("address", server.ip);
 | 
					  favorite.setValue("address", server.address);
 | 
				
			||||||
  favorite.setValue("port", server.port);
 | 
					  favorite.setValue("port", server.port);
 | 
				
			||||||
  favorite.setValue("desc", server.description);
 | 
					  favorite.setValue("desc", server.description);
 | 
				
			||||||
  if (server.socket_type == TcpServerConnection)
 | 
					  favorite.setValue("legacy", server.legacy);
 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    favorite.setValue("protocol", "tcp");
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    favorite.setValue("protocol", "ws");
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  favorite.endGroup();
 | 
					  favorite.endGroup();
 | 
				
			||||||
  favorite.sync();
 | 
					  favorite.sync();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -736,17 +729,10 @@ void Options::updateFavorite(ServerInfo server, int index)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  favorite.beginGroup(QString::number(index));
 | 
					  favorite.beginGroup(QString::number(index));
 | 
				
			||||||
  favorite.setValue("name", server.name);
 | 
					  favorite.setValue("name", server.name);
 | 
				
			||||||
  favorite.setValue("address", server.ip);
 | 
					  favorite.setValue("address", server.address);
 | 
				
			||||||
  favorite.setValue("port", server.port);
 | 
					  favorite.setValue("port", server.port);
 | 
				
			||||||
  favorite.setValue("desc", server.description);
 | 
					  favorite.setValue("desc", server.description);
 | 
				
			||||||
  if (server.socket_type == TcpServerConnection)
 | 
					  favorite.setValue("legacy", server.legacy);
 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    favorite.setValue("protocol", "tcp");
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    favorite.setValue("protocol", "ws");
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  favorite.endGroup();
 | 
					  favorite.endGroup();
 | 
				
			||||||
  favorite.sync();
 | 
					  favorite.sync();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,9 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "network/serverinfo.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <QCoreApplication>
 | 
					#include <QCoreApplication>
 | 
				
			||||||
#include <QSettings>
 | 
					#include <QSettings>
 | 
				
			||||||
#include <datatypes.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Options
 | 
					class Options
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
				
			|||||||
@ -132,7 +132,7 @@ void AOApplication::server_packet_received(AOPacket packet)
 | 
				
			|||||||
      {
 | 
					      {
 | 
				
			||||||
        auto info = server_list.at(selected_server);
 | 
					        auto info = server_list.at(selected_server);
 | 
				
			||||||
        server_name = info.name;
 | 
					        server_name = info.name;
 | 
				
			||||||
        server_address = QString("%1:%2").arg(info.ip, QString::number(info.port));
 | 
					        server_address = QString("%1:%2").arg(info.address, QString::number(info.port));
 | 
				
			||||||
        window_title = server_name;
 | 
					        window_title = server_name;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
@ -144,7 +144,7 @@ void AOApplication::server_packet_received(AOPacket packet)
 | 
				
			|||||||
      {
 | 
					      {
 | 
				
			||||||
        auto info = favorite_list.at(selected_server);
 | 
					        auto info = favorite_list.at(selected_server);
 | 
				
			||||||
        server_name = info.name;
 | 
					        server_name = info.name;
 | 
				
			||||||
        server_address = QString("%1:%2").arg(info.ip, QString::number(info.port));
 | 
					        server_address = QString("%1:%2").arg(info.address, QString::number(info.port));
 | 
				
			||||||
        window_title = server_name;
 | 
					        window_title = server_name;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -50,27 +50,29 @@ void DirectConnectDialog::onConnectPressed()
 | 
				
			|||||||
  QString l_hostname = ui_direct_hostname_edit->text();
 | 
					  QString l_hostname = ui_direct_hostname_edit->text();
 | 
				
			||||||
  if (!SCHEME_PATTERN.match(l_hostname).hasMatch())
 | 
					  if (!SCHEME_PATTERN.match(l_hostname).hasMatch())
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    l_hostname = "tcp://" % l_hostname;
 | 
					    l_hostname = "ws://" % l_hostname;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QUrl l_url(l_hostname);
 | 
					  QUrl l_url(l_hostname);
 | 
				
			||||||
  if (!l_url.isValid())
 | 
					  if (!l_url.isValid())
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    call_error(tr("Invalid URL."));
 | 
					    call_error(tr("Invalid URL."));
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (!SERVER_CONNECTION_TYPE_STRING_MAP.contains(l_url.scheme()))
 | 
					
 | 
				
			||||||
 | 
					  if (l_url.scheme() != "ws")
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    call_error(tr("Scheme not recognized. Must be either of the following: ") % QStringList::fromVector(SERVER_CONNECTION_TYPE_STRING_MAP.keys().toVector()).join(", "));
 | 
					    call_error(tr("Invalid URL scheme. Only ws:// is supported."));
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (l_url.port() == -1)
 | 
					  if (l_url.port() == -1)
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    call_error(tr("Invalid server port."));
 | 
					    call_error(tr("Invalid server port."));
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  ServerInfo l_server;
 | 
					  ServerInfo l_server;
 | 
				
			||||||
  l_server.socket_type = SERVER_CONNECTION_TYPE_STRING_MAP[l_url.scheme()];
 | 
					  l_server.address = l_url.host();
 | 
				
			||||||
  l_server.ip = l_url.host();
 | 
					 | 
				
			||||||
  l_server.port = l_url.port();
 | 
					  l_server.port = l_url.port();
 | 
				
			||||||
  l_server.name = "Direct Connection";
 | 
					  l_server.name = "Direct Connection";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
#include "server_editor_dialog.h"
 | 
					#include "server_editor_dialog.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "datatypes.h"
 | 
					#include "datatypes.h"
 | 
				
			||||||
 | 
					#include "debug_functions.h"
 | 
				
			||||||
#include "gui_utils.h"
 | 
					#include "gui_utils.h"
 | 
				
			||||||
#include "options.h"
 | 
					#include "options.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -30,7 +31,6 @@ ServerEditorDialog::ServerEditorDialog(QWidget *parent)
 | 
				
			|||||||
  FROM_UI(QLineEdit, name);
 | 
					  FROM_UI(QLineEdit, name);
 | 
				
			||||||
  FROM_UI(QLineEdit, hostname);
 | 
					  FROM_UI(QLineEdit, hostname);
 | 
				
			||||||
  FROM_UI(QSpinBox, port);
 | 
					  FROM_UI(QSpinBox, port);
 | 
				
			||||||
  FROM_UI(QComboBox, protocol);
 | 
					 | 
				
			||||||
  FROM_UI(QPlainTextEdit, description);
 | 
					  FROM_UI(QPlainTextEdit, description);
 | 
				
			||||||
  FROM_UI(QDialogButtonBox, button_box);
 | 
					  FROM_UI(QDialogButtonBox, button_box);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -43,52 +43,35 @@ ServerEditorDialog::ServerEditorDialog(QWidget *parent)
 | 
				
			|||||||
  connect(ui_button_box, &QDialogButtonBox::rejected, this, &ServerEditorDialog::reject);
 | 
					  connect(ui_button_box, &QDialogButtonBox::rejected, this, &ServerEditorDialog::reject);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ServerEditorDialog::ServerEditorDialog(const ServerInfo &server, QWidget *parent)
 | 
				
			||||||
 | 
					    : ServerEditorDialog(parent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  ui_name->setText(server.name);
 | 
				
			||||||
 | 
					  ui_hostname->setText(server.address);
 | 
				
			||||||
 | 
					  ui_port->setValue(server.port);
 | 
				
			||||||
 | 
					  ui_description->setPlainText(server.description);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ServerInfo ServerEditorDialog::currentServerInfo() const
 | 
					ServerInfo ServerEditorDialog::currentServerInfo() const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  ServerInfo server;
 | 
					  ServerInfo server;
 | 
				
			||||||
  server.name = ui_name->text();
 | 
					  server.name = ui_name->text();
 | 
				
			||||||
  server.ip = ui_hostname->text();
 | 
					  server.address = ui_hostname->text();
 | 
				
			||||||
  server.port = ui_port->value();
 | 
					  server.port = ui_port->value();
 | 
				
			||||||
  server.description = ui_description->toPlainText();
 | 
					  server.description = ui_description->toPlainText();
 | 
				
			||||||
  server.socket_type = ServerConnectionType(ui_protocol->currentIndex());
 | 
					 | 
				
			||||||
  return server;
 | 
					  return server;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ServerEditorDialog::loadServerInfo(ServerInfo server)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  ui_name->setText(server.name);
 | 
					 | 
				
			||||||
  ui_hostname->setText(server.ip);
 | 
					 | 
				
			||||||
  ui_port->setValue(server.port);
 | 
					 | 
				
			||||||
  ui_description->setPlainText(server.description);
 | 
					 | 
				
			||||||
  ui_protocol->setCurrentIndex(server.socket_type);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void ServerEditorDialog::parseLegacyEntry()
 | 
					void ServerEditorDialog::parseLegacyEntry()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  QStringList entry = ui_legacy_edit->text().split(":");
 | 
					  QStringList entry = ui_legacy_edit->text().split(":");
 | 
				
			||||||
  ServerInfo l_server_entry;
 | 
					  if (entry.size() < 3)
 | 
				
			||||||
  if (entry.isEmpty())
 | 
					 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    qDebug() << "Legacy entry empty.";
 | 
					    call_error("Invalid legacy server entry");
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int item_count = entry.size();
 | 
					 | 
				
			||||||
  if (item_count >= 3)
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
  ui_hostname->setText(entry.at(0));
 | 
					  ui_hostname->setText(entry.at(0));
 | 
				
			||||||
  ui_port->setValue(entry.at(1).toInt());
 | 
					  ui_port->setValue(entry.at(1).toInt());
 | 
				
			||||||
  ui_name->setText(entry.at(2));
 | 
					  ui_name->setText(entry.at(2));
 | 
				
			||||||
    if (item_count >= 4)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      if (entry.at(3) == "ws")
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        ui_protocol->setCurrentIndex(1);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      else
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        ui_protocol->setCurrentIndex(0);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "datatypes.h"
 | 
					#include "network/serverinfo.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <QComboBox>
 | 
					#include <QComboBox>
 | 
				
			||||||
#include <QDialog>
 | 
					#include <QDialog>
 | 
				
			||||||
@ -21,8 +21,6 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  ServerInfo currentServerInfo() const;
 | 
					  ServerInfo currentServerInfo() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void loadServerInfo(ServerInfo server);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
  static const QString UI_FILE_PATH;
 | 
					  static const QString UI_FILE_PATH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -31,7 +29,6 @@ private:
 | 
				
			|||||||
  QLineEdit *ui_name;
 | 
					  QLineEdit *ui_name;
 | 
				
			||||||
  QLineEdit *ui_hostname;
 | 
					  QLineEdit *ui_hostname;
 | 
				
			||||||
  QSpinBox *ui_port;
 | 
					  QSpinBox *ui_port;
 | 
				
			||||||
  QComboBox *ui_protocol;
 | 
					 | 
				
			||||||
  QPlainTextEdit *ui_description;
 | 
					  QPlainTextEdit *ui_description;
 | 
				
			||||||
  QDialogButtonBox *ui_button_box;
 | 
					  QDialogButtonBox *ui_button_box;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user