Bug 84 - Adding utf8 support to dlt-daemon, dlt-viewer. Modified patch, originally...
[profile/ivi/dlt-daemon.git] / src / lib / dlt_user.c
index 117e6ae..1f43801 100644 (file)
@@ -63,7 +63,6 @@
  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 */
@@ -83,6 +82,8 @@
 
 #include <sys/uio.h> /* writev() */
 
+#include <limits.h>
+
 #include "dlt_user.h"
 #include "dlt_user_shared.h"
 #include "dlt_user_shared_cfg.h"
@@ -97,11 +98,31 @@ static sem_t dlt_mutex;
 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);
@@ -112,6 +133,9 @@ static int dlt_user_print_msg(DltMessage *msg, DltContextData *log);
 static int dlt_user_log_check_user_message(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){
 
@@ -223,7 +247,23 @@ int dlt_init(void)
                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)
@@ -251,6 +291,77 @@ 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;
@@ -299,6 +410,7 @@ int dlt_init_common(void)
     }
 
     /* 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;
@@ -306,8 +418,10 @@ int dlt_init_common(void)
     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 */
 
@@ -324,6 +438,10 @@ int dlt_init_common(void)
 
 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();
@@ -412,6 +530,7 @@ int dlt_free(void)
        /* 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++)
@@ -429,6 +548,23 @@ int dlt_free(void)
         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;
 
@@ -975,6 +1111,11 @@ int dlt_forward_msg(void *msgdata,size_t size)
                        }
 
             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)
@@ -1085,7 +1226,7 @@ int dlt_user_log_write_finish(DltContextData *log)
         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)
@@ -1627,7 +1768,50 @@ int dlt_user_log_write_string(DltContextData *log, const char *text)
             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);
@@ -1744,16 +1928,7 @@ int dlt_register_injection_callback(DltContext *handle, uint32_t service_id,
 /**
  * NW Trace related
  */
-#define MAX_TRACE_SEGMENT_SIZE 1024
 
