diff --git a/.dep.inc b/.dep.inc
new file mode 100644
index 0000000..4560e55
--- /dev/null
+++ b/.dep.inc
@@ -0,0 +1,5 @@
+# This code depends on make tool being used
+DEPFILES=$(wildcard $(addsuffix .d, ${OBJECTFILES}))
+ifneq (${DEPFILES},)
+include ${DEPFILES}
+endif
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2247d5f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/build
+/dist
diff --git a/dist/Debug/GNU-Linux-x86/khttp b/dist/Debug/GNU-Linux-x86/khttp
new file mode 100755
index 0000000..923439d
Binary files /dev/null and b/dist/Debug/GNU-Linux-x86/khttp differ
diff --git a/nbproject/Makefile-Debug.mk b/nbproject/Makefile-Debug.mk
index aecd631..69013e7 100644
--- a/nbproject/Makefile-Debug.mk
+++ b/nbproject/Makefile-Debug.mk
@@ -35,6 +35,8 @@ OBJECTDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}
# Object Files
OBJECTFILES= \
+ ${OBJECTDIR}/src/http/http.o \
+ ${OBJECTDIR}/src/http/request.o \
${OBJECTDIR}/src/main.o \
${OBJECTDIR}/src/socket.o
@@ -63,6 +65,16 @@ ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/khttp: ${OBJECTFILES}
${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}
${LINK.c} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/khttp ${OBJECTFILES} ${LDLIBSOPTIONS}
+${OBJECTDIR}/src/http/http.o: src/http/http.c
+ ${MKDIR} -p ${OBJECTDIR}/src/http
+ ${RM} "$@.d"
+ $(COMPILE.c) -g -Wall -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http/http.o src/http/http.c
+
+${OBJECTDIR}/src/http/request.o: src/http/request.c
+ ${MKDIR} -p ${OBJECTDIR}/src/http
+ ${RM} "$@.d"
+ $(COMPILE.c) -g -Wall -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http/request.o src/http/request.c
+
${OBJECTDIR}/src/main.o: src/main.c
${MKDIR} -p ${OBJECTDIR}/src
${RM} "$@.d"
diff --git a/nbproject/Makefile-Release.mk b/nbproject/Makefile-Release.mk
index 676d3bd..b96724e 100644
--- a/nbproject/Makefile-Release.mk
+++ b/nbproject/Makefile-Release.mk
@@ -35,6 +35,8 @@ OBJECTDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}
# Object Files
OBJECTFILES= \
+ ${OBJECTDIR}/src/http/http.o \
+ ${OBJECTDIR}/src/http/request.o \
${OBJECTDIR}/src/main.o \
${OBJECTDIR}/src/socket.o
@@ -63,6 +65,16 @@ ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/khttp: ${OBJECTFILES}
${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}
${LINK.c} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/khttp ${OBJECTFILES} ${LDLIBSOPTIONS}
+${OBJECTDIR}/src/http/http.o: src/http/http.c
+ ${MKDIR} -p ${OBJECTDIR}/src/http
+ ${RM} "$@.d"
+ $(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http/http.o src/http/http.c
+
+${OBJECTDIR}/src/http/request.o: src/http/request.c
+ ${MKDIR} -p ${OBJECTDIR}/src/http
+ ${RM} "$@.d"
+ $(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http/request.o src/http/request.c
+
${OBJECTDIR}/src/main.o: src/main.c
${MKDIR} -p ${OBJECTDIR}/src
${RM} "$@.d"
diff --git a/nbproject/configurations.xml b/nbproject/configurations.xml
index f147ed1..b277912 100644
--- a/nbproject/configurations.xml
+++ b/nbproject/configurations.xml
@@ -4,7 +4,9 @@
+ src/http/http.h
src/main.h
+ src/http/request.h
src/socket.h
+ src/http/http.c
src/main.c
+ src/http/request.c
src/socket.c
2
+ -
+
+ -
+
+ -
+
+ -
+
-
-
@@ -75,6 +87,14 @@
5
+
-
+
+ -
+
+ -
+
+ -
+
-
-
diff --git a/nbproject/private/configurations.xml b/nbproject/private/configurations.xml
index daa4a74..a0dea49 100644
--- a/nbproject/private/configurations.xml
+++ b/nbproject/private/configurations.xml
@@ -13,8 +13,6 @@
-
-
diff --git a/nbproject/private/private.xml b/nbproject/private/private.xml
index c6aa339..873fa0e 100644
--- a/nbproject/private/private.xml
+++ b/nbproject/private/private.xml
@@ -8,10 +8,13 @@
file:/home/sam/NetBeansProjects/KHttp/src/socket.c
+ file:/home/sam/NetBeansProjects/KHttp/src/http/http.h
file:/home/sam/NetBeansProjects/KHttp/src/main.h
+ file:/home/sam/NetBeansProjects/KHttp/src/http/request.h
file:/home/sam/NetBeansProjects/KHttp/src/main.c
- file:/home/sam/NetBeansProjects/KHttp/src/ut/utlist.h
file:/home/sam/NetBeansProjects/KHttp/src/socket.h
+ file:/home/sam/NetBeansProjects/KHttp/src/http/request.c
+ file:/home/sam/NetBeansProjects/KHttp/src/http/http.c
diff --git a/src/http/http.c b/src/http/http.c
new file mode 100644
index 0000000..203f949
--- /dev/null
+++ b/src/http/http.c
@@ -0,0 +1,170 @@
+#include
+#include
+#include
+#include
+#include "http.h"
+
+/*
+ * METHOD_GET, METHOD_POST, METHOD_HEAD, METHOD_PUT,
+ METHOD_DELETE, METHOD_OPTIONS, METHOD_TRACE,
+ METHOD_CONNECT, METHOD_OTHER
+ */
+
+char* http_method_getstring(http_method method, char* method_other) {
+ switch(method) {
+ case METHOD_GET: return "GET";
+ case METHOD_POST: return "POST";
+ case METHOD_HEAD: return "HEAD";
+ case METHOD_PUT: return "PUT";
+ case METHOD_DELETE: return "DELETE";
+ case METHOD_OPTIONS:return "OPTIONS";
+ case METHOD_TRACE: return "TRACE";
+ case METHOD_CONNECT:return "CONNECT";
+ case METHOD_INVALID:return "";
+ case METHOD_OTHER: return method_other;
+ default: return "";
+ }
+}
+
+http_method http_method_fromstring(const char* method) {
+ http_method methods[] = {METHOD_GET, METHOD_POST, METHOD_HEAD, METHOD_PUT,
+ METHOD_DELETE, METHOD_OPTIONS, METHOD_TRACE,
+ METHOD_CONNECT};
+
+ size_t count = sizeof(methods) / sizeof(http_method);
+ for(int i; i < count; i++) {
+ if (strcmp(http_method_getstring(methods[i],NULL), method) == 0) {
+ return methods[i];
+ }
+ }
+ return METHOD_INVALID;
+}
+
+http_request_line *http_request_line_new(http_method method, const char* other) {
+ http_request_line *req = calloc(1, sizeof(http_request_line));
+ req->method = method;
+ if (req->method == METHOD_OTHER) {
+ req->method_other = calloc(strlen(other)+1, sizeof(char));
+ strcpy(req->method_other, other);
+ } else {
+ req->method_other = NULL;
+ }
+ return req;
+}
+void http_request_line_delete(http_request_line *req) {
+ free(req->method_other);
+ free(req->uri);
+ free(req);
+}
+
+http_response_line *http_response_line_new(uint16_t code) {
+ http_response_line *resp = calloc(1, sizeof(http_response_line));
+ resp->code = code;
+ resp->version = HTTP11;
+ return resp;
+}
+char* http_response_line_get_message(http_response_line *resp) {
+ if (resp->custom_message != NULL) {
+ return resp->custom_message;
+ }
+ switch(resp->code) {
+ case 100: return "Continue";
+ case 101: return "Switching Protocols";
+ case 200: return "OK";
+ case 201: return "Created";
+ case 202: return "Accepted";
+ case 203: return "Non-Authoritative Information";
+ case 204: return "No Content";
+ case 205: return "Reset Content";
+ case 206: return "Partial Content";
+ case 300: return "Multiple Choices";
+ case 301: return "Moved Permanently";
+ case 302: return "Found";
+ case 303: return "See Other";
+ case 304: return "Not Modified";
+ case 305: return "Use Proxy";
+ case 307: return "Temporary Redirect";
+ case 400: return "Bad Request";
+ case 401: return "Unauthorized";
+ case 403: return "Forbidden";
+ case 404: return "Not Found";
+ case 405: return "Method Not Allowed";
+ case 406: return "Not Acceptable";
+ case 407: return "Proxy Authentication Required";
+ case 408: return "Request Timeout";
+ case 409: return "Conflict";
+ case 410: return "Gone";
+ case 411: return "Length Required";
+ case 412: return "Precondition Failed";
+ case 413: return "Request Entity Too Large";
+ case 414: return "Request-URI Too Long";
+ case 415: return "Unsupported Media Type";
+ case 416: return "Requested Range Not Satisfiable";
+ case 417: return "Expectation Failed";
+ case 500: return "Internal Server Error";
+ case 501: return "Not Implemented";
+ case 502: return "Bad Gateway";
+ case 503: return "Service Unavailable";
+ case 504: return "Gateway Timeout";
+ case 505: return "HTTP Version Not Supported";
+ default: return "";
+ }
+}
+void http_reponse_line_delete(http_response_line *resp) {
+ free(resp->custom_message);
+ free(resp);
+}
+
+http_header *http_header_new(const char* name) {
+ http_header *header = calloc(1, sizeof(http_header));
+
+ header->name = calloc(strlen(name)+1, sizeof(char));
+ strcpy(header->name, name);
+
+ return header;
+}
+void http_header_append_content(http_header *header, const char* content) {
+ if (header->content == NULL) {
+ header->content = calloc(strlen(content)+1, sizeof(char));
+ strcpy(header->content, content);
+ } else {
+ uint32_t newlen = strlen(header->content) + strlen(content) + 1;
+ header->content = realloc(header->content, newlen);
+ strcat(header->content, content);
+ }
+}
+void http_header_delete(http_header *header) {
+ free(header->name);
+ free(header->content);
+ free(header);
+}
+
+http_request *http_request_new() {
+ http_request *req = calloc(1, sizeof(http_request));
+ req->header_count = 0;
+ req->body = NULL;
+ return req;
+}
+void http_request_add_header(http_request *req, http_header *header) {
+ req->header_count++;
+ req->headers = realloc(req->headers, req->header_count * sizeof(http_header*));
+ req->headers[req->header_count-1] = header;
+}
+void http_request_apppend_body(http_request *req, const char* body) {
+ uint32_t bodylen = 0;
+ if (req->body != NULL) {
+ bodylen = strlen(req->body);
+ }
+ bodylen += strlen(body) + 1;
+ req->body = realloc(req->body, bodylen * sizeof(char));
+ strcat(req->body, body);
+}
+void http_request_delete(http_request *req) {
+ http_request_line_delete(req->req);
+ for(int i =0; i < req->header_count; i++) {
+ http_header_delete(req->headers[i]);
+ }
+ free(req->headers);
+ free(req->body);
+ free(req);
+}
\ No newline at end of file
diff --git a/src/http/http.h b/src/http/http.h
new file mode 100644
index 0000000..1ca2ec7
--- /dev/null
+++ b/src/http/http.h
@@ -0,0 +1,78 @@
+/*
+ * File: http.h
+ * Author: sam
+ *
+ * Created on 18 July 2014, 14:15
+ */
+
+#ifndef HTTP_H
+#define HTTP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include "request.h"
+
+ typedef enum http_method {
+ METHOD_GET, METHOD_POST, METHOD_HEAD, METHOD_PUT,
+ METHOD_DELETE, METHOD_OPTIONS, METHOD_TRACE,
+ METHOD_CONNECT, METHOD_OTHER, METHOD_INVALID
+ } http_method;
+
+ typedef enum http_version {
+ HTTP10, HTTP11
+ } http_version;
+
+ typedef struct http_request_line {
+ http_method method;
+ char* method_other;
+ char* uri;
+ http_version version;
+ } http_request_line;
+
+ typedef struct http_response_line {
+ http_version version;
+ uint16_t code;
+ char* custom_message;
+ } http_response_line;
+
+ typedef struct http_header {
+ char* name;
+ char* content;
+ } http_header;
+
+ typedef struct http_request {
+ http_request_line *req;
+ http_header **headers;
+ uint32_t header_count;
+ char *body;
+ } http_request;
+
+ char* http_method_getstring(http_method method, char* method_other);
+ http_method http_method_fromstring(const char* method);
+
+ http_request_line* http_request_line_new(http_method method, const char* other);
+ void http_request_line_delete(http_request_line *req);
+
+ http_response_line* http_response_line_new(uint16_t code);
+ char* http_response_line_get_message(http_response_line *resp);
+ void http_reponse_line_delete(http_response_line *resp);
+
+ http_header* http_header_new(const char* name);
+ void http_header_append_content(http_header *header, const char* content);
+ void http_header_delete(http_header *header);
+
+ http_request* http_request_new();
+ void http_request_add_header(http_request *req, http_header *header);
+ void http_request_apppend_body(http_request *req, const char* body);
+ void http_request_delete(http_request *req);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HTTP_H */
+
diff --git a/src/http/request.c b/src/http/request.c
new file mode 100644
index 0000000..aded04b
--- /dev/null
+++ b/src/http/request.c
@@ -0,0 +1,6 @@
+#include
+#include
+#include
+#include "http.h"
+
+
diff --git a/src/http/request.h b/src/http/request.h
new file mode 100644
index 0000000..bde8df1
--- /dev/null
+++ b/src/http/request.h
@@ -0,0 +1,25 @@
+/*
+ * File: request.h
+ * Author: sam
+ *
+ * Created on 18 July 2014, 14:43
+ */
+
+#ifndef REQUEST_H
+#define REQUEST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "http.h"
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* REQUEST_H */
+
diff --git a/src/main.c b/src/main.c
index 7c1c5de..26f0e13 100644
--- a/src/main.c
+++ b/src/main.c
@@ -28,8 +28,12 @@ int main(int argc, char** argv) {
svr_listen(serverfd, 1234);
while(1) {
+ uint32_t counter;
+ skt_elem *elem, *tmp;
+
//Accept new connections
- while(svr_canaccept(serverfd)) {
+ LL_COUNT(connections, elem, counter);
+ while(counter < 100 && svr_canaccept(serverfd)) {
skt_info *info = svr_accept(serverfd);
if (info != NULL) {
skt_elem* newconn = calloc(1, sizeof(skt_elem));
@@ -38,7 +42,6 @@ int main(int argc, char** argv) {
}
}
- skt_elem *elem, *tmp;
//Read from connections
LL_FOREACH(connections, elem) {
if (skt_canread(elem->info)) {
@@ -63,16 +66,19 @@ int main(int argc, char** argv) {
}
time_t current = time(NULL);
- time_t timeout = 5;
+ time_t timeout = 30;
time_t maxlife = 500;
//Close where needed
LL_FOREACH(connections, elem) {
if (current - elem->info->last_act > timeout) {
- info("[#%lu %s] Timeout", elem->info->id, skt_addr(elem->info));
+ info("[#%lu %s] Timeout", elem->info->id, skt_clientaddr(elem->info));
elem->info->close = true;
}
if (current - elem->info->time_opened> maxlife) {
- info("[#%lu %s] Reached max life", elem->info->id, skt_addr(elem->info));
+ info("[#%lu %s] Reached max life", elem->info->id, skt_clientaddr(elem->info));
+ elem->info->close = true;
+ }
+ if (elem->info->close_afterwrite && utstring_len(elem->info->write) == 0) {
elem->info->close = true;
}
if (elem->info->close == true) {
diff --git a/src/socket.c b/src/socket.c
index 4fe62c5..0939802 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -27,6 +27,7 @@ skt_info* skt_new(int fd) {
utstring_new(skt->read);
utstring_new(skt->write);
skt->close = false;
+ skt->close_afterwrite = false;
skt->closed = false;
return skt;
@@ -94,13 +95,13 @@ void skt_close(skt_info* skt) {
if (skt->closed == true) {
return;
}
- info("[#%lu %s] Closed", skt->id, skt_addr(skt));
+ info("[#%lu %s] Closed", skt->id, skt_clientaddr(skt));
if (close(skt->fd) < 0) {
warning("error closing socket", true);
}
skt->closed = true;
}
-char* skt_addr(skt_info *skt) {
+char* skt_clientaddr(skt_info *skt) {
char* address = inet_ntoa(skt->clientaddr->sin_addr);
return address;
}
@@ -167,7 +168,7 @@ skt_info* svr_accept(int fd) {
skt->clientaddr = clientaddr;
skt->fd = clientfd;
- info("[#%lu %s] New Connection", skt->id, skt_addr(skt));
+ info("[#%lu %s] New Connection", skt->id, skt_clientaddr(skt));
return skt;
diff --git a/src/socket.h b/src/socket.h
index 5854672..e6cfb4b 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -29,6 +29,7 @@ extern "C" {
UT_string *read;
UT_string *write;
bool close;
+ bool close_afterwrite;
bool closed;
struct sockaddr_in* clientaddr;
};
@@ -46,7 +47,7 @@ extern "C" {
uint32_t skt_read(skt_info *skt);
uint32_t skt_write(skt_info *skt);
void skt_close(skt_info *skt);
- char* skt_addr(skt_info *skt);
+ char* skt_clientaddr(skt_info *skt);
int svr_create();
void svr_listen(int fd, uint16_t port);