bad_alloc handling

+ map.insert() replace map.operator[] for init, more efficient
This commit is contained in:
LuckyLaszlo
2022-08-08 04:24:03 +02:00
parent 1ccf61bc68
commit 02cfdf43bc
8 changed files with 162 additions and 136 deletions

View File

@@ -1,9 +1,10 @@
IN 42 SUBJECT, PRIORITY : IN 42 SUBJECT, PRIORITY :
- chunked request (response not mandatory it seems)
- upload files with confif "upload_dir"
- 505 HTTP Version Not Supported - 505 HTTP Version Not Supported
- CGI - CGI
- handle redirection - handle redirection
- index and autoindex - index and autoindex
- gestion memoire en cas de bad_alloc
- Ecrire des tests ! - Ecrire des tests !
----------------------------- -----------------------------
- replace atoi() with a better function - replace atoi() with a better function
@@ -17,7 +18,6 @@ IN 42 SUBJECT, PRIORITY :
- add headers "Date" and "Last-Modified" to response - add headers "Date" and "Last-Modified" to response
- change "std::string" to reference "std::string &" in most functions - change "std::string" to reference "std::string &" in most functions
and add "const" if apropriate. and add "const" if apropriate.
- http_method en mode binary flags. "std::vector<http_method> allow_methods" -> "unsigned int allow_methods;"
- Dans le parsing, trier les "locations" par ordre de precision. - Dans le parsing, trier les "locations" par ordre de precision.
Compter les "/" dans le chemin, les locations avec le plus de "/" seront en premier dans le vector. Compter les "/" dans le chemin, les locations avec le plus de "/" seront en premier dans le vector.
- Il faut vérifier le path de la requête, voir si le serveur est bien censé délivrer cette ressource et si le client y a accès, avant d'appeler le CGI. - Il faut vérifier le path de la requête, voir si le serveur est bien censé délivrer cette ressource et si le client y a accès, avant d'appeler le CGI.

View File

@@ -44,7 +44,7 @@ int main(int ac, char **av)
} }
catch (std::exception& e) catch (std::exception& e)
{ {
std::cout << e.what() << '\n'; std::cerr << e.what() << '\n';
} }
return (0); return (0);

View File

