blob: db24d80e3f635dbb79aded163af5a11a41a3382c [file] [log] [blame]
Kevin Rocardef8d7272014-04-23 20:34:14 +02001/*
David Wagnerb76c9d62014-02-05 18:30:24 +01002 * Copyright (c) 2011-2014, Intel Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation and/or
13 * other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 * may be used to endorse or promote products derived from this software without
17 * specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Patrick Benavoli68a91282011-08-31 11:23:23 +020029 */
30#include "Message.h"
31#include <assert.h>
32#include "Socket.h"
33#include "RemoteProcessorProtocol.h"
34#include <string.h>
35#include <assert.h>
Kevin Rocardef8d7272014-04-23 20:34:14 +020036#include <errno.h>
Patrick Benavoli68a91282011-08-31 11:23:23 +020037
38CMessage::CMessage(uint8_t ucMsgId) : _ucMsgId(ucMsgId), _pucData(NULL), _uiDataSize(0), _uiIndex(0)
39{
40}
41
Patrick Benavoli930075c2011-08-31 17:09:06 +020042CMessage::CMessage() : _ucMsgId((uint8_t)-1), _pucData(NULL), _uiDataSize(0), _uiIndex(0)
Patrick Benavoli68a91282011-08-31 11:23:23 +020043{
44}
45
46CMessage::~CMessage()
47{
48 delete [] _pucData;
49}
50
51// Msg Id
52uint8_t CMessage::getMsgId() const
53{
54 return _ucMsgId;
55}
56
57// Data
58void CMessage::writeData(const void* pvData, uint32_t uiSize)
59{
60 assert(_uiIndex + uiSize <= _uiDataSize);
61
62 // Copy
63 memcpy(&_pucData[_uiIndex], pvData, uiSize);
64
65 // Index
66 _uiIndex += uiSize;
67}
68
69void CMessage::readData(void* pvData, uint32_t uiSize)
70{
71 assert(_uiIndex + uiSize <= _uiDataSize);
72
73 // Copy
74 memcpy(pvData, &_pucData[_uiIndex], uiSize);
75
76 // Index
77 _uiIndex += uiSize;
78}
79
80void CMessage::writeString(const string& strData)
81{
82 // Size
83 uint32_t uiSize = strData.length();
84
85 writeData(&uiSize, sizeof(uiSize));
86
87 // Content
88 writeData(strData.c_str(), uiSize);
89}
90
91void CMessage::readString(string& strData)
92{
93 // Size
94 uint32_t uiSize;
95
96 readData(&uiSize, sizeof(uiSize));
97
98 // Data
99 char* pcData = new char[uiSize + 1];
100
101 // Content
102 readData(pcData, uiSize);
103
104 // NULL-terminate string
105 pcData[uiSize] = '\0';
106
107 // Output
108 strData = pcData;
109
110 // Delete
111 delete [] pcData;
112}
113
114uint32_t CMessage::getStringSize(const string& strData) const
115{
116 // Return string length plus room to store its length
117 return strData.length() + sizeof(uint32_t);
118}
119
120// Remaining data size
121uint32_t CMessage::getRemainingDataSize() const
122{
123 return _uiDataSize - _uiIndex;
124}
125
126// Send/Receive
Kevin Rocardef8d7272014-04-23 20:34:14 +0200127bool CMessage::serialize(CSocket* pSocket, bool bOut, string& strError)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200128{
129 if (bOut) {
130
131 // Make room for data to send
132 allocateData(getDataSize());
133
134 // Get data from derived
135 fillDataToSend();
136
137 // Finished providing data?
138 assert(_uiIndex == _uiDataSize);
139
140 // First send sync word
141 uint16_t uiSyncWord = SYNC_WORD;
142
143 if (!pSocket->write(&uiSyncWord, sizeof(uiSyncWord))) {
144
Kevin Rocardef8d7272014-04-23 20:34:14 +0200145 strError += string("Sync write failed: ") + strerror(errno);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200146 return false;
147 }
148
149 // Size
150 uint32_t uiSize = sizeof(_ucMsgId) + _uiDataSize;
151
152 if (!pSocket->write(&uiSize, sizeof(uiSize))) {
153
Kevin Rocardef8d7272014-04-23 20:34:14 +0200154 strError += string("Size write failed: ") + strerror(errno);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200155 return false;
156 }
157
158 // Msg Id
159 if (!pSocket->write(&_ucMsgId, sizeof(_ucMsgId))) {
160
Kevin Rocardef8d7272014-04-23 20:34:14 +0200161 strError += string("Msg write failed: ") + strerror(errno);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200162 return false;
163 }
164
165 // Data
166 if (!pSocket->write(_pucData, _uiDataSize)) {
167
Kevin Rocardef8d7272014-04-23 20:34:14 +0200168 strError = string("Data write failed: ") + strerror(errno);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200169 return false;
170 }
171
172 // Checksum
173 uint8_t ucChecksum = computeChecksum();
174
175 if (!pSocket->write(&ucChecksum, sizeof(ucChecksum))) {
176
Kevin Rocardef8d7272014-04-23 20:34:14 +0200177 strError = string("Checksum write failed: ") + strerror(errno);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200178 return false;
179 }
180
181 } else {
182 // First read sync word
183 uint16_t uiSyncWord;
184
185 if (!pSocket->read(&uiSyncWord, sizeof(uiSyncWord))) {
186
Kevin Rocardef8d7272014-04-23 20:34:14 +0200187 strError = string("Sync read failed: ") + strerror(errno);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200188 return false;
189 }
190
191 // Check Sync word
192 if (uiSyncWord != SYNC_WORD) {
193
Kevin Rocardef8d7272014-04-23 20:34:14 +0200194 strError = "Sync word incorrect";
Patrick Benavoli68a91282011-08-31 11:23:23 +0200195 return false;
196 }
197
198 // Size
199 uint32_t uiSize;
200
201 if (!pSocket->read(&uiSize, sizeof(uiSize))) {
202
Kevin Rocardef8d7272014-04-23 20:34:14 +0200203 strError = string("Size read failed: ") + strerror(errno);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200204 return false;
205 }
206
207 // Msg Id
208 if (!pSocket->read(&_ucMsgId, sizeof(_ucMsgId))) {
209
Kevin Rocardef8d7272014-04-23 20:34:14 +0200210 strError = string("Msg id read failed: ") + strerror(errno);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200211 return false;
212 }
213
214 // Data
215
216 // Allocate
217 allocateData(uiSize - sizeof(_ucMsgId));
218
219 // Data receive
220 if (!pSocket->read(_pucData, _uiDataSize)) {
221
Kevin Rocardef8d7272014-04-23 20:34:14 +0200222 strError = string("Data read failed: ") + strerror(errno);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200223 return false;
224 }
225
226 // Checksum
227 uint8_t ucChecksum;
228
229 if (!pSocket->read(&ucChecksum, sizeof(ucChecksum))) {
230
Kevin Rocardef8d7272014-04-23 20:34:14 +0200231 strError = string("Checksum read failed: ") + strerror(errno);
Patrick Benavoli68a91282011-08-31 11:23:23 +0200232 return false;
233 }
234 // Compare
235 if (ucChecksum != computeChecksum()) {
236
Kevin Rocardef8d7272014-04-23 20:34:14 +0200237 strError = "Received checksum != computed checksum";
Patrick Benavoli68a91282011-08-31 11:23:23 +0200238 return false;
239 }
240
241 // Collect data in derived
242 collectReceivedData();
243 }
244
245 return true;
246}
247
248// Checksum
249uint8_t CMessage::computeChecksum() const
250{
Patrick Benavoli1387bda2011-08-31 11:23:24 +0200251 uint8_t uiChecksum = _ucMsgId;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200252
253 uint32_t uiIndex;
254
255 for (uiIndex = 0; uiIndex < _uiDataSize; uiIndex++) {
256
257 uiChecksum += _pucData[uiIndex];
258 }
259
260 return uiChecksum;
261}
262
263// Data allocation
264void CMessage::allocateData(uint32_t uiSize)
265{
266 // Remove previous one
267 if (_pucData) {
268
269 delete [] _pucData;
270 }
271 // Do allocate
272 _pucData = new uint8_t[uiSize];
273
274 // Record size
275 _uiDataSize = uiSize;
276
277 // Reset Index
278 _uiIndex = 0;
279}