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