summaryrefslogtreecommitdiff
path: root/src/gateway
diff options
context:
space:
mode:
Diffstat (limited to 'src/gateway')
-rw-r--r--src/gateway/CMakeLists.txt22
-rw-r--r--src/gateway/dlt_gateway.c1052
-rw-r--r--src/gateway/dlt_gateway.conf9
-rw-r--r--src/gateway/dlt_gateway.h169
-rw-r--r--src/gateway/dlt_gateway_types.h106
5 files changed, 1358 insertions, 0 deletions
diff --git a/src/gateway/CMakeLists.txt b/src/gateway/CMakeLists.txt
new file mode 100644
index 0000000..a34b44e
--- /dev/null
+++ b/src/gateway/CMakeLists.txt
@@ -0,0 +1,22 @@
+#######
+# @licence make begin@
+# SPDX license identifier: MPL-2.0
+#
+# Copyright (C) 2015, Advanced Driver Information Technology
+# This code is developed by Advanced Driver Information Technology.
+# Copyright of Advanced Driver Information Technology, Bosch and DENSO.
+#
+# This file is part of GENIVI Project DLT - Diagnostic Log and Trace.
+#
+# This Source Code Form is subject to the terms of the
+# Mozilla Public License (MPL), 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/.
+#
+# For further information see http://www.genivi.org/.
+# @licence end@
+#######
+
+INSTALL(FILES dlt_gateway.conf
+ DESTINATION ${CONFIGURATION_FILES_DIR}
+ COMPONENT base)
diff --git a/src/gateway/dlt_gateway.c b/src/gateway/dlt_gateway.c
new file mode 100644
index 0000000..a7d7d39
--- /dev/null
+++ b/src/gateway/dlt_gateway.c
@@ -0,0 +1,1052 @@
+/*
+ * @licence app begin@
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
+ *
+ * This file is part of GENIVI Project DLT - Diagnostic Log and Trace.
+ *
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License (MPL), 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/.
+ *
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+/*!
+ * \author
+ * Christoph Lipka <clipka@jp.adit-jv.com>
+ *
+ * \copyright Copyright © 2015 Advanced Driver Information Technology. \n
+ * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
+ *
+ * \file dlt_gateway.c
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <limits.h>
+#include <errno.h>
+#include "dlt_gateway.h"
+#include "dlt_config_file_parser.h"
+#include "dlt_common.h"
+#include "dlt-daemon_cfg.h"
+#include "dlt_daemon_event_handler.h"
+#include "dlt_daemon_connection.h"
+#include "dlt_daemon_client.h"
+
+/**
+ * Expected entries for a passive node configuration
+ * Caution: after changing entries here,
+ * dlt_gateway_check_params need to be updated as well
+ * */
+char *configuration_entries [] =
+{
+ "IPaddress",
+ "Port",
+ "EcuID",
+ "Connect",
+ "Timeout"
+};
+
+#define DLT_GATEWAY_NUM_PROPERTIES_MAX 5
+
+/**
+ * Check if given string is a valid IP address
+ *
+ * @param ip IP address
+ * @param value string to be tested
+ * @return 0 on success, -1 otherwise
+ */
+int dlt_gateway_check_ip(char **ip, char *value)
+{
+ struct sockaddr_in sa;
+ int ret = -1;
+
+ if (ip == NULL || value == NULL)
+ {
+ return -1;
+ }
+
+ ret = inet_pton(AF_INET, value, &(sa.sin_addr));
+
+ /* valid IP address */
+ if (ret != 0)
+ {
+ *ip = strdup(value);
+
+ if (*ip == NULL)
+ {
+ dlt_log(LOG_ERR, "Cannot copy passive node IP address string\n");
+ return -1;
+ }
+
+ return 0;
+ }
+ else
+ {
+ dlt_log(LOG_ERR, "IP address is not valid\n");
+ }
+
+ return -1;
+}
+
+/**
+ * Check socket domain
+ *
+ * This function is currently not used; only AF_INET is supported.
+ *
+ * @param domain socket domain
+ * @param value string to be tested
+ * @return 0 on success, -1 otherwise
+ */
+int dlt_gateway_check_domain(int *domain, char *value)
+{
+ int ret = -1;
+
+ if (domain == NULL || value == NULL)
+ {
+ return -1;
+ }
+
+ ret = strncmp(value, "AF_INET", strlen("AF_INET"));
+
+ if (ret == 0)
+ {
+ *domain = AF_INET;
+ return 0;
+ }
+ else
+ {
+ dlt_log(LOG_ERR, "Only socket domain AF_INET supported\n");
+ }
+
+ return -1;
+}
+
+/**
+ * Check socket type
+ *
+ * This function is currently not used; only SOCK_STREAM is supported.
+ *
+ * @param type socket type
+ * @param value string to be tested
+ * @return 0 on success, -1 otherwise
+ */
+int dlt_gateway_check_type(int *type, char *value)
+{
+ int ret = -1;
+
+ if (type == NULL || value == NULL)
+ {
+ return -1;
+ }
+
+ ret = strncmp(value, "SOCK_STREAM", strlen("SOCK_STREAM"));
+
+ if (ret == 0)
+ {
+ *type = SOCK_STREAM;
+ return 0;
+ }
+ else
+ {
+ dlt_log(LOG_ERR, "Only socket type SOCK_STREAM is supported\n");
+ }
+
+ return -1;
+}
+
+/**
+ * Check socket protocol
+ *
+ * This function is currently not used; only IPPROTO_TCP is supported.
+ *
+ * @param protocol socket protocol
+ * @param value string to be tested
+ * @return 0 on success, -1 otherwise
+ */
+int dlt_gateway_check_protocol(int *protocol, char *value)
+{
+ if (protocol == NULL || value == NULL)
+ {
+ return -1;
+ }
+
+ if (strncmp(value, "IPPROTO_TCP", strlen("IPPROTO_TCP")) == 0)
+ {
+ *protocol = IPPROTO_TCP;
+ return 0;
+ }
+ else
+ {
+ dlt_log(LOG_ERR, "Only protocol IPPROTO_TCP is supported\n");
+ }
+
+ return -1;
+}
+
+/**
+ * Check port number
+ *
+ * @param port port number
+ * @param value string to be tested
+ * @return 0 on success, -1 otherwise
+ */
+int dlt_gateway_check_port(int *port, char *value)
+{
+ int tmp = -1;
+
+ if (port == NULL || value == NULL)
+ {
+ return -1;
+ }
+
+ tmp = (int) strtol(value, NULL, 10);
+
+ /* port ranges for unprivileged applications */
+ if (tmp > IPPORT_RESERVED && tmp <= USHRT_MAX)
+ {
+ *port = tmp;
+ return 0;
+ }
+ else
+ {
+ dlt_log(LOG_ERR, "Port number is invalid\n");
+ }
+
+ return -1;
+}
+
+/**
+ * Check ECU name
+ *
+ * @param ecuid ecu name
+ * @param value string to be used as ECU identifier
+ * @return 0 on success, -1 otherwise
+ */
+int dlt_gateway_check_ecu(char **ecuid, char *value)
+{
+ if (ecuid == NULL || value == NULL)
+ {
+ return -1;
+ }
+
+ *ecuid = strdup(value);
+
+ if (*ecuid == NULL)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Check connection trigger
+ *
+ * @param trigger connection setup trigger
+ * @param value string to be tested
+ * @return 0 on success, -1 otherwise
+ */
+int dlt_gateway_check_connect_trigger(int *trigger, char *value)
+{
+ if (trigger == NULL || value == NULL)
+ {
+ return -1;
+ }
+
+ if (strncasecmp(value, "OnStartup", strlen("OnStartup")) == 0)
+ {
+ *trigger = DLT_GATEWAY_ON_STARTUP;
+ }
+ else if (strncasecmp(value, "OnDemand", strlen("OnDemand")) == 0)
+ {
+ *trigger = DLT_GATEWAY_ON_DEMAND;
+ }
+ else
+ {
+ dlt_log(LOG_ERR, "Wrong connection trigger state given.\n");
+ *trigger = DLT_GATEWAY_UNDEFINED;
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Check connection timeout value
+ *
+ * @param timeout connection timeout
+ * @param value string to be tested
+ * @return 0 on success, -1 otherwise
+ */
+int dlt_gateway_check_timeout(int *timeout, char *value)
+{
+ if (timeout == NULL || value == NULL)
+ {
+ return -1;
+ }
+
+ *timeout = (int) strtol(value, NULL, 10);
+
+ if (*timeout > 0)
+ {
+ return 0;
+ }
+
+ return -1;
+}
+
+/**
+ * Check if gateway connection configuration parameter is valid.
+ *
+ * @param g DltGateway
+ * @param c DltGatewayConnection
+ * @param key DltGatwayConnection property
+ * @param value specified property value from configuration file
+ * @return 0 on success, -1 otherwise
+ */
+int dlt_gateway_check_param(DltGateway *gateway,
+ DltGatewayConnection *con,
+ char *key,
+ char *value)
+{
+ if (gateway == NULL || con == NULL || key == NULL || value == NULL)
+ {
+ return -1;
+ }
+
+ if (strncmp(key, "IPaddress", sizeof("IPaddress")) == 0)
+ {
+ return dlt_gateway_check_ip(&con->ip_address, value);
+ }
+ else if (strncmp(key, "SockDomain", sizeof("SockDomain")) == 0)
+ {
+ return dlt_gateway_check_domain(&(con->sock_domain), value);
+ }
+ else if (strncmp(key, "SockType", sizeof("SockType")) == 0)
+ {
+ return dlt_gateway_check_type(&(con->sock_type), value);
+ }
+ else if (strncmp(key, "SockProtocol", sizeof("SockProtocol")) == 0)
+ {
+ return dlt_gateway_check_protocol(&(con->sock_protocol), value);
+ }
+ else if (strncmp(key, "Port", sizeof("Port")) == 0)
+ {
+ return dlt_gateway_check_port(&(con->port), value);
+ }
+ else if (strncmp(key, "EcuID", sizeof("EcuID")) == 0)
+ {
+ return dlt_gateway_check_ecu(&con->ecuid,value);
+ }
+ else if (strncmp(key, "Connect", sizeof("Connect")) == 0)
+ {
+ return dlt_gateway_check_connect_trigger(&(con->trigger), value);
+ }
+ else if (strncmp(key, "Timeout", sizeof("Timeout")) == 0)
+ {
+ return dlt_gateway_check_timeout(&(con->timeout), value);
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+/**
+ * Store gateway connection in internal data structure
+ *
+ * @param g DltGatway
+ * @param tmp DltGatewayConnection
+ * @param verbose verbose flag
+ * @return 0 on success, -1 otherwise
+ */
+int dlt_gateway_store_connection(DltGateway *gateway,
+ DltGatewayConnection *tmp,
+ int verbose)
+{
+ int i = 0;
+ int ret = 0;
+
+ PRINT_FUNCTION_VERBOSE(verbose);
+
+ if (gateway == NULL || tmp == NULL)
+ {
+ return -1;
+ }
+
+ /* find next free entry in connection array */
+ while (i < gateway->num_connections)
+ {
+ if (gateway->connections[i].status == DLT_GATEWAY_UNINITIALIZED)
+ {
+ break;
+ }
+
+ i++;
+ }
+
+ if (&gateway->connections[i] == NULL)
+ {
+ return -1;
+ }
+
+ /* store values */
+ gateway->connections[i].ip_address = strdup(tmp->ip_address);
+ gateway->connections[i].ecuid = strdup(tmp->ecuid);
+ gateway->connections[i].sock_domain = tmp->sock_domain;
+ gateway->connections[i].sock_type = tmp->sock_type;
+ gateway->connections[i].sock_protocol = tmp->sock_protocol;
+ gateway->connections[i].port = tmp->port;
+ gateway->connections[i].trigger = tmp->trigger;
+ gateway->connections[i].timeout = tmp->timeout;
+ gateway->connections[i].handle = 0;
+ gateway->connections[i].status = DLT_GATEWAY_INITIALIZED;
+
+ if (dlt_client_init(&gateway->connections[i].client, verbose) != 0)
+ {
+ free(gateway->connections[i].ip_address);
+ free(gateway->connections[i].ecuid);
+ dlt_log(LOG_CRIT, "dlt_client_init() failed for gateway connection\n");
+ return -1;
+ }
+ dlt_receiver_init(&gateway->connections[i].client.receiver,
+ gateway->connections[i].client.sock,
+ DLT_DAEMON_RCVBUFSIZESOCK);
+ /* setup DltClient Structure */
+ gateway->connections[i].client.servIP =
+ strdup(gateway->connections[i].ip_address);
+ // TODO: modify DltClient structure to make port configurable
+ // g->connections[i].client.servPort = g->connections[i].port;
+
+ if (ret != 0)
+ {
+ free(gateway->connections[i].ip_address);
+ free(gateway->connections[i].ecuid);
+ dlt_log(LOG_ERR, "Gateway: DltClient initialization failed\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Read configuration file and initialize connection data structures
+ *
+ * @param g DltGateway
+ * @param verbose verbose flag
+ * @return 0 on success, -1 otherwise
+ */
+int dlt_gateway_configure(DltGateway *gateway, int verbose)
+{
+ int ret = 0;
+ int i = 0;
+ DltGatewayConnection tmp;
+ DltConfigFile *file = NULL;
+
+ PRINT_FUNCTION_VERBOSE(verbose);
+
+ if (gateway == NULL)
+ {
+ return -1;
+ }
+
+ memset(&tmp, 0, sizeof(tmp));
+
+ /* read configuration file */
+ file = dlt_config_file_init(DLT_GATEWAY_CONFIG_PATH);
+
+ /* get number of entries and allocate memory to store information */
+ ret = dlt_config_file_get_num_sections(file, &gateway->num_connections);
+
+ if (ret != 0)
+ {
+ dlt_config_file_release(file);
+ dlt_log(LOG_ERR, "Invalid number of sections in configuration file\n");
+ return -1;
+ }
+
+ gateway->connections = calloc(sizeof(DltGatewayConnection),
+ gateway->num_connections);
+
+ if (gateway->connections == NULL)
+ {
+ dlt_config_file_release(file);
+ dlt_log(LOG_CRIT, "Memory allocation for gateway connections failed\n");
+ return -1;
+ }
+
+ for (i = 0; i < gateway->num_connections; i++)
+ {
+ int j = 0;
+ char section[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = {'\0'};
+ char value[DLT_CONFIG_FILE_ENTRY_MAX_LEN] = {'\0'};
+ int is_node_valid = 1; /* 1 - valid, <= 0 invalid */
+
+ ret = dlt_config_file_get_section_name(file, i, section);
+
+ for (j = 0; j < DLT_GATEWAY_NUM_PROPERTIES_MAX; j++)
+ {
+ ret = dlt_config_file_get_value(file,
+ section,
+ configuration_entries[j],
+ value);
+
+ if (ret != 0)
+ {
+ is_node_valid = -1;
+ break;
+ }
+
+ /* check value and store temporary */
+ ret = dlt_gateway_check_param(gateway,
+ &tmp,
+ configuration_entries[j],
+ value);
+
+ if (ret != 0)
+ {
+ char error_str[DLT_DAEMON_TEXTBUFSIZE] = {'\0'};
+ sprintf(error_str,
+ "Configuration %s = %s is invalid\n",
+ configuration_entries[j], value);
+ dlt_log(LOG_ERR, error_str);
+ is_node_valid = -1;
+ break;
+ }
+ }
+
+ if (is_node_valid >= 1)
+ {
+ ret = dlt_gateway_store_connection(gateway, &tmp, verbose);
+
+ if (ret != 0)
+ {
+ dlt_log(LOG_ERR, "Storing gateway connection data failed\n");
+ }
+ }
+
+ /* strdup used inside some get_value function */
+ free(tmp.ecuid);
+ free(tmp.ip_address);
+ }
+
+ dlt_config_file_release(file);
+ return ret;
+}
+
+int dlt_gateway_init(DltDaemonLocal *daemon_local, int verbose)
+{
+ PRINT_FUNCTION_VERBOSE(verbose);
+
+ if (daemon_local == NULL)
+ {
+ return -1;
+ }
+
+ DltGateway *gateway = &daemon_local->pGateway;
+
+ if (gateway != NULL)
+ {
+ if (dlt_gateway_configure(gateway, verbose) != 0)
+ {
+ dlt_log(LOG_ERR, "Gateway initialization failed\n");
+ return -1;
+ }
+ }
+ else
+ {
+ dlt_log(LOG_CRIT, "Pointer to Gateway structure is NULL\n");
+ return -1;
+ }
+
+ /* ignore return value */
+ dlt_gateway_establish_connections(gateway, daemon_local, verbose);
+
+ return 0;
+}
+
+void dlt_gateway_deinit(DltGateway *gateway, int verbose)
+{
+ int i = 0;
+
+ if (gateway == NULL)
+ {
+ return;
+ }
+
+ PRINT_FUNCTION_VERBOSE(verbose);
+
+ for (i = 0; i < gateway->num_connections; i++)
+ {
+ DltGatewayConnection *c = &gateway->connections[i];
+ dlt_client_cleanup(&c->client, verbose);
+ free(c->ip_address);
+ free(c->ecuid);
+ }
+
+ free(gateway->connections);
+ free(gateway);
+}
+
+int dlt_gateway_establish_connections(DltGateway *gateway,
+ DltDaemonLocal *daemon_local,
+ int verbose)
+{
+ int i = 0;
+ int ret = 0;
+
+ PRINT_FUNCTION_VERBOSE(verbose);
+
+ if (gateway == NULL || daemon_local == NULL)
+ {
+ return -1;
+ }
+
+ for (i = 0; i < gateway->num_connections; i++)
+ {
+ DltGatewayConnection *con = &(gateway->connections[i]);
+ if (con == NULL)
+ {
+ dlt_log(LOG_CRIT, "Cannot retrieve gateway connection details\n");
+ return -1;
+ }
+
+ if (con->status != DLT_GATEWAY_CONNECTED &&
+ con->trigger != DLT_GATEWAY_ON_DEMAND &&
+ con->trigger != DLT_GATEWAY_DISABLED)
+ {
+ ret = dlt_client_connect(&con->client, verbose);
+
+ if (ret == 0)
+ {
+ /* connection to passive node established, add to event loop */
+ con->status = DLT_GATEWAY_CONNECTED;
+
+ /* setup dlt connection and add to epoll event loop here */
+ if (dlt_connection_create(daemon_local,
+ &daemon_local->pEvent,
+ con->client.sock,
+ EPOLLIN,
+ DLT_CONNECTION_GATEWAY) != 0)
+ {
+ dlt_log(LOG_ERR, "Gateway connection creation failed\n");
+ return -1;
+ }
+ }
+ else
+ {
+ dlt_log(LOG_DEBUG,
+ "Passive Node is not up. Connection failed.\n");
+
+ con->timeout_cnt++;
+ if (con->timeout_cnt > con->timeout)
+ {
+ con->trigger = DLT_GATEWAY_DISABLED;
+ dlt_log(LOG_WARNING,
+ "Passive Node connection retry timed out. "
+ "Give up.\n");
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+DltReceiver *dlt_gateway_get_connection_receiver(DltGateway *gateway, int fd)
+{
+ int i = 0;
+
+ if (gateway == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0; i < gateway->num_connections; i++)
+ {
+ DltGatewayConnection *c = &gateway->connections[i];
+ if (c->status == DLT_GATEWAY_CONNECTED && c->client.sock == fd)
+ {
+ return &c->client.receiver;
+ }
+ }
+
+ return NULL;
+}
+
+int dlt_gateway_process_passive_node_messages(DltDaemon *daemon,
+ DltDaemonLocal *daemon_local,
+ DltReceiver *receiver,
+ int verbose)
+{
+ int i = 0;
+ DltGateway *gateway = NULL;
+ DltGatewayConnection *con = NULL;
+ DltMessage msg;
+ char local_str[DLT_DAEMON_TEXTBUFSIZE];
+
+ if (daemon == NULL || daemon_local == NULL || receiver == NULL)
+ {
+ return -1;
+ }
+
+ PRINT_FUNCTION_VERBOSE(verbose);
+
+ gateway = &daemon_local->pGateway;
+ if (gateway == NULL)
+ {
+ dlt_log(LOG_ERR, "Gateway structure is NULL\n");
+ return -1;
+ }
+
+ for (i = 0; i < gateway->num_connections; i++)
+ {
+ if (gateway->connections[i].client.sock == receiver->fd)
+ {
+ con = &gateway->connections[i];
+ break;
+ }
+ }
+
+ if (con == NULL)
+ {
+ dlt_log(LOG_ERR, "Cannot associate fd to passive Node connection\n");
+ return -1;
+ }
+
+ /* now the corresponding passive node connection is available */
+ if (dlt_message_init(&msg, verbose) == -1)
+ {
+ dlt_log(LOG_ERR,
+ "Cannot initialize DLT message for passive node forwarding\n");
+ return -1;
+ }
+
+ /* nearly copy and paste of dlt_client_main_loop function */
+ if (dlt_receiver_receive_socket(receiver) <= 0)
+ {
+ /* No more data to be received */
+ if (dlt_message_free(&msg, verbose) < 0)
+ {
+ dlt_log(LOG_ERR, "Cannot free DLT message\n");
+ return -1;
+ }
+
+ con->status = DLT_GATEWAY_DISCONNECTED;
+ if (dlt_event_handler_unregister_connection(&daemon_local->pEvent,
+ daemon_local,
+ receiver->fd,
+ DLT_CONNECTION_GATEWAY) != 0)
+ {
+ dlt_log(LOG_ERR, "Remove passive node Connection failed\n");
+ }
+
+ dlt_log(LOG_WARNING, "Connection to passive node lost\n");
+
+ return 0;
+ }
+
+ while (dlt_message_read(&msg,
+ (unsigned char *)receiver->buf,
+ receiver->bytesRcvd,
+ 0,
+ verbose) == DLT_MESSAGE_ERROR_OK)
+ {
+ DltStandardHeaderExtra *header = (DltStandardHeaderExtra *)
+ (msg.headerbuffer +
+ sizeof(DltStorageHeader) +
+ sizeof(DltStandardHeader));
+
+ /* only forward messages if the received ECUid is the expected one */
+ if (strncmp(header->ecu, con->ecuid, strlen(con->ecuid)) == 0)
+ {
+ if (dlt_daemon_client_send(DLT_DAEMON_SEND_TO_ALL,
+ daemon,
+ daemon_local,
+ msg.headerbuffer,
+ sizeof(DltStorageHeader),
+ msg.headerbuffer + sizeof(DltStorageHeader),
+ msg.headersize - sizeof(DltStorageHeader),
+ msg.databuffer,
+ msg.datasize,
+ verbose) != DLT_DAEMON_ERROR_OK)
+ {
+ dlt_log(LOG_WARNING, "Forward message to clients failed!\n");
+ }
+ }
+ else /* otherwise remove this connection and do not connect again */
+ {
+ snprintf(local_str,
+ DLT_DAEMON_TEXTBUFSIZE,
+ "Received ECUid (%s) differs to configured ECUid(%s). "
+ "Discard this message.\n",
+ header->ecu,
+ con->ecuid);
+ dlt_log(LOG_WARNING, local_str);
+
+ /* disconnect from passive node */
+ con->status = DLT_GATEWAY_DISCONNECTED;
+ con->trigger = DLT_GATEWAY_DISABLED;
+ if (dlt_event_handler_unregister_connection(&daemon_local->pEvent,
+ daemon_local,
+ receiver->fd,
+ DLT_CONNECTION_GATEWAY)
+ != 0)
+ {
+ dlt_log(LOG_ERR, "Remove passive node Connection failed\n");
+ }
+
+ dlt_log(LOG_WARNING,
+ "Disconnect from passive node due to invalid ECUid\n");
+ }
+
+ if (msg.found_serialheader)
+ {
+ if (dlt_receiver_remove(receiver,
+ msg.headersize +
+ msg.datasize -
+ sizeof(DltStorageHeader) +
+ sizeof(dltSerialHeader)) == -1)
+ {
+ /* Return value ignored */
+ dlt_message_free(&msg,verbose);
+ return -1;
+ }
+ }
+ else
+ {
+ if (dlt_receiver_remove(receiver,
+ msg.headersize +
+ msg.datasize -
+ sizeof(DltStorageHeader)) == -1)
+ {
+ /* Return value ignored */
+ dlt_message_free(&msg,verbose);
+ return -1;
+ }
+ }
+ }
+
+ if (dlt_receiver_move_to_begin(receiver) == -1)
+ {
+ /* Return value ignored */
+ dlt_message_free(&msg, verbose);
+ return -1;
+ }
+
+ if (dlt_message_free(&msg, verbose) == -1)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+int dlt_gateway_process_gateway_timer(DltDaemon *daemon,
+ DltDaemonLocal *daemon_local,
+ DltReceiver *receiver,
+ int verbose)
+{
+ uint64_t expir = 0;
+ ssize_t res = 0;
+ char local_str[DLT_DAEMON_TEXTBUFSIZE];
+
+ PRINT_FUNCTION_VERBOSE(verbose);
+
+ if ((daemon_local == NULL) || (daemon == NULL) || (receiver == NULL))
+ {
+ snprintf(local_str,
+ DLT_DAEMON_TEXTBUFSIZE,
+ "%s: invalid parameters",
+ __func__);
+ dlt_log(LOG_ERR, local_str);
+ return -1;
+ }
+
+ res = read(receiver->fd, &expir, sizeof(expir));
+
+ if(res < 0)
+ {
+ snprintf(local_str,
+ DLT_DAEMON_TEXTBUFSIZE,
+ "%s: Fail to read timer (%s)\n", __func__, strerror(errno));
+ dlt_log(LOG_WARNING, local_str);
+ /* Activity received on timer_wd, but unable to read the fd:
+ let's go on sending notification */
+ }
+
+ /* try to connect to passive nodes */
+ dlt_gateway_establish_connections(&daemon_local->pGateway,
+ daemon_local,
+ verbose);
+
+ dlt_log(LOG_DEBUG, "Gateway Timer\n");
+
+ return 0;
+}
+
+int dlt_gateway_forward_control_message(DltGateway *gateway,
+ DltDaemonLocal *daemon_local,
+ DltMessage *msg,
+ char *ecu,
+ int verbose)
+{
+ int i = 0;
+ int ret = 0;
+ DltGatewayConnection *con = NULL;
+
+ PRINT_FUNCTION_VERBOSE(verbose);
+
+ if (gateway == NULL || daemon_local == NULL || msg == NULL || ecu == NULL)
+ {
+ return -1;
+ }
+
+ for (i = 0; i < gateway->num_connections; i++)
+ {
+ if (strncmp(gateway->connections[i].ecuid,
+ ecu,
+ strlen(gateway->connections[i].ecuid)) == 0)
+ {
+ con = &gateway->connections[i];
+ break;
+ }
+ }
+
+ if (con == NULL)
+ {
+ dlt_log(LOG_WARNING, "Unknown passive node identifier\n");
+ return -1;
+ }
+
+ if (con->status != DLT_GATEWAY_CONNECTED)
+ {
+ dlt_log(LOG_INFO, "Passive node is not connected\n");
+ return -1;
+ }
+
+ ret = send(con->client.sock,
+ msg->headerbuffer + sizeof(DltStorageHeader),
+ msg->headersize - sizeof(DltStorageHeader),
+ 0);
+ if (ret == -1)
+ {
+ dlt_log(LOG_ERR, "Sending message to passive DLT Daemon failed\n");
+ return -1;
+ }
+ else
+ {
+ ret = send(con->client.sock, msg->databuffer, msg->datasize, 0);
+ if (ret == -1)
+ {
+ dlt_log(LOG_ERR, "Sending message to passive DLT Daemon failed\n");
+ return -1;
+ }
+ }
+
+ dlt_log(LOG_INFO, "Control message forwarded\n");
+ return 0;
+}
+
+int dlt_gateway_process_on_demand_request(DltGateway *gateway,
+ DltDaemonLocal *daemon_local,
+ char *node_id,
+ int connection_status,
+ int verbose)
+{
+ int i = 0;
+ DltGatewayConnection *con = NULL;
+
+ PRINT_FUNCTION_VERBOSE(verbose);
+
+ if (gateway == NULL || daemon_local == NULL || node_id == NULL)
+ {
+ return -1;
+ }
+
+ /* find connection by ECU id */
+ for (i = 0; i < gateway->num_connections; i++)
+ {
+ if (strncmp(node_id, gateway->connections->ecuid, DLT_ID_SIZE) == 0)
+ {
+ con = &gateway->connections[i];
+ break;
+ }
+ }
+
+ if (con == NULL)
+ {
+ dlt_log(LOG_WARNING, "Specified ECUid not found\n");
+ return -1;
+ }
+
+ if (connection_status == 1) /* try to connect */
+ {
+ if (con->status != DLT_GATEWAY_CONNECTED)
+ {
+ if (dlt_client_connect(&con->client, verbose) == 0)
+ {
+ con->status = DLT_GATEWAY_CONNECTED;
+
+ /* setup dlt connection and add to epoll event loop here */
+ if (dlt_connection_create(daemon_local,
+ &daemon_local->pEvent,
+ con->client.sock,
+ EPOLLIN,
+ DLT_CONNECTION_GATEWAY) != 0)
+ {
+ dlt_log(LOG_ERR, "Gateway connection creation failed\n");
+ return -1;
+ }
+ }
+ else
+ {
+ dlt_log(LOG_ERR, "Could not connect to passive node\n");
+ return -1;
+ }
+ }
+ else
+ {
+ dlt_log(LOG_INFO, "Passive node already connected\n");
+ }
+ }
+ else if (connection_status == 0) /* disconnect*/
+ {
+
+ con->status = DLT_GATEWAY_DISCONNECTED;
+ if (dlt_event_handler_unregister_connection(&daemon_local->pEvent,
+ daemon_local,
+ con->client.sock,
+ DLT_CONNECTION_GATEWAY) != 0)
+ {
+ dlt_log(LOG_ERR,
+ "Remove passive node event handler connection failed\n");
+ }
+
+ if (dlt_client_cleanup(&con->client, verbose) != 0)
+ {
+ dlt_log(LOG_ERR, "Could not cleanup DltClient structure\n");
+ return -1;
+ }
+ }
+ else
+ {
+ dlt_log(LOG_ERR, "Unknown command (connection_status)\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/gateway/dlt_gateway.conf b/src/gateway/dlt_gateway.conf
new file mode 100644
index 0000000..95d8682
--- /dev/null
+++ b/src/gateway/dlt_gateway.conf
@@ -0,0 +1,9 @@
+[PassiveNode1]
+IPaddress=192.168.2.11
+Port=3490
+; passive nodes ECU identifier
+EcuID=ECU2
+; Try connect to passive Node on DLT Daemon startup
+Connect=OnStartup
+; Stop connecting to passive node, if not successful after 10 seconds
+Timeout=10
diff --git a/src/gateway/dlt_gateway.h b/src/gateway/dlt_gateway.h
new file mode 100644
index 0000000..eacdf0b
--- /dev/null
+++ b/src/gateway/dlt_gateway.h
@@ -0,0 +1,169 @@
+/*
+ * @licence app begin@
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
+ *
+ * This file is part of GENIVI Project DLT - Diagnostic Log and Trace.
+ *
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License (MPL), 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/.
+ *
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+/*!
+ * \author
+ * Christoph Lipka <clipka@jp.adit-jv.com>
+ *
+ * \copyright Copyright © 2015 Advanced Driver Information Technology. \n
+ * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
+ *
+ * \file dlt_gateway.h
+ */
+
+/*******************************************************************************
+** **
+** SRC-MODULE: dlt_gateway.h **
+** **
+** TARGET : linux **
+** **
+** PROJECT : DLT **
+** **
+** AUTHOR : Christoph Lipka clipka@jp.adit-jv.com **
+** PURPOSE : **
+** **
+** REMARKS : **
+** **
+** PLATFORM DEPENDANT [yes/no]: yes **
+** **
+** TO BE CHANGED BY USER [yes/no]: no **
+** **
+*******************************************************************************/
+
+/*******************************************************************************
+** Author Identity **
+********************************************************************************
+** **
+** Initials Name Company **
+** -------- ------------------------- ---------------------------------- **
+** cl Christoph Lipka ADIT **
+*******************************************************************************/
+
+#ifndef DLT_GATEWAY_H_
+#define DLT_GATEWAY_H_
+
+#include "dlt-daemon.h"
+#include "dlt_gateway_types.h"
+
+/**
+ * Initialize the gateway to passive nodes
+ *
+ * TODO: Make path to configuration file configurable
+ *
+ * @param daemon_local pointer to DltDaemonLocal
+ * @param verbose verbose flag
+ * @return 0 on success, -1 on error
+ */
+int dlt_gateway_init(DltDaemonLocal *daemon_local, int verbose);
+
+/**
+ * De-initialize the gateway. All internal data will be freed.
+ *
+ * @param g DltGateway pointer
+ * @param verbose verbose flag
+ */
+void dlt_gateway_deinit(DltGateway *g, int verbose);
+
+/**
+ * Establish all connections to passive nodes that are configured to be started
+ * on daemon startup and add this connections to the main event loop.
+ *
+ * TODO: This function is called during gateway initialization and in main loop
+ * whenever the epoll returns. This may need to be improved.
+ *
+ * @param g DltGateway
+ * @param daemon_local DltDaemonLocal
+ * @param verbose verbose flag
+ * @return 0 on success, -1 on error
+ */
+int dlt_gateway_establish_connections(DltGateway *g,
+ DltDaemonLocal *daemon_local,
+ int verbose);
+
+/**
+ * Return the receiver for a given file descriptor
+ *
+ * @param g DltGateway
+ * @param fd file descriptor
+ * @return Pointer to DltReceiver on success, NULL otherwise
+ */
+DltReceiver *dlt_gateway_get_connection_receiver(DltGateway *g, int fd);
+
+
+/**
+ * Process incoming messages from passive nodes
+ *
+ * @param daemon DltDaemon
+ * @param daemon_local DltDaemonLocal
+ * @param recv DltReceiver structure
+ * @param verbose verbose flag
+ * @return 0 on success, -1 otherwise
+ */
+int dlt_gateway_process_passive_node_messages(DltDaemon *daemon,
+ DltDaemonLocal *daemon_local,
+ DltReceiver *recv,
+ int verbose);
+
+/**
+ * Process gateway timer
+ *
+ * @param daemon DltDaemon
+ * @param daemon_loocal DltDaemonLocal
+ * @param verbose verbose flag
+ * @return 0 on success, -1 otherwise
+ */
+int dlt_gateway_process_gateway_timer(DltDaemon *daemon,
+ DltDaemonLocal *daemon_local,
+ DltReceiver *rec,
+ int verbose);
+
+/**
+ * Forward control messages to the specified passive node DLT Daemon.
+ *
+ * @param g DltGateway
+ * @param daemon_local DltDaemonLocal
+ * @param msg DltMessage
+ * @param ecu Identifier of the passive node
+ * @param verbose verbose flag
+ * @return 0 on success, -1 otherwise
+ */
+int dlt_gateway_forward_control_message(DltGateway *g,
+ DltDaemonLocal *daemon_local,
+ DltMessage *msg,
+ char *ecu,
+ int verbose);
+
+/**
+ * Process on demand connect/disconnect of passive nodes
+ *
+ * @param g DltGateway
+ * @param node_id Passive Node identifier
+ * @param connection_status Connection status
+ * @return 0 on success, -1 otherwise
+ */
+int dlt_gateway_process_on_demand_request(DltGateway *g,
+ DltDaemonLocal *daemon_local,
+ char *node_id,
+ int connection_status,
+ int verbose);
+
+/* _ONLY_ for development purposes */
+void print_gateway_connection_details(const DltGateway *g);
+
+#endif
diff --git a/src/gateway/dlt_gateway_types.h b/src/gateway/dlt_gateway_types.h
new file mode 100644
index 0000000..b1247dd
--- /dev/null
+++ b/src/gateway/dlt_gateway_types.h
@@ -0,0 +1,106 @@
+/*
+ * @licence app begin@
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
+ *
+ * This file is part of GENIVI Project DLT - Diagnostic Log and Trace.
+ *
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License (MPL), 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/.
+ *
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+/*!
+ * \author
+ * Christoph Lipka <clipka@jp.adit-jv.com>
+ *
+ * \copyright Copyright © 2015 Advanced Driver Information Technology. \n
+ * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
+ *
+ * \file dlt_gateway_types.h
+ */
+
+/*******************************************************************************
+** **
+** SRC-MODULE: dlt_gateway_types.h **
+** **
+** TARGET : linux **
+** **
+** PROJECT : DLT **
+** **
+** AUTHOR : Christoph Lipka clipka@jp.adit-jv.com **
+** PURPOSE : **
+** **
+** REMARKS : **
+** **
+** PLATFORM DEPENDANT [yes/no]: yes **
+** **
+** TO BE CHANGED BY USER [yes/no]: no **
+** **
+*******************************************************************************/
+
+/*******************************************************************************
+** Author Identity **
+********************************************************************************
+** **
+** Initials Name Company **
+** -------- ------------------------- ---------------------------------- **
+** cl Christoph Lipka ADIT **
+*******************************************************************************/
+
+#ifndef DLT_GATEWAY_TYPES_H_
+#define DLT_GATEWAY_TYPES_H_
+
+#include "dlt_client.h"
+
+#define DLT_GATEWAY_CONFIG_PATH CONFIGURATION_FILES_DIR "/dlt_gateway.conf"
+#define DLT_GATEWAY_TIMER_INTERVAL 1
+
+typedef enum
+{
+ DLT_GATEWAY_UNINITIALIZED,
+ DLT_GATEWAY_INITIALIZED,
+ DLT_GATEWAY_CONNECTED,
+ DLT_GATEWAY_DISCONNECTED
+} connection_status;
+
+typedef enum
+{
+ DLT_GATEWAY_UNDEFINED = -1,
+ DLT_GATEWAY_ON_STARTUP, /* connect directly on startup */
+ DLT_GATEWAY_ON_DEMAND, /* connect on demand only */
+ DLT_GATEWAY_DISABLED /* disable this connection due to problems */
+} connection_trigger;
+
+/* DLT Gateway connection structure */
+typedef struct {
+ int handle; /* connection handle */
+ connection_status status; /* connected/disconnected */
+ char *ecuid; /* name of passive node */
+ char *ip_address; /* IP address */
+ int sock_domain; /* socket domain */
+ int sock_type; /* socket type */
+ int sock_protocol; /* socket protocol */
+ int port; /* port */
+ connection_trigger trigger; /* connection trigger */
+ int timeout; /* connection timeout */
+ int timeout_cnt; /* connection timeout counter */
+
+ DltClient client; /* DltClient structure */
+} DltGatewayConnection;
+
+/* DltGateway structure */
+typedef struct
+{
+ DltGatewayConnection *connections; /* pointer to connections */
+ int num_connections; /* number of connections */
+} DltGateway;
+
+#endif /* DLT_GATEWAY_TYPES_H_ */