mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-28 21:57:57 +03:00
767 lines
16 KiB
C
767 lines
16 KiB
C
![]() |
/*
|
||
|
gpiBuffer.c
|
||
|
GameSpy Presence SDK
|
||
|
Dan "Mr. Pants" Schoenblum
|
||
|
|
||
|
Copyright 1999-2007 GameSpy Industries, Inc
|
||
|
|
||
|
devsupport@gamespy.com
|
||
|
|
||
|
***********************************************************************
|
||
|
Please see the GameSpy Presence SDK documentation for more information
|
||
|
**********************************************************************/
|
||
|
|
||
|
//INCLUDES
|
||
|
//////////
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include "gpi.h"
|
||
|
|
||
|
//DEFINES
|
||
|
/////////
|
||
|
#define GPI_DUMP_NET_TRAFFIC
|
||
|
|
||
|
//FUNCTIONS
|
||
|
///////////
|
||
|
GPResult
|
||
|
gpiAppendCharToBuffer(
|
||
|
GPConnection * connection,
|
||
|
GPIBuffer * outputBuffer,
|
||
|
char c
|
||
|
)
|
||
|
{
|
||
|
int len;
|
||
|
int size;
|
||
|
char * output;
|
||
|
|
||
|
assert(outputBuffer != NULL);
|
||
|
|
||
|
// Init locals.
|
||
|
///////////////
|
||
|
len = outputBuffer->len;
|
||
|
size = outputBuffer->size;
|
||
|
output = outputBuffer->buffer;
|
||
|
|
||
|
// Check if it needs to be resized.
|
||
|
///////////////////////////////////
|
||
|
if(size == len)
|
||
|
{
|
||
|
size += GPI_READ_SIZE;
|
||
|
output = (char*)gsirealloc(output, (unsigned int)size + 1);
|
||
|
if(output == NULL)
|
||
|
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
|
||
|
}
|
||
|
|
||
|
// Do the copy.
|
||
|
///////////////
|
||
|
output[len] = c;
|
||
|
output[len + 1] = '\0';
|
||
|
|
||
|
// Update the buffer info.
|
||
|
//////////////////////////
|
||
|
outputBuffer->len++;
|
||
|
outputBuffer->size = size;
|
||
|
outputBuffer->buffer = output;
|
||
|
|
||
|
return GP_NO_ERROR;
|
||
|
}
|
||
|
|
||
|
GPResult
|
||
|
gpiAppendStringToBufferLen(
|
||
|
GPConnection * connection,
|
||
|
GPIBuffer * outputBuffer,
|
||
|
const char * string,
|
||
|
int stringLen
|
||
|
)
|
||
|
{
|
||
|
int len;
|
||
|
int size;
|
||
|
char * output;
|
||
|
|
||
|
assert(string != NULL);
|
||
|
assert(stringLen >= 0);
|
||
|
assert(outputBuffer != NULL);
|
||
|
|
||
|
if(!string)
|
||
|
return GP_NO_ERROR;
|
||
|
|
||
|
// Init locals.
|
||
|
///////////////
|
||
|
len = outputBuffer->len;
|
||
|
size = outputBuffer->size;
|
||
|
output = outputBuffer->buffer;
|
||
|
|
||
|
// Check if it needs to be resized.
|
||
|
///////////////////////////////////
|
||
|
if((size - len) < stringLen)
|
||
|
{
|
||
|
size += max(GPI_READ_SIZE, stringLen);
|
||
|
output = (char*)gsirealloc(output, (unsigned int)size + 1);
|
||
|
if(output == NULL)
|
||
|
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
|
||
|
}
|
||
|
|
||
|
// Do the copy.
|
||
|
///////////////
|
||
|
memcpy(&output[len], string, (unsigned int)stringLen);
|
||
|
output[len + stringLen] = '\0';
|
||
|
|
||
|
// Update the buffer info.
|
||
|
//////////////////////////
|
||
|
outputBuffer->len += stringLen;
|
||
|
outputBuffer->size = size;
|
||
|
outputBuffer->buffer = output;
|
||
|
|
||
|
return GP_NO_ERROR;
|
||
|
}
|
||
|
|
||
|
GPResult
|
||
|
gpiAppendStringToBuffer(
|
||
|
GPConnection * connection,
|
||
|
GPIBuffer * outputBuffer,
|
||
|
const char * buffer
|
||
|
)
|
||
|
{
|
||
|
return gpiAppendStringToBufferLen(connection, outputBuffer, buffer, (int)strlen(buffer));
|
||
|
}
|
||
|
|
||
|
GPResult gpiAppendShortToBuffer(
|
||
|
GPConnection * connection,
|
||
|
GPIBuffer * outputBuffer,
|
||
|
short num)
|
||
|
{
|
||
|
char shortVal[8];
|
||
|
sprintf(shortVal, "%d", num);
|
||
|
return gpiAppendStringToBuffer(connection, outputBuffer, shortVal);
|
||
|
}
|
||
|
|
||
|
GPResult gpiAppendUShortToBuffer(
|
||
|
GPConnection * connection,
|
||
|
GPIBuffer * outputBuffer,
|
||
|
unsigned short num)
|
||
|
{
|
||
|
char shortVal[8];
|
||
|
sprintf(shortVal, "%u", num);
|
||
|
return gpiAppendStringToBuffer(connection, outputBuffer, shortVal);
|
||
|
}
|
||
|
|
||
|
GPResult
|
||
|
gpiAppendIntToBuffer(
|
||
|
GPConnection * connection,
|
||
|
GPIBuffer * outputBuffer,
|
||
|
int num
|
||
|
)
|
||
|
{
|
||
|
char intValue[16];
|
||
|
sprintf(intValue,"%d",num);
|
||
|
return gpiAppendStringToBuffer(connection, outputBuffer, intValue);
|
||
|
}
|
||
|
|
||
|
GPResult
|
||
|
gpiAppendUIntToBuffer(
|
||
|
GPConnection * connection,
|
||
|
GPIBuffer * outputBuffer,
|
||
|
unsigned int num
|
||
|
)
|
||
|
{
|
||
|
char intValue[16];
|
||
|
sprintf(intValue,"%u",num);
|
||
|
return gpiAppendStringToBuffer(connection, outputBuffer, intValue);
|
||
|
}
|
||
|
|
||
|
static GPResult
|
||
|
gpiSendData(
|
||
|
GPConnection * connection,
|
||
|
SOCKET sock,
|
||
|
const char * buffer,
|
||
|
int bufferLen,
|
||
|
GPIBool * closed,
|
||
|
int * sent,
|
||
|
char id[3]
|
||
|
)
|
||
|
{
|
||
|
int rcode;
|
||
|
|
||
|
rcode = send(sock, buffer, bufferLen, 0);
|
||
|
if(gsiSocketIsError(rcode))
|
||
|
{
|
||
|
rcode = GOAGetLastError(sock);
|
||
|
if((rcode != WSAEWOULDBLOCK) && (rcode != WSAEINPROGRESS) && (rcode != WSAETIMEDOUT) )
|
||
|
{
|
||
|
// handle peer connections specially
|
||
|
if((id[0] == 'P') && (id[1] == 'R'))
|
||
|
return GP_NETWORK_ERROR;
|
||
|
CallbackError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error sending on a socket.");
|
||
|
}
|
||
|
|
||
|
*sent = 0;
|
||
|
*closed = GPIFalse;
|
||
|
}
|
||
|
else if(rcode == 0)
|
||
|
{
|
||
|
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_Comment,
|
||
|
"SENDXXXX(%s): Connection closed\n", id);
|
||
|
|
||
|
*sent = 0;
|
||
|
*closed = GPITrue;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
#if defined(GPI_DUMP_NET_TRAFFIC) && defined(GSI_COMMON_DEBUG)
|
||
|
{
|
||
|
static int sendCount;
|
||
|
char *buf = (char *)gsimalloc((size_t)(rcode + 1));
|
||
|
memcpy(buf, buffer, (size_t)rcode);
|
||
|
buf[rcode] = '\0';
|
||
|
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump, "SENT%04d(%s): %s\n", sendCount++, id, buf);
|
||
|
freeclear(buf);
|
||
|
}
|
||
|
#elif defined(GSI_COMMON_DEBUG)
|
||
|
{
|
||
|
static int sendCount;
|
||
|
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump,
|
||
|
"SENT%04d(%s): %d\n", sendCount++, id, rcode);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
*sent = rcode;
|
||
|
*closed = GPIFalse;
|
||
|
}
|
||
|
|
||
|
return GP_NO_ERROR;
|
||
|
}
|
||
|
|
||
|
GPResult
|
||
|
gpiSendOrBufferChar(
|
||
|
GPConnection * connection,
|
||
|
GPIPeer_st peer,
|
||
|
char c
|
||
|
)
|
||
|
{
|
||
|
//GPIBool closed;
|
||
|
//int sent;
|
||
|
/*
|
||
|
assert(peer->outputBuffer.buffer != NULL);
|
||
|
|
||
|
// Only try to send if the buffer is empty and there are no messages.
|
||
|
/////////////////////////////////////////////////////////////////////
|
||
|
if(!(peer->outputBuffer.len - peer->outputBuffer.pos) && !ArrayLength(peer->messages))
|
||
|
{
|
||
|
CHECK_RESULT(gpiSendData(connection, peer->sock, &c, 1, &closed, &sent, "PT"));
|
||
|
if(sent)
|
||
|
return GP_NO_ERROR;
|
||
|
}
|
||
|
|
||
|
// Buffer if not sent.
|
||
|
//////////////////////
|
||
|
return gpiAppendCharToBuffer(connection, &peer->outputBuffer, c);
|
||
|
*/
|
||
|
GSI_UNUSED(c);
|
||
|
GSI_UNUSED(peer);
|
||
|
GSI_UNUSED(connection);
|
||
|
return GP_NO_ERROR;
|
||
|
}
|
||
|
|
||
|
GPResult
|
||
|
gpiSendOrBufferStringLenToPeer(
|
||
|
GPConnection * connection,
|
||
|
GPIPeer_st peer,
|
||
|
const char * string,
|
||
|
int stringLen
|
||
|
)
|
||
|
{
|
||
|
GPIConnection *iconnection;
|
||
|
|
||
|
unsigned int sent;
|
||
|
unsigned int total;
|
||
|
unsigned int remaining;
|
||
|
|
||
|
assert(peer->outputBuffer.buffer != NULL);
|
||
|
|
||
|
sent = 0;
|
||
|
iconnection = (GPIConnection *)*connection;
|
||
|
remaining = (unsigned int)stringLen;
|
||
|
total = 0;
|
||
|
|
||
|
// Check for nothing to send.
|
||
|
/////////////////////////////
|
||
|
if(stringLen == 0)
|
||
|
return GP_NO_ERROR;
|
||
|
|
||
|
// Only try to send if the buffer is empty and there are no messages.
|
||
|
/////////////////////////////////////////////////////////////////////
|
||
|
if(!(peer->outputBuffer.len - peer->outputBuffer.pos) && !ArrayLength(peer->messages))
|
||
|
{
|
||
|
if ((int)remaining <= (gsUdpEngineGetPeerOutBufferFreeSpace(peer->ip, peer->port) - GS_UDP_RELIABLE_MSG_HEADER - GS_UDP_MSG_HEADER_LEN))
|
||
|
{
|
||
|
gsUdpEngineSendMessage(peer->ip, peer->port, iconnection->mHeader, (unsigned char *)string, remaining, gsi_true);
|
||
|
total = remaining;
|
||
|
remaining = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
unsigned int freeSpace = (unsigned int)gsUdpEngineGetPeerOutBufferFreeSpace(peer->ip, peer->port);
|
||
|
if (freeSpace > (GS_UDP_MSG_HEADER_LEN + GS_UDP_RELIABLE_MSG_HEADER))
|
||
|
{
|
||
|
sent = freeSpace - (GS_UDP_MSG_HEADER_LEN + GS_UDP_RELIABLE_MSG_HEADER);
|
||
|
gsUdpEngineSendMessage(peer->ip, peer->port, iconnection->mHeader, (unsigned char *)string,
|
||
|
sent, gsi_true);
|
||
|
total = sent;
|
||
|
remaining -= sent;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// Buffer what wasn't sent.
|
||
|
///////////////////////////
|
||
|
if(remaining)
|
||
|
CHECK_RESULT(gpiAppendStringToBufferLen(connection, &peer->outputBuffer, &string[total], (int)remaining));
|
||
|
|
||
|
return GP_NO_ERROR;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
GPResult
|
||
|
gpiSendOrBufferStringLen(
|
||
|
GPConnection * connection,
|
||
|
GPIPeer_st peer,
|
||
|
const char * string,
|
||
|
int stringLen
|
||
|
)
|
||
|
{
|
||
|
|
||
|
GPIBool closed;
|
||
|
int sent;
|
||
|
int total;
|
||
|
int remaining;
|
||
|
|
||
|
|
||
|
assert(peer->outputBuffer.buffer != NULL);
|
||
|
|
||
|
remaining = stringLen;
|
||
|
total = 0;
|
||
|
|
||
|
// Check for nothing to send.
|
||
|
/////////////////////////////
|
||
|
if(stringLen == 0)
|
||
|
return GP_NO_ERROR;
|
||
|
|
||
|
// Only try to send if the buffer is empty and there are no messages.
|
||
|
/////////////////////////////////////////////////////////////////////
|
||
|
if(!(peer->outputBuffer.len - peer->outputBuffer.pos) && !ArrayLength(peer->messages))
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
CHECK_RESULT(gpiSendData(connection, peer->sock, &string[total], remaining, &closed, &sent, "PT"));
|
||
|
if(sent)
|
||
|
{
|
||
|
total += sent;
|
||
|
remaining -= sent;
|
||
|
}
|
||
|
}
|
||
|
while(sent && remaining);
|
||
|
}
|
||
|
|
||
|
// Buffer what wasn't sent.
|
||
|
///////////////////////////
|
||
|
if(remaining)
|
||
|
CHECK_RESULT(gpiAppendStringToBufferLen(connection, &peer->outputBuffer, &string[total], remaining));
|
||
|
|
||
|
|
||
|
GSI_UNUSED(stringLen);
|
||
|
GSI_UNUSED(string);
|
||
|
GSI_UNUSED(peer);
|
||
|
GSI_UNUSED(connection);
|
||
|
return GP_NO_ERROR;
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
GPResult
|
||
|
gpiSendOrBufferString(
|
||
|
GPConnection * connection,
|
||
|
GPIPeer_st peer,
|
||
|
char * string
|
||
|
)
|
||
|
{
|
||
|
return gpiSendOrBufferStringLenToPeer(connection, peer, string, (int)strlen(string));
|
||
|
}
|
||
|
|
||
|
GPResult
|
||
|
gpiSendOrBufferInt(
|
||
|
GPConnection * connection,
|
||
|
GPIPeer_st peer,
|
||
|
int num
|
||
|
)
|
||
|
{
|
||
|
char intValue[16];
|
||
|
sprintf(intValue,"%d",num);
|
||
|
return gpiSendOrBufferString(connection, peer, intValue);
|
||
|
}
|
||
|
|
||
|
GPResult
|
||
|
gpiSendOrBufferUInt(
|
||
|
GPConnection * connection,
|
||
|
GPIPeer_st peer,
|
||
|
unsigned int num
|
||
|
)
|
||
|
{
|
||
|
char intValue[16];
|
||
|
sprintf(intValue,"%u",num);
|
||
|
return gpiSendOrBufferString(connection, peer, intValue);
|
||
|
}
|
||
|
|
||
|
GPResult
|
||
|
gpiRecvToBuffer(
|
||
|
GPConnection * connection,
|
||
|
SOCKET sock,
|
||
|
GPIBuffer * inputBuffer,
|
||
|
int * bytesRead,
|
||
|
GPIBool * connClosed,
|
||
|
char id[3]
|
||
|
)
|
||
|
{
|
||
|
char * buffer;
|
||
|
int len;
|
||
|
int size;
|
||
|
int rcode;
|
||
|
int total;
|
||
|
GPIBool closed;
|
||
|
|
||
|
assert(sock != INVALID_SOCKET);
|
||
|
assert(inputBuffer != NULL);
|
||
|
assert(bytesRead != NULL);
|
||
|
assert(connClosed != NULL);
|
||
|
|
||
|
// Init locals.
|
||
|
///////////////
|
||
|
buffer = inputBuffer->buffer;
|
||
|
len = inputBuffer->len;
|
||
|
size = inputBuffer->size;
|
||
|
total = 0;
|
||
|
closed = GPIFalse;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
// Check if the buffer needs to be resized.
|
||
|
///////////////////////////////////////////
|
||
|
if((len + GPI_READ_SIZE) > size)
|
||
|
{
|
||
|
size = (len + GPI_READ_SIZE);
|
||
|
buffer = (char *)gsirealloc(buffer, (unsigned int)size + 1);
|
||
|
if(buffer == NULL)
|
||
|
Error(connection, GP_MEMORY_ERROR, "Out of memory.");
|
||
|
}
|
||
|
|
||
|
// Read from the network.
|
||
|
rcode = recv(sock, &buffer[len], size - len, 0);
|
||
|
|
||
|
|
||
|
if(gsiSocketIsError(rcode))
|
||
|
{
|
||
|
int error = GOAGetLastError(sock);
|
||
|
if((error != WSAEWOULDBLOCK) && (error != WSAEINPROGRESS) && (error != WSAETIMEDOUT) )
|
||
|
{
|
||
|
Error(connection, GP_NETWORK_ERROR, "There was an error reading from a socket.");
|
||
|
}
|
||
|
}
|
||
|
else if(rcode == 0)
|
||
|
{
|
||
|
// Check for a closed connection.
|
||
|
/////////////////////////////////
|
||
|
closed = GPITrue;
|
||
|
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_Comment,
|
||
|
"RECVXXXX(%s): Connection closed\n", id);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
#if defined(GPI_DUMP_NET_TRAFFIC) && defined(GSI_COMMON_DEBUG)
|
||
|
{
|
||
|
static int recvCount;
|
||
|
char *buf = (char *)gsimalloc((size_t)(rcode + 1));
|
||
|
memcpy(buf, &buffer[len], (size_t)rcode);
|
||
|
buf[rcode] = '\0';
|
||
|
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump,
|
||
|
"RECV%04d(%s): %s\n", recvCount++, id, buf);
|
||
|
freeclear(buf);
|
||
|
}
|
||
|
#elif defined(GSI_COMMON_DEBUG)
|
||
|
{
|
||
|
static int recvCount;
|
||
|
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump,
|
||
|
"RECV%04d(%s): %d\n", recvCount++, id, rcode);
|
||
|
}
|
||
|
#endif
|
||
|
// Update the buffer len.
|
||
|
/////////////////////////
|
||
|
len += rcode;
|
||
|
|
||
|
// Update the total.
|
||
|
////////////////////
|
||
|
total += rcode;
|
||
|
}
|
||
|
|
||
|
buffer[len] = '\0';
|
||
|
}
|
||
|
while((rcode >= 0) && !closed && (total < (128 * 1024)));
|
||
|
|
||
|
if(total)
|
||
|
{
|
||
|
gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_RawDump,
|
||
|
"RECVTOTL(%s): %d\n", id, total);
|
||
|
}
|
||
|
|
||
|
// Set output stuff.
|
||
|
////////////////////
|
||
|
inputBuffer->buffer = buffer;
|
||
|
inputBuffer->len = len;
|
||
|
inputBuffer->size = size;
|
||
|
*bytesRead = total;
|
||
|
*connClosed = closed;
|
||
|
|
||
|
GSI_UNUSED(id); //to get rid of codewarrior warnings
|
||
|
|
||
|
return GP_NO_ERROR;
|
||
|
}
|
||
|
|
||
|
GPResult
|
||
|
gpiSendFromBuffer(
|
||
|
GPConnection * connection,
|
||
|
SOCKET sock,
|
||
|
GPIBuffer * outputBuffer,
|
||
|
GPIBool * connClosed,
|
||
|
GPIBool clipSentData,
|
||
|
char id[3]
|
||
|
)
|
||
|
{
|
||
|
GPIBool closed;
|
||
|
int sent;
|
||
|
int total;
|
||
|
int remaining;
|
||
|
char * buffer;
|
||
|
int pos;
|
||
|
int len;
|
||
|
|
||
|
assert(outputBuffer != NULL);
|
||
|
|
||
|
buffer = outputBuffer->buffer;
|
||
|
len = outputBuffer->len;
|
||
|
pos = outputBuffer->pos;
|
||
|
remaining = (len - pos);
|
||
|
total = 0;
|
||
|
|
||
|
// Check for nothing to send.
|
||
|
/////////////////////////////
|
||
|
if(remaining == 0)
|
||
|
return GP_NO_ERROR;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
CHECK_RESULT(gpiSendData(connection, sock, &buffer[pos + total], remaining, &closed, &sent, id));
|
||
|
if(sent)
|
||
|
{
|
||
|
total += sent;
|
||
|
remaining -= sent;
|
||
|
}
|
||
|
}
|
||
|
while(sent && remaining);
|
||
|
|
||
|
if(clipSentData)
|
||
|
{
|
||
|
if(total > 0)
|
||
|
{
|
||
|
memmove(buffer, &buffer[total], (unsigned int)remaining + 1);
|
||
|
len -= total;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pos += total;
|
||
|
}
|
||
|
|
||
|
assert(len >= 0);
|
||
|
assert(pos >= 0);
|
||
|
assert(pos <= len);
|
||
|
|
||
|
// Set outputs.
|
||
|
///////////////
|
||
|
outputBuffer->len = len;
|
||
|
outputBuffer->pos = pos;
|
||
|
if(connClosed)
|
||
|
*connClosed = closed;
|
||
|
|
||
|
return GP_NO_ERROR;
|
||
|
}
|
||
|
|
||
|
GPResult gpiSendBufferToPeer(GPConnection * connection, unsigned int ip, unsigned short port,
|
||
|
GPIBuffer * outputBuffer, GPIBool *closed, GPIBool clipSentData)
|
||
|
{
|
||
|
GPIConnection *iconnection = (GPIConnection *)*connection;
|
||
|
//GPIBool closed;
|
||
|
unsigned int remaining;
|
||
|
unsigned char * buffer;
|
||
|
unsigned int pos;
|
||
|
unsigned int len;
|
||
|
unsigned int total = 0;
|
||
|
GSUdpPeerState aPeerState;
|
||
|
assert(outputBuffer != NULL);
|
||
|
|
||
|
buffer = (unsigned char *)outputBuffer->buffer;
|
||
|
len = (unsigned int)outputBuffer->len;
|
||
|
pos = (unsigned int)outputBuffer->pos;
|
||
|
remaining = (len - pos);
|
||
|
|
||
|
// Check for nothing to send.
|
||
|
/////////////////////////////
|
||
|
if(remaining == 0)
|
||
|
return GP_NO_ERROR;
|
||
|
|
||
|
// length of message remaining must be smaller than total buffer size minus gt2 reliable msg header size minus
|
||
|
// in order to send the message in one shot.
|
||
|
if ((int)remaining <= (gsUdpEngineGetPeerOutBufferFreeSpace(ip, port) - GS_UDP_RELIABLE_MSG_HEADER - GS_UDP_MSG_HEADER_LEN))
|
||
|
{
|
||
|
gsUdpEngineSendMessage(ip, port, iconnection->mHeader, &buffer[pos], remaining, gsi_true);
|
||
|
total = remaining;
|
||
|
remaining = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
unsigned int freeSpace =0;
|
||
|
unsigned int sendAmount = 0;
|
||
|
do
|
||
|
{
|
||
|
freeSpace = (unsigned int)gsUdpEngineGetPeerOutBufferFreeSpace(ip, port);
|
||
|
sendAmount = freeSpace - (GS_UDP_MSG_HEADER_LEN + GS_UDP_RELIABLE_MSG_HEADER);
|
||
|
if (sendAmount <= (GS_UDP_MSG_HEADER_LEN + GS_UDP_RELIABLE_MSG_HEADER))
|
||
|
break;
|
||
|
if (gsUdpEngineSendMessage(ip, port, iconnection->mHeader, &buffer[pos+total], sendAmount, gsi_true) == GS_UDP_SEND_FAILED)
|
||
|
break;
|
||
|
total += sendAmount;
|
||
|
remaining -= sendAmount;
|
||
|
}while (remaining);
|
||
|
}
|
||
|
|
||
|
if(clipSentData)
|
||
|
{
|
||
|
if (total > 0)
|
||
|
{
|
||
|
memmove(buffer, &buffer[total], remaining + 1);
|
||
|
len -= total;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pos += total;
|
||
|
}
|
||
|
// Set outputs.
|
||
|
///////////////
|
||
|
outputBuffer->len = (int)len;
|
||
|
outputBuffer->pos = (int)pos;
|
||
|
|
||
|
gsUdpEngineGetPeerState(ip, port, &aPeerState);
|
||
|
if (aPeerState == GS_UDP_PEER_CLOSED)
|
||
|
*closed = GPITrue;
|
||
|
else
|
||
|
*closed = GPIFalse;
|
||
|
|
||
|
return GP_NO_ERROR;
|
||
|
}
|
||
|
|
||
|
GPResult
|
||
|
gpiReadMessageFromBuffer(
|
||
|
GPConnection * connection,
|
||
|
GPIBuffer * inputBuffer,
|
||
|
char ** message,
|
||
|
int * type,
|
||
|
int * plen
|
||
|
)
|
||
|
{
|
||
|
char * str;
|
||
|
int len;
|
||
|
char intValue[16];
|
||
|
|
||
|
// Default.
|
||
|
///////////
|
||
|
*message = NULL;
|
||
|
|
||
|
// Check for not enough data.
|
||
|
/////////////////////////////
|
||
|
if(inputBuffer->len < 5)
|
||
|
return GP_NO_ERROR;
|
||
|
|
||
|
// Find the end of the header.
|
||
|
//////////////////////////////
|
||
|
str = strchr(inputBuffer->buffer, '\n');
|
||
|
if(str != NULL)
|
||
|
{
|
||
|
// Check that this is the msg.
|
||
|
//////////////////////////////
|
||
|
if(strncmp(str - 5, "\\msg\\", 5) != 0)
|
||
|
return GP_NETWORK_ERROR;
|
||
|
|
||
|
// Cap the header.
|
||
|
//////////////////
|
||
|
*str = '\0';
|
||
|
|
||
|
// Read the header.
|
||
|
///////////////////
|
||
|
if(!gpiValueForKey(inputBuffer->buffer, "\\m\\", intValue, sizeof(intValue)))
|
||
|
return GP_NETWORK_ERROR;
|
||
|
*type = atoi(intValue);
|
||
|
|
||
|
// Get the length.
|
||
|
//////////////////
|
||
|
if(!gpiValueForKey(inputBuffer->buffer, "\\len\\", intValue, sizeof(intValue)))
|
||
|
return GP_NETWORK_ERROR;
|
||
|
len = atoi(intValue);
|
||
|
len++;
|
||
|
|
||
|
// Is the whole message available?
|
||
|
//////////////////////////////////
|
||
|
if(inputBuffer->len > ((str - inputBuffer->buffer) + len))
|
||
|
{
|
||
|
// Does it not end with a NUL?
|
||
|
//////////////////////////////
|
||
|
if(str[len] != '\0')
|
||
|
return GP_NETWORK_ERROR;
|
||
|
|
||
|
// Set the message stuff.
|
||
|
/////////////////////////
|
||
|
*message = &str[1];
|
||
|
*plen = (len - 1);
|
||
|
|
||
|
// Set the position to the end of the message.
|
||
|
//////////////////////////////////////////////
|
||
|
inputBuffer->pos = ((str - inputBuffer->buffer) + len + 1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Put the LF back.
|
||
|
///////////////////
|
||
|
*str = '\n';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
GSI_UNUSED(connection);
|
||
|
return GP_NO_ERROR;
|
||
|
}
|
||
|
|
||
|
GPResult
|
||
|
gpiClipBufferToPosition(
|
||
|
GPConnection * connection,
|
||
|
GPIBuffer * buffer
|
||
|
)
|
||
|
{
|
||
|
if(!buffer || !buffer->buffer || !buffer->pos)
|
||
|
return GP_NO_ERROR;
|
||
|
|
||
|
buffer->len -= buffer->pos;
|
||
|
if(buffer->len)
|
||
|
memmove(buffer->buffer, buffer->buffer + buffer->pos, (unsigned int)buffer->len);
|
||
|
buffer->buffer[buffer->len] = '\0';
|
||
|
buffer->pos = 0;
|
||
|
|
||
|
GSI_UNUSED(connection);
|
||
|
return GP_NO_ERROR;
|
||
|
}
|