1 /*
2 * 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.
29 */
30 #include "Message.h"
31 #include <assert.h>
32 #include "Socket.h"
33 #include "RemoteProcessorProtocol.h"
34 #include <string.h>
35 #include <assert.h>
36 #include <errno.h>
37
38 using std::string;
39
CMessage(uint8_t ucMsgId)40 CMessage::CMessage(uint8_t ucMsgId) : _ucMsgId(ucMsgId), _pucData(NULL), _uiDataSize(0), _uiIndex(0)
41 {
42 }
43
CMessage()44 CMessage::CMessage() : _ucMsgId((uint8_t)-1), _pucData(NULL), _uiDataSize(0), _uiIndex(0)
45 {
46 }
47
~CMessage()48 CMessage::~CMessage()
49 {
50 delete [] _pucData;
51 }
52
53 // Msg Id
getMsgId() const54 uint8_t CMessage::getMsgId() const
55 {
56 return _ucMsgId;
57 }
58
59 // Data
writeData(const void * pvData,size_t uiSize)60 void CMessage::writeData(const void* pvData, size_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
readData(void * pvData,size_t uiSize)71 void CMessage::readData(void* pvData, size_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
writeString(const string & strData)82 void 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
readString(string & strData)93 void CMessage::readString(string& strData)
94 {
95 // Size
96 uint32_t uiSize;
97
98 readData(&uiSize, sizeof(uiSize));
99
100 // Data
101 char pcData[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
getStringSize(const string & strData) const113 size_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
getRemainingDataSize() const120 size_t CMessage::getRemainingDataSize() const
121 {
122 return _uiDataSize - _uiIndex;
123 }
124
125 // Send/Receive
serialize(CSocket * pSocket,bool bOut,string & strError)126 CMessage::Result CMessage::serialize(CSocket* pSocket, bool bOut, string& strError)
127 {
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
144 if (pSocket->hasPeerDisconnected()) {
145 return peerDisconnected;
146 }
147 return error;
148 }
149
150 // Size
151 uint32_t uiSize = (uint32_t)(sizeof(_ucMsgId) + _uiDataSize);
152
153 if (!pSocket->write(&uiSize, sizeof(uiSize))) {
154
155 strError += string("Size write failed: ") + strerror(errno);
156 return error;
157 }
158
159 // Msg Id
160 if (!pSocket->write(&_ucMsgId, sizeof(_ucMsgId))) {
161
162 strError += string("Msg write failed: ") + strerror(errno);
163 return error;
164 }
165
166 // Data
167 if (!pSocket->write(_pucData, _uiDataSize)) {
168
169 strError = string("Data write failed: ") + strerror(errno);
170 return error;
171 }
172
173 // Checksum
174 uint8_t ucChecksum = computeChecksum();
175
176 if (!pSocket->write(&ucChecksum, sizeof(ucChecksum))) {
177
178 strError = string("Checksum write failed: ") + strerror(errno);
179 return error;
180 }
181
182 } else {
183 // First read sync word
184 uint16_t uiSyncWord;
185
186 if (!pSocket->read(&uiSyncWord, sizeof(uiSyncWord))) {
187
188 strError = string("Sync read failed: ") + strerror(errno);
189 if (pSocket->hasPeerDisconnected()) {
190 return peerDisconnected;
191 }
192 return error;
193 }
194
195 // Check Sync word
196 if (uiSyncWord != SYNC_WORD) {
197
198 strError = "Sync word incorrect";
199 return error;
200 }
201
202 // Size
203 uint32_t uiSize;
204
205 if (!pSocket->read(&uiSize, sizeof(uiSize))) {
206
207 strError = string("Size read failed: ") + strerror(errno);
208 return error;
209 }
210
211 // Msg Id
212 if (!pSocket->read(&_ucMsgId, sizeof(_ucMsgId))) {
213
214 strError = string("Msg id read failed: ") + strerror(errno);
215 return error;
216 }
217
218 // Data
219
220 // Allocate
221 allocateData(uiSize - sizeof(_ucMsgId));
222
223 // Data receive
224 if (!pSocket->read(_pucData, _uiDataSize)) {
225
226 strError = string("Data read failed: ") + strerror(errno);
227 return error;
228 }
229
230 // Checksum
231 uint8_t ucChecksum;
232
233 if (!pSocket->read(&ucChecksum, sizeof(ucChecksum))) {
234
235 strError = string("Checksum read failed: ") + strerror(errno);
236 return error;
237 }
238 // Compare
239 if (ucChecksum != computeChecksum()) {
240
241 strError = "Received checksum != computed checksum";
242 return error;
243 }
244
245 // Collect data in derived
246 collectReceivedData();
247 }
248
249 return success;
250 }
251
252 // Checksum
computeChecksum() const253 uint8_t CMessage::computeChecksum() const
254 {
255 uint8_t uiChecksum = _ucMsgId;
256
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 // Allocation of room to store the message
allocateData(size_t uiSize)268 void CMessage::allocateData(size_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 }
284