| /*------------------------------------------------------------------------- |
| * 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 <typename T> T networkToHost (T value); |
| template <typename T> 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, int dataSize) |
| : m_data (data) |
| , m_size (dataSize) |
| , m_pos (0) |
| { |
| } |
| |
| template <typename T> |
| T get (void) |
| { |
| XS_CHECK_MSG(m_pos + (int)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; |
| int m_size; |
| int m_pos; |
| }; |
| |
| class MessageWriter |
| { |
| public: |
| MessageWriter (MessageType msgType, std::vector<deUint8>& buf) |
| : m_buf(buf) |
| { |
| // Place for size. |
| put<int>(0); |
| |
| // Write message type. |
| put<int>(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 <typename T> |
| 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<deUint8>& m_buf; |
| }; |
| |
| template <> |
| void MessageWriter::put<const char*> (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, int dataSize, MessageType& type, int& size) |
| { |
| XS_CHECK_MSG(dataSize >= MESSAGE_HEADER_SIZE, "Incomplete header"); |
| MessageParser parser(data, dataSize); |
| size = (MessageType)parser.get<int>(); |
| type = (MessageType)parser.get<int>(); |
| } |
| |
| void Message::writeHeader (MessageType type, int messageSize, deUint8* dst, int bufSize) |
| { |
| XS_CHECK_MSG(bufSize >= MESSAGE_HEADER_SIZE, "Incomplete header"); |
| int netSize = hostToNetwork(messageSize); |
| int netType = hostToNetwork((int)type); |
| deMemcpy(dst+0, &netSize, sizeof(netSize)); |
| deMemcpy(dst+4, &netType, sizeof(netType)); |
| } |
| |
| void Message::writeNoData (vector<deUint8>& buf) const |
| { |
| MessageWriter writer(type, buf); |
| } |
| |
| HelloMessage::HelloMessage (const deUint8* data, int dataSize) |
| : Message(MESSAGETYPE_HELLO) |
| { |
| MessageParser parser(data, dataSize); |
| version = parser.get<int>(); |
| parser.assumEnd(); |
| } |
| |
| void HelloMessage::write (vector<deUint8>& buf) const |
| { |
| MessageWriter writer(type, buf); |
| writer.put(version); |
| } |
| |
| TestMessage::TestMessage (const deUint8* data, int dataSize) |
| : Message(MESSAGETYPE_TEST) |
| { |
| MessageParser parser(data, dataSize); |
| parser.getString(test); |
| parser.assumEnd(); |
| } |
| |
| void TestMessage::write (vector<deUint8>& buf) const |
| { |
| MessageWriter writer(type, buf); |
| writer.put(test.c_str()); |
| } |
| |
| ExecuteBinaryMessage::ExecuteBinaryMessage (const deUint8* data, int 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<deUint8>& 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, int dataSize) |
| : Message(MESSAGETYPE_PROCESS_LOG_DATA) |
| { |
| MessageParser parser(data, dataSize); |
| parser.getString(logData); |
| parser.assumEnd(); |
| } |
| |
| void ProcessLogDataMessage::write (vector<deUint8>& buf) const |
| { |
| MessageWriter writer(type, buf); |
| writer.put(logData.c_str()); |
| } |
| |
| ProcessLaunchFailedMessage::ProcessLaunchFailedMessage (const deUint8* data, int dataSize) |
| : Message(MESSAGETYPE_PROCESS_LAUNCH_FAILED) |
| { |
| MessageParser parser(data, dataSize); |
| parser.getString(reason); |
| parser.assumEnd(); |
| } |
| |
| void ProcessLaunchFailedMessage::write (vector<deUint8>& buf) const |
| { |
| MessageWriter writer(type, buf); |
| writer.put(reason.c_str()); |
| } |
| |
| ProcessFinishedMessage::ProcessFinishedMessage (const deUint8* data, int dataSize) |
| : Message(MESSAGETYPE_PROCESS_FINISHED) |
| { |
| MessageParser parser(data, dataSize); |
| exitCode = parser.get<int>(); |
| parser.assumEnd(); |
| } |
| |
| void ProcessFinishedMessage::write (vector<deUint8>& buf) const |
| { |
| MessageWriter writer(type, buf); |
| writer.put(exitCode); |
| } |
| |
| InfoMessage::InfoMessage (const deUint8* data, int dataSize) |
| : Message(MESSAGETYPE_INFO) |
| { |
| MessageParser parser(data, dataSize); |
| parser.getString(info); |
| parser.assumEnd(); |
| } |
| |
| void InfoMessage::write (vector<deUint8>& buf) const |
| { |
| MessageWriter writer(type, buf); |
| writer.put(info.c_str()); |
| } |
| |
| } // xs |