You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
267 lines
6.3 KiB
267 lines
6.3 KiB
/*------------------------------------------------------------------------- |
|
* 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, size_t dataSize) |
|
: m_data (data) |
|
, m_size (dataSize) |
|
, m_pos (0) |
|
{ |
|
} |
|
|
|
template <typename T> |
|
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<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, 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<int>(); |
|
type = (MessageType)parser.get<int>(); |
|
} |
|
|
|
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<deUint8>& buf) const |
|
{ |
|
MessageWriter writer(type, buf); |
|
} |
|
|
|
HelloMessage::HelloMessage (const deUint8* data, size_t 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, size_t 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, 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<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, size_t 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, size_t 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, size_t 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, size_t 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
|
|
|