Pol  Revision:f37d500
client.cpp
Go to the documentation of this file.
1 
19 #include "client.h"
20 
21 #include <errno.h>
22 #include <stdlib.h>
23 #include <time.h>
24 
25 #include "../../bscript/berror.h"
26 #include "../../bscript/bstruct.h"
27 #include "../../clib/clib.h"
28 #include "../../clib/logfacility.h"
29 #include "../../clib/strutil.h" //CNXBUG
30 #include "../../clib/wallclock.h"
31 #include "../accounts/account.h"
32 #include "../crypt/cryptbase.h"
33 #include "../crypt/cryptengine.h"
34 #include "../globals/network.h"
35 #include "../globals/state.h"
36 #include "../mobile/charactr.h"
37 #include "../pktdef.h"
38 #include "../pktin.h"
39 #include "../polsig.h"
40 #include "../realms/WorldChangeReasons.h"
41 #include "../ufunc.h" // only in here temporarily, until logout-on-disconnect stuff is removed
42 #include "../unicode.h"
43 #include "../uoclient.h"
44 #include "../uoscrobj.h"
45 #include "../uworld.h"
46 #include "../xbuffer.h"
47 #include "cgdata.h"
48 #include "cliface.h"
49 
50 
51 #define PRE_ENCRYPT
52 
53 #ifndef PRE_ENCRYPT
54 #include "sockio.h"
55 #endif
56 
57 #ifdef _MSC_VER
58 #pragma warning( \
59  disable : 4351 ) // new behavior: elements of array '...' will be default initialized
60 #endif
61 
62 namespace Pol
63 {
64 namespace Core
65 {
66 void cancel_trade( Mobile::Character* chr1 );
67 }
68 namespace Network
69 {
70 unsigned int Client::instance_counter_;
71 std::mutex Client::_SocketMutex;
72 
74  : preDisconnect( 0 ),
75  disconnect( 0 ),
76  acct( NULL ),
77  chr( NULL ),
78  Interface( aInterface ),
79  ready( false ),
80  csocket( INVALID_SOCKET ),
81  listen_port( 0 ),
82  aosresist( false ),
83  recv_state( RECV_STATE_CRYPTSEED_WAIT ),
84  bufcheck1_AA( 0xAA ),
85  buffer(),
86  bufcheck2_55( 0x55 ),
87  bytes_received( 0 ),
88  message_length( 0 ),
89  cryptengine( create_crypt_engine( encryption ) ),
90  encrypt_server_stream( 0 ),
91  msgtype_filter( Core::networkManager.login_filter.get() ),
92  _fpLog_lock(),
93  fpLog( "" ),
94  pause_count( 0 ),
95  first_xmit_buffer( NULL ),
96  last_xmit_buffer( NULL ),
97  n_queued( 0 ),
98  queued_bytes_counter( 0 ),
99  gd( new ClientGameData ),
100  instance_( ++instance_counter_ ),
101  checkpoint( -1 ), // CNXBUG
102  last_msgtype( 255 ),
103  thread_pid( (size_t)-1 ),
104  UOExpansionFlag( 0 ),
105  UOExpansionFlagClient( 0 ),
106  ClientType( 0 ),
107  next_movement( 0 ),
108  movementsequence( 0 ),
109  last_activity_at( 0 ),
110  last_packet_at( 0 ),
111  paused_( false )
112 {
113  weakptr.set( this ); // store weakptr for usage in scripts (see EClientRefObjImp)
114 
115  // For bypassing cryptseed packet
116  if ( Core::settingsManager.ssopt.use_edit_server )
117  {
119  }
120 
121  Interface.register_client( this );
122  memset( buffer, 0, sizeof buffer );
123  memset( &counters, 0, sizeof counters );
124  memset( &clientinfo_, 0, sizeof( clientinfo_ ) );
125  memset( &versiondetail_, 0, sizeof( versiondetail_ ) );
126  memset( &ipaddr, 0, sizeof( ipaddr ) );
127 }
128 
129 void Client::Delete( Client* client )
130 {
131  std::lock_guard<std::mutex> lock( _SocketMutex ); // TODO: check if this is necessary
132  client->PreDelete();
133  delete client->cryptengine; // TODO: move this into a unique_ptr<> or at least ~Client()
134  client->cryptengine = NULL;
135  delete client;
136 }
137 
139 
141 {
142  auto findClient =
143  std::find( Core::networkManager.clients.begin(), Core::networkManager.clients.end(), this );
144  Core::networkManager.clients.erase( findClient ); // TODO: Make networkManager more OO
146 }
147 
149 {
150  // std::lock_guard<std::mutex> lock (_SocketMutex);
151  if ( csocket != INVALID_SOCKET ) //>= 0)
152  {
153 #ifdef _WIN32
154  shutdown( csocket, 2 ); // 2 is both sides, defined in winsock2.h ...
155  closesocket( csocket );
156 #else
157  shutdown( csocket, SHUT_RDWR );
158  close( csocket );
159 #endif
160  }
162 }
163 
165 {
166  closeConnection();
167 
168  if ( chr != NULL && chr->client == this )
169  {
170  if ( chr->logged_in() )
171  {
174  chr->logged_in( false );
175 
176  chr->set_opponent( NULL );
177  chr->removal_cleanup();
178  if ( chr->get_opponent() != NULL )
179  {
180  chr->set_opponent( NULL, true );
181  }
182  }
183  else
184  {
185  ERROR_PRINT << "Uhh... active character not logged in!??\n";
186  }
187  }
188 
189  // detach the account and character from this client, if they
190  // are still associated with it.
191 
192  acct = NULL;
193 
194  if ( chr )
195  {
196  if ( chr->client == this )
197  chr->client = NULL;
198  chr = NULL;
199  }
200 
201  {
203  if ( !fpLog.empty() )
204  {
205  time_t now = time( NULL );
206  auto time = Clib::localtime( now );
207  FLEXLOG( fpLog ) << "Log closed at " << asctime( &time ) << "\n";
208  CLOSE_FLEXLOG( fpLog );
209  fpLog.clear();
210  }
211  }
212 
213  delete gd;
214  gd = NULL;
215 
216  while ( first_xmit_buffer != NULL )
217  {
220  free( xbuffer );
221  --n_queued;
222  }
223  last_xmit_buffer = NULL;
224 
225  // while (!movementqueue.empty())
226  // movementqueue.pop();
227 }
228 
229 // ClientInfo - delivers a lot of usefull infomation about client PC
231 {
232  using namespace Bscript;
233  std::unique_ptr<BStruct> ret( new BStruct );
234 
235  ret->addMember( "unknown1", new BLong( clientinfo_.unknown1 ) ); // Unknown - allways 0x02
236  ret->addMember( "instance", new BLong( clientinfo_.instance ) ); // Unique Instance ID of UO
237  ret->addMember( "os_major", new BLong( clientinfo_.os_major ) ); // OS Major
238  ret->addMember( "os_minor", new BLong( clientinfo_.os_minor ) ); // OS Minor
239  ret->addMember( "os_revision", new BLong( clientinfo_.os_revision ) ); // OS Revision
240  ret->addMember( "cpu_manufacturer",
241  new BLong( clientinfo_.cpu_manufacturer ) ); // CPU Manufacturer
242  ret->addMember( "cpu_family", new BLong( clientinfo_.cpu_family ) ); // CPU Family
243  ret->addMember( "cpu_model", new BLong( clientinfo_.cpu_model ) ); // CPU Model
244  ret->addMember( "cpu_clockspeed",
245  new BLong( clientinfo_.cpu_clockspeed ) ); // CPU Clock Speed [Mhz]
246  ret->addMember( "cpu_quantity", new BLong( clientinfo_.cpu_quantity ) ); // CPU Quantity
247  ret->addMember( "memory", new BLong( clientinfo_.memory ) ); // Memory [MB]
248  ret->addMember( "screen_width", new BLong( clientinfo_.screen_width ) ); // Screen Width
249  ret->addMember( "screen_height", new BLong( clientinfo_.screen_height ) ); // Screen Height
250  ret->addMember( "screen_depth", new BLong( clientinfo_.screen_depth ) ); // Screen Depth [Bit]
251  ret->addMember( "directx_major", new BLong( clientinfo_.directx_major ) ); // DirectX Major
252  ret->addMember( "directx_minor", new BLong( clientinfo_.directx_minor ) ); // DirectX Minor
253 
254  ObjArray* arr_vd;
255  unsigned maxlen_vd =
257  unsigned wlen_vd = 0;
258  while ( ( clientinfo_.video_description[wlen_vd] != L'\0' ) && ( wlen_vd < maxlen_vd ) )
259  ++wlen_vd;
260  if ( !Core::convertUCtoArray( clientinfo_.video_description, arr_vd, wlen_vd, true ) )
261  ret->addMember( "video_description",
262  new Bscript::BError( "Invalid Unicode speech received." ) );
263  else
264  {
265  ret->addMember( "video_description", arr_vd ); // Video Card Description [wide-character]
266  }
267 
268  ret->addMember( "video_vendor", new BLong( clientinfo_.video_vendor ) ); // Video Card Vendor ID
269  ret->addMember( "video_device", new BLong( clientinfo_.video_device ) ); // Video Card Device ID
270  ret->addMember( "video_memory",
271  new BLong( clientinfo_.video_memory ) ); // Video Card Memory [MB]
272  ret->addMember( "distribution", new BLong( clientinfo_.distribution ) ); // Distribution
273  ret->addMember( "clients_running", new BLong( clientinfo_.clients_running ) ); // Clients Running
274  ret->addMember( "clients_installed",
275  new BLong( clientinfo_.clients_installed ) ); // Clients Installed
276  ret->addMember( "partial_installed",
277  new BLong( clientinfo_.partial_installed ) ); // Partial Insstalled
278 
279  ObjArray* arr_lc;
280  unsigned maxlen_lc = sizeof( clientinfo_.langcode ) / sizeof( clientinfo_.langcode[0] );
281  unsigned wlen_lc = 0;
282  while ( ( wlen_lc < maxlen_lc ) && ( clientinfo_.langcode[wlen_lc] != L'\0' ) )
283  ++wlen_lc;
284  if ( !Core::convertUCtoArray( clientinfo_.langcode, arr_lc, wlen_lc, true ) )
285  ret->addMember( "langcode", new Bscript::BError( "Invalid Unicode speech received." ) );
286  else
287  {
288  ret->addMember( "langcode", arr_lc ); // Language Code [wide-character]
289  }
290 
291  std::unique_ptr<ObjArray> arr_u2( new ObjArray );
292  for ( unsigned i = 0; i < sizeof( clientinfo_.unknown2 ); ++i )
293  arr_u2->addElement( new BLong( clientinfo_.unknown2[i] ) );
294  ret->addMember( "unknown2", arr_u2.release() ); // Unknown
295 
296  return ret.release();
297 }
298 
299 void Client::itemizeclientversion( const std::string& ver, VersionDetailStruct& detail )
300 {
301  try
302  {
303  size_t dot1 = ver.find_first_of( '.', 0 );
304  size_t dot2 = ver.find_first_of( '.', dot1 + 1 );
305  size_t dot3 = ver.find_first_of( '.', dot2 + 1 );
306  if ( dot3 == std::string::npos ) // since 5.0.7 patch is digit
307  {
308  dot3 = dot2 + 1;
309  while ( ( dot3 < ver.length() ) && ( isdigit( ver[dot3] ) ) )
310  {
311  dot3++;
312  }
313  }
314 
315  detail.major = atoi( ver.substr( 0, dot1 ).c_str() );
316  detail.minor = atoi( ver.substr( dot1 + 1, dot2 - dot1 - 1 ).c_str() );
317  detail.rev = atoi( ver.substr( dot2 + 1, dot3 - dot2 - 1 ).c_str() );
318  detail.patch = 0;
319  if ( dot3 < ver.length() )
320  {
321  if ( ( detail.major <= 5 ) && ( detail.minor <= 0 ) && ( detail.rev <= 6 ) )
322  {
323  if ( ver[dot3] != ' ' )
324  detail.patch = ( ver[dot3] - 'a' ) + 1; // char to int
325  }
326  else
327  detail.patch = atoi( ver.substr( dot3 + 1, ver.length() - dot3 - 1 ).c_str() );
328  }
329  }
330  catch ( ... )
331  {
332  detail.major = 0;
333  detail.minor = 0;
334  detail.rev = 0;
335  detail.patch = 0;
336  POLLOG.Format( "Malformed clientversion string: {}\n" ) << ver;
337  }
338 }
339 
340 bool Client::compareVersion( const std::string& ver )
341 {
342  VersionDetailStruct ver2;
343  itemizeclientversion( ver, ver2 );
344  return Client::compareVersion( ver2 );
345 }
346 
348 {
350 
351  if ( ver1.major > ver2.major )
352  return true;
353  else if ( ver1.major < ver2.major )
354  return false;
355  else if ( ver1.minor > ver2.minor )
356  return true;
357  else if ( ver1.minor < ver2.minor )
358  return false;
359  else if ( ver1.rev > ver2.rev )
360  return true;
361  else if ( ver1.rev < ver2.rev )
362  return false;
363  else if ( ver1.patch > ver2.patch )
364  return true;
365  else if ( ver1.patch < ver2.patch )
366  return false;
367  else
368  return true;
369 }
370 
372 {
373  ClientType = 0x0;
374  // with fall through !
375  switch ( type )
376  {
377  case CLIENTTYPE_70331:
379  // fall through
380  case CLIENTTYPE_70300:
382  // fall through
383  case CLIENTTYPE_70130:
385  // fall through
386  case CLIENTTYPE_7090:
388  // fall through
389  case CLIENTTYPE_UOSA:
391  // fall through
392  case CLIENTTYPE_7000:
394  // fall through
395  case CLIENTTYPE_UOKR:
397  // fall through
398  case CLIENTTYPE_60142:
400  // fall through
401  case CLIENTTYPE_6017:
403  // fall through
404  case CLIENTTYPE_5020:
406  // fall through
407  case CLIENTTYPE_5000:
409  // fall through
410  case CLIENTTYPE_4070:
412  // fall through
413  case CLIENTTYPE_4000:
415  // fall through
416  default:
417  break;
418  }
419 }
420 
422 {
423  return ( ( ClientType & CLIENTTYPE_UOKR ) && ( !( ClientType & CLIENTTYPE_7000 ) ) );
424 }
425 
426 std::string Client::status() const
427 {
428  std::string st;
429  if ( acct != NULL )
430  st += "AC:" + std::string( acct->name() ) + " ";
431  if ( chr != NULL )
432  st += "CH:" + chr->name() + " ";
433  if ( have_queued_data() )
434  st += "TXBUF ";
435  if ( disconnect )
436  st += "DISC ";
437  if ( paused_ )
438  st += "PAUSE ";
439  if ( ready )
440  st += "RDY ";
441  st += ipaddrAsString() + " ";
442  st += "CHK: " + Clib::decint( checkpoint ) + " ";
443  st += "PID: " + Clib::decint( thread_pid ) + " ";
444  st += "LAST: " + Clib::hexint( last_msgtype );
445  return st;
446 }
447 
448 void Client::queue_data( const void* data, unsigned short datalen )
449 {
450  THREAD_CHECKPOINT( active_client, 300 );
451  Core::XmitBuffer* xbuffer = (Core::XmitBuffer*)malloc( sizeof( Core::XmitBuffer ) - 1 + datalen );
452  THREAD_CHECKPOINT( active_client, 301 );
453  if ( xbuffer )
454  {
455  THREAD_CHECKPOINT( active_client, 302 );
456  xbuffer->next = NULL;
457  xbuffer->nsent = 0;
458  xbuffer->lenleft = datalen;
459  memcpy( xbuffer->data, data, datalen );
460  THREAD_CHECKPOINT( active_client, 303 );
461  if ( first_xmit_buffer == NULL || last_xmit_buffer == NULL )
462  { // in this case, last_xmit_buffer is also NULL, so can't set its ->next.
463  THREAD_CHECKPOINT( active_client, 304 );
464  first_xmit_buffer = xbuffer;
465  }
466  else
467  {
468  THREAD_CHECKPOINT( active_client, 305 );
469  last_xmit_buffer->next = xbuffer;
470  }
471  THREAD_CHECKPOINT( active_client, 306 );
472  last_xmit_buffer = xbuffer;
473  ++n_queued;
474  queued_bytes_counter += datalen;
475  }
476  else
477  {
478  THREAD_CHECKPOINT( active_client, 307 );
479  POLLOG.Format( "Client#{}: Unable to allocate {} bytes for queued data. Disconnecting.\n" )
480  << instance_ << ( sizeof( Core::XmitBuffer ) - 1 + datalen );
481  disconnect = true;
482  }
483  THREAD_CHECKPOINT( active_client, 309 );
484 }
485 
486 void Client::xmit( const void* data, unsigned short datalen )
487 {
488  if ( csocket == INVALID_SOCKET )
489  return;
490  if ( encrypt_server_stream )
491  {
492  if ( cryptengine == NULL )
493  return;
494  this->cryptengine->Encrypt( (void*)data, (void*)data, datalen );
495  }
496  THREAD_CHECKPOINT( active_client, 200 );
497  if ( last_xmit_buffer ) // this client already backlogged, schedule for later
498  {
499  THREAD_CHECKPOINT( active_client, 201 );
500  queue_data( data, datalen );
501  THREAD_CHECKPOINT( active_client, 202 );
502  return;
503  }
504  THREAD_CHECKPOINT( active_client, 203 );
505 
506  /* client not backlogged - try to send. */
507  const unsigned char* cdata = (const unsigned char*)data;
508  int nsent;
509 
510  if ( -1 == ( nsent = send( csocket, (const char*)cdata, datalen, 0 ) ) )
511  {
512  THREAD_CHECKPOINT( active_client, 204 );
513  int sckerr = socket_errno;
514 
515  if ( sckerr == SOCKET_ERRNO( EWOULDBLOCK ) )
516  {
517  THREAD_CHECKPOINT( active_client, 205 );
518  POLLOG_ERROR.Format( "Client#{}: Switching to queued data mode (1, {} bytes)\n" )
519  << instance_ << datalen;
520  THREAD_CHECKPOINT( active_client, 206 );
521  queue_data( data, datalen );
522  THREAD_CHECKPOINT( active_client, 207 );
523  return;
524  }
525  else
526  {
527  THREAD_CHECKPOINT( active_client, 208 );
528  if ( !disconnect )
529  POLLOG_ERROR.Format( "Client#{}: Disconnecting client due to send() error (1): {}\n" )
530  << instance_ << sckerr;
531  disconnect = 1;
532  THREAD_CHECKPOINT( active_client, 209 );
533  return;
534  }
535  }
536  else // no error
537  {
538  THREAD_CHECKPOINT( active_client, 210 );
539  datalen -= static_cast<unsigned short>( nsent );
540  counters.bytes_transmitted += nsent;
542  if ( datalen ) // anything left? if so, queue for later.
543  {
544  THREAD_CHECKPOINT( active_client, 211 );
545  POLLOG_ERROR.Format( "Client#{}: Switching to queued data mode (2)\n" ) << instance_;
546  THREAD_CHECKPOINT( active_client, 212 );
547  queue_data( cdata + nsent, datalen );
548  THREAD_CHECKPOINT( active_client, 213 );
549  }
550  }
551  THREAD_CHECKPOINT( active_client, 214 );
552 }
553 
555 {
556  std::lock_guard<std::mutex> lock( _SocketMutex );
557  Core::XmitBuffer* xbuffer;
558  // hand off data to the sockets layer until it won't take any more.
559  // note if a buffer is sent in full, we try to send the next one, ad infinitum
560  while ( NULL != ( xbuffer = first_xmit_buffer ) )
561  {
562  int nsent;
563  nsent = send( csocket, (char*)&xbuffer->data[xbuffer->nsent], xbuffer->lenleft, 0 );
564  if ( nsent == -1 )
565  {
566 #ifdef _WIN32
567  int sckerr = WSAGetLastError();
568 #else
569  int sckerr = errno;
570 #endif
571  if ( sckerr == SOCKET_ERRNO( EWOULDBLOCK ) )
572  {
573  // do nothing. it'll be re-queued later, when it won't block.
574  return;
575  }
576  else
577  {
578  if ( !disconnect )
579  POLLOG.Format( "Client#{}: Disconnecting client due to send() error (2): {}\n" )
580  << instance_ << sckerr;
581  disconnect = 1;
582  return;
583  }
584  }
585  else
586  {
587  xbuffer->nsent += static_cast<unsigned short>( nsent );
588  xbuffer->lenleft -= static_cast<unsigned short>( nsent );
589  counters.bytes_transmitted += nsent;
591  if ( xbuffer->lenleft == 0 )
592  {
594  if ( first_xmit_buffer == NULL )
595  {
596  last_xmit_buffer = NULL;
597  POLLOG.Format( "Client#{}: Leaving queued mode ({} bytes xmitted)\n" )
599  queued_bytes_counter = 0;
600  }
601  free( xbuffer );
602  --n_queued;
603  }
604  }
605  }
606 }
607 
608 // 33 01 "encrypted": 4F FA
609 static const unsigned char pause_pre_encrypted[2] = {0x4F, 0xFA};
610 // 33 00 "encrypted": 4C D0
611 static const unsigned char restart_pre_encrypted[2] = {0x4C, 0xD0};
612 
614 {
615  if ( Core::networkManager.uoclient_protocol.EnableFlowControlPackets && !paused_ )
616  {
617 #ifndef PRE_ENCRYPT
618  PKTOUT_33 msg;
619  msg.msgtype = PKTOUT_33_ID;
620  msg.flow = MSGOPT_33_FLOW_PAUSE;
621  transmit( this, &msg, sizeof msg );
622 #else
623  xmit( pause_pre_encrypted, sizeof pause_pre_encrypted );
624 #endif
625  paused_ = true;
626  }
627 }
628 
630 {
631  if ( !pause_count )
632  {
633  send_pause();
634  pause_count = 1;
635  }
636 }
637 
639 {
640  if ( paused_ )
641  {
642 #ifndef PRE_ENCRYPT
643  PKTOUT_33 msg;
644  msg.msgtype = PKTOUT_33_ID;
645  msg.flow = MSGOPT_33_FLOW_RESTART;
646  transmit( this, &msg, sizeof msg );
647 #else
648  xmit( restart_pre_encrypted, sizeof restart_pre_encrypted );
649 #endif
650  paused_ = false;
651  }
652 }
653 
655 {
656  send_restart();
657  pause_count = 0;
658 }
659 
660 // Note: this doesnt test single packets it only summs the delay and tests
661 // here only the "start"-value is set the additional delay is set in PKT_02 handler
663 {
664  if ( ( !movementqueue.empty() ) && ( add ) )
665  {
666  if ( movementqueue.size() > 100 )
667  {
668  POLLOG_ERROR.Format( "Client#{}: More then 100 Movepackets in queue. Disconnecting.\n" )
669  << instance_;
670  disconnect = true;
671  return false;
672  }
673  PacketThrottler throttlestruct;
674  memcpy( &throttlestruct.pktbuffer, &buffer, PKTIN_02_SIZE );
675  movementqueue.push( throttlestruct );
676  return false;
677  }
678  if ( chr != nullptr && chr->can_speedhack() )
679  return true;
680  if ( ( next_movement == 0 ) ||
681  ( Clib::wallclock() > next_movement ) ) // never moved or in the past
682  {
684  return true;
685  }
686  // now we dont alter next_movement so we can sum the delay till diff is greater then error margin
688  if ( diff > PKTIN_02_ASYNCHRONOUS ) // delay sum greater then our error margin?
689  {
690  if ( add ) // delay packet
691  {
692  if ( movementqueue.size() > 100 )
693  {
694  POLLOG_ERROR.Format( "Client#{}: More then 100 Movepackets in queue. Disconnecting.\n" )
695  << instance_;
696  disconnect = true;
697  return false;
698  }
699  PacketThrottler throttlestruct;
700  memcpy( &throttlestruct.pktbuffer, &buffer, sizeof( throttlestruct.pktbuffer ) );
701  movementqueue.push( throttlestruct );
702  }
703  return false;
704  }
705  return true;
706 }
707 
709 {
710  return new Module::EClientRefObjImp( weakptr );
711 }
712 
714 {
715  return weakptr;
716 }
717 
718 size_t Client::estimatedSize() const
719 {
721  size_t size = sizeof( Client ) + fpLog.capacity() + version_.capacity();
722  Core::XmitBuffer* buffer_size = first_xmit_buffer;
723  while ( buffer_size != nullptr )
724  {
725  size += sizeof( buffer_size ) + buffer_size->lenleft;
726  buffer_size = buffer_size->next;
727  }
728  size += 3 * sizeof( PacketThrottler* ) + movementqueue.size() * sizeof( PacketThrottler );
729  if ( gd != nullptr )
730  size += gd->estimatedSize();
731  return size;
732 }
733 }
734 }
#define PKTIN_02_ASYNCHRONOUS
Definition: pktdef.h:82
wallclock_t wallclock()
Definition: wallclock.cpp:31
VersionDetailStruct getversiondetail() const
Definition: client.h:164
bool have_queued_data() const
Definition: client.h:281
std::string version_
Definition: client.h:274
std::atomic< u64 > bytes_sent
Definition: polstats.h:21
#define PKTIN_02_SIZE
Definition: pktdef.h:77
void send_queued_data()
Definition: client.cpp:554
void closeConnection()
Definition: client.cpp:148
void send_remove_character_to_nearby(const Character *chr)
Definition: ufunc.cpp:379
void set_opponent(Character *opponent, bool inform_old_opponent=true)
Definition: charactr.cpp:2994
enum Pol::Network::Client::e_recv_states recv_state
virtual ~Client()
Definition: client.cpp:138
#define INVALID_SOCKET
Definition: wnsckt.h:12
sockaddr ipaddr
Definition: client.h:213
Network::Client * client
Definition: charactr.h:871
std::string fpLog
Definition: client.h:222
Accounts::Account * acct
Definition: client.h:181
std::atomic< int > pause_count
Definition: client.h:231
bool SpeedHackPrevention(bool add=true)
Definition: client.cpp:662
std::tm localtime(const std::time_t &t)
threadsafe version of localtime
Definition: clib.h:143
std::string decint(unsigned short v)
Definition: strutil.cpp:64
size_t thread_pid()
Definition: threadhelp.cpp:107
Client(ClientInterface &aInterface, Crypt::TCryptInfo &encryption)
Definition: client.cpp:73
static const unsigned char restart_pre_encrypted[2]
Definition: client.cpp:611
#define MSGOPT_33_FLOW_PAUSE
Definition: pktdef.h:42
#define THREAD_CHECKPOINT(thread, check)
Definition: polsig.h:48
bool logged_in() const
Definition: charactr.cpp:428
#define POLLOG_ERROR
Definition: logfacility.h:207
unsigned char data[1]
Definition: xbuffer.h:24
static void Delete(Client *client)
Definition: client.cpp:129
XmitBuffer * next
Definition: xbuffer.h:21
void transmit(const void *data, int len, bool needslock=false)
Definition: clientio.cpp:189
Mobile::Character * chr
Definition: client.h:182
void xmit(const void *data, unsigned short datalen)
Definition: client.cpp:486
#define FLEXLOG(id)
Definition: logfacility.h:245
Clib::wallclock_t next_movement
Definition: client.h:262
std::string hexint(unsigned short v)
Definition: strutil.cpp:23
unsigned char buffer[10000]
Definition: UoToolMain.cpp:109
Core::PKTIN_D9 clientinfo_
Definition: client.h:275
void checkpoint(const char *msg, unsigned short minlvl)
Definition: checkpnt.cpp:17
size_t estimatedSize() const
Definition: cgdata.cpp:167
unsigned char pktbuffer[PKTIN_02_SIZE]
Definition: client.h:130
CCryptBase * create_crypt_engine(TCryptInfo &infoCrypt)
Definition: cryptengine.cpp:47
NetworkManager networkManager
Definition: network.cpp:28
std::queue< PacketThrottler > movementqueue
Definition: client.h:261
const char * name() const
Definition: account.cpp:193
int queued_bytes_counter
Definition: client.h:243
ClientInterface & Interface
Definition: client.h:183
unsigned char buffer[MAXBUFFER]
Definition: client.h:208
weak_ptr< Client > getWeakPtr() const
Definition: client.cpp:713
#define socket_errno
Definition: wnsckt.cpp:34
#define SOCKET_ERRNO(x)
Definition: wnsckt.cpp:33
static const unsigned char pause_pre_encrypted[2]
Definition: client.cpp:609
#define POLLOG
Definition: logfacility.h:219
static unsigned int instance_counter_
Definition: client.h:254
Core::XmitBuffer * first_xmit_buffer
Definition: client.h:240
ClientGameData * gd
Definition: client.h:252
u16 langcode[4]
Definition: pktin.h:483
bool encrypt_server_stream
Definition: client.h:217
bool convertUCtoArray(const u16 *in_wtext, Bscript::ObjArray *&out_text, size_t textlen, bool ConvFromBE)
Definition: unicode.cpp:46
u8 unknown2[64]
Definition: pktin.h:484
VersionDetailStruct versiondetail_
Definition: client.h:277
void ClrCharacterWorldPosition(Mobile::Character *chr, Realms::WorldChangeReason reason)
Definition: uworld.cpp:149
static std::mutex _SocketMutex
Definition: client.h:193
bool compareVersion(const std::string &ver)
Definition: client.cpp:340
std::unordered_map< u64, ScriptDiffData > data
Definition: osmod.cpp:966
weak_ptr_owner< Client > weakptr
Definition: client.h:278
SettingsManager settingsManager
Definition: settings.cpp:14
unsigned short lenleft
Definition: xbuffer.h:23
Crypt::CCryptBase * cryptengine
Definition: client.h:215
Character * get_opponent() const
Definition: charactr.cpp:2868
wallclock_diff_t wallclock_diff_ms(wallclock_t start, wallclock_t finish)
Definition: wallclock.cpp:38
u16 video_description[64]
Definition: pktin.h:475
Bscript::BStruct * getclientinfo() const
Definition: client.cpp:230
bool can_speedhack() const
Definition: charactr.cpp:1266
void setClientType(ClientTypeFlag type)
Definition: client.cpp:371
unsigned char last_msgtype
Definition: client.h:256
std::string status() const
Definition: client.cpp:426
std::string ipaddrAsString() const
Definition: clientio.cpp:37
struct Pol::Network::Client::@12 counters
void queue_data(const void *data, unsigned short datalen)
Definition: client.cpp:448
virtual void Encrypt(void *pvIn, void *pvOut, int len)
Definition: cryptbase.h:100
unsigned int wallclock_diff_t
Definition: wallclock.h:9
#define ERROR_PRINT
Definition: logfacility.h:230
Bscript::BObjectImp * make_ref()
Definition: client.cpp:708
size_t estimatedSize() const
Definition: client.cpp:718
virtual std::string name() const
Definition: uobject.cpp:196
std::lock_guard< SpinLock > SpinLockGuard
Definition: spinlock.h:33
Clib::SpinLock _fpLog_lock
Definition: client.h:221
void cancel_trade(Mobile::Character *chr1)
Definition: dropitem.cpp:979
Definition: berror.cpp:12
Core::XmitBuffer * last_xmit_buffer
Definition: client.h:241
#define MSGOPT_33_FLOW_RESTART
Definition: pktdef.h:43
unsigned int instance_
Definition: client.h:253
void deregister_client(Client *client)
Definition: cliface.cpp:49
void register_client(Client *client)
Definition: cliface.cpp:45
unsigned short nsent
Definition: xbuffer.h:22
#define CLOSE_FLEXLOG(id)
Definition: logfacility.h:251
static void itemizeclientversion(const std::string &ver, VersionDetailStruct &detail)
Definition: client.cpp:299