Showing
32 changed files
with
1687 additions
and
0 deletions
Makefile
0 → 100644
1 | +PROJECT = xmlrpc | |
2 | +INCLUDE = include | |
3 | +CFLAGS = -Wall -ggdb | |
4 | + | |
5 | +### | |
6 | +# PROJECT CONFIG | |
7 | +# | |
8 | +SUBDIRS = system server reader | |
9 | + | |
10 | +system_OBJ = daemonize.o handleCmdLine.o logRotate.o monitor.o \ | |
11 | + signalHandling.o socket.o | |
12 | +server_OBJ = serverInit.o serverRun.o serverShutdown.o | |
13 | +commonReader_OBJ = clientClose.o clientRead.o writeBuffer.o | |
14 | +httpReader_OBJ = httpRequest.o | |
15 | + | |
16 | +VPATH=$(INCLUDE) | |
17 | + | |
18 | +export CFLAGS INCLUDE \ | |
19 | + system_OBJ server_OBJ commonReader_OBJ httpReader_OBJ | |
20 | + | |
21 | +OBJECTS=$(PROJECT).o \ | |
22 | + $(addprefix system/,$(system_OBJ)) \ | |
23 | + $(addprefix server/,$(server_OBJ)) \ | |
24 | + $(addprefix reader/commonReader/,$(commonReader_OBJ)) \ | |
25 | + $(addprefix reader/httpReader/,$(httpReader_OBJ)) | |
26 | + | |
27 | +### | |
28 | +# EXPLICIT RULES | |
29 | +# | |
30 | +$(PROJECT): $(PROJECT).o subdirs | |
31 | + gcc $(CFLAGS) -o $(PROJECT) -lexpat $(OBJECTS) | |
32 | + | |
33 | +$(PROJECT).o: server.h monitor.h signalHandling.h daemonize.h appConfig.h | |
34 | + | |
35 | +### | |
36 | +# IMPLICIT RULES | |
37 | +# | |
38 | +%.o: %.c | |
39 | + gcc $(CFLAGS) -c $< -o $@ | |
40 | + | |
41 | +### | |
42 | +# PHONYS | |
43 | +# | |
44 | +.PHONY: clean subdirs subdirs_clean $(SUBDIRS) | |
45 | + | |
46 | +subdirs: $(SUBDIRS) | |
47 | + | |
48 | +$(SUBDIRS): | |
49 | + $(MAKE) -C $@ | |
50 | + | |
51 | +subdirs_clean: | |
52 | + for dir in $(SUBDIRS); do \ | |
53 | + $(MAKE) -C $$dir clean; \ | |
54 | + done | |
55 | + | |
56 | +clean: subdirs_clean | |
57 | + -rm *.o | ... | ... |
TODO
0 → 100644
1 | +integrate libicu for unicode support | |
2 | + | |
3 | +integrate the http parsing process into the stream reading process at all | |
4 | + that is...a http parser is nothing else than a specialized stream reader | |
5 | + | |
6 | +decouple all parts so that they are reusable at all...especially don't expect | |
7 | + a structure from one subcomponent as prereuqisite for another. | |
8 | + | |
9 | +read trailing newlines from a request and ignore them instead of heading. | |
10 | + Heading newlines as long as other trailing chars than newlines should throw | |
11 | + an error as they are not specified within protocol. | |
12 | + Throw in this case is: write an HTTP Error code back on the connection and | |
13 | + close it as we don't expect any more sane data from it. | |
14 | + | |
15 | +implement XMLRPC to C and vice versa argument mapping in some form... | |
16 | + in this process implement the XML parsing, i already use libexpat but only | |
17 | + as a testcase | |
18 | + | |
19 | +start multiple workers as paralell connectionts exceed a given limit. | |
20 | + This can be done if everything else works fine. | |
21 | + | |
22 | +make a lib and example application from most of this stuff to make it useable | |
23 | + from other projects. This again can be done later as long as i develope | |
24 | + with this goal in mind... | ... | ... |
include/appConfig.h
0 → 100644
1 | +#ifndef __APP_CONFIG_H__ | |
2 | +#define __APP_CONFIG_H__ | |
3 | + | |
4 | +#define MAXPENDING 10 /* Maximum outstanding connection requests */ | |
5 | +#define MAXCLIENTS 1000 /* Maximum connection handled in paralell */ | |
6 | +#define READBUFSIZE 2048 /* Size of receive buffer */ | |
7 | +#define DEFAULTPORT 8801 /* default port for service */ | |
8 | +#define DEFAULTPATH "logfiles" | |
9 | +#define LOGNAMEPATTERN "log-%Y-%m-%d_%Hh" | |
10 | + | |
11 | +#undef MAX | |
12 | +#define MAX(x,y) ((x) > (y) ? (x) : (y)) | |
13 | + | |
14 | +#undef MIN | |
15 | +#define MIN(x,y) ((x) < (y) ? (x) : (y)) | |
16 | + | |
17 | +typedef struct { | |
18 | + unsigned char verbose; | |
19 | + unsigned char doDaemon; | |
20 | + unsigned int maxPending; | |
21 | + unsigned int port; | |
22 | + char logPath[513]; | |
23 | + char namePat[513]; | |
24 | +} tAppConfig; | |
25 | + | |
26 | +int | |
27 | +handleCmdLine(tAppConfig * config, int argc, char *argv[]); | |
28 | + | |
29 | +#endif // __APP_CONFIG_H__ | ... | ... |
include/client.h
0 → 100644
1 | +#ifndef __CLIENT_H__ | |
2 | +#define __CLIENT_H__ | |
3 | + | |
4 | +#include <stdio.h> /* for FILE */ | |
5 | + | |
6 | +#include <expat.h> | |
7 | + | |
8 | +#include "httpRequest.h" | |
9 | + | |
10 | +#define READBUFSIZE 2048 /* Size of receive readBuffer */ | |
11 | +#define CLIENTMULTMAX 512U /* 1MB maximum size the readbuffer may grow */ | |
12 | + | |
13 | +#define READ_ERR_LONGLINE -2 | |
14 | +#define READ_ERR_MEMORY -3 | |
15 | + | |
16 | +extern int verbose; | |
17 | + | |
18 | +typedef struct { | |
19 | + int socket; | |
20 | + char * readBuffer; | |
21 | + char * writeBuffer; | |
22 | + unsigned int readPos; | |
23 | + unsigned int writePos; | |
24 | + unsigned int readBufMult; | |
25 | + char remoteAddr[16]; | |
26 | + | |
27 | + tHttpHeader httpHeader; | |
28 | + unsigned int bodyLenRemaining; | |
29 | + | |
30 | + XML_Parser parser; | |
31 | +} tClient; | |
32 | + | |
33 | + | |
34 | +void clientClose(tClient * client); | |
35 | +int clientRead(tClient * client); | |
36 | +int clientWrite(tClient * client); | |
37 | +char * clientGetLine(tClient *, const char *, unsigned int *); | |
38 | +char * clientRemoveLine(tClient *, const char *, unsigned int *); | |
39 | + | |
40 | +#endif // __CLIENT_H__ | ... | ... |
include/daemonize.h
0 → 100644
include/httpRequest.h
0 → 100644
1 | +#ifndef __HTTP_REQUEST_H__ | |
2 | +#define __HTTP_REQUEST_H__ | |
3 | + | |
4 | +#define HTTP_REQ_OPTIONS 0 | |
5 | +#define HTTP_REQ_GET 1 | |
6 | +#define HTTP_REQ_HEAD 2 | |
7 | +#define HTTP_REQ_POST 3 | |
8 | +#define HTTP_REQ_PUT 4 | |
9 | +#define HTTP_REQ_DELETE 5 | |
10 | +#define HTTP_REQ_TRACE 6 | |
11 | +#define HTTP_REQ_CONNECT 7 | |
12 | + | |
13 | +extern char httpRequest[8][8]; | |
14 | + | |
15 | + | |
16 | +typedef struct { | |
17 | + char * method; | |
18 | + char * requestUri; | |
19 | + char * httpVersion; | |
20 | +} tRequestLine; | |
21 | + | |
22 | +typedef struct { | |
23 | + char * key; | |
24 | + char * value; | |
25 | +} tHttpHeaderLine; | |
26 | + | |
27 | +typedef struct { | |
28 | + tRequestLine req; | |
29 | + tHttpHeaderLine * headers; | |
30 | + unsigned int headersCount; | |
31 | + | |
32 | + unsigned char bodyLength; | |
33 | +} tHttpHeader; | |
34 | + | |
35 | +typedef struct { | |
36 | + tHttpHeader header; | |
37 | + unsigned int length; | |
38 | + char * body; | |
39 | +} tHttpRequest; | |
40 | + | |
41 | + | |
42 | +int getHttpRequest(char **, unsigned int *, tHttpRequest *); | |
43 | +void freeHttpRequest(tHttpRequest *); | |
44 | +void freeHttpHeader(tHttpHeader *); | |
45 | +unsigned char httpHeaderIsStarted(tHttpHeader *); | |
46 | +int httpHeaderIsComplete(tHttpHeader *); | |
47 | +int httpHeaderGet(char **, unsigned int *, tHttpHeader *); | |
48 | +void httpHeaderParseRequestLine(tHttpHeader *, const char *, unsigned int); | |
49 | + | |
50 | +#endif // __HTTP_REQUEST_H__ | ... | ... |
include/logRotate.h
0 → 100644
include/monitor.h
0 → 100644
1 | +#ifndef __MONITOR_H__ | |
2 | +#define __MONITOR_H__ | |
3 | + | |
4 | +#include <syslog.h> /* for logging */ | |
5 | + | |
6 | +#define MON_INFO 0 | |
7 | +#define MON_WARNING 1 | |
8 | +#define MON_CRITICAL 2 | |
9 | +#define MON_FAILURE 3 | |
10 | + | |
11 | +int monitor(unsigned int sev, const char * pattern, const char * message); | |
12 | +int syslogMonitor (unsigned int logLvl, unsigned int sev, const char *pattern, const char * message, ...) __attribute__ ((format (printf, 4, 5))); | |
13 | + | |
14 | +#endif /* __MONITOR_H__ */ | ... | ... |
include/my.patch
0 → 100644
1 | +--- ../../xmlrpc/include/client.h 2010-08-12 20:15:42.000000000 +0200 | |
2 | ++++ ./include/virtualitemreceiver/client.h 2010-09-13 20:51:51.284184703 +0200 | |
3 | +@@ -3,31 +3,26 @@ | |
4 | + | |
5 | + #include <stdio.h> /* for FILE */ | |
6 | + | |
7 | +-#include <expat.h> | |
8 | ++#include <expat.h> | |
9 | ++#include "httpRequest.h" | |
10 | ++ | |
11 | ++#define READBUFSIZE 2048 /* Size of receive buffer */ | |
12 | ++#define CLIENTMULTMAX 512U /* 1MB maximum size the readbuffer may grow */ | |
13 | + | |
14 | +-#include "httpRequest.h" | |
15 | ++#define WRITE_ERR_IO -1 | |
16 | ++#define WRITE_ERR_NOPRINT -2 | |
17 | + | |
18 | +-#define READBUFSIZE 2048 /* Size of receive readBuffer */ | |
19 | +- | |
20 | +-extern int verbose; | |
21 | ++#define READ_ERR_LONGLINE -2 | |
22 | + | |
23 | + typedef struct { | |
24 | + int socket; | |
25 | +- char * readBuffer; | |
26 | +- char * writeBuffer; | |
27 | ++ char * readBuffer; | |
28 | ++ char * writeBuffer; | |
29 | + unsigned int readPos; | |
30 | +- unsigned int writePos; | |
31 | ++ unsigned int writePos; | |
32 | ++ unsigned int readBufMult; | |
33 | ++ unsigned int writeBufMult; | |
34 | + char remoteAddr[16]; | |
35 | + | |
36 | + tHttpHeader httpHeader; | |
37 | + unsigned int bodyLenRemaining; | |
38 | + | |
39 | + XML_Parser parser; | |
40 | + } tClient; | |
41 | + | |
42 | + | |
43 | +-void clientClose(tClient * client); | |
44 | +-int clientRead(tClient * client); | |
45 | +-int clientWrite(tClient * client); | |
46 | ++void clientClose(tClient *); | |
47 | ++int clientRead(tClient *); | |
48 | ++int writeRemaining(tClient *); | |
49 | ++int writeBuffer(tClient *); | |
50 | + | |
51 | + #endif // __CLIENT_H__ | ... | ... |
include/server.h
0 → 100644
1 | +#ifndef __SERVER_H__ | |
2 | +#define __SERVER_H__ | |
3 | + | |
4 | +#include <stdio.h> /* for printf() and fprintf() */ | |
5 | +#include <sys/select.h> /* for select system call and related */ | |
6 | + | |
7 | +#include "client.h" | |
8 | + | |
9 | +typedef struct { | |
10 | + int servSock; | |
11 | + tClient clients[FD_SETSIZE]; | |
12 | + unsigned int maxFd; | |
13 | + fd_set socks; | |
14 | + char logPath[512]; | |
15 | + char namePat[512]; | |
16 | + FILE * wHandle; | |
17 | +} tServer; | |
18 | + | |
19 | + | |
20 | +void serverShutdown(tServer * server); | |
21 | +void serverInit( | |
22 | + tServer * server, | |
23 | + unsigned int port, | |
24 | + unsigned int pending, | |
25 | + const char * logPath, | |
26 | + const char * namePat); | |
27 | +void serverRun(tServer * server); | |
28 | + | |
29 | +#endif // __SERVER_H__ | ... | ... |
include/signalHandling.h
0 → 100644
include/socket.h
0 → 100644
include/writeBuffer.h
0 → 100644
reader/Makefile
0 → 100644
1 | +SUBDIRS=commonReader httpReader | |
2 | + | |
3 | +.PHONY: all clean subdirs subdirs_clean $(SUBDIRS) | |
4 | + | |
5 | +all: $(SUBDIRS) | |
6 | + | |
7 | +subdirs: $(SUBDIRS) | |
8 | + | |
9 | +$(SUBDIRS): | |
10 | + $(MAKE) -C $@ | |
11 | + | |
12 | +subdirs_clean: | |
13 | + for dir in $(SUBDIRS); do \ | |
14 | + $(MAKE) -C $$dir clean; \ | |
15 | + done | |
16 | + | |
17 | +clean: subdirs_clean | ... | ... |
reader/commonReader/Makefile
0 → 100644
reader/commonReader/clientClose.c
0 → 100644
1 | +#include <stdlib.h> /* for free() */ | |
2 | +#include <unistd.h> /* for close() */ | |
3 | +#include <sys/socket.h> /* for shutdown() */ | |
4 | +#include <string.h> /* for memset and stuff */ | |
5 | + | |
6 | +#include <expat.h> | |
7 | + | |
8 | +#include "../../include/client.h" | |
9 | +#include "../../include/monitor.h" | |
10 | +#include "../../include/httpRequest.h" | |
11 | + | |
12 | +void clientClose(tClient * client) | |
13 | +{ | |
14 | + if (0 != verbose) { | |
15 | + syslog(LOG_INFO, "closing socket for %s", client->remoteAddr); | |
16 | + } | |
17 | + | |
18 | + /* close socket an remove from fd_set */ | |
19 | + shutdown(client->socket, SHUT_RDWR); | |
20 | + close(client->socket); | |
21 | + | |
22 | + /* free readBuffer */ | |
23 | + if (NULL != client->readBuffer) { | |
24 | + free(client->readBuffer); | |
25 | + client->readBuffer = NULL; | |
26 | + } | |
27 | + if (NULL != client->writeBuffer) { | |
28 | + free(client->writeBuffer); | |
29 | + client->writeBuffer = NULL; | |
30 | + } | |
31 | + client->readPos = 0; | |
32 | + client->writePos = 0; | |
33 | + | |
34 | + freeHttpHeader(&(client->httpHeader)); | |
35 | + | |
36 | + XML_ParserFree(client->parser); | |
37 | + | |
38 | + memset(client->remoteAddr, 0, 16); | |
39 | +} | ... | ... |
reader/commonReader/clientRead.c
0 → 100644
1 | +#include <unistd.h> /* for getopt */ | |
2 | +#include <stdlib.h> /* for exit */ | |
3 | +#include <string.h> /* for memset and stuff */ | |
4 | +#include <errno.h> /* for errno */ | |
5 | + | |
6 | +#include "../../include/client.h" | |
7 | +#include "../../include/monitor.h" | |
8 | + | |
9 | +#define GET_MULTIPLIER(size) (((size) - 1) / READBUFSIZE + 1) | |
10 | + | |
11 | +static int | |
12 | +_clientReallocBuffer(tClient * client, unsigned int newSize) | |
13 | +{ | |
14 | + unsigned int newMult = GET_MULTIPLIER(newSize); | |
15 | + | |
16 | + if (CLIENTMULTMAX < newMult) { | |
17 | + /* line exceeds maximum line length */ | |
18 | + return 0; | |
19 | + } | |
20 | + | |
21 | + if (client->readBufMult < newMult) { | |
22 | + | |
23 | + char * newBuffer = calloc(newMult * READBUFSIZE, sizeof(char)); | |
24 | + | |
25 | + if (NULL == newBuffer) { | |
26 | + syslogMonitor(LOG_ERR, MON_CRITICAL, "calloc", | |
27 | + "calloc for readbuffer[%s] failed", | |
28 | + client->remoteAddr); | |
29 | + | |
30 | + exit(EXIT_FAILURE); | |
31 | + } | |
32 | + | |
33 | + if (NULL != client->readBuffer) { | |
34 | + memcpy(newBuffer, client->readBuffer, client->readPos); | |
35 | + free(client->readBuffer); | |
36 | + | |
37 | + client->readBuffer = newBuffer; | |
38 | + client->readBufMult = newMult; | |
39 | + } else { | |
40 | + /* | |
41 | + * we can't get the resized buffer so return the | |
42 | + * old multiplier | |
43 | + */ | |
44 | + newMult = client->readBufMult; | |
45 | + } | |
46 | + | |
47 | + } | |
48 | + | |
49 | + return newMult; | |
50 | +} | |
51 | + | |
52 | +int | |
53 | +clientRead(tClient * client) | |
54 | +{ | |
55 | + int readSize; | |
56 | + char readBuf[READBUFSIZE]; | |
57 | + | |
58 | + /* | |
59 | + * initialize values // read data from socket | |
60 | + */ | |
61 | + memset(readBuf, 0, READBUFSIZE); | |
62 | + readSize = read(client->socket, readBuf, READBUFSIZE); | |
63 | + | |
64 | + switch (readSize) { | |
65 | + case -1: | |
66 | + syslogMonitor(LOG_WARNING, MON_WARNING, "socket.read", | |
67 | + "read returns -1 for client[%s]: %s - connection closed", | |
68 | + client->remoteAddr, strerror(errno)); | |
69 | + break; | |
70 | + | |
71 | + case 0: | |
72 | + break; | |
73 | + | |
74 | + default: | |
75 | + if (!_clientReallocBuffer(client, client->readPos + readSize)) { | |
76 | + syslogMonitor(LOG_WARNING, MON_WARNING, "data.longline", | |
77 | + "got to long line from client[%s] - connection closed", | |
78 | + client->remoteAddr); | |
79 | + | |
80 | + return READ_ERR_LONGLINE; | |
81 | + } | |
82 | + | |
83 | + if (client->readPos +readSize > client->readBufMult *READBUFSIZE) { | |
84 | + syslogMonitor(LOG_WARNING, MON_WARNING, "data.longline", | |
85 | + "can't allocate enough memory for read on client[%s]" | |
86 | + " - connection closed", | |
87 | + client->remoteAddr); | |
88 | + | |
89 | + return READ_ERR_MEMORY; | |
90 | + } | |
91 | + | |
92 | + memcpy(client->readBuffer+client->readPos, readBuf, readSize); | |
93 | + client->readPos += readSize; | |
94 | + break; | |
95 | + } | |
96 | + | |
97 | + return readSize; | |
98 | +} | |
99 | + | |
100 | +#define EOB(client,addr) ((addr) -(client)->readBuffer >= (client)->readPos) | |
101 | +#define REMAINING(client,addr) ((client)->readPos - ((addr) - (client)->readBuffer)) | |
102 | + | |
103 | +static char * | |
104 | +_clientGetLineDelimiter(tClient * client, const char * delim, unsigned int len) | |
105 | +{ | |
106 | + char * foundDelim = memchr(client->readBuffer, delim[0], client->readPos); | |
107 | + | |
108 | + while (NULL != foundDelim && !EOB(client, foundDelim)) { | |
109 | + | |
110 | + unsigned int i = 0; | |
111 | + | |
112 | + while (i < len && !EOB(client, &(foundDelim[i])) && foundDelim[i] == delim[i]) i++; | |
113 | + | |
114 | + if (i == len) { | |
115 | + return foundDelim; | |
116 | + } else { | |
117 | + if (!EOB(client, ++foundDelim)) { | |
118 | + foundDelim = memchr(foundDelim, delim[0], REMAINING(client, foundDelim)); | |
119 | + } | |
120 | + } | |
121 | + } | |
122 | + | |
123 | + return NULL; | |
124 | +} | |
125 | + | |
126 | +/* | |
127 | + * this returns a newly allocate buffer, with the found line | |
128 | + * copied to it. | |
129 | + * The calles has to take care to free this buffer again, | |
130 | + * after he uses it. | |
131 | + */ | |
132 | +char * | |
133 | +clientConsumeLine(tClient * client, const char * delim, unsigned int * len) | |
134 | +{ | |
135 | + char * found = clientGetLine(client, delin, len); | |
136 | + char * line = NULL; | |
137 | + | |
138 | + if (NULL != found) { | |
139 | + line = calloc(*len +1, sizeof(char)); | |
140 | + memcpy(line, found, *len); | |
141 | + } | |
142 | + | |
143 | + return line; | |
144 | +} | |
145 | + | |
146 | +/* | |
147 | + * as a side effect this gives sets length of the found line in len | |
148 | + */ | |
149 | +char * | |
150 | +clientGetLine(tClient * client, const char * delim, unsigned int * len) | |
151 | +{ | |
152 | + char * foundDelim = _clientGetLineDelimiter(client, delim, *len); | |
153 | + | |
154 | + if (NULL != foundDelim) { | |
155 | + *len = foundDelim -client->readBuffer -1; | |
156 | + return client->readBuffer; | |
157 | + } | |
158 | + | |
159 | + return NULL; | |
160 | +} | |
161 | + | |
162 | +char * | |
163 | +clientRemoveLine(tClient * client, const char * delim, unsigned int * len) | |
164 | +{ | |
165 | + unsigned int lineLen; | |
166 | + char * foundDelim = _clientGetLineDelimiter(client, delim, &lineLen); | |
167 | + | |
168 | + if (NULL != foundDelim) { | |
169 | + char * actAddr = client->readBuffer +client->readPos; | |
170 | + | |
171 | + if (actAddr == foundDelim +*len) { | |
172 | + | |
173 | + memset(client->readBuffer, 0, client->readPos); | |
174 | + *len = client->readPos = 0; | |
175 | + | |
176 | + } else { | |
177 | + | |
178 | + unsigned int moveSize = actAddr -foundDelim -*len; | |
179 | + unsigned int clearSize = actAddr -client->readBuffer -moveSize; | |
180 | + | |
181 | + memmove(client->readBuffer, foundDelim +*len, moveSize); | |
182 | + memset(client->readBuffer +moveSize, 0, clearSize); | |
183 | + *len = client->readPos = moveSize; | |
184 | + } | |
185 | + | |
186 | + return client->readBuffer; | |
187 | + } | |
188 | + | |
189 | + return NULL; | |
190 | +} | |
191 | + | |
192 | +/* | |
193 | + * fill a buffer from a stream. This call might not fill the whole | |
194 | + * buffer at once, as not len size data might have been written to | |
195 | + * the stream. In this case it returns a pointer to the position | |
196 | + * the next read has to occur. | |
197 | + * SIDEEFFECT: additially *len is set to the remaining size to read. | |
198 | + */ | |
199 | +char * | |
200 | +clientGetBuffer(tClient * client, char * buffer, unsigned int * len) | |
201 | +{ | |
202 | +} | ... | ... |
reader/commonReader/writeBuffer.c
0 → 100644
1 | +#include <stdio.h> /* for ferror() */ | |
2 | +#include <string.h> /* for memset and stuff */ | |
3 | + | |
4 | + | |
5 | +int | |
6 | +writeBuffer(char ** buffer, unsigned int * readPos, FILE * wHandle) | |
7 | +{ | |
8 | + char * nlpos = strchr(*buffer, '\n'); | |
9 | + int written = 0; | |
10 | + | |
11 | + while (NULL != nlpos) { | |
12 | + unsigned int moveSize, clearSize; | |
13 | + char * actAddr; | |
14 | + | |
15 | + *nlpos = '\0'; | |
16 | + | |
17 | + if (0 != strlen(*buffer)) { | |
18 | + /* write remaining stuff to file */ | |
19 | + fputs(*buffer, wHandle); | |
20 | + if (ferror(wHandle)) { | |
21 | + return -1; | |
22 | + } | |
23 | + | |
24 | + fputc('\n', wHandle); | |
25 | + if (ferror(wHandle)) { | |
26 | + return -1; | |
27 | + } | |
28 | + | |
29 | + fflush(wHandle); | |
30 | + if (ferror(wHandle)) { | |
31 | + return -1; | |
32 | + } | |
33 | + | |
34 | + written += strlen(*buffer) + 1; | |
35 | + } | |
36 | + | |
37 | + actAddr = *buffer + *readPos; | |
38 | + moveSize = actAddr - nlpos - 1; | |
39 | + clearSize = actAddr - *buffer - moveSize; | |
40 | + memmove(*buffer, nlpos+1, moveSize); | |
41 | + memset(*buffer + moveSize, 0, clearSize); | |
42 | + *readPos = moveSize; | |
43 | + | |
44 | + nlpos = strchr(*buffer, '\n'); | |
45 | + } | |
46 | + | |
47 | + return written; | |
48 | +} | ... | ... |
reader/httpReader/Makefile
0 → 100644
reader/httpReader/httpRequest.c
0 → 100644
1 | +#include <string.h> | |
2 | +#include <stdlib.h> | |
3 | +#include <stdio.h> | |
4 | +#include <ctype.h> | |
5 | + | |
6 | +#include "../../include/appConfig.h" | |
7 | +#include "../../include/httpRequest.h" | |
8 | +#include "../../include/client.h" | |
9 | + | |
10 | +#define SPACE 0x20 | |
11 | + | |
12 | + | |
13 | +char httpRequest[8][8] = { | |
14 | + "OPTIONS", | |
15 | + "GET", | |
16 | + "HEAD", | |
17 | + "POST", | |
18 | + "PUT", | |
19 | + "DELETE", | |
20 | + "TRACE", | |
21 | + "CONNECT" | |
22 | +}; | |
23 | + | |
24 | +/* | |
25 | + * Gedanken zum request einlese: | |
26 | + * der client liest stumpf daten, außerdem implementiert er eine Methode um die | |
27 | + * erste Zeile aus dem readbuffer zu entfernen. | |
28 | + * Des weiteren eine Methode getLine die NULL zurück gibt wenn noch keine Zeile | |
29 | + * komplett ist, ansonsten einen Pointer auf diese. | |
30 | + * Der servercode triggert das Daten lesen des client, versucht dann die erste | |
31 | + * Zeile zu lesen und gibt diese im erfolgsfall an den httpCode weiter um | |
32 | + * dann wenn dieser ein OK gibt die erste Zeile über den clientCode wieder zu entfernen. | |
33 | + * Leere Zeile vor der request line werden ignoriert. | |
34 | + * Ebenso leere Zailen nachdem der request komplett eingelesen ist. | |
35 | + * Nachdem alle Header Zeile eingelesen wurden...d.H. sobald eine leere Header Zeile | |
36 | + * gelesen wurde wird exakt bodyLength vom client versucht zu lesen...hierbei | |
37 | + * können die Daten die von client kommen in den body buffer übertragen werden. | |
38 | + * Dabei kann im client code der buffer immer entsprechend zurück gesetzt werden. | |
39 | + */ | |
40 | +int | |
41 | +httpHeaderGetLine(tHttpHeader * header, char ** buffer, unsigned int * readPos) | |
42 | +{ | |
43 | + return 1; | |
44 | +} | |
45 | + | |
46 | +void | |
47 | +httpHeaderParseRequestLine(tHttpHeader * header, const char * line, unsigned int len) | |
48 | +{ | |
49 | +} | |
50 | + | |
51 | +int | |
52 | +httpHeaderIsComplete(tHttpHeader * header) | |
53 | +{ | |
54 | + if (NULL == header->req.method) { | |
55 | + return 0; | |
56 | + } | |
57 | + | |
58 | + return 1; | |
59 | +} | |
60 | + | |
61 | +unsigned char | |
62 | +httpHeaderIsStarted(tHttpHeader * header) { | |
63 | + return 1; | |
64 | +} | |
65 | + | |
66 | +static void | |
67 | +httpRequestStrip(char ** buffer, unsigned int * readPos) | |
68 | +{ | |
69 | + char * end = *buffer; | |
70 | + | |
71 | + /* remove all surrounding CRLF */ | |
72 | + while (('\r' == *end || '\n' == *end) && *end) { | |
73 | + end++; | |
74 | + } | |
75 | + | |
76 | + if (end != *buffer) { | |
77 | + memmove(*buffer, end, *readPos - (end - *buffer)); | |
78 | + memset(*buffer, 0, end - *buffer); | |
79 | + | |
80 | + *readPos -= (end - * buffer); | |
81 | + } | |
82 | +} | |
83 | + | |
84 | +int | |
85 | +httpHeaderGet(char ** buffer, unsigned int * readPos, tHttpHeader * request) | |
86 | +{ | |
87 | + char * end = *buffer; | |
88 | + unsigned int readPosNew; | |
89 | + | |
90 | + httpRequestStrip(buffer, readPos); | |
91 | + end = strstr(*buffer, "\r\n\r\n"); | |
92 | + | |
93 | + /* get header if not already read and complete */ | |
94 | + if (!httpHeaderIsComplete(request) && NULL != end) { | |
95 | + /* get request line */ | |
96 | + char * methodEnd = strchr(*buffer, SPACE); | |
97 | + char * uriEnd = strchr(methodEnd + 1, SPACE); | |
98 | + char * lineEnd = strstr(*buffer, "\r\n"); | |
99 | + | |
100 | + request->req.method = | |
101 | + calloc(methodEnd-*buffer+1, sizeof(char)); | |
102 | + request->req.requestUri = | |
103 | + calloc(uriEnd-methodEnd, sizeof(char)); | |
104 | + request->req.httpVersion = | |
105 | + calloc(lineEnd-uriEnd, sizeof(char)); | |
106 | + | |
107 | + sscanf(*buffer, "%s %s %s\r\n", | |
108 | + request->req.method, | |
109 | + request->req.requestUri, | |
110 | + request->req.httpVersion); | |
111 | + | |
112 | + readPosNew = (*buffer + *readPos) - lineEnd - 2; | |
113 | + memmove(*buffer, lineEnd + 2, readPosNew); | |
114 | + memset(*buffer + readPosNew, 0, *readPos - readPosNew); | |
115 | + *readPos = readPosNew; | |
116 | + | |
117 | + /* get all header lines */ | |
118 | + do { | |
119 | + char * keyEnd = strchr(*buffer, ':'); | |
120 | + | |
121 | + lineEnd = strstr(*buffer, "\r\n"); | |
122 | + | |
123 | + if (lineEnd != *buffer) { | |
124 | + tHttpHeaderLine * actHeader; | |
125 | + char * actKey = NULL; | |
126 | + | |
127 | + request->headersCount += 1; | |
128 | + | |
129 | + request->headers = realloc(request->headers, | |
130 | + request->headersCount * sizeof(tHttpHeaderLine)); | |
131 | + actHeader = &(request->headers[request->headersCount-1]); | |
132 | + memset(actHeader, 0, sizeof(tHttpHeaderLine)); | |
133 | + | |
134 | + actKey = actHeader->key = calloc(keyEnd-*buffer+1, sizeof(char)); | |
135 | + actHeader->value = calloc(lineEnd-keyEnd-1, sizeof(char)); | |
136 | + | |
137 | + sscanf(*buffer, "%[^:]:%s\r\n", | |
138 | + actHeader->key, actHeader->value); | |
139 | + //while (NULL != actKey && *actKey != '\0' && (*actKey = tolower(*(actKey++)))); // strtolower | |
140 | + for (; NULL != actKey && *actKey != '\0'; actKey++) { | |
141 | + *actKey = tolower(*actKey); | |
142 | + } | |
143 | + | |
144 | + if (0 == strncmp("content-length", actHeader->key, strlen(actHeader->key))) { | |
145 | + request->bodyLength = atoi(actHeader->value); | |
146 | + } | |
147 | + } | |
148 | + | |
149 | + readPosNew = (*buffer + *readPos) - lineEnd - 2; | |
150 | + memmove(*buffer, lineEnd + 2, readPosNew); | |
151 | + memset(*buffer + readPosNew, 0, *readPos - readPosNew); | |
152 | + *readPos = readPosNew; | |
153 | + } while (lineEnd != *buffer); | |
154 | + | |
155 | + return request->bodyLength; | |
156 | + } | |
157 | + | |
158 | + return 0; | |
159 | +} | |
160 | + | |
161 | +int | |
162 | +getHttpRequest(char ** buffer, unsigned int * readPos, tHttpRequest * request) | |
163 | +{ | |
164 | + /* get body if header is read and body incomplete */ | |
165 | + if (request->header.bodyLength != request->length) { | |
166 | + size_t size = MIN( | |
167 | + request->header.bodyLength - request->length, | |
168 | + *readPos); | |
169 | + | |
170 | + if (0 != size) { | |
171 | + if (NULL == request->body) { | |
172 | + request->body = calloc(request->header.bodyLength, sizeof(char)); | |
173 | + } | |
174 | + | |
175 | + memcpy(request->body + request->length, *buffer, size); | |
176 | + memmove(*buffer, *buffer + size, *readPos - size); | |
177 | + memset(*buffer + (*readPos - size), 0, size); | |
178 | + *readPos -= size; | |
179 | + request->length += size; | |
180 | + } | |
181 | + } | |
182 | + | |
183 | + return 0; | |
184 | +} | |
185 | + | |
186 | +void | |
187 | +freeHttpHeader(tHttpHeader * header) { | |
188 | + unsigned int i; | |
189 | + | |
190 | + if (NULL != header->req.method) { | |
191 | + free(header->req.method); | |
192 | + } | |
193 | + if (NULL != header->req.requestUri) { | |
194 | + free(header->req.requestUri); | |
195 | + } | |
196 | + if (NULL != header->req.httpVersion) { | |
197 | + free(header->req.httpVersion); | |
198 | + } | |
199 | + | |
200 | + for (i=0; i<header->headersCount; i++) { | |
201 | + if (NULL != header->headers[i].key) { | |
202 | + free(header->headers[i].key); | |
203 | + } | |
204 | + if (NULL != header->headers[i].value) { | |
205 | + free(header->headers[i].value); | |
206 | + } | |
207 | + } | |
208 | + | |
209 | + if (NULL != header->headers) { | |
210 | + free(header->headers); | |
211 | + } | |
212 | + | |
213 | + memset (header, 0, sizeof (tHttpHeader)); | |
214 | +} | |
215 | + | |
216 | +void | |
217 | +freeHttpRequest(tHttpRequest * request) { | |
218 | + unsigned int i; | |
219 | + | |
220 | + if (NULL != request->header.req.method) { | |
221 | + free(request->header.req.method); | |
222 | + request->header.req.method = NULL; | |
223 | + } | |
224 | + if (NULL != request->header.req.requestUri) { | |
225 | + free(request->header.req.requestUri); | |
226 | + request->header.req.requestUri = NULL; | |
227 | + } | |
228 | + if (NULL != request->header.req.httpVersion) { | |
229 | + free(request->header.req.httpVersion); | |
230 | + request->header.req.httpVersion = NULL; | |
231 | + } | |
232 | + | |
233 | + for (i=0; i<request->header.headersCount; i++) { | |
234 | + if (NULL != request->header.headers[i].key) { | |
235 | + free(request->header.headers[i].key); | |
236 | + request->header.headers[i].key = NULL; | |
237 | + } | |
238 | + if (NULL != request->header.headers[i].value) { | |
239 | + free(request->header.headers[i].value); | |
240 | + request->header.headers[i].value = NULL; | |
241 | + } | |
242 | + } | |
243 | + | |
244 | + if (NULL != request->header.headers) { | |
245 | + free(request->header.headers); | |
246 | + request->header.headers = NULL; | |
247 | + } | |
248 | + | |
249 | + if (NULL != request->body) { | |
250 | + free(request->body); | |
251 | + request->body = NULL; | |
252 | + } | |
253 | + | |
254 | + memset (request, 0, sizeof (tHttpRequest)); | |
255 | +} | ... | ... |
server/Makefile
0 → 100644
1 | +INCLUDE=include | |
2 | +VPATH=../$(INCLUDE) | |
3 | + | |
4 | +OBJECTS=$(server_OBJ) | |
5 | + | |
6 | +all: $(OBJECTS) | |
7 | + | |
8 | +%.o: %.c | |
9 | + gcc $(CFLAGS) -c $< -o $@ | |
10 | + | |
11 | +server.h: client.h | |
12 | +server%.o: server.h monitor.h | |
13 | +serverRun.o serverInit.o: socket.h logRotate.h | |
14 | +serverRun.o serverShutdown.o: writeBuffer.h | |
15 | +serverRun.o: signalHandling.h httpRequest.h | |
16 | + | |
17 | +.PHONY: clean | |
18 | +clean: | |
19 | + -rm *.o | ... | ... |
server/serverInit.c
0 → 100644
1 | +#include <sys/select.h> /* for select system call and related */ | |
2 | +#include <string.h> /* for memset and stuff */ | |
3 | +#include <stdlib.h> /* for getopt */ | |
4 | + | |
5 | +#include "../include/server.h" | |
6 | +#include "../include/socket.h" | |
7 | +#include "../include/monitor.h" | |
8 | +#include "../include/logRotate.h" | |
9 | + | |
10 | +void | |
11 | +serverInit( | |
12 | + tServer * server, | |
13 | + unsigned int port, | |
14 | + unsigned int pending, | |
15 | + const char * logPath, | |
16 | + const char * namePat) | |
17 | +{ | |
18 | + FD_ZERO(&(server->socks)); | |
19 | + | |
20 | + server->servSock = initServerSocket(port, pending); | |
21 | + server->maxFd = server->servSock; | |
22 | + FD_SET(server->servSock, &(server->socks)); | |
23 | + | |
24 | + strncpy(server->logPath, logPath, sizeof(server->logPath)-1); | |
25 | + strncpy(server->namePat, namePat, sizeof(server->namePat)-1); | |
26 | + | |
27 | + memset(server->clients, 0, sizeof(server->clients)); | |
28 | + | |
29 | + /* | |
30 | + * try to open file (firstrun) | |
31 | + */ | |
32 | + if (NULL == server->wHandle) { | |
33 | + logRotate(&(server->wHandle), server->logPath, server->namePat); | |
34 | + if (NULL == server->wHandle) { | |
35 | + syslogMonitor(LOG_ERR, MON_INFO, "logfile.rotate", | |
36 | + "no valid handle for logfile - service terminated"); | |
37 | + exit(EXIT_FAILURE); | |
38 | + } | |
39 | + } | |
40 | +} | ... | ... |
server/serverRun.c
0 → 100644
1 | +#include <sys/select.h> /* for select system call and related */ | |
2 | +#include <string.h> /* for memset and stuff */ | |
3 | +#include <stdlib.h> /* for exit */ | |
4 | +#include <errno.h> /* for errno */ | |
5 | +#include <unistd.h> /* for write */ | |
6 | + | |
7 | +#include <expat.h> | |
8 | + | |
9 | +#include "../include/appConfig.h" | |
10 | +#include "../include/server.h" | |
11 | +#include "../include/client.h" | |
12 | +#include "../include/socket.h" | |
13 | +#include "../include/monitor.h" | |
14 | +#include "../include/logRotate.h" | |
15 | +#include "../include/signalHandling.h" | |
16 | +#include "../include/httpRequest.h" | |
17 | + | |
18 | +#define RESPONSE " 200 OK\r\nServer: xmlrpc\r\nStatus: 200\r\nContent-Length: 10\r\nContent-Type: text/plain\r\n\r\n0123456789" | |
19 | + | |
20 | +int Depth; | |
21 | + | |
22 | +void XMLCALL | |
23 | +start(void *data, const char *el, const char **attr) { | |
24 | + int i; | |
25 | + | |
26 | + for (i = 0; i < Depth; i++) | |
27 | + printf(" "); | |
28 | + | |
29 | + printf("%s", el); | |
30 | + | |
31 | + for (i = 0; attr[i]; i += 2) { | |
32 | + printf(" %s='%s'", attr[i], attr[i + 1]); | |
33 | + } | |
34 | + | |
35 | + printf("\n"); | |
36 | + Depth++; | |
37 | +} /* End of start handler */ | |
38 | + | |
39 | +void XMLCALL | |
40 | +end(void *data, const char *el) { | |
41 | + int i; | |
42 | + | |
43 | + Depth--; | |
44 | + for (i = 0; i < Depth; i++) | |
45 | + printf(" "); | |
46 | + printf("--\n"); | |
47 | +} /* End of end handler */ | |
48 | + | |
49 | +void | |
50 | +serverRun(tServer * server) | |
51 | +{ | |
52 | + syslogMonitor(LOG_INFO, MON_INFO, "startup", "service started"); | |
53 | + | |
54 | + while (!doShutdown) /* until error or signal */ | |
55 | + { | |
56 | + fd_set rfds; | |
57 | + fd_set wfds; | |
58 | + int i; | |
59 | + | |
60 | + memcpy(&rfds, &(server->socks), sizeof(fd_set)); | |
61 | + | |
62 | + FD_ZERO(&wfds); | |
63 | + for (i=3; i<=server->maxFd; i++) { | |
64 | + tClient * actClient = &(server->clients)[i]; | |
65 | + | |
66 | + if (FD_ISSET(i, &(server->socks)) | |
67 | + && NULL != actClient->writeBuffer | |
68 | + && 0 != strlen(actClient->writeBuffer)) { | |
69 | + FD_SET(i, &wfds); | |
70 | + } | |
71 | + } | |
72 | + | |
73 | + /* | |
74 | + * wait for handles to become ready | |
75 | + */ | |
76 | + if (-1 == select((server->maxFd)+1, &rfds, &wfds, NULL, NULL)) | |
77 | + { | |
78 | + switch (errno) { | |
79 | + default: | |
80 | + case EBADF: | |
81 | + case EINVAL: | |
82 | + case ENOMEM: | |
83 | + doShutdown = 1; | |
84 | + /* Fallthrough */ | |
85 | + | |
86 | + case EINTR: | |
87 | + syslogMonitor(LOG_ERR, MON_INFO, "select", | |
88 | + "select systemcall failed: [%s] - service terminated", | |
89 | + strerror(errno)); | |
90 | + continue; /* in while loop above */ | |
91 | + } | |
92 | + } | |
93 | + | |
94 | + /* | |
95 | + * handle accept | |
96 | + */ | |
97 | + if (FD_ISSET(server->servSock, &rfds)) { | |
98 | + int fd; | |
99 | + char remoteAddr[16] = ""; | |
100 | + | |
101 | + if (-1 != (fd = acceptConnection(server->servSock, remoteAddr))) { | |
102 | + (server->clients)[fd].socket = fd; // save the socket handle within the client struct | |
103 | + strncpy( | |
104 | + (server->clients)[fd].remoteAddr, | |
105 | + remoteAddr, | |
106 | + sizeof((server->clients)[fd].remoteAddr)-1); | |
107 | + FD_SET(fd, &(server->socks)); | |
108 | + server->maxFd = MAX(fd, server->maxFd); | |
109 | + | |
110 | + (server->clients)[fd].parser = XML_ParserCreate("UTF-8"); | |
111 | + XML_SetElementHandler((server->clients)[fd].parser, &start, &end); | |
112 | + | |
113 | + } | |
114 | + | |
115 | + FD_CLR(server->servSock, &rfds); | |
116 | + } | |
117 | + | |
118 | + /* handle reads (max 10 before next select, else we block accept for to long) */ | |
119 | + for (i=3; i<=server->maxFd; i++) { | |
120 | +// for (i=3, count=0; i<=server->maxFd && count<10; i++, count++) { | |
121 | + tClient * actClient = &(server->clients)[i]; | |
122 | + | |
123 | + if (FD_ISSET(i, &rfds)) { | |
124 | + switch (clientRead(actClient)) { | |
125 | + case -1: | |
126 | + syslogMonitor(LOG_WARNING, MON_INFO, "socket.read", | |
127 | + "read on socket for %s returns -1: %s", | |
128 | + actClient->remoteAddr, strerror(errno)); | |
129 | + /* FALLTHROUGH */ | |
130 | + | |
131 | + case 0: | |
132 | + clientClose(actClient); | |
133 | + FD_CLR(i, &(server->socks)); | |
134 | + break; | |
135 | + | |
136 | + default: | |
137 | + if (! httpHeaderIsComplete(&(actClient->httpHeader))) { | |
138 | + char delim[] = "\r\n"; | |
139 | + unsigned int len = strlen(delim); | |
140 | + char * line = clientGetLine(actClient, delim, &len); | |
141 | + | |
142 | + /* | |
143 | + * len might be 0, thus indicatin an empty line | |
144 | + * this might happen in two cases | |
145 | + * 1. when a header is not already started | |
146 | + * (could be identifies by a null req.method | |
147 | + * 2. if a header is started, then it indicates | |
148 | + * the end of the header. | |
149 | + */ | |
150 | + | |
151 | + while (! httpHeaderIsStarted(&(actClient->httpHeader))) { | |
152 | + | |
153 | + if (0 != len) { | |
154 | + httpHeaderParseRequestLine(&(actClient->httpHeader), line, len); | |
155 | + // TODO: do some error handling here | |
156 | + } | |
157 | + | |
158 | + len = strlen(delim); | |
159 | + clientRemoveLine(actClient, delim, &len); // TODO: do some error handling here | |
160 | + len = strlen(delim); | |
161 | + line = clientGetLine(actClient, delim, &len); | |
162 | + | |
163 | + } | |
164 | + | |
165 | + while (NULL != line) { | |
166 | + if (NULL == actClient->httpHeader.req.method) { | |
167 | + } | |
168 | + } | |
169 | + } | |
170 | + | |
171 | + if (!httpHeaderIsComplete(&(actClient->httpHeader))) { | |
172 | + actClient->bodyLenRemaining = httpHeaderGet( | |
173 | + &(actClient->readBuffer), | |
174 | + &(actClient->readPos), | |
175 | + &(actClient->httpHeader)); | |
176 | + } | |
177 | + | |
178 | + if (httpHeaderIsComplete(&(actClient->httpHeader))) { | |
179 | + size_t size = MIN(actClient->bodyLenRemaining, actClient->readPos); | |
180 | + unsigned int isLast = !(size - actClient->bodyLenRemaining); | |
181 | + | |
182 | + enum XML_Status expatStat; | |
183 | + | |
184 | + expatStat = XML_Parse(actClient->parser, actClient->readBuffer, size, isLast); | |
185 | + | |
186 | + actClient->readPos -= size; | |
187 | + actClient->bodyLenRemaining -= size; | |
188 | + memmove(actClient->readBuffer, actClient->readBuffer + size, actClient->readPos); | |
189 | + memset(actClient->readBuffer + actClient->readPos, 0, size); | |
190 | + | |
191 | + if (isLast && NULL == actClient->writeBuffer) { | |
192 | + | |
193 | + actClient->writeBuffer = calloc( | |
194 | + strlen(actClient->httpHeader.req.httpVersion) + | |
195 | + strlen(RESPONSE) + 3, | |
196 | + sizeof(char)); | |
197 | + sprintf(actClient->writeBuffer, "%s%s", | |
198 | + actClient->httpHeader.req.httpVersion, | |
199 | + RESPONSE); | |
200 | + | |
201 | + freeHttpHeader(&(actClient->httpHeader)); | |
202 | + XML_ParserFree(actClient->parser); | |
203 | + actClient->parser = NULL; | |
204 | + } | |
205 | + } | |
206 | + break; | |
207 | + } | |
208 | + } | |
209 | + } | |
210 | + | |
211 | + /* handle writes */ | |
212 | + for (i=3; i<=server->maxFd; i++) { | |
213 | +// for (i=3, count=0; i<=server->maxFd && count<10; i++, count++) { | |
214 | + tClient * actClient = &(server->clients)[i]; | |
215 | + | |
216 | + // TODO: the && is only symptom fix...need to find real bug. | |
217 | + if (FD_ISSET(i, &wfds) && NULL != actClient->writeBuffer) { | |
218 | + int writeSize = 0; | |
219 | + int toWrite = strlen(actClient->writeBuffer); | |
220 | + | |
221 | + writeSize = write(actClient->socket, actClient->writeBuffer, toWrite); | |
222 | + | |
223 | + if (0 < writeSize) { | |
224 | + if (writeSize == toWrite) { | |
225 | + free(actClient->writeBuffer); | |
226 | + actClient->writeBuffer = NULL; | |
227 | + | |
228 | + clientClose(actClient); | |
229 | + FD_CLR(i, &(server->socks)); | |
230 | + } else { | |
231 | + memmove(actClient->writeBuffer, actClient->writeBuffer + writeSize, toWrite - writeSize); | |
232 | + memset(actClient->writeBuffer + (toWrite - writeSize), 0, writeSize); | |
233 | + } | |
234 | + } | |
235 | + } | |
236 | + } | |
237 | + } | |
238 | +} | ... | ... |
server/serverShutdown.c
0 → 100644
1 | +#include <stdio.h> /* for printf() and fprintf() */ | |
2 | +#include <sys/select.h> /* for select system call and related */ | |
3 | +#include <sys/socket.h> /* for select system call and related */ | |
4 | +#include <stdlib.h> /* for exit */ | |
5 | +#include <string.h> /* for memset and stuff */ | |
6 | +#include <unistd.h> /* for getopt */ | |
7 | +#include <errno.h> /* for errno */ | |
8 | + | |
9 | +#include "../include/server.h" | |
10 | +#include "../include/monitor.h" | |
11 | +#include "../include/writeBuffer.h" | |
12 | + | |
13 | + | |
14 | +void | |
15 | +serverShutdown(tServer * server) | |
16 | +{ | |
17 | + int i; | |
18 | + | |
19 | + for (i=3; i<=server->maxFd; i++) { | |
20 | + if (FD_ISSET(i, &(server->socks))) { | |
21 | + if (i == server->servSock) { | |
22 | + shutdown(server->servSock, SHUT_RDWR); | |
23 | + close(server->servSock); | |
24 | + } else { | |
25 | + /* actual do nothing except closing the client */ | |
26 | + clientClose(&((server->clients)[i])); | |
27 | + FD_CLR(i, &(server->socks)); | |
28 | + } | |
29 | + } | |
30 | + } | |
31 | + | |
32 | + if (NULL != server->wHandle) { | |
33 | + fclose(server->wHandle); | |
34 | + } | |
35 | +} | ... | ... |
system/Makefile
0 → 100644
1 | +INCLUDE=include | |
2 | +VPATH=../$(INCLUDE) | |
3 | + | |
4 | +OBJECTS=$(system_OBJ) | |
5 | + | |
6 | +all: $(OBJECTS) | |
7 | + | |
8 | +%.o: %.c | |
9 | + gcc $(CFLAGS) -c $< -o $@ | |
10 | + | |
11 | +logRotate.o signalHandling.o socket.o: monitor.h | |
12 | +serverRun.o: signalHandling.h httpRequest.h | |
13 | +handleCmdLine.o: appConfig.h | |
14 | + | |
15 | +.PHONY: clean | |
16 | +clean: | |
17 | + -rm *.o | ... | ... |
system/daemonize.c
0 → 100644
1 | +#include <stdio.h> /* for printf() and fprintf() */ | |
2 | +#include <unistd.h> /* for getopt */ | |
3 | +#include <stdlib.h> | |
4 | + | |
5 | + | |
6 | +void daemonize(void) { | |
7 | + pid_t pid; | |
8 | + | |
9 | + if (0 > ((pid = fork()))) { | |
10 | + perror("deamoinze[fork]"); | |
11 | + exit(EXIT_FAILURE); | |
12 | + } else if (0 != pid) { | |
13 | + exit(EXIT_SUCCESS); | |
14 | + } | |
15 | + | |
16 | + /* make new child session leader */ | |
17 | + setsid(); | |
18 | + | |
19 | + /* connect all standard streams to /dev/null */ | |
20 | + freopen("/dev/null", "w", stderr); | |
21 | + freopen("/dev/null", "r", stdin); | |
22 | + freopen("/dev/null", "w", stdout); | |
23 | +} | ... | ... |
system/handleCmdLine.c
0 → 100644
1 | +#include <unistd.h> /* for getopt */ | |
2 | +#include <stdlib.h> | |
3 | +#include <string.h> | |
4 | +#include <stdio.h> | |
5 | + | |
6 | +#include "../include/appConfig.h" | |
7 | + | |
8 | + | |
9 | +int | |
10 | +handleCmdLine(tAppConfig * config, int argc, char *argv[]) | |
11 | +{ | |
12 | + int opt; | |
13 | + | |
14 | + while ((opt = getopt(argc, argv, "Dvp:l:n:b:")) != -1) { | |
15 | + switch (opt) { | |
16 | + case 'p': | |
17 | + /* port */ | |
18 | + config->port = atoi(optarg); | |
19 | + break; | |
20 | + | |
21 | + case 'l': | |
22 | + /* logPath */ | |
23 | + strncpy(config->logPath, optarg, sizeof(config->logPath)-1); | |
24 | + break; | |
25 | + | |
26 | + case 'n': | |
27 | + /* logNamePattern */ | |
28 | + strncpy(config->namePat, optarg, sizeof(config->namePat)-1); | |
29 | + break; | |
30 | + | |
31 | + case 'b': | |
32 | + /* maxPending (connection backlog) */ | |
33 | + config->maxPending = atoi(optarg); | |
34 | + break; | |
35 | + | |
36 | + case 'v': | |
37 | + /* verbose */ | |
38 | + config->verbose = 1; | |
39 | + break; | |
40 | + | |
41 | + case 'D': | |
42 | + /* verbose */ | |
43 | + config->doDaemon = 1; | |
44 | + break; | |
45 | + | |
46 | + default: | |
47 | + /* '?' */ | |
48 | + fprintf( | |
49 | + stderr, | |
50 | + "Usage: %s [-p port] [-l logPath] [-n logNamePattern] [-c maxClient] [-b backlog] [-v] [-D]\n" | |
51 | + "Defaults:\n" | |
52 | + "\t%-20s: port this service will use [%d]\n" | |
53 | + "\t%-20s: path where the logfiles will be stored [%s/]\n" | |
54 | + "\t%-20s: patten used by strftime to create the log filename [%s]\n" | |
55 | + "\t%-20s: maximum connection backlog [%d]\n" | |
56 | + "\t%-20s: be more verbose in syslog [off]\n" | |
57 | + "\t%-20s: deamonize me\n", | |
58 | + argv[0], | |
59 | + "-p port", DEFAULTPORT, | |
60 | + "-l logPath", DEFAULTPATH, | |
61 | + "-n logNamePattern", LOGNAMEPATTERN, | |
62 | + "-b backlog", MAXPENDING, | |
63 | + "-v", | |
64 | + "-D"); | |
65 | + exit(EXIT_FAILURE); | |
66 | + } | |
67 | + } | |
68 | + | |
69 | + return 0; | |
70 | +} | ... | ... |
system/logRotate.c
0 → 100644
1 | +#include <sys/select.h> /* for select system call and related */ | |
2 | +#include <time.h> | |
3 | +#include <unistd.h> /* for fork and exec */ | |
4 | +#include <sys/types.h> | |
5 | +#include <sys/wait.h> | |
6 | +#include <stdio.h> /* fopen and stuff */ | |
7 | +#include <stdlib.h> /* exit */ | |
8 | +#include <string.h> /* strncpy, memcpy, etc. */ | |
9 | +#include <syslog.h> | |
10 | +#include <errno.h> | |
11 | + | |
12 | +#include "../include/monitor.h" | |
13 | + | |
14 | + | |
15 | +extern int verbose; | |
16 | + | |
17 | +void logRotate(FILE ** handle, char * path, char * pattern) { | |
18 | + static char logName[1024] = ""; | |
19 | + | |
20 | + char strftimeName[128] = ""; | |
21 | + char newLogName[1024] = ""; | |
22 | + | |
23 | + time_t t; | |
24 | + struct tm *tmp; | |
25 | + | |
26 | + t = time(NULL); | |
27 | + tmp = localtime(&t); | |
28 | + if (tmp == NULL) { | |
29 | + syslogMonitor(LOG_ERR, MON_INFO, "logrotate.localtime", | |
30 | + "can't get localtime for new logname. continue with old one"); | |
31 | + return; | |
32 | + } | |
33 | + | |
34 | + if (strftime(strftimeName, sizeof(strftimeName)-1, pattern, tmp) == 0) { | |
35 | + syslogMonitor(LOG_ERR, MON_INFO, "logrotate.strftime", | |
36 | + "strftime returned 0 for new logname. continue with old one"); | |
37 | + return; | |
38 | + } | |
39 | + | |
40 | + snprintf(newLogName, sizeof(newLogName)-1, "%s/%s", path, strftimeName); | |
41 | + | |
42 | + if (0 != strncmp(logName, newLogName, sizeof(logName)-1)) { | |
43 | + if (0 != verbose) { | |
44 | + syslog(LOG_INFO, "actual logfile name: %s", logName); | |
45 | + syslog(LOG_INFO, "new logfile name: %s", newLogName); | |
46 | + } | |
47 | + | |
48 | + if (NULL != *handle) { | |
49 | + fclose(*handle); | |
50 | + | |
51 | + pid_t gzipPid = fork(); | |
52 | + | |
53 | + switch(gzipPid) { | |
54 | + pid_t tmpPid; | |
55 | + | |
56 | + case 0: | |
57 | + // We don't care about finishing of child, so decouple it | |
58 | + // by using a second child that stop immediatly | |
59 | + tmpPid = fork(); | |
60 | + if (0 == tmpPid) { | |
61 | + syslog(LOG_INFO, "gzip: %s", logName); | |
62 | + if (-1 == execl("/bin/gzip", "/bin/gzip", "-9", logName, (char *) 0)) { | |
63 | + syslogMonitor(LOG_ERR, MON_INFO, "logrotate.gzip", | |
64 | + "execl failed for gzip %s: %s", logName, strerror(errno)); | |
65 | + } | |
66 | + } | |
67 | + exit(EXIT_SUCCESS); | |
68 | + | |
69 | + case -1: | |
70 | + syslogMonitor(LOG_ERR, MON_INFO, "logrotate.fork", | |
71 | + "fork failed for gzip %s: %s", logName, strerror(errno)); | |
72 | + break; | |
73 | + | |
74 | + default: | |
75 | + wait(NULL); | |
76 | + break; | |
77 | + } | |
78 | + } | |
79 | + | |
80 | + strncpy(logName, newLogName, sizeof(logName)-1); | |
81 | + *handle = fopen(logName, "w"); | |
82 | + } | |
83 | +} | ... | ... |
system/monitor.c
0 → 100644
1 | +#include <stdlib.h> /* for system() */ | |
2 | +#include <sys/wait.h> | |
3 | +#include <stdio.h> | |
4 | +#include <string.h> | |
5 | +#include <errno.h> | |
6 | +#include <signal.h> | |
7 | +#include <stdarg.h> /* for ellipse handling */ | |
8 | + | |
9 | +#include "../include/signalHandling.h" | |
10 | +#include "../include/monitor.h" | |
11 | + | |
12 | + | |
13 | +#define MONITORCMD "/usr/bin/monitor" | |
14 | +#define MONITORTYPE "test" | |
15 | +#define MONITORNAME "virtualitemlogreceiver" | |
16 | + | |
17 | +const char severity[][10] = { | |
18 | + "info", | |
19 | + "warning", | |
20 | + "critical", | |
21 | + "failure" | |
22 | +}; | |
23 | + | |
24 | + | |
25 | +int | |
26 | +monitor( | |
27 | + unsigned int sev, | |
28 | + const char * pattern, | |
29 | + const char * message | |
30 | +) { | |
31 | + char monCall[1024]; | |
32 | + int ret; | |
33 | + | |
34 | + snprintf(monCall, 1023, | |
35 | + "%s %s %s.%s.%s \"%s\"", | |
36 | + MONITORCMD, | |
37 | + severity[sev], | |
38 | + MONITORTYPE, | |
39 | + MONITORNAME, | |
40 | + pattern, | |
41 | + message); | |
42 | + | |
43 | + ret = system(monCall); | |
44 | + | |
45 | + if (WIFSIGNALED(ret)) { | |
46 | + switch (WTERMSIG(ret)) { | |
47 | + case SIGINT: | |
48 | + case SIGQUIT: | |
49 | + syslog(LOG_INFO, "interrupted in monitor call"); | |
50 | + doShutdown=1; | |
51 | + } | |
52 | + } | |
53 | + | |
54 | + if (-1 == ret || 0 != WEXITSTATUS(ret)) { | |
55 | + syslog(LOG_ERR, "call monitoring failed: %s", strerror(errno)); | |
56 | + } | |
57 | + | |
58 | + return ret; | |
59 | +} | |
60 | + | |
61 | +/* this handles simple %d and %s replacements, | |
62 | + * complexer stuff must be prepared via snprintf | |
63 | + * the complete message should not extend 1024 | |
64 | + * Bytes, else it will be truncated silently */ | |
65 | +int | |
66 | +syslogMonitor( | |
67 | + unsigned int logLvl, | |
68 | + unsigned int sev, | |
69 | + const char * pattern, | |
70 | + const char * message, | |
71 | + ... | |
72 | +) { | |
73 | + va_list args; | |
74 | + char buffer[1025]; | |
75 | + int maxBuf = sizeof(buffer)/sizeof(buffer[0]); | |
76 | + | |
77 | + memset(buffer, 0, maxBuf); | |
78 | + | |
79 | + va_start(args, message); | |
80 | + vsnprintf(buffer, 1024, message, args); | |
81 | + va_end(args); | |
82 | + | |
83 | + syslog(logLvl, "%s", buffer); | |
84 | + monitor(sev, pattern, buffer); | |
85 | + | |
86 | + return 0; | |
87 | +} | ... | ... |
system/signalHandling.c
0 → 100644
1 | +#include <signal.h> /* for signal() and signal names */ | |
2 | + | |
3 | +#include "../include/monitor.h" | |
4 | + | |
5 | +volatile int doShutdown; | |
6 | + | |
7 | +void terminate(int signum) | |
8 | +{ | |
9 | + signal(signum, SIG_IGN); | |
10 | + syslogMonitor(LOG_INFO, MON_INFO, "signals", | |
11 | + "caugth deadly signal %d, service terminated", signum); | |
12 | + doShutdown = 1; | |
13 | +} | |
14 | + | |
15 | +void init_signals(void) | |
16 | +{ | |
17 | + signal(SIGTERM, terminate); | |
18 | + signal(SIGHUP, SIG_IGN); | |
19 | + signal(SIGINT, terminate); | |
20 | + signal(SIGQUIT, terminate); | |
21 | + signal(SIGABRT, terminate); | |
22 | + signal(SIGALRM, SIG_IGN); | |
23 | + signal(SIGURG, SIG_IGN); | |
24 | + | |
25 | + signal(SIGPIPE, SIG_IGN); | |
26 | +} | ... | ... |
system/socket.c
0 → 100644
1 | +#include <stdio.h> /* for printf() and fprintf() */ | |
2 | +#include <sys/socket.h> /* for socket(), bind(), and connect() */ | |
3 | +#include <arpa/inet.h> /* for sockaddr_in and inet_ntoa() */ | |
4 | +#include <stdlib.h> /* for atoi() and exit() */ | |
5 | +#include <string.h> /* for memset() */ | |
6 | +#include <unistd.h> /* for close() */ | |
7 | +#include <errno.h> /* for errno */ | |
8 | +#include <syslog.h> | |
9 | + | |
10 | +#include "../include/monitor.h" | |
11 | + | |
12 | + | |
13 | +extern int verbose; | |
14 | + | |
15 | +int initServerSocket(in_port_t port, int backlog) { | |
16 | + int sock; /* socket descriptor for server */ | |
17 | + struct sockaddr_in addr; /* Local address */ | |
18 | + | |
19 | + /* Create socket for incoming connections */ | |
20 | + if (-1 == (sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) { | |
21 | + syslogMonitor(LOG_ERR, MON_INFO, "server.socket", | |
22 | + "error opening socket: %s - service terminated", | |
23 | + strerror(errno)); | |
24 | + exit(EXIT_FAILURE); | |
25 | + } | |
26 | + | |
27 | + /* Construct local address structure */ | |
28 | + memset(&addr, 0, sizeof(addr)); /* Zero out structure */ | |
29 | + | |
30 | + addr.sin_family = AF_INET; /* Internet address family */ | |
31 | + addr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */ | |
32 | + addr.sin_port = htons(port); /* Local port */ | |
33 | + | |
34 | + /* Bind to the local address */ | |
35 | + if (-1 == bind(sock, (struct sockaddr *) &addr, sizeof(addr))) { | |
36 | + syslogMonitor(LOG_ERR, MON_INFO, "server.bind", | |
37 | + "error binding socket: %s - service terminated", | |
38 | + strerror(errno)); | |
39 | + exit(EXIT_FAILURE); | |
40 | + } | |
41 | + | |
42 | + /* Mark the socket so it will listen for incoming connections */ | |
43 | + if (-1 == listen(sock, backlog)) { | |
44 | + syslogMonitor(LOG_ERR, MON_INFO, "server.listen", | |
45 | + "error binding socket: %s - service terminated", | |
46 | + strerror(errno)); | |
47 | + exit(EXIT_FAILURE); | |
48 | + } | |
49 | + | |
50 | + return sock; | |
51 | +} | |
52 | + | |
53 | +int acceptConnection(int servSock, char remoteAddr[16]) { | |
54 | + int sock; /* Socket descriptor for client */ | |
55 | + struct sockaddr_in addr; /* Client address */ | |
56 | + unsigned int len; /* Length of client address data structure */ | |
57 | + | |
58 | + /* Set the size of the in-out parameter */ | |
59 | + len = sizeof(addr); | |
60 | + | |
61 | + /* Wait for a client to connect */ | |
62 | + if (-1 == (sock = accept(servSock, (struct sockaddr *) &addr, &len))) { | |
63 | + syslogMonitor(LOG_ERR, MON_INFO, "server.accept", | |
64 | + "error acception connection: %s", strerror(errno)); | |
65 | + } else { | |
66 | + strncpy (remoteAddr, inet_ntoa(addr.sin_addr), sizeof(remoteAddr)-1); | |
67 | + } | |
68 | + | |
69 | + /* clntSock is connected to a client! */ | |
70 | + if (0 != verbose) { | |
71 | + syslog(LOG_INFO, "handling client %s\n", inet_ntoa(addr.sin_addr)); | |
72 | + } | |
73 | + | |
74 | + return sock; | |
75 | +} | ... | ... |
xmlrpc.c
0 → 100644
1 | +#include <string.h> /* for memset and stuff */ | |
2 | +#include <syslog.h> /* for logging */ | |
3 | + | |
4 | +#include "include/server.h" | |
5 | +#include "include/monitor.h" | |
6 | +#include "include/signalHandling.h" | |
7 | +#include "include/appConfig.h" | |
8 | +#include "include/daemonize.h" | |
9 | + | |
10 | +int verbose; | |
11 | + | |
12 | + | |
13 | +int main(int argc, char *argv[]) | |
14 | +{ | |
15 | + tServer server; | |
16 | + | |
17 | + tAppConfig appConfig = { | |
18 | + 0, | |
19 | + 0, | |
20 | + MAXPENDING, | |
21 | + DEFAULTPORT, | |
22 | + DEFAULTPATH, | |
23 | + LOGNAMEPATTERN | |
24 | + }; | |
25 | + | |
26 | + memset(&server, 0, sizeof(server)); | |
27 | + | |
28 | + handleCmdLine(&appConfig, argc, argv); | |
29 | + verbose = appConfig.verbose; | |
30 | + | |
31 | + /* decouple procss from controlling shell and make it session leader */ | |
32 | + if (appConfig.doDaemon) { | |
33 | + daemonize(); | |
34 | + } | |
35 | + init_signals(); | |
36 | + openlog(argv[0], LOG_PID, LOG_USER); | |
37 | + | |
38 | + syslogMonitor(LOG_INFO, MON_INFO, "startup", "service started"); | |
39 | + | |
40 | + serverInit( | |
41 | + &server, | |
42 | + appConfig.port, | |
43 | + appConfig.maxPending, | |
44 | + appConfig.logPath, | |
45 | + appConfig.namePat); | |
46 | + serverRun(&server); | |
47 | + serverShutdown(&server); | |
48 | + | |
49 | + return 0; | |
50 | +} | ... | ... |
Please
register
or
login
to post a comment