Browse Source

structural changes for worker/process. @TODO actually i have no idea why this happens.

master
Georg Hopp 14 years ago
parent
commit
87b0d50d1d
  1. 8
      ChangeLog
  2. 4
      TODO
  3. 6
      include/http/header.h
  4. 5
      include/http/response.h
  5. 2
      include/interface/class.h
  6. 2
      include/utils/memory.h
  7. 6
      src/Makefile.am
  8. 28
      src/cbuf.c
  9. 16
      src/http/header.c
  10. 17
      src/http/header/add.c
  11. 4
      src/http/header/size_get.c
  12. 12
      src/http/message.c
  13. 8
      src/http/message/queue.c
  14. 14
      src/http/request.c
  15. 17
      src/http/request/parser.c
  16. 8
      src/http/response.c
  17. 33
      src/http/response/304.c
  18. 2
      src/http/response/404.c
  19. 42
      src/http/response/asset.c
  20. 75
      src/http/response/image.c
  21. 2
      src/http/response/me.c
  22. 10
      src/http/response/writer.c
  23. 4
      src/http/response/writer/write.c
  24. 19
      src/http/worker.c
  25. 37
      src/http/worker/add_common_header.c
  26. 29
      src/http/worker/get_asset.c
  27. 76
      src/http/worker/process.c
  28. 6
      src/logger.c
  29. 16
      src/server.c
  30. 4
      src/server/close_conn.c
  31. 2
      src/server/handle_accept.c
  32. 8
      src/socket.c
  33. 6
      src/testserver.c

8
ChangeLog

@ -1,10 +1,14 @@
2012-02-22 12:19:40 +0100 Georg Hopp
* fix memory problems occured with latest changes (HEAD, master)
2012-02-22 09:03:40 +0100 Georg Hopp 2012-02-22 09:03:40 +0100 Georg Hopp
* fixed bug in keep-alive check arised by implementation if #10 (HEAD, master)
* fixed bug in keep-alive check arised by implementation if #10 (origin/master, origin/HEAD)
2012-02-22 08:51:05 +0100 Georg Hopp 2012-02-22 08:51:05 +0100 Georg Hopp
* add forgotten jquery assets (origin/master, origin/HEAD)
* add forgotten jquery assets
2012-02-22 08:48:43 +0100 Georg Hopp 2012-02-22 08:48:43 +0100 Georg Hopp

4
TODO

@ -1,6 +1,6 @@
VERY BIG TODO: VERY BIG TODO:
- give a contructor a way to fail, so that no object will be created at all
- right now i will use long polling ajax calls when feedback from to the client - right now i will use long polling ajax calls when feedback from to the client
is needed. In the long term this should be changed to websockets (ws). But is needed. In the long term this should be changed to websockets (ws). But
right now ws specification is not final anyway. :) right now ws specification is not final anyway. :)
- handle errors after all system call...especially open, close, etc.

6
include/http/header.h

@ -27,16 +27,18 @@
#include "class.h" #include "class.h"
#define HTTP_HEADER_VALUE_CHUNK_SIZE 128
CLASS(HttpHeader) { CLASS(HttpHeader) {
unsigned long hash; unsigned long hash;
char * name; char * name;
char ** value;
char * value[HTTP_HEADER_VALUE_CHUNK_SIZE];
size_t nvalue; size_t nvalue;
}; };
HttpHeader httpHeaderParse(char * line); // @INFO: destructive HttpHeader httpHeaderParse(char * line); // @INFO: destructive
void httpHeaderAdd(const HttpHeader *, HttpHeader);
HttpHeader httpHeaderAdd(const HttpHeader *, HttpHeader);
HttpHeader httpHeaderGet(const HttpHeader *, const char *); HttpHeader httpHeaderGet(const HttpHeader *, const char *);
size_t httpHeaderSizeGet(HttpHeader); size_t httpHeaderSizeGet(HttpHeader);
size_t httpHeaderToString(HttpHeader, char *); size_t httpHeaderToString(HttpHeader, char *);

5
include/http/response.h

@ -38,11 +38,10 @@ CLASS(HttpResponse) {
char * reason; char * reason;
}; };
HttpResponse httpResponse304(int, const char *);
HttpResponse httpResponse304(const char *, const char *, const char *);
HttpResponse httpResponse404(); HttpResponse httpResponse404();
HttpResponse httpResponseMe(int); HttpResponse httpResponseMe(int);
HttpResponse httpResponseImage(int);
HttpResponse httpResponseJquery(int);
HttpResponse httpResponseAsset(const char *, const char *, const char *);
#endif // __HTTP_RESPONSE_H__ #endif // __HTTP_RESPONSE_H__

2
include/interface/class.h

@ -49,7 +49,7 @@ extern void classDelete(void **);
extern void * classClone(void *); extern void * classClone(void *);
#define new(class,...) classNew(_##class, ##__VA_ARGS__) #define new(class,...) classNew(_##class, ##__VA_ARGS__)
#define delete(object) classDelete((void **)(object))
#define delete(object) classDelete((void **)&(object))
#define clone(object) classClone((void *)(object)) #define clone(object) classClone((void *)(object))
#endif // __INTERFACE_CLASS_H__ #endif // __INTERFACE_CLASS_H__

