diff --git a/example_config/example.config b/example_config/example.config new file mode 100644 index 0000000..06a6fcb --- /dev/null +++ b/example_config/example.config @@ -0,0 +1,6 @@ +PATH=/ +HTML='''Test HTML +{{{Var}}} +''' + +Var='''Test var value''' diff --git a/src/arg_parse.c b/src/arg_parse.c index 20e224b..0ca73cd 100644 --- a/src/arg_parse.c +++ b/src/arg_parse.c @@ -24,6 +24,7 @@ void print_usage(void) { puts("Usage:"); puts(" -p | --port "); + puts(" --config="); } Args parse_args(int argc, char **argv) { @@ -42,6 +43,8 @@ Args parse_args(int argc, char **argv) { } --argc; ++argv; + } else if (strncmp(argv[0], "--config=", 9) == 0 && strlen(argv[0]) > 9) { + args.config_file = argv[0] + 9; } else { puts("ERROR: Invalid args!\n"); print_usage(); diff --git a/src/arg_parse.h b/src/arg_parse.h index a17e6d5..6e76206 100644 --- a/src/arg_parse.h +++ b/src/arg_parse.h @@ -20,6 +20,8 @@ typedef struct Args { unsigned short flags; unsigned short port; + // Does not need to be free'd, this should point to a string in argv. + const char *config_file; } Args; void print_usage(void); diff --git a/src/http.c b/src/http.c index b6a2077..a43648a 100644 --- a/src/http.c +++ b/src/http.c @@ -21,8 +21,12 @@ #include #include +// Third party includes. +#include + // Local includes #include "constants.h" +#include "http_template.h" #define REQUEST_TYPE_BUFFER_SIZE 16 #define REQUEST_PATH_BUFFER_SIZE 256 @@ -31,7 +35,11 @@ char *c_simple_http_request_response( const char *request, unsigned int size, - const C_SIMPLE_HTTP_HTTPTemplates *templates) { + const C_SIMPLE_HTTP_HTTPTemplates *templates, + size_t *out_size) { + if (out_size) { + *out_size = 0; + } // parse first line. unsigned int idx = 0; char request_type[REQUEST_TYPE_BUFFER_SIZE] = {0}; @@ -102,8 +110,26 @@ char *c_simple_http_request_response( fprintf(stderr, "Parsing request: got http protocol \"%s\"\n", request_proto); #endif - // TODO - return NULL; + if (strcmp(request_type, "GET") != 0) { + fprintf(stderr, "ERROR Only GET requests are allowed!\n"); + return NULL; + } + + size_t generated_size = 0; + char *generated_buf = c_simple_http_path_to_generated( + request_path, + templates, + &generated_size); + if (!generated_buf || generated_size == 0) { + fprintf(stderr, "ERROR Unable to generate response html for path \"%s\"!\n", + request_path); + return NULL; + } + + if (out_size) { + *out_size = generated_size; + } + return generated_buf; } // vim: ts=2 sts=2 sw=2 diff --git a/src/http.h b/src/http.h index e4264cd..e87ae02 100644 --- a/src/http.h +++ b/src/http.h @@ -17,6 +17,9 @@ #ifndef SEODISPARATE_COM_C_SIMPLE_HTTP_HTTP_H_ #define SEODISPARATE_COM_C_SIMPLE_HTTP_HTTP_H_ +// Standard library includes. +#include + // Third party includes. #include @@ -30,7 +33,8 @@ typedef C_SIMPLE_HTTP_ParsedConfig C_SIMPLE_HTTP_HTTPTemplates; char *c_simple_http_request_response( const char *request, unsigned int size, - const C_SIMPLE_HTTP_HTTPTemplates *templates + const C_SIMPLE_HTTP_HTTPTemplates *templates, + size_t *out_size ); #endif diff --git a/src/main.c b/src/main.c index ae0e1dc..c0f83fd 100644 --- a/src/main.c +++ b/src/main.c @@ -27,6 +27,9 @@ #include #include +// Third party includes. +#include + // Local includes. #include "arg_parse.h" #include "big_endian.h" @@ -39,7 +42,21 @@ int main(int argc, char **argv) { Args args = parse_args(argc, argv); + if (!args.config_file) { + fprintf(stderr, "ERROR Config file not specified!\n"); + print_usage(); + return 2; + } + printf("%u\n", args.port); + printf("config file is: %s\n", args.config_file); + + __attribute__((cleanup(c_simple_http_clean_up_parsed_config))) + C_SIMPLE_HTTP_ParsedConfig parsed_config = c_simple_http_parse_config( + args.config_file, + "PATH", + NULL + ); __attribute__((cleanup(cleanup_tcp_socket))) int tcp_socket = create_tcp_socket(args.port); @@ -95,12 +112,38 @@ int main(int argc, char **argv) { } } puts(""); - // TODO Validate request and send response. - // TODO WIP + + size_t response_size = 0; const char *response = c_simple_http_request_response( - (const char*)recv_buf, read_ret, NULL); + (const char*)recv_buf, read_ret, &parsed_config, &response_size); if (response) { + write(connection_fd, "HTTP/1.1 200 OK\n", 16); + write(connection_fd, "Allow: GET\n", 11); + write(connection_fd, "Content-Type: text/html\n", 24); + char content_length_buf[128]; + size_t content_length_buf_size = 0; + memcpy(content_length_buf, "Content-Length: ", 16); + content_length_buf_size = 16; + int written = 0; + snprintf( + content_length_buf + content_length_buf_size, + 127 - content_length_buf_size, + "%lu\n%n", + response_size, + &written); + content_length_buf_size += written; + write(connection_fd, content_length_buf, content_length_buf_size); + write(connection_fd, "\n", 1); + write(connection_fd, response, response_size); + free((void*)response); + } else { + // TODO handle internal errors also. + write(connection_fd, "HTTP/1.1 404 Not Found\n", 23); + write(connection_fd, "Allow: GET\n", 11); + write(connection_fd, "Content-Type: text/html\n", 24); + write(connection_fd, "Content-Length: 14\n", 19); + write(connection_fd, "\n404 Not Found\n", 15); } close(connection_fd); } else {