+ if (handle==NULL)
+ {
+ return -1;
+ }
+
+ DltContextData log;
+
+ 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)
+ {
+ DLT_SEM_FREE();
+
+ 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;
+ }
+
+ /* 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);
+ }
+ else
+ {
+ DLT_SEM_FREE();
+ }
+
+ /* 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;
+ }
+
+
+
+ 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)
+ {
+ DLT_SEM_FREE();
+
+ 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);
+ }
+ else
+ {
+ DLT_SEM_FREE();
+ }
+ 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;
+ }
+
+ */
+
+ 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)
+ {
+ DLT_SEM_FREE();
+
+ 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);
+ }
+ else
+ {
+ DLT_SEM_FREE();
+ }
+
+ return 0;
+}
+
+int dlt_log_string(DltContext *handle,DltLogLevelType loglevel, const char *text)
+{
+ DltContextData log;
+
+ if (dlt_user.verbose_mode==0)