diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1746e32 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +bin +obj diff --git a/CWebLibrary.make b/CWebLibrary.make new file mode 100644 index 0000000..bb3ee4f --- /dev/null +++ b/CWebLibrary.make @@ -0,0 +1,166 @@ +# GNU Make project makefile autogenerated by Premake + +ifndef config + config=debug +endif + +ifndef verbose + SILENT = @ +endif + +.PHONY: clean prebuild prelink + +ifeq ($(config),debug) + ifeq ($(origin CC), default) + CC = clang + endif + ifeq ($(origin CXX), default) + CXX = clang++ + endif + ifeq ($(origin AR), default) + AR = ar + endif + TARGETDIR = bin/Debug + TARGET = $(TARGETDIR)/libCWebLibrary.a + OBJDIR = obj/Debug/CWebLibrary + DEFINES += + INCLUDES += + FORCE_INCLUDE += + ALL_CPPFLAGS += $(CPPFLAGS) -MD -MP $(DEFINES) $(INCLUDES) + ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) + ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) + ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES) + LIBS += + LDDEPS += + ALL_LDFLAGS += $(LDFLAGS) + LINKCMD = $(AR) -rcs "$@" $(OBJECTS) + define PREBUILDCMDS + endef + define PRELINKCMDS + endef + define POSTBUILDCMDS + endef +all: prebuild prelink $(TARGET) + @: + +endif + +ifeq ($(config),release) + ifeq ($(origin CC), default) + CC = clang + endif + ifeq ($(origin CXX), default) + CXX = clang++ + endif + ifeq ($(origin AR), default) + AR = ar + endif + TARGETDIR = bin/Release + TARGET = $(TARGETDIR)/libCWebLibrary.a + OBJDIR = obj/Release/CWebLibrary + DEFINES += + INCLUDES += + FORCE_INCLUDE += + ALL_CPPFLAGS += $(CPPFLAGS) -MD -MP $(DEFINES) $(INCLUDES) + ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) + ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) + ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES) + LIBS += + LDDEPS += + ALL_LDFLAGS += $(LDFLAGS) + LINKCMD = $(AR) -rcs "$@" $(OBJECTS) + define PREBUILDCMDS + endef + define PRELINKCMDS + endef + define POSTBUILDCMDS + endef +all: prebuild prelink $(TARGET) + @: + +endif + +OBJECTS := \ + $(OBJDIR)/http_content_type.o \ + $(OBJDIR)/http_method.o \ + $(OBJDIR)/http_request.o \ + $(OBJDIR)/http_response.o \ + $(OBJDIR)/http_status.o \ + +RESOURCES := \ + +CUSTOMFILES := \ + +SHELLTYPE := posix +ifeq (.exe,$(findstring .exe,$(ComSpec))) + SHELLTYPE := msdos +endif + +$(TARGET): $(GCH) ${CUSTOMFILES} $(OBJECTS) $(LDDEPS) $(RESOURCES) | $(TARGETDIR) + @echo Linking CWebLibrary + $(SILENT) $(LINKCMD) + $(POSTBUILDCMDS) + +$(CUSTOMFILES): | $(OBJDIR) + +$(TARGETDIR): + @echo Creating $(TARGETDIR) +ifeq (posix,$(SHELLTYPE)) + $(SILENT) mkdir -p $(TARGETDIR) +else + $(SILENT) mkdir $(subst /,\\,$(TARGETDIR)) +endif + +$(OBJDIR): + @echo Creating $(OBJDIR) +ifeq (posix,$(SHELLTYPE)) + $(SILENT) mkdir -p $(OBJDIR) +else + $(SILENT) mkdir $(subst /,\\,$(OBJDIR)) +endif + +clean: + @echo Cleaning CWebLibrary +ifeq (posix,$(SHELLTYPE)) + $(SILENT) rm -f $(TARGET) + $(SILENT) rm -rf $(OBJDIR) +else + $(SILENT) if exist $(subst /,\\,$(TARGET)) del $(subst /,\\,$(TARGET)) + $(SILENT) if exist $(subst /,\\,$(OBJDIR)) rmdir /s /q $(subst /,\\,$(OBJDIR)) +endif + +prebuild: + $(PREBUILDCMDS) + +prelink: + $(PRELINKCMDS) + +ifneq (,$(PCH)) +$(OBJECTS): $(GCH) $(PCH) | $(OBJDIR) +$(GCH): $(PCH) | $(OBJDIR) + @echo $(notdir $<) + $(SILENT) $(CC) -x c-header $(ALL_CFLAGS) -o "$@" -MF "$(@:%.gch=%.d)" -c "$<" +else +$(OBJECTS): | $(OBJDIR) +endif + +$(OBJDIR)/http_content_type.o: http/http_content_type.c + @echo $(notdir $<) + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/http_method.o: http/http_method.c + @echo $(notdir $<) + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/http_request.o: http/http_request.c + @echo $(notdir $<) + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/http_response.o: http/http_response.c + @echo $(notdir $<) + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" +$(OBJDIR)/http_status.o: http/http_status.c + @echo $(notdir $<) + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" + +-include $(OBJECTS:%.o=%.d) +ifneq (,$(PCH)) + -include $(OBJDIR)/$(notdir $(PCH)).d +endif \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9d871db --- /dev/null +++ b/Makefile @@ -0,0 +1,55 @@ +# GNU Make workspace makefile autogenerated by Premake + +ifndef config + config=debug +endif + +ifndef verbose + SILENT = @ +endif + +ifeq ($(config),debug) + CWebLibrary_config = debug + cweb_config = debug +endif +ifeq ($(config),release) + CWebLibrary_config = release + cweb_config = release +endif + +PROJECTS := CWebLibrary cweb + +.PHONY: all clean help $(PROJECTS) + +all: $(PROJECTS) + +CWebLibrary: +ifneq (,$(CWebLibrary_config)) + @echo "==== Building CWebLibrary ($(CWebLibrary_config)) ====" + @${MAKE} --no-print-directory -C . -f CWebLibrary.make config=$(CWebLibrary_config) +endif + +cweb: CWebLibrary +ifneq (,$(cweb_config)) + @echo "==== Building cweb ($(cweb_config)) ====" + @${MAKE} --no-print-directory -C . -f cweb.make config=$(cweb_config) +endif + +clean: + @${MAKE} --no-print-directory -C . -f CWebLibrary.make clean + @${MAKE} --no-print-directory -C . -f cweb.make clean + +help: + @echo "Usage: make [config=name] [target]" + @echo "" + @echo "CONFIGURATIONS:" + @echo " debug" + @echo " release" + @echo "" + @echo "TARGETS:" + @echo " all (default)" + @echo " clean" + @echo " CWebLibrary" + @echo " cweb" + @echo "" + @echo "For more information, see https://github.com/premake/premake-core/wiki" \ No newline at end of file diff --git a/cweb.make b/cweb.make new file mode 100644 index 0000000..8fc30d9 --- /dev/null +++ b/cweb.make @@ -0,0 +1,150 @@ +# GNU Make project makefile autogenerated by Premake + +ifndef config + config=debug +endif + +ifndef verbose + SILENT = @ +endif + +.PHONY: clean prebuild prelink + +ifeq ($(config),debug) + ifeq ($(origin CC), default) + CC = clang + endif + ifeq ($(origin CXX), default) + CXX = clang++ + endif + ifeq ($(origin AR), default) + AR = ar + endif + TARGETDIR = bin/Debug + TARGET = $(TARGETDIR)/cweb + OBJDIR = obj/Debug/cweb + DEFINES += + INCLUDES += -Ihttp + FORCE_INCLUDE += + ALL_CPPFLAGS += $(CPPFLAGS) -MD -MP $(DEFINES) $(INCLUDES) + ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -g + ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -g + ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES) + LIBS += bin/Debug/libCWebLibrary.a + LDDEPS += bin/Debug/libCWebLibrary.a + ALL_LDFLAGS += $(LDFLAGS) + LINKCMD = $(CC) -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS) + define PREBUILDCMDS + endef + define PRELINKCMDS + endef + define POSTBUILDCMDS + endef +all: prebuild prelink $(TARGET) + @: + +endif + +ifeq ($(config),release) + ifeq ($(origin CC), default) + CC = clang + endif + ifeq ($(origin CXX), default) + CXX = clang++ + endif + ifeq ($(origin AR), default) + AR = ar + endif + TARGETDIR = bin/Release + TARGET = $(TARGETDIR)/cweb + OBJDIR = obj/Release/cweb + DEFINES += + INCLUDES += -Ihttp + FORCE_INCLUDE += + ALL_CPPFLAGS += $(CPPFLAGS) -MD -MP $(DEFINES) $(INCLUDES) + ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS) -O2 + ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS) -O2 + ALL_RESFLAGS += $(RESFLAGS) $(DEFINES) $(INCLUDES) + LIBS += bin/Release/libCWebLibrary.a + LDDEPS += bin/Release/libCWebLibrary.a + ALL_LDFLAGS += $(LDFLAGS) + LINKCMD = $(CC) -o "$@" $(OBJECTS) $(RESOURCES) $(ALL_LDFLAGS) $(LIBS) + define PREBUILDCMDS + endef + define PRELINKCMDS + endef + define POSTBUILDCMDS + endef +all: prebuild prelink $(TARGET) + @: + +endif + +OBJECTS := \ + $(OBJDIR)/main.o \ + +RESOURCES := \ + +CUSTOMFILES := \ + +SHELLTYPE := posix +ifeq (.exe,$(findstring .exe,$(ComSpec))) + SHELLTYPE := msdos +endif + +$(TARGET): $(GCH) ${CUSTOMFILES} $(OBJECTS) $(LDDEPS) $(RESOURCES) | $(TARGETDIR) + @echo Linking cweb + $(SILENT) $(LINKCMD) + $(POSTBUILDCMDS) + +$(CUSTOMFILES): | $(OBJDIR) + +$(TARGETDIR): + @echo Creating $(TARGETDIR) +ifeq (posix,$(SHELLTYPE)) + $(SILENT) mkdir -p $(TARGETDIR) +else + $(SILENT) mkdir $(subst /,\\,$(TARGETDIR)) +endif + +$(OBJDIR): + @echo Creating $(OBJDIR) +ifeq (posix,$(SHELLTYPE)) + $(SILENT) mkdir -p $(OBJDIR) +else + $(SILENT) mkdir $(subst /,\\,$(OBJDIR)) +endif + +clean: + @echo Cleaning cweb +ifeq (posix,$(SHELLTYPE)) + $(SILENT) rm -f $(TARGET) + $(SILENT) rm -rf $(OBJDIR) +else + $(SILENT) if exist $(subst /,\\,$(TARGET)) del $(subst /,\\,$(TARGET)) + $(SILENT) if exist $(subst /,\\,$(OBJDIR)) rmdir /s /q $(subst /,\\,$(OBJDIR)) +endif + +prebuild: + $(PREBUILDCMDS) + +prelink: + $(PRELINKCMDS) + +ifneq (,$(PCH)) +$(OBJECTS): $(GCH) $(PCH) | $(OBJDIR) +$(GCH): $(PCH) | $(OBJDIR) + @echo $(notdir $<) + $(SILENT) $(CC) -x c-header $(ALL_CFLAGS) -o "$@" -MF "$(@:%.gch=%.d)" -c "$<" +else +$(OBJECTS): | $(OBJDIR) +endif + +$(OBJDIR)/main.o: main.c + @echo $(notdir $<) + $(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<" + +-include $(OBJECTS:%.o=%.d) +ifneq (,$(PCH)) + -include $(OBJDIR)/$(notdir $(PCH)).d +endif \ No newline at end of file diff --git a/http/http_method.c b/http/http_method.c index 47970a7..86230d5 100644 --- a/http/http_method.c +++ b/http/http_method.c @@ -41,3 +41,23 @@ void http_method(HttpMethod __method, char *__out, size_t __size) { } break; } } + +HttpMethod get_http_method(char *__met) { + if (strcmp(__met, "GET")) + return HTTP_METHOD_GET; + if (strcmp(__met, "POST")) + return HTTP_METHOD_POST; + if (strcmp(__met, "PUT")) + return HTTP_METHOD_PUT; + if (strcmp(__met, "DELETE")) + return HTTP_METHOD_DELETE; + if (strcmp(__met, "PATCH")) + return HTTP_METHOD_PATCH; + if (strcmp(__met, "HEAD")) + return HTTP_METHOD_HEAD; + if (strcmp(__met, "OPTIONS")) + return HTTP_METHOD_OPTIONS; + if (strcmp(__met, "CONNECT")) + return HTTP_METHOD_CONNECT; + return HTTP_METHOD_TRACE; +} diff --git a/http/http_method.h b/http/http_method.h index ac743fe..b2dfb46 100644 --- a/http/http_method.h +++ b/http/http_method.h @@ -16,5 +16,6 @@ typedef enum { } HttpMethod; void http_method(HttpMethod __method, char *__out, size_t __size); +HttpMethod get_http_method(char *__met); #endif diff --git a/http/http_request.c b/http/http_request.c new file mode 100644 index 0000000..3073a53 --- /dev/null +++ b/http/http_request.c @@ -0,0 +1,92 @@ +#include "http_method.h" +#include "http_request.h" +#include +#include +#include +// GET / HTTP/1.1 +// Host: localhost:8080 +// Sec-Fetch-Dest: document +// User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) +// AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15 +// Upgrade-Insecure-Requests: 1 +// Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 +// Sec-Fetch-Site: none +// Sec-Fetch-Mode: navigate +// Accept-Language: en-GB,en;q=0.9 +// Priority: u=0, i +// Accept-Encoding: gzip, deflate +// Connection: keep-alive + +void print_request(const HttpRequest *__req) { + char method[10]; + http_method(__req->method, method, 10); + printf("%s %s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", method, + __req->path, __req->host, __req->sec_fetch_dest, __req->user_agent, + __req->upgrade_insecure_requests, "OK", __req->sec_fetch_site, + __req->sec_fetch_mode, __req->accept_language, + __req->accept_encoding, __req->connection); +} + +void http_request_set(HttpRequest *__req, char *key, char *value) { + if (strcmp(key, "Host")) + __req->host = value; + else if (strcmp(key, "Sec-Fetch-Dest")) + __req->sec_fetch_dest = value; + else if (strcmp(key, "User-Agent")) + __req->user_agent = value; + else if (strcmp(key, "Upgrade-Insecure-Requests")) + __req->upgrade_insecure_requests = value; + else if (strcmp(key, "Accept")) + ; + // __req->accept = value; + else if (strcmp(key, "Sec-Fetch-Site")) + __req->sec_fetch_site = value; + else if (strcmp(key, "Sec-Fetch-Mode")) + __req->sec_fetch_mode = value; + else if (strcmp(key, "Accept-Language")) + __req->accept_language = value; + else if (strcmp(key, "Accept-Encoding")) + __req->accept_encoding = value; + else if (strcmp(key, "Connection")) + __req->connection = value; +} + +HttpRequest *handle_request(char *__req) { + HttpRequest *request = malloc(sizeof(HttpRequest)); + unsigned int line_count = 0; + char *line_start = __req; + char *line_end; + while ((line_end = strchr(line_start, '\n')) != NULL) { + line_count++; + size_t l_length = line_end - line_start; + char *line = malloc(sizeof(char) * l_length); + if (line == NULL) + return NULL; + + strncpy(line, line_start, l_length); + line[l_length] = 0; + if (line_count == 1) { + char method[10]; + char *path = malloc(sizeof(char) * 1024); + if (sscanf(line, "%s %s", method, path) != 3) { + free(path); + return NULL; + } + printf("%s", path); + request->method = get_http_method(method); + request->path = path; + } else { + char *key = malloc(sizeof(char) * 20); + char *value = malloc(sizeof(char) * 256); + if (sscanf(line, "%s: %s", key, value) == 2) { + http_request_set(request, key, value); + } + free(key); + } + // TODO: Analyze line + free(line); + line_start = line_end + 1; + } + + return request; +} diff --git a/http/http_request.h b/http/http_request.h new file mode 100644 index 0000000..c5cc10e --- /dev/null +++ b/http/http_request.h @@ -0,0 +1,24 @@ +#ifndef HTTP_REQUEST_H +#define HTTP_REQUEST_H + +#include "http_content_type.h" +#include "http_method.h" +typedef struct { + HttpMethod method; + char *path; + char *host; + char *sec_fetch_dest; + char *user_agent; + char *upgrade_insecure_requests; + HttpContentType *accept; + char *sec_fetch_site; + char *sec_fetch_mode; + char *accept_language; + char *accept_encoding; + char *connection; +} HttpRequest; + +HttpRequest *handle_request(char *__req); +void print_request(const HttpRequest *__req); + +#endif diff --git a/http/http_response.c b/http/http_response.c index 6a8c86d..61fae97 100644 --- a/http/http_response.c +++ b/http/http_response.c @@ -1,8 +1,12 @@ #include "http_content_type.h" #include "http_response.h" #include "http_status.h" +#include #include +#include #include +#include +#include bool construct_response(HttpResponse __res, char *out) { unsigned long length; @@ -27,8 +31,61 @@ bool construct_response(HttpResponse __res, char *out) { return true; } -void http_respond(HttpResponse __res) { +void http_respond(HttpResponse __res, int clientfd) { char response[BUFSIZ]; // TODO: Handle return construct_response(__res, response); + + send(clientfd, response, strlen(response), 0); +} + +char *read_file(const char *__path) { + if (access(__path, F_OK) != 0) { + return NULL; + } + + FILE *f = fopen(__path, "r"); + if (f == NULL) { + return NULL; + } + fseek(f, 0, SEEK_END); + size_t length = ftell(f); + rewind(f); + + char *content = malloc(length * sizeof(char)); + + if (content == NULL) { + fclose(f); + return NULL; + } + + size_t bytesRead = fread(content, sizeof(char), length, f); + content[bytesRead] = 0; + + fclose(f); + + return content; +} + +HttpResponse *from_file(const char *__path) { + char *content = read_file(__path); + if (content == NULL) + return NULL; + + HttpResponse response = {.status_code = HTTP_OK, + .content_length = strlen(content), + .content_type = HTTP_CT_HTML, + .body = content}; + + HttpResponse *res = malloc(sizeof(response)); + *res = response; + + return res; +} + +void free_response(HttpResponse *__res) { + if (__res->body != NULL) + free(__res->body); + + free(__res); } diff --git a/http/http_response.h b/http/http_response.h index 8671210..a0d7cef 100644 --- a/http/http_response.h +++ b/http/http_response.h @@ -15,4 +15,9 @@ typedef struct { bool construct_response(HttpResponse __res, char *out); +void http_respond(HttpResponse __res, int clientfd); +char *read_file(const char *__path); +HttpResponse *from_file(const char *__path); +void free_response(HttpResponse *__res); + #endif diff --git a/http/http_status.c b/http/http_status.c index 775237f..ee3be72 100644 --- a/http/http_status.c +++ b/http/http_status.c @@ -4,259 +4,259 @@ void http_status_message(HttpStatus __status, char *msg, size_t __size) { switch (__status) { case HTTP_CONTINUE: { - char http_continue[] = "Continue"; + char http_continue[] = "CONTINUE"; strlcpy(msg, http_continue, __size); } break; case HTTP_SWITCHING_PROTOCOLS: { - char http_switching_protocols[] = "Switching Protocols"; + char http_switching_protocols[] = "SWITCHING PROTOCOLS"; strlcpy(msg, http_switching_protocols, __size); } break; case HTTP_PROCESSING: { - char http_processing[] = "Processing"; + char http_processing[] = "PROCESSING"; strlcpy(msg, http_processing, __size); } break; case HTTP_EARLY_HINTS: { - char http_early_hints[] = "Early Hints"; + char http_early_hints[] = "EARLY HINTS"; strlcpy(msg, http_early_hints, __size); } break; case HTTP_OK: { - char http_ok[] = "Ok"; + char http_ok[] = "OK"; strlcpy(msg, http_ok, __size); } break; case HTTP_CREATED: { - char http_created[] = "Created"; + char http_created[] = "CREATED"; strlcpy(msg, http_created, __size); } break; case HTTP_ACCEPTED: { - char http_accepted[] = "Accepted"; + char http_accepted[] = "ACCEPTED"; strlcpy(msg, http_accepted, __size); } break; case HTTP_NON_AUTHORITATIVE_INFORMATION: { char http_non_authoritative_information[] = - "Non Authoritative Information"; + "NON AUTHORITATIVE INFORMATION"; strlcpy(msg, http_non_authoritative_information, __size); } break; case HTTP_NO_CONTENT: { - char http_no_content[] = "No Content"; + char http_no_content[] = "NO CONTENT"; strlcpy(msg, http_no_content, __size); } break; case HTTP_RESET_CONTENT: { - char http_reset_content[] = "Reset Content"; + char http_reset_content[] = "RESET CONTENT"; strlcpy(msg, http_reset_content, __size); } break; case HTTP_PARTIAL_CONTENT: { - char http_partial_content[] = "Partial Content"; + char http_partial_content[] = "PARTIAL CONTENT"; strlcpy(msg, http_partial_content, __size); } break; case HTTP_MULTI_STATUS: { - char http_multi_status[] = "Multi Status"; + char http_multi_status[] = "MULTI STATUS"; strlcpy(msg, http_multi_status, __size); } break; case HTTP_ALREADY_REPORTED: { - char http_already_reported[] = "Already Reported"; + char http_already_reported[] = "ALREADY REPORTED"; strlcpy(msg, http_already_reported, __size); } break; case HTTP_IM_USED: { - char http_im_used[] = "Im Used"; + char http_im_used[] = "IM USED"; strlcpy(msg, http_im_used, __size); } break; case HTTP_MULTIPLE_CHOICES: { - char http_multiple_choices[] = "Multiple Choices"; + char http_multiple_choices[] = "MULTIPLE CHOICES"; strlcpy(msg, http_multiple_choices, __size); } break; case HTTP_MOVED_PERMANENTLY: { - char http_moved_permanently[] = "Moved Permanently"; + char http_moved_permanently[] = "MOVED PERMANENTLY"; strlcpy(msg, http_moved_permanently, __size); } break; case HTTP_FOUND: { - char http_found[] = "Found"; + char http_found[] = "FOUND"; strlcpy(msg, http_found, __size); } break; case HTTP_SEE_OTHER: { - char http_see_other[] = "See Other"; + char http_see_other[] = "SEE OTHER"; strlcpy(msg, http_see_other, __size); } break; case HTTP_NOT_MODIFIED: { - char http_not_modified[] = "Not Modified"; + char http_not_modified[] = "NOT MODIFIED"; strlcpy(msg, http_not_modified, __size); } break; case HTTP_USE_PROXY: { - char http_use_proxy[] = "Use Proxy"; + char http_use_proxy[] = "USE PROXY"; strlcpy(msg, http_use_proxy, __size); } break; case HTTP_TEMPORARY_REDIRECT: { - char http_temporary_redirect[] = "Temporary Redirect"; + char http_temporary_redirect[] = "TEMPORARY REDIRECT"; strlcpy(msg, http_temporary_redirect, __size); } break; case HTTP_PERMANENT_REDIRECT: { - char http_permanent_redirect[] = "Permanent Redirect"; + char http_permanent_redirect[] = "PERMANENT REDIRECT"; strlcpy(msg, http_permanent_redirect, __size); } break; case HTTP_BAD_REQUEST: { - char http_bad_request[] = "Bad Request"; + char http_bad_request[] = "BAD REQUEST"; strlcpy(msg, http_bad_request, __size); } break; case HTTP_UNAUTHORIZED: { - char http_unauthorized[] = "Unauthorized"; + char http_unauthorized[] = "UNAUTHORIZED"; strlcpy(msg, http_unauthorized, __size); } break; case HTTP_PAYMENT_REQUIRED: { - char http_payment_required[] = "Payment Required"; + char http_payment_required[] = "PAYMENT REQUIRED"; strlcpy(msg, http_payment_required, __size); } break; case HTTP_FORBIDDEN: { - char http_forbidden[] = "Forbidden"; + char http_forbidden[] = "FORBIDDEN"; strlcpy(msg, http_forbidden, __size); } break; case HTTP_NOT_FOUND: { - char http_not_found[] = "Not Found"; + char http_not_found[] = "NOT FOUND"; strlcpy(msg, http_not_found, __size); } break; case HTTP_METHOD_NOT_ALLOWED: { - char http_method_not_allowed[] = "Method Not Allowed"; + char http_method_not_allowed[] = "METHOD NOT ALLOWED"; strlcpy(msg, http_method_not_allowed, __size); } break; case HTTP_NOT_ACCEPTABLE: { - char http_not_acceptable[] = "Not Acceptable"; + char http_not_acceptable[] = "NOT ACCEPTABLE"; strlcpy(msg, http_not_acceptable, __size); } break; case HTTP_PROXY_AUTHENTICATION_REQUIRED: { char http_proxy_authentication_required[] = - "Proxy Authentication Required"; + "PROXY AUTHENTICATION REQUIRED"; strlcpy(msg, http_proxy_authentication_required, __size); } break; case HTTP_REQUEST_TIMEOUT: { - char http_request_timeout[] = "Request Timeout"; + char http_request_timeout[] = "REQUEST TIMEOUT"; strlcpy(msg, http_request_timeout, __size); } break; case HTTP_CONFLICT: { - char http_conflict[] = "Conflict"; + char http_conflict[] = "CONFLICT"; strlcpy(msg, http_conflict, __size); } break; case HTTP_GONE: { - char http_gone[] = "Gone"; + char http_gone[] = "GONE"; strlcpy(msg, http_gone, __size); } break; case HTTP_LENGTH_REQUIRED: { - char http_length_required[] = "Length Required"; + char http_length_required[] = "LENGTH REQUIRED"; strlcpy(msg, http_length_required, __size); } break; case HTTP_PRECONDITION_FAILED: { - char http_precondition_failed[] = "Precondition Failed"; + char http_precondition_failed[] = "PRECONDITION FAILED"; strlcpy(msg, http_precondition_failed, __size); } break; case HTTP_PAYLOAD_TOO_LARGE: { - char http_payload_too_large[] = "Payload Too Large"; + char http_payload_too_large[] = "PAYLOAD TOO LARGE"; strlcpy(msg, http_payload_too_large, __size); } break; case HTTP_URI_TOO_LONG: { - char http_uri_too_long[] = "Uri Too Long"; + char http_uri_too_long[] = "URI TOO LONG"; strlcpy(msg, http_uri_too_long, __size); } break; case HTTP_UNSUPPORTED_MEDIA_TYPE: { - char http_unsupported_media_type[] = "Unsupported Media Type"; + char http_unsupported_media_type[] = "UNSUPPORTED MEDIA TYPE"; strlcpy(msg, http_unsupported_media_type, __size); } break; case HTTP_RANGE_NOT_SATISFIABLE: { - char http_range_not_satisfiable[] = "Range Not Satisfiable"; + char http_range_not_satisfiable[] = "RANGE NOT SATISFIABLE"; strlcpy(msg, http_range_not_satisfiable, __size); } break; case HTTP_EXPECTATION_FAILED: { - char http_expectation_failed[] = "Expectation Failed"; + char http_expectation_failed[] = "EXPECTATION FAILED"; strlcpy(msg, http_expectation_failed, __size); } break; case HTTP_IM_A_TEAPOT: { - char http_im_a_teapot[] = "Im A Teapot"; + char http_im_a_teapot[] = "IM A TEAPOT"; strlcpy(msg, http_im_a_teapot, __size); } break; case HTTP_MISDIRECTED_REQUEST: { - char http_misdirected_request[] = "Misdirected Request"; + char http_misdirected_request[] = "MISDIRECTED REQUEST"; strlcpy(msg, http_misdirected_request, __size); } break; case HTTP_UNPROCESSABLE_ENTITY: { - char http_unprocessable_entity[] = "Unprocessable Entity"; + char http_unprocessable_entity[] = "UNPROCESSABLE ENTITY"; strlcpy(msg, http_unprocessable_entity, __size); } break; case HTTP_LOCKED: { - char http_locked[] = "Locked"; + char http_locked[] = "LOCKED"; strlcpy(msg, http_locked, __size); } break; case HTTP_FAILED_DEPENDENCY: { - char http_failed_dependency[] = "Failed Dependency"; + char http_failed_dependency[] = "FAILED DEPENDENCY"; strlcpy(msg, http_failed_dependency, __size); } break; case HTTP_TOO_EARLY: { - char http_too_early[] = "Too Early"; + char http_too_early[] = "TOO EARLY"; strlcpy(msg, http_too_early, __size); } break; case HTTP_UPGRADE_REQUIRED: { - char http_upgrade_required[] = "Upgrade Required"; + char http_upgrade_required[] = "UPGRADE REQUIRED"; strlcpy(msg, http_upgrade_required, __size); } break; case HTTP_PRECONDITION_REQUIRED: { - char http_precondition_required[] = "Precondition Required"; + char http_precondition_required[] = "PRECONDITION REQUIRED"; strlcpy(msg, http_precondition_required, __size); } break; case HTTP_TOO_MANY_REQUESTS: { - char http_too_many_requests[] = "Too Many Requests"; + char http_too_many_requests[] = "TOO MANY REQUESTS"; strlcpy(msg, http_too_many_requests, __size); } break; case HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE: { char http_request_header_fields_too_large[] = - "Request Header Fields Too Large"; + "REQUEST HEADER FIELDS TOO LARGE"; strlcpy(msg, http_request_header_fields_too_large, __size); } break; case HTTP_UNAVAILABLE_FOR_LEGAL_REASONS: { char http_unavailable_for_legal_reasons[] = - "Unavailable For Legal Reasons"; + "UNAVAILABLE FOR LEGAL REASONS"; strlcpy(msg, http_unavailable_for_legal_reasons, __size); } break; case HTTP_INTERNAL_SERVER_ERROR: { - char http_internal_server_error[] = "Internal Server Error"; + char http_internal_server_error[] = "INTERNAL SERVER ERROR"; strlcpy(msg, http_internal_server_error, __size); } break; case HTTP_NOT_IMPLEMENTED: { - char http_not_implemented[] = "Not Implemented"; + char http_not_implemented[] = "NOT IMPLEMENTED"; strlcpy(msg, http_not_implemented, __size); } break; case HTTP_BAD_GATEWAY: { - char http_bad_gateway[] = "Bad Gateway"; + char http_bad_gateway[] = "BAD GATEWAY"; strlcpy(msg, http_bad_gateway, __size); } break; case HTTP_SERVICE_UNAVAILABLE: { - char http_service_unavailable[] = "Service Unavailable"; + char http_service_unavailable[] = "SERVICE UNAVAILABLE"; strlcpy(msg, http_service_unavailable, __size); } break; case HTTP_GATEWAY_TIMEOUT: { - char http_gateway_timeout[] = "Gateway Timeout"; + char http_gateway_timeout[] = "GATEWAY TIMEOUT"; strlcpy(msg, http_gateway_timeout, __size); } break; case HTTP_HTTP_VERSION_NOT_SUPPORTED: { - char http_http_version_not_supported[] = "Http Version Not Supported"; + char http_http_version_not_supported[] = "HTTP VERSION NOT SUPPORTED"; strlcpy(msg, http_http_version_not_supported, __size); } break; case HTTP_VARIANT_ALSO_NEGOTIATES: { - char http_variant_also_negotiates[] = "Variant Also Negotiates"; + char http_variant_also_negotiates[] = "VARIANT ALSO NEGOTIATES"; strlcpy(msg, http_variant_also_negotiates, __size); } break; case HTTP_INSUFFICIENT_STORAGE: { - char http_insufficient_storage[] = "Insufficient Storage"; + char http_insufficient_storage[] = "INSUFFICIENT STORAGE"; strlcpy(msg, http_insufficient_storage, __size); } break; case HTTP_LOOP_DETECTED: { - char http_loop_detected[] = "Loop Detected"; + char http_loop_detected[] = "LOOP DETECTED"; strlcpy(msg, http_loop_detected, __size); } break; case HTTP_NOT_EXTENDED: { - char http_not_extended[] = "Not Extended"; + char http_not_extended[] = "NOT EXTENDED"; strlcpy(msg, http_not_extended, __size); } break; case HTTP_NETWORK_AUTHENTICATION_REQUIRED: { char http_network_authentication_required[] = - "Network Authentication Required"; + "NETWORK AUTHENTICATION REQUIRED"; strlcpy(msg, http_network_authentication_required, __size); } break; } diff --git a/index.html b/index.html new file mode 100644 index 0000000..e3fc74f --- /dev/null +++ b/index.html @@ -0,0 +1,14 @@ + + + + + + + cweb + + + + Hello, World! + + + diff --git a/main.c b/main.c index 0e8109a..3787018 100644 --- a/main.c +++ b/main.c @@ -1,19 +1,65 @@ +#include "http/http_request.h" #include "http/http_response.h" -#include "http/http_status.h" +#include #include +#include #include +#include +#include int main() { - char body[BUFSIZ] = "

