From b5a7d5562248617d5d4d9467002c2fc00032bfe3 Mon Sep 17 00:00:00 2001
From: xboi209 <xboi209@users.noreply.github.com>
Date: Thu, 5 Jun 2014 12:16:53 -0700
Subject: [PATCH 1/5] Packet 0x17 support

---
 src/common/bnet_protocol.h | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/src/common/bnet_protocol.h b/src/common/bnet_protocol.h
index 8e275cb..464157a 100644
--- a/src/common/bnet_protocol.h
+++ b/src/common/bnet_protocol.h
@@ -3270,13 +3270,22 @@ namespace pvpgn
 
 	/******************************************************/
 	/* seen in SC107a */
-#define CLIENT_UNKNOWN_17 0x17ff
+#define CLIENT_READMEMORY 0x17ff
 	typedef struct
 	{
 		t_bnet_header h;
-		/* FIXME: what is in here... is there a cooresponding
-		   server packet? */
-	} PACKED_ATTR() t_client_unknown_17;
+		bn_int        request_id;
+		bn_byte		  memory;
+	} PACKED_ATTR() t_client_readmemory;
+
+#define SERVER_READMEMORY 0x17ff
+	typedef struct
+	{
+		t_bnet_header h;
+		bn_int        request_id;
+		bn_int        address;
+		bn_int        length;
+	} PACKED_ATTR() t_server_readmemory;
 	/******************************************************/
 
 

From f098dceb5f50897d20b693ee8f884b5f47014c87 Mon Sep 17 00:00:00 2001
From: xboi209 <xboi209@users.noreply.github.com>
Date: Thu, 5 Jun 2014 12:25:37 -0700
Subject: [PATCH 2/5] Update packet.cpp

---
 src/common/packet.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/common/packet.cpp b/src/common/packet.cpp
index 33fec35..a34631b 100644
--- a/src/common/packet.cpp
+++ b/src/common/packet.cpp
@@ -431,8 +431,8 @@ namespace pvpgn
 					return "CLIENT_ADCLICK";
 				case CLIENT_ADCLICK2:
 					return "CLIENT_ADCLICK2";
-				case CLIENT_UNKNOWN_17:
-					return "CLIENT_UNKNOWN_17";
+				case CLIENT_READMEMORY:
+					return "CLIENT_READMEMORY";
 				case CLIENT_UNKNOWN_24:
 					return "CLIENT_UNKNOWN_24";
 				case CLIENT_LADDERREQ:
@@ -684,6 +684,8 @@ namespace pvpgn
 					return "SERVER_ADREPLY";
 				case SERVER_ADCLICKREPLY2:
 					return "SERVER_ADCLICKREPLY2";
+				case SERVER_READMEMORY:
+					return "SERVER_READMEMORY";
 				case SERVER_LADDERREPLY:
 					return "SERVER_LADDERREPLY";
 				case SERVER_ECHOREQ:

From be43779622fa0c133f4d5e0161f18702c5bd116e Mon Sep 17 00:00:00 2001
From: xboi209 <xboi209@users.noreply.github.com>
Date: Thu, 5 Jun 2014 12:39:40 -0700
Subject: [PATCH 3/5] Update handle_bnet.cpp

---
 src/bnetd/handle_bnet.cpp | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/src/bnetd/handle_bnet.cpp b/src/bnetd/handle_bnet.cpp
index 1609416..78fdd30 100644
--- a/src/bnetd/handle_bnet.cpp
+++ b/src/bnetd/handle_bnet.cpp
@@ -136,6 +136,7 @@ namespace pvpgn
 		static int _client_adack(t_connection * c, t_packet const *const packet);
 		static int _client_adclick(t_connection * c, t_packet const *const packet);
 		static int _client_adclick2(t_connection * c, t_packet const *const packet);
+		static int _client_readmemory(t_connection * c, t_packet const *const packet);
 		static int _client_statsupdate(t_connection * c, t_packet const *const packet);
 		static int _client_playerinforeq(t_connection * c, t_packet const *const packet);
 		static int _client_progident2(t_connection * c, t_packet const *const packet);
@@ -236,6 +237,7 @@ namespace pvpgn
 			{ CLIENT_ADACK, _client_adack },
 			{ CLIENT_ADCLICK, _client_adclick },
 			{ CLIENT_ADCLICK2, _client_adclick2 },
+			{ CLIENT_READMEMORY, _client_readmemory },
 			{ CLIENT_STATSREQ, _client_statsreq },
 			{ CLIENT_STATSUPDATE, _client_statsupdate },
 			{ CLIENT_PLAYERINFOREQ, _client_playerinforeq },
