From 976746f28e1c4c0a6ee24bf3f94ce66b890b3898 Mon Sep 17 00:00:00 2001 From: Sunil-K-S <54260601+Sunil-K-S@users.noreply.github.com> Date: Fri, 23 Aug 2019 10:01:08 +0530 Subject: UDP Multicast implementation (#155) The feature can be enabled by setting WITH_UDP_CONNECTION to ON. Signed-off-by: sunil.s --- CMakeLists.txt | 2 + README.md | 1 + doc/dlt.conf.5.md | 12 + src/daemon/CMakeLists.txt | 9 +- src/daemon/dlt-daemon.c | 49 ++++ src/daemon/dlt-daemon.h | 5 + src/daemon/dlt.conf | 12 + src/daemon/dlt_daemon_client.c | 15 ++ src/daemon/dlt_daemon_common.h | 9 + .../udp_connection/dlt_daemon_udp_common_socket.h | 73 ++++++ src/daemon/udp_connection/dlt_daemon_udp_socket.c | 258 +++++++++++++++++++++ src/daemon/udp_connection/dlt_daemon_udp_socket.h | 32 +++ src/examples/CMakeLists.txt | 13 +- .../dlt-example-multicast-clientmsg-view.c | 197 ++++++++++++++++ 14 files changed, 684 insertions(+), 3 deletions(-) create mode 100644 src/daemon/udp_connection/dlt_daemon_udp_common_socket.h create mode 100644 src/daemon/udp_connection/dlt_daemon_udp_socket.c create mode 100644 src/daemon/udp_connection/dlt_daemon_udp_socket.h create mode 100644 src/examples/dlt-example-multicast-clientmsg-view.c diff --git a/CMakeLists.txt b/CMakeLists.txt index baf0f34..b303f29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,6 +78,7 @@ option(WITH_DLT_LOGSTORAGE_CTRL_UDEV "PROTOTYPE! Set to ON to build logstorage c option(WITH_DLT_USE_IPv6 "Set to ON for IPv6 support" ON) option(WITH_DLT_KPI "Set to ON to build src/kpi binaries" OFF) option(WITH_DLT_FATAL_LOG_TRAP "Set to ON to enable DLT_LOG_FATAL trap(trigger segv inside dlt-user library)" OFF) +option(WITH_UDP_CONNECTION "Set to ON to enable dlt UDP multicast SUPPORT" ON) # RPM settings set(GENIVI_RPM_RELEASE "1") # ${DLT_REVISION}") @@ -262,6 +263,7 @@ message(STATUS "CMAKE_HOST_SYSTEM_PROCESSOR = ${CMAKE_HOST_SYSTEM_PROCESSOR}") message(STATUS "CMAKE_SYSTEM_PROCESSOR = ${CMAKE_SYSTEM_PROCESSOR}") message(STATUS "WITH_DLT_LOGSTORAGE_CTRL_UDEV = ${WITH_DLT_LOGSTORAGE_CTRL_UDEV}") message(STATUS "DLT_IPC = ${DLT_IPC}(Path: ${DLT_USER_IPC_PATH})") +message(STATUS "WITH_UDP_CONNECTION = ${WITH_UDP_CONNECTION}") message(STATUS "Change a value with: cmake -D=") message(STATUS "-------------------------------------------------------------------------------") message(STATUS) diff --git a/README.md b/README.md index b2644a7..9adf5a7 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ DLT\_USER | genivi | Set user for process not ru WITH\_CHECK\_CONFIG\_FILE | OFF | Set to ON to create a configure file of CheckIncludeFiles and CheckFunctionExists CMAKE\_INSTALL\_PREFIX | /usr/local CMAKE\_BUILD\_TYPE | RelWithDebInfo +WITH\_UDP\_CONNECTION | ON | Set to ON to enable dlt UDP multicast SUPPORT #### Command Line Tool Options diff --git a/doc/dlt.conf.5.md b/doc/dlt.conf.5.md index 5142118..6dd9ee5 100644 --- a/doc/dlt.conf.5.md +++ b/doc/dlt.conf.5.md @@ -321,6 +321,18 @@ Maximal used memory for log storage cache in KB. Default: 30000 KB +## UDPConnectionSetup + +Enable or disable UDP connection. 0 = disabled, 1 = enabled + +## UDPMulticastIPAddress + +The address on which daemon multicasts the log messages + +## UDPMulticastIPPort + +The Multicase IP port. Default: 3491 + # AUTHOR Alexander Wenzel (alexander.aw.wenzel (at) bmw (dot) de) diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt index b5cca17..adddee3 100644 --- a/src/daemon/CMakeLists.txt +++ b/src/daemon/CMakeLists.txt @@ -45,8 +45,6 @@ if(WITH_DLT_SHM_ENABLE) ${PROJECT_SOURCE_DIR}/src/shared/dlt_shm.c) endif() -add_executable(dlt-daemon ${dlt_daemon_SRCS} ${systemd_SRCS}) - if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") set(RT_LIBRARY rt) set(SOCKET_LIBRARY "") @@ -55,6 +53,13 @@ else() set(SOCKET_LIBRARY socket) endif() +if(WITH_UDP_CONNECTION) + include_directories(${PROJECT_SOURCE_DIR}/src/daemon/udp_connection) + add_definitions(-DUDP_CONNECTION_SUPPORT) + set(dlt_daemon_SRCS ${dlt_daemon_SRCS} ${PROJECT_SOURCE_DIR}/src/daemon/udp_connection/dlt_daemon_udp_socket.c) +endif(WITH_UDP_CONNECTION) + +add_executable(dlt-daemon ${dlt_daemon_SRCS} ${systemd_SRCS}) target_link_libraries(dlt-daemon ${RT_LIBRARY} ${SOCKET_LIBRARY} ${CMAKE_THREAD_LIBS_INIT}) install(TARGETS dlt-daemon diff --git a/src/daemon/dlt-daemon.c b/src/daemon/dlt-daemon.c index a06c6ae..cbb85cc 100644 --- a/src/daemon/dlt-daemon.c +++ b/src/daemon/dlt-daemon.c @@ -65,6 +65,9 @@ #include "dlt_daemon_offline_logstorage.h" #include "dlt_gateway.h" +#ifdef UDP_CONNECTION_SUPPORT +# include "dlt_daemon_udp_socket.h" +#endif #if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) || defined(DLT_SYSTEMD_ENABLE) # include "sd-daemon.h" #endif @@ -289,6 +292,11 @@ int option_file_parser(DltDaemonLocal *daemon_local) daemon_local->flags.contextLogLevel = DLT_LOG_INFO; daemon_local->flags.contextTraceStatus = DLT_TRACE_STATUS_OFF; daemon_local->flags.enforceContextLLAndTS = 0; /* default is off */ +#ifdef UDP_CONNECTION_SUPPORT + daemon_local->UDPConnectionSetup = MULTICAST_CONNECTION_ENABLED; + strncpy(daemon_local->UDPMulticastIPAddress, MULTICASTIPADDRESS, MULTICASTIP_MAX_SIZE - 1); + daemon_local->UDPMulticastIPPort = MULTICASTIPPORT; +#endif /* open configuration file */ if (daemon_local->flags.cvalue[0]) @@ -597,6 +605,33 @@ int option_file_parser(DltDaemonLocal *daemon_local) strncpy(daemon_local->flags.daemonFifoGroup, value, NAME_MAX); daemon_local->flags.daemonFifoGroup[NAME_MAX] = 0; } +#endif +#ifdef UDP_CONNECTION_SUPPORT + else if (strcmp(token, "UDPConnectionSetup") == 0) + { + const long longval = strtol(value, NULL, 10); + + if ((longval == MULTICAST_CONNECTION_DISABLED) + || (longval == MULTICAST_CONNECTION_ENABLED)) { + daemon_local->UDPConnectionSetup = longval; + printf("Option: %s=%s\n", token, value); + } + else { + daemon_local->UDPConnectionSetup = MULTICAST_CONNECTION_DISABLED; + fprintf(stderr, + "Invalid value for UDPConnectionSetup set to default %ld\n", + longval); + } + } + else if (strcmp(token, "UDPMulticastIPAddress") == 0) + { + strncpy(daemon_local->UDPMulticastIPAddress, value, + MULTICASTIP_MAX_SIZE - 1); + } + else if (strcmp(token, "UDPMulticastIPPort") == 0) + { + daemon_local->UDPMulticastIPPort = strtol(value, NULL, 10); + } #endif else { fprintf(stderr, "Unknown option: %s=%s\n", token, value); @@ -1204,6 +1239,20 @@ int dlt_daemon_local_connection_init(DltDaemon *daemon, return DLT_RETURN_ERROR; } +#ifdef UDP_CONNECTION_SUPPORT + + if (daemon_local->UDPConnectionSetup == MULTICAST_CONNECTION_ENABLED) { + if (dlt_daemon_udp_connection_setup(daemon_local) < 0) { + dlt_log(LOG_ERR, "UDP fd creation and register in epoll failed\n"); + return DLT_RETURN_ERROR; + } + else { + dlt_log(LOG_INFO, "UDP fd creation and register in epoll success\n"); + } + } + +#endif + /* create and open unix socket to receive incoming connections from * control application * socket access permission set to srw-rw---- (660) */ diff --git a/src/daemon/dlt-daemon.h b/src/daemon/dlt-daemon.h index 4702b69..2520988 100644 --- a/src/daemon/dlt-daemon.h +++ b/src/daemon/dlt-daemon.h @@ -157,6 +157,11 @@ typedef struct unsigned long RingbufferMaxSize; unsigned long RingbufferStepSize; unsigned long daemonFifoSize; +#ifdef UDP_CONNECTION_SUPPORT + int UDPConnectionSetup; /* enable/disable the UDP connection */ + char UDPMulticastIPAddress[MULTICASTIP_MAX_SIZE]; /* multicast ip addres */ + int UDPMulticastIPPort; /* multicast port */ +#endif } DltDaemonLocal; typedef struct diff --git a/src/daemon/dlt.conf b/src/daemon/dlt.conf index 5d61ade..47e9b6d 100644 --- a/src/daemon/dlt.conf +++ b/src/daemon/dlt.conf @@ -183,3 +183,15 @@ ControlSocketPath = /tmp/dlt-ctrl.sock # Maximal used memory for Logstorage Cache in KB (Default: 30000 KB) # OfflineLogstorageCacheSize = 30000 + +############################################################################## +# UDP Multicast Configuration # +############################################################################## +# Enable UDP connection support for daemon(Control Message/Multicast is enabled) +UDPConnectionSetup = 1 + +# UDP multicast address(default:225.0.0.37) +UDPMulticastIPAddress = 225.0.0.37 + +# UDP multicast port(default:3491) +UDPMulticastIPPort = 3491 diff --git a/src/daemon/dlt_daemon_client.c b/src/daemon/dlt_daemon_client.c index 0d626d7..5fe0215 100644 --- a/src/daemon/dlt_daemon_client.c +++ b/src/daemon/dlt_daemon_client.c @@ -81,6 +81,10 @@ static inline int8_t getStatus(uint8_t request_log, int context_log) return (request_log <= context_log) ? request_log : context_log; } +#ifdef UDP_CONNECTION_SUPPORT +# include "dlt_daemon_udp_socket.h" +#endif + /** @brief Sends up to 2 messages to all the clients. * * Runs through the client list and sends the messages to them. If the message @@ -284,6 +288,17 @@ int dlt_daemon_client_send(int sock, /* send messages to daemon socket */ if ((daemon->mode == DLT_USER_MODE_EXTERNAL) || (daemon->mode == DLT_USER_MODE_BOTH)) { +#ifdef UDP_CONNECTION_SUPPORT + + if (daemon_local->UDPConnectionSetup == MULTICAST_CONNECTION_ENABLED) + dlt_daemon_udp_dltmsg_multicast(data1, + size1, + data2, + size2, + verbose); + +#endif + if ((sock == DLT_DAEMON_SEND_FORCE) || (daemon->state == DLT_DAEMON_STATE_SEND_DIRECT)) { sent = dlt_daemon_client_send_all_multiple(daemon, daemon_local, diff --git a/src/daemon/dlt_daemon_common.h b/src/daemon/dlt_daemon_common.h index 83ac640..5e1bb1b 100644 --- a/src/daemon/dlt_daemon_common.h +++ b/src/daemon/dlt_daemon_common.h @@ -104,6 +104,15 @@ extern "C" { #define DLT_DAEMON_SEM_FREE() { sem_post(&dlt_daemon_mutex); } extern sem_t dlt_daemon_mutex; +/* UDPMulticart Default IP and Port */ +# ifdef UDP_CONNECTION_SUPPORT + # define MULTICASTIPADDRESS "225.0.0.37" + # define MULTICASTIPPORT 3491 + # define MULTICASTIP_MAX_SIZE 256 + # define MULTICAST_CONNECTION_DISABLED 0 + # define MULTICAST_CONNECTION_ENABLED 1 +# endif + /** * Definitions of DLT daemon logging states */ diff --git a/src/daemon/udp_connection/dlt_daemon_udp_common_socket.h b/src/daemon/udp_connection/dlt_daemon_udp_common_socket.h new file mode 100644 index 0000000..1299790 --- /dev/null +++ b/src/daemon/udp_connection/dlt_daemon_udp_common_socket.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2019 LG Electronics Inc. + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of GENIVI Project DLT - Diagnostic Log and Trace. + * If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * For further information see http://www.genivi.org/. + */ + +/*! + * \author + * Guruprasad KN + * Sachin Sudhakar Shetty + * Sunil Kovila Sampath + * + * \Copyright (c) 2019 LG Electronics Inc. + * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. + * + * \file dlt_daemon_udp_common_socket.h + */ + +#ifndef DLT_DAEMON_UDP_COMMON_SOCKET_H +#define DLT_DAEMON_UDP_COMMON_SOCKET_H + +#include /* for sockaddr_in and inet_addr() */ +#include +#include +#include +#include +#include /* for atoi() and exit() */ +#include /* for memset() */ +#include +#include /* for socket(), connect(), (), and recv() */ +#include +#include +#include /* for close() */ + +#include "dlt_common.h" +#include "dlt-daemon.h" +#include "dlt_daemon_common_cfg.h" +#include "dlt_daemon_client.h" +#include "dlt_daemon_connection.h" +#include "dlt_daemon_udp_socket.h" +#include "dlt_types.h" + +/* #define variables */ +#define ADDRESS_VALID 1 +#define ADDRESS_INVALID 0 +#define SOCKPORT_MAX_LEN 6 /* port range 0-65535 */ +#define SYSTEM_CALL_ERROR -1 +#define ZERO_BYTE_RECIEVED 0 +#define ONE_BYTE_RECIEVED 0 + +typedef struct sockaddr_storage CLIENT_ADDR_STRUCT; +typedef socklen_t CLIENT_ADDR_STRUCT_SIZE; + +/* udp strutures */ +typedef struct +{ + CLIENT_ADDR_STRUCT clientaddr; + CLIENT_ADDR_STRUCT_SIZE clientaddr_size; + int isvalidflag; +} DltDaemonClientSockInfo; + +/* Function prototype declaration */ +void dlt_daemon_udp_init_clientstruct(DltDaemonClientSockInfo *clientinfo_struct); +DltReturnValue dlt_daemon_udp_socket_open(int *sock, unsigned int servPort); +void dlt_daemon_udp_setmulticast_addr(DltDaemonLocal *daemon_local); + +#endif /* DLT_DAEMON_UDP_COMMON_SOCKET_H */ + diff --git a/src/daemon/udp_connection/dlt_daemon_udp_socket.c b/src/daemon/udp_connection/dlt_daemon_udp_socket.c new file mode 100644 index 0000000..ac99d4d --- /dev/null +++ b/src/daemon/udp_connection/dlt_daemon_udp_socket.c @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2019 LG Electronics Inc. + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of GENIVI Project DLT - Diagnostic Log and Trace. + * If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * For further information see http://www.genivi.org/. + */ + +/*! + * \author + * Guruprasad KN + * Sachin Sudhakar Shetty + * Sunil Kovila Sampath + * + * \Copyright (c) 2019 LG Electronics Inc. + * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. + * + * \file dlt_daemon_udp_socket.c + */ + +#include "dlt_daemon_udp_common_socket.h" + +static void dlt_daemon_udp_clientmsg_send(DltDaemonClientSockInfo *clientinfo, + void *data1, int size1, void *data2, int size2, int verbose); +static int g_udp_sock_fd = -1; +static DltDaemonClientSockInfo g_udpmulticast_addr; + +/* ************************************************************************** */ +/* Function : dlt_daemon_udp_init_clientstruct */ +/* In Param : UDP client_info struct to be initilzed */ +/* Out Param : NIL */ +/* Description: client struct to be initilized to copy control/connect/disconnect */ +/* client addr */ +/* ************************************************************************** */ +void dlt_daemon_udp_init_clientstruct(DltDaemonClientSockInfo *clientinfo_struct) +{ + if (clientinfo_struct == NULL) { + dlt_vlog(LOG_ERR, "%s: NULL arg\n", __func__); + return; + } + + memset(&clientinfo_struct->clientaddr, 0x00, sizeof(clientinfo_struct->clientaddr)); + clientinfo_struct->clientaddr_size = sizeof(clientinfo_struct->clientaddr); + clientinfo_struct->isvalidflag = ADDRESS_INVALID; /* info is invalid */ + dlt_vlog(LOG_DEBUG, "%s: client addr struct init success \n", __func__); + dlt_log(LOG_INFO, "dlt_daemon_udp_init_clientstruct: client addr struct init success \n"); +} + + +/* ************************************************************************** */ +/* Function : dlt_daemon_udp_setmulticast_addr */ +/* In Param : NIL */ +/* Out Param : NIL */ +/* Description: set the multicast addr to global variables */ +/* ************************************************************************** */ +void dlt_daemon_udp_setmulticast_addr(DltDaemonLocal *daemon_local) +{ + if (daemon_local == NULL) { + dlt_vlog(LOG_ERR, "%s: NULL arg\n", __func__); + return; + } + + dlt_daemon_udp_init_clientstruct(&g_udpmulticast_addr); + + struct sockaddr_in clientaddr; + clientaddr.sin_family = AF_INET; + inet_pton(AF_INET, daemon_local->UDPMulticastIPAddress, &clientaddr.sin_addr); + clientaddr.sin_port = htons(daemon_local->UDPMulticastIPPort); + memcpy(&g_udpmulticast_addr.clientaddr, &clientaddr, sizeof(struct sockaddr_in)); + g_udpmulticast_addr.clientaddr_size = sizeof(g_udpmulticast_addr.clientaddr); + g_udpmulticast_addr.isvalidflag = ADDRESS_VALID; +} + +/* ************************************************************************** */ +/* Function : dlt_daemon_udp_connection_setup */ +/* In Param : contains daemon param values used globally */ +/* Out Param : status of udp connection setup and fd registration */ +/* Description: DataGram socket fd connection is setup */ +/* fd is registered with the epoll */ +/* ************************************************************************** */ +DltReturnValue dlt_daemon_udp_connection_setup(DltDaemonLocal *daemon_local) +{ + int fd = DLT_FD_INIT; + DltReturnValue ret_val = DLT_RETURN_WRONG_PARAMETER; + + if (daemon_local == NULL) + return ret_val; + + if ((ret_val = dlt_daemon_udp_socket_open(&fd, daemon_local->flags.port)) != DLT_RETURN_OK) { + dlt_log(LOG_ERR, "Could not initialize udp socket.\n"); + } + else { + /* assign to global udp fd */ + g_udp_sock_fd = fd; + /* set global multicast addr */ + dlt_daemon_udp_setmulticast_addr(daemon_local); + dlt_log(LOG_DEBUG, "initialize udp socket success\n"); + } + + return ret_val; +} + +/* ************************************************************************** */ +/* Function : dlt_daemon_udp_socket_open */ +/* In Param : contains udp port number */ +/* Out Param : status of udp connection setup */ +/* Description: This funtion is used to setup DGRAM connection */ +/* does socket()->bind() on udp port */ +/* ************************************************************************** */ +DltReturnValue dlt_daemon_udp_socket_open(int *sock, unsigned int servPort) +{ + int enable_reuse_addr = 1; + int sockbuffer = DLT_DAEMON_RCVBUFSIZESOCK; + char portnumbuffer[SOCKPORT_MAX_LEN] = { 0 }; + struct addrinfo hints; + struct addrinfo *servinfo = NULL; + struct addrinfo *addrinfo_iterator = NULL; + int getaddrinfo_errorcode = -1; + + if (sock == NULL) + return DLT_RETURN_WRONG_PARAMETER; + + memset(&hints, 0, sizeof hints); +#ifdef DLT_USE_IPv6 + hints.ai_family = AF_INET6; /* force IPv6 - will still work with IPv4 */ +#else + hints.ai_family = AF_INET; +#endif + hints.ai_socktype = SOCK_DGRAM;/* UDP Connection */ + hints.ai_flags = AI_PASSIVE; /* use my IP address */ + + snprintf(portnumbuffer, SOCKPORT_MAX_LEN, "%d", servPort); + + if ((getaddrinfo_errorcode = getaddrinfo(NULL, portnumbuffer, &hints, &servinfo)) != 0) { + dlt_vlog(LOG_WARNING, "[%s:%d] getaddrinfo: %s\n", __func__, __LINE__, + gai_strerror(getaddrinfo_errorcode)); + return DLT_RETURN_ERROR; + } + + for (addrinfo_iterator = servinfo; addrinfo_iterator != NULL; addrinfo_iterator = addrinfo_iterator->ai_next) { + if ((*sock = socket(addrinfo_iterator->ai_family, addrinfo_iterator->ai_socktype, + addrinfo_iterator->ai_protocol)) == SYSTEM_CALL_ERROR) { + dlt_log(LOG_WARNING, "socket() error\n"); + continue; + } + + dlt_vlog(LOG_INFO, + "[%s:%d] Socket created - socket_family:%i socket_type:%i, protocol:%i\n", + __func__, __LINE__, addrinfo_iterator->ai_family, + addrinfo_iterator->ai_socktype, addrinfo_iterator->ai_protocol); + + if (setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, &enable_reuse_addr, sizeof(enable_reuse_addr)) + == SYSTEM_CALL_ERROR) { + dlt_vlog(LOG_WARNING, "[%s:%d] Setsockopt error %s\n", __func__, __LINE__, + strerror(errno)); + close(*sock); + continue; + } + + if (setsockopt(*sock, SOL_SOCKET, SO_RCVBUF, &sockbuffer, sizeof(sockbuffer)) + == SYSTEM_CALL_ERROR) { + dlt_vlog(LOG_WARNING, "[%s:%d] Setsockopt error %s\n", __func__, __LINE__, + strerror(errno)); + close(*sock); + continue; + } + + if (bind(*sock, addrinfo_iterator->ai_addr, addrinfo_iterator->ai_addrlen) + == SYSTEM_CALL_ERROR) { + close(*sock); + dlt_log(LOG_WARNING, "bind() error\n"); + continue; + } + + break; + } + + if (addrinfo_iterator == NULL) { + dlt_log(LOG_WARNING, "failed to bind socket\n"); + return DLT_RETURN_ERROR; + } + + freeaddrinfo(servinfo); + + return DLT_RETURN_OK; /* OK */ +} + +/* ************************************************************************** */ +/* Function : dlt_daemon_udp_dltmsg_multicast */ +/* In Param : data bytes in dlt format */ +/* Out Param : NIL */ +/* Description: multicast UDP dlt-message packets to dlt-client */ +/* ************************************************************************** */ +void dlt_daemon_udp_dltmsg_multicast(void *data1, int size1, + void *data2, int size2, + int verbose) +{ + PRINT_FUNCTION_VERBOSE(verbose); + + /* + * When UDP Buffer is implemented then data2 would be expected to be NULL + * as the data comes from buffer directly. In that case data2 should + * not be checked for NULL + */ + if ((data1 == NULL) || (data2 == NULL)) { + dlt_vlog(LOG_ERR, "%s: NULL arg\n", __func__); + return; + } + + dlt_daemon_udp_clientmsg_send(&g_udpmulticast_addr, data1, size1, + data2, size2, verbose); +} + +/* ************************************************************************** */ +/* Function : dlt_daemon_udp_clientmsg_send */ +/* In Param : data bytes & respective size in dlt format */ +/* Out Param : NIL */ +/* Description: common interface to send data via UDP protocol */ +/* ************************************************************************** */ +void dlt_daemon_udp_clientmsg_send(DltDaemonClientSockInfo *clientinfo, + void *data1, int size1, void *data2, int size2, int verbose) +{ + PRINT_FUNCTION_VERBOSE(verbose); + + if ((clientinfo->isvalidflag == ADDRESS_VALID) && + (size1 > 0) && (size2 > 0)) { + void *data = (void *)calloc(size1 + size2, sizeof(char)); + + if (data == NULL) { + dlt_vlog(LOG_ERR, "%s: calloc failure\n", __func__); + return; + } + + memcpy(data, data1, size1); + memcpy(data + size1, data2, size2); + + if (sendto(g_udp_sock_fd, data, size1 + size2, 0, (struct sockaddr *)&clientinfo->clientaddr, + clientinfo->clientaddr_size) < 0) + dlt_vlog(LOG_ERR, "%s: Send UDP Packet Data failed\n", __func__); + + free(data); + data = NULL; + + } + else { + if (clientinfo->isvalidflag != ADDRESS_VALID) + dlt_vlog(LOG_ERR, "%s: clientinfo->isvalidflag != ADDRESS_VALID %d\n", __func__, clientinfo->isvalidflag); + + if (size1 <= 0) + dlt_vlog(LOG_ERR, "%s: size1 <= 0\n", __func__); + + if (size2 <= 0) + dlt_vlog(LOG_ERR, "%s: size2 <= 0\n", __func__); + } +} diff --git a/src/daemon/udp_connection/dlt_daemon_udp_socket.h b/src/daemon/udp_connection/dlt_daemon_udp_socket.h new file mode 100644 index 0000000..96d33aa --- /dev/null +++ b/src/daemon/udp_connection/dlt_daemon_udp_socket.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019 LG Electronics Inc. + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of GENIVI Project DLT - Diagnostic Log and Trace. + * If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * For further information see http://www.genivi.org/. + */ + +/*! + * \author + * Guruprasad KN + * Sachin Sudhakar Shetty + * Sunil Kovila Sampath + * + * \Copyright (c) 2019 LG Electronics Inc. + * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. + * + * \file dlt_daemon_udp_socket.h + */ + +#ifndef DLT_DAEMON_UDP_SOCKET_H +#define DLT_DAEMON_UDP_SOCKET_H + +#include "dlt-daemon.h" + +DltReturnValue dlt_daemon_udp_connection_setup(DltDaemonLocal *daemon_local); +void dlt_daemon_udp_dltmsg_multicast(void *data1, int size1, void *data2, int size2, + int verbose); +#endif /* DLT_DAEMON_UDP_SOCKET_H */ diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt index 8e6f390..93f76a8 100644 --- a/src/examples/CMakeLists.txt +++ b/src/examples/CMakeLists.txt @@ -33,7 +33,18 @@ add_executable( dlt-example-filetransfer ${dlt_example_filetransfer_SRCS}) target_link_libraries(dlt-example-filetransfer dlt ) set_target_properties(dlt-example-filetransfer PROPERTIES LINKER_LANGUAGE C) +if(WITH_UDP_CONNECTION) + set(dlt-example-multicast-clientmsg-view_SRCS dlt-example-multicast-clientmsg-view.c) + add_executable(dlt-example-multicast-clientmsg-view ${dlt-example-multicast-clientmsg-view_SRCS} ${dlt_most_SRCS}) + target_link_libraries(dlt-example-multicast-clientmsg-view dlt ) + set_target_properties(dlt-example-multicast-clientmsg-view PROPERTIES LINKER_LANGUAGE C) + + install(TARGETS dlt-example-multicast-clientmsg-view + RUNTIME DESTINATION bin + COMPONENT base) + +endif(WITH_UDP_CONNECTION) + install(TARGETS dlt-example-user dlt-example-user-func dlt-example-user-common-api dlt-example-filetransfer RUNTIME DESTINATION bin COMPONENT base) - diff --git a/src/examples/dlt-example-multicast-clientmsg-view.c b/src/examples/dlt-example-multicast-clientmsg-view.c new file mode 100644 index 0000000..aa3d5af --- /dev/null +++ b/src/examples/dlt-example-multicast-clientmsg-view.c @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2019 LG Electronics Inc. + * SPDX-License-Identifier: MPL-2.0 + * + * This file is part of GENIVI Project DLT - Diagnostic Log and Trace. + * If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * For further information see http://www.genivi.org/. + */ + +/*! + * \author + * Guruprasad KN + * Sachin Sudhakar Shetty + * Sunil Kovila Sampath + * + * \Copyright (c) 2019 LG Electronics Inc. + * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. + * + * \file dlt-example-multicast-clientmsg-view.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include /* for isprint() */ +#include /* for atoi() */ +#include /* for S_IRUSR, S_IWUSR, S_IRGRP, S_IROTH */ +#include /* for open() */ +#include /* for writev() */ +#include +#include +#include +#include +#include /* for PATH_MAX */ +#include + +#include "dlt_client.h" +#include "dlt_client_cfg.h" + +#define DLT_RECEIVE_TEXTBUFSIZE 10024 + +#define HELLO_PORT 3491 +#define HELLO_GROUP "225.0.0.37" + +struct clientinfostruct +{ + int fd; + struct sockaddr_in addr; + socklen_t addlen; + DltReceiver receiver; +}; + +int dlt_receiver_receive_socket_udp(struct clientinfostruct *clientinfo, DltReceiver *receiver) +{ + if ((receiver == NULL) || (clientinfo == NULL)) { + printf("NULL receiver or clientinfo in dlt_receiver_receive_socket_udp\n"); + return -1; + } + + if (receiver->buffer == NULL) { + printf("NULL receiver->buffer in dlt_receiver_receive_socket_udp\n"); + return -1; + } + + receiver->buf = (char *)receiver->buffer; + receiver->lastBytesRcvd = receiver->bytesRcvd; + + /* wait for data from socket */ + unsigned int addrlen = sizeof(clientinfo->addr); + + if ((receiver->bytesRcvd = recvfrom(clientinfo->fd, + receiver->buf + receiver->lastBytesRcvd, + receiver->buffersize - receiver->lastBytesRcvd, + 0, + (struct sockaddr *)&(clientinfo->addr), &addrlen)) + <= 0) { + printf("Error\n"); + perror("recvfrom"); + receiver->bytesRcvd = 0; + return receiver->bytesRcvd; + } /* if */ + + receiver->totalBytesRcvd += receiver->bytesRcvd; + receiver->bytesRcvd += receiver->lastBytesRcvd; + + return receiver->bytesRcvd; +} + +int dlt_receive_message_callback_udp(DltMessage *message) +{ + static char text[DLT_RECEIVE_TEXTBUFSIZE]; + + if ((message == NULL)) { + printf("NULL message in dlt_receive_message_callback_udp\n"); + return -1; + } + + /* prepare storage header */ + if (DLT_IS_HTYP_WEID(message->standardheader->htyp)) + dlt_set_storageheader(message->storageheader, message->headerextra.ecu); + else + dlt_set_storageheader(message->storageheader, "ECU1"); + + dlt_message_header(message, text, DLT_RECEIVE_TEXTBUFSIZE, 0); + + printf("%s ", text); + + dlt_message_payload(message, text, DLT_RECEIVE_TEXTBUFSIZE, DLT_OUTPUT_ASCII, 0); + + printf("[%s]\n", text); + + return 0; +} + + +int main() +{ + struct clientinfostruct clientinfo; + struct ip_mreq mreq; + + u_int yes = 1; + + /* create what looks like an ordinary UDP socket */ + if ((clientinfo.fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket"); + exit(1); + } + + /* allow multiple sockets to use the same PORT number */ + if (setsockopt(clientinfo.fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { + perror("Reusing ADDR failed"); + exit(1); + } + + /* set up destination address */ + memset(&clientinfo.addr, 0, sizeof(clientinfo.addr)); + clientinfo.addr.sin_family = AF_INET; + clientinfo.addr.sin_addr.s_addr = htonl(INADDR_ANY); /* N.B.: differs from sender */ + clientinfo.addr.sin_port = htons(HELLO_PORT); + + /* bind to receive address */ + if (bind(clientinfo.fd, (struct sockaddr *)&clientinfo.addr, sizeof(clientinfo.addr)) < 0) { + perror("bind"); + exit(1); + } + + /* use setsockopt() to request that the kernel join a multicast group */ + mreq.imr_multiaddr.s_addr = inet_addr(HELLO_GROUP); + mreq.imr_interface.s_addr = htonl(INADDR_ANY); + + if (setsockopt(clientinfo.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { + perror("setsockopt"); + exit(1); + } + + DltMessage msg; + + if (dlt_message_init(&msg, 0) == DLT_RETURN_ERROR) + return DLT_RETURN_ERROR; + + if (dlt_receiver_init(&(clientinfo.receiver), clientinfo.fd, + DLT_RECEIVE_BUFSIZE) != DLT_RETURN_OK) + return DLT_RETURN_ERROR; + + printf("Waiting for message on ip %s port : %d\n", HELLO_GROUP, HELLO_PORT); + + while (1) { + /* wait for data from socket */ + dlt_receiver_receive_socket_udp(&clientinfo, &(clientinfo.receiver)); + + while (dlt_message_read(&msg, (unsigned char *)(clientinfo.receiver.buf), + clientinfo.receiver.bytesRcvd, 0, 0) == DLT_MESSAGE_ERROR_OK) { + dlt_receive_message_callback_udp(&msg); + + if (dlt_receiver_remove(&(clientinfo.receiver), + msg.headersize + msg.datasize - sizeof(DltStorageHeader)) + == DLT_RETURN_ERROR) { + /* Return value ignored */ + dlt_message_free(&msg, 0); + return DLT_RETURN_ERROR; + } + } + + if (dlt_receiver_move_to_begin(&(clientinfo.receiver)) == DLT_RETURN_ERROR) { + /* Return value ignored */ + dlt_message_free(&msg, 0); + return DLT_RETURN_ERROR; + } + } +} + -- cgit v1.2.1