diff --git a/AutoindexController/AutoindexController.cpp b/AutoindexController/AutoindexController.cpp index d36556d..2d59662 100644 --- a/AutoindexController/AutoindexController.cpp +++ b/AutoindexController/AutoindexController.cpp @@ -1,33 +1,24 @@ #include "AutoindexController.hpp" -std::string - AutoindexController::getAutoIndexBody( - std::string _root, - std::string _path) -{ - FileController - _folder = FileController(_root + _path, FileController::READ); - std::stringstream - _msg_body; +std::string AutoindexController::getAutoIndexBody(std::string _root, std::string _path) { + FileController _folder = FileController(_root + _path, FileController::READ); + std::stringstream _msg_body; _msg_body << ""; _msg_body << "Index of " + _path + ""; _msg_body << ""; _msg_body << "

Index of " + _path + "


";
-	for (int _idx = 0; _idx < _folder.getFilesSize(); _idx++)
-	{
-		if (_folder.getFiles(_idx)->_name == std::string("."))
+
+	for (int _idx = 0; _idx < _folder.getFilesSize(); _idx++) {
+		if (_folder.getFiles(_idx)->name == std::string("."))
 			continue ;
-		std::string
-			_file_name;
-		if (_folder.getFiles(_idx)->_type == FileController::DIRECTORY)
-			_file_name = _folder.getFiles(_idx)->_name + std::string("/");
+		std::string _file_name;
+		if (_folder.getFiles(_idx)->type == FileController::DIRECTORY)
+			_file_name = _folder.getFiles(_idx)->name + std::string("/");
 		else
-			_file_name = _folder.getFiles(_idx)->_name;
+			_file_name = _folder.getFiles(_idx)->name;
 		std::cout << "Autoindex test : " << _file_name << std::endl;
 
-		// _msg_body << "";
-
 		_msg_body << ""));
 		_msg_body << std::right;
-		_msg_body << _folder.getFiles(_idx)->_genr_time;
+		_msg_body << _folder.getFiles(_idx)->gen_time;
 		_msg_body << std::setw(20) << std::setfill(' ');
-		if (_folder.getFiles(_idx)->_type == FileController::DIRECTORY)
+		if (_folder.getFiles(_idx)->type == FileController::DIRECTORY)
 			_msg_body << "-" << std::endl;
 		else
-			_msg_body << _folder.getFiles(_idx)->_size << std::endl;
+			_msg_body << _folder.getFiles(_idx)->size << std::endl;
 	}
 	_msg_body << "