@@ -3293,6 +3295,18 @@ namespace pvpgn
 
 			return 0;
 		}
+		
+		static int _client_readmemory(t_connection * c, t_packet const *const packet)
+		{
+			if (packet_get_size(packet) < sizeof(t_client_readmemory)) {
+				eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad READMEMORY packet (expected %lu bytes, got %u)", conn_get_socket(c), sizeof(t_client_readmemory), packet_get_size(packet));
+				return -1;
+			}
+			
+			eventlog(eventlog_level_debug, __FUNCTION__, "[%d] Received READMEMORY packet with Request ID: %d and Memory: %d", conn_get_socket(c), bn_int_get(packet->u.client_readmemory.request_id),  bn_int_get(packet->u.client_readmemory.memory));
+			
+			return 0;
+		}
 
 		static int _client_statsupdate(t_connection * c, t_packet const *const packet)
 		{

From 8f27283fb5eaf89569766aeb01f4ae7e84c381cd Mon Sep 17 00:00:00 2001
From: xboi209 <xboi209@users.noreply.github.com>
Date: Thu, 5 Jun 2014 12:41:49 -0700
Subject: [PATCH 4/5] Update packet.h

---
 src/common/packet.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/common/packet.h b/src/common/packet.h
index e3c21b3..f3741ae 100644
--- a/src/common/packet.h
+++ b/src/common/packet.h
@@ -147,6 +147,8 @@ namespace pvpgn
 			t_client_adclick            client_adclick;
 			t_client_adclick2           client_adclick2;
 			t_server_adclickreply2      server_adclickreply2;
+			t_client_readmemory	    client_readmemory;
+			t_server_readmemory	    server_readmemory;
 			t_client_game_report        client_gamerep;
 			t_server_sessionkey1        server_sessionkey1;
 			t_server_sessionkey2        server_sessionkey2;

From 9bd578c64d0abcf1c2b66d174bc2ab710262d610 Mon Sep 17 00:00:00 2001
From: HarpyWar <harpywar@gmail.com>
Date: Tue, 17 Jun 2014 11:35:06 +0400
Subject: [PATCH 5/5] add client_readmemory function, and make it available to
 call/handle from Lua

---
 lua/handle_client.lua      | 17 +++++++++++++++++
 src/bnetd/connection.cpp   | 37 +++++++++++++++++++++++++++++++++++++
 src/bnetd/connection.h     |  1 +
 src/bnetd/handle_bnet.cpp  | 24 +++++++++++++++++++++---
 src/bnetd/luafunctions.cpp | 33 +++++++++++++++++++++++++++++++++
 src/bnetd/luafunctions.h   |  2 ++
 src/bnetd/luainterface.cpp | 33 +++++++++++++++++++++++++++++++++
 src/bnetd/luainterface.h   |  5 ++++-
 src/common/bnet_protocol.h |  2 +-
 9 files changed, 149 insertions(+), 5 deletions(-)
 create mode 100644 lua/handle_client.lua

diff --git a/lua/handle_client.lua b/lua/handle_client.lua
new file mode 100644
index 0000000..71de225
--- /dev/null
+++ b/lua/handle_client.lua
@@ -0,0 +1,17 @@
+--[[
+	Copyright (C) 2014 HarpyWar (harpywar@gmail.com)
+	
+	This file is a part of the PvPGN Project http://pvpgn.pro
+	Licensed under the same terms as Lua itself.
+]]--
+
+
+function handle_client_readmemory(account, request_id, data)
+	
+	TRACE("Read memory request Id: " .. request_id)
+	
+	-- display memory bytes
+	DEBUG(data)
+
+end
+
diff --git a/src/bnetd/connection.cpp b/src/bnetd/connection.cpp
index 123caa0..a37462a 100644
--- a/src/bnetd/connection.cpp
+++ b/src/bnetd/connection.cpp
@@ -4193,6 +4193,43 @@ namespace pvpgn
 			return c->protocol.wol.anongame_player;
 		}
 
+
+
+		extern int conn_client_readmemory(t_connection * c, unsigned int request_id, unsigned int offset, unsigned int length)
+		{
+			t_packet    * rpacket;
+			t_clienttag clienttag;
+
+			if (!c)
+			{
+				eventlog(eventlog_level_error, __FUNCTION__, "got NULL conn");
+				return -1;
+			}
+			clienttag = conn_get_clienttag(c);
+
+			// disallow clients that doesn't support SID_READMEMORY
+			if (clienttag != CLIENTTAG_STARCRAFT_UINT && clienttag != CLIENTTAG_BROODWARS_UINT && clienttag != CLIENTTAG_STARJAPAN_UINT && clienttag != CLIENTTAG_SHAREWARE_UINT &&
+				clienttag != CLIENTTAG_DIABLORTL_UINT && clienttag != CLIENTTAG_DIABLOSHR_UINT && clienttag != CLIENTTAG_WARCIIBNE_UINT)
+			{
+				return -1;
+			}
+
+			if (!(rpacket = packet_create(packet_class_bnet)))
+				return -1;
+
+			packet_set_size(rpacket, sizeof(t_server_readmemory));
+			packet_set_type(rpacket, SERVER_READMEMORY);
+
+			bn_int_set(&rpacket->u.server_readmemory.request_id, request_id);
+			bn_int_set(&rpacket->u.server_readmemory.address, offset);
+			bn_int_set(&rpacket->u.server_readmemory.length, length);
+
+			conn_push_outqueue(c, rpacket);
+			packet_del_ref(rpacket);
+
+			return 0;
+		}
+
 	}
 
 }
diff --git a/src/bnetd/connection.h b/src/bnetd/connection.h
index 8b21c36..fecff19 100644
--- a/src/bnetd/connection.h
+++ b/src/bnetd/connection.h
@@ -465,6 +465,7 @@ namespace pvpgn
 		extern void conn_wol_set_anongame_player(t_connection * c, t_anongame_wol_player * anongame_player);
 		extern t_anongame_wol_player * conn_wol_get_anongame_player(t_connection * c);
 
+		extern int conn_client_readmemory(t_connection * c, unsigned int request_id, unsigned int offset, unsigned int length);
 	}
 
 }
diff --git a/src/bnetd/handle_bnet.cpp b/src/bnetd/handle_bnet.cpp
index 7dc8f21..bd6611e 100644
--- a/src/bnetd/handle_bnet.cpp
+++ b/src/bnetd/handle_bnet.cpp
@@ -45,6 +45,7 @@
 #include "common/proginfo.h"
 #include "common/util.h"
 #include "common/bnetsrp3.h"
+#include "common/xstring.h"
 
 #include "handlers.h"
 #include "connection.h"
@@ -3275,13 +3276,30 @@ namespace pvpgn
 		
 		static int _client_readmemory(t_connection * c, t_packet const *const packet)
 		{
+			char * memory;
+			unsigned int size, offset, request_id;
+
 			if (packet_get_size(packet) < sizeof(t_client_readmemory)) {
 				eventlog(eventlog_level_error, __FUNCTION__, "[%d] got bad READMEMORY packet (expected %lu bytes, got %u)", conn_get_socket(c), sizeof(t_client_readmemory), packet_get_size(packet));
 				return -1;
 			}
-			
-			eventlog(eventlog_level_debug, __FUNCTION__, "[%d] Received READMEMORY packet with Request ID: %d and Memory: %d", conn_get_socket(c), bn_int_get(packet->u.client_readmemory.request_id),  bn_int_get(packet->u.client_readmemory.memory));
-			
+ 
+			request_id = bn_int_get(packet->u.client_readmemory.request_id);
+
+			size = (unsigned int)packet_get_size(packet);
+			offset = sizeof(t_client_readmemory);
+
+			eventlog(eventlog_level_debug, __FUNCTION__, "[%d] Received READMEMORY packet with Request ID: %d and Memory size: %d", conn_get_socket(c), request_id, size - offset);
+
+#ifdef WITH_LUA
+			std::vector<int> _data;
+			for (int i = offset; i < size; i++)
+			{
+				_data.push_back(packet->u.data[i]);
+			}
+			lua_handle_client(c, request_id, _data, luaevent_client_readmemory);
+#endif
+
 			return 0;
 		}
 
diff --git a/src/bnetd/luafunctions.cpp b/src/bnetd/luafunctions.cpp
index 3d42927..1661cb2 100644
--- a/src/bnetd/luafunctions.cpp
+++ b/src/bnetd/luafunctions.cpp
@@ -707,6 +707,39 @@ namespace pvpgn
 			}
 			return 0;
 		}
