clientRead.c
5.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#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;
}
/*
* fill a buffer from a stream. This call might not fill the whole
* buffer at once, as not len size data might have been written to
* the stream. In this case it returns a pointer to the position
* the next read has to occur.
* SIDEEFFECT: additially *len is set to the remaining size to read.
*/
char *
clientGetBuffer(tClient * client, char * buffer, unsigned int * len)
{
}