13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*------------------------------------------------------------------------- 23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program Test Executor 33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ------------------------------------------ 43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project 63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License"); 83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License. 93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at 103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * http://www.apache.org/licenses/LICENSE-2.0 123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software 143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS, 153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and 173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License. 183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*! 203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file 213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Tcp/Ip communication link. 223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "xeTcpIpLink.hpp" 253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "xsProtocol.hpp" 263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deClock.h" 273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deInt32.h" 283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 293c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace xe 303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 323c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum 333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SEND_BUFFER_BLOCK_SIZE = 1024, 353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SEND_BUFFER_NUM_BLOCKS = 64 363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Utilities for writing messages out. 393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 403c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void writeMessageHeader (de::BlockBuffer<deUint8>& dst, xs::MessageType type, int messageSize) 413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint8 hdr[xs::MESSAGE_HEADER_SIZE]; 433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry xs::Message::writeHeader(type, messageSize, &hdr[0], xs::MESSAGE_HEADER_SIZE); 443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry dst.write(xs::MESSAGE_HEADER_SIZE, &hdr[0]); 453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 473c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void writeKeepalive (de::BlockBuffer<deUint8>& dst) 483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry writeMessageHeader(dst, xs::MESSAGETYPE_KEEPALIVE, xs::MESSAGE_HEADER_SIZE); 503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry dst.flush(); 513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void writeExecuteBinary (de::BlockBuffer<deUint8>& dst, const char* name, const char* params, const char* workDir, const char* caseList) 543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int nameSize = (int)strlen(name) + 1; 563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int paramsSize = (int)strlen(params) + 1; 573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int workDirSize = (int)strlen(workDir) + 1; 583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int caseListSize = (int)strlen(caseList) + 1; 593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int totalSize = xs::MESSAGE_HEADER_SIZE + nameSize + paramsSize + workDirSize + caseListSize; 603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry writeMessageHeader(dst, xs::MESSAGETYPE_EXECUTE_BINARY, totalSize); 623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry dst.write(nameSize, (const deUint8*)name); 633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry dst.write(paramsSize, (const deUint8*)params); 643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry dst.write(workDirSize, (const deUint8*)workDir); 653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry dst.write(caseListSize, (const deUint8*)caseList); 663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry dst.flush(); 673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void writeStopExecution (de::BlockBuffer<deUint8>& dst) 703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry writeMessageHeader(dst, xs::MESSAGETYPE_STOP_EXECUTION, xs::MESSAGE_HEADER_SIZE); 723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry dst.flush(); 733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// TcpIpLinkState 763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 773c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTcpIpLinkState::TcpIpLinkState (CommLinkState initialState, const char* initialErr) 783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_state (initialState) 793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_error (initialErr) 803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_lastKeepaliveReceived (0) 813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_stateChangedCallback (DE_NULL) 823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_testLogDataCallback (DE_NULL) 833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_infoLogDataCallback (DE_NULL) 843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_userPtr (DE_NULL) 853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 883c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTcpIpLinkState::~TcpIpLinkState (void) 893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 923c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCommLinkState TcpIpLinkState::getState (void) const 933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::ScopedLock lock(m_lock); 953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return m_state; 973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 993c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCommLinkState TcpIpLinkState::getState (std::string& error) const 1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::ScopedLock lock(m_lock); 1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry error = m_error; 1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return m_state; 1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpIpLinkState::setCallbacks (CommLink::StateChangedFunc stateChangedCallback, CommLink::LogDataFunc testLogDataCallback, CommLink::LogDataFunc infoLogDataCallback, void* userPtr) 1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::ScopedLock lock(m_lock); 1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_stateChangedCallback = stateChangedCallback; 1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_testLogDataCallback = testLogDataCallback; 1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_infoLogDataCallback = infoLogDataCallback; 1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_userPtr = userPtr; 1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpIpLinkState::setState (CommLinkState state, const char* error) 1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CommLink::StateChangedFunc callback = DE_NULL; 1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void* userPtr = DE_NULL; 1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::ScopedLock lock(m_lock); 1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_state = state; 1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_error = error; 1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry callback = m_stateChangedCallback; 1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry userPtr = m_userPtr; 1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (callback) 1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry callback(userPtr, state, error); 1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 136745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyryvoid TcpIpLinkState::onTestLogData (const deUint8* bytes, size_t numBytes) const 1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CommLink::LogDataFunc callback = DE_NULL; 1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void* userPtr = DE_NULL; 1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_lock.lock(); 1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry callback = m_testLogDataCallback; 1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry userPtr = m_userPtr; 1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_lock.unlock(); 1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (callback) 1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry callback(userPtr, bytes, numBytes); 1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 150745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyryvoid TcpIpLinkState::onInfoLogData (const deUint8* bytes, size_t numBytes) const 1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CommLink::LogDataFunc callback = DE_NULL; 1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void* userPtr = DE_NULL; 1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_lock.lock(); 1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry callback = m_infoLogDataCallback; 1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry userPtr = m_userPtr; 1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_lock.unlock(); 1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (callback) 1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry callback(userPtr, bytes, numBytes); 1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpIpLinkState::onKeepaliveReceived (void) 1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::ScopedLock lock(m_lock); 1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_lastKeepaliveReceived = deGetMicroseconds(); 1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1703c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeUint64 TcpIpLinkState::getLastKeepaliveRecevied (void) const 1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::ScopedLock lock(m_lock); 1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return m_lastKeepaliveReceived; 1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// TcpIpSendThread 1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1783c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTcpIpSendThread::TcpIpSendThread (de::Socket& socket, TcpIpLinkState& state) 1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_socket (socket) 1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_state (state) 1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_buffer (SEND_BUFFER_BLOCK_SIZE, SEND_BUFFER_NUM_BLOCKS) 1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_isRunning (false) 1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1863c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTcpIpSendThread::~TcpIpSendThread (void) 1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpIpSendThread::start (void) 1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(!m_isRunning); 1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Reset state. 1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_buffer.clear(); 1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_isRunning = true; 1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Thread::start(); 1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpIpSendThread::run (void) 2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry try 2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint8 buf[SEND_BUFFER_BLOCK_SIZE]; 2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry while (!m_buffer.isCanceled()) 2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 209745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry size_t numToSend = 0; 210745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry size_t numSent = 0; 2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deSocketResult result = DE_SOCKETRESULT_LAST; 2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry try 2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Wait for single byte and then try to read more. 2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_buffer.read(1, &buf[0]); 2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry numToSend = 1 + m_buffer.tryRead(DE_LENGTH_OF_ARRAY(buf)-1, &buf[1]); 2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry catch (const de::BlockBuffer<deUint8>::CanceledException&) 2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Handled in loop condition. 2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry while (numSent < numToSend) 2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry result = m_socket.send(&buf[numSent], numToSend-numSent, &numSent); 2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (result == DE_SOCKETRESULT_CONNECTION_CLOSED) 2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry XE_FAIL("Connection closed"); 2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (result == DE_SOCKETRESULT_CONNECTION_TERMINATED) 2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry XE_FAIL("Connection terminated"); 2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (result == DE_SOCKETRESULT_ERROR) 2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry XE_FAIL("Socket error"); 2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (result == DE_SOCKETRESULT_WOULD_BLOCK) 2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \note Socket should not be in non-blocking mode. 237745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry DE_ASSERT(numSent == 0); 2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deYield(); 2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(result == DE_SOCKETRESULT_SUCCESS); 2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry catch (const std::exception& e) 2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_state.setState(COMMLINKSTATE_ERROR, e.what()); 2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpIpSendThread::stop (void) 2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_isRunning) 2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_buffer.cancel(); 2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry join(); 2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_isRunning = false; 2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// TcpIpRecvThread 2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2633c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTcpIpRecvThread::TcpIpRecvThread (de::Socket& socket, TcpIpLinkState& state) 2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_socket (socket) 2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_state (state) 2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_curMsgPos (0) 2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_isRunning (false) 2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2713c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTcpIpRecvThread::~TcpIpRecvThread (void) 2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpIpRecvThread::start (void) 2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(!m_isRunning); 2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Reset state. 2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_curMsgPos = 0; 2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_isRunning = true; 2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry de::Thread::start(); 2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpIpRecvThread::run (void) 2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry try 2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (;;) 2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool hasHeader = m_curMsgPos >= xs::MESSAGE_HEADER_SIZE; 2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool hasPayload = false; 294745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry size_t messageSize = 0; 2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry xs::MessageType messageType = (xs::MessageType)0; 2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (hasHeader) 2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry xs::Message::parseHeader(&m_curMsgBuf[0], xs::MESSAGE_HEADER_SIZE, messageType, messageSize); 3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry hasPayload = m_curMsgPos >= messageSize; 3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (hasPayload) 3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Process message. 3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry handleMessage(messageType, m_curMsgPos > xs::MESSAGE_HEADER_SIZE ? &m_curMsgBuf[xs::MESSAGE_HEADER_SIZE] : DE_NULL, messageSize-xs::MESSAGE_HEADER_SIZE); 3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_curMsgPos = 0; 3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Try to receive missing bytes. 312745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry size_t curSize = hasHeader ? messageSize : (size_t)xs::MESSAGE_HEADER_SIZE; 313745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry size_t bytesToRecv = curSize-m_curMsgPos; 314745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry size_t numRecv = 0; 3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deSocketResult result = DE_SOCKETRESULT_LAST; 3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 317745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry if (m_curMsgBuf.size() < curSize) 3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_curMsgBuf.resize(curSize); 3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry result = m_socket.receive(&m_curMsgBuf[m_curMsgPos], bytesToRecv, &numRecv); 3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (result == DE_SOCKETRESULT_CONNECTION_CLOSED) 3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry XE_FAIL("Connection closed"); 3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (result == DE_SOCKETRESULT_CONNECTION_TERMINATED) 3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry XE_FAIL("Connection terminated"); 3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (result == DE_SOCKETRESULT_ERROR) 3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry XE_FAIL("Socket error"); 3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (result == DE_SOCKETRESULT_WOULD_BLOCK) 3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \note Socket should not be in non-blocking mode. 331745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry DE_ASSERT(numRecv == 0); 3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deYield(); 3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(result == DE_SOCKETRESULT_SUCCESS); 3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(numRecv <= bytesToRecv); 3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_curMsgPos += numRecv; 3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Continue receiving bytes / handle message in next iter. 3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry catch (const std::exception& e) 3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_state.setState(COMMLINKSTATE_ERROR, e.what()); 3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpIpRecvThread::stop (void) 3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_isRunning) 3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \note Socket must be closed before terminating receive thread. 3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry XE_CHECK(!m_socket.isReceiveOpen()); 3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry join(); 3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_isRunning = false; 3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 362745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyryvoid TcpIpRecvThread::handleMessage (xs::MessageType messageType, const deUint8* data, size_t dataSize) 3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (messageType) 3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case xs::MESSAGETYPE_KEEPALIVE: 3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_state.onKeepaliveReceived(); 3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case xs::MESSAGETYPE_PROCESS_STARTED: 3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry XE_CHECK_MSG(m_state.getState() == COMMLINKSTATE_TEST_PROCESS_LAUNCHING, "Unexpected PROCESS_STARTED message"); 3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_state.setState(COMMLINKSTATE_TEST_PROCESS_RUNNING); 3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case xs::MESSAGETYPE_PROCESS_LAUNCH_FAILED: 3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry xs::ProcessLaunchFailedMessage msg(data, dataSize); 3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry XE_CHECK_MSG(m_state.getState() == COMMLINKSTATE_TEST_PROCESS_LAUNCHING, "Unexpected PROCESS_LAUNCH_FAILED message"); 3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_state.setState(COMMLINKSTATE_TEST_PROCESS_LAUNCH_FAILED, msg.reason.c_str()); 3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case xs::MESSAGETYPE_PROCESS_FINISHED: 3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry XE_CHECK_MSG(m_state.getState() == COMMLINKSTATE_TEST_PROCESS_RUNNING, "Unexpected PROCESS_FINISHED message"); 3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry xs::ProcessFinishedMessage msg(data, dataSize); 3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_state.setState(COMMLINKSTATE_TEST_PROCESS_FINISHED); 3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_UNREF(msg); // \todo [2012-06-19 pyry] Report exit code. 3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case xs::MESSAGETYPE_PROCESS_LOG_DATA: 3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case xs::MESSAGETYPE_INFO: 3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Ignore leading \0 if such is present. \todo [2012-06-19 pyry] Improve protocol. 3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (data[dataSize-1] == 0) 3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry dataSize -= 1; 3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (messageType == xs::MESSAGETYPE_PROCESS_LOG_DATA) 3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry XE_CHECK_MSG(m_state.getState() == COMMLINKSTATE_TEST_PROCESS_RUNNING, "Unexpected PROCESS_LOG_DATA message"); 4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_state.onTestLogData(&data[0], dataSize); 4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_state.onInfoLogData(&data[0], dataSize); 4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry XE_FAIL("Unknown message"); 4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// TcpIpLink 4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4143c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTcpIpLink::TcpIpLink (void) 4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_state (COMMLINKSTATE_ERROR, "Not connected") 4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_sendThread (m_socket, m_state) 4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_recvThread (m_socket, m_state) 4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_keepaliveTimer (DE_NULL) 4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_keepaliveTimer = deTimer_create(keepaliveTimerCallback, this); 4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry XE_CHECK(m_keepaliveTimer); 4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4243c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTcpIpLink::~TcpIpLink (void) 4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry try 4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry closeConnection(); 4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry catch (...) 4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Can't do much except to ignore error. 4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deTimer_destroy(m_keepaliveTimer); 4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpIpLink::closeConnection (void) 4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deSocketState state = m_socket.getState(); 4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (state != DE_SOCKETSTATE_DISCONNECTED && state != DE_SOCKETSTATE_CLOSED) 4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_socket.shutdown(); 4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (deTimer_isActive(m_keepaliveTimer)) 4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deTimer_disable(m_keepaliveTimer); 4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_sendThread.isRunning()) 4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_sendThread.stop(); 4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_recvThread.isRunning()) 4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_recvThread.stop(); 4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_socket.getState() != DE_SOCKETSTATE_CLOSED) 4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_socket.close(); 4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpIpLink::connect (const de::SocketAddress& address) 4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry XE_CHECK(m_socket.getState() == DE_SOCKETSTATE_CLOSED); 4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry XE_CHECK(m_state.getState() == COMMLINKSTATE_ERROR); 4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry XE_CHECK(!m_sendThread.isRunning()); 4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry XE_CHECK(!m_recvThread.isRunning()); 4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_socket.connect(address); 4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry try 4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Clear error and set state to ready. 4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_state.setState(COMMLINKSTATE_READY, ""); 4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_state.onKeepaliveReceived(); 4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Launch threads. 4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_sendThread.start(); 4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_recvThread.start(); 4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry XE_CHECK(deTimer_scheduleInterval(m_keepaliveTimer, xs::KEEPALIVE_SEND_INTERVAL)); 4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry catch (const std::exception& e) 4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry closeConnection(); 4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_state.setState(COMMLINKSTATE_ERROR, e.what()); 483e16b0f52b4af5e934670dfc778cece6b3a4eb9b0Mika Isojärvi throw; 4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpIpLink::disconnect (void) 4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry try 4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry closeConnection(); 4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_state.setState(COMMLINKSTATE_ERROR, "Not connected"); 4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry catch (const std::exception& e) 4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_state.setState(COMMLINKSTATE_ERROR, e.what()); 4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpIpLink::reset (void) 5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \note Just clears error state if we are connected. 5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_socket.getState() == DE_SOCKETSTATE_CONNECTED) 5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_state.setState(COMMLINKSTATE_READY, ""); 5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // \todo [2012-07-10 pyry] Do we need to reset send/receive buffers? 5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry disconnect(); // Abnormal state/usage. Disconnect socket. 5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpIpLink::keepaliveTimerCallback (void* ptr) 5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TcpIpLink* link = static_cast<TcpIpLink*>(ptr); 5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint64 lastKeepalive = link->m_state.getLastKeepaliveRecevied(); 5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint64 curTime = deGetMicroseconds(); 5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Check for timeout. 5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if ((deInt64)curTime-(deInt64)lastKeepalive > xs::KEEPALIVE_TIMEOUT*1000) 5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry link->m_state.setState(COMMLINKSTATE_ERROR, "Keepalive timeout"); 5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Enqueue new keepalive. 5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry try 5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry writeKeepalive(link->m_sendThread.getBuffer()); 5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry catch (const de::BlockBuffer<deUint8>::CanceledException&) 5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Ignore. Can happen in connection teardown. 5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5343c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCommLinkState TcpIpLink::getState (void) const 5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return m_state.getState(); 5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5393c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCommLinkState TcpIpLink::getState (std::string& message) const 5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return m_state.getState(message); 5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpIpLink::setCallbacks (StateChangedFunc stateChangedCallback, LogDataFunc testLogDataCallback, LogDataFunc infoLogDataCallback, void* userPtr) 5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_state.setCallbacks(stateChangedCallback, testLogDataCallback, infoLogDataCallback, userPtr); 5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpIpLink::startTestProcess (const char* name, const char* params, const char* workingDir, const char* caseList) 5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry XE_CHECK(m_state.getState() == COMMLINKSTATE_READY); 5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m_state.setState(COMMLINKSTATE_TEST_PROCESS_LAUNCHING); 5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry writeExecuteBinary(m_sendThread.getBuffer(), name, params, workingDir, caseList); 5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TcpIpLink::stopTestProcess (void) 5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry XE_CHECK(m_state.getState() != COMMLINKSTATE_ERROR); 5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry writeStopExecution(m_sendThread.getBuffer()); 5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // xe 564