/base/packet.cpp

https://github.com/buzzer/Taser-Player-Driver · C++ · 359 lines · 231 code · 77 blank · 51 comment · 24 complexity · f78432332f4f8b05018afa89a4aada43 MD5 · raw file

  1. #include "packet.h"
  2. // This constructor is used to create a new packet TO BE SENT
  3. Packet::Packet(unsigned int command)
  4. {
  5. Q_ASSERT(sizeof(int) == 4);
  6. Q_ASSERT(sizeof(unsigned int) == 4);
  7. Q_ASSERT(sizeof(float) == 4);
  8. logger = Logger::instance();
  9. // allocate some memory for our buffer
  10. _bufferSize = 2048;
  11. _buffer = new unsigned char[_bufferSize];
  12. // initialze our pointers. Leave out CRC, as we have to put the
  13. // checksum AFTER the data, and we don't know how long our data is.
  14. _packetMagic = (unsigned int*) (_buffer + 0);
  15. _packetSize = (unsigned int*) (_buffer + 4);
  16. _packetCommand = (unsigned int*) (_buffer + 8);
  17. _packetData = (unsigned int*) (_buffer + 12);
  18. // This pointer always points to the current end of the data payload.
  19. _endOfPayload = (unsigned char*)_packetData;
  20. *_packetMagic = MAGICNUMBER;
  21. *_packetSize = 16; // At the start, we have 4 MAGIC, 4 SIZE, 4 CMD and 4 CHECKSUM
  22. *_packetCommand = command;
  23. _port = _ip = 0;
  24. }
  25. bool Packet::send(QAbstractSocket* socket)
  26. {
  27. // logger->Packet("Packet::send()");
  28. if(socket->socketType() == QAbstractSocket::TcpSocket && socket->state() != QAbstractSocket::ConnectedState)
  29. {
  30. logger->Packet("Packet::send(): The given TCP socket is not in connected state, cannot send!");
  31. return false;
  32. }
  33. // compute CRC etc.
  34. finalize();
  35. // logger->Packet("Packet::send(): now calling socket->write()");
  36. if(socket->write((const char*)_buffer, *_packetSize) < 0)
  37. {
  38. logger->Packet("Packet::send(): couldn't send the packet: %s.", qPrintable(socket->errorString()));
  39. return false;
  40. }
  41. else
  42. {
  43. // logger->Packet("Packet::send(): now calling socket->waitForBytesWritten(-1)");
  44. // socket->waitForBytesWritten(-1);
  45. // logger->Packet("Packet::send(): sent packet with command 0x%08x.", getCommand());
  46. return true;
  47. }
  48. }
  49. void Packet::finalize()
  50. {
  51. // logger->Packet("Packet::finalize()");
  52. // The packet has been filled and will now be sent. Append the CRC value after the data.
  53. _packetCRC = (unsigned int*)_endOfPayload;
  54. *_packetCRC = getCRC();
  55. // logger->Packet("Packet::finalize(): finalizing, packet CRC is %d.", *_packetCRC);
  56. }
  57. unsigned int Packet::getCommand(void) const
  58. {
  59. return *_packetCommand;
  60. }
  61. void Packet::setCommand(const unsigned int command)
  62. {
  63. *_packetCommand = command;
  64. }
  65. bool Packet::isValid(void) const
  66. {
  67. return isValidPacket;
  68. }
  69. Packet::~Packet()
  70. {
  71. delete[] _buffer;
  72. }
  73. /////////////////////////////////////////////////////////////////////////
  74. // PUSH methods
  75. /////////////////////////////////////////////////////////////////////////
  76. void Packet::pushU32(const unsigned int data)
  77. {
  78. // bail out if there's no space left in buffer
  79. if(_endOfPayload - _buffer + sizeof(unsigned int) > _bufferSize) abort("Packet::push(): buffer overflow\n");
  80. // first assign the value, then increment pointer.
  81. *(unsigned int *)_endOfPayload = data;
  82. _endOfPayload += sizeof(unsigned int);
  83. *_packetSize += sizeof(unsigned int);
  84. }
  85. void Packet::pushS32(const signed int data)
  86. {
  87. // bail out if there's no space left in buffer
  88. if(_endOfPayload - _buffer + sizeof(signed int) > _bufferSize) abort("Packet::push(): buffer overflow\n");
  89. // first assign the value, then increment pointer.
  90. *(signed int *)_endOfPayload = data;
  91. _endOfPayload += sizeof(signed int);
  92. *_packetSize += sizeof(signed int);
  93. }
  94. void Packet::pushF32(const float data)
  95. {
  96. // bail out if there's no space left in buffer
  97. if(_endOfPayload - _buffer + sizeof(float) > _bufferSize) abort("Packet::push(): buffer overflow\n");
  98. *(float *)_endOfPayload = data;
  99. _endOfPayload += sizeof(float);
  100. *_packetSize += sizeof(float);
  101. }
  102. void Packet::pushD64(const double data)
  103. {
  104. // bail out if there's no space left in buffer
  105. if(_endOfPayload - _buffer + sizeof(double) > _bufferSize) abort("Packet::push(): buffer overflow\n");
  106. *(double *)_endOfPayload = data;
  107. _endOfPayload += sizeof(double);
  108. *_packetSize += sizeof(double);
  109. }
  110. /////////////////////////////////////////////////////////////////////////
  111. // POP methods
  112. /////////////////////////////////////////////////////////////////////////
  113. unsigned int Packet::popU32(void)
  114. {
  115. // we assume that a packet gets ONLY pop()s XOR push()es,
  116. // so we use the same _endOfPayload pointer
  117. unsigned int data = *(unsigned int*)_endOfPayload;
  118. _endOfPayload += sizeof(unsigned int);
  119. return data;
  120. }
  121. signed int Packet::popS32(void)
  122. {
  123. // we assume that a packet gets ONLY pop()s XOR push()es,
  124. // so we use the same _endOfPayload pointer
  125. signed int data = *(signed int*)_endOfPayload;
  126. _endOfPayload += sizeof(signed int);
  127. return data;
  128. }
  129. float Packet::popF32(void)
  130. {
  131. // we assume that a packet gets ONLY pop()s XOR push()es,
  132. // so we use the same _endOfPayload pointer
  133. float data = *(float*)_endOfPayload;
  134. _endOfPayload += sizeof(float);
  135. return data;
  136. }
  137. double Packet::popD64(void)
  138. {
  139. // we assume that a packet gets ONLY pop()s XOR push()es,
  140. // so we use the same _endOfPayload pointer
  141. double data = *(double*)_endOfPayload;
  142. _endOfPayload += sizeof(double);
  143. return data;
  144. }
  145. /////////////////////////////////////////////////////////////////////////
  146. // PUT methods
  147. /////////////////////////////////////////////////////////////////////////
  148. void Packet::putU32(const unsigned int data, const int offset)
  149. {
  150. *(unsigned int *)(_packetData + offset) = data;
  151. }
  152. void Packet::putS32(const signed int data, const int offset)
  153. {
  154. *(signed int *)(_packetData + offset) = data;
  155. }
  156. void Packet::putF32(const float data, const int offset)
  157. {
  158. *(float *)(_packetData + offset) = data;
  159. }
  160. void Packet::putD64(const double data, const int offset)
  161. {
  162. *(double *)(_packetData + offset) = data;
  163. }
  164. /////////////////////////////////////////////////////////////////////////
  165. // PEEK methods
  166. /////////////////////////////////////////////////////////////////////////
  167. unsigned int Packet::peekU32(int offset)
  168. {
  169. return (unsigned int)*(_packetData + offset);
  170. }
  171. signed int Packet::peekS32(int offset)
  172. {
  173. return (signed int)*(_packetData + offset);
  174. }
  175. float Packet::peekF32(int offset)
  176. {
  177. return (float)*(_packetData + offset);
  178. }
  179. double Packet::peekD64(int offset)
  180. {
  181. return (double)*(_packetData + offset);
  182. }
  183. void Packet::resetPayloadPointer(void)
  184. {
  185. _endOfPayload = _buffer + 12;
  186. }
  187. // This method is used to create a packet from a (received?) buffer
  188. void Packet::setData(const unsigned char* data, const unsigned int length)
  189. {
  190. if(length > _bufferSize)
  191. {
  192. // reallocate enough memory
  193. delete[] _buffer;
  194. _buffer = new unsigned char[length];
  195. }
  196. _bufferSize = length;
  197. // copy the data into our own private buffer
  198. memcpy(_buffer, data, _bufferSize);
  199. // initialize the pointers like in the constructor
  200. _packetMagic = (unsigned int*) (_buffer + 0);
  201. _packetSize = (unsigned int*) (_buffer + 4);
  202. _packetCommand = (unsigned int*) (_buffer + 8);
  203. _packetData = (unsigned int*) (_buffer + 12);
  204. _packetCRC = (unsigned int*) (_buffer + length - 4);
  205. _port = _ip = 0;
  206. if(*_packetMagic == MAGICNUMBER && *_packetCRC == getCRC())
  207. {
  208. isValidPacket = true;
  209. //logger->Packet("Packet::Packet(): reconstructed packet from given data; MAGIC is 0x%08x, CRC is %d, size is %d, command is 0x%08x", *_packetMagic, getCRC(), *_packetSize, *_packetCommand);
  210. }
  211. else
  212. {
  213. isValidPacket = false;
  214. logger->Packet("Packet::setData(): cannot reconstruct packet. CMD is 0x%08x, MAGIC is 0x%08x, size %d, CRC is %d, should be %d, bufferlength was %d", *_packetCommand, *_packetMagic, *_packetSize, getCRC(), *_packetCRC, length);
  215. // abort("");
  216. for(int i = 0; i < *_packetSize; i++)
  217. {
  218. printf("0x%02x\n", _packetData[i]);
  219. }
  220. printf("\n\n");
  221. }
  222. }
  223. unsigned char* Packet::getData(void) const
  224. {
  225. return _buffer;
  226. }
  227. unsigned int Packet::getDataLength(void) const
  228. {
  229. // A packet has 4 MAGIC, 4 SIZE, 4 CMD, N DATA and 4 CRC, so
  230. // the length of DATA is packetlength - MAGIC-SIZE-CMD-CRC
  231. return *_packetSize - 16;
  232. }
  233. unsigned int Packet::getPacketLength(void) const
  234. {
  235. // return the whole packet's length in bytes. This is header + data.
  236. return *_packetSize;
  237. }
  238. unsigned int Packet::getCRC(void) const
  239. {
  240. // logger->Packet("Packet::getCRC()");
  241. // compute CRC over whole packet, minus the last 4 bytes, which is the CRC field itself.
  242. unsigned int length = *_packetSize - 4;
  243. if(length < 4)
  244. {
  245. logger->Packet("Packet::getCRC(): length is smaller 4, aborting.");
  246. abort();
  247. }
  248. static unsigned int crctab[256];
  249. static bool initialized = false;
  250. if(!initialized)
  251. {
  252. for(int i = 0; i < 256; i++)
  253. {
  254. unsigned int crc = i << 24;
  255. for (int j = 0; j < 8; j++)
  256. {
  257. if (crc & 0x80000000)
  258. {
  259. crc = (crc << 1) ^ 0x04c11db7;
  260. }
  261. else
  262. {
  263. crc = crc << 1;
  264. }
  265. }
  266. crctab[i] = crc;
  267. }
  268. }
  269. unsigned char *data = _buffer;
  270. unsigned int result;
  271. result = *data++ << 24;
  272. result |= *data++ << 16;
  273. result |= *data++ << 8;
  274. result |= *data++;
  275. result = ~ result;
  276. length -= 4;
  277. while (length-- > 0)
  278. {
  279. result = (result << 8 | *data++) ^ crctab[result >> 24];
  280. }
  281. return ~result;
  282. }