Pol  Revision:f37d500
clientthread.cpp
Go to the documentation of this file.
1 #include "clientthread.h"
2 
3 #include <errno.h>
4 #include <exception>
5 #include <stddef.h>
6 #include <string>
7 
8 #include "../../bscript/bobject.h"
9 #include "../../clib/esignal.h"
10 #include "../../clib/fdump.h"
11 #include "../../clib/logfacility.h"
12 #include "../../clib/passert.h"
13 #include "../../clib/spinlock.h"
14 #include "../../clib/stlutil.h"
15 #include "../../plib/systemstate.h"
16 #include "../accounts/account.h"
17 #include "../core.h"
18 #include "../crypt/cryptbase.h"
19 #include "../mobile/charactr.h"
20 #include "../pktboth.h"
21 #include "../pktbothid.h"
22 #include "../pktdef.h"
23 #include "../pktinid.h"
24 #include "../polcfg.h"
25 #include "../polclock.h"
26 #include "../polsem.h"
27 #include "../schedule.h"
28 #include "../scrdef.h"
29 #include "../scrsched.h"
30 #include "../sockets.h"
31 #include "../uoscrobj.h"
32 #include "../uworld.h"
33 #include "cgdata.h" // This might not be needed if the client has a clear_gd() method
34 #include "client.h"
35 #include "msgfiltr.h" // Client could also have a method client->is_msg_allowed(), for example. Then this is not needed here.
36 #include "msghandl.h"
37 #include "packethelper.h"
38 #include "packets.h"
39 #include <format/format.h>
40 
41 #define CLIENT_CHECKPOINT( x ) client->checkpoint = x
42 
43 #ifdef _MSC_VER
44 #pragma warning( disable : 4127 ) // conditional expression is constant, because of FD_SET
45 #endif
46 
47 namespace Pol
48 {
49 namespace Core
50 {
51 // This function below is defined (for now) in pol.cpp. That's ugly.
52 void call_chr_scripts( Mobile::Character* chr, const std::string& root_script_ecl,
53  const std::string& pkg_script_ecl, bool offline = false );
54 
55 
56 void report_weird_packet( Network::Client* client, const std::string& why ); // Defined below
57 
58 bool client_io_thread( Network::Client* client, bool login )
59 {
60  fd_set c_recv_fd;
61  fd_set c_err_fd;
62  fd_set c_send_fd;
63  struct timeval c_select_timeout = {0, 0};
64  int checkpoint = 0;
65  int nidle = 0;
66  client->last_packet_at = polclock();
67  if ( !login )
68  {
69  if ( Plib::systemstate.config.loglevel >= 11 )
70  {
71  POLLOG.Format( "Network::Client#{} i/o thread starting\n" ) << client->instance_;
72  }
73  }
74  client->checkpoint = 60; // CNXBUG
75  {
76  PolLock lck;
77  client->checkpoint = 61; // CNXBUG
78  client->last_activity_at = polclock();
79  }
80  if ( !login )
81  {
82  if ( Plib::systemstate.config.loglevel >= 11 )
83  {
84  POLLOG.Format( "Client#{} i/o thread past initial lock\n" ) << client->instance_;
85  }
86  }
87  CLIENT_CHECKPOINT( 0 );
88  try
89  {
90  while ( !Clib::exit_signalled && client->isReallyConnected() )
91  {
92  CLIENT_CHECKPOINT( 1 );
93  int nfds = 0;
94  FD_ZERO( &c_recv_fd );
95  FD_ZERO( &c_err_fd );
96  FD_ZERO( &c_send_fd );
97  checkpoint = 1;
98 
99  SOCKET clientSocket = client->csocket;
100  if ( clientSocket == INVALID_SOCKET )
101  break;
102 
103  // Non-Winsock implementations require nfds to be the largest socket value + 1
104 #ifndef _WIN32
105  passert_r(
106  clientSocket < FD_SETSIZE,
107  "Select() implementation in Linux cant handle this many sockets at the same time." )
108  nfds = clientSocket + 1;
109 #endif
110 
111  FD_SET( clientSocket, &c_recv_fd );
112  FD_SET( clientSocket, &c_err_fd );
113  if ( client->have_queued_data() )
114  FD_SET( clientSocket, &c_send_fd );
115  checkpoint = 2;
116 
117  int res;
118  do
119  {
120  if ( login )
121  {
122  c_select_timeout.tv_sec = 0;
123  c_select_timeout.tv_usec = Plib::systemstate.config.select_timeout_usecs;
124  }
125  else
126  {
127  c_select_timeout.tv_sec = 2;
128  c_select_timeout.tv_usec = 0;
129  }
130  CLIENT_CHECKPOINT( 2 );
131  res = select( nfds, &c_recv_fd, &c_send_fd, &c_err_fd, &c_select_timeout );
132  CLIENT_CHECKPOINT( 3 );
133  } while ( res < 0 && !Clib::exit_signalled && socket_errno == SOCKET_ERRNO( EINTR ) );
134  checkpoint = 3;
135 
136  if ( res < 0 )
137  {
138  int sckerr = socket_errno;
139  POLLOG.Format( "Client#{}: select res={}, sckerr={}\n" )
140  << client->instance_ << res << sckerr;
141  break;
142  }
143  else if ( res == 0 )
144  {
145  if ( ( !client->chr ||
147  Plib::systemstate.config.inactivity_warning_timeout &&
149  {
150  ++nidle;
151  if ( nidle == 30 * Plib::systemstate.config.inactivity_warning_timeout )
152  {
153  CLIENT_CHECKPOINT( 4 );
154  PolLock lck; // multithread
156  msg->Write<u8>( PKTOUT_53_WARN_CHARACTER_IDLE );
157  CLIENT_CHECKPOINT( 5 );
158  msg.Send( client );
159  CLIENT_CHECKPOINT( 18 );
160  if ( client->pause_count )
161  client->restart();
162  }
163  else if ( nidle == 30 * Plib::systemstate.config.inactivity_disconnect_timeout )
164  {
165  client->forceDisconnect();
166  }
167  }
168  }
169 
170  CLIENT_CHECKPOINT( 19 );
171  if ( !client->isReallyConnected() )
172  break;
173 
174  if ( FD_ISSET( clientSocket, &c_err_fd ) )
175  {
176  client->forceDisconnect();
177  break;
178  }
179 
180  // region Speedhack
181  if ( !client->movementqueue.empty() ) // not empty then process the first packet
182  {
183  PolLock lck; // multithread
184  Network::PacketThrottler pkt = client->movementqueue.front();
185  if ( client->SpeedHackPrevention( false ) )
186  {
187  if ( client->isReallyConnected() )
188  {
189  unsigned char msgtype = pkt.pktbuffer[0];
190  Network::MSG_HANDLER packetHandler =
191  Network::PacketRegistry::find_handler( msgtype, client );
192  try
193  {
194  INFO_PRINT_TRACE( 10 ) << "Client#" << client->instance_ << ": message 0x"
195  << fmt::hexu( msgtype ) << "\n";
196  CLIENT_CHECKPOINT( 26 );
197  packetHandler.func( client, pkt.pktbuffer );
198  CLIENT_CHECKPOINT( 27 );
200  }
201  catch ( std::exception& ex )
202  {
203  POLLOG_ERROR.Format( "Client#{}: Exception in message handler 0x{:X}: {}\n" )
204  << client->instance_ << (int)msgtype << ex.what();
205  fmt::Writer tmp;
206  Clib::fdump( tmp, pkt.pktbuffer, 7 );
207  POLLOG << tmp.str() << "\n";
209  throw;
210  }
211  }
212  client->movementqueue.pop();
213  }
214  }
215  // endregion Speedhack
216 
217 
218  if ( FD_ISSET( clientSocket, &c_recv_fd ) )
219  {
220  checkpoint = 4;
221  CLIENT_CHECKPOINT( 6 );
222  if ( process_data( client ) )
223  {
224  CLIENT_CHECKPOINT( 17 );
225  PolLock lck;
226 
227  // reset packet timer
228  client->last_packet_at = polclock();
229  if ( !check_inactivity( client ) )
230  {
231  nidle = 0;
232  client->last_activity_at = polclock();
233  }
234 
235  checkpoint = 5;
236  CLIENT_CHECKPOINT( 7 );
237  send_pulse();
238  if ( TaskScheduler::is_dirty() )
240  }
241  }
242  checkpoint = 6;
243 
244  polclock_t polclock_now = polclock();
245  if ( ( polclock_now - client->last_packet_at ) >= 120000 ) // 2 mins
246  {
247  client->forceDisconnect();
248  break;
249  }
250 
251  if ( client->have_queued_data() && FD_ISSET( clientSocket, &c_send_fd ) )
252  {
253  PolLock lck;
254  CLIENT_CHECKPOINT( 8 );
255  client->send_queued_data();
256  }
257  checkpoint = 7;
258  CLIENT_CHECKPOINT( 21 );
259  if ( login )
260  break;
261  }
262  }
263  catch ( std::string& str )
264  {
265  POLLOG_ERROR.Format( "Client#{}: Exception in i/o thread: {}! (checkpoint={})\n" )
266  << client->instance_ << str << checkpoint;
267  }
268  catch ( const char* msg )
269  {
270  POLLOG_ERROR.Format( "Client#{}: Exception in i/o thread: {}! (checkpoint={})\n" )
271  << client->instance_ << msg << checkpoint;
272  }
273  catch ( std::exception& ex )
274  {
275  POLLOG_ERROR.Format( "Client#{}: Exception in i/o thread: {}! (checkpoint={})\n" )
276  << client->instance_ << ex.what() << checkpoint;
277  }
278  CLIENT_CHECKPOINT( 20 );
279 
280  if ( login && client->isConnected() )
281  return true;
282  POLLOG.Format( "Client#{} ({}): disconnected (account {})\n" )
283  << client->instance_ << Network::AddressToString( &client->ipaddr )
284  << ( ( client->acct != NULL ) ? client->acct->name() : "unknown" );
285 
286 
287  try
288  {
289  // if (1)
290  {
291  CLIENT_CHECKPOINT( 9 );
292  PolLock lck;
293  client->unregister();
294  INFO_PRINT << "Client disconnected from " << Network::AddressToString( &client->ipaddr )
295  << " (" << networkManager.clients.size() << " connections)\n";
296 
297  CoreSetSysTrayToolTip( Clib::tostring( networkManager.clients.size() ) + " clients connected",
299  }
300 
301  checkpoint = 8;
302  CLIENT_CHECKPOINT( 10 );
303  if ( client->chr )
304  {
305  // if (1)
306  int seconds_wait = 0;
307  {
308  CLIENT_CHECKPOINT( 11 );
309  PolLock lck;
310 
311  if ( client->chr )
312  {
313  client->chr->disconnect_cleanup();
314  client->gd->clear();
315  client->chr->connected( false );
316  ScriptDef sd;
317  sd.quickconfig( "scripts/misc/logofftest.ecl" );
318  if ( sd.exists() )
319  {
320  CLIENT_CHECKPOINT( 12 );
321  Bscript::BObject bobj(
323  if ( bobj.isa( Bscript::BObjectImp::OTLong ) )
324  {
325  const Bscript::BLong* blong = static_cast<const Bscript::BLong*>( bobj.impptr() );
326  seconds_wait = blong->value();
327  }
328  }
329  }
330  }
331 
332  polclock_t when_logoff = client->last_activity_at + seconds_wait * POLCLOCKS_PER_SEC;
333 
334  checkpoint = 9;
335  CLIENT_CHECKPOINT( 13 );
336  while ( !Clib::exit_signalled )
337  {
338  CLIENT_CHECKPOINT( 14 );
339  {
340  PolLock lck;
341  if ( polclock() >= when_logoff )
342  break;
343  }
344  pol_sleep_ms( 2000 );
345  }
346 
347  checkpoint = 10;
348  CLIENT_CHECKPOINT( 15 );
349  // if (1)
350  {
351  PolLock lck;
352  if ( client->chr )
353  {
354  Mobile::Character* chr = client->chr;
355  CLIENT_CHECKPOINT( 16 );
356  call_chr_scripts( chr, "scripts/misc/logoff.ecl", "logoff.ecl" );
357  if ( chr->realm ) {
358  chr->realm->notify_left( *chr );
359  }
360  }
361  }
362  }
363  }
364  catch ( std::exception& ex )
365  {
366  POLLOG.Format( "Client#{}: Exception in i/o thread: {}! (checkpoint={}, what={})\n" )
367  << client->instance_ << checkpoint << ex.what();
368  }
369 
370  // queue delete of client ptr see method doc for reason
371  Core::networkManager.clientTransmit->QueueDelete( client );
372  return false;
373 }
374 
375 bool valid_message_length( Network::Client* client, unsigned int length )
376 {
377  if ( length > sizeof client->buffer )
378  {
379  handle_humongous_packet( client, client->message_length );
380  return false;
381  }
382  if ( length < 3 )
383  {
384  report_weird_packet( client, "Too-short message" );
385  return false;
386  }
387  return true;
388 }
389 
390 // bool - return true when a message was processed.
392 {
393  // NOTE: This is coded such that for normal messages, which are completely available,
394  // this function will get the type, then the length, then the data, without having
395  // to wait for a second or third call.
396  // Also, the abnormal state, RECV_STATE_CRYPTSEED_WAIT, is handled at the end, so in
397  // normal processing its code doesn't see the code path.
398  passert( client->bufcheck1_AA == 0xAA );
399  passert( client->bufcheck2_55 == 0x55 );
401  {
402  client->bytes_received = 0;
403  client->recv_remaining( 1 );
404  CLIENT_CHECKPOINT( 22 );
405  if ( client->bytes_received < 1 ) // this really should never happen.
406  {
407  client->forceDisconnect();
408  return false;
409  }
410 
411  unsigned char msgtype = client->buffer[0];
412  client->last_msgtype = msgtype; // CNXBUG
413  if ( Plib::systemstate.config.verbose )
414  INFO_PRINT.Format( "Incoming msg type: 0x{:X}\n" ) << (int)msgtype;
415 
416  if ( !Network::PacketRegistry::is_defined( msgtype ) )
417  {
418  handle_undefined_packet( client );
419  return false; // remain in RECV_STATE_MSGTYPE_WAIT
420  }
421 
422  Network::MSG_HANDLER packetHandler = Network::PacketRegistry::find_handler( msgtype, client );
423  if ( packetHandler.msglen == MSGLEN_2BYTELEN_DATA )
424  {
426  }
427  else
428  {
429  passert( packetHandler.msglen > 0 );
430 
432  client->message_length = packetHandler.msglen;
433  }
434 
435  } /* endif of RECV_STATE_MSGTYPE_WAIT */
436 
438  {
439  client->recv_remaining( 3 );
440  CLIENT_CHECKPOINT( 23 );
441  if ( client->bytes_received == 3 ) // the length bytes were available.
442  {
443  // MSG is [MSGTYPE] [LENHI] [LENLO] [DATA ... ]
444  client->message_length = ( client->buffer[1] << 8 ) + client->buffer[2];
445 
446  if ( !valid_message_length( client, client->message_length ) )
447  {
448  // If the reported length is too short (less than 3 bytes) or
449  // too big (larger than the client buffer), something very odd
450  // happened.
451  client->forceDisconnect();
452  return false;
453  }
455  }
456  // else keep waiting.
457  } /* endif of RECV_STATE_MSGLEN_WAIT */
458 
460  {
461  CLIENT_CHECKPOINT( 24 );
462  client->recv_remaining( client->message_length );
463  CLIENT_CHECKPOINT( 25 );
464  if ( client->bytes_received == client->message_length ) // we have the whole message
465  {
466  unsigned char msgtype = client->buffer[0];
468  networkManager.iostats.received[msgtype].bytes += client->message_length;
469  {
470  Clib::SpinLockGuard guard( client->_fpLog_lock );
471  if ( !client->fpLog.empty() )
472  {
473  fmt::Writer tmp;
474  tmp << "Client -> Server: 0x" << fmt::hexu( msgtype ) << ", " << client->message_length
475  << " bytes\n";
476  Clib::fdump( tmp, &client->buffer, client->message_length );
477  FLEXLOG( client->fpLog ) << tmp.str() << "\n";
478  }
479  }
480 
481  if ( Plib::systemstate.config.verbose )
482  INFO_PRINT.Format( "Message Received: Type 0x{:X}, Length {} bytes\n" )
483  << (int)msgtype << client->message_length;
484 
485  PolLock lck; // multithread
486  // it can happen that a client gets disconnected while waiting for the lock.
487  if ( client->isConnected() )
488  {
489  if ( client->msgtype_filter->msgtype_allowed[msgtype] )
490  {
491  // region Speedhack
492  if ( ( settingsManager.ssopt.speedhack_prevention ) && ( msgtype == PKTIN_02_ID ) )
493  {
494  if ( !client->SpeedHackPrevention() )
495  {
496  // client->SpeedHackPrevention() added packet to queue
498  CLIENT_CHECKPOINT( 28 );
499  return true;
500  }
501  }
502  // endregion Speedhack
503 
504 
505  Network::MSG_HANDLER packetHandler =
506  Network::PacketRegistry::find_handler( msgtype, client );
507  passert( packetHandler.msglen != 0 );
508 
509  try
510  {
511  INFO_PRINT_TRACE( 10 )
512  << "Client#" << client->instance_ << ": message 0x" << fmt::hexu( msgtype ) << "\n";
513  CLIENT_CHECKPOINT( 26 );
514  packetHandler.func( client, client->buffer );
515  CLIENT_CHECKPOINT( 27 );
517  }
518  catch ( std::exception& ex )
519  {
520  POLLOG_ERROR.Format( "Client#{}: Exception in message handler 0x{:X}: {}\n" )
521  << client->instance_ << (int)msgtype << ex.what();
522  fmt::Writer tmp;
523  Clib::fdump( tmp, client->buffer, client->bytes_received );
524  POLLOG << tmp.str() << "\n";
526  throw;
527  }
528  }
529  else
530  {
531  POLLOG_ERROR.Format( "Client#{} ({}, Acct {}) sent non-allowed message type 0x{:X}.\n" )
532  << client->instance_ << Network::AddressToString( &client->ipaddr )
533  << ( client->acct ? client->acct->name() : "unknown" ) << (int)msgtype;
534  }
535  }
537  CLIENT_CHECKPOINT( 28 );
538  return true;
539  }
540  // else keep waiting
541  } /* endif RECV_STATE_MSGDATA_WAIT */
543  { // The abnormal case.
544  // The first four bytes after connection are the
545  // crypto seed
546  client->recv_remaining_nocrypt( 4 );
547 
548  if ( client->bytes_received == 4 )
549  {
550  /* The first four bytes transmitted are the encryption seed */
551  unsigned char cstype = client->buffer[0];
552 
553  if ( ( client->buffer[0] == 0xff ) && ( client->buffer[1] == 0xff ) &&
554  ( client->buffer[2] == 0xff ) && ( client->buffer[3] == 0xff ) )
555  {
556  if ( Plib::systemstate.config.verbose )
557  {
558  INFO_PRINT.Format( "UOKR Seed Message Received: Type 0x{:X}\n" ) << (int)cstype;
559  }
561  msg->WriteFlipped<u16>( 77u );
562  msg->WriteFlipped<u32>( 0x03u );
563  msg->Write<u8>( 0x02u );
564  msg->Write<u8>( 0x01u );
565  msg->Write<u8>( 0x03u );
566  msg->WriteFlipped<u32>( 0x13u );
567  msg->Write<u8>( 0x02u );
568  msg->Write<u8>( 0x11u );
569  msg->Write<u8>( 0x00u );
570  msg->Write<u8>( 0xfcu );
571  msg->Write<u8>( 0x2fu );
572  msg->Write<u8>( 0xe3u );
573  msg->Write<u8>( 0x81u );
574  msg->Write<u8>( 0x93u );
575  msg->Write<u8>( 0xcbu );
576  msg->Write<u8>( 0xafu );
577  msg->Write<u8>( 0x98u );
578  msg->Write<u8>( 0xddu );
579  msg->Write<u8>( 0x83u );
580  msg->Write<u8>( 0x13u );
581  msg->Write<u8>( 0xd2u );
582  msg->Write<u8>( 0x9eu );
583  msg->Write<u8>( 0xeau );
584  msg->Write<u8>( 0xe4u );
585  msg->Write<u8>( 0x13u );
586  msg->WriteFlipped<u32>( 0x10u );
587  msg->Write<u8>( 0x78u );
588  msg->Write<u8>( 0x13u );
589  msg->Write<u8>( 0xb7u );
590  msg->Write<u8>( 0x7bu );
591  msg->Write<u8>( 0xceu );
592  msg->Write<u8>( 0xa8u );
593  msg->Write<u8>( 0xd7u );
594  msg->Write<u8>( 0xbcu );
595  msg->Write<u8>( 0x52u );
596  msg->Write<u8>( 0xdeu );
597  msg->Write<u8>( 0x38u );
598  msg->Write<u8>( 0x30u );
599  msg->Write<u8>( 0xeau );
600  msg->Write<u8>( 0xe9u );
601  msg->Write<u8>( 0x1eu );
602  msg->Write<u8>( 0xa3u );
603  msg->WriteFlipped<u32>( 0x20u );
604  msg->WriteFlipped<u32>( 0x10u );
605  msg->Write<u8>( 0x5au );
606  msg->Write<u8>( 0xceu );
607  msg->Write<u8>( 0x3eu );
608  msg->Write<u8>( 0xe3u );
609  msg->Write<u8>( 0x97u );
610  msg->Write<u8>( 0x92u );
611  msg->Write<u8>( 0xe4u );
612  msg->Write<u8>( 0x8au );
613  msg->Write<u8>( 0xf1u );
614  msg->Write<u8>( 0x9au );
615  msg->Write<u8>( 0xd3u );
616  msg->Write<u8>( 0x04u );
617  msg->Write<u8>( 0x41u );
618  msg->Write<u8>( 0x03u );
619  msg->Write<u8>( 0xcbu );
620  msg->Write<u8>( 0x53u );
622  client->setClientType( Network::CLIENTTYPE_UOKR ); // UO:KR logging in
623  msg.Send( client );
624  }
625  else if ( client->buffer[0] ==
626  PKTIN_EF_ID ) // new seed since 6.0.5.0 (0xef should never appear in normal ipseed)
627  {
628  if ( Plib::systemstate.config.verbose )
629  {
630  INFO_PRINT.Format( "6.0.5.0+ Crypt Seed Message Received: Type 0x{:X}\n" ) << (int)cstype;
631  }
633  }
634  else
635  {
636  client->cryptengine->Init( client->buffer, Crypt::CCryptBase::typeAuto );
638  }
639  }
640  // Else keep waiting for IP address.
641  }
643  {
644  client->recv_remaining_nocrypt(
645  21 ); // receive and send to handler to get directly the version
646  if ( client->bytes_received == 21 )
647  {
649  unsigned char tempseed[4];
650  tempseed[0] = client->buffer[1];
651  tempseed[1] = client->buffer[2];
652  tempseed[2] = client->buffer[3];
653  tempseed[3] = client->buffer[4];
654  client->cryptengine->Init( tempseed, Crypt::CCryptBase::typeLogin );
656  }
657  }
658 
659  return false;
660 }
661 
663 {
664  switch ( client->buffer[0] )
665  {
666  case PKTBI_73_ID:
667  // Fallthrough
668  case PKTIN_09_ID:
669  // Fallthrough
670  case PKTBI_D6_IN_ID:
671  return true;
672  case PKTBI_BF_ID:
673  if ( ( client->buffer[3] == 0 ) && ( client->buffer[4] == PKTBI_BF::TYPE_SESPAM ) )
674  return true;
675  break;
676  default:
677  return false;
678  }
679 
680  return false;
681 }
682 
683 void report_weird_packet( Network::Client* client, const std::string& why )
684 {
685  fmt::Writer tmp;
686  tmp.Format( "Client#{}: {} type 0x{:X}, {} bytes (IP: {}, Account: {})\n" )
687  << client->instance_ << why << (int)client->buffer[0] << client->bytes_received
688  << client->ipaddrAsString() << ( ( client->acct != NULL ) ? client->acct->name() : "None" );
689 
690  if ( client->bytes_received <= 64 )
691  {
692  Clib::fdump( tmp, client->buffer, client->bytes_received );
693  POLLOG_INFO << tmp.str() << "\n";
694  }
695  else
696  {
697  INFO_PRINT << tmp.str();
698  Clib::fdump( tmp, client->buffer, client->bytes_received );
699  POLLOG << tmp.str() << "\n";
700  }
701 }
702 
703 // Called when a packet size is registered but the
704 // packet has no handler in the core
706 {
707  if ( Plib::systemstate.config.display_unknown_packets )
708  report_weird_packet( client, "Unknown packet" );
709 }
710 
711 // Called when POL receives an undefined packet.
712 // Those have no registered size, so we must guess.
714 {
715  int msgtype = (int)client->buffer[0];
716  INFO_PRINT.Format( "Undefined message type 0x{:X}\n" ) << msgtype;
717 
718  // Tries to read as much of it out as possible
719  client->recv_remaining( sizeof client->buffer / 2 );
720 
721  report_weird_packet( client, "Unexpected message" );
722 }
723 
724 // Handles variable-sized packets whose declared size is much larger than
725 // the receive buffer. This packet is most likely a client error, because
726 // the buffer should be big enough to handle anything sent by the known
727 // clients.
728 void handle_humongous_packet( Network::Client* client, unsigned int reported_size )
729 {
730  // Tries to read as much of it out as possible
731  // (the client will be disconnected, but this may
732  // be useful for debugging)
733  client->recv_remaining( sizeof client->buffer / 2 );
734 
735  fmt::Writer tmp;
736  tmp.Format( "Humongous packet (length {})", reported_size );
737  report_weird_packet( client, tmp.str() );
738 }
739 } // namespace Core
740 } // namespace Pol
void pol_sleep_ms(unsigned int millis)
Definition: polclock.cpp:46
unsigned char u8
Definition: rawtypes.h:25
#define CLIENT_CHECKPOINT(x)
bool have_queued_data() const
Definition: client.h:281
#define MSGLEN_2BYTELEN_DATA
Definition: msghandl.h:98
void quickconfig(const Plib::Package *pkg, const std::string &name_ecl)
Definition: scrdef.cpp:112
void send_queued_data()
Definition: client.cpp:554
int value() const
Definition: bobject.h:592
void forceDisconnect()
Definition: client.h:288
enum Pol::Network::Client::e_recv_states recv_state
SystemState systemstate
Definition: systemstate.cpp:12
void recv_remaining_nocrypt(int total_expected)
Definition: clientio.cpp:72
#define INVALID_SOCKET
Definition: wnsckt.h:12
sockaddr ipaddr
Definition: client.h:213
int SOCKET
Definition: wnsckt.h:10
void send_pulse()
Definition: polsem.cpp:188
polclock_t polclock()
Definition: polclock.cpp:72
Core::polclock_t last_packet_at
Definition: client.h:266
void wake_tasks_thread()
Definition: polsem.cpp:230
Core::PolConfig config
Definition: systemstate.h:43
std::string fpLog
Definition: client.h:222
Accounts::Account * acct
Definition: client.h:181
bool client_io_thread(Network::Client *client, bool login)
std::atomic< int > pause_count
Definition: client.h:231
Packet received[256]
Definition: iostats.h:26
PktHandlerFunc func
Definition: msghandl.h:34
bool SpeedHackPrevention(bool add=true)
Definition: client.cpp:662
#define POLLOG_INFO
Definition: logfacility.h:213
void handle_unknown_packet(Client *client)
static MSG_HANDLER find_handler(unsigned char msgid, const Client *client)
Definition: msghandl.cpp:26
unsigned char cmdlevel() const
Definition: charactr.h:993
bool connected() const
Definition: charactr.cpp:438
#define POLLOG_ERROR
Definition: logfacility.h:207
bool isa(BObjectImp::BObjectType type) const
Definition: bobject.h:423
void fdump(fmt::Writer &writer, const void *data, int len)
Definition: fdump.cpp:40
unsigned int bytes_received
Definition: client.h:210
void CoreSetSysTrayToolTip(const std::string &text, Priority priority)
Definition: core.cpp:36
static bool is_defined(unsigned char msgid)
Definition: msghandl.cpp:70
void recv_remaining(int total_expected)
Definition: clientio.cpp:42
unsigned char bufcheck2_55
Definition: client.h:209
bool process_data(Network::Client *client)
static void handle_msg(unsigned char msgid, Client *client, void *data)
Definition: msghandl.cpp:20
Mobile::Character * chr
Definition: client.h:182
#define FLEXLOG(id)
Definition: logfacility.h:245
#define passert_r(exp, reason)
Definition: passert.h:66
unsigned short u16
Definition: rawtypes.h:26
unsigned int u32
Definition: rawtypes.h:27
#define PKTOUT_53_WARN_CHARACTER_IDLE
Definition: pktdef.h:115
bool isConnected() const
Definition: client.h:301
bool check_inactivity(Network::Client *client)
bool exists() const
Definition: scrdef.cpp:126
std::unique_ptr< Network::ClientTransmit > clientTransmit
Definition: network.h:97
unsigned int message_length
Definition: client.h:211
void checkpoint(const char *msg, unsigned short minlvl)
Definition: checkpnt.cpp:17
unsigned char pktbuffer[PKTIN_02_SIZE]
Definition: client.h:130
bool speedhack_prevention
Definition: ssopt.h:82
unsigned char msgtype_allowed[256]
Definition: msgfiltr.h:25
NetworkManager networkManager
Definition: network.cpp:28
std::queue< PacketThrottler > movementqueue
Definition: client.h:261
void Send(Client *client, int len=-1) const
Definition: packethelper.h:69
unsigned short select_timeout_usecs
Definition: polcfg.h:34
static bool is_dirty()
Definition: schedule.h:31
const char * name() const
Definition: account.cpp:193
std::string tostring(const Bscript::BTokenType &v)
Definition: tokens.cpp:19
unsigned char bufcheck1_AA
Definition: client.h:207
unsigned char buffer[MAXBUFFER]
Definition: client.h:208
#define socket_errno
Definition: wnsckt.cpp:34
void handle_undefined_packet(Network::Client *client)
virtual void Init(void *pvSeed, int type=typeAuto)=0
void notify_left(Mobile::Character &wholeft)
Definition: realm.cpp:174
#define SOCKET_ERRNO(x)
Definition: wnsckt.cpp:33
#define passert(exp)
Definition: passert.h:62
const char * AddressToString(struct sockaddr *addr)
Definition: sockio.cpp:212
#define POLLOG
Definition: logfacility.h:219
int polclock_t
Definition: polclock.h:26
ClientGameData * gd
Definition: client.h:252
BObjectImp * impptr()
Definition: bobject.h:428
void handle_humongous_packet(Network::Client *client, unsigned int reported_size)
SettingsManager settingsManager
Definition: settings.cpp:14
Crypt::CCryptBase * cryptengine
Definition: client.h:215
void report_weird_packet(Network::Client *client, const std::string &why)
Network::IOStats iostats
Definition: network.h:71
const Core::MessageTypeFilter * msgtype_filter
Definition: client.h:219
void setClientType(ClientTypeFlag type)
Definition: client.cpp:371
unsigned char last_msgtype
Definition: client.h:256
#define INFO_PRINT_TRACE(n)
Definition: logfacility.h:226
bool isReallyConnected() const
Definition: client.h:295
Realms::Realm * realm
Definition: baseobject.h:56
std::string ipaddrAsString() const
Definition: clientio.cpp:37
bool valid_message_length(Network::Client *client, unsigned int length)
std::atomic< unsigned int > count
Definition: iostats.h:21
std::atomic< unsigned int > bytes
Definition: iostats.h:22
unsigned short inactivity_disconnect_timeout
Definition: polcfg.h:59
bool run_script_to_completion(const char *filename, Bscript::BObjectImp *parameter)
Definition: scrsched.cpp:333
Core::polclock_t last_activity_at
Definition: client.h:265
void restart_all_clients()
Definition: pol.cpp:505
#define INFO_PRINT
Definition: logfacility.h:223
std::lock_guard< SpinLock > SpinLockGuard
Definition: spinlock.h:33
Clib::SpinLock _fpLog_lock
Definition: client.h:221
void call_chr_scripts(Mobile::Character *chr, const std::string &root_script_ecl, const std::string &pkg_script_ecl, bool offline=false)
Definition: pol.cpp:329
Definition: berror.cpp:12
const polclock_t POLCLOCKS_PER_SEC
Definition: polclock.h:29
std::atomic< bool > exit_signalled
unsigned int instance_
Definition: client.h:253
unsigned short min_cmdlvl_ignore_inactivity
Definition: polcfg.h:57