summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoão Sousa <48479050+joaodasousa@users.noreply.github.com>2020-08-31 00:56:03 +0100
committerGitHub <noreply@github.com>2020-08-31 08:56:03 +0900
commit33fbad18c814e13bd7ba2053525d8959fee437d1 (patch)
tree87d30704e5e78c603aace4cb2c0dacdf3554eba6
parent9af27899553dcfe9cd5ffede7f37be57d1a577a6 (diff)
downloadDLT-daemon-33fbad18c814e13bd7ba2053525d8959fee437d1.tar.gz
Implement DLTClient for UDP multicast (#240)
* Add UDP multicast support on client side UDP multicast support is already present on server side. This patch add seemless support for UDP multicast on client side in dlt-receive. Signed-off-by: Joao Sousa <joao.sa.sousa@ctw.bmwgroup.com>
-rw-r--r--include/dlt/dlt_client.h22
-rw-r--r--include/dlt/dlt_common.h11
-rw-r--r--src/console/dlt-receive.c19
-rw-r--r--src/examples/CMakeLists.txt4
-rw-r--r--src/lib/dlt_client.c82
-rw-r--r--src/shared/dlt_common.c15
6 files changed, 140 insertions, 13 deletions
diff --git a/include/dlt/dlt_client.h b/include/dlt/dlt_client.h
index 1fac86a..f649b83 100644
--- a/include/dlt/dlt_client.h
+++ b/include/dlt/dlt_client.h
@@ -81,14 +81,16 @@ typedef enum
DLT_CLIENT_MODE_UNDEFINED = -1,
DLT_CLIENT_MODE_TCP,
DLT_CLIENT_MODE_SERIAL,
- DLT_CLIENT_MODE_UNIX
+ DLT_CLIENT_MODE_UNIX,
+ DLT_CLIENT_MODE_UDP_MULTICAST
} DltClientMode;
typedef struct
{
DltReceiver receiver; /**< receiver pointer to dlt receiver structure */
int sock; /**< sock Connection handle/socket */
- char *servIP; /**< servIP IP adress/Hostname of TCP/IP interface */
+ char *servIP; /**< servIP IP adress/Hostname of interface */
+ char *hostip; /**< hostip IP address of UDP host receiver interface */
int port; /**< Port for TCP connections (optional) */
char *serialDevice; /**< serialDevice Devicename of serial device */
char *socketPath; /**< socketPath Unix socket path */
@@ -270,6 +272,14 @@ DltReturnValue dlt_client_send_reset_to_factory_default(DltClient *client);
DltReturnValue dlt_client_setbaudrate(DltClient *client, int baudrate);
/**
+ * Set mode within dlt client structure
+ * @param client pointer to dlt client structure
+ * @param mode DltClientMode
+ * @return Value from DltReturnValue enum
+ */
+DltReturnValue dlt_client_set_mode(DltClient *client, DltClientMode mode);
+
+/**
* Set server ip
* @param client pointer to dlt client structure
* @param ipaddr pointer to command line argument
@@ -278,6 +288,14 @@ DltReturnValue dlt_client_setbaudrate(DltClient *client, int baudrate);
int dlt_client_set_server_ip(DltClient *client, char *ipaddr);
/**
+ * Set server UDP host receiver interface address
+ * @param client pointer to dlt client structure
+ * @param hostip pointer to multicast group address
+ * @return negative value if there was an error
+ */
+int dlt_client_set_host_if_address(DltClient *client, char *hostip);
+
+/**
* Set serial device
* @param client pointer to dlt client structure
* @param serial_device pointer to command line argument
diff --git a/include/dlt/dlt_common.h b/include/dlt/dlt_common.h
index 9f4096b..166395e 100644
--- a/include/dlt/dlt_common.h
+++ b/include/dlt/dlt_common.h
@@ -77,6 +77,7 @@
# include <stdio.h>
# ifdef __linux__
# include <linux/limits.h>
+# include <sys/socket.h>
# else
# include <limits.h>
# endif
@@ -402,6 +403,7 @@ enum {
typedef enum
{
DLT_RECEIVE_SOCKET,
+ DLT_RECEIVE_UDP_SOCKET,
DLT_RECEIVE_FD
} DltReceiverType;
@@ -767,11 +769,12 @@ typedef struct
int32_t lastBytesRcvd; /**< bytes received in last receive call */
int32_t bytesRcvd; /**< received bytes */
int32_t totalBytesRcvd; /**< total number of received bytes */
- char *buffer; /**< pointer to receiver buffer */
- char *buf; /**< pointer to position within receiver buffer */
- char *backup_buf; /** pointer to the buffer with partial messages if any **/
- int fd; /**< connection handle */
+ char *buffer; /**< pointer to receiver buffer */
+ 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 buffersize; /**< size of receiver buffer */
+ struct sockaddr_in addr; /**< socket address information */
} DltReceiver;
typedef struct
diff --git a/src/console/dlt-receive.c b/src/console/dlt-receive.c
index 24280ee..cdfa274 100644
--- a/src/console/dlt-receive.c
+++ b/src/console/dlt-receive.c
@@ -96,6 +96,7 @@ typedef struct {
int mflag;
int vflag;
int yflag;
+ int uflag;
char *ovalue;
char *ovaluebase; /* ovalue without ".dlt" */
char *fvalue;
@@ -131,6 +132,7 @@ void usage()
printf(" -v Verbose mode\n");
printf(" -h Usage\n");
printf(" -y Serial device mode\n");
+ printf(" -u UDP multicast mode\n");
printf(" -b baudrate Serial device baudrate (Default: 115200)\n");
printf(" -e ecuid Set ECU ID (Default: RECV)\n");
printf(" -o filename Output messages in new DLT file\n");
@@ -300,6 +302,7 @@ int main(int argc, char *argv[])
dltdata.mflag = 0;
dltdata.vflag = 0;
dltdata.yflag = 0;
+ dltdata.uflag = 0;
dltdata.ovalue = 0;
dltdata.ovaluebase = 0;
dltdata.fvalue = 0;
@@ -313,7 +316,7 @@ int main(int argc, char *argv[])
/* Fetch command line arguments */
opterr = 0;
- while ((c = getopt (argc, argv, "vashyxmf:o:e:b:c:")) != -1)
+ while ((c = getopt (argc, argv, "vashyuxmf:o:e:b:c:")) != -1)
switch (c) {
case 'v':
{
@@ -350,6 +353,11 @@ int main(int argc, char *argv[])
dltdata.yflag = 1;
break;
}
+ case 'u':
+ {
+ dltdata.uflag = 1;
+ break;
+ }
case 'f':
{
dltdata.fvalue = optarg;
@@ -425,9 +433,14 @@ int main(int argc, char *argv[])
dlt_client_register_message_callback(dlt_receive_message_callback);
/* Setup DLT Client structure */
- dltclient.mode = dltdata.yflag;
+ if(dltdata.uflag) {
+ dltclient.mode = DLT_CLIENT_MODE_UDP_MULTICAST;
+ }
+ else {
+ dltclient.mode = dltdata.yflag;
+ }
- if (dltclient.mode == DLT_CLIENT_MODE_TCP) {
+ if (dltclient.mode == DLT_CLIENT_MODE_TCP || dltclient.mode == DLT_CLIENT_MODE_UDP_MULTICAST) {
for (index = optind; index < argc; index++)
if (dlt_client_set_server_ip(&dltclient, argv[index]) == -1) {
fprintf(stderr, "set server ip didn't succeed\n");
diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt
index 93f76a8..013700d 100644
--- a/src/examples/CMakeLists.txt
+++ b/src/examples/CMakeLists.txt
@@ -40,8 +40,8 @@ if(WITH_UDP_CONNECTION)
set_target_properties(dlt-example-multicast-clientmsg-view PROPERTIES LINKER_LANGUAGE C)
install(TARGETS dlt-example-multicast-clientmsg-view
- RUNTIME DESTINATION bin
- COMPONENT base)
+ RUNTIME DESTINATION bin
+ COMPONENT base)
endif(WITH_UDP_CONNECTION)
diff --git a/src/lib/dlt_client.c b/src/lib/dlt_client.c
index 5c18c0e..0b44d6e 100644
--- a/src/lib/dlt_client.c
+++ b/src/lib/dlt_client.c
@@ -121,6 +121,7 @@ DltReturnValue dlt_client_init_port(DltClient *client, int port, int verbose)
client->receiver.buffer = NULL;
client->receiver.buf = NULL;
client->receiver.backup_buf = NULL;
+ client->hostip = NULL;
return DLT_RETURN_OK;
}
@@ -153,16 +154,17 @@ DltReturnValue dlt_client_init(DltClient *client, int verbose)
dlt_vlog(LOG_INFO,
"Init dlt client struct with default port: %hu.\n",
servPort);
-
return dlt_client_init_port(client, servPort, verbose);
}
DltReturnValue dlt_client_connect(DltClient *client, int verbose)
{
+ const int yes = 1;
char portnumbuffer[33];
struct addrinfo hints, *servinfo, *p;
struct sockaddr_un addr;
int rv;
+ struct ip_mreq mreq;
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
@@ -266,6 +268,58 @@ DltReturnValue dlt_client_connect(DltClient *client, int verbose)
}
break;
+ case DLT_CLIENT_MODE_UDP_MULTICAST:
+
+ if ((client->sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ {
+ fprintf(stderr, "ERROR: socket error: %s\n", strerror(errno));
+ return DLT_RETURN_ERROR;
+ }
+
+ /* allow multiple sockets to use the same PORT number */
+ if (setsockopt(client->sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0)
+ {
+ fprintf(stderr, "ERROR: Reusing address failed: %s\n", strerror(errno));
+ return DLT_RETURN_ERROR;
+ }
+
+ memset(&client->receiver.addr, 0, sizeof(client->receiver.addr));
+ client->receiver.addr.sin_family = AF_INET;
+ client->receiver.addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ client->receiver.addr.sin_port = htons(client->port);
+
+ /* bind to receive address */
+ if (bind(client->sock, (struct sockaddr*) &client->receiver.addr, sizeof(client->receiver.addr)) < 0)
+ {
+ fprintf(stderr, "ERROR: bind failed: %s\n", strerror(errno));
+ return DLT_RETURN_ERROR;
+ }
+
+ mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+ if (client->hostip)
+ {
+ mreq.imr_interface.s_addr = inet_addr(client->hostip);
+ }
+ if (client->servIP == NULL)
+ {
+ fprintf(stderr, "ERROR: server address not set\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ mreq.imr_multiaddr.s_addr = inet_addr(client->servIP);
+ if (mreq.imr_multiaddr.s_addr == (in_addr_t)-1)
+ {
+ fprintf(stderr, "ERROR: server address not not valid %s\n", client->servIP);
+ return DLT_RETURN_ERROR;
+ }
+
+ if (setsockopt(client->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)) < 0)
+ {
+ fprintf(stderr, "ERROR: setsockopt add membership failed: %s\n", strerror(errno));
+ return DLT_RETURN_ERROR;
+ }
+
+ break;
default:
if (verbose)
@@ -315,6 +369,10 @@ DltReturnValue dlt_client_cleanup(DltClient *client, int verbose)
client->socketPath = NULL;
}
+ if (client->hostip) {
+ free(client->hostip);
+ client->hostip = NULL;
+ }
return ret;
}
@@ -875,6 +933,16 @@ DltReturnValue dlt_client_setbaudrate(DltClient *client, int baudrate)
return DLT_RETURN_OK;
}
+DltReturnValue dlt_client_set_mode(DltClient *client, DltClientMode mode)
+{
+ if (client == 0)
+ return DLT_RETURN_ERROR;
+
+ client->mode = mode;
+ return DLT_RETURN_OK;
+
+}
+
int dlt_client_set_server_ip(DltClient *client, char *ipaddr)
{
client->servIP = strdup(ipaddr);
@@ -887,6 +955,18 @@ int dlt_client_set_server_ip(DltClient *client, char *ipaddr)
return DLT_RETURN_OK;
}
+int dlt_client_set_host_if_address(DltClient *client, char *hostip)
+{
+ client->hostip = strdup(hostip);
+
+ if (client->hostip == NULL) {
+ dlt_log(LOG_ERR, "ERROR: failed to duplicate UDP interface address\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ return DLT_RETURN_OK;
+}
+
int dlt_client_set_serial_device(DltClient *client, char *serial_device)
{
client->serialDevice = strdup(serial_device);
diff --git a/src/shared/dlt_common.c b/src/shared/dlt_common.c
index eb620f5..823bca7 100644
--- a/src/shared/dlt_common.c
+++ b/src/shared/dlt_common.c
@@ -2014,6 +2014,8 @@ DltReturnValue dlt_receiver_free_unix_socket(DltReceiver *receiver)
int dlt_receiver_receive(DltReceiver *receiver, DltReceiverType from_src)
{
+ socklen_t addrlen;
+
if (receiver == NULL)
return -1;
@@ -2035,12 +2037,23 @@ int dlt_receiver_receive(DltReceiver *receiver, DltReceiverType from_src)
receiver->buf + receiver->lastBytesRcvd,
receiver->buffersize - receiver->lastBytesRcvd,
0);
- else
+ else if (from_src == DLT_RECEIVE_FD)
/* wait for data from fd */
receiver->bytesRcvd = read(receiver->fd,
receiver->buf + receiver->lastBytesRcvd,
receiver->buffersize - receiver->lastBytesRcvd);
+ else {
+ /* wait for data from UDP socket */
+ addrlen = sizeof(receiver->addr);
+ receiver->bytesRcvd = recvfrom(receiver->fd,
+ receiver->buf + receiver->lastBytesRcvd,
+ receiver->buffersize - receiver->lastBytesRcvd,
+ 0,
+ (struct sockaddr *)&(receiver->addr),
+ &addrlen);
+ }
+
if (receiver->bytesRcvd <= 0) {
receiver->bytesRcvd = 0;