Valhalla Legends Forums Archive | Battle.net Bot Development | [C++] Inserting Null-Terminating Strings. (Cont.)

AuthorMessageTime
bethra
Make a packet buffer in C++.


I'm having problems converting and between different types.  Again, C++ is much different that VB6 and I am just frustrated.

I'm not quite understanding.  I've searched the forums a bit and I looked at Mynd's C# Packet Buffer (I think it is yours), but I can't make perfect sense of it b/c it's the other kind of C language.

I'm not quite sure but I the closest I think I've gotten is something like this:
[code]
DWORD prodID = 0x07;
char teststr[4];

memcpy(teststr, &prodID, 4);
[/code]

Its doesn't work or seem to.

I've really tried making my own packet buffer.  I've tried not to post because some people get mad if I come across like I'm not giving any effort.

I've sort of daydreamed even in my calculus class about how I could make the packet buffer.  I've spent more hours working on this than playing with my Clan memebers.  Please help.
December 4, 2004, 4:44 PM
Adron
That code is OK.
December 4, 2004, 4:53 PM
bethra
[quote author=Adron link=topic=9774.msg91008#msg91008 date=1102179202]
That code is OK.
[/quote]

hmmmmm

My DebugOutput function might be the problem....
[code]
inline void DebugOutput(const char* buf)
{
int rem = 12;
int len = strlen(buf);

printf("%s\n%s%i\n%s\n", "-----------------------------------", "Size: ", len, "-----------------------------------");
for( int j = 0; j < len; j = (j + 12))
{
if( (len - j) < 12 )
rem = ((len - j));

for( int i = 0; i < rem; i++)
{
printf("%2X ", (buf[i + j]) & 0xFF);
}

printf("%5c", 0x20);

if( rem < 12 )
{
for( int spc = 0; spc < (3 * (12 - rem)); spc++ )
{
printf("%c", 0x20);
}
}


for( int l = 0; l < rem; l++ )
{
if((buf[j + l] == 0x20))
printf("%c", 0x2E);
else
printf("%c", buf[j + l]);
}
printf("\n\n");
}

}
[/code]

It seems to work fine with strings that I tested it with "Qwert likes old, fat, short, bald men."


dunno.
December 4, 2004, 5:29 PM
OnlyMeat
Ill give you the best peace of advice iv ever come across,  sort of discovered it as well i suppose as i went along.

(1) Before you write any code try and put down in writing/diagram format the basic conceptual design of your application/module/class and your goals.

(2) The golden rule of problem solving is - it's all about simplifying and the way you do that is by breaking a problem down into smaller units of work i.e for a packet buffer the way to simplify it would be to create a packet buffer class ( usually polymorphic so you can extend it ) then add member functions to assemble/dissasemble it. An example of a simplified packet buffer:-

[code]
/* 1024 ( this should be as big as you need to store your largest buffer or possibly use a dynamic sizing buffer depending on it's contents - your choice )
*/
#define MAX_PKT 0x400

class CPacket
{
public:
  /////////////////////////////////////////
  // Standard class Constructor/Deconstructor
  CPacket(){m_pBuf = new char[MAX_PKT];} //allocate buf   
    ~CPacket(){delete [] m_pBuf;}  // deallocate buf

public:
  //////////////////////////////////////////
// Interface ( functions that assemble/dissasemble the      //packet)
  void AddDWORD( DWORD dwData );
  void AddWORD ( WORD wData );
  void AddBYTE ( BYTE byData );
  void AddString ( LPCSTR lpData );

  ////////////////////////////////////////////
// Functions that prepare the outgoing structure for sending
  virtual int Send ( char cID, SOCKET s );
  virtual int Serialize ( char cID ); for debug testing etc ( very usefull )

  ////////////////////////////////////////////
// Cleanup functions
  virtual void Clear(); // Resets any state data and the actual //buffer

  ////////////////////////////////////////////
// Disassemble functions ( for extracting primative types    //from the packet buffer
  ...

  ////////////////////////////////////////////
// Read functions ( more advanced i use these to read the //socket data directly into my packet buffer also it can do //length checks i.e bnet chat header + data section to //ensure a complete packet is received before dispatching it
virtual int ReadPart ( char* pBuf ) ;

  ////////////////////////////////////////////
// Status functions ( note most of these interfaces should be //polymorphic to allow overriding for different formats etc )
  virtual BOOL IsComplete(); // header + data section in case // of bnet chat
  virtual BOOL HasHeader();

etc etc.. you get the idea.

private:
char* m_pBuf; // internal packet buffer
int      nPos;    // current position within buffer
}

Now the assemble functions are pretty simple, you will just copy the data to your internal buffer used in your packet class 'm_pBuf' :-

for the function AddDWORD for example you could do this:

void CPacket::AddDWORD(DWORD dwData)
{
      // Copy the dword to our internal packet buffer
      memcpy(m_pBuf + nPos, &dwData, sizeof(DWORD));
     
      // Increment our buffer position counter
      nPos += sizeof(DWORD);
}
[/code]

Thats a very simple example but it should get you started.
December 4, 2004, 5:40 PM
Adron
[quote author=bethra link=topic=9774.msg91012#msg91012 date=1102181371]
My DebugOutput function might be the problem....
[/quote]

You really like to insert things using %c and %s? Much of what you've inserted that way could've been written directly in the format strings instead.. But that's not likely to be a problem.

You may want to replace all characters between 0 and 31 with '.' instead of just spaces.

Could you explain why you think your code isn't working? Show your test program and the output of it?


December 4, 2004, 6:22 PM
bethra
[quote author=Adron link=topic=9774.msg91022#msg91022 date=1102184540]
[quote author=bethra link=topic=9774.msg91012#msg91012 date=1102181371]
My DebugOutput function might be the problem....
[/quote]

You really like to insert things using %c and %s? Much of what you've inserted that way could've been written directly in the format strings instead.. But that's not likely to be a problem.

You may want to replace all characters between 0 and 31 with '.' instead of just spaces.

Could you explain why you think your code isn't working? Show your test program and the output of it?
[/quote]

ok
[code]
void DebugOutput(const char*);

int main(void)
{
unsigned long int iDWORD = 0x07;
char buff[4];

memcpy(buff, &iDWORD, sizeof(iDWORD));

DebugOutput(buff);

        //  I'm the chief of a clan and we all joke around with this 14y/o member :)
DebugOutput("Qwert smells");

return 0;
}

//=============================================================
// dump buffer in hex
inline void DebugOutput(const char* buf)
{
int rem = 12;
int len = strlen(buf);

printf("%s\n%s%i\n%s\n", "-----------------------------------", "Size: ", len, "-----------------------------------");
for( int j = 0; j < len; j = (j + 12))
{
if( (len - j) < 12 )
rem = ((len - j));

for( int i = 0; i < rem; i++)
{
printf("%2X ", (buf[i + j]) & 0xFF);
}

printf("%5c", 0x20);

if( rem < 12 )
{
for( int spc = 0; spc < (3 * (12 - rem)); spc++ )
{
printf("%c", 0x20);
}
}


for( int l = 0; l < rem; l++ )
{
if((buf[j + l] == 0x20))
printf("%c", 0x2E);
else
printf("%c", buf[j + l]);
}
printf("\n\n");
}

}
[/code]

k here is what is returned for the string "Qwert smells":
[quote]
-----------------------------------
Size:  12
-----------------------------------
51 77 65 72 74 20 73 6D 65 6C 6C 73          Qwert.smells
[/quote]

This is what I get for the string buff[4]:
[quote]
-----------------------------------
Size:  1
-----------------------------------
7
[/quote]
This is what is displayed, but my computer actually beeps.  From the computer case/tower.  Not from my head phones or speakers.  The program doesn't crash though.
December 4, 2004, 9:02 PM
tA-Kane
Your computer could beep on this statement:[code]for( int l = 0; l < rem; l++ )
{
if((buf[j + l] == 0x20))
printf("%c", 0x2E);
else
printf("%c", buf[j + l]);
}
printf("\n\n");
}
}[/code]You should check to see if buf[j+l] <= 0x20, not if it's == 0x20. Otherwise, you may end up adding nulls, which some consoles won't handle nicely.

What are you expecting it to display?

0x7 is indeed the same as 0x00000007 when on a Windows platform. If you want it to display 07 00 00 00, then you'll need to add checks for those, and add zeros if necessary. Alternately, I think you can pass some sort of argument to printf() to make a minimum length of the hex str.

If you want it to display as 00 00 00 07, then you'll need to byteswap buf[] before you send it to the debug function.
December 4, 2004, 9:49 PM
Mephisto
LoRd has a public packet buffer.  http://www.fictionwelive.com/lord -- note: prone to buffer overflows (a minimal risk if you make sure you're not overflowing it; unless he fixed it).
December 4, 2004, 9:55 PM
bethra
[quote author=Mephisto link=topic=9774.msg91050#msg91050 date=1102197336]
LoRd has a public packet buffer.  http://www.fictionwelive.com/lord -- note: prone to buffer overflows (a minimal risk if you make sure you're not overflowing it; unless he fixed it).
[/quote]

ummmm link doesn't work... errr well it has nothing there.
December 4, 2004, 9:59 PM
Mephisto
Guess his hosting was shutdown, you should go ask him then.
December 4, 2004, 10:04 PM
iago
There are several packetbuffers around, written by various people.  But it's very good practice to write your own.  I highly recommend continuing with this.
December 4, 2004, 10:13 PM
bethra
[quote author=tA-Kane link=topic=9774.msg91049#msg91049 date=1102196980]
If you want it to display as 00 00 00 07, then you'll need to byteswap buf[] before you send it to the debug function.
[/quote]

Yeah! That is what I want it to display!  k, I'll try redo'ing my DebugOutput.  Thanks.
December 4, 2004, 11:51 PM
Yoni
[quote author=bethra link=topic=9774.msg91063#msg91063 date=1102204289]
[quote author=tA-Kane link=topic=9774.msg91049#msg91049 date=1102196980]
If you want it to display as 00 00 00 07, then you'll need to byteswap buf[] before you send it to the debug function.
[/quote]

Yeah! That is what I want it to display! k, I'll try redo'ing my DebugOutput. Thanks.
[/quote]

I think the problem is different. Look at your DebugOutput function. buf may contain "good nulls", but you're using strlen, which stops when it sees a null.
A solution: Pass len as a parameter, instead of setting len = strlen(buf).
December 5, 2004, 1:32 AM
bethra
ok, I kind of modified my DebugOutput function.

Now, this is how I am trying to make the BNLS_REQUESTVERSIONBYTE (0x10) packet.  Is it correct?

[code]
// packet ID for BNLS_REQUESTVERSIONBYTE
BYTE pID = 0x10;
// packet Size of 0x10
WORD pSize = sizeof(WORD) + sizeof(BYTE) + sizeof(DWORD);
// product ID for Warcraft III
DWORD prodID = 0x07;
// packet buffer
char buff[sizeof(WORD) + sizeof(BYTE) + sizeof(DWORD)];

// constructing the packet buffer
memcpy(buff, &pSize, sizeof(pSize));
memcpy(buff + sizeof(WORD), &pID, sizeof(pID));
memcpy(buff + sizeof(WORD) + sizeof(BYTE), &prodID, sizeof(prodID));[/code]

Ya see, once I can get the gist of how to assemble the different datatypes into  a packet, then I can make my packet buffer work!



EDIT:  I also changed the name displayed.  Sorc.Polgara is my Bnet name.
December 5, 2004, 1:00 PM
Yoni
That looks correct.
Here is another way to do it, without using memcpy:

[code]
*(WORD*)(buff) = pSize;
*(BYTE*)(buff + sizeof(WORD)) = pID;
*(DWORD*)(buff + sizeof(WORD) + sizeof(BYTE)) = prodID;
[/code]

And here is a more elegant way (with a few redundancies which you'll have to get over for the sake of elegancy), which you can think about while writing your packet buffer:

[code]
int pos = 0;

*(WORD*)(buff + pos) = pSize;
pos += sizeof(WORD);

*(BYTE*)(buff + pos) = pID;
pos += sizeof(BYTE);

*(DWORD*)(buff + pos) = prodID;
pos += sizeof(DWORD);
[/code]

Edit:

[quote author=Sorc.Polgara link=topic=9774.msg91007#msg91007 date=1102178650]
I've sort of daydreamed even in my calculus class about how I could make the packet buffer.
[/quote]

No! Do it in history class!
December 5, 2004, 2:16 PM
Arta
The latter method is the one I use.
December 5, 2004, 2:48 PM
bethra
[quote author=Yoni link=topic=9774.msg91126#msg91126 date=1102256189]
And here is a more elegant way (with a few redundancies which you'll have to get over for the sake of elegancy), which you can think about while writing your packet buffer:
[code]
int pos = 0;

*(WORD*)(buff + pos) = pSize;
pos += sizeof(WORD);

*(BYTE*)(buff + pos) = pID;
pos += sizeof(BYTE);

*(DWORD*)(buff + pos) = prodID;
pos += sizeof(DWORD);
[/code]
[/quote]

Yeah, I like this one better for some reason.  Perhaps it is b/c it is easier to look at or hmmm I don't know how to put it, but it explains more I guess.

I put in both your ones with into my debug function and it gave the same results that mine did.  So my mine must work.  However I suppose it is better to not use memcpy() when you don't need to?

The thing about C++ and VB6 that that I find significant is the use of pointers and stuff.  In VB I had to use strings for mostly everything when I handled packets.  In C++ you can make use of different kind of datatypes when handling packets.

k thanks alot.  I'll go make my packet buffer ^_^;  I think I also fixed my DebugOutput function too.
December 5, 2004, 3:01 PM
bethra
Dangit!

My packet buffer, what I've done so far, uses a fixed-size buffer i.e. "char buf[7]".  I would sort of like to use a dynamic array.  I've experimented with the code "char *dynArray = new char[mysize]" along with the "delete [] dynArray" that destroys it or deallocates it from memory.

Also, inserting a null-terminating string into the non-dynamic buffer could be done using the memcpy() and/or strcat() functions?

Another question, is there any difference between using the datatype LPSTR and char*?  Is memmove() prefered over memcpy() in such operations?



EDIT:  Sorry for the double post.  I felt that it was appropriate enough.
December 5, 2004, 8:05 PM
Adron
What depends on a fixed size?

You may have to reallocate your buffer at times. Whenever it's full. One common method is to double the size each time you reallocate.

Inserting a null-terminated string could be done using strcpy, memcpy or memmove. You need to make sure it will fit before you insert it.

LPSTR and char* are the same in current Windows.

You have to use memmove if the source and destination buffers may overlap. I don't think memmove will be optimized the way memcpy can be.
December 5, 2004, 8:15 PM
bethra
[quote author=Adron link=topic=9774.msg91146#msg91146 date=1102277733]
What depends on a fixed size?
[/quote]

My packet buffer inserts into a string/array already set to a specific size.

[quote author=Adron link=topic=9774.msg91146#msg91146 date=1102277733]
You may have to reallocate your buffer at times. Whenever it's full. One common method is to double the size each time you reallocate.
[/quote]

Reallocating, is that where the "char *dynArray = new char[changesize];" kicks in?  When I reallocate, is it possible to preserve the data already in the buffer?  I've tried using the "char *dynArray = new char[changesize];" but it loses the data I've already stored in it.
December 5, 2004, 8:25 PM
Kp
To preserve the data, the old data must be copied to the new buffer.  This is done automatically if you use realloc(3) or HeapReAlloc.  However, C++ lacks a realloc operator, so you must instead create a new array, explicitly copy the data, and then explicitly release the old array (all this would be handled for you by realloc).  Also note that create/copy/free may fail (or waste effort) in cases where realloc succeeds if the only suitable place for the new allocation is growing of the old allocation into free space which follows it.
December 5, 2004, 8:39 PM
Skywing
Yoni's method may fail on IA64 due to alignment faults.
December 5, 2004, 9:15 PM
bethra
Ok, my packet buffer seems like it works, but it doesn't =\


This is the class that is located in the header file "packetbuffer.h"
[code]
// packetbuffer.h
// packet buffer class

#ifndef PACKETBUFFER_H
#define PACKETBUFFER_H

class pbuffer{
public:
pbuffer();
pbuffer(size_t);
~pbuffer();
void InsertDWORD(DWORD);
void InsertWORD(WORD);
void InsertBYTE(BYTE);
        int resizeBuf(size_t);

private:
size_t bufsize;
int pos;
int flag;
char* buffer;
};
#endif
[/code]

Ok I'm only going to show the member functions InsertDWORD(DWORD), the resizeBuf(size_t), and pbuffer() and pbuffer(size_t) because these are the only ones that are used or executed when testing the packet buffer.  They are all located beneath the #endif of course.
[code]
// constructor pbuffer()
pbuffer::pbuffer()
{
pos = 0;
bufsize = 0;
flag = 0;
}

// constructor pbuffer(size_t)
pbuffer::pbuffer(size_t bsize)
{
pos = 0;
flag = 1;

if((bsize <= 0) || (bsize == NULL))
{
if( (buffer = (char*)malloc(sizeof(char*))) == NULL ){
printf("Error allocating buffer sizeof(char*)\n");
exit( 1 );
}
}
else
{
if( (buffer = (char*)malloc(bsize)) == NULL ){
printf("Error allocating the buffer sizeof(bsize)\n");
exit( 1 );
}
}
bufsize = _msize(buffer);

cout <<"Allocated buffer size: " << bufsize << endl << buffer << endl;
}

// member void InsertDWORD(DWORD)
void pbuffer::InsertDWORD(DWORD insDWORD)
{
if( resizeBuf(sizeof(DWORD)) == false ){
printf("Error resizing the buffer to insert a DWORD");
exit( 1 );
}
else{
cout << "Successfully inserted: " << sizeof(buffer) << endl;
}
*(DWORD*)(buffer) = insDWORD;
cout << buffer << endl;
}

// member int resizeBuf(size_t)
int pbuffer::resizeBuf( size_t resize )
{
// buffer is not allocated yet
if( (bufsize) <= 0 || (bufsize == NULL) ){
if( (buffer = (char*)malloc(resize)) == NULL ){
cout << "Error allocating the buffer: " << resize << endl;
return false;
}
cout << "Successfully allocated the buffer: " << sizeof(buffer) << endl;
}
else{
if( (buffer = (char*)realloc(buffer, (bufsize + resize))) == NULL ){
cout << "Error resizing the buffer: " << resize << endl;
return false;
}
cout << "Successfully resized the buffer: " << sizeof(buffer) << endl;
}
return true;
}
[/code]

This is my main() function
[code]
#include <iostream.h>
#include <malloc.h>
#include <stdlib.h>
#include "packetbuffer.h"

int main(void)
{
DWORD prodID = 0x07;

pbuffer pbuf(sizeof(DWORD));
pbuf.InsertDWORD(prodID);

return 0;
}
[/code]

It compiles fine, but when I run it I get
[quote]
Allocated buffer size: 4
====²²²²
Successfully resized the buffer: 0x0042F0704
Successfully inserted: 4
*beep*
[/quote]
the *beep* is brief beeping noise comes directly out from my desktop tower, the build in speaker that is hooked up to my mobo.

Everything seems to be going fine based on the stuff I put there to tell me what is happening.  Except for that beep...

It looks as if the beeping occurs when it hits the end of InsertDWORD(DWORD) where the "*(DWORD*)(buffer) = insDWORD;" is.  It should work, its basically the same thing that Yoni posted and had worked when I put it in the main() function...

dunno, help prz.
December 7, 2004, 12:34 AM
Adron
Outputting a 0x07 is an instruction to the computer to beep. So it's doing exactly what you told it to do.

Some comments on your code:

I don't see why you allocate an initial buffer of 4 bytes and then immediate resize it to add 4 more bytes, when you've only added a single 4 byte DWORD to it.

You shouldn't be using sizeof on buffer, because that won't change as you resize the buffer. Track the allocated size in your own variable bufsize.

Don't resize the buffer every time you add data. Resize it in larger increases.
December 7, 2004, 1:05 AM
Myndfyr
I noticed in your resize function:

[code]
if( (bufsize) <= 0 || (bufsize == NULL) ){
[/code]

You probably want to check if buffer, not bufsize, is NULL.  Rewritten:

[code]
if ( (bufsize <= 0) || (buffer == NULL) ) {
[/code]
December 7, 2004, 1:08 AM
Mephisto
By first look of your InsertDWORD member function you're not really creating a packet buffer...

Examine this statement:
[code]*(DWORD*)(buffer) = insDWORD;[/code]
You're not actually inserting a DWORD, you're just reassigning your buffer to that value.  You should use something like this in your function:
[code]if ((CurrentBufferLength + sizeof(DWORD) > MaximumBufferSize))
return;
memcpy(&buffer[CurrentBufferLength], &insDWORD, sizeof(DWORD));
CurrentBufferLength += sizeof(DWORD);[/code]
December 7, 2004, 1:11 AM
Adron
Or,

[code]
*(DWORD*)(buffer+pos) = insDWORD; pos += sizeof(DWORD);
[/code]
December 7, 2004, 1:15 AM
OnlyMeat
[quote author=Adron link=topic=9774.msg91291#msg91291 date=1102382130]
Or,

[code]
*(DWORD*)(buffer+pos) = insDWORD; pos += sizeof(DWORD);
[/code]
[/quote]

Im sorry but yuk thats ugly i think for purposes of readabillity alone they should atleast be on 2 lines:-

[code]
memcpy( buffer+pos, &insDWORD, sizeof(DWORD) );
pos+= sizeof(DWORD);
[/code]

On the other point i have to agree with adron reallocating every time you add a new dword is very inefficient and will cause fragmentation of the heap. If you are going to use a dynamic sizing buffer then try and make a smart one that does a minimum allocation of say 32 bytes or more so you can atleast add 8 dwords before it has to resize.
December 7, 2004, 1:29 AM
Eibro
It seems a vector or even a deque would work well here...
We are using C++, right?
December 7, 2004, 1:37 AM
Adron
[code](-1)[(DWORD*)(buffer + (pos += 4))] = insDWORD;[/code]
December 7, 2004, 1:39 AM
Mephisto
[quote author=Adron link=topic=9774.msg91307#msg91307 date=1102383572]
[code](-1)[(DWORD*)(buffer + (pos += 4))] = insDWORD;[/code]
[/quote]

:)
December 7, 2004, 1:51 AM
Kp
size_t is traditionally unsigned, so it looks rather silly to use <= when relating it to zero.  Also, why use an 'int' for a position?  It's not exactly common to have negative positions in a packetbuffer.
December 7, 2004, 7:58 PM
bethra
Ok, I'm running into trouble inserting a nt string into another nt string with my packet buffer.  I get tons of "Abort" "Retry" "Cancel" errors when I trid doing the following:

[code]
strncpy(buffer + pos, insNTSTR, strlen(insNTSTR));
strcpy(buffer + pos, insNTSTR, strlen(insNTSTR));
memcpy(buffer + pos, insNTSTR, _msize(insNTSTR));
[/code]

I also tried modifiying the code that peeps i.e. Adron, Yoni etc. showed me, it won't compile though.
[code]
(-1)[(char*)(buffer + (pos += _msize(insNTSTR)))] = insNTSTR;
[/code]

also I tired some other string manipulating routines from the MSDN Library, the packet buffer doesn't like it.

What I've done is basically set my buffer to the size of 32 from the gitgo.  So that I won't have to resize it everytime I add something.  (Suggested by some  peeps)

I've inserted a WORD + BYTE + DWORD into the buffer and next I want to add an NT string.

I can add WORDs, BYTEs, DWORDs as much as I need. however, since some packets require for me to send and recieve data/strings with unspecified lengths which I learned when I had made a bot back in VB6 and first handling packets.

Must I have to cut off that extra buffer space and then catengate (spelling wrong too lazy to look up)  it somehow to the buffer? or is there a way to just do it like with DWORDs WORDs BYTEs etc?

Thanks.  Once I get my NTString thingy going, then I will post my packet buffer for criticism and I can fix it b/c j00 guys are pro programmars.  Thanks.
December 9, 2004, 12:27 AM
Mephisto
why on earth would you copy the string three times w/ three different functions?  And how does that call to strcpy() even compile?  Also make sure that you have the proper amount of space allocated to insert the size of those strings into your buffer.
December 9, 2004, 12:35 AM
shadypalm88
[quote author=Sorc.Polgara link=topic=9774.msg91572#msg91572 date=1102552077]
[code]
strncpy(buffer + pos, insNTSTR, strlen(insNTSTR));
strcpy(buffer + pos, insNTSTR, strlen(insNTSTR));
memcpy(buffer + pos, insNTSTR, _msize(insNTSTR));
[/code][/quote]Well the second one shouldn't even compile.  Realize that the following two lines of code are really equivalent:[code]
strcpy(buffer + pos, insNTSTR);
strncpy(buffer + pos, insNTSTR, strlen(insNTSTR));[/code]
Whichever one you use, you will still need to get the length of the string in order to update your position.  My full routine is:[code]PacketBuffer& PacketBuffer::operator<<(const unsigned char* n) {
    size_t l = std::strlen((const char*) n) + 1;
    ensure(l);
    std::strcpy((buffer + position), (const char*) n);
    position += l;
    bufferLength += l;
}[/code]It's really simple.  Notice the + 1 on the first line, this is so the updated position takes the null-terminator into account.
December 9, 2004, 12:43 AM
bethra
[quote author=Mephisto link=topic=9774.msg91574#msg91574 date=1102552534]
why on earth would you copy the string three times w/ three different functions?  And how does that call to strcpy() even compile?  Also make sure that you have the proper amount of space allocated to insert the size of those strings into your buffer.
[/quote]

nonono I'm showing hte different things I've tried.  nono each line I've used separately in my trial and error stuff.

no way would i use all three of those at the same time errr consecutively.
December 9, 2004, 12:44 AM
OnlyMeat
[quote author=Sorc.Polgara link=topic=9774.msg91572#msg91572 date=1102552077]
[code]
strncpy(buffer + pos, insNTSTR, strlen(insNTSTR));
strcpy(buffer + pos, insNTSTR, strlen(insNTSTR));
memcpy(buffer + pos, insNTSTR, _msize(insNTSTR));
[/code]
[/quote]

First of all strcpy/strncpy only applies to null terminated strings, and as your packet buffer is clearly not going to be a null terminated string  ( remember you are using it to store byte sequences independant of datatype ) you should use memcpy.

Second was insNTSTR allocated on the heap? i ask this because _msize(insNTSTR) is used to determinate the size of a block allocated on the heap not on the stack, so if insNTSTR was not allocated dyamically that call will fail, try this instead:-

[code]
memcpy(buffer + pos, insNTSTR, strlen(insNTSTR));
[/code]

And btw in the world of c++ we use hungarian notation on variables and for a string it's called zero terminated denoted by this variable example:-

[code]
char szMyString[12];
[/code]

December 9, 2004, 1:54 AM
Skywing
People need not conform to your coding style to write valid code.

Besides, that's not even real Hungarian, which names variables based on their meaning, not type.
December 9, 2004, 2:18 PM
Mephisto
[quote author=OnlyMeat link=topic=9774.msg91590#msg91590 date=1102557290]First of all strcpy/strncpy only applies to null terminated strings, and as your packet buffer is clearly not going to be a null terminated string  ( remember you are using it to store byte sequences independant of datatype ) you should use memcpy.

And btw in the world of c++ we use hungarian notation on variables and for a string it's called zero terminated denoted by this variable example:-[/quote]

Using strcpy() in your packet buffer is just fine; you don't need to use memcpy(); and in fact, a string is suppose to be NULL terminated when you send it to Battle.net.

And in the world of C++ we don't always use Hungarian notation.  How many Linux users do you see using it?  I don't see a lot (could be mistaken though); and I myself who use Windows don't use Hungarian notation.  It's a coding style which was invented at Microsoft, and last time I checked, coding style was never standardized in ANSI-C++.

[Kp edit: cleaned up quote tags so Mephisto wouldn't get blamed for the stupid things OnlyMeat said.]
December 9, 2004, 3:09 PM
Adron
Steps to insert a null-terminated string:

1. Make sure the buffer is large enough. If it's full now, enlarge it by strlen(str) + 1;
2. Copy the null-terminated string into the buffer at the current position. Use strcpy(buffer + pos, str); or memcpy(buffer + pos, str, strlen(str) +1); or whatever you like.
3. Update pos: pos += strlen(str) + 1;
December 9, 2004, 8:15 PM

Search