Skip to content

Commit

Permalink
feat(error-handling): added debug message macro
Browse files Browse the repository at this point in the history
- now error messages print the file and line
  • Loading branch information
Taanviir committed Apr 15, 2024
1 parent ec5eb21 commit f86bc0c
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 45 deletions.
7 changes: 7 additions & 0 deletions includes/webserv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ typedef vector<pair<string, string> > vsp;
// socket_descriptor type
typedef int fd;
/* ----------------------------- ERROR MESSAGES ----------------------------- */
#define THROW_EXCEPTION_WITH_INFO(msg) \
do { \
std::ostringstream oss; \
oss << __FILE__ << ":" << __LINE__ << ": " << R << "error: " << RE << (msg); \
throw std::runtime_error(oss.str()); \
} while (0)

static std::string ERR_NULL("Socket: null ptr error");
static std::string ERR_CREAT("Socket: creation failed");
static std::string ERR_BIND("Socket: binding failed");
Expand Down
2 changes: 1 addition & 1 deletion sources/http/handler/RequestHandlerFactory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class RequestHandlerFactory
switch (m)
{
case GET: return new GetRequestHandler;
default: throw runtime_error("Request Method not implemented\n");
default: THROW_EXCEPTION_WITH_INFO("Request Method not implemented\n");
}
}
};
Expand Down
2 changes: 1 addition & 1 deletion sources/http/request/Request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Request::Request(const string &rawRequest)
}
catch (std::ios_base::failure &f)
{
throw runtime_error("Invalid request\n");
THROW_EXCEPTION_WITH_INFO("Invalid request\n");
}
}

Expand Down
2 changes: 1 addition & 1 deletion sources/http/response/Response.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ void Response::send_response(fd recv_socket) const
{
result = send(recv_socket, &message[bytesSent], message.size() - bytesSent, 0);
if (result == -1)
throw runtime_error(ERR_SEND_FAIL + strerror(errno));
THROW_EXCEPTION_WITH_INFO(ERR_SEND_FAIL + strerror(errno));
bytesSent += result;
}
}
Expand Down
9 changes: 5 additions & 4 deletions sources/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
#include "../includes/webserv.hpp"

