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