13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*------------------------------------------------------------------------- 23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program Execution Server 33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * --------------------------------------------- 43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project 63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License"); 83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License. 93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at 103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * http://www.apache.org/licenses/LICENSE-2.0 123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software 143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS, 153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and 173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License. 183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*! 203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file 213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief TCP Server. 223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "xsTcpServer.hpp" 253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <algorithm> 273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <iterator> 283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <cstdio> 293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 303c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace xs 313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 333c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTcpServer::TcpServer (deSocketFamily family, int port) 343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_socket() 353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::SocketAddress address; 373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry address.setFamily(family); 383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry address.setPort(port); 393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry address.setType(DE_SOCKETTYPE_STREAM); 403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry address.setProtocol(DE_SOCKETPROTOCOL_TCP); 413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_socket.listen(address); 433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_socket.setFlags(DE_SOCKET_CLOSE_ON_EXEC); 443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpServer::runServer (void) 473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Socket* clientSocket = DE_NULL; 493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::SocketAddress clientAddr; 503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry while ((clientSocket = m_socket.accept(clientAddr)) != DE_NULL) 523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ConnectionHandler* handler = DE_NULL; 543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry try 563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry handler = createHandler(clientSocket, clientAddr); 583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry catch (...) 603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry delete clientSocket; 623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw; 633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry try 663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry addLiveConnection(handler); 683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry catch (...) 703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry delete handler; 723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry throw; 733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Start handler. 763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry handler->start(); 773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Perform connection list cleanup. 793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deleteDoneConnections(); 803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // One more cleanup pass. 833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deleteDoneConnections(); 843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 863c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpServer::connectionDone (ConnectionHandler* handler) 873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::ScopedLock lock(m_connectionListLock); 893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::vector<ConnectionHandler*>::iterator liveListPos = std::find(m_liveConnections.begin(), m_liveConnections.end(), handler); 913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(liveListPos != m_liveConnections.end()); 923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_doneConnections.reserve(m_doneConnections.size()+1); 943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_liveConnections.erase(liveListPos); 953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_doneConnections.push_back(handler); 963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 983c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpServer::addLiveConnection (ConnectionHandler* handler) 993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::ScopedLock lock(m_connectionListLock); 1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_liveConnections.push_back(handler); 1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpServer::deleteDoneConnections (void) 1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::ScopedLock lock(m_connectionListLock); 1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (std::vector<ConnectionHandler*>::iterator i = m_doneConnections.begin(); i != m_doneConnections.end(); i++) 1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry delete *i; 1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_doneConnections.clear(); 1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpServer::stopServer (void) 1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Close socket. This should get accept() to return null. 1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_socket.close(); 1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1203c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTcpServer::~TcpServer (void) 1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry try 1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::vector<ConnectionHandler*> allConnections; 1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_connectionListLock.tryLock()) 1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \note [pyry] It is possible that cleanup actually fails. 1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry try 1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::copy(m_liveConnections.begin(), m_liveConnections.end(), std::inserter(allConnections, allConnections.end())); 1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::copy(m_doneConnections.begin(), m_doneConnections.end(), std::inserter(allConnections, allConnections.end())); 1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry catch (...) 1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_connectionListLock.unlock(); 1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (std::vector<ConnectionHandler*>::const_iterator i = allConnections.begin(); i != allConnections.end(); i++) 1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry delete *i; 1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_socket.getState() != DE_SOCKETSTATE_CLOSED) 1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_socket.close(); 1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry catch (...) 1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Nada, we're at destructor. 1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1523c827367444ee418f129b2c238299f49d3264554Jarkko PoyryConnectionHandler::~ConnectionHandler (void) 1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry delete m_socket; 1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ConnectionHandler::run (void) 1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry try 1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry handle(); 1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry catch (const std::exception& e) 1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry printf("ConnectionHandler::run(): %s\n", e.what()); 1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Notify server that this connection is done. 1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_server->connectionDone(this); 1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // xs 173