/*------------------------------------------------------------------------- * drawElements Quality Program Execution Server * --------------------------------------------- * * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Execution Server Protocol. *//*--------------------------------------------------------------------*/ #include "xsProtocol.hpp" using std::string; using std::vector; namespace xs { inline deUint32 swapEndianess (deUint32 value) { deUint32 b0 = (value >> 0) & 0xFF; deUint32 b1 = (value >> 8) & 0xFF; deUint32 b2 = (value >> 16) & 0xFF; deUint32 b3 = (value >> 24) & 0xFF; return (b0 << 24) | (b1 << 16) | (b2 << 8) | b3; } template T networkToHost (T value); template T hostToNetwork (T value); template <> int networkToHost (int value) { return (int)swapEndianess((deUint32)value); } template <> int hostToNetwork (int value) { return (int)swapEndianess((deUint32)value); } class MessageParser { public: MessageParser (const deUint8* data, size_t dataSize) : m_data (data) , m_size (dataSize) , m_pos (0) { } template T get (void) { XS_CHECK_MSG(m_pos + sizeof(T) <= m_size, "Invalid payload size"); T netValue; deMemcpy(&netValue, &m_data[m_pos], sizeof(T)); m_pos += sizeof(T); return networkToHost(netValue); } void getString (std::string& dst) { // \todo [2011-09-30 pyry] We should really send a size parameter instead. while (m_data[m_pos] != 0) { dst += (char)m_data[m_pos++]; XS_CHECK_MSG(m_pos < m_size, "Unterminated string payload"); } m_pos += 1; } void assumEnd (void) { if (m_pos != m_size) XS_FAIL("Invalid payload size"); } private: const deUint8* m_data; size_t m_size; size_t m_pos; }; class MessageWriter { public: MessageWriter (MessageType msgType, std::vector& buf) : m_buf(buf) { // Place for size. put(0); // Write message type. put(msgType); } ~MessageWriter (void) { finalize(); } void finalize (void) { DE_ASSERT(m_buf.size() >= MESSAGE_HEADER_SIZE); // Write actual size. int size = hostToNetwork((int)m_buf.size()); deMemcpy(&m_buf[0], &size, sizeof(int)); } template void put (T value) { T netValue = hostToNetwork(value); size_t curPos = m_buf.size(); m_buf.resize(curPos + sizeof(T)); deMemcpy(&m_buf[curPos], &netValue, sizeof(T)); } private: std::vector& m_buf; }; template <> void MessageWriter::put (const char* value) { int curPos = (int)m_buf.size(); int strLen = (int)strlen(value); m_buf.resize(curPos + strLen+1); deMemcpy(&m_buf[curPos], &value[0], strLen+1); } void Message::parseHeader (const deUint8* data, size_t dataSize, MessageType& type, size_t& size) { XS_CHECK_MSG(dataSize >= MESSAGE_HEADER_SIZE, "Incomplete header"); MessageParser parser(data, dataSize); size = (size_t)(MessageType)parser.get(); type = (MessageType)parser.get(); } void Message::writeHeader (MessageType type, size_t messageSize, deUint8* dst, size_t bufSize) { XS_CHECK_MSG(bufSize >= MESSAGE_HEADER_SIZE, "Incomplete header"); int netSize = hostToNetwork((int)messageSize); int netType = hostToNetwork((int)type); deMemcpy(dst+0, &netSize, sizeof(netSize)); deMemcpy(dst+4, &netType, sizeof(netType)); } void Message::writeNoData (vector& buf) const { MessageWriter writer(type, buf); } HelloMessage::HelloMessage (const deUint8* data, size_t dataSize) : Message(MESSAGETYPE_HELLO) { MessageParser parser(data, dataSize); version = parser.get(); parser.assumEnd(); } void HelloMessage::write (vector& buf) const { MessageWriter writer(type, buf); writer.put(version); } TestMessage::TestMessage (const deUint8* data, size_t dataSize) : Message(MESSAGETYPE_TEST) { MessageParser parser(data, dataSize); parser.getString(test); parser.assumEnd(); } void TestMessage::write (vector& buf) const { MessageWriter writer(type, buf); writer.put(test.c_str()); } ExecuteBinaryMessage::ExecuteBinaryMessage (const deUint8* data, size_t dataSize) : Message(MESSAGETYPE_EXECUTE_BINARY) { MessageParser parser(data, dataSize); parser.getString(name); parser.getString(params); parser.getString(workDir); parser.getString(caseList); parser.assumEnd(); } void ExecuteBinaryMessage::write (vector& buf) const { MessageWriter writer(type, buf); writer.put(name.c_str()); writer.put(params.c_str()); writer.put(workDir.c_str()); writer.put(caseList.c_str()); } ProcessLogDataMessage::ProcessLogDataMessage (const deUint8* data, size_t dataSize) : Message(MESSAGETYPE_PROCESS_LOG_DATA) { MessageParser parser(data, dataSize); parser.getString(logData); parser.assumEnd(); } void ProcessLogDataMessage::write (vector& buf) const { MessageWriter writer(type, buf); writer.put(logData.c_str()); } ProcessLaunchFailedMessage::ProcessLaunchFailedMessage (const deUint8* data, size_t dataSize) : Message(MESSAGETYPE_PROCESS_LAUNCH_FAILED) { MessageParser parser(data, dataSize); parser.getString(reason); parser.assumEnd(); } void ProcessLaunchFailedMessage::write (vector& buf) const { MessageWriter writer(type, buf); writer.put(reason.c_str()); } ProcessFinishedMessage::ProcessFinishedMessage (const deUint8* data, size_t dataSize) : Message(MESSAGETYPE_PROCESS_FINISHED) { MessageParser parser(data, dataSize); exitCode = parser.get(); parser.assumEnd(); } void ProcessFinishedMessage::write (vector& buf) const { MessageWriter writer(type, buf); writer.put(exitCode); } InfoMessage::InfoMessage (const deUint8* data, size_t dataSize) : Message(MESSAGETYPE_INFO) { MessageParser parser(data, dataSize); parser.getString(info); parser.assumEnd(); } void InfoMessage::write (vector& buf) const { MessageWriter writer(type, buf); writer.put(info.c_str()); } } // xs