1*c33452fbSAndroid Build Coastguard Worker /*
2*c33452fbSAndroid Build Coastguard Worker * Copyright (c) 2011-2015, Intel Corporation
3*c33452fbSAndroid Build Coastguard Worker * All rights reserved.
4*c33452fbSAndroid Build Coastguard Worker *
5*c33452fbSAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without modification,
6*c33452fbSAndroid Build Coastguard Worker * are permitted provided that the following conditions are met:
7*c33452fbSAndroid Build Coastguard Worker *
8*c33452fbSAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright notice, this
9*c33452fbSAndroid Build Coastguard Worker * list of conditions and the following disclaimer.
10*c33452fbSAndroid Build Coastguard Worker *
11*c33452fbSAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright notice,
12*c33452fbSAndroid Build Coastguard Worker * this list of conditions and the following disclaimer in the documentation and/or
13*c33452fbSAndroid Build Coastguard Worker * other materials provided with the distribution.
14*c33452fbSAndroid Build Coastguard Worker *
15*c33452fbSAndroid Build Coastguard Worker * 3. Neither the name of the copyright holder nor the names of its contributors
16*c33452fbSAndroid Build Coastguard Worker * may be used to endorse or promote products derived from this software without
17*c33452fbSAndroid Build Coastguard Worker * specific prior written permission.
18*c33452fbSAndroid Build Coastguard Worker *
19*c33452fbSAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20*c33452fbSAndroid Build Coastguard Worker * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21*c33452fbSAndroid Build Coastguard Worker * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22*c33452fbSAndroid Build Coastguard Worker * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23*c33452fbSAndroid Build Coastguard Worker * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24*c33452fbSAndroid Build Coastguard Worker * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25*c33452fbSAndroid Build Coastguard Worker * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26*c33452fbSAndroid Build Coastguard Worker * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27*c33452fbSAndroid Build Coastguard Worker * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28*c33452fbSAndroid Build Coastguard Worker * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29*c33452fbSAndroid Build Coastguard Worker */
30*c33452fbSAndroid Build Coastguard Worker #include "Message.h"
31*c33452fbSAndroid Build Coastguard Worker #include "Socket.h"
32*c33452fbSAndroid Build Coastguard Worker #include "Iterator.hpp"
33*c33452fbSAndroid Build Coastguard Worker #include <asio.hpp>
34*c33452fbSAndroid Build Coastguard Worker #include <vector>
35*c33452fbSAndroid Build Coastguard Worker #include <numeric>
36*c33452fbSAndroid Build Coastguard Worker #include <cassert>
37*c33452fbSAndroid Build Coastguard Worker
38*c33452fbSAndroid Build Coastguard Worker using std::string;
39*c33452fbSAndroid Build Coastguard Worker
CMessage(MsgType ucMsgId)40*c33452fbSAndroid Build Coastguard Worker CMessage::CMessage(MsgType ucMsgId) : _ucMsgId(ucMsgId), _uiIndex(0)
41*c33452fbSAndroid Build Coastguard Worker {
42*c33452fbSAndroid Build Coastguard Worker }
43*c33452fbSAndroid Build Coastguard Worker
CMessage()44*c33452fbSAndroid Build Coastguard Worker CMessage::CMessage() : _ucMsgId(MsgType::EInvalid), _uiIndex(0)
45*c33452fbSAndroid Build Coastguard Worker {
46*c33452fbSAndroid Build Coastguard Worker }
47*c33452fbSAndroid Build Coastguard Worker
48*c33452fbSAndroid Build Coastguard Worker // Msg Id
getMsgId() const49*c33452fbSAndroid Build Coastguard Worker CMessage::MsgType CMessage::getMsgId() const
50*c33452fbSAndroid Build Coastguard Worker {
51*c33452fbSAndroid Build Coastguard Worker return _ucMsgId;
52*c33452fbSAndroid Build Coastguard Worker }
53*c33452fbSAndroid Build Coastguard Worker
isValidAccess(size_t offset,size_t size) const54*c33452fbSAndroid Build Coastguard Worker bool CMessage::isValidAccess(size_t offset, size_t size) const
55*c33452fbSAndroid Build Coastguard Worker {
56*c33452fbSAndroid Build Coastguard Worker return offset + size <= getMessageDataSize();
57*c33452fbSAndroid Build Coastguard Worker }
58*c33452fbSAndroid Build Coastguard Worker
59*c33452fbSAndroid Build Coastguard Worker // Data
writeData(const void * pvData,size_t size)60*c33452fbSAndroid Build Coastguard Worker void CMessage::writeData(const void *pvData, size_t size)
61*c33452fbSAndroid Build Coastguard Worker {
62*c33452fbSAndroid Build Coastguard Worker assert(isValidAccess(_uiIndex, size));
63*c33452fbSAndroid Build Coastguard Worker
64*c33452fbSAndroid Build Coastguard Worker auto first = MAKE_ARRAY_ITERATOR(static_cast<const uint8_t *>(pvData), size);
65*c33452fbSAndroid Build Coastguard Worker auto last = first + size;
66*c33452fbSAndroid Build Coastguard Worker auto destFirst = begin(mData) + _uiIndex;
67*c33452fbSAndroid Build Coastguard Worker
68*c33452fbSAndroid Build Coastguard Worker std::copy(first, last, destFirst);
69*c33452fbSAndroid Build Coastguard Worker
70*c33452fbSAndroid Build Coastguard Worker _uiIndex += size;
71*c33452fbSAndroid Build Coastguard Worker }
72*c33452fbSAndroid Build Coastguard Worker
readData(void * pvData,size_t size)73*c33452fbSAndroid Build Coastguard Worker void CMessage::readData(void *pvData, size_t size)
74*c33452fbSAndroid Build Coastguard Worker {
75*c33452fbSAndroid Build Coastguard Worker assert(isValidAccess(_uiIndex, size));
76*c33452fbSAndroid Build Coastguard Worker
77*c33452fbSAndroid Build Coastguard Worker auto first = begin(mData) + _uiIndex;
78*c33452fbSAndroid Build Coastguard Worker auto last = first + size;
79*c33452fbSAndroid Build Coastguard Worker auto destFirst = MAKE_ARRAY_ITERATOR(static_cast<uint8_t *>(pvData), size);
80*c33452fbSAndroid Build Coastguard Worker
81*c33452fbSAndroid Build Coastguard Worker std::copy(first, last, destFirst);
82*c33452fbSAndroid Build Coastguard Worker
83*c33452fbSAndroid Build Coastguard Worker _uiIndex += size;
84*c33452fbSAndroid Build Coastguard Worker }
85*c33452fbSAndroid Build Coastguard Worker
writeString(const string & strData)86*c33452fbSAndroid Build Coastguard Worker void CMessage::writeString(const string &strData)
87*c33452fbSAndroid Build Coastguard Worker {
88*c33452fbSAndroid Build Coastguard Worker // Size
89*c33452fbSAndroid Build Coastguard Worker uint32_t size = static_cast<uint32_t>(strData.length());
90*c33452fbSAndroid Build Coastguard Worker
91*c33452fbSAndroid Build Coastguard Worker writeData(&size, sizeof(size));
92*c33452fbSAndroid Build Coastguard Worker
93*c33452fbSAndroid Build Coastguard Worker // Content
94*c33452fbSAndroid Build Coastguard Worker writeData(strData.c_str(), size);
95*c33452fbSAndroid Build Coastguard Worker }
96*c33452fbSAndroid Build Coastguard Worker
readString(string & strData)97*c33452fbSAndroid Build Coastguard Worker void CMessage::readString(string &strData)
98*c33452fbSAndroid Build Coastguard Worker {
99*c33452fbSAndroid Build Coastguard Worker // Size
100*c33452fbSAndroid Build Coastguard Worker uint32_t uiSize;
101*c33452fbSAndroid Build Coastguard Worker
102*c33452fbSAndroid Build Coastguard Worker readData(&uiSize, sizeof(uiSize));
103*c33452fbSAndroid Build Coastguard Worker
104*c33452fbSAndroid Build Coastguard Worker // Data
105*c33452fbSAndroid Build Coastguard Worker std::vector<char> string(uiSize + 1);
106*c33452fbSAndroid Build Coastguard Worker
107*c33452fbSAndroid Build Coastguard Worker // Content
108*c33452fbSAndroid Build Coastguard Worker readData(string.data(), uiSize);
109*c33452fbSAndroid Build Coastguard Worker
110*c33452fbSAndroid Build Coastguard Worker // NULL-terminate string
111*c33452fbSAndroid Build Coastguard Worker string.back() = '\0';
112*c33452fbSAndroid Build Coastguard Worker
113*c33452fbSAndroid Build Coastguard Worker // Output
114*c33452fbSAndroid Build Coastguard Worker strData = string.data();
115*c33452fbSAndroid Build Coastguard Worker }
116*c33452fbSAndroid Build Coastguard Worker
getStringSize(const string & strData) const117*c33452fbSAndroid Build Coastguard Worker size_t CMessage::getStringSize(const string &strData) const
118*c33452fbSAndroid Build Coastguard Worker {
119*c33452fbSAndroid Build Coastguard Worker // Return string length plus room to store its length
120*c33452fbSAndroid Build Coastguard Worker return strData.length() + sizeof(uint32_t);
121*c33452fbSAndroid Build Coastguard Worker }
122*c33452fbSAndroid Build Coastguard Worker
123*c33452fbSAndroid Build Coastguard Worker // Remaining data size
getRemainingDataSize() const124*c33452fbSAndroid Build Coastguard Worker size_t CMessage::getRemainingDataSize() const
125*c33452fbSAndroid Build Coastguard Worker {
126*c33452fbSAndroid Build Coastguard Worker return getMessageDataSize() - _uiIndex;
127*c33452fbSAndroid Build Coastguard Worker }
128*c33452fbSAndroid Build Coastguard Worker
129*c33452fbSAndroid Build Coastguard Worker // Send/Receive
serialize(Socket && socket,bool bOut,string & strError)130*c33452fbSAndroid Build Coastguard Worker CMessage::Result CMessage::serialize(Socket &&socket, bool bOut, string &strError)
131*c33452fbSAndroid Build Coastguard Worker {
132*c33452fbSAndroid Build Coastguard Worker auto &asioSocket = socket.get();
133*c33452fbSAndroid Build Coastguard Worker
134*c33452fbSAndroid Build Coastguard Worker if (bOut) {
135*c33452fbSAndroid Build Coastguard Worker asio::error_code ec;
136*c33452fbSAndroid Build Coastguard Worker
137*c33452fbSAndroid Build Coastguard Worker // Make room for data to send
138*c33452fbSAndroid Build Coastguard Worker allocateData(getDataSize());
139*c33452fbSAndroid Build Coastguard Worker
140*c33452fbSAndroid Build Coastguard Worker // Get data from derived
141*c33452fbSAndroid Build Coastguard Worker fillDataToSend();
142*c33452fbSAndroid Build Coastguard Worker
143*c33452fbSAndroid Build Coastguard Worker // Finished providing data?
144*c33452fbSAndroid Build Coastguard Worker assert(_uiIndex == getMessageDataSize());
145*c33452fbSAndroid Build Coastguard Worker
146*c33452fbSAndroid Build Coastguard Worker // First send sync word
147*c33452fbSAndroid Build Coastguard Worker uint16_t uiSyncWord = SYNC_WORD;
148*c33452fbSAndroid Build Coastguard Worker
149*c33452fbSAndroid Build Coastguard Worker if (!asio::write(asioSocket, asio::buffer(&uiSyncWord, sizeof(uiSyncWord)), ec)) {
150*c33452fbSAndroid Build Coastguard Worker
151*c33452fbSAndroid Build Coastguard Worker if (ec == asio::error::eof) {
152*c33452fbSAndroid Build Coastguard Worker return peerDisconnected;
153*c33452fbSAndroid Build Coastguard Worker }
154*c33452fbSAndroid Build Coastguard Worker return error;
155*c33452fbSAndroid Build Coastguard Worker }
156*c33452fbSAndroid Build Coastguard Worker
157*c33452fbSAndroid Build Coastguard Worker // Size
158*c33452fbSAndroid Build Coastguard Worker uint32_t uiSize = (uint32_t)(sizeof(_ucMsgId) + getMessageDataSize());
159*c33452fbSAndroid Build Coastguard Worker
160*c33452fbSAndroid Build Coastguard Worker if (!asio::write(asioSocket, asio::buffer(&uiSize, sizeof(uiSize)), ec)) {
161*c33452fbSAndroid Build Coastguard Worker
162*c33452fbSAndroid Build Coastguard Worker strError += string("Size write failed: ") + ec.message();
163*c33452fbSAndroid Build Coastguard Worker return error;
164*c33452fbSAndroid Build Coastguard Worker }
165*c33452fbSAndroid Build Coastguard Worker
166*c33452fbSAndroid Build Coastguard Worker // Msg Id
167*c33452fbSAndroid Build Coastguard Worker if (!asio::write(asioSocket, asio::buffer(&_ucMsgId, sizeof(_ucMsgId)), ec)) {
168*c33452fbSAndroid Build Coastguard Worker
169*c33452fbSAndroid Build Coastguard Worker strError += string("Msg write failed: ") + ec.message();
170*c33452fbSAndroid Build Coastguard Worker return error;
171*c33452fbSAndroid Build Coastguard Worker }
172*c33452fbSAndroid Build Coastguard Worker
173*c33452fbSAndroid Build Coastguard Worker // Data
174*c33452fbSAndroid Build Coastguard Worker if (!asio::write(asioSocket, asio::buffer(mData), ec)) {
175*c33452fbSAndroid Build Coastguard Worker
176*c33452fbSAndroid Build Coastguard Worker strError = string("Data write failed: ") + ec.message();
177*c33452fbSAndroid Build Coastguard Worker return error;
178*c33452fbSAndroid Build Coastguard Worker }
179*c33452fbSAndroid Build Coastguard Worker
180*c33452fbSAndroid Build Coastguard Worker // Checksum
181*c33452fbSAndroid Build Coastguard Worker uint8_t ucChecksum = computeChecksum();
182*c33452fbSAndroid Build Coastguard Worker
183*c33452fbSAndroid Build Coastguard Worker if (!asio::write(asioSocket, asio::buffer(&ucChecksum, sizeof(ucChecksum)), ec)) {
184*c33452fbSAndroid Build Coastguard Worker
185*c33452fbSAndroid Build Coastguard Worker strError = string("Checksum write failed: ") + ec.message();
186*c33452fbSAndroid Build Coastguard Worker return error;
187*c33452fbSAndroid Build Coastguard Worker }
188*c33452fbSAndroid Build Coastguard Worker
189*c33452fbSAndroid Build Coastguard Worker } else {
190*c33452fbSAndroid Build Coastguard Worker // First read sync word
191*c33452fbSAndroid Build Coastguard Worker uint16_t uiSyncWord = 0;
192*c33452fbSAndroid Build Coastguard Worker asio::error_code ec;
193*c33452fbSAndroid Build Coastguard Worker
194*c33452fbSAndroid Build Coastguard Worker if (!asio::read(asioSocket, asio::buffer(&uiSyncWord, sizeof(uiSyncWord)), ec)) {
195*c33452fbSAndroid Build Coastguard Worker strError = string("Sync read failed: ") + ec.message();
196*c33452fbSAndroid Build Coastguard Worker if (ec == asio::error::eof) {
197*c33452fbSAndroid Build Coastguard Worker return peerDisconnected;
198*c33452fbSAndroid Build Coastguard Worker }
199*c33452fbSAndroid Build Coastguard Worker return error;
200*c33452fbSAndroid Build Coastguard Worker }
201*c33452fbSAndroid Build Coastguard Worker
202*c33452fbSAndroid Build Coastguard Worker // Check Sync word
203*c33452fbSAndroid Build Coastguard Worker if (uiSyncWord != SYNC_WORD) {
204*c33452fbSAndroid Build Coastguard Worker
205*c33452fbSAndroid Build Coastguard Worker strError = "Sync word incorrect";
206*c33452fbSAndroid Build Coastguard Worker return error;
207*c33452fbSAndroid Build Coastguard Worker }
208*c33452fbSAndroid Build Coastguard Worker
209*c33452fbSAndroid Build Coastguard Worker // Size
210*c33452fbSAndroid Build Coastguard Worker uint32_t uiSize = 0;
211*c33452fbSAndroid Build Coastguard Worker
212*c33452fbSAndroid Build Coastguard Worker if (!asio::read(asioSocket, asio::buffer(&uiSize, sizeof(uiSize)), ec)) {
213*c33452fbSAndroid Build Coastguard Worker strError = string("Size read failed: ") + ec.message();
214*c33452fbSAndroid Build Coastguard Worker return error;
215*c33452fbSAndroid Build Coastguard Worker }
216*c33452fbSAndroid Build Coastguard Worker
217*c33452fbSAndroid Build Coastguard Worker // Msg Id
218*c33452fbSAndroid Build Coastguard Worker if (!asio::read(asioSocket, asio::buffer(&_ucMsgId, sizeof(_ucMsgId)), ec)) {
219*c33452fbSAndroid Build Coastguard Worker strError = string("Msg id read failed: ") + ec.message();
220*c33452fbSAndroid Build Coastguard Worker return error;
221*c33452fbSAndroid Build Coastguard Worker }
222*c33452fbSAndroid Build Coastguard Worker
223*c33452fbSAndroid Build Coastguard Worker // Data
224*c33452fbSAndroid Build Coastguard Worker
225*c33452fbSAndroid Build Coastguard Worker // Allocate
226*c33452fbSAndroid Build Coastguard Worker allocateData(uiSize - sizeof(_ucMsgId));
227*c33452fbSAndroid Build Coastguard Worker
228*c33452fbSAndroid Build Coastguard Worker // Data receive
229*c33452fbSAndroid Build Coastguard Worker if (!asio::read(asioSocket, asio::buffer(mData), ec)) {
230*c33452fbSAndroid Build Coastguard Worker strError = string("Data read failed: ") + ec.message();
231*c33452fbSAndroid Build Coastguard Worker return error;
232*c33452fbSAndroid Build Coastguard Worker }
233*c33452fbSAndroid Build Coastguard Worker
234*c33452fbSAndroid Build Coastguard Worker // Checksum
235*c33452fbSAndroid Build Coastguard Worker uint8_t ucChecksum = 0;
236*c33452fbSAndroid Build Coastguard Worker
237*c33452fbSAndroid Build Coastguard Worker if (!asio::read(asioSocket, asio::buffer(&ucChecksum, sizeof(ucChecksum)), ec)) {
238*c33452fbSAndroid Build Coastguard Worker strError = string("Checksum read failed: ") + ec.message();
239*c33452fbSAndroid Build Coastguard Worker return error;
240*c33452fbSAndroid Build Coastguard Worker }
241*c33452fbSAndroid Build Coastguard Worker // Compare
242*c33452fbSAndroid Build Coastguard Worker if (ucChecksum != computeChecksum()) {
243*c33452fbSAndroid Build Coastguard Worker
244*c33452fbSAndroid Build Coastguard Worker strError = "Received checksum != computed checksum";
245*c33452fbSAndroid Build Coastguard Worker return error;
246*c33452fbSAndroid Build Coastguard Worker }
247*c33452fbSAndroid Build Coastguard Worker
248*c33452fbSAndroid Build Coastguard Worker // Collect data in derived
249*c33452fbSAndroid Build Coastguard Worker collectReceivedData();
250*c33452fbSAndroid Build Coastguard Worker }
251*c33452fbSAndroid Build Coastguard Worker
252*c33452fbSAndroid Build Coastguard Worker return success;
253*c33452fbSAndroid Build Coastguard Worker }
254*c33452fbSAndroid Build Coastguard Worker
255*c33452fbSAndroid Build Coastguard Worker // Checksum
computeChecksum() const256*c33452fbSAndroid Build Coastguard Worker uint8_t CMessage::computeChecksum() const
257*c33452fbSAndroid Build Coastguard Worker {
258*c33452fbSAndroid Build Coastguard Worker return accumulate(begin(mData), end(mData), static_cast<uint8_t>(_ucMsgId));
259*c33452fbSAndroid Build Coastguard Worker }
260*c33452fbSAndroid Build Coastguard Worker
261*c33452fbSAndroid Build Coastguard Worker // Allocation of room to store the message
allocateData(size_t size)262*c33452fbSAndroid Build Coastguard Worker void CMessage::allocateData(size_t size)
263*c33452fbSAndroid Build Coastguard Worker {
264*c33452fbSAndroid Build Coastguard Worker // Remove previous one
265*c33452fbSAndroid Build Coastguard Worker mData.clear();
266*c33452fbSAndroid Build Coastguard Worker
267*c33452fbSAndroid Build Coastguard Worker // Do allocate
268*c33452fbSAndroid Build Coastguard Worker mData.resize(size);
269*c33452fbSAndroid Build Coastguard Worker
270*c33452fbSAndroid Build Coastguard Worker // Reset Index
271*c33452fbSAndroid Build Coastguard Worker _uiIndex = 0;
272*c33452fbSAndroid Build Coastguard Worker }
273