From 29ec4e8af37baf8a3abcd23377784f2754942a0d Mon Sep 17 00:00:00 2001 From: David Skoland Date: Fri, 6 Jan 2017 03:09:14 +0100 Subject: [PATCH] forgot to add some things --- Attorney_Online_remake.pro | 8 ++- aoapplication.h | 14 ++++++ aopacket.cpp | 55 ++++++++++++++++++++- aopacket.h | 9 ++++ encryption_functions.cpp | 69 ++++++++++++++++++++++++++ encryption_functions.h | 5 ++ hex_functions.cpp | 4 +- lobby.cpp | 24 ++++++--- lobby.h | 3 +- main.cpp | 2 +- networkmanager.cpp | 61 +++++++++++++++++------ networkmanager.h | 9 ++-- packet_distribution.cpp | 99 ++++++++++++++++++++++++++++++++++++-- 13 files changed, 326 insertions(+), 36 deletions(-) diff --git a/Attorney_Online_remake.pro b/Attorney_Online_remake.pro index b24292f..f8a203f 100644 --- a/Attorney_Online_remake.pro +++ b/Attorney_Online_remake.pro @@ -25,7 +25,9 @@ SOURCES += main.cpp\ networkmanager.cpp \ aoapplication.cpp \ aopacket.cpp \ - packet_distribution.cpp + packet_distribution.cpp \ + hex_functions.cpp \ + encryption_functions.cpp HEADERS += lobby.h \ text_file_functions.h \ @@ -38,4 +40,6 @@ HEADERS += lobby.h \ networkmanager.h \ aoapplication.h \ datatypes.h \ - aopacket.h + aopacket.h \ + hex_functions.h \ + encryption_functions.h diff --git a/aoapplication.h b/aoapplication.h index f1bc56b..0b8d453 100644 --- a/aoapplication.h +++ b/aoapplication.h @@ -37,6 +37,20 @@ public: QVector favorite_list; void ms_packet_received(AOPacket *p_packet); + void server_packet_received(AOPacket *p_packet); + + void send_ms_packet(AOPacket *p_packet); + void send_server_packet(AOPacket *p_packet); + + /////////////////server metadata////////////////// + + unsigned int s_decryptor = 5; + bool encryption_needed = true; + bool ao2_features = false; + //player number, it's hardly used but might be needed for some old servers + bool s_pv = 0; + + ////////////////////////////////////////////////// }; #endif // AOAPPLICATION_H diff --git a/aopacket.cpp b/aopacket.cpp index 553816b..fa8f5be 100644 --- a/aopacket.cpp +++ b/aopacket.cpp @@ -1,5 +1,9 @@ #include "aopacket.h" +#include "encryption_functions.h" + +#include + AOPacket::AOPacket(QString p_packet_string) { QStringList packet_contents = p_packet_string.split("#"); @@ -12,6 +16,12 @@ AOPacket::AOPacket(QString p_packet_string) } } +AOPacket::AOPacket(QString p_header, QStringList &p_contents) +{ + m_header = p_header; + m_contents = p_contents; +} + AOPacket::~AOPacket() { @@ -28,5 +38,48 @@ QString AOPacket::to_string() f_string += "#%"; - return f_string; + + if (encrypted) + return "#" + f_string; + else + return f_string; } + +void AOPacket::encrypt_header(unsigned int p_key) +{ + m_header = fanta_encrypt(m_header, p_key); + + encrypted = true; +} + +void AOPacket::decrypt_header(unsigned int p_key) +{ + m_header = fanta_decrypt(m_header, p_key); + + encrypted = false; +} + +void AOPacket::net_encode() +{ + for (int n_element = 0 ; n_element < m_contents.size() ; ++n_element) + { + QString f_element = m_contents.at(n_element); + f_element.replace("#", "").replace("%", "").replace("$", "").replace("&", ""); + + m_contents.removeAt(n_element); + m_contents.insert(n_element, f_element); + } +} + +void AOPacket::net_decode() +{ + for (int n_element = 0 ; n_element < m_contents.size() ; ++n_element) + { + QString f_element = m_contents.at(n_element); + f_element.replace("", "#").replace("", "%").replace("", "$").replace("", "&"); + + m_contents.removeAt(n_element); + m_contents.insert(n_element, f_element); + } +} + diff --git a/aopacket.h b/aopacket.h index 13f4705..40dd3ec 100644 --- a/aopacket.h +++ b/aopacket.h @@ -8,13 +8,22 @@ class AOPacket { public: AOPacket(QString p_packet_string); + AOPacket(QString header, QStringList &p_contents); ~AOPacket(); QString get_header() {return m_header;} QStringList &get_contents() {return m_contents;} QString to_string(); + void encrypt_header(unsigned int p_key); + void decrypt_header(unsigned int p_key); + + void net_encode(); + void net_decode(); + private: + bool encrypted = false; + QString m_header; QStringList m_contents; }; diff --git a/encryption_functions.cpp b/encryption_functions.cpp index e69de29..56b6e34 100644 --- a/encryption_functions.cpp +++ b/encryption_functions.cpp @@ -0,0 +1,69 @@ +#include "encryption_functions.h" + +#include "hex_functions.h" + +#include +#include +#include +#include +#include + +QString fanta_encrypt(QString temp_input, unsigned int p_key) +{ + //using standard stdlib types is actually easier here because of implicit char<->int conversion + //which in turn makes encryption arithmetic easier + + unsigned int key = p_key; + unsigned int C1 = 53761; + unsigned int C2 = 32618; + + QVector temp_result; + std::string input = temp_input.toUtf8().constData(); + + for (unsigned int pos = 0 ; pos < input.size() ; ++pos) + { + uint_fast8_t output = input.at(pos) ^ (key >> 8) % 256; + temp_result.append(output); + key = (temp_result.at(pos) + key) * C1 + C2; + } + + std::string result = ""; + + for (uint_fast8_t i_int : temp_result) + { + result += omni::int_to_hex(i_int); + } + + QString final_result = QString::fromStdString(result); + + return final_result; +} + +QString fanta_decrypt(QString temp_input, unsigned int key) +{ + std::string input = temp_input.toUtf8().constData(); + + QVector unhexed_vector; + + for(unsigned int i=0; i< input.length(); i+=2) + { + std::string byte = input.substr(i,2); + unsigned int hex_int = strtoul(byte.c_str(), nullptr, 16); + unhexed_vector.append(hex_int); + } + + unsigned int C1 = 53761; + unsigned int C2 = 32618; + + std::string result = ""; + + for (int pos = 0 ; pos < unhexed_vector.size() ; ++pos) + { + unsigned char output = unhexed_vector.at(pos) ^ (key >> 8) % 256; + result += output; + key = (unhexed_vector.at(pos) + key) * C1 + C2; + } + + return QString::fromStdString(result); + +} diff --git a/encryption_functions.h b/encryption_functions.h index 0a9cf2e..b6ea1d7 100644 --- a/encryption_functions.h +++ b/encryption_functions.h @@ -1,4 +1,9 @@ #ifndef ENCRYPTION_FUNCTIONS_H #define ENCRYPTION_FUNCTIONS_H +#include + +QString fanta_encrypt(QString p_input, unsigned int key); +QString fanta_decrypt(QString p_input, unsigned int key); + #endif // ENCRYPTION_FUNCTIONS_H diff --git a/hex_functions.cpp b/hex_functions.cpp index 9b1222e..9db2b0a 100644 --- a/hex_functions.cpp +++ b/hex_functions.cpp @@ -1,6 +1,6 @@ -//WELCOME TO THE EXTREME GHETTO HEX CONVERSION KLUDGE BECAUSE I COULDNT MAKE ANYTHING ELSE WORK +//WELCOME TO THE EXTREMELY GHETTO HEX CONVERSION KLUDGE BECAUSE I COULDNT MAKE ANYTHING ELSE WORK -#include "hex_operations.h" +#include "hex_functions.h" namespace omni { diff --git a/lobby.cpp b/lobby.cpp index c7f27af..7bcdaff 100644 --- a/lobby.cpp +++ b/lobby.cpp @@ -15,6 +15,7 @@ Lobby::Lobby(AOApplication *parent) : QMainWindow() this->setWindowTitle("Attorney Online 2"); this->resize(m_lobby_width, m_lobby_height); + this->setFixedSize(m_lobby_width, m_lobby_height); ui_background = new AOImage(this); ui_public_servers = new AOButton(this); @@ -152,7 +153,7 @@ void Lobby::on_refresh_released() AOPacket *f_packet = new AOPacket("ALL#%"); - ao_app->net_manager->send_ms_packet(f_packet); + ao_app->send_ms_packet(f_packet); delete f_packet; } @@ -231,16 +232,19 @@ void Lobby::on_server_list_clicked(QModelIndex p_model) ui_description->moveCursor(QTextCursor::Start); ui_description->ensureCursorVisible(); - //T0D0: uncomment when implemented - //ao_app->net_manager->connect_to_server(f_server.ip, f_server.port); + ui_player_count->setText("Offline"); + + ao_app->net_manager->connect_to_server(f_server); } void Lobby::on_chatfield_return_pressed() { - QString raw_packet = "CT#" + ui_chatname->text() + "#" + ui_chatmessage->text() + "#%"; - AOPacket *f_packet = new AOPacket(raw_packet); + QString f_header = "CT"; + QStringList f_contents{ui_chatname->text(), ui_chatmessage->text()}; - ao_app->net_manager->send_ms_packet(f_packet); + AOPacket *f_packet = new AOPacket(f_header, f_contents); + + ao_app->send_ms_packet(f_packet); ui_chatmessage->clear(); @@ -267,7 +271,13 @@ void Lobby::list_favorites() } } -void Lobby::append_chat_message(QString p_message_line) +void Lobby::append_chatmessage(QString p_message_line) { ui_chatbox->appendPlainText(p_message_line); } + +void Lobby::set_player_count(int players_online, int max_players) +{ + QString f_string = "Online: " + QString::number(players_online) + "/" + QString::number(max_players); + ui_player_count->setText(f_string); +} diff --git a/lobby.h b/lobby.h index 16573c1..becf0e8 100644 --- a/lobby.h +++ b/lobby.h @@ -24,7 +24,8 @@ public: void set_widgets(); void list_servers(); void list_favorites(); - void append_chat_message(QString p_message_line); + void append_chatmessage(QString p_message_line); + void set_player_count(int players_online, int max_players); private: AOApplication *ao_app; diff --git a/main.cpp b/main.cpp index 9425c1f..59578b4 100644 --- a/main.cpp +++ b/main.cpp @@ -12,7 +12,7 @@ int main(int argc, char *argv[]) main_app.construct_lobby(); main_app.net_manager->connect_to_master(); AOPacket *f_packet = new AOPacket("ALL#%"); - main_app.net_manager->send_ms_packet(f_packet); + main_app.send_ms_packet(f_packet); main_app.w_lobby->show(); return main_app.exec(); diff --git a/networkmanager.cpp b/networkmanager.cpp index daca0f3..1aa5a00 100644 --- a/networkmanager.cpp +++ b/networkmanager.cpp @@ -30,20 +30,22 @@ void NetworkManager::connect_to_master() ms_socket->connectToHost(ms_hostname, ms_port); } -void NetworkManager::send_ms_packet(AOPacket *p_packet) +void NetworkManager::connect_to_server(server_type p_server) { - QString f_packet = p_packet->to_string(); + server_socket->close(); + server_socket->abort(); - ms_socket->write(f_packet.toLocal8Bit()); - qDebug() << "S(ms):" << f_packet; + server_socket->connectToHost(p_server.ip, p_server.port); } -void NetworkManager::send_server_packet(AOPacket *p_packet) +void NetworkManager::ship_ms_packet(QString p_packet) { - QString f_packet = p_packet->to_string(); + ms_socket->write(p_packet.toLocal8Bit()); +} - ms_socket->write(f_packet.toLocal8Bit()); - qDebug() << "S(ms):" << f_packet; +void NetworkManager::ship_server_packet(QString p_packet) +{ + server_socket->write(p_packet.toLocal8Bit()); } void NetworkManager::handle_ms_packet() @@ -53,6 +55,42 @@ void NetworkManager::handle_ms_packet() QString in_data = buffer; + if (!in_data.endsWith("%")) + { + ms_partial_packet = true; + ms_temp_packet += in_data; + return; + } + + else + { + if (ms_partial_packet) + { + in_data = ms_temp_packet + in_data; + ms_temp_packet = ""; + ms_partial_packet = false; + } + } + + QStringList packet_list = in_data.split("%", QString::SplitBehavior(QString::SkipEmptyParts)); + + for (QString packet : packet_list) + { + AOPacket *f_packet = new AOPacket(packet); + + ao_app->ms_packet_received(f_packet); + + delete f_packet; + } +} + +void NetworkManager::handle_server_packet() +{ + char buffer[16384] = {0}; + server_socket->read(buffer, server_socket->bytesAvailable()); + + QString in_data = buffer; + if (!in_data.endsWith("%")) { partial_packet = true; @@ -76,14 +114,9 @@ void NetworkManager::handle_ms_packet() { AOPacket *f_packet = new AOPacket(packet); - ao_app->ms_packet_received(f_packet); + ao_app->server_packet_received(f_packet); delete f_packet; } } -void NetworkManager::handle_server_packet() -{ - -} - diff --git a/networkmanager.h b/networkmanager.h index 499ed9e..e10dcca 100644 --- a/networkmanager.h +++ b/networkmanager.h @@ -21,15 +21,18 @@ public: QString ms_hostname = "master.aceattorneyonline.com"; int ms_port = 27016; + bool ms_partial_packet = false; + QString ms_temp_packet = ""; + bool partial_packet = false; QString temp_packet = ""; void connect_to_master(); + void connect_to_server(server_type p_server); public slots: - void send_ms_packet(AOPacket *p_packet); - - void send_server_packet(AOPacket *p_packet); + void ship_ms_packet(QString p_packet); + void ship_server_packet(QString p_packet); private slots: void handle_ms_packet(); diff --git a/packet_distribution.cpp b/packet_distribution.cpp index 5990d25..4e02fb4 100644 --- a/packet_distribution.cpp +++ b/packet_distribution.cpp @@ -1,12 +1,17 @@ #include "aoapplication.h" #include "lobby.h" +#include "networkmanager.h" +#include "encryption_functions.h" #include void AOApplication::ms_packet_received(AOPacket *p_packet) { + p_packet->net_decode(); + QString header = p_packet->get_header(); + QStringList f_contents = p_packet->get_contents(); if (header != "CHECK") qDebug() << "R(ms):" << p_packet->to_string(); @@ -22,7 +27,7 @@ void AOApplication::ms_packet_received(AOPacket *p_packet) if (sub_contents.size() < 4) { - qDebug() << "W: malformed packet!"; + qDebug() << "W: malformed packet"; continue; } @@ -41,8 +46,6 @@ void AOApplication::ms_packet_received(AOPacket *p_packet) } else if (header == "CT") { - QStringList f_contents = p_packet->get_contents(); - QString message_line; if (f_contents.size() == 1) @@ -54,12 +57,98 @@ void AOApplication::ms_packet_received(AOPacket *p_packet) if (lobby_constructed) { - w_lobby->append_chat_message(message_line); + w_lobby->append_chatmessage(message_line); } if (courtroom_constructed) { //T0D0: uncomment this when it's implemented - //w_courtroom->append_chat_message(message_line); + //w_courtroom->append_ms_chat_message(message_line); } } } + +void AOApplication::server_packet_received(AOPacket *p_packet) +{ + p_packet->net_decode(); + + QString header = p_packet->get_header(); + QStringList f_contents = p_packet->get_contents(); + QString f_packet = p_packet->to_string(); + + qDebug() << "R: " << f_packet; + + if (header == "decryptor") + { + if (f_contents.size() == 0) + return; + + //you may ask where 322 comes from. that would be a good question. + s_decryptor = fanta_decrypt(f_contents.at(0), 322).toUInt(); + + //T0D0 add an actual HDID here + AOPacket *hi_packet = new AOPacket("HI#ao2testinginprogressdontmindme#%"); + + send_server_packet(hi_packet); + + delete hi_packet; + } + else if (header == "ID") + { + if (f_contents.size() < 1) + return; + + } + else if (header == "CT") + { + if (f_contents.size() < 2) + { + qDebug() << "W: malformed packet!"; + return; + } + + //QString message_line = f_contents.at(0) + ": " + f_contents.at(1); + + //T0D0, uncomment when implemented + //w_courtroom->append_ooc_chatmessage(message_line) + } + else if (header == "PN") + { + if (f_contents.size() < 2) + return; + + w_lobby->set_player_count(f_contents.at(0).toInt(), f_contents.at(1).toInt()); + } +} + +void AOApplication::send_ms_packet(AOPacket *p_packet) +{ + p_packet->net_encode(); + + QString f_packet = p_packet->to_string(); + + net_manager->ship_ms_packet(f_packet); + + qDebug() << "S(ms):" << f_packet; +} + +void AOApplication::send_server_packet(AOPacket *p_packet) +{ + p_packet->net_encode(); + + QString f_packet = p_packet->to_string(); + + if (encryption_needed) + { + qDebug() << "S:(e)" << f_packet; + + p_packet->encrypt_header(s_decryptor); + f_packet = p_packet->to_string(); + } + else + { + qDebug() << "S:" << f_packet; + } + + net_manager->ship_server_packet(f_packet); + +}