dn_tcp.c
Go to the documentation of this file.
1 
25 #include "stdint.h"
26 #include <string.h>
27 
28 #if defined(_USE_WIN_API)
29 #include <winsock2.h>
30 #include <mstcpip.h>
31 #pragma comment(lib, "wsock32.lib")
32 #elif defined(_USE_LINUX_API)
33 #include <arpa/inet.h>
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <netinet/tcp.h>
37 #include <sys/socket.h>
38 #else
39 #include "dn_additional.h"
40 #endif
41 
42 #include "dn_common.h"
43 #include "dn_device.h"
44 #include "dn_socket.h"
45 #include "dn_tcp.h"
46 
48 
49 #if defined(_USE_WIN_API)
50 static HRESULT _tcp_set_keepalive(int sock, int enable, uint32_t idle, uint32_t interval, uint32_t count)
51 {
52  int ret;
53  DWORD dwBytes;
54  struct tcp_keepalive stParameter =
55  { 0}, stReturned =
56  { 0};
57 
58  stParameter.onoff = (enable != 0) ? 1: 0;
59  stParameter.keepalivetime = (idle == 0) ? 1 : (idle * 1000);
60  stParameter.keepaliveinterval = interval * 1000;
61  ret = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &stParameter, sizeof(stParameter), &stReturned, sizeof(stReturned), &dwBytes, NULL, NULL);
62 
63  return (ret == SOCKET_ERROR) ? OSERR2HRESULT(ret) : S_OK;
64 }
65 #elif defined(_USE_LINUX_API)
66 static HRESULT _tcp_set_keepalive(int sock, int enable, uint32_t idle, uint32_t interval, uint32_t count)
67 {
68  int ret;
69 
70  enable = (enable != 0) ? 1: 0;
71  ret = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&enable, sizeof(enable));
72  if(ret < 0) {
73  ret = DNGetLastError();
74  return OSERR2HRESULT(ret);
75  }
76 
77  idle = (idle == 0) ? 1 : idle;
78  ret = setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, (char *)&idle, sizeof(idle));
79  if(ret < 0) {
80  ret = DNGetLastError();
81  return OSERR2HRESULT(ret);
82  }
83 
84  ret = setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, (char *)&interval, sizeof(interval));
85  if(ret < 0) {
86  ret = DNGetLastError();
87  return OSERR2HRESULT(ret);
88  }
89 
90  ret = setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, (char *)&count, sizeof(count));
91  if(ret < 0) {
92  ret = DNGetLastError();
93  return OSERR2HRESULT(ret);
94  }
95 
96  return S_OK;
97 }
98 #endif
99 
106 HRESULT
107 tcp_open_client(void *param, int *sock)
108 {
109  int ret;
110  HRESULT hr;
111  struct sockaddr_in server;
112  const struct CONN_PARAM_ETH *eth_param = (const struct CONN_PARAM_ETH *) param;
113 #if defined(_USE_WIN_API)
114  WSAEVENT connevt = NULL;
115  WSANETWORKEVENTS events;
116 #else
117  int funcval = 0;
118  fd_set fds;
119  struct timeval tv;
120 #endif
121 
122  if (param == NULL || sock == NULL) {
123  hr = E_INVALIDARG;
124  goto exit_proc;
125  }
126 
127  hr = socket_open(SOCK_STREAM, sock);
128  if (FAILED(hr)) {
129  goto exit_proc;
130  }
131 
132  memset(&server, 0, sizeof(server));
133  server.sin_addr.s_addr = eth_param->dst_addr;
134  server.sin_port = eth_param->dst_port;
135  server.sin_family = AF_INET;
136 
137  if(tcp_conn_timeout > 0) {
138 #if defined(_USE_WIN_API)
139  connevt = WSACreateEvent();
140  if(connevt == WSA_INVALID_EVENT) {
141  hr = OSERR2HRESULT(WSAGetLastError());
142  goto exit_proc;
143  }
144  ret = WSAEventSelect(*sock, connevt, FD_CONNECT);
145  if(ret == SOCKET_ERROR) {
146  hr = OSERR2HRESULT(WSAGetLastError());
147  goto exit_proc;
148  }
149 #else
150  funcval = fcntl(*sock, F_GETFL, 0);
151  if(funcval < 0) {
153  goto exit_proc;
154  }
155  ret = fcntl(*sock, F_SETFL, funcval | O_NONBLOCK);
156  if(ret < 0) {
158  goto exit_proc;
159  }
160 #endif
161  }
162 
163  ret = connect(*sock, (struct sockaddr *) &server, sizeof(server));
164  if (ret < 0) {
165 #if defined(_USE_WIN_API)
166  ret = WSAGetLastError();
167  if(ret != WSAEWOULDBLOCK) {
168  hr = OSERR2HRESULT(ret);
169  goto exit_proc;
170  }
171 
172  ret = WSAWaitForMultipleEvents(1, &connevt,
173  FALSE, tcp_conn_timeout, FALSE);
174  if (ret != WSA_WAIT_EVENT_0) {
175  if (ret == WSA_WAIT_TIMEOUT) {
176  hr = E_TIMEOUT;
177  } else {
178  hr = OSERR2HRESULT(WSAGetLastError());
179  }
180  goto exit_proc;
181  }
182 
183  ret = WSAEnumNetworkEvents(*sock, connevt, &events);
184  if (ret == SOCKET_ERROR) {
185  hr = OSERR2HRESULT(WSAGetLastError());
186  goto exit_proc;
187  }
188  if (!(events.lNetworkEvents & FD_CONNECT)) {
189  hr = E_FAIL;
190  goto exit_proc;
191  }
192  if (events.iErrorCode[FD_CONNECT_BIT] != 0) {
193  hr = OSERR2HRESULT(events.iErrorCode[FD_CONNECT_BIT]);
194  goto exit_proc;
195  }
196 #else
197  ret = DNGetLastError();
198  if (ret != EINPROGRESS) {
199  hr = OSERR2HRESULT(ret);
200  goto exit_proc;
201  }
202 
203  FD_ZERO(&fds);
204  FD_SET(*sock, &fds);
205 
206  tv.tv_sec = tcp_conn_timeout / 1000;
207  tv.tv_usec = (tcp_conn_timeout % 1000) * 1000;
208 
209  ret = select(*sock + 1, NULL, &fds, NULL, &tv);
210  if (ret == 0) {
211  hr = E_TIMEOUT;
212  goto exit_proc;
213  }
214  else if (ret < 0) {
215  ret = DNGetLastError();
216  hr = OSERR2HRESULT(ret);
217  goto exit_proc;
218  }
219 #endif
220  }
221 
222 exit_proc:
223  if((sock != NULL) && (*sock != 0)) {
224 #if defined(_USE_WIN_API)
225  DWORD dwTemp = 0;
226  WSAEventSelect(*sock, NULL, 0);
227  ioctlsocket(*sock, FIONBIO, &dwTemp);
228 
229  if(connevt != NULL) {
230  WSACloseEvent(connevt);
231  }
232 #else
233  fcntl(*sock, F_SETFL, funcval & ~O_NONBLOCK);
234 #endif
235 
236  if(FAILED(hr)) {
237  socket_close(sock);
238  }
239  }
240 
241  /* Reset connection timeout */
242  tcp_conn_timeout = 0;
243 
244  return hr;
245 }
246 
253 HRESULT
254 tcp_open_server(void *param, int *sock)
255 {
256  int ret, flag;
257  HRESULT hr;
258  const struct CONN_PARAM_ETH *eth_param = (const struct CONN_PARAM_ETH *) param;
259 
260  if (param == NULL || sock == NULL)
261  return E_INVALIDARG;
262 
263  if (eth_param->src_port == 0)
264  return E_INVALIDARG;
265 
266  hr = socket_open(SOCK_STREAM, sock);
267  if (FAILED(hr))
268  return hr;
269 
270  /* Sets reuse address option */
271  flag = 1;
272  ret = setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, (const char *) &flag,
273  sizeof(flag));
274  if (ret < 0) {
275  ret = DNGetLastError();
276  socket_close(sock);
277  return OSERR2HRESULT(ret);
278  }
279 
280  /* Binds the created socket */
281  hr = socket_bind(eth_param, sock);
282  if (FAILED(hr)) {
283  socket_close(sock);
284  return hr;
285  }
286 
287  if (SUCCEEDED(hr)) {
288  ret = listen(*sock, 1);
289  if (ret < 0) {
290  ret = DNGetLastError();
291  socket_close(sock);
292  hr = OSERR2HRESULT(ret);
293  }
294  }
295 
296  return hr;
297 }
298 
304 HRESULT
305 tcp_close(int *sock)
306 {
307  return socket_close(sock);
308 }
309 
318 HRESULT
319 tcp_send(int sock, const char *buf, uint32_t len_buf, void *arg)
320 {
321  int ret, flag = 0;
322  uint32_t len_send, len_sended;
323 
324  if (sock <= 0)
325  return E_HANDLE;
326  if (buf == NULL || strlen(buf) == 0)
327  return E_INVALIDARG;
328 
329 #ifdef MSG_NOSIGNAL
330  flag |= MSG_NOSIGNAL;
331 #endif
332 
333  if (arg != NULL) {
334  flag |= *(int *) arg;
335  }
336 
337  len_send = (len_buf != 0) ? len_buf : strlen(buf);
338 
339  ret = send(sock, buf, len_send, flag);
340  len_sended = ret;
341 
342  if (ret < 0) {
343  ret = DNGetLastError();
344  return OSERR2HRESULT(ret);
345  }
346 
347  if (len_send > len_sended) {
348  return E_TIMEOUT;
349  }
350 
351  return S_OK;
352 }
353 
363 HRESULT
364 tcp_recv(int sock, char *buf, uint32_t len_buf, uint32_t *len_recved,
365  uint32_t timeout, void *arg)
366 {
367  int ret, flag = 0;
368  HRESULT hr;
369 
370  if (sock <= 0)
371  return E_HANDLE;
372  if (buf == NULL || len_recved == NULL)
373  return E_INVALIDARG;
374 
375  if (arg != NULL) {
376  flag |= *(int *) arg;
377  }
378 
379  hr = check_timeout(sock, timeout);
380  if (FAILED(hr))
381  return hr;
382 
383  ret = recv(sock, buf, len_buf, flag);
384  *len_recved = ret;
385 
386  if (ret < 0) {
387  ret = DNGetLastError();
388  return OSERR2HRESULT(ret);
389  }
390 
391  if (*len_recved == 0) {
392  return E_ACCESSDENIED;
393  }
394 
395  return S_OK;
396 }
397 
404 HRESULT
405 tcp_set_timeout(int sock, uint32_t timeout)
406 {
407  return socket_set_timeout(sock, timeout);
408 }
409 
416 HRESULT
417 tcp_clear(int sock, uint32_t timeout)
418 {
419  uint32_t len_recv = DEV_BUF_MAX, len_recved;
420  char buf_tmp[DEV_BUF_MAX];
421  HRESULT hr;
422 
423  if (sock <= 0)
424  return E_HANDLE;
425 
426  hr = tcp_set_timeout(sock, 0);
427  if (FAILED(hr))
428  return hr;
429 
430  do {
431  hr = tcp_recv(sock, buf_tmp, len_recv, &len_recved, 0, NULL);
432  } while (SUCCEEDED(hr));
433 
434  hr = tcp_set_timeout(sock, timeout);
435 
436  return hr;
437 }
438 
447 HRESULT
448 tcp_accept(int sock, int *client)
449 {
450  int ret;
451  extern int socket_counter;
452  HRESULT hr;
453 
454  if (sock <= 0)
455  return E_HANDLE;
456  if (client == NULL)
457  return E_INVALIDARG;
458 
459  hr = check_timeout(sock, 0);
460  if (FAILED(hr))
461  return hr;
462 
463  *client = accept(sock, NULL, NULL);
464  if (*client < 0) {
465  *client = 0;
466  ret = DNGetLastError();
467  return OSERR2HRESULT(ret);
468  }
469 
470  socket_counter++;
471 
472  return hr;
473 }
474 
484 HRESULT
485 tcp_set_keepalive(int sock, int enable, uint32_t idle, uint32_t interval,
486  uint32_t count)
487 {
488  if (sock <= 0)
489  return E_HANDLE;
490  return _tcp_set_keepalive(sock, enable, idle, interval, count);
491 }
492 
499 HRESULT
500 tcp_set_nodelay(int sock, int enable)
501 {
502  int ret;
503 
504  if (sock <= 0)
505  return E_HANDLE;
506 
507  enable = (enable != 0) ? 1 : 0;
508  ret = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &enable,
509  sizeof(enable));
510  if (ret < 0) {
511  ret = DNGetLastError();
512  return OSERR2HRESULT(ret);
513  }
514 
515  return S_OK;
516 }
HRESULT tcp_send(int sock, const char *buf, uint32_t len_buf, void *arg)
Sends TCP packet.
Definition: dn_tcp.c:319
TCP API file.
unsigned uint32_t
Definition: stdint.h:43
long tv_sec
Definition: dn_additional.h:56
static SOCKET accept(SOCKET s, struct sockaddr *addr, int *addrlen)
#define S_OK
Succeeded.
Definition: dn_common.h:89
HRESULT tcp_set_timeout(int sock, uint32_t timeout)
Sets timeout value to the TCP socket.
Definition: dn_tcp.c:405
#define F_SETFL
Definition: dn_additional.h:82
Socket API file.
#define F_GETFL
Definition: dn_additional.h:81
#define SOCK_STREAM
Definition: dn_additional.h:67
HRESULT tcp_accept(int sock, int *client)
TCP server accepts a TCP client.
Definition: dn_tcp.c:448
HRESULT tcp_open_server(void *param, int *sock)
Opens TCP server.
Definition: dn_tcp.c:254
HRESULT tcp_close(int *sock)
Closes the socket.
Definition: dn_tcp.c:305
#define FAILED(hr)
A macro that returns TRUE/FALSE. If hr is less than zero, then returns TRUE.
Definition: dn_common.h:77
#define E_HANDLE
Failed because the handle is invalid.
Definition: dn_common.h:119
#define DEV_BUF_MAX
The maximum buffer size of a packet.
Definition: dn_device.h:101
#define E_ACCESSDENIED
Failed because the resource is not ready.
Definition: dn_common.h:113
#define E_INVALIDARG
Failed because some arguments are invalid.
Definition: dn_common.h:131
long tv_usec
Definition: dn_additional.h:57
#define E_FAIL
Failed because unspecified error occurs.
Definition: dn_common.h:107
int32_t HRESULT
Definition: dn_common.h:61
static int send(SOCKET s, const char *buf, int len, int flags)
#define DNGetLastError()
A macro that gets last OS error.
HRESULT tcp_open_client(void *param, int *sock)
Opens TCP client.
Definition: dn_tcp.c:107
static int32_t _tcp_set_keepalive(int sock, int enable, uint32_t idle, uint32_t interval, uint32_t count)
uint16_t sin_port
_DN_EXP_SOCKET HRESULT socket_close(int *sock)
Closes the socket.
Definition: dn_socket.c:176
#define IPPROTO_TCP
Definition: dn_additional.h:76
#define AF_INET
Definition: dn_additional.h:66
uint16_t src_port
Definition: dn_device.h:149
#define SUCCEEDED(hr)
A macro that returns TRUE/FALSE. If hr is zero or more, then returns TRUE.
Definition: dn_common.h:71
_DN_EXP_SOCKET HRESULT socket_bind(const struct CONN_PARAM_ETH *param, int *sock)
Binds the socket with param&#39;s source address and source port.
Definition: dn_socket.c:211
A type definition for Ethernet connection parameters.
Definition: dn_device.h:144
Common device API file.
Common API file.
#define SO_REUSEADDR
Definition: dn_additional.h:71
#define O_NONBLOCK
Definition: dn_additional.h:83
#define SOL_SOCKET
Definition: dn_additional.h:70
User own API file.
_DN_EXP_SOCKET HRESULT socket_set_timeout(int sock, uint32_t timeout)
Sets timeout value to the socket.
Definition: dn_socket.c:255
struct in_addr sin_addr
#define SO_KEEPALIVE
Definition: dn_additional.h:72
#define FD_ZERO(fdsetp)
Definition: dn_additional.h:52
#define TCP_NODELAY
Definition: dn_additional.h:77
_DN_EXP_SOCKET HRESULT socket_open(int type, int *sock)
Creates a socket.
Definition: dn_socket.c:129
#define FD_SET(fd, fdsetp)
Definition: dn_additional.h:51
HRESULT tcp_clear(int sock, uint32_t timeout)
Clears the received buffer.
Definition: dn_tcp.c:417
uint16_t dst_port
Definition: dn_device.h:147
static int setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen)
_DN_EXP_DEVICE HRESULT check_timeout(int sock, uint32_t timeout)
Checks the communication timeout.
Definition: dn_device.c:385
HRESULT tcp_set_nodelay(int sock, int enable)
Sets no delay option.
Definition: dn_tcp.c:500
static int select(int __nfds, fd_set *__restrict __readfds, fd_set *__restrict __writefds, fd_set *__restrict __exceptfds, struct timeval *__restrict __timeout)
uint32_t tcp_conn_timeout
Definition: dn_tcp.c:47
int socket_counter
Definition: dn_socket.c:44
static int recv(SOCKET s, char *buf, int len, int flags)
static int listen(SOCKET s, int backlog)
HRESULT tcp_recv(int sock, char *buf, uint32_t len_buf, uint32_t *len_recved, uint32_t timeout, void *arg)
Receives TCP packet.
Definition: dn_tcp.c:364
#define E_TIMEOUT
Failed because the communication timed out.
Definition: dn_common.h:169
uint32_t dst_addr
Definition: dn_device.h:146
static int connect(SOCKET s, const struct sockaddr *name, int namelen)
short sin_family
HRESULT tcp_set_keepalive(int sock, int enable, uint32_t idle, uint32_t interval, uint32_t count)
Sets keep alive option.
Definition: dn_tcp.c:485
#define OSERR2HRESULT(err)
A macro that returns HREUSLT(0x8091) which means OS error.
Definition: dn_common.h:205


bcap_core
Author(s): DENSO WAVE INCORPORATED
autogenerated on Mon Jun 10 2019 13:12:20