summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjacobkeeler <jacob.keeler@livioradio.com>2019-05-30 15:24:53 -0400
committerjacobkeeler <jacob.keeler@livioradio.com>2019-05-30 15:25:02 -0400
commit2171f329724e8a279748672f35f0af413d7360af (patch)
tree0776285a6b6ebc19c7cf87b657bf9b30429d06e5
parentafc34d149d3b2eebab2df93e4b6783ad7716658f (diff)
parent2be6a9121610ef71235b7e251fd43cc7305aa310 (diff)
downloadsdl_core-2171f329724e8a279748672f35f0af413d7360af.tar.gz
Merge remote-tracking branch 'origin/master' into develop
# Conflicts: # src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_command_factory.cc # src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/mobile_command_factory.cc # src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc # src/components/transport_manager/test/include/transport_manager/cloud/sample_websocket_server.h # src/components/transport_manager/test/sample_websocket_server.cc # src/components/transport_manager/test/transport_adapter_test.cc # src/components/transport_manager/test/websocket_connection_test.cc
-rw-r--r--src/3rd_party/CMakeLists.txt24
-rw-r--r--src/3rd_party/FindBSON.cmake26
-rw-r--r--src/components/application_manager/include/application_manager/smart_object_keys.h13
-rw-r--r--src/components/application_manager/rpc_plugins/app_service_rpc_plugin/include/app_service_rpc_plugin/commands/hmi/as_get_app_service_data_request_from_hmi.h6
-rw-r--r--src/components/application_manager/rpc_plugins/app_service_rpc_plugin/include/app_service_rpc_plugin/commands/hmi/on_as_app_service_data_notification.h6
-rw-r--r--src/components/application_manager/rpc_plugins/app_service_rpc_plugin/src/app_service_mobile_command_factory.cc12
-rw-r--r--src/components/application_manager/rpc_plugins/app_service_rpc_plugin/src/commands/hmi/as_get_app_service_data_request_from_hmi.cc188
-rw-r--r--src/components/application_manager/rpc_plugins/app_service_rpc_plugin/src/commands/hmi/on_as_app_service_data_notification.cc144
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_command_factory.h14
-rw-r--r--src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_command_factory.cc73
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/mobile_command_factory.h13
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/mobile_command_factory.cc94
-rw-r--r--src/components/application_manager/rpc_plugins/vehicle_info_plugin/include/vehicle_info_plugin/vehicle_info_mobile_command_factory.h11
-rw-r--r--src/components/application_manager/rpc_plugins/vehicle_info_plugin/src/vehicle_info_mobile_command_factory.cc88
-rw-r--r--src/components/application_manager/src/commands/command_notification_from_mobile_impl.cc2
-rw-r--r--src/components/application_manager/src/commands/notification_from_hmi.cc2
-rw-r--r--src/components/application_manager/src/smart_object_keys.cc13
-rw-r--r--src/components/protocol_handler/src/protocol_handler_impl.cc112
-rw-r--r--src/components/transport_manager/include/transport_manager/cloud/cloud_device.h15
-rw-r--r--src/components/transport_manager/src/cloud/cloud_device.cc28
-rw-r--r--src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc49
-rw-r--r--src/components/transport_manager/src/cloud/websocket_client_connection.cc4
-rw-r--r--src/components/transport_manager/test/include/transport_manager/cloud/sample_websocket_server.h39
-rw-r--r--src/components/transport_manager/test/sample_websocket_server.cc189
-rw-r--r--src/components/transport_manager/test/transport_adapter_test.cc212
-rw-r--r--src/components/transport_manager/test/websocket_connection_test.cc156
26 files changed, 1301 insertions, 232 deletions
diff --git a/src/3rd_party/CMakeLists.txt b/src/3rd_party/CMakeLists.txt
index c0c6bbfa67..951c437e59 100644
--- a/src/3rd_party/CMakeLists.txt
+++ b/src/3rd_party/CMakeLists.txt
@@ -169,12 +169,13 @@ if(ENABLE_LOG)
endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}")
-set(CMAKE_SOURCE_PREFIX ${CMAKE_SOURCE_PREFIX} "${3RD_PARTY_INSTALL_PREFIX}")
-find_package (BSON)
-message (STATUS "bson installed in " ${BSON_LIBS_DIRECTORY} " , " ${BSON_INCLUDE_DIRECTORY})
-message (STATUS "emhashmap installed in " ${EMHASHMAP_LIBS_DIRECTORY} " , " ${EMHASHMAP_INCLUDE_DIRECTORY})
+set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "${3RD_PARTY_INSTALL_PREFIX}/etc")
+set(ENV{PKG_CONFIG_PATH} $ENV{CMAKE_PREFIX_PATH} "${3RD_PARTY_INSTALL_PREFIX}/etc")
+find_package(PkgConfig)
+pkg_check_modules(BSON libbson)
+message (STATUS "bson installed in " ${BSON_LIBDIR} ", " ${BSON_INCLUDEDIR})
-if (${BSON_LIB} MATCHES "BSON_LIB-NOTFOUND")
+if ((NOT "${BSON_FOUND}") OR ("${BSON_VERSION}" VERSION_LESS "1.2.0"))
message (STATUS "Building bson required")
set(BSON_LIB_SOURCE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bson_c_lib CACHE INTERNAL "Sources of bson library" FORCE)
set(BSON_LIBS_DIRECTORY ${3RD_PARTY_INSTALL_PREFIX}/lib CACHE INTERNAL "Installation path of bson libraries" FORCE)
@@ -188,20 +189,19 @@ if (${BSON_LIB} MATCHES "BSON_LIB-NOTFOUND")
endif()
include(ExternalProject)
ExternalProject_Add(libbson
- GIT_REPOSITORY "http://github.com/smartdevicelink/bson_c_lib.git"
+ GIT_REPOSITORY "https://github.com/smartdevicelink/bson_c_lib.git"
GIT_TAG "master"
BINARY_DIR ${BSON_LIB_SOURCE_DIRECTORY}
INSTALL_DIR ${3RD_PARTY_INSTALL_PREFIX}
DOWNLOAD_DIR ${BSON_LIB_SOURCE_DIRECTORY}
SOURCE_DIR ${BSON_LIB_SOURCE_DIRECTORY}
- CONFIGURE_COMMAND touch aclocal.m4 configure.ac Makefile.am Makefile.in configure config.h.in && ./configure --prefix=${3RD_PARTY_INSTALL_PREFIX}
+ CONFIGURE_COMMAND touch aclocal.m4 configure.ac Makefile.am Makefile.in configure config.h.in libbson.pc.in && ./configure --prefix=${3RD_PARTY_INSTALL_PREFIX}
BUILD_COMMAND make
- INSTALL_COMMAND ${BSON_INSTALL_COMMAND})
+ INSTALL_COMMAND ${BSON_INSTALL_COMMAND}
+ UPDATE_COMMAND git pull)
else()
- get_filename_component(BSON_LIBS_DIRECTORY ${BSON_LIB} DIRECTORY)
- get_filename_component(EMHASHMAP_LIBS_DIRECTORY ${EMHASHMAP_LIB} DIRECTORY)
- set(BSON_LIBS_DIRECTORY ${BSON_LIBS_DIRECTORY} CACHE INTERNAL "Installation path of bson libraries" FORCE)
- set(EMHASHMAP_LIBS_DIRECTORY ${BSON_LIBS_DIRECTORY} CACHE INTERNAL "Installation path of emashmap libraries" FORCE)
+ set(BSON_LIBS_DIRECTORY ${BSON_LIBDIR} CACHE INTERNAL "Installation path of bson libraries" FORCE)
+ set(EMHASHMAP_LIBS_DIRECTORY ${BSON_LIBDIR} CACHE INTERNAL "Installation path of emashmap libraries" FORCE)
add_custom_target(
libbson
DEPENDS ${BSON_LIBS_DIRECTORY}
diff --git a/src/3rd_party/FindBSON.cmake b/src/3rd_party/FindBSON.cmake
deleted file mode 100644
index 91d53624f1..0000000000
--- a/src/3rd_party/FindBSON.cmake
+++ /dev/null
@@ -1,26 +0,0 @@
-set(INCLUDE_PATH "${CMAKE_SOURCE_PREFIX}/include")
-set(LIB_PATH "${CMAKE_SOURCE_PREFIX}/lib")
-
-find_path(BSON_INCLUDE_DIRECTORY bson_object.h bson_array.h bson_util.h
- PATHS "${INCLUDE_PATH}")
-
-find_library(BSON_LIB
- NAMES bson
- PATHS ${LIB_PATH})
-
-find_path(EMHASHMAP_INCLUDE_DIRECTORY emhashmap.h
- PATHS ${INCLUDE_PATH}
- PATH_SUFFIXES emhashmap)
-
-find_library(EMHASHMAP_LIB
- NAMES emhashmap
- PATHS ${LIB_PATH})
-
-
-include(FindPackageHandleStandardArgs)
-
-find_package_handle_standard_args(BSON DEFAULT_MSG BSON_INCLUDE_DIRECTORY BSON_LIB
- EMHASHMAP_INCLUDE_DIRECTORY EMHASHMAP_LIB)
-
-mark_as_advanced(BSON_INCLUDE_DIRECTORY BSON_LIB)
-mark_as_advanced(EMHASHMAP_INCLUDE_DIRECTORY EMHASHMAP_LIB)
diff --git a/src/components/application_manager/include/application_manager/smart_object_keys.h b/src/components/application_manager/include/application_manager/smart_object_keys.h
index c5c50e5da1..65ec4f15c3 100644
--- a/src/components/application_manager/include/application_manager/smart_object_keys.h
+++ b/src/components/application_manager/include/application_manager/smart_object_keys.h
@@ -321,6 +321,19 @@ extern const char* service_published;
extern const char* service_active;
extern const char* app_service_id;
extern const char* service_data;
+extern const char* media_service_data;
+extern const char* weather_service_data;
+extern const char* location;
+extern const char* current_forecast;
+extern const char* minute_forecast;
+extern const char* hourly_forecast;
+extern const char* multiday_forecast;
+extern const char* weather_icon;
+extern const char* navigation_service_data;
+extern const char* origin;
+extern const char* destination;
+extern const char* instructions;
+extern const char* location_details;
extern const char* request_service_active;
extern const char* app_services;
extern const char* update_reason;
diff --git a/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/include/app_service_rpc_plugin/commands/hmi/as_get_app_service_data_request_from_hmi.h b/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/include/app_service_rpc_plugin/commands/hmi/as_get_app_service_data_request_from_hmi.h
index 7b175fc0d4..531d1816e9 100644
--- a/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/include/app_service_rpc_plugin/commands/hmi/as_get_app_service_data_request_from_hmi.h
+++ b/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/include/app_service_rpc_plugin/commands/hmi/as_get_app_service_data_request_from_hmi.h
@@ -88,6 +88,12 @@ class ASGetAppServiceDataRequestFromHMI
void on_event(const app_mngr::event_engine::MobileEvent& event) OVERRIDE;
private:
+ void GetWeatherImagePaths(smart_objects::SmartObject& data,
+ application_manager::ApplicationSharedPtr app);
+ void GetNavigationImagePaths(smart_objects::SmartObject& data,
+ application_manager::ApplicationSharedPtr app);
+ bool ValidateResponse(smart_objects::SmartObject& message_params);
+
DISALLOW_COPY_AND_ASSIGN(ASGetAppServiceDataRequestFromHMI);
};
diff --git a/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/include/app_service_rpc_plugin/commands/hmi/on_as_app_service_data_notification.h b/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/include/app_service_rpc_plugin/commands/hmi/on_as_app_service_data_notification.h
index 30af13038a..cff7c8e5b8 100644
--- a/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/include/app_service_rpc_plugin/commands/hmi/on_as_app_service_data_notification.h
+++ b/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/include/app_service_rpc_plugin/commands/hmi/on_as_app_service_data_notification.h
@@ -70,6 +70,12 @@ class OnASAppServiceDataNotification
virtual void Run();
private:
+ void GetWeatherImagePaths(smart_objects::SmartObject& data,
+ application_manager::ApplicationSharedPtr app);
+ void GetNavigationImagePaths(smart_objects::SmartObject& data,
+ application_manager::ApplicationSharedPtr app);
+ bool ValidateParams(smart_objects::SmartObject& message_params);
+
DISALLOW_COPY_AND_ASSIGN(OnASAppServiceDataNotification);
};
diff --git a/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/src/app_service_mobile_command_factory.cc b/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/src/app_service_mobile_command_factory.cc
index 7a62f7a4c7..76be96cf8f 100644
--- a/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/src/app_service_mobile_command_factory.cc
+++ b/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/src/app_service_mobile_command_factory.cc
@@ -111,9 +111,15 @@ app_mngr::CommandCreator& AppServiceMobileCommandFactory::buildCommandCreator(
switch (function_id) {
case mobile_apis::FunctionID::PublishAppServiceID:
- return mobile_apis::messageType::request == message_type
- ? factory.GetCreator<commands::PublishAppServiceRequest>()
- : factory.GetCreator<commands::PublishAppServiceResponse>();
+ if (app_mngr::commands::Command::CommandSource::SOURCE_MOBILE == source &&
+ mobile_apis::messageType::response != message_type) {
+ return factory.GetCreator<commands::PublishAppServiceRequest>();
+ } else if (app_mngr::commands::Command::CommandSource::SOURCE_SDL ==
+ source &&
+ mobile_apis::messageType::request != message_type) {
+ return factory.GetCreator<commands::PublishAppServiceResponse>();
+ }
+ break;
case mobile_apis::FunctionID::OnAppServiceDataID:
return app_mngr::commands::Command::CommandSource::SOURCE_MOBILE == source
? factory.GetCreator<
diff --git a/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/src/commands/hmi/as_get_app_service_data_request_from_hmi.cc b/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/src/commands/hmi/as_get_app_service_data_request_from_hmi.cc
index a339ffb9a6..2da8834b96 100644
--- a/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/src/commands/hmi/as_get_app_service_data_request_from_hmi.cc
+++ b/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/src/commands/hmi/as_get_app_service_data_request_from_hmi.cc
@@ -31,6 +31,7 @@
*/
#include "app_service_rpc_plugin/commands/hmi/as_get_app_service_data_request_from_hmi.h"
+#include "application_manager/app_service_manager.h"
#include "application_manager/application_impl.h"
#include "application_manager/rpc_service.h"
#include "interfaces/MOBILE_API.h"
@@ -70,30 +71,180 @@ void ASGetAppServiceDataRequestFromHMI::Run() {
true);
}
+void ASGetAppServiceDataRequestFromHMI::GetWeatherImagePaths(
+ smart_objects::SmartObject& data, ApplicationSharedPtr app) {
+ if (data[strings::location].keyExists(strings::location_image)) {
+ MessageHelper::VerifyImage(data[strings::location][strings::location_image],
+ app,
+ application_manager_);
+ }
+
+ if (data.keyExists(strings::current_forecast) &&
+ data[strings::current_forecast].keyExists(strings::weather_icon)) {
+ MessageHelper::VerifyImage(
+ data[strings::current_forecast][strings::weather_icon],
+ app,
+ application_manager_);
+ }
+
+ if (data.keyExists(strings::minute_forecast)) {
+ smart_objects::SmartObject& minute_forecast =
+ data[strings::minute_forecast];
+ for (size_t i = 0; i < minute_forecast.length(); i++) {
+ if (minute_forecast[i].keyExists(strings::weather_icon)) {
+ MessageHelper::VerifyImage(minute_forecast[i][strings::weather_icon],
+ app,
+ application_manager_);
+ }
+ }
+ }
+
+ if (data.keyExists(strings::hourly_forecast)) {
+ smart_objects::SmartObject& hourly_forecast =
+ data[strings::hourly_forecast];
+ for (size_t i = 0; i < hourly_forecast.length(); i++) {
+ if (hourly_forecast[i].keyExists(strings::weather_icon)) {
+ MessageHelper::VerifyImage(hourly_forecast[i][strings::weather_icon],
+ app,
+ application_manager_);
+ }
+ }
+ }
+
+ if (data.keyExists(strings::multiday_forecast)) {
+ smart_objects::SmartObject& multiday_forecast =
+ data[strings::multiday_forecast];
+ for (size_t i = 0; i < multiday_forecast.length(); i++) {
+ if (multiday_forecast[i].keyExists(strings::weather_icon)) {
+ MessageHelper::VerifyImage(multiday_forecast[i][strings::weather_icon],
+ app,
+ application_manager_);
+ }
+ }
+ }
+}
+
+void ASGetAppServiceDataRequestFromHMI::GetNavigationImagePaths(
+ smart_objects::SmartObject& data, ApplicationSharedPtr app) {
+ if (data.keyExists(strings::origin) &&
+ data[strings::origin].keyExists(strings::location_image)) {
+ MessageHelper::VerifyImage(data[strings::origin][strings::location_image],
+ app,
+ application_manager_);
+ }
+
+ if (data.keyExists(strings::destination) &&
+ data[strings::destination].keyExists(strings::location_image)) {
+ MessageHelper::VerifyImage(
+ data[strings::destination][strings::location_image],
+ app,
+ application_manager_);
+ }
+
+ if (data.keyExists(strings::instructions)) {
+ smart_objects::SmartObject& instructions = data[strings::instructions];
+ for (size_t i = 0; i < instructions.length(); i++) {
+ if (instructions[i].keyExists(strings::image)) {
+ MessageHelper::VerifyImage(
+ instructions[i][strings::image], app, application_manager_);
+ }
+
+ if (instructions[i].keyExists(strings::location_details) &&
+ instructions[i][strings::location_details].keyExists(
+ strings::location_image)) {
+ MessageHelper::VerifyImage(
+ instructions[i][strings::location_details][strings::location_image],
+ app,
+ application_manager_);
+ }
+ }
+ }
+}
+
+bool ASGetAppServiceDataRequestFromHMI::ValidateResponse(
+ smart_objects::SmartObject& message_params) {
+ if (!message_params.keyExists(strings::service_data)) {
+ LOG4CXX_DEBUG(
+ logger_,
+ "GASD response received without any service data, passing through");
+ return true;
+ }
+ smart_objects::SmartObject& service_data =
+ message_params[strings::service_data];
+ std::string service_type = service_data[strings::service_type].asString();
+ mobile_apis::AppServiceType::eType service_type_value;
+ const std::string& service_id = service_data[strings::service_id].asString();
+ auto service =
+ application_manager_.GetAppServiceManager().FindServiceByID(service_id);
+ if (!service) {
+ LOG4CXX_ERROR(logger_,
+ "GASD response received with an unpublished service ID");
+ SendErrorResponse(
+ correlation_id(),
+ hmi_apis::FunctionID::AppService_GetAppServiceData,
+ hmi_apis::Common_Result::GENERIC_ERROR,
+ "The provider responded with incorrect data",
+ application_manager::commands::Command::SOURCE_SDL_TO_HMI);
+ return false;
+ }
+
+ using namespace ns_smart_device_link::ns_smart_objects;
+ if (service && service->mobile_service &&
+ EnumConversionHelper<mobile_apis::AppServiceType::eType>::StringToEnum(
+ service_type, &service_type_value)) {
+ auto app = application_manager_.application(service->connection_key);
+ if (!app) {
+ LOG4CXX_ERROR(logger_,
+ "Failed to find service provider for GASD response");
+ SendErrorResponse(
+ correlation_id(),
+ hmi_apis::FunctionID::AppService_GetAppServiceData,
+ hmi_apis::Common_Result::GENERIC_ERROR,
+ "The provider responded with incorrect data",
+ application_manager::commands::Command::SOURCE_SDL_TO_HMI);
+ return false;
+ }
+
+ if (service_type_value == mobile_apis::AppServiceType::WEATHER &&
+ service_data.keyExists(strings::weather_service_data)) {
+ GetWeatherImagePaths(service_data[strings::weather_service_data], app);
+ }
+
+ if (service_type_value == mobile_apis::AppServiceType::NAVIGATION &&
+ service_data.keyExists(strings::navigation_service_data)) {
+ GetNavigationImagePaths(service_data[strings::navigation_service_data],
+ app);
+ }
+ }
+ return true;
+}
+
void ASGetAppServiceDataRequestFromHMI::on_event(
const event_engine::Event& event) {
- const smart_objects::SmartObject& event_message = event.smart_object();
+ smart_objects::SmartObject event_message(event.smart_object());
- auto msg_params = event_message[strings::msg_params];
+ auto& msg_params = event_message[strings::msg_params];
hmi_apis::Common_Result::eType result =
static_cast<hmi_apis::Common_Result::eType>(
event_message[strings::params][hmi_response::code].asInt());
bool success =
IsHMIResultSuccess(result, HmiInterfaces::HMI_INTERFACE_AppService);
- SendResponse(success,
- correlation_id(),
- hmi_apis::FunctionID::AppService_GetAppServiceData,
- result,
- &msg_params,
- application_manager::commands::Command::SOURCE_SDL_TO_HMI);
+ if (ValidateResponse(msg_params)) {
+ SendResponse(success,
+ correlation_id(),
+ hmi_apis::FunctionID::AppService_GetAppServiceData,
+ result,
+ &msg_params,
+ application_manager::commands::Command::SOURCE_SDL_TO_HMI);
+ }
}
void ASGetAppServiceDataRequestFromHMI::on_event(
const event_engine::MobileEvent& event) {
- const smart_objects::SmartObject& event_message = event.smart_object();
+ smart_objects::SmartObject event_message(event.smart_object());
- auto msg_params = event_message[strings::msg_params];
+ auto& msg_params = event_message[strings::msg_params];
mobile_apis::Result::eType mobile_result =
static_cast<mobile_apis::Result::eType>(
@@ -102,19 +253,18 @@ void ASGetAppServiceDataRequestFromHMI::on_event(
MessageHelper::MobileToHMIResult(mobile_result);
bool success = IsMobileResultSuccess(mobile_result);
- SendResponse(success,
- correlation_id(),
- hmi_apis::FunctionID::AppService_GetAppServiceData,
- result,
- &msg_params,
- application_manager::commands::Command::SOURCE_SDL_TO_HMI);
+ if (ValidateResponse(msg_params)) {
+ SendResponse(success,
+ correlation_id(),
+ hmi_apis::FunctionID::AppService_GetAppServiceData,
+ result,
+ &msg_params,
+ application_manager::commands::Command::SOURCE_SDL_TO_HMI);
+ }
}
void ASGetAppServiceDataRequestFromHMI::onTimeOut() {
LOG4CXX_AUTO_TRACE(logger_);
- smart_objects::SmartObject response_params;
- response_params[strings::info] =
- "The provider did not respond to the request";
SendErrorResponse(correlation_id(),
hmi_apis::FunctionID::AppService_GetAppServiceData,
hmi_apis::Common_Result::GENERIC_ERROR,
diff --git a/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/src/commands/hmi/on_as_app_service_data_notification.cc b/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/src/commands/hmi/on_as_app_service_data_notification.cc
index 80dd88c15f..e90de23837 100644
--- a/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/src/commands/hmi/on_as_app_service_data_notification.cc
+++ b/src/components/application_manager/rpc_plugins/app_service_rpc_plugin/src/commands/hmi/on_as_app_service_data_notification.cc
@@ -31,6 +31,11 @@
*/
#include "app_service_rpc_plugin/commands/hmi/on_as_app_service_data_notification.h"
+#include "application_manager/app_service_manager.h"
+#include "application_manager/application_impl.h"
+#include "application_manager/message_helper.h"
+#include "interfaces/MOBILE_API.h"
+#include "smart_objects/enum_schema_item.h"
namespace app_service_rpc_plugin {
using namespace application_manager;
@@ -50,10 +55,147 @@ OnASAppServiceDataNotification::OnASAppServiceDataNotification(
OnASAppServiceDataNotification::~OnASAppServiceDataNotification() {}
+void OnASAppServiceDataNotification::GetWeatherImagePaths(
+ smart_objects::SmartObject& data, ApplicationSharedPtr app) {
+ if (data[strings::location].keyExists(strings::location_image)) {
+ MessageHelper::VerifyImage(data[strings::location][strings::location_image],
+ app,
+ application_manager_);
+ }
+
+ if (data.keyExists(strings::current_forecast) &&
+ data[strings::current_forecast].keyExists(strings::weather_icon)) {
+ MessageHelper::VerifyImage(
+ data[strings::current_forecast][strings::weather_icon],
+ app,
+ application_manager_);
+ }
+
+ if (data.keyExists(strings::minute_forecast)) {
+ smart_objects::SmartObject& minute_forecast =
+ data[strings::minute_forecast];
+ for (size_t i = 0; i < minute_forecast.length(); i++) {
+ if (minute_forecast[i].keyExists(strings::weather_icon)) {
+ MessageHelper::VerifyImage(minute_forecast[i][strings::weather_icon],
+ app,
+ application_manager_);
+ }
+ }
+ }
+
+ if (data.keyExists(strings::hourly_forecast)) {
+ smart_objects::SmartObject& hourly_forecast =
+ data[strings::hourly_forecast];
+ for (size_t i = 0; i < hourly_forecast.length(); i++) {
+ if (hourly_forecast[i].keyExists(strings::weather_icon)) {
+ MessageHelper::VerifyImage(hourly_forecast[i][strings::weather_icon],
+ app,
+ application_manager_);
+ }
+ }
+ }
+
+ if (data.keyExists(strings::multiday_forecast)) {
+ smart_objects::SmartObject& multiday_forecast =
+ data[strings::multiday_forecast];
+ for (size_t i = 0; i < multiday_forecast.length(); i++) {
+ if (multiday_forecast[i].keyExists(strings::weather_icon)) {
+ MessageHelper::VerifyImage(multiday_forecast[i][strings::weather_icon],
+ app,
+ application_manager_);
+ }
+ }
+ }
+}
+
+void OnASAppServiceDataNotification::GetNavigationImagePaths(
+ smart_objects::SmartObject& data, ApplicationSharedPtr app) {
+ if (data.keyExists(strings::origin) &&
+ data[strings::origin].keyExists(strings::location_image)) {
+ MessageHelper::VerifyImage(data[strings::origin][strings::location_image],
+ app,
+ application_manager_);
+ }
+
+ if (data.keyExists(strings::destination) &&
+ data[strings::destination].keyExists(strings::location_image)) {
+ MessageHelper::VerifyImage(
+ data[strings::destination][strings::location_image],
+ app,
+ application_manager_);
+ }
+
+ if (data.keyExists(strings::instructions)) {
+ smart_objects::SmartObject& instructions = data[strings::instructions];
+ for (size_t i = 0; i < instructions.length(); i++) {
+ if (instructions[i].keyExists(strings::image)) {
+ MessageHelper::VerifyImage(
+ instructions[i][strings::image], app, application_manager_);
+ }
+
+ if (instructions[i].keyExists(strings::location_details) &&
+ instructions[i][strings::location_details].keyExists(
+ strings::location_image)) {
+ MessageHelper::VerifyImage(
+ instructions[i][strings::location_details][strings::location_image],
+ app,
+ application_manager_);
+ }
+ }
+ }
+}
+
+bool OnASAppServiceDataNotification::ValidateParams(
+ smart_objects::SmartObject& message_params) {
+ if (!message_params.keyExists(strings::service_data)) {
+ LOG4CXX_DEBUG(logger_,
+ "OASD notification received without any service data");
+ return false;
+ }
+ smart_objects::SmartObject& service_data =
+ message_params[strings::service_data];
+ std::string service_type = service_data[strings::service_type].asString();
+ mobile_apis::AppServiceType::eType service_type_value;
+ const std::string& service_id = service_data[strings::service_id].asString();
+ auto service =
+ application_manager_.GetAppServiceManager().FindServiceByID(service_id);
+ if (!service) {
+ LOG4CXX_ERROR(logger_,
+ "OASD notification received with an unpublished service ID");
+ return false;
+ }
+
+ using namespace ns_smart_device_link::ns_smart_objects;
+ if (service && service->mobile_service &&
+ EnumConversionHelper<mobile_apis::AppServiceType::eType>::StringToEnum(
+ service_type, &service_type_value)) {
+ auto app = application_manager_.application(service->connection_key);
+ if (!app) {
+ LOG4CXX_ERROR(logger_,
+ "Failed to find service provider for OASD message");
+ return false;
+ }
+
+ if (service_type_value == mobile_apis::AppServiceType::WEATHER &&
+ service_data.keyExists(strings::weather_service_data)) {
+ GetWeatherImagePaths(service_data[strings::weather_service_data], app);
+ }
+
+ if (service_type_value == mobile_apis::AppServiceType::NAVIGATION &&
+ service_data.keyExists(strings::navigation_service_data)) {
+ GetNavigationImagePaths(service_data[strings::navigation_service_data],
+ app);
+ }
+ }
+ return true;
+}
+
void OnASAppServiceDataNotification::Run() {
LOG4CXX_AUTO_TRACE(logger_);
LOG4CXX_DEBUG(logger_, "Sending AS data to HMI");
- SendNotification();
+ if (ValidateParams((*message_)[strings::msg_params])) {
+ SendNotification();
+ }
}
} // namespace commands
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_command_factory.h b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_command_factory.h
index 0cae8dd4de..aa01b608b4 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_command_factory.h
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/include/rc_rpc_plugin/rc_command_factory.h
@@ -74,12 +74,18 @@ class RCCommandFactory : public application_manager::CommandFactory {
private:
app_mngr::CommandCreator& get_mobile_creator_factory(
- mobile_apis::FunctionID::eType id,
- mobile_apis::messageType::eType message_type) const;
+ const mobile_apis::FunctionID::eType id,
+ const mobile_apis::messageType::eType message_type,
+ const app_mngr::commands::Command::CommandSource source) const;
+ app_mngr::CommandCreator& get_mobile_command_creator(
+ const mobile_apis::FunctionID::eType id,
+ const mobile_apis::messageType::eType message_type) const;
+ app_mngr::CommandCreator& get_mobile_notification_creator(
+ const mobile_apis::FunctionID::eType id) const;
app_mngr::CommandCreator& get_hmi_creator_factory(
- hmi_apis::FunctionID::eType id,
- hmi_apis::messageType::eType message_type) const;
+ const hmi_apis::FunctionID::eType id,
+ const hmi_apis::messageType::eType message_type) const;
RCCommandParams params_;
};
diff --git a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_command_factory.cc b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_command_factory.cc
index 67329f2a31..93c230dfc3 100644
--- a/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_command_factory.cc
+++ b/src/components/application_manager/rpc_plugins/rc_rpc_plugin/src/rc_command_factory.cc
@@ -144,7 +144,7 @@ CommandSharedPtr RCCommandFactory::CreateCommand(
static_cast<mobile_apis::FunctionID::eType>(
(*message)[strings::params][strings::function_id].asInt());
- return get_mobile_creator_factory(function_id, message_type)
+ return get_mobile_creator_factory(function_id, message_type, source)
.create(message);
}
}
@@ -161,52 +161,91 @@ bool RCCommandFactory::IsAbleToProcess(
hmi_apis::messageType::INVALID_ENUM)
.CanBeCreated();
} else {
- return get_mobile_creator_factory(
- static_cast<mobile_api::FunctionID::eType>(function_id),
- mobile_api::messageType::INVALID_ENUM)
- .CanBeCreated();
+ auto id = static_cast<mobile_apis::FunctionID::eType>(function_id);
+ return get_mobile_command_creator(id,
+ mobile_apis::messageType::INVALID_ENUM)
+ .CanBeCreated() ||
+ get_mobile_notification_creator(id).CanBeCreated();
}
}
-CommandCreator& RCCommandFactory::get_mobile_creator_factory(
- mobile_api::FunctionID::eType id,
- mobile_api::messageType::eType message_type) const {
+CommandCreator& RCCommandFactory::get_mobile_command_creator(
+ const mobile_apis::FunctionID::eType id,
+ const mobile_apis::messageType::eType message_type) const {
LOG4CXX_DEBUG(logger_,
- "CreateMobileCommand function_id: " << id << " message_type: "
- << message_type);
+ "get_mobile_command_creator function_id: "
+ << id << " message_type: " << message_type);
RCCommandCreatorFactory rc_factory(params_);
-
switch (id) {
case mobile_apis::FunctionID::ButtonPressID: {
- return mobile_api::messageType::request == message_type
+ return mobile_apis::messageType::request == message_type
? rc_factory.GetCreator<commands::ButtonPressRequest>()
: rc_factory.GetCreator<commands::ButtonPressResponse>();
}
case mobile_apis::FunctionID::GetInteriorVehicleDataID: {
- return mobile_api::messageType::request == message_type
+ return mobile_apis::messageType::request == message_type
? rc_factory
.GetCreator<commands::GetInteriorVehicleDataRequest>()
: rc_factory
.GetCreator<commands::GetInteriorVehicleDataResponse>();
}
case mobile_apis::FunctionID::SetInteriorVehicleDataID: {
- return mobile_api::messageType::request == message_type
+ return mobile_apis::messageType::request == message_type
? rc_factory
.GetCreator<commands::SetInteriorVehicleDataRequest>()
: rc_factory
.GetCreator<commands::SetInteriorVehicleDataResponse>();
}
+ default: {}
+ }
+ return rc_factory.GetCreator<RCInvalidCommand>();
+}
+
+CommandCreator& RCCommandFactory::get_mobile_notification_creator(
+ const mobile_apis::FunctionID::eType id) const {
+ RCCommandCreatorFactory rc_factory(params_);
+ switch (id) {
case mobile_apis::FunctionID::OnInteriorVehicleDataID: {
return rc_factory
.GetCreator<commands::OnInteriorVehicleDataNotification>();
}
- default: { return rc_factory.GetCreator<RCInvalidCommand>(); }
+ default: {}
+ }
+ return rc_factory.GetCreator<RCInvalidCommand>();
+}
+
+CommandCreator& RCCommandFactory::get_mobile_creator_factory(
+ const mobile_apis::FunctionID::eType id,
+ const mobile_apis::messageType::eType message_type,
+ const app_mngr::commands::Command::CommandSource source) const {
+ RCCommandCreatorFactory rc_factory(params_);
+ switch (message_type) {
+ case mobile_apis::messageType::request: {
+ if (app_mngr::commands::Command::CommandSource::SOURCE_MOBILE == source) {
+ return get_mobile_command_creator(id, message_type);
+ }
+ break;
+ }
+ case mobile_apis::messageType::response: {
+ if (app_mngr::commands::Command::CommandSource::SOURCE_SDL == source) {
+ return get_mobile_command_creator(id, message_type);
+ }
+ break;
+ }
+ case mobile_apis::messageType::notification: {
+ if (app_mngr::commands::Command::CommandSource::SOURCE_SDL == source) {
+ return get_mobile_notification_creator(id);
+ }
+ break;
+ }
+ default: {}
}
+ return rc_factory.GetCreator<RCInvalidCommand>();
}
CommandCreator& RCCommandFactory::get_hmi_creator_factory(
- hmi_apis::FunctionID::eType id,
- hmi_apis::messageType::eType message_type) const {
+ const hmi_apis::FunctionID::eType id,
+ const hmi_apis::messageType::eType message_type) const {
LOG4CXX_DEBUG(logger_,
"CreateHMICommand function_id: " << id << " message_type: "
<< message_type);
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/mobile_command_factory.h b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/mobile_command_factory.h
index d8f790c70e..132b68aaec 100644
--- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/mobile_command_factory.h
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/mobile_command_factory.h
@@ -59,9 +59,16 @@ class MobileCommandFactory : public app_mngr::CommandFactory {
private:
app_mngr::CommandCreator& get_creator_factory(
- mobile_apis::FunctionID::eType id,
- mobile_apis::messageType::eType message_type,
- app_mngr::commands::Command::CommandSource source) const;
+ const mobile_apis::FunctionID::eType id,
+ const mobile_apis::messageType::eType message_type,
+ const app_mngr::commands::Command::CommandSource source) const;
+ app_mngr::CommandCreator& get_command_creator(
+ const mobile_apis::FunctionID::eType id,
+ const mobile_apis::messageType::eType message_type) const;
+ app_mngr::CommandCreator& get_notification_creator(
+ const mobile_apis::FunctionID::eType id) const;
+ app_mngr::CommandCreator& get_notification_from_mobile_creator(
+ const mobile_apis::FunctionID::eType id) const;
app_mngr::ApplicationManager& application_manager_;
app_mngr::rpc_service::RPCService& rpc_service_;
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/mobile_command_factory.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/mobile_command_factory.cc
index 8c37e5729d..1a1d4f725c 100644
--- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/mobile_command_factory.cc
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/mobile_command_factory.cc
@@ -137,13 +137,11 @@ CREATE_LOGGERPTR_GLOBAL(logger_, "ApplicationManager")
namespace sdl_rpc_plugin {
using namespace application_manager;
-CommandCreator& MobileCommandFactory::get_creator_factory(
- mobile_apis::FunctionID::eType id,
- mobile_apis::messageType::eType message_type,
- app_mngr::commands::Command::CommandSource source) const {
+CommandCreator& MobileCommandFactory::get_command_creator(
+ const mobile_apis::FunctionID::eType id,
+ const mobile_apis::messageType::eType message_type) const {
CommandCreatorFactory factory(
application_manager_, rpc_service_, hmi_capabilities_, policy_handler_);
-
switch (id) {
case mobile_apis::FunctionID::RegisterAppInterfaceID: {
return mobile_api::messageType::request == message_type
@@ -182,7 +180,6 @@ CommandCreator& MobileCommandFactory::get_creator_factory(
? factory.GetCreator<commands::AddSubMenuRequest>()
: factory.GetCreator<commands::AddSubMenuResponse>();
}
-
case mobile_apis::FunctionID::DeleteSubMenuID: {
return mobile_api::messageType::request == message_type
? factory.GetCreator<commands::DeleteSubMenuRequest>()
@@ -215,7 +212,6 @@ CommandCreator& MobileCommandFactory::get_creator_factory(
? factory.GetCreator<commands::PerformAudioPassThruRequest>()
: factory.GetCreator<commands::PerformAudioPassThruResponse>();
}
-
case mobile_apis::FunctionID::CreateInteractionChoiceSetID: {
return mobile_api::messageType::request == message_type
? factory.GetCreator<
@@ -298,7 +294,6 @@ CommandCreator& MobileCommandFactory::get_creator_factory(
? factory.GetCreator<commands::ScrollableMessageRequest>()
: factory.GetCreator<commands::ScrollableMessageResponse>();
}
-
case mobile_apis::FunctionID::AlertManeuverID: {
return mobile_api::messageType::request == message_type
? factory.GetCreator<commands::AlertManeuverRequest>()
@@ -361,6 +356,20 @@ CommandCreator& MobileCommandFactory::get_creator_factory(
: factory
.GetCreator<commands::GetCloudAppPropertiesResponse>();
}
+ case mobile_apis::FunctionID::GenericResponseID: {
+ using app_mngr::commands::Command;
+ return factory.GetCreator<commands::GenericResponse>();
+ }
+ default: {}
+ }
+ return factory.GetCreator<InvalidCommand>();
+}
+
+CommandCreator& MobileCommandFactory::get_notification_creator(
+ const mobile_apis::FunctionID::eType id) const {
+ CommandCreatorFactory factory(
+ application_manager_, rpc_service_, hmi_capabilities_, policy_handler_);
+ switch (id) {
case mobile_apis::FunctionID::OnButtonEventID: {
return factory.GetCreator<commands::mobile::OnButtonEventNotification>();
}
@@ -391,11 +400,7 @@ CommandCreator& MobileCommandFactory::get_creator_factory(
return factory.GetCreator<commands::OnPermissionsChangeNotification>();
}
case mobile_apis::FunctionID::OnHMIStatusID: {
- using app_mngr::commands::Command;
- return Command::CommandSource::SOURCE_MOBILE == source
- ? factory.GetCreator<
- commands::OnHMIStatusNotificationFromMobile>()
- : factory.GetCreator<commands::OnHMIStatusNotification>();
+ return factory.GetCreator<commands::OnHMIStatusNotification>();
}
case mobile_apis::FunctionID::OnKeyboardInputID: {
return factory
@@ -413,19 +418,60 @@ CommandCreator& MobileCommandFactory::get_creator_factory(
.GetCreator<commands::mobile::OnSystemRequestNotification>();
}
case mobile_apis::FunctionID::OnHashChangeID: {
- using app_mngr::commands::Command;
return factory.GetCreator<commands::mobile::OnHashChangeNotification>();
}
case mobile_apis::FunctionID::OnWayPointChangeID: {
- using app_mngr::commands::Command;
return factory.GetCreator<commands::OnWayPointChangeNotification>();
}
- case mobile_apis::FunctionID::GenericResponseID: {
- using app_mngr::commands::Command;
- return factory.GetCreator<commands::GenericResponse>();
+ default: {}
+ }
+ return factory.GetCreator<InvalidCommand>();
+}
+
+CommandCreator& MobileCommandFactory::get_notification_from_mobile_creator(
+ const mobile_apis::FunctionID::eType id) const {
+ CommandCreatorFactory factory(
+ application_manager_, rpc_service_, hmi_capabilities_, policy_handler_);
+ switch (id) {
+ case mobile_apis::FunctionID::OnHMIStatusID: {
+ return factory.GetCreator<commands::OnHMIStatusNotificationFromMobile>();
}
- default: { return factory.GetCreator<InvalidCommand>(); }
+ default: {}
+ }
+ return factory.GetCreator<InvalidCommand>();
+}
+
+CommandCreator& MobileCommandFactory::get_creator_factory(
+ const mobile_apis::FunctionID::eType id,
+ const mobile_apis::messageType::eType message_type,
+ const app_mngr::commands::Command::CommandSource source) const {
+ switch (message_type) {
+ case mobile_api::messageType::request: {
+ if (app_mngr::commands::Command::CommandSource::SOURCE_MOBILE == source) {
+ return get_command_creator(id, message_type);
+ }
+ break;
+ }
+ case mobile_api::messageType::response: {
+ if (app_mngr::commands::Command::CommandSource::SOURCE_SDL == source) {
+ return get_command_creator(id, message_type);
+ }
+ break;
+ }
+ case mobile_api::messageType::notification: {
+ if (app_mngr::commands::Command::CommandSource::SOURCE_SDL == source) {
+ return get_notification_creator(id);
+ } else if (app_mngr::commands::Command::CommandSource::SOURCE_MOBILE ==
+ source) {
+ return get_notification_from_mobile_creator(id);
+ }
+ break;
+ }
+ default: {}
}
+ CommandCreatorFactory factory(
+ application_manager_, rpc_service_, hmi_capabilities_, policy_handler_);
+ return factory.GetCreator<InvalidCommand>();
}
MobileCommandFactory::MobileCommandFactory(
@@ -442,12 +488,10 @@ bool MobileCommandFactory::IsAbleToProcess(
const int32_t function_id,
const application_manager::commands::Command::CommandSource message_source)
const {
- using app_mngr::commands::Command;
- return get_creator_factory(
- static_cast<mobile_apis::FunctionID::eType>(function_id),
- mobile_apis::messageType::INVALID_ENUM,
- message_source)
- .CanBeCreated();
+ auto id = static_cast<mobile_apis::FunctionID::eType>(function_id);
+ return get_command_creator(id, mobile_apis::messageType::INVALID_ENUM)
+ .CanBeCreated() ||
+ get_notification_creator(id).CanBeCreated();
}
CommandSharedPtr MobileCommandFactory::CreateCommand(
diff --git a/src/components/application_manager/rpc_plugins/vehicle_info_plugin/include/vehicle_info_plugin/vehicle_info_mobile_command_factory.h b/src/components/application_manager/rpc_plugins/vehicle_info_plugin/include/vehicle_info_plugin/vehicle_info_mobile_command_factory.h
index 9743aee769..41bd355852 100644
--- a/src/components/application_manager/rpc_plugins/vehicle_info_plugin/include/vehicle_info_plugin/vehicle_info_mobile_command_factory.h
+++ b/src/components/application_manager/rpc_plugins/vehicle_info_plugin/include/vehicle_info_plugin/vehicle_info_mobile_command_factory.h
@@ -63,8 +63,15 @@ class VehicleInfoMobileCommandFactory : public app_mngr::CommandFactory {
app_mngr::HMICapabilities& hmi_capabilities_;
policy::PolicyHandlerInterface& policy_handler_;
- app_mngr::CommandCreator& buildCommandCreator(
- const int32_t function_id, const int32_t message_type) const;
+ app_mngr::CommandCreator& get_creator_factory(
+ const mobile_apis::FunctionID::eType function_id,
+ const mobile_apis::messageType::eType message_type,
+ const app_mngr::commands::Command::CommandSource source) const;
+ app_mngr::CommandCreator& get_command_creator(
+ const mobile_apis::FunctionID::eType id,
+ const mobile_apis::messageType::eType message_type) const;
+ app_mngr::CommandCreator& get_notification_creator(
+ const mobile_apis::FunctionID::eType id) const;
DISALLOW_COPY_AND_ASSIGN(VehicleInfoMobileCommandFactory);
};
diff --git a/src/components/application_manager/rpc_plugins/vehicle_info_plugin/src/vehicle_info_mobile_command_factory.cc b/src/components/application_manager/rpc_plugins/vehicle_info_plugin/src/vehicle_info_mobile_command_factory.cc
index 7d1d25560a..dffc836a89 100644
--- a/src/components/application_manager/rpc_plugins/vehicle_info_plugin/src/vehicle_info_mobile_command_factory.cc
+++ b/src/components/application_manager/rpc_plugins/vehicle_info_plugin/src/vehicle_info_mobile_command_factory.cc
@@ -69,8 +69,6 @@ VehicleInfoMobileCommandFactory::VehicleInfoMobileCommandFactory(
app_mngr::CommandSharedPtr VehicleInfoMobileCommandFactory::CreateCommand(
const app_mngr::commands::MessageSharedPtr& message,
app_mngr::commands::Command::CommandSource source) {
- UNUSED(source);
-
const mobile_apis::FunctionID::eType function_id =
static_cast<mobile_apis::FunctionID::eType>(
(*message)[strings::params][strings::function_id].asInt());
@@ -91,54 +89,102 @@ app_mngr::CommandSharedPtr VehicleInfoMobileCommandFactory::CreateCommand(
"HMICommandFactory::CreateCommand function_id: "
<< function_id << ", message type: " << message_type_str);
- return buildCommandCreator(function_id, message_type).create(message);
+ return get_creator_factory(function_id, message_type, source).create(message);
}
bool VehicleInfoMobileCommandFactory::IsAbleToProcess(
const int32_t function_id,
const app_mngr::commands::Command::CommandSource source) const {
UNUSED(source);
- return buildCommandCreator(function_id,
- mobile_apis::messageType::INVALID_ENUM)
- .CanBeCreated();
+ auto id = static_cast<mobile_apis::FunctionID::eType>(function_id);
+ return get_command_creator(id, mobile_apis::messageType::INVALID_ENUM)
+ .CanBeCreated() ||
+ get_notification_creator(id).CanBeCreated();
}
-app_mngr::CommandCreator& VehicleInfoMobileCommandFactory::buildCommandCreator(
- const int32_t function_id, const int32_t message_type) const {
+app_mngr::CommandCreator& VehicleInfoMobileCommandFactory::get_command_creator(
+ const mobile_apis::FunctionID::eType id,
+ const mobile_apis::messageType::eType message_type) const {
auto factory = app_mngr::CommandCreatorFactory(
application_manager_, rpc_service_, hmi_capabilities_, policy_handler_);
-
- switch (function_id) {
- case mobile_apis::FunctionID::GetVehicleDataID:
+ switch (id) {
+ case mobile_apis::FunctionID::GetVehicleDataID: {
return mobile_apis::messageType::request == message_type
? factory.GetCreator<commands::GetVehicleDataRequest>()
: factory.GetCreator<commands::GetVehicleDataResponse>();
- case mobile_apis::FunctionID::SubscribeVehicleDataID:
+ }
+ case mobile_apis::FunctionID::SubscribeVehicleDataID: {
return mobile_apis::messageType::request == message_type
? factory.GetCreator<commands::SubscribeVehicleDataRequest>()
: factory.GetCreator<commands::SubscribeVehicleDataResponse>();
- case mobile_apis::FunctionID::UnsubscribeVehicleDataID:
+ }
+ case mobile_apis::FunctionID::UnsubscribeVehicleDataID: {
return mobile_apis::messageType::request == message_type
? factory.GetCreator<commands::UnsubscribeVehicleDataRequest>()
: factory
.GetCreator<commands::UnsubscribeVehicleDataResponse>();
- case mobile_apis::FunctionID::OnVehicleDataID:
- return factory.GetCreator<commands::OnVehicleDataNotification>();
- case mobile_apis::FunctionID::ReadDIDID:
+ }
+ case mobile_apis::FunctionID::ReadDIDID: {
return mobile_apis::messageType::request == message_type
? factory.GetCreator<commands::ReadDIDRequest>()
: factory.GetCreator<commands::ReadDIDResponse>();
- case mobile_apis::FunctionID::GetDTCsID:
+ }
+ case mobile_apis::FunctionID::GetDTCsID: {
return mobile_apis::messageType::request == message_type
? factory.GetCreator<commands::GetDTCsRequest>()
: factory.GetCreator<commands::GetDTCsResponse>();
- case mobile_apis::FunctionID::DiagnosticMessageID:
+ }
+ case mobile_apis::FunctionID::DiagnosticMessageID: {
return mobile_apis::messageType::request == message_type
? factory.GetCreator<commands::DiagnosticMessageRequest>()
: factory.GetCreator<commands::DiagnosticMessageResponse>();
- default:
- LOG4CXX_WARN(logger_, "Unsupported function_id: " << function_id);
- return factory.GetCreator<app_mngr::InvalidCommand>();
+ }
+ default: {}
+ }
+ return factory.GetCreator<app_mngr::InvalidCommand>();
+}
+
+app_mngr::CommandCreator&
+VehicleInfoMobileCommandFactory::get_notification_creator(
+ const mobile_apis::FunctionID::eType id) const {
+ auto factory = app_mngr::CommandCreatorFactory(
+ application_manager_, rpc_service_, hmi_capabilities_, policy_handler_);
+ switch (id) {
+ case mobile_apis::FunctionID::OnVehicleDataID: {
+ return factory.GetCreator<commands::OnVehicleDataNotification>();
+ }
+ default: {}
+ }
+ return factory.GetCreator<app_mngr::InvalidCommand>();
+}
+
+app_mngr::CommandCreator& VehicleInfoMobileCommandFactory::get_creator_factory(
+ const mobile_apis::FunctionID::eType id,
+ const mobile_apis::messageType::eType message_type,
+ const app_mngr::commands::Command::CommandSource source) const {
+ switch (message_type) {
+ case mobile_apis::messageType::request: {
+ if (app_mngr::commands::Command::CommandSource::SOURCE_MOBILE == source) {
+ return get_command_creator(id, message_type);
+ }
+ break;
+ }
+ case mobile_apis::messageType::response: {
+ if (app_mngr::commands::Command::CommandSource::SOURCE_SDL == source) {
+ return get_command_creator(id, message_type);
+ }
+ break;
+ }
+ case mobile_apis::messageType::notification: {
+ if (app_mngr::commands::Command::CommandSource::SOURCE_SDL == source) {
+ return get_notification_creator(id);
+ }
+ break;
+ }
+ default: {}
}
+ auto factory = app_mngr::CommandCreatorFactory(
+ application_manager_, rpc_service_, hmi_capabilities_, policy_handler_);
+ return factory.GetCreator<app_mngr::InvalidCommand>();
}
} // namespace vehicle_info_plugin
diff --git a/src/components/application_manager/src/commands/command_notification_from_mobile_impl.cc b/src/components/application_manager/src/commands/command_notification_from_mobile_impl.cc
index fa1006de2f..bd4fa58c8f 100644
--- a/src/components/application_manager/src/commands/command_notification_from_mobile_impl.cc
+++ b/src/components/application_manager/src/commands/command_notification_from_mobile_impl.cc
@@ -90,7 +90,7 @@ void CommandNotificationFromMobileImpl::SendNotificationToHMI(
const hmi_apis::FunctionID::eType& hmi_function_id) {
(*message_)[strings::params][strings::protocol_type] = hmi_protocol_type_;
(*message_)[strings::params][strings::function_id] = hmi_function_id;
- rpc_service_.SendMessageToHMI(message_);
+ rpc_service_.ManageHMICommand(message_, SOURCE_SDL_TO_HMI);
}
void CommandNotificationFromMobileImpl::SendNotificationToConsumers(
diff --git a/src/components/application_manager/src/commands/notification_from_hmi.cc b/src/components/application_manager/src/commands/notification_from_hmi.cc
index b6bb8d4e3c..5e1314bad3 100644
--- a/src/components/application_manager/src/commands/notification_from_hmi.cc
+++ b/src/components/application_manager/src/commands/notification_from_hmi.cc
@@ -84,7 +84,7 @@ void NotificationFromHMI::SendNotificationToMobile(
void NotificationFromHMI::SendNotificationToHMI(MessageSharedPtr& message) {
(*message)[strings::params][strings::protocol_type] = hmi_protocol_type_;
- rpc_service_.SendMessageToHMI(message);
+ rpc_service_.ManageHMICommand(message, SOURCE_SDL_TO_HMI);
}
void NotificationFromHMI::CreateHMIRequest(
diff --git a/src/components/application_manager/src/smart_object_keys.cc b/src/components/application_manager/src/smart_object_keys.cc
index a1dedd1d64..48e293a782 100644
--- a/src/components/application_manager/src/smart_object_keys.cc
+++ b/src/components/application_manager/src/smart_object_keys.cc
@@ -288,6 +288,19 @@ const char* service_published = "servicePublished";
const char* service_active = "serviceActive";
const char* app_service_id = "appServiceId";
const char* service_data = "serviceData";
+const char* media_service_data = "mediaServiceData";
+const char* weather_service_data = "weatherServiceData";
+const char* location = "location";
+const char* current_forecast = "currentForecast";
+const char* minute_forecast = "minuteForecast";
+const char* hourly_forecast = "hourlyForecast";
+const char* multiday_forecast = "multidayForecast";
+const char* weather_icon = "weatherIcon";
+const char* navigation_service_data = "navigationServiceData";
+const char* origin = "origin";
+const char* destination = "destination";
+const char* instructions = "instructions";
+const char* location_details = "locationDetails";
const char* request_service_active = "requestServiceActive";
const char* app_services = "appServices";
const char* update_reason = "updateReason";
diff --git a/src/components/protocol_handler/src/protocol_handler_impl.cc b/src/components/protocol_handler/src/protocol_handler_impl.cc
index e0768b3adf..222ca635d0 100644
--- a/src/components/protocol_handler/src/protocol_handler_impl.cc
+++ b/src/components/protocol_handler/src/protocol_handler_impl.cc
@@ -1501,11 +1501,18 @@ uint32_t get_hash_id(const ProtocolPacket& packet) {
return HASH_ID_WRONG;
}
if (packet.protocol_version() >= PROTOCOL_VERSION_5) {
- BsonObject obj = bson_object_from_bytes(packet.data());
- const uint32_t hash_id =
- (uint32_t)bson_object_get_int32(&obj, strings::hash_id);
- bson_object_deinitialize(&obj);
- return hash_id;
+ BsonObject obj;
+ size_t obj_size = bson_object_from_bytes_len(
+ &obj, packet.data(), packet.total_data_bytes());
+ if (obj_size > 0) {
+ const uint32_t hash_id =
+ (uint32_t)bson_object_get_int32(&obj, strings::hash_id);
+ bson_object_deinitialize(&obj);
+ return hash_id;
+ } else {
+ LOG4CXX_WARN(logger_, "Failed to parse BSON field for hash ID");
+ return HASH_ID_WRONG;
+ }
} else {
const uint32_t hash_be = *(reinterpret_cast<uint32_t*>(packet.data()));
const uint32_t hash_le = BE_TO_LE32(hash_be);
@@ -1637,7 +1644,13 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessageStartSession(
BsonObject bson_obj;
if (packet->data() != NULL) {
- bson_obj = bson_object_from_bytes(packet->data());
+ size_t bson_obj_size = bson_object_from_bytes_len(
+ &bson_obj, packet->data(), packet->total_data_bytes());
+ if (bson_obj_size == 0) {
+ LOG4CXX_WARN(logger_,
+ "Failed to parse BSON field of start service packet");
+ bson_object_initialize_default(&bson_obj);
+ }
} else {
bson_object_initialize_default(&bson_obj);
}
@@ -1730,33 +1743,42 @@ void ProtocolHandlerImpl::NotifySessionStarted(
// when video service is successfully started, copy input parameters
// ("width", "height", "videoProtocol", "videoCodec") to the ACK packet
if (packet->service_type() == kMobileNav && packet->data() != NULL) {
- BsonObject req_param = bson_object_from_bytes(packet->data());
- BsonElement* element = NULL;
-
- if ((element = bson_object_get(&req_param, strings::height)) != NULL &&
- element->type == TYPE_INT32) {
- bson_object_put_int32(start_session_ack_params.get(),
- strings::height,
- bson_object_get_int32(&req_param, strings::height));
- }
- if ((element = bson_object_get(&req_param, strings::width)) != NULL &&
- element->type == TYPE_INT32) {
- bson_object_put_int32(start_session_ack_params.get(),
- strings::width,
- bson_object_get_int32(&req_param, strings::width));
- }
- char* protocol =
- bson_object_get_string(&req_param, strings::video_protocol);
- if (protocol != NULL) {
- bson_object_put_string(
- start_session_ack_params.get(), strings::video_protocol, protocol);
- }
- char* codec = bson_object_get_string(&req_param, strings::video_codec);
- if (codec != NULL) {
- bson_object_put_string(
- start_session_ack_params.get(), strings::video_codec, codec);
+ BsonObject req_param;
+ size_t req_param_size = bson_object_from_bytes_len(
+ &req_param, packet->data(), packet->total_data_bytes());
+ if (req_param_size > 0) {
+ BsonElement* element = NULL;
+
+ if ((element = bson_object_get(&req_param, strings::height)) != NULL &&
+ element->type == TYPE_INT32) {
+ bson_object_put_int32(
+ start_session_ack_params.get(),
+ strings::height,
+ bson_object_get_int32(&req_param, strings::height));
+ }
+ if ((element = bson_object_get(&req_param, strings::width)) != NULL &&
+ element->type == TYPE_INT32) {
+ bson_object_put_int32(
+ start_session_ack_params.get(),
+ strings::width,
+ bson_object_get_int32(&req_param, strings::width));
+ }
+ char* protocol =
+ bson_object_get_string(&req_param, strings::video_protocol);
+ if (protocol != NULL) {
+ bson_object_put_string(
+ start_session_ack_params.get(), strings::video_protocol, protocol);
+ }
+ char* codec = bson_object_get_string(&req_param, strings::video_codec);
+ if (codec != NULL) {
+ bson_object_put_string(
+ start_session_ack_params.get(), strings::video_codec, codec);
+ }
+ bson_object_deinitialize(&req_param);
+ } else {
+ LOG4CXX_WARN(logger_,
+ "Failed to parse BSON field of start service (video)");
}
- bson_object_deinitialize(&req_param);
}
std::shared_ptr<utils::SemanticVersion> fullVersion;
@@ -1765,16 +1787,24 @@ void ProtocolHandlerImpl::NotifySessionStarted(
// could still be a payload, in which case we can get the real protocol
// version
if (packet->service_type() == kRpc && packet->data() != NULL) {
- BsonObject request_params = bson_object_from_bytes(packet->data());
- char* version_param =
- bson_object_get_string(&request_params, strings::protocol_version);
- std::string version_string(version_param == NULL ? "" : version_param);
- fullVersion = std::make_shared<utils::SemanticVersion>(version_string);
- // Constructed payloads added in Protocol v5
- if (fullVersion->major_version_ < PROTOCOL_VERSION_5) {
- rejected_params.push_back(std::string(strings::protocol_version));
+ BsonObject request_params;
+ size_t request_params_size = bson_object_from_bytes_len(
+ &request_params, packet->data(), packet->total_data_bytes());
+ if (request_params_size > 0) {
+ char* version_param =
+ bson_object_get_string(&request_params, strings::protocol_version);
+ std::string version_string(version_param == NULL ? "" : version_param);
+ fullVersion = std::make_shared<utils::SemanticVersion>(version_string);
+ // Constructed payloads added in Protocol v5
+ if (fullVersion->major_version_ < PROTOCOL_VERSION_5) {
+ rejected_params.push_back(std::string(strings::protocol_version));
+ }
+ bson_object_deinitialize(&request_params);
+ } else {
+ LOG4CXX_WARN(logger_,
+ "Failed to parse start service packet for version string");
+ fullVersion = std::make_shared<utils::SemanticVersion>();
}
- bson_object_deinitialize(&request_params);
} else {
fullVersion = std::make_shared<utils::SemanticVersion>();
}
diff --git a/src/components/transport_manager/include/transport_manager/cloud/cloud_device.h b/src/components/transport_manager/include/transport_manager/cloud/cloud_device.h
index 47a82e7921..9c25be2a3e 100644
--- a/src/components/transport_manager/include/transport_manager/cloud/cloud_device.h
+++ b/src/components/transport_manager/include/transport_manager/cloud/cloud_device.h
@@ -43,22 +43,33 @@
namespace transport_manager {
namespace transport_adapter {
+struct CloudAppEndpoint {
+ std::string host;
+ std::string port;
+ std::string path;
+ std::string query;
+ std::string fragment;
+};
+
class CloudDevice : public Device {
public:
CloudDevice(std::string& host, std::string& port, std::string& name);
+ CloudDevice(CloudAppEndpoint endpoint, std::string& name);
+
virtual const std::string& GetHost() const;
virtual const std::string& GetPort() const;
+ virtual const std::string GetTarget() const;
+
protected:
virtual bool IsSameAs(const Device* other_device) const;
virtual ApplicationList GetApplicationList() const;
private:
- const std::string host_;
- const std::string port_;
+ const CloudAppEndpoint endpoint_;
};
} // namespace transport_adapter
diff --git a/src/components/transport_manager/src/cloud/cloud_device.cc b/src/components/transport_manager/src/cloud/cloud_device.cc
index 35510f4cf8..c1ad186ded 100644
--- a/src/components/transport_manager/src/cloud/cloud_device.cc
+++ b/src/components/transport_manager/src/cloud/cloud_device.cc
@@ -42,7 +42,15 @@ CREATE_LOGGERPTR_GLOBAL(logger_, "TransportManager")
CloudDevice::CloudDevice(std::string& host,
std::string& port,
std::string& name)
- : Device(name, std::string(name)), host_(host), port_(port) {}
+ : Device(name, std::string(name))
+ , endpoint_(CloudAppEndpoint{.host = host,
+ .port = port,
+ .path = "/",
+ .query = "",
+ .fragment = ""}) {}
+
+CloudDevice::CloudDevice(CloudAppEndpoint endpoint, std::string& name)
+ : Device(name, std::string(name)), endpoint_(endpoint) {}
bool CloudDevice::IsSameAs(const Device* other) const {
LOG4CXX_TRACE(logger_, "enter. device: " << other);
@@ -54,12 +62,18 @@ bool CloudDevice::IsSameAs(const Device* other) const {
return false;
}
- if (host_ != other_cloud_device->GetHost()) {
+ if (GetHost() != other_cloud_device->GetHost()) {
+ return false;
+ }
+
+ if (GetPort() != other_cloud_device->GetPort()) {
return false;
}
- if (port_ != other_cloud_device->GetPort()) {
+
+ if (GetTarget() != other_cloud_device->GetTarget()) {
return false;
}
+
return true;
}
@@ -68,11 +82,15 @@ ApplicationList CloudDevice::GetApplicationList() const {
}
const std::string& CloudDevice::GetHost() const {
- return host_;
+ return endpoint_.host;
}
const std::string& CloudDevice::GetPort() const {
- return port_;
+ return endpoint_.port;
+}
+
+const std::string CloudDevice::GetTarget() const {
+ return endpoint_.path + endpoint_.query + endpoint_.fragment;
}
} // namespace transport_adapter
diff --git a/src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc b/src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc
index e141a65ec0..622531b120 100644
--- a/src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc
+++ b/src/components/transport_manager/src/cloud/cloud_websocket_transport_adapter.cc
@@ -80,15 +80,20 @@ void CloudWebsocketTransportAdapter::CreateDevice(const std::string& uid) {
return;
}
- // Port after second colon in valid endpoint string
- std::size_t pos_port = uid.find(":");
- pos_port = uid.find(":", pos_port + 1);
+ std::string protocol_pattern = "(wss?)";
+ std::string host_pattern =
+ "(([^?#%\\\\/@:\\s]{1,})\\:?([^?#%\\\\/@\\s]*)\\@?([^?#%\\\\/\\s]*))";
+ std::string port_pattern = "(\\d{2,5})";
+ // Optional parameters
+ std::string path_pattern = "((\\/[^\\/#?\\s]+)*)?\\/?";
+ std::string query_pattern = "(\\?[^=&#\\s]*=?[^#\\s]*&?)?";
+ std::string fragment_pattern = "(#[^\\s]*)?";
// Extract host and port from endpoint string
- boost::regex group_pattern(
- "(wss?:\\/\\/)([A-Z\\d\\.-]{2,}\\.?([A-Z]{2,})?)(:)(\\d{2,5})(\\/"
- "[A-Z\\d\\.-]+)*\\/?",
- boost::regex::icase);
+ boost::regex group_pattern(protocol_pattern + ":\\/\\/" + host_pattern + ":" +
+ port_pattern + path_pattern + query_pattern +
+ fragment_pattern,
+ boost::regex::icase);
boost::smatch results;
std::string str = uid;
@@ -97,20 +102,30 @@ void CloudWebsocketTransportAdapter::CreateDevice(const std::string& uid) {
return;
}
- std::string host = results[2];
- std::string port = results[5];
+ LOG4CXX_DEBUG(logger_, "#Results: " << results.size());
+ std::string results_str;
+ for (size_t i = 0; i < results.size(); i++) {
+ results_str += " R[" + std::to_string(i) + "]:";
+ results_str +=
+ (results[i].length() != 0) ? results[i] : std::string("<EMPTY>");
+ }
+ LOG4CXX_DEBUG(logger_, "Results: " << results_str);
- LOG4CXX_DEBUG(logger_,
- "Results: " << results[0] << " " << results[1] << " "
- << results[2] << " " << results[3] << " "
- << results[4] << " " << results[5] << " ");
std::string device_id = uid;
- LOG4CXX_DEBUG(
- logger_,
- "Creating Cloud Device For Host: " << host << " and Port: " << port);
+ CloudAppEndpoint endpoint{.host = results[2],
+ .port = results[6],
+ .path = results[7] + "/",
+ .query = results[9],
+ .fragment = results[10]};
+
+ LOG4CXX_DEBUG(logger_,
+ "Creating Cloud Device For Host: "
+ << endpoint.host << " at Port: " << endpoint.port
+ << " with Target: "
+ << (endpoint.path + endpoint.query + endpoint.fragment));
- auto cloud_device = std::make_shared<CloudDevice>(host, port, device_id);
+ auto cloud_device = std::make_shared<CloudDevice>(endpoint, device_id);
DeviceVector devices{cloud_device};
diff --git a/src/components/transport_manager/src/cloud/websocket_client_connection.cc b/src/components/transport_manager/src/cloud/websocket_client_connection.cc
index a93a27ba40..ec2fb0bcfb 100644
--- a/src/components/transport_manager/src/cloud/websocket_client_connection.cc
+++ b/src/components/transport_manager/src/cloud/websocket_client_connection.cc
@@ -160,11 +160,11 @@ TransportAdapter::Error WebsocketClientConnection::Start() {
// Perform websocket handshake
if (cloud_properties.cloud_transport_type == "WS") {
- ws_.handshake(host, "/", ec);
+ ws_.handshake(host, cloud_device->GetTarget(), ec);
}
#ifdef ENABLE_SECURITY
else if (cloud_properties.cloud_transport_type == "WSS") {
- wss_.handshake(host, "/", ec);
+ wss_.handshake(host, cloud_device->GetTarget(), ec);
}
#endif // ENABLE_SECURITY
if (ec) {
diff --git a/src/components/transport_manager/test/include/transport_manager/cloud/sample_websocket_server.h b/src/components/transport_manager/test/include/transport_manager/cloud/sample_websocket_server.h
index a60aefc7b0..a8b801c1fe 100644
--- a/src/components/transport_manager/test/include/transport_manager/cloud/sample_websocket_server.h
+++ b/src/components/transport_manager/test/include/transport_manager/cloud/sample_websocket_server.h
@@ -34,8 +34,6 @@
#ifndef SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_CLOUD_SAMPLE_WEBSOCKET_SERVER_H_
#define SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_CLOUD_SAMPLE_WEBSOCKET_SERVER_H_
-#include <unistd.h>
-#include <algorithm>
#include <boost/asio/bind_executor.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/placeholders.hpp>
@@ -46,13 +44,11 @@
#include <boost/beast/websocket/ssl.hpp>
#include <boost/make_shared.hpp>
#include <boost/thread/thread.hpp>
-#include <cstdlib>
-#include <functional>
#include <iostream>
-#include <memory>
+#include <queue>
+#include <set>
#include <string>
#include <thread>
-#include <vector>
namespace sample {
namespace websocket {
@@ -70,19 +66,31 @@ class WSSession {
class WSServer {
public:
explicit WSServer(tcp::socket&& socket);
+ void AddURLRoute(const std::string& route);
+ // Start the asynchronous operation
void Run();
- void OnAccept(beast::error_code ec);
private:
+ void OnWebsocketHandshake(const boost::system::error_code& ec);
+ void OnAccept(beast::error_code ec);
+ // Check if route can be handled by the server
+ bool CanHandleRoute(const std::string& route);
+ std::string ParseRouteFromTarget(const std::string& target);
+
websocket::stream<tcp::socket> ws_;
beast::flat_buffer buffer_;
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
+ http::request<http::string_body> req_;
+ std::set<std::string> url_routes_;
};
public:
WSSession(const std::string& address, uint16_t port);
+ // Start Accepting incoming connections
void Run();
void Stop();
+ // Add route endpoint which can be handled the server
+ void AddRoute(const std::string& route);
private:
void on_accept(boost::system::error_code ec);
@@ -94,6 +102,7 @@ class WSSession {
beast::flat_buffer buffer_;
boost::asio::ip::tcp::endpoint endpoint_;
std::shared_ptr<WSServer> ws_;
+ std::queue<std::string> buffered_routes_;
};
// Accepts incoming connections and launches the sessions
@@ -103,14 +112,23 @@ class WSSSession {
public:
// Take ownership of the socket
WSSServer(tcp::socket&& socket, ssl::context& ctx);
+ void AddURLRoute(const std::string& route);
// Start the asynchronous operation
void Run();
+
+ private:
void OnSSLHandshake(beast::error_code ec);
+ void OnWebsocketHandshake(const boost::system::error_code& ec);
void OnAccept(beast::error_code ec);
- private:
+ // Check if route can be handled by the server
+ bool CanHandleRoute(const std::string& route);
+ std::string ParseRouteFromTarget(const std::string& target);
+
websocket::stream<ssl::stream<tcp::socket> > wss_;
beast::flat_buffer buffer_;
+ http::request<http::string_body> req_;
+ std::set<std::string> url_routes_;
};
public:
@@ -121,6 +139,8 @@ class WSSSession {
// Start accepting incoming connections
void Run();
void Stop();
+ // Add route endpoint which can be handled the server
+ void AddRoute(const std::string& route);
private:
void do_accept();
@@ -133,9 +153,10 @@ class WSSSession {
ssl::context ctx_;
tcp::endpoint endpoint_;
std::shared_ptr<WSSServer> wss_;
+ std::queue<std::string> buffered_routes_;
};
} // namespace websocket
} // namespace sample
-#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_CLOUD_SAMPLE_WEBSOCKET_SERVER_H_ \ No newline at end of file
+#endif // SRC_COMPONENTS_TRANSPORT_MANAGER_TEST_INCLUDE_TRANSPORT_MANAGER_CLOUD_SAMPLE_WEBSOCKET_SERVER_H_
diff --git a/src/components/transport_manager/test/sample_websocket_server.cc b/src/components/transport_manager/test/sample_websocket_server.cc
index 56899e72e2..917184a361 100644
--- a/src/components/transport_manager/test/sample_websocket_server.cc
+++ b/src/components/transport_manager/test/sample_websocket_server.cc
@@ -1,3 +1,35 @@
+/*
+ * Copyright (c) 2019, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
#include "transport_manager/cloud/sample_websocket_server.h"
namespace {
@@ -13,20 +45,78 @@ namespace websocket {
WSSession::WSServer::WSServer(tcp::socket&& socket)
: ws_(std::move(socket)), strand_(ws_.get_executor()) {}
+void WSSession::WSServer::AddURLRoute(const std::string& target) {
+ url_routes_.insert(ParseRouteFromTarget(target));
+}
+
void WSSession::WSServer::Run() {
- // Accept the websocket handshake
- ws_.async_accept(boost::asio::bind_executor(
- strand_, std::bind(&WSServer::OnAccept, this, std::placeholders::_1)));
+ req_ = {};
+ http::async_read(
+ ws_.next_layer(),
+ buffer_,
+ req_,
+ std::bind(&WSServer::OnWebsocketHandshake, this, std::placeholders::_1));
+}
+
+void WSSession::WSServer::OnWebsocketHandshake(
+ const boost::system::error_code& ec) {
+ if (ec) {
+ return Fail("ERROR_HTTP_REQUEST_READ", ec);
+ }
+ if (websocket::is_upgrade(req_)) {
+ // Check target
+ std::string route = ParseRouteFromTarget(req_.target().to_string());
+ if (!CanHandleRoute(route)) {
+ auto error = boost::system::errc::make_error_code(
+ boost::system::errc::address_not_available);
+ ws_.next_layer().close();
+ return Fail("ERROR_INVALID_TARGET", error);
+ }
+ // Accept the websocket handshake
+ ws_.async_accept(
+ req_,
+ boost::asio::bind_executor(
+ strand_,
+ std::bind(&WSServer::OnAccept, this, std::placeholders::_1)));
+ }
}
void WSSession::WSServer::OnAccept(beast::error_code ec) {
if (ec) {
- return Fail("ERROR_CONNECTION_ACCEPT", ec);
+ return Fail("ERROR_WEBSOCKET_HANDSHAKE", ec);
+ }
+}
+
+bool WSSession::WSServer::CanHandleRoute(const std::string& route) {
+ if (url_routes_.find(route) == url_routes_.end()) {
+ return false;
+ }
+ return true;
+}
+
+std::string WSSession::WSServer::ParseRouteFromTarget(
+ const std::string& target) {
+ std::string route = target;
+ // Remove fragment
+ auto fragment_pos = route.find('#');
+ if (fragment_pos != std::string::npos) {
+ route = route.substr(0, fragment_pos);
+ }
+ // Remove query
+ auto query_pos = route.find('?');
+ if (query_pos != std::string::npos) {
+ route = route.substr(0, query_pos);
}
+
+ return route;
}
WSSession::WSSession(const std::string& address, uint16_t port)
- : address_(address), port_(port), acceptor_(ioc_), socket_(ioc_) {
+ : address_(address)
+ , port_(port)
+ , acceptor_(ioc_)
+ , socket_(ioc_)
+ , ws_(nullptr) {
endpoint_ = {boost::asio::ip::make_address(address), port};
boost::system::error_code error;
@@ -76,6 +166,14 @@ void WSSession::Stop() {
}
}
+void WSSession::AddRoute(const std::string& route) {
+ if (ws_ == nullptr) {
+ buffered_routes_.push(route);
+ return;
+ }
+ ws_->AddURLRoute(route);
+}
+
void WSSession::on_accept(boost::system::error_code ec) {
if (ec) {
Fail("ERROR_ON_ACCEPT", ec);
@@ -85,12 +183,20 @@ void WSSession::on_accept(boost::system::error_code ec) {
// Make websocket object and start
ws_ = std::make_shared<WSServer>(std::move(socket_));
+ // Load routes stored in buffer
+ while (!buffered_routes_.empty()) {
+ ws_->AddURLRoute(buffered_routes_.front());
+ buffered_routes_.pop();
+ }
ws_->Run();
}
WSSSession::WSSServer::WSSServer(tcp::socket&& socket, ssl::context& ctx)
: wss_(std::move(socket), ctx) {}
+void WSSSession::WSSServer::AddURLRoute(const std::string& target) {
+ url_routes_.insert(ParseRouteFromTarget(target));
+}
void WSSSession::WSSServer::Run() {
// Perform the SSL handshake
wss_.next_layer().async_handshake(
@@ -103,9 +209,32 @@ void WSSSession::WSSServer::OnSSLHandshake(beast::error_code ec) {
return Fail("ERROR_SSL_HANDSHAKE", ec);
}
- // Accept the websocket handshake
- wss_.async_accept(
- std::bind(&WSSServer::OnAccept, this, std::placeholders::_1));
+ req_ = {};
+ http::async_read(
+ wss_.next_layer(),
+ buffer_,
+ req_,
+ std::bind(&WSSServer::OnWebsocketHandshake, this, std::placeholders::_1));
+}
+
+void WSSSession::WSSServer::OnWebsocketHandshake(
+ const boost::system::error_code& ec) {
+ if (ec) {
+ return Fail("ERROR_HTTP_REQUEST_READ", ec);
+ }
+ if (websocket::is_upgrade(req_)) {
+ // Check target
+ std::string route = ParseRouteFromTarget(req_.target().to_string());
+ if (!CanHandleRoute(route)) {
+ auto error = boost::system::errc::make_error_code(
+ boost::system::errc::address_not_available);
+ wss_.next_layer().next_layer().close();
+ return Fail("ERROR_INVALID_TARGET", error);
+ }
+ // Accept the websocket handshake
+ wss_.async_accept(
+ req_, std::bind(&WSSServer::OnAccept, this, std::placeholders::_1));
+ }
}
void WSSSession::WSSServer::OnAccept(beast::error_code ec) {
@@ -114,11 +243,38 @@ void WSSSession::WSSServer::OnAccept(beast::error_code ec) {
}
}
+bool WSSSession::WSSServer::CanHandleRoute(const std::string& route) {
+ if (url_routes_.find(route) == url_routes_.end()) {
+ return false;
+ }
+ return true;
+}
+
+std::string WSSSession::WSSServer::ParseRouteFromTarget(
+ const std::string& target) {
+ std::string route = target;
+ // Remove fragment
+ auto fragment_pos = route.find('#');
+ if (fragment_pos != std::string::npos) {
+ route = route.substr(0, fragment_pos);
+ }
+ // Remove query
+ auto query_pos = route.find('?');
+ if (query_pos != std::string::npos) {
+ route = route.substr(0, query_pos);
+ }
+
+ return route;
+}
+
WSSSession::WSSSession(const std::string& address,
uint16_t port,
const std::string& certificate,
const std::string& private_key)
- : acceptor_(ioc_), socket_(ioc_), ctx_(ssl::context::sslv23_server) {
+ : acceptor_(ioc_)
+ , socket_(ioc_)
+ , ctx_(ssl::context::sslv23_server)
+ , wss_(nullptr) {
beast::error_code ec;
endpoint_ = {boost::asio::ip::make_address(address), port};
@@ -185,6 +341,14 @@ void WSSSession::Stop() {
}
}
+void WSSSession::AddRoute(const std::string& route) {
+ if (wss_ == nullptr) {
+ buffered_routes_.push(route);
+ return;
+ }
+ wss_->AddURLRoute(route);
+}
+
void WSSSession::do_accept() {
if (acceptor_.is_open()) {
acceptor_.async_accept(
@@ -202,8 +366,13 @@ void WSSSession::on_accept(boost::system::error_code ec) {
}
// Create the session and run it
wss_ = std::make_shared<WSSServer>(std::move(socket_), ctx_);
+ // Load routes stored in buffer
+ while (!buffered_routes_.empty()) {
+ wss_->AddURLRoute(buffered_routes_.front());
+ buffered_routes_.pop();
+ }
wss_->Run();
}
} // namespace websocket
-} // namespace sample \ No newline at end of file
+} // namespace sample
diff --git a/src/components/transport_manager/test/transport_adapter_test.cc b/src/components/transport_manager/test/transport_adapter_test.cc
index 3cef78493d..56386db201 100644
--- a/src/components/transport_manager/test/transport_adapter_test.cc
+++ b/src/components/transport_manager/test/transport_adapter_test.cc
@@ -42,6 +42,8 @@
#include "utils/test_async_waiter.h"
#include "protocol/raw_message.h"
+#include "transport_manager/cloud/cloud_device.h"
+#include "transport_manager/cloud/cloud_websocket_transport_adapter.h"
#include "transport_manager/transport_adapter/connection.h"
#include "transport_manager/transport_adapter/transport_adapter_controller.h"
#include "transport_manager/transport_adapter/transport_adapter_impl.h"
@@ -84,6 +86,139 @@ class TransportAdapterTest : public ::testing::Test {
std::string dev_id;
std::string uniq_id;
int app_handle;
+
+#if defined(CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT)
+ struct TestEndpoint {
+ std::string test_string;
+ std::string host;
+ std::string port;
+ std::string target;
+ };
+
+ CloudAppProperties test_cloud_properties_{.endpoint = "",
+ .certificate = "no cert",
+ .enabled = true,
+ .auth_token = "no auth token",
+ .cloud_transport_type = "WS",
+ .hybrid_app_preference = "CLOUD"};
+ std::vector<std::string> kWebsocketProtocols{"ws://", "wss://"};
+
+ std::vector<TestEndpoint> kValidTestEndpoints{
+ // Host and port
+ TestEndpoint{"localhost:40/", "localhost", "40", "/"},
+ TestEndpoint{"[::1]:40", "[::1]", "40", "/"},
+ TestEndpoint{"username:password@localhost.com:80",
+ "username:password@localhost.com",
+ "80",
+ "/"},
+ // With path
+ TestEndpoint{
+ "localhost:440/file.html", "localhost", "440", "/file.html/"},
+ TestEndpoint{"101.180.1.213:23234/folder/img_index(1)/file.html",
+ "101.180.1.213",
+ "23234",
+ "/folder/img_index(1)/file.html/"},
+ TestEndpoint{"[2600:3c00::f03c:91ff:fe73:2b08]:31333/folder/img_index(1)/"
+ "file.html",
+ "[2600:3c00::f03c:91ff:fe73:2b08]",
+ "31333",
+ "/folder/img_index(1)/file.html/"},
+ // With query and/or fragment
+ TestEndpoint{
+ "username@localhost:22/folder/img_index(1)/"
+ "file.html?eventId=2345&eventName='some%20event'&eventSuccess=true",
+ "username@localhost",
+ "22",
+ "/folder/img_index(1)/file.html/"
+ "?eventId=2345&eventName='some%20event'&eventSuccess="
+ "true"},
+ TestEndpoint{"username@localhost.com:80/folder/img_index(1)/"
+ "file.html?eventId=2345&eventName='some%20event'&"
+ "eventSuccess=true#section1",
+ "username@localhost.com",
+ "80",
+ "/folder/img_index(1)/file.html/"
+ "?eventId=2345&eventName='some%20event'&eventSuccess=true#"
+ "section1"},
+ TestEndpoint{
+ "localhost:443/"
+ "?eventId=2345&eventName='some%20event'&eventSuccess=true#section1",
+ "localhost",
+ "443",
+ "/?eventId=2345&eventName='some%20event'&eventSuccess=true#"
+ "section1"},
+ TestEndpoint{"a1-b2.com:443/folder/img_index(1)/file.html#section1",
+ "a1-b2.com",
+ "443",
+ "/folder/img_index(1)/file.html/#section1"},
+ TestEndpoint{"a1-b2.com:23#section1", "a1-b2.com", "23", "/#section1"}};
+
+ std::vector<TestEndpoint> kInvalidTestEndpoints{
+ // Invalid hostname
+ TestEndpoint{"/localhost:80", "localhost", "80", "/"},
+ TestEndpoint{"local?host:80", "local?host", "80", "/"},
+ TestEndpoint{"local#host:80", "local#host", "80", "/"},
+ TestEndpoint{"local\%host:80", "local\%host", "80", "/"},
+ TestEndpoint{"local\\host:80", "local\\host", "80", "/"},
+ TestEndpoint{"local/host:80", "local/host", "80", "/"},
+ TestEndpoint{"local host:80", "local host", "80", "/"},
+ TestEndpoint{"local\thost:80", "local\thost", "80", "/"},
+ TestEndpoint{":80#section1", "", "80", "/#section1"},
+ // Invalid port
+ TestEndpoint{"username:password@localhost.com",
+ "username:password@localhost.com",
+ "",
+ "/"},
+ TestEndpoint{"username:password@localhost.com:5",
+ "username:password@localhost.com",
+ "5",
+ "/"},
+ TestEndpoint{"201.123.213:2h32/", "201.123.213", "2h32", "/"}};
+ std::vector<TestEndpoint> kIncorrectTestEndpoints{
+ // Incorrect port number
+ TestEndpoint{"201.123.1.213:232454/folder/img_index(1)/file.html",
+ "201.123.1.213",
+ "232454",
+ "/folder/img_index(1)/file.html/"},
+ // Incorrect path
+ TestEndpoint{"201.123.1.213:232//folder/img_index(1)/file.html",
+ "201.123.1.213",
+ "232",
+ "//folder/img_index(1)/file.html/"},
+ TestEndpoint{"201.123.1.213:232/folder/img_index(1)//file.html",
+ "201.123.1.213",
+ "232",
+ "/folder/img_index(1)//file.html/"},
+ TestEndpoint{"201.123.1.213:232/folder/img index(1)//file.html",
+ "201.123.1.213",
+ "232",
+ "/folder/img index(1)//file.html/"},
+ TestEndpoint{"201.123.1.213:232/folder/img\tindex(1)//file.html",
+ "201.123.1.213",
+ "232",
+ "/folder/img\tindex(1)//file.html/"},
+ // Incorrect query
+ TestEndpoint{"username@localhost:443/?eventId=2345&eventName='some "
+ "event'&eventSuccess=true",
+ "username@localhost",
+ "443",
+ "?eventId=2345&eventName='some event'&eventSuccess=true"},
+ TestEndpoint{"username@localhost:443/"
+ "?eventId=2345&eventName='some\tevent'&eventSuccess=true",
+ "username@localhost",
+ "443",
+ "?eventId=2345&eventName='some\tevent'&eventSuccess=true"},
+ // Incorrect fragment
+ TestEndpoint{"a1(b2).com:80/folder/img_index(1)/file.html#section 1",
+ "a1(b2).com",
+ "80",
+ "/folder/img_index(1)/file.html#section 1"},
+ TestEndpoint{"a1(b2).com:80/folder/img_index(1)/file.html#section\t1",
+ "a1(b2).com",
+ "80",
+ "/folder/img_index(1)/file.html#section\t1"}};
+
+#endif // CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT
};
TEST_F(TransportAdapterTest, Init) {
@@ -609,6 +744,83 @@ TEST_F(TransportAdapterTest,
EXPECT_CALL(*serverMock, Terminate());
}
+
+TEST_F(TransportAdapterTest, WebsocketEndpointParsing_SUCCESS) {
+ std::shared_ptr<CloudWebsocketTransportAdapter> cta =
+ std::make_shared<CloudWebsocketTransportAdapter>(
+ last_state_, transport_manager_settings);
+
+ for (auto protocol : kWebsocketProtocols) {
+ for (auto endpoint : kValidTestEndpoints) {
+ test_cloud_properties_.endpoint = protocol + endpoint.test_string;
+ cta->SetAppCloudTransportConfig("cloud app", test_cloud_properties_);
+
+ auto ta = std::dynamic_pointer_cast<TransportAdapter>(cta);
+ ASSERT_NE(ta.use_count(), 0);
+
+ ta->CreateDevice(test_cloud_properties_.endpoint);
+
+ auto device = cta->FindDevice(test_cloud_properties_.endpoint);
+ ASSERT_NE(device.use_count(), 0);
+
+ std::shared_ptr<CloudDevice> cloud_device =
+ std::dynamic_pointer_cast<CloudDevice>(device);
+ ASSERT_NE(cloud_device.use_count(), 0);
+
+ EXPECT_EQ(cloud_device->GetHost(), endpoint.host);
+ EXPECT_EQ(cloud_device->GetPort(), endpoint.port);
+ EXPECT_EQ(cloud_device->GetTarget(), endpoint.target);
+ }
+ }
+}
+TEST_F(TransportAdapterTest, WebsocketEndpointParsing_INVALID) {
+ std::shared_ptr<CloudWebsocketTransportAdapter> cta =
+ std::make_shared<CloudWebsocketTransportAdapter>(
+ last_state_, transport_manager_settings);
+
+ for (auto protocol : kWebsocketProtocols) {
+ for (auto endpoint : kInvalidTestEndpoints) {
+ test_cloud_properties_.endpoint = protocol + endpoint.test_string;
+ cta->SetAppCloudTransportConfig("cloud app", test_cloud_properties_);
+
+ auto ta = std::dynamic_pointer_cast<TransportAdapter>(cta);
+ ASSERT_NE(ta.use_count(), 0);
+
+ ta->CreateDevice(test_cloud_properties_.endpoint);
+
+ auto device = cta->FindDevice(test_cloud_properties_.endpoint);
+ EXPECT_EQ(device.use_count(), 0);
+ }
+ }
+}
+TEST_F(TransportAdapterTest, WebsocketEndpointParsing_INCORRECT) {
+ std::shared_ptr<CloudWebsocketTransportAdapter> cta =
+ std::make_shared<CloudWebsocketTransportAdapter>(
+ last_state_, transport_manager_settings);
+
+ for (auto protocol : kWebsocketProtocols) {
+ for (auto endpoint : kIncorrectTestEndpoints) {
+ test_cloud_properties_.endpoint = protocol + endpoint.test_string;
+ cta->SetAppCloudTransportConfig("cloud app", test_cloud_properties_);
+
+ auto ta = std::dynamic_pointer_cast<TransportAdapter>(cta);
+ ASSERT_NE(ta.use_count(), 0);
+
+ ta->CreateDevice(test_cloud_properties_.endpoint);
+
+ auto device = cta->FindDevice(test_cloud_properties_.endpoint);
+ ASSERT_NE(device.use_count(), 0);
+
+ std::shared_ptr<CloudDevice> cloud_device =
+ std::dynamic_pointer_cast<CloudDevice>(device);
+ ASSERT_NE(cloud_device.use_count(), 0);
+
+ EXPECT_FALSE(cloud_device->GetHost() == endpoint.host &&
+ cloud_device->GetPort() == endpoint.port &&
+ cloud_device->GetTarget() == endpoint.target);
+ }
+ }
+}
#endif // CLOUD_APP_WEBSOCKET_TRANSPORT_SUPPORT
TEST_F(TransportAdapterTest, DisconnectDevice_DeviceAddedConnectionCreated) {
diff --git a/src/components/transport_manager/test/websocket_connection_test.cc b/src/components/transport_manager/test/websocket_connection_test.cc
index 9f9793765a..db3bc598b1 100644
--- a/src/components/transport_manager/test/websocket_connection_test.cc
+++ b/src/components/transport_manager/test/websocket_connection_test.cc
@@ -84,14 +84,16 @@ class WebsocketConnectionTest : public ::testing::Test {
ASSERT_NE(client_out.connection.use_count(), 0);
}
- void StartWSServer() {
+ void StartWSServer(std::string path) {
ws_session = std::make_shared<websocket::WSSession>(kHost, kPort);
+ ws_session->AddRoute(path);
ws_session->Run();
}
- void StartWSSServer() {
+ void StartWSSServer(std::string path) {
wss_session = std::make_shared<websocket::WSSSession>(
kHost, kPort, kCertificate, kPrivateKey);
+ wss_session->AddRoute(path);
wss_session->Run();
}
@@ -115,6 +117,10 @@ class WebsocketConnectionTest : public ::testing::Test {
WebsocketClient ws_client;
std::string kHost = "127.0.0.1";
uint16_t kPort = 8080;
+ std::string kPath = "/folder/file.html/";
+ std::string kQuery = "?eventId=2345&eventName='Test'&expectedResult=true";
+ std::string kFragment = "#section_1";
+
// Sample certificate for localhost
std::string kCertificate =
"-----BEGIN "
@@ -262,7 +268,39 @@ class WebsocketConnectionTest : public ::testing::Test {
TEST_F(WebsocketConnectionTest, WSConnection_SUCCESS) {
transport_manager::transport_adapter::CloudAppProperties properties{
- .endpoint = "ws://" + kHost + ":" + std::to_string(kPort) + "/",
+ .endpoint = "ws://" + kHost + ":" + std::to_string(kPort),
+ .certificate = "no cert",
+ .enabled = true,
+ .auth_token = "auth_token",
+ .cloud_transport_type = "WS",
+ .hybrid_app_preference = "CLOUD"};
+
+ // Start server
+ std::thread t1(&WebsocketConnectionTest::StartWSServer, this, "/");
+ usleep(5000);
+
+ // Start client
+ InitWebsocketClient(properties, ws_client);
+ std::shared_ptr<WebsocketClientConnection> ws_connection =
+ ws_client.connection;
+
+ // Check websocket connection
+ TransportAdapter::Error ret_code = ws_connection->Start();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop client
+ ret_code = ws_connection->Disconnect();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop server thread
+ ws_session->Stop();
+ t1.join();
+}
+
+TEST_F(WebsocketConnectionTest, WSConnection_SUCCESS_ValidTarget) {
+ transport_manager::transport_adapter::CloudAppProperties properties{
+ .endpoint = "ws://" + kHost + ":" + std::to_string(kPort) + kPath +
+ kQuery + kFragment,
.certificate = "no cert",
.enabled = true,
.auth_token = "auth_token",
@@ -270,8 +308,8 @@ TEST_F(WebsocketConnectionTest, WSConnection_SUCCESS) {
.hybrid_app_preference = "CLOUD"};
// Start server
- std::thread t1(&WebsocketConnectionTest::StartWSServer, this);
- sleep(1);
+ std::thread t1(&WebsocketConnectionTest::StartWSServer, this, kPath);
+ usleep(5000);
// Start client
InitWebsocketClient(properties, ws_client);
@@ -291,9 +329,41 @@ TEST_F(WebsocketConnectionTest, WSConnection_SUCCESS) {
t1.join();
}
+TEST_F(WebsocketConnectionTest, WSConnection_FAILURE_InvalidTarget) {
+ transport_manager::transport_adapter::CloudAppProperties properties{
+ .endpoint = "ws://" + kHost + ":" + std::to_string(kPort) + kPath +
+ kQuery + kFragment,
+ .certificate = "no cert",
+ .enabled = true,
+ .auth_token = "auth_token",
+ .cloud_transport_type = "WS",
+ .hybrid_app_preference = "CLOUD"};
+
+ // Start server
+ std::thread t1(&WebsocketConnectionTest::StartWSServer, this, "/");
+ usleep(5000);
+
+ // Start client
+ InitWebsocketClient(properties, ws_client);
+ std::shared_ptr<WebsocketClientConnection> ws_connection =
+ ws_client.connection;
+
+ // Check websocket connection
+ TransportAdapter::Error ret_code = ws_connection->Start();
+ EXPECT_EQ(TransportAdapter::FAIL, ret_code);
+
+ // Stop client
+ ret_code = ws_connection->Disconnect();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop server thread
+ ws_session->Stop();
+ t1.join();
+}
+
TEST_F(WebsocketConnectionTest, WSSConnection_SUCCESS) {
transport_manager::transport_adapter::CloudAppProperties properties{
- .endpoint = "wss://" + kHost + ":" + std::to_string(kPort) + "/",
+ .endpoint = "wss://" + kHost + ":" + std::to_string(kPort),
.certificate = kCACertificate,
.enabled = true,
.auth_token = "auth_token",
@@ -301,8 +371,8 @@ TEST_F(WebsocketConnectionTest, WSSConnection_SUCCESS) {
.hybrid_app_preference = "CLOUD"};
// Start server
- std::thread t1(&WebsocketConnectionTest::StartWSSServer, this);
- sleep(1);
+ std::thread t1(&WebsocketConnectionTest::StartWSSServer, this, "/");
+ usleep(5000);
// Start client
InitWebsocketClient(properties, ws_client);
@@ -322,9 +392,73 @@ TEST_F(WebsocketConnectionTest, WSSConnection_SUCCESS) {
t1.join();
}
+TEST_F(WebsocketConnectionTest, WSSConnection_SUCCESS_ValidTarget) {
+ transport_manager::transport_adapter::CloudAppProperties properties{
+ .endpoint = "wss://" + kHost + ":" + std::to_string(kPort) + kPath,
+ .certificate = kCACertificate,
+ .enabled = true,
+ .auth_token = "auth_token",
+ .cloud_transport_type = "WSS",
+ .hybrid_app_preference = "CLOUD"};
+
+ // Start server
+ std::thread t1(&WebsocketConnectionTest::StartWSSServer,
+ this,
+ (kPath + kQuery + kFragment));
+ usleep(5000);
+
+ // Start client
+ InitWebsocketClient(properties, ws_client);
+ std::shared_ptr<WebsocketClientConnection> wss_connection =
+ ws_client.connection;
+
+ // Check websocket connection
+ TransportAdapter::Error ret_code = wss_connection->Start();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop client
+ ret_code = wss_connection->Disconnect();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop server thread
+ wss_session->Stop();
+ t1.join();
+}
+
+TEST_F(WebsocketConnectionTest, WSSConnection_FAILURE_InvalidTarget) {
+ transport_manager::transport_adapter::CloudAppProperties properties{
+ .endpoint = "wss://" + kHost + ":" + std::to_string(kPort),
+ .certificate = kCACertificate,
+ .enabled = true,
+ .auth_token = "auth_token",
+ .cloud_transport_type = "WSS",
+ .hybrid_app_preference = "CLOUD"};
+
+ // Start server
+ std::thread t1(&WebsocketConnectionTest::StartWSSServer, this, kPath);
+ usleep(5000);
+
+ // Start client
+ InitWebsocketClient(properties, ws_client);
+ std::shared_ptr<WebsocketClientConnection> wss_connection =
+ ws_client.connection;
+
+ // Check websocket connection
+ TransportAdapter::Error ret_code = wss_connection->Start();
+ EXPECT_EQ(TransportAdapter::FAIL, ret_code);
+
+ // Stop client
+ ret_code = wss_connection->Disconnect();
+ EXPECT_EQ(TransportAdapter::OK, ret_code);
+
+ // Stop server thread
+ wss_session->Stop();
+ t1.join();
+}
+
TEST_F(WebsocketConnectionTest, WSSConnection_FAILURE_IncorrectCert) {
transport_manager::transport_adapter::CloudAppProperties properties{
- .endpoint = "wss://" + kHost + ":" + std::to_string(kPort) + "/",
+ .endpoint = "wss://" + kHost + ":" + std::to_string(kPort),
.certificate = kIncorrectCertificate,
.enabled = true,
.auth_token = "auth_token",
@@ -332,8 +466,8 @@ TEST_F(WebsocketConnectionTest, WSSConnection_FAILURE_IncorrectCert) {
.hybrid_app_preference = "CLOUD"};
// Start server
- std::thread t1(&WebsocketConnectionTest::StartWSSServer, this);
- sleep(1);
+ std::thread t1(&WebsocketConnectionTest::StartWSSServer, this, "/");
+ usleep(5000);
// Start client
InitWebsocketClient(properties, ws_client);