2
include/utils/memory.h

@ -23,7 +23,7 @@
#ifndef __UTILS_MEMORY_H__ #ifndef __UTILS_MEMORY_H__
#define __UTILS_MEMORY_H__ #define __UTILS_MEMORY_H__
#define FREE(val) (ffree((void**)(val)))
#define FREE(val) (ffree((void**)&(val)))
void ffree(void **); void ffree(void **);

6
src/Makefile.am

@ -23,10 +23,10 @@ REQ = http/request.c http/request/has_valid_method.c
RESP = http/response.c \ RESP = http/response.c \
http/response/304.c \ http/response/304.c \
http/response/404.c \ http/response/404.c \
http/response/image.c \
http/response/jquery.c \
http/response/asset.c \
http/response/me.c http/response/me.c
WORKER = http/worker.c http/worker/process.c http/worker/write.c
WORKER = http/worker.c http/worker/process.c http/worker/write.c \
http/worker/get_asset.c http/worker/add_common_header.c
WRITER = http/response/writer.c http/response/writer/write.c WRITER = http/response/writer.c http/response/writer/write.c
HEADER = http/header.c http/header/get.c http/header/add.c \ HEADER = http/header.c http/header/get.c http/header/add.c \
http/header/size_get.c http/header/to_string.c http/header/size_get.c http/header/to_string.c

28
src/cbuf.c

@ -35,18 +35,19 @@
#include "class.h" #include "class.h"
#include "interface/class.h" #include "interface/class.h"
#include "utils/memory.h"
#include "cbuf.h" #include "cbuf.h"
static void dtor(void*);
static void cbufDtor(void*);
static static
int int
ctor(void * _this, va_list * params)
cbufCtor(void * _this, va_list * params)
{ {
Cbuf this = _this; Cbuf this = _this;
char state = 0;
char state = -1;
char * shm_name = va_arg(*params, char*); char * shm_name = va_arg(*params, char*);
long psize = sysconf(_SC_PAGESIZE); long psize = sysconf(_SC_PAGESIZE);
size_t size; size_t size;
@ -64,7 +65,7 @@ ctor(void * _this, va_list * params)
size = (0 >= size)? 1 : (0 != size%psize)? (size/psize)+1 : size/psize; size = (0 >= size)? 1 : (0 != size%psize)? (size/psize)+1 : size/psize;
this->bsize = psize * size; this->bsize = psize * size;
while (0 == state) {
while (-1 == state) {
shm = shm_open(this->shm_name, O_RDWR|O_CREAT|O_EXCL, S_IRWXU); shm = shm_open(this->shm_name, O_RDWR|O_CREAT|O_EXCL, S_IRWXU);
if (-1 == shm) { if (-1 == shm) {
break; break;
@ -93,7 +94,7 @@ ctor(void * _this, va_list * params)
break; break;
} }
state = 1;
state = 0;
} }
if (-1 != shm) { if (-1 != shm) {
@ -101,32 +102,25 @@ ctor(void * _this, va_list * params)
close(shm); close(shm);
} }
if (1 != state) {
dtor(this);
}
return 0;
return state;
} }
static static
void void
dtor(void * _this)
cbufDtor(void * _this)
{ {
Cbuf this = _this; Cbuf this = _this;
if (NULL != this->shm_name) {
free(this->shm_name);
}
FREE(this->shm_name);
if (NULL != this->data && MAP_FAILED != this->data) { if (NULL != this->data && MAP_FAILED != this->data) {
munmap(this->data, this->bsize << 1); munmap(this->data, this->bsize << 1);
} }
this->shm_name = NULL;
this->data = NULL;
this->data = NULL;
} }
INIT_IFACE(Class, ctor, dtor, NULL);
INIT_IFACE(Class, cbufCtor, cbufDtor, NULL);
CREATE_CLASS(Cbuf, NULL, IFACE(Class)); CREATE_CLASS(Cbuf, NULL, IFACE(Class));
// vim: set ts=4 sw=4: // vim: set ts=4 sw=4:

16
src/http/header.c

