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.
238 lines
8.8 KiB
238 lines
8.8 KiB
#include <sys/select.h> /* for select system call and related */
|
|
#include <string.h> /* for memset and stuff */
|
|
#include <stdlib.h> /* for exit */
|
|
#include <errno.h> /* for errno */
|
|
#include <unistd.h> /* for write */
|
|
|
|
#include <expat.h>
|
|
|
|
#include "../include/appConfig.h"
|
|
#include "../include/server.h"
|
|
#include "../include/client.h"
|
|
#include "../include/socket.h"
|
|
#include "../include/monitor.h"
|
|
#include "../include/logRotate.h"
|
|
#include "../include/signalHandling.h"
|
|
#include "../include/httpRequest.h"
|
|
|
|
#define RESPONSE " 200 OK\r\nServer: xmlrpc\r\nStatus: 200\r\nContent-Length: 10\r\nContent-Type: text/plain\r\n\r\n0123456789"
|
|
|
|
int Depth;
|
|
|
|
void XMLCALL
|
|
start(void *data, const char *el, const char **attr) {
|
|
int i;
|
|
|
|
for (i = 0; i < Depth; i++)
|
|
printf(" ");
|
|
|
|
printf("%s", el);
|
|
|
|
for (i = 0; attr[i]; i += 2) {
|
|
printf(" %s='%s'", attr[i], attr[i + 1]);
|
|
}
|
|
|
|
printf("\n");
|
|
Depth++;
|
|
} /* End of start handler */
|
|
|
|
void XMLCALL
|
|
end(void *data, const char *el) {
|
|
int i;
|
|
|
|
Depth--;
|
|
for (i = 0; i < Depth; i++)
|
|
printf(" ");
|
|
printf("--\n");
|
|
} /* End of end handler */
|
|
|
|
void
|
|
serverRun(tServer * server)
|
|
{
|
|
syslogMonitor(LOG_INFO, MON_INFO, "startup", "service started");
|
|
|
|
while (!doShutdown) /* until error or signal */
|
|
{
|
|
fd_set rfds;
|
|
fd_set wfds;
|
|
int i;
|
|
|
|
memcpy(&rfds, &(server->socks), sizeof(fd_set));
|
|
|
|
FD_ZERO(&wfds);
|
|
for (i=3; i<=server->maxFd; i++) {
|
|
tClient * actClient = &(server->clients)[i];
|
|
|
|
if (FD_ISSET(i, &(server->socks))
|
|
&& NULL != actClient->writeBuffer
|
|
&& 0 != strlen(actClient->writeBuffer)) {
|
|
FD_SET(i, &wfds);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* wait for handles to become ready
|
|
*/
|
|
if (-1 == select((server->maxFd)+1, &rfds, &wfds, NULL, NULL))
|
|
{
|
|
switch (errno) {
|
|
default:
|
|
case EBADF:
|
|
case EINVAL:
|
|
case ENOMEM:
|
|
doShutdown = 1;
|
|
/* Fallthrough */
|
|
|
|
case EINTR:
|
|
syslogMonitor(LOG_ERR, MON_INFO, "select",
|
|
"select systemcall failed: [%s] - service terminated",
|
|
strerror(errno));
|
|
continue; /* in while loop above */
|
|
}
|
|
}
|
|
|
|
/*
|
|
* handle accept
|
|
*/
|
|
if (FD_ISSET(server->servSock, &rfds)) {
|
|
int fd;
|
|
char remoteAddr[16] = "";
|
|
|
|
if (-1 != (fd = acceptConnection(server->servSock, remoteAddr))) {
|
|
(server->clients)[fd].socket = fd; // save the socket handle within the client struct
|
|
strncpy(
|
|
(server->clients)[fd].remoteAddr,
|
|
remoteAddr,
|
|
sizeof((server->clients)[fd].remoteAddr)-1);
|
|
FD_SET(fd, &(server->socks));
|
|
server->maxFd = MAX(fd, server->maxFd);
|
|
|
|
(server->clients)[fd].parser = XML_ParserCreate("UTF-8");
|
|
XML_SetElementHandler((server->clients)[fd].parser, &start, &end);
|
|
|
|
}
|
|
|
|
FD_CLR(server->servSock, &rfds);
|
|
}
|
|
|
|
/* handle reads (max 10 before next select, else we block accept for to long) */
|
|
for (i=3; i<=server->maxFd; i++) {
|
|
// for (i=3, count=0; i<=server->maxFd && count<10; i++, count++) {
|
|
tClient * actClient = &(server->clients)[i];
|
|
|
|
if (FD_ISSET(i, &rfds)) {
|
|
switch (clientRead(actClient)) {
|
|
case -1:
|
|
syslogMonitor(LOG_WARNING, MON_INFO, "socket.read",
|
|
"read on socket for %s returns -1: %s",
|
|
actClient->remoteAddr, strerror(errno));
|
|
/* FALLTHROUGH */
|
|
|
|
case 0:
|
|
clientClose(actClient);
|
|
FD_CLR(i, &(server->socks));
|
|
break;
|
|
|
|
default:
|
|
if (! httpHeaderIsComplete(&(actClient->httpHeader))) {
|
|
char delim[] = "\r\n";
|
|
unsigned int len = strlen(delim);
|
|
char * line = clientGetLine(actClient, delim, &len);
|
|
|
|
/*
|
|
* len might be 0, thus indicatin an empty line
|
|
* this might happen in two cases
|
|
* 1. when a header is not already started
|
|
* (could be identifies by a null req.method
|
|
* 2. if a header is started, then it indicates
|
|
* the end of the header.
|
|
*/
|
|
|
|
while (! httpHeaderIsStarted(&(actClient->httpHeader))) {
|
|
|
|
if (0 != len) {
|
|
httpHeaderParseRequestLine(&(actClient->httpHeader), line, len);
|
|
// TODO: do some error handling here
|
|
}
|
|
|
|
len = strlen(delim);
|
|
clientRemoveLine(actClient, delim, &len); // TODO: do some error handling here
|
|
len = strlen(delim);
|
|
line = clientGetLine(actClient, delim, &len);
|
|
|
|
}
|
|
|
|
while (NULL != line) {
|
|
if (NULL == actClient->httpHeader.req.method) {
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!httpHeaderIsComplete(&(actClient->httpHeader))) {
|
|
actClient->bodyLenRemaining = httpHeaderGet(
|
|
&(actClient->readBuffer),
|
|
&(actClient->readPos),
|
|
&(actClient->httpHeader));
|
|
}
|
|
|
|
if (httpHeaderIsComplete(&(actClient->httpHeader))) {
|
|
size_t size = MIN(actClient->bodyLenRemaining, actClient->readPos);
|
|
unsigned int isLast = !(size - actClient->bodyLenRemaining);
|
|
|
|
enum XML_Status expatStat;
|
|
|
|
expatStat = XML_Parse(actClient->parser, actClient->readBuffer, size, isLast);
|
|
|
|
actClient->readPos -= size;
|
|
actClient->bodyLenRemaining -= size;
|
|
memmove(actClient->readBuffer, actClient->readBuffer + size, actClient->readPos);
|
|
memset(actClient->readBuffer + actClient->readPos, 0, size);
|
|
|
|
if (isLast && NULL == actClient->writeBuffer) {
|
|
|
|
actClient->writeBuffer = calloc(
|
|
strlen(actClient->httpHeader.req.httpVersion) +
|
|
strlen(RESPONSE) + 3,
|
|
sizeof(char));
|
|
sprintf(actClient->writeBuffer, "%s%s",
|
|
actClient->httpHeader.req.httpVersion,
|
|
RESPONSE);
|
|
|
|
freeHttpHeader(&(actClient->httpHeader));
|
|
XML_ParserFree(actClient->parser);
|
|
actClient->parser = NULL;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* handle writes */
|
|
for (i=3; i<=server->maxFd; i++) {
|
|
// for (i=3, count=0; i<=server->maxFd && count<10; i++, count++) {
|
|
tClient * actClient = &(server->clients)[i];
|
|
|
|
// TODO: the && is only symptom fix...need to find real bug.
|
|
if (FD_ISSET(i, &wfds) && NULL != actClient->writeBuffer) {
|
|
int writeSize = 0;
|
|
int toWrite = strlen(actClient->writeBuffer);
|
|
|
|
writeSize = write(actClient->socket, actClient->writeBuffer, toWrite);
|
|
|
|
if (0 < writeSize) {
|
|
if (writeSize == toWrite) {
|
|
free(actClient->writeBuffer);
|
|
actClient->writeBuffer = NULL;
|
|
|
|
clientClose(actClient);
|
|
FD_CLR(i, &(server->socks));
|
|
} else {
|
|
memmove(actClient->writeBuffer, actClient->writeBuffer + writeSize, toWrite - writeSize);
|
|
memset(actClient->writeBuffer + (toWrite - writeSize), 0, writeSize);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|