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

Generated by: LCOV version 2.0-1