Browse Source

started a response handler and changed serverRun to use it for its response

master
Georg Hopp 14 years ago
parent
commit
f82c178b5b
  1. 8
      ChangeLog
  2. 2
      TODO
  3. 3
      include/http/header.h
  4. 4
      include/http/request.h
  5. 17
      include/http/response.h
  6. 2
      include/server.h
  7. 20
      src/Makefile.am
  8. 16
      src/http/header/size_get.c
  9. 21
      src/http/header/to_string.c
  10. 31
      src/http/request/has_keep_alive.c
  11. 60
      src/http/response.c
  12. 49
      src/http/response/404.c
  13. 13
      src/http/response/header_set.c
  14. 27
      src/http/response/size_get.c
  15. 46
      src/http/response/to_string.c
  16. 4
      src/server.c
  17. 81
      src/server/run.c

8
ChangeLog

@ -1,6 +1,10 @@
2012-02-10 19:57:57 +0100 Georg Hopp
* started a response handler and changed serverRun to use it for its response (HEAD, master)
2012-02-10 12:42:04 +0100 Georg Hopp
* fixed bug at server destructor (HEAD, master)
* fixed bug at server destructor (origin/master, origin/HEAD)
2012-02-10 09:59:41 +0100 Georg Hopp
@ -12,7 +16,7 @@
2012-02-10 08:14:31 +0100 Georg Hopp
* now only use keep-alive.... (origin/master, origin/HEAD)
* now only use keep-alive....
2012-02-10 06:36:43 +0100 Georg Hopp

2
TODO

@ -0,0 +1,2 @@
VERY BIG TODO:
- give a contructor a way to fail, so that no object will be created at all

3
include/http/header.h

@ -10,8 +10,11 @@ CLASS(HttpHeader) {
};
HttpHeader httpHeaderParse(char * line); // @INFO: destructive
void httpHeaderSort(const HttpHeader [], int);
char * httpHeaderGet(const HttpHeader [], int, const char *);
size_t httpHeaderSizeGet(HttpHeader);
size_t httpHeaderToString(HttpHeader, char *);
#endif // __HTTP_HEADER_H__

4
include/http/request.h

@ -16,8 +16,8 @@ CLASS(HttpRequest) {
int nbody;
};
char *
httpRequestHeaderGet(HttpRequest this, const char * name);
char * httpRequestHeaderGet(HttpRequest, const char *);
char httpRequestHasKeepAlive(HttpRequest);
#endif /* __HTTP_REQUEST_H__ */

17
include/http/response.h

