blob: 9df038c71cfa632be31c8c9be5fa4b4d5d4dc37b [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
101 char* pcData = new char[uiSize + 1];
102
103 // Content
104 readData(pcData, uiSize);
105
106 // NULL-terminate string
107 pcData[uiSize] = '\0';
108
109 // Output
110 strData = pcData;
111
112 // Delete
113 delete [] pcData;
114}
115
116uint32_t CMessage::getStringSize(const string& strData) const
117{
118 // Return string length plus room to store its length
119 return strData.length() + sizeof(uint32_t);
120}
121
122// Remaining data size
123uint32_t CMessage::getRemainingDataSize() const
124{
125 return _uiDataSize - _uiIndex;
126}
127
128// Send/Receive
Kevin Rocarde874c252014-04-25 15:11:12 +0200129CMessage::Result CMessage::serialize(CSocket* pSocket, bool bOut, string& strError)
Patrick Benavoli68a91282011-08-31 11:23:23 +0200130{
131 if (bOut) {
132
133 // Make room for data to send
134 allocateData(getDataSize());
135
136 // Get data from derived
137 fillDataToSend();
138
139 // Finished providing data?
140 assert(_uiIndex == _uiDataSize);
141
142 // First send sync word
143 uint16_t uiSyncWord = SYNC_WORD;
144
145 if (!pSocket->write(&uiSyncWord, sizeof(uiSyncWord))) {
146
Kevin Rocarde874c252014-04-25 15:11:12 +0200147 if (pSocket->hasPeerDisconnected()) {
148 return peerDisconnected;
149 }
150 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200151 }
152
153 // Size
154 uint32_t uiSize = sizeof(_ucMsgId) + _uiDataSize;
155
156 if (!pSocket->write(&uiSize, sizeof(uiSize))) {
157
Kevin Rocardef8d7272014-04-23 20:34:14 +0200158 strError += string("Size write failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200159 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200160 }
161
162 // Msg Id
163 if (!pSocket->write(&_ucMsgId, sizeof(_ucMsgId))) {
164
Kevin Rocardef8d7272014-04-23 20:34:14 +0200165 strError += string("Msg write failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200166 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200167 }
168
169 // Data
170 if (!pSocket->write(_pucData, _uiDataSize)) {
171
Kevin Rocardef8d7272014-04-23 20:34:14 +0200172 strError = string("Data write failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200173 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200174 }
175
176 // Checksum
177 uint8_t ucChecksum = computeChecksum();
178
179 if (!pSocket->write(&ucChecksum, sizeof(ucChecksum))) {
180
Kevin Rocardef8d7272014-04-23 20:34:14 +0200181 strError = string("Checksum write failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200182 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200183 }
184
185 } else {
186 // First read sync word
187 uint16_t uiSyncWord;
188
189 if (!pSocket->read(&uiSyncWord, sizeof(uiSyncWord))) {
190
Kevin Rocardef8d7272014-04-23 20:34:14 +0200191 strError = string("Sync read failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200192 if (pSocket->hasPeerDisconnected()) {
193 return peerDisconnected;
194 }
195 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200196 }
197
198 // Check Sync word
199 if (uiSyncWord != SYNC_WORD) {
200
Kevin Rocardef8d7272014-04-23 20:34:14 +0200201 strError = "Sync word incorrect";
Kevin Rocarde874c252014-04-25 15:11:12 +0200202 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200203 }
204
205 // Size
206 uint32_t uiSize;
207
208 if (!pSocket->read(&uiSize, sizeof(uiSize))) {
209
Kevin Rocardef8d7272014-04-23 20:34:14 +0200210 strError = string("Size read failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200211 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200212 }
213
214 // Msg Id
215 if (!pSocket->read(&_ucMsgId, sizeof(_ucMsgId))) {
216
Kevin Rocardef8d7272014-04-23 20:34:14 +0200217 strError = string("Msg id read failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200218 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200219 }
220
221 // Data
222
223 // Allocate
224 allocateData(uiSize - sizeof(_ucMsgId));
225
226 // Data receive
227 if (!pSocket->read(_pucData, _uiDataSize)) {
228
Kevin Rocardef8d7272014-04-23 20:34:14 +0200229 strError = string("Data read failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200230 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200231 }
232
233 // Checksum
234 uint8_t ucChecksum;
235
236 if (!pSocket->read(&ucChecksum, sizeof(ucChecksum))) {
237
Kevin Rocardef8d7272014-04-23 20:34:14 +0200238 strError = string("Checksum read failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200239 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200240 }
241 // Compare
242 if (ucChecksum != computeChecksum()) {
243
Kevin Rocardef8d7272014-04-23 20:34:14 +0200244 strError = "Received checksum != computed checksum";
Kevin Rocarde874c252014-04-25 15:11:12 +0200245 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200246 }
247
248 // Collect data in derived
249 collectReceivedData();
250 }
251
Kevin Rocarde874c252014-04-25 15:11:12 +0200252 return success;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200253}
254
255// Checksum
256uint8_t CMessage::computeChecksum() const
257{
Patrick Benavoli1387bda2011-08-31 11:23:24 +0200258 uint8_t uiChecksum = _ucMsgId;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200259
260 uint32_t uiIndex;
261
262 for (uiIndex = 0; uiIndex < _uiDataSize; uiIndex++) {
263
264 uiChecksum += _pucData[uiIndex];
265 }
266
267 return uiChecksum;
268}
269
270// Data allocation
271void CMessage::allocateData(uint32_t uiSize)
272{
273 // Remove previous one
274 if (_pucData) {
275
276 delete [] _pucData;
277 }
278 // Do allocate
279 _pucData = new uint8_t[uiSize];
280
281 // Record size
282 _uiDataSize = uiSize;
283
284 // Reset Index
285 _uiIndex = 0;
286}