Browse Source

closes #10: values for header ids are now stored in a char ** making multiple values for one id possible. Additionally added a jquery action that delivers the jquery java script and use it on the me action

master
Georg Hopp 14 years ago
parent
commit
59ccbf0207
  1. 8
      ChangeLog
  2. 11
      include/http/header.h
  3. 1
      include/http/response.h
  4. 1
      src/Makefile.am
  5. 15
      src/http/header.c
  6. 8
      src/http/header/add.c
  7. 4
      src/http/header/get.c
  8. 7
      src/http/header/size_get.c
  9. 17
      src/http/header/to_string.c
  10. 11
      src/http/message/has_keep_alive.c
  11. 2
      src/http/message/header_size_get.c
  12. 2
      src/http/message/header_to_string.c
  13. 6
      src/http/request/parser/get_body.c
  14. 78
      src/http/response/jquery.c
  15. 25
      src/http/response/me.c
  16. 13
      src/http/worker/process.c
  17. 14
      src/testserver.c

8
ChangeLog

@ -1,10 +1,14 @@
2012-02-22 08:48:43 +0100 Georg Hopp
* closes #10: values for header ids are now stored in a char ** making multiple values for one id possible. Additionally added a jquery action that delivers the jquery java script and use it on the me action (HEAD, master)
2012-02-21 13:01:38 +0100 Georg Hopp
* now when a constructor returns -1 the new call will in turn call the destructor effectively freeing all resources. ATTENTION: now the destructor has to be aware that it might be called with a not completely initialized object. To make this more ease there is the FREE makro with the corresponding ffree that does NULL pointer checking and the destructor checks for NULL pointer too. Additionally the handle_accept now handles _SC_OPEN_MAX - 10 connections. The 10 are reserved for internal usage. (HEAD, master)
* now when a constructor returns -1 the new call will in turn call the destructor effectively freeing all resources. ATTENTION: now the destructor has to be aware that it might be called with a not completely initialized object. To make this more ease there is the FREE makro with the corresponding ffree that does NULL pointer checking and the destructor checks for NULL pointer too. Additionally the handle_accept now handles _SC_OPEN_MAX - 10 connections. The 10 are reserved for internal usage. (origin/master, origin/HEAD)
2012-02-21 09:45:01 +0100 Georg Hopp
* now a child is spawned and writes random values in a shared memory segment. These values will be shown in the me action (origin/master, origin/HEAD)
* now a child is spawned and writes random values in a shared memory segment. These values will be shown in the me action
2012-02-20 21:36:55 +0100 Georg Hopp

11
include/http/header.h

@ -30,15 +30,16 @@
CLASS(HttpHeader) {
unsigned long hash;
char * name;
char * value;
char ** value;
size_t nvalue;
};
HttpHeader httpHeaderParse(char * line); // @INFO: destructive
void httpHeaderAdd(const HttpHeader *, HttpHeader);
char * httpHeaderGet(const HttpHeader *, const char *);
size_t httpHeaderSizeGet(HttpHeader);
size_t httpHeaderToString(HttpHeader, char *);
void httpHeaderAdd(const HttpHeader *, HttpHeader);
HttpHeader httpHeaderGet(const HttpHeader *, const char *);
size_t httpHeaderSizeGet(HttpHeader);
size_t httpHeaderToString(HttpHeader, char *);
#endif // __HTTP_HEADER_H__

1
include/http/response.h

@ -42,6 +42,7 @@ HttpResponse httpResponse304(int, const char *);
HttpResponse httpResponse404();
HttpResponse httpResponseMe(int);
HttpResponse httpResponseImage(int);
HttpResponse httpResponseJquery(int);
#endif // __HTTP_RESPONSE_H__

1
src/Makefile.am

@ -24,6 +24,7 @@ RESP = http/response.c \
http/response/304.c \
http/response/404.c \
http/response/image.c \
http/response/jquery.c \
http/response/me.c
WORKER = http/worker.c http/worker/process.c http/worker/write.c
WRITER = http/response/writer.c http/response/writer/write.c

15
src/http/header.c

