Home | History | Annotate | Download | only in execserver
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program Execution Server
      3  * ---------------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief Execution Server Protocol.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "xsProtocol.hpp"
     25 
     26 using std::string;
     27 using std::vector;
     28 
     29 namespace xs
     30 {
     31 
     32 inline deUint32 swapEndianess (deUint32 value)
     33 {
     34 	deUint32 b0 = (value >>  0) & 0xFF;
     35 	deUint32 b1 = (value >>  8) & 0xFF;
     36 	deUint32 b2 = (value >> 16) & 0xFF;
     37 	deUint32 b3 = (value >> 24) & 0xFF;
     38 	return (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
     39 }
     40 
     41 template <typename T> T networkToHost (T value);
     42 template <typename T> T hostToNetwork (T value);
     43 
     44 template <> int networkToHost (int value) { return (int)swapEndianess((deUint32)value); }
     45 template <> int hostToNetwork (int value) { return (int)swapEndianess((deUint32)value); }
     46 
     47 class MessageParser
     48 {
     49 public:
     50 	MessageParser (const deUint8* data, int dataSize)
     51 		: m_data	(data)
     52 		, m_size	(dataSize)
     53 		, m_pos		(0)
     54 	{
     55 	}
     56 
     57 	template <typename T>
     58 	T get (void)
     59 	{
     60 		XS_CHECK_MSG(m_pos + (int)sizeof(T) <= m_size, "Invalid payload size");
     61 		T netValue;
     62 		deMemcpy(&netValue, &m_data[m_pos], sizeof(T));
     63 		m_pos += sizeof(T);
     64 		return networkToHost(netValue);
     65 	}
     66 
     67 	void getString (std::string& dst)
     68 	{
     69 		// \todo [2011-09-30 pyry] We should really send a size parameter instead.
     70 		while (m_data[m_pos] != 0)
     71 		{
     72 			dst += (char)m_data[m_pos++];
     73 			XS_CHECK_MSG(m_pos < m_size, "Unterminated string payload");
     74 		}
     75 
     76 		m_pos += 1;
     77 	}
     78 
     79 	void assumEnd (void)
     80 	{
     81 		if (m_pos != m_size)
     82 			XS_FAIL("Invalid payload size");
     83 	}
     84 
     85 private:
     86 	const deUint8*	m_data;
     87 	int				m_size;
     88 	int				m_pos;
     89 };
     90 
     91 class MessageWriter
     92 {
     93 public:
     94 	MessageWriter (MessageType msgType, std::vector<deUint8>& buf)
     95 		: m_buf(buf)
     96 	{
     97 		// Place for size.
     98 		put<int>(0);
     99 
    100 		// Write message type.
    101 		put<int>(msgType);
    102 	}
    103 
    104 	~MessageWriter (void)
    105 	{
    106 		finalize();
    107 	}
    108 
    109 	void finalize (void)
    110 	{
    111 		DE_ASSERT(m_buf.size() >= MESSAGE_HEADER_SIZE);
    112 
    113 		// Write actual size.
    114 		int size = hostToNetwork((int)m_buf.size());
    115 		deMemcpy(&m_buf[0], &size, sizeof(int));
    116 	}
    117 
    118 	template <typename T>
    119 	void put (T value)
    120 	{
    121 		T netValue = hostToNetwork(value);
    122 		size_t curPos = m_buf.size();
    123 		m_buf.resize(curPos + sizeof(T));
    124 		deMemcpy(&m_buf[curPos], &netValue, sizeof(T));
    125 	}
    126 
    127 private:
    128 	std::vector<deUint8>& m_buf;
    129 };
    130 
    131 template <>
    132 void MessageWriter::put<const char*> (const char* value)
    133 {
    134 	int curPos = (int)m_buf.size();
    135 	int strLen = (int)strlen(value);
    136 
    137 	m_buf.resize(curPos + strLen+1);
    138 	deMemcpy(&m_buf[curPos], &value[0], strLen+1);
    139 }
    140 
    141 void Message::parseHeader (const deUint8* data, int dataSize, MessageType& type, int& size)
    142 {
    143 	XS_CHECK_MSG(dataSize >= MESSAGE_HEADER_SIZE, "Incomplete header");
    144 	MessageParser parser(data, dataSize);
    145 	size	= (MessageType)parser.get<int>();
    146 	type	= (MessageType)parser.get<int>();
    147 }
    148 
    149 void Message::writeHeader (MessageType type, int messageSize, deUint8* dst, int bufSize)
    150 {
    151 	XS_CHECK_MSG(bufSize >= MESSAGE_HEADER_SIZE, "Incomplete header");
    152 	int netSize = hostToNetwork(messageSize);
    153 	int netType = hostToNetwork((int)type);
    154 	deMemcpy(dst+0, &netSize, sizeof(netSize));
    155 	deMemcpy(dst+4, &netType, sizeof(netType));
    156 }
    157 
    158 void Message::writeNoData (vector<deUint8>& buf) const
    159 {
    160 	MessageWriter writer(type, buf);
    161 }
    162 
    163 HelloMessage::HelloMessage (const deUint8* data, int dataSize)
    164 	: Message(MESSAGETYPE_HELLO)
    165 {
    166 	MessageParser parser(data, dataSize);
    167 	version = parser.get<int>();
    168 	parser.assumEnd();
    169 }
    170 
    171 void HelloMessage::write (vector<deUint8>& buf) const
    172 {
    173 	MessageWriter writer(type, buf);
    174 	writer.put(version);
    175 }
    176 
    177 TestMessage::TestMessage (const deUint8* data, int dataSize)
    178 	: Message(MESSAGETYPE_TEST)
    179 {
    180 	MessageParser parser(data, dataSize);
    181 	parser.getString(test);
    182 	parser.assumEnd();
    183 }
    184 
    185 void TestMessage::write (vector<deUint8>& buf) const
    186 {
    187 	MessageWriter writer(type, buf);
    188 	writer.put(test.c_str());
    189 }
    190 
    191 ExecuteBinaryMessage::ExecuteBinaryMessage (const deUint8* data, int dataSize)
    192 	: Message(MESSAGETYPE_EXECUTE_BINARY)
    193 {
    194 	MessageParser parser(data, dataSize);
    195 	parser.getString(name);
    196 	parser.getString(params);
    197 	parser.getString(workDir);
    198 	parser.getString(caseList);
    199 	parser.assumEnd();
    200 }
    201 
    202 void ExecuteBinaryMessage::write (vector<deUint8>& buf) const
    203 {
    204 	MessageWriter writer(type, buf);
    205 	writer.put(name.c_str());
    206 	writer.put(params.c_str());
    207 	writer.put(workDir.c_str());
    208 	writer.put(caseList.c_str());
    209 }
    210 
    211 ProcessLogDataMessage::ProcessLogDataMessage (const deUint8* data, int dataSize)
    212 	: Message(MESSAGETYPE_PROCESS_LOG_DATA)
    213 {
    214 	MessageParser parser(data, dataSize);
    215 	parser.getString(logData);
    216 	parser.assumEnd();
    217 }
    218 
    219 void ProcessLogDataMessage::write (vector<deUint8>& buf) const
    220 {
    221 	MessageWriter writer(type, buf);
    222 	writer.put(logData.c_str());
    223 }
    224 
    225 ProcessLaunchFailedMessage::ProcessLaunchFailedMessage (const deUint8* data, int dataSize)
    226 	: Message(MESSAGETYPE_PROCESS_LAUNCH_FAILED)
    227 {
    228 	MessageParser parser(data, dataSize);
    229 	parser.getString(reason);
    230 	parser.assumEnd();
    231 }
    232 
    233 void ProcessLaunchFailedMessage::write (vector<deUint8>& buf) const
    234 {
    235 	MessageWriter writer(type, buf);
    236 	writer.put(reason.c_str());
    237 }
    238 
    239 ProcessFinishedMessage::ProcessFinishedMessage (const deUint8* data, int dataSize)
    240 	: Message(MESSAGETYPE_PROCESS_FINISHED)
    241 {
    242 	MessageParser parser(data, dataSize);
    243 	exitCode = parser.get<int>();
    244 	parser.assumEnd();
    245 }
    246 
    247 void ProcessFinishedMessage::write (vector<deUint8>& buf) const
    248 {
    249 	MessageWriter writer(type, buf);
    250 	writer.put(exitCode);
    251 }
    252 
    253 InfoMessage::InfoMessage (const deUint8* data, int dataSize)
    254 	: Message(MESSAGETYPE_INFO)
    255 {
    256 	MessageParser parser(data, dataSize);
    257 	parser.getString(info);
    258 	parser.assumEnd();
    259 }
    260 
    261 void InfoMessage::write (vector<deUint8>& buf) const
    262 {
    263 	MessageWriter writer(type, buf);
    264 	writer.put(info.c_str());
    265 }
    266 
    267 } // xs
    268