int main(int argc, char **argv) {
if (argc > 2) {
std::cerr << "Usage: " << argv[0] << " [<config_file>]" << std::endl;
if (argc > 2)
{
cerr << "Usage: " << argv[0] << " [<config_file>]" << endl;
exit(1);
}

Expand All @@ -18,8 +19,8 @@ int main(int argc, char **argv) {
Server &webserv = Server::get_instance(configs[0], 10);
webserv.start(SELECT);
}
catch (std::exception &e)
catch (std::exception &error)
{
std::cerr << e.what();
cerr << error.what() << endl;
}
}
68 changes: 34 additions & 34 deletions sources/parser/ConfigParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ ConfigParser::ConfigParser(string const& configFile) {

// checking file extension
if (configFile.find(".conf") == string::npos)
throw runtime_error(ERR_INVALID_FILE);
THROW_EXCEPTION_WITH_INFO(ERR_INVALID_FILE);

// check if file exists and is a regular file
struct stat fileStat;
if (stat(configFile.c_str(), &fileStat) == -1 || !S_ISREG(fileStat.st_mode))
throw runtime_error(ERR_STAT);
THROW_EXCEPTION_WITH_INFO(ERR_STAT);

// open file
ifstream file(configFile.c_str());
if (!file.is_open())
throw runtime_error(ERR_OPEN);
THROW_EXCEPTION_WITH_INFO(ERR_OPEN);
else if (file.peek() == ifstream::traits_type::eof()) // check if file is empty
throw runtime_error(ERR_EMPTY);
THROW_EXCEPTION_WITH_INFO(ERR_EMPTY);

string line;
while (std::getline(file, line)) {
Expand All @@ -44,32 +44,32 @@ void ConfigParser::_parse_error_page(map<STATUS_CODE, string>& errorPages, strin
DEBUG_MSG("Parsing error_page directive", RE);

if (root.empty())
throw runtime_error(ERR_MISSING_ROOT);
THROW_EXCEPTION_WITH_INFO(ERR_MISSING_ROOT);

++_itr; // move to error code
if (*_itr == ";")
throw runtime_error(ERR_ERROR_CODE);
THROW_EXCEPTION_WITH_INFO(ERR_ERROR_CODE);

vector<STATUS_CODE> codes;
while (_is_string_number(*_itr)) {
codes.push_back(static_cast<STATUS_CODE>(std::atoi(_itr->c_str())));
++_itr; // move to next error code
}
if (*_itr == ";")
throw runtime_error(ERR_ERROR_PATH);
THROW_EXCEPTION_WITH_INFO(ERR_ERROR_PATH);

string errorPath = *_itr;
if (errorPath.find(".html") == string::npos &&
errorPath.find(".htm") == string::npos &&
errorPath.find(".txt") == string::npos)
throw runtime_error(ERR_INVALID_ERROR_PATH);
THROW_EXCEPTION_WITH_INFO(ERR_INVALID_ERROR_PATH);
if (errorPath.find("/") == string::npos)
throw runtime_error(ERR_INVALID_ERROR_PATH);
THROW_EXCEPTION_WITH_INFO(ERR_INVALID_ERROR_PATH);
else if (errorPath.find_first_of("/") != errorPath.find_last_of("/"))
throw runtime_error(ERR_INVALID_ERROR_PATH);
THROW_EXCEPTION_WITH_INFO(ERR_INVALID_ERROR_PATH);
if (errorPath.find("x") == string::npos) {
if (errorPath.find_first_of("x") != errorPath.find_last_of("x"))
throw runtime_error(ERR_INVALID_ERROR_PATH);
THROW_EXCEPTION_WITH_INFO(ERR_INVALID_ERROR_PATH);
}

for (vector<STATUS_CODE>::const_iterator itr = codes.begin(); itr != codes.end(); ++itr) {
Expand All @@ -90,12 +90,12 @@ vector<string> ConfigParser::_parse_index(string const& root) {
vector<string> indexFiles;

if (root.empty())
throw runtime_error(ERR_MISSING_ROOT);
THROW_EXCEPTION_WITH_INFO(ERR_MISSING_ROOT);

++_itr; // move to index file
while (*_itr != ";") {
if (_is_keyword(*_itr))
throw runtime_error(ERR_INVALID_INDEX);
THROW_EXCEPTION_WITH_INFO(ERR_INVALID_INDEX);
indexFiles.push_back(root + "/" + *_itr);
++_itr;
}
Expand All @@ -108,7 +108,7 @@ Location ConfigParser::_parse_location_context(void) {

++_itr; // move to location modifier/path
if (*_itr == "{")
throw runtime_error(ERR_INVALID_LOCATION);
THROW_EXCEPTION_WITH_INFO(ERR_INVALID_LOCATION);

Location location;
if (*_itr == "=" || *_itr == "~") {
Expand All @@ -119,7 +119,7 @@ Location ConfigParser::_parse_location_context(void) {

++_itr; // move to {
if (*_itr != "{")
throw runtime_error(ERR_INVALID_LOCATION);
THROW_EXCEPTION_WITH_INFO(ERR_INVALID_LOCATION);
++_itr; // move to location content

while (*_itr != "}") {
Expand All @@ -131,7 +131,7 @@ Location ConfigParser::_parse_location_context(void) {
location.indexFiles = _parse_index(location.root);
else {
cout << *_itr << endl;
throw runtime_error(ERR_UNEXPECTED_TOKENS_IN_LOCATION);
THROW_EXCEPTION_WITH_INFO(ERR_UNEXPECTED_TOKENS_IN_LOCATION);
}
++_itr;
}
Expand All @@ -145,14 +145,14 @@ fd ConfigParser::_parse_listen(void) {

++_itr; // move to port number
if (*(_itr + 1) != ";")
throw runtime_error(ERR_MISSING_SEMICOLON);
THROW_EXCEPTION_WITH_INFO(ERR_MISSING_SEMICOLON);

if (!_is_string_number(*_itr))
throw runtime_error(ERR_INVALID_LISTEN);
THROW_EXCEPTION_WITH_INFO(ERR_INVALID_LISTEN);

fd listenerPort = std::atoi(_itr->c_str()); //! listen can also handle IP address like 0.0.0.0:80
if (listenerPort > MAX_PORT || listenerPort < 0)
throw runtime_error(ERR_INVALID_LISTEN);
THROW_EXCEPTION_WITH_INFO(ERR_INVALID_LISTEN);

_check_semicolon();
return listenerPort;
Expand All @@ -164,7 +164,7 @@ void ConfigParser::_parse_server_name(vector<string>& serverName) {
++_itr; // move to server name
while (*_itr != ";") {
if (_is_keyword(*_itr))
throw runtime_error(ERR_INVALID_SERVER_NAME);
THROW_EXCEPTION_WITH_INFO(ERR_INVALID_SERVER_NAME);
serverName.push_back(*_itr);
++_itr;
}
Expand All @@ -175,7 +175,7 @@ string ConfigParser::_parse_root(void) {

++_itr; // move to root path
if (*(_itr + 1) != ";")
throw runtime_error(ERR_MISSING_SEMICOLON);
THROW_EXCEPTION_WITH_INFO(ERR_MISSING_SEMICOLON);

string rootPath = *_itr;
_check_semicolon();
Expand All @@ -188,13 +188,13 @@ string ConfigParser::_parse_client_max_body_size(void) {

++_itr; // move to max body size
if (*(_itr + 1) != ";")
throw runtime_error(ERR_MISSING_SEMICOLON);
THROW_EXCEPTION_WITH_INFO(ERR_MISSING_SEMICOLON);

string maxBodySize = *_itr; //! need to handle suffixes like 1m, 1k, 1g
if (maxBodySize.find_first_not_of("0123456789kKmMgG") != string::npos)
throw runtime_error(ERR_INVALID_BODY_SIZE);
THROW_EXCEPTION_WITH_INFO(ERR_INVALID_BODY_SIZE);
else if (maxBodySize.find_first_of("0123456789") == string::npos)
throw runtime_error(ERR_INVALID_BODY_SIZE);
THROW_EXCEPTION_WITH_INFO(ERR_INVALID_BODY_SIZE);

_check_semicolon();

Expand All @@ -207,7 +207,7 @@ bool ConfigParser::_parse_autoindex(void) {
++_itr; // move to on/off
string autoindex = *_itr;
if (autoindex != "on" && autoindex != "off")
throw runtime_error(ERR_INVALID_AUTOINDEX);
THROW_EXCEPTION_WITH_INFO(ERR_INVALID_AUTOINDEX);
_check_semicolon();
return autoindex == "on";
}
Expand All @@ -217,7 +217,7 @@ ServerConfig ConfigParser::_parse_server_context(void) {

++_itr; // move to {
if (*_itr != "{")
throw runtime_error(ERR_OPENINING_BRACE);
THROW_EXCEPTION_WITH_INFO(ERR_OPENINING_BRACE);
++_itr; // move to first directive

ServerConfig _serverConfig;
Expand All @@ -239,7 +239,7 @@ ServerConfig ConfigParser::_parse_server_context(void) {
else if (*_itr == "autoindex")
_serverConfig.autoindex = _parse_autoindex();
else
throw runtime_error(ERR_UNEXPECTED_TOKENS_IN_SERVER);
THROW_EXCEPTION_WITH_INFO(ERR_UNEXPECTED_TOKENS_IN_SERVER);
if (*_itr == ";")
++_itr;
}
Expand All @@ -253,24 +253,24 @@ vector<ServerConfig> ConfigParser::_parse_HTTP_context(void) {
// setting values for Config object
_itr = _tokens.begin();
if (*_itr != "http") //! maybe there's stuff in the global context
throw runtime_error(ERR_MISSING_HTTP);
THROW_EXCEPTION_WITH_INFO(ERR_MISSING_HTTP);

++_itr; // move to {
if (*_itr != "{")
throw runtime_error(ERR_OPENINING_BRACE);
THROW_EXCEPTION_WITH_INFO(ERR_OPENINING_BRACE);
++_itr; // move to first directive

vector<ServerConfig> serverConfigs;
while (*_itr != "}") {
if (*_itr == "server")
serverConfigs.push_back(_parse_server_context());
else
throw runtime_error(ERR_UNEXPECTED_TOKENS_IN);
THROW_EXCEPTION_WITH_INFO(ERR_UNEXPECTED_TOKENS_IN);
++_itr;
}

if ((_itr + 1) != _tokens.end())
throw runtime_error(ERR_UNEXPECTED_TOKENS_OUT);
THROW_EXCEPTION_WITH_INFO(ERR_UNEXPECTED_TOKENS_OUT);

return serverConfigs;
}
Expand Down Expand Up @@ -303,17 +303,17 @@ vector<ServerConfig> ConfigParser::parse(void) {
if (*itr == "{") {
if (*(itr - 1) != "server" && *(itr - 1) != "http" &&
*(itr - 2) != "location" && *(itr - 3) != "location")
throw runtime_error(ERR_MISSING_CONTEXT);
THROW_EXCEPTION_WITH_INFO(ERR_MISSING_CONTEXT);
braces.push("{");
}
else if (*itr == "}") {
if (braces.empty()) // missing opening brace
throw runtime_error(ERR_OPENINING_BRACE);
THROW_EXCEPTION_WITH_INFO(ERR_OPENINING_BRACE);
braces.pop();
}
}
if (!braces.empty()) // missing closing brace
throw runtime_error(ERR_CLOSING_BRACE);
THROW_EXCEPTION_WITH_INFO(ERR_CLOSING_BRACE);

return _parse_HTTP_context();
}
2 changes: 1 addition & 1 deletion sources/parser/ConfigParser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class ConfigParser {
}
void _check_semicolon(void) {
if (*(_itr + 1) != ";")
throw runtime_error(ERR_MISSING_SEMICOLON);
THROW_EXCEPTION_WITH_INFO(ERR_MISSING_SEMICOLON);
++_itr; // move to semicolon
}
};
Expand Down
6 changes: 3 additions & 3 deletions sources/server/Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ bool Server::handle_connection(fd recvSocket)
bytesReceived = recv(recvSocket, &buffer[0], BUFFER_SIZE, 0);

if (bytesReceived == -1)
throw runtime_error(strerror(errno));
THROW_EXCEPTION_WITH_INFO(strerror(errno));

if (bytesReceived == 0)
return CLOSE_CONNECTION;
Expand Down Expand Up @@ -134,7 +134,7 @@ void Server::select_strat()
readytoRead = activeSockets;

if (select(maxSocketDescriptor + 1, &readytoRead, NULL, NULL, &selectTimeOut) < 0)
throw runtime_error(strerror(errno));
THROW_EXCEPTION_WITH_INFO(strerror(errno));
selectTimeOut.tv_sec = SELECTWAITTIME;

for (fd currentSocket = 0; currentSocket <= maxSocketDescriptor; currentSocket++)
Expand Down Expand Up @@ -177,6 +177,6 @@ void Server::start(enum polling_strat strategy)
// case KQUEUE: kqueue_strat(); break;
// case POLL: poll_strat(); break;
// case EPOLL: epoll_strat(); break;
default: throw runtime_error("Invalid strategy"); break;
default: THROW_EXCEPTION_WITH_INFO("Invalid strategy"); break;
}
}

0 comments on commit f86bc0c

Please sign in to comment.