Merge Receive and Send base modules
Moderator: Moderators
-
- Developers
- Posts: 1798
- Joined: 05 Dec 2008, 05:42
- Noob?: Yes
Re: Merge Receive and Send base modules
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.
Re: Merge Receive and Send base modules
Yeah. The same system could be used to Construct and Reconstruct any packet, even depending on ServerType.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.
-
- Developers
- Posts: 1798
- Joined: 05 Dec 2008, 05:42
- Noob?: Yes
Re: Merge Receive and Send base modules
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.
Re: Merge Receive and Send base modules
Well the old part. Not. I did not seen any trace of it anywhere.EternalHarvest wrote:Was that particular decrypt/encrypt stuff used for anything since then? Is it in actually working state now? (How to test it?)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.
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.
-
- Developers
- Posts: 1798
- Joined: 05 Dec 2008, 05:42
- Noob?: Yes
Re: Merge Receive and Send base modules
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
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;
}
}
Re: Merge Receive and Send base modules
Yeah. Because it was Designed to Check whatever AccountID was received or not. But never completed.EternalHarvest wrote: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
# $conState contains the connection state: # 2.5 (set by parseMsg()): Just passed character selection; next 4 bytes will be # the account ID
Also return value is never used.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; } }
-
- Developers
- Posts: 1798
- Joined: 05 Dec 2008, 05:42
- Noob?: Yes
Re: Merge Receive and Send base modules
Less offtopic, please, as you know very well that delphine and other protections work via different methods.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.
Can we remove/disregard that old decrypt/encrypt?
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".kLabMouse wrote:Yeah. Because it was Designed to Check whatever AccountID was received or not. But never completed.
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.
Re: Merge Receive and Send base modules
Trow it out. Only left the ability to encrypt/decrypt packet itself. And may-be some place to filter out random receive of AccountID.EternalHarvest wrote:Less offtopic, please, as you know very well that delphine and other protections work via different methods.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.
Can we remove/disregard that old decrypt/encrypt?
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".kLabMouse wrote:Yeah. Because it was Designed to Check whatever AccountID was received or not. But never completed.
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.
P.S. There is such a mess there... I failed last time when I tried to port some parts to AI 2008.
-
- Developers
- Posts: 1798
- Joined: 05 Dec 2008, 05:42
- Noob?: Yes
Re: Merge Receive and Send base modules
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);
}
Let's ignore that "replicated packet 0259 (server-side bug)" while network state is 2.5 for now.
-
- Developers
- Posts: 1798
- Joined: 05 Dec 2008, 05:42
- Noob?: Yes
Re: Merge Receive and Send base modules
No more parseIncomingMessage:
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.
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;
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.