-typedef struct {
-       DltContext handle;
-       DltNetworkTraceType nw_trace_type;
-       uint16_t header_len;
-       void *header;
-       uint16_t payload_len;
-       void *payload;
-} s_segmented_data;
 
 int check_buffer()
 {
@@ -1771,18 +1946,15 @@ int check_buffer()
  * Send the start of a segment chain.
  * Returns -1 on failure
  */
-int dlt_user_trace_network_segmented_start(unsigned int *id, DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len)
+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)
 {
 
     DltContextData log;
        struct timeval tv;
 
-    if (dlt_user_initialised==0)
+    if (handle==NULL)
     {
-        if (dlt_init()<0)
-        {
-            return -1;
-        }
+        return -1;
     }
 
     if (dlt_user_log_init(handle, &log)==-1)
@@ -1790,12 +1962,6 @@ int dlt_user_trace_network_segmented_start(unsigned int *id, DltContext *handle,
                return -1;
     }
 
-    if (handle==0)
-    {
-        return -1;
-    }
-
-
     DLT_SEM_LOCK();
 
     if (dlt_user.dlt_ll_ts==0)
@@ -1822,7 +1988,7 @@ int dlt_user_trace_network_segmented_start(unsigned int *id, DltContext *handle,
         }
 
         /* Write stream handle */
-        if(dlt_user_log_write_uint(&log, *id) < 0)
+        if(dlt_user_log_write_uint16(&log, *id) < 0)
         {
                return -1;
         }
@@ -1834,21 +2000,27 @@ int dlt_user_trace_network_segmented_start(unsigned int *id, DltContext *handle,
         }
 
         /* Write size of payload */
-        if(dlt_user_log_write_uint(&log, payload_len))
+        if(dlt_user_log_write_uint16(&log, payload_len) < 0)
         {
                return -1;
         }
 
         /* Write expected segment count */
-        uint16_t segment_count = floor(payload_len/MAX_TRACE_SEGMENT_SIZE)+1;
+        uint16_t segment_count = payload_len/DLT_MAX_TRACE_SEGMENT_SIZE+1;
 
-        if(dlt_user_log_write_uint(&log, segment_count))
+        /* 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_uint(&log, MAX_TRACE_SEGMENT_SIZE))
+        if(dlt_user_log_write_uint16(&log, DLT_MAX_TRACE_SEGMENT_SIZE) < 0)
         {
                return -1;
         }
@@ -1863,42 +2035,26 @@ int dlt_user_trace_network_segmented_start(unsigned int *id, DltContext *handle,
     return 0;
 }
 
-int dlt_user_trace_network_segmented_segment(int id, DltContext *handle, DltNetworkTraceType nw_trace_type, int sequence, uint16_t payload_len, void *payload)
+int dlt_user_trace_network_segmented_segment(uint16_t id, DltContext *handle, DltNetworkTraceType nw_trace_type, int sequence, uint16_t payload_len, void *payload)
 {
-       int max_wait = 20;
-       usleep(1000); // Yield, to give other threads time
        while(check_buffer() < 0)
        {
                usleep(1000*50); // Wait 50ms
-               if(max_wait-- < 0)
-               {
-                       // Waited one second for buffer to flush, return error.
-                       return -1;
-               }
                dlt_user_log_resend_buffer();
        }
 
-    DltContextData log;
-
-    if (dlt_user_initialised==0)
+    if (handle==NULL)
     {
-        if (dlt_init()<0)
-        {
-            return -1;
-        }
+        return -1;
     }
 
+    DltContextData log;
+
     if (dlt_user_log_init(handle, &log)==-1)
     {
                return -1;
     }
 
-    if (handle==0)
-    {
-        return -1;
-    }
-
-
     DLT_SEM_LOCK();
 
     if (dlt_user.dlt_ll_ts==0)
@@ -1922,13 +2078,13 @@ int dlt_user_trace_network_segmented_segment(int id, DltContext *handle, DltNetw
         }
 
         /* Write stream handle */
-        if(dlt_user_log_write_uint(&log, id) < 0)
+        if(dlt_user_log_write_uint16(&log, id) < 0)
         {
                return -1;
         }
 
         /* Write segment sequence number */
-        if(dlt_user_log_write_uint(&log, sequence))
+        if(dlt_user_log_write_uint16(&log, sequence) < 0)
         {
                return -1;
         }
@@ -1946,19 +2102,19 @@ int dlt_user_trace_network_segmented_segment(int id, DltContext *handle, DltNetw
     {
         DLT_SEM_FREE();
     }
+
+    /* Allow other threads to log between chunks */
+       pthread_yield();
     return 0;
 }
 
-int dlt_user_trace_network_segmented_end(int id, DltContext *handle, DltNetworkTraceType nw_trace_type)
+int dlt_user_trace_network_segmented_end(uint16_t id, DltContext *handle, DltNetworkTraceType nw_trace_type)
 {
     DltContextData log;
 
-    if (dlt_user_initialised==0)
+    if (handle==0)
     {
-        if (dlt_init()<0)
-        {
-            return -1;
-        }
+        return -1;
     }
 
     if (dlt_user_log_init(handle, &log)==-1)
@@ -1966,10 +2122,6 @@ int dlt_user_trace_network_segmented_end(int id, DltContext *handle, DltNetworkT
                return -1;
     }
 
-    if (handle==0)
-    {
-        return -1;
-    }
 
 
     DLT_SEM_LOCK();
@@ -2010,67 +2162,187 @@ int dlt_user_trace_network_segmented_end(int id, DltContext *handle, DltNetworkT
     return 0;
 }
 
-void dlt_user_trace_network_segmented_thread(s_segmented_data *data)
+
+void dlt_user_trace_network_segmented_thread(void *unused)
 {
-       unsigned int id;
-       /* Send initial message */
-       if(dlt_user_trace_network_segmented_start(&id, &(data->handle), data->nw_trace_type, data->header_len, data->header, data->payload_len) < 0)
-       {
-               // TODO: Report error
-               return;
-       }
+       /* Unused on purpose. */
+       (void) unused;
 
-       /* Send segments */
-       uint16_t offset = 0;
-       uint16_t sequence = 0;
-       void *ptr;
+       s_segmented_data *data;
 
-       do
-       {
-               uint16_t len = data->payload_len - offset;
-               if(len > MAX_TRACE_SEGMENT_SIZE)
-               {
-                       len = MAX_TRACE_SEGMENT_SIZE;
-               }
-               ptr = data->payload + offset;
-               if(dlt_user_trace_network_segmented_segment(id, &(data->handle), data->nw_trace_type, sequence++, len, ptr) < 0)
-               {
-                       // TODO: Report error
-                       return;
-               }
-               offset += MAX_TRACE_SEGMENT_SIZE;
-       }while(offset < data->payload_len);
+        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 *))
+                {
 
-       dlt_user_trace_network_segmented_end(id, &(data->handle), data->nw_trace_type);
+                        char str[255];
+                        snprintf(str,254,"NWTSegmented: Error while reading queue: %s \n",strerror(errno));
+                        dlt_log(LOG_CRIT, str);
+                        continue;
+                }
 
-       // Allocated outside of thread, free here.
-       free(data->header);
-       free(data->payload);
-       free(data);
+                /* 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(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
+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 */
-       memcpy(&(thread_data->handle), handle, sizeof(DltContext));
+       thread_data->handle = handle;
        thread_data->nw_trace_type = nw_trace_type;
        thread_data->header_len = header_len;
-       thread_data->header = malloc(header_len);
        memcpy(thread_data->header, header, header_len);
        thread_data->payload_len = payload_len;
-       thread_data->payload = malloc(payload_len);
        memcpy(thread_data->payload, payload, payload_len);
 
-       /* Begin background thread */
-       pthread_t thread;
-       pthread_create(&thread, NULL, (void *)dlt_user_trace_network_segmented_thread, thread_data);
+       /* 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, 0);
+       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)
@@ -2128,8 +2400,6 @@ int dlt_user_trace_network_truncated(DltContext *handle, DltNetworkTraceType nw_
         /* 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)
         {
-               int truncated_payload_len = DLT_USER_BUF_MAX_SIZE - header_len - 40; // 40 == overhead bytes
-
                /* Identify as truncated */
                if(dlt_user_log_write_string(&log, "NWTR") < 0)
                {
@@ -2143,11 +2413,18 @@ int dlt_user_trace_network_truncated(DltContext *handle, DltNetworkTraceType nw_
             }
 
                /* Write original size of payload */
-            if(dlt_user_log_write_uint(&log, payload_len) < 0)
+            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)
             {
@@ -2461,37 +2738,80 @@ int dlt_user_log_init(DltContext *handle, DltContextData *log)
     return 0;
 }
 
-int dlt_user_log_send_log(DltContextData *log, int mtype)
+int dlt_user_queue_resend(void)
+{
+       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)
+       {
+               dlt_log(LOG_ERR, "NWTSegmented: Could not open queue.\n");
+                free(resend_data);
+               return -1;
+       }
+
+    if(mq_send(dlt_user.dlt_segmented_queue_write_handle, (char *)&resend_data, sizeof(s_segmented_data *), 1) < 0)
+    {
+        char str[255];
+        snprintf(str,254,"Could not request resending.: %s \n",strerror(errno));
+        dlt_log(LOG_CRIT, str);
+       free(resend_data);
+       return -1;
+    }
+    //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 */
@@ -2501,19 +2821,19 @@ int dlt_user_log_send_log(DltContextData *log, int mtype)
     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));
