Browse Source

add StreamReader interface, modify HttpRequestParser and Server to use it

master
Georg Hopp 14 years ago
parent
commit
90476e07d8
  1. 54
      ChangeLog
  2. 17
      include/http/request.h
  3. 32
      include/http/request_parser.h
  4. 6
      include/http/request_queue.h
  5. 19
      include/interface/stream_reader.h
  6. 6
      include/server.h
  7. 5
      src/Makefile.am
  8. 111
      src/http/request_parser.c
  9. 19
      src/interface/stream_reader.c
  10. 2
      src/server.c
  11. 28
      src/server/run.c
  12. 22
      src/testserver.c

54
ChangeLog

@ -1,6 +1,58 @@
2012-02-06 11:20:00 +0100 Georg Hopp
* add StreamReader interface, modify HttpRequestParser and Server to use it (HEAD, master)
2012-02-06 11:15:00 +0100 Georg Hopp
* add missing include to stdarg.h
2012-02-06 10:45:33 +0100 Georg Hopp
* implement clone selector
2012-02-06 10:43:59 +0100 Georg Hopp
* add ability to call interface methods with return value
2012-02-06 02:37:55 +0100 Georg Hopp
* make build system work again
2012-02-06 02:37:24 +0100 Georg Hopp
* remove inline stuff for now ... add carefully again later perhaps
2012-02-06 00:57:26 +0100 Georg Hopp
* and also mod conigure.ac
2012-02-06 00:55:44 +0100 Georg Hopp
* makefile modification for new class stuff
2012-02-05 22:55:16 +0100 Georg Hopp
* changed class tool. Now multiple interface per class are supported as well as simple inheritence.
2012-02-05 22:47:10 +0100 Georg Hopp
* some latest work
2012-02-05 22:44:59 +0100 Georg Hopp
* added some documentation
2012-02-05 22:42:37 +0100 Georg Hopp
* changes related to server code
2012-01-19 16:41:41 +0100 Georg Hopp
* added some valueable thought about cclass and how this structure might evolve to a real class
2012-01-18 07:52:07 +0100 Georg Hopp
* add testserver and did some fixes not shown by my incomplete tests (HEAD, master)
* add testserver and did some fixes not shown by my incomplete tests
2012-01-17 15:40:07 +0100 Georg Hopp

17
include/http/request.h

@ -1,21 +1,20 @@
#ifndef __HTTP_REQUEST_H__
#define __HTTP_REQUEST_H__
#include "cclass.h"
#include "class.h"
CLASS(HTTP_REQUEST) {
char * http_version;
char * uri;
char * method;
CLASS(HttpRequest) {
char * http_version;
char * uri;
char * method;
struct {
char * name;
char * value;
} header[128];
} header[128];
char * body;
unsigned char done;
char * body;
char done;
};
#endif /* __HTTP_REQUEST_H__ */

32
include/http/request_parser.h

