Hello,
I'm having a little trouble with some code I've written that receives a variable number of data objects from a client. The objects are not represented in this code; The data received is merely buffered and passed to a callback function that returns:-
-2 if it has encountered a marker indicating the end of the list;
-1 if it encountered an error;
0 if it has not read any data (waiting for more);
Or a positive number of bytes read.
The code is based around filling a 512 byte queue-style buffer with data and moving a write pointer within it depending on how much data is received.
Unfortunately I have encountered a few situations now where ulSize, which is supposed to describe to the callback function how many bytes in the buffer is available to it, exceeds the maximum length of the buffer (512), which is naturally very bad.
It never happens when there is a debugger attached, which suggests that there is a very specific set of circumstances which causes the problem.
I know it's probably not the best implementation in the world but it (almost) does the job. If anyone could suggest improvements I'd be grateful.
Code:
// snippet, here's the variables used
int iRet, iRet2;
unsigned char lpBuffer[512], *lpPtr;
unsigned long ulSize;
SOCKET sockClient;
// initialize queue stuff
lpPtr = lpBuffer;
ulSize = 0;
while (1)
{
// receive data into the queue beginning at the write pointer
iRet = recv(sockClient, lpPtr, (lpBuffer + 512) - lpPtr, 0);
if (!iRet || iRet == SOCKET_ERROR)
iRet = -2; // transmission error
else
{
ulSize += iRet; // add the length of the new data to the total in the queue
if (ulSize > 512)
WriteLog("What the...?!?\r\n"); // this appears in the log when bad things happen
while (ulSize) // there is data in the queue
{
// pass the received data to the callback function
iRet2 = g_lpCommand.fpCallback(ulSize, lpBuffer);
if (iRet2 == -1) // error
{
iRet = -2; // transmission error
break;
}
else if (iRet2 == -2) // complete
{
iRet = -3; // complete
break;
}
if (iRet2) // a positive number was returned from the callback (bytes read)
{
ulSize -= iRet2; // subtract from the total
if (ulSize) // if some is left, move it to the front of the queue
memmove(lpBuffer, lpBuffer + iRet2, ulSize);
// if some is left, position the write pointer after it, else point to the front
if (ulSize < 512)
lpPtr = lpBuffer + ulSize;
else
lpPtr = lpBuffer;
}
else // nothing read, get more data
break;
}
}
if (iRet < 0) // there was an error, stop receiving
break;
}
if (iRet == -3) // clear error if it indicates completion
iRet = 0;