summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2023-03-06 16:19:36 -0400
committermrb0nk500 <b0nk@b0nk.xyz>2023-03-06 16:19:36 -0400
commit06d75ece6452a33f11afd7e5ec3dd1f916c8583f (patch)
tree6a3b5d45eee8d64630a647d04a43638ebef91605
parent306a76cb444102bc207ee16e8a65aa9e90bbd37a (diff)
TProtocol: Match both `parse_packet()`, and `run_task()`
-rw-r--r--context.h55
-rw-r--r--include/pso/TProtocol.h28
-rw-r--r--include/pso/TSocket.h23
-rw-r--r--include/pso/TTcpSocket.h2
-rw-r--r--src/pso/TProtocol.cpp76
-rw-r--r--src/pso/TSocket.cpp13
-rw-r--r--src/pso/TTcpSocket.cpp4
7 files changed, 152 insertions, 49 deletions
diff --git a/context.h b/context.h
index 95824e4..497c12b 100644
--- a/context.h
+++ b/context.h
@@ -538,6 +538,10 @@ extern short tcp_receive(short nh, void (*notify)(short size, short sock_fd), sh
extern int get_link_status();
extern char *get_sock_status_name(short code);
+// pso/TSocket.h
+extern u16 to_be_uint16_t(u16 val);
+extern u16 to_le_uint16_t(u16 val);
+
// THeap.cpp
extern void heap_xfree(void *ptr);
extern void *heap_xmalloc(size_t size);
@@ -560,6 +564,9 @@ extern void func_803e11f0();
extern void func_803369b4();
+// pso/TProtocol.h
+extern void copy_packet(struct packet *pkt);
+
// pso/protocol.h
extern void bswap_16(u16 *val);
extern void bswap_32(u32 *val);
@@ -693,13 +700,23 @@ struct send_buffs {
// pso/TProtocol.h
struct packet {
- packet_header header;
- TArray<u8, 0x7c00-sizeof(packet_header)> data;
+ union {
+ struct {
+ packet_header header;
+ TArray<u8, 0x7c00-sizeof(packet_header)> data;
+ } packet;
+ u8 bytes[0x7c00];
+ };
template<typename T>
T &as() {
return reinterpret_cast<T>(*this);
};
+
+ template<typename T>
+ T *as_ptr() {
+ return reinterpret_cast<T *>(this);
+ };
};
struct GameListEntry {
@@ -1082,15 +1099,15 @@ public:
};
// pso/TSocket.h
-class TSocket : private TObject {
-private:
+class TSocket : public TObject {
+public:
ipv4_addr m_dst_addr;
u16 m_dst_port;
u16 m_src_port;
ipv4_addr m_src_addr;
s16 m_sock_fd;
- u8 m_sock_flags;
- bool m_buffer_cleared;
+ char m_is_invalid_packet;
+ char m_buffer_cleared;
s16 m_size;
s16 m_buffer_offset;
u32 m_unused;
@@ -1118,19 +1135,19 @@ public:
int is_empty();
void set_flags(u8 flags) {
- m_sock_flags |= flags;
+ m_is_invalid_packet |= flags;
};
void clear_flags(u8 flags) {
- m_sock_flags &= ~flags;
+ m_is_invalid_packet &= ~flags;
};
void toggle_flags(u8 flags) {
- m_sock_flags ^= flags;
+ m_is_invalid_packet ^= flags;
};
u8 get_flags(u8 flags) {
- return m_sock_flags & flags;
+ return m_is_invalid_packet & flags;
};
PRIVATE_MEMBER_ACCESSORS(ipv4_addr, dst_addr);
@@ -1138,8 +1155,8 @@ public:
PRIVATE_MEMBER_ACCESSORS(u16, src_port);
PRIVATE_MEMBER_ACCESSORS(ipv4_addr, src_addr);
PRIVATE_MEMBER_ACCESSORS(s16, sock_fd);
- PRIVATE_MEMBER_ACCESSORS(u8, sock_flags);
- PRIVATE_MEMBER_ACCESSORS(bool, buffer_cleared);
+ PRIVATE_MEMBER_ACCESSORS(char, is_invalid_packet);
+ PRIVATE_MEMBER_ACCESSORS(char, buffer_cleared);
PRIVATE_MEMBER_ACCESSORS(s16, size);
PRIVATE_MEMBER_ACCESSORS(s16, buffer_offset);
PRIVATE_MEMBER_ACCESSORS(u32, unused);
@@ -1154,7 +1171,7 @@ public:
// pso/TTcpSocket.h
class TTcpSocket : public TSocket {
-private:
+public:
PSOV3EncryptionTCP m_send_crypt;
PSOV3EncryptionTCP m_recv_crypt;
int m_is_encrypted;
@@ -1259,7 +1276,7 @@ private:
// pso/TProtocol.h
class TProtocol : public TTcpSocket {
-private:
+public:
TPlySmth m_smth;
TPlyGuildCardTag m_guildcard_tag;
u16 m_sub_version;
@@ -1267,7 +1284,7 @@ private:
int m_connected;
int m_joined_game;
int m_has_meet_user_settings;
- int m_buffer_ready;
+ int m_handle_pings_only;
int m_entry_count;
int m_unused;
int m_lobby_list_count;
@@ -1300,9 +1317,11 @@ public:
virtual ~TProtocol();
virtual void run_task();
- virtual int send(u8 *data, size_t size);
+ virtual short send(u8 *data, size_t size);
- int handle_command(packet *pkt);
+ void some_stub();
+ int handle_command(struct packet *pkt);
+ void parse_packet();
PRIVATE_MEMBER_ACCESSORS(TPlySmth, smth);
PRIVATE_MEMBER_ACCESSORS(TPlyGuildCardTag, guildcard_tag);
@@ -1311,7 +1330,7 @@ public:
PRIVATE_MEMBER_ACCESSORS(int, connected);
PRIVATE_MEMBER_ACCESSORS(int, joined_game);
PRIVATE_MEMBER_ACCESSORS(int, has_meet_user_settings);
- PRIVATE_MEMBER_ACCESSORS(int, buffer_ready);
+ PRIVATE_MEMBER_ACCESSORS(int, handle_pings_only);
PRIVATE_MEMBER_ACCESSORS(int, entry_count);
PRIVATE_MEMBER_ACCESSORS(int, unused);
PRIVATE_MEMBER_ACCESSORS(int, lobby_list_count);
diff --git a/include/pso/TProtocol.h b/include/pso/TProtocol.h
index ed80d04..6cd2a9e 100644
--- a/include/pso/TProtocol.h
+++ b/include/pso/TProtocol.h
@@ -18,17 +18,27 @@
#include <pso/TSocket.h>
#include <pso/TTcpSocket.h>
-
EXTERN_OBJECT_NAME(TProtocol);
+extern void copy_packet(struct packet *pkt);
struct packet {
- packet_header header;
- TArray<u8, 0x7c00-sizeof(packet_header)> data;
+ union {
+ struct {
+ packet_header header;
+ TArray<u8, 0x7c00-sizeof(packet_header)> data;
+ } packet;
+ u8 bytes[0x7c00];
+ };
template<typename T>
T &as() {
return reinterpret_cast<T>(*this);
};
+
+ template<typename T>
+ T *as_ptr() {
+ return reinterpret_cast<T *>(this);
+ };
};
struct GameListEntry {
@@ -51,7 +61,7 @@ struct QuestListEntry {
typedef void (*recv_packet_handler)(packet &pkt);
class TProtocol : public TTcpSocket {
-private:
+public:
TPlySmth m_smth;
TPlyGuildCardTag m_guildcard_tag;
u16 m_sub_version;
@@ -59,7 +69,7 @@ private:
int m_connected;
int m_joined_game;
int m_has_meet_user_settings;
- int m_buffer_ready;
+ int m_handle_pings_only;
int m_entry_count;
int m_unused;
int m_lobby_list_count;
@@ -92,9 +102,11 @@ public:
virtual ~TProtocol();
virtual void run_task();
- virtual int send(u8 *data, size_t size);
+ virtual short send(u8 *data, size_t size);
- int handle_command(packet *pkt);
+ void some_stub();
+ int handle_command(struct packet *pkt);
+ void parse_packet();
PRIVATE_MEMBER_ACCESSORS(TPlySmth, smth);
PRIVATE_MEMBER_ACCESSORS(TPlyGuildCardTag, guildcard_tag);
@@ -103,7 +115,7 @@ public:
PRIVATE_MEMBER_ACCESSORS(int, connected);
PRIVATE_MEMBER_ACCESSORS(int, joined_game);
PRIVATE_MEMBER_ACCESSORS(int, has_meet_user_settings);
- PRIVATE_MEMBER_ACCESSORS(int, buffer_ready);
+ PRIVATE_MEMBER_ACCESSORS(int, handle_pings_only);
PRIVATE_MEMBER_ACCESSORS(int, entry_count);
PRIVATE_MEMBER_ACCESSORS(int, unused);
PRIVATE_MEMBER_ACCESSORS(int, lobby_list_count);
diff --git a/include/pso/TSocket.h b/include/pso/TSocket.h
index c55dd08..6f79e13 100644
--- a/include/pso/TSocket.h
+++ b/include/pso/TSocket.h
@@ -13,15 +13,18 @@ union ipv4_addr {
TArray<u8, 4> addr_bytes;
};
-class TSocket : private TObject {
-private:
+extern u16 to_be_uint16_t(u16 val);
+extern u16 to_le_uint16_t(u16 val);
+
+class TSocket : public TObject {
+public:
ipv4_addr m_dst_addr;
u16 m_dst_port;
u16 m_src_port;
ipv4_addr m_src_addr;
s16 m_sock_fd;
- u8 m_sock_flags;
- bool m_buffer_cleared;
+ char m_is_invalid_packet;
+ char m_buffer_cleared;
s16 m_size;
s16 m_buffer_offset;
u32 m_unused;
@@ -49,19 +52,19 @@ public:
int is_empty();
void set_flags(u8 flags) {
- m_sock_flags |= flags;
+ m_is_invalid_packet |= flags;
};
void clear_flags(u8 flags) {
- m_sock_flags &= ~flags;
+ m_is_invalid_packet &= ~flags;
};
void toggle_flags(u8 flags) {
- m_sock_flags ^= flags;
+ m_is_invalid_packet ^= flags;
};
u8 get_flags(u8 flags) {
- return m_sock_flags & flags;
+ return m_is_invalid_packet & flags;
};
PRIVATE_MEMBER_ACCESSORS(ipv4_addr, dst_addr);
@@ -69,8 +72,8 @@ public:
PRIVATE_MEMBER_ACCESSORS(u16, src_port);
PRIVATE_MEMBER_ACCESSORS(ipv4_addr, src_addr);
PRIVATE_MEMBER_ACCESSORS(s16, sock_fd);
- PRIVATE_MEMBER_ACCESSORS(u8, sock_flags);
- PRIVATE_MEMBER_ACCESSORS(bool, buffer_cleared);
+ PRIVATE_MEMBER_ACCESSORS(char, is_invalid_packet);
+ PRIVATE_MEMBER_ACCESSORS(char, buffer_cleared);
PRIVATE_MEMBER_ACCESSORS(s16, size);
PRIVATE_MEMBER_ACCESSORS(s16, buffer_offset);
PRIVATE_MEMBER_ACCESSORS(u32, unused);
diff --git a/include/pso/TTcpSocket.h b/include/pso/TTcpSocket.h
index b2c8cfb..8e90558 100644
--- a/include/pso/TTcpSocket.h
+++ b/include/pso/TTcpSocket.h
@@ -14,7 +14,7 @@ EXTERN_OBJECT_NAME(TTcpSocket);
extern TTcpSocket *tcp_socket_table[16];
class TTcpSocket : public TSocket {
-private:
+public:
PSOV3EncryptionTCP m_send_crypt;
PSOV3EncryptionTCP m_recv_crypt;
int m_is_encrypted;
diff --git a/src/pso/TProtocol.cpp b/src/pso/TProtocol.cpp
index b0be8ee..d30df7d 100644
--- a/src/pso/TProtocol.cpp
+++ b/src/pso/TProtocol.cpp
@@ -14,18 +14,84 @@
OBJECT_NAME(TProtocol);
-void TProtocol::run_task() {
+packet *server_packet = nullptr;
+
+void copy_packet(struct packet *pkt) {
}
-int TProtocol::send(u8 *data, size_t size) {
- return TTcpSocket::send(data, size);
+int TProtocol::handle_command(struct packet *pkt) {
+
}
-int handle_command(packet *pkt) {
+void TProtocol::parse_packet() {
+ // This is needed to match, either that or cast the sizeof to an int.
+ const int max_packet_size = sizeof(struct packet);
+ while (!is_empty()) {
+ m_packet.bytes[m_packet_offset++] = next();
+ if (m_packet_offset == sizeof(packet_header)) {
+ if (m_is_encrypted) {
+ m_recv_crypt.encrypt(&m_packet.packet.header, sizeof(packet_header));
+ }
+ }
+ // NOTE: The `const int &` is required here to match.
+ // Convert packet size to native endian.
+ const int &packet_size = m_packet_size = to_be_uint16_t(m_packet.packet.header.size);
+ // Is the packet size invalid?
+ if (packet_size > max_packet_size || !packet_size) {
+ m_packet_size = 0;
+ m_packet_offset = 0;
+ m_is_invalid_packet = true;
+ break;
+ // Do we have the rest of the packet yet?
+ } else if (m_packet_size > 0 && m_packet_offset >= m_packet_size) {
+ // Decrypt it if necessary.
+ if (m_is_encrypted) {
+ m_recv_crypt.encrypt(&m_packet.packet.data, m_packet_size-sizeof(packet_header));
+ }
+ struct packet *pkt = &m_packet;
+ m_packet_size = 0;
+ m_packet_offset = 0;
+ if (m_handle_pings_only) {
+ if (pkt->packet.header.command == 0x1d) {
+ if (!handle_command(pkt)) {
+ continue;
+ } else {
+ break;
+ }
+ } else {
+ copy_packet(pkt);
+ }
+ } else if (handle_command(pkt)) {
+ break;
+ }
+ }
+ }
}
+short TProtocol::send(u8 *data, size_t size) {
+ return TTcpSocket::send(data, size);
+}
+
+void TProtocol::run_task() {
+ TTcpSocket::some_stub();
+ some_stub();
+ if (m_is_invalid_packet) {
+ close();
+ m_is_encrypted = 0;
+ m_connected = 0;
+ m_packet_offset = 0;
+ m_packet_size = 0;
+ } else if (!m_buffer_cleared) {
+ server_packet = &m_packet;
+ parse_packet();
+ recv();
+ }
+}
+
+void TProtocol::some_stub() {};
+
TProtocol::~TProtocol() {
}
@@ -56,7 +122,7 @@ TProtocol::TProtocol(TObject *parent, u16 sub_version, int language, char *seria
m_connected = 0;
m_joined_game = 0;
m_has_meet_user_settings = 0;
- m_buffer_ready = 0;
+ m_handle_pings_only = false;
m_entry_count = 0;
m_unused = 0;
m_lobby_list_count = 0;
diff --git a/src/pso/TSocket.cpp b/src/pso/TSocket.cpp
index 0a0166e..3c5576f 100644
--- a/src/pso/TSocket.cpp
+++ b/src/pso/TSocket.cpp
@@ -5,8 +5,6 @@
#include "pso/TObject.h"
#include "pso/TSocket.h"
-u16 bswap_word(u16 val);
-
int TSocket::is_empty() {
if (all_parents_unqueued_for_destruction()) {
return !m_size;
@@ -25,7 +23,7 @@ const u8 TSocket::next() {
}
void TSocket::set_port(u32 port) {
- m_dst_port = bswap_word(port);
+ m_dst_port = to_le_uint16_t(port);
}
void TSocket::set_ip_address(u32 addr) {
@@ -42,14 +40,19 @@ TSocket::TSocket(TObject *parent) : TObject(parent) {
m_dst_port = 0;
m_src_port = 0;
m_sock_fd = -1;
- m_sock_flags = 0;
+ m_is_invalid_packet = false;
m_size = 0;
m_buffer_offset = 0;
m_buffer_cleared = true;
m_callback = nullptr;
}
-u16 bswap_word(u16 val) {
+u16 to_be_uint16_t(u16 val) {
+ u8 *ptr = reinterpret_cast<u8 *>(&val);
+ return ptr[0] + (ptr[1] << 8);
+}
+
+u16 to_le_uint16_t(u16 val) {
u8 *ptr = reinterpret_cast<u8 *>(&val);
return ptr[1] + (ptr[0] << 8);
}
diff --git a/src/pso/TTcpSocket.cpp b/src/pso/TTcpSocket.cpp
index f105298..e923abb 100644
--- a/src/pso/TTcpSocket.cpp
+++ b/src/pso/TTcpSocket.cpp
@@ -99,7 +99,7 @@ int TTcpSocket::send(u8 *data, size_t size) {
m_send_crypt.encrypt(data, size);
}
- const s8 flags = sock_flags();
+ const s8 flags = is_invalid_packet();
if (flags || !get_link_status()) {
return -1;
} else {
@@ -138,7 +138,7 @@ int TTcpSocket::send(u8 *data, size_t size) {
short TTcpSocket::send(u8 *data) {
if (sock_fd() != -1) {
- const s8 flags = sock_flags();
+ const s8 flags = is_invalid_packet();
if (flags || !get_link_status()) {
return -1;
} else {