@ -1,32 +1,28 @@
#ifndef __HTTP_REQUEST_PARSER_H__
#define __HTTP_REQUEST_PARSER_H__
#include "cclass.h"
#include "server.h"
#include "http/request.h"
#include "http/request_queue.h"
#include "class.h"
//#include "http/request.h"
//#include "http/request_queue.h"
#define HTTP_REQUEST_PARSER_READ_CHUNK 1024
#define HTTP_REQUEST_PARSER_START 0
#define HTTP_REQUEST_PARSER_REQUEST_LINE_DONE 1
#define HTTP_REQUEST_PARSER_HEADERS_DONE 2
#define HTTP_REQUEST_PARSER_DONE 3
typedef enum e_HttpRequestState {
HTTP_REQUEST_START=0,
HTTP_REQUEST_REQEUST_LINE_DONE,
HTTP_REQUEST_HEADERS_DONE,
HTTP_REQUEST_DONE
} HttpRequestState;
CLASS(HTTP_REQUEST_PARSER) {
server_read_hook get_data;
CLASS(HttpRequestParser) {
char * buffer;
size_t buffer_used;
char * buffer;
size_t buffer_used;
HTTP_REQUEST_QUEUE request_queue;
unsigned char state;
//HttpRequestQueue request_queue;
HttpRequestState state;
};
void http_request_parser_parse(const char * buffer, size_t size);
#endif /* __HTTP_REQUEST_PARSER_H__ */
// vim: set ts=4 sw=4:

6
include/http/request_queue.h

@ -1,14 +1,14 @@
#ifndef __HTTP_REQUEST_QUEUE_H__
#define __HTTP_REQUEST_QUEUE_H__
#include "cclass.h"
#include "class.h"
#include "http/request.h"
#define HTTP_REQUEST_QUEUE_MAX 1024
CLASS(HTTP_REQUEST_QUEUE) {
REQUEST requests[HTTP_REQUEST_QUEUE_MAX];
CLASS(HttpRequestQueue) {
HttpRequest requests[HTTP_REQUEST_QUEUE_MAX];
size_t nrequests;
}

19
include/interface/stream_reader.h

@ -0,0 +1,19 @@
#ifndef __STREAM_READER_H__
#define __STREAM_READER_H__
#include <sys/types.h>
typedef size_t (* fptr_streamReaderRead)(void *, int fd);
extern const struct interface i_StreamReader;
struct i_StreamReader {
const struct interface * const _;
fptr_streamReaderRead read;
};
extern size_t streamReaderRead(void *, int fd);
#endif // __STREAM_READER_H__
// vim: set ts=4 sw=4:

6
include/server.h

@ -26,18 +26,20 @@ typedef void (*server_read_hook)(const char *, size_t);
CLASS(Server) {
Logger logger;
Sock sock;
void * reader;
nfds_t nfds;
struct pollfd fds[POLL_FD_NSIZE];
struct {
Sock sock;
void * reader;
char * wbuf;
char * rbuf;
unsigned int rpos;
unsigned int wpos;
} conns[POLL_FD_NSIZE];
server_read_hook read_hook;
};
void serverRun(Server this);

5
src/Makefile.am

@ -5,10 +5,13 @@ CLASS = class.c interface.c interface/class.c
SOCKET = socket.c socket/accept.c socket/connect.c socket/listen.c
SERVER = server.c server/run.c server/close_conn.c
LOGGER = logger.c logger/stderr.c logger/syslog.c interface/logger.c
HTTP = interface/stream_reader.c http/request_parser.c
AM_CFLAGS = -Wall -I ../include/
bin_PROGRAMS = testserver
testserver_SOURCES = testserver.c $(CLASS) $(SOCKET) $(SERVER) $(LOGGER) signalHandling.c daemonize.c
testserver_SOURCES = testserver.c \
$(CLASS) $(SOCKET) $(SERVER) $(LOGGER) $(HTTP) \
signalHandling.c daemonize.c
testserver_CFLAGS = -Wall -I ../include/

111
src/http/request_parser.c

@ -1,51 +1,108 @@
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include "cclass.h"
#include "http/request.h"
#include "class.h"
#include "http/request_parser.h"
INIT_CLASS(HTTP_REQUEST_PARSER);
__construct(LOGGER)
#include "interface/class.h"
#include "interface/stream_reader.h"
//#include "http/request.h"
//#include "http/request_queue.h"
static
void
httpRequestParserParse(char * data, size_t * size);
static
void
ctor(void * _this, va_list * params)
{
this->request_queue = va_arg(*params, HTTP_REQUEST_QUEUE);
HttpRequestParser this = _this;
//this->request_queue = va_arg(*params, HttpRequestQueue);
this->buffer = malloc(HTTP_REQUEST_PARSER_READ_CHUNK);
}
__destruct(LOGGER)
static
void
dtor(void * _this)
{
HttpRequestParser this = _this;
free(this->buffer);
}
__jsonConst(LOGGER) {}
__toJson(LOGGER) {}
__clear(LOGGER) {}
static void
get_data(HTTP_REQUEST_PARSER this, const char * data, size_t size)
static
void
_clone(void * _this, void * _base)
{
size_t remaining, chunks;
HttpRequestParser this = _this;
HttpRequestParser base = _base;
size_t chunks;
//this->request_queue = base->request_queue;
this->buffer_used = base->buffer_used;
remaining = this->buffer_used % HTTP_REQUEST_PARSER_READ_CHUNK;
chunks = this->buffer_used / HTTP_REQUEST_PARSER_READ_CHUNK;
chunks = this->buffer_used / HTTP_REQUEST_PARSER_READ_CHUNK;
chunks++;
chunks = (0 == remaining) ? chunks++ : chunks;
this->buffer = malloc(chunks * HTTP_REQUEST_PARSER_READ_CHUNK);
memcpy(this->buffer, base->buffer, this->buffer_used);
}
if (size > remaining) {
this->buffer =
realloc(this->buffer, chunks * HTTP_REQUEST_PARSER_READ_CHUNK);
static
size_t
get_data(void * _this, int fd)
{
HttpRequestParser this = _this;
size_t remaining, chunks;
char buffer[1024];
size_t size = read(fd, buffer, 1024);
if (0 < size) {
remaining = this->buffer_used % HTTP_REQUEST_PARSER_READ_CHUNK;
chunks = this->buffer_used / HTTP_REQUEST_PARSER_READ_CHUNK;
/**
* because a division always rounds down
* chunks holds exactly the currently allocated chunks if
* remaining equals 0 but there is no space left.
* Else chunks holds the actually allocated amount of chunks
* minus 1.
* For this reason chunks always has to be increased by 1.
*/
chunks++;
if (size > remaining) {
this->buffer =
realloc(this->buffer, chunks * HTTP_REQUEST_PARSER_READ_CHUNK);
}
memcpy(this->buffer + this->buffer_used, buffer, size);
this->buffer_used += size;
httpRequestParserParse(this->buffer, &this->buffer_used);
}
memcpy(this->buffer + this->buffer_used, data, size);
this->buffer_used += size;
return size;
}
void http_request_parser_parse(const char * data, size_t size)
INIT_IFACE(Class, ctor, dtor, _clone);
INIT_IFACE(StreamReader, get_data);
CREATE_CLASS(HttpRequestParser, NULL, IFACE(Class), IFACE(StreamReader));
static
void
httpRequestParserParse(char * data, size_t * size)
{
data[*size] = 0;
printf("%s", data);
*size = 0;
}
// vim: set ts=4 sw=4:

19
src/interface/stream_reader.c

@ -0,0 +1,19 @@
#include "class.h"
#include "interface/stream_reader.h"
const struct interface i_StreamReader = {
"streamReader",
1
};
size_t
streamReaderRead(void * object, int fd)
{
size_t ret;
RETCALL(object, StreamReader, read, ret, fd);
return ret;
}
// vim: set ts=4 sw=4:

2
src/server.c

@ -17,6 +17,7 @@ ctor(void * _this, va_list * params)
unsigned int backlog;
this->logger = va_arg(* params, Logger);
this->reader = va_arg(* params, void*);
port = va_arg(* params, int);
backlog = va_arg(* params, unsigned int);
@ -40,6 +41,7 @@ dtor(void * _this)
* @TODO do some finalization...buffer handling...etc.
*/
delete(&(this->conns[i]).sock);
delete(&(this->conns[i]).reader);
}
delete(&this->sock);

28
src/server/run.c

@ -9,6 +9,7 @@
#include "logger.h"
#include "signalHandling.h"
#include "interface/class.h"
#include "interface/stream_reader.h"
#undef MAX
#define MAX(x,y) ((x) > (y) ? (x) : (y))
@ -52,9 +53,10 @@ serverHandleAccept(Server this)
acc = socketAccept(this->sock, remoteAddr);
if (-1 != acc->handle) {
(this->conns)[this->nfds].sock = acc; // save the socket handle
(this->fds)[this->nfds].fd = acc->handle;
(this->fds)[this->nfds].events = POLLIN;
(this->conns)[this->nfds].sock = acc; // save the socket handle
(this->conns)[this->nfds].reader = clone(this->reader); // clone reader
(this->fds)[this->nfds].fd = acc->handle;
(this->fds)[this->nfds].events = POLLIN;
this->nfds++;
} else {
delete(&acc);
@ -69,32 +71,34 @@ int
serverRead(Server this)
{
unsigned int i;
size_t _read;
char buffer[1024];
for (i=1; i<this->nfds; i++) {
if (0 != ((this->fds)[i].revents & POLLIN)) {
switch (_read = read((this->fds)[i].fd, buffer, 1024)) {
if (NULL == (this->conns)[i].reader) {
loggerLog(
this->logger,
LOGGER_INFO,
"initialization error: NULL reader");
serverCloseConn(this, i);
}
switch (streamReaderRead((this->conns)[i].reader, (this->fds)[i].fd)) {
case 0:
/*
* normal close: write remaining data
* @TODO: actually we have no remaining data here....
*/
/* FALLTHROUGH */
/* DROP-THROUGH */
case -1:
/*
* read failure / close connection
* FALLTHROUGH
*/
loggerLog(this->logger, LOGGER_INFO, "connection closed...");
serverCloseConn(this, i);
break;
default:
(this->fds)[i].revents |= POLLIN;
if (NULL != this->read_hook) {
this->read_hook(buffer, _read);
}
break;
}
}

22
src/testserver.c

@ -4,33 +4,25 @@
#include "server.h"
#include "logger.h"
#include "signalHandling.h"
#include "interface/class.h"
static void
read_hook(const char * _buffer, size_t size)
{
char buffer[1025];
#include "http/request_parser.h"
memset(buffer, 0, 1025);
snprintf(buffer, 1025>size? size : 1024, "%s", _buffer);
#include "signalHandling.h"
printf("%s\n", buffer);
}
#include "interface/class.h"
int
main()
{
Logger logger = new(LoggerStderr, LOGGER_INFO);
Server server = new(Server, logger, 11212, SOMAXCONN);
server->read_hook = read_hook;
Logger logger = new(LoggerStderr, LOGGER_INFO);
HttpRequestParser parser = new(HttpRequestParser);
Server server = new(Server, logger, parser, 11212, SOMAXCONN);
init_signals();
serverRun(server);
delete(&server);
delete(&logger);
delete(&parser);
return 0;
}

Loading…
Cancel
Save