diff options
author | Conlain Kelly <conlain.k@gmail.com> | 2018-08-10 11:04:43 -0400 |
---|---|---|
committer | Conlain Kelly <conlain.k@gmail.com> | 2018-08-10 11:04:43 -0400 |
commit | 72a64f7419d20bc379d1e050fdaac90b2a6d097f (patch) | |
tree | f5be0f57b4699b2fd30a459c105cfb44c6903508 /src/components/protocol_handler | |
parent | 3b5ddfdacb94f4e3f5752bb7165ca668f62f4a5d (diff) | |
parent | 43e53192045daeff8e9e2887c8b67894725240b5 (diff) | |
download | sdl_core-72a64f7419d20bc379d1e050fdaac90b2a6d097f.tar.gz |
Merge branch 'develop' of https://github.com/smartdevicelink/sdl_core into feature/boost_datetime_implementation
Diffstat (limited to 'src/components/protocol_handler')
11 files changed, 2201 insertions, 307 deletions
diff --git a/src/components/protocol_handler/CMakeLists.txt b/src/components/protocol_handler/CMakeLists.txt index ed3aaaf24c..ff8678b826 100644 --- a/src/components/protocol_handler/CMakeLists.txt +++ b/src/components/protocol_handler/CMakeLists.txt @@ -65,7 +65,6 @@ 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 99f03b1c04..58877ac611 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 @@ -42,8 +42,9 @@ #include "utils/prioritized_queue.h" #include "utils/message_queue.h" #include "utils/threads/message_loop_thread.h" -#include "utils/shared_ptr.h" + #include "utils/messagemeter.h" +#include "utils/custom_string.h" #include "protocol_handler/protocol_handler.h" #include "protocol_handler/protocol_packet.h" @@ -55,6 +56,7 @@ #include "transport_manager/common.h" #include "transport_manager/transport_manager.h" #include "transport_manager/transport_manager_listener_empty.h" +#include "transport_manager/transport_adapter/transport_adapter.h" #include "connection_handler/connection_handler.h" #include "application_manager/policies/policy_handler_observer.h" @@ -131,6 +133,30 @@ typedef threads::MessageLoopThread< utils::PrioritizedQueue<RawFordMessageFromMobile> > FromMobileQueue; typedef threads::MessageLoopThread< utils::PrioritizedQueue<RawFordMessageToMobile> > ToMobileQueue; + +// Type to allow easy mapping between a device type and transport +// characteristics +typedef enum { + TT_NONE = -1, + TT_USB = 0, + TT_BLUETOOTH = 1, + TT_WIFI = 2 +} TransportType; + +struct TransportDescription { + TransportDescription(const TransportType transport_type, + const bool ios_transport, + const bool android_transport) + : transport_type_(transport_type) + , ios_transport_(ios_transport) + , android_transport_(android_transport) {} + + TransportType transport_type_; + bool ios_transport_; + bool android_transport_; +}; + +typedef std::map<std::string, TransportDescription> TransportTypes; } // namespace impl /** @@ -231,7 +257,15 @@ class ProtocolHandlerImpl */ void SendEndSession(int32_t connection_id, uint8_t session_id); - void SendEndService(int32_t connection_id, + /** + * \brief Sends ending session to mobile application + * \param primary_connection_id Identifier of connection within which + * service exists + * \param connection_id Identifier of the actual transport for the service + * \param session_id ID of session to be ended + */ + void SendEndService(int32_t primary_connection_id, + int32_t connection_id, uint8_t session_id, uint8_t service_type); @@ -422,10 +456,19 @@ class ProtocolHandlerImpl const impl::ToMobileQueue& get_to_mobile_queue() const { return raw_ford_messages_to_mobile_; } + + void set_tcp_config(bool tcp_enabled, + std::string tcp_address, + std::string tcp_port) { + tcp_enabled_ = tcp_enabled; + tcp_ip_address_ = tcp_address; + tcp_port_ = tcp_port; + } #endif private: - void SendEndServicePrivate(int32_t connection_id, + void SendEndServicePrivate(int32_t primary_connection_id, + int32_t connection_id, uint8_t session_id, uint8_t service_type); @@ -436,6 +479,28 @@ class ProtocolHandlerImpl uint8_t session_id, uint32_t message_id); + /* + * Prepare and send TransportUpdateEvent message + */ + void SendTransportUpdateEvent(ConnectionID connection_id, uint8_t session_id); + + /* + * Prepare and send RegisterSecondaryTransportAck message + */ + RESULT_CODE SendRegisterSecondaryTransportAck( + ConnectionID connection_id, + ConnectionID primary_transport_connection_id, + uint8_t session_id); + + /* + * Prepare and send RegisterSecondaryTransportNAck message + */ + RESULT_CODE SendRegisterSecondaryTransportNAck( + ConnectionID connection_id, + ConnectionID primary_transport_connection_id, + uint8_t session_id, + BsonObject* reason = NULL); + /** * @brief Notifies about receiving message from TM. * @@ -474,6 +539,19 @@ class ProtocolHandlerImpl void OnConnectionClosed( const transport_manager::ConnectionUID connection_id) OVERRIDE; + void OnUnexpectedDisconnect( + const transport_manager::ConnectionUID connection_id, + const transport_manager::CommunicationError& error) OVERRIDE; + + /** + * @brief Notifies that configuration of a transport has been updated. + * + * @param configs pairs of key and value that represent configuration. + */ + void OnTransportConfigUpdated( + const transport_manager::transport_adapter::TransportConfig& configs) + OVERRIDE; + /** * @brief Notifies subscribers about message * received from mobile device. @@ -575,6 +653,9 @@ class ProtocolHandlerImpl RESULT_CODE HandleControlMessageStartSession(const ProtocolFramePtr packet); + RESULT_CODE HandleControlMessageRegisterSecondaryTransport( + const ProtocolFramePtr packet); + RESULT_CODE HandleControlMessageHeartBeat(const ProtocolPacket& packet); void PopValideAndExpirateMultiframes(); @@ -603,6 +684,32 @@ class ProtocolHandlerImpl */ uint8_t SupportedSDLProtocolVersion() const; + const impl::TransportDescription GetTransportTypeFromConnectionType( + const std::string& device_type) const; + + const bool ParseSecondaryTransportConfiguration( + const ConnectionID connection_id, + std::vector<std::string>& secondaryTransports, + std::vector<int32_t>& audioServiceTransports, + std::vector<int32_t>& videoServiceTransports) const; + + void GenerateSecondaryTransportsForStartSessionAck( + const std::vector<std::string>& secondary_transport_types, + bool device_is_ios, + bool device_is_android, + std::vector<std::string>& secondaryTransports) const; + + void GenerateServiceTransportsForStartSessionAck( + bool secondary_enabled, + const std::vector<std::string>& service_transports, + const std::string& primary_connection_type, + const impl::TransportType primary_transport_type, + const std::vector<std::string>& secondary_transport_types, + std::vector<int32_t>& serviceTransports) const; + + const std::string TransportTypeFromTransport( + const utils::custom_string::CustomString& transport) const; + const ProtocolHandlerSettings& settings_; /** @@ -689,6 +796,10 @@ class ProtocolHandlerImpl sync_primitives::Lock start_session_frame_map_lock_; StartSessionFrameMap start_session_frame_map_; + bool tcp_enabled_; + std::string tcp_port_; + std::string tcp_ip_address_; + #ifdef TELEMETRY_MONITOR PHTelemetryObserver* metric_observer_; #endif // TELEMETRY_MONITOR diff --git a/src/components/protocol_handler/include/protocol_handler/protocol_packet.h b/src/components/protocol_handler/include/protocol_handler/protocol_packet.h index b6c05d4c46..ff084beff8 100644 --- a/src/components/protocol_handler/include/protocol_handler/protocol_packet.h +++ b/src/components/protocol_handler/include/protocol_handler/protocol_packet.h @@ -332,6 +332,11 @@ class ProtocolPacket { ConnectionID connection_id() const; /** + * \brief Setter of Connection Identifier + */ + void set_connection_id(ConnectionID connection_id); + + /** * \brief Getter for data payload size */ uint32_t payload_size() const; @@ -370,7 +375,7 @@ class ProtocolPacket { * @brief Type definition for variable that hold shared pointer to protocolol * packet */ -typedef utils::SharedPtr<protocol_handler::ProtocolPacket> ProtocolFramePtr; +typedef std::shared_ptr<protocol_handler::ProtocolPacket> ProtocolFramePtr; typedef std::list<ProtocolFramePtr> ProtocolFramePtrList; template <typename _CharT> diff --git a/src/components/protocol_handler/src/multiframe_builder.cc b/src/components/protocol_handler/src/multiframe_builder.cc index 487d1f8d73..c34e2ec640 100644 --- a/src/components/protocol_handler/src/multiframe_builder.cc +++ b/src/components/protocol_handler/src/multiframe_builder.cc @@ -35,7 +35,7 @@ #include <limits> #include "utils/logger.h" -#include "utils/make_shared.h" + #include "utils/lock.h" #include "utils/date_time.h" diff --git a/src/components/protocol_handler/src/protocol_handler_impl.cc b/src/components/protocol_handler/src/protocol_handler_impl.cc index ee94f2f39b..b4b66f47be 100644 --- a/src/components/protocol_handler/src/protocol_handler_impl.cc +++ b/src/components/protocol_handler/src/protocol_handler_impl.cc @@ -31,6 +31,7 @@ */ #include "protocol_handler/protocol_handler_impl.h" +#include <arpa/inet.h> // for INET6_ADDRSTRLEN #include <memory.h> #include <algorithm> // std::find #include <bson_object.h> @@ -60,7 +61,8 @@ std::string ConvertPacketDataToString(const uint8_t* data, const size_t kStackSize = 65536; -ProtocolPacket::ProtocolVersion defaultProtocolVersion(5, 0, 0); +ProtocolPacket::ProtocolVersion defaultProtocolVersion(5, 1, 0); +ProtocolPacket::ProtocolVersion minMultipleTransportsVersion(5, 1, 0); ProtocolHandlerImpl::ProtocolHandlerImpl( const ProtocolHandlerSettings& settings, @@ -84,6 +86,7 @@ ProtocolHandlerImpl::ProtocolHandlerImpl( "PH ToMobile", this, threads::ThreadOptions(kStackSize)) , start_session_frame_map_lock_() , start_session_frame_map_() + , tcp_enabled_(false) #ifdef TELEMETRY_MONITOR , metric_observer_(NULL) #endif // TELEMETRY_MONITOR @@ -242,6 +245,8 @@ void ProtocolHandlerImpl::SendStartSessionAck( BsonObject& params) { LOG4CXX_AUTO_TRACE(logger_); + bool send_transport_update_event = false; + uint8_t ack_protocol_version = SupportedSDLProtocolVersion(); const bool proxy_supports_v5_protocol = @@ -317,6 +322,91 @@ void ProtocolHandlerImpl::SendStartSessionAck( "Protocol version parameter was written to bson params: " << protocol_ver_written << "; Value: " << bson_object_get_string(¶ms, strings::protocol_version)); + + LOG4CXX_INFO(logger_, + "Protocol Version String " << protocolVersionString); + + std::vector<std::string> secondaryTransports; + std::vector<int32_t> audioServiceTransports; + std::vector<int32_t> videoServiceTransports; + if (*minVersion >= minMultipleTransportsVersion) { + if (ParseSecondaryTransportConfiguration(connection_id, + secondaryTransports, + audioServiceTransports, + videoServiceTransports)) { + LOG4CXX_DEBUG(logger_, "Multiple transports are enabled."); + BsonArray secondaryTransportsArr; + bson_array_initialize(&secondaryTransportsArr, + secondaryTransports.size()); + for (unsigned int i = 0; i < secondaryTransports.size(); i++) { + char secondaryTransport[255]; + strncpy(secondaryTransport, + secondaryTransports[i].c_str(), + sizeof(secondaryTransport)); + secondaryTransport[sizeof(secondaryTransport) - 1] = '\0'; + LOG4CXX_DEBUG( + logger_, + "Adding " + << secondaryTransport + << " to secondaryTransports parameter of StartSessionAck"); + bson_array_add_string(&secondaryTransportsArr, secondaryTransport); + } + bson_object_put_array( + ¶ms, strings::secondary_transports, &secondaryTransportsArr); + + BsonArray audioServiceTransportsArr; + bson_array_initialize(&audioServiceTransportsArr, + audioServiceTransports.size()); + for (unsigned int i = 0; i < audioServiceTransports.size(); i++) { + LOG4CXX_DEBUG(logger_, + "Adding " << audioServiceTransports[i] + << " to audioServiceTransports parameter " + "of StartSessionAck"); + bson_array_add_int32(&audioServiceTransportsArr, + audioServiceTransports[i]); + } + bson_object_put_array(¶ms, + strings::audio_service_transports, + &audioServiceTransportsArr); + + BsonArray videoServiceTransportsArr; + bson_array_initialize(&videoServiceTransportsArr, + videoServiceTransports.size()); + for (unsigned int i = 0; i < videoServiceTransports.size(); i++) { + LOG4CXX_DEBUG(logger_, + "Adding " << videoServiceTransports[i] + << " to videoServiceTransports parameter " + "of StartSessionAck"); + bson_array_add_int32(&videoServiceTransportsArr, + videoServiceTransports[i]); + } + bson_object_put_array(¶ms, + strings::video_service_transports, + &videoServiceTransportsArr); + + if (settings_.multiple_transports_enabled()) { + send_transport_update_event = true; + } else { + LOG4CXX_DEBUG( + logger_, + "Multiple transports feature is disabled by configuration"); + // In this case, we must remember that this session will never have + // a secondary transport. + connection_handler_.SetSecondaryTransportID(session_id, + kDisabledSecondary); + } + } else { + LOG4CXX_WARN( + logger_, + "Failed to set up secondary transport and service type params"); + connection_handler_.SetSecondaryTransportID(session_id, + kDisabledSecondary); + } + } else { + LOG4CXX_INFO(logger_, "Older protocol version. No multiple transports"); + connection_handler_.SetSecondaryTransportID(session_id, + kDisabledSecondary); + } } uint8_t* payloadBytes = bson_object_to_bytes(¶ms); ptr->set_data(payloadBytes, bson_object_size(¶ms)); @@ -334,6 +424,16 @@ void ProtocolHandlerImpl::SendStartSessionAck( << static_cast<int32_t>(service_type) << " session_id " << static_cast<int32_t>(session_id) << " protection " << (protection ? "ON" : "OFF")); + + if (send_transport_update_event) { + // Wait until the StartService ACK has been processed for sending. + // The TransportUpdateEvent has a higher priority, being that it's + // a SERVICE_TYPE_CONTROL message. (The ACK is SERVICE_TYPE_RPC.) + LOG4CXX_DEBUG(logger_, "Waiting for the MessageToMobile queue to be empty"); + raw_ford_messages_to_mobile_.WaitDumpQueue(); + LOG4CXX_DEBUG(logger_, "Sending the TransportUpdate event"); + SendTransportUpdateEvent(connection_id, session_id); + } } void ProtocolHandlerImpl::SendStartSessionNAck(ConnectionID connection_id, @@ -491,14 +591,18 @@ void ProtocolHandlerImpl::SendEndSessionAck(ConnectionID connection_id, << static_cast<int32_t>(session_id)); } -void ProtocolHandlerImpl::SendEndServicePrivate(int32_t connection_id, +void ProtocolHandlerImpl::SendEndServicePrivate(int32_t primary_connection_id, + int32_t connection_id, uint8_t session_id, uint8_t service_type) { LOG4CXX_AUTO_TRACE(logger_); uint8_t protocol_version; if (session_observer_.ProtocolVersionUsed( - connection_id, session_id, protocol_version)) { + primary_connection_id, session_id, protocol_version)) { + LOG4CXX_TRACE(logger_, + "SendEndServicePrivate using protocol version " + << static_cast<int32_t>(protocol_version)); ProtocolFramePtr ptr( new protocol_handler::ProtocolPacket(connection_id, protocol_version, @@ -513,25 +617,31 @@ void ProtocolHandlerImpl::SendEndServicePrivate(int32_t connection_id, raw_ford_messages_to_mobile_.PostMessage( impl::RawFordMessageToMobile(ptr, false)); LOG4CXX_DEBUG(logger_, - "SendEndSession() for connection " - << connection_id << " for service_type " << service_type + "SendEndServicePrivate() for connection " + << primary_connection_id << " for service_type " + << static_cast<int>(service_type) + << " service connection " << connection_id << " session_id " << static_cast<int32_t>(session_id)); } else { LOG4CXX_WARN( logger_, - "SendEndSession is failed connection or session does not exist"); + "SendEndServicePrivate is failed connection or session does not exist"); } } void ProtocolHandlerImpl::SendEndSession(int32_t connection_id, uint8_t session_id) { - SendEndServicePrivate(connection_id, session_id, SERVICE_TYPE_RPC); + // A session is always associated with a primary connection ID + SendEndServicePrivate( + connection_id, connection_id, session_id, SERVICE_TYPE_RPC); } -void ProtocolHandlerImpl::SendEndService(int32_t connection_id, +void ProtocolHandlerImpl::SendEndService(int32_t primary_connection_id, + int32_t connection_id, uint8_t session_id, uint8_t service_type) { - SendEndServicePrivate(connection_id, session_id, service_type); + SendEndServicePrivate( + primary_connection_id, connection_id, session_id, service_type); } RESULT_CODE ProtocolHandlerImpl::SendHeartBeatAck(ConnectionID connection_id, @@ -563,6 +673,139 @@ RESULT_CODE ProtocolHandlerImpl::SendHeartBeatAck(ConnectionID connection_id, return RESULT_FAIL; } +void ProtocolHandlerImpl::SendTransportUpdateEvent(ConnectionID connection_id, + uint8_t session_id) { + LOG4CXX_AUTO_TRACE(logger_); + + 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_CONTROL, + FRAME_DATA_TRANSPORT_EVENT_UPDATE, + session_id, + 0, + message_counters_[session_id]++)); + + BsonObject payload_obj; + bson_object_initialize_default(&payload_obj); + + int32_t tcp_port = atoi(tcp_port_.c_str()); + char tcp_ip_address[INET6_ADDRSTRLEN + 1]; + if (tcp_enabled_ && (tcp_port != 0)) { + strncpy(tcp_ip_address, tcp_ip_address_.c_str(), INET6_ADDRSTRLEN); + tcp_ip_address[INET6_ADDRSTRLEN] = '\0'; + bson_object_put_string( + &payload_obj, strings::tcp_ip_address, tcp_ip_address); + bson_object_put_int32(&payload_obj, strings::tcp_port, tcp_port); + } else { + tcp_ip_address[0] = '\0'; + bson_object_put_string( + &payload_obj, strings::tcp_ip_address, tcp_ip_address); + // omit TCP port number + } + LOG4CXX_INFO(logger_, + "SendTransportUpdateEvent IP address: " + << tcp_ip_address << " Port: " << tcp_port); + + uint8_t* payloadBytes = bson_object_to_bytes(&payload_obj); + ptr->set_data(payloadBytes, bson_object_size(&payload_obj)); + free(payloadBytes); + bson_object_deinitialize(&payload_obj); + + raw_ford_messages_to_mobile_.PostMessage( + impl::RawFordMessageToMobile(ptr, false)); + + LOG4CXX_DEBUG(logger_, + "SendTransportUpdateEvent() for connection " + << connection_id << " for session " + << static_cast<int32_t>(session_id)); + } else { + LOG4CXX_WARN(logger_, + "SendTransportUpdateEvent is failed connection or session " + "does not exist"); + } +} + +RESULT_CODE ProtocolHandlerImpl::SendRegisterSecondaryTransportAck( + ConnectionID connection_id, + ConnectionID primary_transport_connection_id, + uint8_t session_id) { + LOG4CXX_AUTO_TRACE(logger_); + + // acquire the protocol version from primary transport + uint8_t protocol_version; + if (session_observer_.ProtocolVersionUsed( + primary_transport_connection_id, session_id, protocol_version)) { + ProtocolFramePtr ptr(new protocol_handler::ProtocolPacket( + connection_id, + protocol_version, + PROTECTION_OFF, + FRAME_TYPE_CONTROL, + SERVICE_TYPE_CONTROL, + FRAME_DATA_REGISTER_SECONDARY_TRANSPORT_ACK, + session_id, + 0u, + 2)); + + raw_ford_messages_to_mobile_.PostMessage( + impl::RawFordMessageToMobile(ptr, false)); + return RESULT_OK; + } + LOG4CXX_WARN(logger_, + "RegisterSecondaryTransportAck is failed connection or session " + "does not exist"); + return RESULT_FAIL; +} + +RESULT_CODE ProtocolHandlerImpl::SendRegisterSecondaryTransportNAck( + ConnectionID connection_id, + ConnectionID primary_transport_connection_id, + uint8_t session_id, + BsonObject* reason) { + LOG4CXX_AUTO_TRACE(logger_); + + // If mobile sends an invalid session ID and we cannot find out the Connection + // ID of primary transport, then we use version 5. (The multiple-transports + // feature is added in 5.1.0.) + uint8_t protocol_version = PROTOCOL_VERSION_5; + if (primary_transport_connection_id > 0) { + // acquire the protocol version from primary transport + if (!session_observer_.ProtocolVersionUsed( + primary_transport_connection_id, session_id, protocol_version)) { + LOG4CXX_WARN(logger_, + "Failed to acquire protocol version for " + "RegisterSecondaryTransportNAck"); + return RESULT_FAIL; + } + } + + ProtocolFramePtr ptr(new protocol_handler::ProtocolPacket( + connection_id, + protocol_version, + PROTECTION_OFF, + FRAME_TYPE_CONTROL, + SERVICE_TYPE_CONTROL, + FRAME_DATA_REGISTER_SECONDARY_TRANSPORT_NACK, + session_id, + 0u, + 2)); + + if (reason) { + uint8_t* payloadBytes = bson_object_to_bytes(reason); + ptr->set_data(payloadBytes, bson_object_size(reason)); + free(payloadBytes); + } + + raw_ford_messages_to_mobile_.PostMessage( + impl::RawFordMessageToMobile(ptr, false)); + return RESULT_OK; +} + void ProtocolHandlerImpl::SendHeartBeat(int32_t connection_id, uint8_t session_id) { LOG4CXX_AUTO_TRACE(logger_); @@ -682,8 +925,7 @@ void ProtocolHandlerImpl::SendMessageToMobileApp(const RawMessagePtr message, } #ifdef TELEMETRY_MONITOR if (metric_observer_) { - PHTelemetryObserver::MessageMetric* metric = - new PHTelemetryObserver::MessageMetric(); + auto metric = std::make_shared<PHTelemetryObserver::MessageMetric>(); metric->message_id = message_id; metric->connection_key = message->connection_key(); metric->raw_msg = message; @@ -857,6 +1099,12 @@ void ProtocolHandlerImpl::OnConnectionClosed( multiframe_builder_.RemoveConnection(connection_id); } +void ProtocolHandlerImpl::OnUnexpectedDisconnect( + const transport_manager::ConnectionUID connection_id, + const transport_manager::CommunicationError& error) { + OnConnectionClosed(connection_id); +} + void ProtocolHandlerImpl::NotifyOnFailedHandshake() { LOG4CXX_AUTO_TRACE(logger_); #ifdef ENABLE_SECURITY @@ -864,6 +1112,72 @@ void ProtocolHandlerImpl::NotifyOnFailedHandshake() { #endif // ENABLE_SECURITY } +void ProtocolHandlerImpl::OnTransportConfigUpdated( + const transport_manager::transport_adapter::TransportConfig& configs) { + LOG4CXX_AUTO_TRACE(logger_); + + transport_manager::transport_adapter::TransportConfig::const_iterator it = + configs.find(transport_manager::transport_adapter::tc_enabled); + if (configs.end() == it) { + LOG4CXX_WARN(logger_, "No enabled field in OnTransportConfigUpdated"); + return; + } + + bool tcp_enabled = (0 == strcmp("true", it->second.c_str())); + std::string tcp_port; + + if (tcp_enabled) { + it = configs.find(transport_manager::transport_adapter::tc_tcp_port); + if (configs.end() == it) { + LOG4CXX_WARN(logger_, "No port field in OnTransportConfigUpdated"); + return; + } + tcp_port = it->second; + + it = configs.find(transport_manager::transport_adapter::tc_tcp_ip_address); + if (configs.end() == it) { + LOG4CXX_WARN(logger_, "No IP address field in OnTransportConfigUpdated"); + return; + } + tcp_enabled_ = true; + tcp_port_ = tcp_port; + tcp_ip_address_ = it->second; + } else { + tcp_enabled_ = false; + tcp_port_.clear(); + tcp_ip_address_.clear(); + } + + LOG4CXX_INFO(logger_, + "OnTransportConfigUpdated: new config enabled is " + << tcp_enabled_ << ". Port is " << tcp_port_ + << ". IP Address is " << tcp_ip_address_); + + // Walk the SessionConnection map and find all sessions that need a + // TransportUpdate Event. Sessions flagged with kDisabledSecondary in their + // secondary transport are ineligible for secondary transport, and + // therefore don't get this event. + DataAccessor<connection_handler::SessionConnectionMap> + session_connection_map_accessor = + connection_handler_.session_connection_map(); + const connection_handler::SessionConnectionMap& session_connection_map = + session_connection_map_accessor.GetData(); + connection_handler::SessionConnectionMap::const_iterator itr = + session_connection_map.begin(); + while (itr != session_connection_map.end()) { + const connection_handler::SessionTransports st = itr->second; + LOG4CXX_INFO(logger_, + "OnTransportConfigUpdated found session " + << itr->first << " with primary connection " + << st.primary_transport << " and secondary connection " + << st.secondary_transport); + if (st.secondary_transport != kDisabledSecondary) { + SendTransportUpdateEvent(st.primary_transport, itr->first); + } + itr++; + } +} + RESULT_CODE ProtocolHandlerImpl::SendFrame(const ProtocolFramePtr packet) { LOG4CXX_AUTO_TRACE(logger_); if (!packet) { @@ -1048,6 +1362,13 @@ RESULT_CODE ProtocolHandlerImpl::HandleSingleFrameMessage( << packet->data_size() << "; message " << ConvertPacketDataToString(packet->data(), packet->data_size())); + // Replace a potential secondary transport ID in the packet with the primary + // transport ID + const connection_handler::SessionTransports st = + connection_handler_.GetSessionTransports(packet->session_id()); + if (st.primary_transport != 0) { + packet->set_connection_id(st.primary_transport); + } const uint32_t connection_key = session_observer_.KeyFromPair( packet->connection_id(), packet->session_id()); @@ -1062,8 +1383,7 @@ RESULT_CODE ProtocolHandlerImpl::HandleSingleFrameMessage( } #ifdef TELEMETRY_MONITOR if (metric_observer_) { - PHTelemetryObserver::MessageMetric* metric = - new PHTelemetryObserver::MessageMetric(); + auto metric = std::make_shared<PHTelemetryObserver::MessageMetric>(); metric->message_id = packet->message_id(); metric->connection_key = connection_key; metric->raw_msg = rawMessage; @@ -1080,6 +1400,14 @@ RESULT_CODE ProtocolHandlerImpl::HandleMultiFrameMessage( const ProtocolFramePtr packet) { LOG4CXX_AUTO_TRACE(logger_); + // Replace a potential secondary transport ID in the packet with the primary + // transport ID + const connection_handler::SessionTransports st = + connection_handler_.GetSessionTransports(packet->session_id()); + if (st.primary_transport != 0) { + packet->set_connection_id(st.primary_transport); + } + if (multiframe_builder_.AddFrame(packet) != RESULT_OK) { LOG4CXX_WARN(logger_, "Frame assembling issue"); } @@ -1117,6 +1445,10 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessage( << packet->connection_id()); return RESULT_OK; } + case FRAME_DATA_REGISTER_SECONDARY_TRANSPORT: { + LOG4CXX_TRACE(logger_, "FrameData: RegisterSecondaryTransport"); + return HandleControlMessageRegisterSecondaryTransport(packet); + } default: LOG4CXX_WARN(logger_, "Control message of type " @@ -1401,6 +1733,11 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessageStartSession( const ConnectionID connection_id = packet->connection_id(); const uint8_t session_id = packet->session_id(); + LOG4CXX_INFO(logger_, + "StartSession ID " << static_cast<int>(session_id) + << " and Connection ID " + << static_cast<int>(connection_id)); + { sync_primitives::AutoLock auto_lock(start_session_frame_map_lock_); start_session_frame_map_[std::make_pair(connection_id, session_id)] = @@ -1414,6 +1751,50 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessageStartSession( return RESULT_OK; } +RESULT_CODE ProtocolHandlerImpl::HandleControlMessageRegisterSecondaryTransport( + const ProtocolFramePtr packet) { + LOG4CXX_AUTO_TRACE(logger_); + const uint8_t session_id = packet->session_id(); + const ConnectionID connection_id = packet->connection_id(); + ConnectionID primary_connection_id = 0; + + LOG4CXX_INFO(logger_, + "RegisterSecondaryTransport ID " + << static_cast<int>(session_id) << " and Connection ID " + << static_cast<int>(connection_id)); + + if (connection_handler_.OnSecondaryTransportStarted( + primary_connection_id, connection_id, session_id)) { + SendRegisterSecondaryTransportAck( + connection_id, primary_connection_id, session_id); + } else { + char reason[256]; + BsonObject registerSecondaryTransportNackObj; + bson_object_initialize_default(®isterSecondaryTransportNackObj); + if (0 == session_id) { + strncpy(reason, + "RegisterSecondaryTransport MUST include a non-zero session ID", + 255); + } else if (primary_connection_id == 0) { + strncpy(reason, "RegisterSecondaryTransport session ID not found", 255); + } else { + strncpy( + reason, + "RegisterSecondaryTransport session ID has already been registered", + 255); + } + bson_object_put_string( + ®isterSecondaryTransportNackObj, strings::reason, reason); + SendRegisterSecondaryTransportNAck(connection_id, + primary_connection_id, + session_id, + ®isterSecondaryTransportNackObj); + bson_object_deinitialize(®isterSecondaryTransportNackObj); + } + + return RESULT_OK; +} + void ProtocolHandlerImpl::NotifySessionStartedResult( int32_t connection_id, uint8_t session_id, @@ -1423,6 +1804,7 @@ void ProtocolHandlerImpl::NotifySessionStartedResult( std::vector<std::string>& rejected_params) { LOG4CXX_AUTO_TRACE(logger_); protocol_handler::SessionContext context(connection_id, + connection_id, session_id, generated_session_id, ServiceType::kInvalidServiceType, @@ -1670,8 +2052,7 @@ void ProtocolHandlerImpl::PopValideAndExpirateMultiframes() { #ifdef TELEMETRY_MONITOR if (metric_observer_) { - PHTelemetryObserver::MessageMetric* metric = - new PHTelemetryObserver::MessageMetric(); + auto metric = std::make_shared<PHTelemetryObserver::MessageMetric>(); metric->raw_msg = rawMessage; metric_observer_->EndMessageProcess(metric); } @@ -1989,4 +2370,241 @@ uint8_t ProtocolHandlerImpl::SupportedSDLProtocolVersion() const { LOG4CXX_AUTO_TRACE(logger_); return get_settings().max_supported_protocol_version(); } + +const impl::TransportTypes transportTypes = { + std::make_pair( + std::string("AOA_USB"), + impl::TransportDescription(impl::TransportType::TT_USB, false, true)), + std::make_pair(std::string("SPP_BLUETOOTH"), + impl::TransportDescription( + impl::TransportType::TT_BLUETOOTH, false, true)), + std::make_pair(std::string("IAP_BLUETOOTH"), + impl::TransportDescription( + impl::TransportType::TT_BLUETOOTH, true, false)), + std::make_pair( + std::string("IAP_USB"), + impl::TransportDescription(impl::TransportType::TT_USB, true, false)), + std::make_pair( + std::string("TCP_WIFI"), + impl::TransportDescription(impl::TransportType::TT_WIFI, true, true)), + std::make_pair( + std::string("IAP_USB_HOST_MODE"), + impl::TransportDescription(impl::TransportType::TT_USB, true, false)), + std::make_pair( + std::string("IAP_USB_DEVICE_MODE"), + impl::TransportDescription(impl::TransportType::TT_USB, true, false)), + std::make_pair( + std::string("IAP_CARPLAY"), + impl::TransportDescription(impl::TransportType::TT_WIFI, true, false))}; + +const impl::TransportDescription +ProtocolHandlerImpl::GetTransportTypeFromConnectionType( + const std::string& connection_type) const { + impl::TransportDescription result = + impl::TransportDescription(impl::TransportType::TT_NONE, false, false); + impl::TransportTypes::const_iterator it = + transportTypes.find(connection_type); + if (it != transportTypes.end()) { + result = it->second; + } else { + LOG4CXX_ERROR(logger_, "Unknown connection type " << connection_type); + } + + return result; +} + +const bool ProtocolHandlerImpl::ParseSecondaryTransportConfiguration( + const ConnectionID connection_id, + std::vector<std::string>& secondaryTransports, + std::vector<int32_t>& audioServiceTransports, + std::vector<int32_t>& videoServiceTransports) const { + LOG4CXX_AUTO_TRACE(logger_); + std::vector<std::string> secondary_transport_types; + + // First discover what the connection type of the primary transport is + // and look up the allowed secondary transports for that primary transport + const std::string connection_type = + session_observer_.TransportTypeProfileStringFromConnHandle(connection_id); + const impl::TransportDescription td = + GetTransportTypeFromConnectionType(connection_type); + if (settings_.multiple_transports_enabled()) { + if (td.transport_type_ == impl::TransportType::TT_USB) { + secondary_transport_types = settings_.secondary_transports_for_usb(); + } else if (td.transport_type_ == impl::TransportType::TT_BLUETOOTH) { + secondary_transport_types = + settings_.secondary_transports_for_bluetooth(); + } else if (td.transport_type_ == impl::TransportType::TT_WIFI) { + secondary_transport_types = settings_.secondary_transports_for_wifi(); + } else { + LOG4CXX_ERROR( + logger_, + "Bad or unknown device type in ParseSecondaryTransportConfiguration"); + return false; + } + } + // note: even if settings_.multiple_transports_enabled() is false, we still + // send out an empty "secondaryTransports" parameter, along with + // "videoServiceTransports" and "audioServiceTransports" params which are + // useful without secondary transport. + + // Then, generate the "secondaryTransports" array for the StartSession ACK + GenerateSecondaryTransportsForStartSessionAck(secondary_transport_types, + td.ios_transport_, + td.android_transport_, + secondaryTransports); + + // Next, figure out which connections audio or video services are allowed on + GenerateServiceTransportsForStartSessionAck( + settings_.multiple_transports_enabled(), + settings_.audio_service_transports(), + connection_type, + td.transport_type_, + secondary_transport_types, + audioServiceTransports); + + GenerateServiceTransportsForStartSessionAck( + settings_.multiple_transports_enabled(), + settings_.video_service_transports(), + connection_type, + td.transport_type_, + secondary_transport_types, + videoServiceTransports); + + return true; +} + +void ProtocolHandlerImpl::GenerateSecondaryTransportsForStartSessionAck( + const std::vector<std::string>& secondary_transport_types, + bool device_is_ios, + bool device_is_android, + std::vector<std::string>& secondaryTransports) const { + LOG4CXX_AUTO_TRACE(logger_); + + // Parse the "secondary_transport_types" vector (which comes from + // smartDeviceLink.ini). For each entry in the vector, add an + // appropriate string to the secondaryTransports + std::vector<std::string>::const_iterator it = + secondary_transport_types.begin(); + while (it != secondary_transport_types.end()) { + const utils::custom_string::CustomString transport_type(*it); + if (transport_type.CompareIgnoreCase("USB")) { + if (device_is_ios) { + LOG4CXX_TRACE( + logger_, + "Adding IAP_USB to secondaryTransports for StartSessionAck"); + secondaryTransports.push_back("IAP_USB"); + } + if (device_is_android) { + LOG4CXX_TRACE( + logger_, + "Adding AOA_USB to secondaryTransports for StartSessionAck"); + secondaryTransports.push_back("AOA_USB"); + } + } else if (transport_type.CompareIgnoreCase("Bluetooth")) { + if (device_is_ios) { + LOG4CXX_TRACE( + logger_, + "Adding IAP_BLUETOOTH to secondaryTransports for StartSessionAck"); + secondaryTransports.push_back("IAP_BLUETOOTH"); + } + if (device_is_android) { + LOG4CXX_TRACE( + logger_, + "Adding SPP_BLUETOOTH to secondaryTransports for StartSessionAck"); + secondaryTransports.push_back("SPP_BLUETOOTH"); + } + } + if (transport_type.CompareIgnoreCase("WiFi")) { + LOG4CXX_TRACE( + logger_, + "Adding TCP_WIFI to secondaryTransports for StartSessionAck"); + secondaryTransports.push_back("TCP_WIFI"); + } + + it++; + } +} + +void ProtocolHandlerImpl::GenerateServiceTransportsForStartSessionAck( + bool secondary_enabled, + const std::vector<std::string>& service_transports, + const std::string& primary_connection_type, + const impl::TransportType primary_transport_type, + const std::vector<std::string>& secondary_transport_types, + std::vector<int32_t>& serviceTransports) const { + LOG4CXX_AUTO_TRACE(logger_); + + if (service_transports.size() == 0) { + if (secondary_enabled && !secondary_transport_types.empty()) { + LOG4CXX_TRACE(logger_, + "Empty Service Transports. Allowing service to run on both " + "connections"); + serviceTransports.push_back(1); + serviceTransports.push_back(2); + } else { + serviceTransports.push_back(1); + } + } else { + bool fPrimaryAdded = false; + bool fSecondaryAdded = false; + std::vector<std::string>::const_iterator it = service_transports.begin(); + for (; it != service_transports.end(); it++) { + const utils::custom_string::CustomString transport(*it); + LOG4CXX_TRACE(logger_, + "Service Allowed to run on " << transport.c_str() + << " transport"); + + if (!fPrimaryAdded && + (transport.CompareIgnoreCase(primary_connection_type.c_str()) || + (transport.CompareIgnoreCase("IAP_USB") && + primary_transport_type == impl::TransportType::TT_USB))) { + LOG4CXX_TRACE(logger_, "Service allowed on primary transport"); + serviceTransports.push_back(1); + fPrimaryAdded = true; + } + + if (!fSecondaryAdded) { + const utils::custom_string::CustomString transport_type( + TransportTypeFromTransport(transport)); + std::vector<std::string>::const_iterator found = + std::find_if(secondary_transport_types.begin(), + secondary_transport_types.end(), + [&](const std::string& secondary_transport_type) { + return transport_type.CompareIgnoreCase( + secondary_transport_type.c_str()); + }); + if (found != secondary_transport_types.end()) { + LOG4CXX_TRACE(logger_, "Service allowed on secondary transport"); + serviceTransports.push_back(2); + fSecondaryAdded = true; + } + } + + if (fPrimaryAdded && fSecondaryAdded) { + break; + } + } + } +} + +const std::string ProtocolHandlerImpl::TransportTypeFromTransport( + const utils::custom_string::CustomString& transport) const { + std::string transport_type; + + if (transport.CompareIgnoreCase("IAP_BLUETOOTH") || + transport.CompareIgnoreCase("SPP_BLUETOOTH")) { + transport_type = "Bluetooth"; + } else if (transport.CompareIgnoreCase("IAP_USB") || + transport.CompareIgnoreCase("AOA_USB") || + transport.CompareIgnoreCase("IAP_USB_HOST_MODE") || + transport.CompareIgnoreCase("IAP_USB_DEVICE_MODE")) { + transport_type = "USB"; + } else if (transport.CompareIgnoreCase("TCP_WIFI") || + transport.CompareIgnoreCase("IAP_CARPLAY")) { + transport_type = "WiFi"; + } + + return transport_type; +} + } // namespace protocol_handler diff --git a/src/components/protocol_handler/src/protocol_packet.cc b/src/components/protocol_handler/src/protocol_packet.cc index a490916c99..3cd9e7f781 100644 --- a/src/components/protocol_handler/src/protocol_packet.cc +++ b/src/components/protocol_handler/src/protocol_packet.cc @@ -304,8 +304,8 @@ RESULT_CODE ProtocolPacket::ProtocolHeaderValidator::validate( // 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 Control frames Frame info value shall be from 0x00 to 0x09 or + // 0xFD(Transport Event Update), 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: { @@ -317,6 +317,10 @@ RESULT_CODE ProtocolPacket::ProtocolHeaderValidator::validate( case FRAME_DATA_END_SERVICE: case FRAME_DATA_END_SERVICE_ACK: case FRAME_DATA_END_SERVICE_NACK: + case FRAME_DATA_REGISTER_SECONDARY_TRANSPORT: + case FRAME_DATA_REGISTER_SECONDARY_TRANSPORT_ACK: + case FRAME_DATA_REGISTER_SECONDARY_TRANSPORT_NACK: + case FRAME_DATA_TRANSPORT_EVENT_UPDATE: case FRAME_DATA_SERVICE_DATA_ACK: case FRAME_DATA_HEART_BEAT_ACK: break; @@ -642,6 +646,10 @@ ConnectionID ProtocolPacket::connection_id() const { return connection_id_; } +void ProtocolPacket::set_connection_id(ConnectionID connection_id) { + connection_id_ = connection_id; +} + uint32_t ProtocolPacket::payload_size() const { return payload_size_; } diff --git a/src/components/protocol_handler/test/include/protocol_handler/mock_telemetry_observer.h b/src/components/protocol_handler/test/include/protocol_handler/mock_telemetry_observer.h index 3296d716fa..9a91a5d1f7 100644 --- a/src/components/protocol_handler/test/include/protocol_handler/mock_telemetry_observer.h +++ b/src/components/protocol_handler/test/include/protocol_handler/mock_telemetry_observer.h @@ -45,7 +45,7 @@ class MockPHTelemetryObserver : public ::protocol_handler::PHTelemetryObserver { public: MOCK_METHOD2(StartMessageProcess, void(uint32_t, const date_time::TimeDuration&)); - MOCK_METHOD2(EndMessageProcess, void(utils::SharedPtr<MessageMetric>)); + MOCK_METHOD2(EndMessageProcess, void(std::shared_ptr<MessageMetric>)); }; } // namespace protocol_handler_test diff --git a/src/components/protocol_handler/test/incoming_data_handler_test.cc b/src/components/protocol_handler/test/incoming_data_handler_test.cc index d0a311583c..9abf5d69af 100644 --- a/src/components/protocol_handler/test/incoming_data_handler_test.cc +++ b/src/components/protocol_handler/test/incoming_data_handler_test.cc @@ -74,7 +74,7 @@ class IncomingDataHandlerTest : public ::testing::Test { void AppendPacketToTMData(const ProtocolPacket& packet) { const RawMessagePtr msg = packet.serializePacket(); - EXPECT_TRUE(msg.valid()); + EXPECT_TRUE(msg.use_count() != 0); EXPECT_GT(msg->data_size(), 0u); tm_data.insert(tm_data.end(), msg->data(), msg->data() + msg->data_size()); } @@ -192,49 +192,51 @@ TEST_F(IncomingDataHandlerTest, Heartbeat_pack) { TEST_F(IncomingDataHandlerTest, MixedPayloadData_TwoConnections) { FrameList mobile_packets; // single packet RPC - mobile_packets.push_back(new ProtocolPacket(uid1, - PROTOCOL_VERSION_1, - PROTECTION_OFF, - FRAME_TYPE_SINGLE, - kRpc, - FRAME_DATA_SINGLE, - some_session_id, - some_data_size, - protov1_message_id, - some_data)); + mobile_packets.push_back(std::make_shared<ProtocolPacket>(uid1, + PROTOCOL_VERSION_1, + PROTECTION_OFF, + FRAME_TYPE_SINGLE, + kRpc, + FRAME_DATA_SINGLE, + some_session_id, + some_data_size, + protov1_message_id, + some_data)); // consecutive packet Audio - mobile_packets.push_back(new ProtocolPacket(uid1, - PROTOCOL_VERSION_2, - PROTECTION_ON, - FRAME_TYPE_CONSECUTIVE, - kAudio, - FRAME_DATA_LAST_CONSECUTIVE, - ++some_session_id, - some_data2_size, - some_message_id, - some_data2)); + mobile_packets.push_back( + std::make_shared<ProtocolPacket>(uid1, + PROTOCOL_VERSION_2, + PROTECTION_ON, + FRAME_TYPE_CONSECUTIVE, + kAudio, + FRAME_DATA_LAST_CONSECUTIVE, + ++some_session_id, + some_data2_size, + some_message_id, + some_data2)); // single packet Nav - mobile_packets.push_back(new ProtocolPacket(uid1, - PROTOCOL_VERSION_3, - PROTECTION_ON, - FRAME_TYPE_SINGLE, - kMobileNav, - FRAME_DATA_SINGLE, - ++some_session_id, - some_data_size, - ++some_message_id, - some_data)); + mobile_packets.push_back(std::make_shared<ProtocolPacket>(uid1, + PROTOCOL_VERSION_3, + PROTECTION_ON, + FRAME_TYPE_SINGLE, + kMobileNav, + FRAME_DATA_SINGLE, + ++some_session_id, + some_data_size, + ++some_message_id, + some_data)); // consecutive packet Bulk - mobile_packets.push_back(new ProtocolPacket(uid1, - PROTOCOL_VERSION_3, - PROTECTION_ON, - FRAME_TYPE_CONSECUTIVE, - kBulk, - FRAME_DATA_LAST_CONSECUTIVE, - ++some_session_id, - some_data2_size, - ++some_message_id, - some_data2)); + mobile_packets.push_back( + std::make_shared<ProtocolPacket>(uid1, + PROTOCOL_VERSION_3, + PROTECTION_ON, + FRAME_TYPE_CONSECUTIVE, + kBulk, + FRAME_DATA_LAST_CONSECUTIVE, + ++some_session_id, + some_data2_size, + ++some_message_id, + some_data2)); for (FrameList::iterator it = mobile_packets.begin(); it != mobile_packets.end(); ++it) { @@ -268,16 +270,17 @@ TEST_F(IncomingDataHandlerTest, MalformedPacket_Version) { malformed_versions.push_back(version); } for (size_t i = 0; i < malformed_versions.size(); ++i) { - malformed_packets.push_back(new ProtocolPacket(uid1, - malformed_versions[i], - PROTECTION_OFF, - FRAME_TYPE_CONTROL, - kControl, - FRAME_DATA_HEART_BEAT, - some_session_id, - 0u, - some_message_id, - NULL)); + malformed_packets.push_back( + std::make_shared<ProtocolPacket>(uid1, + malformed_versions[i], + PROTECTION_OFF, + FRAME_TYPE_CONTROL, + kControl, + FRAME_DATA_HEART_BEAT, + some_session_id, + 0u, + some_message_id, + nullptr)); } // We count malformed only first time when it occurs after correct message @@ -316,16 +319,17 @@ TEST_F(IncomingDataHandlerTest, MalformedPacket_ServiceType) { malformed_serv_types.push_back(0x0D); malformed_serv_types.push_back(0x0E); for (size_t i = 0; i < malformed_serv_types.size(); ++i) { - malformed_packets.push_back(new ProtocolPacket(uid1, - PROTOCOL_VERSION_3, - PROTECTION_OFF, - FRAME_TYPE_CONTROL, - malformed_serv_types[i], - FRAME_DATA_HEART_BEAT, - some_session_id, - 0u, - some_message_id, - NULL)); + malformed_packets.push_back( + std::make_shared<ProtocolPacket>(uid1, + PROTOCOL_VERSION_3, + PROTECTION_OFF, + FRAME_TYPE_CONTROL, + malformed_serv_types[i], + FRAME_DATA_HEART_BEAT, + some_session_id, + 0u, + some_message_id, + nullptr)); } // We count malformed only first time when it occurs after correct message @@ -360,16 +364,17 @@ TEST_F(IncomingDataHandlerTest, MalformedPacket_FrameType) { malformed_frame_types.push_back(frame_type); } for (size_t i = 0; i < malformed_frame_types.size(); ++i) { - malformed_packets.push_back(new ProtocolPacket(uid1, - PROTOCOL_VERSION_3, - PROTECTION_OFF, - malformed_frame_types[i], - kControl, - FRAME_DATA_HEART_BEAT, - some_session_id, - 0u, - some_message_id, - NULL)); + malformed_packets.push_back( + std::make_shared<ProtocolPacket>(uid1, + PROTOCOL_VERSION_3, + PROTECTION_OFF, + malformed_frame_types[i], + kControl, + FRAME_DATA_HEART_BEAT, + some_session_id, + 0u, + some_message_id, + nullptr)); } // We count malformed only first time when it occurs after correct message @@ -393,27 +398,28 @@ TEST_F(IncomingDataHandlerTest, MalformedPacket_FrameType) { } } -// For Control frames Frame info value shall be from 0x00 to 0x06 or 0xFE(Data -// Ack), 0xFF(HB Ack) +// For Control frames Frame info value shall be from 0x00 to 0x09 or 0xFD +// (Transport Update Event), 0xFE(Data Ack), 0xFF(HB Ack) TEST_F(IncomingDataHandlerTest, MalformedPacket_ControlFrame) { FrameList malformed_packets; std::vector<uint8_t> malformed_frame_data; - for (uint8_t frame_type = FRAME_DATA_END_SERVICE_NACK + 1; - frame_type < FRAME_DATA_SERVICE_DATA_ACK; + for (uint8_t frame_type = FRAME_DATA_REGISTER_SECONDARY_TRANSPORT_NACK + 1; + frame_type < FRAME_DATA_TRANSPORT_EVENT_UPDATE; ++frame_type) { malformed_frame_data.push_back(frame_type); } for (size_t i = 0; i < malformed_frame_data.size(); ++i) { - malformed_packets.push_back(new ProtocolPacket(uid1, - PROTOCOL_VERSION_3, - PROTECTION_OFF, - FRAME_TYPE_CONTROL, - kControl, - malformed_frame_data[i], - some_session_id, - 0u, - some_message_id, - NULL)); + malformed_packets.push_back( + std::make_shared<ProtocolPacket>(uid1, + PROTOCOL_VERSION_3, + PROTECTION_OFF, + FRAME_TYPE_CONTROL, + kControl, + malformed_frame_data[i], + some_session_id, + 0u, + some_message_id, + nullptr)); } // We count malformed only first time when it occurs after correct message @@ -448,16 +454,17 @@ TEST_F(IncomingDataHandlerTest, MalformedPacket_SingleFrame) { } malformed_frame_data.push_back(FRAME_DATA_MAX_VALUE); for (size_t i = 0; i < malformed_frame_data.size(); ++i) { - malformed_packets.push_back(new ProtocolPacket(uid1, - PROTOCOL_VERSION_3, - PROTECTION_OFF, - FRAME_TYPE_SINGLE, - kControl, - malformed_frame_data[i], - some_session_id, - 0u, - some_message_id, - NULL)); + malformed_packets.push_back( + std::make_shared<ProtocolPacket>(uid1, + PROTOCOL_VERSION_3, + PROTECTION_OFF, + FRAME_TYPE_SINGLE, + kControl, + malformed_frame_data[i], + some_session_id, + 0u, + some_message_id, + nullptr)); } // We count malformed only first time when it occurs after correct message @@ -492,16 +499,17 @@ TEST_F(IncomingDataHandlerTest, MalformedPacket_FirstFrame) { } malformed_frame_data.push_back(FRAME_DATA_MAX_VALUE); for (size_t i = 0; i < malformed_frame_data.size(); ++i) { - malformed_packets.push_back(new ProtocolPacket(uid1, - PROTOCOL_VERSION_3, - PROTECTION_OFF, - FRAME_TYPE_SINGLE, - kControl, - malformed_frame_data[i], - some_session_id, - 0u, - some_message_id, - NULL)); + malformed_packets.push_back( + std::make_shared<ProtocolPacket>(uid1, + PROTOCOL_VERSION_3, + PROTECTION_OFF, + FRAME_TYPE_SINGLE, + kControl, + malformed_frame_data[i], + some_session_id, + 0u, + some_message_id, + nullptr)); } // We count malformed only first time when it occurs after correct message @@ -529,106 +537,110 @@ TEST_F(IncomingDataHandlerTest, MalformedPacket_FirstFrame) { TEST_F(IncomingDataHandlerTest, MalformedPacket_AdditionalByte) { FrameList mobile_packets; // single packet RPC - mobile_packets.push_back(new ProtocolPacket(uid1, - PROTOCOL_VERSION_1, - PROTECTION_OFF, - FRAME_TYPE_SINGLE, - kRpc, - FRAME_DATA_SINGLE, - some_session_id, - some_data_size, - protov1_message_id, - some_data)); + mobile_packets.push_back(std::make_shared<ProtocolPacket>(uid1, + PROTOCOL_VERSION_1, + PROTECTION_OFF, + FRAME_TYPE_SINGLE, + kRpc, + FRAME_DATA_SINGLE, + some_session_id, + some_data_size, + protov1_message_id, + some_data)); AppendPacketToTMData(*mobile_packets.back()); // Add malformed byte tm_data.insert(tm_data.end(), 1, 0x1); // consecutive packet Audio - mobile_packets.push_back(new ProtocolPacket(uid1, - PROTOCOL_VERSION_2, - PROTECTION_ON, - FRAME_TYPE_CONSECUTIVE, - kAudio, - FRAME_DATA_LAST_CONSECUTIVE, - ++some_session_id, - some_data2_size, - some_message_id, - some_data2)); + mobile_packets.push_back( + std::make_shared<ProtocolPacket>(uid1, + PROTOCOL_VERSION_2, + PROTECTION_ON, + FRAME_TYPE_CONSECUTIVE, + kAudio, + FRAME_DATA_LAST_CONSECUTIVE, + ++some_session_id, + some_data2_size, + some_message_id, + some_data2)); AppendPacketToTMData(*mobile_packets.back()); // Add malformed bytes tm_data.insert(tm_data.end(), 2, 0x2); // single packet Nav - mobile_packets.push_back(new ProtocolPacket(uid1, - PROTOCOL_VERSION_3, - PROTECTION_ON, - FRAME_TYPE_SINGLE, - kMobileNav, - FRAME_DATA_SINGLE, - ++some_session_id, - some_data_size, - ++some_message_id, - some_data)); + mobile_packets.push_back(std::make_shared<ProtocolPacket>(uid1, + PROTOCOL_VERSION_3, + PROTECTION_ON, + FRAME_TYPE_SINGLE, + kMobileNav, + FRAME_DATA_SINGLE, + ++some_session_id, + some_data_size, + ++some_message_id, + some_data)); AppendPacketToTMData(*mobile_packets.back()); // Add malformed bytes tm_data.insert(tm_data.end(), 3, 0x3); // consecutive packet Bulk - mobile_packets.push_back(new ProtocolPacket(uid1, - PROTOCOL_VERSION_3, - PROTECTION_ON, - FRAME_TYPE_CONSECUTIVE, - kBulk, - FRAME_DATA_LAST_CONSECUTIVE, - ++some_session_id, - some_data2_size, - ++some_message_id, - some_data2)); + mobile_packets.push_back( + std::make_shared<ProtocolPacket>(uid1, + PROTOCOL_VERSION_3, + PROTECTION_ON, + FRAME_TYPE_CONSECUTIVE, + kBulk, + FRAME_DATA_LAST_CONSECUTIVE, + ++some_session_id, + some_data2_size, + ++some_message_id, + some_data2)); AppendPacketToTMData(*mobile_packets.back()); // Add malformed bytes tm_data.insert(tm_data.end(), 4, 0x4); // single packet RPC - mobile_packets.push_back(new ProtocolPacket(uid1, - PROTOCOL_VERSION_1, - PROTECTION_OFF, - FRAME_TYPE_CONTROL, - kRpc, - FRAME_DATA_HEART_BEAT, - some_session_id, - some_data_size, - protov1_message_id, - some_data)); + mobile_packets.push_back( + std::make_shared<ProtocolPacket>(uid1, + PROTOCOL_VERSION_1, + PROTECTION_OFF, + FRAME_TYPE_CONTROL, + kRpc, + FRAME_DATA_HEART_BEAT, + some_session_id, + some_data_size, + protov1_message_id, + some_data)); AppendPacketToTMData(*mobile_packets.back()); // Add malformed bytes tm_data.insert(tm_data.end(), 5, 0x5); // single packet Audio - mobile_packets.push_back(new ProtocolPacket(uid1, - PROTOCOL_VERSION_1, - PROTECTION_OFF, - FRAME_TYPE_CONTROL, - kAudio, - FRAME_DATA_HEART_BEAT, - some_session_id, - some_data_size, - protov1_message_id, - some_data)); + mobile_packets.push_back( + std::make_shared<ProtocolPacket>(uid1, + PROTOCOL_VERSION_1, + PROTECTION_OFF, + FRAME_TYPE_CONTROL, + kAudio, + FRAME_DATA_HEART_BEAT, + some_session_id, + some_data_size, + protov1_message_id, + some_data)); AppendPacketToTMData(*mobile_packets.back()); // Add malformed bytes tm_data.insert(tm_data.end(), 6, 0x6); // single packet RPC - mobile_packets.push_back(new ProtocolPacket(uid1, - PROTOCOL_VERSION_1, - PROTECTION_OFF, - FRAME_TYPE_SINGLE, - kRpc, - FRAME_DATA_SINGLE, - some_session_id, - some_data_size, - protov1_message_id, - some_data)); + mobile_packets.push_back(std::make_shared<ProtocolPacket>(uid1, + PROTOCOL_VERSION_1, + PROTECTION_OFF, + FRAME_TYPE_SINGLE, + kRpc, + FRAME_DATA_SINGLE, + some_session_id, + some_data_size, + protov1_message_id, + some_data)); AppendPacketToTMData(*mobile_packets.back()); ProcessData(uid1, &tm_data[0], tm_data.size()); @@ -651,29 +663,30 @@ TEST_F(IncomingDataHandlerTest, MalformedPacket_AdditionalByte) { TEST_F(IncomingDataHandlerTest, MalformedPacket_Mix) { FrameList mobile_packets; // single packet RPC - mobile_packets.push_back(new ProtocolPacket(uid1, - PROTOCOL_VERSION_1, - PROTECTION_OFF, - FRAME_TYPE_SINGLE, - kRpc, - FRAME_DATA_SINGLE, - some_session_id, - some_data_size, - protov1_message_id, - some_data)); + mobile_packets.push_back(std::make_shared<ProtocolPacket>(uid1, + PROTOCOL_VERSION_1, + PROTECTION_OFF, + FRAME_TYPE_SINGLE, + kRpc, + FRAME_DATA_SINGLE, + some_session_id, + some_data_size, + protov1_message_id, + some_data)); AppendPacketToTMData(*mobile_packets.back()); // consecutive packet Audio - mobile_packets.push_back(new ProtocolPacket(uid1, - PROTOCOL_VERSION_2, - PROTECTION_ON, - FRAME_TYPE_CONSECUTIVE, - kAudio, - FRAME_DATA_LAST_CONSECUTIVE, - ++some_session_id, - some_data2_size, - some_message_id, - some_data2)); + mobile_packets.push_back( + std::make_shared<ProtocolPacket>(uid1, + PROTOCOL_VERSION_2, + PROTECTION_ON, + FRAME_TYPE_CONSECUTIVE, + kAudio, + FRAME_DATA_LAST_CONSECUTIVE, + ++some_session_id, + some_data2_size, + some_message_id, + some_data2)); AppendPacketToTMData(*mobile_packets.back()); // Malformed packet 1 @@ -691,16 +704,17 @@ TEST_F(IncomingDataHandlerTest, MalformedPacket_Mix) { AppendPacketToTMData(malformed_packet1); // consecutive packet Bulk - mobile_packets.push_back(new ProtocolPacket(uid1, - PROTOCOL_VERSION_3, - PROTECTION_ON, - FRAME_TYPE_CONSECUTIVE, - kBulk, - FRAME_DATA_LAST_CONSECUTIVE, - ++some_session_id, - some_data2_size, - ++some_message_id, - some_data2)); + mobile_packets.push_back( + std::make_shared<ProtocolPacket>(uid1, + PROTOCOL_VERSION_3, + PROTECTION_ON, + FRAME_TYPE_CONSECUTIVE, + kBulk, + FRAME_DATA_LAST_CONSECUTIVE, + ++some_session_id, + some_data2_size, + ++some_message_id, + some_data2)); AppendPacketToTMData(*mobile_packets.back()); // Malformed packet 2 @@ -718,16 +732,17 @@ TEST_F(IncomingDataHandlerTest, MalformedPacket_Mix) { AppendPacketToTMData(malformed_packet2); // Audio packet - mobile_packets.push_back(new ProtocolPacket(uid1, - PROTOCOL_VERSION_3, - PROTECTION_OFF, - FRAME_TYPE_CONTROL, - kAudio, - FRAME_DATA_HEART_BEAT, - some_session_id, - some_data_size, - protov1_message_id, - some_data)); + mobile_packets.push_back( + std::make_shared<ProtocolPacket>(uid1, + PROTOCOL_VERSION_3, + PROTECTION_OFF, + FRAME_TYPE_CONTROL, + kAudio, + FRAME_DATA_HEART_BEAT, + some_session_id, + some_data_size, + protov1_message_id, + some_data)); AppendPacketToTMData(*mobile_packets.back()); ProcessData(uid1, &tm_data[0], tm_data.size()); diff --git a/src/components/protocol_handler/test/multiframe_builder_test.cc b/src/components/protocol_handler/test/multiframe_builder_test.cc index ad8a39f79a..f919ec92af 100644 --- a/src/components/protocol_handler/test/multiframe_builder_test.cc +++ b/src/components/protocol_handler/test/multiframe_builder_test.cc @@ -35,7 +35,7 @@ #include <algorithm> #include <utility> #include <limits> -#include "utils/make_shared.h" + #include "protocol_handler/multiframe_builder.h" namespace test { @@ -149,7 +149,7 @@ class MultiFrameBuilderTest : public ::testing::Test { const ProtocolFramePtrList::const_iterator it_last = --(multiframes.end()); while (it != it_last) { const ProtocolFramePtr frame = *it; - ASSERT_TRUE(frame); + ASSERT_TRUE((bool)frame); EXPECT_EQ(RESULT_OK, multiframe_builder_.AddFrame(frame)) << "Non final CONSECUTIVE frame: " << frame; EXPECT_EQ(ProtocolFramePtrList(), multiframe_builder_.PopMultiframes()) @@ -331,7 +331,7 @@ TEST_F(MultiFrameBuilderTest, Add_FirstFrames_NoConnections) { const ProtocolFramePtrList& multiframes = multiframe_data.multiframes; ASSERT_FALSE(multiframes.empty()); const ProtocolFramePtr first_frame = multiframes.front(); - ASSERT_TRUE(first_frame); + ASSERT_TRUE((bool)first_frame); EXPECT_EQ(RESULT_FAIL, multiframe_builder_.AddFrame(first_frame)) << "Non-existed connection " << connection_id << "- to be skipped first frame: " << first_frame; @@ -365,7 +365,7 @@ TEST_F(MultiFrameBuilderTest, Add_FirstFrames_only) { const ProtocolFramePtrList& multiframes = multiframe_data.multiframes; ASSERT_FALSE(multiframes.empty()); const ProtocolFramePtr first_frame = multiframes.front(); - ASSERT_TRUE(first_frame); + ASSERT_TRUE((bool)first_frame); EXPECT_EQ(RESULT_OK, multiframe_builder_.AddFrame(first_frame)) << "First frame: " << first_frame; @@ -440,7 +440,7 @@ TEST_F(MultiFrameBuilderTest, Add_ConsecutiveFrames_per1) { ASSERT_FALSE(multiframes.empty()); const ProtocolFramePtr frame = multiframes.front(); - ASSERT_TRUE(frame); + ASSERT_TRUE((bool)frame); EXPECT_EQ(RESULT_OK, multiframe_builder_.AddFrame(frame)) << "Frame: " << frame; @@ -501,7 +501,7 @@ TEST_F(MultiFrameBuilderTest, FrameExpired_OneMSec) { const ProtocolFramePtrList& multiframes = multiframe_data.multiframes; ASSERT_FALSE(multiframes.empty()); const ProtocolFramePtr first_frame = multiframes.front(); - ASSERT_TRUE(first_frame); + ASSERT_TRUE((bool)first_frame); EXPECT_EQ(RESULT_OK, multiframe_builder_.AddFrame(first_frame)) << "First frame: " << first_frame; 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 0cb8e155d0..cfda0a550a 100644 --- a/src/components/protocol_handler/test/protocol_handler_tm_test.cc +++ b/src/components/protocol_handler/test/protocol_handler_tm_test.cc @@ -41,16 +41,26 @@ #include "protocol_handler/mock_protocol_handler_settings.h" #include "protocol_handler/mock_session_observer.h" #include "connection_handler/mock_connection_handler.h" +#include "connection_handler/connection_handler_impl.h" #ifdef ENABLE_SECURITY #include "security_manager/mock_security_manager.h" #include "security_manager/mock_ssl_context.h" #endif // ENABLE_SECURITY #include "transport_manager/mock_transport_manager.h" #include "utils/mock_system_time_handler.h" -#include "utils/make_shared.h" + #include "utils/test_async_waiter.h" #include <bson_object.h> +namespace transport_manager { +namespace transport_adapter { +// taken from transport_adapter_impl.cc +const char* tc_enabled = "enabled"; +const char* tc_tcp_port = "tcp_port"; +const char* tc_tcp_ip_address = "tcp_ip_address"; +} +} + namespace test { namespace components { namespace protocol_handler_test { @@ -88,6 +98,10 @@ 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_TRANSPORT_EVENT_UPDATE; using protocol_handler::kRpc; using protocol_handler::kControl; using protocol_handler::kAudio; @@ -108,10 +122,12 @@ using ContextCreationStrategy = using connection_handler::DeviceHandle; // Google Testing Framework Entities using ::testing::Return; +using ::testing::ReturnRef; using ::testing::ReturnRefOfCopy; using ::testing::ReturnNull; using ::testing::An; using ::testing::AnyOf; +using ::testing::AtLeast; using ::testing::ByRef; using ::testing::DoAll; using ::testing::SaveArg; @@ -190,6 +206,9 @@ class ProtocolHandlerImplTest : public ::testing::Test { . // Return false to avoid call KeepConnectionAlive WillRepeatedly(Return(false)); + + session_connection_map_lock_ptr_ = + std::make_shared<sync_primitives::Lock>(); } void TearDown() OVERRIDE { @@ -216,6 +235,7 @@ class ProtocolHandlerImplTest : public ::testing::Test { const uint32_t hash_id, const bool protection_flag) { return protocol_handler::SessionContext(connection_id, + connection_id, initial_session_id, new_session_id, service_type, @@ -223,7 +243,7 @@ class ProtocolHandlerImplTest : public ::testing::Test { protection_flag); } - void AddSession(const ::utils::SharedPtr<TestAsyncWaiter>& waiter, + void AddSession(const std::shared_ptr<TestAsyncWaiter>& waiter, uint32_t& times) { using namespace protocol_handler; ASSERT_TRUE(NULL != waiter.get()); @@ -320,10 +340,11 @@ class ProtocolHandlerImplTest : public ::testing::Test { uint8_t service_type, uint8_t sessionId, uint32_t frame_data, + uint8_t protocol_version = PROTOCOL_VERSION_3, uint32_t dataSize = 0u, const uint8_t* data = NULL) { SendTMMessage(connection_id, - PROTOCOL_VERSION_3, + protocol_version, protection, FRAME_TYPE_CONTROL, service_type, @@ -334,8 +355,20 @@ class ProtocolHandlerImplTest : public ::testing::Test { data); } + void VerifySecondaryTransportParamsInStartSessionAck( + bool config_multiple_transports_enabled, + const std::vector<std::string>& config_secondary_transports_for_usb, + const std::vector<std::string>& config_secondary_transports_for_bluetooth, + const std::vector<std::string>& config_secondary_transports_for_wifi, + const std::vector<std::string>& config_audio_service_transports, + const std::vector<std::string>& config_video_service_transports, + const std::string& connection_type_string, + const std::vector<std::string>& expected_transport_strings, + const std::vector<int32_t>& expected_audio_service_transports, + const std::vector<int32_t>& expected_video_service_transports); + testing::NiceMock<MockProtocolHandlerSettings> protocol_handler_settings_mock; - ::utils::SharedPtr<ProtocolHandlerImpl> protocol_handler_impl; + std::shared_ptr<ProtocolHandlerImpl> protocol_handler_impl; TransportManagerListener* tm_listener; // Uniq connection ::transport_manager::ConnectionUID connection_id; @@ -360,6 +393,10 @@ class ProtocolHandlerImplTest : public ::testing::Test { std::vector<int> force_unprotected_services; #endif // ENABLE_SECURITY std::vector<std::string> empty_rejected_param_; + // Used by OnTransportConfigUpdated() tests. The lifetime of these objects + // should be longer than that of a test case. + connection_handler::SessionConnectionMap session_connection_map_; + std::shared_ptr<sync_primitives::Lock> session_connection_map_lock_ptr_; }; #ifdef ENABLE_SECURITY @@ -584,8 +621,7 @@ TEST_F(ProtocolHandlerImplTest, TEST_F(ProtocolHandlerImplTest, StartSession_Protected_SessionObserverAccept) { SetProtocolVersion2(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -799,8 +835,7 @@ TEST_F(ProtocolHandlerImplTest, * ProtocolHandler shall send NAck on session_observer rejection */ TEST_F(ProtocolHandlerImplTest, EndSession_SessionObserverReject) { - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -833,8 +868,7 @@ TEST_F(ProtocolHandlerImplTest, EndSession_SessionObserverReject) { * ProtocolHandler shall send NAck on wrong hash code */ TEST_F(ProtocolHandlerImplTest, EndSession_Success) { - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -867,8 +901,7 @@ TEST_F(ProtocolHandlerImplTest, EndSession_Success) { #ifdef ENABLE_SECURITY TEST_F(ProtocolHandlerImplTest, SecurityEnable_StartSessionProtocoloV1) { using namespace protocol_handler; - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1485,14 +1518,1138 @@ TEST_F(ProtocolHandlerImplTest, } #endif // ENABLE_SECURITY +void ProtocolHandlerImplTest::VerifySecondaryTransportParamsInStartSessionAck( + bool config_multiple_transports_enabled, + const std::vector<std::string>& config_secondary_transports_for_usb, + const std::vector<std::string>& config_secondary_transports_for_bluetooth, + const std::vector<std::string>& config_secondary_transports_for_wifi, + const std::vector<std::string>& config_audio_service_transports, + const std::vector<std::string>& config_video_service_transports, + const std::string& connection_type_string, + const std::vector<std::string>& expected_transport_strings, + const std::vector<int32_t>& expected_audio_service_transports, + const std::vector<int32_t>& expected_video_service_transports) { + 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; + ProtocolPacket::ProtocolVersion full_version(5, 1, 0); + char full_version_string[] = "5.1.0"; + + // configuration setup + EXPECT_CALL(protocol_handler_settings_mock, max_supported_protocol_version()) + .WillRepeatedly(Return(PROTOCOL_VERSION_5)); + EXPECT_CALL(protocol_handler_settings_mock, multiple_transports_enabled()) + .WillRepeatedly(Return(config_multiple_transports_enabled)); + EXPECT_CALL(protocol_handler_settings_mock, secondary_transports_for_usb()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_usb)); + EXPECT_CALL(protocol_handler_settings_mock, + secondary_transports_for_bluetooth()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_bluetooth)); + EXPECT_CALL(protocol_handler_settings_mock, secondary_transports_for_wifi()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_wifi)); + EXPECT_CALL(protocol_handler_settings_mock, audio_service_transports()) + .WillOnce(ReturnRef(config_audio_service_transports)); + EXPECT_CALL(protocol_handler_settings_mock, video_service_transports()) + .WillOnce(ReturnRef(config_video_service_transports)); + + EXPECT_CALL(session_observer_mock, + TransportTypeProfileStringFromConnHandle(connection_id)) + .WillRepeatedly(Return(connection_type_string)); + + // 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, + expected_transport_strings.size()); + for (std::vector<std::string>::const_iterator it = + expected_transport_strings.begin(); + it != expected_transport_strings.end(); + ++it) { + // note: if there is no transport allowed, we can either make the array + // empty, or completely omit the array. (The spec allows both cases.) In + // this test case we make the array empty. + bson_array_add_string(&secondary_transports, + const_cast<char*>(it->c_str())); + } + bson_object_put_array(&expected_obj, + protocol_handler::strings::secondary_transports, + &secondary_transports); + // audioServiceTransports + BsonArray audio_service_transports; + if (expected_audio_service_transports.size() > 0) { + bson_array_initialize(&audio_service_transports, + expected_audio_service_transports.size()); + for (std::vector<int32_t>::const_iterator it = + expected_audio_service_transports.begin(); + it != expected_audio_service_transports.end(); + ++it) { + bson_array_add_int32(&audio_service_transports, *it); + } + bson_object_put_array(&expected_obj, + protocol_handler::strings::audio_service_transports, + &audio_service_transports); + } + // videoServiceTransports + BsonArray video_service_transports; + if (expected_video_service_transports.size() > 0) { + bson_array_initialize(&video_service_transports, + expected_video_service_transports.size()); + for (std::vector<int32_t>::const_iterator it = + expected_video_service_transports.begin(); + it != expected_video_service_transports.end(); + ++it) { + bson_array_add_int32(&video_service_transports, *it); + } + bson_object_put_array(&expected_obj, + protocol_handler::strings::video_service_transports, + &video_service_transports); + } + + 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, + connection_id, + Eq(expected_param)))) + .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)); +} + +TEST_F(ProtocolHandlerImplTest, + StartSessionAck_SecondaryTransportParams_Enabled) { + // config allows secondary transport only when connected through Bluetooth, + // and the secondary is Wi-Fi + std::vector<std::string> secondary_transports_for_usb; // empty + std::vector<std::string> secondary_transports_for_bluetooth; + secondary_transports_for_bluetooth.push_back("WiFi"); + std::vector<std::string> secondary_transports_for_wifi; // empty + // config allows video and audio services to run on all transports except + // Bluetooth + std::vector<std::string> audio_service_transports; + audio_service_transports.push_back("IAP_USB"); + audio_service_transports.push_back("IAP_USB_HOST_MODE"); + audio_service_transports.push_back("IAP_USB_DEVICE_MODE"); + audio_service_transports.push_back("IAP_CARPLAY"); + audio_service_transports.push_back("AOA_USB"); + audio_service_transports.push_back("TCP_WIFI"); + std::vector<std::string> video_service_transports; + video_service_transports.push_back("IAP_USB"); + video_service_transports.push_back("IAP_USB_HOST_MODE"); + video_service_transports.push_back("IAP_USB_DEVICE_MODE"); + video_service_transports.push_back("IAP_CARPLAY"); + video_service_transports.push_back("AOA_USB"); + video_service_transports.push_back("TCP_WIFI"); + + // assume the device is Android and is connected through Bluetooth SPP + std::string connection_type_string("SPP_BLUETOOTH"); + + // Core should specify WiFi for secondary transport, and should allow video + // and audio services only on secondary transport + std::vector<std::string> expected_transport_strings; + expected_transport_strings.push_back("TCP_WIFI"); + std::vector<int32_t> expected_audio_service_transports; + expected_audio_service_transports.push_back(2); + std::vector<int32_t> expected_video_service_transports; + expected_video_service_transports.push_back(2); + + // 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)); + + VerifySecondaryTransportParamsInStartSessionAck( + true, + secondary_transports_for_usb, + secondary_transports_for_bluetooth, + secondary_transports_for_wifi, + audio_service_transports, + video_service_transports, + connection_type_string, + expected_transport_strings, + expected_audio_service_transports, + expected_video_service_transports); +} + +TEST_F(ProtocolHandlerImplTest, + StartSessionAck_SecondaryTransportParams_NoSecondaryTransport) { + // config allows secondary transport only when connected through Bluetooth, + // and the secondary is Wi-Fi + std::vector<std::string> secondary_transports_for_usb; // empty + std::vector<std::string> secondary_transports_for_bluetooth; + secondary_transports_for_bluetooth.push_back("WiFi"); + std::vector<std::string> secondary_transports_for_wifi; // empty + // config allows video and audio services to run on all transports except + // Bluetooth + std::vector<std::string> audio_service_transports; + audio_service_transports.push_back("IAP_USB"); + audio_service_transports.push_back("IAP_USB_HOST_MODE"); + audio_service_transports.push_back("IAP_USB_DEVICE_MODE"); + audio_service_transports.push_back("IAP_CARPLAY"); + audio_service_transports.push_back("AOA_USB"); + audio_service_transports.push_back("TCP_WIFI"); + std::vector<std::string> video_service_transports; + video_service_transports.push_back("IAP_USB"); + video_service_transports.push_back("IAP_USB_HOST_MODE"); + video_service_transports.push_back("IAP_USB_DEVICE_MODE"); + video_service_transports.push_back("IAP_CARPLAY"); + video_service_transports.push_back("AOA_USB"); + video_service_transports.push_back("TCP_WIFI"); + + // assume the device is iOS and is connected through iAP over USB + std::string connection_type_string("IAP_USB"); + + // Core should not offer any secondary transport. It will allow both video + // and audio services on primary transport. + std::vector<std::string> expected_transport_strings; // empty + std::vector<int32_t> expected_audio_service_transports; + expected_audio_service_transports.push_back(1); + std::vector<int32_t> expected_video_service_transports; + expected_video_service_transports.push_back(1); + + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly(Return(false)); + + VerifySecondaryTransportParamsInStartSessionAck( + true, + secondary_transports_for_usb, + secondary_transports_for_bluetooth, + secondary_transports_for_wifi, + audio_service_transports, + video_service_transports, + connection_type_string, + expected_transport_strings, + expected_audio_service_transports, + expected_video_service_transports); +} + +TEST_F(ProtocolHandlerImplTest, + StartSessionAck_SecondaryTransportParams_MultipleSecondaryTransports) { + // config allows secondary transport only when connected through Bluetooth, + // and the secondary is Wi-Fi and USB + std::vector<std::string> secondary_transports_for_usb; // empty + std::vector<std::string> secondary_transports_for_bluetooth; + secondary_transports_for_bluetooth.push_back("WiFi"); + secondary_transports_for_bluetooth.push_back("USB"); + std::vector<std::string> secondary_transports_for_wifi; // empty + // config allows video and audio services to run on all transports except + // Bluetooth + std::vector<std::string> audio_service_transports; + audio_service_transports.push_back("IAP_USB"); + audio_service_transports.push_back("IAP_USB_HOST_MODE"); + audio_service_transports.push_back("IAP_USB_DEVICE_MODE"); + audio_service_transports.push_back("IAP_CARPLAY"); + audio_service_transports.push_back("AOA_USB"); + audio_service_transports.push_back("TCP_WIFI"); + std::vector<std::string> video_service_transports; + video_service_transports.push_back("IAP_USB"); + video_service_transports.push_back("IAP_USB_HOST_MODE"); + video_service_transports.push_back("IAP_USB_DEVICE_MODE"); + video_service_transports.push_back("IAP_CARPLAY"); + video_service_transports.push_back("AOA_USB"); + video_service_transports.push_back("TCP_WIFI"); + + // assume the device is iOS and is connected through iAP over Bluetooth + std::string connection_type_string("IAP_BLUETOOTH"); + + // Core should offer both Wi-Fi and USB for secondary transport. Since the + // device is iOS, Core should specify "IAP_USB". + std::vector<std::string> expected_transport_strings; + expected_transport_strings.push_back("TCP_WIFI"); + expected_transport_strings.push_back("IAP_USB"); + std::vector<int32_t> expected_audio_service_transports; + expected_audio_service_transports.push_back(2); + std::vector<int32_t> expected_video_service_transports; + expected_video_service_transports.push_back(2); + + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly(Return(false)); + + VerifySecondaryTransportParamsInStartSessionAck( + true, + secondary_transports_for_usb, + secondary_transports_for_bluetooth, + secondary_transports_for_wifi, + audio_service_transports, + video_service_transports, + connection_type_string, + expected_transport_strings, + expected_audio_service_transports, + expected_video_service_transports); +} + +TEST_F( + ProtocolHandlerImplTest, + StartSessionAck_SecondaryTransportParams_ServiceAllowedOnBothTransports) { + std::vector<std::string> secondary_transports_for_usb; + secondary_transports_for_usb.push_back("WiFi"); + std::vector<std::string> secondary_transports_for_bluetooth; + secondary_transports_for_bluetooth.push_back("USB"); + std::vector<std::string> secondary_transports_for_wifi; // empty + // config allows video service to run on Wi-Fi transports only, and audio + // service to run on all transports + std::vector<std::string> audio_service_transports; + audio_service_transports.push_back("IAP_BLUETOOTH"); + audio_service_transports.push_back("IAP_USB"); + audio_service_transports.push_back("IAP_USB_HOST_MODE"); + audio_service_transports.push_back("IAP_USB_DEVICE_MODE"); + audio_service_transports.push_back("IAP_CARPLAY"); + audio_service_transports.push_back("SPP_BLUETOOTH"); + audio_service_transports.push_back("AOA_USB"); + audio_service_transports.push_back("TCP_WIFI"); + std::vector<std::string> video_service_transports; + video_service_transports.push_back("IAP_CARPLAY"); + video_service_transports.push_back("TCP_WIFI"); + + // assume the device is Android and is connected through AOA + std::string connection_type_string("AOA_USB"); + + // Core should offer Wi-Fi for secondary transport. It should allow audio + // service to run on both primary and secondary, while video service to run + // on secondary only. Since the list specifies AOA_USB then TCP_WIFI, the + // priority is primary > secondary. + std::vector<std::string> expected_transport_strings; + expected_transport_strings.push_back("TCP_WIFI"); + std::vector<int32_t> expected_audio_service_transports; + expected_audio_service_transports.push_back(1); // primary preferred + expected_audio_service_transports.push_back(2); + std::vector<int32_t> expected_video_service_transports; + expected_video_service_transports.push_back(2); + + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly(Return(false)); + + VerifySecondaryTransportParamsInStartSessionAck( + true, + secondary_transports_for_usb, + secondary_transports_for_bluetooth, + secondary_transports_for_wifi, + audio_service_transports, + video_service_transports, + connection_type_string, + expected_transport_strings, + expected_audio_service_transports, + expected_video_service_transports); +} + +TEST_F(ProtocolHandlerImplTest, + StartSessionAck_SecondaryTransportParams_SecondaryDisabled) { + std::vector<std::string> secondary_transports_for_usb; // empty + std::vector<std::string> secondary_transports_for_bluetooth; // empty + std::vector<std::string> secondary_transports_for_wifi; // empty + // config allows video and audio services to run on all transports + std::vector<std::string> audio_service_transports; + audio_service_transports.push_back("IAP_BLUETOOTH"); + audio_service_transports.push_back("IAP_USB"); + audio_service_transports.push_back("IAP_USB_HOST_MODE"); + audio_service_transports.push_back("IAP_USB_DEVICE_MODE"); + audio_service_transports.push_back("IAP_CARPLAY"); + audio_service_transports.push_back("SPP_BLUETOOTH"); + audio_service_transports.push_back("AOA_USB"); + audio_service_transports.push_back("TCP_WIFI"); + std::vector<std::string> video_service_transports; + video_service_transports.push_back("IAP_BLUETOOTH"); + video_service_transports.push_back("IAP_USB"); + video_service_transports.push_back("IAP_USB_HOST_MODE"); + video_service_transports.push_back("IAP_USB_DEVICE_MODE"); + video_service_transports.push_back("IAP_CARPLAY"); + video_service_transports.push_back("SPP_BLUETOOTH"); + video_service_transports.push_back("AOA_USB"); + video_service_transports.push_back("TCP_WIFI"); + + // assume the device is iOS and is connected through iAP over Bluetooth + std::string connection_type_string("IAP_BLUETOOTH"); + + // Core should not offer any secondary transport. It should still send + // the video/audio service transport lists. + std::vector<std::string> expected_transport_strings; // empty + std::vector<int32_t> expected_audio_service_transports; + expected_audio_service_transports.push_back(1); + std::vector<int32_t> expected_video_service_transports; + expected_video_service_transports.push_back(1); + + connection_handler::SessionTransports dummy_st = {0, 0}; + EXPECT_CALL(connection_handler_mock, + SetSecondaryTransportID(_, kDisabledSecondary)) + .WillOnce(Return(dummy_st)); + + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly(Return(false)); + + VerifySecondaryTransportParamsInStartSessionAck( + false, /* disabled */ + secondary_transports_for_usb, + secondary_transports_for_bluetooth, + secondary_transports_for_wifi, + audio_service_transports, + video_service_transports, + connection_type_string, + expected_transport_strings, + expected_audio_service_transports, + expected_video_service_transports); +} + +TEST_F(ProtocolHandlerImplTest, + StartSessionAck_SecondaryTransportParams_ServicesMapEmpty) { + std::vector<std::string> secondary_transports_for_usb; // empty + std::vector<std::string> secondary_transports_for_bluetooth; + secondary_transports_for_bluetooth.push_back("USB"); + std::vector<std::string> secondary_transports_for_wifi; + secondary_transports_for_wifi.push_back("USB"); + // config does not specify video and audio services + std::vector<std::string> audio_service_transports; // empty + std::vector<std::string> video_service_transports; // empty + + // assume the device is connected through Wi-Fi (so not sure if it's iOS or + // Android) + std::string connection_type_string("TCP_WIFI"); + + // Core should offer USB transport for secondary transport. (Since the OS type + // is unknown, it will offer both IAP_USB and AOA_USB.) Also, it should allow + // video/audio services on all transports. + std::vector<std::string> expected_transport_strings; + expected_transport_strings.push_back("IAP_USB"); + expected_transport_strings.push_back("AOA_USB"); + std::vector<int32_t> expected_audio_service_transports; + expected_audio_service_transports.push_back(1); + expected_audio_service_transports.push_back(2); + std::vector<int32_t> expected_video_service_transports; + expected_video_service_transports.push_back(1); + expected_video_service_transports.push_back(2); + + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly(Return(false)); + + VerifySecondaryTransportParamsInStartSessionAck( + true, + secondary_transports_for_usb, + secondary_transports_for_bluetooth, + secondary_transports_for_wifi, + audio_service_transports, + video_service_transports, + connection_type_string, + expected_transport_strings, + expected_audio_service_transports, + expected_video_service_transports); +} + +TEST_F( + ProtocolHandlerImplTest, + StartSessionAck_SecondaryTransportParams_SecondaryDisabled_ServicesMapEmpty) { + std::vector<std::string> secondary_transports_for_usb; // empty + std::vector<std::string> secondary_transports_for_bluetooth; // empty + std::vector<std::string> secondary_transports_for_wifi; // empty + // config does not specify video and audio services + std::vector<std::string> audio_service_transports; // empty + std::vector<std::string> video_service_transports; // empty + + std::string connection_type_string("IAP_BLUETOOTH"); + + // Core should not offer any secondary transport. It should still send + // the video/audio service transport lists. + std::vector<std::string> expected_transport_strings; // empty + std::vector<int32_t> expected_audio_service_transports; + expected_audio_service_transports.push_back(1); + std::vector<int32_t> expected_video_service_transports; + expected_video_service_transports.push_back(1); + + connection_handler::SessionTransports dummy_st = {0, 0}; + EXPECT_CALL(connection_handler_mock, + SetSecondaryTransportID(_, kDisabledSecondary)) + .WillOnce(Return(dummy_st)); + + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly(Return(false)); + + VerifySecondaryTransportParamsInStartSessionAck( + false, /* disabled */ + secondary_transports_for_usb, + secondary_transports_for_bluetooth, + secondary_transports_for_wifi, + audio_service_transports, + video_service_transports, + connection_type_string, + expected_transport_strings, + expected_audio_service_transports, + expected_video_service_transports); +} + +// Secondary transport param should not be included for apps with v5.0.0 +TEST_F(ProtocolHandlerImplTest, + StartSessionAck_Unprotected_NoSecondaryTransportParamsForV5) { + TestAsyncWaiter waiter; + uint32_t times = 0; + + const uint8_t input_protocol_version = 5; + const uint32_t hash_id = 123456; + ProtocolPacket::ProtocolVersion full_version(5, 0, 0); + char full_version_string[] = "5.0.0"; + + 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); + + // configuration + std::vector<std::string> config_secondary_transports_for_usb; // empty + std::vector<std::string> config_secondary_transports_for_bluetooth; + config_secondary_transports_for_bluetooth.push_back("USB"); + std::vector<std::string> config_secondary_transports_for_wifi; + config_secondary_transports_for_wifi.push_back("USB"); + + // assume the device is iOS and is connected through iAP over Bluetooth + std::string connection_type_string("IAP_BLUETOOTH"); + + // configuration setup + EXPECT_CALL(protocol_handler_settings_mock, max_supported_protocol_version()) + .WillRepeatedly(Return(PROTOCOL_VERSION_5)); + EXPECT_CALL(protocol_handler_settings_mock, multiple_transports_enabled()) + .WillRepeatedly(Return(true)); + EXPECT_CALL(protocol_handler_settings_mock, secondary_transports_for_usb()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_usb)); + EXPECT_CALL(protocol_handler_settings_mock, + secondary_transports_for_bluetooth()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_bluetooth)); + EXPECT_CALL(protocol_handler_settings_mock, secondary_transports_for_wifi()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_wifi)); + + EXPECT_CALL(session_observer_mock, + TransportTypeProfileStringFromConnHandle(connection_id)) + .WillRepeatedly(Return(connection_type_string)); + + // BSON params should not include any of "secondaryTransports", + // "audioServiceTransports" and "videoServiceTransports" since v5.0.0 app + // does not understand them + 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); + + 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, + connection_id, + Eq(expected_param)))) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; + + connection_handler::SessionTransports dummy_st = {0, 0}; + EXPECT_CALL(connection_handler_mock, + SetSecondaryTransportID(_, kDisabledSecondary)) + .WillOnce(Return(dummy_st)); + + // Since the protocol version is less than 5.1.0, Core should not issue + // TransportEventUpdate frame. Enable ProtocolVersionUsed() call and verify + // that transport_manager_mock will NOT receive another SendMessageToDevice() + // call. + ON_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillByDefault(Return(true)); + +#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)); +} + +TEST_F(ProtocolHandlerImplTest, StartSessionAck_PrimaryTransportUSBHostMode) { + // config allows secondary transport only when connected through Bluetooth, + // and the secondary is Wi-Fi + std::vector<std::string> secondary_transports_for_usb; + secondary_transports_for_usb.push_back("WiFi"); + std::vector<std::string> secondary_transports_for_bluetooth; // empty + std::vector<std::string> secondary_transports_for_wifi; // empty + // config allows video and audio services to run on all transports except + // Bluetooth + std::vector<std::string> audio_service_transports; + audio_service_transports.push_back("IAP_USB_DEVICE_MODE"); + audio_service_transports.push_back("IAP_CARPLAY"); + audio_service_transports.push_back("AOA_USB"); + audio_service_transports.push_back("TCP_WIFI"); + std::vector<std::string> video_service_transports; + video_service_transports.push_back("IAP_USB"); + video_service_transports.push_back("IAP_CARPLAY"); + video_service_transports.push_back("AOA_USB"); + video_service_transports.push_back("TCP_WIFI"); + + // assume the device is IOS and is connected through USB Host Mode + std::string connection_type_string("IAP_USB_HOST_MODE"); + + // Core should specify WiFi for secondary transport, and should allow video + // services on both transports, and audio only on secondary transport + std::vector<std::string> expected_transport_strings; + expected_transport_strings.push_back("TCP_WIFI"); + std::vector<int32_t> expected_audio_service_transports; + expected_audio_service_transports.push_back(2); + std::vector<int32_t> expected_video_service_transports; + expected_video_service_transports.push_back(1); + expected_video_service_transports.push_back(2); + + // 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)); + + VerifySecondaryTransportParamsInStartSessionAck( + true, + secondary_transports_for_usb, + secondary_transports_for_bluetooth, + secondary_transports_for_wifi, + audio_service_transports, + video_service_transports, + connection_type_string, + expected_transport_strings, + expected_audio_service_transports, + expected_video_service_transports); +} + +TEST_F(ProtocolHandlerImplTest, + TransportEventUpdate_afterVersionNegotiation_TCPEnabled) { + TestAsyncWaiter waiter; + uint32_t times = 0; + + const uint8_t input_protocol_version = 5; + const uint32_t hash_id = 123456; + ProtocolPacket::ProtocolVersion full_version(5, 1, 0); + + 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); + + // TCP configuration setup + bool tcp_enabled = true; + char tcp_address[] = "192.168.1.1"; + int32_t tcp_port = 12345; + std::string tcp_port_str = "12345"; + protocol_handler_impl->set_tcp_config( + tcp_enabled, std::string(tcp_address), tcp_port_str); + + // configuration setup + std::vector<std::string> config_secondary_transports_for_usb; // empty + std::vector<std::string> config_secondary_transports_for_bluetooth; + config_secondary_transports_for_bluetooth.push_back("WiFi"); + std::vector<std::string> config_secondary_transports_for_wifi; // empty + std::vector<std::string> config_audio_service_transports; + config_audio_service_transports.push_back("IAP_USB"); + config_audio_service_transports.push_back("IAP_USB_HOST_MODE"); + config_audio_service_transports.push_back("IAP_USB_DEVICE_MODE"); + config_audio_service_transports.push_back("IAP_CARPLAY"); + config_audio_service_transports.push_back("AOA_USB"); + config_audio_service_transports.push_back("TCP_WIFI"); + std::vector<std::string> config_video_service_transports; + config_video_service_transports.push_back("IAP_USB"); + config_video_service_transports.push_back("IAP_USB_HOST_MODE"); + config_video_service_transports.push_back("IAP_USB_DEVICE_MODE"); + config_video_service_transports.push_back("IAP_CARPLAY"); + config_video_service_transports.push_back("AOA_USB"); + config_video_service_transports.push_back("TCP_WIFI"); + + EXPECT_CALL(protocol_handler_settings_mock, max_supported_protocol_version()) + .WillRepeatedly(Return(PROTOCOL_VERSION_5)); + EXPECT_CALL(protocol_handler_settings_mock, multiple_transports_enabled()) + .WillRepeatedly(Return(true)); + EXPECT_CALL(protocol_handler_settings_mock, secondary_transports_for_usb()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_usb)); + EXPECT_CALL(protocol_handler_settings_mock, + secondary_transports_for_bluetooth()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_bluetooth)); + EXPECT_CALL(protocol_handler_settings_mock, secondary_transports_for_wifi()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_wifi)); + EXPECT_CALL(protocol_handler_settings_mock, audio_service_transports()) + .WillOnce(ReturnRef(config_audio_service_transports)); + EXPECT_CALL(protocol_handler_settings_mock, video_service_transports()) + .WillOnce(ReturnRef(config_video_service_transports)); + + // assume the device is iOS and is connected through iAP over Bluetooth + std::string connection_type_string("IAP_BLUETOOTH"); + + EXPECT_CALL(session_observer_mock, + TransportTypeProfileStringFromConnHandle(connection_id)) + .WillRepeatedly(Return(connection_type_string)); + + EXPECT_CALL( + transport_manager_mock, + SendMessageToDevice(ControlMessage( + FRAME_DATA_START_SERVICE_ACK, PROTECTION_OFF, connection_id, _))) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; + + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly( + DoAll(SetArgReferee<2>(PROTOCOL_VERSION_5), Return(true))); + + BsonObject expected_obj; + bson_object_initialize_default(&expected_obj); + // IP address + bson_object_put_string( + &expected_obj, protocol_handler::strings::tcp_ip_address, tcp_address); + // TCP port number + bson_object_put_int32( + &expected_obj, protocol_handler::strings::tcp_port, tcp_port); + + std::vector<uint8_t> expected_param = + CreateVectorFromBsonObject(&expected_obj); + + bson_object_deinitialize(&expected_obj); + + EXPECT_CALL( + transport_manager_mock, + SendMessageToDevice(ControlMessage(FRAME_DATA_TRANSPORT_EVENT_UPDATE, + PROTECTION_OFF, + connection_id, + Eq(expected_param)))) + .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)); +} + +TEST_F(ProtocolHandlerImplTest, + TransportEventUpdate_afterVersionNegotiation_TCPDisabled) { + TestAsyncWaiter waiter; + uint32_t times = 0; + + const uint8_t input_protocol_version = 5; + const uint32_t hash_id = 123456; + ProtocolPacket::ProtocolVersion full_version(5, 1, 0); + + 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); + + // TCP configuration setup + bool tcp_enabled = false; + char tcp_address[] = "192.168.2.3"; + std::string tcp_port_str = "12345"; + protocol_handler_impl->set_tcp_config( + tcp_enabled, std::string(tcp_address), tcp_port_str); + + std::vector<std::string> config_secondary_transports_for_usb; // empty + std::vector<std::string> config_secondary_transports_for_bluetooth; + config_secondary_transports_for_bluetooth.push_back("WiFi"); + std::vector<std::string> config_secondary_transports_for_wifi; // empty + std::vector<std::string> config_audio_service_transports; + config_audio_service_transports.push_back("IAP_USB"); + config_audio_service_transports.push_back("IAP_USB_HOST_MODE"); + config_audio_service_transports.push_back("IAP_USB_DEVICE_MODE"); + config_audio_service_transports.push_back("IAP_CARPLAY"); + config_audio_service_transports.push_back("AOA_USB"); + config_audio_service_transports.push_back("TCP_WIFI"); + std::vector<std::string> config_video_service_transports; + config_video_service_transports.push_back("IAP_USB"); + config_video_service_transports.push_back("IAP_USB_HOST_MODE"); + config_video_service_transports.push_back("IAP_USB_DEVICE_MODE"); + config_video_service_transports.push_back("IAP_CARPLAY"); + config_video_service_transports.push_back("AOA_USB"); + config_video_service_transports.push_back("TCP_WIFI"); + + EXPECT_CALL(protocol_handler_settings_mock, max_supported_protocol_version()) + .WillRepeatedly(Return(PROTOCOL_VERSION_5)); + EXPECT_CALL(protocol_handler_settings_mock, multiple_transports_enabled()) + .WillRepeatedly(Return(true)); + EXPECT_CALL(protocol_handler_settings_mock, secondary_transports_for_usb()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_usb)); + EXPECT_CALL(protocol_handler_settings_mock, + secondary_transports_for_bluetooth()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_bluetooth)); + EXPECT_CALL(protocol_handler_settings_mock, secondary_transports_for_wifi()) + .Times(AtLeast(0)) + .WillRepeatedly(ReturnRef(config_secondary_transports_for_wifi)); + EXPECT_CALL(protocol_handler_settings_mock, audio_service_transports()) + .WillOnce(ReturnRef(config_audio_service_transports)); + EXPECT_CALL(protocol_handler_settings_mock, video_service_transports()) + .WillOnce(ReturnRef(config_video_service_transports)); + + // assume the device is iOS and is connected through iAP over Bluetooth + std::string connection_type_string("IAP_BLUETOOTH"); + + EXPECT_CALL(session_observer_mock, + TransportTypeProfileStringFromConnHandle(connection_id)) + .WillRepeatedly(Return(connection_type_string)); + + EXPECT_CALL( + transport_manager_mock, + SendMessageToDevice(ControlMessage( + FRAME_DATA_START_SERVICE_ACK, PROTECTION_OFF, connection_id, _))) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; + + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly( + DoAll(SetArgReferee<2>(PROTOCOL_VERSION_5), Return(true))); + + BsonObject expected_obj; + bson_object_initialize_default(&expected_obj); + // IP address + char empty_ip_address[] = ""; + bson_object_put_string(&expected_obj, + protocol_handler::strings::tcp_ip_address, + empty_ip_address); + // TCP port number should be omitted + + std::vector<uint8_t> expected_param = + CreateVectorFromBsonObject(&expected_obj); + + bson_object_deinitialize(&expected_obj); + + EXPECT_CALL( + transport_manager_mock, + SendMessageToDevice(ControlMessage(FRAME_DATA_TRANSPORT_EVENT_UPDATE, + PROTECTION_OFF, + connection_id, + Eq(expected_param)))) + .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)); +} + +TEST_F(ProtocolHandlerImplTest, + OnTransportConfigUpdated_TransportEventUpdate_TCPEnabled) { + using connection_handler::SessionConnectionMap; + using connection_handler::SessionTransports; + + TestAsyncWaiter waiter; + uint32_t times = 0; + + char tcp_address[] = "172.16.2.3"; + int32_t tcp_port = 23456; + std::string tcp_port_str = "23456"; + + transport_manager::transport_adapter::TransportConfig configs; + configs[transport_manager::transport_adapter::tc_enabled] = + std::string("true"); + configs[transport_manager::transport_adapter::tc_tcp_port] = tcp_port_str; + configs[transport_manager::transport_adapter::tc_tcp_ip_address] = + std::string(tcp_address); + + transport_manager::ConnectionUID device1_primary_connection_id = 100; + transport_manager::ConnectionUID device2_primary_connection_id = 101; + transport_manager::ConnectionUID device2_secondary_connection_id = 150; + + SessionTransports st1 = {device1_primary_connection_id, kDisabledSecondary}; + SessionTransports st2 = {device2_primary_connection_id, + device2_secondary_connection_id}; + session_connection_map_[0x11] = st1; + session_connection_map_[0x22] = st2; + + EXPECT_CALL(connection_handler_mock, session_connection_map()) + .WillOnce(Return(DataAccessor<SessionConnectionMap>( + session_connection_map_, session_connection_map_lock_ptr_))); + + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly( + DoAll(SetArgReferee<2>(PROTOCOL_VERSION_5), Return(true))); + + BsonObject expected_obj; + bson_object_initialize_default(&expected_obj); + // IP address + bson_object_put_string( + &expected_obj, protocol_handler::strings::tcp_ip_address, tcp_address); + // TCP port number + bson_object_put_int32( + &expected_obj, protocol_handler::strings::tcp_port, tcp_port); + + std::vector<uint8_t> expected_param = + CreateVectorFromBsonObject(&expected_obj); + + bson_object_deinitialize(&expected_obj); + + // since device 1 doesn't support secondary transport feature, + // TransportEvetUpdate should be delivered only to device 2 + EXPECT_CALL( + transport_manager_mock, + SendMessageToDevice(ControlMessage(FRAME_DATA_TRANSPORT_EVENT_UPDATE, + PROTECTION_OFF, + device2_primary_connection_id, + Eq(expected_param)))) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; + + tm_listener->OnTransportConfigUpdated(configs); + + EXPECT_TRUE(waiter.WaitFor(times, kAsyncExpectationsTimeout)); +} + +TEST_F(ProtocolHandlerImplTest, + OnTransportConfigUpdated_TransportEventUpdate_TCPDisabled) { + using connection_handler::SessionConnectionMap; + using connection_handler::SessionTransports; + + TestAsyncWaiter waiter; + uint32_t times = 0; + + char tcp_address[] = "172.16.2.3"; + std::string tcp_port_str = "23456"; + + transport_manager::transport_adapter::TransportConfig configs; + configs[transport_manager::transport_adapter::tc_enabled] = + std::string("false"); + configs[transport_manager::transport_adapter::tc_tcp_port] = tcp_port_str; + configs[transport_manager::transport_adapter::tc_tcp_ip_address] = + std::string(tcp_address); + + transport_manager::ConnectionUID device1_primary_connection_id = 100; + transport_manager::ConnectionUID device1_secondary_connection_id = 150; + transport_manager::ConnectionUID device2_primary_connection_id = 101; + transport_manager::ConnectionUID device3_primary_connection_id = 102; + transport_manager::ConnectionUID device3_secondary_connection_id = 151; + + SessionTransports st1 = {device1_primary_connection_id, + device1_secondary_connection_id}; + SessionTransports st2 = {device2_primary_connection_id, kDisabledSecondary}; + SessionTransports st3 = {device3_primary_connection_id, + device3_secondary_connection_id}; + session_connection_map_[0x11] = st1; + session_connection_map_[0x22] = st2; + session_connection_map_[0x33] = st3; + + EXPECT_CALL(connection_handler_mock, session_connection_map()) + .WillOnce(Return(DataAccessor<SessionConnectionMap>( + session_connection_map_, session_connection_map_lock_ptr_))); + + EXPECT_CALL(session_observer_mock, ProtocolVersionUsed(_, _, _)) + .WillRepeatedly( + DoAll(SetArgReferee<2>(PROTOCOL_VERSION_5), Return(true))); + + BsonObject expected_obj; + bson_object_initialize_default(&expected_obj); + // IP address + char empty_ip_address[] = ""; + bson_object_put_string(&expected_obj, + protocol_handler::strings::tcp_ip_address, + empty_ip_address); + // TCP port number should be omitted + + std::vector<uint8_t> expected_param = + CreateVectorFromBsonObject(&expected_obj); + + bson_object_deinitialize(&expected_obj); + + // both device 1 and device 3 should receive TransportEventUpdate frames + EXPECT_CALL( + transport_manager_mock, + SendMessageToDevice(ControlMessage(FRAME_DATA_TRANSPORT_EVENT_UPDATE, + PROTECTION_OFF, + device1_primary_connection_id, + Eq(expected_param)))) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; + EXPECT_CALL( + transport_manager_mock, + SendMessageToDevice(ControlMessage(FRAME_DATA_TRANSPORT_EVENT_UPDATE, + PROTECTION_OFF, + device3_primary_connection_id, + Eq(expected_param)))) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; + + tm_listener->OnTransportConfigUpdated(configs); + + EXPECT_TRUE(waiter.WaitFor(times, kAsyncExpectationsTimeout)); +} + +TEST_F(ProtocolHandlerImplTest, RegisterSecondaryTransport_SUCCESS) { + AddConnection(); + + TestAsyncWaiter waiter; + uint32_t times = 0; + + transport_manager::ConnectionUID primary_connection_id = 123; + + EXPECT_CALL(session_observer_mock, + ProtocolVersionUsed(primary_connection_id, _, _)) + .WillRepeatedly( + DoAll(SetArgReferee<2>(PROTOCOL_VERSION_5), Return(true))); + + EXPECT_CALL(connection_handler_mock, + OnSecondaryTransportStarted(_, connection_id, session_id)) + .WillOnce(DoAll(SetArgReferee<0>(primary_connection_id), Return(true))); + + EXPECT_CALL(transport_manager_mock, + SendMessageToDevice( + ControlMessage(FRAME_DATA_REGISTER_SECONDARY_TRANSPORT_ACK, + PROTECTION_OFF, + connection_id, + _))) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; + + SendControlMessage(PROTECTION_OFF, + kControl, + session_id, + FRAME_DATA_REGISTER_SECONDARY_TRANSPORT, + PROTOCOL_VERSION_5); + + EXPECT_TRUE(waiter.WaitFor(times, kAsyncExpectationsTimeout)); +} + +TEST_F(ProtocolHandlerImplTest, RegisterSecondaryTransport_FAILURE) { + AddConnection(); + + TestAsyncWaiter waiter; + uint32_t times = 0; + + transport_manager::ConnectionUID primary_connection_id = 123; + + EXPECT_CALL(session_observer_mock, + ProtocolVersionUsed(primary_connection_id, _, _)) + .WillRepeatedly( + DoAll(SetArgReferee<2>(PROTOCOL_VERSION_5), Return(true))); + + // check the behavior when OnSecondaryTransportStarted() returns false + EXPECT_CALL(connection_handler_mock, + OnSecondaryTransportStarted(_, connection_id, session_id)) + .WillOnce(DoAll(SetArgReferee<0>(primary_connection_id), Return(false))); + + EXPECT_CALL(transport_manager_mock, + SendMessageToDevice( + ControlMessage(FRAME_DATA_REGISTER_SECONDARY_TRANSPORT_NACK, + PROTECTION_OFF, + connection_id, + _))) + .WillOnce(DoAll(NotifyTestAsyncWaiter(&waiter), Return(E_SUCCESS))); + times++; + + SendControlMessage(PROTECTION_OFF, + kControl, + session_id, + FRAME_DATA_REGISTER_SECONDARY_TRANSPORT, + PROTOCOL_VERSION_5); + + EXPECT_TRUE(waiter.WaitFor(times, kAsyncExpectationsTimeout)); +} + TEST_F(ProtocolHandlerImplTest, DISABLED_FloodVerification) { const size_t period_msec = 10000; const size_t max_messages = 1000; InitProtocolHandlerImpl(period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1529,8 +2686,7 @@ TEST_F(ProtocolHandlerImplTest, DISABLED_FloodVerification_ThresholdValue) { InitProtocolHandlerImpl(period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1566,8 +2722,7 @@ TEST_F(ProtocolHandlerImplTest, DISABLED_FloodVerification_VideoFrameSkip) { InitProtocolHandlerImpl(period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1595,8 +2750,7 @@ TEST_F(ProtocolHandlerImplTest, DISABLED_FloodVerification_AudioFrameSkip) { InitProtocolHandlerImpl(period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1624,8 +2778,7 @@ TEST_F(ProtocolHandlerImplTest, DISABLED_FloodVerificationDisable) { InitProtocolHandlerImpl(period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1653,8 +2806,7 @@ TEST_F(ProtocolHandlerImplTest, MalformedVerificationDisable) { InitProtocolHandlerImpl(0u, 0u, false, period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1686,8 +2838,7 @@ TEST_F(ProtocolHandlerImplTest, DISABLED_MalformedLimitVerification) { InitProtocolHandlerImpl(0u, 0u, true, period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1734,8 +2885,7 @@ TEST_F(ProtocolHandlerImplTest, InitProtocolHandlerImpl(0u, 0u, true, period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1806,8 +2956,7 @@ TEST_F(ProtocolHandlerImplTest, MalformedLimitVerification_MalformedOnly) { InitProtocolHandlerImpl(0u, 0u, true, period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1867,8 +3016,7 @@ TEST_F(ProtocolHandlerImplTest, MalformedLimitVerification_NullTimePeriod) { InitProtocolHandlerImpl(0u, 0u, true, period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1901,8 +3049,7 @@ TEST_F(ProtocolHandlerImplTest, MalformedLimitVerification_NullCount) { InitProtocolHandlerImpl(0u, 0u, true, period_msec, max_messages); AddConnection(); - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1945,8 +3092,7 @@ TEST_F(ProtocolHandlerImplTest, TEST_F(ProtocolHandlerImplTest, DISABLED_SendEndServicePrivate_EndSession_MessageSent) { // Arrange - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1970,8 +3116,7 @@ TEST_F(ProtocolHandlerImplTest, TEST_F(ProtocolHandlerImplTest, SendEndServicePrivate_ServiceTypeControl_MessageSent) { // Arrange - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -1990,7 +3135,8 @@ TEST_F(ProtocolHandlerImplTest, times++; // Act - protocol_handler_impl->SendEndService(connection_id, session_id, kControl); + protocol_handler_impl->SendEndService( + connection_id, connection_id, session_id, kControl); EXPECT_TRUE(waiter->WaitFor(times, kAsyncExpectationsTimeout)); } @@ -2009,8 +3155,7 @@ TEST_F(ProtocolHandlerImplTest, SendHeartBeat_NoConnection_NotSent) { TEST_F(ProtocolHandlerImplTest, SendHeartBeat_Successful) { // Arrange - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -2035,8 +3180,7 @@ TEST_F(ProtocolHandlerImplTest, SendHeartBeat_Successful) { TEST_F(ProtocolHandlerImplTest, SendHeartBeatAck_Successful) { // Arrange - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -2065,8 +3209,7 @@ TEST_F(ProtocolHandlerImplTest, SendHeartBeatAck_Successful) { TEST_F(ProtocolHandlerImplTest, DISABLED_SendHeartBeatAck_WrongProtocolVersion_NotSent) { // Arrange - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -2095,8 +3238,7 @@ TEST_F(ProtocolHandlerImplTest, TEST_F(ProtocolHandlerImplTest, SendMessageToMobileApp_SendSingleControlMessage) { // Arrange - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -2104,7 +3246,7 @@ TEST_F(ProtocolHandlerImplTest, const bool is_final = true; const uint32_t total_data_size = 1; UCharDataVector data(total_data_size); - RawMessagePtr message = utils::MakeShared<RawMessage>( + RawMessagePtr message = std::make_shared<RawMessage>( connection_key, PROTOCOL_VERSION_3, &data[0], total_data_size, kControl); // Expect getting pair from key from session observer EXPECT_CALL(session_observer_mock, @@ -2134,8 +3276,7 @@ TEST_F(ProtocolHandlerImplTest, TEST_F(ProtocolHandlerImplTest, SendMessageToMobileApp_SendSingleNonControlMessage) { // Arrange - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -2143,7 +3284,7 @@ TEST_F(ProtocolHandlerImplTest, const bool is_final = true; const uint32_t total_data_size = 1; UCharDataVector data(total_data_size); - RawMessagePtr message = utils::MakeShared<RawMessage>( + RawMessagePtr message = std::make_shared<RawMessage>( connection_key, PROTOCOL_VERSION_3, &data[0], total_data_size, kRpc); // Expect getting pair from key from session observer EXPECT_CALL(session_observer_mock, @@ -2177,8 +3318,7 @@ TEST_F(ProtocolHandlerImplTest, TEST_F(ProtocolHandlerImplTest, SendMessageToMobileApp_SendMultiframeMessage) { // Arrange - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -2187,7 +3327,7 @@ TEST_F(ProtocolHandlerImplTest, SendMessageToMobileApp_SendMultiframeMessage) { const uint32_t total_data_size = MAXIMUM_FRAME_DATA_V2_SIZE * 2; UCharDataVector data(total_data_size); const uint8_t first_consecutive_frame = 0x01; - RawMessagePtr message = utils::MakeShared<RawMessage>( + RawMessagePtr message = std::make_shared<RawMessage>( connection_key, PROTOCOL_VERSION_3, &data[0], total_data_size, kBulk); // Expect getting pair from key from session observer EXPECT_CALL(session_observer_mock, @@ -2232,8 +3372,7 @@ TEST_F(ProtocolHandlerImplTest, SendMessageToMobileApp_SendMultiframeMessage) { } TEST_F(ProtocolHandlerImplTest, SendServiceDataAck_PreVersion5) { - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); @@ -2259,8 +3398,7 @@ TEST_F(ProtocolHandlerImplTest, SendServiceDataAck_PreVersion5) { } TEST_F(ProtocolHandlerImplTest, SendServiceDataAck_AfterVersion5) { - ::utils::SharedPtr<TestAsyncWaiter> waiter = - utils::MakeShared<TestAsyncWaiter>(); + std::shared_ptr<TestAsyncWaiter> waiter = std::make_shared<TestAsyncWaiter>(); uint32_t times = 0; AddSession(waiter, times); diff --git a/src/components/protocol_handler/test/protocol_header_validator_test.cc b/src/components/protocol_handler/test/protocol_header_validator_test.cc index e42ba96251..5554bfd280 100644 --- a/src/components/protocol_handler/test/protocol_header_validator_test.cc +++ b/src/components/protocol_handler/test/protocol_header_validator_test.cc @@ -230,12 +230,12 @@ TEST_F(ProtocolHeaderValidatorTest, Malformed_FrameType) { } } -// For Control frames Frame info value shall be from 0x00 to 0x06 or 0xFE(Data -// Ack), 0xFF(HB Ack) +// For Control frames Frame info value shall be from 0x00 to 0x09 or 0xFD +// (Transport Update Event), 0xFE(Data Ack), 0xFF(HB Ack) TEST_F(ProtocolHeaderValidatorTest, Malformed_ControlFrame) { std::vector<uint8_t> malformed_frame_data; - for (uint8_t frame_type = FRAME_DATA_END_SERVICE_NACK + 1; - frame_type < FRAME_DATA_SERVICE_DATA_ACK; + for (uint8_t frame_type = FRAME_DATA_REGISTER_SECONDARY_TRANSPORT_NACK + 1; + frame_type < FRAME_DATA_TRANSPORT_EVENT_UPDATE; ++frame_type) { malformed_frame_data.push_back(frame_type); } |