@ -33,7 +33,7 @@
static static
int int
ctor(void * _this, va_list * params) {
httpHeaderCtor(void * _this, va_list * params) {
HttpHeader this = _this; HttpHeader this = _this;
char * name; char * name;
char * value; char * value;
@ -46,29 +46,27 @@ ctor(void * _this, va_list * params) {
this->hash = sdbm((unsigned char *)name); this->hash = sdbm((unsigned char *)name);
this->value = malloc(sizeof(char*) * (++(this->nvalue)));
(this->value)[this->nvalue - 1] = malloc(strlen(value) + 1);
strcpy((this->value)[this->nvalue - 1], value);
(this->value)[this->nvalue] = malloc(strlen(value) + 1);
strcpy((this->value)[this->nvalue++], value);
return 0; return 0;
} }
static static
void void
dtor(void * _this)
httpHeaderDtor(void * _this)
{ {
HttpHeader this = _this; HttpHeader this = _this;
size_t i; size_t i;
FREE(&(this->name));
FREE(this->name);
for (i=0; i<this->nvalue; i++) { for (i=0; i<this->nvalue; i++) {
FREE(&(this->value[i]));
FREE(this->value[i]);
} }
FREE(&(this->value));
} }
INIT_IFACE(Class, ctor, dtor, NULL);
INIT_IFACE(Class, httpHeaderCtor, httpHeaderDtor, NULL);
CREATE_CLASS(HttpHeader, NULL, IFACE(Class)); CREATE_CLASS(HttpHeader, NULL, IFACE(Class));
// vim: set ts=4 sw=4: // vim: set ts=4 sw=4:

17
src/http/header/add.c

@ -40,20 +40,21 @@ comp(const void * _a, const void * _b)
return (a->hash < b->hash)? -1 : (a->hash > b->hash)? 1 : 0; return (a->hash < b->hash)? -1 : (a->hash > b->hash)? 1 : 0;
} }
void
HttpHeader
httpHeaderAdd(const HttpHeader * root, HttpHeader header) httpHeaderAdd(const HttpHeader * root, HttpHeader header)
{ {
HttpHeader * found = tsearch(header, (void **)root, comp); HttpHeader * found = tsearch(header, (void **)root, comp);
if (*found != header) { if (*found != header) {
(*found)->value = realloc(
(*found)->value,
sizeof(char*) * (++(*found)->nvalue));
(*found)->value[(*found)->nvalue - 1] = malloc(
strlen((header->value)[0]) + 1);
strcpy(((*found)->value)[(*found)->nvalue - 1], (header->value)[0]);
delete(&header);
if ((*found)->nvalue >= HTTP_HEADER_VALUE_CHUNK_SIZE) {
return NULL;
}
(*found)->value[(*found)->nvalue++] = (header->value)[0];
(header->value)[0] = NULL;
delete(header);
} }
return *found;
} }
// vim: set ts=4 sw=4: // vim: set ts=4 sw=4:

4
src/http/header/size_get.c

