Merge Receive and Send base modules

Forum closed. All further discussion to be discussed at https://github.com/OpenKore/

Moderator: Moderators

Message
Author
EternalHarvest
Developers
Developers
Posts: 1798
Joined: 05 Dec 2008, 05:42
Noob?: Yes

Re: Merge Receive and Send base modules

#11 Post by EternalHarvest »

Well, it's not really good, but such a transition would allow to eliminate the need in almost all sendSomething functions (excluding compatibility reasons), as well as would be helpful for XKore and Poseidon.

User avatar
kLabMouse
Administrator
Administrator
Posts: 1301
Joined: 24 Apr 2008, 12:02

Re: Merge Receive and Send base modules

#12 Post by kLabMouse »

EternalHarvest wrote:Well, it's not really good, but such a transition would allow to eliminate the need in almost all sendSomething functions (excluding compatibility reasons), as well as would be helpful for XKore and Poseidon.
Yeah. The same system could be used to Construct and Reconstruct any packet, even depending on ServerType.

EternalHarvest
Developers
Developers
Posts: 1798
Joined: 05 Dec 2008, 05:42
Noob?: Yes

Re: Merge Receive and Send base modules

#13 Post by EternalHarvest »

Code: Select all

# This is an old method used back in the iRO beta 2 days when iRO had encrypted packets.
# At the moment (December 20 2006) there are no servers that still use encrypted packets.
Was that particular decrypt/encrypt stuff used for anything since then? Is it in actually working state now? (How to test it?)

User avatar
kLabMouse
Administrator
Administrator
Posts: 1301
Joined: 24 Apr 2008, 12:02

Re: Merge Receive and Send base modules

#14 Post by kLabMouse »

EternalHarvest wrote:

Code: Select all

# This is an old method used back in the iRO beta 2 days when iRO had encrypted packets.
# At the moment (December 20 2006) there are no servers that still use encrypted packets.
Was that particular decrypt/encrypt stuff used for anything since then? Is it in actually working state now? (How to test it?)
Well the old part. Not. I did not seen any trace of it anywhere.
They only thing was the Packet Prefix Encryption... but it was too simple one.
Anyway. Encrypt/Decrypt is needed, at least as hooks or some calls to embedded functions. so they could be used to defeat such protections as SHANDA PROTECT (cRO), Delphine, etc.

EternalHarvest
Developers
Developers
Posts: 1798
Joined: 05 Dec 2008, 05:42
Noob?: Yes

Re: Merge Receive and Send base modules

#15 Post by EternalHarvest »

Code: Select all

# $conState contains the connection state:
# 2.5 (set by parseMsg()): Just passed character selection; next 4 bytes will be
#      the account ID
Only set in gameguard_grant actually (because account ID messages are handled... differently now?). Now what's this, right in one of most important subs, parseIncomingMessage?

Code: Select all

	# The user is running in X-Kore mode and wants to switch character or gameGuard type 2 after 0259 tag 02.
	# We're now expecting an accountID, unless the server has replicated packet 0259 (server-side bug).
	if ($net->getState() == 2.5 && (!$config{gameGuard} || ($switch ne '0259' && $config{gameGuard} eq "2"))) {
		if (length($msg) >= 4) {
			$net->setState(Network::CONNECTED_TO_MASTER_SERVER);
			$accountID = substr($msg, 0, 4);
			debug "Selecting character, new accountID: ".unpack("V", $accountID)."\n", "connection";
			$net->clientSend($accountID);
			return substr($msg, 4);
		} else {
			return $msg;
		}
	}
Also return value is never used.

User avatar
kLabMouse
Administrator
Administrator
Posts: 1301
Joined: 24 Apr 2008, 12:02

Re: Merge Receive and Send base modules

#16 Post by kLabMouse »

EternalHarvest wrote:

Code: Select all

# $conState contains the connection state:
# 2.5 (set by parseMsg()): Just passed character selection; next 4 bytes will be
#      the account ID
Only set in gameguard_grant actually (because account ID messages are handled... differently now?). Now what's this, right in one of most important subs, parseIncomingMessage?

Code: Select all

	# The user is running in X-Kore mode and wants to switch character or gameGuard type 2 after 0259 tag 02.
	# We're now expecting an accountID, unless the server has replicated packet 0259 (server-side bug).
	if ($net->getState() == 2.5 && (!$config{gameGuard} || ($switch ne '0259' && $config{gameGuard} eq "2"))) {
		if (length($msg) >= 4) {
			$net->setState(Network::CONNECTED_TO_MASTER_SERVER);
			$accountID = substr($msg, 0, 4);
			debug "Selecting character, new accountID: ".unpack("V", $accountID)."\n", "connection";
			$net->clientSend($accountID);
			return substr($msg, 4);
		} else {
			return $msg;
		}
	}
Also return value is never used.
Yeah. Because it was Designed to Check whatever AccountID was received or not. But never completed.

EternalHarvest
Developers
Developers
Posts: 1798
Joined: 05 Dec 2008, 05:42
Noob?: Yes

Re: Merge Receive and Send base modules

