From 2262f8b3406ac903a37f96a63c6250de215d1866 Mon Sep 17 00:00:00 2001 From: Manikandan C Date: Wed, 28 Nov 2018 11:01:44 +0100 Subject: Made socket send reliable Made TCP socket send reliable by storing the unsent/partial message in the ring buffer. This will avoid the corrupted messages/Gaps in Viewer side Signed-off-by: ManikandanC --- include/dlt/dlt_common.h | 1 + src/daemon/dlt_daemon_client.c | 35 ++++++++++++++++----- src/daemon/dlt_daemon_connection.c | 28 +++++++++++------ src/daemon/dlt_daemon_socket.c | 64 ++++++++++++++++++++------------------ src/daemon/dlt_daemon_socket.h | 2 +- src/shared/dlt_common.c | 1 + 6 files changed, 83 insertions(+), 48 deletions(-) diff --git a/include/dlt/dlt_common.h b/include/dlt/dlt_common.h index 4803663..fa68997 100644 --- a/include/dlt/dlt_common.h +++ b/include/dlt/dlt_common.h @@ -765,6 +765,7 @@ typedef struct char *buf; /**< pointer to position within receiver buffer */ char *backup_buf; /** pointer to the buffer with partial messages if any **/ int fd; /**< connection handle */ + int32_t bytes_sent; /**< total bytes sent in a single msg */ int32_t buffersize; /**< size of receiver buffer */ } DltReceiver; diff --git a/src/daemon/dlt_daemon_client.c b/src/daemon/dlt_daemon_client.c index bd3233f..120d2af 100644 --- a/src/daemon/dlt_daemon_client.c +++ b/src/daemon/dlt_daemon_client.c @@ -114,14 +114,11 @@ static int dlt_daemon_client_send_all_multiple(DltDaemon *daemon, int type_mask = (DLT_CON_MASK_CLIENT_MSG_TCP | DLT_CON_MASK_CLIENT_MSG_SERIAL); char local_str[DLT_DAEMON_TEXTBUFSIZE]; + uint8_t *tmp_buffer = NULL; if ((daemon == NULL) || (daemon_local == NULL)) { - snprintf(local_str, - DLT_DAEMON_TEXTBUFSIZE, - "%s: Invalid parameters\n", - __func__); - dlt_log(LOG_ERR, local_str); + dlt_vlog(LOG_ERR, "%s: Invalid parameters\n", __func__); return 0; } @@ -146,9 +143,33 @@ static int dlt_daemon_client_send_all_multiple(DltDaemon *daemon, daemon->sendserialheader); DLT_DAEMON_SEM_FREE(); - if((ret != DLT_DAEMON_ERROR_OK) && - DLT_CONNECTION_CLIENT_MSG_TCP == temp->type) + if ((ret != DLT_DAEMON_ERROR_OK) && + DLT_CONNECTION_CLIENT_MSG_TCP == temp->type) { + if (daemon->state != DLT_DAEMON_STATE_BUFFER_FULL) + { + if (temp->receiver->bytes_sent < (size1 + size2)) + { + tmp_buffer = (uint8_t*)calloc(size1 + size2, sizeof(uint8_t)); + memcpy(tmp_buffer, data1, size1); + memcpy(tmp_buffer + size1, data2, size2); + DLT_DAEMON_SEM_LOCK(); + /* Store message in history buffer */ + if (dlt_buffer_push3(&(daemon->client_ringbuffer), + tmp_buffer + temp->receiver->bytes_sent, + (size1 + size2 - temp->receiver->bytes_sent), + 0, + 0, + 0, + 0) < DLT_RETURN_OK) + { + dlt_vlog(LOG_DEBUG, "%s: Buffer is full! Message discarded.\n", __func__); + dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_BUFFER_FULL); + } + free(tmp_buffer); + DLT_DAEMON_SEM_FREE(); + } + } dlt_daemon_close_socket(temp->receiver->fd, daemon, daemon_local, diff --git a/src/daemon/dlt_daemon_connection.c b/src/daemon/dlt_daemon_connection.c index 3595981..e0cb003 100644 --- a/src/daemon/dlt_daemon_connection.c +++ b/src/daemon/dlt_daemon_connection.c @@ -70,6 +70,8 @@ DLT_STATIC int dlt_connection_send(DltConnection *conn, size_t msg_size) { DltConnectionType type = DLT_CONNECTION_TYPE_MAX; + int bytes_sent = 0; + int ret = 0; if ((conn != NULL) && (conn->receiver != NULL)) { @@ -78,14 +80,22 @@ DLT_STATIC int dlt_connection_send(DltConnection *conn, switch (type) { - case DLT_CONNECTION_CLIENT_MSG_SERIAL: - if(write(conn->receiver->fd, msg, msg_size) > 0) - return DLT_DAEMON_ERROR_OK; - return DLT_DAEMON_ERROR_UNKNOWN; - case DLT_CONNECTION_CLIENT_MSG_TCP: - return dlt_daemon_socket_sendreliable(conn->receiver->fd, msg, msg_size); - default: - return DLT_DAEMON_ERROR_UNKNOWN; + case DLT_CONNECTION_CLIENT_MSG_SERIAL: + if (write(conn->receiver->fd, msg, msg_size) > 0) + { + return DLT_DAEMON_ERROR_OK; + } + return DLT_DAEMON_ERROR_UNKNOWN; + + case DLT_CONNECTION_CLIENT_MSG_TCP: + ret = dlt_daemon_socket_sendreliable(conn->receiver->fd, + msg, + msg_size, + &bytes_sent); + conn->receiver->bytes_sent += bytes_sent; + return ret; + default: + return DLT_DAEMON_ERROR_UNKNOWN; } } @@ -124,7 +134,7 @@ int dlt_connection_send_multiple(DltConnection *con, sizeof(dltSerialHeader)); } - if ((data1 != NULL) && (ret == DLT_RETURN_OK )) + if ((data1 != NULL) && (ret == DLT_RETURN_OK)) { ret = dlt_connection_send(con, data1, size1); } diff --git a/src/daemon/dlt_daemon_socket.c b/src/daemon/dlt_daemon_socket.c index 521b3e6..c85798f 100644 --- a/src/daemon/dlt_daemon_socket.c +++ b/src/daemon/dlt_daemon_socket.c @@ -146,53 +146,62 @@ int dlt_daemon_socket_close(int sock) int dlt_daemon_socket_send(int sock,void* data1,int size1,void* data2,int size2,char serialheader) { - /* Optional: Send serial header, if requested */ int ret = DLT_RETURN_OK; + int bytes_sent = 0; + + /* Optional: Send serial header, if requested */ if (serialheader) { - ret = dlt_daemon_socket_sendreliable(sock, (void *) dltSerialHeader, sizeof(dltSerialHeader)); - if(ret != DLT_RETURN_OK) + ret = dlt_daemon_socket_sendreliable(sock, + (void *) dltSerialHeader, + sizeof(dltSerialHeader), + &bytes_sent); + if (ret != DLT_RETURN_OK) return ret; } /* Send data */ - if(data1 != NULL && size1 > 0) + + if ((data1 != NULL) && (size1 > 0)) { - ret = dlt_daemon_socket_sendreliable(sock, data1, size1); - if(ret != DLT_RETURN_OK) + ret = dlt_daemon_socket_sendreliable(sock, data1, size1, &bytes_sent); + if (ret != DLT_RETURN_OK) + { return ret; + } } - if(data2 != NULL && size2 > 0) + if ((data2 != NULL) && (size2 > 0)) { - ret = dlt_daemon_socket_sendreliable(sock, data2, size2); - if(ret != DLT_RETURN_OK) - return ret; + ret = dlt_daemon_socket_sendreliable(sock, data2, size2, &bytes_sent); } return ret; } -int dlt_daemon_socket_sendreliable(int sock, void* buffer, int message_size) +int dlt_daemon_socket_get_send_qeue_max_size(int sock) +{ + int n = 0; + socklen_t m = sizeof(n); + getsockopt(sock,SOL_SOCKET,SO_SNDBUF,(void *)&n, &m); + + return n; +} + +int dlt_daemon_socket_sendreliable(int sock, void* data_buffer, int message_size, int* bytes_sent) { int data_sent = 0; while (data_sent < message_size) { - ssize_t ret = send(sock, buffer + data_sent, message_size - data_sent, 0); + ssize_t ret = send(sock, data_buffer + data_sent, message_size - data_sent, 0); if (ret < 0) { - const int lastErrno=errno; - if (lastErrno==EINTR || lastErrno==EAGAIN || lastErrno==EWOULDBLOCK) - { - // Temporary error. - dlt_vlog(LOG_INFO,"dlt_daemon_socket_sendreliable: socket send() error %d: %s, trying again.\n", lastErrno, strerror(lastErrno)); - } - else - { - dlt_vlog(LOG_WARNING,"dlt_daemon_socket_sendreliable: socket send() error %d: %s\n", lastErrno, strerror(lastErrno)); - return DLT_DAEMON_ERROR_SEND_FAILED; - } + dlt_vlog(LOG_WARNING, + "dlt_daemon_socket_sendreliable: socket send failed [errno: %d]!\n", + errno); + *bytes_sent = data_sent; + return DLT_DAEMON_ERROR_SEND_FAILED; } else { @@ -200,15 +209,8 @@ int dlt_daemon_socket_sendreliable(int sock, void* buffer, int message_size) } } + *bytes_sent = data_sent; return DLT_DAEMON_ERROR_OK; } -int dlt_daemon_socket_get_send_qeue_max_size(int sock) -{ - int n = 0; - socklen_t m = sizeof(n); - getsockopt(sock,SOL_SOCKET,SO_SNDBUF,(void *)&n, &m); - - return n; -} diff --git a/src/daemon/dlt_daemon_socket.h b/src/daemon/dlt_daemon_socket.h index a7f9ca6..a94990f 100644 --- a/src/daemon/dlt_daemon_socket.h +++ b/src/daemon/dlt_daemon_socket.h @@ -76,6 +76,6 @@ int dlt_daemon_socket_send(int sock,void* data1,int size1,void* data2,int size2, * @param message_size * @return on sucess: DLT_DAEMON_ERROR_OK, on error: DLT_DAEMON_ERROR_SEND_FAILED */ -int dlt_daemon_socket_sendreliable(int sock, void* buffer,int message_size); +int dlt_daemon_socket_sendreliable(int sock, void* data_buffer, int message_size, int* bytes_sent); #endif /* DLT_DAEMON_SOCKET_H */ diff --git a/src/shared/dlt_common.c b/src/shared/dlt_common.c index 7ddef50..ce2d3f4 100644 --- a/src/shared/dlt_common.c +++ b/src/shared/dlt_common.c @@ -2134,6 +2134,7 @@ DltReturnValue dlt_receiver_init(DltReceiver *receiver, int fd, int buffersize) receiver->lastBytesRcvd = 0; receiver->bytesRcvd = 0; receiver->totalBytesRcvd = 0; + receiver->bytes_sent = 0; receiver->buffersize = buffersize; receiver->fd = fd; receiver->buffer = (char*)malloc(receiver->buffersize); -- cgit v1.2.1