00001 #include <unistd.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 #include <errno.h>
00005
00006 #include "../../include/client.h"
00007 #include "../../include/monitor.h"
00008
00009 #define GET_MULTIPLIER(size) (((size) - 1) / READBUFSIZE + 1)
00010
00011 static int
00012 _clientReallocBuffer(tClient * client, unsigned int newSize)
00013 {
00014 unsigned int newMult = GET_MULTIPLIER(newSize);
00015
00016 if (CLIENTMULTMAX < newMult) {
00017
00018 return 0;
00019 }
00020
00021 if (client->readBufMult < newMult) {
00022
00023 char * newBuffer = calloc(newMult * READBUFSIZE, sizeof(char));
00024
00025 if (NULL == newBuffer) {
00026 syslogMonitor(LOG_ERR, MON_CRITICAL, "calloc",
00027 "calloc for readbuffer[%s] failed",
00028 client->remoteAddr);
00029
00030 exit(EXIT_FAILURE);
00031 }
00032
00033 if (NULL != client->readBuffer) {
00034 memcpy(newBuffer, client->readBuffer, client->readPos);
00035 free(client->readBuffer);
00036
00037 client->readBuffer = newBuffer;
00038 client->readBufMult = newMult;
00039 } else {
00040
00041
00042
00043
00044 newMult = client->readBufMult;
00045 }
00046
00047 }
00048
00049 return newMult;
00050 }
00051
00052 int
00053 clientRead(tClient * client)
00054 {
00055 int readSize;
00056 char readBuf[READBUFSIZE];
00057
00058
00059
00060
00061 memset(readBuf, 0, READBUFSIZE);
00062 readSize = read(client->socket, readBuf, READBUFSIZE);
00063
00064 switch (readSize) {
00065 case -1:
00066 syslogMonitor(LOG_WARNING, MON_WARNING, "socket.read",
00067 "read returns -1 for client[%s]: %s - connection closed",
00068 client->remoteAddr, strerror(errno));
00069 break;
00070
00071 case 0:
00072 break;
00073
00074 default:
00075 if (!_clientReallocBuffer(client, client->readPos + readSize)) {
00076 syslogMonitor(LOG_WARNING, MON_WARNING, "data.longline",
00077 "got to long line from client[%s] - connection closed",
00078 client->remoteAddr);
00079
00080 return READ_ERR_LONGLINE;
00081 }
00082
00083 if (client->readPos +readSize > client->readBufMult *READBUFSIZE) {
00084 syslogMonitor(LOG_WARNING, MON_WARNING, "data.longline",
00085 "can't allocate enough memory for read on client[%s]"
00086 " - connection closed",
00087 client->remoteAddr);
00088
00089 return READ_ERR_MEMORY;
00090 }
00091
00092 memcpy(client->readBuffer+client->readPos, readBuf, readSize);
00093 client->readPos += readSize;
00094 break;
00095 }
00096
00097 return readSize;
00098 }
00099
00100 #define EOB(client,addr) ((addr) -(client)->readBuffer >= (client)->readPos)
00101 #define REMAINING(client,addr) ((client)->readPos - ((addr) - (client)->readBuffer))
00102
00103 static char *
00104 _clientGetLineDelimiter(tClient * client, const char * delim, unsigned int len)
00105 {
00106 char * foundDelim = memchr(client->readBuffer, delim[0], client->readPos);
00107
00108 while (NULL != foundDelim && !EOB(client, foundDelim)) {
00109
00110 unsigned int i = 0;
00111
00112 while (i < len && !EOB(client, &(foundDelim[i])) && foundDelim[i] == delim[i]) i++;
00113
00114 if (i == len) {
00115 return foundDelim;
00116 } else {
00117 if (!EOB(client, ++foundDelim)) {
00118 foundDelim = memchr(foundDelim, delim[0], REMAINING(client, foundDelim));
00119 }
00120 }
00121 }
00122
00123 return NULL;
00124 }
00125
00126
00127
00128
00129
00130
00131
00132 char *
00133 clientConsumeLine(tClient * client, const char * delim, unsigned int * len)
00134 {
00135 char * found = clientGetLine(client, delim, len);
00136 char * line = NULL;
00137
00138 if (NULL != found) {
00139 line = calloc(*len +1, sizeof(char));
00140 clientRemoveLine(client, delim, len);
00141 memcpy(line, found, *len);
00142 }
00143
00144 return line;
00145 }
00146
00147
00148
00149
00150 char *
00151 clientGetLine(tClient * client, const char * delim, unsigned int * len)
00152 {
00153 char * foundDelim = _clientGetLineDelimiter(client, delim, *len);
00154
00155 if (NULL != foundDelim) {
00156 *len = foundDelim -client->readBuffer -1;
00157 return client->readBuffer;
00158 }
00159
00160 return NULL;
00161 }
00162
00163 char *
00164 clientRemoveLine(tClient * client, const char * delim, unsigned int * len)
00165 {
00166 unsigned int lineLen;
00167 char * foundDelim = _clientGetLineDelimiter(client, delim, &lineLen);
00168
00169 if (NULL != foundDelim) {
00170 char * actAddr = client->readBuffer +client->readPos;
00171
00172 if (actAddr == foundDelim +*len) {
00173
00174 memset(client->readBuffer, 0, client->readPos);
00175 *len = client->readPos = 0;
00176
00177 } else {
00178
00179 unsigned int moveSize = actAddr -foundDelim -*len;
00180 unsigned int clearSize = actAddr -client->readBuffer -moveSize;
00181
00182 memmove(client->readBuffer, foundDelim +*len, moveSize);
00183 memset(client->readBuffer +moveSize, 0, clearSize);
00184 *len = client->readPos = moveSize;
00185 }
00186
00187 return client->readBuffer;
00188 }
00189
00190 return NULL;
00191 }
00192