diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..e57e5af --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,69 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug webserv", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/build/webserv", + "args": ["${workspaceFolder}/config/default.conf"], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "preLaunchTask": "Build Debug", + "miDebuggerPath": "/usr/bin/gdb", + "internalConsoleOptions": "openOnSessionStart" + }, + { + "name": "Debug webserv (ASAN)", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/build/webserv", + "args": ["${workspaceFolder}/config/default.conf"], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [ + { + "name": "ASAN_OPTIONS", + "value": "abort_on_error=1:detect_leaks=1:check_initialization_order=1" + } + ], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "preLaunchTask": "Build ASAN", + "miDebuggerPath": "/usr/bin/gdb", + "internalConsoleOptions": "openOnSessionStart" + }, + { + "name": "Launch Release", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/build/webserv", + "args": ["${workspaceFolder}/config/default.conf"], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "preLaunchTask": "Build Release", + "miDebuggerPath": "/usr/bin/gdb", + "internalConsoleOptions": "openOnSessionStart" + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a232413 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,45 @@ +{ + "cmake.buildTypes": [ + { + "name": "Debug", + "displayName": "Debug", + "description": "Debug build with symbols and no optimization", + "buildType": "Debug" + }, + { + "name": "Release", + "displayName": "Release", + "description": "Optimized release build", + "buildType": "Release" + }, + { + "name": "ASAN", + "displayName": "AddressSanitizer", + "description": "Debug build with AddressSanitizer", + "buildType": "ASAN" + } + ], + "cmake.defaultVariants": { + "buildType": { + "default": "Release", + "description": "The build type", + "choices": { + "debug": { + "short": "Debug", + "long": "Debug build with symbols", + "buildType": "Debug" + }, + "release": { + "short": "Release", + "long": "Optimized release build", + "buildType": "Release" + }, + "asan": { + "short": "ASAN", + "long": "AddressSanitizer build", + "buildType": "ASAN" + } + } + } + } +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..d3c7b17 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,95 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Build All", + "type": "shell", + "command": "make", + "args": ["all"], + "group": { + "kind": "build", + "isDefault": true + }, + "problemMatcher": ["$gcc"], + "detail": "Build all targets (release, debug, asan)" + }, + { + "label": "Build Release", + "type": "shell", + "command": "make", + "args": ["release"], + "group": "build", + "problemMatcher": ["$gcc"], + "detail": "Build release target" + }, + { + "label": "Build Debug", + "type": "shell", + "command": "make", + "args": ["debug"], + "group": "build", + "problemMatcher": ["$gcc"], + "detail": "Build debug target" + }, + { + "label": "Build ASAN", + "type": "shell", + "command": "make", + "args": ["asan"], + "group": "build", + "problemMatcher": ["$gcc"], + "detail": "Build AddressSanitizer target" + }, + { + "label": "Run Release", + "type": "shell", + "command": "make", + "args": ["run_release"], + "group": "test", + "dependsOn": "Build Release", + "detail": "Build and run release version" + }, + { + "label": "Run Debug", + "type": "shell", + "command": "make", + "args": ["run_debug"], + "group": "test", + "dependsOn": "Build Debug", + "detail": "Build and run debug version" + }, + { + "label": "Run ASAN", + "type": "shell", + "command": "make", + "args": ["run_asan"], + "group": "test", + "dependsOn": "Build ASAN", + "detail": "Build and run AddressSanitizer version" + }, + { + "label": "Clean", + "type": "shell", + "command": "make", + "args": ["clean"], + "group": "build", + "detail": "Clean build artifacts" + }, + { + "label": "Full Clean", + "type": "shell", + "command": "make", + "args": ["fclean"], + "group": "build", + "detail": "Remove build directory completely" + }, + { + "label": "Rebuild", + "type": "shell", + "command": "make", + "args": ["re"], + "group": "build", + "detail": "Full clean and rebuild" + } + ] +} diff --git a/CMakeLists.txt b/CMakeLists.txt index d3f984d..bf17ce3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,15 @@ if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() +# Define available build types for IDE +set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" + "Release" + "ASAN" + "RelWithDebInfo" + "MinSizeRel" +) + message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") # Set build flags for different build types diff --git a/Makefile b/Makefile index 9be1db8..1afd9c4 100644 --- a/Makefile +++ b/Makefile @@ -1,87 +1,51 @@ -# Compiler and flags -CXX = c++ -CXXFLAGS = -Wall -Wextra -Werror -std=c++20 -MMD -MP - -# Build type (default to debug) -BUILD_TYPE ?= debug - -# Build-specific flags -ifeq ($(BUILD_TYPE), release) - CXXFLAGS += -O3 -DNDEBUG - BUILD_SUFFIX = release -else ifeq ($(BUILD_TYPE), asan) - CXXFLAGS += -g -O1 -fsanitize=address -fno-omit-frame-pointer - BUILD_SUFFIX = asan -else - CXXFLAGS += -g -O0 -DDEBUG - BUILD_SUFFIX = debug -endif - -# Directories -SRCDIR = webserv -BUILDDIR = build/$(BUILD_SUFFIX) -OBJDIR = $(BUILDDIR)/obj - -# Target executable -NAME = $(BUILDDIR)/webserv - -# Source files -SOURCES = $(wildcard $(SRCDIR)/*.cpp) \ - $(wildcard $(SRCDIR)/*/*.cpp) - -# Object files -OBJECTS = $(SOURCES:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o) - -# Dependency files -DEPENDS = $(OBJECTS:.o=.d) - -# Include directories -INCLUDES = -I. +# Variables +BUILD_DIR = build +CMAKE = cmake +CMAKE_BUILD = cmake --build +CMAKE_FLAGS = -DCMAKE_EXPORT_COMPILE_COMMANDS=ON +CONFIG_FILE = config/default.conf # Default target -all: $(NAME) +all: release debug asan -# Create executable -$(NAME): $(OBJECTS) - @mkdir -p $(BUILDDIR) - $(CXX) $(CXXFLAGS) $(OBJECTS) -o $(NAME) +# Configure CMake if build directory doesn't exist +$(BUILD_DIR): + $(CMAKE) -B $(BUILD_DIR) $(CMAKE_FLAGS) -# Compile source files to object files -$(OBJDIR)/%.o: $(SRCDIR)/%.cpp Makefile - @mkdir -p $(dir $@) - $(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@ +# Build targets with specific build types +release: $(BUILD_DIR) + $(CMAKE) -B $(BUILD_DIR) $(CMAKE_FLAGS) -DCMAKE_BUILD_TYPE=Release + $(CMAKE_BUILD) $(BUILD_DIR) --target webserv -# Clean object files +debug: $(BUILD_DIR) + $(CMAKE) -B $(BUILD_DIR) $(CMAKE_FLAGS) -DCMAKE_BUILD_TYPE=Debug + $(CMAKE_BUILD) $(BUILD_DIR) --target webserv + +asan: $(BUILD_DIR) + $(CMAKE) -B $(BUILD_DIR) $(CMAKE_FLAGS) -DCMAKE_BUILD_TYPE=ASAN + $(CMAKE_BUILD) $(BUILD_DIR) --target webserv + +# Run targets +run_release: release + ./$(BUILD_DIR)/webserv $(CONFIG_FILE) + +run_debug: debug + ./$(BUILD_DIR)/webserv $(CONFIG_FILE) + +run_asan: asan + ./$(BUILD_DIR)/webserv $(CONFIG_FILE) + +# Clean targets clean: - rm -rf $(OBJDIR) + @if [ -d "$(BUILD_DIR)" ]; then \ + $(CMAKE_BUILD) $(BUILD_DIR) --target clean; \ + fi -# Clean everything (object files, executable, and build directory) -fclean: clean - rm -rf $(BUILDDIR) - -# Clean all build types -fclean-all: - rm -rf build +fclean: + rm -rf $(BUILD_DIR) # Rebuild everything re: fclean all -# Run the executable (rebuild first) -run: re - ./$(NAME) - -# Build type targets -debug: - $(MAKE) BUILD_TYPE=debug - -release: - $(MAKE) BUILD_TYPE=release - -asan: - $(MAKE) BUILD_TYPE=asan - -# Phony targets -.PHONY: all clean fclean fclean-all re run debug release asan - -# Include dependency files --include $(DEPENDS) \ No newline at end of file +# Mark targets as phony +.PHONY: all release debug asan run_release run_debug run_asan clean fclean re diff --git a/Makefile.old b/Makefile.old new file mode 100644 index 0000000..9be1db8 --- /dev/null +++ b/Makefile.old @@ -0,0 +1,87 @@ +# Compiler and flags +CXX = c++ +CXXFLAGS = -Wall -Wextra -Werror -std=c++20 -MMD -MP + +# Build type (default to debug) +BUILD_TYPE ?= debug + +# Build-specific flags +ifeq ($(BUILD_TYPE), release) + CXXFLAGS += -O3 -DNDEBUG + BUILD_SUFFIX = release +else ifeq ($(BUILD_TYPE), asan) + CXXFLAGS += -g -O1 -fsanitize=address -fno-omit-frame-pointer + BUILD_SUFFIX = asan +else + CXXFLAGS += -g -O0 -DDEBUG + BUILD_SUFFIX = debug +endif + +# Directories +SRCDIR = webserv +BUILDDIR = build/$(BUILD_SUFFIX) +OBJDIR = $(BUILDDIR)/obj + +# Target executable +NAME = $(BUILDDIR)/webserv + +# Source files +SOURCES = $(wildcard $(SRCDIR)/*.cpp) \ + $(wildcard $(SRCDIR)/*/*.cpp) + +# Object files +OBJECTS = $(SOURCES:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o) + +# Dependency files +DEPENDS = $(OBJECTS:.o=.d) + +# Include directories +INCLUDES = -I. + +# Default target +all: $(NAME) + +# Create executable +$(NAME): $(OBJECTS) + @mkdir -p $(BUILDDIR) + $(CXX) $(CXXFLAGS) $(OBJECTS) -o $(NAME) + +# Compile source files to object files +$(OBJDIR)/%.o: $(SRCDIR)/%.cpp Makefile + @mkdir -p $(dir $@) + $(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@ + +# Clean object files +clean: + rm -rf $(OBJDIR) + +# Clean everything (object files, executable, and build directory) +fclean: clean + rm -rf $(BUILDDIR) + +# Clean all build types +fclean-all: + rm -rf build + +# Rebuild everything +re: fclean all + +# Run the executable (rebuild first) +run: re + ./$(NAME) + +# Build type targets +debug: + $(MAKE) BUILD_TYPE=debug + +release: + $(MAKE) BUILD_TYPE=release + +asan: + $(MAKE) BUILD_TYPE=asan + +# Phony targets +.PHONY: all clean fclean fclean-all re run debug release asan + +# Include dependency files +-include $(DEPENDS) \ No newline at end of file diff --git a/config/default.conf b/config/default.conf new file mode 100644 index 0000000..4863e6c --- /dev/null +++ b/config/default.conf @@ -0,0 +1,40 @@ +server { + listen 80; + server_name localhost; + + root /var/www/html; + index index.html index.htm; + + error_page 400 /400.html; + error_page 403 /403.html; + error_page 404 /404.html; + error_page 405 /405.html; + error_page 413 /413.html; + error_page 500 /500.html; + error_page 502 /502.html; + error_page 504 /504.html; + + client_max_body_size 1M; + + location / { + autoindex off; + index index.html; + allow_methods GET POST DELETE; + } + + location /uploads { + root /var/www/uploads; + autoindex on; + allow_methods GET POST; + } + + location /images { + root /var/www/images; + autoindex off; + index index.jpg; + allow_methods GET; + } + + cgi_pass /cgi-bin/; + cgi_ext .py .php; +} \ No newline at end of file diff --git a/webserv/ConfigManager/ConfigManager.cpp b/webserv/ConfigManager/ConfigManager.cpp new file mode 100644 index 0000000..8971f4a --- /dev/null +++ b/webserv/ConfigManager/ConfigManager.cpp @@ -0,0 +1,28 @@ +#include +#include + +ConfigManager::ConfigManager() : _initialized(false) +{ +} + +ConfigManager::~ConfigManager() +{ +} + +ConfigManager &ConfigManager::getInstance() +{ + static ConfigManager instance; + std::cout << "ConfigManager instance" << '\n'; + return instance; +} + +void ConfigManager::init(const std::string &filePath) +{ + if (_initialized) + { + throw std::runtime_error("ConfigManager is already initialized."); + } + std::cout << "Initializing ConfigManager with file: " << filePath << '\n'; + // parseConfigFile(filePath); + _initialized = true; +} \ No newline at end of file diff --git a/webserv/ConfigManager/ConfigManager.hpp b/webserv/ConfigManager/ConfigManager.hpp new file mode 100644 index 0000000..1f57d65 --- /dev/null +++ b/webserv/ConfigManager/ConfigManager.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include +#include +#include +#include + +struct LocationConfig +{ + std::string path; + bool autoIndex; + std::string indexFile; + // Add other location-specific configurations as needed +}; + +struct ServerConfig +{ + std::string host; + int port; + std::string root; + // Add other server-specific configurations as needed + std::unique_ptr> locations; +}; + +class ConfigManager +{ + public: + ConfigManager &operator=(const ConfigManager &other) = delete; + ConfigManager &&operator=(const ConfigManager &&other) = delete; + ConfigManager(const ConfigManager &other) = delete; + ConfigManager(const ConfigManager &&other) = delete; + + void init(const std::string &filePath); + static ConfigManager &getInstance(); + + private: + bool _initialized; + ConfigManager(); + ~ConfigManager(); + std::vector serverConfigs; + + // void parseConfigFile(const std::string &filePath); + // void parseServerBlock(const std::string &block); + // void parseLocationBlock(const std::string &block, ServerConfig &serverConfig); +}; \ No newline at end of file diff --git a/webserv/main.cpp b/webserv/main.cpp index 97fe900..9aa6511 100644 --- a/webserv/main.cpp +++ b/webserv/main.cpp @@ -1,7 +1,23 @@ -#include +#include -int main() +#include +#include +#include + +int main(int argc, char **argv) { - MyModule::doSomething(); + std::vector args; + args.reserve(static_cast(argc)); + for (int i = 0; i < argc; ++i) + { + args.emplace_back(argv[i]); + } + + if (args.size() < 2) + { + std::cerr << "Usage: " << args[0] << " \n"; + return 1; + } + ConfigManager::getInstance().init(args[1]); return 0; } \ No newline at end of file diff --git a/webserv/mymodule/MyModule.cpp b/webserv/mymodule/MyModule.cpp deleted file mode 100644 index d55afeb..0000000 --- a/webserv/mymodule/MyModule.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include - -#include - -void MyModule::doSomething() -{ - std::cout << "Doing really something!\n"; -} \ No newline at end of file diff --git a/webserv/mymodule/MyModule.hpp b/webserv/mymodule/MyModule.hpp deleted file mode 100644 index 34baab8..0000000 --- a/webserv/mymodule/MyModule.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -class MyModule -{ - public: - static void doSomething(); -}; \ No newline at end of file