Initial MSVC 2008 projects workspace

This commit is contained in:
alexey.min
2012-02-01 05:25:08 +00:00
commit 03de3bdc95
1446 changed files with 476853 additions and 0 deletions

View File

@@ -0,0 +1,239 @@
#include "stdafx.h"
#include "ByteArray.h"
#include "../xcpt/L2Packets_xcpt.h"
#ifdef _DEBUG
int ByteArray::_debugPrintf( const char *_Format, ... )
{
if( !this->bDebugMode ) return 0;
if( !_Format ) return 0;
if( !this->fLogFile ) return 0;
va_list args;
int ret = 0;
va_start( args, _Format );
ret = vfprintf( this->fLogFile, _Format, args );
return ret;
}
void ByteArray::setDebugMode( bool bDebug, FILE *flog )
{
if( bDebug && flog )
{
this->bDebugMode = bDebug;
this->fLogFile = flog;
return;
}
if( !bDebug )
{
this->bDebugMode = false;
this->fLogFile = NULL;
}
}
void ByteArray::dumpArrayInfo( FILE * fOut )
{
if( !fOut ) return;
fprintf( fOut, "==== Dump of Array info ====\n" );
fprintf( fOut, " Size: %u\n", this->byteCount );
if( this->byteCount > 0 )
{
unsigned i = 0;
while( i < this->byteCount )
{
fprintf( fOut, "%c:%02X ", this->bytes[i], this->bytes[i] );
i++;
}
}
fprintf( fOut, "\n==== end dump ====\n" );
}
#endif
void ByteArray::_initNull()
{
// data
this->byteCount = 0;
this->bytes = NULL;
// debug mode vars
#ifdef _DEBUG
this->bDebugMode = false;
this->fLogFile = NULL;
#endif
}
void ByteArray::_freeSelf()
{
if( (this->byteCount > 0) && (this->bytes) )
{
free( this->bytes );
this->bytes = NULL;
this->byteCount = 0;
#ifdef _DEBUG
_debugPrintf( "ByteArray::_freeSelf() freeed\n" );
#endif
}
#ifdef _DEBUG
else _debugPrintf( "ByteArray::_freeSelf() nothing to free\n" );
#endif
}
ByteArray::ByteArray()
{
this->_initNull();
}
ByteArray::ByteArray( unsigned int length )
{
this->_initNull();
if( length > 0 ) this->setSize( length );
}
ByteArray::ByteArray( const char *string )
{
this->_initNull();
if( string ) this->setBytesFromString( string );
}
ByteArray::ByteArray( const unsigned char *newBytes, unsigned int length )
{
this->_initNull();
this->setBytes( newBytes, length );
}
ByteArray::ByteArray( const ByteArray& ba )
{
this->_initNull();
this->setBytes( ba.bytes, ba.byteCount );
}
ByteArray::~ByteArray()
{
this->_freeSelf();
#ifdef _DEBUG
_debugPrintf( "ByteArray::~ByteArray() worked\n" );
#endif
}
bool ByteArray::setSize( unsigned int newSize )
{
if( newSize == 0 )
{
this->_freeSelf();
return true;
}
if( newSize == this->byteCount ) return true; // already have that size
if( newSize > 0 )
{
unsigned char *newPtr = (unsigned char *)realloc( this->bytes, newSize );
if( newPtr )
{
this->bytes = newPtr;
this->byteCount = newSize;
return true;
}
#ifdef L2P_THROW
else throw L2P_MemoryError( "ByteArray::setSize()", newSize );
#else
return false;
#endif
}
return false;
}
unsigned char ByteArray::getByteAt( unsigned int index ) const
{
if( (this->byteCount > 0) && (this->bytes) )
{
if( index < (this->byteCount) ) return this->bytes[index];
return 0;
}
#ifdef L2P_THROW
throw L2P_ReadException( "ByteArray::getByteAt()", 1, (int)index, (int)byteCount );
#else
return 0;
#endif
}
unsigned char ByteArray::setByteAt( unsigned int index, unsigned char byteSet )
{
if( (this->byteCount > 0) && (this->bytes) )
{
unsigned char retVal = 0;
if( index < (this->byteCount) )
{
retVal = this->bytes[index];
this->bytes[index] = byteSet;
}
#ifdef L2P_THROW
else throw L2P_WriteException( "ByteArray::setByteAt()", 1, (int)index, (int)byteCount );
#endif
return retVal;
}
else
{
#ifdef L2P_THROW
throw L2P_WriteException( "ByteArray::setByteAt()", 1, (int)index, (int)byteCount );
#else
return 0;
#endif
}
}
void ByteArray::memset( unsigned char c )
{
if( (this->byteCount > 0) && (this->bytes) )
{
/*unsigned int i = 0;
while( i < this->byteCount )
this->bytes[i++] = c;*/
::memset( this->bytes, c, this->byteCount );
}
}
bool ByteArray::setBytes( const unsigned char *newBytes, unsigned int length )
{
if( length < 1 ) return false;
//unsigned int i = 0;
//
//printf( "ByteArray::setBytes( 0x%p, %u )\n", newBytes, length );
//printf( "ByteArray::setBytes(): %u < %u?\n", this->byteCount, length );
//
// check if it is enough space in 'bytes' now
if( this->byteCount < length ) // not enough
{
// we should try to grow to required size
if( !this->setSize( length ) ) return false; // growing failed :(
}
// if we're here, space in 'bytes' buffer is enough to hold 'length' bytes
this->memset( 0x00 );
//while( i < length ) this->bytes[i] = newBytes[i++];
memcpy( this->bytes, newBytes, length );
//printf( "ByteArray::setBytes(): %u bytes set OK (buffer len %u)\n", length, this->byteCount );
return true;
}
bool ByteArray::setBytesFromString( const char *string )
{
if( !string ) return false;
unsigned int str_len = strlen( string );
if( str_len < 1 ) return false;
return this->setBytes( (const unsigned char *)string, str_len );
}
bool ByteArray::setBytesFromPtrNoMemcpy( unsigned char *bytes, unsigned int length )
{
if( !bytes || (length<1) ) return false;
this->byteCount = length;
this->bytes = bytes;
return true;
}
unsigned char ByteArray::operator[]( int index ) const
{
if( (this->byteCount > 0) && (this->bytes) )
{
if( (index>=0) && (index<((int)(this->byteCount))) ) return this->bytes[index];
return 0;
}
return 0;
}

