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
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;
|
|
}
|
|
|