Browse Source

changed request handling. @TODO: I still seem to have the problem that the file handles are not closed and freed correctly as the service refuses connections after about a 1000.

master
Georg Hopp 14 years ago
parent
commit
228b1d0d29
  1. 10
      ChangeLog
  2. 13
      include/server.h
  3. 7
      src/http/request_parser.c
  4. 12
      src/server/close_conn.c
  5. 6
      src/server/handle_accept.c
  6. 28
      src/server/poll.c
  7. 12
      src/server/read.c
  8. 79
      src/server/run.c
  9. 9
      src/socket.c
  10. 2
      src/socket/accept.c
  11. 1
      src/testserver.c

10
ChangeLog

@ -1,6 +1,14 @@
2012-02-08 10:21:04 +0100 Georg Hopp
* changed request handling. @TODO: I still seem to have the problem that the file handles are not closed and freed correctly as the service refuses connections after about a 1000. (HEAD, master)
2012-02-07 14:20:00 +0100 Georg Hopp
* now stuff seems to work correct even if read does not provide a complete request (tested with telnet)
2012-02-07 13:41:49 +0100 Georg Hopp
* now each HttpRequestParser initializes its own request queue and enqueus completed requests there. The server now gets the queue and prints completed requests. (HEAD, master)
* now each HttpRequestParser initializes its own request queue and enqueus completed requests there. The server now gets the queue and prints completed requests.
2012-02-07 11:12:30 +0100 Georg Hopp

13
include/server.h