@ -29,6 +29,7 @@
#include "http/header.h"
#include "utils/hash.h"
#include "utils/memory.h"
static
int
@ -45,8 +46,9 @@ ctor(void * _this, va_list * params) {
this->hash = sdbm((unsigned char *)name);
this->value = malloc(strlen(value) + 1);
strcpy(this->value, value);
this->value = malloc(sizeof(char*) * (++this->nvalue));
this->value[this->nvalue - 1] = malloc(strlen(value) + 1);
strcpy(this->value[this->nvalue - 1], value);
return 0;
}
@ -56,9 +58,14 @@ void
dtor(void * _this)
{
HttpHeader this = _this;
size_t i;
free(this->name);
free(this->value);
FREE(&(this->name));
for (i=0; i<this->nvalue; i++) {
FREE(&(this->value[i]));
}
FREE(&(this->value));
}
INIT_IFACE(Class, ctor, dtor, NULL);

8
src/http/header/add.c

@ -22,6 +22,8 @@
#include <search.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "class.h"
#include "interface/class.h"
@ -44,9 +46,9 @@ httpHeaderAdd(const HttpHeader * root, HttpHeader header)
HttpHeader * found = tsearch(header, (void **)root, comp);
if (*found != header) {
puts("uhh, duplicate header set. "
"This is not implemented right now. "
"Keep the first one found.");
(*found)->value = realloc((*found)->value, sizeof(char) * (++(*found)->nvalue));
(*found)->value[(*found)->nvalue - 1] = malloc(strlen(header->value) + 1);
strcpy(((*found)->value)[(*found)->nvalue - 1], (header->value)[0]);
delete(&header);
}
}

4
src/http/header/get.c

@ -38,13 +38,13 @@ comp(const void * _a, const void * _b)
return (a->hash < b->hash)? -1 : (a->hash > b->hash)? 1 : 0;
}
char *
HttpHeader
httpHeaderGet(const HttpHeader * root, const char * name)
{
struct c_HttpHeader search = {sdbm((const unsigned char*)name), NULL, NULL};
HttpHeader * found = tfind(&search, (void**)root, comp);
return (NULL != found)? (*found)->value : NULL;
return (NULL != found)? *found : NULL;
}
// vim: set ts=4 sw=4:

7
src/http/header/size_get.c

@ -29,9 +29,12 @@ size_t
httpHeaderSizeGet(HttpHeader header)
{
size_t size = 0;
int i;
size += strlen(header->name) + 2;
size += strlen(header->value);
for (i=0; i<header->nvalue; i++) {
size += strlen(header->name) + 2;
size += strlen(header->value[i]) + 2;
}
return size;
}

17
src/http/header/to_string.c

@ -29,14 +29,21 @@ size_t
httpHeaderToString(HttpHeader header, char * string)
{
size_t size = httpHeaderSizeGet(header);
int i;
strcpy(string, header->name);
string += strlen(string);
for (i=0; i<header->nvalue; i++) {
strcpy(string, header->name);
string += strlen(string);
*string++ = ':';
*string++ = ' ';
*string++ = ':';
*string++ = ' ';
strcpy(string, header->value);
strcpy(string, header->value[i]);
string += strlen(string);
*string++ = '\r';
*string++ = '\n';
}
return size;
}

11
src/http/message/has_keep_alive.c

