automotive-dlt
dlt_daemon_socket.c
Go to the documentation of this file.
1 /*
2  * @licence app begin@
3  * SPDX license identifier: MPL-2.0
4  *
5  * Copyright (C) 2011-2015, BMW AG
6  *
7  * This file is part of GENIVI Project DLT - Diagnostic Log and Trace.
8  *
9  * This Source Code Form is subject to the terms of the
10  * Mozilla Public License (MPL), v. 2.0.
11  * If a copy of the MPL was not distributed with this file,
12  * You can obtain one at http://mozilla.org/MPL/2.0/.
13  *
14  * For further information see http://www.genivi.org/.
15  * @licence end@
16  */
17 
31 #include <netdb.h>
32 #include <ctype.h>
33 #include <stdio.h> /* for printf() and fprintf() */
34 #include <sys/socket.h> /* for socket(), connect(), (), and recv() */
35 #include <arpa/inet.h> /* for sockaddr_in and inet_addr() */
36 #include <stdlib.h> /* for atoi() and exit() */
37 #include <string.h> /* for memset() */
38 #include <unistd.h> /* for close() */
39 #include <fcntl.h>
40 #include <signal.h>
41 #include <syslog.h>
42 #include <errno.h>
43 #include <pthread.h>
44 #include <sys/ioctl.h>
45 #include <net/if.h>
46 
47 #ifdef linux
48 #include <sys/timerfd.h>
49 #endif
50 #include <sys/stat.h>
51 #include <sys/time.h>
52 #ifdef linux
53 #include <linux/stat.h>
54 #endif
55 
56 #include "dlt_types.h"
57 #include "dlt-daemon.h"
58 #include "dlt-daemon_cfg.h"
59 #include "dlt_daemon_common_cfg.h"
60 
61 #include "dlt_daemon_socket.h"
62 
65 
66 int dlt_daemon_socket_open(int *sock, unsigned int servPort)
67 {
68  int yes = 1;
69  char portnumbuffer[33];
70  struct addrinfo hints, *servinfo, *p;
71  int rv;
72 
73  memset(&hints, 0, sizeof hints);
74 #ifdef DLT_USE_IPv6
75  hints.ai_family = AF_INET6; // force IPv6 - will still work with IPv4
76 #else
77  hints.ai_family = AF_INET;
78 #endif
79  hints.ai_socktype = SOCK_STREAM;
80  hints.ai_flags = AI_PASSIVE; // use my IP address
81 
82  snprintf(portnumbuffer, 32, "%d", servPort);
83  if ((rv = getaddrinfo(NULL, portnumbuffer, &hints, &servinfo)) != 0) {
84  dlt_vlog(LOG_WARNING, "getaddrinfo error %d: %s\n", rv, gai_strerror(rv));
85  return -1;
86  }
87 
88  for(p = servinfo; p != NULL; p = p->ai_next) {
89  if ((*sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
90  const int lastErrno = errno;
91  dlt_vlog(LOG_WARNING, "dlt_daemon_socket_open: socket() error %d: %s\n", lastErrno, strerror(lastErrno));
92  continue;
93  }
94 
95  snprintf(str, DLT_DAEMON_TEXTBUFSIZE, "%s: Socket created - socket_family:%i, socket_type:%i, protocol:%i\n",
96  __FUNCTION__, p->ai_family, p->ai_socktype, p->ai_protocol);
97  dlt_log(LOG_INFO, str);
98 
99  if (setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
100  {
101  const int lastErrno = errno;
102  dlt_vlog(LOG_WARNING, "dlt_daemon_socket_open: Setsockopt error %d in dlt_daemon_local_connection_init: %s\n", lastErrno, strerror(lastErrno));
103  continue;
104  }
105 
106  if (bind(*sock, p->ai_addr, p->ai_addrlen) == -1) {
107  const int lastErrno = errno; //close() may set errno too
108  close(*sock);
109  dlt_vlog(LOG_WARNING, "dlt_daemon_socket_open: bind() error %d: %s\n", lastErrno, strerror(lastErrno));
110  continue;
111  }
112 
113  break;
114  }
115 
116  if (p == NULL) {
117  dlt_log(LOG_WARNING, "failed to bind socket\n");
118  return -1;
119  }
120 
121  freeaddrinfo(servinfo);
122 
123  snprintf(str, DLT_DAEMON_TEXTBUFSIZE, "%s: Listening on port: %u\n", __FUNCTION__, servPort);
124  dlt_log(LOG_INFO, str);
125 
126  // get socket buffer size
127  snprintf(str, DLT_DAEMON_TEXTBUFSIZE, "dlt_daemon_socket_open: Socket send queue size: %d\n", dlt_daemon_socket_get_send_qeue_max_size(*sock));
128  dlt_log(LOG_INFO, str);
129 
130  if (listen(*sock, 3) < 0)
131  {
132  const int lastErrno = errno;
133  dlt_vlog(LOG_WARNING, "dlt_daemon_socket_open: listen() failed with error %d: %s\n", lastErrno, strerror(lastErrno));
134  return -1;
135  }
136 
137  return 0; // OK
138 }
139 
141 {
142  close(sock);
143 
144  return 0;
145 }
146 
147 int dlt_daemon_socket_send(int sock,void* data1,int size1,void* data2,int size2,char serialheader)
148 {
149  /* Optional: Send serial header, if requested */
150  int ret = DLT_RETURN_OK;
151  if (serialheader)
152  {
153  ret = dlt_daemon_socket_sendreliable(sock, (void *) dltSerialHeader, sizeof(dltSerialHeader));
154  if(ret != DLT_RETURN_OK)
155  return ret;
156  }
157 
158  /* Send data */
159  if(data1 != NULL && size1 > 0)
160  {
161  ret = dlt_daemon_socket_sendreliable(sock, data1, size1);
162  if(ret != DLT_RETURN_OK)
163  return ret;
164  }
165 
166  if(data2 != NULL && size2 > 0)
167  {
168  ret = dlt_daemon_socket_sendreliable(sock, data2, size2);
169  if(ret != DLT_RETURN_OK)
170  return ret;
171  }
172 
173  return ret;
174 }
175 
176 int dlt_daemon_socket_sendreliable(int sock, void* buffer, int message_size)
177 {
178  int data_sent = 0;
179 
180  while (data_sent < message_size)
181  {
182  ssize_t ret = send(sock, buffer + data_sent, message_size - data_sent, 0);
183  if (ret < 0)
184  {
185  const int lastErrno=errno;
186  if (lastErrno==EINTR || lastErrno==EAGAIN || lastErrno==EWOULDBLOCK)
187  {
188  // Temporary error.
189  dlt_vlog(LOG_INFO,"dlt_daemon_socket_sendreliable: socket send() error %d: %s, trying again.\n", lastErrno, strerror(lastErrno));
190  }
191  else
192  {
193  dlt_vlog(LOG_WARNING,"dlt_daemon_socket_sendreliable: socket send() error %d: %s\n", lastErrno, strerror(lastErrno));
195  }
196  }
197  else
198  {
199  data_sent += ret;
200  }
201  }
202 
203  return DLT_DAEMON_ERROR_OK;
204 }
205 
207 {
208  int n = 0;
209  socklen_t m = sizeof(n);
210  getsockopt(sock,SOL_SOCKET,SO_SNDBUF,(void *)&n, &m);
211 
212  return n;
213 }
214 
#define DLT_DAEMON_ERROR_OK
Definition: dlt-daemon.h:170
DltReturnValue dlt_log(int prio, char *s)
Definition: dlt_common.c:2029
int dlt_daemon_socket_open(int *sock, unsigned int servPort)
#define DLT_DAEMON_ERROR_SEND_FAILED
Definition: dlt-daemon.h:173
int dlt_daemon_socket_close(int sock)
unsigned char buffer[BUFFER_SIZE]
Buffer for dlt file transfer. The size is defined by BUFFER_SIZE.
const char dltSerialHeader[DLT_ID_SIZE]
Definition: dlt_common.c:70
int dlt_daemon_socket_send(int sock, void *data1, int size1, void *data2, int size2, char serialheader)
int dlt_daemon_socket_sendreliable(int sock, void *buffer, int message_size)
dlt_daemon_socket_sendreliable - sends data to socket with additional checks and resending functional...
int dlt_daemon_socket_get_send_qeue_max_size(int sock)
static char str[DLT_DAEMON_TEXTBUFSIZE]
#define DLT_DAEMON_TEXTBUFSIZE
DltReturnValue dlt_vlog(int prio, const char *format,...)
Definition: dlt_common.c:2078
#define NULL
Definition: dlt_common.h:232