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