blob: 8591847343c50c5897be874bdb9d9e6d231da277 [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 Rocarde874c252014-04-25 15:11:12 +0200127CMessage::Result 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 Rocarde874c252014-04-25 15:11:12 +0200145 if (pSocket->hasPeerDisconnected()) {
146 return peerDisconnected;
147 }
148 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200149 }
150
151 // Size
152 uint32_t uiSize = sizeof(_ucMsgId) + _uiDataSize;
153
154 if (!pSocket->write(&uiSize, sizeof(uiSize))) {
155
Kevin Rocardef8d7272014-04-23 20:34:14 +0200156 strError += string("Size write failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200157 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200158 }
159
160 // Msg Id
161 if (!pSocket->write(&_ucMsgId, sizeof(_ucMsgId))) {
162
Kevin Rocardef8d7272014-04-23 20:34:14 +0200163 strError += string("Msg write failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200164 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200165 }
166
167 // Data
168 if (!pSocket->write(_pucData, _uiDataSize)) {
169
Kevin Rocardef8d7272014-04-23 20:34:14 +0200170 strError = string("Data write failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200171 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200172 }
173
174 // Checksum
175 uint8_t ucChecksum = computeChecksum();
176
177 if (!pSocket->write(&ucChecksum, sizeof(ucChecksum))) {
178
Kevin Rocardef8d7272014-04-23 20:34:14 +0200179 strError = string("Checksum write failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200180 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200181 }
182
183 } else {
184 // First read sync word
185 uint16_t uiSyncWord;
186
187 if (!pSocket->read(&uiSyncWord, sizeof(uiSyncWord))) {
188
Kevin Rocardef8d7272014-04-23 20:34:14 +0200189 strError = string("Sync read failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200190 if (pSocket->hasPeerDisconnected()) {
191 return peerDisconnected;
192 }
193 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200194 }
195
196 // Check Sync word
197 if (uiSyncWord != SYNC_WORD) {
198
Kevin Rocardef8d7272014-04-23 20:34:14 +0200199 strError = "Sync word incorrect";
Kevin Rocarde874c252014-04-25 15:11:12 +0200200 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200201 }
202
203 // Size
204 uint32_t uiSize;
205
206 if (!pSocket->read(&uiSize, sizeof(uiSize))) {
207
Kevin Rocardef8d7272014-04-23 20:34:14 +0200208 strError = string("Size read failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200209 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200210 }
211
212 // Msg Id
213 if (!pSocket->read(&_ucMsgId, sizeof(_ucMsgId))) {
214
Kevin Rocardef8d7272014-04-23 20:34:14 +0200215 strError = string("Msg id read failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200216 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200217 }
218
219 // Data
220
221 // Allocate
222 allocateData(uiSize - sizeof(_ucMsgId));
223
224 // Data receive
225 if (!pSocket->read(_pucData, _uiDataSize)) {
226
Kevin Rocardef8d7272014-04-23 20:34:14 +0200227 strError = string("Data read failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200228 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200229 }
230
231 // Checksum
232 uint8_t ucChecksum;
233
234 if (!pSocket->read(&ucChecksum, sizeof(ucChecksum))) {
235
Kevin Rocardef8d7272014-04-23 20:34:14 +0200236 strError = string("Checksum read failed: ") + strerror(errno);
Kevin Rocarde874c252014-04-25 15:11:12 +0200237 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200238 }
239 // Compare
240 if (ucChecksum != computeChecksum()) {
241
Kevin Rocardef8d7272014-04-23 20:34:14 +0200242 strError = "Received checksum != computed checksum";
Kevin Rocarde874c252014-04-25 15:11:12 +0200243 return error;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200244 }
245
246 // Collect data in derived
247 collectReceivedData();
248 }
249
Kevin Rocarde874c252014-04-25 15:11:12 +0200250 return success;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200251}
252
253// Checksum
254uint8_t CMessage::computeChecksum() const
255{
Patrick Benavoli1387bda2011-08-31 11:23:24 +0200256 uint8_t uiChecksum = _ucMsgId;
Patrick Benavoli68a91282011-08-31 11:23:23 +0200257
258 uint32_t uiIndex;
259
260 for (uiIndex = 0; uiIndex < _uiDataSize; uiIndex++) {
261
262 uiChecksum += _pucData[uiIndex];
263 }
264
265 return uiChecksum;
266}
267
268// Data allocation
269void CMessage::allocateData(uint32_t uiSize)
270{
271 // Remove previous one
272 if (_pucData) {
273
274 delete [] _pucData;
275 }
276 // Do allocate
277 _pucData = new uint8_t[uiSize];
278
279 // Record size
280 _uiDataSize = uiSize;
281
282 // Reset Index
283 _uiIndex = 0;
284}