
#include "Webserv.hpp"

void	Webserv::init_virtual_servers(std::vector<ServerConfig>* servers)
{
	int	ret;
	std::vector<std::string>	open_sockets;
	struct listen_socket		new_socket;
	std::string					host_port;

	_servers = *servers;
	_listen_sockets.clear();
	std::vector<ServerConfig>::iterator	it = _servers.begin();

	while (it != _servers.end())
	{
		host_port.clear();
		host_port.append(it->host);
		host_port.append(":");
		host_port.append(it->port);
		if ( std::find(open_sockets.begin(), open_sockets.end(), host_port) != open_sockets.end() )
		{
			++it;
			continue;
		}

		ret = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); // (SOCK_CLOEXEC) for CGI fork ?
		if (ret == -1)
		{
			std::perror("err socket()");
			throw std::runtime_error("Socket init");
		}
		new_socket.fd = ret;
		new_socket.host = it->host;
		new_socket.port = it->port;
		_listen_sockets.push_back(new_socket);

		// HUGO ADD
		//
		// allow socket descriptor to be reuseable
		// I just copied it from https://www.ibm.com/docs/en/i/7.2?topic=designs-example-nonblocking-io-select
		int	on = 1;
		if (setsockopt(new_socket.fd, SOL_SOCKET,  SO_REUSEADDR, &on, sizeof(on)) < 0)
		{
			::perror("err setsockopt()");
			throw std::runtime_error("Socket init");
		}
		//
		// HUGO ADD END

		_bind(new_socket.fd, std::atoi(it->port.c_str()), it->host);
		_listen(new_socket.fd, 512); // 512 arbitrary

		if (_epoll_update(new_socket.fd, EPOLLIN, EPOLL_CTL_ADD) == -1)
			throw std::runtime_error("Socket init");
		
		open_sockets.push_back(host_port);
		++it;
	}
}

void	Webserv::_bind(int socket_fd, in_port_t port, std::string host)
{
	// cast invalid ? how to ?
	// const struct sockaddr* cast_test = static_cast<const struct sockaddr*>(addr);

	struct sockaddr_in	addr;
	std::memset(&addr, 0, sizeof addr);
	addr.sin_family = AF_INET;
	addr.sin_port = ::htons(port);
	addr.sin_addr.s_addr = ::htonl(::inet_addr(host.c_str()));
	// addr.sin_addr.s_addr = ::htonl(INADDR_ANY);  // htonl useless with 0 value (INADDR_ANY) ?

	if (::bind(socket_fd, (const sockaddr*)&addr, sizeof addr) == -1)
	{
		std::perror("err bind()");
		throw std::runtime_error("Socket bind");		
	}
}

void	Webserv::_listen(int socket_fd, unsigned int max_connections)
{
	if (::listen(socket_fd, max_connections) == -1)
	{
		std::perror("err listen()");
		throw std::runtime_error("Socket listen");
	}
}

void	Webserv::_init_http_status_map()
{
	_http_status[200] = S200;
	_http_status[201] = S201;
	_http_status[204] = S204;

	_http_status[400] = S400;
	_http_status[403] = S403;
	_http_status[404] = S404;
	_http_status[405] = S405;
	_http_status[413] = S413;

	_http_status[500] = S500;
	_http_status[501] = S501;
}

void	Webserv::_init_mime_types_map()
{
	_mime_types[""]			= "application/octet-stream";

	_mime_types["html"]		= "text/html";
	_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["txt"]		= "text/plain";
	_mime_types["jad"]		= "text/vnd.sun.j2me.app-descriptor";
	_mime_types["wml"]		= "text/vnd.wap.wml";
	_mime_types["htc"]		= "text/x-component";

	_mime_types["png"]		= "image/png";
	_mime_types["tif"]		= "image/tiff";
	_mime_types["tiff"]		= "image/tiff";
	_mime_types["wbmp"]		= "image/vnd.wap.wbmp";
	_mime_types["ico"]		= "image/x-icon";
	_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["jar"]		= "application/java-archive";
	_mime_types["war"]		= "application/java-archive";
	_mime_types["ear"]		= "application/java-archive";
	_mime_types["json"]		= "application/json";
	_mime_types["hqx"]		= "application/mac-binhex40";
	_mime_types["doc"]		= "application/msword";
	_mime_types["pdf"]		= "application/pdf";
	_mime_types["ps"]		= "application/postscript";
	_mime_types["eps"]		= "application/postscript";
	_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["exe"]		= "application/octet-stream";
	_mime_types["dll"]		= "application/octet-stream";
	_mime_types["deb"]		= "application/octet-stream";
	_mime_types["dmg"]		= "application/octet-stream";
	_mime_types["iso"]		= "application/octet-stream";
	_mime_types["img"]		= "application/octet-stream";
	_mime_types["msi"]		= "application/octet-stream";
	_mime_types["msp"]		= "application/octet-stream";
	_mime_types["msm"]		= "application/octet-stream";

	_mime_types["docx"]		= "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
	_mime_types["xlsx"]		= "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
	_mime_types["pptx"]		= "application/vnd.openxmlformats-officedocument.presentationml.presentation";

	_mime_types["mid"]		= "audio/midi";
	_mime_types["midi"]		= "audio/midi";
	_mime_types["kar"]		= "audio/midi";
	_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["3gp"]		= "video/3gpp";
	_mime_types["ts"]		= "video/mp2t";
	_mime_types["mp4"]		= "video/mp4";
	_mime_types["mpeg"]		= "video/mpeg";
	_mime_types["mpg"]		= "video/mpeg";
	_mime_types["mov"]		= "video/quicktime";
	_mime_types["webm"]		= "video/webm";
	_mime_types["flv"]		= "video/x-flv";
	_mime_types["m4v"]		= "video/x-m4v";
	_mime_types["mng"]		= "video/x-mng";
	_mime_types["asx"]		= "video/x-ms-asf";
	_mime_types["asf"]		= "video/x-ms-asf";
	_mime_types["wmv"]		= "video/x-ms-wmv";
	_mime_types["avi"]		= "video/x-msvideo";
}

