/** * @file TcpipServer.cpp * @author Tomas Urban * @version 0.3 * @date 23/07/2009 */ #include "TcpipServer.h" #include #include #include #include "Logger/Logger.h" using namespace std; TcpipServer::TcpipServer(void) : m_hListeningSocket (SOCKET_CALL_ERROR) { } TcpipServer::~TcpipServer(void) { } void TcpipServer::Run(int nPort) { signal(SIGINT, OnExit); Logger::Instance().LogDebug("Initializing TCP/IP connection..."); // create socket and start listening struct sockaddr_in srvAddr; memset(&srvAddr, 0, sizeof srvAddr); srvAddr.sin_family = AF_INET; srvAddr.sin_addr.s_addr = INADDR_ANY; srvAddr.sin_port = htons(nPort); if ( (m_hListeningSocket = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_CALL_ERROR ) { Logger::Instance().LogError("Error creating listening socket"); return; } Logger::Instance().LogDebug("Listening socket successfully created"); if (bind(m_hListeningSocket, reinterpret_cast (&srvAddr), sizeof(srvAddr)) != 0) { Logger::Instance().LogError("Error binding listening socket; the port is probably used by other process"); return; } Logger::Instance().LogDebug("Listening socket successfully bound"); if (listen(m_hListeningSocket, 0) != 0 ) { Logger::Instance().LogError("Listening operation failed"); return; } std::string s = "Waiting for connection request on port "; s += boost::lexical_cast(nPort); s += "..."; Logger::Instance().LogInfo(s); struct sockaddr_in clientAddr; while (-1) { int nLen = sizeof(clientAddr); SOCKET_TYPE sock = accept( m_hListeningSocket, reinterpret_cast(&clientAddr), &nLen); if (sock == SOCKET_CALL_ERROR) break; Logger::Instance().LogInfo("Connection accepted"); Logger::Instance().LogDebug("Starting socket thread..."); ConnectionHandler handler(sock); boost::thread thread(handler); } OnExit(); } TcpipServer::ConnectionHandler::ConnectionHandler(SOCKET_TYPE hSocket) : m_hSocket(hSocket) { } void TcpipServer::ConnectionHandler::operator()() { Logger::Instance().LogDebug("Socket thread started successfully"); ConnectionController cc(m_hSocket); { boost::mutex::scoped_lock lock(TcpipServer::Instance().m_mutex); TcpipServer::Instance().m_lActiveControllers.push_back(&cc); } cc.Run(); { boost::mutex::scoped_lock lock(TcpipServer::Instance().m_mutex); TcpipServer::Instance().m_lActiveControllers.remove(&cc); if (m_hSocket != SOCKET_CALL_ERROR) { CLOSE_SOCKET(m_hSocket); m_hSocket = SOCKET_CALL_ERROR; } Logger::Instance().LogDebug("Socket thread terminated"); TcpipServer::Instance().m_operationEnded.notify_one(); } } void TcpipServer::OnExit() { if (m_hListeningSocket != SOCKET_CALL_ERROR) { { boost::mutex::scoped_lock lock(m_mutex); for(std::list::iterator it = m_lActiveControllers.begin(); it != m_lActiveControllers.end(); it++) (*it)->Stop(); } // wait for threads to quit while (-1) { boost::mutex::scoped_lock cond(m_mutex); if (m_lActiveControllers.begin() == m_lActiveControllers.end()) break; m_operationEnded.wait(cond); } CLOSE_SOCKET(m_hListeningSocket); m_hListeningSocket = SOCKET_CALL_ERROR; Logger::Instance().LogDebug("Listening socket closed"); } } void TcpipServer::OnExit(int nSig) { Instance().OnExit(); }