+
+		/* Read memory of game client */
+		extern int __client_readmemory(lua_State* L)
+		{
+			const char * username;
+			unsigned int request_id, offset, length;
+			int messagebox_type;
+			try
+			{
+				lua::stack st(L);
+				// get args
+				st.at(1, username);
+				st.at(2, request_id);
+				st.at(3, offset);
+				st.at(4, length);
+
+				if (t_account * account = accountlist_find_account(username))
+				{
+					if (t_connection * c = account_get_conn(account))
+						conn_client_readmemory(c, request_id, offset, length);
+				}
+			}
+			catch (const std::exception& e)
+			{
+				eventlog(eventlog_level_error, __FUNCTION__, e.what());
+			}
+			catch (...)
+			{
+				eventlog(eventlog_level_error, __FUNCTION__, "lua exception\n");
+			}
+			return 0;
+		}
+
 	}
 }
 #endif
\ No newline at end of file
diff --git a/src/bnetd/luafunctions.h b/src/bnetd/luafunctions.h
index dfcb163..2532c6b 100644
--- a/src/bnetd/luafunctions.h
+++ b/src/bnetd/luafunctions.h
@@ -51,6 +51,8 @@ namespace pvpgn
 		extern int __server_get_games(lua_State* L);
 		extern int __server_get_channels(lua_State* L);
 
+		extern int __client_readmemory(lua_State* L);
+
 		extern int __command_get_group(lua_State* L);
 		extern int __icon_get_rank(lua_State* L);
 		extern int __describe_command(lua_State* L);
diff --git a/src/bnetd/luainterface.cpp b/src/bnetd/luainterface.cpp
index 9f574fc..a0c2ad4 100644
--- a/src/bnetd/luainterface.cpp
+++ b/src/bnetd/luainterface.cpp
@@ -139,6 +139,8 @@ namespace pvpgn
 				{ "server_get_games", __server_get_games },
 				{ "server_get_channels", __server_get_channels },
 
+				{ "client_readmemory", __client_readmemory },
+
 				{ "command_get_group", __command_get_group },
 				{ "icon_get_rank", __icon_get_rank },
 				{ "describe_command", __describe_command },
@@ -509,6 +511,37 @@ namespace pvpgn
 				eventlog(eventlog_level_error, __FUNCTION__, "lua exception\n");
 			}
 		}
+
+		extern void lua_handle_client(t_connection * c, int request_id, std::vector<int> data, t_luaevent_type luaevent)
+		{
+			t_account * account;
+			const char * func_name;
+			switch (luaevent)
+			{
+			case luaevent_client_readmemory:
+				func_name = "handle_client_readmemory";
+				break;
+			default:
+				return;
+			}
+			try
+			{
+				if (!(account = conn_get_account(c)))
+					return;
+
+				std::map<std::string, std::string> o_account = get_account_object(account);
+
+				lua::transaction(vm) << lua::lookup(func_name) << o_account << request_id << data << lua::invoke << lua::end; // invoke lua function
+			}
+			catch (const std::exception& e)
+			{
+				eventlog(eventlog_level_error, __FUNCTION__, e.what());
+			}
+			catch (...)
+			{
+				eventlog(eventlog_level_error, __FUNCTION__, "lua exception\n");
+			}
+		}
 #endif
 
 
diff --git a/src/bnetd/luainterface.h b/src/bnetd/luainterface.h
index cbb6d50..250e573 100644
--- a/src/bnetd/luainterface.h
+++ b/src/bnetd/luainterface.h
@@ -54,7 +54,9 @@ namespace pvpgn
 			luaevent_user_disconnect,
 
 			luaevent_server_start,
-			luaevent_server_mainloop
+			luaevent_server_mainloop,
+
+			luaevent_client_readmemory
 
 		} t_luaevent_type;
 
@@ -67,6 +69,7 @@ namespace pvpgn
 		extern int lua_handle_channel(t_channel * channel, t_connection * c, char const * message_text, t_message_type message_type, t_luaevent_type luaevent);
 		extern int lua_handle_user(t_connection * c, t_connection * c_dst, char const * message_text, t_luaevent_type luaevent);
 		extern void lua_handle_server(t_luaevent_type luaevent);
+		extern void lua_handle_client(t_connection * c, int request_id, std::vector<int> data, t_luaevent_type luaevent);
 
 	}
 
diff --git a/src/common/bnet_protocol.h b/src/common/bnet_protocol.h
index 464157a..af0185a 100644
--- a/src/common/bnet_protocol.h
+++ b/src/common/bnet_protocol.h
@@ -3275,7 +3275,7 @@ namespace pvpgn
 	{
 		t_bnet_header h;
 		bn_int        request_id;
-		bn_byte		  memory;
+		/* Memory */
 	} PACKED_ATTR() t_client_readmemory;
 
 #define SERVER_READMEMORY 0x17ff