@@ -1,6 +1,14 @@
#include "utils.hpp" #include "utils.hpp"
void throw_test()
{
static int i = 0;
++i;
if (i % 8 == 0)
throw std::bad_alloc();
}
std::vector<std::string> split(std::string input, char delimiter) std::vector<std::string> split(std::string input, char delimiter)
{ {
std::vector<std::string> answer; std::vector<std::string> answer;

View File

@@ -46,5 +46,6 @@ std::string trim(std::string str, char c);
http_method str_to_http_method(std::string &str); http_method str_to_http_method(std::string &str);
std::string http_methods_to_str(unsigned int methods); std::string http_methods_to_str(unsigned int methods);
void replace_all_substr(std::string &str, const std::string &ori_substr, const std::string &new_substr); void replace_all_substr(std::string &str, const std::string &ori_substr, const std::string &new_substr);
void throw_test();
#endif #endif

View File

@@ -89,135 +89,144 @@ void Webserv::_listen(int socket_fd, unsigned int max_connections)
void Webserv::_init_http_status_map() void Webserv::_init_http_status_map()
{ {
_http_status[200] = S200; /* "map.insert()" over "map.operator[]" :
_http_status[201] = S201; ** http://www.uml.org.cn/c%2B%2B/pdf/EffectiveSTL.pdf#page=93
_http_status[204] = S204; */
typedef std::map<int, std::string>::value_type status_pair;
_http_status[400] = S400; // _http_status.insert(std::make_pair(200, S200)); // equivalent
_http_status[403] = S403; _http_status.insert(status_pair(200, S200));
_http_status[404] = S404; _http_status.insert(status_pair(201, S201));
_http_status[405] = S405; _http_status.insert(status_pair(204, S204));
_http_status[413] = S413;
_http_status[500] = S500; _http_status.insert(status_pair(400, S400));
_http_status[501] = S501; _http_status.insert(status_pair(403, S403));
_http_status.insert(status_pair(404, S404));
_http_status.insert(status_pair(405, S405));
_http_status.insert(status_pair(413, S413));
_http_status.insert(status_pair(500, S500));
_http_status.insert(status_pair(501, S501));
} }
void Webserv::_init_mime_types_map() void Webserv::_init_mime_types_map()
{ {
/* /* From :
** From : http://nginx.org/en/docs/http/ngx_http_core_module.html#types ** http://nginx.org/en/docs/http/ngx_http_core_module.html#types
*/ */
_mime_types[""] = MIME_TYPE_DEFAULT; typedef std::map<std::string, std::string>::value_type mime_pair;
_mime_types["html"] = "text/html"; _mime_types.insert(mime_pair("", MIME_TYPE_DEFAULT));
_mime_types["htm"] = "text/html";
_mime_types["shtml"] = "text/html";
_mime_types["css"] = "text/css";
_mime_types["xml"] = "text/xml";
_mime_types["gif"] = "image/gif";
_mime_types["jpeg"] = "image/jpeg";
_mime_types["jpg"] = "image/jpeg";
_mime_types["js"] = "application/javascript";
_mime_types["atom"] = "application/atom+xml";
_mime_types["rss"] = "application/rss+xml";
_mime_types["mml"] = "text/mathml"; _mime_types.insert(mime_pair("html", "text/html"));
_mime_types["txt"] = "text/plain"; _mime_types.insert(mime_pair("html", "text/html"));
_mime_types["jad"] = "text/vnd.sun.j2me.app-descriptor"; _mime_types.insert(mime_pair("htm", "text/html"));
_mime_types["wml"] = "text/vnd.wap.wml"; _mime_types.insert(mime_pair("shtml", "text/html"));
_mime_types["htc"] = "text/x-component"; _mime_types.insert(mime_pair("css", "text/css"));
_mime_types.insert(mime_pair("xml", "text/xml"));
_mime_types.insert(mime_pair("gif", "image/gif"));
_mime_types.insert(mime_pair("jpeg", "image/jpeg"));
_mime_types.insert(mime_pair("jpg", "image/jpeg"));
_mime_types.insert(mime_pair("js", "application/javascript"));
_mime_types.insert(mime_pair("atom", "application/atom+xml"));
_mime_types.insert(mime_pair("rss", "application/rss+xml"));
_mime_types["png"] = "image/png"; _mime_types.insert(mime_pair("mml", "text/mathml"));
_mime_types["tif"] = "image/tiff"; _mime_types.insert(mime_pair("txt", "text/plain"));
_mime_types["tiff"] = "image/tiff"; _mime_types.insert(mime_pair("jad", "text/vnd.sun.j2me.app-descriptor"));
_mime_types["wbmp"] = "image/vnd.wap.wbmp"; _mime_types.insert(mime_pair("wml", "text/vnd.wap.wml"));
_mime_types["ico"] = "image/x-icon"; _mime_types.insert(mime_pair("htc", "text/x-component"));
_mime_types["jng"] = "image/x-jng";
_mime_types["bmp"] = "image/x-ms-bmp";
_mime_types["svg"] = "image/svg+xml";
_mime_types["svgz"] = "image/svg+xml";
_mime_types["webp"] = "image/webp";
_mime_types["woff"] = "application/font-woff"; _mime_types.insert(mime_pair("png", "image/png"));
_mime_types["jar"] = "application/java-archive"; _mime_types.insert(mime_pair("tif", "image/tiff"));
_mime_types["war"] = "application/java-archive"; _mime_types.insert(mime_pair("tiff", "image/tiff"));
_mime_types["ear"] = "application/java-archive"; _mime_types.insert(mime_pair("wbmp", "image/vnd.wap.wbmp"));
_mime_types["json"] = "application/json"; _mime_types.insert(mime_pair("ico", "image/x-icon"));
_mime_types["hqx"] = "application/mac-binhex40"; _mime_types.insert(mime_pair("jng", "image/x-jng"));
_mime_types["doc"] = "application/msword"; _mime_types.insert(mime_pair("bmp", "image/x-ms-bmp"));
_mime_types["pdf"] = "application/pdf"; _mime_types.insert(mime_pair("svg", "image/svg+xml"));
_mime_types["ps"] = "application/postscript"; _mime_types.insert(mime_pair("svgz", "image/svg+xml"));
_mime_types["eps"] = "application/postscript"; _mime_types.insert(mime_pair("webp", "image/webp"));
_mime_types["ai"] = "application/postscript";
_mime_types["rtf"] = "application/rtf";
_mime_types["m3u8"] = "application/vnd.apple.mpegurl";
_mime_types["xls"] = "application/vnd.ms-excel";
_mime_types["eot"] = "application/vnd.ms-fontobject";
_mime_types["ppt"] = "application/vnd.ms-powerpoint";
_mime_types["wmlc"] = "application/vnd.wap.wmlc";
_mime_types["kml"] = "application/vnd.google-earth.kml+xml";
_mime_types["kmz"] = "application/vnd.google-earth.kmz";
_mime_types["7z"] = "application/x-7z-compressed";
_mime_types["cco"] = "application/x-cocoa";
_mime_types["jardiff"] = "application/x-java-archive-diff";
_mime_types["jnlp"] = "application/x-java-jnlp-file";
_mime_types["run"] = "application/x-makeself";
_mime_types["pl"] = "application/x-perl";
_mime_types["pm"] = "application/x-perl";
_mime_types["prc"] = "application/x-pilot";
_mime_types["pdb"] = "application/x-pilot";
_mime_types["rar"] = "application/x-rar-compressed";
_mime_types["rpm"] = "application/x-redhat-package-manager";
_mime_types["sea"] = "application/x-sea";
_mime_types["swf"] = "application/x-shockwave-flash";
_mime_types["sit"] = "application/x-stuffit";
_mime_types["tcl"] = "application/x-tcl";
_mime_types["tk"] = "application/x-tcl";
_mime_types["der"] = "application/x-x509-ca-cert";
_mime_types["pem"] = "application/x-x509-ca-cert";
_mime_types["crt"] = "application/x-x509-ca-cert";
_mime_types["xpi"] = "application/x-xpinstall";
_mime_types["xhtml"] = "application/xhtml+xml";
_mime_types["xspf"] = "application/xspf+xml";
_mime_types["zip"] = "application/zip";
_mime_types["bin"] = "application/octet-stream"; _mime_types.insert(mime_pair("woff", "application/font-woff"));
_mime_types["exe"] = "application/octet-stream"; _mime_types.insert(mime_pair("jar", "application/java-archive"));
_mime_types["dll"] = "application/octet-stream"; _mime_types.insert(mime_pair("war", "application/java-archive"));
_mime_types["deb"] = "application/octet-stream"; _mime_types.insert(mime_pair("ear", "application/java-archive"));
_mime_types["dmg"] = "application/octet-stream"; _mime_types.insert(mime_pair("json", "application/json"));
_mime_types["iso"] = "application/octet-stream"; _mime_types.insert(mime_pair("hqx", "application/mac-binhex40"));
_mime_types["img"] = "application/octet-stream"; _mime_types.insert(mime_pair("doc", "application/msword"));
_mime_types["msi"] = "application/octet-stream"; _mime_types.insert(mime_pair("pdf", "application/pdf"));
_mime_types["msp"] = "application/octet-stream"; _mime_types.insert(mime_pair("ps", "application/postscript"));
_mime_types["msm"] = "application/octet-stream"; _mime_types.insert(mime_pair("eps", "application/postscript"));
_mime_types.insert(mime_pair("ai", "application/postscript"));
_mime_types.insert(mime_pair("rtf", "application/rtf"));
_mime_types.insert(mime_pair("m3u8", "application/vnd.apple.mpegurl"));
_mime_types.insert(mime_pair("xls", "application/vnd.ms-excel"));
_mime_types.insert(mime_pair("eot", "application/vnd.ms-fontobject"));
_mime_types.insert(mime_pair("ppt", "application/vnd.ms-powerpoint"));
_mime_types.insert(mime_pair("wmlc", "application/vnd.wap.wmlc"));
_mime_types.insert(mime_pair("kml", "application/vnd.google-earth.kml+xml"));
_mime_types.insert(mime_pair("kmz", "application/vnd.google-earth.kmz"));
_mime_types.insert(mime_pair("7z", "application/x-7z-compressed"));
_mime_types.insert(mime_pair("cco", "application/x-cocoa"));
_mime_types.insert(mime_pair("jardiff", "application/x-java-archive-diff"));
_mime_types.insert(mime_pair("jnlp", "application/x-java-jnlp-file"));
_mime_types.insert(mime_pair("run", "application/x-makeself"));
_mime_types.insert(mime_pair("pl", "application/x-perl"));
_mime_types.insert(mime_pair("pm", "application/x-perl"));
_mime_types.insert(mime_pair("prc", "application/x-pilot"));
_mime_types.insert(mime_pair("pdb", "application/x-pilot"));
_mime_types.insert(mime_pair("rar", "application/x-rar-compressed"));
_mime_types.insert(mime_pair("rpm", "application/x-redhat-package-manager"));
_mime_types.insert(mime_pair("sea", "application/x-sea"));
_mime_types.insert(mime_pair("swf", "application/x-shockwave-flash"));
_mime_types.insert(mime_pair("sit", "application/x-stuffit"));
_mime_types.insert(mime_pair("tcl", "application/x-tcl"));
_mime_types.insert(mime_pair("tk", "application/x-tcl"));
_mime_types.insert(mime_pair("der", "application/x-x509-ca-cert"));
_mime_types.insert(mime_pair("pem", "application/x-x509-ca-cert"));
_mime_types.insert(mime_pair("crt", "application/x-x509-ca-cert"));
_mime_types.insert(mime_pair("xpi", "application/x-xpinstall"));
_mime_types.insert(mime_pair("xhtml", "application/xhtml+xml"));
_mime_types.insert(mime_pair("xspf", "application/xspf+xml"));
_mime_types.insert(mime_pair("zip", "application/zip"));
_mime_types["docx"] = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; _mime_types.insert(mime_pair("bin", "application/octet-stream"));
_mime_types["xlsx"] = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; _mime_types.insert(mime_pair("exe", "application/octet-stream"));
_mime_types["pptx"] = "application/vnd.openxmlformats-officedocument.presentationml.presentation"; _mime_types.insert(mime_pair("dll", "application/octet-stream"));
_mime_types.insert(mime_pair("deb", "application/octet-stream"));
_mime_types.insert(mime_pair("dmg", "application/octet-stream"));
_mime_types.insert(mime_pair("iso", "application/octet-stream"));
_mime_types.insert(mime_pair("img", "application/octet-stream"));
_mime_types.insert(mime_pair("msi", "application/octet-stream"));
_mime_types.insert(mime_pair("msp", "application/octet-stream"));
_mime_types.insert(mime_pair("msm", "application/octet-stream"));
_mime_types["mid"] = "audio/midi"; _mime_types.insert(mime_pair("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"));
_mime_types["midi"] = "audio/midi"; _mime_types.insert(mime_pair("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
_mime_types["kar"] = "audio/midi"; _mime_types.insert(mime_pair("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"));
_mime_types["mp3"] = "audio/mpeg";
_mime_types["ogg"] = "audio/ogg";
_mime_types["m4a"] = "audio/x-m4a";
_mime_types["ra"] = "audio/x-realaudio";
_mime_types["3gpp"] = "video/3gpp"; _mime_types.insert(mime_pair("mid", "audio/midi"));
_mime_types["3gp"] = "video/3gpp"; _mime_types.insert(mime_pair("midi", "audio/midi"));
_mime_types["ts"] = "video/mp2t"; _mime_types.insert(mime_pair("kar", "audio/midi"));
_mime_types["mp4"] = "video/mp4"; _mime_types.insert(mime_pair("mp3", "audio/mpeg"));
_mime_types["mpeg"] = "video/mpeg"; _mime_types.insert(mime_pair("ogg", "audio/ogg"));
_mime_types["mpg"] = "video/mpeg"; _mime_types.insert(mime_pair("m4a", "audio/x-m4a"));
_mime_types["mov"] = "video/quicktime"; _mime_types.insert(mime_pair("ra", "audio/x-realaudio"));
_mime_types["webm"] = "video/webm";
_mime_types["flv"] = "video/x-flv"; _mime_types.insert(mime_pair("3gpp", "video/3gpp"));
_mime_types["m4v"] = "video/x-m4v"; _mime_types.insert(mime_pair("3gp", "video/3gpp"));
_mime_types["mng"] = "video/x-mng"; _mime_types.insert(mime_pair("ts", "video/mp2t"));
_mime_types["asx"] = "video/x-ms-asf"; _mime_types.insert(mime_pair("mp4", "video/mp4"));
_mime_types["asf"] = "video/x-ms-asf"; _mime_types.insert(mime_pair("mpeg", "video/mpeg"));
_mime_types["wmv"] = "video/x-ms-wmv"; _mime_types.insert(mime_pair("mpg", "video/mpeg"));
_mime_types["avi"] = "video/x-msvideo"; _mime_types.insert(mime_pair("mov", "video/quicktime"));
_mime_types.insert(mime_pair("webm", "video/webm"));
_mime_types.insert(mime_pair("flv", "video/x-flv"));
_mime_types.insert(mime_pair("m4v", "video/x-m4v"));
_mime_types.insert(mime_pair("mng", "video/x-mng"));
_mime_types.insert(mime_pair("asx", "video/x-ms-asf"));
_mime_types.insert(mime_pair("asf", "video/x-ms-asf"));
_mime_types.insert(mime_pair("wmv", "video/x-ms-wmv"));
_mime_types.insert(mime_pair("avi", "video/x-msvideo"));
} }

View File

@@ -11,7 +11,7 @@ void Webserv::_request(Client *client)
_handle_last_signal(); _handle_last_signal();
} }
void Webserv::_read_request(Client *client) void Webserv::_read_request(Client *client) // Messy, Need refactoring
{ {
char buf[BUFSIZE]; char buf[BUFSIZE];
ssize_t ret; ssize_t ret;

View File

@@ -15,7 +15,8 @@ void Webserv::_send_response(Client *client)
std::cerr << "send()\n"; std::cerr << "send()\n";
_append_base_headers(client); _append_base_headers(client);
_construct_response(client); if (!client->status)
_construct_response(client);
_insert_status_line(client); _insert_status_line(client);
if (client->status >= 400) if (client->status >= 400)
_error_html_response(client); _error_html_response(client);
@@ -181,7 +182,6 @@ void Webserv::_get_file(Client *client, const std::string &path)
// Then chunk // Then chunk
client->status = 500; // WIP temp client->status = 500; // WIP temp
std::cerr << "File too large for non chunk body\n"; std::cerr << "File too large for non chunk body\n";
ifd.close();
return ; return ;
} }
@@ -198,8 +198,6 @@ void Webserv::_get_file(Client *client, const std::string &path)
std::string file_ext = _determine_file_extension(path); std::string file_ext = _determine_file_extension(path);
_append_body(client, buf.str(), file_ext); _append_body(client, buf.str(), file_ext);
} }
ifd.close();
} }
} }
@@ -287,8 +285,6 @@ void Webserv::_post_file(Client *client, const std::string &path)
client->status = 201; client->status = 201;
// WIP https://www.rfc-editor.org/rfc/rfc9110.html#section-9.3.3-4 // WIP https://www.rfc-editor.org/rfc/rfc9110.html#section-9.3.3-4
} }
ofd.close();
} }
} }