111
l2packets/base/ByteArray.h Normal file
View File

@@ -0,0 +1,111 @@
#ifndef H_BYTEARRAY
#define H_BYTEARRAY
/** \class ByteArray
* Represents array of bytes with variable size.\n
* L2Packets programmer does not work with ByteArray directly.
* This object is used inside L2BasePacket to hold raw packet data bytes.
*/
class ByteArray
{
public: // constructors/destructors
/** Default constructor with zero array length */
ByteArray();
/** Constructs ByteArray object with specified array length
* \param length - size in bytes to reserve space
*/
ByteArray( unsigned int length );
/** Constructs ByteArray object with length equal to length of string \n
* and with contents of this string. \n
* Calls setBytesFromString( string );
* \param string - string from which to set contents of created ByteArray
*/
ByteArray( const char *string );
/** Copy constructor */
ByteArray( const ByteArray& ba );
/** Constructs ByteArray object and sets its size and contents.
* \param newBytes pointer to data to set contents
* \param length data size
*/
ByteArray( const unsigned char *newBytes, unsigned int length );
~ByteArray();
public: // size funcs
/** \return Current array size. */
inline unsigned int getSize() const { return this->byteCount; }
/** sets new size of buffer. Contents remain unchanged (but may be truncated). \n
* In general, calls C runtime realloc()\n
* May throw L2P_MemoryError exception, if enabled.
* \param newSize new size of buffer. Must be >= 0
*/
bool setSize( unsigned int newSize );
public: // data functions
/** \return pointer to internal data buffer */
inline unsigned char *getBytesPtr() const { return this->bytes; }
/** Get byte value at specified index.\n
* May throw L2P_ReadException, if enabled.
* \param index Index of byte to retreive. If index is out of array bounds, function returns zero.
* \return byte alue at index, or 0 if index does not belong to array.
*/
unsigned char getByteAt( unsigned int index ) const;
/** Sets byte at specified index.\n
* May throw L2P_WriteException, if enabled.
* \param index Byte index to set. If index does not belong to array, function does nothing.
* \param byteSet new byte value
* \return previous byte value */
unsigned char setByteAt( unsigned int index, unsigned char byteSet );
/** Fills array with specified byte value.
* \param c value to assign to all bytes. */
void memset( unsigned char c );
/** Sets all array contents. Data is copied to internal storage
* \param newBytes data to set.
* \param length length of data. If length is > current array length, function resizes array to fit contents.
* \return true, if set was ok. false, if there were errors (memory failure?)
*/
bool setBytes( const unsigned char *newBytes, unsigned int length );
/** Sets array data from string data. Terminating zero is not appended.
* \param string string from which to copy bytes.
* \return true/false */
bool setBytesFromString( const char *string );
/** Sets internal pointer to data buffer and internal bytes counter from specified pointer to data and size.\n
* Data is not copied (works much faster)\n
* This function is not recommended to use, because:\n
* WARNING! buffer must be allocated by the same C runtime as library uses - malloc(), realloc(), calloc(). \n
* WARNING! object frees its buffer when destructor executes, so, free() will be called for source buffer.
* \param bytes data to set.
* \param length length of data. If length is > current array length, function resizes array to fit contents.
* \return true, if set was ok.*/
bool setBytesFromPtrNoMemcpy( unsigned char *bytes, unsigned int length );
public: // operators
/** Calls getByteAt( index ) */
unsigned char operator[]( int index ) const;
protected: // internal functions
void _initNull();
void _freeSelf();
// debug functions
#ifdef _DEBUG
public:
void setDebugMode( bool bDebug, FILE *flog );
int _debugPrintf( const char *_Format, ... );
void dumpArrayInfo( FILE * fOut );
#endif
protected:
// data
unsigned int byteCount; ///< internal array size counter
unsigned char *bytes; ///< internal pointer to allocated buffer
// debug mode vars
#ifdef _DEBUG
bool bDebugMode;
FILE *fLogFile;
#endif
};
#endif

View File

