1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Execution Server
3 * ---------------------------------------------
5 * Copyright 2014 The Android Open Source Project
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
22 *//*--------------------------------------------------------------------*/
24 #include "xsTcpServer.hpp"
33 TcpServer::TcpServer (deSocketFamily family, int port)
36 de::SocketAddress address;
37 address.setFamily(family);
38 address.setPort(port);
39 address.setType(DE_SOCKETTYPE_STREAM);
40 address.setProtocol(DE_SOCKETPROTOCOL_TCP);
42 m_socket.listen(address);
43 m_socket.setFlags(DE_SOCKET_CLOSE_ON_EXEC);
46 void TcpServer::runServer (void)
48 de::Socket* clientSocket = DE_NULL;
49 de::SocketAddress clientAddr;
51 while ((clientSocket = m_socket.accept(clientAddr)) != DE_NULL)
53 ConnectionHandler* handler = DE_NULL;
57 handler = createHandler(clientSocket, clientAddr);
67 addLiveConnection(handler);
78 // Perform connection list cleanup.
79 deleteDoneConnections();
82 // One more cleanup pass.
83 deleteDoneConnections();
86 void TcpServer::connectionDone (ConnectionHandler* handler)
88 de::ScopedLock lock(m_connectionListLock);
90 std::vector<ConnectionHandler*>::iterator liveListPos = std::find(m_liveConnections.begin(), m_liveConnections.end(), handler);
91 DE_ASSERT(liveListPos != m_liveConnections.end());
93 m_doneConnections.reserve(m_doneConnections.size()+1);
94 m_liveConnections.erase(liveListPos);
95 m_doneConnections.push_back(handler);
98 void TcpServer::addLiveConnection (ConnectionHandler* handler)
100 de::ScopedLock lock(m_connectionListLock);
101 m_liveConnections.push_back(handler);
104 void TcpServer::deleteDoneConnections (void)
106 de::ScopedLock lock(m_connectionListLock);
108 for (std::vector<ConnectionHandler*>::iterator i = m_doneConnections.begin(); i != m_doneConnections.end(); i++)
111 m_doneConnections.clear();
114 void TcpServer::stopServer (void)
116 // Close socket. This should get accept() to return null.
120 TcpServer::~TcpServer (void)
124 std::vector<ConnectionHandler*> allConnections;
126 if (m_connectionListLock.tryLock())
128 // \note [pyry] It is possible that cleanup actually fails.
131 std::copy(m_liveConnections.begin(), m_liveConnections.end(), std::inserter(allConnections, allConnections.end()));
132 std::copy(m_doneConnections.begin(), m_doneConnections.end(), std::inserter(allConnections, allConnections.end()));
137 m_connectionListLock.unlock();
140 for (std::vector<ConnectionHandler*>::const_iterator i = allConnections.begin(); i != allConnections.end(); i++)
143 if (m_socket.getState() != DE_SOCKETSTATE_CLOSED)
148 // Nada, we're at destructor.
152 ConnectionHandler::~ConnectionHandler (void)
157 void ConnectionHandler::run (void)
163 catch (const std::exception& e)
165 printf("ConnectionHandler::run(): %s\n", e.what());
168 // Notify server that this connection is done.
169 m_server->connectionDone(this);