diff options
Diffstat (limited to 'src/components/protocol_handler/src/protocol_handler_impl.cc')
-rw-r--r-- | src/components/protocol_handler/src/protocol_handler_impl.cc | 644 |
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( + ¶ms, + 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( + ¶ms, 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( + ¶ms, strings::protocol_version, protocolVersionString); + } + uint8_t* payloadBytes = bson_object_to_bytes(¶ms); + ptr->set_data(payloadBytes, bson_object_size(¶ms)); + 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(¶ms); + } protocol_handler_->SendStartSessionAck(connection_id_, session_id_, protocol_version_, hash_id_, service_type_, - success); + success, + full_version_, + params); + bson_object_deinitialize(¶ms); } + 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 |