summaryrefslogtreecommitdiff
path: root/src/components/protocol_handler/src/protocol_packet.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/protocol_handler/src/protocol_packet.cc')
-rw-r--r--src/components/protocol_handler/src/protocol_packet.cc335
1 files changed, 247 insertions, 88 deletions
diff --git a/src/components/protocol_handler/src/protocol_packet.cc b/src/components/protocol_handler/src/protocol_packet.cc
index 19c73127c..a31678ec6 100644
--- a/src/components/protocol_handler/src/protocol_packet.cc
+++ b/src/components/protocol_handler/src/protocol_packet.cc
@@ -33,55 +33,220 @@
#include <stdint.h>
#include <memory.h>
#include <new>
+#include <cstring>
+#include <limits>
+
+#include "protocol/common.h"
#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) {
+}
+
+inline uint32_t read_be_uint32(const uint8_t* const data) {
+ // Int value read byte per byte
+ // reintercast for non-4 byte address alignment lead to UB on arm platform
+ uint32_t value = data[3];
+ value += (data[2] << 8);
+ value += (data[1] << 16);
+ value += (data[0] << 24);
+ return value;
+}
+
+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
+ dataSize = read_be_uint32(message + 4);
+ switch (version) {
+ case PROTOCOL_VERSION_2:
+ case PROTOCOL_VERSION_3:
+ case PROTOCOL_VERSION_4:{
+ if (messageSize < PROTOCOL_HEADER_V2_SIZE) {
+ return;
+ }
+ messageId = read_be_uint32(message + 8);
+ }
+ 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 {
+ // expected payload size will be calculated depending
+ // on used protocol version
+ size_t payload_size = MAXIMUM_FRAME_DATA_V2_SIZE;
+ // Protocol version shall be from 1 to 4
+ switch (header.version) {
+ case PROTOCOL_VERSION_1:
+ case PROTOCOL_VERSION_2:
+ break;
+ case PROTOCOL_VERSION_3:
+ case PROTOCOL_VERSION_4:
+ payload_size = max_payload_size_ > MAXIMUM_FRAME_DATA_V2_SIZE ?
+ max_payload_size_ : MAXIMUM_FRAME_DATA_V2_SIZE;
+ 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 payload size
+ if (header.dataSize > 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 +254,35 @@ 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);
- DCHECK((offset + packet_data_.totalDataBytes) <= MAXIMUM_FRAME_DATA_SIZE);
+ uint8_t *packet = new (std::nothrow) uint8_t[total_packet_size];
+ if (!packet) {
+ return RawMessagePtr();
+ }
- 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 +294,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 +313,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 +352,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 +374,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 +425,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 : 0u;
}
}
@@ -280,7 +439,7 @@ void ProtocolPacket::set_data(
memcpy(packet_data_.data, new_data, packet_data_.totalDataBytes);
} else {
// TODO(EZamakhov): add log info about memory problem
- packet_header_.dataSize = packet_data_.totalDataBytes = 0;
+ packet_header_.dataSize = packet_data_.totalDataBytes = 0u;
}
}
}