summaryrefslogtreecommitdiff
path: root/src/components/protocol_handler/src/protocol_handler_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/protocol_handler/src/protocol_handler_impl.cc')
-rw-r--r--src/components/protocol_handler/src/protocol_handler_impl.cc644
1 files changed, 580 insertions, 64 deletions
diff --git a/src/components/protocol_handler/src/protocol_handler_impl.cc b/src/components/protocol_handler/src/protocol_handler_impl.cc
index aa2910722d..23ac2927ef 100644
--- a/src/components/protocol_handler/src/protocol_handler_impl.cc
+++ b/src/components/protocol_handler/src/protocol_handler_impl.cc
@@ -33,6 +33,8 @@
#include "protocol_handler/protocol_handler_impl.h"
#include <memory.h>
#include <algorithm> // std::find
+#include <bson_object.h>
+#include <protocol/bson_object_keys.h>
#include "connection_handler/connection_handler_impl.h"
#include "protocol_handler/session_observer.h"
@@ -55,7 +57,9 @@ CREATE_LOGGERPTR_GLOBAL(logger_, "ProtocolHandler")
std::string ConvertPacketDataToString(const uint8_t* data,
const size_t data_size);
-const size_t kStackSize = 32768;
+const size_t kStackSize = 65536;
+
+ProtocolPacket::ProtocolVersion defaultProtocolVersion(5, 0, 0);
ProtocolHandlerImpl::ProtocolHandlerImpl(
const ProtocolHandlerSettings& settings,
@@ -77,6 +81,8 @@ ProtocolHandlerImpl::ProtocolHandlerImpl(
"PH FromMobile", this, threads::ThreadOptions(kStackSize))
, raw_ford_messages_to_mobile_(
"PH ToMobile", this, threads::ThreadOptions(kStackSize))
+ , start_session_frame_map_lock_()
+ , start_session_frame_map_()
#ifdef TELEMETRY_MONITOR
, metric_observer_(NULL)
#endif // TELEMETRY_MONITOR
@@ -85,6 +91,14 @@ ProtocolHandlerImpl::ProtocolHandlerImpl(
LOG4CXX_AUTO_TRACE(logger_);
protocol_header_validator_.set_max_payload_size(
get_settings().maximum_payload_size());
+ protocol_header_validator_.set_max_control_payload_size(
+ get_settings().maximum_control_payload_size());
+ protocol_header_validator_.set_max_rpc_payload_size(
+ get_settings().maximum_rpc_payload_size());
+ protocol_header_validator_.set_max_audio_payload_size(
+ get_settings().maximum_audio_payload_size());
+ protocol_header_validator_.set_max_video_payload_size(
+ get_settings().maximum_video_payload_size());
incoming_data_handler_.set_validator(&protocol_header_validator_);
const size_t& message_frequency_count =
@@ -176,17 +190,82 @@ void set_hash_id(uint32_t hash_id, protocol_handler::ProtocolPacket& packet) {
void ProtocolHandlerImpl::SendStartSessionAck(ConnectionID connection_id,
uint8_t session_id,
- uint8_t,
+ uint8_t input_protocol_version,
uint32_t hash_id,
uint8_t service_type,
bool protection) {
LOG4CXX_AUTO_TRACE(logger_);
+ ProtocolPacket::ProtocolVersion fullVersion;
+ SendStartSessionAck(connection_id,
+ session_id,
+ input_protocol_version,
+ hash_id,
+ service_type,
+ protection,
+ fullVersion);
+}
+
+void ProtocolHandlerImpl::SendStartSessionAck(
+ ConnectionID connection_id,
+ uint8_t session_id,
+ uint8_t input_protocol_version,
+ uint32_t hash_id,
+ uint8_t service_type,
+ bool protection,
+ ProtocolPacket::ProtocolVersion& full_version) {
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ BsonObject empty_param;
+ bson_object_initialize_default(&empty_param);
+
+ SendStartSessionAck(connection_id,
+ session_id,
+ input_protocol_version,
+ hash_id,
+ service_type,
+ protection,
+ full_version,
+ empty_param);
+
+ bson_object_deinitialize(&empty_param);
+}
+
+void ProtocolHandlerImpl::SendStartSessionAck(
+ ConnectionID connection_id,
+ uint8_t session_id,
+ uint8_t input_protocol_version,
+ uint32_t hash_id,
+ uint8_t service_type,
+ bool protection,
+ ProtocolPacket::ProtocolVersion& full_version,
+ BsonObject& params) {
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ uint8_t ack_protocol_version = SupportedSDLProtocolVersion();
+
+ const bool proxy_supports_v5_protocol =
+ input_protocol_version >= PROTOCOL_VERSION_5 ||
+ (ServiceTypeFromByte(service_type) == kRpc &&
+ full_version.majorVersion >= PROTOCOL_VERSION_5);
- uint8_t protocolVersion = SupportedSDLProtocolVersion();
+ if (kRpc != service_type) {
+ // In case if input protocol version os bigger then supported, SDL should
+ // respond with maximum supported protocol version
+ ack_protocol_version = input_protocol_version < ack_protocol_version
+ ? input_protocol_version
+ : ack_protocol_version;
+ }
+
+ // We can't send a V5+ packet if the proxy doesn't support it,
+ // so we manually set a maximum of V4 in that case
+ if (!proxy_supports_v5_protocol &&
+ ack_protocol_version >= PROTOCOL_VERSION_5) {
+ ack_protocol_version = PROTOCOL_VERSION_4;
+ }
ProtocolFramePtr ptr(
new protocol_handler::ProtocolPacket(connection_id,
- protocolVersion,
+ ack_protocol_version,
protection,
FRAME_TYPE_CONTROL,
service_type,
@@ -195,7 +274,37 @@ void ProtocolHandlerImpl::SendStartSessionAck(ConnectionID connection_id,
0u,
message_counters_[session_id]++));
- set_hash_id(hash_id, *ptr);
+ // Cannot include a constructed payload if either side doesn't support it
+ if (ack_protocol_version >= PROTOCOL_VERSION_5) {
+ ServiceType serviceTypeValue = ServiceTypeFromByte(service_type);
+
+ bson_object_put_int64(
+ &params,
+ strings::mtu,
+ static_cast<int64_t>(
+ protocol_header_validator_.max_payload_size_by_service_type(
+ serviceTypeValue)));
+ if (serviceTypeValue == kRpc) {
+ // Hash ID is only used in RPC case
+ bson_object_put_int32(
+ &params, strings::hash_id, static_cast<int32_t>(hash_id));
+ // Minimum protocol version supported by both
+ ProtocolPacket::ProtocolVersion* minVersion =
+ (full_version.majorVersion < PROTOCOL_VERSION_5)
+ ? &defaultProtocolVersion
+ : ProtocolPacket::ProtocolVersion::min(full_version,
+ defaultProtocolVersion);
+ char protocolVersionString[256];
+ strncpy(protocolVersionString, (*minVersion).to_string().c_str(), 255);
+ bson_object_put_string(
+ &params, strings::protocol_version, protocolVersionString);
+ }
+ uint8_t* payloadBytes = bson_object_to_bytes(&params);
+ ptr->set_data(payloadBytes, bson_object_size(&params));
+ free(payloadBytes);
+ } else {
+ set_hash_id(hash_id, *ptr);
+ }
raw_ford_messages_to_mobile_.PostMessage(
impl::RawFordMessageToMobile(ptr, false));
@@ -212,6 +321,20 @@ void ProtocolHandlerImpl::SendStartSessionNAck(ConnectionID connection_id,
uint8_t session_id,
uint8_t protocol_version,
uint8_t service_type) {
+ std::vector<std::string> rejectedParams;
+ SendStartSessionNAck(connection_id,
+ session_id,
+ protocol_version,
+ service_type,
+ rejectedParams);
+}
+
+void ProtocolHandlerImpl::SendStartSessionNAck(
+ ConnectionID connection_id,
+ uint8_t session_id,
+ uint8_t protocol_version,
+ uint8_t service_type,
+ std::vector<std::string>& rejectedParams) {
LOG4CXX_AUTO_TRACE(logger_);
ProtocolFramePtr ptr(
@@ -225,6 +348,27 @@ void ProtocolHandlerImpl::SendStartSessionNAck(ConnectionID connection_id,
0u,
message_counters_[session_id]++));
+ uint8_t maxProtocolVersion = SupportedSDLProtocolVersion();
+
+ if (protocol_version >= PROTOCOL_VERSION_5 &&
+ maxProtocolVersion >= PROTOCOL_VERSION_5 && rejectedParams.size() > 0) {
+ BsonObject payloadObj;
+ bson_object_initialize_default(&payloadObj);
+ BsonArray rejectedParamsArr;
+ bson_array_initialize(&rejectedParamsArr, rejectedParams.size());
+ for (std::string param : rejectedParams) {
+ char paramPtr[255];
+ strncpy(paramPtr, param.c_str(), 255);
+ bson_array_add_string(&rejectedParamsArr, paramPtr);
+ }
+ bson_object_put_array(
+ &payloadObj, strings::rejected_params, &rejectedParamsArr);
+ uint8_t* payloadBytes = bson_object_to_bytes(&payloadObj);
+ ptr->set_data(payloadBytes, bson_object_size(&payloadObj));
+ free(payloadBytes);
+ bson_object_deinitialize(&payloadObj);
+ }
+
raw_ford_messages_to_mobile_.PostMessage(
impl::RawFordMessageToMobile(ptr, false));
@@ -239,6 +383,20 @@ void ProtocolHandlerImpl::SendEndSessionNAck(ConnectionID connection_id,
uint32_t session_id,
uint8_t protocol_version,
uint8_t service_type) {
+ std::vector<std::string> rejectedParams;
+ SendEndSessionNAck(connection_id,
+ session_id,
+ protocol_version,
+ service_type,
+ rejectedParams);
+}
+
+void ProtocolHandlerImpl::SendEndSessionNAck(
+ ConnectionID connection_id,
+ uint32_t session_id,
+ uint8_t protocol_version,
+ uint8_t service_type,
+ std::vector<std::string>& rejectedParams) {
LOG4CXX_AUTO_TRACE(logger_);
ProtocolFramePtr ptr(
@@ -252,6 +410,27 @@ void ProtocolHandlerImpl::SendEndSessionNAck(ConnectionID connection_id,
0u,
message_counters_[session_id]++));
+ uint8_t maxProtocolVersion = SupportedSDLProtocolVersion();
+
+ if (protocol_version >= PROTOCOL_VERSION_5 &&
+ maxProtocolVersion >= PROTOCOL_VERSION_5 && rejectedParams.size() > 0) {
+ BsonObject payloadObj;
+ bson_object_initialize_default(&payloadObj);
+ BsonArray rejectedParamsArr;
+ bson_array_initialize(&rejectedParamsArr, rejectedParams.size());
+ for (std::string param : rejectedParams) {
+ char paramPtr[255];
+ strncpy(paramPtr, param.c_str(), 255);
+ bson_array_add_string(&rejectedParamsArr, paramPtr);
+ }
+ bson_object_put_array(
+ &payloadObj, strings::rejected_params, &rejectedParamsArr);
+ uint8_t* payloadBytes = bson_object_to_bytes(&payloadObj);
+ ptr->set_data(payloadBytes, bson_object_size(&payloadObj));
+ free(payloadBytes);
+ bson_object_deinitialize(&payloadObj);
+ }
+
raw_ford_messages_to_mobile_.PostMessage(
impl::RawFordMessageToMobile(ptr, false));
@@ -413,7 +592,7 @@ void ProtocolHandlerImpl::SendMessageToMobileApp(const RawMessagePtr message,
metric_observer_->StartMessageProcess(message_id, start_time);
}
#endif // TELEMETRY_MONITOR
- const size_t max_frame_size = get_settings().maximum_payload_size();
+ size_t max_frame_size = get_settings().maximum_payload_size();
size_t frame_size = MAXIMUM_FRAME_DATA_V2_SIZE;
switch (message->protocol_version()) {
case PROTOCOL_VERSION_3:
@@ -422,6 +601,13 @@ void ProtocolHandlerImpl::SendMessageToMobileApp(const RawMessagePtr message,
? max_frame_size
: MAXIMUM_FRAME_DATA_V2_SIZE;
break;
+ case PROTOCOL_VERSION_5:
+ max_frame_size =
+ protocol_header_validator_.max_payload_size_by_service_type(
+ ServiceTypeFromByte(message->service_type()));
+ frame_size = max_frame_size > MAXIMUM_FRAME_DATA_V2_SIZE
+ ? max_frame_size
+ : MAXIMUM_FRAME_DATA_V2_SIZE;
default:
break;
}
@@ -883,7 +1069,7 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessage(
switch (packet->frame_data()) {
case FRAME_DATA_START_SERVICE: {
LOG4CXX_TRACE(logger_, "FrameData: StartService");
- return HandleControlMessageStartSession(*packet);
+ return HandleControlMessageStartSession(packet);
}
case FRAME_DATA_END_SERVICE: {
LOG4CXX_TRACE(logger_, "FrameData: StopService");
@@ -924,10 +1110,19 @@ uint32_t get_hash_id(const ProtocolPacket& packet) {
LOG4CXX_WARN(logger_, "Packet without hash data (data size less 4)");
return HASH_ID_WRONG;
}
- const uint32_t hash_be = *(reinterpret_cast<uint32_t*>(packet.data()));
- const uint32_t hash_le = BE_TO_LE32(hash_be);
- // null hash is wrong hash value
- return hash_le == HASH_ID_NOT_SUPPORTED ? HASH_ID_WRONG : hash_le;
+ if (packet.protocol_version() >= PROTOCOL_VERSION_5) {
+ BsonObject obj = bson_object_from_bytes(packet.data());
+ const uint32_t hash_id =
+ (uint32_t)bson_object_get_int32(&obj, strings::hash_id);
+ bson_object_deinitialize(&obj);
+ return hash_id;
+ } else {
+ const uint32_t hash_be = *(reinterpret_cast<uint32_t*>(packet.data()));
+ const uint32_t hash_le = BE_TO_LE32(hash_be);
+
+ // null hash is wrong hash value
+ return hash_le == HASH_ID_NOT_SUPPORTED ? HASH_ID_WRONG : hash_le;
+ }
}
RESULT_CODE ProtocolHandlerImpl::HandleControlMessageEndSession(
@@ -935,12 +1130,12 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessageEndSession(
LOG4CXX_AUTO_TRACE(logger_);
const uint8_t current_session_id = packet.session_id();
- const uint32_t hash_id = get_hash_id(packet);
+ uint32_t hash_id = get_hash_id(packet);
const ServiceType service_type = ServiceTypeFromByte(packet.service_type());
const ConnectionID connection_id = packet.connection_id();
const uint32_t session_key = session_observer_.OnSessionEndedCallback(
- connection_id, current_session_id, hash_id, service_type);
+ connection_id, current_session_id, &hash_id, service_type);
// TODO(EZamakhov): add clean up output queue (for removed service)
if (session_key != 0) {
@@ -953,10 +1148,22 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessageEndSession(
LOG4CXX_WARN(logger_,
"Refused to end session " << static_cast<int>(service_type)
<< " type.");
- SendEndSessionNAck(connection_id,
- current_session_id,
- packet.protocol_version(),
- service_type);
+ if (packet.protocol_version() >= PROTOCOL_VERSION_5) {
+ std::vector<std::string> rejectedParams;
+ if (hash_id == protocol_handler::HASH_ID_WRONG) {
+ rejectedParams.push_back(std::string(strings::hash_id));
+ }
+ SendEndSessionNAck(connection_id,
+ current_session_id,
+ packet.protocol_version(),
+ service_type,
+ rejectedParams);
+ } else {
+ SendEndSessionNAck(connection_id,
+ current_session_id,
+ packet.protocol_version(),
+ service_type);
+ }
}
return RESULT_OK;
}
@@ -1006,12 +1213,37 @@ class StartSessionHandler : public security_manager::SecurityManagerListener {
, protocol_version_(protocol_version)
, hash_id_(hash_id)
, service_type_(service_type)
- , force_protected_service_(force_protected_service) {}
+ , force_protected_service_(force_protected_service)
+ , full_version_()
+ , payload_(NULL) {}
+ StartSessionHandler(uint32_t connection_key,
+ ProtocolHandlerImpl* protocol_handler,
+ SessionObserver& session_observer,
+ ConnectionID connection_id,
+ int32_t session_id,
+ uint8_t protocol_version,
+ uint32_t hash_id,
+ ServiceType service_type,
+ const std::vector<int>& force_protected_service,
+ ProtocolPacket::ProtocolVersion& full_version,
+ uint8_t* payload)
+ : connection_key_(connection_key)
+ , protocol_handler_(protocol_handler)
+ , session_observer_(session_observer)
+ , connection_id_(connection_id)
+ , session_id_(session_id)
+ , protocol_version_(protocol_version)
+ , hash_id_(hash_id)
+ , service_type_(service_type)
+ , force_protected_service_(force_protected_service)
+ , full_version_(full_version)
+ , payload_(payload) {}
bool OnHandshakeDone(
const uint32_t connection_key,
security_manager::SSLContext::HandshakeResult result) OVERRIDE {
if (connection_key != connection_key_) {
+ delete[] payload_;
return false;
}
const bool success =
@@ -1031,13 +1263,23 @@ class StartSessionHandler : public security_manager::SecurityManagerListener {
if (success) {
session_observer_.SetProtectionFlag(connection_key_, service_type_);
}
+ BsonObject params;
+ if (payload_ != NULL) {
+ params = bson_object_from_bytes(payload_);
+ } else {
+ bson_object_initialize_default(&params);
+ }
protocol_handler_->SendStartSessionAck(connection_id_,
session_id_,
protocol_version_,
hash_id_,
service_type_,
- success);
+ success,
+ full_version_,
+ params);
+ bson_object_deinitialize(&params);
}
+ delete[] payload_;
delete this;
return true;
}
@@ -1059,10 +1301,13 @@ class StartSessionHandler : public security_manager::SecurityManagerListener {
const uint32_t hash_id_;
const ServiceType service_type_;
const std::vector<int> force_protected_service_;
+ ProtocolPacket::ProtocolVersion full_version_;
+ uint8_t* payload_;
};
} // namespace
#endif // ENABLE_SECURITY
+// DEPRECATED
RESULT_CODE ProtocolHandlerImpl::HandleControlMessageStartSession(
const ProtocolPacket& packet) {
LOG4CXX_AUTO_TRACE(logger_);
@@ -1121,7 +1366,30 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessageStartSession(
PROTECTION_OFF);
return RESULT_OK;
}
- if (ssl_context->IsInitCompleted()) {
+ ProtocolPacket::ProtocolVersion* fullVersion;
+ std::vector<std::string> rejectedParams(0, std::string(""));
+ // Can't check protocol_version because the first packet is v1, but there
+ // could still be a payload, in which case we can get the real protocol
+ // version
+ if (packet.service_type() == kRpc && packet.data_size() != 0) {
+ BsonObject obj = bson_object_from_bytes(packet.data());
+ fullVersion = new ProtocolPacket::ProtocolVersion(
+ std::string(bson_object_get_string(&obj, "protocolVersion")));
+ bson_object_deinitialize(&obj);
+ // Constructed payloads added in Protocol v5
+ if (fullVersion->majorVersion < PROTOCOL_VERSION_5) {
+ rejectedParams.push_back(std::string("protocolVersion"));
+ }
+ } else {
+ fullVersion = new ProtocolPacket::ProtocolVersion();
+ }
+ if (!rejectedParams.empty()) {
+ SendStartSessionNAck(connection_id,
+ packet.session_id(),
+ protocol_version,
+ packet.service_type(),
+ rejectedParams);
+ } else if (ssl_context->IsInitCompleted()) {
// mark service as protected
session_observer_.SetProtectionFlag(connection_key, service_type);
// Start service as protected with current SSLContext
@@ -1130,7 +1398,8 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessageStartSession(
packet.protocol_version(),
hash_id,
packet.service_type(),
- PROTECTION_ON);
+ PROTECTION_ON,
+ *fullVersion);
} else {
security_manager_->AddListener(
new StartSessionHandler(connection_key,
@@ -1141,28 +1410,282 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessageStartSession(
packet.protocol_version(),
hash_id,
service_type,
- get_settings().force_protected_service()));
+ get_settings().force_protected_service(),
+ *fullVersion,
+ NULL));
if (!ssl_context->IsHandshakePending()) {
// Start handshake process
security_manager_->StartHandshake(connection_key);
}
}
+ delete fullVersion;
LOG4CXX_DEBUG(logger_,
"Protection establishing for connection "
<< connection_key << " is in progress");
return RESULT_OK;
}
#endif // ENABLE_SECURITY
- // Start service without protection
- SendStartSessionAck(connection_id,
- session_id,
- packet.protocol_version(),
- hash_id,
- packet.service_type(),
- PROTECTION_OFF);
+ if (packet.service_type() == kRpc && packet.data_size() != 0) {
+ BsonObject obj = bson_object_from_bytes(packet.data());
+ ProtocolPacket::ProtocolVersion fullVersion(
+ bson_object_get_string(&obj, "protocolVersion"));
+ bson_object_deinitialize(&obj);
+
+ if (fullVersion.majorVersion >= PROTOCOL_VERSION_5) {
+ // Start service without protection
+ SendStartSessionAck(connection_id,
+ session_id,
+ packet.protocol_version(),
+ hash_id,
+ packet.service_type(),
+ PROTECTION_OFF,
+ fullVersion);
+ } else {
+ std::vector<std::string> rejectedParams(1,
+ std::string("protocolVersion"));
+ SendStartSessionNAck(connection_id,
+ packet.session_id(),
+ protocol_version,
+ packet.service_type(),
+ rejectedParams);
+ }
+
+ } else {
+ // Start service without protection
+ SendStartSessionAck(connection_id,
+ session_id,
+ packet.protocol_version(),
+ hash_id,
+ packet.service_type(),
+ PROTECTION_OFF);
+ }
return RESULT_OK;
}
+RESULT_CODE ProtocolHandlerImpl::HandleControlMessageStartSession(
+ const ProtocolFramePtr packet) {
+ LOG4CXX_AUTO_TRACE(logger_);
+ LOG4CXX_DEBUG(
+ logger_,
+ "Protocol version:" << static_cast<int>(packet->protocol_version()));
+ const ServiceType service_type = ServiceTypeFromByte(packet->service_type());
+ const uint8_t protocol_version = packet->protocol_version();
+ BsonObject bson_obj;
+ if (packet->data() != NULL) {
+ bson_obj = bson_object_from_bytes(packet->data());
+ } else {
+ bson_object_initialize_default(&bson_obj);
+ }
+
+#ifdef ENABLE_SECURITY
+ const bool protection =
+ // Protocolo version 1 is not support protection
+ (protocol_version > PROTOCOL_VERSION_1) ? packet->protection_flag()
+ : false;
+#else
+ const bool protection = false;
+#endif // ENABLE_SECURITY
+
+ const ConnectionID connection_id = packet->connection_id();
+ const uint8_t session_id = packet->session_id();
+
+ {
+ sync_primitives::AutoLock auto_lock(start_session_frame_map_lock_);
+ start_session_frame_map_[std::make_pair(connection_id, session_id)] =
+ packet;
+ }
+
+ session_observer_.OnSessionStartedCallback(
+ connection_id, packet->session_id(), service_type, protection, &bson_obj);
+ bson_object_deinitialize(&bson_obj);
+
+ return RESULT_OK;
+}
+
+void ProtocolHandlerImpl::NotifySessionStartedResult(
+ int32_t connection_id,
+ uint8_t session_id,
+ uint8_t generated_session_id,
+ uint32_t hash_id,
+ bool protection,
+ std::vector<std::string>& rejected_params) {
+ ProtocolFramePtr packet;
+ {
+ sync_primitives::AutoLock auto_lock(start_session_frame_map_lock_);
+ StartSessionFrameMap::iterator it = start_session_frame_map_.find(
+ std::make_pair(connection_id, session_id));
+ if (it == start_session_frame_map_.end()) {
+ LOG4CXX_ERROR(logger_, "Cannot find Session Started packet");
+ return;
+ }
+ packet = it->second;
+ start_session_frame_map_.erase(it);
+ }
+
+ const ServiceType service_type = ServiceTypeFromByte(packet->service_type());
+ const uint8_t protocol_version = packet->protocol_version();
+
+ if (0 == generated_session_id) {
+ LOG4CXX_WARN(logger_,
+ "Refused by session_observer to create service "
+ << static_cast<int32_t>(service_type) << " type.");
+ SendStartSessionNAck(connection_id,
+ packet->session_id(),
+ protocol_version,
+ packet->service_type(),
+ rejected_params);
+ return;
+ }
+
+ BsonObject start_session_ack_params;
+ bson_object_initialize_default(&start_session_ack_params);
+ // when video service is successfully started, copy input parameters
+ // ("width", "height", "videoProtocol", "videoCodec") to the ACK packet
+ if (packet->service_type() == kMobileNav && packet->data() != NULL) {
+ BsonObject req_param = bson_object_from_bytes(packet->data());
+ BsonElement* element = NULL;
+
+ if ((element = bson_object_get(&req_param, strings::height)) != NULL &&
+ element->type == TYPE_INT32) {
+ bson_object_put_int32(&start_session_ack_params,
+ strings::height,
+ bson_object_get_int32(&req_param, strings::height));
+ }
+ if ((element = bson_object_get(&req_param, strings::width)) != NULL &&
+ element->type == TYPE_INT32) {
+ bson_object_put_int32(&start_session_ack_params,
+ strings::width,
+ bson_object_get_int32(&req_param, strings::width));
+ }
+ char* protocol =
+ bson_object_get_string(&req_param, strings::video_protocol);
+ if (protocol != NULL) {
+ bson_object_put_string(
+ &start_session_ack_params, strings::video_protocol, protocol);
+ }
+ char* codec = bson_object_get_string(&req_param, strings::video_codec);
+ if (codec != NULL) {
+ bson_object_put_string(
+ &start_session_ack_params, strings::video_codec, codec);
+ }
+ bson_object_deinitialize(&req_param);
+ }
+
+ ProtocolPacket::ProtocolVersion* fullVersion;
+
+ // Can't check protocol_version because the first packet is v1, but there
+ // could still be a payload, in which case we can get the real protocol
+ // version
+ if (packet->service_type() == kRpc && packet->data() != NULL) {
+ BsonObject request_params = bson_object_from_bytes(packet->data());
+ char* version_param =
+ bson_object_get_string(&request_params, strings::protocol_version);
+ std::string version_string(version_param == NULL ? "" : version_param);
+ fullVersion = new ProtocolPacket::ProtocolVersion(version_string);
+ // Constructed payloads added in Protocol v5
+ if (fullVersion->majorVersion < PROTOCOL_VERSION_5) {
+ rejected_params.push_back(std::string(strings::protocol_version));
+ }
+ bson_object_deinitialize(&request_params);
+ } else {
+ fullVersion = new ProtocolPacket::ProtocolVersion();
+ }
+
+#ifdef ENABLE_SECURITY
+ // for packet is encrypted and security plugin is enable
+ if (protection && security_manager_) {
+ const uint32_t connection_key =
+ session_observer_.KeyFromPair(connection_id, generated_session_id);
+
+ security_manager::SSLContext* ssl_context =
+ security_manager_->CreateSSLContext(connection_key);
+ if (!ssl_context) {
+ const std::string error("CreateSSLContext failed");
+ LOG4CXX_ERROR(logger_, error);
+ security_manager_->SendInternalError(
+ connection_key,
+ security_manager::SecurityManager::ERROR_INTERNAL,
+ error);
+ // Start service without protection
+ SendStartSessionAck(connection_id,
+ generated_session_id,
+ packet->protocol_version(),
+ hash_id,
+ packet->service_type(),
+ PROTECTION_OFF,
+ *fullVersion,
+ start_session_ack_params);
+ delete fullVersion;
+ bson_object_deinitialize(&start_session_ack_params);
+ return;
+ }
+
+ if (!rejected_params.empty()) {
+ SendStartSessionNAck(connection_id,
+ packet->session_id(),
+ protocol_version,
+ packet->service_type(),
+ rejected_params);
+ } else if (ssl_context->IsInitCompleted()) {
+ // mark service as protected
+ session_observer_.SetProtectionFlag(connection_key, service_type);
+ // Start service as protected with current SSLContext
+ SendStartSessionAck(connection_id,
+ generated_session_id,
+ packet->protocol_version(),
+ hash_id,
+ packet->service_type(),
+ PROTECTION_ON,
+ *fullVersion,
+ start_session_ack_params);
+ } else {
+ // Need a copy because fullVersion will be deleted
+ ProtocolPacket::ProtocolVersion fullVersionCopy(*fullVersion);
+ security_manager_->AddListener(new StartSessionHandler(
+ connection_key,
+ this,
+ session_observer_,
+ connection_id,
+ generated_session_id,
+ packet->protocol_version(),
+ hash_id,
+ service_type,
+ get_settings().force_protected_service(),
+ fullVersionCopy,
+ bson_object_to_bytes(&start_session_ack_params)));
+ if (!ssl_context->IsHandshakePending()) {
+ // Start handshake process
+ security_manager_->StartHandshake(connection_key);
+ }
+ }
+ delete fullVersion;
+ bson_object_deinitialize(&start_session_ack_params);
+ LOG4CXX_DEBUG(logger_,
+ "Protection establishing for connection "
+ << connection_key << " is in progress");
+ return;
+ }
+#endif // ENABLE_SECURITY
+ if (rejected_params.empty()) {
+ SendStartSessionAck(connection_id,
+ generated_session_id,
+ packet->protocol_version(),
+ hash_id,
+ packet->service_type(),
+ PROTECTION_OFF,
+ *fullVersion,
+ start_session_ack_params);
+ } else {
+ SendStartSessionNAck(connection_id,
+ packet->session_id(),
+ protocol_version,
+ packet->service_type(),
+ rejected_params);
+ }
+ delete fullVersion;
+ bson_object_deinitialize(&start_session_ack_params);
+}
+
RESULT_CODE ProtocolHandlerImpl::HandleControlMessageHeartBeat(
const ProtocolPacket& packet) {
const ConnectionID connection_id = packet.connection_id();
@@ -1173,8 +1696,8 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessageHeartBeat(
if (session_observer_.ProtocolVersionUsed(
connection_id, packet.session_id(), protocol_version)) {
// TODO(EZamakhov): investigate message_id for HeartBeatAck
- if (PROTOCOL_VERSION_3 == protocol_version ||
- PROTOCOL_VERSION_4 == protocol_version) {
+ if (protocol_version >= PROTOCOL_VERSION_3 &&
+ protocol_version <= PROTOCOL_VERSION_5) {
return SendHeartBeatAck(
connection_id, packet.session_id(), packet.message_id());
} else {
@@ -1329,6 +1852,9 @@ void ProtocolHandlerImpl::Handle(const impl::RawFordMessageToMobile message) {
void ProtocolHandlerImpl::Stop() {
raw_ford_messages_from_mobile_.Shutdown();
raw_ford_messages_to_mobile_.Shutdown();
+
+ sync_primitives::AutoLock auto_lock(start_session_frame_map_lock_);
+ start_session_frame_map_.clear();
}
#ifdef ENABLE_SECURITY
@@ -1444,33 +1970,34 @@ void ProtocolHandlerImpl::SendFramesNumber(uint32_t connection_key,
LOG4CXX_DEBUG(
logger_, "SendFramesNumber MobileNaviAck for session " << connection_key);
- // TODO(EZamakhov): add protocol version check - to avoid send for
- // PROTOCOL_VERSION_1
transport_manager::ConnectionUID connection_id = 0;
uint8_t session_id = 0;
session_observer_.PairFromKey(connection_key, &connection_id, &session_id);
uint8_t protocol_version;
if (session_observer_.ProtocolVersionUsed(
connection_id, session_id, protocol_version)) {
- ProtocolFramePtr ptr(
- new protocol_handler::ProtocolPacket(connection_id,
- protocol_version,
- PROTECTION_OFF,
- FRAME_TYPE_CONTROL,
- SERVICE_TYPE_NAVI,
- FRAME_DATA_SERVICE_DATA_ACK,
- session_id,
- 0,
- message_counters_[session_id]++));
-
- // Flow control data shall be 4 bytes according Ford Protocol
- DCHECK(sizeof(number_of_frames) == 4);
- number_of_frames = LE_TO_BE32(number_of_frames);
- ptr->set_data(reinterpret_cast<const uint8_t*>(&number_of_frames),
- sizeof(number_of_frames));
- raw_ford_messages_to_mobile_.PostMessage(
- impl::RawFordMessageToMobile(ptr, false));
- LOG4CXX_DEBUG(logger_, "SendFramesNumber finished successfully");
+ if (protocol_version > PROTOCOL_VERSION_1 &&
+ protocol_version < PROTOCOL_VERSION_5) {
+ ProtocolFramePtr ptr(new protocol_handler::ProtocolPacket(
+ connection_id,
+ protocol_version,
+ PROTECTION_OFF,
+ FRAME_TYPE_CONTROL,
+ SERVICE_TYPE_NAVI,
+ FRAME_DATA_SERVICE_DATA_ACK,
+ session_id,
+ 0,
+ message_counters_[session_id]++));
+
+ // Flow control data shall be 4 bytes according Ford Protocol
+ DCHECK(sizeof(number_of_frames) == 4);
+ number_of_frames = LE_TO_BE32(number_of_frames);
+ ptr->set_data(reinterpret_cast<const uint8_t*>(&number_of_frames),
+ sizeof(number_of_frames));
+ raw_ford_messages_to_mobile_.PostMessage(
+ impl::RawFordMessageToMobile(ptr, false));
+ LOG4CXX_DEBUG(logger_, "SendFramesNumber finished successfully");
+ }
} else {
LOG4CXX_WARN(
logger_,
@@ -1504,17 +2031,6 @@ std::string ConvertPacketDataToString(const uint8_t* data,
uint8_t ProtocolHandlerImpl::SupportedSDLProtocolVersion() const {
LOG4CXX_AUTO_TRACE(logger_);
-
- bool heart_beat_support = (0 != get_settings().heart_beat_timeout());
-
- bool sdl4_support = get_settings().enable_protocol_4();
-
- if (sdl4_support) {
- return PROTOCOL_VERSION_4;
- }
- if (heart_beat_support) {
- return PROTOCOL_VERSION_3;
- }
- return PROTOCOL_VERSION_2;
+ return get_settings().max_supported_protocol_version();
}
} // namespace protocol_handler