Pol  Revision:cb584c9
packetscrobj.cpp
Go to the documentation of this file.
1 
17 #include "packetscrobj.h"
18 
19 #include <iomanip>
20 #include <stddef.h>
21 
22 #include "../bscript/berror.h"
23 #include "../bscript/bobject.h"
24 #include "../bscript/executor.h"
25 #include "../bscript/impstr.h"
26 #include "../bscript/objmembers.h"
27 #include "../bscript/objmethods.h"
28 #include "../clib/clib_endian.h"
29 #include "../clib/stlutil.h"
30 #include "globals/network.h"
31 #include "mobile/charactr.h"
32 #include "network/client.h"
33 #include "network/clienttransmit.h"
34 #include "realms.h"
35 #include "realms/realm.h"
36 #include "unicode.h"
37 #include "uoexhelp.h"
38 #include "uworld.h"
39 
40 namespace Pol
41 {
42 namespace Core
43 {
44 using namespace Bscript;
45 
46 BPacket::BPacket() : BObjectImp( OTPacket ), is_variable_length( false ) {}
47 BPacket::BPacket( const BPacket& copyfrom )
48  : BObjectImp( OTPacket ),
49  buffer( copyfrom.buffer ),
51 {
52 }
53 BPacket::BPacket( u8 type, signed short length ) : BObjectImp( OTPacket )
54 {
55  if ( length == -1 )
56  {
57  is_variable_length = true;
58  buffer.resize( 1, type );
59  }
60  else
61  {
62  is_variable_length = false;
63  if ( length > 0 )
64  {
65  buffer.resize( length, 0 );
66  buffer[0] = type;
67  }
68  }
69 }
70 BPacket::BPacket( const unsigned char* data, unsigned short length, bool variable_len )
71  : BObjectImp( OTPacket ), buffer( data, data + length )
72 {
73  is_variable_length = variable_len;
74 }
76 
77 BObjectRef BPacket::get_member_id( const int /*id*/ ) // id test
78 {
79  return BObjectRef( new BLong( 0 ) );
80 }
81 BObjectRef BPacket::get_member( const char* membername )
82 {
83  ObjMember* objmember = getKnownObjMember( membername );
84  if ( objmember != nullptr )
85  return this->get_member_id( objmember->id );
86  else
87  return BObjectRef( UninitObject::create() );
88 }
89 
90 BObjectImp* BPacket::call_method_id( const int id, Executor& ex, bool /*forcebuiltin*/ )
91 {
92  switch ( id )
93  {
94  case MTH_SENDPACKET:
95  {
96  if ( ex.numParams() != 1 )
97  return new BError( "SendPacket requires 1 parameter." );
98 
99  Mobile::Character* chr = nullptr;
100  Network::Client* client = nullptr;
101  if ( getCharacterOrClientParam( ex, 0, chr, client ) )
102  {
103  if ( chr != nullptr )
104  {
105  if ( !chr->has_active_client() )
106  return new BLong( 0 );
107 
108  client = chr->client;
109  }
110 
111  if ( client != nullptr )
112  {
113  if ( client->isConnected() )
114  {
115  Core::networkManager.clientTransmit->AddToQueue( client, (void*)( &buffer[0] ),
116  static_cast<int>( buffer.size() ) );
117  return new BLong( 1 );
118  }
119  else
120  return new BLong( 0 );
121  }
122  }
123  break;
124  }
125 
126  case MTH_SENDAREAPACKET:
127  {
128  if ( ex.numParams() != 4 )
129  return new BError( "SendAreaPacket requires 4 parameters." );
130  unsigned short x, y, range;
131  const String* strrealm;
132  if ( ex.getParam( 0, x ) && ex.getParam( 1, y ) && ex.getParam( 2, range ) &&
133  ex.getStringParam( 3, strrealm ) )
134  {
135  Realms::Realm* realm = find_realm( strrealm->value() );
136  if ( !realm )
137  return new BError( "Realm not found" );
138  if ( !realm->valid( x, y, 0 ) )
139  return new BError( "Invalid Coordinates for realm" );
140 
141  unsigned short num_sent_to = 0;
143  x, y, realm, range, [&]( Mobile::Character* chr ) {
144  Core::networkManager.clientTransmit->AddToQueue( chr->client, (void*)( &buffer[0] ),
145  static_cast<int>( buffer.size() ) );
146  num_sent_to++;
147  } );
148  return new BLong( num_sent_to );
149  }
150  break;
151  }
152 
153  case MTH_GETINT8:
154  {
155  if ( ex.numParams() != 1 )
156  return new BError( "GetInt8 requires 1 parameter." );
157  unsigned short offset;
158  if ( ex.getParam( 0, offset ) )
159  {
160  if ( offset >= buffer.size() ) // don't allow getting bytes past end of buffer
161  return new BError( "Offset too high" );
162  u8* data = reinterpret_cast<u8*>( &buffer[offset] );
163  return new BLong( *data );
164  }
165  break;
166  }
167 
168  case MTH_GETINT16:
169  {
170  if ( ex.numParams() != 1 )
171  return new BError( "GetInt16 requires 1 parameter." );
172  unsigned short offset;
173  if ( ex.getParam( 0, offset ) )
174  {
175  if ( offset > buffer.size() - sizeof( u16 ) ) // don't allow getting bytes past end of buffer
176  return new BError( "Offset too high" );
177  u16* data = reinterpret_cast<u16*>( &buffer[offset] );
178  return new BLong( cfBEu16( *data ) );
179  }
180  break;
181  }
182 
183  case MTH_GETINT32:
184  {
185  if ( ex.numParams() != 1 )
186  return new BError( "GetInt32 requires 1 parameter." );
187  unsigned short offset;
188  if ( ex.getParam( 0, offset ) )
189  {
190  if ( offset > buffer.size() - sizeof( u32 ) ) // don't allow getting bytes past end of buffer
191  return new BError( "Offset too high" );
192  u32* data = reinterpret_cast<u32*>( &buffer[offset] );
193  return new BLong( cfBEu32( *data ) );
194  }
195  break;
196  }
197 
198  case MTH_GETINT16FLIPPED:
199  {
200  if ( ex.numParams() != 1 )
201  return new BError( "GetInt16Flipped requires 1 parameter." );
202  unsigned short offset;
203  if ( ex.getParam( 0, offset ) )
204  {
205  if ( offset > buffer.size() - sizeof( u16 ) ) // don't allow getting bytes past end of buffer
206  return new BError( "Offset too high" );
207  u16* data = reinterpret_cast<u16*>( &buffer[offset] );
208  return new BLong( cfLEu16( *data ) );
209  }
210  break;
211  }
212 
213  case MTH_GETINT32FLIPPED:
214  {
215  if ( ex.numParams() != 1 )
216  return new BError( "GetInt32Flipped requires 1 parameter." );
217  unsigned short offset;
218  if ( ex.getParam( 0, offset ) )
219  {
220  if ( offset > buffer.size() - sizeof( u32 ) ) // don't allow getting bytes past end of buffer
221  return new BError( "Offset too high" );
222  u32* data = reinterpret_cast<u32*>( &buffer[offset] );
223  return new BLong( cfLEu32( *data ) );
224  }
225  break;
226  }
227 
228  case MTH_GETSTRING:
229  {
230  if ( ex.numParams() != 2 )
231  return new BError( "GetString requires 2 parameter." );
232  unsigned short offset, len;
233  if ( ex.getParam( 0, offset ) && ex.getParam( 1, len ) )
234  {
235  if ( ( offset >= buffer.size() ) ||
236  ( static_cast<u16>( offset + len ) >
237  buffer.size() ) ) // don't allow getting bytes past end of buffer
238  return new BError( "Offset too high" );
239 
240  const char* str_offset = reinterpret_cast<const char*>( &buffer[offset] );
241  int real_len = 0;
242 
243  // Returns maximum of len characters or up to the first null-byte
244  while ( real_len < len && *( str_offset + real_len ) )
245  real_len++;
246 
247  return new String( str_offset, real_len );
248  }
249  break;
250  }
251 
253  {
254  if ( ex.numParams() != 2 )
255  return new BError( "GetUnicodeString requires 2 parameter." );
256  unsigned short offset, len;
257  if ( ex.getParam( 0, offset ) &&
258  ex.getParam( 1, len ) ) // len is in unicode characters, not bytes
259  {
260  if ( ( offset >= buffer.size() ) ||
261  ( static_cast<u16>( offset + len * 2 ) >
262  buffer.size() ) ) // don't allow getting bytes past end of buffer
263  return new BError( "Offset too high" );
264 
265  ObjArray* arr;
266  Core::convertUCtoArray( reinterpret_cast<u16*>( &buffer[offset] ), arr, len, true );
267  return arr;
268  }
269  break;
270  }
271 
273  {
274  if ( ex.numParams() != 2 )
275  return new BError( "GetUnicodeStringFlipped requires 2 parameter." );
276  unsigned short offset, len;
277  if ( ex.getParam( 0, offset ) &&
278  ex.getParam( 1, len ) ) // len is in unicode characters, not bytes
279  {
280  if ( ( offset >= buffer.size() ) ||
281  ( static_cast<u16>( offset + len * 2 ) >
282  buffer.size() ) ) // don't allow getting bytes past end of buffer
283  return new BError( "Offset too high" );
284 
285  ObjArray* arr;
286  Core::convertUCtoArray( reinterpret_cast<u16*>( &buffer[offset] ), arr, len, false );
287  return arr;
288  }
289  break;
290  }
291 
292  case MTH_GETSIZE:
293  return new BLong( static_cast<int>( buffer.size() ) );
294 
295  case MTH_SETSIZE:
296  {
297  if ( ex.numParams() != 1 )
298  return new BError( "SetSize requires 1 parameter." );
299  unsigned short newsize;
300  if ( ex.getParam( 0, newsize ) )
301  {
302  return SetSize( newsize, true );
303  }
304  break;
305  }
306 
307  case MTH_SETINT8:
308  {
309  if ( ex.numParams() != 2 )
310  return new BError( "SetInt8 requires 2 parameters." );
311  unsigned short offset, value;
312  if ( ex.getParam( 0, offset ) && ex.getParam( 1, value ) )
313  {
314  if ( is_variable_length )
315  if ( offset >= buffer.size() )
316  {
317  if ( !SetSize( ( offset + sizeof( u8 ) ) ) )
318  {
319  return new BError( "Offset value out of range on a fixed length packet" );
320  ;
321  }
322  }
323  buffer[offset] = static_cast<u8>( value );
324  return new BLong( 1 );
325  }
326  break;
327  }
328 
329  case MTH_SETINT16:
330  {
331  if ( ex.numParams() != 2 )
332  return new BError( "SetInt16 requires 2 parameters." );
333  unsigned short offset, value;
334  if ( ex.getParam( 0, offset ) && ex.getParam( 1, value ) )
335  {
336  if ( static_cast<u16>( offset + sizeof( u16 ) ) > buffer.size() )
337  {
338  if ( !SetSize( ( offset + sizeof( u16 ) ) ) )
339  {
340  return new BError( "Offset value out of range on a fixed length packet" );
341  ;
342  }
343  }
344 
345  u16* bufptr = reinterpret_cast<u16*>( &buffer[offset] );
346  *bufptr = ctBEu16( static_cast<u16>( value ) );
347  return new BLong( 1 );
348  }
349  break;
350  }
351 
352  case MTH_SETINT32:
353  {
354  if ( ex.numParams() != 2 )
355  return new BError( "SetInt32 requires 2 parameters." );
356  unsigned short offset;
357  int lvalue;
358  if ( ex.getParam( 0, offset ) && ex.getParam( 1, lvalue ) )
359  {
360  if ( static_cast<u32>( offset + sizeof( u32 ) ) > buffer.size() )
361  {
362  if ( !SetSize( offset + sizeof( u32 ) ) )
363  {
364  return new BError( "Offset value out of range on a fixed length packet" );
365  ;
366  }
367  }
368 
369  u32* bufptr = reinterpret_cast<u32*>( &buffer[offset] );
370  *bufptr = ctBEu32( static_cast<u32>( lvalue ) );
371  return new BLong( 1 );
372  }
373  break;
374  }
375 
376  case MTH_SETINT16FLIPPED:
377  {
378  if ( ex.numParams() != 2 )
379  return new BError( "SetInt16Flipped requires 2 parameters." );
380  unsigned short offset, value;
381  if ( ex.getParam( 0, offset ) && ex.getParam( 1, value ) )
382  {
383  if ( static_cast<u16>( offset + sizeof( u16 ) ) > buffer.size() )
384  {
385  if ( !SetSize( ( offset + sizeof( u16 ) ) ) )
386  {
387  return new BError( "Offset value out of range on a fixed length packet" );
388  ;
389  }
390  }
391 
392  u16* bufptr = reinterpret_cast<u16*>( &buffer[offset] );
393  *bufptr = ctLEu16( static_cast<u16>( value ) );
394  return new BLong( 1 );
395  }
396  break;
397  }
398 
399  case MTH_SETINT32FLIPPED:
400  {
401  if ( ex.numParams() != 2 )
402  return new BError( "SetInt32Flipped requires 2 parameters." );
403  unsigned short offset;
404  int lvalue;
405  if ( ex.getParam( 0, offset ) && ex.getParam( 1, lvalue ) )
406  {
407  if ( static_cast<u32>( offset + sizeof( u32 ) ) > buffer.size() )
408  {
409  if ( !SetSize( ( offset + sizeof( u32 ) ) ) )
410  {
411  return new BError( "Offset value out of range on a fixed length packet" );
412  ;
413  }
414  }
415  u32* bufptr = reinterpret_cast<u32*>( &buffer[offset] );
416  *bufptr = ctLEu32( static_cast<u32>( lvalue ) );
417  return new BLong( 1 );
418  }
419  break;
420  }
421 
422  case MTH_SETSTRING:
423  {
424  if ( ex.numParams() != 3 )
425  return new BError( "SetString requires 3 parameters." );
426  unsigned short offset, nullterm;
427  const String* text;
428  if ( ex.getParam( 0, offset ) && ex.getStringParam( 1, text ) && ex.getParam( 2, nullterm ) )
429  {
430  u16 textlen = static_cast<u16>( text->length() );
431  if ( static_cast<u16>( offset + textlen + nullterm ) > buffer.size() )
432  {
433  if ( !SetSize( ( offset + textlen + nullterm ) ) )
434  {
435  return new BError( "Offset value out of range on a fixed length packet" );
436  ;
437  }
438  }
439 
440  u8* bufptr = reinterpret_cast<u8*>( &buffer[offset] );
441  const char* textptr = text->value().c_str();
442  for ( u16 i = 0; i < textlen; i++ )
443  bufptr[i] = textptr[i];
444 
445  if ( nullterm )
446  bufptr[textlen] = 0;
447 
448  return new BLong( 1 );
449  }
450  break;
451  }
453  {
454  if ( ex.numParams() != 3 )
455  return new BError( "SetUnicodeString requires 3 parameters." );
456  unsigned short offset, nullterm;
457  ObjArray* unitext;
458  if ( ex.getParam( 0, offset ) && ex.getObjArrayParam( 1, unitext ) &&
459  ex.getParam( 2, nullterm ) )
460  {
461  u16 textlen =
462  static_cast<u16>( unitext->ref_arr.size() ); // number of unicode chars, not bytes
463  u16 nulltermlen = nullterm ? 2 : 0;
464  if ( static_cast<u16>( offset + ( textlen * 2 ) + nulltermlen ) > buffer.size() )
465  {
466  if ( !SetSize( ( offset + ( textlen * 2 ) + nulltermlen ) ) )
467  {
468  return new BError( "Offset value out of range on a fixed length packet" );
469  ;
470  }
471  }
472  if ( !Core::convertArrayToUC( unitext, reinterpret_cast<u16*>( &buffer[offset] ), textlen,
473  true, nullterm ? true : false ) )
474  return new BError( "Invalid value in Unicode array." );
475 
476  return new BLong( 1 );
477  }
478  break;
479  }
481  {
482  if ( ex.numParams() != 3 )
483  return new BError( "SetUnicodeStringFlipped requires 3 parameters." );
484  unsigned short offset, nullterm;
485  ObjArray* unitext;
486  if ( ex.getParam( 0, offset ) && ex.getObjArrayParam( 1, unitext ) &&
487  ex.getParam( 2, nullterm ) )
488  {
489  u16 textlen =
490  static_cast<u16>( unitext->ref_arr.size() ); // number of unicode chars, not bytes
491  u16 nulltermlen = nullterm ? 2 : 0;
492  if ( static_cast<u16>( offset + ( textlen * 2 ) + nulltermlen ) > buffer.size() )
493  {
494  if ( !SetSize( ( offset + ( textlen * 2 ) + nulltermlen ) ) )
495  {
496  return new BError( "Offset value out of range on a fixed length packet" );
497  ;
498  }
499  }
500  if ( !Core::convertArrayToUC( unitext, reinterpret_cast<u16*>( &buffer[offset] ), textlen,
501  false, nullterm ? true : false ) )
502  return new BError( "Invalid value in Unicode array." );
503  return new BLong( 1 );
504  }
505  break;
506  }
507  default:
508  return nullptr;
509  }
510  return new BError( "Invalid parameter" );
511 }
512 
513 
514 BObjectImp* BPacket::call_method( const char* methodname, Executor& ex )
515 {
516  ObjMethod* objmethod = getKnownObjMethod( methodname );
517  if ( objmethod != nullptr )
518  return this->call_method_id( objmethod->id, ex );
519  else
520  return nullptr;
521 }
523 {
524  return new BPacket( *this );
525 }
526 std::string BPacket::getStringRep() const
527 {
528  OSTRINGSTREAM os;
529  for ( auto itr = buffer.begin(); itr != buffer.end(); ++itr )
530  os << std::setfill( '0' ) << std::setw( 2 ) << std::hex << static_cast<u16>( *itr );
531 
532  return OSTRINGSTREAM_STR( os );
533 }
534 
535 bool BPacket::SetSize( u16 newsize )
536 {
537  if ( !is_variable_length )
538  return false;
539  // unsigned short oldsize = buffer.size();
540  buffer.resize( newsize );
541  u16* sizeptr = reinterpret_cast<u16*>( &buffer[1] );
542  *sizeptr = ctBEu16( newsize );
543  return true;
544 }
545 
546 BObjectImp* BPacket::SetSize( u16 newsize, bool /*giveReturn*/ )
547 {
548  if ( !is_variable_length )
549  return new BError( "Attempted to resize a fixed length packet" );
550  unsigned short oldsize = static_cast<unsigned short>( buffer.size() );
551  buffer.resize( newsize );
552  u16* sizeptr = reinterpret_cast<u16*>( &buffer[1] );
553  *sizeptr = ctBEu16( newsize );
554  return new BLong( oldsize );
555 }
556 }
557 }
unsigned char u8
Definition: rawtypes.h:25
std::vector< unsigned char > buffer
Definition: packetscrobj.h:42
const std::string & value() const
Definition: impstr.h:67
BObjectType type() const
Definition: bobject.h:358
Network::Client * client
Definition: charactr.h:871
#define ctLEu16(x)
Definition: clib_endian.h:41
#define cfBEu32(x)
Definition: clib_endian.h:43
ObjMember * getKnownObjMember(const char *token)
Definition: parser.cpp:483
virtual Bscript::BObjectImp * call_method(const char *methodname, Bscript::Executor &ex) POL_OVERRIDE
#define ctBEu16(x)
Definition: clib_endian.h:46
bool has_active_client() const
Definition: charactr.cpp:448
#define OSTRINGSTREAM_STR(x)
Definition: stlutil.h:76
static void InRange(u16 x, u16 y, const Realms::Realm *realm, unsigned range, F &&f)
Definition: uworld.h:235
ObjMethod * getKnownObjMethod(const char *token)
Definition: parser.cpp:666
virtual std::string getStringRep() const POL_OVERRIDE
unsigned short u16
Definition: rawtypes.h:26
unsigned int u32
Definition: rawtypes.h:27
bool isConnected() const
Definition: client.h:301
std::unique_ptr< Network::ClientTransmit > clientTransmit
Definition: network.h:97
virtual Bscript::BObjectRef get_member(const char *membername) POL_OVERRIDE
bool getCharacterOrClientParam(Executor &exec, unsigned param, Mobile::Character *&chrptr, Network::Client *&clientptr)
Definition: uoexhelp.cpp:43
NetworkManager networkManager
Definition: network.cpp:28
bool convertArrayToUC(Bscript::ObjArray *&in_text, u16 *out_wtext, size_t textlen, bool ConvToBE, bool nullterm)
Definition: unicode.cpp:21
#define OSTRINGSTREAM
Definition: stlutil.h:75
static UninitObject * create()
Definition: bobject.h:482
size_t numParams() const
Definition: executor.h:145
#define cfBEu16(x)
Definition: clib_endian.h:44
bool convertUCtoArray(const u16 *in_wtext, Bscript::ObjArray *&out_text, size_t textlen, bool ConvFromBE)
Definition: unicode.cpp:46
std::unordered_map< u64, ScriptDiffData > data
Definition: osmod.cpp:966
#define ctBEu32(x)
Definition: clib_endian.h:45
#define cfLEu32(x)
Definition: clib_endian.h:38
#define cfLEu16(x)
Definition: clib_endian.h:39
const String * getStringParam(unsigned param)
Definition: executor.cpp:347
Realms::Realm * find_realm(const std::string &name)
Definition: realms.cpp:64
#define ctLEu32(x)
Definition: clib_endian.h:40
bool valid(unsigned short x, unsigned short y, short z) const
Definition: realm.cpp:119
virtual Bscript::BObjectRef get_member_id(const int id) POL_OVERRIDE
bool getObjArrayParam(unsigned param, ObjArray *&pobjarr)
Definition: executor.cpp:457
bool SetSize(u16 newsize)
Definition: berror.cpp:12
virtual Bscript::BObjectImp * call_method_id(const int id, Bscript::Executor &ex, bool forcebuiltin=false) POL_OVERRIDE
virtual Bscript::BObjectImp * copy() const POL_OVERRIDE
size_t length() const
Definition: impstr.h:68
bool getParam(unsigned param, int &value)
Definition: executor.cpp:363