#17 Post by EternalHarvest »

kLabMouse wrote:Anyway. Encrypt/Decrypt is needed, at least as hooks or some calls to embedded functions. so they could be used to defeat such protections as SHANDA PROTECT (cRO), Delphine, etc.
Less offtopic, please, as you know very well that delphine and other protections work via different methods.

Can we remove/disregard that old decrypt/encrypt?
kLabMouse wrote:Yeah. Because it was Designed to Check whatever AccountID was received or not. But never completed.
So, what to do with it? Looks like it would work only as mentioned server-side bug workaround anyway, as 2.5 isn't used for "wants to switch character".

I'm creating new method in MessageTokenizer which will read, parse and handle all the messages it can (merge of Base::RagnarokServer::onClientData and a part of mainLoop_initialized, including parseIncomingMessage and parseOutgoingClientMessage), so I need to understand what to do with all the weird stuff there.

User avatar
kLabMouse
Administrator
Administrator
Posts: 1301
Joined: 24 Apr 2008, 12:02

Re: Merge Receive and Send base modules

#18 Post by kLabMouse »

EternalHarvest wrote:
kLabMouse wrote:Anyway. Encrypt/Decrypt is needed, at least as hooks or some calls to embedded functions. so they could be used to defeat such protections as SHANDA PROTECT (cRO), Delphine, etc.
Less offtopic, please, as you know very well that delphine and other protections work via different methods.

Can we remove/disregard that old decrypt/encrypt?
kLabMouse wrote:Yeah. Because it was Designed to Check whatever AccountID was received or not. But never completed.
So, what to do with it? Looks like it would work only as mentioned server-side bug workaround anyway, as 2.5 isn't used for "wants to switch character".

I'm creating new method in MessageTokenizer which will read, parse and handle all the messages it can (merge of Base::RagnarokServer::onClientData and a part of mainLoop_initialized, including parseIncomingMessage and parseOutgoingClientMessage), so I need to understand what to do with all the weird stuff there.
Trow it out. Only left the ability to encrypt/decrypt packet itself. And may-be some place to filter out random receive of AccountID.

P.S. There is such a mess there... I failed last time when I tried to port some parts to AI 2008.

EternalHarvest
Developers
Developers
Posts: 1798
Joined: 05 Dec 2008, 05:42
Noob?: Yes

Re: Merge Receive and Send base modules

#19 Post by EternalHarvest »

Code: Select all

sub gameguard_grant {
	my ($self, $args) = @_;

	if ($args->{server} == 0) {
		error T("The server Denied the login because GameGuard packets where not replied " .
			"correctly or too many time has been spent to send the response.\n" .
			"Please verify the version of your poseidon server and try again\n"), "poseidon";
		return;
	} elsif ($args->{server} == 1) {
		message T("Server granted login request to account server\n"), "poseidon";
	} else {
		message T("Server granted login request to char/map server\n"), "poseidon";
		change_to_constate25 if ($config{'gameGuard'} eq "2");
	}
	$net->setState(1.3) if ($net->getState() == 1.2);
}
Kore requests for this packet when logging into account server, that's right. But how/when the second type (char/map server) is requested or received? I've tried it with XKore 2 using kore with "gameGuard 2" as a client, and after adding support for gameguard_grant in account server only it connects just fine.

Let's ignore that "replicated packet 0259 (server-side bug)" while network state is 2.5 for now.

EternalHarvest
Developers
Developers
Posts: 1798
Joined: 05 Dec 2008, 05:42
Noob?: Yes

Re: Merge Receive and Send base modules

#20 Post by EternalHarvest »

No more parseIncomingMessage:

Code: Select all

Index: src/functions.pl
===================================================================
--- src/functions.pl	(revision 7788)
+++ src/functions.pl	(working copy)
@@ -694,26 +694,8 @@
 	if (defined($data) && length($data) > 0) {
 		Benchmark::begin("parseMsg") if DEBUG;
 
-		my $type;
 		$incomingMessages->add($data);
-		while ($data = $incomingMessages->readNext(\$type)) {
-			if ($type == Network::MessageTokenizer::KNOWN_MESSAGE) {
-				parseIncomingMessage($data);
-			} else {
-				if ($type == Network::MessageTokenizer::UNKNOWN_MESSAGE) {
-					# Unknown message - ignore it
-					my $messageID = Network::MessageTokenizer::getMessageID($data);
-					if (!existsInList($config{debugPacket_exclude}, $messageID)) {
-						warning TF("Packet Tokenizer: Unknown switch: %s\n", $messageID), "connection";
-						visualDump($data, "<< Received unknown packet") if ($config{debugPacket_unparsed});
-					}
-				} elsif ($config{debugPacket_received}) {
-					debug "Received account ID\n", "parseMsg", 0 ;
-				}
-				# Pass it along to the client, whatever it is
-				$net->clientSend($data);
-			}
-		}
+		$net->clientSend($packetParser->processTokenizer($incomingMessages));
 		$net->clientFlush() if (UNIVERSAL::isa($net, 'Network::XKoreProxy'));
 		Benchmark::end("parseMsg") if DEBUG;
 	}
