Pol  Revision:4b29d2b
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 != nullptr ) ? 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  {
359  chr->realm->notify_left( *chr );
360  }
361  }
362  }
363  }
364  }
365  catch ( std::exception& ex )
366  {
367  POLLOG.Format( "Client#{}: Exception in i/o thread: {}! (checkpoint={}, what={})\n" )
368  << client->instance_ << checkpoint << ex.what();
369  }
370 
371  // queue delete of client ptr see method doc for reason
372  Core::networkManager.clientTransmit->QueueDelete( client );
373  return false;
374 }
375 
376 bool valid_message_length( Network::Client* client, unsigned int length )
377 {
378  if ( length > sizeof client->buffer )
379  {
380  handle_humongous_packet( client, client->message_length );
381  return false;
382  }
383  if ( length < 3 )
384  {
385  report_weird_packet( client, "Too-short message" );
386  return false;
387  }
388  return true;
389 }
390 
391 // bool - return true when a message was processed.
393 {
394  // NOTE: This is coded such that for normal messages, which are completely available,
395  // this function will get the type, then the length, then the data, without having
396  // to wait for a second or third call.
397  // Also, the abnormal state, RECV_STATE_CRYPTSEED_WAIT, is handled at the end, so in
398  // normal processing its code doesn't see the code path.
399  passert( client->bufcheck1_AA == 0xAA );
400  passert( client->bufcheck2_55 == 0x55 );
402  {
403  client->bytes_received = 0;
404  client->recv_remaining( 1 );
405  CLIENT_CHECKPOINT( 22 );
406  if ( client->bytes_received < 1 ) // this really should never happen.
407  {
408  client->forceDisconnect();
409  return false;
410  }
411 
412  unsigned char msgtype = client->buffer[0];
413  client->last_msgtype = msgtype; // CNXBUG
414  if ( Plib::systemstate.config.verbose )
415  INFO_PRINT.Format( "Incoming msg type: 0x{:X}\n" ) << (int)msgtype;
416 
417  if ( !Network::PacketRegistry::is_defined( msgtype ) )
418  {
419  handle_undefined_packet( client );
420  return false; // remain in RECV_STATE_MSGTYPE_WAIT
421  }
422 
423  Network::MSG_HANDLER packetHandler = Network::PacketRegistry::find_handler( msgtype, client );
424  if ( packetHandler.msglen == MSGLEN_2BYTELEN_DATA )
425  {
427  }
428  else
429  {
430  passert( packetHandler.msglen > 0 );
431 
433  client->message_length = packetHandler.msglen;
434  }
435 
436  } /* endif of RECV_STATE_MSGTYPE_WAIT */
437 
439  {
440  client->recv_remaining( 3 );
441  CLIENT_CHECKPOINT( 23 );
442  if ( client->bytes_received == 3 ) // the length bytes were available.
443  {
444  // MSG is [MSGTYPE] [LENHI] [LENLO] [DATA ... ]
445  client->message_length = ( client->buffer[1] << 8 ) + client->buffer[2];
446 
447  if ( !valid_message_length( client, client->message_length ) )
448  {
449  // If the reported length is too short (less than 3 bytes) or
450  // too big (larger than the client buffer), something very odd
451  // happened.
452  client->forceDisconnect();
453  return false;
454  }
456  }
457  // else keep waiting.
458  } /* endif of RECV_STATE_MSGLEN_WAIT */
459 
461  {
462  CLIENT_CHECKPOINT( 24 );
463  client->recv_remaining( client->message_length );
464  CLIENT_CHECKPOINT( 25 );
465  if ( client->bytes_received == client->message_length ) // we have the whole message
466  {
467  unsigned char msgtype = client->buffer[0];
469  networkManager.iostats.received[msgtype].bytes += client->message_length;
470  {
471  Clib::SpinLockGuard guard( client->_fpLog_lock );
472  if ( !client->fpLog.empty() )
473  {
474  fmt::Writer tmp;
475  tmp << "Client -> Server: 0x" << fmt::hexu( msgtype ) << ", " << client->message_length
476  << " bytes\n";
477  Clib::fdump( tmp, &client->buffer, client->message_length );
478  FLEXLOG( client->fpLog ) << tmp.str() << "\n";
479  }
480  }
481 
482  if ( Plib::systemstate.config.verbose )
483  INFO_PRINT.Format( "Message Received: Type 0x{:X}, Length {} bytes\n" )
484  << (int)msgtype << client->message_length;
485 
486  PolLock lck; // multithread
487  // it can happen that a client gets disconnected while waiting for the lock.
488  if ( client->isConnected() )
489  {
490  if ( client->msgtype_filter->msgtype_allowed[msgtype] )
491  {
492  // region Speedhack
493  if ( ( settingsManager.ssopt.speedhack_prevention ) && ( msgtype == PKTIN_02_ID ) )
494  {
495  if ( !client->SpeedHackPrevention() )
496  {
497  // client->SpeedHackPrevention() added packet to queue
499  CLIENT_CHECKPOINT( 28 );
500  return true;
501  }
502  }
503  // endregion Speedhack
504 
505 
506  Network::MSG_HANDLER packetHandler =
507  Network::PacketRegistry::find_handler( msgtype, client );
508  passert( packetHandler.msglen != 0 );
509 
510  try
511  {
512  INFO_PRINT_TRACE( 10 )
513  << "Client#" << client->instance_ << ": message 0x" << fmt::hexu( msgtype ) << "\n";
514  CLIENT_CHECKPOINT( 26 );
515  packetHandler.func( client, client->buffer );
516  CLIENT_CHECKPOINT( 27 );
518  }
519  catch ( std::exception& ex )
520  {
521  POLLOG_ERROR.Format( "Client#{}: Exception in message handler 0x{:X}: {}\n" )
522  << client->instance_ << (int)msgtype << ex.what();
523  fmt::Writer tmp;
524  Clib::fdump( tmp, client->buffer, client->bytes_received );
525  POLLOG << tmp.str() << "\n";
527  throw;
528  }
529  }
530  else
531  {
532  POLLOG_ERROR.Format( "Client#{} ({}, Acct {}) sent non-allowed message type 0x{:X}.\n" )
533  << client->instance_ << Network::AddressToString( &client->ipaddr )
534  << ( client->acct ? client->acct->name() : "unknown" ) << (int)msgtype;
535  }
536  }
538  CLIENT_CHECKPOINT( 28 );
539  return true;
540  }
541  // else keep waiting
542  } /* endif RECV_STATE_MSGDATA_WAIT */
544  { // The abnormal case.
545  // The first four bytes after connection are the
546  // crypto seed
547  client->recv_remaining_nocrypt( 4 );
548 
549  if ( client->bytes_received == 4 )
550  {
551  /* The first four bytes transmitted are the encryption seed */
552  unsigned char cstype = client->buffer[0];
553 
554  if ( ( client->buffer[0] == 0xff ) && ( client->buffer[1] == 0xff ) &&
555  ( client->buffer[2] == 0xff ) && ( client->buffer[3] == 0xff ) )
556  {
557  if ( Plib::systemstate.config.verbose )
558  {
559  INFO_PRINT.Format( "UOKR Seed Message Received: Type 0x{:X}\n" ) << (int)cstype;
560  }
562  msg->WriteFlipped<u16>( 77u );
563  msg->WriteFlipped<u32>( 0x03u );
564  msg->Write<u8>( 0x02u );
565  msg->Write<u8>( 0x01u );
566  msg->Write<u8>( 0x03u );
567  msg->WriteFlipped<u32>( 0x13u );
568  msg->Write<u8>( 0x02u );
569  msg->Write<u8>( 0x11u );
570  msg->Write<u8>( 0x00u );
571  msg->Write<u8>( 0xfcu );
572  msg->Write<u8>( 0x2fu );
573  msg->Write<u8>( 0xe3u );
574  msg->Write<u8>( 0x81u );
575  msg->Write<u8>( 0x93u );
576  msg->Write<u8>( 0xcbu );
577  msg->Write<u8>( 0xafu );
578  msg->Write<u8>( 0x98u );
579  msg->Write<u8>( 0xddu );
580  msg->Write<u8>( 0x83u );
581  msg->Write<u8>( 0x13u );
582  msg->Write<u8>( 0xd2u );
583  msg->Write<u8>( 0x9eu );
584  msg->Write<u8>( 0xeau );
585  msg->Write<u8>( 0xe4u );
586  msg->Write<u8>( 0x13u );
587  msg->WriteFlipped<u32>( 0x10u );
588  msg->Write<u8>( 0x78u );
589  msg->Write<u8>( 0x13u );
590  msg->Write<u8>( 0xb7u );
591  msg->Write<u8>( 0x7bu );
592  msg->Write<u8>( 0xceu );
593  msg->Write<u8>( 0xa8u );
594  msg->Write<u8>( 0xd7u );
595  msg->Write<u8>( 0xbcu );
596  msg->Write<u8>( 0x52u );
597  msg->Write<u8>( 0xdeu );
598  msg->Write<u8>( 0x38u );
599  msg->Write<u8>( 0x30u );
600  msg->Write<u8>( 0xeau );
601  msg->Write<u8>( 0xe9u );
602  msg->Write<u8>( 0x1eu );
603  msg->Write<u8>( 0xa3u );
604  msg->WriteFlipped<u32>( 0x20u );
605  msg->WriteFlipped<u32>( 0x10u );
606  msg->Write<u8>( 0x5au );
607  msg->Write<u8>( 0xceu );
608  msg->Write<u8>( 0x3eu );
609  msg->Write<u8>( 0xe3u );
610  msg->Write<u8>( 0x97u );
611  msg->Write<u8>( 0x92u );
612  msg->Write<u8>( 0xe4u );
613  msg->Write<u8>( 0x8au );
614  msg->Write<u8>( 0xf1u );
615  msg->Write<u8>( 0x9au );
616  msg->Write<u8>( 0xd3u );
617  msg->Write<u8>( 0x04u );
618  msg->Write<u8>( 0x41u );
619  msg->Write<u8>( 0x03u );
620  msg->Write<u8>( 0xcbu );
621  msg->Write<u8>( 0x53u );
623  client->setClientType( Network::CLIENTTYPE_UOKR ); // UO:KR logging in
624  msg.Send( client );
625  }
626  else if ( client->buffer[0] ==
627  PKTIN_EF_ID ) // new seed since 6.0.5.0 (0xef should never appear in normal ipseed)
628  {
629  if ( Plib::systemstate.config.verbose )
630  {
631  INFO_PRINT.Format( "6.0.5.0+ Crypt Seed Message Received: Type 0x{:X}\n" ) << (int)cstype;
632  }
634  }
635  else
636  {
637  client->cryptengine->Init( client->buffer, Crypt::CCryptBase::typeAuto );
639  }
640  }
641  // Else keep waiting for IP address.
642  }
644  {
645  client->recv_remaining_nocrypt(
646  21 ); // receive and send to handler to get directly the version
647  if ( client->bytes_received == 21 )
648  {
650  unsigned char tempseed[4];
651  tempseed[0] = client->buffer[1];
652  tempseed[1] = client->buffer[2];
653  tempseed[2] = client->buffer[3];
654  tempseed[3] = client->buffer[4];
655  client->cryptengine->Init( tempseed, Crypt::CCryptBase::typeLogin );
657  }
658  }
659 
660  return false;
661 }
662 
664 {
665  switch ( client->buffer[0] )
666  {
667  case PKTBI_73_ID:
668  // Fallthrough
669  case PKTIN_09_ID:
670  // Fallthrough
671  case PKTBI_D6_IN_ID:
672  return true;
673  case PKTBI_BF_ID:
674  if ( ( client->buffer[3] == 0 ) && ( client->buffer[4] == PKTBI_BF::TYPE_SESPAM ) )
675  return true;
676  break;
677  default:
678  return false;
679  }
680 
681  return false;
682 }
683 
684 void report_weird_packet( Network::Client* client, const std::string& why )
685 {
686  fmt::Writer tmp;
687  tmp.Format( "Client#{}: {} type 0x{:X}, {} bytes (IP: {}, Account: {})\n" )
688  << client->instance_ << why << (int)client->buffer[0] << client->bytes_received
689  << client->ipaddrAsString()
690  << ( ( client->acct != nullptr ) ? client->acct->name() : "None" );
691 
692  if ( client->bytes_received <= 64 )
693  {
694  Clib::fdump( tmp, client->buffer, client->bytes_received );
695  POLLOG_INFO << tmp.str() << "\n";
696  }
697  else
698  {
699  INFO_PRINT << tmp.str();
700  Clib::fdump( tmp, client->buffer, client->bytes_received );
701  POLLOG << tmp.str() << "\n";
702  }
703 }
704 
705 // Called when a packet size is registered but the
706 // packet has no handler in the core
708 {
709  if ( Plib::systemstate.config.display_unknown_packets )
710  report_weird_packet( client, "Unknown packet" );
711 }
712 
713 // Called when POL receives an undefined packet.
714 // Those have no registered size, so we must guess.
716 {
717  int msgtype = (int)client->buffer[0];
718  INFO_PRINT.Format( "Undefined message type 0x{:X}\n" ) << msgtype;
719 
720  // Tries to read as much of it out as possible
721  client->recv_remaining( sizeof client->buffer / 2 );
722 
723  report_weird_packet( client, "Unexpected message" );
724 }
725 
726 // Handles variable-sized packets whose declared size is much larger than
727 // the receive buffer. This packet is most likely a client error, because
728 // the buffer should be big enough to handle anything sent by the known
729 // clients.
730 void handle_humongous_packet( Network::Client* client, unsigned int reported_size )
731 {
732  // Tries to read as much of it out as possible
733  // (the client will be disconnected, but this may
734  // be useful for debugging)
735  client->recv_remaining( sizeof client->buffer / 2 );
736 
737  fmt::Writer tmp;
738  tmp.Format( "Humongous packet (length {})", reported_size );
739  report_weird_packet( client, tmp.str() );
740 }
741 } // namespace Core
742 } // 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