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