@@ -723,6 +705,7 @@
 	if (defined($data) && length($data) > 0) {
 		my $type;
 		$outgoingClientMessages->add($data);
+		# $net->serverSend($messageSender->processTokenizer($outgoingClientMessages, <callback object ?>));
 		while ($data = $outgoingClientMessages->readNext(\$type)) {
 			parseOutgoingClientMessage($data);
 		}
@@ -1004,7 +987,7 @@
 	}
 	my $switch = Network::MessageTokenizer::getMessageID($msg);
 	
-	parseMessage_pre('ro_sent', $switch, $msg, $sendMsg);
+	parseMessage_pre('Network::Send', $switch, $msg, $sendMsg);
 
 	my $serverType = $masterServer->{serverType};
 
@@ -1315,8 +1298,8 @@
 sub parseMessage_pre {
 	my ($mode, $switch, $msg, $realMsg) = @_;
 	my ($title, $config_suffix, $desc_key, $dumpMethod5_word, $hook) = @{{
-		'received' => ['<< Received packet:', 'received', 'Recv', 'recv', 'parseMsg/pre'],
-		'ro_sent' => ['<< Sent by RO client:', 'ro_sent', 'Send', 'send', 'RO_sendMsg_pre'],
+		'Network::Receive' => ['<< Received packet:', 'received', 'Recv', 'recv', 'parseMsg/pre'],
+		'Network::Send' => ['<< Sent by RO client:', 'ro_sent', 'Send', 'send', 'RO_sendMsg_pre'],
 	}->{$mode}};
 	
 	if ($config{'debugPacket_'.$config_suffix} && !existsInList($config{'debugPacket_exclude'}, $switch) ||
Index: src/Network/PacketParser.pm
===================================================================
--- src/Network/PacketParser.pm	(revision 7791)
+++ src/Network/PacketParser.pm	(working copy)
@@ -310,4 +310,69 @@
 	return $hook_args{return};
 }
 
+sub processTokenizer {
+	my ($self, $tokenizer) = @_;
+	
+	my $result = '';
+	my $type;
+	while (my $message = $tokenizer->readNext(\$type)) {
+		if ($type == Network::MessageTokenizer::KNOWN_MESSAGE) {
+			my $switch = Network::MessageTokenizer::getMessageID($message);
+			
+			main::parseMessage_pre($self->{hook_prefix}, $switch, $message, $message);
+			
+			my $willMangle = $self->willMangle($switch);
+			# If we're running in X-Kore mode, pass the message back to the RO client.
+			$result .= $message unless $willMangle;
+			
+			$self->{lastPacketTime} = time;
+			if (my $args = $self->parse($message)) {
+				# Use the new object-oriented packet parser
+				if ($config{debugPacket_received} == 3 &&
+						existsInList($config{'debugPacket_include'}, $switch)) {
+					my $switch = $args->{switch};
+					my $packet = $packetParser->{packet_list}{$switch};
+					my ($name, $packString, $varNames) = @{$packet};
+					
+					my @vars = ();
+					for my $varName (@{$varNames}) {
+						message "$varName = $args->{$varName}\n";
+					}
+				}
+				
+				if ($willMangle) {
+					my $ret = $self->mangle($args);
+					if (!$ret) {
+						# Packet was not mangled
+						$result .= $args->{RAW_MSG};
+					} elsif ($ret == 1) {
+						# Packet was mangled
+						$result .= $packetParser->reconstruct($args);
+					} else {
+						# Packet was suppressed
+					}
+				}
+			}
+			
+		} elsif ($type == Network::MessageTokenizer::ACCOUNT_ID) {
+			$result .= $message;
+			
+		} elsif ($type == Network::MessageTokenizer::UNKNOWN_MESSAGE) {
+			# Unknown message - ignore it
+			my $switch = Network::MessageTokenizer::getMessageID($message);
+			if (!existsInList($config{debugPacket_exclude}, $switch)) {
+				warning TF("Packet Tokenizer: Unknown switch: %s\n", $switch), "connection";
+				visualDump($message, "<< Received unknown packet") if ($config{debugPacket_unparsed});
+			}
+			# Pass it along to the client, whatever it is
+			$result .= $message;
+			
+		} else {
+			die "Packet Tokenizer: Unknown type: $type";
+		}
+	}
+	
+	return $result;
+}
+
 1;
Now, parse() and processTokenizer() need to be able to use object argument to look handlers in (currently it uses $self), and additional arguments to pass to handlers ($client in case of Base::RagnarokServer). Something like $PacketParser->parse($bytes, $object, $arg1, $arg2...). Also, maybe $args hashref for packet handlers should always be the first argument, so handlers would be called as $object->$handler($args, $arg1, $arg2...)? Currently, $client is positioned before $bytes in Base::RagnarokServer.

Object classes with handlers would include currently existing ServerType stuff (handlers should be moved away to separate module later but will work as is), {Base::Ragnarok,Network::XKore2}::{Account,Char,Map}Server, and new modules to replace parseOutgoingClientMessage and such.

Locked