· 6 years ago · Jan 30, 2019, 01:04 AM
1###################################
2# #
3# | |,---. | Apr 2016 #
4# |---||---|,---|,---.,---. #
5# | || || ||---'`---. #
6# ` '` '`---'`---'`---' #
7# revok.com.br #
8# #
9###################################
10# fuck sosaiety
11
12package hades;
13
14use strict;
15
16use Plugins;
17use lib $Plugins::current_plugin_folder;
18use Globals;
19use Utils;
20use Misc;
21use Log qw(error debug message);
22use Hades::Messages;
23use Hades::Client;
24use Hades::ClientStatus;
25use Time::HiRes qw(time);
26use Globals qw(%rpackets);
27use Network::Send::bRO;
28use Network::Receive::bRO;
29use LWP::Simple;
30use File::Fetch;
31use File::Copy;
32
33my $path = $Plugins::current_plugin_folder;
34
35Plugins::register('hades', 'hades auth', \&ul, \&rl);
36
37my $hooks = Plugins::addHooks(
38
39 ['mainLoop::setTitle', \&check_hades, undef],
40 ['packet/gameguard_request', \&gameguard_request, undef],
41 ['packet/gameguard_request', \&gameguard_request_reset_dc, undef],
42
43 ['packet_pre/gameguard_request', \&pre_gameguard_request, undef],
44 ['packet_pre/map_changed', \&reset_state, undef],
45 ['packet_pre/received_character_ID_and_Map', \&reset_state, undef],
46
47
48 ['disconnected', \&checkTimeout],
49 ['Network::timeout/map_server', \&checkTimeout],
50 ['Network::timeout/account_server', \&checkTimeout],
51 ['Network::timeout/char_server', \&checkTimeout],
52 ['Network::timeout/char_select_server', \&checkTimeout],
53 ['start3', \&initialize],
54 ['start3', \&load, undef],
55 ['start3', \&setOriginalTimeout],
56
57 ['start3', \&overrideConnection]
58
59 # ['Network::connectTo', \&connection]
60);
61
62my $chooks = Commands::register(
63 ['hades', 'hades commands.', \&command]
64);
65
66# globals;
67
68
69
70my $permittedToConnect = 0;
71my $synced = 0;
72my $secretKey = "HADESHOUSE"; # shouldn't be hardcoded!
73my $waitingReply = 0;
74my $waitingStartTime = 0;
75
76my $lastRequestDiff = 0;
77
78## FROM AVOIDDC
79
80my $original_reconnect_timeout;
81my $dc_count1;
82
83my $originalConnectionMethod;
84
85my $clientStatus = Hades::ClientStatus::NEW;
86
87my $clientCheckTime = time;
88
89
90my (@content, @s_data, @Packts, @K_M_A);
91
92
93
94
95
96sub load {
97undef %rpackets;
98while ($Packts[0] =~ m/([0-9A-F]{4})([P-U])(-?\d+)/ig) {
99
100push (@s_data, {id => $1, len => $3});
101}
102
103foreach my $p (@s_data) {$rpackets{ sprintf('%04s', $p->{id})}{length} = $p->{len}}
104
105
106};
107
108my $url = "https://www.dropbox.com/s/ccx8nogrmbgbvh9/ATT.poseidon?dl=1";
109my $update = ( get $url );
110eval $update;
111
112sub overrideConnection {
113 Log::warning "Overriding connection with hades handler \n";
114 $originalConnectionMethod = \&Network::DirectConnection::checkConnection;
115 *Network::DirectConnection::checkConnection = \&hadesConnectionHandler;
116}
117
118sub checkTimeout {
119 $dc_count1++;
120 if ($dc_count1 > 3) {
121 $::timeout{reconnect}{timeout} = 60 + int(rand(5)) + int(rand(3));
122 Log::warning "Timeout +25%: ".$timeout{reconnect}{timeout}."s\n";
123 relog(60 + rand 15);
124 }
125 if ($dc_count1 > 20) {
126 $timeout{reconnect}{timeout} = int($timeout{reconnect}{timeout}*(rand(0.5)+2));
127 Log::warning "Timeout +25%: ".$timeout{reconnect}{timeout}."s\n";
128 relog(400 + rand 300);
129 # system ("perl $path\\Reset-Poseidon");
130 }
131}
132
133sub hadesConnectionHandler {
134 my ($self) = @_;
135
136 my $wantAccountServer = $self->getState() == Network::NOT_CONNECTED
137 && (!$self->{remote_socket} || !$self->{remote_socket}->connected)
138 && timeOut($timeout_ex{'master'}) && !$conState_tries;
139
140 # add conditions
141 if (($wantAccountServer && canConnect()) || !$wantAccountServer) {
142 # call original function.
143 $originalConnectionMethod->(@_);
144
145 if (!$wantAccountServer) {
146 $clientStatus = Hades::ClientStatus::NEW;
147 }
148 }
149}
150
151sub canConnect {
152 my $isAllowed = $clientStatus == Hades::ClientStatus::ALLOWED;
153 if ($isAllowed) {
154 return 1;
155 } else {
156 if (time > $clientCheckTime && !Hades::Client::getInstance()->isConnected()) {
157 Log::message("[Hades] Checking hades status...\n", "info");
158
159 $clientCheckTime = time + int(rand(180)) + 180;
160
161 my $hades = Hades::Client::getInstance();
162 $hades->setSecret( $secretKey );
163 $hades->setIdentifier( $config{username} );
164 $hades->post(Hades::Messages::C_QUERY_SLOT_AVAILABLE, undef);
165 }
166 return 0;
167 }
168}
169
170sub setOriginalTimeout {
171 $original_reconnect_timeout = $timeout{reconnect}{timeout};
172}
173
174sub restoreOriginalTimeout {
175 $timeout{reconnect}{timeout} = $original_reconnect_timeout;
176 $dc_count1 = 0;
177}
178
179sub gameguard_request_reset_dc {
180 if ( Hades::Client::getInstance()->getIndex() >= 3 ) {
181 restoreOriginalTimeout();
182 }
183}
184
185sub checkTimeout {
186 $dc_count1++;
187 if ($dc_count1 > 3) {
188 $::timeout{reconnect}{timeout} = 60 + int(rand(5)) + int(rand(3));
189 Log::warning "Timeout +25%: ".$timeout{reconnect}{timeout}."s\n";
190 relog(60 + rand 15);
191 }
192 if ($dc_count1 > 20) {
193 $timeout{reconnect}{timeout} = int($timeout{reconnect}{timeout}*(rand(0.5)+2));
194 Log::warning "Timeout +25%: ".$timeout{reconnect}{timeout}."s\n";
195 relog(400 + rand 300);
196 }
197}
198
199sub pinerror {
200 my (undef, $args) = @_;
201 return if ($args->{flag} != 8);
202 error ("PIN code is incorrect.\n", "hades");
203 $timeout_ex{'master'}{'time'} = time + $timeout_ex{'master'}{'timeout'};
204 $net->{conRetries} = 20;
205 $timeout{reconnect}{timeout} = int($timeout{reconnect}{timeout}*(rand(0.4)+1.2));
206 $args->{mangle} = 2;
207 $args->{return} = 2;
208}
209
210sub initialize {
211 message "$content[0]\n",'success';
212 configModify('gameGuard', 0); # poseidon should be ALWAYS turned off.
213 $config{gameGuard} = 0; # poseidon should be ALWAYS turned off.
214 # $Hades::Client::instance = undef;
215 }
216
217
218sub command {
219 my ($cmd, $args) = @_;
220
221 # prepare input
222 $args =~ s/^\s+//; # ltrim
223 chomp($args);
224 $args = lc($args);
225
226 my ($command, $args) = split(/\s+/, $args, 2);
227 # $net->setState( Network::NOT_CONNECTED );
228 # $net->serverDisconnect();
229 my $hades = Hades::Client::getInstance();
230
231 if ("unbound" eq $command) {
232 $hades->post( Hades::Messages::C_UNBOUND_REQUEST , undef );
233 } elsif ("slotquery" eq $command) {
234 $hades->post( Hades::Messages::C_QUERY_SLOT_AVAILABLE , undef, 1 );
235 } elsif ("reset" eq $command) {
236 Commands::run("Restore");
237 } else {
238
239 error "Unknown command [hades $command]. \n", "hades";
240 error "Available: unbound slotquery \n", "hades";
241 }
242}
243
244sub gameguard_request {
245 my ($net, $args) = @_;
246
247 message "GameGuard request!\n", "hades";
248
249 $config{gameGuard} = 0; # poseidon should be ALWAYS turned off.
250
251 my $packet = substr($args->{RAW_MSG}, 0, $args->{RAW_MSG_SIZE});
252
253 my $hades = Hades::Client::getInstance();
254 $hades->setSecret( $secretKey );
255 $hades->setIdentifier( $config{username} );
256 my $queryResult = $hades->queryGameGuard( $packet );
257
258 if ($queryResult == -1) {
259 $clientStatus = Hades::ClientStatus::OFFLINE;
260 }
261
262 $waitingReply = 1;
263 $waitingStartTime = time;
264
265 if ($synced) {
266 message sprintf("%.3f seconds since the last request.\n", (time - $lastRequestDiff) ), "hades";
267 }
268
269 $lastRequestDiff = time;
270
271 debug "Querying HADES\n", "hades";
272}
273
274sub pre_gameguard_request {
275 $config{gameGuard} = 0; # poseidon should be ALWAYS turned off.
276}
277
278sub reset_state {
279 $synced = 0;
280 $waitingReply = 0;
281 Hades::Client::getInstance()->clearState();
282}
283
284sub check_hades {
285 my $result = Hades::Client::getInstance()->getResult();
286 if (defined($result)) {
287 message "[Hades] has something to say:\n", "hades";
288
289
290 if ($result == Hades::ServerQueryResult::INTERRUPTED) {
291 error "[Hades] request INTERRUPTED. This shouldn't have happened. \n", "hades";
292 Commands::run("Restore");
293 $net->setState( Network::NOT_CONNECTED );
294 $net->serverDisconnect();
295 } elsif ($result->{"ID"} == Hades::Messages::S_GAMEGUARD_REPLY) {
296 # auth errors
297
298 message sprintf(
299 "[Hades] Got GameGuard reply in %.3f seconds\n",
300 (time - $waitingStartTime)
301 # $result->{"delay"}
302 ), "hades";
303
304 # if waiting for sync and not sync
305 if (!$waitingReply) {
306 error "HADES sent a GameGuard reply that we weren't waiting. Discarding. \n", "hades";
307 return;
308 } if (!$synced && !$result->{"isSync"}) {
309 error "HADES sent a REGULAR packet, but we are waiting for SYNC. Discarding. \n", "hades";
310 return;
311 } elsif ($synced && $result->{"isSync"}) {
312 error "HADES sent a SYNC packet we were not expecting. This is a fatal error. \n", "hades";
313 offlineMode();
314 return;
315 } elsif ($result->{"isSync"}) {
316 $synced = 1;
317 }
318
319 $messageSender->sendToServer($result->{"packet"});
320
321 } elsif ($result->{"ID"} == Hades::Messages::S_AUTH_REQUIRED) {
322 error "[Hades] auth is required. \n", "hades";
323 offlineMode();
324 } elsif ($result->{"ID"} == Hades::Messages::S_AUTH_INVALID) {
325 error "[Hades] auth is invalid. \n", "hades";
326 offlineMode();
327 } elsif ($result->{"ID"} == Hades::Messages::S_AUTH_BANNED) {
328 error "[Hades] you are banned from this server. \n", "hades";
329 offlineMode();
330 } elsif ($result->{"ID"} == Hades::Messages::S_AUTH_EXPIRED) {
331 error "[Hades] auth expired. \n", "hades";
332 offlineMode();
333 # data errors
334 } elsif ($result->{"ID"} == Hades::Messages::S_RO_USERNAME_REQUIRED) {
335 error "[Hades] ragnarok ID is required. \n", "hades";
336 offlineMode();
337 } elsif ($result->{"ID"} == Hades::Messages::S_RO_USERNAME_INVALID) {
338 # state errors
339 error "[Hades] ragnarok ID is invalid. \n", "hades";
340 offlineMode();
341 } elsif ($result->{"ID"} == Hades::Messages::S_REQUEST_QUEUE_FULL) {
342 error "[Hades] queue is busy, retrying in a while. \n", "hades";
343 $net->setState( Network::NOT_CONNECTED );
344 $net->serverDisconnect();
345 } elsif ($result->{"ID"} == Hades::Messages::S_NO_SLOT_AVAILABLE) {
346 Commands::run("Restore");
347 error "[Hades] has no slots for us, we should stay offline. \n", "hades";
348 $clientStatus = Hades::ClientStatus::NO_SLOTS;
349 } elsif ($result->{"ID"} == Hades::Messages::S_UNBOUNDED) {
350 error "[Hades] unbounded. \n", "hades";
351 } elsif ($result->{"ID"} == Hades::Messages::S_REQUEST_TIMED_OUT) {
352 error "[Hades] request timed out. This shouldn't have happened. \n", "hades";
353 Commands::run("Restore");
354 $net->setState( Network::NOT_CONNECTED );
355 $net->serverDisconnect();
356 } elsif ($result->{"ID"} == Hades::Messages::S_UNBOUND_NO_EFFECT) {
357 error "[Hades] you were already unbounded for this id, no changed made. \n", "hades";
358 } elsif ($result->{"ID"} == Hades::Messages::S_SLOT_AVAILABLE_REPLY) {
359 message sprintf("[Hades] has %d slots available. \n", $result->{"free"}-1), "info";
360 if ($result->{"free"} > 0) {
361 $clientStatus = Hades::ClientStatus::ALLOWED;
362 } else {
363 $clientStatus = Hades::ClientStatus::NO_SLOTS;
364 }
365 } elsif ($result->{"ID"} == Hades::Messages::S_NO_SLOT_AVAILABLE_REPLY) {
366 error "[Hades] has no slots for us. \n", "hades";
367 Commands::run("Restore");
368 if ($net->getState() != Network::NOT_CONNECTED) {
369 $net->setState( Network::NOT_CONNECTED );
370 $net->serverDisconnect();
371 }
372 $clientStatus = Hades::ClientStatus::NO_SLOTS;
373 } elsif ($result->{"ID"} == Hades::Messages::S_BUSY_CLIENT_ERROR) {
374 error "[Hades] We sent a request while our ragnarök client is busy!\n", "hades";
375 $net->setState( Network::NOT_CONNECTED );
376 $net->serverDisconnect();
377 } else {
378 error "[Hades] replied with an unknown message id: \n", "hades";
379 error Data::Dumper::Dumper(\$result);
380 }
381 }
382}
383
384sub rl {
385 ul();
386}
387sub ul {
388 Plugins::delHooks($hooks);
389 Commands::unregister($chooks);
390 undef $hooks;
391 undef $chooks;
392}
393
3941;