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 38using std::string; 39 40CMessage::CMessage(uint8_t ucMsgId) : _ucMsgId(ucMsgId), _pucData(NULL), _uiDataSize(0), _uiIndex(0) 41{ 42} 43 44CMessage::CMessage() : _ucMsgId((uint8_t)-1), _pucData(NULL), _uiDataSize(0), _uiIndex(0) 45{ 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, 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 71void 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 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[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 113size_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 120size_t CMessage::getRemainingDataSize() const 121{ 122 return _uiDataSize - _uiIndex; 123} 124 125// Send/Receive 126CMessage::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 253uint8_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 268void 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