mirror of
https://github.com/eclipse-openvehicle-api/openvehicle-api.git
synced 2026-08-30 04:15:10 +00:00
connection between 2 systems and bug fixes (#14)
This commit is contained in:
@@ -60,12 +60,22 @@ MAKE_ERROR_MSG(-134, CONFIG_SERVICE_ACCESS_ERROR, "Configuration service is not
|
||||
MAKE_ERROR_MSG(-135, COMMUNICATION_CONTROL_SERVICE_ACCESS_ERROR, "Communication control service is not accessible.", "The communication control service service could not be accessed.")
|
||||
MAKE_ERROR_MSG(-136, APP_CONTROL_SERVICE_ACCESS_ERROR, "Application control service is not accessible.", "The application control service could not be accessed.")
|
||||
MAKE_ERROR_MSG(-170, CANNOT_FIND_OBJECT, "The object cannot be found.", "A search for an object with supplied name was not successful.")
|
||||
MAKE_ERROR_MSG(-180, CANNOT_LOAD_SETTINGS, "The system settings cannot be loaded.", "For a specific instance, the system settings cannot be loaded.")
|
||||
MAKE_ERROR_MSG(-180, CANNOT_SAVE_SETTINGS, "The system settings cannot be saved.", "For a specific instance, the system settings cannot be saved.")
|
||||
MAKE_ERROR_MSG(-181, PROCESS_LISTENER_CONFIG_ERROR, "The listener configuration contains errors.", "The listener configuration contains errors and cannot be processed.")
|
||||
MAKE_ERROR_MSG(-182, PROCESS_CONNECTION_CONFIG_ERROR, "The connection configuration contains errors.", "The connection configuration contains errors and cannot be processed.")
|
||||
MAKE_ERROR_MSG(-183, ADD_LISTENER_ERROR, "Failed to add a listener to the system settings.", "The listener configuration could not be added to the system settings. This might be caused by a duplicate listener configuration.")
|
||||
MAKE_ERROR_MSG(-184, REMOVE_LISTENER_ERROR, "Failed to remove a listener from the system settings.", "The listener configuration could not be removed from the system settings. This might be caused by a missing listener configuration.")
|
||||
MAKE_ERROR_MSG(-185, SHOW_LISTENER_ERROR, "Failed to request the listener configuration from the system settings.", "The listener configuration could not be requested. This might be caused by a missing listener configuration.")
|
||||
MAKE_ERROR_MSG(-186, ADD_CONNECTION_ERROR, "Failed to add a connection to the system settings.", "The connection configuration could not be added to the system settings. This might be caused by a duplicate connection configuration.")
|
||||
MAKE_ERROR_MSG(-187, REMOVE_CONNECTION_ERROR, "Failed to remove a connection from the system settings.", "The connection configuration could not be removed from the system settings. This might be caused by a missing connection configuration.")
|
||||
MAKE_ERROR_MSG(-188, SHOW_CONNECTION_ERROR, "Failed to request the connection configuration from the system settings.", "The connection configuration could not be requested. This might be caused by a missing connection configuration.")
|
||||
|
||||
|
||||
////////// LOCAL APP CONTROL ERROR CODES ////////////
|
||||
|
||||
MAKE_ERROR_MSG(-204, APP_CONTROL_STARTUP_ERROR, "Cannot start application control.", "Application control start was initiated, but returned an error.")
|
||||
MAKE_ERROR_MSG(-205, APP_CONTROL_START_LOOP_FAIELD, "Starting the running loop failed.", "Failed to enter the processing loop for a server application.")
|
||||
MAKE_ERROR_MSG(-205, APP_CONTROL_START_LOOP_FAILED, "Starting the running loop failed.", "Failed to enter the processing loop for a server application.")
|
||||
MAKE_ERROR_MSG(-206, APP_CONTROL_DUPLICATE_INSTANCE, "Another process with specified instance is already running.", "Another core process initiated the application control with the same instance. Only one core process per instance is allowed.")
|
||||
MAKE_ERROR_MSG(-210, APP_CONTROL_INVALID_ISOLATION_CONFIG, "An invalid isolation configuration was supplied.", "The application control configuration section contains an invalid isolation configuration.")
|
||||
MAKE_ERROR_MSG(-218, SETTING_FILE_VERSION_INVALID, "Settings file has an invalid version.", "Settings file contains an invalid/incompatible version number.")
|
||||
|
||||
@@ -25,7 +25,7 @@ add_executable(sdv_control
|
||||
"startup_shutdown.h"
|
||||
"startup_shutdown.cpp"
|
||||
"context.h"
|
||||
"print_table.h" "start_stop_service.cpp" "start_stop_service.h" "installation.h" "installation.cpp")
|
||||
"print_table.h" "start_stop_service.cpp" "start_stop_service.h" "installation.h" "installation.cpp" "connection_config.h" "connection_config.cpp")
|
||||
|
||||
target_link_libraries(sdv_control ${CMAKE_DL_LIBS})
|
||||
|
||||
|
||||
471
sdv_executables/sdv_control/connection_config.cpp
Normal file
471
sdv_executables/sdv_control/connection_config.cpp
Normal file
@@ -0,0 +1,471 @@
|
||||
/********************************************************************************
|
||||
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Erik Verhoeven - initial API and implementation
|
||||
********************************************************************************/
|
||||
|
||||
#include "connection_config.h"
|
||||
#include "../../global/cmdlnparser/cmdlnparser.h"
|
||||
#include <support/toml.h>
|
||||
#include <interfaces/app.h>
|
||||
#include "../error_msg.h"
|
||||
#include <charconv>
|
||||
|
||||
void ListenerHelp(const SContext& rsContext)
|
||||
{
|
||||
// First argument should be "LISTENER"
|
||||
if (rsContext.seqCmdLine.size() < 1)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: missing listener command..." << std::endl;
|
||||
return;
|
||||
}
|
||||
if (iequals(rsContext.seqCmdLine[0], "LISTENER"))
|
||||
{
|
||||
CCommandLine::PrintHelpText(std::cout,
|
||||
"Usage: sdv_control LISTENER ADD <name> <provider> <parameters...> [options...]\n"
|
||||
" sdv_control LISTENER REMOVE <name> [options...]\n"
|
||||
" sdv_control LISTENER SHOW <name> [options...]\n\n"
|
||||
"Configure the system to add (or update) or remove a listener. The command doesn't check for valid parameters. A "
|
||||
"server restart is required for the new listener settings to take effect.\n\n"
|
||||
"A list of actively configured listeners can be requested by executing \"sdv_control LIST LISTENERS\"\n\n"
|
||||
"Note: if not explicitly added, a default listener will added to the list for the communication between isolated "
|
||||
"applications and the core system.\n\n");
|
||||
return;
|
||||
}
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: invalid listener command..." << std::endl;
|
||||
}
|
||||
|
||||
void ConnectionHelp(const SContext& rsContext)
|
||||
{
|
||||
// First argument should be "CONNECTION"
|
||||
if (rsContext.seqCmdLine.size() < 1)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: missing connection command..." << std::endl;
|
||||
return;
|
||||
}
|
||||
if (iequals(rsContext.seqCmdLine[0], "CONNECTION"))
|
||||
{
|
||||
CCommandLine::PrintHelpText(std::cout,
|
||||
"Usage: sdv_control CONNECTION ADD <name> <provider> <parameters...> [options...]\n"
|
||||
" sdv_control CONNECTION REMOVE <name> [options...]\n"
|
||||
" sdv_control CONNECTION SHOW <name> [options...]\n\n"
|
||||
"Configure the system to add (or update) or remove a connection. The command doesn't check for valid parameters. A "
|
||||
"server restart is required for the new connection settings to take effect.\n\n"
|
||||
"A list of actively configured connections can be requested by executing \"sdv_control LIST CONNECTIONS\"\n\n"
|
||||
"Note: if not explicitly added, a default connetion will be added to the list for the communication between external "
|
||||
"applications and the core system.\n\n"
|
||||
"Options:\n"
|
||||
" --insert_before<string> With ADD, Insert the connection before an existing connection with the supplied name.\n\n");
|
||||
return;
|
||||
}
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: invalid connection command..." << std::endl;
|
||||
}
|
||||
|
||||
int ConfigureListener(const SContext& rsContext)
|
||||
{
|
||||
// First argument should be "CONNECTION"
|
||||
if (rsContext.seqCmdLine.size() < 2)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Missing listener command... " << std::endl;
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
if (!iequals(rsContext.seqCmdLine[0], "LISTENER"))
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Invalid command: " << rsContext.seqCmdLine[0] << std::endl;
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
|
||||
// Which list command is requested
|
||||
enum class ECommand { unknown, add, remove, show } eCommand = ECommand::unknown;
|
||||
if (iequals(rsContext.seqCmdLine[1], "ADD")) eCommand = ECommand::add;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "REMOVE")) eCommand = ECommand::remove;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "SHOW")) eCommand = ECommand::show;
|
||||
else
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
{
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Invalid listener command." << std::endl;
|
||||
ListenerHelp(rsContext);
|
||||
}
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
|
||||
if (rsContext.seqCmdLine.size() < 3)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Missing listener name... " << std::endl;
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
|
||||
// Get the name
|
||||
std::string ssListener = rsContext.seqCmdLine[2];
|
||||
|
||||
switch (eCommand)
|
||||
{
|
||||
case ECommand::remove:
|
||||
return RemoveListener(ssListener, rsContext);
|
||||
case ECommand::show:
|
||||
return ShowListenerConfig(ssListener, rsContext);
|
||||
case ECommand::add:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// For add, check for provider and parameters
|
||||
if (rsContext.seqCmdLine.size() < 4)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Missing listener provider... " << std::endl;
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
std::string ssProvider = rsContext.seqCmdLine[3];
|
||||
|
||||
sdv::toml::CTOMLParser parser;
|
||||
parser.AddValue("Provider.Name", ssProvider);
|
||||
|
||||
// Check for parameters
|
||||
// Parameters have the format "param=value". It is possible that parameters have additional sub-tables. Then the format is:
|
||||
// "table.param=value".
|
||||
sdv::toml::CNodeCollection ipc_channel_table = parser.AddTable("IpcChannel");
|
||||
for (size_t nIndex = 4; nIndex < rsContext.seqCmdLine.size(); nIndex++)
|
||||
{
|
||||
std::string ssRawParam = rsContext.seqCmdLine[nIndex];
|
||||
|
||||
// Search for the equal sign
|
||||
size_t nEqualPos = ssRawParam.find_first_of('=');
|
||||
std::string ssParamName = ssRawParam.substr(0, nEqualPos);
|
||||
while (!ssParamName.empty() && std::isspace(ssParamName.back()))
|
||||
ssParamName.pop_back();
|
||||
if (ssParamName.empty() || nEqualPos == std::string::npos)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Invalid listener parameter: " << ssRawParam << std::endl;
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
sdv::any_t anyValue;
|
||||
size_t nValuePos = nEqualPos + 1;
|
||||
while (nValuePos < ssRawParam.size() && std::isspace(ssRawParam[nValuePos]))
|
||||
nValuePos++;
|
||||
if (nValuePos < ssRawParam.size())
|
||||
{
|
||||
std::string ssValue = ssRawParam.substr(nValuePos);
|
||||
if (!ssValue.empty() && ssValue.find_first_not_of("-0123456789") == std::string::npos)
|
||||
{
|
||||
int64_t iValue = 0;
|
||||
if (std::from_chars(ssValue.data(), ssValue.data() + ssValue.size(), iValue).ec == std::errc())
|
||||
anyValue = iValue;
|
||||
else
|
||||
anyValue = ssValue;
|
||||
}
|
||||
else
|
||||
anyValue = ssValue;
|
||||
|
||||
}
|
||||
ipc_channel_table.AddValue(ssParamName, anyValue);
|
||||
}
|
||||
|
||||
return AddListener(ssListener, parser.GetTOML(), rsContext);
|
||||
}
|
||||
|
||||
int AddListener(const std::string& rssListener, const std::string& rssConfig, const SContext& rsContext)
|
||||
{
|
||||
// Load the settings.
|
||||
auto ptrAppService = sdv::core::GetObject("AppSettingsService");
|
||||
sdv::app::IAppSettingsPersist* pAppSettingsPersist = ptrAppService.GetInterface<sdv::app::IAppSettingsPersist>();
|
||||
sdv::app::IAppConnections* pAppConnections = ptrAppService.GetInterface<sdv::app::IAppConnections>();
|
||||
if (!pAppSettingsPersist || !pAppConnections || !pAppSettingsPersist->LoadSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_LOAD_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_LOAD_SETTINGS;
|
||||
}
|
||||
|
||||
// Add the listener
|
||||
if (!pAppConnections->AddListenerConfig(rssListener, rssConfig))
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << ADD_LISTENER_ERROR_MSG << std::endl;
|
||||
return ADD_LISTENER_ERROR;
|
||||
}
|
||||
|
||||
// Save the settings.
|
||||
if (!pAppSettingsPersist->SaveSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_SAVE_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_SAVE_SETTINGS;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int RemoveListener(const std::string& rssListener, const SContext& rsContext)
|
||||
{
|
||||
// Load the settings.
|
||||
auto ptrAppService = sdv::core::GetObject("AppSettingsService");
|
||||
sdv::app::IAppSettingsPersist* pAppSettingsPersist = ptrAppService.GetInterface<sdv::app::IAppSettingsPersist>();
|
||||
sdv::app::IAppConnections* pAppConnections = ptrAppService.GetInterface<sdv::app::IAppConnections>();
|
||||
if (!pAppSettingsPersist || !pAppConnections || !pAppSettingsPersist->LoadSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_LOAD_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_LOAD_SETTINGS;
|
||||
}
|
||||
|
||||
// Remove the listener
|
||||
if (!pAppConnections->RemoveListenerConfig(rssListener))
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << REMOVE_LISTENER_ERROR_MSG << std::endl;
|
||||
return REMOVE_LISTENER_ERROR;
|
||||
}
|
||||
|
||||
// Save the settings.
|
||||
if (!pAppSettingsPersist->SaveSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_SAVE_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_SAVE_SETTINGS;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int ShowListenerConfig(const std::string& rssListener, const SContext& rsContext)
|
||||
{
|
||||
// Load the settings.
|
||||
auto ptrAppService = sdv::core::GetObject("AppSettingsService");
|
||||
sdv::app::IAppSettingsPersist* pAppSettingsPersist = ptrAppService.GetInterface<sdv::app::IAppSettingsPersist>();
|
||||
sdv::app::IAppConnections* pAppConnections = ptrAppService.GetInterface<sdv::app::IAppConnections>();
|
||||
if (!pAppSettingsPersist || !pAppConnections || !pAppSettingsPersist->LoadSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_LOAD_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_LOAD_SETTINGS;
|
||||
}
|
||||
|
||||
// Remove the listener
|
||||
std::string ssConfig = pAppConnections->GetListenerConfig(rssListener);
|
||||
if (ssConfig.empty())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << SHOW_LISTENER_ERROR_MSG << std::endl;
|
||||
return SHOW_LISTENER_ERROR;
|
||||
}
|
||||
|
||||
std::cout << ssConfig << std::endl;
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int ConfigureConnection(const SContext& rsContext)
|
||||
{
|
||||
// First argument should be "CONNECTION"
|
||||
if (rsContext.seqCmdLine.size() < 2)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Missing connection command... " << std::endl;
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
if (!iequals(rsContext.seqCmdLine[0], "CONNECTION"))
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Invalid command: " << rsContext.seqCmdLine[0] << std::endl;
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
|
||||
// Which list command is requested
|
||||
enum class ECommand { unknown, add, remove, show } eCommand = ECommand::unknown;
|
||||
if (iequals(rsContext.seqCmdLine[1], "ADD")) eCommand = ECommand::add;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "REMOVE")) eCommand = ECommand::remove;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "SHOW")) eCommand = ECommand::show;
|
||||
else
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
{
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Invalid connection command." << std::endl;
|
||||
ConnectionHelp(rsContext);
|
||||
}
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
|
||||
if (rsContext.seqCmdLine.size() < 3)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Missing connection name... " << std::endl;
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
|
||||
// Get the name
|
||||
std::string ssConnection = rsContext.seqCmdLine[2];
|
||||
|
||||
switch (eCommand)
|
||||
{
|
||||
case ECommand::remove:
|
||||
return RemoveConnection(ssConnection, rsContext);
|
||||
case ECommand::show:
|
||||
return ShowConnectionConfig(ssConnection, rsContext);
|
||||
case ECommand::add:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// For add, check for provider and parameters
|
||||
if (rsContext.seqCmdLine.size() < 4)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Missing connection provider... " << std::endl;
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
std::string ssProvider = rsContext.seqCmdLine[3];
|
||||
|
||||
sdv::toml::CTOMLParser parser;
|
||||
parser.AddValue("Provider.Name", ssProvider);
|
||||
|
||||
// Check for parameters
|
||||
// Parameters have the format "param=value". It is possible that parameters have additional sub-tables. Then the format is:
|
||||
// "table.param=value".
|
||||
sdv::toml::CNodeCollection ipc_channel_table = parser.AddTable("IpcChannel");
|
||||
for (size_t nIndex = 4; nIndex < rsContext.seqCmdLine.size(); nIndex++)
|
||||
{
|
||||
std::string ssRawParam = rsContext.seqCmdLine[nIndex];
|
||||
|
||||
// Search for the equal sign
|
||||
size_t nEqualPos = ssRawParam.find_first_of('=');
|
||||
std::string ssParamName = ssRawParam.substr(0, nEqualPos);
|
||||
while (!ssParamName.empty() && std::isspace(ssParamName.back()))
|
||||
ssParamName.pop_back();
|
||||
if (ssParamName.empty() || nEqualPos == std::string::npos)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Invalid listener parameter: " << ssRawParam << std::endl;
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
sdv::any_t anyValue;
|
||||
size_t nValuePos = nEqualPos + 1;
|
||||
while (nValuePos < ssRawParam.size() && std::isspace(ssRawParam[nValuePos]))
|
||||
nValuePos++;
|
||||
if (nValuePos < ssRawParam.size())
|
||||
{
|
||||
std::string ssValue = ssRawParam.substr(nValuePos);
|
||||
if (!ssValue.empty() && ssValue.find_first_not_of("-0123456789") == std::string::npos)
|
||||
{
|
||||
int64_t iValue = 0;
|
||||
if (std::from_chars(ssValue.data(), ssValue.data() + ssValue.size(), iValue).ec == std::errc())
|
||||
anyValue = iValue;
|
||||
else
|
||||
anyValue = ssValue;
|
||||
}
|
||||
else
|
||||
anyValue = ssValue;
|
||||
|
||||
}
|
||||
ipc_channel_table.AddValue(ssParamName, anyValue);
|
||||
}
|
||||
|
||||
return AddConnection(ssConnection, parser.GetTOML(), rsContext);
|
||||
}
|
||||
|
||||
int AddConnection(const std::string& rssConnection, const std::string& rssConfig, const SContext& rsContext)
|
||||
{
|
||||
// Load the settings.
|
||||
auto ptrAppService = sdv::core::GetObject("AppSettingsService");
|
||||
sdv::app::IAppSettingsPersist* pAppSettingsPersist = ptrAppService.GetInterface<sdv::app::IAppSettingsPersist>();
|
||||
sdv::app::IAppConnections* pAppConnections = ptrAppService.GetInterface<sdv::app::IAppConnections>();
|
||||
if (!pAppSettingsPersist || !pAppConnections || !pAppSettingsPersist->LoadSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_LOAD_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_LOAD_SETTINGS;
|
||||
}
|
||||
|
||||
// Add the connection
|
||||
if (!pAppConnections->AddConnectionConfig(rssConnection, rssConfig, rsContext.ssInsertBeforeConnection))
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << ADD_CONNECTION_ERROR_MSG << std::endl;
|
||||
return ADD_CONNECTION_ERROR;
|
||||
}
|
||||
|
||||
// Save the settings.
|
||||
if (!pAppSettingsPersist->SaveSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_SAVE_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_SAVE_SETTINGS;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int RemoveConnection(const std::string& rssConnection, const SContext& rsContext)
|
||||
{
|
||||
// Load the settings.
|
||||
auto ptrAppService = sdv::core::GetObject("AppSettingsService");
|
||||
sdv::app::IAppSettingsPersist* pAppSettingsPersist = ptrAppService.GetInterface<sdv::app::IAppSettingsPersist>();
|
||||
sdv::app::IAppConnections* pAppConnections = ptrAppService.GetInterface<sdv::app::IAppConnections>();
|
||||
if (!pAppSettingsPersist || !pAppConnections || !pAppSettingsPersist->LoadSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_LOAD_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_LOAD_SETTINGS;
|
||||
}
|
||||
|
||||
// Remove the connection
|
||||
if (!pAppConnections->RemoveConnectionConfig(rssConnection))
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << REMOVE_CONNECTION_ERROR_MSG << std::endl;
|
||||
return REMOVE_CONNECTION_ERROR;
|
||||
}
|
||||
|
||||
// Save the settings.
|
||||
if (!pAppSettingsPersist->SaveSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_SAVE_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_SAVE_SETTINGS;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int ShowConnectionConfig(const std::string& rssConnection, const SContext& rsContext)
|
||||
{
|
||||
// Load the settings.
|
||||
auto ptrAppService = sdv::core::GetObject("AppSettingsService");
|
||||
sdv::app::IAppSettingsPersist* pAppSettingsPersist = ptrAppService.GetInterface<sdv::app::IAppSettingsPersist>();
|
||||
sdv::app::IAppConnections* pAppConnections = ptrAppService.GetInterface<sdv::app::IAppConnections>();
|
||||
if (!pAppSettingsPersist || !pAppConnections || !pAppSettingsPersist->LoadSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_LOAD_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_LOAD_SETTINGS;
|
||||
}
|
||||
|
||||
// Remove the connection
|
||||
std::string ssConfig = pAppConnections->GetConnectionConfig(rssConnection);
|
||||
if (ssConfig.empty())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << SHOW_CONNECTION_ERROR_MSG << std::endl;
|
||||
return SHOW_CONNECTION_ERROR;
|
||||
}
|
||||
|
||||
std::cout << ssConfig << std::endl;
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
98
sdv_executables/sdv_control/connection_config.h
Normal file
98
sdv_executables/sdv_control/connection_config.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/********************************************************************************
|
||||
* Copyright (c) 2025-2026 ZF Friedrichshafen AG
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Apache License Version 2.0 which is available at
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Erik Verhoeven - initial API and implementation
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef CONNECTION_CONFIG_H
|
||||
#define CONNECTION_CONFIG_H
|
||||
|
||||
#include "context.h"
|
||||
#include <support/sequence.h>
|
||||
#include <support/string.h>
|
||||
|
||||
/**
|
||||
* @brief Help for configuring listeners.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
*/
|
||||
void ListenerHelp(const SContext& rsContext);
|
||||
|
||||
/**
|
||||
* @brief Help for configuring connections.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
*/
|
||||
void ConnectionHelp(const SContext& rsContext);
|
||||
|
||||
/**
|
||||
* @brief Configure the listener.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
* @return The application exit code. 0 is no error.
|
||||
*/
|
||||
int ConfigureListener(const SContext& rsContext);
|
||||
|
||||
/**
|
||||
* @brief Add a listener to the system settings.
|
||||
* @param[in] rssListener Reference to the string containing the listener configuration name.
|
||||
* @param[in] rssConfig Reference to the string containing the listener configuration.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
* @return The application exit code. 0 is no error.
|
||||
*/
|
||||
int AddListener(const std::string& rssListener, const std::string& rssConfig, const SContext& rsContext);
|
||||
|
||||
/**
|
||||
* @brief Remove a listener from the system settings.
|
||||
* @param[in] rssListener Reference to the string containing the listener configuration name.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
* @return The application exit code. 0 is no error.
|
||||
*/
|
||||
int RemoveListener(const std::string& rssListener, const SContext& rsContext);
|
||||
|
||||
/**
|
||||
* @brief Show a listener configuration.
|
||||
* @param[in] rssListener Reference to the string containing the listener configuration name.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
* @return The application exit code. 0 is no error.
|
||||
*/
|
||||
int ShowListenerConfig(const std::string& rssListener, const SContext& rsContext);
|
||||
|
||||
/**
|
||||
* @brief Configure the connection.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
* @return The application exit code. 0 is no error.
|
||||
*/
|
||||
int ConfigureConnection(const SContext& rsContext);
|
||||
|
||||
/**
|
||||
* @brief Add a connection to the system settings.
|
||||
* @param[in] rssConnection Reference to the string containing the connection configuration name.
|
||||
* @param[in] rssConfig Reference to the string containing the connection configuration.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
* @return The application exit code. 0 is no error.
|
||||
*/
|
||||
int AddConnection(const std::string& rssConnection, const std::string& rssConfig, const SContext& rsContext);
|
||||
|
||||
/**
|
||||
* @brief Remove a connection from the system settings.
|
||||
* @param[in] rssConnection Reference to the string containing the connection configuration name.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
* @return The application exit code. 0 is no error.
|
||||
*/
|
||||
int RemoveConnection(const std::string& rssConnection, const SContext& rsContext);
|
||||
|
||||
/**
|
||||
* @brief Show a connection configuration.
|
||||
* @param[in] rssConnection Reference to the string containing the connection configuration name.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
* @return The application exit code. 0 is no error.
|
||||
*/
|
||||
int ShowConnectionConfig(const std::string& rssConnection, const SContext& rsContext);
|
||||
|
||||
|
||||
#endif // !defined CONNECTION_CONFIG_H
|
||||
@@ -33,6 +33,7 @@ struct SContext
|
||||
bool bListShort = false; ///< Print only a shortened list with one column.
|
||||
sdv::sequence<sdv::u8string> seqCmdLine; ///< The commands provided on the command line.
|
||||
std::filesystem::path pathInstallDir; ///< Optional installation directory.
|
||||
std::string ssInsertBeforeConnection; ///< Insert before the provided connection
|
||||
};
|
||||
|
||||
#include <cctype> // std::tolower
|
||||
|
||||
@@ -88,7 +88,7 @@ int Install(const SContext& rsContext)
|
||||
ssName = rsContext.seqCmdLine[1];
|
||||
|
||||
// Try to connect
|
||||
sdv::TObjectPtr ptrRepository = sdv::com::ConnectToLocalServerRepository(rsContext.uiInstanceID);
|
||||
sdv::TObjectPtr ptrRepository = sdv::com::ConnectToLocalServerRepository();
|
||||
if (!ptrRepository)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
|
||||
@@ -14,8 +14,10 @@
|
||||
#include "list_elements.h"
|
||||
#include "print_table.h"
|
||||
#include <interfaces/config.h>
|
||||
#include <interfaces/app.h>
|
||||
#include <support/sdv_core.h>
|
||||
#include <support/local_service_access.h>
|
||||
#include <support/toml.h>
|
||||
#include "../../global/cmdlnparser/cmdlnparser.h"
|
||||
#include "../../global/exec_dir_helper.h"
|
||||
#include "../../global/flags.h"
|
||||
@@ -38,13 +40,14 @@ void ListHelp(const SContext& rsContext)
|
||||
}
|
||||
|
||||
// Which list command help is requested
|
||||
enum class EListCommand { unknown, modules, classes, components, installations, connections } eListCommand = EListCommand::unknown;
|
||||
enum class EListCommand { unknown, modules, classes, components, installations, listeners, connections } eListCommand = EListCommand::unknown;
|
||||
if (rsContext.seqCmdLine.size() >= 2)
|
||||
{
|
||||
if (iequals(rsContext.seqCmdLine[1], "MODULES")) eListCommand = EListCommand::modules;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "CLASSES")) eListCommand = EListCommand::classes;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "COMPONENTS")) eListCommand = EListCommand::components;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "INSTALLATIONS")) eListCommand = EListCommand::installations;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "LISTENERS")) eListCommand = EListCommand::listeners;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "CONNECTIONS")) eListCommand = EListCommand::connections;
|
||||
}
|
||||
|
||||
@@ -65,20 +68,24 @@ void ListHelp(const SContext& rsContext)
|
||||
case EListCommand::installations:
|
||||
CCommandLine::PrintHelpText(std::cout, "Usage: sdv_control LIST INSTALLATIONS [options...]\n\nShow a list of all installations.\n");
|
||||
break;
|
||||
case EListCommand::listeners:
|
||||
CCommandLine::PrintHelpText(std::cout, "Usage: sdv_control LIST LISTENERS [options...]\n\nShow a list of all configured listeners.\n");
|
||||
break;
|
||||
case EListCommand::connections:
|
||||
CCommandLine::PrintHelpText(std::cout, "Usage: sdv_control LIST CONNECTIONS [options...]\n\nShow a list of all connected applications.\n");
|
||||
CCommandLine::PrintHelpText(std::cout, "Usage: sdv_control LIST CONNECTIONS [options...]\n\nShow a list of all configured connections.\n");
|
||||
break;
|
||||
default:
|
||||
CCommandLine::PrintHelpText(std::cout, R"code(Usage: sdv_control LIST <list_command> [options...]
|
||||
CCommandLine::PrintHelpText(std::cout, R"text(Usage: sdv_control LIST <list_command> [options...]
|
||||
|
||||
Supported listing commands:
|
||||
LIST MODULES Show a list of loaded server modules.
|
||||
LIST CLASSES Show a list of available component classes.
|
||||
LIST COMPONENTS Show a list of instantiated server components
|
||||
LIST INSTALLATIONS Show a list of installations.
|
||||
LIST LISTENERS Show a list of current listeners.
|
||||
LIST CONNECTIONS Show a list of current connections.
|
||||
|
||||
)code");
|
||||
)text");
|
||||
break;
|
||||
}
|
||||
std::cout << "Options:\n";
|
||||
@@ -103,33 +110,39 @@ int ListElements(const SContext& rsContext, std::ostream& rstream /*= std::cout*
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
|
||||
// Which list command help is requested
|
||||
enum class EListCommand { unknown, modules, classes, components, installations, connections } eListCommand = EListCommand::unknown;
|
||||
// Which list command is requested
|
||||
enum class EListCommand { unknown, modules, classes, components, installations, listeners, connections } eListCommand = EListCommand::unknown;
|
||||
if (rsContext.seqCmdLine.size() >= 2)
|
||||
{
|
||||
if (iequals(rsContext.seqCmdLine[1], "MODULES")) eListCommand = EListCommand::modules;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "CLASSES")) eListCommand = EListCommand::classes;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "COMPONENTS")) eListCommand = EListCommand::components;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "INSTALLATIONS")) eListCommand = EListCommand::installations;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "LISTENERS")) eListCommand = EListCommand::listeners;
|
||||
else if (iequals(rsContext.seqCmdLine[1], "CONNECTIONS")) eListCommand = EListCommand::connections;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
{
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Missing listing command.." << std::endl << std::endl;
|
||||
std::cerr << "ERROR: " << CMDLN_ARG_ERR_MSG << " Missing listing command." << std::endl;
|
||||
ListHelp(rsContext);
|
||||
}
|
||||
return CMDLN_ARG_ERR;
|
||||
}
|
||||
|
||||
// Try to connect
|
||||
sdv::TObjectPtr ptrRepository = sdv::com::ConnectToLocalServerRepository(rsContext.uiInstanceID);
|
||||
if (!ptrRepository)
|
||||
// Try to connect (except when listing the listeners and connections... they can be read from the settings).
|
||||
sdv::TObjectPtr ptrRepository;
|
||||
if (eListCommand != EListCommand::listeners && eListCommand != EListCommand::connections)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CONNECT_SDV_SERVER_ERROR_MSG << " Instance #" << rsContext.uiInstanceID << "." << std::endl;
|
||||
return CONNECT_SDV_SERVER_ERROR;
|
||||
ptrRepository = sdv::com::ConnectToLocalServerRepository();
|
||||
if (!ptrRepository)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CONNECT_SDV_SERVER_ERROR_MSG << " Instance #" << rsContext.uiInstanceID << "."
|
||||
<< std::endl;
|
||||
return CONNECT_SDV_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
int iRet = -100;
|
||||
@@ -147,12 +160,16 @@ int ListElements(const SContext& rsContext, std::ostream& rstream /*= std::cout*
|
||||
case EListCommand::installations:
|
||||
iRet = ListInstallations(rsContext, ptrRepository, rstream);
|
||||
break;
|
||||
case EListCommand::listeners:
|
||||
iRet = ListListeners(rsContext, rstream);
|
||||
break;
|
||||
case EListCommand::connections:
|
||||
iRet = ListConnections(rsContext, ptrRepository, rstream);
|
||||
iRet = ListConnections(rsContext, rstream);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
rstream << std::endl;
|
||||
return iRet;
|
||||
}
|
||||
|
||||
@@ -388,8 +405,107 @@ int ListInstallations(const SContext& rsContext, const sdv::TObjectPtr& rptrRepo
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int ListConnections(const SContext& /*rsContext*/, const sdv::TObjectPtr& /*rptrRepository*/, std::ostream& /*rstream = std::cout */ )
|
||||
std::string BuildParameters(const sdv::toml::CNodeCollection& rtable, const std::string& ssPrefix = std::string())
|
||||
{
|
||||
std::cout << "ERROR: " << NOT_IMPLEMENTED_MSG << " :-(" << std::endl;
|
||||
return NOT_IMPLEMENTED;
|
||||
std::string ssParams;
|
||||
for (uint32_t uiIndex = 0; uiIndex < rtable.GetCount(); uiIndex++)
|
||||
{
|
||||
sdv::toml::CNode node = rtable.Get(uiIndex);
|
||||
if (!node) continue;
|
||||
std::string ssNodeText;
|
||||
if (node.GetType() == sdv::toml::ENodeType::node_table)
|
||||
{
|
||||
sdv::toml::CNodeCollection tableChild(node);
|
||||
if (!tableChild) continue;
|
||||
ssNodeText = BuildParameters(tableChild, static_cast<std::string>(tableChild.GetName()) + ".");
|
||||
}
|
||||
else if (node.GetType() == sdv::toml::ENodeType::node_array)
|
||||
{
|
||||
// TODO...
|
||||
}
|
||||
else
|
||||
ssNodeText = ssPrefix + node.GetName() + "=" + node.GetValueAsString();
|
||||
|
||||
// Add the text
|
||||
if (!ssParams.empty())
|
||||
ssParams += ", ";
|
||||
ssParams += ssNodeText;
|
||||
}
|
||||
return ssParams;
|
||||
}
|
||||
|
||||
int ListListeners(const SContext& rsContext, std::ostream& rstream /*= std::cout */ )
|
||||
{
|
||||
std::vector<std::array<std::string, 3>> vecListenerList;
|
||||
vecListenerList.push_back({"Listener", "Provider", "Parameters"});
|
||||
|
||||
// Request the settings.
|
||||
auto ptrAppService = sdv::core::GetObject("AppSettingsService");
|
||||
sdv::app::IAppSettingsPersist* pAppSettingsPersist = ptrAppService.GetInterface<sdv::app::IAppSettingsPersist>();
|
||||
sdv::app::IAppConnections* pAppConnections = ptrAppService.GetInterface<sdv::app::IAppConnections>();
|
||||
if (!pAppSettingsPersist || !pAppConnections)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_LOAD_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_LOAD_SETTINGS;
|
||||
}
|
||||
auto seqListeners = pAppConnections->GetListeners();
|
||||
for (const sdv::u8string& rssListener : seqListeners)
|
||||
{
|
||||
std::string ssListener = rssListener;
|
||||
auto ssConfig = pAppConnections->GetListenerConfig(rssListener);
|
||||
sdv::toml::CTOMLParser parser(ssConfig);
|
||||
if (!parser)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << PROCESS_LISTENER_CONFIG_ERROR_MSG << std::endl;
|
||||
return PROCESS_LISTENER_CONFIG_ERROR;
|
||||
}
|
||||
std::string ssProvider = parser.GetDirect("Provider.Name").GetValueAsString();
|
||||
std::string ssParams = BuildParameters(parser.GetDirect("IpcChannel"));
|
||||
vecListenerList.push_back({ssListener, ssProvider, ssParams});
|
||||
}
|
||||
|
||||
PrintTable(vecListenerList, rstream, rsContext.bListNoHdr);
|
||||
if (vecListenerList.size() < 2)
|
||||
rstream << " No listeners configured!" << std::endl;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int ListConnections(const SContext& rsContext, std::ostream& rstream /*= std::cout */ )
|
||||
{
|
||||
std::vector<std::array<std::string, 3>> vecConnectionList;
|
||||
vecConnectionList.push_back({"Connection", "Provider", "Parameters"});
|
||||
|
||||
// Request the settings.
|
||||
auto ptrAppService = sdv::core::GetObject("AppSettingsService");
|
||||
sdv::app::IAppSettingsPersist* pAppSettingsPersist = ptrAppService.GetInterface<sdv::app::IAppSettingsPersist>();
|
||||
sdv::app::IAppConnections* pAppConnections = ptrAppService.GetInterface<sdv::app::IAppConnections>();
|
||||
if (!pAppSettingsPersist || !pAppConnections || !pAppSettingsPersist->LoadSettings())
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << CANNOT_LOAD_SETTINGS_MSG << std::endl;
|
||||
return CANNOT_LOAD_SETTINGS;
|
||||
}
|
||||
auto seqConnections = pAppConnections->GetConnections();
|
||||
for (const sdv::u8string& rssConnection : seqConnections)
|
||||
{
|
||||
std::string ssConnection = rssConnection;
|
||||
auto ssConfig = pAppConnections->GetConnectionConfig(rssConnection);
|
||||
sdv::toml::CTOMLParser parser(ssConfig);
|
||||
if (!parser)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: " << PROCESS_CONNECTION_CONFIG_ERROR_MSG << std::endl;
|
||||
return PROCESS_CONNECTION_CONFIG_ERROR;
|
||||
}
|
||||
std::string ssProvider = parser.GetDirect("Provider.Name").GetValueAsString();
|
||||
std::string ssParams = BuildParameters(parser.GetDirect("IpcChannel"));
|
||||
vecConnectionList.push_back({ssConnection, ssProvider, ssParams});
|
||||
}
|
||||
|
||||
PrintTable(vecConnectionList, rstream, rsContext.bListNoHdr);
|
||||
if (vecConnectionList.size() < 2)
|
||||
rstream << " No connections configured!" << std::endl;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -71,12 +71,19 @@ int ListComponents(const SContext& rsContext, const sdv::TObjectPtr& rptrReposit
|
||||
int ListInstallations(const SContext& rsContext, const sdv::TObjectPtr& rptrRepository, std::ostream& rstream);
|
||||
|
||||
/**
|
||||
* @brief List the current connections.
|
||||
* @brief List the current configured listeners.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
* @param[in] rptrRepository Reference to the saerver repository.
|
||||
* @param[in] rstream The output stream to use for printing (table only).
|
||||
* @return The application exit code. 0 is no error.
|
||||
*/
|
||||
int ListConnections(const SContext& rsContext, const sdv::TObjectPtr& rptrRepository, std::ostream& rstream);
|
||||
int ListListeners(const SContext& rsContext, std::ostream& rstream);
|
||||
|
||||
/**
|
||||
* @brief List the current connections.
|
||||
* @param[in] rsContext Reference to the context.
|
||||
* @param[in] rstream The output stream to use for printing (table only).
|
||||
* @return The application exit code. 0 is no error.
|
||||
*/
|
||||
int ListConnections(const SContext& rsContext, std::ostream& rstream);
|
||||
|
||||
#endif // !defined LIST_ELEMENTS_H
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "list_elements.h"
|
||||
#include "start_stop_service.h"
|
||||
#include "installation.h"
|
||||
#include "connection_config.h"
|
||||
#include "../error_msg.h"
|
||||
|
||||
/**
|
||||
@@ -53,12 +54,6 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
// NOTE EVE 27.05.2025: This task has been taken over by the process watchdog.
|
||||
CProcessWatchdog watchdog;
|
||||
|
||||
// If not set, set the runtime location to the EXE directory.
|
||||
if (sdv::app::CAppControl::GetFrameworkRuntimeDirectory().empty())
|
||||
sdv::app::CAppControl::SetFrameworkRuntimeDirectory(GetExecDirectory());
|
||||
if (sdv::app::CAppControl::GetComponentInstallDirectory().empty())
|
||||
sdv::app::CAppControl::SetComponentInstallDirectory(GetExecDirectory());
|
||||
|
||||
CCommandLine cmdln(static_cast<uint32_t>(CCommandLine::EParseFlags::no_assignment_character));
|
||||
SContext sContext;
|
||||
bool bError = false;
|
||||
@@ -67,24 +62,40 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
std::string ssArgError;
|
||||
try
|
||||
{
|
||||
auto& rArgHelpDef = cmdln.DefineOption("?", bHelp, "Show help. Use <COMMAND> --help for specific help on the command.");
|
||||
// Argument groups 1 - 10:
|
||||
// STARTUP
|
||||
// SHUTDOWN
|
||||
// LIST
|
||||
// INSTALL
|
||||
// UPDATE
|
||||
// UNINSTALL
|
||||
// START
|
||||
// STOP
|
||||
// LISTENER
|
||||
// CONNECTION
|
||||
auto& rArgHelpDef =
|
||||
cmdln.DefineOption("?", bHelp, "Show help. Use <COMMAND> --help for specific help on the command.");
|
||||
rArgHelpDef.AddSubOptionName("help");
|
||||
auto& rArgSilentDef = cmdln.DefineOption("s", sContext.bSilent, "Do not show any information on std::cout. Not compatible with 'verbose'.");
|
||||
auto& rArgSilentDef = cmdln.DefineOption("s", sContext.bSilent, "Do not show any information on std::cout. Not compatible "
|
||||
"with 'verbose'.");
|
||||
rArgSilentDef.AddSubOptionName("silent");
|
||||
auto& rArgVerboseDef = cmdln.DefineOption("v", sContext.bVerbose, "Provide verbose information. Not compatible with 'silent'.");
|
||||
auto& rArgVerboseDef = cmdln.DefineOption("v", sContext.bVerbose, "Provide verbose information. Not compatible with "
|
||||
"'silent'.");
|
||||
rArgVerboseDef.AddSubOptionName("verbose");
|
||||
cmdln.DefineSubOption("version", bVersion, "Show version information.");
|
||||
cmdln.DefineSubOption("instance", sContext.uiInstanceID, "The instance ID of the SDV instance (default ID is 1000).");
|
||||
cmdln.DefineSubOption("server_silent", sContext.bServerSilent, "Only used with STARTUP command: Server is started using "
|
||||
"silent option. Not compatible with 'server_verbose'.");
|
||||
"silent option. Not compatible with 'server_verbose'.", true, 1);
|
||||
cmdln.DefineSubOption("server_verbose", sContext.bServerVerbose, "Only used with STARTUP command: Server is started using "
|
||||
"verbose option. Not compatible with 'server_silent'.");
|
||||
"verbose option. Not compatible with 'server_silent'.", true, 1);
|
||||
cmdln.DefineSubOption("install_dir", sContext.pathInstallDir, "Only used with STARTUP command: Installation directory "
|
||||
"(absolute or relative to the sdv_core executable).");
|
||||
"(absolute or relative to the sdv_core executable).", true, 1);
|
||||
cmdln.DefineSubOption("no_header", sContext.bListNoHdr, "Only used with LIST command: Do not print a header for the "
|
||||
"listing table.");
|
||||
"listing table.", true, 3);
|
||||
cmdln.DefineSubOption("short", sContext.bListShort, "Only used with LIST command: Print only the most essential "
|
||||
"information as one column.");
|
||||
"information as one column.", true, 3);
|
||||
cmdln.DefineSubOption(
|
||||
"insert_before", sContext.ssInsertBeforeConnection, "Name of the connection to insert before.", true, 10);
|
||||
cmdln.DefineDefaultArgument(sContext.seqCmdLine, "COMMAND");
|
||||
|
||||
cmdln.Parse(static_cast<size_t>(iArgc), rgszArgv);
|
||||
@@ -98,7 +109,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (!sContext.bSilent)
|
||||
{
|
||||
std::cout << "SDV Server Control Utility" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2026 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Author: Erik Verhoeven" << std::endl << std::endl;
|
||||
}
|
||||
|
||||
@@ -113,7 +124,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
bError = true;
|
||||
}
|
||||
|
||||
enum class ECommand { unknown, startup, shutdown, list, install, update, uninstall, start, stop } eCommand = ECommand::unknown;
|
||||
enum class ECommand { unknown, startup, shutdown, list, install, update, uninstall, start, stop, listener, connection } eCommand = ECommand::unknown;
|
||||
if (!sContext.seqCmdLine.empty())
|
||||
{
|
||||
if (iequals(sContext.seqCmdLine[0], "STARTUP")) eCommand = ECommand::startup;
|
||||
@@ -124,6 +135,8 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
else if (iequals(sContext.seqCmdLine[0], "UNINSTALL")) eCommand = ECommand::uninstall;
|
||||
else if (iequals(sContext.seqCmdLine[0], "START")) eCommand = ECommand::start;
|
||||
else if (iequals(sContext.seqCmdLine[0], "STOP")) eCommand = ECommand::stop;
|
||||
else if (iequals(sContext.seqCmdLine[0], "LISTENER")) eCommand = ECommand::listener;
|
||||
else if (iequals(sContext.seqCmdLine[0], "CONNECTION")) eCommand = ECommand::connection;
|
||||
else
|
||||
{
|
||||
if (!sContext.bSilent)
|
||||
@@ -157,17 +170,25 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
case ECommand::uninstall:
|
||||
InstallationHelp(sContext);
|
||||
break;
|
||||
case ECommand::listener:
|
||||
ListenerHelp(sContext);
|
||||
break;
|
||||
case ECommand::connection:
|
||||
ConnectionHelp(sContext);
|
||||
break;
|
||||
default:
|
||||
cmdln.PrintHelp(std::cout, R"code(Supported commands:
|
||||
STARTUP Start the core application server
|
||||
SHUTDOWN Stop the core application server
|
||||
LIST List module/classes/component/installation/connection information.
|
||||
INSTALL Install a new application or service.
|
||||
UPDATE Update an existing installation.
|
||||
UNINSTALL Uninstall an installed application or service.
|
||||
START Start a service (complex services only).
|
||||
STOP Stop a service (complex services only).
|
||||
)code");
|
||||
cmdln.PrintHelp(std::cout, R"text(Supported commands:
|
||||
STARTUP Start the core application server
|
||||
SHUTDOWN Stop the core application server
|
||||
LIST List information about modules/classes/components/installations/listeners/connections.
|
||||
INSTALL Install a new application or service.
|
||||
UPDATE Update an existing installation.
|
||||
UNINSTALL Uninstall an installed application or service.
|
||||
START Start a service (complex services and vehicle functions only).
|
||||
STOP Stop a service (complex services and vehicle functions only).
|
||||
LISTENER Add or remove a communication listener configuration.
|
||||
CONNECTION Add or remove a connection configuration.
|
||||
)text");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -185,11 +206,11 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (sContext.bVerbose)
|
||||
std::cout << "Starting local application control.." << std::endl;
|
||||
sdv::app::CAppControl appcontrol;
|
||||
std::string ssAppConfig = std::string(R"code(
|
||||
std::string ssAppConfig = std::string(R"toml(
|
||||
[Application]
|
||||
Mode = "Maintenance"
|
||||
Instance = )code") + std::to_string(sContext.uiInstanceID) + R"code(
|
||||
)code";
|
||||
Instance = )toml") + std::to_string(sContext.uiInstanceID) + R"toml(
|
||||
)toml";
|
||||
if (!appcontrol.Startup(ssAppConfig))
|
||||
{
|
||||
if (!sContext.bSilent)
|
||||
@@ -224,6 +245,12 @@ Instance = )code") + std::to_string(sContext.uiInstanceID) + R"code(
|
||||
case ECommand::uninstall:
|
||||
iRet = Uninstall(sContext);
|
||||
break;
|
||||
case ECommand::listener:
|
||||
iRet = ConfigureListener(sContext);
|
||||
break;
|
||||
case ECommand::connection:
|
||||
iRet = ConfigureConnection(sContext);
|
||||
break;
|
||||
default:
|
||||
std::cout << "Command missing :-(" << std::endl;
|
||||
break;
|
||||
|
||||
@@ -35,8 +35,8 @@ void StartStopServiceHelp(const SContext& rsContext)
|
||||
" sdv_control START <class> <name> [options...]\n\n"
|
||||
"Start a complex service with the supplied object name as is defined in the configuration (first usage) or the "
|
||||
"supplied class name and with object name assignment and add to the configuration (second usage).\n"
|
||||
"Only complex services can be started. If the service depends on not running other services, these are started as "
|
||||
"well.\n\n");
|
||||
"Only vehicle functions and complex services can be started. If the service depends on not running other services, "
|
||||
"these are started as well.\n\n");
|
||||
return;
|
||||
}
|
||||
if (iequals(rsContext.seqCmdLine[0], "STOP"))
|
||||
@@ -47,15 +47,14 @@ void StartStopServiceHelp(const SContext& rsContext)
|
||||
" sdv_control STOP <module> [options...]\n\n"
|
||||
"Stop the complex service(s) with the supplied object name (first usage), with supplied object ID (second usage), with "
|
||||
"supplied class name (third usage) or contained in the module with the supplied module name (fourth usage).\n"
|
||||
"Only complex services can be stopped. Dependent services are stopped as well. If one of object to be stopped is not a "
|
||||
"complex service, the command fails.\n\n");
|
||||
"Only vehicle functions and complex services can be stopped. Dependent services are stopped as well. If one of object "
|
||||
"to be stopped is not a vehicle function or a complex service, the command fails.\n\n");
|
||||
return;
|
||||
}
|
||||
if (!rsContext.bSilent)
|
||||
std::cerr << "ERROR: invalid start/stop command..." << std::endl;
|
||||
}
|
||||
|
||||
|
||||
int StartService(const SContext& rsContext)
|
||||
{
|
||||
// First argument should be "START"
|
||||
@@ -88,7 +87,7 @@ int StartService(const SContext& rsContext)
|
||||
ssName = rsContext.seqCmdLine[1];
|
||||
|
||||
// Try to connect
|
||||
sdv::TObjectPtr ptrRepository = sdv::com::ConnectToLocalServerRepository(rsContext.uiInstanceID);
|
||||
sdv::TObjectPtr ptrRepository = sdv::com::ConnectToLocalServerRepository();
|
||||
if (!ptrRepository)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
@@ -154,7 +153,7 @@ int StopService(const SContext& rsContext)
|
||||
ssName = rsContext.seqCmdLine[1];
|
||||
|
||||
// Try to connect
|
||||
sdv::TObjectPtr ptrRepository = sdv::com::ConnectToLocalServerRepository(rsContext.uiInstanceID);
|
||||
sdv::TObjectPtr ptrRepository = sdv::com::ConnectToLocalServerRepository();
|
||||
if (!ptrRepository)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
|
||||
@@ -76,9 +76,9 @@ void StartupShutdownHelp(const SContext& rsContext)
|
||||
"Start the SDV server with the supplied instance ID. If no instance ID is supplied, use the default instance "
|
||||
"ID #1000.\n\n"
|
||||
"Options:\n"
|
||||
" --server_silent Server is started using silent option. Not compatible with 'server_verbose'.\n"
|
||||
" --server_verbose Server is started using verbose option. Not compatible with 'server_silent'.\n"
|
||||
" --install_dir Installation directory (absolute or relative to the sdv_core executable).\n\n");
|
||||
" --server_silent Server is started using silent option. Not compatible with 'server_verbose'.\n"
|
||||
" --server_verbose Server is started using verbose option. Not compatible with 'server_silent'.\n"
|
||||
" --install_dir<path> Installation directory (absolute or relative to the sdv_core executable).\n\n");
|
||||
return;
|
||||
}
|
||||
if (iequals(rsContext.seqCmdLine[0], "SHUTDOWN"))
|
||||
@@ -156,7 +156,7 @@ int StartupSDVServer(const SContext& rsContext)
|
||||
}
|
||||
|
||||
// Try to connect
|
||||
auto ptrRepository = sdv::com::ConnectToLocalServerRepository(rsContext.uiInstanceID);
|
||||
auto ptrRepository = sdv::com::ConnectToLocalServerRepository();
|
||||
if (!ptrRepository)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
@@ -183,7 +183,7 @@ int ShutdownSDVServer(const SContext& rsContext)
|
||||
std::cout << "Connecting to the SDV #" << rsContext.uiInstanceID << " server..." << std::endl;
|
||||
|
||||
// Try to connect
|
||||
auto ptrRepository = sdv::com::ConnectToLocalServerRepository(rsContext.uiInstanceID);
|
||||
auto ptrRepository = sdv::com::ConnectToLocalServerRepository();
|
||||
if (!ptrRepository)
|
||||
{
|
||||
if (!rsContext.bSilent)
|
||||
|
||||
@@ -18,6 +18,40 @@
|
||||
#include <support/app_control.h>
|
||||
#include "../error_msg.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
/**
|
||||
* @brief Console application control handler (CTRL+C, close, shutdown, etc.).
|
||||
* @param[in] dwCtrlType The control type triggered by the system.
|
||||
* @return Returns TRUE when the signal was handled.
|
||||
*/
|
||||
static BOOL WINAPI ControlHandler(DWORD dwCtrlType)
|
||||
{
|
||||
switch (dwCtrlType)
|
||||
{
|
||||
case CTRL_C_EVENT:
|
||||
case CTRL_BREAK_EVENT:
|
||||
case CTRL_CLOSE_EVENT:
|
||||
case CTRL_LOGOFF_EVENT:
|
||||
case CTRL_SHUTDOWN_EVENT:
|
||||
return TRUE;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#elif defined __unix__
|
||||
#include <signal.h>
|
||||
|
||||
/**
|
||||
* @brief Signal handler to catch signal events.
|
||||
* @param[in] iSigNum The signal type that was triggered.
|
||||
*/
|
||||
static void SignalHandler(int /*iSigNum*/)
|
||||
{
|
||||
// Do nothing...
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Main function of the executable.
|
||||
* @param[in] iArgc Amount of arguments provided.
|
||||
@@ -46,12 +80,6 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (thread.joinable())
|
||||
thread.join();
|
||||
|
||||
// If not set, set the runtime location to the EXE directory.
|
||||
if (sdv::app::CAppControl::GetFrameworkRuntimeDirectory().empty())
|
||||
sdv::app::CAppControl::SetFrameworkRuntimeDirectory(GetExecDirectory());
|
||||
if (sdv::app::CAppControl::GetComponentInstallDirectory().empty())
|
||||
sdv::app::CAppControl::SetComponentInstallDirectory(GetExecDirectory());
|
||||
|
||||
CCommandLine cmdln(static_cast<uint32_t>(CCommandLine::EParseFlags::no_assignment_character));
|
||||
bool bHelp = false;
|
||||
bool bError = false;
|
||||
@@ -91,7 +119,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (!bSilent && !bNoBanner)
|
||||
{
|
||||
std::cout << "SDV core application" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2026 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Author: Erik Verhoeven" << std::endl << std::endl;
|
||||
}
|
||||
|
||||
@@ -185,14 +213,40 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
return APP_CONTROL_STARTUP_ERROR;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// Register the console control handler
|
||||
if (!SetConsoleCtrlHandler(&ControlHandler, TRUE))
|
||||
{
|
||||
if (!bSilent)
|
||||
std::cerr << "ERROR: " << APP_CONTROL_START_LOOP_FAILED_MSG << " - failed registering control handler." << std::endl;
|
||||
return APP_CONTROL_START_LOOP_FAILED;
|
||||
}
|
||||
#elif defined __unix__
|
||||
// Install our signal handler
|
||||
struct sigaction sSigAction
|
||||
{};
|
||||
sSigAction.sa_handler = SignalHandler;
|
||||
sSigAction.sa_flags = SA_RESTART;
|
||||
if (sigaction(SIGINT, &sSigAction, NULL) == -1)
|
||||
{
|
||||
if (!bSilent)
|
||||
std::cerr << "ERROR: " << APP_CONTROL_START_LOOP_FAILED_MSG << " - failed registering control handler." << std::endl;
|
||||
return APP_CONTROL_START_LOOP_FAILED;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Start the running loop
|
||||
if (!appcontrol.RunLoop())
|
||||
{
|
||||
if (!bSilent)
|
||||
std::cerr << "ERROR: " << APP_CONTROL_DUPLICATE_INSTANCE_MSG << std::endl;
|
||||
return APP_CONTROL_DUPLICATE_INSTANCE;
|
||||
std::cerr << "ERROR: " << APP_CONTROL_START_LOOP_FAILED_MSG << std::endl;
|
||||
return APP_CONTROL_START_LOOP_FAILED;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
SetConsoleCtrlHandler(&ControlHandler, FALSE);
|
||||
#endif
|
||||
|
||||
if (bVerbose)
|
||||
{
|
||||
std::cout << "Shutdown request received..." << std::endl;
|
||||
|
||||
@@ -372,7 +372,10 @@ bool CreateCoreServiceTomlFile(const std::string& resources)
|
||||
std::ofstream tomlFile("sdv_core_reloc.toml");
|
||||
if (tomlFile.is_open())
|
||||
{
|
||||
tomlFile << "# Location of the SDV binaries and configuration files\ndirectory = \"";
|
||||
tomlFile << R"toml(# Location of the SDV binaries and configuration files
|
||||
[CoreLocation]
|
||||
Version = 100
|
||||
Framework = ")toml";
|
||||
tomlFile << resources;
|
||||
tomlFile << "\"\n";
|
||||
tomlFile.close();
|
||||
|
||||
@@ -82,7 +82,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (!bSilent)
|
||||
{
|
||||
std::cout << "DBC utility" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2026 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Author: Erik Verhoeven" << std::endl;
|
||||
}
|
||||
if (bHelp)
|
||||
|
||||
@@ -174,6 +174,9 @@ std::string CProxyGenerator::GetFuncImpl(const SFuncInfo& rsFunc, CKeywordMap& r
|
||||
else
|
||||
sstreamExceptions << R"code(sdv::XUnknownException exception;
|
||||
exception.unknown_id = except_id;
|
||||
// Cpp-Check 2.7 warns about the uninitialized variable _id. This variable is allocated as inline static const and is
|
||||
// assigned a value. Suppress the warning.
|
||||
// cppcheck-suppress uninitvar
|
||||
throw exception;)code";
|
||||
for (const std::string& rssException : rvecExceptions)
|
||||
{
|
||||
@@ -181,6 +184,9 @@ std::string CProxyGenerator::GetFuncImpl(const SFuncInfo& rsFunc, CKeywordMap& r
|
||||
{
|
||||
)code" << rssException << R"code( exception;
|
||||
desOutput >> exception;
|
||||
// Cpp-Check 2.7 warns about the uninitialized variable _id. This variable is allocated as inline static const and is
|
||||
// assigned a value. Suppress the warning.
|
||||
// cppcheck-suppress uninitvar
|
||||
throw exception;
|
||||
}
|
||||
)code";
|
||||
@@ -190,6 +196,9 @@ std::string CProxyGenerator::GetFuncImpl(const SFuncInfo& rsFunc, CKeywordMap& r
|
||||
{
|
||||
sdv::XUnknownException exception;
|
||||
exception.unknown_id = except_id;
|
||||
// Cpp-Check 2.7 warns about the uninitialized variable _id. This variable is allocated as inline static const and is
|
||||
// assigned a value. Suppress the warning.
|
||||
// cppcheck-suppress uninitvar
|
||||
throw exception;
|
||||
}
|
||||
})code";
|
||||
|
||||
@@ -41,7 +41,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
CProcessWatchdog watchdog;
|
||||
|
||||
std::cout << "SDV IDL Compiler" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2026 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Author: Erik Verhoeven" << std::endl;
|
||||
|
||||
// Create a list of UTF-8 arguments
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "token.h"
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <clocale>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
#include <cuchar>
|
||||
@@ -71,7 +72,7 @@ const std::string& CSource::GetCodeRef() const
|
||||
void CSource::ReadFile(const std::filesystem::path& rpath)
|
||||
{
|
||||
// Set the locale to work with UTF8
|
||||
std::setlocale(LC_ALL, "en_US.utf8");
|
||||
::setlocale(LC_ALL, "en_US.utf8");
|
||||
|
||||
if (rpath.empty())
|
||||
throw CCompileException("File name missing");
|
||||
|
||||
@@ -22,6 +22,40 @@
|
||||
#include <support/local_service_access.h>
|
||||
#include "../error_msg.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
/**
|
||||
* @brief Console application control handler (CTRL+C, close, shutdown, etc.).
|
||||
* @param[in] dwCtrlType The control type triggered by the system.
|
||||
* @return Returns TRUE when the signal was handled.
|
||||
*/
|
||||
static BOOL WINAPI ControlHandler(DWORD dwCtrlType)
|
||||
{
|
||||
switch (dwCtrlType)
|
||||
{
|
||||
case CTRL_C_EVENT:
|
||||
case CTRL_BREAK_EVENT:
|
||||
case CTRL_CLOSE_EVENT:
|
||||
case CTRL_LOGOFF_EVENT:
|
||||
case CTRL_SHUTDOWN_EVENT:
|
||||
return TRUE;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#elif defined __unix__
|
||||
#include <signal.h>
|
||||
|
||||
/**
|
||||
* @brief Signal handler to catch signal events.
|
||||
* @param[in] iSigNum The signal type that was triggered.
|
||||
*/
|
||||
static void SignalHandler(int /*iSigNum*/)
|
||||
{
|
||||
// Do nothing...
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Connect event callback wrapper. Calls shutdown request on disconnect or error.
|
||||
*/
|
||||
@@ -93,12 +127,6 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (thread.joinable())
|
||||
thread.join();
|
||||
|
||||
// If not set, set the runtime location to the EXE directory.
|
||||
if (sdv::app::CAppControl::GetFrameworkRuntimeDirectory().empty())
|
||||
sdv::app::CAppControl::SetFrameworkRuntimeDirectory(GetExecDirectory());
|
||||
if (sdv::app::CAppControl::GetComponentInstallDirectory().empty())
|
||||
sdv::app::CAppControl::SetComponentInstallDirectory(GetExecDirectory());
|
||||
|
||||
CCommandLine cmdln(static_cast<uint32_t>(CCommandLine::EParseFlags::no_assignment_character));
|
||||
bool bHelp = false;
|
||||
bool bError = false;
|
||||
@@ -126,23 +154,29 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
{
|
||||
ssArgError = rsExcept.what();
|
||||
bHelp = true;
|
||||
bError = true;
|
||||
}
|
||||
|
||||
if (!bSilent)
|
||||
{
|
||||
std::cout << "SDV isolation application" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2026 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Author: Erik Verhoeven" << std::endl << std::endl;
|
||||
}
|
||||
|
||||
if (!ssArgError.empty() && !bSilent)
|
||||
if (!ssArgError.empty() && !bSilent && !bHelp && !bVersion)
|
||||
std::cerr << "ERROR: " << ssArgError << std::endl;
|
||||
|
||||
if (ssConfigBase64.empty())
|
||||
if (bVersion || bVerbose)
|
||||
{
|
||||
ssArgError = "Missing app configuration.";
|
||||
bHelp = true;
|
||||
std::cout << "Version: " << (SDVFrameworkBuildVersion / 100) << "." << (SDVFrameworkBuildVersion % 100) << " build "
|
||||
<< SDVFrameworkSubbuildVersion << " interface " << SDVFrameworkInterfaceVersion << std::endl;
|
||||
}
|
||||
|
||||
if (!bHelp && ssConfigBase64.empty())
|
||||
{
|
||||
if (!bSilent && !bVersion)
|
||||
std::cout << "Missing app configuration.";
|
||||
bError = true;
|
||||
}
|
||||
|
||||
if (bHelp)
|
||||
@@ -153,17 +187,14 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
std::cout << std::endl;
|
||||
cmdln.PrintHelp(std::cout, "The isolation application is used to isolate components from the core process. The "
|
||||
"isolation aims to improve the overall stability of the system.\n");
|
||||
return bError ? CMDLN_ARG_ERR : NO_ERROR;
|
||||
}
|
||||
return (bError && !bVersion && !bHelp) ? CMDLN_ARG_ERR : NO_ERROR;
|
||||
}
|
||||
if (bError) return CMDLN_ARG_ERR;
|
||||
if (bError) return (bError && !bVersion && !bHelp) ? CMDLN_ARG_ERR : NO_ERROR;
|
||||
|
||||
// Check for encoded configuration
|
||||
std::string ssIsoAppConfig = Base64DecodePlainText(ssConfigBase64);
|
||||
|
||||
if (bVersion || bVerbose)
|
||||
std::cout << "Version: " << (SDVFrameworkBuildVersion / 100) << "." << (SDVFrameworkBuildVersion % 100) << " build " <<
|
||||
SDVFrameworkSubbuildVersion << " interface " << SDVFrameworkInterfaceVersion << std::endl;
|
||||
if (!bSilent)
|
||||
std::cout << "Instance ID: " << uiInstanceID << std::endl;
|
||||
|
||||
@@ -267,7 +298,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
std::cerr << "ERROR: " << LINK_REPO_SERVICE_ERROR_MSG << std::endl;
|
||||
return LINK_REPO_SERVICE_ERROR;
|
||||
}
|
||||
pLinkCoreRepo->LinkCoreRepository(pCoreRepo);
|
||||
sdv::core::TLinkID tRepoLink = pLinkCoreRepo->LinkCoreRepository(pCoreRepo);
|
||||
|
||||
// Create the one object... is this a service or a utility?
|
||||
std::string ssClassName = parser.GetDirect("Isolation.Class").GetValue();
|
||||
@@ -332,6 +363,28 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
// The lifetime of the object is now taken over by the core or if failed, the object will be destroyed.
|
||||
ptrObject.Clear();
|
||||
|
||||
#ifdef _WIN32
|
||||
// Register the console control handler
|
||||
if (!SetConsoleCtrlHandler(&ControlHandler, TRUE))
|
||||
{
|
||||
if (!bSilent)
|
||||
std::cerr << "ERROR: " << APP_CONTROL_START_LOOP_FAILED_MSG << " - failed registering control handler." << std::endl;
|
||||
return APP_CONTROL_START_LOOP_FAILED;
|
||||
}
|
||||
#elif defined __unix__
|
||||
// Install our signal handler
|
||||
struct sigaction sSigAction
|
||||
{};
|
||||
sSigAction.sa_handler = SignalHandler;
|
||||
sSigAction.sa_flags = SA_RESTART;
|
||||
if (sigaction(SIGINT, &sSigAction, NULL) == -1)
|
||||
{
|
||||
if (!bSilent)
|
||||
std::cerr << "ERROR: " << APP_CONTROL_START_LOOP_FAILED_MSG << " - failed registering control handler." << std::endl;
|
||||
return APP_CONTROL_START_LOOP_FAILED;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Deactivate the configuration mode.
|
||||
appcontrol.SetRunningMode();
|
||||
|
||||
@@ -339,10 +392,14 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (!appcontrol.RunLoop())
|
||||
{
|
||||
if (!bSilent)
|
||||
std::cerr << "ERROR: " << APP_CONTROL_START_LOOP_FAIELD_MSG << std::endl;
|
||||
return APP_CONTROL_START_LOOP_FAIELD;
|
||||
std::cerr << "ERROR: " << APP_CONTROL_START_LOOP_FAILED_MSG << std::endl;
|
||||
return APP_CONTROL_START_LOOP_FAILED;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
SetConsoleCtrlHandler(&ControlHandler, FALSE);
|
||||
#endif
|
||||
|
||||
// TODO EVE
|
||||
if (appcontrol.IsConfiguring())
|
||||
std::cout << "Iso app configuring... " << __LINE__ << std::endl;
|
||||
@@ -358,7 +415,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
// Shutdwown
|
||||
pConnect->UnregisterStateEventCallback(uiCookie);
|
||||
parser.Clear();
|
||||
pLinkCoreRepo->UnlinkCoreRepository();
|
||||
pLinkCoreRepo->UnlinkCoreRepository(tRepoLink);
|
||||
appcontrol.Shutdown();
|
||||
|
||||
if (!bSilent)
|
||||
|
||||
@@ -32,12 +32,6 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
// NOTE EVE 27.05.2025: This task has been taken over by the process watchdog.
|
||||
CProcessWatchdog watchdog;
|
||||
|
||||
// If not set, set the runtime location to the EXE directory.
|
||||
if (sdv::app::CAppControl::GetFrameworkRuntimeDirectory().empty())
|
||||
sdv::app::CAppControl::SetFrameworkRuntimeDirectory(GetExecDirectory());
|
||||
if (sdv::app::CAppControl::GetComponentInstallDirectory().empty())
|
||||
sdv::app::CAppControl::SetComponentInstallDirectory(GetExecDirectory());
|
||||
|
||||
CCommandLine cmdln(static_cast<uint32_t>(CCommandLine::EParseFlags::no_assignment_character));
|
||||
bool bHelp = false;
|
||||
bool bError = false;
|
||||
@@ -67,7 +61,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (!bSilent)
|
||||
{
|
||||
std::cout << "SDV Local Instance Shutdown Utility" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2026 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Author: Erik Verhoeven" << std::endl << std::endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,4 +24,5 @@
|
||||
#include "../../sdv_services/core/toml_parser/character_reader_utf_8.cpp"
|
||||
#include "../../sdv_services/core/toml_parser/miscellaneous.cpp"
|
||||
#include "../../sdv_services/core/toml_parser/code_snippet.cpp"
|
||||
#include "../../sdv_services/core/toml_parser/parser_node_indexer.cpp"
|
||||
|
||||
|
||||
@@ -12,9 +12,8 @@
|
||||
********************************************************************************/
|
||||
|
||||
#include "environment.h"
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include "../../global/exec_dir_helper.h"
|
||||
#include "../../global/cmdlnparser/cmdlnparser.cpp"
|
||||
|
||||
CSdvPackagerEnvironment::CSdvPackagerEnvironment() :
|
||||
@@ -862,13 +861,16 @@ bool CSdvPackagerEnvironment::ProcessCommandLine(const std::vector<std::string>&
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const wchar_t* szInstallDir = _wgetenv(L"SDV_COMPONENT_INSTALL");
|
||||
if (!szInstallDir) szInstallDir = _wgetenv(L"SDV_FRAMEWORK_RUNTIME");
|
||||
if (szInstallDir) m_pathTargetLocation = szInstallDir;
|
||||
#elif defined __unix__
|
||||
const char* szInstallDir = getenv("SDV_COMPONENT_INSTALL");
|
||||
if (!szInstallDir) szInstallDir = getenv("SDV_FRAMEWORK_RUNTIME");
|
||||
if (szInstallDir) m_pathTargetLocation = std::filesystem::u8path(szInstallDir);
|
||||
#else
|
||||
#error OS not supported!
|
||||
#endif
|
||||
if (m_pathTargetLocation.empty()) m_pathTargetLocation = GetExecDirectory();
|
||||
}
|
||||
|
||||
// Is the directory existing? If not, create the directory
|
||||
|
||||
@@ -41,12 +41,6 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
// NOTE EVE 27.05.2025: This task has been taken over by the process watchdog.
|
||||
CProcessWatchdog watchdog;
|
||||
|
||||
// If not set, set the runtime location to the EXE directory.
|
||||
if (sdv::app::CAppControl::GetFrameworkRuntimeDirectory().empty())
|
||||
sdv::app::CAppControl::SetFrameworkRuntimeDirectory(GetExecDirectory());
|
||||
if (sdv::app::CAppControl::GetComponentInstallDirectory().empty())
|
||||
sdv::app::CAppControl::SetComponentInstallDirectory(GetExecDirectory());
|
||||
|
||||
// Process the command line.
|
||||
CSdvPackagerEnvironment environment(iArgc, rgszArgv);
|
||||
|
||||
@@ -54,7 +48,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (!environment.Silent())
|
||||
{
|
||||
std::cout << "SDV Component Installation Package Utility" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2026 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Author: Erik Verhoeven" << std::endl << std::endl;
|
||||
}
|
||||
|
||||
@@ -114,7 +108,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
}
|
||||
|
||||
// If running as server, load the settings file
|
||||
if (!environment.Local() && !GetAppSettings().LoadSettingsFile())
|
||||
if (!environment.Local() && !GetAppSettings().LoadSettings())
|
||||
{
|
||||
std::cerr << "ERROR: Failed to load the application settings file; cannot continue!" << std::endl;
|
||||
return -1;
|
||||
|
||||
@@ -450,7 +450,7 @@ bool CPackager::Configure()
|
||||
m_ssArgError = CMDLN_MISSING_TARGET_MSG;
|
||||
return false;
|
||||
}
|
||||
if (!GetAppSettings().SaveSettingsFile())
|
||||
if (!GetAppSettings().SaveSettings())
|
||||
{
|
||||
SDV_LOG_ERROR("Failed to save application settings. Cannot configure components!");
|
||||
return false;
|
||||
@@ -743,7 +743,7 @@ bool CPackager::ConfigureFromManifest(const CInstallManifest& rmanifest)
|
||||
auto pathConfig = GetAppSettings().GetConfigPath(CAppSettings::EConfigType::user_config);
|
||||
WriteConfig(vecClasses, pathConfig, vecComponentsToAdd, true, vecAddedToConfig);
|
||||
}
|
||||
if (!GetAppSettings().SaveSettingsFile())
|
||||
if (!GetAppSettings().SaveSettings())
|
||||
{
|
||||
SDV_LOG_ERROR("Failed to save application settings. Cannot configure components!");
|
||||
return false;
|
||||
@@ -806,11 +806,11 @@ void CPackager::WriteConfig(const std::vector<sdv::SClassInfo>& rvecAllClasses,
|
||||
break;
|
||||
case sdv::EObjectType::complex_service:
|
||||
case sdv::EObjectType::vehicle_function:
|
||||
case sdv::EObjectType::utility:
|
||||
eIncompatible = bUserConfig ? ECompatibility::compatible : ECompatibility::incompatible;
|
||||
break;
|
||||
case sdv::EObjectType::proxy:
|
||||
case sdv::EObjectType::stub:
|
||||
case sdv::EObjectType::utility:
|
||||
eIncompatible = ECompatibility::silent_incompatible;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -65,7 +65,7 @@ static BOOL WINAPI ControlHandler(DWORD dwCtrlType)
|
||||
}
|
||||
#elif defined __unix__
|
||||
/**
|
||||
* @brief Signal handler to catch signal eevents.
|
||||
* @brief Signal handler to catch signal events.
|
||||
* @param[in] iSigNum The signal type that was triggered.
|
||||
*/
|
||||
static void SignalHandler(int iSigNum)
|
||||
@@ -97,12 +97,6 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (thread.joinable())
|
||||
thread.join();
|
||||
|
||||
// If not set, set the runtime location to the EXE directory.
|
||||
if (sdv::app::CAppControl::GetFrameworkRuntimeDirectory().empty())
|
||||
sdv::app::CAppControl::SetFrameworkRuntimeDirectory(GetExecDirectory());
|
||||
if (sdv::app::CAppControl::GetComponentInstallDirectory().empty())
|
||||
sdv::app::CAppControl::SetComponentInstallDirectory(GetExecDirectory());
|
||||
|
||||
CCommandLine cmdln(static_cast<uint32_t>(CCommandLine::EParseFlags::no_assignment_character));
|
||||
bool bHelp = false;
|
||||
bool bVersion = false;
|
||||
@@ -123,7 +117,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
}
|
||||
|
||||
std::cout << "SDV Server Log Monitor Utility" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2026 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Author: Erik Verhoeven" << std::endl << std::endl;
|
||||
|
||||
if (bVersion)
|
||||
|
||||
@@ -109,7 +109,7 @@ extern "C" int main(int iArgc, const char* rgszArgv[])
|
||||
if (!bSilent)
|
||||
{
|
||||
std::cout << "abtract device / basic services utility" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2025 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Copyright (C): 2022-2026 ZF Friedrichshafen AG" << std::endl;
|
||||
std::cout << "Author: Thomas Pfleiderer" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user