@@ -2545,7 +2865,7 @@ int dlt_user_log_send_log(DltContextData *log, int mtype)
 
     if (dlt_message_set_extraparameters(&msg,0)==-1)
     {
-       return -1;
+       return DLT_RETURN_ERROR;
     }
 
     /* Fill out extended header, if extended header should be provided */
@@ -2569,7 +2889,7 @@ int dlt_user_log_send_log(DltContextData *log, int mtype)
         default:
         {
                    /* This case should not occur */
-            return -1;
+            return DLT_RETURN_ERROR;
             break;
         }
         }
@@ -2596,7 +2916,7 @@ int dlt_user_log_send_log(DltContextData *log, int mtype)
     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);
@@ -2609,7 +2929,7 @@ int dlt_user_log_send_log(DltContextData *log, int mtype)
         {
             if (dlt_user_print_msg(&msg, log)==-1)
             {
-                               return -1;
+                               return DLT_RETURN_ERROR;
             }
         }
     }
@@ -2618,7 +2938,7 @@ int dlt_user_log_send_log(DltContextData *log, int mtype)
     {
         /* 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
     {
@@ -2634,10 +2954,10 @@ int dlt_user_log_send_log(DltContextData *log, int mtype)
         }
 
                /* 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
@@ -2681,18 +3001,30 @@ int dlt_user_log_send_log(DltContextData *log, int mtype)
                                 log->buffer, log->size)==-1)
                        {
                                dlt_log(LOG_ERR,"Storing message to history buffer failed! Message 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 */
+               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:
         {
@@ -2710,26 +3042,26 @@ int dlt_user_log_send_log(DltContextData *log, int mtype)
                 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)
@@ -2787,6 +3119,11 @@ int dlt_user_log_send_register_application(void)
              }
 
         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;
@@ -2893,6 +3230,11 @@ int dlt_user_log_send_register_context(DltContextData *log)
              }
 
         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;
@@ -3113,7 +3455,8 @@ int dlt_user_log_check_user_message(void)
                 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;
                 }
@@ -3215,7 +3558,10 @@ int dlt_user_log_check_user_message(void)
                         /* 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);
-                               free(delayed_inject_buffer);
+                                delayed_injection_callback.injection_callback = 0;
+                                free(delayed_inject_buffer);
+                                delayed_inject_buffer = NULL;
+
                         }
 
                         /* keep not read data in buffer */
@@ -3276,7 +3622,6 @@ int dlt_user_log_check_user_message(void)
 int dlt_user_log_resend_buffer(void)
 {
        int num,count;
-    uint8_t buf[DLT_USER_RCVBUF_MAX_SIZE];
     int size;
        DltReturnValue ret;
        
@@ -3289,38 +3634,24 @@ int dlt_user_log_resend_buffer(void)
        {
 
                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
                        {
@@ -3379,7 +3710,7 @@ void dlt_user_log_reattach_to_daemon(void)
             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);