220 lines
6.0 KiB
C
220 lines
6.0 KiB
C
/*
|
|
* Copyright 2023, Digi International Inc.
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#include <cccs_services.h>
|
|
#include <libgen.h>
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
|
|
#if !(defined UNUSED_ARGUMENT)
|
|
#define UNUSED_ARGUMENT(a) (void)(a)
|
|
#endif
|
|
|
|
#define TARGET_GET_TIME "get_time"
|
|
|
|
/*
|
|
* sigaction_handler() - Handler to execute after receiving a signal
|
|
*
|
|
* @signum: Received signal.
|
|
*/
|
|
static void sigaction_handler(int signum)
|
|
{
|
|
log_debug("%s: received signal %d", __func__, signum);
|
|
|
|
exit(0);
|
|
}
|
|
|
|
/*
|
|
* cleanup() - Frees all the allocated memory before exiting
|
|
*/
|
|
static void cleanup(void)
|
|
{
|
|
cccs_resp_t resp;
|
|
cccs_comm_error_t ret;
|
|
|
|
ret = cccs_remove_request_target(TARGET_GET_TIME, &resp);
|
|
if (ret != CCCS_SEND_ERROR_NONE) {
|
|
log_error("%s: Cannot unregister target '%s': CCCSD error %d",
|
|
__func__, TARGET_GET_TIME, ret);
|
|
} else if (resp.code != 0) {
|
|
if (resp.hint)
|
|
log_error("%s: Cannot unregister target '%s': CCCSD error, %s (%d)",
|
|
__func__, TARGET_GET_TIME, resp.hint, resp.code);
|
|
else
|
|
log_error("%s: Cannot unregister target '%s': CCCSD error, %d",
|
|
__func__, TARGET_GET_TIME, resp.code);
|
|
}
|
|
|
|
free(resp.hint);
|
|
|
|
deinit_logger();
|
|
}
|
|
|
|
/*
|
|
* register_signals() - Registers program signals
|
|
*/
|
|
static void register_signals(void)
|
|
{
|
|
struct sigaction new_action;
|
|
struct sigaction old_action;
|
|
|
|
atexit(cleanup);
|
|
|
|
new_action.sa_handler = sigaction_handler;
|
|
new_action.sa_flags = 0;
|
|
sigemptyset(&new_action.sa_mask);
|
|
|
|
sigaction(SIGINT, NULL, &old_action);
|
|
if (old_action.sa_handler != SIG_IGN)
|
|
sigaction(SIGINT, &new_action, NULL);
|
|
|
|
sigaction(SIGHUP, &old_action, NULL);
|
|
if (old_action.sa_handler != SIG_IGN)
|
|
sigaction(SIGHUP, &new_action, NULL);
|
|
|
|
sigaction(SIGTERM, &old_action, NULL);
|
|
if (old_action.sa_handler != SIG_IGN)
|
|
sigaction(SIGTERM, &new_action, NULL);
|
|
}
|
|
|
|
/*
|
|
* get_time_cb() - Data callback for 'get_time' data requests
|
|
*
|
|
* @target: Target ID of the data request (get_time).
|
|
* @req_buf_info: Buffer containing the data request.
|
|
* @resp_buf_info: Buffer to store the answer of the request.
|
|
*
|
|
* Logs information about the received request and executes the corresponding
|
|
* command.
|
|
*
|
|
* Return: 'CCCS_RECEIVE_ERROR_NONE' if success, any other value on failure.
|
|
*/
|
|
static cccs_receive_error_t get_time_cb(char const *const target,
|
|
cccs_buffer_info_t const *const req_buf_info,
|
|
cccs_buffer_info_t *const resp_buf_info)
|
|
{
|
|
time_t t = time(NULL);
|
|
char *time_str = ctime(&t);
|
|
|
|
UNUSED_ARGUMENT(req_buf_info);
|
|
log_debug("%s: target='%s'", __func__, target);
|
|
|
|
resp_buf_info->length = snprintf(NULL, 0, "Time: %s", time_str);
|
|
resp_buf_info->buffer = calloc(resp_buf_info->length + 1, sizeof(char));
|
|
if (resp_buf_info->buffer == NULL) {
|
|
log_error("%s: resp_buf_info calloc error", __func__);
|
|
|
|
return CCCS_RECEIVE_ERROR_INSUFFICIENT_MEMORY;
|
|
}
|
|
|
|
resp_buf_info->length = sprintf(resp_buf_info->buffer, "Time: %s", time_str);
|
|
|
|
return CCCS_RECEIVE_ERROR_NONE;
|
|
}
|
|
|
|
/*
|
|
* get_time_status_cb() - Status callback for 'get_time' data requests
|
|
*
|
|
* @target: Target ID of the data request (get_time)
|
|
* @resp_buf_info: Buffer containing the response data.
|
|
* @receive_error: The error status of the receive process.
|
|
* @receive_error_hint: The error hint from the connector service.
|
|
*
|
|
* This callback is executed when the response process has finished. It doesn't
|
|
* matter if everything worked or there was an error during the process.
|
|
*
|
|
* Cleans and frees the response buffer.
|
|
*/
|
|
static void get_time_status_cb(char const *const target,
|
|
cccs_buffer_info_t *const resp_buf_info,
|
|
int receive_error,
|
|
const char *const receive_error_hint)
|
|
{
|
|
log_debug("%s: target='%s' - error='%d' - error-hint='%s'",
|
|
__func__, target, receive_error, receive_error_hint);
|
|
|
|
/* Free the response buffer */
|
|
if (resp_buf_info != NULL)
|
|
free(resp_buf_info->buffer);
|
|
}
|
|
|
|
/*
|
|
* Use the following SCI request to test this example (insert your Device ID):
|
|
*
|
|
* <sci_request version="1.0">
|
|
* <data_service>
|
|
* <targets>
|
|
* <device id="00000000-00000000-XXXXXXXX-XXXXXXXX"/>
|
|
* </targets>
|
|
* <requests>
|
|
* <device_request target_name="get_time"/>
|
|
* </requests>
|
|
* </data_service>
|
|
* </sci_request>
|
|
*
|
|
*/
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
cccs_comm_error_t ret;
|
|
char *name = basename(argv[0]);
|
|
cccs_resp_t resp;
|
|
int read_char;
|
|
|
|
init_logger(LOG_DEBUG, LOG_CONS | LOG_NDELAY | LOG_PID | LOG_PERROR, name);
|
|
|
|
register_signals();
|
|
|
|
if (!cccs_is_daemon_ready(CCCSD_NO_WAIT)) {
|
|
log_error("%s: CCCS daemon not ready... exiting", __func__);
|
|
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
ret = cccs_add_request_target(TARGET_GET_TIME, get_time_cb,
|
|
get_time_status_cb, &resp);
|
|
if (ret != CCCS_SEND_ERROR_NONE) {
|
|
log_error("%s: Cannot register target '%s': CCCSD error %d",
|
|
__func__, TARGET_GET_TIME, ret);
|
|
|
|
return EXIT_FAILURE;
|
|
} else if (resp.code != 0) {
|
|
if (resp.hint) {
|
|
log_error("%s: Cannot register target '%s': CCCSD error, %s (%d)",
|
|
__func__, TARGET_GET_TIME, resp.hint, resp.code);
|
|
free(resp.hint);
|
|
} else {
|
|
log_error("%s: Cannot register target '%s': CCCSD error, %d",
|
|
__func__, TARGET_GET_TIME, resp.code);
|
|
}
|
|
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
free(resp.hint);
|
|
|
|
printf("Waiting for Remote Manager request...\n");
|
|
printf("Press 'q' and 'Enter' to exit\n");
|
|
do {
|
|
read_char = getchar();
|
|
} while (read_char != 'q');
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|