An xmlrpc test project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

192 lines
5.2 KiB

#include <unistd.h> /* for getopt */
#include <stdlib.h> /* for exit */
#include <string.h> /* for memset and stuff */
#include <errno.h> /* for errno */
#include "../../include/client.h"
#include "../../include/monitor.h"
#define GET_MULTIPLIER(size) (((size) - 1) / READBUFSIZE + 1)
static int
_clientReallocBuffer(tClient * client, unsigned int newSize)
{
unsigned int newMult = GET_MULTIPLIER(newSize);
if (CLIENTMULTMAX < newMult) {
/* line exceeds maximum line length */
return 0;
}
if (client->readBufMult < newMult) {
char * newBuffer = calloc(newMult * READBUFSIZE, sizeof(char));
if (NULL == newBuffer) {
syslogMonitor(LOG_ERR, MON_CRITICAL, "calloc",
"calloc for readbuffer[%s] failed",
client->remoteAddr);
exit(EXIT_FAILURE);
}
if (NULL != client->readBuffer) {
memcpy(newBuffer, client->readBuffer, client->readPos);
free(client->readBuffer);
client->readBuffer = newBuffer;
client->readBufMult = newMult;
} else {
/*
* we can't get the resized buffer so return the
* old multiplier
*/
newMult = client->readBufMult;
}
}
return newMult;
}
int
clientRead(tClient * client)
{
int readSize;
char readBuf[READBUFSIZE];
/*
* initialize values // read data from socket
*/
memset(readBuf, 0, READBUFSIZE);
readSize = read(client->socket, readBuf, READBUFSIZE);
switch (readSize) {
case -1:
syslogMonitor(LOG_WARNING, MON_WARNING, "socket.read",
"read returns -1 for client[%s]: %s - connection closed",
client->remoteAddr, strerror(errno));
break;
case 0:
break;
default:
if (!_clientReallocBuffer(client, client->readPos + readSize)) {
syslogMonitor(LOG_WARNING, MON_WARNING, "data.longline",
"got to long line from client[%s] - connection closed",
client->remoteAddr);
return READ_ERR_LONGLINE;
}
if (client->readPos +readSize > client->readBufMult *READBUFSIZE) {
syslogMonitor(LOG_WARNING, MON_WARNING, "data.longline",
"can't allocate enough memory for read on client[%s]"
" - connection closed",
client->remoteAddr);
return READ_ERR_MEMORY;
}
memcpy(client->readBuffer+client->readPos, readBuf, readSize);
client->readPos += readSize;
break;
}
return readSize;
}
#define EOB(client,addr) ((addr) -(client)->readBuffer >= (client)->readPos)
#define REMAINING(client,addr) ((client)->readPos - ((addr) - (client)->readBuffer))
static char *
_clientGetLineDelimiter(tClient * client, const char * delim, unsigned int len)
{
char * foundDelim = memchr(client->readBuffer, delim[0], client->readPos);
while (NULL != foundDelim && !EOB(client, foundDelim)) {
unsigned int i = 0;
while (i < len && !EOB(client, &(foundDelim[i])) && foundDelim[i] == delim[i]) i++;
if (i == len) {
return foundDelim;
} else {
if (!EOB(client, ++foundDelim)) {
foundDelim = memchr(foundDelim, delim[0], REMAINING(client, foundDelim));
}
}
}
return NULL;
}
/*
* this returns a newly allocate buffer, with the found line
* copied to it.
* The caller has to take care to free this buffer again,
* after he uses it.
*/
char *
clientConsumeLine(tClient * client, const char * delim, unsigned int * len)
{
char * found = clientGetLine(client, delim, len);
char * line = NULL;
if (NULL != found) {
line = calloc(*len +1, sizeof(char));
clientRemoveLine(client, delim, len);
memcpy(line, found, *len);
}
return line;
}
/*
* as a side effect this gives sets length of the found line in len
*/
char *
clientGetLine(tClient * client, const char * delim, unsigned int * len)
{
char * foundDelim = _clientGetLineDelimiter(client, delim, *len);
if (NULL != foundDelim) {
*len = foundDelim -client->readBuffer -1;
return client->readBuffer;
}
return NULL;
}
char *
clientRemoveLine(tClient * client, const char * delim, unsigned int * len)
{
unsigned int lineLen;
char * foundDelim = _clientGetLineDelimiter(client, delim, &lineLen);
if (NULL != foundDelim) {
char * actAddr = client->readBuffer +client->readPos;
if (actAddr == foundDelim +*len) {
memset(client->readBuffer, 0, client->readPos);
*len = client->readPos = 0;
} else {
unsigned int moveSize = actAddr -foundDelim -*len;
unsigned int clearSize = actAddr -client->readBuffer -moveSize;
memmove(client->readBuffer, foundDelim +*len, moveSize);
memset(client->readBuffer +moveSize, 0, clearSize);
*len = client->readPos = moveSize;
}
return client->readBuffer;
}
return NULL;
}