@@ -0,0 +1,650 @@
#include "stdafx.h"
#include "L2BasePacket.h"
#include "../xcpt/L2Packets_xcpt.h"
L2BasePacket::L2BasePacket()
{
this->_initNull();
}
L2BasePacket::L2BasePacket( const unsigned char *bytes, unsigned int length )
{
this->_initNull();
this->setBytes( bytes, length );
}
L2BasePacket::~L2BasePacket()
{
_freeSelf();
}
bool L2BasePacket::setBytes( const unsigned char *bytes, unsigned int length )
{
_initNull();
if( !bytes || (length < 2) ) return false;
//
//printf( "L2BasePacket::setBytes( 0x%p, %u )\n", bytes, length );
//
this->ensureCanWriteBytes( length );
bool ret = this->b.setBytes( bytes, length );
if( ret )
{
this->buffer_size = b.getSize();
this->real_size = length;
this->datasize = length - 2; // length always >= 2 here
this->write_ptr = length;
this->read_ptr = 2;
// should we update packet size field in packet (0,1 bytes) here?, YES, imo
this->b.setByteAt( 0, (unsigned char)((length) & 0xff) );
this->b.setByteAt( 1, (unsigned char)((length >> 8) & 0xff) );
}
return ret;
}
bool L2BasePacket::setBytesPtr( unsigned char *bytes, unsigned int length )
{
if( !bytes || (length < 2) ) return false;
if( this->b.setBytesFromPtrNoMemcpy( bytes, length ) )
{
this->buffer_size = b.getSize();
this->real_size = length;
this->datasize = length - 2;
this->write_ptr = length;
this->read_ptr = 2;
// should we update packet size field in packet (0,1 bytes) here?, YES, imo
this->b.setByteAt( 0, (unsigned char)((length) & 0xff) );
this->b.setByteAt( 1, (unsigned char)((length >> 8) & 0xff) );
return true;
}
return false;
}
void L2BasePacket::setPacketType( unsigned char type )
{
writeReset();
writeUChar( type );
}
void L2BasePacket::setPacketType2( unsigned char opcode, unsigned short opcode2 )
{
writeReset();
writeUChar( opcode );
writeUShort( opcode2 );
}
void L2BasePacket::setPacketType3( unsigned char opcode, unsigned short opcode2, unsigned short opcode3 )
{
writeReset();
writeUChar( opcode );
writeUShort( opcode2 );
writeUShort( opcode3 );
}
/*unsigned char L2BasePacket::getPacketType()
{
readReset();
return readUChar();
}*/
/*unsigned short L2BasePacket::getPacketSize() const
{
return (unsigned short)(this->real_size);
}*/
/*unsigned short L2BasePacket::getDataSize() const// number of DATA bytes in packet
{
return (unsigned short)(this->datasize);
}*/
bool L2BasePacket::ensureCanWriteBytes( unsigned int nBytes )
{
if( nBytes == 0 ) return true;
unsigned int end_ptr = write_ptr + nBytes - 1; // calc write end pointer
// loop until end_ptr fits in buffer size
while( end_ptr >= buffer_size ) // not enough place in buffer
{
if( !this->_growBuffer() ) return false; // _growBuffer() increases buffer_size
}
return true;
}
void L2BasePacket::writeChar( char c )
{
if( !this->ensureCanWriteBytes( 1 ) ) return; // TODO: Throw exception??
this->b.setByteAt( this->write_ptr, (unsigned char)c );
this->write_ptr++;
this->real_size++;
this->datasize++;
// update packet size
// 1st 2 bytes contain only DATA size? no IMO
unsigned short psize = (unsigned short)real_size;
//unsigned short psize = (unsigned short)datasize;
unsigned char *psaddr = (unsigned char *)&psize;
b.setByteAt( 0, psaddr[0] );
b.setByteAt( 1, psaddr[1] );
}
void L2BasePacket::writeUChar( unsigned char c )
{
if( !this->ensureCanWriteBytes( 1 ) ) return; // TODO: Throw exception??
//printf( "L2BasePacket::writeUChar(): writing [0x%02X] at idx [%d]\n",
// (unsigned int)c, this->write_ptr );
this->b.setByteAt( this->write_ptr, c );
this->write_ptr++;
this->real_size++;
this->datasize++;
// update packet size
unsigned short psize = (unsigned short)real_size;
unsigned char *psaddr = (unsigned char *)&psize;
b.setByteAt( 0, psaddr[0] );
b.setByteAt( 1, psaddr[1] );
}
void L2BasePacket::writeBytes( const unsigned char *bytes, unsigned int len )
{
if( !bytes || (len<1) ) return;
unsigned int i;
for( i=0; i<len; i++ ) this->writeUChar( bytes[i] );
}
void L2BasePacket::writeShort( short int s )
{
char leftByte = (char)(s & 0x00FF);
char rightByte = (char)( (s & 0xFF00) >> 8 );
this->writeChar( leftByte );
this->writeChar( rightByte );
}
void L2BasePacket::writeUShort( unsigned short int s )
{
unsigned char leftByte = (unsigned char)( s & (unsigned short)0x00FF);
unsigned char rightByte = (unsigned char)( (s & (unsigned short)0xFF00) >> 8 );
this->writeUChar( leftByte );
this->writeUChar( rightByte );
}
void L2BasePacket::writeInt( int i )
{
char b1 = (char)( i & (int)0x000000FF);
char b2 = (char)( (i & (int)0x0000FF00) >> 8 );
char b3 = (char)( (i & (int)0x00FF0000) >> 16 );
char b4 = (char)( (i & (int)0xFF000000) >> 24 );
this->writeChar( b1 );
this->writeChar( b2 );
this->writeChar( b3 );
this->writeChar( b4 );
}
void L2BasePacket::writeUInt( unsigned int i )
{
unsigned char b1 = (unsigned char)( i & (unsigned int)0x000000FF);
unsigned char b2 = (unsigned char)( (i & (unsigned int)0x0000FF00) >> 8 );
unsigned char b3 = (unsigned char)( (i & (unsigned int)0x00FF0000) >> 16 );
unsigned char b4 = (unsigned char)( (i & (unsigned int)0xFF000000) >> 24 );
this->writeUChar( b1 );
this->writeUChar( b2 );
this->writeUChar( b3 );
this->writeUChar( b4 );
}
void L2BasePacket::writeInt64( long long int i64 )
{
char *i64b = (char *)(&i64);
unsigned int i;
for( i=0; i<sizeof(long long int); i++ ) this->writeChar( i64b[i] );
}
void L2BasePacket::writeUInt64( unsigned long long int i64 )
{
unsigned char *i64b = (unsigned char *)(&i64);
unsigned int i;
for( i=0; i<sizeof(unsigned long long int); i++ ) this->writeUChar( i64b[i] );
}
void L2BasePacket::writeDouble( double d )
{
char *pd = (char *)(&d);
unsigned int i;
for( i=0; i<sizeof(double); i++ ) this->writeChar( pd[i] );
}
void L2BasePacket::writeString( const char *str )
{
if( !str ) return;
char *p = (char *)str;
while( (*p) )
{
this->writeChar( (*p) );
p++;
}
this->writeChar( 0 );
}
void L2BasePacket::writeUnicodeString( const wchar_t *ustr )
{
if( !ustr ) return;
wchar_t *p = (wchar_t *)ustr;
while( (*p) )
{
this->writeShort( (*p) );
p++;
}
this->writeShort( 0x0000 );
}
bool L2BasePacket::canReadBytes( unsigned int nBytes )
{
if( nBytes == 0 ) return true;
unsigned int end_ptr = read_ptr + nBytes;
if( end_ptr <= real_size ) return true;
return false;
}
char L2BasePacket::readChar()
{
if( !canReadBytes( 1 ) )
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::readChar()", 1, (int)read_ptr, (int)real_size );
#else
return 0;
#endif
char ret = b.getByteAt( read_ptr );
read_ptr++;
return ret;
}
unsigned char L2BasePacket::readUChar()
{
if( !canReadBytes( 1 ) )
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::readUChar()", 1, (int)read_ptr, (int)real_size );
#else
return 0;
#endif
unsigned char ret = b.getByteAt( read_ptr );
read_ptr++;
return ret;
}
bool L2BasePacket::readBytes( unsigned char *bytes, unsigned int num )
{
if( !bytes || (num<1) ) return false;
unsigned int i;
for( i=0; i<num; i++ ) bytes[i] = this->readUChar();
return true;
}
short int L2BasePacket::readShort()
{
if( canReadBytes( 2 ) )
{
unsigned char c1 = readChar();
unsigned char c2 = readChar();
unsigned short int ret = ((unsigned short int)c1) | ((unsigned short int)c2 << 8);
return ret;
}
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::readShort()", 2, (int)read_ptr, (int)real_size );
#else
return 0;
#endif
}
unsigned short int L2BasePacket::readUShort()
{
if( canReadBytes( 2 ) )
{
unsigned char c1 = readUChar();
unsigned char c2 = readUChar();
unsigned short int ret = ((unsigned short int)c1) | ((unsigned short int)c2 << 8);
return ret;
}
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::readUShort()", 2, (int)read_ptr, (int)real_size );
#else
return 0;
#endif
}
int L2BasePacket::readInt()
{
if( canReadBytes( 4 ) )
{
unsigned char c1 = readChar();
unsigned char c2 = readChar();
unsigned char c3 = readChar();
unsigned char c4 = readChar();
unsigned int ret = (unsigned int)c1;
ret |= ( (unsigned int)c2 << 8 );
ret |= ( (unsigned int)c3 << 16 );
ret |= ( (unsigned int)c4 << 24 );
return ret;
}
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::readInt()", 4, (int)read_ptr, (int)real_size );
#else
return 0;
#endif
}
unsigned int L2BasePacket::readUInt()
{
if( canReadBytes( 4 ) )
{
unsigned char c1 = readChar();
unsigned char c2 = readChar();
unsigned char c3 = readChar();
unsigned char c4 = readChar();
unsigned int ret = (unsigned int)c1;
ret |= ( (unsigned int)c2 << 8 );
ret |= ( (unsigned int)c3 << 16 );
ret |= ( (unsigned int)c4 << 24 );
return ret;
}
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::readUInt()", 4, (int)read_ptr, (int)real_size );
#else
return 0;
#endif
}
long long int L2BasePacket::readInt64()
{
long long int ret = 0;
if( this->canReadBytes( 8 ) )
{
unsigned int i;
unsigned char c = 0;
unsigned char *retaddr = (unsigned char *)&ret;
for( i=0; i<sizeof(long long int); i++ )
{
c = readChar();
(*retaddr) = c;
retaddr++;
}
return ret;
}
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::readInt64()", 8, (int)read_ptr, (int)real_size );
#else
return 0;
#endif
}
unsigned long long int L2BasePacket::readUInt64()
{
unsigned long long int ret = 0;
if( this->canReadBytes( 8 ) )
{
unsigned int i;
unsigned char c = 0;
unsigned char *retaddr = (unsigned char *)&ret;
for( i=0; i<sizeof(unsigned long long int); i++ )
{
c = readUChar();
(*retaddr) = c;
retaddr++;
}
return ret;
}
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::readUInt64()", 8, (int)read_ptr, (int)real_size );
#else
return 0;
#endif
}
double L2BasePacket::readDouble()
{
double ret = 0.0;
if( canReadBytes( 8 ) )
{
unsigned int i = 0;
unsigned char c = 0;
unsigned char *retaddr = (unsigned char *)&ret;
for( i=0; i<sizeof(double); i++ )
{
c = readChar();
(*retaddr) = c;
retaddr++;
}
return ret;
}
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::readDouble()", 8, (int)read_ptr, (int)real_size );
#else
return 0.0;
#endif
}
char *L2BasePacket::readString()
{
unsigned int save_read_ptr = this->read_ptr;
unsigned int str_len = 0;
char c = 0;
char *str = NULL;
// count string length (including terminating 0x00 byte)
while( this->canReadBytes(1) )
{
c = this->readChar();
str_len++;
if( c == 0 ) break;
}
// restore read_ptr
this->read_ptr = save_read_ptr;
// assert
if( str_len == 0 ) return NULL;
// allocate buffer
str = (char *)malloc( str_len+1 ); // +1 for additional safety
if( !str ) return NULL;
str[str_len] = 0x00;
// read bytes to buffer
if( this->readBytes( (unsigned char *)str, str_len ) ) return str;
// some error? O_o
free( str );
str = NULL;
return NULL;
}
// returns allocated by malloc() buffer. must be freed later by caller!
wchar_t *L2BasePacket::readUnicodeString()
{
unsigned int save_read_ptr = this->read_ptr;
unsigned int str_len = 0;
unsigned int buffer_len = 0;
unsigned short int c = 0;
wchar_t *wstr = NULL;
// count string length (including terminating 0x0000 word)
while( this->canReadBytes(2) )
{
c = this->readUShort();
str_len++;
buffer_len += 2;
if( c == 0x0000 ) break;
}
// restore read_ptr
this->read_ptr = save_read_ptr;
// assert
if( str_len == 0 ) return NULL;
// allocate buffer
wstr = (wchar_t *)malloc( buffer_len+2 ); // +2 for more safety
if( !wstr ) return NULL;
wstr[str_len] = 0x0000;
// read bytes to buffer
if( this->readBytes( (unsigned char *)wstr, buffer_len ) ) return wstr;
// some error? O_o
free( wstr );
wstr = NULL;
return NULL;
}
// returns read-only pointer to wchar_t inside packet.
const wchar_t *L2BasePacket::readUnicodeStringPtr()
{
//unsigned int str_len = 0;
unsigned short int ch = 0;
// we return poiter to internal buffer
wchar_t *wstr = (wchar_t *)( this->getBytesPtr() + this->read_ptr );
// count string length (including terminating 0x0000 word), also moving current read_ptr
while( this->canReadBytes(2) )
{
ch = this->readUShort();
//str_len++;
//buffer_len += 2;
if( ch == 0x0000 ) break;
}
//wstr += str_len; // add counted string length to returned ptr
return wstr;
}
void L2BasePacket::writeReset()
{
write_ptr = 2; // pass 1st 2 bytes - packet size
real_size = 2; // think that only 2 bytes written
read_ptr = 2; // cannot read more than written :)
datasize = 0;
_preAllocateBuffer();
// update packet size field
b.setByteAt( 0, 2 );
b.setByteAt( 1, 0 );
}
void L2BasePacket::readReset()
{
read_ptr = 2; // pass 1st 2 bytes - packet size
}
bool L2BasePacket::_preAllocateBuffer()
{
if( !b.setSize( buffer_size ) ) return false; // TODO: or throw exception?
return true;
}
bool L2BasePacket::_growBuffer()
{
buffer_size *= 2;
return _preAllocateBuffer();
}
void L2BasePacket::_initNull()
{
buffer_size = 256;
datasize = 0;
writeReset();
readReset();
}
void L2BasePacket::_freeSelf()
{
buffer_size = 256;
writeReset();
readReset();
}
void L2BasePacket::dumpToFile( FILE *f )
{
if( !f ) return;
fprintf( f, "L2BasePacket::dumpToFile() begin\n" );
fprintf( f, "-- read_ptr : %u\n", this->read_ptr );
fprintf( f, "-- write_ptr : %u\n", this->write_ptr );
fprintf( f, "-- buffer_size : %u\n", this->buffer_size );
fprintf( f, "-- real_size : %u\n", this->real_size );
unsigned int psize = (unsigned int)(this->b[0]) |
( ((unsigned int)this->b[1]) << 8 );
fprintf( f, "-- Packet size : %u (%02X %02X)\n", psize, this->b[0], this->b[1] );
if( this->real_size > 2 )
{
fprintf( f, "-- Packet type : %u (%02X)\n", this->b.getByteAt( 2 ), this->b[2] );
fprintf( f, "-- ByteArray b :\n" );
unsigned int i = 0;
for( i=0; i<this->real_size; i++ )
fprintf( f, "%02X ", this->b[i] );
fprintf( f, "\n" );
}
fprintf( f, "L2BasePacket::dumpToFile() end\n\n" );
}
void L2BasePacket::saveToFileRaw( const char *filename )
{
if( !filename ) return;
FILE *f = fopen( filename, "wb" );
if( !f ) return;
fprintf( f, "L2BasePacket::dumpToFile() begin\r\n" );
fprintf( f, "-- read_ptr : %u\r\n", this->read_ptr );
fprintf( f, "-- write_ptr : %u\r\n", this->write_ptr );
fprintf( f, "-- buffer_size : %u\r\n", this->buffer_size );
fprintf( f, "-- real_size : %u\r\n", this->real_size );
unsigned int psize = this->b[0] + (this->b[1] << 8);
fprintf( f, "-- Packet size : %u (%02X %02X)\r\n", psize, this->b[0], this->b[1] );
if( this->real_size > 2 )
{
unsigned char *bytes = b.getBytesPtr();
unsigned int count = b.getSize();
fwrite( bytes, 1, count, f );
}
fprintf( f, "L2BasePacket::dumpToFile() end\n\n" );
fclose( f );
}
void L2BasePacket::displaySelfNice( FILE *f )
{
this->dumpToFile( f );
}
unsigned char L2BasePacket::getByteAt( unsigned int index )
{
if( index >= real_size )
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::getByteAt()", 1, (int)index, (int)real_size );
#else
return 0;
#endif
char c = b.getByteAt( index );
return c;
}
unsigned char L2BasePacket::setByteAt( unsigned int index, unsigned char byte )
{
// checks are inside of ByteArray::setByteAt() (throwing exceptions if enabled)
return b.setByteAt( index, byte );
}
inline const unsigned char *L2BasePacket::getBytesPtr() const
{
return b.getBytesPtr();
}
/*L2BasePacket::operator const unsigned char *() const
{
return this->getBytesPtr();
}*/
ByteArray *L2BasePacket::readB( unsigned int count )
{
ByteArray *pByteArray = new ByteArray();
if( !pByteArray ) return NULL;
pByteArray->setSize( count );
if( this->readBytes( pByteArray->getBytesPtr(), count ) ) return pByteArray;
delete pByteArray;
#ifdef L2P_THROW
throw L2P_ReadException( "L2BasePacket::readB()", (int)count, (int)read_ptr, (int)real_size );
#else
return NULL;
#endif
}
// must be overrided in child classes
bool L2BasePacket::parse( L2_VERSION ver )
{
UNREFERENCED_PARAMETER(ver);
this->readReset();
this->readUChar();
return true;
}
// must be overrided in child classes
bool L2BasePacket::create( L2_VERSION ver )
{
UNREFERENCED_PARAMETER(ver);
this->writeReset();
return true;
}