View File

@@ -34,17 +34,29 @@ void Webserv::run()
i = 0; i = 0;
while (i < nfds) while (i < nfds)
{ {
// TODO : handle EPOLLERR and EPOLLHUP try
it_socket = std::find(_listen_sockets.begin(), _listen_sockets.end(), events[i].data.fd); {
if (it_socket != _listen_sockets.end() && events[i].events & EPOLLIN) // TODO : handle EPOLLERR and EPOLLHUP
_accept_connection(*it_socket); it_socket = std::find(_listen_sockets.begin(), _listen_sockets.end(), events[i].data.fd);
else if (events[i].events & EPOLLIN) if (it_socket != _listen_sockets.end() && events[i].events & EPOLLIN)
_request( &(*std::find(_clients.begin(), _clients.end(), events[i].data.fd)) ); _accept_connection(*it_socket);
else if (events[i].events & EPOLLOUT) else if (events[i].events & EPOLLIN)
_response( &(*std::find(_clients.begin(), _clients.end(), events[i].data.fd)) ); _request( &(*std::find(_clients.begin(), _clients.end(), events[i].data.fd)) );
++i; else if (events[i].events & EPOLLOUT)
if (!g_run) _response( &(*std::find(_clients.begin(), _clients.end(), events[i].data.fd)) );
++i;
if (!g_run)
break;
}
catch (const std::bad_alloc& e)
{
std::cerr << e.what() << '\n';
_close_all_clients();
/* Swap to free the memory
From : http://www.uml.org.cn/c%2B%2B/pdf/EffectiveSTL.pdf#page=66 */
std::vector<Client>().swap(_clients);
break; break;
}
} }
} }
} }