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 
swapEndianess(deUint32 value)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 
networkToHost(int value)44 template <> int networkToHost (int value) { return (int)swapEndianess((deUint32)value); }
hostToNetwork(int value)45 template <> int hostToNetwork (int value) { return (int)swapEndianess((deUint32)value); }
46 
47 class MessageParser
48 {
49 public:
MessageParser(const deUint8 * data,size_t dataSize)50 	MessageParser (const deUint8* data, size_t dataSize)
51 		: m_data	(data)
52 		, m_size	(dataSize)
53 		, m_pos		(0)
54 	{
55 	}
56 
57 	template <typename T>
get(void)58 	T get (void)
59 	{
60 		XS_CHECK_MSG(m_pos + 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 
getString(std::string & dst)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 
assumEnd(void)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 	size_t			m_size;
88 	size_t			m_pos;
89 };
90 
91 class MessageWriter
92 {
93 public:
MessageWriter(MessageType msgType,std::vector<deUint8> & buf)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 
~MessageWriter(void)104 	~MessageWriter (void)
105 	{
106 		finalize();
107 	}
108 
finalize(void)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>
put(T value)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 <>
put(const char * value)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 
parseHeader(const deUint8 * data,size_t dataSize,MessageType & type,size_t & size)141 void Message::parseHeader (const deUint8* data, size_t dataSize, MessageType& type, size_t& size)
142 {
143 	XS_CHECK_MSG(dataSize >= MESSAGE_HEADER_SIZE, "Incomplete header");
144 	MessageParser parser(data, dataSize);
145 	size	= (size_t)(MessageType)parser.get<int>();
146 	type	= (MessageType)parser.get<int>();
147 }
148 
writeHeader(MessageType type,size_t messageSize,deUint8 * dst,size_t bufSize)149 void Message::writeHeader (MessageType type, size_t messageSize, deUint8* dst, size_t bufSize)
150 {
151 	XS_CHECK_MSG(bufSize >= MESSAGE_HEADER_SIZE, "Incomplete header");
152 	int netSize = hostToNetwork((int)messageSize);
153 	int netType = hostToNetwork((int)type);
154 	deMemcpy(dst+0, &netSize, sizeof(netSize));
155 	deMemcpy(dst+4, &netType, sizeof(netType));
156 }
157 
writeNoData(vector<deUint8> & buf) const158 void Message::writeNoData (vector<deUint8>& buf) const
159 {
160 	MessageWriter writer(type, buf);
161 }
162 
HelloMessage(const deUint8 * data,size_t dataSize)163 HelloMessage::HelloMessage (const deUint8* data, size_t dataSize)
164 	: Message(MESSAGETYPE_HELLO)
165 {
166 	MessageParser parser(data, dataSize);
167 	version = parser.get<int>();
168 	parser.assumEnd();
169 }
170 
write(vector<deUint8> & buf) const171 void HelloMessage::write (vector<deUint8>& buf) const
172 {
173 	MessageWriter writer(type, buf);
174 	writer.put(version);
175 }
176 
TestMessage(const deUint8 * data,size_t dataSize)177 TestMessage::TestMessage (const deUint8* data, size_t dataSize)
178 	: Message(MESSAGETYPE_TEST)
179 {
180 	MessageParser parser(data, dataSize);
181 	parser.getString(test);
182 	parser.assumEnd();
183 }
184 
write(vector<deUint8> & buf) const185 void TestMessage::write (vector<deUint8>& buf) const
186 {
187 	MessageWriter writer(type, buf);
188 	writer.put(test.c_str());
189 }
190 
ExecuteBinaryMessage(const deUint8 * data,size_t dataSize)191 ExecuteBinaryMessage::ExecuteBinaryMessage (const deUint8* data, size_t 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 
write(vector<deUint8> & buf) const202 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 
ProcessLogDataMessage(const deUint8 * data,size_t dataSize)211 ProcessLogDataMessage::ProcessLogDataMessage (const deUint8* data, size_t dataSize)
212 	: Message(MESSAGETYPE_PROCESS_LOG_DATA)
213 {
214 	MessageParser parser(data, dataSize);
215 	parser.getString(logData);
216 	parser.assumEnd();
217 }
218 
write(vector<deUint8> & buf) const219 void ProcessLogDataMessage::write (vector<deUint8>& buf) const
220 {
221 	MessageWriter writer(type, buf);
222 	writer.put(logData.c_str());
223 }
224 
ProcessLaunchFailedMessage(const deUint8 * data,size_t dataSize)225 ProcessLaunchFailedMessage::ProcessLaunchFailedMessage (const deUint8* data, size_t dataSize)
226 	: Message(MESSAGETYPE_PROCESS_LAUNCH_FAILED)
227 {
228 	MessageParser parser(data, dataSize);
229 	parser.getString(reason);
230 	parser.assumEnd();
231 }
232 
write(vector<deUint8> & buf) const233 void ProcessLaunchFailedMessage::write (vector<deUint8>& buf) const
234 {
235 	MessageWriter writer(type, buf);
236 	writer.put(reason.c_str());
237 }
238 
ProcessFinishedMessage(const deUint8 * data,size_t dataSize)239 ProcessFinishedMessage::ProcessFinishedMessage (const deUint8* data, size_t dataSize)
240 	: Message(MESSAGETYPE_PROCESS_FINISHED)
241 {
242 	MessageParser parser(data, dataSize);
243 	exitCode = parser.get<int>();
244 	parser.assumEnd();
245 }
246 
write(vector<deUint8> & buf) const247 void ProcessFinishedMessage::write (vector<deUint8>& buf) const
248 {
249 	MessageWriter writer(type, buf);
250 	writer.put(exitCode);
251 }
252 
InfoMessage(const deUint8 * data,size_t dataSize)253 InfoMessage::InfoMessage (const deUint8* data, size_t dataSize)
254 	: Message(MESSAGETYPE_INFO)
255 {
256 	MessageParser parser(data, dataSize);
257 	parser.getString(info);
258 	parser.assumEnd();
259 }
260 
write(vector<deUint8> & buf) const261 void InfoMessage::write (vector<deUint8>& buf) const
262 {
263 	MessageWriter writer(type, buf);
264 	writer.put(info.c_str());
265 }
266 
267 } // xs
268