@ -31,8 +31,8 @@
char
httpMessageHasKeepAlive(HttpMessage message)
{
char * header;
char * header_ptr;
HttpHeader header;
char * con;
header = httpHeaderGet(&(message->header), "connection");
@ -40,11 +40,12 @@ httpMessageHasKeepAlive(HttpMessage message)
return 0;
}
for (header_ptr = header; 0 != *header_ptr; header_ptr++) {
*header_ptr = tolower(*header_ptr);
con = (header->value)[0];
for (; 0 != *con; con++) {
*con = tolower(*con);
}
if (0 == strcmp(header, "keep-alive")) {
if (0 == strcmp(con, "keep-alive")) {
return 1;
}

2
src/http/message/header_size_get.c

@ -37,7 +37,7 @@ void
addHeaderSize(const void * node, const VISIT which, const int depth)
{
if (endorder == which || leaf == which) {
size += httpHeaderSizeGet(*(HttpHeader *)node) + 2;
size += httpHeaderSizeGet(*(HttpHeader *)node);
}
}

2
src/http/message/header_to_string.c

@ -35,8 +35,6 @@ addHeaderString(const void * node, const VISIT which, const int depth)
{
if (endorder == which || leaf == which) {
string += httpHeaderToString(*(HttpHeader *)node, string);
*string++ = '\r';
*string++ = '\n';
}
}

6
src/http/request/parser/get_body.c

@ -43,17 +43,17 @@ httpRequestParserGetBody(HttpRequestParser this)
size_t len;
if (0 == message->nbody) {
char * nbody = httpHeaderGet(
HttpHeader clen = httpHeaderGet(
&(message->header),
"Content-Length");
if (NULL == nbody) {
if (NULL == clen) {
this->state = HTTP_REQUEST_DONE;
return;
}
else {
message->type = HTTP_MESSAGE_BUFFERED;
message->nbody = atoi(nbody);
message->nbody = atoi((clen->value)[0]);
message->body = calloc(1, message->nbody);
message->dbody = 0;
}

78
src/http/response/jquery.c

@ -0,0 +1,78 @@
/**
* \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 <time.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
httpResponseJquery(int handle)
{
time_t t;
struct tm * tmp;
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", "text/javascript"));
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:

25
src/http/response/me.c

@ -35,9 +35,24 @@
#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>200 - OK</title></head>" \
"<body><h1>200 - OK</h1><img src=\"/image/\" /><hr />%02d</body>" \
"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">" \
"<head>" \
"<title>200 - OK</title>" \
"<script type=\"text/javascript\" src=\"/jquery/\"></script>" \
"<script>" \
"$(document).ready(function() {" \
"$(\"a\").click(function() {" \
"alert(\"Hello world!\");" \
"});" \
"});" \
"</script>" \
"</head>" \
"<body>" \
"<h1>Testpage</h1>" \
"<img src=\"/image/\" />" \
"<hr />%02d" \
"<hr /><a href=\"#\">Link</a>" \
"</body>" \
"</html>"
@ -55,6 +70,10 @@ httpResponseMe(int value)
new(HttpHeader, "Content-Type", "text/html"));
httpHeaderAdd(&(message->header),
new(HttpHeader, "Server", "testserver"));
httpHeaderAdd(&(message->header),
new(HttpHeader, "Set-Cookie", "name=\"Georg Hopp\""));
httpHeaderAdd(&(message->header),
new(HttpHeader, "Set-Cookie", "profession=\"coder\""));
message->type = HTTP_MESSAGE_BUFFERED;
message->nbody = sizeof(RESP_DATA) - 1;

13
src/http/worker/process.c

@ -71,6 +71,19 @@ httpWorkerProcess(HttpWorker this, int fd)
response = (HttpMessage)httpResponseImage(handle);
}
}
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");
}
else {
response = (HttpMessage)httpResponseJquery(handle);
}
}
else {
response = (HttpMessage)httpResponse404();
}

14
src/testserver.c

@ -42,10 +42,10 @@
#include "utils/signalHandling.h"
//#define DEFAULT_SECS 0
//#define DEFAULT_USECS (1000000 / HZ)
#define DEFAULT_SECS 1
#define DEFAULT_USECS 0
#define DEFAULT_USECS (1000000 / HZ * 2)
//#define DEFAULT_SECS 1
//#define DEFAULT_USECS 0
void nullhandler() {}
@ -103,16 +103,16 @@ main()
exit (1);
}
interval.it_value.tv_sec = DEFAULT_SECS;
interval.it_value.tv_usec = DEFAULT_USECS;
interval.it_interval.tv_sec = DEFAULT_SECS;
interval.it_value.tv_sec = DEFAULT_SECS;
interval.it_value.tv_usec = DEFAULT_USECS;
interval.it_interval.tv_sec = DEFAULT_SECS;
interval.it_interval.tv_usec = DEFAULT_USECS;
setitimer(ITIMER_REAL, &interval, NULL);
// child
while(!doShutdown) {
*value = rand() % 10;
*value = rand() % 100;
sigsuspend(&pause_mask);
}

Loading…
Cancel
Save