#include "Server.h" #include #include #include #include namespace MailServer { Server::Server(asio::io_service& ioService, unsigned short port, const std::string& path, const std::string& url) : m_ioService(ioService), m_signal(ioService, SIGCHLD), m_acceptor(ioService, asio::ip::tcp::endpoint(asio::ip::tcp::v4(), port)), m_socket(ioService) { m_context.path = path; m_context.url = url; StartSignalWait(); StartAccept(); } void Server::StartSignalWait() { m_signal.async_wait(std::bind(&Server::HandleSignalWait, this)); } void Server::HandleSignalWait() { // Only the parent process should check for this signal. We can determine // whether we are in the parent by checking if the acceptor is still open. if (m_acceptor.is_open()) { // Reap completed child processes so that we don't end up with zombies. int status = 0; while (waitpid(-1, &status, WNOHANG) > 0) {} StartSignalWait(); } } void Server::StartAccept() { m_connection.reset(new Connection(m_ioService, m_context)); m_acceptor.async_accept(m_connection->Socket(), std::bind(&Server::HandleAccept, this, std::placeholders::_1)); } void Server::HandleAccept(const asio::error_code& ec) { if (!ec) { m_ioService.notify_fork(asio::io_service::fork_prepare); if (fork() == 0) { m_ioService.notify_fork(asio::io_service::fork_child); m_acceptor.close(); m_signal.cancel(); m_connection->Start(); } else { m_ioService.notify_fork(asio::io_service::fork_parent); m_connection.reset(); m_socket.close(); StartAccept(); } } else { std::stringstream ss; ss << "Server::HandleAccept() - Error" << std::endl; Logging::Log(Logging::Severity::Error, ss.str()); StartAccept(); } } } // namespace MailServer