"; diff --git a/AutoindexController/AutoindexController.hpp b/AutoindexController/AutoindexController.hpp index c20c51b..1343908 100644 --- a/AutoindexController/AutoindexController.hpp +++ b/AutoindexController/AutoindexController.hpp @@ -13,9 +13,7 @@ extern NginxConfig::GlobalConfig _config; class AutoindexController { public: - static std::string - getAutoIndexBody( - std::string root_path, std::string dir_path); + static std::string getAutoIndexBody(std::string root_path, std::string dir_path); }; #endif diff --git a/CGI/CGIData.cpp b/CGI/CGIData.cpp deleted file mode 100644 index c1c827c..0000000 --- a/CGI/CGIData.cpp +++ /dev/null @@ -1,193 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -class CGIData { - private: - char** argv; - char** envp; - int inputPair[2]; - int outputPair[2]; - int env_size; - std::string only_root; - std::string only_file; - pid_t _pid; - std::string root; - std::string query_string; - public: - CGIData() : root("Users/mac/Documents/websv/webserv/juhpark/mmm/new/cgiBinary/php-cgi"), query_string("123=abc") - { - setCGIArgv(); - setEnvp(); - for (int i = 0; i < 3; i++) - std::cout << "argv[" << i << "] :" << argv[i] << std::endl; - //환경변수가 잘들갔나 - for (int i = 0; i < env_size; i++) - std::cout << envp[i] << std::endl; - } - - ~CGIData() - { - - for (int i = 0; i < 3; i++) - delete argv[i]; - delete argv; - - for (int i = 0; i < env_size; i++) - delete envp[i]; - delete envp; - } - - - // execve 1번째 파라미터 - char* getFilePath() { return (argv[0]); } - - // execve 2번째 파라미터 - char** getArgv() { return (argv); } - - // execve 3번째 파라미터, setEnvp의 후속으로 - char **generateEnvp(std::map env) - { - char **ret = new char*[env.size() + 1]; - int i = 0; - std::map::iterator it; - env_size = env.size(); - for (it = env.begin(); it != env.end(); ++it) - { - ret[i] = new char[(it->first.length() + it->second.length() + 2)]; - strcpy(ret[i], it->first.c_str()); - strcat(ret[i], "="); - strcat(ret[i], it->second.c_str()); - i++; - } - ret[i] = NULL; - i = env_size; - return (ret); - } - - void setCGIArgv() { - this->argv = new char*[4]; - - // this->argv[0] = new char[root.size()]; - // strcpy(argv[0], root.c_str()); - this->argv[0] = new char[22]; - strcpy(argv[0], "./../cgiBinary/php-cgi"); - - this->argv[1] = new char[25]; - strcpy(argv[1], "./../cgiBinary/sample.php"); - - this->argv[2] = new char[query_string.size()]; - strcpy(argv[2], query_string.c_str()); - argv[3] = NULL; - } - - void setEnvp() { - std::map _envMap; - //cgi루트에서 파일명만 뺴고 싶다면 - size_t start = root.find_last_of("/"); - size_t finish = root.find_last_of(root); - only_file = root.substr(start + 1, finish - start); - only_root = root.substr(0, start); - //일단루트랑 파일명이랑 분리할 필요가 있음 - - // local 환경변수에 이미 존재하는 아이들 - _envMap[std::string("USER")] = std::string(std::getenv("USER")); - _envMap[std::string("PATH")] = std::string(std::getenv("PATH")); - _envMap[std::string("LANG")] = std::string(std::getenv("LANG")); - _envMap[std::string("PWD")] = std::string(std::getenv("PWD")); - // parsing으로 가져온 아이들 - // _envMap[std::string("REQUEST_METHOD")] = "GET"; - _envMap[std::string("SERVER_PROTOCOL")] = std::string("HTTP/1.1"); - _envMap[std::string("REQUEST_SCHEME")] = "GET"; - _envMap[std::string("GATEWAY_INTERFACE")] = std::string("CGI/1.1"); - // _envMap[std::string("SERVER_SOFTWARE")] = std::string("webserv/1.0"); - - _envMap[std::string("CONTENT_TYPE")] = "php-cgi"; - _envMap[std::string("CONTENT_LENGTH")] = "22"; - - _envMap[std::string("REMOTE_ADDR")] = "127.0.0.1"; // server socket addr - _envMap[std::string("SERVER_PORT")] = "4242"; // host port - _envMap[std::string("QUERY_STRING")] = query_string; - _envMap[std::string("SCRIPT_NAME")] = root; - _envMap[std::string("PATH_INFO")] = root; - - _envMap[std::string("DOCUMENT_ROOT")] = only_root; - _envMap[std::string("REQUEST_URI")] = root; - _envMap[std::string("DOCUMENT_URI")] = root; - _envMap[std::string("SCRIPT_FILENAME")] = root; - //그 이외RFC에 있는데 안들어간거 - //AUTH_TYPE ->식별자 - //PATH_TRANSLATED -> 로컬 변환값, 대충 cgi안에 있는 경로 불면 될듯한데... - //REMOTE_IDENT ->얜 안넣어도 된다고 - //REMOTE_USER ->식별자2 - //SERVER_NAME -> 얜 conf에 있는거 돚거하면 될듯 - //SERVER_SOFTWARE - - envp = generateEnvp(_envMap); - - } - - //얜 타겟 없어도 되는건가 - void run(void) - { - std::cout << "RUNRURNRURFHSDFUEWFEWFSDFSDfsd" << std::endl; - if (pipe(this->inputPair) == -1 || pipe(this->outputPair) == -1) { - std::cout << "Pipe Making Error."<inputPair[0], STDIN_FILENO) == -1) || (dup2(this->outputPair[1], STDOUT_FILENO) == -1)) { - std::cout << "duplicate File Descriptor Error." << std::endl; - exit(1); - } -// std::cerr << "222RUNRURNRURFHSDFUEWFEWFSDFSDfsd" << std::endl; - if ((close(this->inputPair[1]) == -1) || (close(this->outputPair[0]) == -1)) { - std::cout << "File Descriptor closing Error1." << std::endl;; - exit(1); - } -// std::cerr << "arg : " << argv[0] << " env : " << envp[0] << std::endl; - if (execve(this->argv[0], argv, envp) == -1) { - std::cout << "execve error" << std::endl; - //throw ErrorHandler(__FILE__, __func__, __LINE__, "execve File Descriptor Error."); - exit(1); - } - } else if (_pid > 0) { - if ((close(this->inputPair[0]) == -1) || (close(this->outputPair[1]) == -1)) { - std::cout << "File Descriptor closing Error2." << std::endl; - return ; - } - int status; - waitpid(_pid, &status, WNOHANG); - char buf[1024]; - int len = 0; - while (len == 0) - { - len = read(this->outputPair[0], buf, 1024); - if (len < 0) { - std::cout << "read error" << std::endl; - return ; - } - buf[len] = '\0'; - } - std::cout << " buf : " << buf << std::endl; - } - } - - -}; - -int main() -{ - CGIData cgi; - cgi.run(); -} diff --git a/CGI/CGIProcess.hpp b/CGI/CGIProcess.hpp index d23b820..9150be3 100644 --- a/CGI/CGIProcess.hpp +++ b/CGI/CGIProcess.hpp @@ -21,10 +21,9 @@ class CGIProcess { int env_size; std::string only_root; std::string only_file; - pid_t _pid; + pid_t pid; public: - CGIProcess(HTTPData* data) - { + CGIProcess(HTTPData* data) { setCGIArgv(data); setEnvp(data); @@ -36,13 +35,12 @@ class CGIProcess { #endif } - ~CGIProcess() - { + ~CGIProcess() { int status; - if (_pid > 0) { - waitpid(_pid, &status, 0); + if (pid > 0) { + waitpid(pid, &status, 0); if (status & 0177) { - kill(_pid, SIGTERM); + kill(pid, SIGTERM); } } for (int i = 0; i < 3; i++) @@ -54,22 +52,18 @@ class CGIProcess { delete envp; } - - // execve 1번째 파라미터 - char* getFilePath() { return (argv[0]); } - - // execve 2번째 파라미터 - char** getArgv() { return (argv); } + char* getFilePath(void) { return (argv[0]); } + char** getArgv(void) { return (argv); } + int& getInputPair(void) { return (inputPair[1]); } + int& getOutputPair(void) { return (outputPair[0]); } // execve 3번째 파라미터, setEnvp의 후속으로 - char **generateEnvp(std::map env) - { + char** generateEnvp(std::map env) { char **ret = new char*[env.size() + 1]; int i = 0; std::map::iterator it; env_size = env.size(); - for (it = env.begin(); it != env.end(); ++it) - { + for (it = env.begin(); it != env.end(); ++it) { ret[i] = new char[(it->first.length() + it->second.length() + 2)]; strcpy(ret[i], it->first.c_str()); strcat(ret[i], "="); @@ -83,8 +77,8 @@ class CGIProcess { void setCGIArgv(HTTPData* data) { this->argv = new char*[4]; - this->argv[0] = new char[data->CGI_root.size() + 1]; - strcpy(argv[0], data->CGI_root.c_str()); + this->argv[0] = new char[data->cgi_pass.size() + 1]; + strcpy(argv[0], data->cgi_pass.c_str()); // TODO // 요청으로 들어온 경로를 절대경로로 넣어줄 것 @@ -99,10 +93,10 @@ class CGIProcess { argv[3] = NULL; } - void setEnvp(HTTPData* data) { + void setEnvp(HTTPData* data) { std::map _envMap; //cgi루트에서 파일명만 뺴고 싶다면 - std::string root = data->CGI_root.substr(1, data->CGI_root.size()); + std::string root = data->cgi_pass.substr(1, data->cgi_pass.size()); size_t start = root.find_last_of("/"); size_t finish = root.find_last_of(root); only_file = root.substr(start + 1, finish - start); @@ -152,56 +146,25 @@ class CGIProcess { _envMap[key] = iter->second; } envp = generateEnvp(_envMap); - - //환경변수가 잘들갔나 - // for (std::map::iterator iter = _envMap.begin(); iter != _envMap.end(); iter++) { - // std::cout << iter->first << " = " << iter->second << std::endl; -// } - } - - //파이프는 1로 들어가서 0으로 나온다 - /* - * 파이프A[1] -----------------> 파이프A[0] - * 메인 자식 - * 파이프B[0] <----------------- 파이프B[1] - * */ - int& getInputPair(void) - { - return (inputPair[1]); - } - - int& getOutputPair(void) - { - return (outputPair[0]); } - - //얜 타겟 없어도 되는건가 - //그건 POST메소드에서 타겟이 있다면 해당 타겟을fd화 시켜서 인자로 넣으면 됨 - //킹치만 그건 없었으니... - void run(void) - { - if (pipe(this->inputPair) == -1 || pipe(this->outputPair) == -1) { + + void run(void) { + if (pipe(this->inputPair) == -1 || pipe(this->outputPair) == -1) throw ErrorHandler(__FILE__, __func__, __LINE__, "Pipe Making Error."); - } //fork - if ((_pid = fork()) < 0) { + if ((pid = fork()) < 0) throw ErrorHandler(__FILE__, __func__, __LINE__, "Process Making Error."); - } //자식 - if (_pid == 0) { - if ((dup2(this->inputPair[0], STDIN_FILENO) == -1) || (dup2(this->outputPair[1], STDOUT_FILENO) == -1)) { + if (pid == 0) { + if ((dup2(this->inputPair[0], STDIN_FILENO) == -1) || (dup2(this->outputPair[1], STDOUT_FILENO) == -1)) throw ErrorHandler(__FILE__, __func__, __LINE__, "duplicate File Descriptor Error."); - } - if ((close(this->inputPair[1]) == -1) || (close(this->outputPair[0]) == -1)) { + if ((close(this->inputPair[1]) == -1) || (close(this->outputPair[0]) == -1)) throw ErrorHandler(__FILE__, __func__, __LINE__, "File Descriptor closing Error1."); - } - if (execve(this->argv[0], argv, envp) == -1) { + if (execve(this->argv[0], argv, envp) == -1) throw ErrorHandler(__FILE__, __func__, __LINE__, "execve File Descriptor Error."); - } } else { - if ((close(this->inputPair[0]) == -1) || (close(this->outputPair[1]) == -1)) { + if ((close(this->inputPair[0]) == -1) || (close(this->outputPair[1]) == -1)) throw ErrorHandler(__FILE__, __func__, __LINE__, "File Descriptor closing Error2."); - } } } }; diff --git a/CGI/other.cpp b/CGI/other.cpp deleted file mode 100644 index 64c25e3..0000000 --- a/CGI/other.cpp +++ /dev/null @@ -1,175 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class Kqueue { - int kfd; - struct timespec pollingTime; - size_t get_events_size; - size_t set_events_size; - struct kevent* getEvent; - struct kevent* setEvent; -public: - Kqueue(size_t events_size) : get_events_size(events_size), set_events_size(0) { - // polling time = 1 sec - pollingTime.tv_sec = 1; - pollingTime.tv_nsec = 0; - getEvent = new struct kevent[events_size]; - setEvent = new struct kevent[events_size]; - kfd = kqueue(); - } - ~Kqueue() { - delete getEvent; - delete setEvent; - close(kfd); - } - size_t accessEvents() { - size_t events = kevent(kfd, setEvent, set_events_size, getEvent, get_events_size, &pollingTime); - set_events_size = 0; - return events; - } - - void addEvent(int fd, int16_t event, void* instancePointer) { - EV_SET(&setEvent[set_events_size++], fd, event, EV_ADD | EV_EOF, 0, 0, instancePointer); - } - - void removeEvent(int fd, int16_t event, void* instancePointer) { - EV_SET(&setEvent[set_events_size++], fd, event, EV_DELETE, 0, 0, instancePointer); - } - - void enableEvent(int fd, int16_t event, void* instancePointer) { - EV_SET(&setEvent[set_events_size++], fd, event, EV_ENABLE, 0, 0, instancePointer); - } - void disableEvent(int fd, int16_t event, void* instancePointer) { - EV_SET(&setEvent[set_events_size++], fd, event, EV_DISABLE, 0, 0, instancePointer); - } - void* getInstanceByEventIndex(int index) { - return getEvent[index].udata; - } - int getDataByEventIndex(int index) { - return getEvent[index].data; - } - int getFdByEventIndex(int index) { - return getEvent[index].ident; - } - bool isCloseByEventIndex(int index) { - return (getEvent[index].flags & EV_EOF); - } -}; - - -class CGISession { - private: - pid_t _pid; - int _inputStream; - int _outputStream; - std::string _path; - CGISession(); - public: - CGISession(std::string path) : _path(path), _pid(-1) {} - ~CGISession() { - } - int getInputStream(void) { return _inputStream; } - int getOutputStream(void) { return _outputStream; } - void run() { - int pairForI[2]; - int pairForO[2]; - if (pipe(pairForI) == -1 || pipe(pairForO) == -1) { - std::cout << "파이프 생성 에러~" << std::endl; - exit(-1); - } - _inputStream = pairForI[1]; - _outputStream = pairForO[0]; - if ((_pid = fork()) < 0) { - std::cout << "포크 에러~" << std::endl; - exit(-1); - } - if (_pid == 0) { - if ((dup2(pairForI[0], STDIN_FILENO) == -1) || (dup2(pairForO[1], STDOUT_FILENO) == -1)) { - std::cout << "파이프 복제 에러~" << std::endl; - exit(-1); - } - if ((close(pairForI[1]) == -1) || (close(pairForO[0]) == -1)) { - std::cout << "파이프 닫기 에러~" << std::endl; - exit(-1); - } - char* _arg[2]; - _arg[0] = new char[8]; - strcpy(_arg[0], "/bin/cat"); - _arg[1] = NULL; - if (execve(_path.c_str(), _arg, NULL) == -1) { - std::cout << "프로세스 실행 에러~" << std::endl; - exit(-1); - } - } else { - if ((close(pairForI[0]) == -1) || (close(pairForO[1]) == -1)) { - std::cout << "파이프 닫기 에러~" << std::endl; - exit(-1); - } - } - } -}; - -int main(int argc, char const *argv[]) -{ - Kqueue kq(100); - - int cnt = 10; - - CGISession cgi("/bin/cat"); // cat 명령어는 데이터를 표준입력으로 EOF를 보낸 만큼 표준출력으로 동일한 값을 출력해 줌. - cgi.run(); //wait없이 지금 시전해도 되는 이유는 어차피 아래 while문에서 이벤트를 기다리고 있기 떄문이란다 - int cgi_write_fd = cgi.getInputStream(); - int cgi_read_fd = cgi.getOutputStream(); - - kq.addEvent(cgi_write_fd, EVFILT_WRITE, NULL); - while (true) { - int events = kq.accessEvents(); - if (events) { - for (int i = 0; i < events; i++) { - std::cout << "fd : " << kq.getFdByEventIndex(i) << std::endl; - std::cout << "data : " << kq.getDataByEventIndex(i) << std::endl; - if (kq.isCloseByEventIndex(i)) { // 프로세스는 데이터를 다 전송하면 close()를 하기 때문에 close 이벤트로 감지할 수 있음. - std::cout << "close fd " << kq.getFdByEventIndex(i) << std::endl; - close(kq.getFdByEventIndex(i)); // Close 처리를 해야 커널큐에서 제거됨 - } else { - // 보낼 때 데이터를 10번 끊어서 보냄. - if (kq.getFdByEventIndex(i) == cgi_write_fd) { - int writeLength = write(cgi_write_fd, "hello~", 6); - std::cout << "writeLength : " << writeLength << std::endl; - cnt--; - if (cnt == 0) { // 데이터를 다 보내면 fd를 닫음. - close(cgi_write_fd); - kq.addEvent(cgi_read_fd, EVFILT_READ, NULL); - } - //write 요약 - //만약에 CGI부분에 적을 게 있다면 - //fd를 받아서 - //이벤트를 wirte로 바꾸게 하여(이떄, fd는 파이프에서 가져온 Input fd) - //write 를 시전한다 - //여기 예시로는 미리 카운트를 10주어서 - //한번 write할떄마다 1을 깎게 되고 0이 되었으면 해당 fd를 닫아버리고 read로 이벤트를 바꾸게 만든다 - } else { - // 버퍼를 일부러 작은 값으로 설정해서 끊어서 받도록 유도함. - char buffer[10]; - int readLength = read(cgi_read_fd, buffer, 10); - std::cout << "readLength : " << readLength << std::endl; - std::cout << "data : " << std::string(buffer, readLength) << std::endl; - } - //만약에 CGI쪽에서 다 읽고 read로 되었다면 읽은 fd를 기준으로 가져온다 - } - } - } else { - std::cout << "waiting..." << std::endl; - } - } - return 0; -} diff --git a/CGI/ttt.sh b/CGI/ttt.sh deleted file mode 100644 index 7656a9f..0000000 --- a/CGI/ttt.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -#export CONTENT_LENGTH=30 -export CONTENT_TYPE="php-cgi" -export DOCUMENT_ROOT="Users/mac/Documents/websv/webserv/juhpark/mmm/new/cgiBinary/php-cgi" -export DOCUMENT_URI="Users/mac/Documents/websv/webserv/juhpark/mmm/new/cgiBinary/php-cgi" -#export GATEWAY_INTERFACE="CGI/1.1" -export LANG="ko_KR.UTF-8" -export PATH="usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" -export PATH_INFO="Users/mac/Documents/websv/webserv/juhpark/mmm/new/cgiBinary/php-cgi" -export PWD="Users/mac/Documents/websv/webserv/juhpark/mmm/new/CGI" -export QUERY_STRING="123=abc" -export REMOTE_ADDR="127.0.0.1" -#export REQUEST_METHOD="GET" -export REQUEST_SCHEME="GET" -export REQUEST_URI="Users/mac/Documents/websv/webserv/juhpark/mmm/new/cgiBinary/php-cgi" -export SCRIPT_FILENAME="Users/mac/Documents/websv/webserv/juhpark/mmm/new/cgiBinary/php-cgi" -export SCRIPT_NAME="Users/mac/Documents/websv/webserv/juhpark/mmm/new/cgiBinary/php-cgi" -export SERVER_PORT=4242 -export SERVER_PROTOCOL="HTTP/1.1" -#export SERVER_SOFTWARE="webserv/1.0" -export USER="juhpark" - - -#echo "pval=1234&name=asd" | ../cgiBinary/php-cgi "val=value" -./../cgiBinary/php-cgi ./../cgiBinary/sample.php "123=abc" diff --git a/ErrorHandler/ErrorHandler.cpp b/ErrorHandler/ErrorHandler.cpp index 69be918..501f88d 100644 --- a/ErrorHandler/ErrorHandler.cpp +++ b/ErrorHandler/ErrorHandler.cpp @@ -1,45 +1,53 @@ #include "ErrorHandler.hpp" -ErrorHandler::ErrorHandler() : msg(""), tmp(-1), e_file(""), e_func("") { } +ErrorHandler::ErrorHandler() {}; +ErrorHandler::ErrorHandler(char const* file, char const* func, int line, std::string msg) + : file(file), func(func), line(line), msg(msg), level(DEFAULT) { } +ErrorHandler::ErrorHandler(char const* file, char const* func, int line, std::string msg, e_Lev level) + : file(file), func(func), line(line), msg(msg), level(level) { } +ErrorHandler::~ErrorHandler() throw() {}; -ErrorHandler::ErrorHandler(std::string wha) : msg(wha), tmp(-1), e_file(""), e_func("") { } +const char* ErrorHandler::what() const throw() { + static std::string rtn; -ErrorHandler::ErrorHandler(std::string wha, int asd) : msg(wha), tmp(asd), e_file(""), e_func("") { } + rtn += "\n\033[38;5;196m"; + rtn += "~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~\n"; + rtn += "[ERR] "; + if (level == DEFAULT) + rtn += "DEFAULT OR NOT YET : "; + if (level == CRIT) + rtn += "CRITICAL : "; + if (level == NON_CRIT) + rtn += "NON_CRITICAL : "; + rtn += "\033[38;5;220m"; + rtn += msg; + rtn += "\033[38;5;196m"; + rtn += "\n[FILE] "; + rtn += "\033[38;5;220m"; + rtn += file; + rtn += "\033[38;5;196m"; + rtn += "\n[FUNC] "; + rtn += "\033[38;5;220m"; + rtn += func; + rtn += "\033[38;5;196m"; + rtn += "\n[LINE] "; + rtn += "\033[38;5;220m"; + rtn += std::to_string(line); -ErrorHandler::~ErrorHandler() throw() { } - -//yamkim님의 것을 슬쩍 보았는데 -//에러처리에선 -//발생한 시간이랑 메세지 출력만 나와있었다 - -//에러 메세지를 만든다 -const char* ErrorHandler::what() const throw() -{ - static std::string reason; + if (errno) + { + rtn += "\n"; + //rtn += ANSI_BLU; + rtn += "[INF] "; + //rtn += ANSI_RES; + rtn += (std::strerror(errno)); + } + rtn += "\033[38;5;196m"; + rtn += "\n~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~"; + rtn += "\033[0m"; + return (rtn.c_str()); +} - reason.clear(); - reason += "\033[38;5;196m"; - reason += "ERROR! : "; - reason += msg; - /* - if (e_file && e_func) - { - reason += "file : " - reason += e_file; - reason += "\nfunc : " - reason += e_func; - } - */ - if (errno) //yamkim님의 것에선 저걸 넣었는데 read,write만 아니면 되는건가 - { - reason += "\n"; - reason += "Reason : "; - reason += "\033[38;5;220m"; - reason += (std::strerror(errno)); - } - //요 if 문은 그냥 명목상으로 만든거 - if (tmp == 0) - reason += "!"; - reason += "\033[0m"; - return (reason.c_str()); +ErrorHandler::e_Lev ErrorHandler::getLevel() const { + return level; } diff --git a/ErrorHandler/ErrorHandler.hpp b/ErrorHandler/ErrorHandler.hpp index cbff408..2c4a61b 100644 --- a/ErrorHandler/ErrorHandler.hpp +++ b/ErrorHandler/ErrorHandler.hpp @@ -1,15 +1,3 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* ErrorHandler.hpp :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: hyunja +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2022/02/15 12:19:51 by juhpark #+# #+# */ -/* Updated: 2022/03/16 21:19:25 by juhpark ### ########.fr */ -/* */ -/* ************************************************************************** */ - #ifndef ERRORHANDLER_HPP # define ERRORHANDLER_HPP @@ -17,16 +5,7 @@ # include # include -//throw ErrorHandler(__FILE__, __func__, __LINE__, "Error Message", ErrorHandler::에러의 치명도); -//요로케 던지면 됩니다 -//리펙토링으로 Error_Handler가 되려나..? - -//크게 2가지로 -//그냥 소켓만 끊는거랑 -//프로세스를 뽀개버리는 걸루 - -class ErrorHandler : public std::exception -{ +class ErrorHandler : public std::exception { public: typedef enum ErrorLevel { DEFAULT, @@ -34,70 +13,20 @@ class ErrorHandler : public std::exception NON_CRIT } e_Lev; private: - const char* _fil; - const char* _fnc; - int _lin; - std::string _msg; - e_Lev _lev; + char const* file; + char const* func; + int line; + std::string msg; + e_Lev level; public: - ErrorHandler(void) {} - - ErrorHandler(const char* _ch1, const char* _ch2, int _int, std::string _str) - : _fil(_ch1), _fnc(_ch2), _lin(_int), _msg(_str), _lev(DEFAULT) { } - - ErrorHandler(const char* _ch1, const char* _ch2, int _int, std::string _str, ErrorHandler::e_Lev _level) - : _fil(_ch1), _fnc(_ch2), _lin(_int), _msg(_str), _lev(_level) { } - - virtual ~ErrorHandler() throw() { } - - e_Lev getLevel() const { return(_lev); } - - std::string getMsg() const { return(_msg); } - - virtual const char *what() const throw() - { - static std::string _rst; - - _rst.clear(); - _rst += "\n\033[38;5;196m"; - _rst += "~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~\n"; - _rst += "[ERR] "; - if (_lev == DEFAULT) - _rst += "DEFAULT OR NOT YET : "; - if (_lev == CRIT) - _rst += "CRITICAL : "; - if (_lev == NON_CRIT) - _rst += "NON_CRITICAL : "; - _rst += "\033[38;5;220m"; - _rst += _msg; - _rst += "\033[38;5;196m"; - _rst += "\n[FILE] "; - _rst += "\033[38;5;220m"; - _rst += _fil; - _rst += "\033[38;5;196m"; - _rst += "\n[FUNC] "; - _rst += "\033[38;5;220m"; - _rst += _fnc; - _rst += "\033[38;5;196m"; - _rst += "\n[LINE] "; - _rst += "\033[38;5;220m"; - _rst += std::to_string(_lin); + ErrorHandler(); + ErrorHandler(char const* file, char const* func, int line, std::string msg); + ErrorHandler(char const* file, char const* func, int line, std::string msg, e_Lev level); + virtual ~ErrorHandler() throw(); + const char* what() const throw(); + e_Lev getLevel() const; - //yamkim님의 것에선 저걸 넣었는데 read,write만 아니면 되는건가 - if (errno) - { - _rst += "\n"; - //_rst += ANSI_BLU; - _rst += "[INF] "; - //_rst += ANSI_RES; - _rst += (std::strerror(errno)); - } - _rst += "\033[38;5;196m"; - _rst += "\n~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~"; - _rst += "\033[0m"; - return (_rst.c_str()); - } }; #endif diff --git a/ErrorPageController/ErrorPageController.cpp b/ErrorPageController/ErrorPageController.cpp index 59d803a..8b1aec9 100644 --- a/ErrorPageController/ErrorPageController.cpp +++ b/ErrorPageController/ErrorPageController.cpp @@ -1,9 +1,64 @@ #include "ErrorPageController.hpp" +ErrorPageController::ErrorPageController(HTTPData *_data) : data(_data) {} + +std::vector + ErrorPageController::findLocation( + std::string uri) +{ + std::vector location = _config._http._server[data->server_block]._location; + std::vector::iterator it = location.begin(); + + for (it = location.begin(); it != location.end(); it++) { + if (it->_location.compare(uri) == 0) { + return (it->_error_page); + } + } + return (_config._http._server[data->server_block]._error_page); +} + std::string - ErrorPageController::getErrorBody( + ErrorPageController::findRoot( + void) +{ + std::map::iterator rootFinder; + + rootFinder = _config._http._server[data->server_block]._dir_map.find("root"); + + if (rootFinder != _config._http._server[data->server_block]._dir_map.end()) + return (rootFinder->second); + else + return ("./static_html"); +} + +std::string + ErrorPageController::findErrorPage( std::string _error_code) { + std::vector error_page = findLocation(data->uri_dir); + std::vector::iterator pagePos = find(error_page.begin(), error_page.end(), _error_code); + std::string root = findRoot(); + + for (; pagePos != error_page.end(); pagePos++) { + int finder = (*pagePos).find_last_of(".html"); + if (finder != -1 && access(((root + data->uri_dir + *pagePos).c_str()), F_OK) == 0) { + std::ifstream file((root + data->uri_dir + *pagePos).c_str()); + std::stringstream buffer; + buffer << file.rdbuf(); + return (buffer.str()); + } + } + return ("NULL"); +} + +std::string + ErrorPageController::getDefaultErrorBody(std::string _error_code) +{ + std::string ret = findErrorPage(_error_code); + + if (ret != "NULL") + return (ret); + std::stringstream _msg_body; @@ -27,4 +82,4 @@ std::string _msg_body << "\t\n"; _msg_body << ""; return (_msg_body.str()); -} \ No newline at end of file +} diff --git a/ErrorPageController/ErrorPageController.hpp b/ErrorPageController/ErrorPageController.hpp index 0be865a..3bf45f0 100644 --- a/ErrorPageController/ErrorPageController.hpp +++ b/ErrorPageController/ErrorPageController.hpp @@ -6,22 +6,43 @@ #include #include #include +#include +#include +#include +#include #include "FileController.hpp" #include "ConfigStatus.hpp" +#include "ConfigBlocks.hpp" +#include "HTTPData.hpp" extern StatusConfig _status; +extern NginxConfig::GlobalConfig + _config; class ErrorPageController { - public: - /* - 해당 디렉토리가 존재하지 않는 경우 -1 반환 - 해당 디렉토리 내 index 존재할 경우 0 반환 - 해당 디렉토리 내 index 존재하지 않는 경우, autoindex로 표시할 파일 및 폴더 수 반환 - */ - static std::string - getErrorBody( +public: + ErrorPageController( + HTTPData *data); + + std::string + getDefaultErrorBody( + std::string _error_code); + + std::vector + findLocation( + std::string uri); + + std::string + findRoot( + void); + + std::string + findErrorPage( std::string _error_code); + + private: + HTTPData *data; }; #endif \ No newline at end of file diff --git a/FileController/FileController.cpp b/FileController/FileController.cpp index 997914b..24e00d3 100644 --- a/FileController/FileController.cpp +++ b/FileController/FileController.cpp @@ -1,228 +1,163 @@ # include "FileController.hpp" -FileController::FileController( - void) -{ }; - -FileController::FileController( - std::string _tmp_path, - Mode _tmp_mode) -{ - if (_tmp_path.empty() || - setPath(_tmp_path) == -1) - { - this->_path = std::string(""); - throw ErrorHandler(__FILE__, __func__, __LINE__, - "something wrong about your path.", ErrorHandler::CRIT); +FileController::FileController(void) : fd(-1) { }; + +FileController::FileController(std::string path, Mode mode) { + if (path.empty() || setPath(path) == -1) { + this->path = std::string(""); + throw ErrorHandler(__FILE__, __func__, __LINE__, "something wrong about your path.", ErrorHandler::CRIT); } - this->_mode = _tmp_mode; - if (this->_mode == READ) - { - this->_type = checkType(_path); - if (_type == FileController::FILE) - { - _meta = getMetaData(_path); - _fd = open(_path.c_str(), O_RDONLY); + this->mode = mode; + if (this->mode == READ) { + this->type = checkType(path); + if (this->type == FileController::FILE) { + this->meta = getMetaData(path); + this->fd = open(path.c_str(), O_RDONLY); } - else if (_type == FileController::DIRECTORY) - { - _meta = getMetaData(_path); - getFilesOfFolder(_path, _files_meta); + else if (type == FileController::DIRECTORY) { + this->meta = getMetaData(path); + getFilesOfFolder(path, this->files_meta); } else - throw ErrorHandler(__FILE__, __func__, __LINE__, - "file not found.", ErrorHandler::CRIT); + throw ErrorHandler(__FILE__, __func__, __LINE__, "file not found.", ErrorHandler::CRIT); } - else - { - _type = FileController::FILE; - _fd = open(_path.c_str(), O_WRONLY | O_CREAT, S_IRWXU | S_IRWXG); + else { + this->type = FileController::FILE; + this->fd = open(path.c_str(), O_WRONLY | O_CREAT, S_IRWXU | S_IRWXG); } }; -FileController::~FileController( - void) -{ - delete _meta; - std::vector::iterator - _itr; - for (_itr = _files_meta.begin(); _itr != _files_meta.end(); ++_itr) - delete *(_itr); - if (_fd != -1) - close(_fd); +FileController::~FileController(void) { + delete this->meta; + std::vector::iterator iter; + for (iter = this->files_meta.begin(); iter != this->files_meta.end(); ++iter) + delete *(iter); + if (this->fd != -1) + close(this->fd); } -int - FileController::setPath( - std::string _tmp_path) -{ - this->_path = _tmp_path; - this->_path = toAbsPath(this->_path); - if (checkType(this->_path) == FileController::NON) +int FileController::setPath(std::string path) { + this->path = toAbsPath(path); + if (checkType(this->path) == FileController::NON) return (-1); return (0); } -std::string - FileController::getPath( - void) -{ - return (this->_path); +std::string FileController::getPath(void) { + return (this->path); } -FileController::FileMetaData* - FileController::getMetaData( - std::string _tmp_path) -{ - char - _tim_buffer[20]; - FileController::FileMetaData* - _rst = NULL; - struct stat - _buf; - struct passwd* - _u_data; - struct tm* - _tim_info; - if (stat(_tmp_path.c_str(), &_buf) == -1 || - !( S_ISREG(_buf.st_mode) || - S_ISDIR(_buf.st_mode))) +FileController::FileMetaData* FileController::getMetaData(std::string path) { + char time_str[20]; + FileController::FileMetaData* rtn; + struct stat buf; + struct passwd* u_data; + struct tm* time_info; + + if (stat(path.c_str(), &buf) == -1 || + !( S_ISREG(buf.st_mode) || + S_ISDIR(buf.st_mode))) return (NULL); - _rst = new FileController::FileMetaData(); - _u_data = getpwuid(_buf.st_uid); - _tim_info = std::localtime(&(_buf.st_mtimespec.tv_sec)); - std::strftime(_tim_buffer, 20, "%Y/%m/%d %H:%M:%S", _tim_info); + rtn = new FileController::FileMetaData(); + u_data = getpwuid(buf.st_uid); + time_info = std::localtime(&(buf.st_mtimespec.tv_sec)); + std::strftime(time_str, 20, "%Y/%m/%d %H:%M:%S", time_info); - size_t - _find = _tmp_path.rfind("/"); - if (_find == std::string::npos) - _rst->_name = _tmp_path; + size_t find = path.rfind("/"); + if (find == std::string::npos) + rtn->name = path; else - _rst->_name = _tmp_path.substr(_find + 1); - if (_u_data != NULL) - _rst->_user = std::string(_u_data->pw_name); + rtn->name = path.substr(find + 1); + if (u_data != NULL) + rtn->user = std::string(u_data->pw_name); else - _rst->_user = std::string(""); - _rst->_type = modeToType(_buf.st_mode); - _rst->_size = _buf.st_size; - _rst->_genr_time = std::string(_tim_buffer); + rtn->user = std::string(""); + rtn->type = modeToType(buf.st_mode); + rtn->size = buf.st_size; + rtn->gen_time = std::string(time_str); - return (_rst); + return (rtn); } -void - FileController::getFilesOfFolder( - std::string& _tmp_path, - std::vector& _tmp_files_meta) -{ - struct dirent* - _dirent; - DIR* _dir = opendir(_tmp_path.c_str()); - while ((_dirent = readdir(_dir)) != NULL) - { - std::string - _sub_path; - if (_tmp_path.at(_tmp_path.length() - 1) == '/') - _sub_path = _tmp_path + std::string(_dirent->d_name, _dirent->d_namlen); +void FileController::getFilesOfFolder(std::string& path, std::vector& files_meta) { + struct dirent* dirent; + DIR* dir = opendir(path.c_str()); + while ((dirent = readdir(dir)) != NULL) { + std::string sub_path; + if (path.at(path.length() - 1) == '/') + sub_path = path + std::string(dirent->d_name, dirent->d_namlen); else - _sub_path = _tmp_path + "/" + std::string(_dirent->d_name, _dirent->d_namlen); - _tmp_files_meta.push_back(getMetaData(_sub_path)); + sub_path = path + "/" + std::string(dirent->d_name, dirent->d_namlen); + files_meta.push_back(getMetaData(sub_path)); } - closedir(_dir); + closedir(dir); } -int - FileController::getFileSize( - std::string _pth) -{ - int - _siz = 0; - std::ifstream - _ifs(_pth, std::ios::in | std::ios::binary); +int FileController::getFileSize(std::string path) { + int size = 0; + std::ifstream ifs(path, std::ios::in | std::ios::binary); // @TODO : errorhandler non_crit으로 바꿔야하나? - if (_ifs.is_open() == 0) - { + if (ifs.is_open() == 0) { std::cout << "NO FILE" << std::endl; return (-1); } - _ifs.seekg(0, std::ios::end); - _siz = _ifs.tellg(); - _ifs.close(); - return (_siz); + ifs.seekg(0, std::ios::end); + size = ifs.tellg(); + ifs.close(); + return (size); } -int - FileController::getFilesSize( - void) const -{ - if (this->_mode == READ) - return (this->_files_meta.size()); +int FileController::getFilesSize(void) const { + if (this->mode == READ) + return (this->files_meta.size()); else return (-1); } -FileController::FileMetaData* - FileController::getFiles( - int _idx) const -{ - if (_idx < 0) - return (_meta); - else if (_files_meta.size() <= size_t(_idx)) +FileController::FileMetaData* FileController::getFiles(int idx) const { + if (idx < 0) + return (this->meta); + else if (this->files_meta.size() <= size_t(idx)) return (NULL); else - return (_files_meta[_idx]); + return (this->files_meta[idx]); } -FileController::Type - FileController::modeToType( - mode_t _mod) -{ - if (S_ISREG(_mod)) +FileController::Type FileController::modeToType(mode_t mode) { + if (S_ISREG(mode)) return (FILE); - else if (S_ISDIR(_mod)) + else if (S_ISDIR(mode)) return (DIRECTORY); else return (NON); } -FileController::Type - FileController::checkType( - std::string _pth) -{ - struct stat - _stat; - if (stat(_pth.c_str(), &_stat) == -1) +FileController::Type FileController::checkType(std::string path) { + struct stat stat_tmp; + if (stat(path.c_str(), &stat_tmp) == -1) return (NON); - return (modeToType(_stat.st_mode)); + return (modeToType(stat_tmp.st_mode)); } -std::string& - FileController::toAbsPath( - std::string& _pth) -{ - if (_pth.empty() == false) - if (_pth.at(0) != '/') - { - char* - _pwd = getcwd(NULL, 0); - _pth = std::string(_pwd) + "/" + _pth; - delete _pwd; +std::string& FileController::toAbsPath(std::string& path) { + if (path.empty() == false) { + if (path.at(0) != '/') { + char* pwd = getcwd(NULL, 0); + path = std::string(pwd) + "/" + path; + delete pwd; } - return (_pth); + } + return (path); } -std::string - FileController::getPrePath( - std::string _pth) -{ - std::string - _tmp = _pth; - if (_pth.substr(_pth.length() - 1, _pth.length()) == "/") - _tmp = _tmp.substr(0, _tmp.length() - 1); - std::cout << _tmp << " vs " << _pth << std::endl; +std::string FileController::getPrePath(std::string path) { + std::string tmp = path; + if (path.substr(path.length() - 1, path.length()) == "/") + tmp = tmp.substr(0, tmp.length() - 1); + std::cout << tmp << " vs " << path << std::endl; int - _idx = _tmp.find_last_of("/"); - return (_tmp.substr(0, _idx + 1)); + idx = tmp.find_last_of("/"); + return (tmp.substr(0, idx + 1)); } diff --git a/FileController/FileController.hpp b/FileController/FileController.hpp index 201a8ab..f823563 100644 --- a/FileController/FileController.hpp +++ b/FileController/FileController.hpp @@ -12,93 +12,52 @@ # include # include "ErrorHandler.hpp" -class - FileController -{ - public: - typedef enum eType - { - FILE, - DIRECTORY, - NON - } Type; - - typedef enum eMode - { - READ, - WRITE - } Mode; - - typedef struct sFileMetaData - { - std::string - _name, - _user, - _genr_time; - long - _size; - FileController::Type - _type; - } FileMetaData; +class FileController { +public: + typedef enum Type { + FILE, + DIRECTORY, + NON + } Type; + + typedef enum Mode { + READ, + WRITE + } Mode; + + typedef struct FileMetaData { + std::string name; + std::string user; + std::string gen_time; + long size; + FileController::Type type; + } FileMetaData; + +private: + int fd; + Type type; + Mode mode; + std::string path; + FileMetaData* meta; + std::vector files_meta; - private: - int - _fd; - Type - _type; - Mode - _mode; - std::string - _path; - FileMetaData* - _meta; - std::vector - _files_meta; - - static FileMetaData* - getMetaData( - std::string _tmp_path); - static inline void - getFilesOfFolder( - std::string& _tmp_path, - std::vector& _tmp_files_meta); - - public: - FileController( - void); - FileController( - std::string _tmp_path, Mode _tmp_mode); - ~FileController( - void); - - int - setPath( - std::string _tmp_path); - std::string - getPath( - void); - int - getFilesSize( - void) const; - FileMetaData* - getFiles( - int _idx) const; - - static int - getFileSize( - std::string _pth); - static inline Type - modeToType( - mode_t _mod); - static Type - checkType( - std::string _pth); - static std::string& - toAbsPath( - std::string& _pth); - static std::string - getPrePath( - std::string path); + static FileMetaData* getMetaData(std::string path); + static inline void getFilesOfFolder(std::string& path, std::vector& files_meta); + +public: + FileController(void); + FileController(std::string path, Mode mode); + ~FileController(void); + + int setPath(std::string path); + std::string getPath(void); + int getFilesSize(void) const; + FileMetaData* getFiles(int idx) const; + static int getFileSize(std::string path); + static inline Type modeToType(mode_t mode); + static Type checkType(std::string path); + static std::string& toAbsPath(std::string& path); + static std::string getPrePath(std::string path); }; #endif \ No newline at end of file diff --git a/HTTPMessageController/HTTPConnection.cpp b/HTTPMessageController/HTTPConnection.cpp index 1fb2983..c4c9f4a 100644 --- a/HTTPMessageController/HTTPConnection.cpp +++ b/HTTPMessageController/HTTPConnection.cpp @@ -1,340 +1,26 @@ #include "HTTPConnection.hpp" -extern NginxConfig::GlobalConfig _config; - -HTTPConnection::HTTPConnection( - int fd, - int block, - int server_port, - std::string client_ip, - std::string client_port, - std::string host_ip, - std::string host_port) +HTTPConnection::HTTPConnection(int fd, int block, SocketController* socket) { - seq = REQUEST; - socket_fd = fd; - http_data = new HTTPData(block, server_port, client_ip); - http_data->client_ip = client_ip; - http_data->client_port = client_port; - http_data->host_ip = host_ip; - http_data->host_port = host_port; - request_message = new RequestMessage(http_data); - response_message = new ResponseMessage(http_data); - if (_config._http._server[ - this->http_data->server_block]._dir_map[ - "client_max_body_size"].empty() == true) - limit_size = 1024; - else - limit_size = - atoi( - _config._http._server[ - this->http_data->server_block]._dir_map[ - "client_max_body_size"].c_str()); - current_size = 0; -} - -HTTPConnection::~HTTPConnection() { - if (this->http_data->isCGI == true) - delete cgi_process; - delete request_message; - delete response_message; - delete http_data; - close(socket_fd); -} + seq = HTTP_READ; + socket_fd = fd; -void HTTPConnection::killConnection(void* hc) { - delete reinterpret_cast(hc); -} -int HTTPConnection::getServerBlock(void) { return (this->http_data->getSBlock()); } -int HTTPConnection::getFileFd(void) { return (this->file_fd); } -int HTTPConnection::getSocketFd(void) { return (this->socket_fd); } -int HTTPConnection::getCgiOutputFd(void) { return (this->cgi_output_fd); } -int HTTPConnection::getCgiInputFd(void) { return (this->cgi_input_fd); } + int server_port = (int)ntohs((socketController->getServerAddr()).sin_port); + std::string client_ip = std::string(inet_ntoa((socketController->getServerAddr()).sin_addr)); + std::string host_ip = std::string(inet_ntoa((socketController->getClientAddr()).sin_addr)); + std::stringstream clientPortString; + std::stringstream hostPortString; + clientPortString << ntohs(socketController->getServerAddr().sin_port); + hostPortString << ntohs(socketController->getClientAddr().sin_port); -int HTTPConnection::run() { - std::cout << "sequence : " << seq << std::endl; - if (seq == REQUEST) { - std::cout << "[REQUEST]\n"; - readLength = read(socket_fd, buffer, BUF_SIZ-1); - buffer[readLength] = '\0'; - if (readLength > 0) - request_message->setMessage(buffer); - int request_result = request_message->parsingRequestMessage(); - if (request_result == RequestMessage::ERROR) - { - std::string - _msg_body = ErrorPageController::getErrorBody(request_message->error_code); - http_data->str_buffer = "Content-Length: "; - std::stringstream ss; - ss << _msg_body.size(); - http_data->str_buffer += ss.str(); - http_data->str_buffer += "\r\nContent-Type: text/html\r\n\r\n"; - http_data->str_buffer += _msg_body; - http_data->is_buffer_write = true; - seq = REQUEST_TO_RESPONSE; - } - else if (request_result == RequestMessage::FINISH_PARSE) { - std::map::iterator res; - if ((res = this->http_data->header_field.find("Connection")) != this->http_data->header_field.end()) - if (res->second == "keep-alive") - keep_alive = true; - if (this->http_data->isCGI == true) { - cgi_process = new CGIProcess(http_data); - cgi_process->run(); - cgi_input_fd = cgi_process->getInputPair(); - cgi_output_fd = cgi_process->getOutputPair(); - if (fcntl(cgi_input_fd, F_SETFL, O_NONBLOCK) == -1 || - fcntl(cgi_output_fd, F_SETFL, O_NONBLOCK) == -1) - throw ErrorHandler(__FILE__, __func__, __LINE__, - "something wrong with fd. check the file exists : ?", ErrorHandler::NON_CRIT); - } - if (http_data->header_field.find("Content-Length") != http_data->header_field.end() && - (http_data->header_field["Content-Length"] != "0" && http_data->header_field["Content-Length"] != "")) - seq = READY_TO_MESSAGE_BODY; - else - seq = REQUEST_TO_RESPONSE; - if (http_data->header_field["Content-Length"].empty() == false && - atoi(http_data->header_field["Content-Length"].c_str()) > limit_size) - { - std::cout << "???1" << std::endl; - std::string - _msg_body = ErrorPageController::getErrorBody("413"); - http_data->str_buffer = "Content-Length: "; - std::stringstream ss; - ss << _msg_body.size(); - http_data->str_buffer += ss.str(); - http_data->str_buffer += "\r\nContent-Type: text/html\r\n\r\n"; - http_data->str_buffer += _msg_body; - seq = REQUEST_TO_RESPONSE; - } - } - else if (request_result == RequestMessage::MESSAGE_BODY) { - if (this->http_data->isCGI == true) { - cgi_process = new CGIProcess(http_data); - cgi_process->run(); - cgi_input_fd = cgi_process->getInputPair(); - cgi_output_fd = cgi_process->getOutputPair(); - if (fcntl(cgi_input_fd, F_SETFL, O_NONBLOCK) == -1 || - fcntl(cgi_output_fd, F_SETFL, O_NONBLOCK) == -1) - throw ErrorHandler(__FILE__, __func__, __LINE__, - "something wrong with fd. check the file exists : ?", ErrorHandler::NON_CRIT); - seq = READY_TO_MESSAGE_BODY; - } - else - seq = REQUEST_TO_RESPONSE; - if (http_data->header_field["Content-Length"].empty() == false && - atoi(http_data->header_field["Content-Length"].c_str()) > limit_size) - { - std::cout << "???2" << std::endl; - std::string - _msg_body = ErrorPageController::getErrorBody("413"); - http_data->str_buffer = "Content-Length: "; - std::stringstream ss; - ss << _msg_body.size(); - http_data->str_buffer += ss.str(); - http_data->str_buffer += "\r\nContent-Type: text/html\r\n\r\n"; - http_data->str_buffer += _msg_body; - seq = ERROR_WRITE; - } - } - } - else if (seq == READY_TO_MESSAGE_BODY) { - std::cout << "[READY_TO_MESSAGE_BODY]\n"; - write(cgi_input_fd, request_message->getMessage().data(), request_message->getMessage().size()); - std::stringstream ss; - ss << request_message->getMessage().size(); - if (ss.str() == http_data->header_field["Content-Length"]) - seq = BODY_TO_RESPONSE; - else - seq = MESSAGE_BODY_READ; - } - else if (seq == BODY_TO_RESPONSE) { - std::cout << "[BODY_TO_RESPONSE]\n"; - seq = REQUEST_TO_RESPONSE; - } - else if (seq == MESSAGE_BODY_READ) { - std::cout << "[MESSAGE_BODY_READ]" << std::endl; - readLength = read(socket_fd, buffer, BUF_SIZ - 1); - buffer[readLength] = '\0'; - if (readLength > 0) { -// buffer[readLength] = '\0'; - seq = MESSAGE_BODY_WRITE; - } - else { - seq = REQUEST_TO_RESPONSE; - } - } - else if (seq == MESSAGE_BODY_WRITE) { - std::cout << "[MESSAGE_BODY_WRITE]" << std::endl; - writeLength = write(cgi_input_fd, buffer, readLength); - if (writeLength == BUF_SIZ - 1) - seq = MESSAGE_BODY_READ; - else - seq = REQUEST_TO_RESPONSE; - } - else if (seq == REQUEST_TO_RESPONSE) { - std::cout << "[REQUEST_TO_RESPONSE]" << std::endl; - if (http_data->is_buffer_write == false) - response_message->setResponseMessage(); - seq = RESPONSE; - } - else if (seq == RESPONSE) { - std::cout << "RESPONSE" << std::endl; - int - write_size = ((int)response_message->getMessage().size() < BUF_SIZ ? (int)response_message->getMessage().size() : BUF_SIZ); - writeLength = write(socket_fd, response_message->getMessage().data(), write_size); - if (http_data->is_buffer_write == true) - { - size_t r = write(socket_fd, http_data->str_buffer.data(), http_data->str_buffer.size()); - std::cout << "r : " << r << std::endl; - std::cout << "buffer_size : " << http_data->str_buffer.size() << std::endl; - http_data->is_buffer_write = false; - seq = CLOSE; - } - else if (writeLength != BUF_SIZ) { - if (this->http_data->isCGI == true) { - seq = READY_TO_CGI; - } - else if (this->http_data->is_autoindex == true) { - std::string - _msg_body = AutoindexController::getAutoIndexBody(_config._http._server[1]._dir_map["root"], this->http_data->url_directory); - http_data->str_buffer = "Content-Length: "; - std::stringstream ss; - ss << _msg_body.size(); - http_data->str_buffer += ss.str(); - http_data->str_buffer += "\r\nContent-Type: text/html\r\n\r\n"; - http_data->str_buffer += _msg_body; - seq = AUTOINDEX_WRITE; - } - else { - std::string _pth = - _config._http._server[this->http_data->server_block]._dir_map["root"] + - this->http_data->uri_dir + - this->http_data->uri_file; - _pth = FileController::toAbsPath(_pth); - file_fd = open(_pth.c_str(), O_RDONLY); - if (fcntl(file_fd, F_SETFL, O_NONBLOCK) == -1) - throw ErrorHandler(__FILE__, __func__, __LINE__, - "something wrong with fd. check the file exists : \n" + _pth, ErrorHandler::NON_CRIT); - seq = READY_TO_FILE; - } - } - else - response_message->resetMessage(writeLength); - } - else if (seq == AUTOINDEX_WRITE) { - std::cout << "[AUTOINDEX_WRITE]\n"; - write(socket_fd, http_data->str_buffer.data(), http_data->str_buffer.size()); - seq = CLOSE; - } - else if (seq == ERROR_WRITE) { - // std::cout << "[ERROR_WRITE]\n"; - // write(socket_fd, http_data->str_buffer.data(), http_data->str_buffer.size()); - // seq = CLOSE; - } - else if (seq == READY_TO_CGI) { - std::cout << "[READY_TO_CGI]" << std::endl; - close(cgi_input_fd); - seq = CGI_READ; - } - else if (seq == CGI_READ) { - std::cout << "[CGI_READ]" << std::endl; - readLength = read(cgi_output_fd, buffer, BUF_SIZ - 1); - buffer[readLength] = '\0'; - seq = CGI_WRITE; - } - else if (seq == CGI_WRITE) { - std::cout << "[CGI_WRITE]" << std::endl; - if (readLength == 0) - seq = CLOSE; - else if (readLength == -1) - throw ErrorHandler(__FILE__, __func__, __LINE__, - "exit -1 replaced", ErrorHandler::CRIT); - else { - writeLength = write(socket_fd, buffer, readLength); - std::cout << "---CGI_WRITE---" << std::endl << buffer << std::endl; - if (readLength != writeLength) { - throw ErrorHandler(__FILE__, __func__, __LINE__, - "exit -1 replaced", ErrorHandler::CRIT); - }/* - if (writeLength != BUF_SIZ - 1) { - std::cout << "READ LEN : " << readLength << std::endl; - std::cout << "WRITE LEN : " << writeLength << std::endl; - std::cout << "test1" << std::endl; - close(cgi_output_fd); - seq = CLOSE; - } - else - */ - seq = CGI_READ; - } - } - else if (seq == READY_TO_FILE) { - std::cout << "[READY_TO_FILE]" << std::endl; - seq = FILE_READ; - } - else if (seq == FILE_READ) { - std::cout << "[FILE_READ]" << std::endl; - readLength = read(file_fd, buffer, BUF_SIZ); - std::cout << buffer << std::endl; - seq = FILE_WRITE; - } - else if (seq == FILE_WRITE) { - std::cout << "[FILE_WRITE]" << std::endl; - if (readLength == 0) - seq = CLOSE; - else if (readLength == -1) - throw ErrorHandler(__FILE__, __func__, __LINE__, - "exit -1 replaced", ErrorHandler::CRIT); - else { - writeLength = write(socket_fd, buffer, readLength); - if (readLength != writeLength) { - throw ErrorHandler(__FILE__, __func__, __LINE__, - "exit -1 replaced", ErrorHandler::CRIT); - } - if (writeLength != BUF_SIZ) { - close(file_fd); - seq = CLOSE; - } - else - seq = FILE_READ; - if (seq == CLOSE && keep_alive == true) - seq = RE_KEEPALIVE; - } - } - else if (seq == RE_KEEPALIVE) { - int backup_block; - int backup_port; - std::string backup_ip; - backup_block = this->http_data->server_block; - backup_port = this->http_data->server_port; - backup_ip = this->http_data->client_ip; + data = new HTTPData(block, server_port, client_ip); + request = new RequestMessage(data); + response = new ResponseMessage(data); - if (this->http_data->isCGI == true) - delete cgi_process; - delete request_message; - delete response_message; - delete http_data; - buffer[0] = '\0'; - readLength = -2; - writeLength = -2; - if (file_fd > 0) - file_fd = -2; - if (cgi_output_fd > 0) - cgi_output_fd = -2; - if (cgi_input_fd > 0) - cgi_input_fd = -2; +} - //keep_alive = false; - //다음 연결에서 keep-alive가 안되는 경우도 있다? +int HTTPConnection::run(void) { - http_data = new HTTPData(backup_block, backup_port, backup_ip); - request_message = new RequestMessage(http_data); - response_message = new ResponseMessage(http_data); - seq = REQUEST; - } - std::cout << "sequence : " << seq << std::endl; - return seq; -}; +} \ No newline at end of file diff --git a/HTTPMessageController/HTTPConnection.hpp b/HTTPMessageController/HTTPConnection.hpp index 6b2e68a..b7bb0dd 100644 --- a/HTTPMessageController/HTTPConnection.hpp +++ b/HTTPMessageController/HTTPConnection.hpp @@ -1,14 +1,17 @@ #ifndef HTTPCONNECTION_HPP # define HTTPCONNECTION_HPP -#include "ClassController.hpp" #include "HTTPData.hpp" #include "RequestMessage.hpp" #include "ResponseMessage.hpp" -#include "KernelQueueController.hpp" +#include "ClassController.hpp" +#include "ErrorPageController.hpp" #include "FileController.hpp" #include "AutoindexController.hpp" #include "ErrorPageController.hpp" +#include "SocketController.hpp" + + #include #include @@ -16,57 +19,53 @@ extern NginxConfig::GlobalConfig _config; + + class HTTPConnection : public ClassController { - public: - typedef enum e_Seq { - REQUEST, - READY_TO_MESSAGE_BODY, - MESSAGE_BODY_READ, - MESSAGE_BODY_WRITE, - REQUEST_TO_RESPONSE, - BODY_TO_RESPONSE, - RESPONSE, - READY_TO_CGI, - CGI_READ, - CGI_WRITE, - READY_TO_FILE, - FILE_READ, - FILE_WRITE, - CLOSE, - RE_KEEPALIVE, - AUTOINDEX_WRITE, - ERROR_WRITE + public: + typedef enum e_Seq { + HTTP_READ, + READY_CGI_INPUT, + READY_AUTOINDEX, + READY_REDIRECT, + READY_ERROR, + CGI_INPUT_READ, + CGI_INPUT_WRITE, + FINISH_CGI_INPUT, + CGI_GET_HEADER, + SET_RESPONSE, + WRITE_RESPONSE, + CGI_OUTPUT_READ, + CGI_OUTPUT_WRITE, + BUFFER_WRITE, + FILE_READ, + FILE_WRITE, + CLOSE } Seq; + private: + Seq seq; + + HTTPData* data; + RequestMessage* request; + ResponseMessage* response; + CGIProcess* cgi; + + + + int socket_fd; + int file_fd; + int read_len; + int write_len; + char buffer[BUF_SIZ]; + bool keep_alive; + + public: + HTTPConnection(int fd, int block, SocketController* socket); + virtual ~HTTPConnection(); + static void killConnection(void* hc); + + int run(); - private: - Seq seq; - int socket_fd; - int file_fd; - int cgi_output_fd; - int cgi_input_fd; - char buffer[BUF_SIZ]; - HTTPData* http_data; - RequestMessage* request_message; - ResponseMessage* response_message; - CGIProcess* cgi_process; - int readLength; - int writeLength; - bool keep_alive; - int current_size; - int limit_size; - - public: - HTTPConnection(int fd, int block, int server_port, std::string client_ip, std::string client_port, std::string host_ip, std::string host_port); - virtual ~HTTPConnection(); - static void killConnection(void* hc); - - int getServerBlock(void); - int getFileFd(void); - int getSocketFd(void); - int getCgiOutputFd(void); - int getCgiInputFd(void); - - int run(); }; -#endif +#endif \ No newline at end of file diff --git a/HTTPMessageController/HTTPData.cpp b/HTTPMessageController/HTTPData.cpp index 209028b..6310398 100644 --- a/HTTPMessageController/HTTPData.cpp +++ b/HTTPMessageController/HTTPData.cpp @@ -3,9 +3,14 @@ int HTTPData::getSBlock(void) { return(this->server_block); } HTTPData::HTTPData(int server_block, int server_port, std::string client_ip) { + this->status_code = 200; this->server_block = server_block; this->server_port = server_port; this->client_ip = client_ip; this->is_autoindex = false; this->is_buffer_write = false; + this->is_cgi = false; + this->is_redirect = false; + this->cgi_extension = ""; + this->cgi_pass = ""; } diff --git a/HTTPMessageController/HTTPData.hpp b/HTTPMessageController/HTTPData.hpp index a24beff..4382ec2 100644 --- a/HTTPMessageController/HTTPData.hpp +++ b/HTTPMessageController/HTTPData.hpp @@ -21,11 +21,11 @@ class HTTPData { std::string uri_file; std::string query_string; std::string file_extension; - std::string CGI_root; - std::string CGI_what; - bool isCGI; + std::string cgi_pass; + std::string cgi_extension; + double http_version; - bool is_autoindex; + std::string url_directory; // Header Field std::map header_field; @@ -37,6 +37,12 @@ class HTTPData { bool is_buffer_write; int status_code; + bool is_cgi; + bool is_autoindex; + bool is_redirect; + + int client_body_size; + int getSBlock(void); HTTPData(int server_block, int server_port, std::string client_ip); diff --git a/HTTPMessageController/RequestMessage.cpp b/HTTPMessageController/RequestMessage.cpp index 0a0310f..eb41c89 100644 --- a/HTTPMessageController/RequestMessage.cpp +++ b/HTTPMessageController/RequestMessage.cpp @@ -1,375 +1,150 @@ -#include "RequestMessage.hpp" +# include "RequestMessage.hpp" -RequestMessage::RequestMessage(HTTPData* _data) : data(_data), parsing_pointer(0), message(""), seq(START_LINE) { cgi = NULL; } +// Contructor -void RequestMessage::setMessage(char* buffer) { - std::string temp(buffer); - this->message += temp; - this->has_index = true; - return ; +RequestMessage::RequestMessage( + HTTPData* _tmp) +{ + this->_data = _tmp; + this->_parse_ptr = 0; + this->_message = ""; + this->_seq = START_LINE; + this->_has_index = false; + this->_status_code = 200; } -void RequestMessage::resetMessage() { - this->message = this->message.substr(this->parsing_pointer); - this->parsing_pointer = 0; +// Getter && Setter + +void + RequestMessage::setMessage( + char* buffer) +{ + std::string temp(buffer); + this->_message += temp; return ; } -std::string - RequestMessage::getMessage(void) +std::string + RequestMessage::getMessage( + void) { - return this->message; + return (this->_message); } -/** Header **/ +int + RequestMessage::setError( + int _arg_status_code) +{ + this->_data->status_code = _arg_status_code; + this->_seq = ERROR; + return (ERROR); +} -// message 내에 start line이 모두 담겨져있는지 확인하는 메소드 -// start line 파싱이 가능하면 true, 불가능하면 false 반환 +// parse main +int + RequestMessage::parse( + void) +{ + int + _rst; -int RequestMessage::parsingRequestMessage() { - if (this->seq == START_LINE) { - int - start_line_pos = int(this->message.find("\r\n")), - _second_space = 0; - std::string - start_line_msg = this->message.substr(0, start_line_pos); - for (int _idx=0; _idx<(int)start_line_msg.size(); _idx++) { - if (start_line_msg[_idx] == ' ') + if (this->_seq == START_LINE) + { + if (int(this->_message.find("\r\n")) != -1) + { + _rst = parseStartLine(this->_message); + if (_rst == ERROR) { - if (_second_space == 0) - _second_space = 1; - else - { - _second_space = _idx; - break; - } + } - } - if (start_line_pos != -1) { - parseStartLine(start_line_msg); - if (this->seq != ERROR) + else if (_rst == IS_CGI) { - data->url_directory = this->message.substr(0, start_line_pos).substr(data->method.length() + 1, _second_space - (data->method.length() + 1)); - resetMessage(); - this->seq = HEADER_FIELD; + } - } - } - if (this->seq == HEADER_FIELD) { - if (int(this->message.find("\r\n\r\n", 0)) != -1) { - parseHeaderField(this->message); - resetMessage(); - this->seq = MESSAGE_BODY; - } - } - if (this->seq == MESSAGE_BODY) { - if (data->header_field.find("Content-Length") != data->header_field.end() && - data->header_field["Content-Length"] != "0") { - if (int(this->message.length()) == atoi(data->header_field["Content-Length"].c_str())) { - parseMessageBody(this->message); - this->seq = FINISH_PARSE; + else if (_rst == IS_AUTOINDEX) + { + // if (this->seq != ERROR && this->has_index == false) + // { + // if (checkAutoIndex( + // _config._http._server[1]._dir_map["root"], + // this->data->url_directory) + // == 1) + // { + // data->is_autoindex = true; + // data->status_code = 200; + // } + // } } + else if (_rst == IS_REDIRECT) + { + + } + this->_seq == HEADER_FIELD; } - else - this->seq = FINISH_PARSE; } - std::cout << "request sequence : " << this->seq << std::endl; - return (this->seq); -} - -int RequestMessage::checkAutoIndex(std::string _root, std::string _path) -{ - std::string - _abs_path = _root + _path, - _abs_root = _root; - _abs_path = FileController::toAbsPath(_abs_path); - _abs_root = FileController::toAbsPath(_abs_root); - - if (FileController::checkType(_abs_path) != FileController::DIRECTORY) - return (-1); - else if (_config._http._server[1].findLocationIndexByDir(_path) != -1 && - _config._http._server[1]._location[ - _config._http._server[1].findLocationIndexByDir(_path) - ]._dir_map["autoindex"] == "on") - return (1); - else if (_config._http._server[1].findLocationIndexByDir(_path) != -1 && - _config._http._server[1]._location[ - _config._http._server[1].findLocationIndexByDir(_path) - ]._dir_map["autoindex"] == "off") - return (-1); - else + else if (this->_seq == HEADER_FIELD) { - if (_abs_path.find_last_of("/") == _abs_path.length()) - _abs_path = _abs_path.substr(0, _abs_path.length() - 1); - if (_abs_path == _abs_root) - return (-1); - else - return (checkAutoIndex(_root, FileController::getPrePath(_path))); - } -} -void RequestMessage::parseStartLine(std::string &msg) { - int start, end; - this->parseMethod(start, end, msg); - this->parseTarget(start, end, msg); - this->parseHttpVersion(start, end, msg); - this->parsing_pointer = start + 2; - if (data->uri_file.compare("") == 0) { - checkTarget(); } - if (this->seq == ERROR && this->has_index == false) + else if (this->_seq == MESSAGE_BODY) { - if (checkAutoIndex( - _config._http._server[1]._dir_map["root"], - this->data->url_directory) - == 1) - { - data->is_autoindex = true; - data->status_code = 200; - } - } -} - -void RequestMessage::parseMethod(int &start, int &end, std::string &msg) { - start = 0; - end = msg.find(' '); - if (end == -1) - throw ErrorHandler(__FILE__, __func__, __LINE__, "There is no HTTP Method in Request msg"); - data->method = msg.substr(start, end); - if (data->method.compare("GET") == 0 || - data->method.compare("POST") == 0 || - data->method.compare("DELETE") == 0) - return; - else - { - this->error_code = "405"; - this->seq = ERROR; - } -} - -void RequestMessage::parseTarget(int &start, int &end, std::string &msg) { - std::string target; - start = end + 1; - end = msg.find(' ', start); - if (end == -1) - throw ErrorHandler(__FILE__, __func__, __LINE__, "There is no URI in Request msg"); - target = msg.substr(start, end - start); - - int query_pos = int(target.find_last_of("?")); - if (query_pos != -1) { - data->query_string = target.substr(query_pos + 1); - target = target.substr(0, target.length() - data->query_string.length() - 1); - } - int extension_pos = target.find_last_of("."); - this->data->isCGI = false; - this->data->CGI_root = ""; - if (extension_pos != -1) { - data->file_extension = target.substr(extension_pos + 1); - int file_pos = target.find_last_of("/"); - data->uri_file = target.substr(file_pos + 1); - target = target.substr(0, target.length() - data->uri_file.length()); - for (int i = 0; i < int(_config._http._server[1]._location.size()); i++) { - std::string temp = _config._http._server[1]._location[i]._location; - temp = temp.substr(1, temp.length() - 2); - if (this->data->file_extension.compare(temp) == 0) { - this->data->isCGI = true; - this->data->CGI_root = _config._http._server[1]._location[i]._dir_map["cgi_pass"]; - this->data->CGI_what = temp; - //그럼 cgi를 찾았다면 - //어느 cgi인지(php냐 아님 python이냐) - //그것도 여기서 찾아야 할것이고 - //그것에 대한 경로 파일도 찾아내는게 맞을듯 - break; - } - } - } - data->uri_dir = target; - this->parsing_pointer = end + 2; -} -std::vector RequestMessage::checkURIDIR(void) { - std::vector location = _config._http._server[data->server_block]._location; - std::vector::iterator it = location.begin(); - for (it = location.begin(); it != location.end(); it++) { - if (it->_location.compare(data->uri_dir) == 0) { - return (it->_index); - } } - return (_config._http._server[data->server_block]._index); + return (this->_seq); } -std::vector RequestMessage::checkErrorPage(void) { - std::vector location = _config._http._server[data->server_block]._location; - std::vector::iterator it = location.begin(); - for (it = location.begin(); it != location.end(); it++) { - if (it->_location.compare(data->uri_dir) == 0) { - return (it->_error_page); - } - } - return (_config._http._server[data->server_block]._error_page); -} +// Start Line +int + RequestMessage::parseStartLine( + std::string& msg) +{ + int + _start, + _end; -std::string RequestMessage::getErrorPage(std::vector error_page, std::string root) { - std::vector::iterator pagePos = find(error_page.begin(), error_page.end(), std::to_string(data->status_code)); - if (pagePos != error_page.end()) { - while (pagePos != error_page.end()) { - int finder = (*pagePos).find_last_of(".html"); - if (finder != -1 && access((root + data->uri_dir + *pagePos).c_str(), F_OK) == 0) { - return (*pagePos); + parseMethod(_start, _end, msg); + if (this->_seq != ERROR) + { + parseTarget(_start, _end, msg); + if (this->_seq != ERROR) + { + parseHttpVersion(_start, _end, msg); + if (this->_seq != ERROR) + { + if (this->_has_index == false && + checkAutoindex( + _config._http._server[1]._dir_map["root"], + this->_data->url_directory) == 1) + this->_seq = AUTOINDEX; } - pagePos++; - } - data->uri_dir = "/"; - return ("defaul_error.html"); - } - else { - data->uri_dir = "/"; - return ("defaul_error.html"); - } -} - -// 에러 페이지 띄워주기 설정 -void RequestMessage::checkTarget(void) { - std::map::iterator - rootFinder; - rootFinder = _config._http._server[1]._dir_map.find("root"); - std::string - root; - // default root 값 변경해야함 - // root값이 없다는 것을 알려주여야 status 코드를 띄울 수 있음 (304) - if (rootFinder == _config._http._server[1]._dir_map.end()) { - root = "./static_html"; - std::cout << "여기서 default root 값을 넣어주여야 함!" << std::endl; - } - - root = _config._http._server[1]._dir_map["root"]; - this->data->url_directory = data->uri_dir; - - std::vector index = checkURIDIR(); - std::vector::iterator it; - - std::vector error_page = checkErrorPage(); - // index 자체가 없을 때 - // root 경로에 default index.html을 띄워준다. - // index.html이 없는 경우에는 403 - - if (index.empty()) { - std::string filePath = root + data->uri_dir + "index.html"; - if (access(filePath.c_str(), F_OK) == 0) { - data->uri_file = "index.html"; - data->file_extension = "html"; - data->status_code = 304; - this->has_index = true; - return ; - } else { - data->uri_file = getErrorPage(error_page, root); - data->file_extension = "html"; - data->status_code = 403; - this->has_index = true; - return ; - } - } - - for(it = index.begin(); it != index.end(); it++) { - std::string filePath = root + data->uri_dir + "/" + *it; - if (access(filePath.c_str(), F_OK) == 0) { - data->file_extension = (*it).substr((*it).find_last_of('.') + 1); - data->uri_file = *it; - data->status_code = 200; - this->has_index = true; - return ; + return (this->_seq); } } - if (it == index.end()) { - data->uri_file = getErrorPage(error_page, root); - data->file_extension = "html"; - data->status_code = 403; - this->has_index = false; - } -} - -void RequestMessage::parseHttpVersion (int &start, int &end, std::string &msg) { - start = end + 1; - std::string httpCheck = msg.substr(start); - if (httpCheck.compare("HTTP/1.1") == 0) { - this->data->http_version = 1.1; - start += httpCheck.length(); - return ; - } - else - throw ErrorHandler(__FILE__, __func__, __LINE__, "Not HTTP 1.1"); } -void RequestMessage::printStartLine(void) { - std::cout << "[REQUEST MSG - START LINE]" << std::endl; - std::cout << "Method : " << data->method << std::endl; - std::cout << "uri_dir : " << data->uri_dir << std::endl; - std::cout << "uri_file : " << data->uri_file << std::endl; - std::cout << "query_string : " << data->query_string << std::endl; - std::cout << "file_extension : " << data->file_extension << std::endl; - std::cout << "http_version : " << data->http_version << std::endl; - std::cout << "isCGI : " << data->isCGI << std::endl; -} - - /** Header Field **/ -void RequestMessage::parseHeaderField(std::string &msg) { - int start = this->parsing_pointer, end; - std::string key, value; - // header_field가 없는 경우 - if ((int)msg.length() == start) { - this->parsing_pointer = start + 2; - return ; - } - while (true) { - end = msg.find(':', start); - key = msg.substr(start, end - start); - start = end + 1; - if (msg.at(end + 1) == ' ') - start++; - end = msg.find("\r\n", start); - value = msg.substr(start, end - start); - data->header_field.insert(std::pair(key, value)); - start = end + 2; - // header_field가 끝나는 경우 (CRLF) - if (msg.at(start) == '\r' && msg.at(start + 1) == '\n') - break; - } - this->parsing_pointer = start + 2; - return ; -} - -void RequestMessage::printHeaderField(void) { - std::cout << "[REQUEST MSG - HEADER FIELD]" << std::endl; - std::map::iterator it; - - for (it = data->header_field.begin(); it != data->header_field.end(); it++) - std::cout << it->first << " : " << it->second << std::endl; -} - -/** Body **/ -void RequestMessage::parseMessageBody(std::string &msg) { - int start = this->parsing_pointer; - - data->message_body = msg.substr(start); - if (data->isCGI) { - // data->message_body += data->CGI_read; - // write(cgi->getInputPair(), data->message_body.c_str(), data->message_body.length()); - } -} - -void RequestMessage::printBody(void) { - std::cout << "[REQUEST MSG - BODY]" << std::endl; - std::cout << data->message_body << std::endl; -} +// 405: Method Not Allowed void - RequestMessage::set413ErrorPage( - void) + RequestMessage::parseMethod( + int& _start, + int& _end, + std::string& _msg) { - data->uri_file = "413.html"; - data->file_extension = "html"; - data->status_code = 413; - data->uri_dir = "/"; - data->isCGI = false; + _start = 0; + _end = _msg.find(' '); + if (_end == -1) + this->_seq = this->setError(400); + _data->method = _msg.substr(_start, _end); + if (_data->method.compare("GET") != 0 && + _data->method.compare("POST") != 0 && + _data->method.compare("DELETE") != 0) + this->_seq = this->setError(405); + /* + if (nginx.conf 내 accepted_method가 있는 경우) { + if (현재 HTTP method가 accepted_method와 매칭되지 않는 경우) + return (setError(405)); + } + */ + this->_seq = START_LINE; } \ No newline at end of file diff --git a/HTTPMessageController/RequestMessage.hpp b/HTTPMessageController/RequestMessage.hpp index 82bff79..e6b03f8 100644 --- a/HTTPMessageController/RequestMessage.hpp +++ b/HTTPMessageController/RequestMessage.hpp @@ -1,66 +1,89 @@ -#ifndef REQUESTMESSAGE_HPP -# define REQUESTMESSAGE_HPP +#ifndef REQUESTMESSAGE_HPP +# define REQEUSTMESSAGE_HPP -#include -#include -#include -#include "HTTPData.hpp" -#include "ErrorHandler.hpp" -#include "ConfigBlocks.hpp" -#include "CGIProcess.hpp" -#include "FileController.hpp" +# include +# include +# include +# include "HTTPData.hpp" +# include "ErrorHandler.hpp" +# include "ConfigBlocks.hpp" +# include "CGIProcess.hpp" +# include "FileController.hpp" extern NginxConfig::GlobalConfig _config; -class RequestMessage { +class RequestMessage +{ public: - typedef enum e_Seq { + typedef enum e_seq { START_LINE, HEADER_FIELD, MESSAGE_BODY, FINISH_PARSE, + CGI, + AUTOINDEX, + REDIRECT, ERROR - } Seq; - std::string error_code; - + } e_seq; + private: - HTTPData* data; - CGIProcess* cgi; - int parsing_pointer; - std::string message; - Seq seq; - bool has_index; - + HTTPData* + _data; + int + _parse_ptr; + std::string + _message; + e_seq + _seq; + bool + _has_index; + public: - RequestMessage(HTTPData* _data); - - void setMessage(char* buffer); - void resetMessage(); + // Contructor + RequestMessage( + HTTPData* _tmp); + + // Setter && Getter + int + setError( + int _arg_status_code); + void + setMessage( + char* buffer); + std::string - getMessage(); - - /** Header **/ - int parsingRequestMessage(); - void parseStartLine(std::string &msg); - void parseMethod(int &start, int &end, std::string &msg); - void parseTarget(int &start, int &end, std::string &msg); - int checkAutoIndex(std::string _root, std::string _pth); - void checkTarget(void); - std::vector checkURIDIR(void); - std::vector checkErrorPage(void); - std::string getErrorPage(std::vector error_page, std::string root); - void parseHttpVersion (int &start, int &end, std::string &msg); - void printStartLine(void); - - /** Header Field **/ - void parseHeaderField(std::string &msg); - void printHeaderField(void); + getMessage( + void); + + int + parse( + void); + + // Header + void + parseStartLine( + std::string& msg); + void + parseMethod( + int& start, + int& end, + std::string& msg); + void + parseTarget( + int& start, + int& end, + std::string& msg); - /** Body **/ - void parseMessageBody(std::string &msg); - void printBody(void); - void set413ErrorPage(void); + // Header Field + int + parseHeaderField( + std::string& msg); + + // Body + void + parseMessageBody( + std::string& msg); }; -#endif +#endif \ No newline at end of file diff --git a/HTTPMessageController/ResponseMessage.cpp b/HTTPMessageController/ResponseMessage.cpp index c56d78f..ee379a9 100644 --- a/HTTPMessageController/ResponseMessage.cpp +++ b/HTTPMessageController/ResponseMessage.cpp @@ -71,7 +71,7 @@ void ResponseMessage::setHeaderField() { std::string _path = _config._http._server[this->_data->server_block]._dir_map["root"] + this->_data->uri_dir + this->_data->uri_file; std::cout << "PATH : " << _path << std::endl; - if (this->_data->isCGI == true) { + if (this->_data->is_cgi == true) { // FIXME // CGI의 경우, Chunked _data를 받아야 함. //this->_header_field += "Transfer-Encoding: chunked\r\n"; @@ -114,7 +114,7 @@ int setHeaderField(); this->_message += (this->_start_line + "\r\n"); this->_message += this->_header_field; - if (this->_data->isCGI == false && + if (this->_data->is_cgi == false && this->_data->is_autoindex == false) this->_message += "\r\n"; return (0); diff --git a/HTTPMessageController/requestMain.cpp b/HTTPMessageController/requestMain.cpp new file mode 100644 index 0000000..73cd3a8 --- /dev/null +++ b/HTTPMessageController/requestMain.cpp @@ -0,0 +1 @@ +`#include "RequestMessage" \ No newline at end of file diff --git a/HTTPMessageController/testMain.cpp b/HTTPMessageController/testMain.cpp new file mode 100644 index 0000000..85c68d1 --- /dev/null +++ b/HTTPMessageController/testMain.cpp @@ -0,0 +1,2 @@ +#include "RequestMessage.hpp" +#include "HTTPConnection.hpp" diff --git a/HTTPMessageController_old/HTTPConnection.cpp b/HTTPMessageController_old/HTTPConnection.cpp new file mode 100644 index 0000000..c0194b4 --- /dev/null +++ b/HTTPMessageController_old/HTTPConnection.cpp @@ -0,0 +1,330 @@ +#include "HTTPConnection.hpp" + +extern NginxConfig::GlobalConfig _config; + +HTTPConnection::HTTPConnection(int fd, int block, int server_port, std::string client_ip, std::string client_port, std::string host_ip, std::string host_port) { + seq = HTTP_READ; + socket_fd = fd; + http_data = new HTTPData(block, server_port, client_ip); + http_data->client_ip = client_ip; + http_data->client_port = client_port; + http_data->host_ip = host_ip; + http_data->host_port = host_port; + request_message = new RequestMessage(http_data); + response_message = new ResponseMessage(http_data); + if (_config._http._server[this->http_data->server_block]._dir_map["client_max_body_size"].empty() == true) + http_data->client_body_size = 1024; + else + http_data->client_body_size = atoi(_config._http._server[this->http_data->server_block]._dir_map["client_max_body_size"].c_str()); + current_size = 0; +} + +HTTPConnection::~HTTPConnection() { + if (this->http_data->is_cgi == true) + delete cgi_process; + delete request_message; + delete response_message; + delete http_data; + close(socket_fd); +} + +void HTTPConnection::killConnection(void* hc) { + delete reinterpret_cast(hc); +} + +int HTTPConnection::getServerBlock(void) { return (this->http_data->getSBlock()); } +int HTTPConnection::getFileFd(void) { return (this->file_fd); } +int HTTPConnection::getSocketFd(void) { return (this->socket_fd); } +int HTTPConnection::getCgiOutputFd(void) { return (this->cgi_output_fd); } +int HTTPConnection::getCgiInputFd(void) { return (this->cgi_input_fd); } + +int HTTPConnection::run() { + if (seq == HTTP_READ) { + readLength = read(socket_fd, buffer, BUF_SIZ - 1); + buffer[readLength] = '\0'; + if (readLength > 0) + request_message->setMessage(buffer); + int request_result = request_message->parsingRequestMessage(); + } + /* + if (seq == REQUEST) { + std::cout << "[REQUEST]\n"; + readLength = read(socket_fd, buffer, BUF_SIZ - 1); + buffer[readLength] = '\0'; + if (readLength > 0) + request_message->setMessage(buffer); + int request_result = request_message->parsingRequestMessage(); + if (request_result == RequestMessage::ERROR) + { + std::string + _msg_body = ErrorPageController::getErrorBody(request_message->error_code); + http_data->str_buffer = "Content-Length: "; + std::stringstream ss; + ss << _msg_body.size(); + http_data->str_buffer += ss.str(); + http_data->str_buffer += "\r\nContent-Type: text/html\r\n\r\n"; + http_data->str_buffer += _msg_body; + http_data->is_buffer_write = true; + seq = REQUEST_TO_RESPONSE; + } + else if (request_result == RequestMessage::FINISH_PARSE) { + std::map::iterator res; + if ((res = this->http_data->header_field.find("Connection")) != this->http_data->header_field.end()) + if (res->second == "keep-alive") + keep_alive = true; + if (this->http_data->is_cgi == true) { + cgi_process = new CGIProcess(http_data); + cgi_process->run(); + cgi_input_fd = cgi_process->getInputPair(); + cgi_output_fd = cgi_process->getOutputPair(); + if (fcntl(cgi_input_fd, F_SETFL, O_NONBLOCK) == -1 || + fcntl(cgi_output_fd, F_SETFL, O_NONBLOCK) == -1) + throw ErrorHandler(__FILE__, __func__, __LINE__, + "something wrong with fd. check the file exists : ?", ErrorHandler::NON_CRIT); + } + if (http_data->header_field.find("Content-Length") != http_data->header_field.end() && + (http_data->header_field["Content-Length"] != "0" && http_data->header_field["Content-Length"] != "")) + seq = READY_TO_MESSAGE_BODY; + else + seq = REQUEST_TO_RESPONSE; + if (http_data->header_field["Content-Length"].empty() == false && + atoi(http_data->header_field["Content-Length"].c_str()) > limit_size) + { + std::cout << "???1" << std::endl; + std::string + _msg_body = ErrorPageController::getErrorBody("413"); + http_data->str_buffer = "Content-Length: "; + std::stringstream ss; + ss << _msg_body.size(); + http_data->str_buffer += ss.str(); + http_data->str_buffer += "\r\nContent-Type: text/html\r\n\r\n"; + http_data->str_buffer += _msg_body; + seq = REQUEST_TO_RESPONSE; + } + } + else if (request_result == RequestMessage::MESSAGE_BODY) { + if (this->http_data->is_cgi == true) { + cgi_process = new CGIProcess(http_data); + cgi_process->run(); + cgi_input_fd = cgi_process->getInputPair(); + cgi_output_fd = cgi_process->getOutputPair(); + if (fcntl(cgi_input_fd, F_SETFL, O_NONBLOCK) == -1 || + fcntl(cgi_output_fd, F_SETFL, O_NONBLOCK) == -1) + throw ErrorHandler(__FILE__, __func__, __LINE__, + "something wrong with fd. check the file exists : ?", ErrorHandler::NON_CRIT); + seq = READY_TO_MESSAGE_BODY; + } + else + seq = REQUEST_TO_RESPONSE; + if (http_data->header_field["Content-Length"].empty() == false && + atoi(http_data->header_field["Content-Length"].c_str()) > limit_size) + { + std::cout << "???2" << std::endl; + std::string + _msg_body = ErrorPageController::getErrorBody("413"); + http_data->str_buffer = "Content-Length: "; + std::stringstream ss; + ss << _msg_body.size(); + http_data->str_buffer += ss.str(); + http_data->str_buffer += "\r\nContent-Type: text/html\r\n\r\n"; + http_data->str_buffer += _msg_body; + seq = ERROR_WRITE; + } + } + } + else if (seq == READY_TO_MESSAGE_BODY) { + std::cout << "[READY_TO_MESSAGE_BODY]\n"; + write(cgi_input_fd, request_message->getMessage().data(), request_message->getMessage().size()); + std::stringstream ss; + ss << request_message->getMessage().size(); + if (ss.str() == http_data->header_field["Content-Length"]) + seq = BODY_TO_RESPONSE; + else + seq = MESSAGE_BODY_READ; + } + else if (seq == BODY_TO_RESPONSE) { + std::cout << "[BODY_TO_RESPONSE]\n"; + seq = REQUEST_TO_RESPONSE; + } + else if (seq == MESSAGE_BODY_READ) { + std::cout << "[MESSAGE_BODY_READ]" << std::endl; + readLength = read(socket_fd, buffer, BUF_SIZ - 1); + buffer[readLength] = '\0'; + if (readLength > 0) { +// buffer[readLength] = '\0'; + seq = MESSAGE_BODY_WRITE; + } + else { + seq = REQUEST_TO_RESPONSE; + } + } + else if (seq == MESSAGE_BODY_WRITE) { + std::cout << "[MESSAGE_BODY_WRITE]" << std::endl; + writeLength = write(cgi_input_fd, buffer, readLength); + if (writeLength == BUF_SIZ - 1) + seq = MESSAGE_BODY_READ; + else + seq = REQUEST_TO_RESPONSE; + } + else if (seq == REQUEST_TO_RESPONSE) { + std::cout << "[REQUEST_TO_RESPONSE]" << std::endl; + if (http_data->is_buffer_write == false) + response_message->setResponseMessage(); + seq = RESPONSE; + } + else if (seq == RESPONSE) { + std::cout << "RESPONSE" << std::endl; + int + write_size = ((int)response_message->getMessage().size() < BUF_SIZ ? (int)response_message->getMessage().size() : BUF_SIZ); + writeLength = write(socket_fd, response_message->getMessage().data(), write_size); + if (http_data->is_buffer_write == true) + { + size_t r = write(socket_fd, http_data->str_buffer.data(), http_data->str_buffer.size()); + std::cout << "r : " << r << std::endl; + std::cout << "buffer_size : " << http_data->str_buffer.size() << std::endl; + http_data->is_buffer_write = false; + seq = CLOSE; + } + else if (writeLength != BUF_SIZ) { + if (this->http_data->is_cgi == true) { + seq = READY_TO_CGI; + } + else if (this->http_data->is_autoindex == true) { + std::string + _msg_body = AutoindexController::getAutoIndexBody(_config._http._server[1]._dir_map["root"], this->http_data->url_directory); + http_data->str_buffer = "Content-Length: "; + std::stringstream ss; + ss << _msg_body.size(); + http_data->str_buffer += ss.str(); + http_data->str_buffer += "\r\nContent-Type: text/html\r\n\r\n"; + http_data->str_buffer += _msg_body; + seq = AUTOINDEX_WRITE; + } + else { + std::string _pth = + _config._http._server[this->http_data->server_block]._dir_map["root"] + + this->http_data->uri_dir + + this->http_data->uri_file; + _pth = FileController::toAbsPath(_pth); + file_fd = open(_pth.c_str(), O_RDONLY); + if (fcntl(file_fd, F_SETFL, O_NONBLOCK) == -1) + throw ErrorHandler(__FILE__, __func__, __LINE__, + "something wrong with fd. check the file exists : \n" + _pth, ErrorHandler::NON_CRIT); + seq = READY_TO_FILE; + } + } + else + response_message->resetMessage(writeLength); + } + else if (seq == AUTOINDEX_WRITE) { + std::cout << "[AUTOINDEX_WRITE]\n"; + write(socket_fd, http_data->str_buffer.data(), http_data->str_buffer.size()); + seq = CLOSE; + } + else if (seq == ERROR_WRITE) { + // std::cout << "[ERROR_WRITE]\n"; + // write(socket_fd, http_data->str_buffer.data(), http_data->str_buffer.size()); + // seq = CLOSE; + } + else if (seq == READY_TO_CGI) { + std::cout << "[READY_TO_CGI]" << std::endl; + close(cgi_input_fd); + seq = CGI_READ; + } + else if (seq == CGI_READ) { + std::cout << "[CGI_READ]" << std::endl; + readLength = read(cgi_output_fd, buffer, BUF_SIZ - 1); + buffer[readLength] = '\0'; + seq = CGI_WRITE; + } + else if (seq == CGI_WRITE) { + std::cout << "[CGI_WRITE]" << std::endl; + if (readLength == 0) + seq = CLOSE; + else if (readLength == -1) + throw ErrorHandler(__FILE__, __func__, __LINE__, + "exit -1 replaced", ErrorHandler::CRIT); + else { + writeLength = write(socket_fd, buffer, readLength); + if (readLength != writeLength) { + throw ErrorHandler(__FILE__, __func__, __LINE__, + "exit -1 replaced", ErrorHandler::CRIT); + }/* + if (writeLength != BUF_SIZ - 1) { + std::cout << "READ LEN : " << readLength << std::endl; + std::cout << "WRITE LEN : " << writeLength << std::endl; + std::cout << "test1" << std::endl; + close(cgi_output_fd); + seq = CLOSE; + } + else + /// + seq = CGI_READ; + } + } + else if (seq == READY_TO_FILE) { + std::cout << "[READY_TO_FILE]" << std::endl; + seq = FILE_READ; + } + else if (seq == FILE_READ) { + std::cout << "[FILE_READ]" << std::endl; + readLength = read(file_fd, buffer, BUF_SIZ); + seq = FILE_WRITE; + } + else if (seq == FILE_WRITE) { + std::cout << "[FILE_WRITE]" << std::endl; + if (readLength == 0) + seq = CLOSE; + else if (readLength == -1) + throw ErrorHandler(__FILE__, __func__, __LINE__, + "exit -1 replaced", ErrorHandler::CRIT); + else { + writeLength = write(socket_fd, buffer, readLength); + if (readLength != writeLength) { + throw ErrorHandler(__FILE__, __func__, __LINE__, + "exit -1 replaced", ErrorHandler::CRIT); + } + if (writeLength != BUF_SIZ) { + close(file_fd); + seq = CLOSE; + } + else + seq = FILE_READ; + if (seq == CLOSE && keep_alive == true) + seq = RE_KEEPALIVE; + } + } + else if (seq == RE_KEEPALIVE) { + int backup_block; + int backup_port; + std::string backup_ip; + + backup_block = this->http_data->server_block; + backup_port = this->http_data->server_port; + backup_ip = this->http_data->client_ip; + + if (this->http_data->is_cgi == true) + delete cgi_process; + delete request_message; + delete response_message; + delete http_data; + buffer[0] = '\0'; + readLength = -2; + writeLength = -2; + if (file_fd > 0) + file_fd = -2; + if (cgi_output_fd > 0) + cgi_output_fd = -2; + if (cgi_input_fd > 0) + cgi_input_fd = -2; + + //keep_alive = false; + //다음 연결에서 keep-alive가 안되는 경우도 있다? + + http_data = new HTTPData(backup_block, backup_port, backup_ip); + request_message = new RequestMessage(http_data); + response_message = new ResponseMessage(http_data); + seq = REQUEST; + }*/ + return seq; +}; diff --git a/HTTPMessageController_old/HTTPConnection.hpp b/HTTPMessageController_old/HTTPConnection.hpp new file mode 100644 index 0000000..346276c --- /dev/null +++ b/HTTPMessageController_old/HTTPConnection.hpp @@ -0,0 +1,82 @@ +#ifndef HTTPCONNECTION_HPP +# define HTTPCONNECTION_HPP + +#include "ClassController.hpp" +#include "HTTPData.hpp" +#include "RequestMessage.hpp" +#include "ResponseMessage.hpp" +#include "KernelQueueController.hpp" +#include "FileController.hpp" +#include "AutoindexController.hpp" +#include "ErrorPageController.hpp" +#include +#include + +#define BUF_SIZ 2048 + +extern NginxConfig::GlobalConfig _config; + +class HTTPConnection : public ClassController { + public: + typedef enum e_Seq { + HTTP_READ, + READY_AUTOINDEX, + READY_REDIRECT, + ERROR, + READY_CGI_INPUT, + CGI_INPUT_READ, + CGI_INPUT_WRITE, + FINISH_CGI_INPUT, + CGI_GET_HEADER, + SET_RESPONSE, + + REQUEST, + READY_TO_MESSAGE_BODY, + MESSAGE_BODY_READ, + MESSAGE_BODY_WRITE, + REQUEST_TO_RESPONSE, + BODY_TO_RESPONSE, + RESPONSE, + READY_TO_CGI, + CGI_READ, + CGI_WRITE, + READY_TO_FILE, + FILE_READ, + FILE_WRITE, + CLOSE, + RE_KEEPALIVE, + AUTOINDEX_WRITE, + ERROR_WRITE + } Seq; + + private: + Seq seq; + int socket_fd; + int file_fd; + int cgi_output_fd; + int cgi_input_fd; + char buffer[BUF_SIZ]; + HTTPData* http_data; + RequestMessage* request_message; + ResponseMessage* response_message; + CGIProcess* cgi_process; + int readLength; + int writeLength; + bool keep_alive; + int current_size; + + public: + HTTPConnection(int fd, int block, int server_port, std::string client_ip, std::string client_port, std::string host_ip, std::string host_port); + virtual ~HTTPConnection(); + static void killConnection(void* hc); + + int getServerBlock(void); + int getFileFd(void); + int getSocketFd(void); + int getCgiOutputFd(void); + int getCgiInputFd(void); + + int run(); +}; + +#endif diff --git a/HTTPMessageController_old/HTTPData.cpp b/HTTPMessageController_old/HTTPData.cpp new file mode 100644 index 0000000..6310398 --- /dev/null +++ b/HTTPMessageController_old/HTTPData.cpp @@ -0,0 +1,16 @@ +#include "HTTPData.hpp" + +int HTTPData::getSBlock(void) { return(this->server_block); } + +HTTPData::HTTPData(int server_block, int server_port, std::string client_ip) { + this->status_code = 200; + this->server_block = server_block; + this->server_port = server_port; + this->client_ip = client_ip; + this->is_autoindex = false; + this->is_buffer_write = false; + this->is_cgi = false; + this->is_redirect = false; + this->cgi_extension = ""; + this->cgi_pass = ""; +} diff --git a/HTTPMessageController_old/HTTPData.hpp b/HTTPMessageController_old/HTTPData.hpp new file mode 100644 index 0000000..4382ec2 --- /dev/null +++ b/HTTPMessageController_old/HTTPData.hpp @@ -0,0 +1,51 @@ +#ifndef HTTPDATA_HPP +# define HTTPDATA_HPP + +#include +#include +#include + +class HTTPData { + public: + // Nginx Server Block num + int server_block; + // server port & client IP + int server_port; + std::string client_ip; + std::string client_port; + std::string host_ip; + std::string host_port; + // Start Line + std::string method; + std::string uri_dir; + std::string uri_file; + std::string query_string; + std::string file_extension; + std::string cgi_pass; + std::string cgi_extension; + + double http_version; + + std::string url_directory; + // Header Field + std::map header_field; + + // Message Body + std::string message_body; + + std::string str_buffer; + bool is_buffer_write; + int status_code; + + bool is_cgi; + bool is_autoindex; + bool is_redirect; + + int client_body_size; + + int getSBlock(void); + + HTTPData(int server_block, int server_port, std::string client_ip); +}; + +#endif diff --git a/HTTPMessageController_old/RequestMessage.cpp b/HTTPMessageController_old/RequestMessage.cpp new file mode 100644 index 0000000..468e9dd --- /dev/null +++ b/HTTPMessageController_old/RequestMessage.cpp @@ -0,0 +1,367 @@ +#include "RequestMessage.hpp" + +RequestMessage::RequestMessage(HTTPData* _data) { + this->data = _data; + this->parsing_pointer = 0; + this->message = ""; + this->seq = START_LINE; +} + +int RequestMessage::setError(int status_code) { + this->data->is_error = true; + this->data->status_code = status_code; + return (ERROR); +} + +void RequestMessage::setMessage(char* buffer) { + std::string temp(buffer); + this->message += temp; + return ; +} + +void RequestMessage::resetMessage() { + this->message = this->message.substr(this->parsing_pointer); + this->parsing_pointer = 0; + return ; +} + +std::string RequestMessage::getMessage(void) { + return (this->message); +} + +/** Header **/ + +// message 내에 start line이 모두 담겨져있는지 확인하는 메소드 +// start line 파싱이 가능하면 true, 불가능하면 false 반환 + + +int RequestMessage::parsingRequestMessage() { + if (this->seq == START_LINE) { + if (int(this->message.find("\r\n")) != -1) { + if (parseStartLine(this->message) == ERROR) + return (ERROR); + resetMessage(); + this->seq = HEADER_FIELD; + } + } + if (this->seq == HEADER_FIELD) { + if (int(this->message.find("\r\n\r\n", 0)) != -1) { + if (parseHeaderField(this->message) == ERROR) + return (ERROR); + resetMessage(); + this->seq = MESSAGE_BODY; + } + } + if (this->seq == MESSAGE_BODY) { + if (data->header_field.find("Content-Length") != data->header_field.end() && + data->header_field["Content-Length"] != "0") { + if (int(this->message.length()) == atoi(data->header_field["Content-Length"].c_str())) { + parseMessageBody(this->message); + this->seq = FINISH_PARSE; + } + } + else + this->seq = FINISH_PARSE; + } + return (this->seq); +} + +int RequestMessage::checkAutoIndex(std::string _root, std::string _path) +{ + std::string + _abs_path = _root + _path, + _abs_root = _root; + _abs_path = FileController::toAbsPath(_abs_path); + _abs_root = FileController::toAbsPath(_abs_root); + + if (FileController::checkType(_abs_path) != FileController::DIRECTORY) + return (-1); + else if (_config._http._server[1].findLocationIndexByDir(_path) != -1 && + _config._http._server[1]._location[ + _config._http._server[1].findLocationIndexByDir(_path) + ]._dir_map["autoindex"] == "on") + return (1); + else if (_config._http._server[1].findLocationIndexByDir(_path) != -1 && + _config._http._server[1]._location[ + _config._http._server[1].findLocationIndexByDir(_path) + ]._dir_map["autoindex"] == "off") + return (-1); + else + { + if (_abs_path.find_last_of("/") == _abs_path.length()) + _abs_path = _abs_path.substr(0, _abs_path.length() - 1); + if (_abs_path == _abs_root) + return (-1); + else + return (checkAutoIndex(_root, FileController::getPrePath(_path))); + } +} + +// TODO +// 접근하는 경로가 파일이고, 해당 파일을 찾을 수 없는 경우 -> 404 ERROR +// 접근하는 경로가 파일이고, 해당 파일을 열 수 없는 경우 -> 403 ERROR +// 접근하는 경로가 디렉토리일 때, 오토인덱스 on이고, 인덱스 파일이 없는 경우 -> this->data->is_autoindex = true; +// 접근하는 경로가 디렉토리일 때, 오토인덱스 off이고, 인덱스 파일이 있는 경우 -> nginx 비교 +// 접근하는 경로가 디렉토리일 때, 오토인덱스 off이고, 인덱스 파일이 없는 경우 -> nginx 비교 +int RequestMessage::parseStartLine(std::string &msg) { + int start, end; + if (this->parseMethod(start, end, msg) == ERROR) + return (ERROR); + if (this->parseTarget(start, end, msg) == ERROR) + return (ERROR); + this->parseHttpVersion(start, end, msg); + this->parsing_pointer = start + 2; + /* + if (TODO 조건에 따라 에러인 경우) + return (setError(해당 에러 번호)); + */ + return (START_LINE); +} + +// TODO +// nginx.conf 에서 accepted_method에 해당하지 않는 경우, 405 에러 반환 +// accepted_method에 GET, POST는 명시되지 않아도 적용 가능해야 함. +int RequestMessage::parseMethod(int &start, int &end, std::string &msg) { + start = 0; + end = msg.find(' '); + if (end == -1) + return (setError(400)); + data->method = msg.substr(start, end); + if (data->method.compare("GET") != 0 && data->method.compare("POST") != 0 && data->method.compare("DELETE") != 0) + return (setError(400)); + /* + if (nginx.conf 내 accepted_method가 있는 경우) { + if (현재 HTTP method가 accepted_method와 매칭되지 않는 경우) + return (setError(405)); + } + */ + return (START_LINE); +} + +int RequestMessage::parseTarget(int &start, int &end, std::string &msg) { + std::string target; + start = end + 1; + end = msg.find(' ', start); + if (end == -1) + return (setError(400)); + + target = msg.substr(start, end - start); + + int query_pos = int(target.find_last_of("?")); + if (query_pos != -1) { + data->query_string = target.substr(query_pos + 1); + target = target.substr(0, target.length() - data->query_string.length() - 1); + } + int extension_pos = target.find_last_of("."); + if (extension_pos != -1) { + data->file_extension = target.substr(extension_pos + 1); + int file_pos = target.find_last_of("/"); + data->uri_file = target.substr(file_pos + 1); + target = target.substr(0, target.length() - data->uri_file.length()); + } + data->uri_dir = target; + this->parsing_pointer = end + 2; + return (START_LINE); +} + +void RequestMessage::checkIsCgi(void) { + for (int i = 0; i < int(_config._http._server[this->data->server_block]._location.size()); i++) { + std::string temp = _config._http._server[this->data->server_block]._location[i]._location; + temp = temp.substr(1, temp.length() - 2); + if (this->data->file_extension.compare(temp) == 0) { + this->data->is_cgi = true; + this->data->cgi_pass = _config._http._server[this->data->server_block]._location[i]._dir_map["cgi_pass"]; + this->data->cgi_extension = temp; + break; + } + } +} + +std::vector RequestMessage::checkURIDIR(void) { + std::vector location = _config._http._server[data->server_block]._location; + std::vector::iterator it = location.begin(); + for (it = location.begin(); it != location.end(); it++) { + if (it->_location.compare(data->uri_dir) == 0) { + return (it->_index); + } + } + return (_config._http._server[data->server_block]._index); +} + +std::vector RequestMessage::checkErrorPage(void) { + std::vector location = _config._http._server[data->server_block]._location; + std::vector::iterator it = location.begin(); + for (it = location.begin(); it != location.end(); it++) { + if (it->_location.compare(data->uri_dir) == 0) { + return (it->_error_page); + } + } + return (_config._http._server[data->server_block]._error_page); +} + +std::string RequestMessage::getErrorPage(std::vector error_page, std::string root) { + std::vector::iterator pagePos = find(error_page.begin(), error_page.end(), std::to_string(data->status_code)); + if (pagePos != error_page.end()) { + while (pagePos != error_page.end()) { + int finder = (*pagePos).find_last_of(".html"); + if (finder != -1 && access((root + data->uri_dir + *pagePos).c_str(), F_OK) == 0) { + return (*pagePos); + } + pagePos++; + } + data->uri_dir = "/"; + return ("defaul_error.html"); + } + else { + data->uri_dir = "/"; + return ("defaul_error.html"); + } +} + +// 에러 페이지 띄워주기 설정 +void RequestMessage::checkTarget(void) { + std::map::iterator rootFinder; + rootFinder = _config._http._server[1]._dir_map.find("root"); + std::string root; + // default root 값 변경해야함 + // root값이 없다는 것을 알려주여야 status 코드를 띄울 수 있음 (304) + if (rootFinder == _config._http._server[this->data->server_block]._dir_map.end()) { + root = "./static_html"; + std::cout << "여기서 default root 값을 넣어주여야 함!" << std::endl; + } + + root = _config._http._server[this->data->server_block]._dir_map["root"]; + this->data->url_directory = data->uri_dir; + + std::vector index = checkURIDIR(); + std::vector::iterator it; + + std::vector error_page = checkErrorPage(); + // index 자체가 없을 때 + // root 경로에 default index.html을 띄워준다. + // index.html이 없는 경우에는 403 + + if (index.empty()) { + std::string filePath = root + data->uri_dir + "index.html"; + if (access(filePath.c_str(), F_OK) == 0) { + data->uri_file = "index.html"; + data->file_extension = "html"; + data->status_code = 304; + this->has_index = true; + return ; + } else { + data->uri_file = getErrorPage(error_page, root); + data->file_extension = "html"; + data->status_code = 403; + this->has_index = true; + return ; + } + } + + for(it = index.begin(); it != index.end(); it++) { + std::string filePath = root + data->uri_dir + "/" + *it; + if (access(filePath.c_str(), F_OK) == 0) { + data->file_extension = (*it).substr((*it).find_last_of('.') + 1); + data->uri_file = *it; + data->status_code = 200; + this->has_index = true; + return ; + } + } + if (it == index.end()) { + data->uri_file = getErrorPage(error_page, root); + data->file_extension = "html"; + data->status_code = 403; + this->has_index = false; + } +} + +void RequestMessage::parseHttpVersion (int &start, int &end, std::string &msg) { + start = end + 1; + std::string http_check = msg.substr(start); + if (http_check.compare("HTTP/1.1") == 0) { + this->data->http_version = 1.1; + start += http_check.length(); + return ; + } + else + throw ErrorHandler(__FILE__, __func__, __LINE__, "Not HTTP 1.1"); +} + +void RequestMessage::printStartLine(void) { + std::cout << "[REQUEST MSG - START LINE]" << std::endl; + std::cout << "Method : " << data->method << std::endl; + std::cout << "uri_dir : " << data->uri_dir << std::endl; + std::cout << "uri_file : " << data->uri_file << std::endl; + std::cout << "query_string : " << data->query_string << std::endl; + std::cout << "file_extension : " << data->file_extension << std::endl; + std::cout << "http_version : " << data->http_version << std::endl; + std::cout << "is_cgi : " << data->is_cgi << std::endl; +} + + /** Header Field **/ +int RequestMessage::parseHeaderField(std::string &msg) { + int start = this->parsing_pointer, end; + std::string key, value; + // header_field가 없는 경우 + if ((int)msg.length() == start) { + this->parsing_pointer = start + 2; + return (HEADER_FIELD); + } + while (true) { + end = msg.find(':', start); + key = msg.substr(start, end - start); + start = end + 1; + if (msg.at(end + 1) == ' ') + start++; + end = msg.find("\r\n", start); + value = msg.substr(start, end - start); + data->header_field.insert(std::pair(key, value)); + start = end + 2; + // header_field가 끝나는 경우 (CRLF) + if (msg.at(start) == '\r' && msg.at(start + 1) == '\n') + break; + } + if (this->data->is_cgi == true && data->header_field["Content-Length"].empty() == false) { + int content_length = atoi(data->header_field["Content-Length"].c_str()); + if (content_length > this->data->client_body_size) + return (setError(413)); + } + this->parsing_pointer = start + 2; + return (HEADER_FIELD); +} + +void RequestMessage::printHeaderField(void) { + std::cout << "[REQUEST MSG - HEADER FIELD]" << std::endl; + std::map::iterator it; + + for (it = data->header_field.begin(); it != data->header_field.end(); it++) + std::cout << it->first << " : " << it->second << std::endl; +} + +/** Body **/ +void RequestMessage::parseMessageBody(std::string &msg) { + int start = this->parsing_pointer; + + data->message_body = msg.substr(start); + if (data->is_cgi) { + // data->message_body += data->CGI_read; + // write(cgi->getInputPair(), data->message_body.c_str(), data->message_body.length()); + } +} + +void RequestMessage::printBody(void) { + std::cout << "[REQUEST MSG - BODY]" << std::endl; + std::cout << data->message_body << std::endl; +} + +void + RequestMessage::set413ErrorPage( + void) +{ + data->uri_file = "413.html"; + data->file_extension = "html"; + data->status_code = 413; + data->uri_dir = "/"; + data->is_cgi = false; +} \ No newline at end of file diff --git a/HTTPMessageController_old/RequestMessage.hpp b/HTTPMessageController_old/RequestMessage.hpp new file mode 100644 index 0000000..61c1ad8 --- /dev/null +++ b/HTTPMessageController_old/RequestMessage.hpp @@ -0,0 +1,67 @@ +#ifndef REQUESTMESSAGE_HPP +# define REQUESTMESSAGE_HPP + +#include +#include +#include +#include "HTTPData.hpp" +#include "ErrorHandler.hpp" +#include "ConfigBlocks.hpp" +#include "CGIProcess.hpp" +#include "FileController.hpp" + +extern NginxConfig::GlobalConfig + _config; + +class RequestMessage { + public: + typedef enum e_Seq { + START_LINE, + HEADER_FIELD, + MESSAGE_BODY, + FINISH_PARSE, + ERROR + } Seq; + std::string error_code; + + private: + HTTPData* data; + int parsing_pointer; + std::string message; + Seq seq; + bool has_index; + + public: + RequestMessage(HTTPData* _data); + + void setMessage(char* buffer); + void resetMessage(); + std::string getMessage(); + + /** Header **/ + int parsingRequestMessage(); + int parseStartLine(std::string &msg); + int parseMethod(int &start, int &end, std::string &msg); + int parseTarget(int &start, int &end, std::string &msg); + int checkAutoIndex(std::string _root, std::string _pth); + void checkTarget(void); + std::vector checkURIDIR(void); + std::vector checkErrorPage(void); + std::string getErrorPage(std::vector error_page, std::string root); + void parseHttpVersion (int &start, int &end, std::string &msg); + void printStartLine(void); + + /** Header Field **/ + int parseHeaderField(std::string &msg); + void printHeaderField(void); + + /** Body **/ + void parseMessageBody(std::string &msg); + void printBody(void); + void set413ErrorPage(void); + + int setError(int); + void checkIsCgi(void); +}; + +#endif diff --git a/HTTPMessageController_old/ResponseMessage.cpp b/HTTPMessageController_old/ResponseMessage.cpp new file mode 100644 index 0000000..ee379a9 --- /dev/null +++ b/HTTPMessageController_old/ResponseMessage.cpp @@ -0,0 +1,121 @@ +#include "ResponseMessage.hpp" + +ResponseMessage::ResponseMessage(HTTPData* _tmp) { + this->_data = _tmp; + this->_message = ""; + this->_start_line = ""; + this->_header_field = ""; + this->_status_msg_path = "./setting/status_code.txt"; +} + +std::string returnRedirectMessage() { + std::string + redirectMessage = "HTTP/1.1 302\nLocation: "; + redirectMessage += _config._http._server[1]._location[6]._rewrite[1]; + redirectMessage += "\nContent-Type: text/html;charset=UTF-8\nContent-Length: 0\r\n"; + return (redirectMessage); +} + +void ResponseMessage::resetMessage(int buf_size) { + this->_message = this->_message.substr(buf_size); +} + +void ResponseMessage::printStartLine(void) { + std::cout << this->_start_line << std::endl; +} +void ResponseMessage::printHeaderField(void) { + std::cout << this->_header_field << std::endl; +} + +std::string ResponseMessage::getMessage(void) { + return (this->_message); +} + +std::string ResponseMessage::setStatusMessage(std::string status_code) { + std::string rtn, read, temp; + rtn = ""; + int start, end; + std::ifstream fileRead(this->_status_msg_path.c_str()); + + if (fileRead.peek() == std::ifstream::traits_type::eof()) + throw ErrorHandler(__FILE__, __func__, __LINE__, "status_code.txt is empty"); + while (getline(fileRead, read)) { + start = 0; + end = read.find(": "); + temp = read.substr(start, end - start); + if (status_code.compare(temp) == 0) { + start = end + 2; + end = read.find("\n"); + rtn = read.substr(start, end - start); + break; + } + } + return (rtn); +} + +void ResponseMessage::setStartLine() { + std::stringstream temp; + std::string str_status_code; + + temp << this->_data->status_code; + temp >> str_status_code; + + this->_start_line += "HTTP/1.1 "; + this->_start_line += str_status_code; + this->_start_line += " "; + this->_start_line += setStatusMessage(str_status_code); + return ; +} + +void ResponseMessage::setHeaderField() { + std::string + _path = _config._http._server[this->_data->server_block]._dir_map["root"] + this->_data->uri_dir + this->_data->uri_file; + std::cout << "PATH : " << _path << std::endl; + if (this->_data->is_cgi == true) { + // FIXME + // CGI의 경우, Chunked _data를 받아야 함. + //this->_header_field += "Transfer-Encoding: chunked\r\n"; + //this->_header_field += "Content-Length: 51\r\n"; + } + else if (this->_data->is_autoindex == true) + { + + } + else { + // TODO + // content-type을 지정해주기 위해서 request message의 uri중 파일 확장자가 필요 + this->_header_field += ("Content-Type: " + _mime.getMIME(this->_data->file_extension) + "\r\n"); + std::string + _path = _config._http._server[this->_data->server_block]._dir_map["root"] + this->_data->uri_dir + this->_data->uri_file; + std::stringstream + _strstream; + _strstream << FileController::getFileSize(_path); + this->_header_field += ("Content-Length: " + _strstream.str() + "\r\n"); + } + this->_header_field += "Accept-Ranges: bytes\r\n"; + return ; +} + +int + ResponseMessage::setResponseMessage( + void) +{ + for (int _idx=0; _idx<(int)(_config._http._server[1]._location.size()); _idx++) + { + if (_config._http._server[1]._location[_idx]._location == this->_data->url_directory && + (int)_config._http._server[1]._location[_idx]._rewrite.size() != 0 && + _config._http._server[1]._location[_idx]._rewrite[0] == this->_data->url_directory) + { + this->_message += returnRedirectMessage(); + return (1); + } + } + setStartLine(); + setHeaderField(); + this->_message += (this->_start_line + "\r\n"); + this->_message += this->_header_field; + if (this->_data->is_cgi == false && + this->_data->is_autoindex == false) + this->_message += "\r\n"; + return (0); +} \ No newline at end of file diff --git a/HTTPMessageController_old/ResponseMessage.hpp b/HTTPMessageController_old/ResponseMessage.hpp new file mode 100644 index 0000000..a65c620 --- /dev/null +++ b/HTTPMessageController_old/ResponseMessage.hpp @@ -0,0 +1,58 @@ +#ifndef RESPONSEMESSAGE_HPP +# define RESPONSEMESSAGE_HPP + +# include "HTTPData.hpp" +# include +# include +# include "ConfigBlocks.hpp" +# include "ConfigMime.hpp" +# include "FileController.hpp" + +extern MimeConfig + _mime; +extern NginxConfig::GlobalConfig + _config; + +class ResponseMessage { + private: + /** + * data : Request Message로부터 파싱된 데이터들이 담긴 클래스 + * message : Response message (start line + header field + message body) + * statusMessagePath : 상태코드에 따른 메세지를 설정하기 위한 파일 경로 + */ + HTTPData* + _data; + std::string + _message, + _start_line, + _header_field, + _status_msg_path; + public: + /** + * setStartLine -> setMessageBody -> setHeaderField 순으로 호출 + * message body가 있어야 header field의 content-length를 구할 수 있기 때문 + */ + FileController::Type + _type; + ResponseMessage(HTTPData* _data); + void + setStartLine(void); + std::string + setStatusMessage(std::string status_code); + void + setHeaderField(void); + int + setResponseMessage(void); + + void + printStartLine(void); + void + printHeaderField(void); + + std::string + getMessage(); + void + resetMessage(int buf_size); +}; + +#endif diff --git a/Makefile b/Makefile index e12ca8f..bea8357 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ HEADER = -I./HTTPMessageController \ -I./AutoindexController \ -I./ErrorPageController -SRCS = ./server.cpp\ +SRCS = ./webserv.cpp\ ./ParsingController/Parser.cpp \ ./ParsingController/NginxParser.cpp \ ./ParsingController/ConfigGlobal.cpp \ @@ -39,18 +39,20 @@ SRCS = ./server.cpp\ ./HTTPMessageController/ResponseMessage.cpp \ ./FileController/FileController.cpp \ ./AutoindexController/AutoindexController.cpp \ - ./ErrorPageController/ErrorPageController.cpp + ./ErrorPageController/ErrorPageController.cpp \ + ./ErrorHandler/ErrorHandler.cpp \ + ./TimeController/TimeController.cpp OBJS = $(SRCS:.cpp=.o) %.o: %.cpp - @printf "\033[34m[WEBSERV]\033[0m Generating file : " + @printf "\033[34m[WEBSERV]\033[0m Compiling file ($<) : " @$(COMP) $(FLAG) $(HEADER) -c -o $@ $< @sleep 0.05 && printf "\033[33m." && sleep 0.05 && printf "\033[33m." && sleep 0.05 && printf "\033[33m. " @printf "\033[32mOK\033[0m\n" $(NAME): $(OBJS) - @printf "\033[34m[WEBSERV]\033[0m Compiling file : " + @printf "\033[34m[WEBSERV]\033[0m Linking object files (*.o) to $(NAME) binary : " @$(COMP) $(FLAG) $(HEADER) $(OBJS) -o $(NAME) @sleep 0.05 && printf "\033[33m." && sleep 0.05 && printf "\033[33m." && sleep 0.05 && printf "\033[33m. " @printf "\033[32mOK\033[0m\n" diff --git a/ServerProcess/ServerProcess.cpp b/ServerProcess/ServerProcess.cpp index 5333327..396084a 100644 --- a/ServerProcess/ServerProcess.cpp +++ b/ServerProcess/ServerProcess.cpp @@ -34,16 +34,14 @@ void ServerProcess::serverProcess() { close(conn_socket); throw ErrorHandler(__FILE__, __func__, __LINE__, "We can't find that block", ErrorHandler::NON_CRIT); } + int server_port = (int)ntohs((socketController->getServerAddr()).sin_port); + std::string client_ip = std::string(inet_ntoa((socketController->getServerAddr()).sin_addr)); + std::string host_ip = std::string(inet_ntoa((socketController->getClientAddr()).sin_addr)); std::stringstream clientPortString; std::stringstream hostPortString; - - std::string client_ip = std::string(inet_ntoa((socketController->getServerAddr()).sin_addr)); clientPortString << ntohs(socketController->getServerAddr().sin_port); - - std::string host_ip = std::string(inet_ntoa((socketController->getClientAddr()).sin_addr)); hostPortString << ntohs(socketController->getClientAddr().sin_port); - - int server_port = (int)ntohs((socketController->getServerAddr()).sin_port); + HTTPConnection* httpConnection = new HTTPConnection(conn_socket, server_block, server_port, client_ip, std::string(clientPortString.str()), host_ip, std::string(hostPortString.str())); if (fcntl(conn_socket, F_SETFL, O_NONBLOCK) == -1) exit(-1); @@ -73,6 +71,8 @@ void ServerProcess::serverProcess() { } else { int result = hc->run(); + if () + /* if (result == HTTPConnection::REQUEST_TO_RESPONSE) { kq.disableEvent(hc->getSocketFd(), EVFILT_READ, udata); kq.enableEvent(hc->getSocketFd(), EVFILT_WRITE, udata); @@ -106,7 +106,8 @@ void ServerProcess::serverProcess() { } else if (result == HTTPConnection::FILE_WRITE) { kq.disableEvent(hc->getFileFd(), EVFILT_READ, udata); kq.enableEvent(hc->getSocketFd(), EVFILT_WRITE, udata); - } else if (result == HTTPConnection::CLOSE) { + } + */else if (result == HTTPConnection::CLOSE) { // 이벤트 제거 // std::cout << "kq(w) : " << fd << std::endl; timer.del_time(hc->getSocketFd()); diff --git a/SocketController/SocketController.cpp b/SocketController/SocketController.cpp index 305db23..1249179 100644 --- a/SocketController/SocketController.cpp +++ b/SocketController/SocketController.cpp @@ -1,9 +1,4 @@ #include "SocketController.hpp" -#include "ConfigBlocks.hpp" - -#include -#include - extern NginxConfig::GlobalConfig _config; @@ -20,18 +15,13 @@ SocketController::~SocketController() { close(serverSocket); }; -struct sockaddr_in SocketController::getServerAddr() { - return (this->serverAddress); -}; - -struct sockaddr_in SocketController::getClientAddr() { - return (this->clientAddress); -}; +struct sockaddr_in SocketController::getServerAddr() { return (this->serverAddress); }; +struct sockaddr_in SocketController::getClientAddr() { return (this->clientAddress); }; int SocketController::getServerBlockNum(){ int port = int(ntohs(serverAddress.sin_port)); - for (int i = 0; i < (int)_config._http._server.size(); i++) { + for (size_t i = 0; i < _config._http._server.size(); i++) { if (atoi(_config._http._server[i]._dir_map["listen"].c_str()) == port) return (i); } @@ -57,8 +47,7 @@ int SocketController::binding() { int e2 = listen(serverSocket, 42); int e3 = fcntl(serverSocket, F_SETFL, O_NONBLOCK); if (e1 < 0 || e2 < 0 || e3 < 0) { - std::cout << "바인드 에러~" << std::endl; - return (0); + throw ErrorHandler(__FILE__, __func__, __LINE__, "Bind Error~"); } return serverSocket; }; diff --git a/SocketController/SocketController.hpp b/SocketController/SocketController.hpp index ba9e3fb..becf69d 100644 --- a/SocketController/SocketController.hpp +++ b/SocketController/SocketController.hpp @@ -2,30 +2,35 @@ # define SOCKETCONTROLLER_HPP #include "ClassController.hpp" +#include "ConfigBlocks.hpp" #include #include #include #include +#include +#include +#include "ErrorHandler.hpp" class SocketController : public ClassController { - struct sockaddr_in serverAddress; - struct sockaddr_in clientAddress; - socklen_t addressSize; - int serverSocket; +private: + struct sockaddr_in serverAddress; + struct sockaddr_in clientAddress; + socklen_t addressSize; + int serverSocket; public: SocketController(); SocketController(int port); virtual ~SocketController(); - int getServerBlockNum(); + int getServerBlockNum(); - struct sockaddr_in getServerAddr(); - struct sockaddr_in getClientAddr(); + struct sockaddr_in getServerAddr(); + struct sockaddr_in getClientAddr(); - void generator(int port); - int binding(); - int run(); + void generator(int port); + int binding(); + int run(); }; #endif diff --git a/TimeController/TimeController.cpp b/TimeController/TimeController.cpp new file mode 100644 index 0000000..ca928ec --- /dev/null +++ b/TimeController/TimeController.cpp @@ -0,0 +1,61 @@ +#include "TimeController.hpp" + +void TimeController::init_time(int id, void *ob, int timeout) { + timer_info info; + + info.obj = ob; + info.start = time(NULL); + info.keepalive_timeout = timeout; + timer_list[id] = info; +} + +double TimeController::get_time(int id) { + time_t end; + end = time(NULL); + // std::cout << "start : " << timer_list[id].start << " end : " << double(end) << std::endl; + // std::cout << "time : " << double(end - timer_list[id].start) << std::endl; + return (double(end - timer_list[id].start)); +} + +void TimeController::del_time(int id) { + timer_list.erase(id); + std::cout << "timer delete : " << id << std::endl; +} + +void TimeController::clean_time(int id) { + if (timer_list.find(id) != timer_list.end()) + timer_list[id].start = time(NULL); + else + return ; +// std::cout << id << " timer reset : " << timer_list[id].start << std::endl; +} + +bool TimeController::find_time(int id) { + if (timer_list.find(id) != timer_list.end()) + return (true); + else + return (false); +} + +void TimeController::check_time(void (*del)(void *)) { + int flag = 0; + std::map::iterator del_it; + std::map::iterator iter; + for (iter = timer_list.begin(); iter != timer_list.end(); iter++) { + if (flag == 1) { + del(del_it->second.obj); + timer_list.erase(del_it->first); + std::cout << "keepalive_timeout bye" << std::endl; + flag = 0; + } + if (get_time(iter->first) >= iter->second.keepalive_timeout) { + flag = 1; + del_it = iter; + } + } + if (flag == 1) { + del(del_it->second.obj); + timer_list.erase(del_it->first); + std::cout << "keepalive_timeout bye" << std::endl; + } +} \ No newline at end of file diff --git a/TimeController/TimeController.hpp b/TimeController/TimeController.hpp index e420318..43616f5 100644 --- a/TimeController/TimeController.hpp +++ b/TimeController/TimeController.hpp @@ -7,92 +7,22 @@ #include #include -class TimeController -{ +class TimeController { private: - struct timer_info - { - void *obj; - time_t start; + struct timer_info { + void *obj; + time_t start; int keepalive_timeout; - -// timer_info(HTTPConnection &ob) : obj(ob) { } }; std::map timer_list; public: - - void init_time(int id, void *ob, int timeout) - { - timer_info info; - - info.obj = ob; - info.start = time(NULL); - info.keepalive_timeout = timeout; - timer_list[id] = info; - //timer_list[id] = clock(); -// std::cout << "timer start : " << (double)timer_list[id] << std::endl; - } - - double get_time(int id) - { - time_t end; - end = time(NULL); - // std::cout << "start : " << timer_list[id].start << " end : " << double(end) << std::endl; - // std::cout << "time : " << double(end - timer_list[id].start) << std::endl; - return (double(end - timer_list[id].start)); - } - - void del_time(int id) - { - timer_list.erase(id); - std::cout << "timer delete : " << id << std::endl; - } - - void clean_time(int id) - { - if (timer_list.find(id) != timer_list.end()) - timer_list[id].start = time(NULL); - else - return ; -// std::cout << id << " timer reset : " << timer_list[id].start << std::endl; - } - - bool find_time(int id) - { - if (timer_list.find(id) != timer_list.end()) - return (true); - else - return (false); - } - - //디폴트가 60초 - void check_time(void (*del)(void *)) - { - int flag = 0; - std::map::iterator del_it; - //(void)(del); - for (std::map::iterator it = timer_list.begin(); it != timer_list.end(); it++) - { - if (flag == 1) - { - del(del_it->second.obj); - timer_list.erase(del_it->first); - std::cout << "keepalive_timeout bye" << std::endl; - flag = 0; - } - if (get_time(it->first) >= it->second.keepalive_timeout) { - flag = 1; - del_it = it; - } - } - if (flag == 1) - { - del(del_it->second.obj); - timer_list.erase(del_it->first); - std::cout << "keepalive_timeout bye" << std::endl; - } - } + void init_time(int id, void *ob, int timeout); + double get_time(int id); + void del_time(int id); + void clean_time(int id); + bool find_time(int id); + void check_time(void (*del)(void *)); }; diff --git a/TimeController/test_time.cpp b/TimeController/test_time.cpp deleted file mode 100644 index 468448b..0000000 --- a/TimeController/test_time.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include -#include -#include -//밀리초를 기준으로 한다 - -class Timer -{ -private: - clock_t start; - std::map map; - -public: - void init_timer(int i) - { - map[i] = clock(); - } - - double get_time(int i) - { - clock_t end; - end = clock(); - return (double(end - map[i])); - } - - void del_time(int i) - { - map.erase(i); - } - - void clean_time(int i) - { - map[i] = 0; - } -}; - -int main(void) -{ - Timer t; - - time_t start = time(NULL); - for (int i = 0; i < 10; i++) - { - time_t end = time(NULL); - std::cout << "start : " << start << " end : " << end << std::endl; - std::cout << "time : " << double(end - start)<< std::endl; - sleep(1); - } - return (0); -} diff --git a/server.cpp b/server.cpp deleted file mode 100644 index e3c930f..0000000 --- a/server.cpp +++ /dev/null @@ -1,82 +0,0 @@ -# include "ConfigBlocks.hpp" -# include "ConfigMime.hpp" -# include "ConfigStatus.hpp" -# include "SocketController.hpp" -# include "ServerProcess.hpp" -# include "KernelQueueController.hpp" -# include "ErrorHandler.hpp" -# include "ErrorPageController.hpp" - -# include -# include - -# define CONF_PATH "./setting/nginx.conf" -# define MIME_PATH "./setting/mime.types" -# define STAT_PATH "./setting/status_code.txt" - -NginxConfig::GlobalConfig - _config; -extern NginxConfig::GlobalConfig - _config; - -MimeConfig - _mime; -extern MimeConfig - _mime; - -StatusConfig - _status; -extern StatusConfig - _status; - -ErrorPageController - _error_page; - -void - check_argv_str( - std::string& _conf_uri, - std::string& _mime_uri, - std::string& _stat_uri, - std::string _tmp) -{ - if (_tmp.substr(_tmp.length() - 5, _tmp.length()).compare(".conf") == 0) - _conf_uri = _tmp; - else if (_tmp.substr(_tmp.length() - 6, _tmp.length()).compare(".types") == 0) - _mime_uri = _tmp; - else if (_tmp.substr(_tmp.length() - 3, _tmp.length()).compare(".txt") == 0) - _stat_uri = _tmp; - else - throw ErrorHandler(__FILE__, __func__, __LINE__, - "Invalid file name on argument(.conf, .types and .txt only) : " + _tmp); -} - -int - main(int _arc, char** _arv) - { - try - { - std::string - _conf_uri = CONF_PATH, - _mime_uri = MIME_PATH, - _stat_uri = STAT_PATH; - if (_arc == 2) - check_argv_str(_conf_uri, _mime_uri, _stat_uri, _arv[2]); - if (_arc == 3) - check_argv_str(_conf_uri, _mime_uri, _stat_uri, _arv[3]); - if (_arc == 4) - check_argv_str(_conf_uri, _mime_uri, _stat_uri, _arv[4]); - else if (_arc != 1) - throw ErrorHandler(__FILE__, __func__, __LINE__, - "Too many arguments. Please input one ~ three, or just nothing."); - _config.startConfig(_conf_uri); - _mime.startConfig(_mime_uri); - _status.startConfig(_stat_uri); - ServerProcess::serverProcess(); - } - catch (const ErrorHandler& err) - { - std::cerr << err.what() << std::endl; - return (-1); - } - return (0); -} diff --git a/static_html/403.html b/static_html/403.html index aa63b66..8d8080d 100644 --- a/static_html/403.html +++ b/static_html/403.html @@ -3,6 +3,6 @@

403 Forbidden

-
hybae
+
diff --git a/static_html/404.html b/static_html/404.html index d1ba790..c1ea9b2 100644 --- a/static_html/404.html +++ b/static_html/404.html @@ -3,6 +3,6 @@

404 Not Found

-
hybae
+
diff --git a/static_html/defaul_error.html b/static_html/defaul_error.html index d859c61..3dc144a 100644 --- a/static_html/defaul_error.html +++ b/static_html/defaul_error.html @@ -3,6 +3,6 @@

DEFAULT ERROR PAGE

-
skim
+
diff --git a/webserv.cpp b/webserv.cpp new file mode 100644 index 0000000..ca0c4d7 --- /dev/null +++ b/webserv.cpp @@ -0,0 +1,54 @@ +#include "ConfigBlocks.hpp" +#include "ConfigMime.hpp" +#include "ConfigStatus.hpp" +#include "SocketController.hpp" +#include "ServerProcess.hpp" +#include "KernelQueueController.hpp" +#include "ErrorHandler.hpp" +#include "ErrorPageController.hpp" + +#include +#include + +#define CONF_PATH "./setting/nginx.conf" +#define MIME_PATH "./setting/mime.types" +#define STAT_PATH "./setting/status_code.txt" + +NginxConfig::GlobalConfig _config; +extern NginxConfig::GlobalConfig _config; + +MimeConfig _mime; +extern MimeConfig _mime; + +StatusConfig _status; +extern StatusConfig _status; + +ErrorPageController _error_page; + +void check_argv_str (std::string& _conf_uri, std::string _tmp) { + if (_tmp.substr(_tmp.length() - 5, _tmp.length()).compare(".conf") == 0) + _conf_uri = _tmp; + else + throw ErrorHandler(__FILE__, __func__, __LINE__, std::string("Invalid file name on argument(.conf, .types and .txt only) : " + _tmp)); +} + +int main(int argc, char** argv) { + try { + std::string _conf_uri = CONF_PATH; + std::string _mime_uri = MIME_PATH; + std::string _stat_uri = STAT_PATH; + if (argc == 2) + check_argv_str(_conf_uri, argv[1]); + else if (argc != 1) + throw ErrorHandler(__FILE__, __func__, __LINE__, "Too many arguments. Please input one ~ three, or just nothing."); + _config.startConfig(_conf_uri); + _mime.startConfig(_mime_uri); + _status.startConfig(_stat_uri); + ServerProcess::serverProcess(); + } + catch (const ErrorHandler& err) { + std::cerr << err.what() << std::endl; + return (-1); + } + return (0); +} diff --git a/webserv.drawio b/webserv.drawio new file mode 100644 index 0000000..a3d49be --- /dev/null +++ b/webserv.drawio @@ -0,0 +1 @@ +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 \ No newline at end of file