17 changed files with 335 additions and 85 deletions
-
8ChangeLog
-
2TODO
-
7include/http/header.h
-
4include/http/request.h
-
25include/http/response.h
-
2include/server.h
-
20src/Makefile.am
-
16src/http/header/size_get.c
-
21src/http/header/to_string.c
-
31src/http/request/has_keep_alive.c
-
60src/http/response.c
-
49src/http/response/404.c
-
13src/http/response/header_set.c
-
27src/http/response/size_get.c
-
46src/http/response/to_string.c
-
4src/server.c
-
85src/server/run.c
@ -0,0 +1,2 @@ |
|||||
|
VERY BIG TODO: |
||||
|
- give a contructor a way to fail, so that no object will be created at all |
||||
@ -1,22 +1,29 @@ |
|||||
#ifndef __HTTP_RESPONSE_H__ |
#ifndef __HTTP_RESPONSE_H__ |
||||
#define __HTTP_RESPONSE_H__ |
#define __HTTP_RESPONSE_H__ |
||||
|
|
||||
|
#include <sys/types.h> |
||||
|
|
||||
#include "class.h" |
#include "class.h" |
||||
|
#include "http/header.h" |
||||
|
|
||||
|
|
||||
CLASS(HttpResponse) { |
CLASS(HttpResponse) { |
||||
char * http_version; |
|
||||
char * status; |
|
||||
char * reson; |
|
||||
|
char * version; |
||||
|
unsigned int status; |
||||
|
char * reason; |
||||
|
|
||||
HttpHeader header[128]; |
|
||||
int nheader; |
|
||||
|
HttpHeader header[128]; |
||||
|
int nheader; |
||||
|
|
||||
char * body; |
|
||||
int nbody; |
|
||||
|
char * body; |
||||
|
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__ */ |
#endif /* __HTTP_RESPONSE_H__ */ |
||||
|
|
||||
|
|||||
@ -1,20 +1,26 @@ |
|||||
ACLOCAL_AMFLAGS = -I m4 |
ACLOCAL_AMFLAGS = -I m4 |
||||
AUTOMAKE_OPTIONS = subdir-objects |
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 |
SOCKET = socket.c socket/accept.c socket/connect.c socket/listen.c |
||||
SERVER = server.c server/run.c server/close_conn.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 |
http/request/parser/parse.c http/request/parser/get_request_line.c |
||||
|
|
||||
|
|
||||
AM_CFLAGS = -Wall -I ../include/ |
AM_CFLAGS = -Wall -I ../include/ |
||||
|
|
||||
bin_PROGRAMS = testserver |
bin_PROGRAMS = testserver |
||||
|
|
||||
testserver_SOURCES = testserver.c \
|
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/ |
testserver_CFLAGS = -Wall -I ../include/ |
||||
@ -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: |
||||
@ -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: |
||||
@ -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: |
||||
@ -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: |
||||
@ -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: |
||||
@ -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: |
||||
@ -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: |
||||
@ -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: |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue