i am creating WRQ packet for TFTP client in cPP. the code works fine in Little endian system (PC) and have proble m with Big Endian system while creating packets.
the code is
#define TFTP_OPCODE_READ 1
#define TFTP_OPCODE_WRITE 2
#define TFTP_OPCODE_DATA 3
#define TFTP_OPCODE_ACK 4
#define TFTP_OPCODE_ERROR 5
#define cTFTPPacket_MAX_SIZE 1024
#define cTFTPPacket_DATA_SIZE 512
#define TFTP_DEFAULT_TRANSFER_MODE "octet" //"netascii", "octet", or "mail"
typedef unsigned char BYTE;
typedef unsigned short WORD;
///////////////////////// below is Packet.cpp file ///////
bool cTFTPPacket::addByte(BYTE b)
{
if (mCurPacketSize >= cTFTPPacket_MAX_SIZE)
{
return false;
}
mData[mCurPacketSize] = (unsigned char)b;
mCurPacketSize++;
return true;
}
bool cTFTPPacket::addWord(WORD w)
{
if (!addByte(*(((BYTE*)&w)+1)))
{
return false;
}
return (!addByte(*((BYTE*)&w)));
}
bool cTFTPPacket::addString(char* str)
{
int n = strlen(str);
int i=0;
for (i=0;i<n;i++)
{
if (!addByte(*(str + i)))
{
return false;
}
}
return true;
}
Expected packet is
0x00 0x02 string 0x00 octet 0x00
Obtain in big endian is
0x02 0x00 string 0x00 octet 0x00
Code to create the Packets are
bool cTFTPPacket::createWRQ(char* filename)
{
/* structure is the same as RRQ */
clear();
addWord(TFTP_OPCODE_WRITE);
addString(filename);
addByte(0);
addString(TFTP_DEFAULT_TRANSFER_MODE);
addByte(0);
return true;
}
bool cTFTPPacket::createACK(int packet_num)
{
clear();
addWord(TFTP_OPCODE_ACK);
addWord(packet_num);
return true;
}
bool cTFTPPacket::createData(int block, char* mData, int data_size)
{
/* 2 bytes 2 bytes n bytes
----------------------------------------
DATA | 03 | Block # | Data |
---------------------------------------- */
clear(); // to clean the memory location
addWord(TFTP_OPCODE_DATA);
addWord(block);
addMemory(mData, data_size);
return true;
}
bool cTFTPPacket::addMemory(char* buffer, int len)
{
bool oStatus=false;
if (mCurPacketSize + len >= cTFTPPacket_MAX_SIZE)
{
cout<<("Packet max size exceeded");
oStatus= false;
}
else
{
memcpy(&(mData[mCurPacketSize]), buffer, len);
mCurPacketSize += len;
oStatus= true;
}
return oStatus;
}
BYTE cTFTPPacket::getByte(int offset)
{
return (BYTE)mData[offset];
}
WORD cTFTPPacket::getWord(int offset)
{
WORD hi = getByte(offset);
//WORD lo = getByte(offset + 1);
WORD lo = getByte(offset + 1);
return ((hi<<8)|lo);
}
WORD cTFTPPacket::getNumber()
{
if (this->isData() || this->isACK())
{
return this->getWord(2);
}
else
{
return 0;
}
}
bool cTFTPPacket::getString(int offset, char* buffer, int len)
{
bool oStatus=false;
if (offset > mCurPacketSize)
{
oStatus=false;
}
else if (len < mCurPacketSize - offset)
{
oStatus= false;
}
else
{
memcpy(buffer, &(mData[offset]), mCurPacketSize - offset);
oStatus= true;
}
return oStatus;
}
bool cTFTPPacket::createError(int error_code, char* message) {
/* 2 bytes 2 bytes string 1 byte
----------------------------------------
ERROR | 05 | ErrorCode | ErrMsg | 0 |
---------------------------------------- */
clear();
addWord(TFTP_OPCODE_ERROR);
addWord(error_code);
addString(message);
addByte(0);
return true;
}
int cTFTPPacket::getSize()
{
return mCurPacketSize;
}
bool cTFTPPacket::setSize(int size)
{
if (size <= cTFTPPacket_MAX_SIZE)
{
mCurPacketSize = size;
return true;
}
else
{
return false;
}
}
bool cTFTPPacket::isRRQ()
{
return (this->getWord(0) == TFTP_OPCODE_READ);
}
bool cTFTPPacket::isWRQ()
{
return (this->getWord(0) == TFTP_OPCODE_WRITE);
}
bool cTFTPPacket::isACK()
{
return (this->getWord(0) == TFTP_OPCODE_ACK);
}
bool cTFTPPacket::isData() {
return (this->getWord(0) == TFTP_OPCODE_DATA);
}
bool cTFTPPacket::isError()
{
return (this->getWord(0) == TFTP_OPCODE_ERROR);
}
void cTFTPPacket::clear()
{
mCurPacketSize = 0;
memset(mData, mCurPacketSize, cTFTPPacket_MAX_SIZE);
}
unsigned char* cTFTPPacket::getData(int offset)
{
return &(mData[offset]);
}
bool cTFTPPacket::copyData(int offset, char* dest, int length)
{
bool oStatus=false;
if (offset > this->getSize())
{
oStatus= false;
}
else if (length < (this->getSize() - offset))
{
oStatus= false;
}
else
{
memcpy(dest, &(mData[offset]), (this->getSize()-offset));
oStatus= true;
}
return oStatus;
}
void cTFTPPacket::dumpData() {
xRM_DEBUG("\n--------------DATA DUMP---------------------\n");
xRM_DEBUG("Size: " << mCurPacketSize );
for (int i = 0; i < mCurPacketSize; i++)
{
xRM_DEBUG(mData[i]);
cout<<mData[i];
}
}
cTFTPPacket::~cTFTPPacket() {
}
i figured the proble is occuring in Addword and get Word how to over come this problem. and one more thing my server is little endian (normal linux machine) and hardware is big endian
The "traditional" approach is to pretend that there are only two possible orderings (although I've seen at least three), and that all machines are twos complement with 8 bit bytes. A better approach is to process the numeric format logically. For unsigned, something like:
void
insertUnsigned16Bits( char* dest, unsigned value )
{
*dest ++ = (value >> 8) & 0xFF;
*dest ++ = (value ) & 0xFF;
}
unsigned
extractUnsigned16Bits( char const* source )
{
unsigned result = 0;
result |= (*source ++ & 0xFF) << 8;
result |= (*source ++ & 0xFF);
return result;
}
This easily extends to any size of unsigned integers that can be represented on your machine.
For signed output, if the format specifies 2's complement, just convert to unsigned—the standard requires such conversions to do the right thing. On input, to be really portable, you have to read into a larger type, test whether the unsigned value you read is greater than the maximum signed value, and if so, subtract the corresponding unsigned max; on most machines, however, just reading into an unsigned, then converting to the signed type will work.