Bonsoir

"; - HttpResponse response = {.status_code = HTTP_OK, - .content_type = HTTP_CT_HTML, - .content_length = strlen(body), - .body = body}; + const int PORT = 8080; - char out[BUFSIZ]; - construct_response(response, out); + int serverfd, clientfd; + ssize_t valread; + + struct sockaddr_in address; + int opt = 1; + socklen_t addrlen = sizeof(address); + char request[BUFSIZ] = {0}; + + if ((serverfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("socket failed"); + exit(EXIT_FAILURE); + } + + // Forcefully attaching socket to the port 8080 + if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) { + perror("setsockopt"); + exit(EXIT_FAILURE); + } + address.sin_family = AF_INET; + address.sin_addr.s_addr = INADDR_ANY; + address.sin_port = htons(PORT); + + if (bind(serverfd, (struct sockaddr *)&address, sizeof(address)) < 0) { + perror("bind failed"); + exit(EXIT_FAILURE); + } + if (listen(serverfd, 3) < 0) { + perror("listen"); + exit(EXIT_FAILURE); + } + if ((clientfd = accept(serverfd, (struct sockaddr *)&address, &addrlen)) < + 0) { + perror("accept"); + exit(EXIT_FAILURE); + } + valread = read(clientfd, request, + 1024 - 1); // subtract 1 for the null + // terminator at the end + HttpRequest *req = handle_request(request); + // print_request(req); + HttpResponse *res = from_file("./index.html"); + http_respond(*res, clientfd); + free_response(res); + printf("Hello message sent\n"); + + // closing the connected socket + close(clientfd); + // closing the listening socket + close(clientfd); - printf("%s", out); return 0; } diff --git a/premake5.lua b/premake5.lua new file mode 100644 index 0000000..773f41c --- /dev/null +++ b/premake5.lua @@ -0,0 +1,28 @@ +workspace "CWeb" +configurations { "Debug", "Release" } + +project "CWebLibrary" +kind "StaticLib" +language "C" +targetdir "bin/%{cfg.buildcfg}" + +files { + "http/*.c", + "http/*.h" +} + +project "cweb" +kind "ConsoleApp" +language "C" +targetdir "bin/%{cfg.buildcfg}" + +files { "main.c" } + +includedirs { "http" } +links { "CWebLibrary" } + +filter "configurations:Debug" +symbols "On" + +filter "configurations:Release" +optimize "On"