blob: 852111709335ae5d9438f7acac2734685f96ab01 [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
Sebastien Gonzalved9526492014-02-20 22:28:03 +010038using std::string;
39
Patrick Benavoli68a91282011-08-31 11:23:23 +020040CMessage::CMessage(uint8_t ucMsgId) : _ucMsgId(ucMsgId), _pucData(NULL), _uiDataSize(0), _uiIndex(0)
41{
42}
43
Patrick Benavoli930075c2011-08-31 17:09:06 +020044CMessage::CMessage() : _ucMsgId((uint8_t)-1), _pucData(NULL), _uiDataSize(0), _uiIndex(0)
Patrick Benavoli68a91282011-08-31 11:23:23 +020045{
46}
47
48CMessage::~CMessage()
49{
50 delete [] _pucData;
51}
52
53// Msg Id
54uint8_t CMessage::getMsgId() const
55{
56 return _ucMsgId;
57}
58
59// Data
60void CMessage::writeData(const void* pvData, uint32_t uiSize)
61{
62 assert(_uiIndex + uiSize <= _uiDataSize);
63
64 // Copy
65 memcpy(&_pucData[_uiIndex], pvData, uiSize);
66
67 // Index
68 _uiIndex += uiSize;
69}
70
71void CMessage::readData(void* pvData, uint32_t uiSize)
72{
73 assert(_uiIndex + uiSize <= _uiDataSize);
74
75 // Copy
76 memcpy(pvData, &_pucData[_uiIndex], uiSize);
77
78 // Index
79 _uiIndex += uiSize;
80}
81
82void CMessage::writeString(const string& strData)
83{
84 // Size
85 uint32_t uiSize = strData.length();
86
87 writeData(&uiSize, sizeof(uiSize));
88
89 // Content
90 writeData(strData.c_str(), uiSize);
91}
92
93void CMessage::readString(string& strData)
94{
95 // Size
96 uint32_t uiSize;
97
98 readData(&uiSize, sizeof(uiSize));
99
100 // Data
Kevin Rocard0a7b18e2014-12-19 15:11:21 +0100101 char pcData[uiSize + 1];
Patrick Benavoli68a91282011-08-31 11:23:23 +0200102
103 // Content
104 readData(pcData, uiSize);
105
106 // NULL-terminate string
107 pcData[uiSize] = '\0';
108
109 // Output
110 strData = pcData;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200111}
112
113uint32_t CMessage::getStringSize(const string& strData) const
114{
115 // Return string length plus room to store its length
116 return strData.length() + sizeof(uint32_t);
117}
118
119// Remaining data size
120uint32_t CMessage::getRemainingDataSize() const
121{
122 return _uiDataSize - _uiIndex;
123}
124
125// Send/Receive
Kevin Rocarde874c252014-04-25 15:11:12 +0200126CMessage::Result CMessage::serialize(CSocket* pSocket, bool bOut, string& strError)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200127{
128 if (bOut) {
129
130 // Make room for data to send
131 allocateData(getDataSize());
132
133 // Get data from derived
134 fillDataToSend();
135
136 // Finished providing data?
137 assert(_uiIndex == _uiDataSize);
138
139 // First send sync word
140 uint16_t uiSyncWord = SYNC_WORD;
141
142 if (!pSocket->write(&uiSyncWord, sizeof(uiSyncWord))) {
143
Kevin Rocarde874c252014-04-25 15:11:12 +0200144 if (pSocket->hasPeerDisconnected()) {
145 return peerDisconnected;
146 }
147 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200148 }
149
150 // Size
151 uint32_t uiSize = sizeof(_ucMsgId) + _uiDataSize;
152
153 if (!pSocket->write(&uiSize, sizeof(uiSize))) {
154
Kevin Rocarde3a06ba2014-10-01 10:41:24 +0200155 strError += string("Size write failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200156 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200157 }
158
159 // Msg Id
160 if (!pSocket->write(&_ucMsgId, sizeof(_ucMsgId))) {
161
Kevin Rocarde3a06ba2014-10-01 10:41:24 +0200162 strError += string("Msg write failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200163 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200164 }
165
166 // Data
167 if (!pSocket->write(_pucData, _uiDataSize)) {
168
Kevin Rocarde3a06ba2014-10-01 10:41:24 +0200169 strError = string("Data write failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200170 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200171 }
172
173 // Checksum
174 uint8_t ucChecksum = computeChecksum();
175
176 if (!pSocket->write(&ucChecksum, sizeof(ucChecksum))) {
177
Kevin Rocarde3a06ba2014-10-01 10:41:24 +0200178 strError = string("Checksum write failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200179 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200180 }
181
182 } else {
183 // First read sync word
184 uint16_t uiSyncWord;
185
186 if (!pSocket->read(&uiSyncWord, sizeof(uiSyncWord))) {
187
Kevin Rocarde3a06ba2014-10-01 10:41:24 +0200188 strError = string("Sync read failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200189 if (pSocket->hasPeerDisconnected()) {
190 return peerDisconnected;
191 }
192 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200193 }
194
195 // Check Sync word
196 if (uiSyncWord != SYNC_WORD) {
197
Kevin Rocardef8d7272014-04-23 20:34:14 +0200198 strError = "Sync word incorrect";
Kevin Rocarde874c252014-04-25 15:11:12 +0200199 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200200 }
201
202 // Size
203 uint32_t uiSize;
204
205 if (!pSocket->read(&uiSize, sizeof(uiSize))) {
206
Kevin Rocarde3a06ba2014-10-01 10:41:24 +0200207 strError = string("Size read failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200208 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200209 }
210
211 // Msg Id
212 if (!pSocket->read(&_ucMsgId, sizeof(_ucMsgId))) {
213
Kevin Rocarde3a06ba2014-10-01 10:41:24 +0200214 strError = string("Msg id read failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200215 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200216 }
217
218 // Data
219
220 // Allocate
221 allocateData(uiSize - sizeof(_ucMsgId));
222
223 // Data receive
224 if (!pSocket->read(_pucData, _uiDataSize)) {
225
Kevin Rocarde3a06ba2014-10-01 10:41:24 +0200226 strError = string("Data read failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200227 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200228 }
229
230 // Checksum
231 uint8_t ucChecksum;
232
233 if (!pSocket->read(&ucChecksum, sizeof(ucChecksum))) {
234
Kevin Rocarde3a06ba2014-10-01 10:41:24 +0200235 strError = string("Checksum read failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200236 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200237 }
238 // Compare
239 if (ucChecksum != computeChecksum()) {
240
Kevin Rocardef8d7272014-04-23 20:34:14 +0200241 strError = "Received checksum != computed checksum";
Kevin Rocarde874c252014-04-25 15:11:12 +0200242 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200243 }
244
245 // Collect data in derived
246 collectReceivedData();
247 }
248
Kevin Rocarde874c252014-04-25 15:11:12 +0200249 return success;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200250}
251
252// Checksum
253uint8_t CMessage::computeChecksum() const
254{
Patrick Benavoli1387bda2011-08-31 11:23:24 +0200255 uint8_t uiChecksum = _ucMsgId;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200256
257 uint32_t uiIndex;
258
259 for (uiIndex = 0; uiIndex < _uiDataSize; uiIndex++) {
260
261 uiChecksum += _pucData[uiIndex];
262 }
263
264 return uiChecksum;
265}
266
267// Data allocation
268void CMessage::allocateData(uint32_t uiSize)
269{
270 // Remove previous one
271 if (_pucData) {
272
273 delete [] _pucData;
274 }
275 // Do allocate
276 _pucData = new uint8_t[uiSize];
277
278 // Record size
279 _uiDataSize = uiSize;
280
281 // Reset Index
282 _uiIndex = 0;
283}