diff options
Diffstat (limited to 'src/components/protocol_handler')
4 files changed, 238 insertions, 65 deletions
diff --git a/src/components/protocol_handler/CMakeLists.txt b/src/components/protocol_handler/CMakeLists.txt index ff8678b826..ed3aaaf24c 100644 --- a/src/components/protocol_handler/CMakeLists.txt +++ b/src/components/protocol_handler/CMakeLists.txt @@ -65,6 +65,7 @@ endforeach() add_library(ProtocolHandler ${SOURCES}) +add_dependencies(ProtocolHandler libbson) target_link_libraries(ProtocolHandler ${LIBRARIES}) if(BUILD_TESTS) diff --git a/src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h b/src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h index 3e7d64e9d2..7c2b411dcb 100644 --- a/src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h +++ b/src/components/protocol_handler/include/protocol_handler/protocol_handler_impl.h @@ -141,7 +141,8 @@ typedef enum { TT_NONE = -1, TT_USB = 0, TT_BLUETOOTH = 1, - TT_WIFI = 2 + TT_WIFI = 2, + TT_WEBSOCKET = 3 } TransportType; struct TransportDescription { @@ -428,6 +429,9 @@ class ProtocolHandlerImpl void NotifySessionStarted(const SessionContext& context, std::vector<std::string>& rejected_params) OVERRIDE; + void OnAuthTokenUpdated(const std::string& policy_app_id, + const std::string& auth_token) OVERRIDE; + #ifdef BUILD_TESTS const impl::FromMobileQueue& get_from_mobile_queue() const { return raw_ford_messages_from_mobile_; @@ -512,6 +516,10 @@ class ProtocolHandlerImpl void OnTMMessageSendFailed(const transport_manager::DataSendError& error, const RawMessagePtr message) OVERRIDE; + void OnConnectionPending( + const transport_manager::DeviceInfo& device_info, + const transport_manager::ConnectionUID connection_id) OVERRIDE; + void OnConnectionEstablished( const transport_manager::DeviceInfo& device_info, const transport_manager::ConnectionUID connection_id) OVERRIDE; @@ -773,6 +781,10 @@ class ProtocolHandlerImpl sync_primitives::Lock start_session_frame_map_lock_; StartSessionFrameMap start_session_frame_map_; + // Map policy app id -> auth token + sync_primitives::Lock auth_token_map_lock_; + std::map<std::string, std::string> auth_token_map_; + bool tcp_enabled_; std::string tcp_port_; std::string tcp_ip_address_; diff --git a/src/components/protocol_handler/src/protocol_handler_impl.cc b/src/components/protocol_handler/src/protocol_handler_impl.cc index d03030b747..944d80d5d9 100644 --- a/src/components/protocol_handler/src/protocol_handler_impl.cc +++ b/src/components/protocol_handler/src/protocol_handler_impl.cc @@ -59,10 +59,11 @@ CREATE_LOGGERPTR_GLOBAL(logger_, "ProtocolHandler") std::string ConvertPacketDataToString(const uint8_t* data, const size_t data_size); -const size_t kStackSize = 65536; +const size_t kStackSize = 131072; -utils::SemanticVersion defaultProtocolVersion(5, 1, 0); -utils::SemanticVersion minMultipleTransportsVersion(5, 1, 0); +utils::SemanticVersion default_protocol_version(5, 2, 0); +utils::SemanticVersion min_multiple_transports_version(5, 1, 0); +utils::SemanticVersion min_cloud_app_version(5, 2, 0); ProtocolHandlerImpl::ProtocolHandlerImpl( const ProtocolHandlerSettings& settings, @@ -309,16 +310,16 @@ void ProtocolHandlerImpl::SendStartSessionAck( ¶ms, strings::hash_id))); // Minimum protocol version supported by both - utils::SemanticVersion* minVersion = + utils::SemanticVersion* min_version = (full_version.major_version_ < PROTOCOL_VERSION_5) - ? &defaultProtocolVersion + ? &default_protocol_version : utils::SemanticVersion::min(full_version, - defaultProtocolVersion); - char protocolVersionString[256]; - strncpy(protocolVersionString, (*minVersion).toString().c_str(), 255); + default_protocol_version); + char protocol_version_string[256]; + strncpy(protocol_version_string, (*min_version).toString().c_str(), 255); const bool protocol_ver_written = bson_object_put_string( - ¶ms, strings::protocol_version, protocolVersionString); + ¶ms, strings::protocol_version, protocol_version_string); UNUSED(protocol_ver_written); LOG4CXX_DEBUG( logger_, @@ -327,12 +328,12 @@ void ProtocolHandlerImpl::SendStartSessionAck( << bson_object_get_string(¶ms, strings::protocol_version)); LOG4CXX_INFO(logger_, - "Protocol Version String " << protocolVersionString); + "Protocol Version String " << protocol_version_string); std::vector<std::string> secondaryTransports; std::vector<int32_t> audioServiceTransports; std::vector<int32_t> videoServiceTransports; - if (*minVersion >= minMultipleTransportsVersion) { + if (*min_version >= min_multiple_transports_version) { if (ParseSecondaryTransportConfiguration(connection_id, secondaryTransports, audioServiceTransports, @@ -410,10 +411,23 @@ void ProtocolHandlerImpl::SendStartSessionAck( connection_handler_.SetSecondaryTransportID(session_id, kDisabledSecondary); } + + std::string policy_app_id = + connection_handler_.GetCloudAppID(connection_id); + if (*min_version >= min_cloud_app_version && !policy_app_id.empty()) { + sync_primitives::AutoLock lock(auth_token_map_lock_); + auto it = auth_token_map_.find(policy_app_id); + if (it != auth_token_map_.end()) { + char auth_token[65536]; + strncpy(auth_token, it->second.c_str(), 65535); + auth_token[sizeof(auth_token) - 1] = '\0'; + bson_object_put_string(¶ms, strings::auth_token, auth_token); + } + } } - uint8_t* payloadBytes = bson_object_to_bytes(¶ms); - ptr->set_data(payloadBytes, bson_object_size(¶ms)); - free(payloadBytes); + uint8_t* payload_bytes = bson_object_to_bytes(¶ms); + ptr->set_data(payload_bytes, bson_object_size(¶ms)); + free(payload_bytes); } else { set_hash_id(hash_id, *ptr); } @@ -1087,6 +1101,10 @@ void ProtocolHandlerImpl::OnTMMessageSendFailed( << "Error_text: " << error.text()); } +void ProtocolHandlerImpl::OnConnectionPending( + const transport_manager::DeviceInfo& device_info, + const transport_manager::ConnectionUID connection_id) {} + void ProtocolHandlerImpl::OnConnectionEstablished( const transport_manager::DeviceInfo& device_info, const transport_manager::ConnectionUID connection_id) { @@ -1181,6 +1199,17 @@ void ProtocolHandlerImpl::OnTransportConfigUpdated( } } +void ProtocolHandlerImpl::OnAuthTokenUpdated(const std::string& policy_app_id, + const std::string& auth_token) { + LOG4CXX_AUTO_TRACE(logger_); + sync_primitives::AutoLock lock(auth_token_map_lock_); + if (auth_token.empty()) { + auth_token_map_.erase(policy_app_id); + } else { + auth_token_map_[policy_app_id] = auth_token; + } +} + RESULT_CODE ProtocolHandlerImpl::SendFrame(const ProtocolFramePtr packet) { LOG4CXX_AUTO_TRACE(logger_); if (!packet) { @@ -1681,13 +1710,12 @@ void ProtocolHandlerImpl::NotifySessionStarted( start_session_frame_map_.erase(it); } - const ServiceType service_type = ServiceTypeFromByte(packet->service_type()); const uint8_t protocol_version = packet->protocol_version(); if (0 == context.new_session_id_) { LOG4CXX_WARN(logger_, "Refused by session_observer to create service " - << static_cast<int32_t>(service_type) << " type."); + << packet->service_type() << " type."); SendStartSessionNAck(context.connection_id_, packet->session_id(), protocol_version, @@ -1752,6 +1780,7 @@ void ProtocolHandlerImpl::NotifySessionStarted( } #ifdef ENABLE_SECURITY + const ServiceType service_type = ServiceTypeFromByte(packet->service_type()); // for packet is encrypted and security plugin is enable if (context.is_protected_ && security_manager_) { const uint32_t connection_key = session_observer_.KeyFromPair( @@ -2245,7 +2274,10 @@ const impl::TransportTypes transportTypes = { impl::TransportDescription(impl::TransportType::TT_USB, true, false)), std::make_pair( std::string("IAP_CARPLAY"), - impl::TransportDescription(impl::TransportType::TT_WIFI, true, false))}; + impl::TransportDescription(impl::TransportType::TT_WIFI, true, false)), + std::make_pair(std::string("WEBSOCKET"), + impl::TransportDescription( + impl::TransportType::TT_WEBSOCKET, false, false))}; const impl::TransportDescription ProtocolHandlerImpl::GetTransportTypeFromConnectionType( diff --git a/src/components/protocol_handler/test/protocol_handler_tm_test.cc b/src/components/protocol_handler/test/protocol_handler_tm_test.cc index 51284dfcda..e1149fefb2 100644 --- a/src/components/protocol_handler/test/protocol_handler_tm_test.cc +++ b/src/components/protocol_handler/test/protocol_handler_tm_test.cc @@ -29,19 +29,19 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#include "gtest/gtest.h" #include <string> -#include "protocol_handler/protocol_handler.h" -#include "protocol_handler/protocol_handler_impl.h" +#include "connection_handler/connection_handler_impl.h" +#include "connection_handler/mock_connection_handler.h" +#include "gtest/gtest.h" #include "protocol/bson_object_keys.h" #include "protocol/common.h" #include "protocol_handler/control_message_matcher.h" #include "protocol_handler/mock_protocol_handler.h" -#include "protocol_handler/mock_protocol_observer.h" #include "protocol_handler/mock_protocol_handler_settings.h" +#include "protocol_handler/mock_protocol_observer.h" #include "protocol_handler/mock_session_observer.h" -#include "connection_handler/mock_connection_handler.h" -#include "connection_handler/connection_handler_impl.h" +#include "protocol_handler/protocol_handler.h" +#include "protocol_handler/protocol_handler_impl.h" #ifdef ENABLE_SECURITY #include "security_manager/mock_security_manager.h" #include "security_manager/mock_ssl_context.h" @@ -50,8 +50,8 @@ #include "utils/mock_system_time_handler.h" #include "utils/semantic_version.h" -#include "utils/test_async_waiter.h" #include <bson_object.h> +#include "utils/test_async_waiter.h" namespace transport_manager { namespace transport_adapter { @@ -59,8 +59,8 @@ namespace transport_adapter { const char* tc_enabled = "enabled"; const char* tc_tcp_port = "tcp_port"; const char* tc_tcp_ip_address = "tcp_ip_address"; -} -} +} // namespace transport_adapter +} // namespace transport_manager namespace test { namespace components { @@ -70,50 +70,50 @@ namespace protocol_handler_test { #define NEW_SESSION_ID 0u #define SESSION_START_REJECT 0u // Protocol Handler Entities -using protocol_handler::ProtocolHandlerImpl; -using protocol_handler::ServiceType; -using protocol_handler::RawMessage; -using protocol_handler::RawMessagePtr; -using protocol_handler::PROTECTION_ON; -using protocol_handler::PROTECTION_OFF; -using protocol_handler::PROTOCOL_VERSION_1; -using protocol_handler::PROTOCOL_VERSION_2; -using protocol_handler::PROTOCOL_VERSION_3; -using protocol_handler::PROTOCOL_VERSION_4; -using protocol_handler::PROTOCOL_VERSION_5; -using protocol_handler::PROTOCOL_VERSION_MAX; -using protocol_handler::FRAME_TYPE_CONTROL; -using protocol_handler::FRAME_TYPE_SINGLE; -using protocol_handler::FRAME_TYPE_FIRST; -using protocol_handler::FRAME_TYPE_CONSECUTIVE; -using protocol_handler::FRAME_TYPE_MAX_VALUE; -using protocol_handler::MAXIMUM_FRAME_DATA_V2_SIZE; -using protocol_handler::FRAME_DATA_START_SERVICE; -using protocol_handler::FRAME_DATA_START_SERVICE_ACK; -using protocol_handler::FRAME_DATA_END_SERVICE_NACK; -using protocol_handler::FRAME_DATA_END_SERVICE_ACK; using protocol_handler::FRAME_DATA_END_SERVICE; +using protocol_handler::FRAME_DATA_END_SERVICE_ACK; +using protocol_handler::FRAME_DATA_END_SERVICE_NACK; +using protocol_handler::FRAME_DATA_FIRST; using protocol_handler::FRAME_DATA_HEART_BEAT; using protocol_handler::FRAME_DATA_HEART_BEAT_ACK; -using protocol_handler::FRAME_DATA_SERVICE_DATA_ACK; -using protocol_handler::FRAME_DATA_SINGLE; -using protocol_handler::FRAME_DATA_FIRST; using protocol_handler::FRAME_DATA_LAST_CONSECUTIVE; using protocol_handler::FRAME_DATA_REGISTER_SECONDARY_TRANSPORT; using protocol_handler::FRAME_DATA_REGISTER_SECONDARY_TRANSPORT_ACK; using protocol_handler::FRAME_DATA_REGISTER_SECONDARY_TRANSPORT_NACK; +using protocol_handler::FRAME_DATA_SERVICE_DATA_ACK; +using protocol_handler::FRAME_DATA_SINGLE; +using protocol_handler::FRAME_DATA_START_SERVICE; +using protocol_handler::FRAME_DATA_START_SERVICE_ACK; using protocol_handler::FRAME_DATA_TRANSPORT_EVENT_UPDATE; -using protocol_handler::kRpc; -using protocol_handler::kControl; +using protocol_handler::FRAME_TYPE_CONSECUTIVE; +using protocol_handler::FRAME_TYPE_CONTROL; +using protocol_handler::FRAME_TYPE_FIRST; +using protocol_handler::FRAME_TYPE_MAX_VALUE; +using protocol_handler::FRAME_TYPE_SINGLE; using protocol_handler::kAudio; -using protocol_handler::kMobileNav; using protocol_handler::kBulk; +using protocol_handler::kControl; using protocol_handler::kInvalidServiceType; +using protocol_handler::kMobileNav; +using protocol_handler::kRpc; +using protocol_handler::MAXIMUM_FRAME_DATA_V2_SIZE; +using protocol_handler::PROTECTION_OFF; +using protocol_handler::PROTECTION_ON; +using protocol_handler::PROTOCOL_VERSION_1; +using protocol_handler::PROTOCOL_VERSION_2; +using protocol_handler::PROTOCOL_VERSION_3; +using protocol_handler::PROTOCOL_VERSION_4; +using protocol_handler::PROTOCOL_VERSION_5; +using protocol_handler::PROTOCOL_VERSION_MAX; +using protocol_handler::ProtocolHandlerImpl; +using protocol_handler::RawMessage; +using protocol_handler::RawMessagePtr; +using protocol_handler::ServiceType; // For TM states -using transport_manager::TransportManagerListener; using test::components::security_manager_test::MockSystemTimeHandler; -using transport_manager::E_SUCCESS; using transport_manager::DeviceInfo; +using transport_manager::E_SUCCESS; +using transport_manager::TransportManagerListener; #ifdef ENABLE_SECURITY // For security using ContextCreationStrategy = @@ -122,21 +122,21 @@ using ContextCreationStrategy = // For CH entities using connection_handler::DeviceHandle; // Google Testing Framework Entities -using ::testing::Return; -using ::testing::ReturnRef; -using ::testing::ReturnRefOfCopy; -using ::testing::ReturnNull; +using ::testing::_; using ::testing::An; using ::testing::AnyOf; using ::testing::AtLeast; using ::testing::ByRef; using ::testing::DoAll; -using ::testing::SaveArg; using ::testing::Eq; -using ::testing::_; using ::testing::Invoke; -using ::testing::SetArgReferee; +using ::testing::Return; +using ::testing::ReturnNull; +using ::testing::ReturnRef; +using ::testing::ReturnRefOfCopy; +using ::testing::SaveArg; using ::testing::SetArgPointee; +using ::testing::SetArgReferee; typedef std::vector<uint8_t> UCharDataVector; @@ -149,7 +149,7 @@ namespace { const uint32_t kAsyncExpectationsTimeout = 10000u; const uint32_t kMicrosecondsInMillisecond = 1000u; const uint32_t kAddSessionWaitTimeMs = 100u; -} +} // namespace class ProtocolHandlerImplTest : public ::testing::Test { protected: @@ -383,6 +383,9 @@ class ProtocolHandlerImplTest : public ::testing::Test { const std::vector<int32_t>& expected_audio_service_transports, const std::vector<int32_t>& expected_video_service_transports); + void VerifyCloudAppParamsInStartSessionAck(const std::string& policy_app_id, + char* auth_token); + testing::NiceMock<MockProtocolHandlerSettings> protocol_handler_settings_mock; std::shared_ptr<ProtocolHandlerImpl> protocol_handler_impl; TransportManagerListener* tm_listener; @@ -1920,6 +1923,117 @@ void ProtocolHandlerImplTest::VerifySecondaryTransportParamsInStartSessionAck( bson_object_deinitialize(&expected_obj); + EXPECT_CALL( + transport_manager_mock, + SendMessageToDevice(ControlMessage( + FRAME_DATA_START_SERVICE_ACK, PROTECTION_OFF, connection_id, _))) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; + +#ifdef ENABLE_SECURITY + AddSecurityManager(); + + EXPECT_CALL(session_observer_mock, KeyFromPair(connection_id, session_id)) + .WillOnce(Return(connection_key)); + + EXPECT_CALL(session_observer_mock, GetSSLContext(connection_key, kRpc)) + .WillOnce(ReturnNull()); +#endif // ENABLE_SECURITY + + protocol_handler_impl->SendStartSessionAck(connection_id, + session_id, + input_protocol_version, + hash_id, + protocol_handler::SERVICE_TYPE_RPC, + false /* protection */, + full_version); + + EXPECT_TRUE(waiter.WaitFor(times, kAsyncExpectationsTimeout)); +} + +void ProtocolHandlerImplTest::VerifyCloudAppParamsInStartSessionAck( + const std::string& policy_app_id, char* auth_token) { + const size_t maximum_rpc_payload_size = 1500; + EXPECT_CALL(protocol_handler_settings_mock, maximum_rpc_payload_size()) + .WillRepeatedly(Return(maximum_rpc_payload_size)); + InitProtocolHandlerImpl(0u, 0u); + + TestAsyncWaiter waiter; + uint32_t times = 0; + + const uint8_t input_protocol_version = 5; + const uint32_t hash_id = 123456; + utils::SemanticVersion full_version(5, 2, 0); + char full_version_string[] = "5.2.0"; + + // configuration setup + EXPECT_CALL(protocol_handler_settings_mock, max_supported_protocol_version()) + .WillRepeatedly(Return(PROTOCOL_VERSION_5)); + EXPECT_CALL(connection_handler_mock, GetCloudAppID(connection_id)) + .WillOnce(Return(policy_app_id)); + connection_handler::SessionTransports dummy_st = {0, 0}; + EXPECT_CALL(connection_handler_mock, + SetSecondaryTransportID(_, kDisabledSecondary)) + .WillOnce(Return(dummy_st)); + EXPECT_CALL(protocol_handler_settings_mock, multiple_transports_enabled()) + .WillRepeatedly(Return(false)); + std::vector<std::string> empty_vec; + EXPECT_CALL(protocol_handler_settings_mock, audio_service_transports()) + .WillRepeatedly(ReturnRef(empty_vec)); + EXPECT_CALL(protocol_handler_settings_mock, video_service_transports()) + .WillRepeatedly(ReturnRef(empty_vec)); + EXPECT_CALL(session_observer_mock, + TransportTypeProfileStringFromConnHandle(connection_id)) + .WillRepeatedly(Return("WEBSOCKET")); + + // Prepare expected BSON parameters. When we add another param in Start + // Service ACK frame in future, it should be also added here. + BsonObject expected_obj; + bson_object_initialize_default(&expected_obj); + + // mtu + bson_object_put_int64(&expected_obj, + protocol_handler::strings::mtu, + static_cast<int64_t>(maximum_rpc_payload_size)); + // hashId + bson_object_put_int32(&expected_obj, + protocol_handler::strings::hash_id, + static_cast<int32_t>(hash_id)); + // protocolVersion + bson_object_put_string(&expected_obj, + protocol_handler::strings::protocol_version, + full_version_string); + + // secondaryTransports + BsonArray secondary_transports; + bson_array_initialize(&secondary_transports, 0); + bson_object_put_array(&expected_obj, + protocol_handler::strings::secondary_transports, + &secondary_transports); + + BsonArray audio_service_transports; + bson_array_initialize(&audio_service_transports, 1); + bson_array_add_int32(&audio_service_transports, 1); + bson_object_put_array(&expected_obj, + protocol_handler::strings::audio_service_transports, + &audio_service_transports); + + BsonArray video_service_transports; + bson_array_initialize(&video_service_transports, 1); + bson_array_add_int32(&video_service_transports, 1); + bson_object_put_array(&expected_obj, + protocol_handler::strings::video_service_transports, + &video_service_transports); + + // authToken + bson_object_put_string( + &expected_obj, protocol_handler::strings::auth_token, auth_token); + + std::vector<uint8_t> expected_param = + CreateVectorFromBsonObject(&expected_obj); + + bson_object_deinitialize(&expected_obj); + EXPECT_CALL(transport_manager_mock, SendMessageToDevice(ControlMessage(FRAME_DATA_START_SERVICE_ACK, PROTECTION_OFF, @@ -1938,6 +2052,8 @@ void ProtocolHandlerImplTest::VerifySecondaryTransportParamsInStartSessionAck( .WillOnce(ReturnNull()); #endif // ENABLE_SECURITY + protocol_handler_impl->OnAuthTokenUpdated(policy_app_id, + std::string(auth_token)); protocol_handler_impl->SendStartSessionAck(connection_id, session_id, input_protocol_version, @@ -2468,6 +2584,18 @@ TEST_F(ProtocolHandlerImplTest, StartSessionAck_PrimaryTransportUSBHostMode) { expected_video_service_transports); } +TEST_F(ProtocolHandlerImplTest, StartSessionAck_CloudAppAuthTokenAvailable) { + std::string policy_id = "policy_id"; + char auth_token[] = "Sample auth token"; + + // A TransportUpdateEvent is also issued after Start Service ACK. We don't + // check it in this test case. + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly(Return(false)); + + VerifyCloudAppParamsInStartSessionAck(policy_id, auth_token); +} + TEST_F(ProtocolHandlerImplTest, TransportEventUpdate_afterVersionNegotiation_TCPEnabled) { TestAsyncWaiter waiter; |