#include "Poll.hpp" #include "Logger.hpp" #include "Common.hpp" #include #include Poll::Poll( StreamConnection *connection, const nfds_t maxClient, const int timeOut ) : m_timeOut(timeOut) , m_connection(connection) , m_polling(false) , m_connections() , m_maxclients(maxClient) , m_fds(0) , m_num_of_fds(0) { TRACE; m_fds = new pollfd[m_maxclients+1]; // plus the server socket addFd( m_connection->getSocket(), POLLIN | POLLPRI ); } Poll::~Poll() { TRACE; delete[] m_fds; } void Poll::startPolling() { TRACE; m_polling = true; while ( m_polling ) { int ret = poll( m_fds , m_maxclients, m_timeOut); if ( ret == -1 ) { LOG( Logger::ERR, errnoToString("ERROR polling. ").c_str() ); /// @todo reconnect at client case? return; } if ( ret != 0 ) { // not timeout for ( nfds_t i = 0; i < m_num_of_fds; ++i ) if ( m_fds[i].revents != 0 ) m_fds[i].fd == m_connection->getSocket() ? acceptClient() : handleClient(m_fds[i].fd); } removeTimeoutedConnections(); } // while } void Poll::stopPolling() { TRACE; m_polling = false; } bool Poll::isPolling() const { TRACE; return m_polling; } void Poll::acceptClient() { TRACE; int client_socket = -1; if ( !m_connection->accept( client_socket ) ) return; StreamConnection *streamConnection = dynamic_cast( m_connection->clone(client_socket)); LOG_BEGIN(Logger::INFO) LOG_PROP("host", streamConnection->getHost()) LOG_PROP("port", streamConnection->getPort()) LOG_PROP("socket", client_socket) LOG_END("New client connected."); m_connections[client_socket] = streamConnection; addFd( client_socket, POLLIN | POLLPRI ); } void Poll::handleClient( const int socket ) { TRACE; ConnectionMap::iterator it = m_connections.find(socket); if (it == m_connections.end()) { LOG_BEGIN(Logger::ERR) LOG_SPROP(socket) LOG_END("Socket not found in map."); return; } if (!it->second->receive()) removeConnection(socket, it); } void Poll::removeTimeoutedConnections() { // TRACE; // // if (m_connections.empty()) // return; // // ConnectionMap::iterator it; // for (it = m_connections.begin(); it != m_connections.end(); ) // // /// @bug pull up closed() from TcpConnection to StreamConnection? // if (it->second->closed()) { // it = removeConnection(it->second->getSocket(), it); // } else { // ++it; // } } Poll::ConnectionMap::iterator Poll::removeConnection(int socket, std::map< int, StreamConnection* >::iterator it) { TRACE; ConnectionMap::iterator next = it; next++; removeFd(socket); delete it->second; m_connections.erase(it); return next; } bool Poll::addFd( const int socket, const short events ) { TRACE; LOG_BEGIN(Logger::DEBUG) LOG_SPROP(socket) LOG_END("Adding socket."); if (m_num_of_fds >= m_maxclients ) return false; m_fds[m_num_of_fds].fd = socket; m_fds[m_num_of_fds].events = events; m_fds[m_num_of_fds].revents = 0; m_num_of_fds++; return true; } bool Poll::removeFd( const int socket ) { TRACE; LOG_BEGIN(Logger::DEBUG) LOG_SPROP(socket) LOG_END("Removing socket."); unsigned int i = 0 ; while (i < m_maxclients && m_fds[i].fd != socket ) i++; if ( i == m_maxclients ) return false; for ( ; i < m_maxclients - 1; ++i ) m_fds[i] = m_fds[i+1] ; m_fds[i].fd = 0 ; m_fds[i].events = 0 ; m_fds[i].revents = 0 ; m_num_of_fds--; return true; }