View File

@@ -0,0 +1,284 @@
#ifndef H_L2BASEPACKET
#define H_L2BASEPACKET
#include "ByteArray.h"
#include "../L2_versions.h"
#ifndef UNREFERENCED_PARAMETER
#define UNREFERENCED_PARAMETER(x) // will produce compiler warnings, anyway
#endif
/** \class L2BasePacket
* Represents base class for all L2 packets. Provides way to create packets,
* write data to packets, read data from them.\n
* Internally uses ByteArray object to hold raw packet data bytes.
* Allows writing data/reading data from packet, using readXXXX or writeXXXX functions.\n
* \n
* In Lineage protocol, all packets start with 2 bytes, which hold all packet length (including these first 2 bytes).
* These 2 bytes are never encrypted, so client application receives first 2 bytes,
* treates them as packet length and then reads the rest length-2 bytes.\n
* \n
* L2BasePacket internally uses ByteArray object to hold packet data. Initially created L2BasePacket object
* has preallocated space for 256 bytes in its internal storage (ByteArray::setSize(256)), so most write
* operations do not cause packet to grow. If 256 bytes is not enough, L2BasePacket automatically doubles
* size of its internal buffer, and so on.\n
* \n
* \n
*<pre>
* Lineage II packet structure:\n
* Size field packet data
* |----------------------|--------------------------|
* | low byte | high byte | opcode | ... ... ... ... |
* |----------------------|--------------------------|
* 0 1 2 3 .......... << byte ordinal numbers
* </pre>
* \n
* Size field is 16-bit integer, defines size of ALL packet, including size field itself. So,
* maximum length of L2 packet is 65536 bytes (maximum data size is 65534).
*/
class L2BasePacket
{
public:
/** Default constructor for empty packet. Preallocates buffer size for 256 bytes. */
L2BasePacket();
/** Copies length bytes to packet */
L2BasePacket( const unsigned char *bytes, unsigned int length ); // does memcpy()
/** Frees object memory */
virtual ~L2BasePacket();
public:
/** Reads byte at index from internal storage. Calls ByteArray::getByteAt()\n
* May throw L2P_ReadException in case of range error.
\param index - byte index to read
\return byte value, or 0 if index is out of range.
*/
virtual unsigned char getByteAt( unsigned int index );
/** Sets byte at specified index to value. Does nothing if index out of bounds. Calls ByteArray::setByteAt()\n
* May throw L2P_WriteException in case of range error.
* \param index byte index
* \param byte byte value to set
* \return previous byte value
*/
virtual unsigned char setByteAt( unsigned int index, unsigned char byte );
/** Copies bytes to internal storage buffer. Resizes internal buffer if needed. Calls ByteArray::setBytes()
* \param bytes pointer to source data buffer to copy from
* \param length source buffer size
* \return success state
*/
virtual bool setBytes( const unsigned char *bytes, unsigned int length );
/** Sets internal ByteArray's buffer pointer to [bytes], and length to [length]. Does no memcpy()\n
* Do not use this function!
* \param bytes pointer to new data buffer
* \param length source buffer size
* \return success state
* \see ByteArray::setBytesFromPtrNoMemcpy() */
virtual bool setBytesPtr( unsigned char *bytes, unsigned int length );
/** Sets 3rd byte of packet (which holds packet opcode).
* Equivalent to call writeReset() and writeUChar() with parameter type.
* Moves write pointer to byte #3 (next after opcode)
* \param type new packet opcode. */
virtual void setPacketType( unsigned char type );
/** Sets 3rd,4th,5th bytes of packet (which holds packet opcode and extended opcode).
* Equivalent to call writeReset(); writeUChar(); writeUShort() with parameter type.
* Moves write pointer!
* \param opcode new packet opcode.
* \param opcode2 extended opcode. */
virtual void setPacketType2( unsigned char opcode, unsigned short opcode2 );
/** Sets 3rd,4th,5th,6th,7th bytes of packet (which holds packet opcode, ext opcode, ext opcode 2).
* Equivalent to call writeReset(); writeUChar(); writeUShort() writeUShort() with parameter type.
* Moves write pointer!
* \param opcode new packet opcode.
* \param opcode2 extended opcode.
* \param opcode3 extended opcode 2.
*/
virtual void setPacketType3( unsigned char opcode, unsigned short opcode2, unsigned short opcode3 );
/** Reads packet opcode. Moves read pointer to byte #3 (next after opcode). Equivalent calls: readReset(); readUChar()
* \return read packet opcode. */
virtual unsigned char getPacketType() { readReset(); return readUChar(); }
/** Gets packet length in bytes (not size of internal data buffer, which is larger)
* \return packet lentgh */
virtual unsigned short getPacketSize() const { return (unsigned short)(this->real_size); }
/** Gets number of data bytes in packet (excluding 1st 2 bytes, which hold all packet size).
* Equivalent to getPacketSize()-2.
* \return number of <b>data</b> bytes in buffer. */
virtual unsigned short getDataSize() const { return (unsigned short)(this->datasize); }
public: // write funcs
// All of read/write funcs can throw subclasses of L2P_Exception in case of read/write errors.
/** Checks if it is possible to write nBytes bytes to packet; if no, tries to increase buffer size.
* Called automatically from write-functions.
* \param nBytes checked size
* \return false on memory error */
virtual bool ensureCanWriteBytes( unsigned int nBytes );
/** Moves write pointer to the beginning of the packet, to byte #2, where starts opcode.
* First 2 bytes (byte #0, byte #1 - packet size) are always updated automatically, and
* they cannot be accessed by read/write-functions, only by setByteAt() / getByteAt().
* Pre-allocates internal buffer, sets packet size to 2. */
virtual void writeReset();
/** Writes single byte to packet. Moves write pointer one char right
* \param c byte to write to packet. */
virtual void writeChar( char c );
/** Writes single byte to packet. Moves write pointer one char right
* \param c byte to write to packet. */
virtual void writeUChar( unsigned char c );
/** Writes short integer to packet. Moves write pointer two chars right
* \param s value to write to packet. */
virtual void writeShort( short int s );
/** Writes short integer to packet. Moves write pointer two chars right
* \param s value to write to packet. */
virtual void writeUShort( unsigned short int s );
/** Writes 32-bit integer to packet. Moves write pointer 4 chars right
* \param i value to write to packet. */
virtual void writeInt( int i );
/** Writes 32-bit integer to packet. Moves write pointer 4 chars right
* \param i value to write to packet. */
virtual void writeUInt( unsigned int i );
/** Writes 64-bit integer to packet. Moves write pointer 8 chars right
* \param i64 value to write to packet. */
virtual void writeInt64( long long int i64 );
/** Writes 64-bit integer to packet. Moves write pointer 8 chars right
* \param i64 value to write to packet. */
virtual void writeUInt64( unsigned long long int i64 );
/** Writes double value to packet. Moves write pointer 8 chars right
* \param d value to write to packet. */
virtual void writeDouble( double d );
/** Writes ANSI string to packet, also NULL terminator. Moves write pointer right by string length
* \param str string to write to packet. */
virtual void writeString( const char *str );
/** Writes Unicode string to packet, also Unicode NULL terminator. Moves write pointer right by string length*2
* \param ustr string to write to packet. */
virtual void writeUnicodeString( const wchar_t *ustr );
/** Writes bytes array to packet (len bytes). Moves write pointer right by len bytes
* \param bytes pointer to data to write to packet.
* \param len data length. */
virtual void writeBytes( const unsigned char *bytes, unsigned int len );
public: // read funcs
// All of read/write funcs can throw subclasses of L2P_Exception in case of read/write errors.
/** Checks if there are some bytes left to read form current read position in packet.
* \param nBytes number of bytes to test to readability.
* \return true, if nBytes bytes can be read form current read position; false if there are less than
* nBytes left in buffer. */
virtual bool canReadBytes( unsigned int nBytes );
/** Moves read pointer to byte #2 (opcode will be read next). */
virtual void readReset();
/** Reads one byte from packet. Moves read pointer to next position
* \return byte */
virtual char readChar();
/** Reads one byte from packet. Moves read pointer to next position
* \return byte */
virtual unsigned char readUChar();
/** Reads 16-bit integer from packet. Moves read pointer to next position
* \return short int */
virtual short int readShort();
/** Reads 16-bit integer from packet. Moves read pointer to next position
* \return short int */
virtual unsigned short int readUShort();
/** Reads 32-bit integer from packet. Moves read pointer to next position
* \return int */
virtual int readInt();
/** Reads 32-bit integer from packet. Moves read pointer to next position
* \return int */
virtual unsigned int readUInt();
/** Reads 64-bit integer from packet. Moves read pointer to next position
* \return long long int */
virtual long long int readInt64();
/** Reads 64-bit integer from packet. Moves read pointer to next position
* \return long long int */
virtual unsigned long long int readUInt64();
/** Reads double value from packet. Moves read pointer to next position
* \return double */
virtual double readDouble();
/** Reads ANSI string from packet. Moves read pointer to next read position
* \return pointer to allocated string */
virtual char *readString();
/** Reads Unicode string from packet. Moves read pointer to next read position. Allocates buffer.
* \return pointer to allocated string. Calling function must free() this buffer. */
virtual wchar_t *readUnicodeString();
/** Reads Unicode string from packet. Moves read pointer to next read position.\n
* Function does not allocate buffer,
* it just returns casted to (wchar_t *) pointer to internal data buffer as read-only.\n
* Warning! Returning pointer will be invalid, because internal data buffer is freed when object is destroyed.\n
* Warning! Data is read-only.\n
* This function may be faster than readUnicodeString() because it does not do
* memory allocation.
* \return pointer to allocated string */
virtual const wchar_t *readUnicodeStringPtr();
/** Reads num bytes from packet
* \param bytes pointer to buffer to store data
* \param num number of bytes to read
* \returns success state */
virtual bool readBytes( unsigned char *bytes, unsigned int num );
public: // L2J aliases
// writers
/** Alias to writeChar() */
virtual inline void writeC( char c ) { writeChar( c ); }
/** Alias to writeShort() */
virtual inline void writeH( short h ) { writeShort( h ); }
/** Alias to writeInt() */
virtual inline void writeD( int d ) { writeInt( d ); }
/** Alias to writeInt64() */
virtual inline void writeQ( long long int Q ) { writeInt64( Q ); }
/** Alias to writeDouble() */
virtual inline void writeF( double f ) { writeDouble( f ); }
/** Alias to writeUnicodeString() */
virtual inline void writeS( const wchar_t *string ) { writeUnicodeString( string ); }
/** Alias to writeBytes() */
virtual inline void writeB( const ByteArray& bytes ) { writeBytes( bytes.getBytesPtr(), bytes.getSize() ); }
// readers
/** Alias to readChar() */
virtual inline char readC() { return readChar(); }
/** Alias to readShort() */
virtual inline short readH() { return readShort(); }
/** Alias to readInt() */
virtual inline int readD() { return readInt(); }
/** Alias to readDouble() */
virtual inline double readF() { return readDouble(); }
/** Alias to readInt64() */
virtual inline long long int readQ() { return readInt64(); }
/** Alias to readUnicodeString() */
virtual inline wchar_t *readS() { return readUnicodeString(); }
/** Alias to readBytes() */
virtual ByteArray *readB( unsigned int count ); // not inline :)
public: // parsers/creators
/** Parses packet. Must be overriden in child classes */
virtual bool parse( L2_VERSION ver = L2_VERSION_T1 );
/** Default method to create packet. Must be overriden in subclasses */
virtual bool create( L2_VERSION ver = L2_VERSION_T1 );
// DEBUG funcs
public:
/** Writes packet dump to file f n HEX
* \param f - file to write to */
virtual void dumpToFile( FILE *f );
/** Saves all packet to file as binary data
* \param filename - file name to save to */
virtual void saveToFileRaw( const char *filename );
/** here calls dumpToFile(). Must be overriden in child classes
* \param f - file to write to */
virtual void displaySelfNice( FILE *f );
public: // typeconv
//virtual operator const unsigned char *() const;
/** Returns pointer to all internal data buffer. Calls ByteArray::getBytesPtr()
* \return pointer to all internal data buffer */
virtual const unsigned char *getBytesPtr() const;
protected:
/** Internal function - called from constuctors. Initializes object state:
* Sets buffer_size to 256, calls readReset(), writeReset() */
virtual void _initNull();
/** Internal function. Pre-allocates internal buffer to buffer_size */
virtual bool _preAllocateBuffer();
/** Internal function. Tries to increase buffer size twice */
virtual bool _growBuffer();
/** almost the same as _initNull()... */
virtual void _freeSelf();
protected:
unsigned int buffer_size; ///< current buffer size
unsigned int real_size; ///< number of used bytes in buffer
unsigned int write_ptr; ///< index of next byte that will be written to buffer
unsigned int read_ptr; ///< index of next byte that will be read from buffer
unsigned int datasize; ///< number of data bytes in packet (excluding first 2 bytes that hold packet size)
ByteArray b; ///< internal buffer to hold raw packet data
};
#endif