Added server config
This commit is contained in:
2
Makefile
2
Makefile
@@ -58,7 +58,7 @@ build: .build-post
|
||||
|
||||
.build-post: .build-impl
|
||||
# Add your post 'build' code here...
|
||||
cp --recursive --force ${CND_BASEDIR}/content ${CND_ARTIFACT_DIR_${CONF}}/
|
||||
cp --recursive --force ${CND_BASEDIR}/content/* ${CND_ARTIFACT_DIR_${CONF}}/
|
||||
|
||||
# clean
|
||||
clean: .clean-post
|
||||
|
||||
10
content/khttpd.ini
Normal file
10
content/khttpd.ini
Normal file
@@ -0,0 +1,10 @@
|
||||
[Server]
|
||||
name=test.example.com
|
||||
admin=sam@xnet.tk
|
||||
listen=8080
|
||||
|
||||
[Host]
|
||||
name=orion.local
|
||||
enabled=yes
|
||||
default=yes
|
||||
serve=public_html
|
||||
11
content/public_html/index.html
Normal file
11
content/public_html/index.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>TODO supply a title</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
</head>
|
||||
<body>
|
||||
<div>TODO write content</div>
|
||||
</body>
|
||||
</html>
|
||||
186
lib/ini.c
Normal file
186
lib/ini.c
Normal file
@@ -0,0 +1,186 @@
|
||||
/* inih -- simple .INI file parser
|
||||
|
||||
inih is released under the New BSD license (see LICENSE.txt). Go to the project
|
||||
home page for more info:
|
||||
|
||||
http://code.google.com/p/inih/
|
||||
|
||||
* Sam Stevens - 07/2014 - Modified to add callback when a new section is found
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ini.h"
|
||||
|
||||
#if !INI_USE_STACK
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#define MAX_SECTION 50
|
||||
#define MAX_NAME 50
|
||||
|
||||
/* Strip whitespace chars off end of given string, in place. Return s. */
|
||||
static char* rstrip(char* s)
|
||||
{
|
||||
char* p = s + strlen(s);
|
||||
while (p > s && isspace((unsigned char)(*--p)))
|
||||
*p = '\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Return pointer to first non-whitespace char in given string. */
|
||||
static char* lskip(const char* s)
|
||||
{
|
||||
while (*s && isspace((unsigned char)(*s)))
|
||||
s++;
|
||||
return (char*)s;
|
||||
}
|
||||
|
||||
/* Return pointer to first char c or ';' comment in given string, or pointer to
|
||||
null at end of string if neither found. ';' must be prefixed by a whitespace
|
||||
character to register as a comment. */
|
||||
static char* find_char_or_comment(const char* s, char c)
|
||||
{
|
||||
int was_whitespace = 0;
|
||||
while (*s && *s != c && !(was_whitespace && *s == ';')) {
|
||||
was_whitespace = isspace((unsigned char)(*s));
|
||||
s++;
|
||||
}
|
||||
return (char*)s;
|
||||
}
|
||||
|
||||
/* Version of strncpy that ensures dest (size bytes) is null-terminated. */
|
||||
static char* strncpy0(char* dest, const char* src, size_t size)
|
||||
{
|
||||
strncpy(dest, src, size);
|
||||
dest[size - 1] = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* See documentation in header file. */
|
||||
int ini_parse_file(FILE* file,
|
||||
int (*handler)(void*, const char*, const char*,
|
||||
const char*),
|
||||
void* user)
|
||||
{
|
||||
/* Uses a fair bit of stack (use heap instead if you need to) */
|
||||
#if INI_USE_STACK
|
||||
char line[INI_MAX_LINE];
|
||||
#else
|
||||
char* line;
|
||||
#endif
|
||||
char section[MAX_SECTION] = "";
|
||||
char prev_name[MAX_NAME] = "";
|
||||
|
||||
char* start;
|
||||
char* end;
|
||||
char* name;
|
||||
char* value;
|
||||
int lineno = 0;
|
||||
int error = 0;
|
||||
|
||||
#if !INI_USE_STACK
|
||||
line = (char*)malloc(INI_MAX_LINE);
|
||||
if (!line) {
|
||||
return -2;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Scan through file line by line */
|
||||
while (fgets(line, INI_MAX_LINE, file) != NULL) {
|
||||
lineno++;
|
||||
|
||||
start = line;
|
||||
#if INI_ALLOW_BOM
|
||||
if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
|
||||
(unsigned char)start[1] == 0xBB &&
|
||||
(unsigned char)start[2] == 0xBF) {
|
||||
start += 3;
|
||||
}
|
||||
#endif
|
||||
start = lskip(rstrip(start));
|
||||
|
||||
if (*start == ';' || *start == '#') {
|
||||
/* Per Python ConfigParser, allow '#' comments at start of line */
|
||||
}
|
||||
#if INI_ALLOW_MULTILINE
|
||||
else if (*prev_name && *start && start > line) {
|
||||
/* Non-black line with leading whitespace, treat as continuation
|
||||
of previous name's value (as per Python ConfigParser). */
|
||||
if (!handler(user, section, prev_name, start) && !error)
|
||||
error = lineno;
|
||||
}
|
||||
#endif
|
||||
else if (*start == '[') {
|
||||
/* A "[section]" line */
|
||||
end = find_char_or_comment(start + 1, ']');
|
||||
if (*end == ']') {
|
||||
*end = '\0';
|
||||
strncpy0(section, start + 1, sizeof(section));
|
||||
*prev_name = '\0';
|
||||
//MODIFIED - call with null name on new section
|
||||
if (!handler(user, section, NULL, NULL) && !error)
|
||||
error = lineno;
|
||||
}
|
||||
else if (!error) {
|
||||
/* No ']' found on section line */
|
||||
error = lineno;
|
||||
}
|
||||
}
|
||||
else if (*start && *start != ';') {
|
||||
/* Not a comment, must be a name[=:]value pair */
|
||||
end = find_char_or_comment(start, '=');
|
||||
if (*end != '=') {
|
||||
end = find_char_or_comment(start, ':');
|
||||
}
|
||||
if (*end == '=' || *end == ':') {
|
||||
*end = '\0';
|
||||
name = rstrip(start);
|
||||
value = lskip(end + 1);
|
||||
end = find_char_or_comment(value, '\0');
|
||||
if (*end == ';')
|
||||
*end = '\0';
|
||||
rstrip(value);
|
||||
|
||||
/* Valid name[=:]value pair found, call handler */
|
||||
strncpy0(prev_name, name, sizeof(prev_name));
|
||||
if (!handler(user, section, name, value) && !error)
|
||||
error = lineno;
|
||||
}
|
||||
else if (!error) {
|
||||
/* No '=' or ':' found on name[=:]value line */
|
||||
error = lineno;
|
||||
}
|
||||
}
|
||||
|
||||
#if INI_STOP_ON_FIRST_ERROR
|
||||
if (error)
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !INI_USE_STACK
|
||||
free(line);
|
||||
#endif
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/* See documentation in header file. */
|
||||
int ini_parse(const char* filename,
|
||||
int (*handler)(void*, const char*, const char*, const char*),
|
||||
void* user)
|
||||
{
|
||||
FILE* file;
|
||||
int error;
|
||||
|
||||
file = fopen(filename, "r");
|
||||
if (!file)
|
||||
return -1;
|
||||
error = ini_parse_file(file, handler, user);
|
||||
fclose(file);
|
||||
return error;
|
||||
}
|
||||
77
lib/ini.h
Normal file
77
lib/ini.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/* inih -- simple .INI file parser
|
||||
|
||||
inih is released under the New BSD license (see LICENSE.txt). Go to the project
|
||||
home page for more info:
|
||||
|
||||
http://code.google.com/p/inih/
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __INI_H__
|
||||
#define __INI_H__
|
||||
|
||||
/* Make this header file easier to include in C++ code */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Parse given INI-style file. May have [section]s, name=value pairs
|
||||
(whitespace stripped), and comments starting with ';' (semicolon). Section
|
||||
is "" if name=value pair parsed before any section heading. name:value
|
||||
pairs are also supported as a concession to Python's ConfigParser.
|
||||
|
||||
For each name=value pair parsed, call handler function with given user
|
||||
pointer as well as section, name, and value (data only valid for duration
|
||||
of handler call). Handler should return nonzero on success, zero on error.
|
||||
|
||||
Returns 0 on success, line number of first error on parse error (doesn't
|
||||
stop on first error), -1 on file open error, or -2 on memory allocation
|
||||
error (only when INI_USE_STACK is zero).
|
||||
*/
|
||||
int ini_parse(const char* filename,
|
||||
int (*handler)(void* user, const char* section,
|
||||
const char* name, const char* value),
|
||||
void* user);
|
||||
|
||||
/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
|
||||
close the file when it's finished -- the caller must do that. */
|
||||
int ini_parse_file(FILE* file,
|
||||
int (*handler)(void* user, const char* section,
|
||||
const char* name, const char* value),
|
||||
void* user);
|
||||
|
||||
/* Nonzero to allow multi-line value parsing, in the style of Python's
|
||||
ConfigParser. If allowed, ini_parse() will call the handler with the same
|
||||
name for each subsequent line parsed. */
|
||||
#ifndef INI_ALLOW_MULTILINE
|
||||
#define INI_ALLOW_MULTILINE 1
|
||||
#endif
|
||||
|
||||
/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of
|
||||
the file. See http://code.google.com/p/inih/issues/detail?id=21 */
|
||||
#ifndef INI_ALLOW_BOM
|
||||
#define INI_ALLOW_BOM 1
|
||||
#endif
|
||||
|
||||
/* Nonzero to use stack, zero to use heap (malloc/free). */
|
||||
#ifndef INI_USE_STACK
|
||||
#define INI_USE_STACK 1
|
||||
#endif
|
||||
|
||||
/* Stop parsing on first error (default is to keep parsing). */
|
||||
#ifndef INI_STOP_ON_FIRST_ERROR
|
||||
#define INI_STOP_ON_FIRST_ERROR 0
|
||||
#endif
|
||||
|
||||
/* Maximum line length for any line in INI file. */
|
||||
#ifndef INI_MAX_LINE
|
||||
#define INI_MAX_LINE 200
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __INI_H__ */
|
||||
@@ -36,8 +36,11 @@ OBJECTDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}
|
||||
# Object Files
|
||||
OBJECTFILES= \
|
||||
${OBJECTDIR}/lib/http_parser.o \
|
||||
${OBJECTDIR}/src/http/http.o \
|
||||
${OBJECTDIR}/src/http/parse.o \
|
||||
${OBJECTDIR}/lib/ini.o \
|
||||
${OBJECTDIR}/src/config.o \
|
||||
${OBJECTDIR}/src/http-reader.o \
|
||||
${OBJECTDIR}/src/http-server.o \
|
||||
${OBJECTDIR}/src/http.o \
|
||||
${OBJECTDIR}/src/main.o \
|
||||
${OBJECTDIR}/src/socket.o
|
||||
|
||||
@@ -66,30 +69,45 @@ ${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}/lib/http_parser.o: lib/http_parser.c
|
||||
${OBJECTDIR}/lib/http_parser.o: nbproject/Makefile-${CND_CONF}.mk lib/http_parser.c
|
||||
${MKDIR} -p ${OBJECTDIR}/lib
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -g -Werror -Ilib -include lib/http_parser.h -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/lib/http_parser.o lib/http_parser.c
|
||||
$(COMPILE.c) -g -Werror -DINI_ALLOW_BOM=0 -DINI_ALLOW_MULTILINE=0 -D_GNU_SOURCE -Ilib -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/lib/http_parser.o lib/http_parser.c
|
||||
|
||||
${OBJECTDIR}/src/http/http.o: src/http/http.c
|
||||
${MKDIR} -p ${OBJECTDIR}/src/http
|
||||
${OBJECTDIR}/lib/ini.o: nbproject/Makefile-${CND_CONF}.mk lib/ini.c
|
||||
${MKDIR} -p ${OBJECTDIR}/lib
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -g -Werror -Ilib -include lib/http_parser.h -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http/http.o src/http/http.c
|
||||
$(COMPILE.c) -g -Werror -DINI_ALLOW_BOM=0 -DINI_ALLOW_MULTILINE=0 -D_GNU_SOURCE -Ilib -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/lib/ini.o lib/ini.c
|
||||
|
||||
${OBJECTDIR}/src/http/parse.o: src/http/parse.c
|
||||
${MKDIR} -p ${OBJECTDIR}/src/http
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -g -Werror -Ilib -include lib/http_parser.h -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http/parse.o src/http/parse.c
|
||||
|
||||
${OBJECTDIR}/src/main.o: src/main.c
|
||||
${OBJECTDIR}/src/config.o: nbproject/Makefile-${CND_CONF}.mk src/config.c
|
||||
${MKDIR} -p ${OBJECTDIR}/src
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -g -Werror -Ilib -include lib/http_parser.h -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/main.o src/main.c
|
||||
$(COMPILE.c) -g -Werror -DINI_ALLOW_BOM=0 -DINI_ALLOW_MULTILINE=0 -D_GNU_SOURCE -Ilib -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/config.o src/config.c
|
||||
|
||||
${OBJECTDIR}/src/socket.o: src/socket.c
|
||||
${OBJECTDIR}/src/http-reader.o: nbproject/Makefile-${CND_CONF}.mk src/http-reader.c
|
||||
${MKDIR} -p ${OBJECTDIR}/src
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -g -Werror -Ilib -include lib/http_parser.h -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/socket.o src/socket.c
|
||||
$(COMPILE.c) -g -Werror -DINI_ALLOW_BOM=0 -DINI_ALLOW_MULTILINE=0 -D_GNU_SOURCE -Ilib -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http-reader.o src/http-reader.c
|
||||
|
||||
${OBJECTDIR}/src/http-server.o: nbproject/Makefile-${CND_CONF}.mk src/http-server.c
|
||||
${MKDIR} -p ${OBJECTDIR}/src
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -g -Werror -DINI_ALLOW_BOM=0 -DINI_ALLOW_MULTILINE=0 -D_GNU_SOURCE -Ilib -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http-server.o src/http-server.c
|
||||
|
||||
${OBJECTDIR}/src/http.o: nbproject/Makefile-${CND_CONF}.mk src/http.c
|
||||
${MKDIR} -p ${OBJECTDIR}/src
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -g -Werror -DINI_ALLOW_BOM=0 -DINI_ALLOW_MULTILINE=0 -D_GNU_SOURCE -Ilib -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http.o src/http.c
|
||||
|
||||
${OBJECTDIR}/src/main.o: nbproject/Makefile-${CND_CONF}.mk src/main.c
|
||||
${MKDIR} -p ${OBJECTDIR}/src
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -g -Werror -DINI_ALLOW_BOM=0 -DINI_ALLOW_MULTILINE=0 -D_GNU_SOURCE -Ilib -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/main.o src/main.c
|
||||
|
||||
${OBJECTDIR}/src/socket.o: nbproject/Makefile-${CND_CONF}.mk src/socket.c
|
||||
${MKDIR} -p ${OBJECTDIR}/src
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -g -Werror -DINI_ALLOW_BOM=0 -DINI_ALLOW_MULTILINE=0 -D_GNU_SOURCE -Ilib -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/socket.o src/socket.c
|
||||
|
||||
# Subprojects
|
||||
.build-subprojects:
|
||||
|
||||
@@ -36,8 +36,11 @@ OBJECTDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}
|
||||
# Object Files
|
||||
OBJECTFILES= \
|
||||
${OBJECTDIR}/lib/http_parser.o \
|
||||
${OBJECTDIR}/src/http/http.o \
|
||||
${OBJECTDIR}/src/http/parse.o \
|
||||
${OBJECTDIR}/lib/ini.o \
|
||||
${OBJECTDIR}/src/config.o \
|
||||
${OBJECTDIR}/src/http-reader.o \
|
||||
${OBJECTDIR}/src/http-server.o \
|
||||
${OBJECTDIR}/src/http.o \
|
||||
${OBJECTDIR}/src/main.o \
|
||||
${OBJECTDIR}/src/socket.o
|
||||
|
||||
@@ -71,15 +74,30 @@ ${OBJECTDIR}/lib/http_parser.o: lib/http_parser.c
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/lib/http_parser.o lib/http_parser.c
|
||||
|
||||
${OBJECTDIR}/src/http/http.o: src/http/http.c
|
||||
${MKDIR} -p ${OBJECTDIR}/src/http
|
||||
${OBJECTDIR}/lib/ini.o: lib/ini.c
|
||||
${MKDIR} -p ${OBJECTDIR}/lib
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http/http.o src/http/http.c
|
||||
$(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/lib/ini.o lib/ini.c
|
||||
|
||||
${OBJECTDIR}/src/http/parse.o: src/http/parse.c
|
||||
${MKDIR} -p ${OBJECTDIR}/src/http
|
||||
${OBJECTDIR}/src/config.o: src/config.c
|
||||
${MKDIR} -p ${OBJECTDIR}/src
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http/parse.o src/http/parse.c
|
||||
$(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/config.o src/config.c
|
||||
|
||||
${OBJECTDIR}/src/http-reader.o: src/http-reader.c
|
||||
${MKDIR} -p ${OBJECTDIR}/src
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http-reader.o src/http-reader.c
|
||||
|
||||
${OBJECTDIR}/src/http-server.o: src/http-server.c
|
||||
${MKDIR} -p ${OBJECTDIR}/src
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http-server.o src/http-server.c
|
||||
|
||||
${OBJECTDIR}/src/http.o: src/http.c
|
||||
${MKDIR} -p ${OBJECTDIR}/src
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http.o src/http.c
|
||||
|
||||
${OBJECTDIR}/src/main.o: src/main.c
|
||||
${MKDIR} -p ${OBJECTDIR}/src
|
||||
|
||||
@@ -4,10 +4,13 @@
|
||||
<logicalFolder name="HeaderFiles"
|
||||
displayName="Header Files"
|
||||
projectFiles="true">
|
||||
<itemPath>src/http/http.h</itemPath>
|
||||
<itemPath>src/config.h</itemPath>
|
||||
<itemPath>src/http-reader.h</itemPath>
|
||||
<itemPath>src/http-server.h</itemPath>
|
||||
<itemPath>src/http.h</itemPath>
|
||||
<itemPath>lib/http_parser.h</itemPath>
|
||||
<itemPath>lib/ini.h</itemPath>
|
||||
<itemPath>src/main.h</itemPath>
|
||||
<itemPath>src/http/parse.h</itemPath>
|
||||
<itemPath>src/socket.h</itemPath>
|
||||
</logicalFolder>
|
||||
<logicalFolder name="ResourceFiles"
|
||||
@@ -17,10 +20,13 @@
|
||||
<logicalFolder name="SourceFiles"
|
||||
displayName="Source Files"
|
||||
projectFiles="true">
|
||||
<itemPath>src/http/http.c</itemPath>
|
||||
<itemPath>src/config.c</itemPath>
|
||||
<itemPath>src/http-reader.c</itemPath>
|
||||
<itemPath>src/http-server.c</itemPath>
|
||||
<itemPath>src/http.c</itemPath>
|
||||
<itemPath>lib/http_parser.c</itemPath>
|
||||
<itemPath>lib/ini.c</itemPath>
|
||||
<itemPath>src/main.c</itemPath>
|
||||
<itemPath>src/http/parse.c</itemPath>
|
||||
<itemPath>src/socket.c</itemPath>
|
||||
</logicalFolder>
|
||||
<logicalFolder name="TestFiles"
|
||||
@@ -35,7 +41,9 @@
|
||||
<itemPath>Makefile</itemPath>
|
||||
</logicalFolder>
|
||||
<itemPath>content/error.html</itemPath>
|
||||
<itemPath>content/lorem.txt</itemPath>
|
||||
<itemPath>content/public_html/index.html</itemPath>
|
||||
<itemPath>content/khttpd.ini</itemPath>
|
||||
<itemPath>content/public_html/lorem.txt</itemPath>
|
||||
</logicalFolder>
|
||||
<projectmakefile>Makefile</projectmakefile>
|
||||
<confs>
|
||||
@@ -43,7 +51,7 @@
|
||||
<toolsSet>
|
||||
<compilerSet>default</compilerSet>
|
||||
<dependencyChecking>true</dependencyChecking>
|
||||
<rebuildPropChanged>false</rebuildPropChanged>
|
||||
<rebuildPropChanged>true</rebuildPropChanged>
|
||||
</toolsSet>
|
||||
<compileType>
|
||||
<cTool>
|
||||
@@ -51,28 +59,46 @@
|
||||
<incDir>
|
||||
<pElem>lib</pElem>
|
||||
</incDir>
|
||||
<incFile>
|
||||
<pElem>lib/http_parser.h</pElem>
|
||||
</incFile>
|
||||
<commandLine>-O0</commandLine>
|
||||
<preprocessorList>
|
||||
<Elem>INI_ALLOW_BOM=0</Elem>
|
||||
<Elem>INI_ALLOW_MULTILINE=0</Elem>
|
||||
<Elem>_GNU_SOURCE</Elem>
|
||||
</preprocessorList>
|
||||
<warningLevel>3</warningLevel>
|
||||
</cTool>
|
||||
</compileType>
|
||||
<item path="content/error.html" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="content/lorem.txt" ex="false" tool="3" flavor2="0">
|
||||
<item path="content/khttpd.ini" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="content/public_html/index.html" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="content/public_html/lorem.txt" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="lib/http_parser.c" ex="false" tool="0" flavor2="0">
|
||||
</item>
|
||||
<item path="lib/http_parser.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="src/http/http.c" ex="false" tool="0" flavor2="0">
|
||||
<item path="lib/ini.c" ex="false" tool="0" flavor2="0">
|
||||
</item>
|
||||
<item path="src/http/http.h" ex="false" tool="3" flavor2="0">
|
||||
<item path="lib/ini.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="src/http/parse.c" ex="false" tool="0" flavor2="0">
|
||||
<item path="src/config.c" ex="false" tool="0" flavor2="0">
|
||||
</item>
|
||||
<item path="src/http/parse.h" ex="false" tool="3" flavor2="0">
|
||||
<item path="src/config.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="src/http-reader.c" ex="false" tool="0" flavor2="0">
|
||||
</item>
|
||||
<item path="src/http-reader.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="src/http-server.c" ex="false" tool="0" flavor2="0">
|
||||
</item>
|
||||
<item path="src/http-server.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="src/http.c" ex="false" tool="0" flavor2="0">
|
||||
</item>
|
||||
<item path="src/http.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="src/main.c" ex="false" tool="0" flavor2="0">
|
||||
</item>
|
||||
@@ -105,19 +131,35 @@
|
||||
</compileType>
|
||||
<item path="content/error.html" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="content/lorem.txt" ex="false" tool="3" flavor2="0">
|
||||
<item path="content/khttpd.ini" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="content/public_html/index.html" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="content/public_html/lorem.txt" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="lib/http_parser.c" ex="false" tool="0" flavor2="0">
|
||||
</item>
|
||||
<item path="lib/http_parser.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="src/http/http.c" ex="false" tool="0" flavor2="0">
|
||||
<item path="lib/ini.c" ex="false" tool="0" flavor2="0">
|
||||
</item>
|
||||
<item path="src/http/http.h" ex="false" tool="3" flavor2="0">
|
||||
<item path="lib/ini.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="src/http/parse.c" ex="false" tool="0" flavor2="0">
|
||||
<item path="src/config.c" ex="false" tool="0" flavor2="0">
|
||||
</item>
|
||||
<item path="src/http/parse.h" ex="false" tool="3" flavor2="0">
|
||||
<item path="src/config.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="src/http-reader.c" ex="false" tool="0" flavor2="0">
|
||||
</item>
|
||||
<item path="src/http-reader.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="src/http-server.c" ex="false" tool="0" flavor2="0">
|
||||
</item>
|
||||
<item path="src/http-server.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="src/http.c" ex="false" tool="0" flavor2="0">
|
||||
</item>
|
||||
<item path="src/http.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="src/main.c" ex="false" tool="0" flavor2="0">
|
||||
</item>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<runcommandpicklistitem>"${OUTPUT_PATH}"</runcommandpicklistitem>
|
||||
</runcommandpicklist>
|
||||
<runcommand>"${OUTPUT_PATH}"</runcommand>
|
||||
<rundir></rundir>
|
||||
<rundir>/home/sam/NetBeansProjects/KHttp/./dist/Debug/GNU-Linux-x86</rundir>
|
||||
<buildfirst>true</buildfirst>
|
||||
<terminal-type>0</terminal-type>
|
||||
<remove-instrumentation>0</remove-instrumentation>
|
||||
|
||||
@@ -8,17 +8,16 @@
|
||||
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
|
||||
<group>
|
||||
<file>file:/home/sam/NetBeansProjects/KHttp/src/socket.c</file>
|
||||
<file>file:/home/sam/NetBeansProjects/KHttp/src/http/http.h</file>
|
||||
<file>file:/home/sam/NetBeansProjects/KHttp/src/http/parse.c</file>
|
||||
<file>file:/home/sam/NetBeansProjects/KHttp/src/http-server.h</file>
|
||||
<file>file:/home/sam/NetBeansProjects/KHttp/src/http.c</file>
|
||||
<file>file:/home/sam/NetBeansProjects/KHttp/src/http-reader.h</file>
|
||||
<file>file:/home/sam/NetBeansProjects/KHttp/src/main.h</file>
|
||||
<file>file:/home/sam/NetBeansProjects/KHttp/Makefile</file>
|
||||
<file>file:/home/sam/NetBeansProjects/KHttp/lib/http_parser.h</file>
|
||||
<file>file:/home/sam/NetBeansProjects/KHttp/content/error.html</file>
|
||||
<file>file:/home/sam/NetBeansProjects/KHttp/src/http/parse.h</file>
|
||||
<file>file:/home/sam/NetBeansProjects/KHttp/src/main.c</file>
|
||||
<file>file:/home/sam/NetBeansProjects/KHttp/lib/http_parser.c</file>
|
||||
<file>file:/home/sam/NetBeansProjects/KHttp/src/socket.h</file>
|
||||
<file>file:/home/sam/NetBeansProjects/KHttp/src/http/http.c</file>
|
||||
<file>file:/home/sam/NetBeansProjects/KHttp/src/http-server.c</file>
|
||||
<file>file:/home/sam/NetBeansProjects/KHttp/src/http.h</file>
|
||||
<file>file:/home/sam/NetBeansProjects/KHttp/src/http-reader.c</file>
|
||||
</group>
|
||||
</open-files>
|
||||
</project-private>
|
||||
|
||||
142
src/config.c
Normal file
142
src/config.c
Normal file
@@ -0,0 +1,142 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "config.h"
|
||||
#include "ini.h"
|
||||
|
||||
const char *default_servername = "localhost";
|
||||
const char *default_administrator = "root@localhost";
|
||||
|
||||
config_server* config_server_new() {
|
||||
config_server* config = calloc(1, sizeof(config_server));
|
||||
config->host_count = 0;
|
||||
config->listen_port = 80;
|
||||
|
||||
config->servername = calloc(128, sizeof(char));
|
||||
if (gethostname(config->servername, 128) < 0) {
|
||||
warning("failed to get server hostname", true);
|
||||
free(config->servername);
|
||||
config->servername = strdup(default_servername);
|
||||
}
|
||||
config->servername = realloc(config->servername, (strlen(config->servername)+1)*sizeof(char));
|
||||
|
||||
config->administrator = strdup(default_servername);
|
||||
|
||||
return config;
|
||||
}
|
||||
void config_server_addhost(config_server *config, config_host *host) {
|
||||
if (config->host_count == 0) {
|
||||
config->hosts = calloc(1, sizeof(config_server*));
|
||||
config->host_count++;
|
||||
} else {
|
||||
config->hosts = realloc(config->hosts, ++config->host_count * sizeof(config_server*));
|
||||
}
|
||||
config->hosts[config->host_count-1] = host;
|
||||
}
|
||||
config_host* config_server_gethost(config_server *config, char *name) {
|
||||
config_host *defaulthost=NULL;
|
||||
config_host *host=NULL;
|
||||
CONFIG_SERVER_FOREACH_HOST(config, host) {
|
||||
if (strcasecmp(name, host->hostname) == 0) {
|
||||
return host;
|
||||
}
|
||||
if (host->default_host == true) {
|
||||
defaulthost = host;
|
||||
}
|
||||
}
|
||||
return defaulthost;
|
||||
}
|
||||
void config_server_delete(config_server* config) {
|
||||
if (config->administrator != NULL) free(config->administrator);
|
||||
if (config->servername != NULL) free(config->servername);
|
||||
config_host *host;
|
||||
CONFIG_SERVER_FOREACH_HOST(config, host) {
|
||||
config_host_delete(host);
|
||||
}
|
||||
if (config->hosts != NULL) free(config->hosts);
|
||||
free(config);
|
||||
}
|
||||
|
||||
config_host* config_host_new() {
|
||||
config_host *host = calloc(1, sizeof(config_host));
|
||||
host->default_host = false;
|
||||
host->enabled = true;
|
||||
host->hostname = NULL;
|
||||
host->serve_dir = NULL;
|
||||
|
||||
return host;
|
||||
}
|
||||
void config_host_delete(config_host *host) {
|
||||
if (host->hostname != NULL) free(host->hostname);
|
||||
if (host->serve_dir != NULL) free(host->serve_dir);
|
||||
free(host);
|
||||
}
|
||||
|
||||
static int config_read_ini_cb(void* _config, const char* section, const char* name,
|
||||
const char* value) {
|
||||
config_server *config = (config_server*)_config;
|
||||
static config_host *host = NULL;
|
||||
|
||||
#define MATCH(s, n) strcasecmp(s, section) == 0 && strcasecmp(n, name) == 0
|
||||
|
||||
if (name == NULL && strcasecmp(section, "Host") == 0) {
|
||||
host = config_host_new();
|
||||
config_server_addhost(config, host);
|
||||
} else if (strcasecmp("Host", section) == 0 && host == NULL) {
|
||||
return -1;
|
||||
} else if (name != NULL) {
|
||||
if (MATCH("Server", "name")) {
|
||||
config->servername = strdup(value);
|
||||
} else if (MATCH("Server", "admin")) {
|
||||
config->administrator = strdup(value);
|
||||
} else if (MATCH("Server", "listen")) {
|
||||
errno = 0;
|
||||
config->listen_port = (uint16_t)strtol(value, NULL, 10);
|
||||
if (errno != 0) {
|
||||
warning("Config: Invalid port number for [Server]listen", true);
|
||||
}
|
||||
return -1;
|
||||
} else if (MATCH("Host", "name")) {
|
||||
host->hostname = strdup(value);
|
||||
} else if (MATCH("Host", "enabled")) {
|
||||
if (strcasecmp(value, "yes") == 0) {
|
||||
host->enabled = true;
|
||||
} else if (strcasecmp(value, "no") == 0) {
|
||||
host->enabled = false;
|
||||
}
|
||||
} else if (MATCH("Host", "default")) {
|
||||
|
||||
if (strcasecmp(value, "yes") == 0) {
|
||||
//Ensure there is only one default host
|
||||
config_host *tmp;
|
||||
CONFIG_SERVER_FOREACH_HOST(config, tmp) {
|
||||
tmp->default_host = false;
|
||||
}
|
||||
host->default_host = true;
|
||||
} else if (strcasecmp(value, "no") == 0) {
|
||||
host->default_host = false;
|
||||
}
|
||||
} else if (MATCH("Host", "serve")) {
|
||||
DIR *dir = opendir(value);
|
||||
if (dir == NULL) {
|
||||
warning("Config: host serve directory is invalid", true);
|
||||
return -1;
|
||||
}
|
||||
closedir(dir);
|
||||
host->serve_dir = strdup(value);
|
||||
}
|
||||
}
|
||||
#undef MATCH
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int config_read_ini(const char* filename, config_server *config) {
|
||||
return ini_parse(filename, config_read_ini_cb, config);
|
||||
}
|
||||
53
src/config.h
Normal file
53
src/config.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* File: config.h
|
||||
* Author: sam
|
||||
*
|
||||
* Created on 27 July 2014, 18:47
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "main.h"
|
||||
|
||||
#define CONFIG_SERVER_FOREACH_HOST(config, elem) \
|
||||
elem = config->hosts[0]; \
|
||||
for(int i=0; i < config->host_count; elem=config->hosts[i++])
|
||||
|
||||
typedef struct config_host {
|
||||
char *hostname;
|
||||
bool default_host;
|
||||
bool enabled;
|
||||
char* serve_dir;
|
||||
} config_host;
|
||||
|
||||
typedef struct config_server {
|
||||
char *servername;
|
||||
char *administrator;
|
||||
uint16_t listen_port;
|
||||
|
||||
config_host **hosts;
|
||||
size_t host_count;
|
||||
} config_server;
|
||||
|
||||
config_server* config_server_new();
|
||||
void config_server_addhost(config_server *config, config_host *host);
|
||||
config_host* config_server_gethost(config_server *config, char* name);
|
||||
void config_server_delete(config_server* config);
|
||||
|
||||
config_host* config_host_new();
|
||||
void config_host_delete(config_host *host);
|
||||
|
||||
int config_read_ini(const char* filename, config_server *config);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_H */
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <http_parser.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "../main.h"
|
||||
#include "main.h"
|
||||
#include "http.h"
|
||||
#include "parse.h"
|
||||
#include "http_parser.h"
|
||||
#include "http-reader.h"
|
||||
|
||||
#define GET_CB_STR(str, at, length) do { \
|
||||
str = calloc(length+1, sizeof(char));\
|
||||
@@ -30,6 +30,12 @@ http_parser_settings* parser_get_settings(skt_elem *elem) {
|
||||
}
|
||||
return parser_settings;
|
||||
}
|
||||
void parser_free_settings() {
|
||||
if (parser_settings != NULL) {
|
||||
free(parser_settings);
|
||||
parser_settings = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int parser_cb_on_message_begin(http_parser* parser) {
|
||||
if (SKT(parser)->current_request != NULL) {
|
||||
@@ -83,6 +89,7 @@ int parser_cb_on_header_field(http_parser* parser, const char *at, size_t length
|
||||
http_header* header = SKT(parser)->parser_current_header;
|
||||
size_t newlen = strlen(header->name) + length +1;
|
||||
header->name = realloc(header->name, newlen * sizeof(char));
|
||||
strcat(header->name, str);
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
@@ -14,12 +14,10 @@ extern "C" {
|
||||
|
||||
#include "http_parser.h"
|
||||
#include "http.h"
|
||||
#include "../main.h"
|
||||
|
||||
|
||||
void parser_set_currentskt(skt_elem *elem);
|
||||
#include "main.h"
|
||||
|
||||
http_parser_settings* parser_get_settings(skt_elem *elem);
|
||||
void parser_free_settings();
|
||||
|
||||
int parser_cb_on_message_begin(http_parser* parser);
|
||||
int parser_cb_on_url(http_parser* parser, const char *at, size_t length);
|
||||
6
src/http-server.c
Normal file
6
src/http-server.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "http.h"
|
||||
#include "main.h"
|
||||
|
||||
26
src/http-server.h
Normal file
26
src/http-server.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* File: http-server.h
|
||||
* Author: sam
|
||||
*
|
||||
* Created on 26 July 2014, 15:32
|
||||
*/
|
||||
|
||||
#ifndef HTTP_SERVER_H
|
||||
#define HTTP_SERVER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "http.h"
|
||||
#include "main.h"
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HTTP_SERVER_H */
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
#include "../main.h"
|
||||
#include "main.h"
|
||||
#include "ut/utarray.h"
|
||||
#include "ut/utstring.h"
|
||||
#include "http.h"
|
||||
@@ -360,7 +360,7 @@ http_response* http_response_create_builtin(uint16_t code, char* errmsg) {
|
||||
|
||||
http_header_list_add(resp->headers, http_header_new(HEADER_CONTENT_TYPE, "text/html"), false);
|
||||
|
||||
file_map* errorpage = file_map_new("content/error.html");
|
||||
file_map* errorpage = file_map_new("error.html");
|
||||
if (errorpage != NULL) {
|
||||
http_response_append_body(resp, errorpage->map);
|
||||
file_map_delete(errorpage);
|
||||
41
src/main.c
41
src/main.c
@@ -21,16 +21,22 @@
|
||||
#include "ut/utarray.h"
|
||||
#include "main.h"
|
||||
#include "socket.h"
|
||||
#include "http/http.h"
|
||||
#include "http/parse.h"
|
||||
#include "http.h"
|
||||
#include "http-reader.h"
|
||||
#include "config.h"
|
||||
|
||||
int serverfd = 0;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
config_server *config = config_server_new();
|
||||
if (config_read_ini("khttpd.ini", config) < 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
skt_elem *connections = NULL;
|
||||
|
||||
serverfd = svr_create();
|
||||
svr_listen(serverfd, 1234);
|
||||
svr_listen(serverfd, config->listen_port);
|
||||
|
||||
while(1) {
|
||||
uint32_t counter;
|
||||
@@ -55,34 +61,35 @@ int main(int argc, char** argv) {
|
||||
//Process sockets
|
||||
LL_FOREACH(connections, elem) {
|
||||
if (utstring_len(elem->info->read) > 0) {
|
||||
//Parse the incoming data
|
||||
int parsedcount = http_parser_execute(
|
||||
elem->parser,
|
||||
parser_get_settings(elem),
|
||||
utstring_body(elem->info->read),
|
||||
utstring_len(elem->info->read));
|
||||
//Check that all data was read
|
||||
if (parsedcount != utstring_len(elem->info->read)) {
|
||||
//emit warning
|
||||
char warningmsg[2048] = {0};
|
||||
snprintf(warningmsg, 2048,
|
||||
"error parsing request (%s: %s). closing connection",
|
||||
http_errno_name(elem->parser->http_errno),
|
||||
http_errno_description(elem->parser->http_errno));
|
||||
warning(warningmsg, false);
|
||||
elem->info->close = true;
|
||||
}
|
||||
utstring_clear(elem->info->read);
|
||||
if (elem->request_complete == true) {
|
||||
char* reqstr = http_request_write(elem->current_request);
|
||||
info("\n%s\n", reqstr);
|
||||
free(reqstr);
|
||||
|
||||
http_response* resp = http_response_create_builtin(200, elem->current_request->req->uri);
|
||||
utstring_printf(elem->info->write, "%s", http_response_write(resp));
|
||||
http_response_delete(resp);
|
||||
elem->request_complete = false;
|
||||
http_request_delete(elem->current_request);
|
||||
elem->current_request = NULL;
|
||||
//send 400 back and close connection
|
||||
http_response *resp400 = http_response_create_builtin(400, "Request was invalid or could not be read");
|
||||
char *resp400str = http_response_write(resp400);
|
||||
utstring_printf(elem->info->write, "%s", resp400str);
|
||||
http_response_delete(resp400);
|
||||
free(resp400str);
|
||||
elem->info->close_afterwrite = true;
|
||||
}
|
||||
//Clear read data now that we have processed it
|
||||
utstring_clear(elem->info->read);
|
||||
//Process request if received
|
||||
if (elem->request_complete == true) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ extern "C" {
|
||||
#include <stdbool.h>
|
||||
#include "http_parser.h"
|
||||
#include "socket.h"
|
||||
#include "http/http.h"
|
||||
#include "http.h"
|
||||
|
||||
typedef struct file_map {
|
||||
char* map;
|
||||
|
||||
@@ -17,7 +17,7 @@ extern "C" {
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <time.h>
|
||||
#include "http/http.h"
|
||||
#include "http.h"
|
||||
#include "ut/utstring.h"
|
||||
|
||||
typedef struct skt_info skt_info;
|
||||
|
||||
Reference in New Issue
Block a user