-/*
-* Dlt- Diagnostic Log and Trace user library
-* @licence app begin@
+/**
+ * @licence app begin@
+ * Copyright (C) 2012 BMW AG
+ *
+ * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
+ *
+ * Contributions are licensed to the GENIVI Alliance under one or more
+ * Contribution License Agreements.
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
- * Copyright (C) 2011, BMW AG - Alexander Wenzel <alexander.wenzel@bmw.de>
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU Lesser General Public License, version 2.1, as published by the Free Software Foundation.
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
- * Public License, version 2.1, for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License, version 2.1, along
- * with this program; if not, see <http://www.gnu.org/licenses/lgpl-2.1.html>.
- *
- * Note that the copyright holders assume that the GNU Lesser General Public License, version 2.1, may
- * also be applicable to programs even in cases in which the program is not a library in the technical sense.
- *
- * Linking DLT statically or dynamically with other modules is making a combined work based on DLT. You may
- * license such other modules under the GNU Lesser General Public License, version 2.1. If you do not want to
- * license your linked modules under the GNU Lesser General Public License, version 2.1, you
- * may use the program under the following exception.
- *
- * As a special exception, the copyright holders of DLT give you permission to combine DLT
- * with software programs or libraries that are released under any license unless such a combination is not
- * permitted by the license of such a software program or library. You may copy and distribute such a
- * system following the terms of the GNU Lesser General Public License, version 2.1, including this
- * special exception, for DLT and the licenses of the other code concerned.
- *
- * Note that people who make modified versions of DLT are not obligated to grant this special exception
- * for their modified versions; it is their choice whether to do so. The GNU Lesser General Public License,
- * version 2.1, gives permission to release a modified version without this exception; this exception
- * also makes it possible to release a modified version which carries forward this exception.
*
+ * \author Alexander Wenzel <alexander.aw.wenzel@bmw.de> BMW 2011-2012
+ *
+ * \file dlt_user.c
+ * For further information see http://www.genivi.org/.
* @licence end@
-*/
+ */
/*******************************************************************************
Initials Date Comment
aw 13.01.2010 initial
*/
-
#include <stdlib.h> /* for getenv(), free(), atexit() */
#include <string.h> /* for strcmp(), strncmp(), strlen(), memset(), memcpy() */
#include <signal.h> /* for signal(), SIGPIPE, SIG_IGN */
#include <pthread.h> /* POSIX Threads */
#endif
+#include <sys/time.h>
+#include <math.h>
+
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/uio.h> /* writev() */
+#include <limits.h>
+
#include "dlt_user.h"
#include "dlt_user_shared.h"
#include "dlt_user_shared_cfg.h"
static pthread_t dlt_receiverthread_handle;
static pthread_attr_t dlt_receiverthread_attr;
+/* Segmented Network Trace */
+#define DLT_MAX_TRACE_SEGMENT_SIZE 1024
+#define DLT_MESSAGE_QUEUE_NAME "/dlt_message_queue"
+#define DLT_DELAYED_RESEND_INDICATOR_PATTERN 0xFFFF
+
+/* Mutex to wait on while message queue is not initialized */
+pthread_mutex_t mq_mutex;
+pthread_cond_t mq_init_condition;
+
+/* Structure to pass data to segmented thread */
+typedef struct {
+ DltContext *handle;
+ uint16_t id;
+ DltNetworkTraceType nw_trace_type;
+ uint16_t header_len;
+ void *header;
+ uint16_t payload_len;
+ void *payload;
+} s_segmented_data;
+
/* Function prototypes for internally used functions */
static void dlt_user_receiverthread_function(void *ptr);
static void dlt_user_atexit_handler(void);
static int dlt_user_log_init(DltContext *handle, DltContextData *log);
-static int dlt_user_log_send_log(DltContextData *log, int mtype);
+static DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype);
static int dlt_user_log_send_register_application(void);
static int dlt_user_log_send_unregister_application(void);
static int dlt_user_log_send_register_context(DltContextData *log);
static int dlt_user_log_send_log_mode(DltUserLogMode mode);
static int dlt_user_print_msg(DltMessage *msg, DltContextData *log);
static int dlt_user_log_check_user_message(void);
-static int dlt_user_log_resend_buffer(void);
static void dlt_user_log_reattach_to_daemon(void);
static int dlt_user_log_send_overflow(void);
+static void dlt_user_trace_network_segmented_thread(void *unused);
+static void dlt_user_trace_network_segmented_thread_segmenter(s_segmented_data *data);
+static int dlt_user_queue_resend(void);
int dlt_user_check_library_version(const char *user_major_version,const char *user_minor_version){
dlt_user.dlt_is_file = 0;
dlt_user.overflow = 0;
+ dlt_user.overflow_counter = 0;
#ifdef DLT_SHM_ENABLE
memset(&(dlt_user.dlt_shm),0,sizeof(DltShm));
#endif
/* Try to delete existing pipe, ignore result of unlink */
unlink(filename);
- ret=mkfifo(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH );
+ ret=mkfifo(filename, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP );
if (ret==-1)
{
sprintf(str,"Loging disabled, FIFO user %s cannot be created!\n",filename);
/* return 0; */ /* removed to prevent error, when FIFO already exists */
}
- dlt_user.dlt_user_handle = open(filename, O_RDWR);
- if (dlt_user.dlt_user_handle == -1)
+ // S_IWGRP cannot be set by mkfifo (???), let's reassign right bits
+ ret=chmod(filename, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP );
+ if (ret==-1)
+ {
+ sprintf(str,"FIFO user %s cannot be chmoded!\n", DLT_USER_DIR);
+ dlt_log(LOG_ERR, str);
+ return -1;
+ }
+
+ dlt_user.dlt_user_handle = open(filename, O_RDWR | O_CLOEXEC);
+ if (dlt_user.dlt_user_handle == DLT_FD_INIT)
{
sprintf(str,"Loging disabled, FIFO user %s cannot be opened!\n",filename);
dlt_log(LOG_WARNING, str);
}
/* open DLT output FIFO */
- dlt_user.dlt_log_handle = open(DLT_USER_FIFO, O_WRONLY | O_NONBLOCK);
+ dlt_user.dlt_log_handle = open(DLT_USER_FIFO, O_WRONLY | O_NONBLOCK | O_CLOEXEC );
if (dlt_user.dlt_log_handle==-1)
{
sprintf(str,"Loging disabled, FIFO %s cannot be opened with open()!\n",DLT_USER_FIFO);
dlt_log(LOG_WARNING, "Can't destroy thread attributes!\n");
}
- return 0;
+ /* These will be lazy initialized only when needed */
+ dlt_user.dlt_segmented_queue_read_handle = -1;
+ dlt_user.dlt_segmented_queue_write_handle = -1;
+
+ /* Wait mutext for segmented thread */
+ pthread_mutex_init(&mq_mutex, NULL);
+ pthread_cond_init(&mq_init_condition, NULL);
+
+ /* Start the segmented thread */
+ if(pthread_create(&(dlt_user.dlt_segmented_nwt_handle), NULL,
+ (void *)dlt_user_trace_network_segmented_thread, NULL))
+ {
+ dlt_log(LOG_CRIT, "Can't start segmented thread!\n");
+ return -1;
+ }
+
+ return 0;
}
int dlt_init_file(const char *name)
return 0;
}
+int dlt_init_message_queue(void)
+{
+ pthread_mutex_lock(&mq_mutex);
+ if(dlt_user.dlt_segmented_queue_read_handle >= 0 &&
+ dlt_user.dlt_segmented_queue_write_handle >= 0)
+ {
+ // Already intialized
+ pthread_mutex_unlock(&mq_mutex);
+ return 0;
+ }
+
+ /* Generate per process name for queue */
+ char queue_name[NAME_MAX];
+ sprintf(queue_name, "%s.%d", DLT_MESSAGE_QUEUE_NAME, getpid());
+
+ /* Maximum queue size is 10, limit to size of pointers */
+ struct mq_attr mqatr;
+ mqatr.mq_flags = 0;
+ mqatr.mq_maxmsg = 10;
+ mqatr.mq_msgsize = sizeof(s_segmented_data *);
+ mqatr.mq_curmsgs = 0;
+
+ /**
+ * Create the message queue. It must be newly created
+ * if old one was left by a crashing process.
+ * */
+ dlt_user.dlt_segmented_queue_read_handle = mq_open(queue_name, O_CREAT| O_RDONLY | O_EXCL,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, &mqatr);
+ if(dlt_user.dlt_segmented_queue_read_handle < 0)
+ {
+ if(errno == EEXIST)
+ {
+ dlt_log(LOG_WARNING, "Old message queue exists, trying to delete.\n");
+ if(mq_unlink(queue_name) < 0)
+ {
+ char str[256];
+ snprintf(str,255,"Could not delete existing message queue!: %s \n",strerror(errno));
+ dlt_log(LOG_CRIT, str);
+ }
+ else // Retry
+ {
+ dlt_user.dlt_segmented_queue_read_handle = mq_open(queue_name, O_CREAT| O_RDONLY | O_EXCL,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, &mqatr);
+ }
+ }
+ if(dlt_user.dlt_segmented_queue_read_handle < 0)
+ {
+ char str[256];
+ snprintf(str,255,"Can't create message queue read handle!: %s \n",strerror(errno));
+ dlt_log(LOG_CRIT, str);
+ pthread_mutex_unlock(&mq_mutex);
+ return -1;
+ }
+ }
+
+ dlt_user.dlt_segmented_queue_write_handle = mq_open(queue_name, O_WRONLY|O_NONBLOCK);
+ if(dlt_user.dlt_segmented_queue_write_handle < 0)
+ {
+
+ char str[256];
+ snprintf(str,255,"Can't open message queue write handle!: %s \n",strerror(errno));
+ dlt_log(LOG_CRIT, str);
+ pthread_mutex_unlock(&mq_mutex);
+ return -1;
+ }
+
+ pthread_cond_signal(&mq_init_condition);
+ pthread_mutex_unlock(&mq_mutex);
+ return 0;
+}
+
int dlt_init_common(void)
{
char *env_local_print;
dlt_user.log_state = -1;
dlt_user.dlt_log_handle=-1;
- dlt_user.dlt_user_handle=-1;
+ dlt_user.dlt_user_handle=DLT_FD_INIT;
dlt_set_id(dlt_user.ecuID,DLT_USER_DEFAULT_ECU_ID);
dlt_set_id(dlt_user.appID,"");
}
/* Initialize LogLevel/TraceStatus field */
+ DLT_SEM_LOCK();
dlt_user.dlt_ll_ts = 0;
dlt_user.dlt_ll_ts_max_num_entries = 0;
dlt_user.dlt_ll_ts_num_entries = 0;
if (dlt_buffer_init_dynamic(&(dlt_user.startup_buffer), DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)==-1)
{
dlt_user_initialised = 0;
+ DLT_SEM_FREE();
return -1;
}
+ DLT_SEM_FREE();
signal(SIGPIPE,SIG_IGN); /* ignore pipe signals */
atexit(dlt_user_atexit_handler);
+#ifdef DLT_TEST_ENABLE
+ dlt_user.corrupt_user_header = 0;
+ dlt_user.corrupt_message_size = 0;
+ dlt_user.corrupt_message_size_size = 0;
+#endif
+
return 0;
}
void dlt_user_atexit_handler(void)
{
+ if (dlt_user_initialised==0)
+ {
+ return;
+ }
/* Try to resend potential log messages in the user buffer */
int count = dlt_user_atexit_blow_out_user_buffer();
pthread_cancel(dlt_receiverthread_handle);
}
- if (dlt_user.dlt_user_handle!=-1)
+ if (dlt_user.dlt_user_handle!=DLT_FD_INIT)
{
- sprintf(filename,"/tmp/dlt%d",getpid());
+ sprintf(filename,"%s/dlt%d",DLT_USER_DIR,getpid());
close(dlt_user.dlt_user_handle);
- dlt_user.dlt_user_handle=-1;
+ dlt_user.dlt_user_handle=DLT_FD_INIT;
unlink(filename);
}
/* Ignore return value */
dlt_buffer_free_dynamic(&(dlt_user.startup_buffer));
+ DLT_SEM_LOCK();
if (dlt_user.dlt_ll_ts)
{
for (i=0;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
dlt_user.dlt_ll_ts_max_num_entries = 0;
dlt_user.dlt_ll_ts_num_entries = 0;
}
+ DLT_SEM_FREE();
+
+ if (dlt_user.dlt_segmented_nwt_handle)
+ {
+ pthread_cancel(dlt_user.dlt_segmented_nwt_handle);
+ }
+
+ char queue_name[NAME_MAX];
+ sprintf(queue_name, "%s.%d", DLT_MESSAGE_QUEUE_NAME, getpid());
+
+ /**
+ * Ignore errors from these, to not to spam user if dlt_free
+ * is accidentally called multiple times.
+ */
+ mq_close(dlt_user.dlt_segmented_queue_write_handle);
+ mq_close(dlt_user.dlt_segmented_queue_read_handle);
+ mq_unlink(queue_name);
dlt_user_initialised = 0;
return -1;
}
+ /* check if application already registered */
+ /* if yes do not register again */
+ if(appid[1]==0)
+ {
+ if(appid[0]==dlt_user.appID[0])
+ return 0;
+ }
+ else if(appid[2]==0)
+ {
+ if(appid[0]==dlt_user.appID[0] &&
+ appid[1]==dlt_user.appID[1])
+ return 0;
+ }
+ else if(appid[3]==0)
+ {
+ if(appid[0]==dlt_user.appID[0] &&
+ appid[1]==dlt_user.appID[1] &&
+ appid[2]==dlt_user.appID[2])
+ return 0;
+ }
+ else
+ {
+ if(appid[0]==dlt_user.appID[0] &&
+ appid[1]==dlt_user.appID[1] &&
+ appid[2]==dlt_user.appID[2] &&
+ appid[3]==dlt_user.appID[3])
+ return 0;
+ }
+
DLT_SEM_LOCK();
/* Store locally application id and application description */
if (description!=0)
{
- dlt_user.application_description= malloc(strlen(description)+1);
- strncpy(dlt_user.application_description, description, strlen(description));
+ size_t desc_len = strlen(description);
+ dlt_user.application_description= malloc(desc_len+1);
+ if (dlt_user.application_description){
+ strncpy(dlt_user.application_description, description, desc_len);
- /* Terminate transmitted string with 0 */
- dlt_user.application_description[strlen(description)]='\0';
+ /* Terminate transmitted string with 0 */
+ dlt_user.application_description[desc_len]='\0';
+ }
+ else
+ {
+ DLT_SEM_FREE();
+ return -1;
+ }
}
DLT_SEM_FREE();
return -1;
}
+ /* Reset message counter */
+ handle->mcnt = 0;
+
/* Store context id in log level/trace status field */
/* Check if already registered, else register context */
dlt_user.dlt_ll_ts[i].log_level = DLT_USER_INITIAL_LOG_LEVEL;
dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
+ dlt_user.dlt_ll_ts[i].log_level_ptr = 0;
+ dlt_user.dlt_ll_ts[i].trace_status_ptr = 0;
+
dlt_user.dlt_ll_ts[i].context_description = 0;
dlt_user.dlt_ll_ts[i].injection_table = 0;
if ((dlt_user.dlt_ll_ts_num_entries%DLT_USER_CONTEXT_ALLOC_SIZE)==0)
{
/* allocate memory in steps of DLT_USER_CONTEXT_ALLOC_SIZE, e.g. 500 */
- dlt_ll_ts_type *old;
- old = dlt_user.dlt_ll_ts;
+ dlt_ll_ts_type *old_ll_ts;
+ uint32_t old_max_entries;
+
+ old_ll_ts = dlt_user.dlt_ll_ts;
+ old_max_entries = dlt_user.dlt_ll_ts_max_num_entries;
+
dlt_user.dlt_ll_ts_max_num_entries = ((dlt_user.dlt_ll_ts_num_entries/DLT_USER_CONTEXT_ALLOC_SIZE)+1)*DLT_USER_CONTEXT_ALLOC_SIZE;
dlt_user.dlt_ll_ts = (dlt_ll_ts_type*) malloc(sizeof(dlt_ll_ts_type)*
dlt_user.dlt_ll_ts_max_num_entries);
if (dlt_user.dlt_ll_ts==0)
{
+ dlt_user.dlt_ll_ts = old_ll_ts;
+ dlt_user.dlt_ll_ts_max_num_entries = old_max_entries;
DLT_SEM_FREE();
return -1;
}
- memcpy(dlt_user.dlt_ll_ts,old,sizeof(dlt_ll_ts_type)*dlt_user.dlt_ll_ts_num_entries);
- free(old);
+ memcpy(dlt_user.dlt_ll_ts,old_ll_ts,sizeof(dlt_ll_ts_type)*dlt_user.dlt_ll_ts_num_entries);
+ free(old_ll_ts);
/* Initialize new entries */
for (i=dlt_user.dlt_ll_ts_num_entries;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
dlt_user.dlt_ll_ts[i].log_level = DLT_USER_INITIAL_LOG_LEVEL;
dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
+ dlt_user.dlt_ll_ts[i].log_level_ptr = 0;
+ dlt_user.dlt_ll_ts[i].trace_status_ptr = 0;
+
dlt_user.dlt_ll_ts[i].context_description = 0;
dlt_user.dlt_ll_ts[i].injection_table = 0;
if (description!=0)
{
- dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description = malloc(strlen(description)+1);
- strncpy(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description, description, strlen(description));
+ size_t desc_len = strlen(description);
+ dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description = malloc(desc_len+1);
+ if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description == 0)
+ {
+ DLT_SEM_FREE();
+ return -1;
+ }
+
+ strncpy(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description, description, desc_len);
/* Terminate transmitted string with 0 */
- dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description[strlen(description)]='\0';
+ dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description[desc_len]='\0';
+ }
+
+ if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr == 0)
+ {
+ dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr = malloc(sizeof(int8_t));
+ if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr == 0)
+ {
+ DLT_SEM_FREE();
+ return -1;
+ }
+ }
+ if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr == 0)
+ {
+ dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr = malloc(sizeof(int8_t));
+ if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr == 0)
+ {
+ DLT_SEM_FREE();
+ return -1;
+ }
}
if (loglevel!=DLT_USER_LOG_LEVEL_NOT_SET)
dlt_set_id(handle->contextID, contextid);
handle->log_level_pos = dlt_user.dlt_ll_ts_num_entries;
+ handle->log_level_ptr = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr;
+ handle->trace_status_ptr = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr;
+
log.context_description = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description;
+ *(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr) = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level;
+ *(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr) = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status = tracestatus;
+
if (loglevel!=DLT_USER_LOG_LEVEL_NOT_SET)
{
log.log_level = loglevel;
DLT_SEM_LOCK();
+ handle->log_level_ptr = 0;
+ handle->trace_status_ptr = 0;
+
if (dlt_user.dlt_ll_ts)
{
/* Clear and free local stored context information */
free(dlt_user.dlt_ll_ts[handle->log_level_pos].context_description);
}
+ if (dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr!=0)
+ {
+ free(dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr);
+ dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr = 0;
+ }
+
+ if (dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr!=0)
+ {
+ free(dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr);
+ dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr = 0;
+ }
+
dlt_user.dlt_ll_ts[handle->log_level_pos].context_description = 0;
if (dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table)
{
dlt_user.dlt_ll_ts[i].log_level = loglevel;
dlt_user.dlt_ll_ts[i].trace_status = tracestatus;
+ if(dlt_user.dlt_ll_ts[i].log_level_ptr)
+ *(dlt_user.dlt_ll_ts[i].log_level_ptr) = loglevel;
+ if(dlt_user.dlt_ll_ts[i].trace_status_ptr)
+ *(dlt_user.dlt_ll_ts[i].trace_status_ptr) = tracestatus;
}
DLT_SEM_FREE();
/* Reattach to daemon if neccesary */
dlt_user_log_reattach_to_daemon();
- if (dlt_user.overflow)
+ if (dlt_user.overflow_counter)
{
if (dlt_user_log_send_overflow()==0)
{
- dlt_user.overflow=0;
- }
+ sprintf(str,"Buffer full! %u messages discarded!\n",dlt_user.overflow_counter);
+ dlt_log(LOG_ERR, str);
+ dlt_user.overflow_counter=0; }
}
/* log to FIFO */
(unsigned char *)&(userheader), sizeof(DltUserHeader),
msgdata, size, 0, 0)==-1)
{
- dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
+ if(dlt_user.overflow_counter==0)
+ {
+ dlt_log(LOG_ERR,"Buffer full! First message discarded!\n");
+ }
+ ret = DLT_RETURN_BUFFER_FULL;
}
DLT_SEM_FREE();
+
+ if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
+ {
+ ;//dlt_log(LOG_WARNING, "dlt_forward_msg: Failed to queue resending.\n");
+ }
}
switch (ret)
{
+ case DLT_RETURN_BUFFER_FULL:
+ {
+ /* Buffer full */
+ dlt_user.overflow_counter += 1;
+ return -1;
+ }
case DLT_RETURN_PIPE_FULL:
{
/* data could not be written */
- dlt_user.overflow = 1;
return -1;
}
case DLT_RETURN_PIPE_ERROR:
/* ********************************************************************************************* */
-int dlt_user_log_write_start(DltContext *handle, DltContextData *log,DltLogLevelType loglevel)
+inline int dlt_user_log_write_start(DltContext *handle, DltContextData *log,DltLogLevelType loglevel)
{
return dlt_user_log_write_start_id(handle,log,loglevel,DLT_USER_DEFAULT_MSGID);
}
int dlt_user_log_write_start_id(DltContext *handle, DltContextData *log,DltLogLevelType loglevel, uint32_t messageid)
{
- uint32_t mid;
-
- if (dlt_user_initialised==0)
- {
- if (dlt_init()<0)
- {
- return -1;
- }
- }
-
- if (dlt_user_log_init(handle, log)==-1)
- {
- return -1;
- }
-
+ if(dlt_user_initialised==0)
+ {
+ if (dlt_init()<0)
+ {
+ return -1;
+ }
+ }
if (log==0)
{
return -1;
}
- /* Removed because of DltLogLevelType
-
- if ((loglevel<DLT_LOG_DEFAULT) || (loglevel>DLT_LOG_VERBOSE))
+ if (dlt_user_log_init(handle, log)==-1)
{
- return -1;
+ return -1;
}
- */
-
- mid = messageid;
-
- log->args_num = 0;
- log->log_level = loglevel;
- log->size = 0;
-
if (dlt_user.dlt_ll_ts==0)
{
return -1;
}
- DLT_SEM_LOCK();
-
- if ((log->log_level<=(int)(dlt_user.dlt_ll_ts[handle->log_level_pos].log_level) ) && (log->log_level!=0))
+ if (handle->log_level_ptr && (loglevel<=(int)*(handle->log_level_ptr) ) && (loglevel!=0))
{
- DLT_SEM_FREE();
+ log->args_num = 0;
+ log->log_level = loglevel;
/* In non-verbose mode, insert message id */
if (dlt_user.verbose_mode==0)
return -1;
}
/* Write message id */
- memcpy(log->buffer,&(mid),sizeof(uint32_t));
+ memcpy(log->buffer,&(messageid),sizeof(uint32_t));
log->size = sizeof(uint32_t);
/* as the message id is part of each message in non-verbose mode,
it doesn't increment the argument counter in extended header (if used) */
}
+ else log->size=0;
return 1;
}
- else
- {
- DLT_SEM_FREE();
- return 0;
- }
return -1;
}
return -1;
}
- return dlt_user_log_send_log(log, DLT_TYPE_LOG);
+ return dlt_user_log_send_log(log, DLT_TYPE_LOG) < 0 ? -1 : 0;
}
int dlt_user_log_write_raw(DltContextData *log,void *data,uint16_t length)
return -1;
}
- type_info = DLT_TYPE_INFO_STRG;
+ type_info = DLT_TYPE_INFO_STRG | DLT_SCOD_ASCII;
+
+ memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
+ log->size += sizeof(uint32_t);
+ }
+
+ arg_size = strlen(text) + 1;
+
+ memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
+ log->size += sizeof(uint16_t);
+
+ memcpy((log->buffer)+log->size,text,arg_size);
+ log->size += arg_size;
+
+ log->args_num ++;
+
+ return 0;
+}
+
+int dlt_user_log_write_utf8_string(DltContextData *log, const char *text)
+{
+ uint16_t arg_size;
+ uint32_t type_info;
+
+ if ((log==0) || (text==0))
+ {
+ return -1;
+ }
+
+ arg_size = strlen(text)+1;
+
+ if ((log->size+arg_size+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
+ {
+ return -1;
+ }
+
+ if (dlt_user.verbose_mode)
+ {
+ if ((log->size+arg_size+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
+ {
+ return -1;
+ }
+
+ type_info = DLT_TYPE_INFO_STRG | DLT_SCOD_UTF8;
memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
log->size += sizeof(uint32_t);
if (dlt_user.dlt_ll_ts[i].injection_table == 0)
{
dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback*) malloc(sizeof(DltUserInjectionCallback));
+ if(dlt_user.dlt_ll_ts[i].injection_table == 0)
+ {
+ DLT_SEM_FREE();
+ return -1;
+ }
}
else
{
old = dlt_user.dlt_ll_ts[i].injection_table;
dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback*) malloc(sizeof(DltUserInjectionCallback)*(j+1));
+ if(dlt_user.dlt_ll_ts[i].injection_table == 0)
+ {
+ dlt_user.dlt_ll_ts[i].injection_table = old;
+ DLT_SEM_FREE();
+ return -1;
+ }
memcpy(dlt_user.dlt_ll_ts[i].injection_table,old,sizeof(DltUserInjectionCallback)*j);
free(old);
}
return 0;
}
-int dlt_user_trace_network(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
-{
- DltContextData log;
+/**
+ * NW Trace related
+ */
- if (dlt_user_initialised==0)
- {
- if (dlt_init()<0)
- {
- return -1;
- }
- }
- if (dlt_user_log_init(handle, &log)==-1)
- {
+int check_buffer()
+{
+ int total_size, used_size;
+ dlt_user_check_buffer(&total_size, &used_size);
+
+ if((total_size - used_size) < (total_size/2))
+ {
return -1;
- }
+ }
+ return 1;
+}
- if (handle==0)
- {
- return -1;
- }
+/**
+ * Send the start of a segment chain.
+ * Returns -1 on failure
+ */
+int dlt_user_trace_network_segmented_start(uint16_t *id, DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len)
+{
- /* Commented out because of DltNetworkTraceType:
+ DltContextData log;
+ struct timeval tv;
- if ((nw_trace_type<=0) || (nw_trace_type>0x15))
+ if (handle==NULL)
{
return -1;
}
- */
+ if (dlt_user_log_init(handle, &log)==-1)
+ {
+ return -1;
+ }
- DLT_SEM_LOCK();
if (dlt_user.dlt_ll_ts==0)
{
- DLT_SEM_FREE();
return -1;
}
- if (dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status==DLT_TRACE_STATUS_ON)
+ if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
{
- DLT_SEM_FREE();
log.args_num = 0;
log.trace_status = nw_trace_type;
log.size = 0;
- if (header==0)
+ gettimeofday(&tv, NULL);
+ *id = tv.tv_usec;
+
+ /* Write identifier */
+ if(dlt_user_log_write_string(&log, "NWST") < 0)
{
- header_len=0;
+ return -1;
}
- /* Write header and its length */
- if (dlt_user_log_write_raw(&log, header, header_len)==-1)
+ /* Write stream handle */
+ if(dlt_user_log_write_uint16(&log, *id) < 0)
{
return -1;
}
- if (payload==0)
+ /* Write header */
+ if(dlt_user_log_write_raw(&log, header, header_len) < 0)
{
- payload_len=0;
+ return -1;
}
- /* Write payload and its length */
- if (dlt_user_log_write_raw(&log, payload, payload_len)==-1)
+ /* Write size of payload */
+ if(dlt_user_log_write_uint16(&log, payload_len) < 0)
{
- return -1;
+ return -1;
+ }
+
+ /* Write expected segment count */
+ uint16_t segment_count = payload_len/DLT_MAX_TRACE_SEGMENT_SIZE+1;
+
+ /* If segments align perfectly with segment size, avoid sending empty segment */
+ if((payload_len % DLT_MAX_TRACE_SEGMENT_SIZE) == 0)
+ {
+ segment_count--;
+ }
+
+ if(dlt_user_log_write_uint16(&log, segment_count) < 0)
+ {
+ return -1;
+ }
+
+ /* Write length of one segment */
+ if(dlt_user_log_write_uint16(&log, DLT_MAX_TRACE_SEGMENT_SIZE) < 0)
+ {
+ return -1;
}
/* Send log */
return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
}
- else
- {
- DLT_SEM_FREE();
- }
-
return 0;
}
-int dlt_log_string(DltContext *handle,DltLogLevelType loglevel, const char *text)
+int dlt_user_trace_network_segmented_segment(uint16_t id, DltContext *handle, DltNetworkTraceType nw_trace_type, int sequence, uint16_t payload_len, void *payload)
{
- DltContextData log;
+ while(check_buffer() < 0)
+ {
+ usleep(1000*50); // Wait 50ms
+ dlt_user_log_resend_buffer();
+ }
- if (dlt_user.verbose_mode==0)
+ if (handle==NULL)
{
return -1;
}
- if ((handle==0) || (text==0))
+ DltContextData log;
+
+ if (dlt_user_log_init(handle, &log)==-1)
+ {
+ return -1;
+ }
+
+ if (dlt_user.dlt_ll_ts==0)
{
return -1;
}
- if (dlt_user_log_write_start(handle,&log,loglevel))
+ if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
{
- if (dlt_user_log_write_string(&log,text)==-1)
+
+ log.args_num = 0;
+ log.trace_status = nw_trace_type;
+ log.size = 0;
+
+ /* Write identifier */
+ if(dlt_user_log_write_string(&log, "NWCH") < 0)
{
- return -1;
+ return -1;
+ }
+
+ /* Write stream handle */
+ if(dlt_user_log_write_uint16(&log, id) < 0)
+ {
+ return -1;
+ }
+
+ /* Write segment sequence number */
+ if(dlt_user_log_write_uint16(&log, sequence) < 0)
+ {
+ return -1;
+ }
+
+ /* Write data */
+ if(dlt_user_log_write_raw(&log, payload, payload_len) < 0)
+ {
+ return -1;
+ }
+
+ /* Send log */
+ return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
+ }
+
+ /* Allow other threads to log between chunks */
+ pthread_yield();
+ return 0;
+}
+
+int dlt_user_trace_network_segmented_end(uint16_t id, DltContext *handle, DltNetworkTraceType nw_trace_type)
+{
+ DltContextData log;
+
+ if (handle==0)
+ {
+ return -1;
+ }
+
+ if (dlt_user_log_init(handle, &log)==-1)
+ {
+ return -1;
+ }
+
+
+
+ if (dlt_user.dlt_ll_ts==0)
+ {
+ return -1;
+ }
+
+ if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
+ {
+
+ log.args_num = 0;
+ log.trace_status = nw_trace_type;
+ log.size = 0;
+
+ /* Write identifier */
+ if(dlt_user_log_write_string(&log, "NWEN") < 0)
+ {
+ return -1;
+ }
+
+ /* Write stream handle */
+ if(dlt_user_log_write_uint(&log, id) < 0)
+ {
+ return -1;
+ }
+
+ /* Send log */
+ return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
+ }
+ return 0;
+}
+
+
+void dlt_user_trace_network_segmented_thread(void *unused)
+{
+ /* Unused on purpose. */
+ (void) unused;
+
+ s_segmented_data *data;
+
+ while(1)
+ {
+ // Wait until message queue is initialized
+ pthread_mutex_lock(&mq_mutex);
+ if(dlt_user.dlt_segmented_queue_read_handle < 0)
+ {
+ pthread_cond_wait(&mq_init_condition, &mq_mutex);
+ }
+ pthread_mutex_unlock(&mq_mutex);
+
+ ssize_t read = mq_receive(dlt_user.dlt_segmented_queue_read_handle, (char *)&data,
+ sizeof(s_segmented_data * ), NULL);
+
+ if(read != sizeof(s_segmented_data *))
+ {
+
+ char str[255];
+ snprintf(str,254,"NWTSegmented: Error while reading queue: %s \n",strerror(errno));
+ dlt_log(LOG_CRIT, str);
+ continue;
+ }
+
+ /* Indicator just to try to flush the buffer */
+ if(data->payload_len == DLT_DELAYED_RESEND_INDICATOR_PATTERN)
+ {
+ // Sleep 100ms, to allow other process to read FIFO
+ usleep(100*1000);
+ if(dlt_user_log_resend_buffer() < 0)
+ {
+ // Requeue if still not empty
+ if ( dlt_user_queue_resend() < 0 )
+ {
+ //dlt_log(LOG_WARNING, "Failed to queue resending in dlt_user_trace_network_segmented_thread.\n");
+ }
+ }
+ free(data);
+ continue;
+ }
+
+ dlt_user_trace_network_segmented_thread_segmenter(data);
+
+ /* Send the end message */
+ DltReturnValue err = dlt_user_trace_network_segmented_end(data->id, data->handle, data->nw_trace_type);
+ if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
+ {
+ dlt_log(LOG_ERR,"NWTSegmented: Could not send end segment.\n");
+ }
+
+ /* Free resources */
+ free(data->header);
+ free(data->payload);
+ free(data);
+ }
+}
+
+void dlt_user_trace_network_segmented_thread_segmenter(s_segmented_data *data)
+{
+ /* Segment the data and send the chunks */
+ void *ptr = NULL;
+ uint16_t offset = 0;
+ uint16_t sequence = 0;
+ do
+ {
+ uint16_t len = 0;
+ if(offset + DLT_MAX_TRACE_SEGMENT_SIZE > data->payload_len)
+ {
+ len = data->payload_len - offset;
+ }
+ else
+ {
+ len = DLT_MAX_TRACE_SEGMENT_SIZE;
+ }
+ /* If payload size aligns perfectly with segment size, avoid sending empty segment */
+ if(len == 0)
+ {
+ break;
+ }
+
+ ptr = data->payload + offset;
+ DltReturnValue err = dlt_user_trace_network_segmented_segment(data->id, data->handle, data->nw_trace_type, sequence++, len, ptr);
+ if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
+ {
+ dlt_log(LOG_ERR,"NWTSegmented: Could not send segment. Aborting.\n");
+ break; // loop
+ }
+ offset += len;
+ }while(ptr < data->payload + data->payload_len);
+}
+
+
+int dlt_user_trace_network_segmented(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
+{
+ /* Send as normal trace if possible */
+ if(header_len+payload_len+sizeof(uint16_t) < DLT_USER_BUF_MAX_SIZE) {
+ return dlt_user_trace_network(handle, nw_trace_type, header_len, header, payload_len, payload);
+ }
+
+ /* Allocate Memory */
+ s_segmented_data *thread_data = malloc(sizeof(s_segmented_data));
+ if(thread_data == NULL)
+ {
+ return -1;
+ }
+ thread_data->header = malloc(header_len);
+ if(thread_data->header == NULL)
+ {
+ free(thread_data);
+ return -1;
+ }
+ thread_data->payload = malloc(payload_len);
+ if(thread_data->payload == NULL)
+ {
+ free(thread_data->header);
+ free(thread_data);
+ return -1;
+ }
+
+ /* Copy data */
+ thread_data->handle = handle;
+ thread_data->nw_trace_type = nw_trace_type;
+ thread_data->header_len = header_len;
+ memcpy(thread_data->header, header, header_len);
+ thread_data->payload_len = payload_len;
+ memcpy(thread_data->payload, payload, payload_len);
+
+ /* Send start message */
+ DltReturnValue err = dlt_user_trace_network_segmented_start(&(thread_data->id),
+ thread_data->handle, thread_data->nw_trace_type,
+ thread_data->header_len, thread_data->header,
+ thread_data->payload_len);
+ if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
+ {
+ dlt_log(LOG_ERR,"NWTSegmented: Could not send start segment. Aborting.\n");
+ free(thread_data->header);
+ free(thread_data->payload);
+ free(thread_data);
+ return -1;
+ }
+
+ /* Open queue if it is not open */
+ if(dlt_init_message_queue() < 0)
+ {
+ dlt_log(LOG_ERR, "NWTSegmented: Could not open queue.\n");
+ free(thread_data->header);
+ free(thread_data->payload);
+ free(thread_data);
+
+ return -1;
+ }
+
+ /* Add to queue */
+ if(mq_send(dlt_user.dlt_segmented_queue_write_handle,
+ (char *)&thread_data, sizeof(s_segmented_data *), 1) < 0)
+ {
+ if(errno == EAGAIN)
+ {
+ dlt_log(LOG_ERR, "NWTSegmented: Queue full. Message discarded.\n");
+ }
+ free(thread_data->header);
+ free(thread_data->payload);
+ free(thread_data);
+ char str[256];
+ snprintf(str,255,"NWTSegmented: Could not write into queue: %s \n",strerror(errno));
+ dlt_log(LOG_CRIT, str);
+ return -1;
+ }
+
+ //thread_data will be freed by the receiver function
+ //coverity[leaked_storage]
+ return 0;
+}
+
+int dlt_user_trace_network(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
+{
+ return dlt_user_trace_network_truncated(handle, nw_trace_type, header_len, header, payload_len, payload, 1);
+}
+
+int dlt_user_trace_network_truncated(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload, int allow_truncate)
+{
+ DltContextData log;
+
+ if (dlt_user_initialised==0)
+ {
+ if (dlt_init()<0)
+ {
+ return -1;
+ }
+ }
+
+ if (dlt_user_log_init(handle, &log)==-1)
+ {
+ return -1;
+ }
+
+ if (handle==0)
+ {
+ return -1;
+ }
+
+ /* Commented out because of DltNetworkTraceType:
+
+ if ((nw_trace_type<=0) || (nw_trace_type>0x15))
+ {
+ return -1;
+ }
+
+ */
+
+ if (dlt_user.dlt_ll_ts==0)
+ {
+ return -1;
+ }
+
+ if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
+ {
+
+ log.args_num = 0;
+ log.trace_status = nw_trace_type;
+ log.size = 0;
+
+ if (header==0)
+ {
+ header_len=0;
+ }
+
+ /* If truncation is allowed, check if we must do it */
+ if(allow_truncate > 0 && (header_len+payload_len+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
+ {
+ /* Identify as truncated */
+ if(dlt_user_log_write_string(&log, "NWTR") < 0)
+ {
+ return -1;
+ }
+
+ /* Write header and its length */
+ if (dlt_user_log_write_raw(&log, header, header_len) < 0)
+ {
+ return -1;
+ }
+
+ /* Write original size of payload */
+ if(dlt_user_log_write_uint16(&log, payload_len) < 0)
+ {
+ return -1;
+ }
+
+ /**
+ * Calculate maximum avaialble space in sending buffer after headers.
+ */
+
+ int truncated_payload_len = DLT_USER_BUF_MAX_SIZE -
+ log.size - sizeof(uint16_t) - sizeof(uint32_t);
+
+ /* Write truncated payload */
+ if (dlt_user_log_write_raw(&log, payload, truncated_payload_len) < 0)
+ {
+ return -1;
+ }
+ }
+ else /* Truncation not allowed or data short enough */
+ {
+ /* Write header and its length */
+ if (dlt_user_log_write_raw(&log, header, header_len)==-1)
+ {
+ return -1;
+ }
+
+ if (payload==0)
+ {
+ payload_len=0;
+ }
+
+ /* Write payload and its length */
+ if (dlt_user_log_write_raw(&log, payload, payload_len)==-1)
+ {
+ return -1;
+ }
+ }
+
+ /* Send log */
+ return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
+ }
+
+ return 0;
+}
+
+int dlt_log_string(DltContext *handle,DltLogLevelType loglevel, const char *text)
+{
+ DltContextData log;
+
+ if (dlt_user.verbose_mode==0)
+ {
+ return -1;
+ }
+
+ if ((handle==0) || (text==0))
+ {
+ return -1;
+ }
+
+ if (dlt_user_log_write_start(handle,&log,loglevel)>0)
+ {
+ if (dlt_user_log_write_string(&log,text)==-1)
+ {
+ return -1;
}
if (dlt_user_log_write_finish(&log)==-1)
{
return -1;
}
- if (dlt_user_log_write_start(handle,&log,loglevel))
+ if (dlt_user_log_write_start(handle,&log,loglevel)>0)
{
if (dlt_user_log_write_string(&log,text)==-1)
{
return -1;
}
- if (dlt_user_log_write_start(handle,&log,loglevel))
+ if (dlt_user_log_write_start(handle,&log,loglevel)>0)
{
if (dlt_user_log_write_string(&log,text)==-1)
{
return -1;
}
- if (dlt_user_log_write_start(handle,&log,loglevel))
+ if (dlt_user_log_write_start(handle,&log,loglevel)>0)
{
if (dlt_user_log_write_int(&log,data)==-1)
{
return -1;
}
- if (dlt_user_log_write_start(handle,&log,loglevel))
+ if (dlt_user_log_write_start(handle,&log,loglevel)>0)
{
if (dlt_user_log_write_uint(&log,data)==-1)
{
return -1;
}
- if (dlt_user_log_write_start(handle,&log,loglevel))
+ if (dlt_user_log_write_start(handle,&log,loglevel)>0)
{
if (dlt_user_log_write_raw(&log,data,length)==-1)
{
return 0;
}
-void dlt_user_receiverthread_function(void *ptr)
+void dlt_user_receiverthread_function(__attribute__((unused)) void *ptr)
{
while (1)
{
}
log->handle = handle;
- log->mcnt = 0;
return 0;
}
-int dlt_user_log_send_log(DltContextData *log, int mtype)
+int dlt_user_queue_resend(void)
+{
+ static unsigned char dlt_user_queue_resend_error_counter = 0;
+
+ if(dlt_user.dlt_log_handle < 0)
+ {
+ // Fail silenty. FIFO is not open yet
+ return -1;
+ }
+ /**
+ * Ask segmented thread to try emptying the buffer soon.
+ * This will be freed in dlt_user_trace_network_segmented_thread
+ * */
+ s_segmented_data *resend_data = malloc(sizeof(s_segmented_data));
+
+ if (NULL == resend_data)
+ {
+ return -1;
+ }
+
+ resend_data->payload_len = DLT_DELAYED_RESEND_INDICATOR_PATTERN;
+
+
+
+ /* Open queue if it is not open */
+ if(dlt_init_message_queue() < 0)
+ {
+ if(!dlt_user_queue_resend_error_counter)
+ {
+ // log error only when problem occurred first time
+ dlt_log(LOG_ERR, "NWTSegmented: Could not open queue.\n");
+ }
+ dlt_user_queue_resend_error_counter = 1;
+ free(resend_data);
+ return -1;
+ }
+
+ if(mq_send(dlt_user.dlt_segmented_queue_write_handle, (char *)&resend_data, sizeof(s_segmented_data *), 1) < 0)
+ {
+ if(!dlt_user_queue_resend_error_counter)
+ {
+ // log error only when problem occurred first time
+ char str[255];
+ snprintf(str,254,"Could not request resending.: %s \n",strerror(errno));
+ dlt_log(LOG_CRIT, str);
+ }
+ dlt_user_queue_resend_error_counter = 1;
+ free(resend_data);
+ return -1;
+ }
+
+ dlt_user_queue_resend_error_counter = 0;
+
+ //thread_data will be freed by the receiver function
+ //coverity[leaked_storage]
+ return 0;
+}
+
+DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype)
{
DltMessage msg;
DltUserHeader userheader;
int32_t len;
- DltReturnValue ret = 0;
+ DltReturnValue ret = DLT_RETURN_OK;
if (log==0)
{
- return -1;
+ return DLT_RETURN_ERROR;
}
if (log->handle==0)
{
- return -1;
+ return DLT_RETURN_ERROR;
}
if (dlt_user.appID[0]=='\0')
{
- return -1;
+ return DLT_RETURN_ERROR;
}
if (log->handle->contextID[0]=='\0')
{
- return -1;
+ return DLT_RETURN_ERROR;
}
if ((mtype<DLT_TYPE_LOG) || (mtype>DLT_TYPE_CONTROL))
{
- return -1;
+ return DLT_RETURN_ERROR;
}
/* also for Trace messages */
if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG)==-1)
#endif
{
- return -1;
+ return DLT_RETURN_ERROR;
}
if (dlt_message_init(&msg,0)==-1)
{
- return -1;
+ return DLT_RETURN_ERROR;
}
msg.storageheader = (DltStorageHeader*)msg.headerbuffer;
if (dlt_set_storageheader(msg.storageheader,dlt_user.ecuID)==-1)
{
- return -1;
+ return DLT_RETURN_ERROR;
}
msg.standardheader = (DltStandardHeader*)(msg.headerbuffer + sizeof(DltStorageHeader));
msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_MSBF);
#endif
- msg.standardheader->mcnt = log->mcnt++;
+ msg.standardheader->mcnt = log->handle->mcnt++;
/* Set header extra parameters */
dlt_set_id(msg.headerextra.ecu,dlt_user.ecuID);
if (dlt_message_set_extraparameters(&msg,0)==-1)
{
- return -1;
+ return DLT_RETURN_ERROR;
}
/* Fill out extended header, if extended header should be provided */
default:
{
/* This case should not occur */
- return -1;
+ return DLT_RETURN_ERROR;
break;
}
}
if (len>UINT16_MAX)
{
dlt_log(LOG_CRIT,"Huge message discarded!\n");
- return -1;
+ return DLT_RETURN_ERROR;
}
msg.standardheader->len = DLT_HTOBE_16(len);
{
if (dlt_user_print_msg(&msg, log)==-1)
{
- return -1;
+ return DLT_RETURN_ERROR;
}
}
}
{
/* log to file */
ret=dlt_user_log_out2(dlt_user.dlt_log_handle, msg.headerbuffer, msg.headersize, log->buffer, log->size);
- return ((ret==DLT_RETURN_OK)?0:-1);
+ return ret;
}
else
{
/* Reattach to daemon if neccesary */
dlt_user_log_reattach_to_daemon();
- if (dlt_user.overflow)
+ if (dlt_user.overflow_counter)
{
if (dlt_user_log_send_overflow()==0)
{
- dlt_user.overflow=0;
+ sprintf(str,"%u messages discarded!\n",dlt_user.overflow_counter);
+ dlt_log(LOG_ERR, str);
+ dlt_user.overflow_counter=0;
}
}
/* try to resent old data first */
- ret = 0;
+ ret = DLT_RETURN_OK;
if(dlt_user.dlt_log_handle!=-1)
ret = dlt_user_log_resend_buffer();
- if(ret==0)
+ if(ret==DLT_RETURN_OK)
{
/* resend ok or nothing to resent */
#ifdef DLT_SHM_ENABLE
0, 0);
#else
/* log to FIFO */
+#ifdef DLT_TEST_ENABLE
+ if(dlt_user.corrupt_user_header) {
+ userheader.pattern[0]=0xff;
+ userheader.pattern[1]=0xff;
+ userheader.pattern[2]=0xff;
+ userheader.pattern[3]=0xff;
+ }
+ if(dlt_user.corrupt_message_size) {
+ msg.standardheader->len = DLT_HTOBE_16(dlt_user.corrupt_message_size_size);
+ }
+#endif
ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
&(userheader), sizeof(DltUserHeader),
msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
log->buffer, log->size)==-1)
{
- dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
+ if(dlt_user.overflow_counter==0)
+ {
+
+ dlt_log(LOG_ERR,"Buffer full! Messages will be discarded.\n");
+ }
+ ret = DLT_RETURN_BUFFER_FULL;
}
DLT_SEM_FREE();
+
+ // Fail silenty if FIFO is not open
+ if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
+ {
+ ;//dlt_log(LOG_WARNING, "dlt_user_log_send_log: Failed to queue resending.\n");
+ }
}
switch (ret)
{
+ case DLT_RETURN_BUFFER_FULL:
+ {
+ /* Buffer full */
+ dlt_user.overflow_counter += 1;
+ return DLT_RETURN_BUFFER_FULL;
+ }
case DLT_RETURN_PIPE_FULL:
{
/* data could not be written */
- dlt_user.overflow = 1;
- return -1;
+ return DLT_RETURN_PIPE_FULL;
}
case DLT_RETURN_PIPE_ERROR:
{
dlt_user_print_msg(&msg, log);
}
- return -1;
+ return DLT_RETURN_PIPE_ERROR;
}
case DLT_RETURN_ERROR:
{
/* other error condition */
- return -1;
+ return DLT_RETURN_ERROR;
}
case DLT_RETURN_OK:
{
- return 0;
+ return DLT_RETURN_OK;
}
default:
{
/* This case should never occur. */
- return -1;
+ return DLT_RETURN_ERROR;
}
}
}
- return 0;
+ return DLT_RETURN_OK;
}
int dlt_user_log_send_register_application(void)
/* log to FIFO */
ret=dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterApplication),dlt_user.application_description,usercontext.description_length);
- return ((ret==DLT_RETURN_OK)?0:-1);
+
+ /* store message in ringbuffer, if an error has occured */
+ if (ret!=DLT_RETURN_OK)
+ {
+ DLT_SEM_LOCK();
+
+ if (dlt_buffer_push3(&(dlt_user.startup_buffer),
+ (unsigned char *)&(userheader), sizeof(DltUserHeader),
+ (const unsigned char*)&(usercontext), sizeof(DltUserControlMsgRegisterApplication),
+ (const unsigned char*)dlt_user.application_description, usercontext.description_length)==-1)
+ {
+ dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
+ DLT_SEM_FREE();
+ return -1;
+ }
+
+ DLT_SEM_FREE();
+
+ if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
+ {
+ ;//dlt_log(LOG_WARNING, "dlt_user_log_send_register_application: Failed to queue resending.\n");
+ }
+ }
+
+ return 0;
}
int dlt_user_log_send_unregister_application(void)
/* log to FIFO */
ret=dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterContext),log->context_description,usercontext.description_length);
- return ((ret==DLT_RETURN_OK)?0:-1);
+
+ /* store message in ringbuffer, if an error has occured */
+ if (ret!=DLT_RETURN_OK)
+ {
+ DLT_SEM_LOCK();
+
+ if (dlt_buffer_push3(&(dlt_user.startup_buffer),
+ (unsigned char *)&(userheader), sizeof(DltUserHeader),
+ (const unsigned char*)&(usercontext), sizeof(DltUserControlMsgRegisterContext),
+ (const unsigned char*)log->context_description, usercontext.description_length)==-1)
+ {
+ dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
+ DLT_SEM_FREE();
+ return -1;
+ }
+
+ DLT_SEM_FREE();
+
+ if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
+ {
+ ;//dlt_log(LOG_WARNING, "dlt_user_log_send_register_context: Failed to queue resending.\n");
+ }
+ }
+
+ return 0;
+
}
int dlt_user_log_send_unregister_context(DltContextData *log)
{
uint8_t *databuffer_tmp;
int32_t datasize_tmp;
+ int32_t databuffersize_tmp;
static char text[DLT_USER_TEXT_LENGTH];
if ((msg==0) || (log==0))
/* Save variables before print */
databuffer_tmp = msg->databuffer;
datasize_tmp = msg->datasize;
+ databuffersize_tmp = msg->databuffersize;
/* Act like a receiver, convert header back to host format */
msg->standardheader->len = DLT_BETOH_16(msg->standardheader->len);
msg->databuffer = log->buffer;
msg->datasize = log->size;
+ msg->databuffersize = log->size;
/* Print message as ASCII */
if (dlt_message_print_ascii(msg,text,DLT_USER_TEXT_LENGTH,0)==-1)
/* Restore variables and set len to BE*/
msg->databuffer = databuffer_tmp;
+ msg->databuffersize = databuffersize_tmp;
msg->datasize = datasize_tmp;
msg->standardheader->len = DLT_HTOBE_16(msg->standardheader->len);
DltUserControlMsgInjection *usercontextinj;
DltUserControlMsgLogState *userlogstate;
unsigned char *userbuffer;
- unsigned char *inject_buffer;
- if (dlt_user.dlt_user_handle!=-1)
+ /* For delayed calling of injection callback, to avoid deadlock */
+ DltUserInjectionCallback delayed_injection_callback;
+ unsigned char *delayed_inject_buffer = 0;
+ uint32_t delayed_inject_data_length = 0;
+
+ /* Ensure that callback is null before searching for it */
+ delayed_injection_callback.injection_callback = 0;
+ delayed_injection_callback.service_id = 0;
+
+ if (dlt_user.dlt_user_handle!=DLT_FD_INIT)
{
while (1)
{
while ((int32_t)(sizeof(DltUserHeader)+offset)<=receiver->bytesRcvd);
/* Check for user header pattern */
- if (dlt_user_check_userheader(userheader)==0)
+ if (dlt_user_check_userheader(userheader)<0 ||
+ dlt_user_check_userheader(userheader)==0)
{
break;
}
{
dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level = usercontextll->log_level;
dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status = usercontextll->trace_status;
+ if(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_ptr)
+ *(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_ptr) = usercontextll->log_level;
+ if(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status_ptr)
+ *(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status_ptr) = usercontextll->trace_status;
}
}
usercontextinj = (DltUserControlMsgInjection*) (receiver->buf+sizeof(DltUserHeader));
userbuffer = (unsigned char*) (receiver->buf+sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection));
- inject_buffer = 0;
if (userbuffer!=0)
{
if ((dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table) &&
(dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].service_id == usercontextinj->service_id))
{
- /* callback available, so prepare data, then call it */
- inject_buffer = malloc(usercontextinj->data_length_inject);
- if (inject_buffer!=0)
- {
- /* copy from receiver to inject_buffer */
- memcpy(inject_buffer, userbuffer, usercontextinj->data_length_inject);
-
- /* call callback */
- if (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].injection_callback!=0)
- {
- // printf("Got injection(%d), length=%d, '%s' \n", usercontext->service_id, usercontext->data_length_inject, inject_buffer);
- dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].injection_callback(
- usercontextinj->service_id, inject_buffer, usercontextinj->data_length_inject);
- }
-
- if (inject_buffer!=0)
- {
- free(inject_buffer);
- inject_buffer = 0;
- }
- }
-
+ /* Prepare delayed injection callback call */
+ if (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].injection_callback!=0)
+ {
+ delayed_injection_callback.injection_callback = dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].injection_callback;
+ delayed_injection_callback.service_id = usercontextinj->service_id;
+ delayed_inject_data_length = usercontextinj->data_length_inject;
+ delayed_inject_buffer = malloc(delayed_inject_data_length);
+ if(delayed_inject_buffer != 0) {
+ memcpy(delayed_inject_buffer, userbuffer, delayed_inject_data_length);
+ }
+
+ }
break;
}
}
DLT_SEM_FREE();
+ /* Delayed injection callback call */
+ if(delayed_inject_buffer != 0 && delayed_injection_callback.injection_callback != 0) {
+ delayed_injection_callback.injection_callback(delayed_injection_callback.service_id, delayed_inject_buffer, delayed_inject_data_length);
+ delayed_injection_callback.injection_callback = 0;
+ free(delayed_inject_buffer);
+ delayed_inject_buffer = NULL;
+
+ }
+
/* keep not read data in buffer */
if (dlt_receiver_remove(receiver,(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)+usercontextinj->data_length_inject))==-1)
{
int dlt_user_log_resend_buffer(void)
{
int num,count;
- uint8_t buf[DLT_USER_RCVBUF_MAX_SIZE];
int size;
DltReturnValue ret;
{
DLT_SEM_LOCK();
- size = dlt_buffer_copy(&(dlt_user.startup_buffer),buf,sizeof(buf));
+ size = dlt_buffer_copy(&(dlt_user.startup_buffer),dlt_user.resend_buffer,sizeof(dlt_user.resend_buffer));
if (size>0)
{
#ifdef DLT_SHM_ENABLE
- dlt_shm_push(&dlt_user.dlt_shm,buf+sizeof(DltUserHeader),size-sizeof(DltUserHeader),0,0,0,0);
+ dlt_shm_push(&dlt_user.dlt_shm,dlt_user.resend_buffer+sizeof(DltUserHeader),size-sizeof(DltUserHeader),0,0,0,0);
/* log to FIFO */
- ret = dlt_user_log_out3(dlt_user.dlt_log_handle, buf,sizeof(DltUserHeader),0,0,0,0);
+ ret = dlt_user_log_out3(dlt_user.dlt_log_handle, dlt_user.resend_buffer,sizeof(DltUserHeader),0,0,0,0);
#else
/* log to FIFO */
- ret = dlt_user_log_out3(dlt_user.dlt_log_handle, buf,size,0,0,0,0);
+ ret = dlt_user_log_out3(dlt_user.dlt_log_handle, dlt_user.resend_buffer,size,0,0,0,0);
#endif
/* in case of error, keep message in ringbuffer */
if (ret==DLT_RETURN_OK)
{
dlt_buffer_remove(&(dlt_user.startup_buffer));
- /*
- DLT_SEM_LOCK();
- if (dlt_buffer_push(&(dlt_user.startup_buffer), buf, size)==-1)
- {
- dlt_log(LOG_ERR,"Error pushing back message to history buffer. Message discarded.\n");
- }
- DLT_SEM_FREE();
-
- // In case of: data could not be written, set overflow flag
- if (ret==DLT_RETURN_PIPE_FULL)
- {
- dlt_user.overflow = 1;
- }
- */
}
else
{
for (num=0; num<dlt_user.dlt_ll_ts_num_entries; num++)
{
/* Re-register stored context */
- if ((dlt_user.appID[0]!='\0') && (dlt_user.dlt_ll_ts[num].contextID[0]!='\0') && (dlt_user.dlt_ll_ts))
+ if ((dlt_user.appID[0]!='\0') && (dlt_user.dlt_ll_ts) && (dlt_user.dlt_ll_ts[num].contextID[0]!='\0'))
{
//dlt_set_id(log_new.appID, dlt_user.appID);
dlt_set_id(handle.contextID, dlt_user.dlt_ll_ts[num].contextID);
int dlt_user_log_send_overflow(void)
{
DltUserHeader userheader;
+ DltUserControlMsgBufferOverflow userpayload;
DltReturnValue ret;
/* set userheader */
return 0;
}
+ /* set user message parameters */
+ userpayload.overflow_counter = dlt_user.overflow_counter;
+ dlt_set_id(userpayload.apid,dlt_user.appID);
+
/* log to FIFO */
- ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), 0, 0);
+ ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader),
+ &(userpayload), sizeof(DltUserControlMsgBufferOverflow));
return ((ret==DLT_RETURN_OK)?0:-1);
}
return 0; /* ok */
}
+#ifdef DLT_TEST_ENABLE
+void dlt_user_test_corrupt_user_header(int enable)
+{
+ dlt_user.corrupt_user_header = enable;
+}
+void dlt_user_test_corrupt_message_size(int enable,int16_t size)
+{
+ dlt_user.corrupt_message_size = enable;
+ dlt_user.corrupt_message_size_size = size;
+}
+#endif
+
+