@ -1,12 +1,16 @@
#ifndef __HTTP_RESPONSE_H__
#define __HTTP_RESPONSE_H__
#include <sys/types.h>
#include "class.h"
#include "http/header.h"
CLASS(HttpResponse) {
char * http_version;
char * status;
char * reson;
char * version;
unsigned int status;
char * reason;
HttpHeader header[128];
int nheader;
@ -15,8 +19,11 @@ CLASS(HttpResponse) {
int nbody;
};
char *
httpRequestHeaderGet(HttpRequest this, const char * name);
HttpResponse httpResponse404();
void httpResponseHeaderSet(HttpResponse, const char *, const char *);
size_t httpResponseSizeGet(HttpResponse);
size_t httpResponseToString(HttpResponse, char *);
#endif /* __HTTP_RESPONSE_H__ */

2
include/server.h

@ -43,7 +43,7 @@ CLASS(Server) {
char keep_alive;
char wbuf[2048];
char * wbuf;
char * rbuf;
unsigned int rpos;
unsigned int wpos;

20
src/Makefile.am

@ -1,20 +1,26 @@
ACLOCAL_AMFLAGS = -I m4
AUTOMAKE_OPTIONS = subdir-objects
CLASS = class.c interface.c interface/class.c
IFACE = interface/class.c interface/stream_reader.c interface/logger.c
CLASS = class.c interface.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 http/request.c \
http/request/queue.c http/header.c http/header/get.c \
http/header/sort.c http/request/parser/get_header.c \
LOGGER = logger.c logger/stderr.c logger/syslog.c
REQ = http/request.c http/request/queue.c http/request/has_keep_alive.c
RESP = http/response.c http/response/header_set.c \
http/response/404.c http/response/size_get.c \
http/response/to_string.c
HEADER = http/header.c http/header/get.c http/header/sort.c \
http/header/size_get.c http/header/to_string.c
PARSER = http/request/parser.c http/request/parser/get_header.c \
http/request/parser/parse.c http/request/parser/get_request_line.c
AM_CFLAGS = -Wall -I ../include/
bin_PROGRAMS = testserver
testserver_SOURCES = testserver.c \
$(CLASS) $(SOCKET) $(SERVER) $(LOGGER) $(HTTP) \
signalHandling.c daemonize.c
$(IFACE) $(CLASS) $(SOCKET) $(SERVER) $(LOGGER) $(REQ) \
$(RESP) $(HEADER) $(PARSER) signalHandling.c daemonize.c
testserver_CFLAGS = -Wall -I ../include/

16
src/http/header/size_get.c

@ -0,0 +1,16 @@
#include <sys/types.h>
#include "http/header.h"
size_t
httpHeaderSizeGet(HttpHeader header)
{
size_t size = 0;
size += strlen(header->name) + 2;
size += strlen(header->value);
return size;
}
// vim: set ts=4 sw=4:

21
src/http/header/to_string.c

@ -0,0 +1,21 @@
#include <string.h>
#include "http/header.h"
size_t
httpHeaderToString(HttpHeader header, char * string)
{
size_t size = httpHeaderSizeGet(header);
strcpy(string, header->name);
string += strlen(string);
*string++ = ':';
*string++ = ' ';
strcpy(string, header->value);
return size;
}
// vim: set ts=4 sw=4:

31
src/http/request/has_keep_alive.c

@ -0,0 +1,31 @@
#include <string.h>
#include <ctype.h>
#include "http/request.h"
#include "http/header.h"
char
httpRequestHasKeepAlive(HttpRequest request)
{
char * header;
char * header_ptr;
header = httpHeaderGet(request->header, request->nheader, "connection");
if (NULL == header) {
return 0;
}
for (header_ptr = header; 0 != *header_ptr; header_ptr++) {
*header_ptr = tolower(*header_ptr);
}
if (0 == strcmp(header, "keep-alive")) {
return 1;
}
return 0;
}
// vim: set ts=4 sw=4:

60
src/http/response.c

@ -0,0 +1,60 @@
#include <stdlib.h>
#include <stdarg.h>
#include "class.h"
#include "interface/class.h"
#include "http/response.h"
static
void
_free(void ** data)
{
if (NULL != *data) {
free(*data);
}
}
static
void
ctor(void * _this, va_list * params)
{
char * version;
char * reason;
HttpResponse this = _this;
version = va_arg(* params, char *);
this->status = va_arg(* params, unsigned int);
reason = va_arg(* params, char *);
this->version = calloc(1, strlen(version)+1);
strcpy(this->version, version);
this->reason = calloc(1, strlen(reason)+1);
strcpy(this->reason, reason);
}
static
void
dtor(void * _this)
{
HttpResponse this = _this;
int i;
_free((void **)&(this->version));
_free((void **)&(this->reason));
for (i=0; i<128; i++) {
if (NULL == (this->header)[i]) break;
delete(&(this->header)[i]);
}
_free((void **)&(this->body));
}
INIT_IFACE(Class, ctor, dtor, NULL);
CREATE_CLASS(HttpResponse, NULL, IFACE(Class));
// vim: set ts=4 sw=4:

49
src/http/response/404.c

@ -0,0 +1,49 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include "class.h"
#include "interface/class.h"
#include "http/response.h"
#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>"
HttpResponse
httpResponse404()
{
time_t t;
struct tm * tmp;
char buffer[200];
HttpResponse response;
response = new(HttpResponse, "HTTP/1.1", 404, "Not Found");
httpResponseHeaderSet(response, "Content-Type", "text/html");
httpResponseHeaderSet(response, "Server", "testserver");
response->nbody = sizeof(RESP_DATA) - 1;
response->body = calloc(1, sizeof(RESP_DATA));
strcpy(response->body, RESP_DATA);
sprintf(buffer, "%d", response->nbody);
httpResponseHeaderSet(response, "Content-Length", buffer);
t = time(NULL);
tmp = localtime(&t);
strftime(buffer, sizeof(buffer), "%a, %d %b %Y %T %Z", tmp);
httpResponseHeaderSet(response, "Date", buffer);
return response;
}
// vim: set ts=4 sw=4:

13
src/http/response/header_set.c

@ -0,0 +1,13 @@
#include "class.h"
#include "interface/class.h"
#include "http/response.h"
#include "http/header.h"
void
httpResponseHeaderSet(HttpResponse this, const char * name, const char * value)
{
(this->header)[this->nheader++] = new(HttpHeader, name, value);
}
// vim: set ts=4 sw=4:

27
src/http/response/size_get.c

@ -0,0 +1,27 @@
#include <string.h>
#include <sys/types.h>
#include "http/response.h"
#include "http/header.h"
size_t
httpResponseSizeGet(HttpResponse response)
{
int i;
size_t size = 0;
size += strlen(response->version) + 1;
size += 4; // for status
size += strlen(response->reason) + 2;
for (i=0; i<response->nheader; i++) {
size += httpHeaderSizeGet(response->header[i]) + 2;
}
size += 2;
size += response->nbody;
return size;
}
// vim: set ts=4 sw=4:

46
src/http/response/to_string.c

@ -0,0 +1,46 @@
#include <string.h>
#include <stdio.h>
#include "http/response.h"
#include "http/header.h"
size_t
httpResponseToString(HttpResponse response, char * string)
{
int i;
size_t size = httpResponseSizeGet(response);
char status[4];
snprintf(status, 4, "%d", response->status);
strcpy(string, response->version);
string += strlen(string);
*string++ = ' ';
strcpy(string, status);
string += strlen(string);
*string++ = ' ';
strcpy(string, response->reason);
string += strlen(string);
*string++ = '\r';
*string++ = '\n';
for (i=0; i<response->nheader; i++) {
string += httpHeaderToString(response->header[i], string);
*string++ = '\r';
*string++ = '\n';
}
*string++ = '\r';
*string++ = '\n';
memcpy(string, response->body, response->nbody);
return size;
}
// vim: set ts=4 sw=4:

4
src/server.c

@ -36,14 +36,14 @@ dtor(void * _this)
Server this = _this;
int i;
printf("nfds: %d\n", this->nfds);
for (i=1; i<this->nfds; i++) {
/*
* @TODO do some finalization...buffer handling...etc.
*/
delete(&(this->conns[(this->fds)[i].fd]).sock);
delete(&(this->conns[(this->fds)[i].fd]).reader);
if (this->conns[(this->fds)[i].fd].wbuf)
free(this->conns[(this->fds)[i].fd].wbuf);
}
delete(&this->sock);

81
src/server/run.c

@ -18,7 +18,7 @@
#include "http/request.h"
#include "http/request/parser.h"
#include "http/request/queue.h"
#include "http/header.h"
#include "http/response.h"
//* until here
#undef MAX
@ -82,72 +82,35 @@ serverRun(Server this)
for (j=0; j<queue->nrequests; j++) {
HttpRequest request = queue->requests[j];
char * header;
char * header_ptr;
HttpResponse response;
//if (NULL != request->body) {
// puts("==REQUEST BODY==");
// puts(request->body);
//}
header = httpHeaderGet(
request->header,
request->nheader,
"connection");
if (NULL != header) {
for (header_ptr = header;
0 != *header_ptr;
header_ptr++) {
*header_ptr = tolower(*header_ptr);
}
if (0 == strcmp(header, "keep-alive")) {
(this->conns)[fd].keep_alive = 1;
}
}
/**
* @TODO: for now simply remove request and send not found.
* Make this sane.
*/
response = httpResponse404();
delete(&request);
/**
* @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);
/**
* @TODO: just to send an answer and be able to make some
* apache benchs i do it here...this definetly MUST BE moved
*/
if ((this->conns)[fd].keep_alive) {
sprintf((this->conns)[fd].wbuf, RESP_HEAD "Connection: Keep-Alive\r\n\r\n" RESP_DATA, sizeof(RESP_DATA) - 1, timestr);
if (httpRequestHasKeepAlive(request)) {
httpResponseHeaderSet(
response,
"Connection",
"Keep-Alive");
}
else {
sprintf((this->conns)[fd].wbuf, RESP_HEAD "Connection: close\r\n\r\n" RESP_DATA, sizeof(RESP_DATA) - 1, timestr);
httpResponseHeaderSet(
response,
"Connection",
"Close");
}
delete(&request);
(this->conns)[fd].wbuf = calloc(
1, httpResponseSizeGet(response) + 1);
httpResponseToString(response, (this->conns)[fd].wbuf);
delete(&response);
(this->fds)[i].events |= POLLOUT;
}
@ -180,6 +143,8 @@ serverRun(Server this)
else {
serverCloseConn(this, i);
}
free((this->conns)[fd].wbuf);
(this->conns)[fd].wbuf = NULL;
}
else {
memmove((this->conns)[fd].wbuf,

Loading…
Cancel
Save