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(uint32_t value)32 inline uint32_t swapEndianess(uint32_t value)
33 {
34 uint32_t b0 = (value >> 0) & 0xFF;
35 uint32_t b1 = (value >> 8) & 0xFF;
36 uint32_t b2 = (value >> 16) & 0xFF;
37 uint32_t b3 = (value >> 24) & 0xFF;
38 return (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
39 }
40
41 template <typename T>
42 T networkToHost(T value);
43 template <typename T>
44 T hostToNetwork(T value);
45
46 template <>
networkToHost(int value)47 int networkToHost(int value)
48 {
49 return (int)swapEndianess((uint32_t)value);
50 }
51 template <>
hostToNetwork(int value)52 int hostToNetwork(int value)
53 {
54 return (int)swapEndianess((uint32_t)value);
55 }
56
57 class MessageParser
58 {
59 public:
MessageParser(const uint8_t * data,size_t dataSize)60 MessageParser(const uint8_t *data, size_t dataSize) : m_data(data), m_size(dataSize), m_pos(0)
61 {
62 }
63
64 template <typename T>
get(void)65 T get(void)
66 {
67 XS_CHECK_MSG(m_pos + sizeof(T) <= m_size, "Invalid payload size");
68 T netValue;
69 deMemcpy(&netValue, &m_data[m_pos], sizeof(T));
70 m_pos += sizeof(T);
71 return networkToHost(netValue);
72 }
73
getString(std::string & dst)74 void getString(std::string &dst)
75 {
76 // \todo [2011-09-30 pyry] We should really send a size parameter instead.
77 while (m_data[m_pos] != 0)
78 {
79 dst += (char)m_data[m_pos++];
80 XS_CHECK_MSG(m_pos < m_size, "Unterminated string payload");
81 }
82
83 m_pos += 1;
84 }
85
assumEnd(void)86 void assumEnd(void)
87 {
88 if (m_pos != m_size)
89 XS_FAIL("Invalid payload size");
90 }
91
92 private:
93 const uint8_t *m_data;
94 size_t m_size;
95 size_t m_pos;
96 };
97
98 class MessageWriter
99 {
100 public:
MessageWriter(MessageType msgType,std::vector<uint8_t> & buf)101 MessageWriter(MessageType msgType, std::vector<uint8_t> &buf) : m_buf(buf)
102 {
103 // Place for size.
104 put<int>(0);
105
106 // Write message type.
107 put<int>(msgType);
108 }
109
~MessageWriter(void)110 ~MessageWriter(void)
111 {
112 finalize();
113 }
114
finalize(void)115 void finalize(void)
116 {
117 DE_ASSERT(m_buf.size() >= MESSAGE_HEADER_SIZE);
118
119 // Write actual size.
120 int size = hostToNetwork((int)m_buf.size());
121 deMemcpy(&m_buf[0], &size, sizeof(int));
122 }
123
124 template <typename T>
put(T value)125 void put(T value)
126 {
127 T netValue = hostToNetwork(value);
128 size_t curPos = m_buf.size();
129 m_buf.resize(curPos + sizeof(T));
130 deMemcpy(&m_buf[curPos], &netValue, sizeof(T));
131 }
132
133 private:
134 std::vector<uint8_t> &m_buf;
135 };
136
137 template <>
put(const char * value)138 void MessageWriter::put<const char *>(const char *value)
139 {
140 int curPos = (int)m_buf.size();
141 int strLen = (int)strlen(value);
142
143 m_buf.resize(curPos + strLen + 1);
144 deMemcpy(&m_buf[curPos], &value[0], strLen + 1);
145 }
146
parseHeader(const uint8_t * data,size_t dataSize,MessageType & type,size_t & size)147 void Message::parseHeader(const uint8_t *data, size_t dataSize, MessageType &type, size_t &size)
148 {
149 XS_CHECK_MSG(dataSize >= MESSAGE_HEADER_SIZE, "Incomplete header");
150 MessageParser parser(data, dataSize);
151 size = (size_t)(MessageType)parser.get<int>();
152 type = (MessageType)parser.get<int>();
153 }
154
writeHeader(MessageType type,size_t messageSize,uint8_t * dst,size_t bufSize)155 void Message::writeHeader(MessageType type, size_t messageSize, uint8_t *dst, size_t bufSize)
156 {
157 XS_CHECK_MSG(bufSize >= MESSAGE_HEADER_SIZE, "Incomplete header");
158 int netSize = hostToNetwork((int)messageSize);
159 int netType = hostToNetwork((int)type);
160 deMemcpy(dst + 0, &netSize, sizeof(netSize));
161 deMemcpy(dst + 4, &netType, sizeof(netType));
162 }
163
writeNoData(vector<uint8_t> & buf) const164 void Message::writeNoData(vector<uint8_t> &buf) const
165 {
166 MessageWriter writer(type, buf);
167 }
168
HelloMessage(const uint8_t * data,size_t dataSize)169 HelloMessage::HelloMessage(const uint8_t *data, size_t dataSize) : Message(MESSAGETYPE_HELLO)
170 {
171 MessageParser parser(data, dataSize);
172 version = parser.get<int>();
173 parser.assumEnd();
174 }
175
write(vector<uint8_t> & buf) const176 void HelloMessage::write(vector<uint8_t> &buf) const
177 {
178 MessageWriter writer(type, buf);
179 writer.put(version);
180 }
181
TestMessage(const uint8_t * data,size_t dataSize)182 TestMessage::TestMessage(const uint8_t *data, size_t dataSize) : Message(MESSAGETYPE_TEST)
183 {
184 MessageParser parser(data, dataSize);
185 parser.getString(test);
186 parser.assumEnd();
187 }
188
write(vector<uint8_t> & buf) const189 void TestMessage::write(vector<uint8_t> &buf) const
190 {
191 MessageWriter writer(type, buf);
192 writer.put(test.c_str());
193 }
194
ExecuteBinaryMessage(const uint8_t * data,size_t dataSize)195 ExecuteBinaryMessage::ExecuteBinaryMessage(const uint8_t *data, size_t dataSize) : Message(MESSAGETYPE_EXECUTE_BINARY)
196 {
197 MessageParser parser(data, dataSize);
198 parser.getString(name);
199 parser.getString(params);
200 parser.getString(workDir);
201 parser.getString(caseList);
202 parser.assumEnd();
203 }
204
write(vector<uint8_t> & buf) const205 void ExecuteBinaryMessage::write(vector<uint8_t> &buf) const
206 {
207 MessageWriter writer(type, buf);
208 writer.put(name.c_str());
209 writer.put(params.c_str());
210 writer.put(workDir.c_str());
211 writer.put(caseList.c_str());
212 }
213
ProcessLogDataMessage(const uint8_t * data,size_t dataSize)214 ProcessLogDataMessage::ProcessLogDataMessage(const uint8_t *data, size_t dataSize)
215 : Message(MESSAGETYPE_PROCESS_LOG_DATA)
216 {
217 MessageParser parser(data, dataSize);
218 parser.getString(logData);
219 parser.assumEnd();
220 }
221
write(vector<uint8_t> & buf) const222 void ProcessLogDataMessage::write(vector<uint8_t> &buf) const
223 {
224 MessageWriter writer(type, buf);
225 writer.put(logData.c_str());
226 }
227
ProcessLaunchFailedMessage(const uint8_t * data,size_t dataSize)228 ProcessLaunchFailedMessage::ProcessLaunchFailedMessage(const uint8_t *data, size_t dataSize)
229 : Message(MESSAGETYPE_PROCESS_LAUNCH_FAILED)
230 {
231 MessageParser parser(data, dataSize);
232 parser.getString(reason);
233 parser.assumEnd();
234 }
235
write(vector<uint8_t> & buf) const236 void ProcessLaunchFailedMessage::write(vector<uint8_t> &buf) const
237 {
238 MessageWriter writer(type, buf);
239 writer.put(reason.c_str());
240 }
241
ProcessFinishedMessage(const uint8_t * data,size_t dataSize)242 ProcessFinishedMessage::ProcessFinishedMessage(const uint8_t *data, size_t dataSize)
243 : Message(MESSAGETYPE_PROCESS_FINISHED)
244 {
245 MessageParser parser(data, dataSize);
246 exitCode = parser.get<int>();
247 parser.assumEnd();
248 }
249
write(vector<uint8_t> & buf) const250 void ProcessFinishedMessage::write(vector<uint8_t> &buf) const
251 {
252 MessageWriter writer(type, buf);
253 writer.put(exitCode);
254 }
255
InfoMessage(const uint8_t * data,size_t dataSize)256 InfoMessage::InfoMessage(const uint8_t *data, size_t dataSize) : Message(MESSAGETYPE_INFO)
257 {
258 MessageParser parser(data, dataSize);
259 parser.getString(info);
260 parser.assumEnd();
261 }
262
write(vector<uint8_t> & buf) const263 void InfoMessage::write(vector<uint8_t> &buf) const
264 {
265 MessageWriter writer(type, buf);
266 writer.put(info.c_str());
267 }
268
269 } // namespace xs
270