LCOV - code coverage report
Current view: top level - console - dlt-control-common.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 68.9 % 209 144
Test Date: 2025-12-23 11:07:30 Functions: 94.7 % 19 18

            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              :                             token[sizeof(token) - 1] = 0;
     216              :                         }
     217              :                         else {
     218              :                             strncpy(value, pch, sizeof(value) - 1);
     219              :                             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 = (int32_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 - (int32_t)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 = (int32_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              :     union {
     436              :         void *ptr;
     437              :         int (*callback)(DltMessage *message, void *data);
     438              :     } callback_converter;
     439              :     int (*callback)(DltMessage *message, void *data);
     440              : 
     441              :     callback_converter.ptr = cb;
     442            2 :     callback = callback_converter.callback;
     443              : 
     444            2 :     if (!cb || !client) {
     445            0 :         pr_error("%s: Invalid parameters\n", __func__);
     446            0 :         return -1;
     447              :     }
     448              : 
     449            2 :     pr_verbose("Initializing the connection.\n");
     450              : 
     451            2 :     if (dlt_client_init(client, get_verbosity()) != 0) {
     452            0 :         pr_error("Failed to register callback (NULL)\n");
     453            0 :         return -1;
     454              :     }
     455              : 
     456            2 :     dlt_client_register_message_callback(callback);
     457              : 
     458            2 :     client->socketPath = NULL;
     459              : 
     460            2 :     if (dlt_parse_config_param("ControlSocketPath", &client->socketPath) != 0) {
     461              :         /* Failed to read from conf, copy default */
     462            0 :         if (dlt_client_set_socket_path(client, DLT_DAEMON_DEFAULT_CTRL_SOCK_PATH) == -1) {
     463            0 :             pr_error("set socket path didn't succeed\n");
     464            0 :             return -1;
     465              :         }
     466              :     }
     467              : 
     468            2 :     client->mode = DLT_CLIENT_MODE_UNIX;
     469              : 
     470            2 :     return dlt_client_connect(client, get_verbosity());
     471              : }
     472              : 
     473              : /** @brief Daemon listener function
     474              :  *
     475              :  * This function will continuously read on the DLT socket, until an error occurs
     476              :  * or the thread executing this function is canceled.
     477              :  *
     478              :  * @param data Thread parameter
     479              :  *
     480              :  * @return The thread parameter given as argument.
     481              :  */
     482            2 : static void *dlt_control_listen_to_daemon(void *data)
     483              : {
     484            2 :     pr_verbose("Ready to receive DLT answers.\n");
     485            2 :     dlt_client_main_loop(&g_client, NULL, get_verbosity());
     486            2 :     return data;
     487              : }
     488              : 
     489              : /** @brief Internal callback for DLT response
     490              :  *
     491              :  * This function is called by the dlt_client_main_loop once a response is read
     492              :  * from the DLT socket.
     493              :  * After some basic checks, the user's response analyzer is called. The return
     494              :  * value of the analyzer is then provided back to the dlt_control_send_message
     495              :  * function to be given back as a return value.
     496              :  * As this function is called in a dedicated thread, the return value is
     497              :  * provided using a global variable.
     498              :  * Access to this variable is controlled through a dedicated mutex.
     499              :  * New values are signaled using a dedicated condition variable.
     500              :  *
     501              :  * @param message The DLT answer
     502              :  * @param data Unused
     503              :  *
     504              :  * @return The analyzer return value or -1 on early errors.
     505              :  */
     506            2 : static int dlt_control_callback(DltMessage *message, void *data)
     507              : {
     508            2 :     char text[DLT_RECEIVE_BUFSIZE] = { 0 };
     509              :     (void)data;
     510              : 
     511            2 :     if (message == NULL) {
     512            0 :         pr_error("Received message is null\n");
     513            0 :         return -1;
     514              :     }
     515              : 
     516              :     /* prepare storage header */
     517            2 :     if (DLT_IS_HTYP_WEID(message->standardheader->htyp))
     518            2 :         dlt_set_storageheader(message->storageheader, message->headerextra.ecu);
     519              :     else
     520            0 :         dlt_set_storageheader(message->storageheader, "LCTL");
     521              : 
     522            2 :     dlt_message_header(message, text, DLT_RECEIVE_BUFSIZE, get_verbosity());
     523              : 
     524              :     /* Extracting payload */
     525            2 :     dlt_message_payload(message, text,
     526              :                         DLT_RECEIVE_BUFSIZE,
     527              :                         DLT_OUTPUT_ASCII,
     528              :                         get_verbosity());
     529              : 
     530              :     /*
     531              :      * Checking payload with the provided callback and return the result
     532              :      */
     533            2 :     pthread_mutex_lock(&answer_lock);
     534            4 :     callback_return = response_analyzer_cb(text,
     535            2 :                                            message->databuffer,
     536            2 :                                            (int) message->datasize);
     537            2 :     pthread_cond_signal(&answer_cond);
     538            2 :     pthread_mutex_unlock(&answer_lock);
     539              : 
     540            2 :     return callback_return;
     541              : }
     542              : 
     543              : /** @brief Send a message to the daemon and wait for the asynchronous answer.
     544              :  *
     545              :  * The answer is received and analyzed by a dedicated thread. Thus we need
     546              :  * to wait for the signal from this thread and then read the return value
     547              :  * to be provided to the user.
     548              :  * In case of timeout, this function fails.
     549              :  * The message provided by the user is formated in DLT format before sending.
     550              :  *
     551              :  * @param body The message provided by the user
     552              :  * @param timeout The time to wait before considering that no answer will come
     553              :  *
     554              :  * @return The user response analyzer return value, -1 in case of early error.
     555              :  */
     556            2 : int dlt_control_send_message(DltControlMsgBody *body, int timeout)
     557              : {
     558              :     struct timespec t;
     559              :     DltMessage *msg = NULL;
     560              : 
     561            2 :     if (!body) {
     562            0 :         pr_error("%s: Invalid input.\n", __func__);
     563            0 :         return -1;
     564              :     }
     565              : 
     566            2 :     if (clock_gettime(CLOCK_REALTIME, &t) == -1) {
     567            0 :         pr_error("Cannot read system time.\n");
     568            0 :         return -1;
     569              :     }
     570              : 
     571            2 :     t.tv_sec += timeout;
     572              : 
     573              :     /* send command to daemon here */
     574            2 :     msg = dlt_control_prepare_message(body);
     575              : 
     576            2 :     if (msg == NULL) {
     577            0 :         pr_error("Control message preparation failed\n");
     578            0 :         return -1;
     579              :     }
     580              : 
     581            2 :     pthread_mutex_lock(&answer_lock);
     582              : 
     583              :     /* Re-init the return value */
     584            2 :     callback_return = -1;
     585              : 
     586            2 :     if (dlt_client_send_message_to_socket(&g_client, msg) != DLT_RETURN_OK)
     587              :     {
     588            0 :         pr_error("Sending message to daemon failed\n");
     589            0 :         dlt_message_free(msg, get_verbosity());
     590            0 :         free(msg);
     591              : 
     592              :         /* make sure the mutex is unlocked to prevent deadlocks */
     593            0 :         pthread_mutex_unlock(&answer_lock);
     594            0 :         return -1;
     595              :     }
     596              : 
     597              :     /*
     598              :     * When a timeouts occurs, pthread_cond_timedwait()
     599              :     * shall nonetheless release and re-acquire the mutex referenced by mutex
     600              :     */
     601            2 :     pthread_cond_timedwait(&answer_cond, &answer_lock, &t);
     602            2 :     pthread_mutex_unlock(&answer_lock);
     603              : 
     604              :     /* Destroying the message */
     605            2 :     dlt_message_free(msg, get_verbosity());
     606            2 :     free(msg);
     607              : 
     608              :     /* At this point either the value is already correct, either it's still -1.
     609              :      * Then, we don't care to lock the access.
     610              :      */
     611            2 :     return callback_return;
     612              : }
     613              : 
     614              : /** @brief Control communication initialization
     615              :  *
     616              :  * This will prepare the DLT connection and the thread dedicated to the
     617              :  * response listening.
     618              :  *
     619              :  * @param response_analyzer User defined function used to analyze the response
     620              :  * @param ecuid The ECUID to provide to the daemon
     621              :  * @param verbosity The verbosity level
     622              :  *
     623              :  * @return 0 on success, -1 otherwise.
     624              :  */
     625            2 : int dlt_control_init(int (*response_analyzer)(char *, void *, int),
     626              :                      char *ecuid,
     627              :                      int verbosity)
     628              : {
     629            2 :     if (!response_analyzer || !ecuid) {
     630            0 :         pr_error("%s: Invalid input.\n", __func__);
     631            0 :         return -1;
     632              :     }
     633              : 
     634              :     union {
     635              :         void *ptr;
     636              :         int (*callback)(DltMessage *message, void *data);
     637              :     } callback_converter;
     638              : 
     639            2 :     response_analyzer_cb = response_analyzer;
     640            2 :     set_ecuid(ecuid);
     641              :     set_verbosity(verbosity);
     642              :     callback_converter.callback = dlt_control_callback;
     643              : 
     644              :     /* Initialize DLT connection */
     645            2 :     if (dlt_control_init_connection(&g_client, callback_converter.ptr) != 0) {
     646            0 :         pr_error("Connection initialization failed\n");
     647            0 :         dlt_client_cleanup(&g_client, get_verbosity());
     648            0 :         return -1;
     649              :     }
     650              : 
     651              :     /* Contact DLT daemon */
     652            2 :     if (pthread_create(&daemon_connect_thread,
     653              :                        NULL,
     654              :                        dlt_control_listen_to_daemon,
     655              :                        NULL) != 0) {
     656            0 :         pr_error("Cannot create thread to communicate with DLT daemon.\n");
     657            0 :         return -1;
     658              :     }
     659              : 
     660              :     return 0;
     661              : }
     662              : 
     663              : /** @brief Control communication clean-up
     664              :  *
     665              :  * Cancels the listener thread and clean=up the dlt client structure.
     666              :  *
     667              :  * @return 0 on success, -1 otherwise.
     668              :  */
     669            2 : int dlt_control_deinit(void)
     670              : {
     671              :     /* At this stage, we want to stop sending/receiving
     672              :      * from dlt-daemon. So in order to avoid cancellation
     673              :      * at recv(), shutdown and close the socket
     674              :      */
     675            2 :     if (g_client.receiver.fd) {
     676            2 :         shutdown(g_client.receiver.fd, SHUT_RDWR);
     677            2 :         close(g_client.receiver.fd);
     678            2 :         g_client.receiver.fd = -1;
     679              :     }
     680              : 
     681            2 :     if (pthread_join(daemon_connect_thread, NULL)) {
     682            0 :         pr_error("Unable to join the thread with ERRNO=%s\n", strerror(errno));
     683              :     }
     684              : 
     685              :     /* Closing the socket */
     686            2 :     return dlt_client_cleanup(&g_client, get_verbosity());
     687              : }
     688              : 
     689              : 
     690              : #ifdef EXTENDED_FILTERING /* EXTENDED_FILTERING */
     691              : #   if defined(__linux__) || defined(__ANDROID_API__)
     692              : DltReturnValue dlt_json_filter_load(DltFilter *filter, const char *filename, int verbose)
     693              : {
     694              :     if ((filter == NULL) || (filename == NULL))
     695              :         return DLT_RETURN_WRONG_PARAMETER;
     696              : 
     697              :     if(verbose)
     698              :         pr_verbose("dlt_json_filter_load()\n");
     699              : 
     700              :     FILE *handle;
     701              :     char buffer[JSON_FILTER_SIZE*DLT_FILTER_MAX];
     702              :     struct json_object *j_parsed_json;
     703              :     struct json_object *j_app_id;
     704              :     struct json_object *j_context_id;
     705              :     struct json_object *j_log_level;
     706              :     struct json_object *j_payload_min;
     707              :     struct json_object *j_payload_max;
     708              :     enum json_tokener_error jerr;
     709              : 
     710              :     char app_id[DLT_ID_SIZE + 1] = "";
     711              :     char context_id[DLT_ID_SIZE + 1] = "";
     712              :     int32_t log_level = 0;
     713              :     int32_t payload_max = INT32_MAX;
     714              :     int32_t payload_min = 0;
     715              : 
     716              :     handle = fopen(filename, "r");
     717              : 
     718              :     if (handle == NULL) {
     719              :         pr_error("Filter file %s cannot be opened!\n", filename);
     720              :         return DLT_RETURN_ERROR;
     721              :     }
     722              : 
     723              :     if (fread(buffer, sizeof(buffer), 1, handle) != 0) {
     724              :         if (!feof(handle)) {
     725              :             pr_error("Filter file %s is to big for reading it with current buffer!\n", filename);
     726              :             return DLT_RETURN_ERROR;
     727              :         }
     728              :     }
     729              : 
     730              :     j_parsed_json = json_tokener_parse_verbose(buffer, &jerr);
     731              : 
     732              :     if (jerr != json_tokener_success) {
     733              :         pr_error("Faild to parse given filter %s: %s\n", filename, json_tokener_error_desc(jerr));
     734              :         return DLT_RETURN_ERROR;
     735              :     }
     736              : 
     737              :     printf("The following filter(s) are applied: \n");
     738              :     pr_verbose("The following filter(s) are applied: \n");
     739              :     int iterator = 0;
     740              :     json_object_object_foreach(j_parsed_json, key, val)
     741              :     {
     742              :         if (iterator >= DLT_FILTER_MAX) {
     743              :             pr_error("Maximum number (%d) of allowed filters reached, ignoring rest of filters!\n",
     744              :                      DLT_FILTER_MAX);
     745              :             break;
     746              :         }
     747              : 
     748              :         printf("%s:\n", key);
     749              :         pr_verbose("%s:\n", key);
     750              : 
     751              :         if (json_object_object_get_ex(val, "AppId", &j_app_id))
     752              :             strncpy(app_id, json_object_get_string(j_app_id), DLT_ID_SIZE);
     753              :         else
     754              :             dlt_set_id(app_id, "");
     755              : 
     756              :         if (json_object_object_get_ex(val, "ContextId", &j_context_id))
     757              :             strncpy(context_id, json_object_get_string(j_context_id), DLT_ID_SIZE);
     758              :         else
     759              :             dlt_set_id(context_id, "");
     760              : 
     761              :         if (json_object_object_get_ex(val, "LogLevel", &j_log_level))
     762              :             log_level = json_object_get_int(j_log_level);
     763              :         else
     764              :             log_level = 0;
     765              : 
     766              :         if (json_object_object_get_ex(val, "PayloadMin", &j_payload_min))
     767              :             payload_min = json_object_get_int(j_payload_min);
     768              :         else
     769              :             payload_min = 0;
     770              : 
     771              :         if (json_object_object_get_ex(val, "PayloadMax", &j_payload_max))
     772              :             payload_max = json_object_get_int(j_payload_max);
     773              :         else
     774              :             payload_max = INT32_MAX;
     775              : 
     776              :         dlt_filter_add(filter, app_id, context_id, log_level, payload_min, payload_max, verbose);
     777              : 
     778              :         printf("\tAppId: %.*s\n", DLT_ID_SIZE, app_id);
     779              :         pr_verbose("\tAppId: %.*s\n", DLT_ID_SIZE, app_id);
     780              :         printf("\tConextId: %.*s\n", DLT_ID_SIZE, context_id);
     781              :         pr_verbose("\tConextId: %.*s\n", DLT_ID_SIZE, context_id);
     782              :         printf("\tLogLevel: %i\n", log_level);
     783              :         pr_verbose("\tLogLevel: %i\n", log_level);
     784              :         printf("\tPayloadMin: %i\n", payload_min);
     785              :         pr_verbose("\tPayloadMin: %i\n", payload_min);
     786              :         printf("\tPayloadMax: %i\n", payload_max);
     787              :         pr_verbose("\tPayloadMax: %i\n", payload_max);
     788              : 
     789              :         iterator++;
     790              :     }
     791              : 
     792              :     fclose(handle);
     793              : 
     794              :     return DLT_RETURN_OK;
     795              : }
     796              : #   endif /* __Linux__ */
     797              : 
     798              : #   ifdef __QNX__
     799              : DltReturnValue dlt_json_filter_load(DltFilter *filter, const char *filename, int verbose)
     800              : {
     801              :     if ((filter == NULL) || (filename == NULL))
     802              :         return DLT_RETURN_WRONG_PARAMETER;
     803              : 
     804              :     if(verbose)
     805              :         pr_verbose("dlt_json_filter_load()\n");
     806              : 
     807              :     json_decoder_t *j_decoder = json_decoder_create();
     808              : 
     809              :     const char *s_app_id;
     810              :     const char *s_context_id;
     811              :     int32_t log_level = 0;
     812              :     int32_t payload_max = INT32_MAX;
     813              :     int32_t payload_min = 0;
     814              : 
     815              :     json_decoder_error_t ret = json_decoder_parse_file(j_decoder, filename);
     816              : 
     817              :     if (ret != JSON_DECODER_OK) {
     818              :         pr_error("Faild to parse given filter %s: json_decoder_error_t is %i\n", filename, ret);
     819              :         return DLT_RETURN_ERROR;
     820              :     }
     821              : 
     822              :     json_decoder_push_object(j_decoder, NULL, true);
     823              : 
     824              :     int iterator = 0;
     825              :     bool end_of_json = false;
     826              : 
     827              :     while (!end_of_json) {
     828              :         if (iterator >= DLT_FILTER_MAX) {
     829              :             pr_error("Maximum number (%d) of allowed filters reached, ignoring rest of filters!\n",
     830              :                      DLT_FILTER_MAX);
     831              :             break;
     832              :         }
     833              : 
     834              :         if (json_decoder_next(j_decoder) == JSON_DECODER_NOT_FOUND)
     835              :             end_of_json = true;
     836              : 
     837              :         json_decoder_previous(j_decoder);
     838              : 
     839              :         printf("%s:\n", json_decoder_name(j_decoder));
     840              :         json_decoder_push_object(j_decoder, NULL, true);
     841              : 
     842              :         if (json_decoder_get_string(j_decoder, "AppId", &s_app_id, true) != JSON_DECODER_OK)
     843              :             s_app_id = "";
     844              : 
     845              :         if (json_decoder_get_string(j_decoder, "ContextId", &s_context_id, true) != JSON_DECODER_OK)
     846              :             s_context_id = "";
     847              : 
     848              :         if (json_decoder_get_int(j_decoder, "LogLevel", &log_level, true) != JSON_DECODER_OK)
     849              :             log_level = 0;
     850              : 
     851              :         if (json_decoder_get_int(j_decoder, "PayloadMin", &payload_min, true) != JSON_DECODER_OK)
     852              :             payload_min = 0;
     853              : 
     854              :         if (json_decoder_get_int(j_decoder, "PayloadMax", &payload_max, true) != JSON_DECODER_OK)
     855              :             payload_max = INT32_MAX;
     856              : 
     857              :         char app_id[DLT_ID_SIZE];
     858              :         char context_id[DLT_ID_SIZE];
     859              : 
     860              :         #pragma GCC diagnostic push
     861              :         #pragma GCC diagnostic ignored "-Wstringop-truncation"
     862              :         strncpy(app_id, s_app_id, DLT_ID_SIZE);
     863              :         strncpy(context_id, s_context_id, DLT_ID_SIZE);
     864              :         #pragma GCC diagnostic pop
     865              : 
     866              :         dlt_filter_add(filter, app_id, context_id, log_level, payload_min, payload_max, verbose);
     867              : 
     868              :         printf("\tAppId: %.*s\n", DLT_ID_SIZE, app_id);
     869              :         printf("\tConextId: %.*s\n", DLT_ID_SIZE, context_id);
     870              :         printf("\tLogLevel: %i\n", log_level);
     871              :         printf("\tPayloadMin: %i\n", payload_min);
     872              :         printf("\tPayloadMax: %i\n", payload_max);
     873              : 
     874              :         json_decoder_pop(j_decoder);
     875              : 
     876              :         iterator++;
     877              :     }
     878              : 
     879              :     json_decoder_destroy(j_decoder);
     880              : 
     881              :     return DLT_RETURN_OK;
     882              : }
     883              : #   endif /* __QNX__ */
     884              : #endif /* EXTENDED_FILTERING */
     885              : 
     886              : #ifdef EXTENDED_FILTERING /* EXTENDED_FILTERING */
     887              : #   if defined(__linux__) || defined(__ANDROID_API__)
     888              : DltReturnValue dlt_json_filter_save(DltFilter *filter, const char *filename, int verbose)
     889              : {
     890              :     if ((filter == NULL) || (filename == NULL))
     891              :         return DLT_RETURN_WRONG_PARAMETER;
     892              : 
     893              :     if(verbose)
     894              :         pr_verbose("dlt_json_filter_save()\n");
     895              : 
     896              :     struct json_object *json_filter_obj = json_object_new_object();
     897              : 
     898              :     for (int num = 0; num < filter->counter; num++) {
     899              :         struct json_object *tmp_json_obj = json_object_new_object();
     900              :         char filter_name[JSON_FILTER_NAME_SIZE];
     901              :         sprintf(filter_name, "filter%i", num);
     902              : 
     903              :         if (filter->apid[num][DLT_ID_SIZE - 1] != 0)
     904              :             json_object_object_add(tmp_json_obj, "AppId", json_object_new_string_len(filter->apid[num], DLT_ID_SIZE));
     905              :         else
     906              :             json_object_object_add(tmp_json_obj, "AppId", json_object_new_string(filter->apid[num]));
     907              : 
     908              :         if (filter->ctid[num][DLT_ID_SIZE - 1] != 0)
     909              :             json_object_object_add(tmp_json_obj, "ContextId",
     910              :                                    json_object_new_string_len(filter->ctid[num], DLT_ID_SIZE));
     911              :         else
     912              :             json_object_object_add(tmp_json_obj, "ContextId", json_object_new_string(filter->ctid[num]));
     913              : 
     914              :         json_object_object_add(tmp_json_obj, "LogLevel", json_object_new_int(filter->log_level[num]));
     915              :         json_object_object_add(tmp_json_obj, "PayloadMin", json_object_new_int(filter->payload_min[num]));
     916              :         json_object_object_add(tmp_json_obj, "PayloadMax", json_object_new_int(filter->payload_max[num]));
     917              : 
     918              :         json_object_object_add(json_filter_obj, filter_name, tmp_json_obj);
     919              :     }
     920              : 
     921              :     printf("Saving current filter into '%s'\n", filename);
     922              :     json_object_to_file((char*)filename, json_filter_obj);
     923              : 
     924              :     return DLT_RETURN_OK;
     925              : }
     926              : #   endif /* __Linux__ */
     927              : 
     928              : #   ifdef __QNX__
     929              : DltReturnValue dlt_json_filter_save(DltFilter *filter, const char *filename, int verbose)
     930              : {
     931              :     if ((filter == NULL) || (filename == NULL))
     932              :         return DLT_RETURN_WRONG_PARAMETER;
     933              : 
     934              :     if(verbose)
     935              :         pr_verbose("dlt_json_filter_save()\n");
     936              : 
     937              :     char s_app_id[DLT_ID_SIZE + 1];
     938              :     char s_context_id[DLT_ID_SIZE + 1];
     939              : 
     940              :     json_encoder_t *j_encoder = json_encoder_create();
     941              :     json_encoder_start_object(j_encoder, NULL);
     942              : 
     943              :     for (int num = 0; num < filter->counter; num++) {
     944              :         char filter_name[JSON_FILTER_NAME_SIZE];
     945              :         sprintf(filter_name, "filter%i", num);
     946              :         json_encoder_start_object(j_encoder, filter_name);
     947              : 
     948              :         strncpy(s_app_id, filter->apid[num], DLT_ID_SIZE);
     949              : 
     950              :         if (filter->apid[num][DLT_ID_SIZE - 1] != 0)
     951              :             s_app_id[DLT_ID_SIZE] = '\0';
     952              : 
     953              :         strncpy(s_context_id, filter->ctid[num], DLT_ID_SIZE);
     954              : 
     955              :         if (filter->ctid[num][DLT_ID_SIZE - 1] != 0)
     956              :             s_context_id[DLT_ID_SIZE] = '\0';
     957              : 
     958              :         json_encoder_add_string(j_encoder, "AppId", s_app_id);
     959              :         json_encoder_add_string(j_encoder, "ContextId", s_context_id);
     960              :         json_encoder_add_int(j_encoder, "LogLevel", filter->log_level[num]);
     961              :         json_encoder_add_int(j_encoder, "PayloadMin", filter->payload_min[num]);
     962              :         json_encoder_add_int(j_encoder, "PayloadMax", filter->payload_max[num]);
     963              : 
     964              :         json_encoder_end_object(j_encoder);
     965              :     }
     966              : 
     967              :     json_encoder_end_object(j_encoder);
     968              : 
     969              :     printf("Saving current filter into '%s'\n", filename);
     970              :     FILE *handle = fopen(filename, "w");
     971              :     int filter_buffer_size = 100 * (filter->counter);
     972              :     char filter_buffer[filter_buffer_size];
     973              :     snprintf(filter_buffer, filter_buffer_size, json_encoder_buffer(j_encoder));
     974              :     fprintf(handle, filter_buffer);
     975              : 
     976              :     fclose(handle);
     977              :     json_encoder_destroy(j_encoder);
     978              : 
     979              :     return DLT_RETURN_OK;
     980              : }
     981              : #   endif /* __QNX__ */
     982              : #endif /* EXTENDED_FILTERING */
        

Generated by: LCOV version 2.0-1