@ -28,11 +28,11 @@
size_t size_t
httpHeaderSizeGet(HttpHeader header) httpHeaderSizeGet(HttpHeader header)
{ {
size_t size = 0;
size_t nsize = strlen(header->name) + 2;
size_t size = header->nvalue * nsize;
int i; int i;
for (i=0; i<header->nvalue; i++) { for (i=0; i<header->nvalue; i++) {
size += strlen(header->name) + 2;
size += strlen(header->value[i]) + 2; size += strlen(header->value[i]) + 2;
} }

12
src/http/message.c

@ -42,12 +42,12 @@ inline
void void
tDelete(void * node) tDelete(void * node)
{ {
delete(&node);
delete(node);
} }
static static
int int
ctor(void * _this, va_list * params)
httpMessageCtor(void * _this, va_list * params)
{ {
HttpMessage this = _this; HttpMessage this = _this;
char * version = va_arg(* params, char *); char * version = va_arg(* params, char *);
@ -60,11 +60,11 @@ ctor(void * _this, va_list * params)
static static
void void
dtor(void * _this)
httpMessageDtor(void * _this)
{ {
HttpMessage this = _this; HttpMessage this = _this;
ffree((void **)&(this->version));
FREE(this->version);
/** /**
* this is a GNU extension...anyway on most non * this is a GNU extension...anyway on most non
@ -75,7 +75,7 @@ dtor(void * _this)
switch (this->type) { switch (this->type) {
case HTTP_MESSAGE_BUFFERED: case HTTP_MESSAGE_BUFFERED:
ffree((void **)&(this->body));
FREE(this->body);
break; break;
case HTTP_MESSAGE_PIPED: case HTTP_MESSAGE_PIPED:
@ -87,7 +87,7 @@ dtor(void * _this)
} }
} }
INIT_IFACE(Class, ctor, dtor, NULL);
INIT_IFACE(Class, httpMessageCtor, httpMessageDtor, NULL);
CREATE_CLASS(HttpMessage, NULL, IFACE(Class)); CREATE_CLASS(HttpMessage, NULL, IFACE(Class));
// vim: set ts=4 sw=4: // vim: set ts=4 sw=4:

8
src/http/message/queue.c

@ -29,24 +29,24 @@
static static
int int
ctor(void * _this, va_list * params)
messageQueueCtor(void * _this, va_list * params)
{ {
return 0; return 0;
} }
static static
void void
dtor(void * _this)
messageQueueDtor(void * _this)
{ {
HttpMessageQueue this = _this; HttpMessageQueue this = _this;
int i; int i;
for (i=0; i<this->nmsgs; i++) { for (i=0; i<this->nmsgs; i++) {
delete(&(this->msgs)[i]);
delete((this->msgs)[i]);
} }
} }
INIT_IFACE(Class, ctor, dtor, NULL);
INIT_IFACE(Class, messageQueueCtor, messageQueueDtor, NULL);
CREATE_CLASS(HttpMessageQueue, NULL, IFACE(Class)); CREATE_CLASS(HttpMessageQueue, NULL, IFACE(Class));
// vim: set ts=4 sw=4: // vim: set ts=4 sw=4:

14
src/http/request.c

@ -35,19 +35,23 @@
static static
int int
ctor(void * _this, va_list * params)
httpRequestCtor(void * _this, va_list * params)
{ {
/**
* the parent is not called by intention. All infomations
* are read from the request stream.
*/
return 0; return 0;
} }
static static
void void
dtor(void * _this)
httpRequestDtor(void * _this)
{ {
HttpRequest this = _this; HttpRequest this = _this;
ffree((void **)&(this->uri));
ffree((void **)&(this->method));
FREE(this->uri);
FREE(this->method);
PARENTCALL(_this, Class, dtor); PARENTCALL(_this, Class, dtor);
} }
@ -88,7 +92,7 @@ toString(void * _this, char * string)
return string; return string;
} }
INIT_IFACE(Class, ctor, dtor, NULL);
INIT_IFACE(Class, httpRequestCtor, httpRequestDtor, NULL);
INIT_IFACE(HttpIntro, sizeGet, toString); INIT_IFACE(HttpIntro, sizeGet, toString);
CREATE_CLASS(HttpRequest, CREATE_CLASS(HttpRequest,
HttpMessage, HttpMessage,

17
src/http/request/parser.c

@ -33,10 +33,12 @@
#include "http/request.h" #include "http/request.h"
#include "cbuf.h" #include "cbuf.h"
#include "utils/memory.h"
static static
int int
ctor(void * _this, va_list * params)
requestParserCtor(void * _this, va_list * params)
{ {
HttpRequestParser this = _this; HttpRequestParser this = _this;
@ -48,23 +50,20 @@ ctor(void * _this, va_list * params)
static static
void void
dtor(void * _this)
requestParserDtor(void * _this)
{ {
HttpRequestParser this = _this; HttpRequestParser this = _this;
delete(&(this->request_queue));
delete(this->request_queue);
if (TRUE == this->ourLock) if (TRUE == this->ourLock)
cbufRelease(this->buffer); cbufRelease(this->buffer);
if (NULL != this->incomplete)
free(this->incomplete);
if (NULL != this->cur_request)
delete(&(this->cur_request));
FREE(this->incomplete);
delete(this->cur_request);
} }
INIT_IFACE(Class, ctor, dtor, NULL);
INIT_IFACE(Class, requestParserCtor, requestParserDtor, NULL);
INIT_IFACE(StreamReader, (fptr_streamReaderRead)httpRequestParserParse); INIT_IFACE(StreamReader, (fptr_streamReaderRead)httpRequestParserParse);
CREATE_CLASS(HttpRequestParser, NULL, IFACE(Class), IFACE(StreamReader)); CREATE_CLASS(HttpRequestParser, NULL, IFACE(Class), IFACE(StreamReader));

8
src/http/response.c

@ -36,7 +36,7 @@
static static
int int
ctor(void * _this, va_list * params)
httpResponseCtor(void * _this, va_list * params)
{ {
HttpResponse this = _this; HttpResponse this = _this;
char * reason; char * reason;
@ -54,11 +54,11 @@ ctor(void * _this, va_list * params)
static static
void void
dtor(void * _this)
httpResponseDtor(void * _this)
{ {
HttpResponse this = _this; HttpResponse this = _this;
ffree((void **)&(this->reason));
FREE(this->reason);
PARENTCALL(_this, Class, dtor); PARENTCALL(_this, Class, dtor);
} }
@ -99,7 +99,7 @@ toString(void * _this, char * string)
return string; return string;
} }
INIT_IFACE(Class, ctor, dtor, NULL);
INIT_IFACE(Class, httpResponseCtor, httpResponseDtor, NULL);
INIT_IFACE(HttpIntro, sizeGet, toString); INIT_IFACE(HttpIntro, sizeGet, toString);
CREATE_CLASS( CREATE_CLASS(
HttpResponse, HttpResponse,

33
src/http/response/304.c

@ -20,11 +20,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdio.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "class.h" #include "class.h"
#include "interface/class.h" #include "interface/class.h"
@ -34,44 +29,24 @@
HttpResponse HttpResponse
httpResponse304(int handle, const char * content_type)
httpResponse304(const char * mime, const char * etag, const char * mtime)
{ {
time_t t;
struct tm * tmp;
char buffer[200];
struct stat st;
HttpResponse response; HttpResponse response;
HttpMessage message; HttpMessage message;
fstat(handle, &st);
response = new(HttpResponse, "HTTP/1.1", 304, "Not Modified"); response = new(HttpResponse, "HTTP/1.1", 304, "Not Modified");
message = (HttpMessage)response; message = (HttpMessage)response;
httpHeaderAdd(&(message->header),
new(HttpHeader, "Content-Type", content_type));
httpHeaderAdd(&(message->header),
new(HttpHeader, "Server", "testserver"));
message->type = HTTP_MESSAGE_BUFFERED; message->type = HTTP_MESSAGE_BUFFERED;
message->nbody = 0; message->nbody = 0;
message->body = NULL; message->body = NULL;
tmp = localtime(&(st.st_mtime));
strftime(buffer, sizeof(buffer), "%s", tmp);
httpHeaderAdd(&(message->header), httpHeaderAdd(&(message->header),
new(HttpHeader, "ETag", buffer));
tmp = localtime(&(st.st_mtime));
strftime(buffer, sizeof(buffer), "%a, %d %b %Y %T %Z", tmp);
new(HttpHeader, "Content-Type", mime));
httpHeaderAdd(&(message->header), httpHeaderAdd(&(message->header),
new(HttpHeader, "Last-Modified", buffer));
t = time(NULL);
tmp = localtime(&t);
strftime(buffer, sizeof(buffer), "%a, %d %b %Y %T %Z", tmp);
new(HttpHeader, "ETag", etag));
httpHeaderAdd(&(message->header), httpHeaderAdd(&(message->header),
new(HttpHeader, "Date", buffer));
new(HttpHeader, "Last-Modified", mtime));
return response; return response;
} }

2
src/http/response/404.c

@ -53,8 +53,6 @@ httpResponse404()
httpHeaderAdd(&(message->header), httpHeaderAdd(&(message->header),
new(HttpHeader, "Content-Type", "text/html")); new(HttpHeader, "Content-Type", "text/html"));
httpHeaderAdd(&(message->header),
new(HttpHeader, "Server", "testserver"));
message->type = HTTP_MESSAGE_BUFFERED; message->type = HTTP_MESSAGE_BUFFERED;
message->nbody = sizeof(RESP_DATA) - 1; message->nbody = sizeof(RESP_DATA) - 1;

42
src/http/response/jquery.c → src/http/response/asset.c

@ -21,9 +21,9 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <time.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <string.h>
#include "class.h" #include "class.h"
#include "interface/class.h" #include "interface/class.h"
@ -34,43 +34,45 @@
HttpResponse HttpResponse
httpResponseJquery(int handle)
httpResponseAsset(const char * fname, const char * mime, const char * match)
{ {
time_t t;
struct tm * tmp; struct tm * tmp;
char buffer[200];
char etag[200];
char mtime[200];
char clen[200];
struct stat st; struct stat st;
HttpResponse response; HttpResponse response;
HttpMessage message; HttpMessage message;
int handle;
handle = open(fname, O_RDONLY);
fstat(handle, &st); fstat(handle, &st);
tmp = localtime(&(st.st_mtime));
strftime(etag, sizeof(etag), "%s", tmp);
strftime(mtime, sizeof(mtime), "%a, %d %b %Y %T %Z", tmp);
if (0 == strcmp(etag, match)) {
return httpResponse304(mime, etag, mtime);
}
response = new(HttpResponse, "HTTP/1.1", 200, "OK"); response = new(HttpResponse, "HTTP/1.1", 200, "OK");
message = (HttpMessage)response; message = (HttpMessage)response;
httpHeaderAdd(&(message->header),
new(HttpHeader, "Content-Type", "text/javascript"));
httpHeaderAdd(&(message->header),
new(HttpHeader, "Server", "testserver"));
message->type = HTTP_MESSAGE_PIPED; message->type = HTTP_MESSAGE_PIPED;
message->handle = handle; message->handle = handle;
message->nbody = st.st_size; message->nbody = st.st_size;
sprintf(buffer, "%d", message->nbody);
httpHeaderAdd(&(message->header),
new(HttpHeader, "Content-Length", buffer));
sprintf(clen, "%d", message->nbody);
tmp = localtime(&(st.st_mtime));
strftime(buffer, sizeof(buffer), "%s", tmp);
httpHeaderAdd(&(message->header), httpHeaderAdd(&(message->header),
new(HttpHeader, "ETag", buffer));
t = time(NULL);
tmp = localtime(&t);
strftime(buffer, sizeof(buffer), "%a, %d %b %Y %T %Z", tmp);
new(HttpHeader, "Content-Type", mime));
httpHeaderAdd(&(message->header),
new(HttpHeader, "Content-Length", clen));
httpHeaderAdd(&(message->header),
new(HttpHeader, "ETag", etag));
httpHeaderAdd(&(message->header), httpHeaderAdd(&(message->header),
new(HttpHeader, "Date", buffer));
new(HttpHeader, "Last-Modified", mtime));
return response; return response;
} }

75
src/http/response/image.c

@ -1,75 +0,0 @@
/**
* \file
*
* \author Georg Hopp
*
* \copyright
* Copyright (C) 2012 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "class.h"
#include "interface/class.h"
#include "http/response.h"
#include "http/message.h"
#include "http/header.h"
HttpResponse
httpResponseImage(int handle)
{
char buffer[200];
struct stat st;
HttpResponse response;
HttpMessage message;
fstat(handle, &st);
response = new(HttpResponse, "HTTP/1.1", 200, "OK");
message = (HttpMessage)response;
httpHeaderAdd(&(message->header),
new(HttpHeader, "Content-Type", "image/jpeg"));
httpHeaderAdd(&(message->header),
new(HttpHeader, "Server", "testserver"));
message->type = HTTP_MESSAGE_PIPED;
message->handle = handle;
message->nbody = st.st_size;
sprintf(buffer, "%d", message->nbody);
httpHeaderAdd(&(message->header),
new(HttpHeader, "Content-Length", buffer));
tmp = localtime(&(st.st_mtime));
strftime(buffer, sizeof(buffer), "%s", tmp);
httpHeaderAdd(&(message->header),
new(HttpHeader, "ETag", buffer));
t = time(NULL);
tmp = localtime(&t);
strftime(buffer, sizeof(buffer), "%a, %d %b %Y %T %Z", tmp);
httpHeaderAdd(&(message->header),
new(HttpHeader, "Date", buffer));
return response;
}
// vim: set ts=4 sw=4:

2
src/http/response/me.c

@ -68,8 +68,6 @@ httpResponseMe(int value)
httpHeaderAdd(&(message->header), httpHeaderAdd(&(message->header),
new(HttpHeader, "Content-Type", "text/html")); new(HttpHeader, "Content-Type", "text/html"));
httpHeaderAdd(&(message->header),
new(HttpHeader, "Server", "testserver"));
httpHeaderAdd(&(message->header), httpHeaderAdd(&(message->header),
new(HttpHeader, "Set-Cookie", "name=\"Georg Hopp\"")); new(HttpHeader, "Set-Cookie", "name=\"Georg Hopp\""));
httpHeaderAdd(&(message->header), httpHeaderAdd(&(message->header),

10
src/http/response/writer.c

@ -31,7 +31,7 @@
static static
int int
ctor(void * _this, va_list * params)
responseWriterCtor(void * _this, va_list * params)
{ {
HttpResponseWriter this = _this; HttpResponseWriter this = _this;
@ -43,20 +43,20 @@ ctor(void * _this, va_list * params)
static static
void void
dtor(void * _this)
responseWriterDtor(void * _this)
{ {
HttpResponseWriter this = _this; HttpResponseWriter this = _this;
delete(&(this->response_queue));
delete(this->response_queue);
if (TRUE == this->ourLock) if (TRUE == this->ourLock)
cbufRelease(this->buffer); cbufRelease(this->buffer);
if (NULL != this->cur_response) if (NULL != this->cur_response)
delete(&(this->cur_response));
delete(this->cur_response);
} }
INIT_IFACE(Class, ctor, dtor, NULL);
INIT_IFACE(Class, responseWriterCtor, responseWriterDtor, NULL);
INIT_IFACE(StreamWriter, (fptr_streamWriterWrite)httpResponseWriterWrite); INIT_IFACE(StreamWriter, (fptr_streamWriterWrite)httpResponseWriterWrite);
CREATE_CLASS(HttpResponseWriter, NULL, IFACE(Class), IFACE(StreamWriter)); CREATE_CLASS(HttpResponseWriter, NULL, IFACE(Class), IFACE(StreamWriter));

4
src/http/response/writer/write.c

@ -143,13 +143,13 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd)
*/ */
cbufRelease(this->buffer); cbufRelease(this->buffer);
this->ourLock = FALSE; this->ourLock = FALSE;
delete(&this->cur_response);
delete(this->cur_response);
return -1; return -1;
} }
cbufRelease(this->buffer); cbufRelease(this->buffer);
this->ourLock = FALSE; this->ourLock = FALSE;
delete(&this->cur_response);
delete(this->cur_response);
break; break;
} }

19
src/http/worker.c

@ -13,10 +13,11 @@
#include "interface/stream_reader.h" #include "interface/stream_reader.h"
#include "interface/stream_writer.h" #include "interface/stream_writer.h"
#define SHMN "/worker_"
#include "utils/memory.h"
static static
int int
ctor(void * _this, va_list * params)
httpWorkerCtor(void * _this, va_list * params)
{ {
HttpWorker this = _this; HttpWorker this = _this;
char * id = va_arg(*params, char *); char * id = va_arg(*params, char *);
@ -41,17 +42,17 @@ ctor(void * _this, va_list * params)
static static
void void
dtor(void * _this)
httpWorkerDtor(void * _this)
{ {
HttpWorker this = _this; HttpWorker this = _this;
if (NULL != this->id) free(this->id);
FREE(this->id);
delete(&(this->parser));
delete(&(this->writer));
delete(this->parser);
delete(this->writer);
if (NULL != this->pbuf) delete(&(this->pbuf));
if (NULL != this->wbuf) delete(&(this->wbuf));
if (NULL != this->pbuf) delete(this->pbuf);
if (NULL != this->wbuf) delete(this->wbuf);
} }
static static
@ -70,7 +71,7 @@ _clone(void * _this, void * _base)
this->writer = new(HttpResponseWriter, base->wbuf); this->writer = new(HttpResponseWriter, base->wbuf);
} }
INIT_IFACE(Class, ctor, dtor, _clone);
INIT_IFACE(Class, httpWorkerCtor, httpWorkerDtor, _clone);
INIT_IFACE(StreamReader, (fptr_streamReaderRead)httpWorkerProcess); INIT_IFACE(StreamReader, (fptr_streamReaderRead)httpWorkerProcess);
INIT_IFACE(StreamWriter, (fptr_streamWriterWrite)httpWorkerWrite); INIT_IFACE(StreamWriter, (fptr_streamWriterWrite)httpWorkerWrite);
CREATE_CLASS( CREATE_CLASS(

37
src/http/worker/add_common_header.c

@ -0,0 +1,37 @@
#include <time.h>
#include "class.h"
#include "interface/class.h"
#include "http/message.h"
#include "http/response.h"
void
httpWorkerAddCommonHeader(HttpMessage request, HttpMessage response)
{
time_t t;
struct tm * tmp;
char buffer[200];
if (httpMessageHasKeepAlive(request)) {
httpHeaderAdd(
&(response->header),
new(HttpHeader, "Connection", "Keep-Alive"));
}
else {
httpHeaderAdd(
&(response->header),
new(HttpHeader, "Connection", "Close"));
}
httpHeaderAdd(&(response->header),
new(HttpHeader, "Server", "testserver"));
t = time(NULL);
tmp = localtime(&t);
strftime(buffer, sizeof(buffer), "%a, %d %b %Y %T %Z", tmp);
httpHeaderAdd(&(response->header),
new(HttpHeader, "Date", buffer));
}
// vim: set ts=4 sw=4:

29
src/http/worker/get_asset.c

@ -0,0 +1,29 @@
#include "http/header.h"
#include "http/message.h"
#include "http/request.h"
#include "http/response.h"
HttpMessage
httpWorkerGetAsset(
HttpRequest request,
const char * fname,
const char * mime)
{
char * match;
HttpHeader header;
header = httpHeaderGet(
&(((HttpMessage)request)->header),
"If-None-Match");
if (NULL == header) {
match = "";
}
else {
match = (header->value)[0];
}
return (HttpMessage)httpResponseAsset(fname, mime, match);
}
// vim: set ts=4 sw=4:

76
src/http/worker/process.c

@ -21,18 +21,22 @@
*/ */
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "class.h" #include "class.h"
#include "interface/class.h" #include "interface/class.h"
#include "http/worker.h" #include "http/worker.h"
#include "http/message.h"
#include "http/request.h"
#include "http/message/queue.h"
#include "http/request/parser.h" #include "http/request/parser.h"
#include "http/header.h" #include "http/header.h"
#include "http/request.h" #include "http/request.h"
#include "http/message.h" #include "http/message.h"
HttpMessage httpWorkerGetAsset(HttpRequest, const char *, const char *);
void httpWorkerAddCommonHeader(HttpMessage, HttpMessage);
ssize_t ssize_t
httpWorkerProcess(HttpWorker this, int fd) httpWorkerProcess(HttpWorker this, int fd)
{ {
@ -47,57 +51,35 @@ httpWorkerProcess(HttpWorker this, int fd)
HttpMessageQueue respq = this->writer->response_queue; HttpMessageQueue respq = this->writer->response_queue;
for (i=0; i<reqq->nmsgs; i++) { for (i=0; i<reqq->nmsgs; i++) {
/**
* \todo for now simply remove request and send not found.
* Make this sane.
*/
HttpRequest request = (HttpRequest)(reqq->msgs[i]);
HttpMessage response = NULL;
if (0 == strcmp("GET", request->method) &&
0 == strcmp("/me/", request->uri)) {
response = (HttpMessage)httpResponseMe(*(this->val));
}
else if (0 == strcmp("GET", request->method) &&
0 == strcmp("/image/", request->uri)) {
int handle = open("./assets/waldschrat.jpg", O_RDONLY);
if (NULL != httpHeaderGet(
&(((HttpMessage)request)->header),
"If-None-Match")) {
response = (HttpMessage)httpResponse304(handle, "image/jpeg");
}
else {
response = (HttpMessage)httpResponseImage(handle);
HttpRequest request = (HttpRequest)(reqq->msgs[i]);
HttpMessage response = NULL;
if (0 == strcmp("GET", request->method)) {
if (0 == strcmp("/me/", request->uri)) {
response = (HttpMessage)httpResponseMe(*(this->val));
} }
}
else if (0 == strcmp("GET", request->method) &&
0 == strcmp("/jquery/", request->uri)) {
int handle = open("./assets/jquery-1.7.1.min.js", O_RDONLY);
if (NULL != httpHeaderGet(
&(((HttpMessage)request)->header),
"If-None-Match")) {
response = (HttpMessage)httpResponse304(handle, "text/javascript");
if (0 == strcmp("/image/", request->uri)) {
response = httpWorkerGetAsset(
request,
"./assets/waldschrat.jpg",
"image/jpeg");
} }
else {
response = (HttpMessage)httpResponseJquery(handle);
if (0 == strcmp("/jquery/", request->uri)) {
response = httpWorkerGetAsset(
request,
"./assets/jquery-1.7.1.min.js",
"text/javascript");
} }
} }
else {
if (NULL == response) {
response = (HttpMessage)httpResponse404(); response = (HttpMessage)httpResponse404();
} }
if (httpMessageHasKeepAlive(reqq->msgs[i])) {
httpHeaderAdd(
&(response->header),
new(HttpHeader, "Connection", "Keep-Alive"));
}
else {
httpHeaderAdd(
&(response->header),
new(HttpHeader, "Connection", "Close"));
}
httpWorkerAddCommonHeader((HttpMessage)request, response);
t = time(NULL); t = time(NULL);
tmp = localtime(&t); tmp = localtime(&t);
@ -107,7 +89,7 @@ httpWorkerProcess(HttpWorker this, int fd)
respq->msgs[(respq->nmsgs)++] = response; respq->msgs[(respq->nmsgs)++] = response;
response = NULL; response = NULL;
delete(&(reqq->msgs[i]));
delete((reqq->msgs)[i]);
} }
reqq->nmsgs = 0; reqq->nmsgs = 0;

6
src/logger.c

@ -41,7 +41,7 @@ logger_level_str[] = {
static static
int int
ctor(void * _this, va_list * params)
loggerCtor(void * _this, va_list * params)
{ {
Logger this = _this; Logger this = _this;
this->min_level = va_arg(*params, int); this->min_level = va_arg(*params, int);
@ -49,9 +49,9 @@ ctor(void * _this, va_list * params)
return 0; return 0;
} }
static void dtor(void * _this) {}
static void loggerDtor(void * _this) {}
INIT_IFACE(Class, ctor, dtor, NULL);
INIT_IFACE(Class, loggerCtor, loggerDtor, NULL);
CREATE_CLASS(Logger, NULL, IFACE(Class)); CREATE_CLASS(Logger, NULL, IFACE(Class));
// vim: set ts=4 sw=4: // vim: set ts=4 sw=4:

16
src/server.c

@ -34,7 +34,7 @@
static static
int int
ctor(void * _this, va_list * params)
serverCtor(void * _this, va_list * params)
{ {
Server this = _this; Server this = _this;
in_port_t port; in_port_t port;
@ -73,25 +73,25 @@ ctor(void * _this, va_list * params)
static static
void void
dtor(void * _this)
serverDtor(void * _this)
{ {
Server this = _this; Server this = _this;
int i; int i;
for (i=0; i<this->nfds; i++) { for (i=0; i<this->nfds; i++) {
if (this->sock->handle != (this->fds)[i].fd) { if (this->sock->handle != (this->fds)[i].fd) {
delete(&(this->conns[(this->fds)[i].fd]).sock);
delete(&(this->conns[(this->fds)[i].fd]).worker);
delete((this->conns[(this->fds)[i].fd]).sock);
delete((this->conns[(this->fds)[i].fd]).worker);
} }
} }
FREE(&(this->fds));
FREE(&(this->conns));
FREE(this->fds);
FREE(this->conns);
delete(&this->sock);
delete(this->sock);
} }
INIT_IFACE(Class, ctor, dtor, NULL);
INIT_IFACE(Class, serverCtor, serverDtor, NULL);
CREATE_CLASS(Server, NULL, IFACE(Class)); CREATE_CLASS(Server, NULL, IFACE(Class));
// vim: set ts=4 sw=4: // vim: set ts=4 sw=4:

4
src/server/close_conn.c

@ -31,8 +31,8 @@ serverCloseConn(Server this, unsigned int i)
{ {
int fd = (this->fds)[i].fd; int fd = (this->fds)[i].fd;
delete(&((this->conns)[fd].sock));
delete(&((this->conns)[fd].worker));
delete((this->conns)[fd].sock);
delete((this->conns)[fd].worker);
memset(&(this->fds[i]), 0, sizeof(struct pollfd)); memset(&(this->fds[i]), 0, sizeof(struct pollfd));
} }

2
src/server/handle_accept.c

@ -52,7 +52,7 @@ serverHandleAccept(Server this)
(this->fds)[this->nfds].events = POLLIN; (this->fds)[this->nfds].events = POLLIN;
this->nfds++; this->nfds++;
} else { } else {
delete(&acc);
delete(acc);
switch(errno) { switch(errno) {
case EAGAIN: case EAGAIN:

8
src/socket.c

@ -31,7 +31,7 @@
static static
int int
ctor(void * _this, va_list * params)
socketCtor(void * _this, va_list * params)
{ {
Sock this = _this; Sock this = _this;
int reUse = 1; //! \todo make this configurable int reUse = 1; //! \todo make this configurable
@ -44,7 +44,7 @@ ctor(void * _this, va_list * params)
loggerLog(this->log, LOGGER_CRIT, loggerLog(this->log, LOGGER_CRIT,
"error opening socket: %s - service terminated", "error opening socket: %s - service terminated",
strerror(errno)); strerror(errno));
return;
return -1;
} }
//! Make the socket REUSE a TIME_WAIT socket //! Make the socket REUSE a TIME_WAIT socket
@ -55,7 +55,7 @@ ctor(void * _this, va_list * params)
static static
void void
dtor(void * _this)
socketDtor(void * _this)
{ {
Sock this = _this; Sock this = _this;
@ -65,7 +65,7 @@ dtor(void * _this)
} }
} }
INIT_IFACE(Class, ctor, dtor, NULL);
INIT_IFACE(Class, socketCtor, socketDtor, NULL);
CREATE_CLASS(Sock, NULL, IFACE(Class)); CREATE_CLASS(Sock, NULL, IFACE(Class));
// vim: set ts=4 sw=4: // vim: set ts=4 sw=4:

6
src/testserver.c

@ -165,9 +165,9 @@ main()
} }
} while (!WIFEXITED(status) && !WIFSIGNALED(status)); } while (!WIFEXITED(status) && !WIFSIGNALED(status));
if (NULL != server) delete(&server);
if (NULL != worker) delete(&worker);
if (NULL != logger) delete(&logger);
if (NULL != server) delete(server);
if (NULL != worker) delete(worker);
if (NULL != logger) delete(logger);
} }
break; break;

Loading…
Cancel
Save