1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 2e5c31af7Sopenharmony_ci * drawElements Quality Program Execution Server 3e5c31af7Sopenharmony_ci * --------------------------------------------- 4e5c31af7Sopenharmony_ci * 5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project 6e5c31af7Sopenharmony_ci * 7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 10e5c31af7Sopenharmony_ci * 11e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 12e5c31af7Sopenharmony_ci * 13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 17e5c31af7Sopenharmony_ci * limitations under the License. 18e5c31af7Sopenharmony_ci * 19e5c31af7Sopenharmony_ci *//*! 20e5c31af7Sopenharmony_ci * \file 21e5c31af7Sopenharmony_ci * \brief TCP Server. 22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 23e5c31af7Sopenharmony_ci 24e5c31af7Sopenharmony_ci#include "xsTcpServer.hpp" 25e5c31af7Sopenharmony_ci 26e5c31af7Sopenharmony_ci#include <algorithm> 27e5c31af7Sopenharmony_ci#include <iterator> 28e5c31af7Sopenharmony_ci#include <cstdio> 29e5c31af7Sopenharmony_ci 30e5c31af7Sopenharmony_cinamespace xs 31e5c31af7Sopenharmony_ci{ 32e5c31af7Sopenharmony_ci 33e5c31af7Sopenharmony_ciTcpServer::TcpServer (deSocketFamily family, int port) 34e5c31af7Sopenharmony_ci : m_socket() 35e5c31af7Sopenharmony_ci{ 36e5c31af7Sopenharmony_ci de::SocketAddress address; 37e5c31af7Sopenharmony_ci address.setFamily(family); 38e5c31af7Sopenharmony_ci address.setPort(port); 39e5c31af7Sopenharmony_ci address.setType(DE_SOCKETTYPE_STREAM); 40e5c31af7Sopenharmony_ci address.setProtocol(DE_SOCKETPROTOCOL_TCP); 41e5c31af7Sopenharmony_ci 42e5c31af7Sopenharmony_ci m_socket.listen(address); 43e5c31af7Sopenharmony_ci m_socket.setFlags(DE_SOCKET_CLOSE_ON_EXEC); 44e5c31af7Sopenharmony_ci} 45e5c31af7Sopenharmony_ci 46e5c31af7Sopenharmony_civoid TcpServer::runServer (void) 47e5c31af7Sopenharmony_ci{ 48e5c31af7Sopenharmony_ci de::Socket* clientSocket = DE_NULL; 49e5c31af7Sopenharmony_ci de::SocketAddress clientAddr; 50e5c31af7Sopenharmony_ci 51e5c31af7Sopenharmony_ci while ((clientSocket = m_socket.accept(clientAddr)) != DE_NULL) 52e5c31af7Sopenharmony_ci { 53e5c31af7Sopenharmony_ci ConnectionHandler* handler = DE_NULL; 54e5c31af7Sopenharmony_ci 55e5c31af7Sopenharmony_ci try 56e5c31af7Sopenharmony_ci { 57e5c31af7Sopenharmony_ci handler = createHandler(clientSocket, clientAddr); 58e5c31af7Sopenharmony_ci } 59e5c31af7Sopenharmony_ci catch (...) 60e5c31af7Sopenharmony_ci { 61e5c31af7Sopenharmony_ci delete clientSocket; 62e5c31af7Sopenharmony_ci throw; 63e5c31af7Sopenharmony_ci } 64e5c31af7Sopenharmony_ci 65e5c31af7Sopenharmony_ci try 66e5c31af7Sopenharmony_ci { 67e5c31af7Sopenharmony_ci addLiveConnection(handler); 68e5c31af7Sopenharmony_ci } 69e5c31af7Sopenharmony_ci catch (...) 70e5c31af7Sopenharmony_ci { 71e5c31af7Sopenharmony_ci delete handler; 72e5c31af7Sopenharmony_ci throw; 73e5c31af7Sopenharmony_ci } 74e5c31af7Sopenharmony_ci 75e5c31af7Sopenharmony_ci // Start handler. 76e5c31af7Sopenharmony_ci handler->start(); 77e5c31af7Sopenharmony_ci 78e5c31af7Sopenharmony_ci // Perform connection list cleanup. 79e5c31af7Sopenharmony_ci deleteDoneConnections(); 80e5c31af7Sopenharmony_ci } 81e5c31af7Sopenharmony_ci 82e5c31af7Sopenharmony_ci // One more cleanup pass. 83e5c31af7Sopenharmony_ci deleteDoneConnections(); 84e5c31af7Sopenharmony_ci} 85e5c31af7Sopenharmony_ci 86e5c31af7Sopenharmony_civoid TcpServer::connectionDone (ConnectionHandler* handler) 87e5c31af7Sopenharmony_ci{ 88e5c31af7Sopenharmony_ci de::ScopedLock lock(m_connectionListLock); 89e5c31af7Sopenharmony_ci 90e5c31af7Sopenharmony_ci std::vector<ConnectionHandler*>::iterator liveListPos = std::find(m_liveConnections.begin(), m_liveConnections.end(), handler); 91e5c31af7Sopenharmony_ci DE_ASSERT(liveListPos != m_liveConnections.end()); 92e5c31af7Sopenharmony_ci 93e5c31af7Sopenharmony_ci m_doneConnections.reserve(m_doneConnections.size()+1); 94e5c31af7Sopenharmony_ci m_liveConnections.erase(liveListPos); 95e5c31af7Sopenharmony_ci m_doneConnections.push_back(handler); 96e5c31af7Sopenharmony_ci} 97e5c31af7Sopenharmony_ci 98e5c31af7Sopenharmony_civoid TcpServer::addLiveConnection (ConnectionHandler* handler) 99e5c31af7Sopenharmony_ci{ 100e5c31af7Sopenharmony_ci de::ScopedLock lock(m_connectionListLock); 101e5c31af7Sopenharmony_ci m_liveConnections.push_back(handler); 102e5c31af7Sopenharmony_ci} 103e5c31af7Sopenharmony_ci 104e5c31af7Sopenharmony_civoid TcpServer::deleteDoneConnections (void) 105e5c31af7Sopenharmony_ci{ 106e5c31af7Sopenharmony_ci de::ScopedLock lock(m_connectionListLock); 107e5c31af7Sopenharmony_ci 108e5c31af7Sopenharmony_ci for (std::vector<ConnectionHandler*>::iterator i = m_doneConnections.begin(); i != m_doneConnections.end(); i++) 109e5c31af7Sopenharmony_ci delete *i; 110e5c31af7Sopenharmony_ci 111e5c31af7Sopenharmony_ci m_doneConnections.clear(); 112e5c31af7Sopenharmony_ci} 113e5c31af7Sopenharmony_ci 114e5c31af7Sopenharmony_civoid TcpServer::stopServer (void) 115e5c31af7Sopenharmony_ci{ 116e5c31af7Sopenharmony_ci // Close socket. This should get accept() to return null. 117e5c31af7Sopenharmony_ci m_socket.close(); 118e5c31af7Sopenharmony_ci} 119e5c31af7Sopenharmony_ci 120e5c31af7Sopenharmony_ciTcpServer::~TcpServer (void) 121e5c31af7Sopenharmony_ci{ 122e5c31af7Sopenharmony_ci try 123e5c31af7Sopenharmony_ci { 124e5c31af7Sopenharmony_ci std::vector<ConnectionHandler*> allConnections; 125e5c31af7Sopenharmony_ci 126e5c31af7Sopenharmony_ci if (m_connectionListLock.tryLock()) 127e5c31af7Sopenharmony_ci { 128e5c31af7Sopenharmony_ci // \note [pyry] It is possible that cleanup actually fails. 129e5c31af7Sopenharmony_ci try 130e5c31af7Sopenharmony_ci { 131e5c31af7Sopenharmony_ci std::copy(m_liveConnections.begin(), m_liveConnections.end(), std::inserter(allConnections, allConnections.end())); 132e5c31af7Sopenharmony_ci std::copy(m_doneConnections.begin(), m_doneConnections.end(), std::inserter(allConnections, allConnections.end())); 133e5c31af7Sopenharmony_ci } 134e5c31af7Sopenharmony_ci catch (...) 135e5c31af7Sopenharmony_ci { 136e5c31af7Sopenharmony_ci } 137e5c31af7Sopenharmony_ci m_connectionListLock.unlock(); 138e5c31af7Sopenharmony_ci } 139e5c31af7Sopenharmony_ci 140e5c31af7Sopenharmony_ci for (std::vector<ConnectionHandler*>::const_iterator i = allConnections.begin(); i != allConnections.end(); i++) 141e5c31af7Sopenharmony_ci delete *i; 142e5c31af7Sopenharmony_ci 143e5c31af7Sopenharmony_ci if (m_socket.getState() != DE_SOCKETSTATE_CLOSED) 144e5c31af7Sopenharmony_ci m_socket.close(); 145e5c31af7Sopenharmony_ci } 146e5c31af7Sopenharmony_ci catch (...) 147e5c31af7Sopenharmony_ci { 148e5c31af7Sopenharmony_ci // Nada, we're at destructor. 149e5c31af7Sopenharmony_ci } 150e5c31af7Sopenharmony_ci} 151e5c31af7Sopenharmony_ci 152e5c31af7Sopenharmony_ciConnectionHandler::~ConnectionHandler (void) 153e5c31af7Sopenharmony_ci{ 154e5c31af7Sopenharmony_ci delete m_socket; 155e5c31af7Sopenharmony_ci} 156e5c31af7Sopenharmony_ci 157e5c31af7Sopenharmony_civoid ConnectionHandler::run (void) 158e5c31af7Sopenharmony_ci{ 159e5c31af7Sopenharmony_ci try 160e5c31af7Sopenharmony_ci { 161e5c31af7Sopenharmony_ci handle(); 162e5c31af7Sopenharmony_ci } 163e5c31af7Sopenharmony_ci catch (const std::exception& e) 164e5c31af7Sopenharmony_ci { 165e5c31af7Sopenharmony_ci printf("ConnectionHandler::run(): %s\n", e.what()); 166e5c31af7Sopenharmony_ci } 167e5c31af7Sopenharmony_ci 168e5c31af7Sopenharmony_ci // Notify server that this connection is done. 169e5c31af7Sopenharmony_ci m_server->connectionDone(this); 170e5c31af7Sopenharmony_ci} 171e5c31af7Sopenharmony_ci 172e5c31af7Sopenharmony_ci} // xs 173