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