xref: /aosp_15_r20/external/deqp/execserver/xsExecutionServer.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 Test Execution Server.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "xsExecutionServer.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "deClock.h"
26*35238bceSAndroid Build Coastguard Worker 
27*35238bceSAndroid Build Coastguard Worker #include <cstdio>
28*35238bceSAndroid Build Coastguard Worker 
29*35238bceSAndroid Build Coastguard Worker using std::string;
30*35238bceSAndroid Build Coastguard Worker using std::vector;
31*35238bceSAndroid Build Coastguard Worker 
32*35238bceSAndroid Build Coastguard Worker #if 1
33*35238bceSAndroid Build Coastguard Worker #define DBG_PRINT(X) printf X
34*35238bceSAndroid Build Coastguard Worker #else
35*35238bceSAndroid Build Coastguard Worker #define DBG_PRINT(X)
36*35238bceSAndroid Build Coastguard Worker #endif
37*35238bceSAndroid Build Coastguard Worker 
38*35238bceSAndroid Build Coastguard Worker namespace xs
39*35238bceSAndroid Build Coastguard Worker {
40*35238bceSAndroid Build Coastguard Worker 
isComplete(void) const41*35238bceSAndroid Build Coastguard Worker inline bool MessageBuilder::isComplete(void) const
42*35238bceSAndroid Build Coastguard Worker {
43*35238bceSAndroid Build Coastguard Worker     if (m_buffer.size() < MESSAGE_HEADER_SIZE)
44*35238bceSAndroid Build Coastguard Worker         return false;
45*35238bceSAndroid Build Coastguard Worker     else
46*35238bceSAndroid Build Coastguard Worker         return m_buffer.size() == getMessageSize();
47*35238bceSAndroid Build Coastguard Worker }
48*35238bceSAndroid Build Coastguard Worker 
getMessageData(void) const49*35238bceSAndroid Build Coastguard Worker const uint8_t *MessageBuilder::getMessageData(void) const
50*35238bceSAndroid Build Coastguard Worker {
51*35238bceSAndroid Build Coastguard Worker     return m_buffer.size() > MESSAGE_HEADER_SIZE ? &m_buffer[MESSAGE_HEADER_SIZE] : DE_NULL;
52*35238bceSAndroid Build Coastguard Worker }
53*35238bceSAndroid Build Coastguard Worker 
getMessageDataSize(void) const54*35238bceSAndroid Build Coastguard Worker size_t MessageBuilder::getMessageDataSize(void) const
55*35238bceSAndroid Build Coastguard Worker {
56*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(isComplete());
57*35238bceSAndroid Build Coastguard Worker     return m_buffer.size() - MESSAGE_HEADER_SIZE;
58*35238bceSAndroid Build Coastguard Worker }
59*35238bceSAndroid Build Coastguard Worker 
read(ByteBuffer & src)60*35238bceSAndroid Build Coastguard Worker void MessageBuilder::read(ByteBuffer &src)
61*35238bceSAndroid Build Coastguard Worker {
62*35238bceSAndroid Build Coastguard Worker     // Try to get header.
63*35238bceSAndroid Build Coastguard Worker     if (m_buffer.size() < MESSAGE_HEADER_SIZE)
64*35238bceSAndroid Build Coastguard Worker     {
65*35238bceSAndroid Build Coastguard Worker         while (m_buffer.size() < MESSAGE_HEADER_SIZE && src.getNumElements() > 0)
66*35238bceSAndroid Build Coastguard Worker             m_buffer.push_back(src.popBack());
67*35238bceSAndroid Build Coastguard Worker 
68*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(m_buffer.size() <= MESSAGE_HEADER_SIZE);
69*35238bceSAndroid Build Coastguard Worker 
70*35238bceSAndroid Build Coastguard Worker         if (m_buffer.size() == MESSAGE_HEADER_SIZE)
71*35238bceSAndroid Build Coastguard Worker         {
72*35238bceSAndroid Build Coastguard Worker             // Got whole header, parse it.
73*35238bceSAndroid Build Coastguard Worker             Message::parseHeader(&m_buffer[0], (int)m_buffer.size(), m_messageType, m_messageSize);
74*35238bceSAndroid Build Coastguard Worker         }
75*35238bceSAndroid Build Coastguard Worker     }
76*35238bceSAndroid Build Coastguard Worker 
77*35238bceSAndroid Build Coastguard Worker     if (m_buffer.size() >= MESSAGE_HEADER_SIZE)
78*35238bceSAndroid Build Coastguard Worker     {
79*35238bceSAndroid Build Coastguard Worker         // We have header.
80*35238bceSAndroid Build Coastguard Worker         size_t msgSize      = getMessageSize();
81*35238bceSAndroid Build Coastguard Worker         size_t numBytesLeft = msgSize - m_buffer.size();
82*35238bceSAndroid Build Coastguard Worker         size_t numToRead    = (size_t)de::min(src.getNumElements(), (int)numBytesLeft);
83*35238bceSAndroid Build Coastguard Worker 
84*35238bceSAndroid Build Coastguard Worker         if (numToRead > 0)
85*35238bceSAndroid Build Coastguard Worker         {
86*35238bceSAndroid Build Coastguard Worker             int curBufPos = (int)m_buffer.size();
87*35238bceSAndroid Build Coastguard Worker             m_buffer.resize(curBufPos + numToRead);
88*35238bceSAndroid Build Coastguard Worker             src.popBack(&m_buffer[curBufPos], (int)numToRead);
89*35238bceSAndroid Build Coastguard Worker         }
90*35238bceSAndroid Build Coastguard Worker     }
91*35238bceSAndroid Build Coastguard Worker }
92*35238bceSAndroid Build Coastguard Worker 
clear(void)93*35238bceSAndroid Build Coastguard Worker void MessageBuilder::clear(void)
94*35238bceSAndroid Build Coastguard Worker {
95*35238bceSAndroid Build Coastguard Worker     m_buffer.clear();
96*35238bceSAndroid Build Coastguard Worker     m_messageType = MESSAGETYPE_NONE;
97*35238bceSAndroid Build Coastguard Worker     m_messageSize = 0;
98*35238bceSAndroid Build Coastguard Worker }
99*35238bceSAndroid Build Coastguard Worker 
ExecutionServer(xs::TestProcess * testProcess,deSocketFamily family,int port,RunMode runMode)100*35238bceSAndroid Build Coastguard Worker ExecutionServer::ExecutionServer(xs::TestProcess *testProcess, deSocketFamily family, int port, RunMode runMode)
101*35238bceSAndroid Build Coastguard Worker     : TcpServer(family, port)
102*35238bceSAndroid Build Coastguard Worker     , m_testDriver(testProcess)
103*35238bceSAndroid Build Coastguard Worker     , m_runMode(runMode)
104*35238bceSAndroid Build Coastguard Worker {
105*35238bceSAndroid Build Coastguard Worker }
106*35238bceSAndroid Build Coastguard Worker 
~ExecutionServer(void)107*35238bceSAndroid Build Coastguard Worker ExecutionServer::~ExecutionServer(void)
108*35238bceSAndroid Build Coastguard Worker {
109*35238bceSAndroid Build Coastguard Worker }
110*35238bceSAndroid Build Coastguard Worker 
acquireTestDriver(void)111*35238bceSAndroid Build Coastguard Worker TestDriver *ExecutionServer::acquireTestDriver(void)
112*35238bceSAndroid Build Coastguard Worker {
113*35238bceSAndroid Build Coastguard Worker     if (!m_testDriverLock.tryLock())
114*35238bceSAndroid Build Coastguard Worker         throw Error("Failed to acquire test driver");
115*35238bceSAndroid Build Coastguard Worker 
116*35238bceSAndroid Build Coastguard Worker     return &m_testDriver;
117*35238bceSAndroid Build Coastguard Worker }
118*35238bceSAndroid Build Coastguard Worker 
releaseTestDriver(TestDriver * driver)119*35238bceSAndroid Build Coastguard Worker void ExecutionServer::releaseTestDriver(TestDriver *driver)
120*35238bceSAndroid Build Coastguard Worker {
121*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(&m_testDriver == driver);
122*35238bceSAndroid Build Coastguard Worker     DE_UNREF(driver);
123*35238bceSAndroid Build Coastguard Worker     m_testDriverLock.unlock();
124*35238bceSAndroid Build Coastguard Worker }
125*35238bceSAndroid Build Coastguard Worker 
createHandler(de::Socket * socket,const de::SocketAddress & clientAddress)126*35238bceSAndroid Build Coastguard Worker ConnectionHandler *ExecutionServer::createHandler(de::Socket *socket, const de::SocketAddress &clientAddress)
127*35238bceSAndroid Build Coastguard Worker {
128*35238bceSAndroid Build Coastguard Worker     printf("ExecutionServer: New connection from %s:%d\n", clientAddress.getHost(), clientAddress.getPort());
129*35238bceSAndroid Build Coastguard Worker     return new ExecutionRequestHandler(this, socket);
130*35238bceSAndroid Build Coastguard Worker }
131*35238bceSAndroid Build Coastguard Worker 
connectionDone(ConnectionHandler * handler)132*35238bceSAndroid Build Coastguard Worker void ExecutionServer::connectionDone(ConnectionHandler *handler)
133*35238bceSAndroid Build Coastguard Worker {
134*35238bceSAndroid Build Coastguard Worker     if (m_runMode == RUNMODE_SINGLE_EXEC)
135*35238bceSAndroid Build Coastguard Worker         m_socket.close();
136*35238bceSAndroid Build Coastguard Worker 
137*35238bceSAndroid Build Coastguard Worker     TcpServer::connectionDone(handler);
138*35238bceSAndroid Build Coastguard Worker }
139*35238bceSAndroid Build Coastguard Worker 
ExecutionRequestHandler(ExecutionServer * server,de::Socket * socket)140*35238bceSAndroid Build Coastguard Worker ExecutionRequestHandler::ExecutionRequestHandler(ExecutionServer *server, de::Socket *socket)
141*35238bceSAndroid Build Coastguard Worker     : ConnectionHandler(server, socket)
142*35238bceSAndroid Build Coastguard Worker     , m_execServer(server)
143*35238bceSAndroid Build Coastguard Worker     , m_testDriver(DE_NULL)
144*35238bceSAndroid Build Coastguard Worker     , m_bufferIn(RECV_BUFFER_SIZE)
145*35238bceSAndroid Build Coastguard Worker     , m_bufferOut(SEND_BUFFER_SIZE)
146*35238bceSAndroid Build Coastguard Worker     , m_run(false)
147*35238bceSAndroid Build Coastguard Worker     , m_sendRecvTmpBuf(SEND_RECV_TMP_BUFFER_SIZE)
148*35238bceSAndroid Build Coastguard Worker {
149*35238bceSAndroid Build Coastguard Worker     // Set flags.
150*35238bceSAndroid Build Coastguard Worker     m_socket->setFlags(DE_SOCKET_NONBLOCKING | DE_SOCKET_KEEPALIVE | DE_SOCKET_CLOSE_ON_EXEC);
151*35238bceSAndroid Build Coastguard Worker 
152*35238bceSAndroid Build Coastguard Worker     // Init protocol keepalives.
153*35238bceSAndroid Build Coastguard Worker     initKeepAlives();
154*35238bceSAndroid Build Coastguard Worker }
155*35238bceSAndroid Build Coastguard Worker 
~ExecutionRequestHandler(void)156*35238bceSAndroid Build Coastguard Worker ExecutionRequestHandler::~ExecutionRequestHandler(void)
157*35238bceSAndroid Build Coastguard Worker {
158*35238bceSAndroid Build Coastguard Worker     if (m_testDriver)
159*35238bceSAndroid Build Coastguard Worker         m_execServer->releaseTestDriver(m_testDriver);
160*35238bceSAndroid Build Coastguard Worker }
161*35238bceSAndroid Build Coastguard Worker 
handle(void)162*35238bceSAndroid Build Coastguard Worker void ExecutionRequestHandler::handle(void)
163*35238bceSAndroid Build Coastguard Worker {
164*35238bceSAndroid Build Coastguard Worker     DBG_PRINT(("ExecutionRequestHandler::handle()\n"));
165*35238bceSAndroid Build Coastguard Worker 
166*35238bceSAndroid Build Coastguard Worker     try
167*35238bceSAndroid Build Coastguard Worker     {
168*35238bceSAndroid Build Coastguard Worker         // Process execution session.
169*35238bceSAndroid Build Coastguard Worker         processSession();
170*35238bceSAndroid Build Coastguard Worker     }
171*35238bceSAndroid Build Coastguard Worker     catch (const std::exception &e)
172*35238bceSAndroid Build Coastguard Worker     {
173*35238bceSAndroid Build Coastguard Worker         printf("ExecutionRequestHandler::run(): %s\n", e.what());
174*35238bceSAndroid Build Coastguard Worker     }
175*35238bceSAndroid Build Coastguard Worker 
176*35238bceSAndroid Build Coastguard Worker     DBG_PRINT(("ExecutionRequestHandler::handle(): Done!\n"));
177*35238bceSAndroid Build Coastguard Worker 
178*35238bceSAndroid Build Coastguard Worker     // Release test driver.
179*35238bceSAndroid Build Coastguard Worker     if (m_testDriver)
180*35238bceSAndroid Build Coastguard Worker     {
181*35238bceSAndroid Build Coastguard Worker         try
182*35238bceSAndroid Build Coastguard Worker         {
183*35238bceSAndroid Build Coastguard Worker             m_testDriver->reset();
184*35238bceSAndroid Build Coastguard Worker         }
185*35238bceSAndroid Build Coastguard Worker         catch (...)
186*35238bceSAndroid Build Coastguard Worker         {
187*35238bceSAndroid Build Coastguard Worker         }
188*35238bceSAndroid Build Coastguard Worker         m_execServer->releaseTestDriver(m_testDriver);
189*35238bceSAndroid Build Coastguard Worker         m_testDriver = DE_NULL;
190*35238bceSAndroid Build Coastguard Worker     }
191*35238bceSAndroid Build Coastguard Worker 
192*35238bceSAndroid Build Coastguard Worker     // Close connection.
193*35238bceSAndroid Build Coastguard Worker     if (m_socket->isConnected())
194*35238bceSAndroid Build Coastguard Worker         m_socket->shutdown();
195*35238bceSAndroid Build Coastguard Worker }
196*35238bceSAndroid Build Coastguard Worker 
acquireTestDriver(void)197*35238bceSAndroid Build Coastguard Worker void ExecutionRequestHandler::acquireTestDriver(void)
198*35238bceSAndroid Build Coastguard Worker {
199*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!m_testDriver);
200*35238bceSAndroid Build Coastguard Worker 
201*35238bceSAndroid Build Coastguard Worker     // Try to acquire test driver - may fail.
202*35238bceSAndroid Build Coastguard Worker     m_testDriver = m_execServer->acquireTestDriver();
203*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(m_testDriver);
204*35238bceSAndroid Build Coastguard Worker     m_testDriver->reset();
205*35238bceSAndroid Build Coastguard Worker }
206*35238bceSAndroid Build Coastguard Worker 
processSession(void)207*35238bceSAndroid Build Coastguard Worker void ExecutionRequestHandler::processSession(void)
208*35238bceSAndroid Build Coastguard Worker {
209*35238bceSAndroid Build Coastguard Worker     m_run = true;
210*35238bceSAndroid Build Coastguard Worker 
211*35238bceSAndroid Build Coastguard Worker     uint64_t lastIoTime = deGetMicroseconds();
212*35238bceSAndroid Build Coastguard Worker 
213*35238bceSAndroid Build Coastguard Worker     while (m_run)
214*35238bceSAndroid Build Coastguard Worker     {
215*35238bceSAndroid Build Coastguard Worker         bool anyIO = false;
216*35238bceSAndroid Build Coastguard Worker 
217*35238bceSAndroid Build Coastguard Worker         // Read from socket to buffer.
218*35238bceSAndroid Build Coastguard Worker         anyIO = receive() || anyIO;
219*35238bceSAndroid Build Coastguard Worker 
220*35238bceSAndroid Build Coastguard Worker         // Send bytes in buffer.
221*35238bceSAndroid Build Coastguard Worker         anyIO = send() || anyIO;
222*35238bceSAndroid Build Coastguard Worker 
223*35238bceSAndroid Build Coastguard Worker         // Process incoming data.
224*35238bceSAndroid Build Coastguard Worker         if (m_bufferIn.getNumElements() > 0)
225*35238bceSAndroid Build Coastguard Worker         {
226*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(!m_msgBuilder.isComplete());
227*35238bceSAndroid Build Coastguard Worker             m_msgBuilder.read(m_bufferIn);
228*35238bceSAndroid Build Coastguard Worker         }
229*35238bceSAndroid Build Coastguard Worker 
230*35238bceSAndroid Build Coastguard Worker         if (m_msgBuilder.isComplete())
231*35238bceSAndroid Build Coastguard Worker         {
232*35238bceSAndroid Build Coastguard Worker             // Process message.
233*35238bceSAndroid Build Coastguard Worker             processMessage(m_msgBuilder.getMessageType(), m_msgBuilder.getMessageData(),
234*35238bceSAndroid Build Coastguard Worker                            m_msgBuilder.getMessageDataSize());
235*35238bceSAndroid Build Coastguard Worker 
236*35238bceSAndroid Build Coastguard Worker             m_msgBuilder.clear();
237*35238bceSAndroid Build Coastguard Worker         }
238*35238bceSAndroid Build Coastguard Worker 
239*35238bceSAndroid Build Coastguard Worker         // Keepalives, anyone?
240*35238bceSAndroid Build Coastguard Worker         pollKeepAlives();
241*35238bceSAndroid Build Coastguard Worker 
242*35238bceSAndroid Build Coastguard Worker         // Poll test driver for IO.
243*35238bceSAndroid Build Coastguard Worker         if (m_testDriver)
244*35238bceSAndroid Build Coastguard Worker             anyIO = getTestDriver()->poll(m_bufferOut) || anyIO;
245*35238bceSAndroid Build Coastguard Worker 
246*35238bceSAndroid Build Coastguard Worker         // If no IO happens in a reasonable amount of time, go to sleep.
247*35238bceSAndroid Build Coastguard Worker         {
248*35238bceSAndroid Build Coastguard Worker             uint64_t curTime = deGetMicroseconds();
249*35238bceSAndroid Build Coastguard Worker             if (anyIO)
250*35238bceSAndroid Build Coastguard Worker                 lastIoTime = curTime;
251*35238bceSAndroid Build Coastguard Worker             else if (curTime - lastIoTime > SERVER_IDLE_THRESHOLD * 1000)
252*35238bceSAndroid Build Coastguard Worker                 deSleep(SERVER_IDLE_SLEEP); // Too long since last IO, sleep for a while.
253*35238bceSAndroid Build Coastguard Worker             else
254*35238bceSAndroid Build Coastguard Worker                 deYield(); // Just give other threads chance to run.
255*35238bceSAndroid Build Coastguard Worker         }
256*35238bceSAndroid Build Coastguard Worker     }
257*35238bceSAndroid Build Coastguard Worker }
258*35238bceSAndroid Build Coastguard Worker 
processMessage(MessageType type,const uint8_t * data,size_t dataSize)259*35238bceSAndroid Build Coastguard Worker void ExecutionRequestHandler::processMessage(MessageType type, const uint8_t *data, size_t dataSize)
260*35238bceSAndroid Build Coastguard Worker {
261*35238bceSAndroid Build Coastguard Worker     switch (type)
262*35238bceSAndroid Build Coastguard Worker     {
263*35238bceSAndroid Build Coastguard Worker     case MESSAGETYPE_HELLO:
264*35238bceSAndroid Build Coastguard Worker     {
265*35238bceSAndroid Build Coastguard Worker         HelloMessage msg(data, dataSize);
266*35238bceSAndroid Build Coastguard Worker         DBG_PRINT(("HelloMessage: version = %d\n", msg.version));
267*35238bceSAndroid Build Coastguard Worker         if (msg.version != PROTOCOL_VERSION)
268*35238bceSAndroid Build Coastguard Worker             throw ProtocolError("Unsupported protocol version");
269*35238bceSAndroid Build Coastguard Worker         break;
270*35238bceSAndroid Build Coastguard Worker     }
271*35238bceSAndroid Build Coastguard Worker 
272*35238bceSAndroid Build Coastguard Worker     case MESSAGETYPE_TEST:
273*35238bceSAndroid Build Coastguard Worker     {
274*35238bceSAndroid Build Coastguard Worker         TestMessage msg(data, dataSize);
275*35238bceSAndroid Build Coastguard Worker         DBG_PRINT(("TestMessage: '%s'\n", msg.test.c_str()));
276*35238bceSAndroid Build Coastguard Worker         break;
277*35238bceSAndroid Build Coastguard Worker     }
278*35238bceSAndroid Build Coastguard Worker 
279*35238bceSAndroid Build Coastguard Worker     case MESSAGETYPE_KEEPALIVE:
280*35238bceSAndroid Build Coastguard Worker     {
281*35238bceSAndroid Build Coastguard Worker         KeepAliveMessage msg(data, dataSize);
282*35238bceSAndroid Build Coastguard Worker         DBG_PRINT(("KeepAliveMessage\n"));
283*35238bceSAndroid Build Coastguard Worker         keepAliveReceived();
284*35238bceSAndroid Build Coastguard Worker         break;
285*35238bceSAndroid Build Coastguard Worker     }
286*35238bceSAndroid Build Coastguard Worker 
287*35238bceSAndroid Build Coastguard Worker     case MESSAGETYPE_EXECUTE_BINARY:
288*35238bceSAndroid Build Coastguard Worker     {
289*35238bceSAndroid Build Coastguard Worker         ExecuteBinaryMessage msg(data, dataSize);
290*35238bceSAndroid Build Coastguard Worker         DBG_PRINT(("ExecuteBinaryMessage: '%s', '%s', '%s', '%s'\n", msg.name.c_str(), msg.params.c_str(),
291*35238bceSAndroid Build Coastguard Worker                    msg.workDir.c_str(), msg.caseList.substr(0, 10).c_str()));
292*35238bceSAndroid Build Coastguard Worker         getTestDriver()->startProcess(msg.name.c_str(), msg.params.c_str(), msg.workDir.c_str(), msg.caseList.c_str());
293*35238bceSAndroid Build Coastguard Worker         keepAliveReceived(); // \todo [2011-10-11 pyry] Remove this once Candy is fixed.
294*35238bceSAndroid Build Coastguard Worker         break;
295*35238bceSAndroid Build Coastguard Worker     }
296*35238bceSAndroid Build Coastguard Worker 
297*35238bceSAndroid Build Coastguard Worker     case MESSAGETYPE_STOP_EXECUTION:
298*35238bceSAndroid Build Coastguard Worker     {
299*35238bceSAndroid Build Coastguard Worker         StopExecutionMessage msg(data, dataSize);
300*35238bceSAndroid Build Coastguard Worker         DBG_PRINT(("StopExecutionMessage\n"));
301*35238bceSAndroid Build Coastguard Worker         getTestDriver()->stopProcess();
302*35238bceSAndroid Build Coastguard Worker         break;
303*35238bceSAndroid Build Coastguard Worker     }
304*35238bceSAndroid Build Coastguard Worker 
305*35238bceSAndroid Build Coastguard Worker     default:
306*35238bceSAndroid Build Coastguard Worker         throw ProtocolError("Unsupported message");
307*35238bceSAndroid Build Coastguard Worker     }
308*35238bceSAndroid Build Coastguard Worker }
309*35238bceSAndroid Build Coastguard Worker 
initKeepAlives(void)310*35238bceSAndroid Build Coastguard Worker void ExecutionRequestHandler::initKeepAlives(void)
311*35238bceSAndroid Build Coastguard Worker {
312*35238bceSAndroid Build Coastguard Worker     uint64_t curTime        = deGetMicroseconds();
313*35238bceSAndroid Build Coastguard Worker     m_lastKeepAliveSent     = curTime;
314*35238bceSAndroid Build Coastguard Worker     m_lastKeepAliveReceived = curTime;
315*35238bceSAndroid Build Coastguard Worker }
316*35238bceSAndroid Build Coastguard Worker 
keepAliveReceived(void)317*35238bceSAndroid Build Coastguard Worker void ExecutionRequestHandler::keepAliveReceived(void)
318*35238bceSAndroid Build Coastguard Worker {
319*35238bceSAndroid Build Coastguard Worker     m_lastKeepAliveReceived = deGetMicroseconds();
320*35238bceSAndroid Build Coastguard Worker }
321*35238bceSAndroid Build Coastguard Worker 
pollKeepAlives(void)322*35238bceSAndroid Build Coastguard Worker void ExecutionRequestHandler::pollKeepAlives(void)
323*35238bceSAndroid Build Coastguard Worker {
324*35238bceSAndroid Build Coastguard Worker     uint64_t curTime = deGetMicroseconds();
325*35238bceSAndroid Build Coastguard Worker 
326*35238bceSAndroid Build Coastguard Worker     // Check that we've got keepalives in timely fashion.
327*35238bceSAndroid Build Coastguard Worker     if (curTime - m_lastKeepAliveReceived > KEEPALIVE_TIMEOUT * 1000)
328*35238bceSAndroid Build Coastguard Worker         throw ProtocolError("Keepalive timeout occurred");
329*35238bceSAndroid Build Coastguard Worker 
330*35238bceSAndroid Build Coastguard Worker     // Send some?
331*35238bceSAndroid Build Coastguard Worker     if (curTime - m_lastKeepAliveSent > KEEPALIVE_SEND_INTERVAL * 1000 &&
332*35238bceSAndroid Build Coastguard Worker         m_bufferOut.getNumFree() >= MESSAGE_HEADER_SIZE)
333*35238bceSAndroid Build Coastguard Worker     {
334*35238bceSAndroid Build Coastguard Worker         vector<uint8_t> buf;
335*35238bceSAndroid Build Coastguard Worker         KeepAliveMessage().write(buf);
336*35238bceSAndroid Build Coastguard Worker         m_bufferOut.pushFront(&buf[0], (int)buf.size());
337*35238bceSAndroid Build Coastguard Worker 
338*35238bceSAndroid Build Coastguard Worker         m_lastKeepAliveSent = deGetMicroseconds();
339*35238bceSAndroid Build Coastguard Worker     }
340*35238bceSAndroid Build Coastguard Worker }
341*35238bceSAndroid Build Coastguard Worker 
receive(void)342*35238bceSAndroid Build Coastguard Worker bool ExecutionRequestHandler::receive(void)
343*35238bceSAndroid Build Coastguard Worker {
344*35238bceSAndroid Build Coastguard Worker     size_t maxLen = de::min(m_sendRecvTmpBuf.size(), (size_t)m_bufferIn.getNumFree());
345*35238bceSAndroid Build Coastguard Worker 
346*35238bceSAndroid Build Coastguard Worker     if (maxLen > 0)
347*35238bceSAndroid Build Coastguard Worker     {
348*35238bceSAndroid Build Coastguard Worker         size_t numRecv;
349*35238bceSAndroid Build Coastguard Worker         deSocketResult result = m_socket->receive(&m_sendRecvTmpBuf[0], maxLen, &numRecv);
350*35238bceSAndroid Build Coastguard Worker 
351*35238bceSAndroid Build Coastguard Worker         if (result == DE_SOCKETRESULT_SUCCESS)
352*35238bceSAndroid Build Coastguard Worker         {
353*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(numRecv > 0);
354*35238bceSAndroid Build Coastguard Worker             m_bufferIn.pushFront(&m_sendRecvTmpBuf[0], (int)numRecv);
355*35238bceSAndroid Build Coastguard Worker             return true;
356*35238bceSAndroid Build Coastguard Worker         }
357*35238bceSAndroid Build Coastguard Worker         else if (result == DE_SOCKETRESULT_CONNECTION_CLOSED)
358*35238bceSAndroid Build Coastguard Worker         {
359*35238bceSAndroid Build Coastguard Worker             m_run = false;
360*35238bceSAndroid Build Coastguard Worker             return true;
361*35238bceSAndroid Build Coastguard Worker         }
362*35238bceSAndroid Build Coastguard Worker         else if (result == DE_SOCKETRESULT_WOULD_BLOCK)
363*35238bceSAndroid Build Coastguard Worker             return false;
364*35238bceSAndroid Build Coastguard Worker         else if (result == DE_SOCKETRESULT_CONNECTION_TERMINATED)
365*35238bceSAndroid Build Coastguard Worker             throw ConnectionError("Connection terminated");
366*35238bceSAndroid Build Coastguard Worker         else
367*35238bceSAndroid Build Coastguard Worker             throw ConnectionError("receive() failed");
368*35238bceSAndroid Build Coastguard Worker     }
369*35238bceSAndroid Build Coastguard Worker     else
370*35238bceSAndroid Build Coastguard Worker         return false;
371*35238bceSAndroid Build Coastguard Worker }
372*35238bceSAndroid Build Coastguard Worker 
send(void)373*35238bceSAndroid Build Coastguard Worker bool ExecutionRequestHandler::send(void)
374*35238bceSAndroid Build Coastguard Worker {
375*35238bceSAndroid Build Coastguard Worker     size_t maxLen = de::min(m_sendRecvTmpBuf.size(), (size_t)m_bufferOut.getNumElements());
376*35238bceSAndroid Build Coastguard Worker 
377*35238bceSAndroid Build Coastguard Worker     if (maxLen > 0)
378*35238bceSAndroid Build Coastguard Worker     {
379*35238bceSAndroid Build Coastguard Worker         m_bufferOut.peekBack(&m_sendRecvTmpBuf[0], (int)maxLen);
380*35238bceSAndroid Build Coastguard Worker 
381*35238bceSAndroid Build Coastguard Worker         size_t numSent;
382*35238bceSAndroid Build Coastguard Worker         deSocketResult result = m_socket->send(&m_sendRecvTmpBuf[0], maxLen, &numSent);
383*35238bceSAndroid Build Coastguard Worker 
384*35238bceSAndroid Build Coastguard Worker         if (result == DE_SOCKETRESULT_SUCCESS)
385*35238bceSAndroid Build Coastguard Worker         {
386*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(numSent > 0);
387*35238bceSAndroid Build Coastguard Worker             m_bufferOut.popBack((int)numSent);
388*35238bceSAndroid Build Coastguard Worker             return true;
389*35238bceSAndroid Build Coastguard Worker         }
390*35238bceSAndroid Build Coastguard Worker         else if (result == DE_SOCKETRESULT_CONNECTION_CLOSED)
391*35238bceSAndroid Build Coastguard Worker         {
392*35238bceSAndroid Build Coastguard Worker             m_run = false;
393*35238bceSAndroid Build Coastguard Worker             return true;
394*35238bceSAndroid Build Coastguard Worker         }
395*35238bceSAndroid Build Coastguard Worker         else if (result == DE_SOCKETRESULT_WOULD_BLOCK)
396*35238bceSAndroid Build Coastguard Worker             return false;
397*35238bceSAndroid Build Coastguard Worker         else if (result == DE_SOCKETRESULT_CONNECTION_TERMINATED)
398*35238bceSAndroid Build Coastguard Worker             throw ConnectionError("Connection terminated");
399*35238bceSAndroid Build Coastguard Worker         else
400*35238bceSAndroid Build Coastguard Worker             throw ConnectionError("send() failed");
401*35238bceSAndroid Build Coastguard Worker     }
402*35238bceSAndroid Build Coastguard Worker     else
403*35238bceSAndroid Build Coastguard Worker         return false;
404*35238bceSAndroid Build Coastguard Worker }
405*35238bceSAndroid Build Coastguard Worker 
406*35238bceSAndroid Build Coastguard Worker } // namespace xs
407