@ -21,21 +21,28 @@
MOVE_SIZE(sizeof(((server)->conns)[0]),(idx)))
typedef void (*server_read_hook)(const char *, size_t);
CLASS(Server) {
Logger logger;
Sock sock;
void * reader;
/**
* loeschen: fds[i].event auf 0
* dann nfds um die anzahl der geloeschten elemente verkleinern.
* die in close pending stehenden socket schliessen.
* vor jedem poll qsort auf fds ueber event.
* nach dem poll qsort auf fds ueber revent und reuckgebewert
* von poll beruecksichtigen.
*/
nfds_t nfds;
nfds_t ndel;
struct pollfd fds[POLL_FD_NSIZE];
struct {
Sock sock;
void * reader;
char * wbuf;
char wbuf[2048];
char * rbuf;
unsigned int rpos;
unsigned int wpos;

7
src/http/request_parser.c

@ -142,7 +142,6 @@ httpRequestParserParse(HttpRequestParser this)
while(cont) {
switch(this->state) {
case HTTP_REQUEST_GARBAGE:
puts("==skip garbage==");
data = this->buffer; // initialize static pointer
httpRequestSkip(&data);
request = new(HttpRequest);
@ -151,7 +150,6 @@ httpRequestParserParse(HttpRequestParser this)
break;
case HTTP_REQUEST_START:
puts("==request line==");
if (NULL == (line = httpRequestLineGet(&data))) {
cont = 0;
break;
@ -193,7 +191,6 @@ httpRequestParserParse(HttpRequestParser this)
break;
case HTTP_REQUEST_REQUEST_LINE_DONE:
puts("==read header==");
if (NULL == (line = httpRequestLineGet(&data))) {
cont = 0;
break;
@ -222,8 +219,6 @@ httpRequestParserParse(HttpRequestParser this)
break;
case HTTP_REQUEST_HEADERS_DONE:
puts("==headers done==");
/**
* @TODO: here comes the body handling
*/
@ -231,8 +226,6 @@ httpRequestParserParse(HttpRequestParser this)
break;
case HTTP_REQUEST_DONE:
puts("==request done==");
/**
* enqueue current request
*/

12
src/server/close_conn.c

@ -6,10 +6,14 @@
void
serverCloseConn(Server this, unsigned int i)
{
delete(&((this->conns)[i].sock));
delete(&((this->conns)[i].reader));
CLEAR_CONN(this, i);
this->nfds--;
int fd = (this->fds)[i].fd;
delete(&((this->conns)[fd].sock));
delete(&((this->conns)[fd].reader));
(this->fds)[i].events = 0;
this->ndel++;
// CLEAR_CONN(this, i);
// this->nfds--;
}
// vim: set ts=4 sw=4:

6
src/server/handle_accept.c

@ -2,7 +2,6 @@ static
void
serverHandleAccept(Server this)
{
if (0 != ((this->fds)[0].revents & POLLIN)) {
char remoteAddr[16] = "";
Sock acc;
@ -10,10 +9,10 @@ serverHandleAccept(Server this)
if (-1 != acc->handle) {
//* save the socket handle
(this->conns)[this->nfds].sock = acc;
(this->conns)[acc->handle].sock = acc;
//* clone reader
(this->conns)[this->nfds].reader = clone(this->reader);
(this->conns)[acc->handle].reader = clone(this->reader);
(this->fds)[this->nfds].fd = acc->handle;
(this->fds)[this->nfds].events = POLLIN;
@ -24,6 +23,5 @@ serverHandleAccept(Server this)
(this->fds)[0].revents |= POLLIN;
}
}
// vim: set ts=4 sw=4:

28
src/server/poll.c

@ -1,8 +1,34 @@
#define POLLFD(ptr) ((struct pollfd *)(ptr))
static
inline
int
sortEvents(const void * a, const void * b)
{
return POLLFD(a)->events > POLLFD(b)->events ?
-1 : POLLFD(a)->events < POLLFD(b)->events ?
1 : 0;
}
static
inline
int
sortRevents(const void * a, const void * b)
{
return POLLFD(a)->revents > POLLFD(b)->revents ?
-1 : POLLFD(a)->revents < POLLFD(b)->revents ?
1 : 0;
}
static
int
serverPoll(Server this) {
int events;
qsort(this->fds, this->nfds, sizeof(struct pollfd), sortEvents);
this->nfds -= this->ndel;
this->ndel = 0;
/*
* wait for handles to become ready
*/
@ -23,6 +49,8 @@ serverPoll(Server this) {
}
}
qsort(this->fds, this->nfds, sizeof(struct pollfd), sortRevents);
return events;
}

12
src/server/read.c

@ -1,12 +1,10 @@
static
int
serverRead(Server this)
serverRead(Server this, unsigned int i)
{
unsigned int i;
int fd = (this->fds)[i].fd;
for (i=1; i<this->nfds; i++) {
if (0 != ((this->fds)[i].revents & POLLIN)) {
if (NULL == (this->conns)[i].reader) {
if (NULL == (this->conns)[fd].reader) {
loggerLog(
this->logger,
LOGGER_INFO,
@ -14,7 +12,7 @@ serverRead(Server this)
serverCloseConn(this, i);
}
switch (streamReaderRead((this->conns)[i].reader, (this->fds)[i].fd)) {
switch (streamReaderRead((this->conns)[fd].reader, fd)) {
case 0:
/*
* normal close: write remaining data
@ -33,8 +31,6 @@ serverRead(Server this)
default:
break;
}
}
}
return 0;
}

79
src/server/run.c

@ -3,6 +3,7 @@
#include <stdlib.h> /* for exit */
#include <errno.h> /* for errno */
#include <unistd.h>
#include <time.h>
#include "server.h"
#include "socket.h"
@ -43,23 +44,28 @@ serverRun(Server this)
while (!doShutdown) /* until error or signal */
{
int events;
unsigned int i;
/**
* @TODO take return value of poll into account with
* further handling!
*/
events = serverPoll(this);
if (doShutdown) break;
for (i=0; i < events; i++) {
int fd = (this->fds)[i].fd;
//int nreads = 0, nwrites = 0;
if (0 != ((this->fds)[i].revents & POLLIN)) {
/**
* handle accept
*/
if (this->sock->handle == (this->fds)[i].fd) {
serverHandleAccept(this);
}
/**
* handle reads
*/
serverRead(this);
else {
serverRead(this, i);
/**
* do some other processing
@ -68,38 +74,69 @@ serverRun(Server this)
* generalizing here.
*/
{
int i;
for (i=1; i<this->nfds; i++) {
int j;
HttpRequestQueue queue =
((HttpRequestParser)(this->conns)[i].reader)->request_queue;
((HttpRequestParser)(this->conns)[fd].reader)->request_queue;
for (j=0; j<queue->nrequests; j++) {
int k;
HttpRequest request = queue->requests[j];
printf("method: %s\n", request->method);
printf("uri: %s\n", request->uri);
printf("version: %s\n", request->http_version);
puts("");
/**
* @TODO: for now simply remove request and send not found.
* Make this sane.
*/
delete(&request);
for (k=0; k<128; k++) {
if (NULL == (request->header)[k].name) break;
printf("header-name: %s\n", (request->header)[k].name);
printf("header-value: %s\n", (request->header)[k].value);
}
/**
* @TODO: the complete response stuff have to be removed here.
*/
time_t t;
struct tm * tmp;
char timestr[200];
#define RESP_HEAD "HTTP/1.1 404 Not Found\r\n" \
"Content-Type: text/html\r\n" \
"Content-Length: %lu\r\n" \
"Date: %s\r\n" \
"Server: testserver\r\n"
#define RESP_DATA "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n" \
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n" \
" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" \
"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n" \
"<head><title>404 - Not Found</title></head>" \
"<body><h1>404 - Not Found</h1></body>" \
"</html>"
t = time(NULL);
tmp = localtime(&t);
strftime(timestr, sizeof(timestr), "%a, %d %b %Y %T %Z", tmp);
delete(&request);
/**
* @TODO: just to send an answer and be able to make some
* apache benchs i do it here...this definetly MUST BE moved
*/
sprintf((this->conns)[fd].wbuf, RESP_HEAD "\r\n" RESP_DATA, sizeof(RESP_DATA), timestr);
(this->fds)[i].events = (this->fds)[i].events | POLLOUT;
}
queue->nrequests = 0;
}
}
}
/**
* handle writes
*/
if (0 != ((this->fds)[i].revents & POLLOUT)) {
write(
(this->fds)[i].fd,
(this->conns)[fd].wbuf,
strlen((this->conns)[fd].wbuf));
(this->fds)[i].events = (this->fds)[i].events & ~POLLOUT;
serverCloseConn(this, i);
}
}
}
}

9
src/socket.c

@ -21,7 +21,14 @@ ctor(void * _this, va_list * params)
loggerLog(this->log, LOGGER_CRIT,
"error opening socket: %s - service terminated",
strerror(errno));
exit(EXIT_FAILURE);
//exit(EXIT_FAILURE);
/**
* @TODO: uhhhh, here we are leaking memory the socket is not
* initialized correctly and no one notices...
* Think about a way to prevent this.
* Well maybe we notice in server....
*/
return;
}
/* Make the socket REUSE a TIME_WAIT socket */

2
src/socket/accept.c

@ -22,7 +22,7 @@ socketAccept(Sock this, char remoteAddr[16])
sock->handle = accept(this->handle, (struct sockaddr *) &(sock->addr), &len);
if (-1 == sock->handle) {
loggerLog(this->log, LOGGER_WARNING,
"error acception connection: %s", strerror(errno));
"error accepting connection: %s", strerror(errno));
} else {
loggerLog(this->log, LOGGER_INFO,
"handling client %s\n", inet_ntoa((sock->addr).sin_addr));

1
src/testserver.c

@ -16,6 +16,7 @@ main()
Logger logger = new(LoggerStderr, LOGGER_INFO);
HttpRequestParser parser = new(HttpRequestParser);
Server server = new(Server, logger, parser, 11212, SOMAXCONN);
//Server server = new(Server, logger, parser, 11212, 20);
init_signals();
serverRun(server);

Loading…
Cancel
Save