LCOV - code coverage report
Current view: top level - console - dlt-control-common.c (source / functions) Hit Total Coverage
Test: dlt_final_coverage.info Lines: 147 213 69.0 %
Date: 2024-12-06 04:41:42 Functions: 18 19 94.7 %

          Line data    Source code
       1             : /**
       2             :  * Copyright (C) 2015  Advanced Driver Information Technology.
       3             :  * This code is developed by Advanced Driver Information Technology.
       4             :  * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
       5             :  *
       6             :  * This file is part of COVESA Project Dlt - Diagnostic Log and Trace console apps.
       7             :  *
       8             :  *
       9             :  * \copyright
      10             :  * This Source Code Form is subject to the terms of the
      11             :  * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
      12             :  * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
      13             :  *
      14             :  *
      15             :  * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015
      16             :  * \author Frederic Berat <fberat@de.adit-jv.com> ADIT 2015
      17             :  *
      18             :  * \file dlt-control-common.c
      19             :  * For further information see http://www.covesa.org/.
      20             :  */
      21             : 
      22             : /*******************************************************************************
      23             : **                                                                            **
      24             : **  SRC-MODULE: dlt-control-common.c                                          **
      25             : **                                                                            **
      26             : **  TARGET    : linux                                                         **
      27             : **                                                                            **
      28             : **  PROJECT   : DLT                                                           **
      29             : **                                                                            **
      30             : **  AUTHOR    : Christoph Lipka clipka@jp.adit-jv.com                         **
      31             : **  PURPOSE   :                                                               **
      32             : **                                                                            **
      33             : **  REMARKS   :                                                               **
      34             : **                                                                            **
      35             : **  PLATFORM DEPENDANT [yes/no]: yes                                          **
      36             : **                                                                            **
      37             : **  TO BE CHANGED BY USER [yes/no]: no                                        **
      38             : **                                                                            **
      39             : *******************************************************************************/
      40             : 
      41             : /*******************************************************************************
      42             : **                      Author Identity                                       **
      43             : ********************************************************************************
      44             : **                                                                            **
      45             : ** Initials     Name                       Company                            **
      46             : ** --------     -------------------------  ---------------------------------- **
      47             : **  cl          Christoph Lipka            ADIT                               **
      48             : **  fb          Frederic Berat             ADIT                               **
      49             : *******************************************************************************/
      50             : #define pr_fmt(fmt) "Common control: "fmt
      51             : 
      52             : #include <errno.h>
      53             : #include <dirent.h>
      54             : #include <stdio.h>
      55             : #include <stdlib.h>
      56             : #include <string.h>
      57             : #include <pthread.h>
      58             : #include <sys/types.h>
      59             : #include <sys/socket.h>
      60             : 
      61             : #include "dlt_common.h"
      62             : #include "dlt_protocol.h"
      63             : #include "dlt_client.h"
      64             : 
      65             : #include "dlt-control-common.h"
      66             : 
      67             : #ifdef EXTENDED_FILTERING
      68             :     #   if defined(__linux__) || defined(__ANDROID_API__)
      69             :     #      include <json-c/json.h> /* for json filter parsing on Linux and Android */
      70             :     #   endif
      71             :     #   ifdef __QNX__
      72             :     #      include <sys/json.h> /* for json filter parsing on QNX */
      73             :     #   endif
      74             : #endif
      75             : 
      76             : #define DLT_CTRL_APID    "DLTC"
      77             : #define DLT_CTRL_CTID    "DLTC"
      78             : 
      79             : /** @brief Analyze the daemon answer
      80             :  *
      81             :  * This function as to be provided by the user of the connection.
      82             :  *
      83             :  * @param answer  The textual answer of the daemon
      84             :  * @param payload The daemons answer payload
      85             :  * @param length  The daemons answer payload length
      86             :  *
      87             :  * @return User defined.
      88             :  */
      89             : static int (*response_analyzer_cb)(char *, void *, int);
      90             : 
      91             : static pthread_t daemon_connect_thread;
      92             : static DltClient g_client;
      93             : static int callback_return = -1;
      94             : static pthread_mutex_t answer_lock = PTHREAD_MUTEX_INITIALIZER;
      95             : static pthread_cond_t answer_cond = PTHREAD_COND_INITIALIZER;
      96             : 
      97             : static int local_verbose;
      98             : static char local_ecuid[DLT_CTRL_ECUID_LEN]; /* Name of ECU */
      99             : static int local_timeout;
     100             : static char local_filename[DLT_MOUNT_PATH_MAX]= {0}; /* Path to dlt.conf */
     101             : 
     102          18 : int get_verbosity(void)
     103             : {
     104          46 :     return local_verbose;
     105             : }
     106             : 
     107           0 : void set_verbosity(int v)
     108             : {
     109           2 :     local_verbose = !!v;
     110           0 : }
     111             : 
     112           4 : char *get_ecuid(void)
     113             : {
     114           4 :     return local_ecuid;
     115             : }
     116             : 
     117           2 : void set_ecuid(char *ecuid)
     118             : {
     119           2 :     char *ecuid_conf = NULL;
     120             : 
     121           2 :     if (local_ecuid != ecuid) {
     122             :         /* If user pass NULL, read ECUId from dlt.conf */
     123           0 :         if (ecuid == NULL) {
     124           0 :             if (dlt_parse_config_param("ECUId", &ecuid_conf) == 0) {
     125             :                 memset(local_ecuid, 0, DLT_CTRL_ECUID_LEN);
     126           0 :                 strncpy(local_ecuid, ecuid_conf, DLT_CTRL_ECUID_LEN);
     127           0 :                 local_ecuid[DLT_CTRL_ECUID_LEN -1] = '\0';
     128             :                 if (ecuid_conf !=NULL)
     129           0 :                     free(ecuid_conf);
     130             :             }
     131             :             else {
     132           0 :                 pr_error("Cannot read ECUid from dlt.conf\n");
     133             :             }
     134             :         }
     135             :         else {
     136             :             /* Set user passed ECUID */
     137             :             memset(local_ecuid, 0, DLT_CTRL_ECUID_LEN);
     138             :             strncpy(local_ecuid, ecuid, DLT_CTRL_ECUID_LEN);
     139           0 :             local_ecuid[DLT_CTRL_ECUID_LEN - 1] = '\0';
     140             :         }
     141             :     }
     142           2 : }
     143             : 
     144           2 : void set_conf(char *file_path)
     145             : {
     146           2 :     if (file_path != NULL) {
     147             :         memset(local_filename, 0, DLT_MOUNT_PATH_MAX);
     148             :         strncpy(local_filename, file_path, DLT_MOUNT_PATH_MAX);
     149           2 :         local_filename[DLT_MOUNT_PATH_MAX - 1] = '\0';
     150             :     }
     151             :     else {
     152           0 :         pr_error("Argument is NULL\n");
     153             :     }
     154           2 : }
     155             : 
     156           2 : int get_timeout(void)
     157             : {
     158           2 :     return local_timeout;
     159             : }
     160             : 
     161           2 : void set_timeout(int t)
     162             : {
     163           2 :     local_timeout = DLT_CTRL_TIMEOUT;
     164             : 
     165           2 :     if (t > 1)
     166           2 :         local_timeout = t;
     167             :     else
     168           0 :         pr_error("Timeout to small. Set to default: %d",
     169             :                  DLT_CTRL_TIMEOUT);
     170           2 : }
     171             : 
     172           2 : void set_send_serial_header(const int value)
     173             : {
     174           2 :     g_client.send_serial_header = value;
     175           2 : }
     176             : 
     177           2 : void set_resync_serial_header(const int value)
     178             : {
     179           2 :     g_client.resync_serial_header = value;
     180           2 : }
     181             : 
     182           2 : int dlt_parse_config_param(char *config_id, char **config_data)
     183             : {
     184             :     FILE *pFile = NULL;
     185             :     int value_length = DLT_LINE_LEN;
     186           2 :     char line[DLT_LINE_LEN - 1] = { 0 };
     187           2 :     char token[DLT_LINE_LEN] = { 0 };
     188           2 :     char value[DLT_LINE_LEN] = { 0 };
     189             :     char *pch = NULL;
     190             :     const char *filename = NULL;
     191             : 
     192           2 :     if (*config_data != NULL)
     193           0 :         *config_data = NULL;
     194             : 
     195             :     /* open configuration file */
     196           2 :     if (local_filename[0] != 0) {
     197             :         filename = local_filename;
     198             :     } else {
     199             :         filename = CONFIGURATION_FILES_DIR "/dlt.conf";
     200             :     }
     201           2 :     pFile = fopen(filename, "r");
     202             : 
     203           2 :     if (pFile != NULL) {
     204             :         while (1) {
     205             :             /* fetch line from configuration file */
     206          14 :             if (fgets(line, value_length - 1, pFile) != NULL) {
     207          12 :                 if (strncmp(line, config_id, strlen(config_id)) == 0) {
     208           2 :                     pch = strtok(line, " =\r\n");
     209           2 :                     token[0] = 0;
     210           2 :                     value[0] = 0;
     211             : 
     212           4 :                     while (pch != NULL) {
     213           4 :                         if (token[0] == 0) {
     214             :                             strncpy(token, pch, sizeof(token) - 1);
     215           2 :                             token[sizeof(token) - 1] = 0;
     216             :                         }
     217             :                         else {
     218             :                             strncpy(value, pch, sizeof(value) - 1);
     219           2 :                             value[sizeof(value) - 1] = 0;
     220           2 :                             break;
     221             :                         }
     222             : 
     223           2 :                         pch = strtok(NULL, " =\r\n");
     224             :                     }
     225             : 
     226           2 :                     if (token[0] && value[0]) {
     227           2 :                         if (strcmp(token, config_id) == 0) {
     228           2 :                             *(config_data) = (char *)
     229           2 :                                 calloc(DLT_DAEMON_FLAG_MAX, sizeof(char));
     230             :                             memcpy(*config_data,
     231             :                                    value,
     232             :                                    DLT_DAEMON_FLAG_MAX - 1);
     233             :                         }
     234             :                     }
     235             :                 }
     236             :             }
     237             :             else {
     238             :                 break;
     239             :             }
     240             :         }
     241             : 
     242           2 :         fclose (pFile);
     243             :     }
     244             :     else {
     245           0 :         fprintf(stderr, "Cannot open configuration file: %s\n", filename);
     246             :     }
     247             : 
     248           2 :     if (*config_data == NULL)
     249           0 :         return -1;
     250             : 
     251             :     return 0;
     252             : }
     253             : 
     254             : /** @brief Prepare the extra headers of a DLT message
     255             :  *
     256             :  * Modifies the extra headers of the message so that it can be sent.
     257             :  *
     258             :  * @param msg The message to be prepared
     259             :  * @param header The base header to be used.
     260             :  *
     261             :  * @return 0 on success, -1 otherwise.
     262             :  */
     263           2 : static int prepare_extra_headers(DltMessage *msg, uint8_t *header)
     264             : {
     265             :     uint32_t shift = 0;
     266             : 
     267           2 :     pr_verbose("Preparing extra headers.\n");
     268             : 
     269           2 :     if (!msg || !header)
     270             :         return -1;
     271             : 
     272           2 :     shift = (uint32_t) (sizeof(DltStorageHeader) +
     273             :         sizeof(DltStandardHeader) +
     274           2 :         DLT_STANDARD_HEADER_EXTRA_SIZE(msg->standardheader->htyp));
     275             : 
     276             :     /* Set header extra parameters */
     277           2 :     dlt_set_id(msg->headerextra.ecu, get_ecuid());
     278             : 
     279           2 :     msg->headerextra.tmsp = dlt_uptime();
     280             : 
     281             :     /* Copy header extra parameters to header buffer */
     282           2 :     if (dlt_message_set_extraparameters(msg, get_verbosity()) == -1) {
     283           0 :         pr_error("Cannot copy header extra parameter\n");
     284           0 :         return -1;
     285             :     }
     286             : 
     287             :     /* prepare extended header */
     288           2 :     msg->extendedheader = (DltExtendedHeader *)(header + shift);
     289             : 
     290           2 :     msg->extendedheader->msin = DLT_MSIN_CONTROL_REQUEST;
     291             : 
     292           2 :     msg->extendedheader->noar = 1; /* one payload packet */
     293             : 
     294             :     /* Dummy values have to be set */
     295           2 :     dlt_set_id(msg->extendedheader->apid, DLT_CTRL_APID);
     296           2 :     dlt_set_id(msg->extendedheader->ctid, DLT_CTRL_CTID);
     297             : 
     298           2 :     return 0;
     299             : }
     300             : 
     301             : /** @brief Prepare the headers of a DLT message
     302             :  *
     303             :  * Modifies the headers of the message so that it can be sent.
     304             :  *
     305             :  * @param msg The message to be prepared
     306             :  * @param header The base header to be used.
     307             :  *
     308             :  * @return 0 on success, -1 otherwise.
     309             :  */
     310           2 : static int prepare_headers(DltMessage *msg, uint8_t *header)
     311             : {
     312             :     uint32_t len = 0;
     313             : 
     314           2 :     pr_verbose("Preparing headers.\n");
     315             : 
     316           2 :     if (!msg || !header)
     317             :         return -1;
     318             : 
     319           2 :     msg->storageheader = (DltStorageHeader *)header;
     320             : 
     321           2 :     if (dlt_set_storageheader(msg->storageheader, "") == -1) {
     322           0 :         pr_error("Storage header initialization failed.\n");
     323           0 :         return -1;
     324             :     }
     325             : 
     326             :     /* prepare standard header */
     327           2 :     msg->standardheader =
     328           2 :         (DltStandardHeader *)(header + sizeof(DltStorageHeader));
     329             : 
     330           2 :     msg->standardheader->htyp = DLT_HTYP_WEID |
     331             :         DLT_HTYP_WTMS | DLT_HTYP_UEH | DLT_HTYP_PROTOCOL_VERSION1;
     332             : 
     333             : #if (BYTE_ORDER == BIG_ENDIAN)
     334             :     msg->standardheader->htyp = (msg->standardheader->htyp | DLT_HTYP_MSBF);
     335             : #endif
     336             : 
     337           2 :     msg->standardheader->mcnt = 0;
     338             : 
     339             :     /* prepare length information */
     340           2 :     msg->headersize = (uint32_t) (sizeof(DltStorageHeader) +
     341             :         sizeof(DltStandardHeader) +
     342             :         sizeof(DltExtendedHeader) +
     343             :         DLT_STANDARD_HEADER_EXTRA_SIZE(msg->standardheader->htyp));
     344             : 
     345           2 :     len = (uint32_t) (msg->headersize - sizeof(DltStorageHeader) + msg->datasize);
     346             : 
     347           2 :     if (len > UINT16_MAX) {
     348           0 :         pr_error("Message header is too long.\n");
     349           0 :         return -1;
     350             :     }
     351             : 
     352           2 :     msg->standardheader->len = DLT_HTOBE_16(len);
     353             : 
     354           2 :     return 0;
     355             : }
     356             : 
     357             : /** @brief Prepare a DLT message.
     358             :  *
     359             :  * The DLT message is built using the data given by the user.
     360             :  * The data is basically composed of a buffer and a size.
     361             :  *
     362             :  * @param data The message body to be used to build the DLT message.
     363             :  *
     364             :  * @return 0 on success, -1 otherwise.
     365             :  */
     366           2 : static DltMessage *dlt_control_prepare_message(DltControlMsgBody *data)
     367             : {
     368             :     DltMessage *msg = NULL;
     369             : 
     370           2 :     pr_verbose("Preparing message.\n");
     371             : 
     372           2 :     if (data == NULL) {
     373           0 :         pr_error("Data for message body is NULL\n");
     374           0 :         return NULL;
     375             :     }
     376             : 
     377           2 :     msg = calloc(1, sizeof(DltMessage));
     378             : 
     379           2 :     if (msg == NULL) {
     380           0 :         pr_error("Cannot allocate memory for Dlt Message\n");
     381           0 :         return NULL;
     382             :     }
     383             : 
     384           2 :     if (dlt_message_init(msg, get_verbosity()) == -1) {
     385           0 :         pr_error("Cannot initialize Dlt Message\n");
     386           0 :         free(msg);
     387           0 :         return NULL;
     388             :     }
     389             : 
     390             :     /* prepare payload of data */
     391           2 :     msg->databuffersize = msg->datasize = (uint32_t) data->size;
     392             : 
     393             :     /* Allocate memory for Dlt Message's buffer */
     394           2 :     msg->databuffer = (uint8_t *)calloc(1, data->size);
     395             : 
     396           2 :     if (msg->databuffer == NULL) {
     397           0 :         pr_error("Cannot allocate memory for data buffer\n");
     398           0 :         free(msg);
     399           0 :         return NULL;
     400             :     }
     401             : 
     402             :     /* copy data into message */
     403           2 :     memcpy(msg->databuffer, data->data, data->size);
     404             : 
     405             :     /* prepare storage header */
     406           2 :     if (prepare_headers(msg, msg->headerbuffer)) {
     407           0 :         dlt_message_free(msg, get_verbosity());
     408           0 :         free(msg);
     409           0 :         return NULL;
     410             :     }
     411             : 
     412             :     /* prepare extra headers */
     413           2 :     if (prepare_extra_headers(msg, msg->headerbuffer)) {
     414           0 :         dlt_message_free(msg, get_verbosity());
     415           0 :         free(msg);
     416           0 :         return NULL;
     417             :     }
     418             : 
     419             :     return msg;
     420             : }
     421             : 
     422             : /** @brief Initialize the connection with the daemon
     423             :  *
     424             :  * The connection is initialized using an internal callback. The user's
     425             :  * response analyzer will be finally executed by this callback.
     426             :  * The client pointer is used to established the connection.
     427             :  *
     428             :  * @param client A pointer to a valid client structure
     429             :  * @param cb The internal callback to be executed while receiving a new message
     430             :  *
     431             :  * @return 0 on success, -1 otherwise.
     432             :  */
     433           2 : static int dlt_control_init_connection(DltClient *client, void *cb)
     434             : {
     435           2 :     int (*callback)(DltMessage *message, void *data) = cb;
     436             : 
     437           2 :     if (!cb || !client) {
     438           0 :         pr_error("%s: Invalid parameters\n", __func__);
     439           0 :         return -1;
     440             :     }
     441             : 
     442           2 :     pr_verbose("Initializing the connection.\n");
     443             : 
     444           2 :     if (dlt_client_init(client, get_verbosity()) != 0) {
     445           0 :         pr_error("Failed to register callback (NULL)\n");
     446           0 :         return -1;
     447             :     }
     448             : 
     449           2 :     dlt_client_register_message_callback(callback);
     450             : 
     451           2 :     client->socketPath = NULL;
     452             : 
     453           2 :     if (dlt_parse_config_param("ControlSocketPath", &client->socketPath) != 0) {
     454             :         /* Failed to read from conf, copy default */
     455           0 :         if (dlt_client_set_socket_path(client, DLT_DAEMON_DEFAULT_CTRL_SOCK_PATH) == -1) {
     456           0 :             pr_error("set socket path didn't succeed\n");
     457           0 :             return -1;
     458             :         }
     459             :     }
     460             : 
     461           2 :     client->mode = DLT_CLIENT_MODE_UNIX;
     462             : 
     463           2 :     return dlt_client_connect(client, get_verbosity());
     464             : }
     465             : 
     466             : /** @brief Daemon listener function
     467             :  *
     468             :  * This function will continuously read on the DLT socket, until an error occurs
     469             :  * or the thread executing this function is canceled.
     470             :  *
     471             :  * @param data Thread parameter
     472             :  *
     473             :  * @return The thread parameter given as argument.
     474             :  */
     475           2 : static void *dlt_control_listen_to_daemon(void *data)
     476             : {
     477           2 :     pr_verbose("Ready to receive DLT answers.\n");
     478           2 :     dlt_client_main_loop(&g_client, NULL, get_verbosity());
     479           2 :     return data;
     480             : }
     481             : 
     482             : /** @brief Internal callback for DLT response
     483             :  *
     484             :  * This function is called by the dlt_client_main_loop once a response is read
     485             :  * from the DLT socket.
     486             :  * After some basic checks, the user's response analyzer is called. The return
     487             :  * value of the analyzer is then provided back to the dlt_control_send_message
     488             :  * function to be given back as a return value.
     489             :  * As this function is called in a dedicated thread, the return value is
     490             :  * provided using a global variable.
     491             :  * Access to this variable is controlled through a dedicated mutex.
     492             :  * New values are signaled using a dedicated condition variable.
     493             :  *
     494             :  * @param message The DLT answer
     495             :  * @param data Unused
     496             :  *
     497             :  * @return The analyzer return value or -1 on early errors.
     498             :  */
     499           2 : static int dlt_control_callback(DltMessage *message, void *data)
     500             : {
     501           2 :     char text[DLT_RECEIVE_BUFSIZE] = { 0 };
     502             :     (void)data;
     503             : 
     504           2 :     if (message == NULL) {
     505           0 :         pr_error("Received message is null\n");
     506           0 :         return -1;
     507             :     }
     508             : 
     509             :     /* prepare storage header */
     510           2 :     if (DLT_IS_HTYP_WEID(message->standardheader->htyp))
     511           2 :         dlt_set_storageheader(message->storageheader, message->headerextra.ecu);
     512             :     else
     513           0 :         dlt_set_storageheader(message->storageheader, "LCTL");
     514             : 
     515           2 :     dlt_message_header(message, text, DLT_RECEIVE_BUFSIZE, get_verbosity());
     516             : 
     517             :     /* Extracting payload */
     518           2 :     dlt_message_payload(message, text,
     519             :                         DLT_RECEIVE_BUFSIZE,
     520             :                         DLT_OUTPUT_ASCII,
     521             :                         get_verbosity());
     522             : 
     523             :     /*
     524             :      * Checking payload with the provided callback and return the result
     525             :      */
     526           2 :     pthread_mutex_lock(&answer_lock);
     527           4 :     callback_return = response_analyzer_cb(text,
     528           2 :                                            message->databuffer,
     529           2 :                                            (int) message->datasize);
     530           2 :     pthread_cond_signal(&answer_cond);
     531           2 :     pthread_mutex_unlock(&answer_lock);
     532             : 
     533           2 :     return callback_return;
     534             : }
     535             : 
     536             : /** @brief Send a message to the daemon and wait for the asynchronous answer.
     537             :  *
     538             :  * The answer is received and analyzed by a dedicated thread. Thus we need
     539             :  * to wait for the signal from this thread and then read the return value
     540             :  * to be provided to the user.
     541             :  * In case of timeout, this function fails.
     542             :  * The message provided by the user is formated in DLT format before sending.
     543             :  *
     544             :  * @param body The message provided by the user
     545             :  * @param timeout The time to wait before considering that no answer will come
     546             :  *
     547             :  * @return The user response analyzer return value, -1 in case of early error.
     548             :  */
     549           2 : int dlt_control_send_message(DltControlMsgBody *body, int timeout)
     550             : {
     551             :     struct timespec t;
     552             :     DltMessage *msg = NULL;
     553             : 
     554           2 :     if (!body) {
     555           0 :         pr_error("%s: Invalid input.\n", __func__);
     556           0 :         return -1;
     557             :     }
     558             : 
     559           2 :     if (clock_gettime(CLOCK_REALTIME, &t) == -1) {
     560           0 :         pr_error("Cannot read system time.\n");
     561           0 :         return -1;
     562             :     }
     563             : 
     564           2 :     t.tv_sec += timeout;
     565             : 
     566             :     /* send command to daemon here */
     567           2 :     msg = dlt_control_prepare_message(body);
     568             : 
     569           2 :     if (msg == NULL) {
     570           0 :         pr_error("Control message preparation failed\n");
     571           0 :         return -1;
     572             :     }
     573             : 
     574           2 :     pthread_mutex_lock(&answer_lock);
     575             : 
     576             :     /* Re-init the return value */
     577           2 :     callback_return = -1;
     578             : 
     579           2 :     if (dlt_client_send_message_to_socket(&g_client, msg) != DLT_RETURN_OK)
     580             :     {
     581           0 :         pr_error("Sending message to daemon failed\n");
     582           0 :         dlt_message_free(msg, get_verbosity());
     583           0 :         free(msg);
     584             : 
     585             :         /* make sure the mutex is unlocked to prevent deadlocks */
     586           0 :         pthread_mutex_unlock(&answer_lock);
     587           0 :         return -1;
     588             :     }
     589             : 
     590             :     /*
     591             :     * When a timeouts occurs, pthread_cond_timedwait()
     592             :     * shall nonetheless release and re-acquire the mutex referenced by mutex
     593             :     */
     594           2 :     pthread_cond_timedwait(&answer_cond, &answer_lock, &t);
     595           2 :     pthread_mutex_unlock(&answer_lock);
     596             : 
     597             :     /* Destroying the message */
     598           2 :     dlt_message_free(msg, get_verbosity());
     599           2 :     free(msg);
     600             : 
     601             :     /* At this point either the value is already correct, either it's still -1.
     602             :      * Then, we don't care to lock the access.
     603             :      */
     604           2 :     return callback_return;
     605             : }
     606             : 
     607             : /** @brief Control communication initialization
     608             :  *
     609             :  * This will prepare the DLT connection and the thread dedicated to the
     610             :  * response listening.
     611             :  *
     612             :  * @param response_analyzer User defined function used to analyze the response
     613             :  * @param ecuid The ECUID to provide to the daemon
     614             :  * @param verbosity The verbosity level
     615             :  *
     616             :  * @return 0 on success, -1 otherwise.
     617             :  */
     618           2 : int dlt_control_init(int (*response_analyzer)(char *, void *, int),
     619             :                      char *ecuid,
     620             :                      int verbosity)
     621             : {
     622           2 :     if (!response_analyzer || !ecuid) {
     623           0 :         pr_error("%s: Invalid input.\n", __func__);
     624           0 :         return -1;
     625             :     }
     626             : 
     627           2 :     response_analyzer_cb = response_analyzer;
     628           2 :     set_ecuid(ecuid);
     629             :     set_verbosity(verbosity);
     630             : 
     631           2 :     if (dlt_control_init_connection(&g_client, dlt_control_callback) != 0) {
     632           0 :         pr_error("Connection initialization failed\n");
     633           0 :         dlt_client_cleanup(&g_client, get_verbosity());
     634           0 :         return -1;
     635             :     }
     636             : 
     637             :     /* Contact DLT daemon */
     638           2 :     if (pthread_create(&daemon_connect_thread,
     639             :                        NULL,
     640             :                        dlt_control_listen_to_daemon,
     641             :                        NULL) != 0) {
     642           0 :         pr_error("Cannot create thread to communicate with DLT daemon.\n");
     643           0 :         return -1;
     644             :     }
     645             : 
     646             :     return 0;
     647             : }
     648             : 
     649             : /** @brief Control communication clean-up
     650             :  *
     651             :  * Cancels the listener thread and clean=up the dlt client structure.
     652             :  *
     653             :  * @return 0 on success, -1 otherwise.
     654             :  */
     655           2 : int dlt_control_deinit(void)
     656             : {
     657             :     /* At this stage, we want to stop sending/receiving
     658             :      * from dlt-daemon. So in order to avoid cancellation
     659             :      * at recv(), shutdown and close the socket
     660             :      */
     661           2 :     if (g_client.receiver.fd) {
     662           2 :         shutdown(g_client.receiver.fd, SHUT_RDWR);
     663           2 :         close(g_client.receiver.fd);
     664           2 :         g_client.receiver.fd = -1;
     665             :     }
     666             : 
     667             :         /* Stopping the listener thread */
     668           2 :     if (pthread_cancel(daemon_connect_thread)) {
     669           0 :         pr_error("Unable to cancel the thread with ERRNO=%s\n", strerror(errno));
     670             :     }
     671             :     else {
     672           2 :         if (pthread_join(daemon_connect_thread, NULL)) {
     673           0 :             pr_error("Unable to join the thread with ERRNO=%s\n", strerror(errno));
     674             :         }
     675             :     }
     676             : 
     677             :     /* Closing the socket */
     678           2 :     return dlt_client_cleanup(&g_client, get_verbosity());
     679             : }
     680             : 
     681             : 
     682             : #ifdef EXTENDED_FILTERING /* EXTENDED_FILTERING */
     683             : #   if defined(__linux__) || defined(__ANDROID_API__)
     684             : DltReturnValue dlt_json_filter_load(DltFilter *filter, const char *filename, int verbose)
     685             : {
     686             :     if ((filter == NULL) || (filename == NULL))
     687             :         return DLT_RETURN_WRONG_PARAMETER;
     688             : 
     689             :     if(verbose)
     690             :         pr_verbose("dlt_json_filter_load()\n");
     691             : 
     692             :     FILE *handle;
     693             :     char buffer[JSON_FILTER_SIZE*DLT_FILTER_MAX];
     694             :     struct json_object *j_parsed_json;
     695             :     struct json_object *j_app_id;
     696             :     struct json_object *j_context_id;
     697             :     struct json_object *j_log_level;
     698             :     struct json_object *j_payload_min;
     699             :     struct json_object *j_payload_max;
     700             :     enum json_tokener_error jerr;
     701             : 
     702             :     char app_id[DLT_ID_SIZE + 1] = "";
     703             :     char context_id[DLT_ID_SIZE + 1] = "";
     704             :     int32_t log_level = 0;
     705             :     int32_t payload_max = INT32_MAX;
     706             :     int32_t payload_min = 0;
     707             : 
     708             :     handle = fopen(filename, "r");
     709             : 
     710             :     if (handle == NULL) {
     711             :         pr_error("Filter file %s cannot be opened!\n", filename);
     712             :         return DLT_RETURN_ERROR;
     713             :     }
     714             : 
     715             :     if (fread(buffer, sizeof(buffer), 1, handle) != 0) {
     716             :         if (!feof(handle)) {
     717             :             pr_error("Filter file %s is to big for reading it with current buffer!\n", filename);
     718             :             return DLT_RETURN_ERROR;
     719             :         }
     720             :     }
     721             : 
     722             :     j_parsed_json = json_tokener_parse_verbose(buffer, &jerr);
     723             : 
     724             :     if (jerr != json_tokener_success) {
     725             :         pr_error("Faild to parse given filter %s: %s\n", filename, json_tokener_error_desc(jerr));
     726             :         return DLT_RETURN_ERROR;
     727             :     }
     728             : 
     729             :     printf("The following filter(s) are applied: \n");
     730             :     pr_verbose("The following filter(s) are applied: \n");
     731             :     int iterator = 0;
     732             :     json_object_object_foreach(j_parsed_json, key, val)
     733             :     {
     734             :         if (iterator >= DLT_FILTER_MAX) {
     735             :             pr_error("Maximum number (%d) of allowed filters reached, ignoring rest of filters!\n",
     736             :                      DLT_FILTER_MAX);
     737             :             break;
     738             :         }
     739             : 
     740             :         printf("%s:\n", key);
     741             :         pr_verbose("%s:\n", key);
     742             : 
     743             :         if (json_object_object_get_ex(val, "AppId", &j_app_id))
     744             :             strncpy(app_id, json_object_get_string(j_app_id), DLT_ID_SIZE);
     745             :         else
     746             :             dlt_set_id(app_id, "");
     747             : 
     748             :         if (json_object_object_get_ex(val, "ContextId", &j_context_id))
     749             :             strncpy(context_id, json_object_get_string(j_context_id), DLT_ID_SIZE);
     750             :         else
     751             :             dlt_set_id(context_id, "");
     752             : 
     753             :         if (json_object_object_get_ex(val, "LogLevel", &j_log_level))
     754             :             log_level = json_object_get_int(j_log_level);
     755             :         else
     756             :             log_level = 0;
     757             : 
     758             :         if (json_object_object_get_ex(val, "PayloadMin", &j_payload_min))
     759             :             payload_min = json_object_get_int(j_payload_min);
     760             :         else
     761             :             payload_min = 0;
     762             : 
     763             :         if (json_object_object_get_ex(val, "PayloadMax", &j_payload_max))
     764             :             payload_max = json_object_get_int(j_payload_max);
     765             :         else
     766             :             payload_max = INT32_MAX;
     767             : 
     768             :         dlt_filter_add(filter, app_id, context_id, log_level, payload_min, payload_max, verbose);
     769             : 
     770             :         printf("\tAppId: %.*s\n", DLT_ID_SIZE, app_id);
     771             :         pr_verbose("\tAppId: %.*s\n", DLT_ID_SIZE, app_id);
     772             :         printf("\tConextId: %.*s\n", DLT_ID_SIZE, context_id);
     773             :         pr_verbose("\tConextId: %.*s\n", DLT_ID_SIZE, context_id);
     774             :         printf("\tLogLevel: %i\n", log_level);
     775             :         pr_verbose("\tLogLevel: %i\n", log_level);
     776             :         printf("\tPayloadMin: %i\n", payload_min);
     777             :         pr_verbose("\tPayloadMin: %i\n", payload_min);
     778             :         printf("\tPayloadMax: %i\n", payload_max);
     779             :         pr_verbose("\tPayloadMax: %i\n", payload_max);
     780             : 
     781             :         iterator++;
     782             :     }
     783             : 
     784             :     fclose(handle);
     785             : 
     786             :     return DLT_RETURN_OK;
     787             : }
     788             : #   endif /* __Linux__ */
     789             : 
     790             : #   ifdef __QNX__
     791             : DltReturnValue dlt_json_filter_load(DltFilter *filter, const char *filename, int verbose)
     792             : {
     793             :     if ((filter == NULL) || (filename == NULL))
     794             :         return DLT_RETURN_WRONG_PARAMETER;
     795             : 
     796             :     if(verbose)
     797             :         pr_verbose("dlt_json_filter_load()\n");
     798             : 
     799             :     json_decoder_t *j_decoder = json_decoder_create();
     800             : 
     801             :     const char *s_app_id;
     802             :     const char *s_context_id;
     803             :     int32_t log_level = 0;
     804             :     int32_t payload_max = INT32_MAX;
     805             :     int32_t payload_min = 0;
     806             : 
     807             :     json_decoder_error_t ret = json_decoder_parse_file(j_decoder, filename);
     808             : 
     809             :     if (ret != JSON_DECODER_OK) {
     810             :         pr_error("Faild to parse given filter %s: json_decoder_error_t is %i\n", filename, ret);
     811             :         return DLT_RETURN_ERROR;
     812             :     }
     813             : 
     814             :     json_decoder_push_object(j_decoder, NULL, true);
     815             : 
     816             :     int iterator = 0;
     817             :     bool end_of_json = false;
     818             : 
     819             :     while (!end_of_json) {
     820             :         if (iterator >= DLT_FILTER_MAX) {
     821             :             pr_error("Maximum number (%d) of allowed filters reached, ignoring rest of filters!\n",
     822             :                      DLT_FILTER_MAX);
     823             :             break;
     824             :         }
     825             : 
     826             :         if (json_decoder_next(j_decoder) == JSON_DECODER_NOT_FOUND)
     827             :             end_of_json = true;
     828             : 
     829             :         json_decoder_previous(j_decoder);
     830             : 
     831             :         printf("%s:\n", json_decoder_name(j_decoder));
     832             :         json_decoder_push_object(j_decoder, NULL, true);
     833             : 
     834             :         if (json_decoder_get_string(j_decoder, "AppId", &s_app_id, true) != JSON_DECODER_OK)
     835             :             s_app_id = "";
     836             : 
     837             :         if (json_decoder_get_string(j_decoder, "ContextId", &s_context_id, true) != JSON_DECODER_OK)
     838             :             s_context_id = "";
     839             : 
     840             :         if (json_decoder_get_int(j_decoder, "LogLevel", &log_level, true) != JSON_DECODER_OK)
     841             :             log_level = 0;
     842             : 
     843             :         if (json_decoder_get_int(j_decoder, "PayloadMin", &payload_min, true) != JSON_DECODER_OK)
     844             :             payload_min = 0;
     845             : 
     846             :         if (json_decoder_get_int(j_decoder, "PayloadMax", &payload_max, true) != JSON_DECODER_OK)
     847             :             payload_max = INT32_MAX;
     848             : 
     849             :         char app_id[DLT_ID_SIZE];
     850             :         char context_id[DLT_ID_SIZE];
     851             : 
     852             :         #pragma GCC diagnostic push
     853             :         #pragma GCC diagnostic ignored "-Wstringop-truncation"
     854             :         strncpy(app_id, s_app_id, DLT_ID_SIZE);
     855             :         strncpy(context_id, s_context_id, DLT_ID_SIZE);
     856             :         #pragma GCC diagnostic pop
     857             : 
     858             :         dlt_filter_add(filter, app_id, context_id, log_level, payload_min, payload_max, verbose);
     859             : 
     860             :         printf("\tAppId: %.*s\n", DLT_ID_SIZE, app_id);
     861             :         printf("\tConextId: %.*s\n", DLT_ID_SIZE, context_id);
     862             :         printf("\tLogLevel: %i\n", log_level);
     863             :         printf("\tPayloadMin: %i\n", payload_min);
     864             :         printf("\tPayloadMax: %i\n", payload_max);
     865             : 
     866             :         json_decoder_pop(j_decoder);
     867             : 
     868             :         iterator++;
     869             :     }
     870             : 
     871             :     json_decoder_destroy(j_decoder);
     872             : 
     873             :     return DLT_RETURN_OK;
     874             : }
     875             : #   endif /* __QNX__ */
     876             : #endif /* EXTENDED_FILTERING */
     877             : 
     878             : #ifdef EXTENDED_FILTERING /* EXTENDED_FILTERING */
     879             : #   if defined(__linux__) || defined(__ANDROID_API__)
     880             : DltReturnValue dlt_json_filter_save(DltFilter *filter, const char *filename, int verbose)
     881             : {
     882             :     if ((filter == NULL) || (filename == NULL))
     883             :         return DLT_RETURN_WRONG_PARAMETER;
     884             : 
     885             :     if(verbose)
     886             :         pr_verbose("dlt_json_filter_save()\n");
     887             : 
     888             :     struct json_object *json_filter_obj = json_object_new_object();
     889             : 
     890             :     for (int num = 0; num < filter->counter; num++) {
     891             :         struct json_object *tmp_json_obj = json_object_new_object();
     892             :         char filter_name[JSON_FILTER_NAME_SIZE];
     893             :         sprintf(filter_name, "filter%i", num);
     894             : 
     895             :         if (filter->apid[num][DLT_ID_SIZE - 1] != 0)
     896             :             json_object_object_add(tmp_json_obj, "AppId", json_object_new_string_len(filter->apid[num], DLT_ID_SIZE));
     897             :         else
     898             :             json_object_object_add(tmp_json_obj, "AppId", json_object_new_string(filter->apid[num]));
     899             : 
     900             :         if (filter->ctid[num][DLT_ID_SIZE - 1] != 0)
     901             :             json_object_object_add(tmp_json_obj, "ContextId",
     902             :                                    json_object_new_string_len(filter->ctid[num], DLT_ID_SIZE));
     903             :         else
     904             :             json_object_object_add(tmp_json_obj, "ContextId", json_object_new_string(filter->ctid[num]));
     905             : 
     906             :         json_object_object_add(tmp_json_obj, "LogLevel", json_object_new_int(filter->log_level[num]));
     907             :         json_object_object_add(tmp_json_obj, "PayloadMin", json_object_new_int(filter->payload_min[num]));
     908             :         json_object_object_add(tmp_json_obj, "PayloadMax", json_object_new_int(filter->payload_max[num]));
     909             : 
     910             :         json_object_object_add(json_filter_obj, filter_name, tmp_json_obj);
     911             :     }
     912             : 
     913             :     printf("Saving current filter into '%s'\n", filename);
     914             :     json_object_to_file((char*)filename, json_filter_obj);
     915             : 
     916             :     return DLT_RETURN_OK;
     917             : }
     918             : #   endif /* __Linux__ */
     919             : 
     920             : #   ifdef __QNX__
     921             : DltReturnValue dlt_json_filter_save(DltFilter *filter, const char *filename, int verbose)
     922             : {
     923             :     if ((filter == NULL) || (filename == NULL))
     924             :         return DLT_RETURN_WRONG_PARAMETER;
     925             : 
     926             :     if(verbose)
     927             :         pr_verbose("dlt_json_filter_save()\n");
     928             : 
     929             :     char s_app_id[DLT_ID_SIZE + 1];
     930             :     char s_context_id[DLT_ID_SIZE + 1];
     931             : 
     932             :     json_encoder_t *j_encoder = json_encoder_create();
     933             :     json_encoder_start_object(j_encoder, NULL);
     934             : 
     935             :     for (int num = 0; num < filter->counter; num++) {
     936             :         char filter_name[JSON_FILTER_NAME_SIZE];
     937             :         sprintf(filter_name, "filter%i", num);
     938             :         json_encoder_start_object(j_encoder, filter_name);
     939             : 
     940             :         strncpy(s_app_id, filter->apid[num], DLT_ID_SIZE);
     941             : 
     942             :         if (filter->apid[num][DLT_ID_SIZE - 1] != 0)
     943             :             s_app_id[DLT_ID_SIZE] = '\0';
     944             : 
     945             :         strncpy(s_context_id, filter->ctid[num], DLT_ID_SIZE);
     946             : 
     947             :         if (filter->ctid[num][DLT_ID_SIZE - 1] != 0)
     948             :             s_context_id[DLT_ID_SIZE] = '\0';
     949             : 
     950             :         json_encoder_add_string(j_encoder, "AppId", s_app_id);
     951             :         json_encoder_add_string(j_encoder, "ContextId", s_context_id);
     952             :         json_encoder_add_int(j_encoder, "LogLevel", filter->log_level[num]);
     953             :         json_encoder_add_int(j_encoder, "PayloadMin", filter->payload_min[num]);
     954             :         json_encoder_add_int(j_encoder, "PayloadMax", filter->payload_max[num]);
     955             : 
     956             :         json_encoder_end_object(j_encoder);
     957             :     }
     958             : 
     959             :     json_encoder_end_object(j_encoder);
     960             : 
     961             :     printf("Saving current filter into '%s'\n", filename);
     962             :     FILE *handle = fopen(filename, "w");
     963             :     int filter_buffer_size = 100 * (filter->counter);
     964             :     char filter_buffer[filter_buffer_size];
     965             :     snprintf(filter_buffer, filter_buffer_size, json_encoder_buffer(j_encoder));
     966             :     fprintf(handle, filter_buffer);
     967             : 
     968             :     fclose(handle);
     969             :     json_encoder_destroy(j_encoder);
     970             : 
     971             :     return DLT_RETURN_OK;
     972             : }
     973             : #   endif /* __QNX__ */
     974             : #endif /* EXTENDED_FILTERING */

Generated by: LCOV version 1.14