summaryrefslogtreecommitdiff
path: root/src/components/protocol_handler/src/protocol_packet.cc
diff options
context:
space:
mode:
authorJustin Dickow <jjdickow@gmail.com>2015-01-24 16:58:15 -0500
committerJustin Dickow <jjdickow@gmail.com>2015-01-24 16:58:15 -0500
commita24079cb8de5563376dcf782cdb9fe3cae063841 (patch)
tree1fca30dde1aa30c7ac11fb6b009d2bd6420bd648 /src/components/protocol_handler/src/protocol_packet.cc
parentf948dd4539eeecb2c32084cc39b68923fc94e3dd (diff)
downloadsdl_core-a24079cb8de5563376dcf782cdb9fe3cae063841.tar.gz
HmiStatus modify
HU DCHECK occurs during multisession registration Remove unused variable SIGSEGV handler added to flush logger queue FixIncomplete device list in UpdateDeviceList request Fix Memory leak on PutFile break Fix Thread and Timer Fix OnHmiStatus Notification Fix Url array sending for endpoints. Fix HashChange Fix SDL parse incoming JSON message with both members error and result as success message Fix Core crashes while connecting mobile app Signed-off-by: Justin Dickow <jjdickow@gmail.com>
Diffstat (limited to 'src/components/protocol_handler/src/protocol_packet.cc')
-rw-r--r--src/components/protocol_handler/src/protocol_packet.cc319
1 files changed, 232 insertions, 87 deletions
diff --git a/src/components/protocol_handler/src/protocol_packet.cc b/src/components/protocol_handler/src/protocol_packet.cc
index 19c73127cb..d40f13b5f0 100644
--- a/src/components/protocol_handler/src/protocol_packet.cc
+++ b/src/components/protocol_handler/src/protocol_packet.cc
@@ -33,55 +33,203 @@
#include <stdint.h>
#include <memory.h>
#include <new>
+#include <cstring>
+#include <limits>
+
#include "protocol_handler/protocol_packet.h"
#include "utils/macro.h"
+#include "utils/byte_order.h"
namespace protocol_handler {
+ProtocolPacket::ProtocolData::ProtocolData()
+ : data(NULL), totalDataBytes(0u) { }
+
+ProtocolPacket::ProtocolData::~ProtocolData() {
+ delete[] data;
+}
+
+ProtocolPacket::ProtocolHeader::ProtocolHeader()
+ : version(0x00),
+ protection_flag(PROTECTION_OFF),
+ frameType(0x00),
+ serviceType(0x00),
+ frameData(0x00),
+ sessionId(0x00),
+ dataSize(0x00),
+ messageId(0x00) {
+}
+
+ProtocolPacket::ProtocolHeader::ProtocolHeader(
+ uint8_t version, bool protection, uint8_t frameType, uint8_t serviceType,
+ uint8_t frameData, uint8_t sessionID, uint32_t dataSize, uint32_t messageID)
+ : version(version),
+ protection_flag(protection),
+ frameType(frameType),
+ serviceType(serviceType),
+ frameData(frameData),
+ sessionId(sessionID),
+ dataSize(dataSize),
+ messageId(messageID) {
+}
+
+void ProtocolPacket::ProtocolHeader::deserialize(
+ const uint8_t* message, const size_t messageSize) {
+ if (messageSize < PROTOCOL_HEADER_V1_SIZE) {
+ return;
+ }
+ // first 4 bits
+ version = message[0] >> 4u;
+ // 5th bit
+ protection_flag = message[0] & 0x08u;
+ // 6-8 bits
+ frameType = message[0] & 0x07u;
+
+ serviceType = message[1];
+ frameData = message[2];
+ sessionId = message[3];
+
+ // FIXME(EZamakhov): usage for FirstFrame message
+ const uint32_t data_size_be = *(reinterpret_cast<const uint32_t*>(message + 4));
+ dataSize = BE_TO_LE32(data_size_be);
+ switch (version) {
+ case PROTOCOL_VERSION_2:
+ case PROTOCOL_VERSION_3: {
+ if (messageSize < PROTOCOL_HEADER_V2_SIZE) {
+ return;
+ }
+ const uint32_t message_id_be =
+ *(reinterpret_cast<const uint32_t*>(message + 8));
+ messageId = BE_TO_LE32(message_id_be);
+ }
+ break;
+ default:
+ messageId = 0;
+ break;
+ }
+}
+
+ProtocolPacket::ProtocolHeaderValidator::ProtocolHeaderValidator()
+ : max_payload_size_(std::numeric_limits<size_t>::max()) {}
+
+void ProtocolPacket::ProtocolHeaderValidator::set_max_payload_size(
+ const size_t max_payload_size) {
+ max_payload_size_ = max_payload_size;
+}
+
+size_t ProtocolPacket::ProtocolHeaderValidator::max_payload_size() const {
+ return max_payload_size_;
+}
+
+RESULT_CODE ProtocolPacket::ProtocolHeaderValidator::validate(const ProtocolHeader& header) const {
+ // Protocol version shall be from 1 to 3
+ switch (header.version) {
+ case PROTOCOL_VERSION_1:
+ case PROTOCOL_VERSION_2:
+ case PROTOCOL_VERSION_3:
+ break;
+ default:
+ return RESULT_FAIL;
+ }
+ // ServiceType shall be equal 0x0 (Control), 0x07 (RPC), 0x0A (PCM), 0x0B (Video), 0x0F (Bulk)
+ if (ServiceTypeFromByte(header.serviceType) == kInvalidServiceType) {
+ return RESULT_FAIL;
+ }
+ // Check frame info for each frame type
+ // Frame type shall be 0x00 (Control), 0x01 (Single), 0x02 (First), 0x03 (Consecutive)
+ // For Control frames Frame info value shall be from 0x00 to 0x06 or 0xFE(Data Ack), 0xFF(HB Ack)
+ // For Single and First frames Frame info value shall be equal 0x00
+ switch (header.frameType) {
+ case FRAME_TYPE_CONTROL : {
+ switch (header.frameData) {
+ case FRAME_DATA_HEART_BEAT:
+ case FRAME_DATA_START_SERVICE:
+ case FRAME_DATA_START_SERVICE_ACK:
+ case FRAME_DATA_START_SERVICE_NACK:
+ case FRAME_DATA_END_SERVICE:
+ case FRAME_DATA_END_SERVICE_ACK:
+ case FRAME_DATA_END_SERVICE_NACK:
+ case FRAME_DATA_SERVICE_DATA_ACK:
+ case FRAME_DATA_HEART_BEAT_ACK:
+ break;
+ default:
+ return RESULT_FAIL;
+ }
+ break;
+ }
+ case FRAME_TYPE_SINGLE:
+ if (header.frameData != FRAME_DATA_SINGLE) {
+ return RESULT_FAIL;
+ }
+ break;
+ case FRAME_TYPE_FIRST:
+ if (header.frameData != FRAME_DATA_FIRST) {
+ return RESULT_FAIL;
+ }
+ break;
+ case FRAME_TYPE_CONSECUTIVE:
+ // Could have any FrameInfo value
+ break;
+ default:
+ // All other Frame type is invalid
+ return RESULT_FAIL;
+ }
+ // For Control frames Data Size value shall be less than MTU header
+ // For Single and Consecutive Data Size value shall be greater than 0x00
+ // and shall be less than N (this value will be defined in .ini file)
+ if (header.dataSize > max_payload_size_) {
+ return RESULT_FAIL;
+ }
+ switch (header.frameType) {
+ case FRAME_TYPE_SINGLE:
+ case FRAME_TYPE_CONSECUTIVE:
+ if (header.dataSize <= 0) {
+ return RESULT_FAIL;
+ }
+ break;
+ default:
+ break;
+ }
+ // Message ID be equal or greater than 0x01 (not actual for 1 protocol version and Control frames)
+ if (FRAME_TYPE_CONTROL != header.frameType && PROTOCOL_VERSION_1 != header.version
+ && header.messageId <= 0) {
+ // Message ID shall be greater than 0x00, but not implemented in SPT
+ // TODO(EZamakhov): return on fix on mobile side - APPLINK-9990
+ return RESULT_FAIL;
+ }
+ return RESULT_OK;
+}
+
+
ProtocolPacket::ProtocolPacket()
- : payload_size_(0),
- packet_id_(0),
- connection_id_(0) {
+ : payload_size_(0), connection_id_(0) {
}
-ProtocolPacket::ProtocolPacket(uint8_t connection_id,
+ProtocolPacket::ProtocolPacket(ConnectionID connection_id,
uint8_t version, bool protection,
uint8_t frameType,
uint8_t serviceType,
uint8_t frameData, uint8_t sessionID,
uint32_t dataSize, uint32_t messageID,
- const uint8_t *data,
- uint32_t packet_id)
+ const uint8_t *data)
: packet_header_(version, protection, frameType, serviceType,
frameData, sessionID, dataSize, messageID),
+ packet_data_(),
payload_size_(0),
- packet_id_(packet_id),
connection_id_(connection_id) {
set_data(data, dataSize);
- DCHECK(MAXIMUM_FRAME_DATA_SIZE >= dataSize);
}
-ProtocolPacket::ProtocolPacket(uint8_t connection_id, uint8_t *data_param,
- uint32_t data_size)
- : payload_size_(0),
- packet_id_(0),
+ProtocolPacket::ProtocolPacket(ConnectionID connection_id)
+ : packet_header_(),
+ packet_data_(),
+ payload_size_(0),
connection_id_(connection_id) {
- RESULT_CODE result = deserializePacket(data_param, data_size);
- if (result != RESULT_OK) {
- //NOTREACHED();
- }
-}
-
-ProtocolPacket::~ProtocolPacket() {
- delete[] packet_data_.data;
}
// Serialization
RawMessagePtr ProtocolPacket::serializePacket() const {
- uint8_t *packet = new (std::nothrow) uint8_t[MAXIMUM_FRAME_DATA_SIZE];
- if (!packet) {
- return RawMessagePtr();
- }
+ // TODO(EZamakhov): Move header serialization to ProtocolHeader
// version is low byte
const uint8_t version_byte = packet_header_.version << 4;
// protection is first bit of second byte
@@ -89,30 +237,38 @@ RawMessagePtr ProtocolPacket::serializePacket() const {
// frame type is last 3 bits of second byte
const uint8_t frame_type_byte = packet_header_.frameType & 0x07;
+ uint8_t header[PROTOCOL_HEADER_V2_SIZE];
uint8_t offset = 0;
- packet[offset++] = version_byte | protection_byte | frame_type_byte;
- packet[offset++] = packet_header_.serviceType;
- packet[offset++] = packet_header_.frameData;
- packet[offset++] = packet_header_.sessionId;
+ header[offset++] = version_byte | protection_byte | frame_type_byte;
+ header[offset++] = packet_header_.serviceType;
+ header[offset++] = packet_header_.frameData;
+ header[offset++] = packet_header_.sessionId;
- packet[offset++] = packet_header_.dataSize >> 24;
- packet[offset++] = packet_header_.dataSize >> 16;
- packet[offset++] = packet_header_.dataSize >> 8;
- packet[offset++] = packet_header_.dataSize;
+ header[offset++] = packet_header_.dataSize >> 24;
+ header[offset++] = packet_header_.dataSize >> 16;
+ header[offset++] = packet_header_.dataSize >> 8;
+ header[offset++] = packet_header_.dataSize;
if (packet_header_.version != PROTOCOL_VERSION_1) {
- packet[offset++] = packet_header_.messageId >> 24;
- packet[offset++] = packet_header_.messageId >> 16;
- packet[offset++] = packet_header_.messageId >> 8;
- packet[offset++] = packet_header_.messageId;
+ header[offset++] = packet_header_.messageId >> 24;
+ header[offset++] = packet_header_.messageId >> 16;
+ header[offset++] = packet_header_.messageId >> 8;
+ header[offset++] = packet_header_.messageId;
+ };
+
+ size_t total_packet_size = offset + (packet_data_.data ? packet_data_.totalDataBytes : 0);
+#ifndef BUILD_TESTS // Remove DCHECK for PH tests
+ DCHECK(total_packet_size <= MAXIMUM_FRAME_DATA_SIZE);
+#endif
+
+ uint8_t *packet = new (std::nothrow) uint8_t[total_packet_size];
+ if (!packet) {
+ return RawMessagePtr();
}
- DCHECK((offset + packet_data_.totalDataBytes) <= MAXIMUM_FRAME_DATA_SIZE);
-
- size_t total_packet_size = offset;
- if (packet_data_.data) {
+ memcpy(packet, header, offset);
+ if (packet_data_.data && packet_data_.totalDataBytes) {
memcpy(packet + offset, packet_data_.data, packet_data_.totalDataBytes);
- total_packet_size += packet_data_.totalDataBytes;
}
const RawMessagePtr out_message(
@@ -124,14 +280,10 @@ RawMessagePtr ProtocolPacket::serializePacket() const {
return out_message;
}
-uint32_t ProtocolPacket::packet_id() const {
- return packet_id_;
-}
-
RESULT_CODE ProtocolPacket::appendData(uint8_t *chunkData,
uint32_t chunkDataSize) {
if (payload_size_ + chunkDataSize <= packet_data_.totalDataBytes) {
- if (chunkData) {
+ if (chunkData && chunkDataSize > 0) {
if (packet_data_.data) {
memcpy(packet_data_.data + payload_size_, chunkData, chunkDataSize);
payload_size_ += chunkDataSize;
@@ -147,39 +299,36 @@ size_t ProtocolPacket::packet_size() const {
return packet_header_.dataSize;
}
-RESULT_CODE ProtocolPacket::deserializePacket(const uint8_t *message,
- uint32_t messageSize) {
- uint8_t offset = 0;
- uint8_t firstByte = message[offset];
- offset++;
-
- packet_header_.version = firstByte >> 4u;
-
- if (firstByte & 0x08u) {
- packet_header_.protection_flag = true;
- } else {
- packet_header_.protection_flag = false;
+bool ProtocolPacket::operator==(const ProtocolPacket& other) const {
+ if (connection_id_ == other.connection_id_ &&
+ packet_header_.version == other.packet_header_.version &&
+ packet_header_.protection_flag == other.packet_header_.protection_flag &&
+ packet_header_.frameType == other.packet_header_.frameType &&
+ packet_header_.serviceType == other.packet_header_.serviceType &&
+ packet_header_.frameData == other.packet_header_.frameData &&
+ packet_header_.sessionId == other.packet_header_.sessionId &&
+ packet_header_.dataSize == other.packet_header_.dataSize &&
+ packet_header_.messageId == other.packet_header_.messageId &&
+ packet_data_.totalDataBytes == other.packet_data_.totalDataBytes) {
+ if (other.packet_data_.totalDataBytes == 0) {
+ return true;
+ }
+ // Compare payload data
+ if (packet_data_.data && other.packet_data_.data &&
+ 0 == memcmp(packet_data_.data, other.packet_data_.data,
+ packet_data_.totalDataBytes)) {
+ return true;
+ }
}
+ return false;
+}
- packet_header_.frameType = firstByte & 0x07u;
-
- packet_header_.serviceType = message[offset++];
- packet_header_.frameData = message[offset++];
- packet_header_.sessionId = message[offset++];
-
- packet_header_.dataSize = message[offset++] << 24u;
- packet_header_.dataSize |= message[offset++] << 16u;
- packet_header_.dataSize |= message[offset++] << 8u;
- packet_header_.dataSize |= message[offset++];
-
- if (packet_header_.version != PROTOCOL_VERSION_1) {
- packet_header_.messageId = message[offset++] << 24u;
- packet_header_.messageId |= message[offset++] << 16u;
- packet_header_.messageId |= message[offset++] << 8u;
- packet_header_.messageId |= message[offset++];
- } else {
- packet_header_.messageId = 0u;
- }
+RESULT_CODE ProtocolPacket::deserializePacket(
+ const uint8_t *message, const size_t messageSize) {
+ packet_header_.deserialize(message, messageSize);
+ const uint8_t offset =
+ packet_header_.version == PROTOCOL_VERSION_1 ? PROTOCOL_HEADER_V1_SIZE
+ : PROTOCOL_HEADER_V2_SIZE;
packet_data_.totalDataBytes = packet_header_.dataSize;
@@ -189,15 +338,14 @@ RESULT_CODE ProtocolPacket::deserializePacket(const uint8_t *message,
dataPayloadSize = messageSize - offset;
}
- uint8_t *data = 0;
+ uint8_t *data = NULL;
if (dataPayloadSize) {
data = new (std::nothrow) uint8_t[dataPayloadSize];
- if (data) {
- memcpy(data, message + offset, dataPayloadSize);
- payload_size_ = dataPayloadSize;
- } else {
+ if (!data) {
return RESULT_FAIL;
}
+ memcpy(data, message + offset, dataPayloadSize);
+ payload_size_ = dataPayloadSize;
}
if (packet_header_.frameType == FRAME_TYPE_FIRST) {
@@ -212,9 +360,7 @@ RESULT_CODE ProtocolPacket::deserializePacket(const uint8_t *message,
return RESULT_FAIL;
}
} else {
- if (packet_data_.data) {
- delete[] packet_data_.data;
- }
+ delete[] packet_data_.data;
packet_data_.data = data;
}
@@ -265,8 +411,7 @@ void ProtocolPacket::set_total_data_bytes(size_t dataBytes) {
if (dataBytes) {
delete[] packet_data_.data;
packet_data_.data = new (std::nothrow) uint8_t[dataBytes];
- packet_data_.totalDataBytes =
- packet_data_.data ? dataBytes : 0;
+ packet_data_.totalDataBytes = packet_data_.data ? dataBytes : 0;
}
}