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

Generated by: LCOV version 2.0-1