1 /* coap_io.c -- Default network I/O functions for libcoap
2 *
3 * Copyright (C) 2012,2014,2016-2019 Olaf Bergmann <bergmann@tzi.org> and others
4 * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved.
5 *
6 * This file is part of the CoAP library libcoap. Please see
7 * README for terms of use.
8 */
9
10 #include "coap_internal.h"
11
12 #ifdef HAVE_STDIO_H
13 # include <stdio.h>
14 #endif
15
16 #ifdef HAVE_SYS_SELECT_H
17 # include <sys/select.h>
18 #endif
19 #ifdef HAVE_SYS_SOCKET_H
20 # include <sys/socket.h>
21 # define OPTVAL_T(t) (t)
22 # define OPTVAL_GT(t) (t)
23 #endif
24 #ifdef HAVE_SYS_IOCTL_H
25 #include <sys/ioctl.h>
26 #endif
27 #ifdef HAVE_NETINET_IN_H
28 # include <netinet/in.h>
29 #endif
30 #ifdef HAVE_WS2TCPIP_H
31 #include <ws2tcpip.h>
32 # define OPTVAL_T(t) (const char*)(t)
33 # define OPTVAL_GT(t) (char*)(t)
34 # undef CMSG_DATA
35 # define CMSG_DATA WSA_CMSG_DATA
36 #endif
37 #ifdef HAVE_SYS_UIO_H
38 # include <sys/uio.h>
39 #endif
40 #ifdef HAVE_UNISTD_H
41 # include <unistd.h>
42 #endif
43 #include <errno.h>
44 #ifdef COAP_EPOLL_SUPPORT
45 #include <sys/epoll.h>
46 #include <sys/timerfd.h>
47 #endif /* COAP_EPOLL_SUPPORT */
48
49 #ifdef WITH_CONTIKI
50 # include "uip.h"
51 #endif
52
53 #if !defined(WITH_CONTIKI)
54 /* define generic PKTINFO for IPv4 */
55 #if defined(IP_PKTINFO)
56 # define GEN_IP_PKTINFO IP_PKTINFO
57 #elif defined(IP_RECVDSTADDR)
58 # define GEN_IP_PKTINFO IP_RECVDSTADDR
59 #else
60 # error "Need IP_PKTINFO or IP_RECVDSTADDR to request ancillary data from OS."
61 #endif /* IP_PKTINFO */
62
63 /* define generic KTINFO for IPv6 */
64 #ifdef IPV6_RECVPKTINFO
65 # define GEN_IPV6_PKTINFO IPV6_RECVPKTINFO
66 #elif defined(IPV6_PKTINFO)
67 # define GEN_IPV6_PKTINFO IPV6_PKTINFO
68 #else
69 # error "Need IPV6_PKTINFO or IPV6_RECVPKTINFO to request ancillary data from OS."
70 #endif /* IPV6_RECVPKTINFO */
71 #endif
72
73 #ifdef COAP_SUPPORT_SOCKET_BROADCAST
74 #include <arpa/inet.h>
75 #include <net/if.h>
76 #include <address.h>
77 #endif
78 void coap_free_endpoint(coap_endpoint_t *ep);
79
80 #ifdef WITH_CONTIKI
81 static int ep_initialized = 0;
82
83 struct coap_endpoint_t *
coap_malloc_endpoint()84 coap_malloc_endpoint() {
85 static struct coap_endpoint_t ep;
86
87 if (ep_initialized) {
88 return NULL;
89 } else {
90 ep_initialized = 1;
91 return &ep;
92 }
93 }
94
95 void
coap_mfree_endpoint(struct coap_endpoint_t * ep)96 coap_mfree_endpoint(struct coap_endpoint_t *ep) {
97 ep_initialized = 0;
98 }
99
100 int
coap_socket_bind_udp(coap_socket_t * sock,const coap_address_t * listen_addr,coap_address_t * bound_addr)101 coap_socket_bind_udp(coap_socket_t *sock,
102 const coap_address_t *listen_addr,
103 coap_address_t *bound_addr) {
104 sock->conn = udp_new(NULL, 0, NULL);
105
106 if (!sock->conn) {
107 coap_log(LOG_WARNING, "coap_socket_bind_udp");
108 return 0;
109 }
110
111 coap_address_init(bound_addr);
112 uip_ipaddr_copy(&bound_addr->addr, &listen_addr->addr);
113 bound_addr->port = listen_addr->port;
114 udp_bind((struct uip_udp_conn *)sock->conn, bound_addr->port);
115 return 1;
116 }
117
118 int
coap_socket_connect_udp(coap_socket_t * sock,const coap_address_t * local_if,const coap_address_t * server,int default_port,coap_address_t * local_addr,coap_address_t * remote_addr)119 coap_socket_connect_udp(coap_socket_t *sock,
120 const coap_address_t *local_if,
121 const coap_address_t *server,
122 int default_port,
123 coap_address_t *local_addr,
124 coap_address_t *remote_addr) {
125 return 0;
126 }
127
128 int
coap_socket_connect_tcp1(coap_socket_t * sock,const coap_address_t * local_if,const coap_address_t * server,int default_port,coap_address_t * local_addr,coap_address_t * remote_addr)129 coap_socket_connect_tcp1(coap_socket_t *sock,
130 const coap_address_t *local_if,
131 const coap_address_t *server,
132 int default_port,
133 coap_address_t *local_addr,
134 coap_address_t *remote_addr) {
135 return 0;
136 }
137
138 int
coap_socket_connect_tcp2(coap_socket_t * sock,coap_address_t * local_addr,coap_address_t * remote_addr)139 coap_socket_connect_tcp2(coap_socket_t *sock,
140 coap_address_t *local_addr,
141 coap_address_t *remote_addr) {
142 return 0;
143 }
144
145 int
coap_socket_bind_tcp(coap_socket_t * sock,const coap_address_t * listen_addr,coap_address_t * bound_addr)146 coap_socket_bind_tcp(coap_socket_t *sock,
147 const coap_address_t *listen_addr,
148 coap_address_t *bound_addr) {
149 return 0;
150 }
151
152 int
coap_socket_accept_tcp(coap_socket_t * server,coap_socket_t * new_client,coap_address_t * local_addr,coap_address_t * remote_addr)153 coap_socket_accept_tcp(coap_socket_t *server,
154 coap_socket_t *new_client,
155 coap_address_t *local_addr,
156 coap_address_t *remote_addr) {
157 return 0;
158 }
159
160 ssize_t
coap_socket_write(coap_socket_t * sock,const uint8_t * data,size_t data_len)161 coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len) {
162 return -1;
163 }
164
165 ssize_t
coap_socket_read(coap_socket_t * sock,uint8_t * data,size_t data_len)166 coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len) {
167 return -1;
168 }
169
coap_socket_close(coap_socket_t * sock)170 void coap_socket_close(coap_socket_t *sock) {
171 if (sock->conn)
172 uip_udp_remove((struct uip_udp_conn *)sock->conn);
173 sock->flags = COAP_SOCKET_EMPTY;
174 }
175
176 #else
177
178 static const char *coap_socket_format_errno( int error );
179
180 struct coap_endpoint_t *
coap_malloc_endpoint(void)181 coap_malloc_endpoint(void) {
182 return (struct coap_endpoint_t *)coap_malloc_type(COAP_ENDPOINT, sizeof(struct coap_endpoint_t));
183 }
184
185 void
coap_mfree_endpoint(struct coap_endpoint_t * ep)186 coap_mfree_endpoint(struct coap_endpoint_t *ep) {
187 coap_free_type(COAP_ENDPOINT, ep);
188 }
189
190 int
coap_socket_bind_udp(coap_socket_t * sock,const coap_address_t * listen_addr,coap_address_t * bound_addr)191 coap_socket_bind_udp(coap_socket_t *sock,
192 const coap_address_t *listen_addr,
193 coap_address_t *bound_addr) {
194 int on = 1, off = 0;
195 #ifdef _WIN32
196 u_long u_on = 1;
197 #endif
198
199 sock->fd = socket(listen_addr->addr.sa.sa_family, SOCK_DGRAM, 0);
200
201 if (sock->fd == COAP_INVALID_SOCKET) {
202 coap_log(LOG_WARNING,
203 "coap_socket_bind_udp: socket: %s\n", coap_socket_strerror());
204 goto error;
205 }
206
207 #ifdef _WIN32
208 if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) {
209 #else
210 if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) {
211 #endif
212 coap_log(LOG_WARNING,
213 "coap_socket_bind_udp: ioctl FIONBIO: %s\n", coap_socket_strerror());
214 }
215
216 if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR)
217 coap_log(LOG_WARNING,
218 "coap_socket_bind_udp: setsockopt SO_REUSEADDR: %s\n",
219 coap_socket_strerror());
220
221 switch (listen_addr->addr.sa.sa_family) {
222 case AF_INET:
223 if (setsockopt(sock->fd, IPPROTO_IP, GEN_IP_PKTINFO, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR)
224 coap_log(LOG_ALERT,
225 "coap_socket_bind_udp: setsockopt IP_PKTINFO: %s\n",
226 coap_socket_strerror());
227 break;
228 case AF_INET6:
229 /* Configure the socket as dual-stacked */
230 if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR)
231 coap_log(LOG_ALERT,
232 "coap_socket_bind_udp: setsockopt IPV6_V6ONLY: %s\n",
233 coap_socket_strerror());
234 if (setsockopt(sock->fd, IPPROTO_IPV6, GEN_IPV6_PKTINFO, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR)
235 coap_log(LOG_ALERT,
236 "coap_socket_bind_udp: setsockopt IPV6_PKTINFO: %s\n",
237 coap_socket_strerror());
238 setsockopt(sock->fd, IPPROTO_IP, GEN_IP_PKTINFO, OPTVAL_T(&on), sizeof(on)); /* ignore error, because the likely cause is that IPv4 is disabled at the os level */
239 break;
240 default:
241 coap_log(LOG_ALERT, "coap_socket_bind_udp: unsupported sa_family\n");
242 break;
243 }
244
245 if (bind(sock->fd, &listen_addr->addr.sa,
246 listen_addr->addr.sa.sa_family == AF_INET ?
247 sizeof(struct sockaddr_in) :
248 listen_addr->size) == COAP_SOCKET_ERROR) {
249 coap_log(LOG_WARNING, "coap_socket_bind_udp: bind: %s\n",
250 coap_socket_strerror());
251 goto error;
252 }
253
254 bound_addr->size = (socklen_t)sizeof(*bound_addr);
255 if (getsockname(sock->fd, &bound_addr->addr.sa, &bound_addr->size) < 0) {
256 coap_log(LOG_WARNING,
257 "coap_socket_bind_udp: getsockname: %s\n",
258 coap_socket_strerror());
259 goto error;
260 }
261
262 return 1;
263
264 error:
265 coap_socket_close(sock);
266 return 0;
267 }
268
269 int
270 coap_socket_connect_tcp1(coap_socket_t *sock,
271 const coap_address_t *local_if,
272 const coap_address_t *server,
273 int default_port,
274 coap_address_t *local_addr,
275 coap_address_t *remote_addr) {
276 int on = 1, off = 0;
277 #ifdef _WIN32
278 u_long u_on = 1;
279 #endif
280 coap_address_t connect_addr;
281 coap_address_copy( &connect_addr, server );
282
283 sock->flags &= ~COAP_SOCKET_CONNECTED;
284 sock->fd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0);
285
286 if (sock->fd == COAP_INVALID_SOCKET) {
287 coap_log(LOG_WARNING,
288 "coap_socket_connect_tcp1: socket: %s\n",
289 coap_socket_strerror());
290 goto error;
291 }
292
293 #ifdef _WIN32
294 if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) {
295 #else
296 if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) {
297 #endif
298 coap_log(LOG_WARNING,
299 "coap_socket_connect_tcp1: ioctl FIONBIO: %s\n",
300 coap_socket_strerror());
301 }
302
303 switch (server->addr.sa.sa_family) {
304 case AF_INET:
305 if (connect_addr.addr.sin.sin_port == 0)
306 connect_addr.addr.sin.sin_port = htons(default_port);
307 break;
308 case AF_INET6:
309 if (connect_addr.addr.sin6.sin6_port == 0)
310 connect_addr.addr.sin6.sin6_port = htons(default_port);
311 /* Configure the socket as dual-stacked */
312 if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR)
313 coap_log(LOG_WARNING,
314 "coap_socket_connect_tcp1: setsockopt IPV6_V6ONLY: %s\n",
315 coap_socket_strerror());
316 break;
317 default:
318 coap_log(LOG_ALERT, "coap_socket_connect_tcp1: unsupported sa_family\n");
319 break;
320 }
321
322 if (local_if && local_if->addr.sa.sa_family) {
323 coap_address_copy(local_addr, local_if);
324 if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR)
325 coap_log(LOG_WARNING,
326 "coap_socket_connect_tcp1: setsockopt SO_REUSEADDR: %s\n",
327 coap_socket_strerror());
328 if (bind(sock->fd, &local_if->addr.sa,
329 local_if->addr.sa.sa_family == AF_INET ?
330 sizeof(struct sockaddr_in) :
331 local_if->size) == COAP_SOCKET_ERROR) {
332 coap_log(LOG_WARNING, "coap_socket_connect_tcp1: bind: %s\n",
333 coap_socket_strerror());
334 goto error;
335 }
336 } else {
337 local_addr->addr.sa.sa_family = server->addr.sa.sa_family;
338 }
339
340 if (connect(sock->fd, &connect_addr.addr.sa, connect_addr.size) == COAP_SOCKET_ERROR) {
341 #ifdef _WIN32
342 if (WSAGetLastError() == WSAEWOULDBLOCK) {
343 #else
344 if (errno == EINPROGRESS) {
345 #endif
346 /*
347 * COAP_SOCKET_CONNECTED needs to be set here as there will be reads/writes
348 * by underlying TLS libraries during connect() and we do not want to
349 * assert() in coap_read_session() or coap_write_session() when called by coap_read()
350 */
351 sock->flags |= COAP_SOCKET_WANT_CONNECT | COAP_SOCKET_CONNECTED;
352 return 1;
353 }
354 coap_log(LOG_WARNING, "coap_socket_connect_tcp1: connect: %s\n",
355 coap_socket_strerror());
356 goto error;
357 }
358
359 if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) {
360 coap_log(LOG_WARNING, "coap_socket_connect_tcp1: getsockname: %s\n",
361 coap_socket_strerror());
362 }
363
364 if (getpeername(sock->fd, &remote_addr->addr.sa, &remote_addr->size) == COAP_SOCKET_ERROR) {
365 coap_log(LOG_WARNING, "coap_socket_connect_tcp1: getpeername: %s\n",
366 coap_socket_strerror());
367 }
368
369 sock->flags |= COAP_SOCKET_CONNECTED;
370 return 1;
371
372 error:
373 coap_socket_close(sock);
374 return 0;
375 }
376
377 int
378 coap_socket_connect_tcp2(coap_socket_t *sock,
379 coap_address_t *local_addr,
380 coap_address_t *remote_addr) {
381 int error = 0;
382 #ifdef _WIN32
383 int optlen = (int)sizeof( error );
384 #else
385 socklen_t optlen = (socklen_t)sizeof( error );
386 #endif
387
388 sock->flags &= ~(COAP_SOCKET_WANT_CONNECT | COAP_SOCKET_CAN_CONNECT);
389
390 if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, OPTVAL_GT(&error),
391 &optlen) == COAP_SOCKET_ERROR) {
392 coap_log(LOG_WARNING, "coap_socket_finish_connect_tcp: getsockopt: %s\n",
393 coap_socket_strerror());
394 }
395
396 if (error) {
397 coap_log(LOG_WARNING,
398 "coap_socket_finish_connect_tcp: connect failed: %s\n",
399 coap_socket_format_errno(error));
400 coap_socket_close(sock);
401 return 0;
402 }
403
404 if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) {
405 coap_log(LOG_WARNING, "coap_socket_connect_tcp: getsockname: %s\n",
406 coap_socket_strerror());
407 }
408
409 if (getpeername(sock->fd, &remote_addr->addr.sa, &remote_addr->size) == COAP_SOCKET_ERROR) {
410 coap_log(LOG_WARNING, "coap_socket_connect_tcp: getpeername: %s\n",
411 coap_socket_strerror());
412 }
413
414 return 1;
415 }
416
417 int
418 coap_socket_bind_tcp(coap_socket_t *sock,
419 const coap_address_t *listen_addr,
420 coap_address_t *bound_addr) {
421 int on = 1, off = 0;
422 #ifdef _WIN32
423 u_long u_on = 1;
424 #endif
425
426 sock->fd = socket(listen_addr->addr.sa.sa_family, SOCK_STREAM, 0);
427
428 if (sock->fd == COAP_INVALID_SOCKET) {
429 coap_log(LOG_WARNING, "coap_socket_bind_tcp: socket: %s\n",
430 coap_socket_strerror());
431 goto error;
432 }
433
434 #ifdef _WIN32
435 if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) {
436 #else
437 if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) {
438 #endif
439 coap_log(LOG_WARNING, "coap_socket_bind_tcp: ioctl FIONBIO: %s\n",
440 coap_socket_strerror());
441 }
442 if (setsockopt (sock->fd, SOL_SOCKET, SO_KEEPALIVE, OPTVAL_T(&on),
443 sizeof (on)) == COAP_SOCKET_ERROR)
444 coap_log(LOG_WARNING,
445 "coap_socket_bind_tcp: setsockopt SO_KEEPALIVE: %s\n",
446 coap_socket_strerror());
447
448 if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on),
449 sizeof(on)) == COAP_SOCKET_ERROR)
450 coap_log(LOG_WARNING,
451 "coap_socket_bind_tcp: setsockopt SO_REUSEADDR: %s\n",
452 coap_socket_strerror());
453
454 switch (listen_addr->addr.sa.sa_family) {
455 case AF_INET:
456 break;
457 case AF_INET6:
458 /* Configure the socket as dual-stacked */
459 if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR)
460 coap_log(LOG_ALERT,
461 "coap_socket_bind_tcp: setsockopt IPV6_V6ONLY: %s\n",
462 coap_socket_strerror());
463 break;
464 default:
465 coap_log(LOG_ALERT, "coap_socket_bind_tcp: unsupported sa_family\n");
466 }
467
468 if (bind(sock->fd, &listen_addr->addr.sa,
469 listen_addr->addr.sa.sa_family == AF_INET ?
470 sizeof(struct sockaddr_in) :
471 listen_addr->size) == COAP_SOCKET_ERROR) {
472 coap_log(LOG_ALERT, "coap_socket_bind_tcp: bind: %s\n",
473 coap_socket_strerror());
474 goto error;
475 }
476
477 bound_addr->size = (socklen_t)sizeof(*bound_addr);
478 if (getsockname(sock->fd, &bound_addr->addr.sa, &bound_addr->size) < 0) {
479 coap_log(LOG_WARNING, "coap_socket_bind_tcp: getsockname: %s\n",
480 coap_socket_strerror());
481 goto error;
482 }
483
484 if (listen(sock->fd, 5) == COAP_SOCKET_ERROR) {
485 coap_log(LOG_ALERT, "coap_socket_bind_tcp: listen: %s\n",
486 coap_socket_strerror());
487 goto error;
488 }
489
490 return 1;
491
492 error:
493 coap_socket_close(sock);
494 return 0;
495 }
496
497 int
498 coap_socket_accept_tcp(coap_socket_t *server,
499 coap_socket_t *new_client,
500 coap_address_t *local_addr,
501 coap_address_t *remote_addr) {
502 #ifdef _WIN32
503 u_long u_on = 1;
504 #else
505 int on = 1;
506 #endif
507
508 server->flags &= ~COAP_SOCKET_CAN_ACCEPT;
509
510 new_client->fd = accept(server->fd, &remote_addr->addr.sa,
511 &remote_addr->size);
512 if (new_client->fd == COAP_INVALID_SOCKET) {
513 coap_log(LOG_WARNING, "coap_socket_accept_tcp: accept: %s\n",
514 coap_socket_strerror());
515 return 0;
516 }
517
518 if (getsockname( new_client->fd, &local_addr->addr.sa, &local_addr->size) < 0)
519 coap_log(LOG_WARNING, "coap_socket_accept_tcp: getsockname: %s\n",
520 coap_socket_strerror());
521
522 #ifdef _WIN32
523 if (ioctlsocket(new_client->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) {
524 #else
525 if (ioctl(new_client->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) {
526 #endif
527 coap_log(LOG_WARNING, "coap_socket_accept_tcp: ioctl FIONBIO: %s\n",
528 coap_socket_strerror());
529 }
530
531 return 1;
532 }
533
534 #ifdef COAP_SUPPORT_SOCKET_BROADCAST
535 static int
536 bind_to_device(int sockfd, const struct sockaddr_in *local_addr) {
537 struct ifreq buf[COAP_INTERFACE_MAX];
538 struct ifconf ifc;
539 memset(buf, 0x00, COAP_INTERFACE_MAX * sizeof(struct ifreq));
540 memset(&ifc, 0x00, sizeof(struct ifconf));
541 ifc.ifc_len = sizeof(buf);
542 ifc.ifc_buf = (char *)buf;
543 if (ioctl(sockfd, SIOCGIFCONF, (char *)&ifc) < 0) {
544 coap_log(LOG_DEBUG, "ioctl fail, errno = %d\n", errno);
545 return -1;
546 }
547
548 int interface_num = ifc.ifc_len / sizeof(struct ifreq);
549 for (int i = 0; i < interface_num && i < COAP_INTERFACE_MAX; i++) {
550 coap_log(LOG_DEBUG, "device name: %s\n", buf[i].ifr_name);
551 if (ioctl(sockfd, SIOCGIFFLAGS, (char *)(&buf[i])) < 0) {
552 coap_log(LOG_ERR, "ioctl fail, errno = %d\n", errno);
553 return -1;
554 }
555 if (!((uint16_t)buf[i].ifr_flags & IFF_UP)) {
556 coap_log(LOG_ERR, "interface is not up\n");
557 continue;
558 }
559 /* get IP of this interface */
560 if (ioctl(sockfd, SIOCGIFADDR, (char *)&buf[i]) < 0) {
561 coap_log(LOG_DEBUG, "ioctl fail, errno = %d\n", errno);
562 return -1;
563 }
564
565 if (local_addr->sin_addr.s_addr == ((struct sockaddr_in *)&(buf[i].ifr_addr))->sin_addr.s_addr) {
566 /* if find the target interface, begin to bind */
567 struct ifreq ifr;
568 memset(&ifr, 0, sizeof(ifr));
569 (void)strncpy(ifr.ifr_ifrn.ifrn_name, buf[i].ifr_name, sizeof(ifr.ifr_ifrn.ifrn_name) - 1);
570 if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, (char *)&ifr, sizeof(ifr)) < 0) {
571 coap_log(LOG_ERR, "setsockopt fail, errno = %d\n", errno);
572 return -1;
573 }
574 coap_log(LOG_INFO, "binding interface %s success\n", buf[i].ifr_name);
575 break;
576 }
577 }
578 return 0;
579 }
580 #endif
581
582 int
583 coap_socket_connect_udp(coap_socket_t *sock,
584 const coap_address_t *local_if,
585 const coap_address_t *server,
586 int default_port,
587 coap_address_t *local_addr,
588 coap_address_t *remote_addr) {
589 int on = 1, off = 0;
590 #ifdef _WIN32
591 u_long u_on = 1;
592 #endif
593 coap_address_t connect_addr;
594 int is_mcast = coap_is_mcast(server);
595 #ifdef COAP_SUPPORT_SOCKET_BROADCAST
596 int is_bcast = coap_is_bcast(server);
597 #endif
598 coap_address_copy(&connect_addr, server);
599
600 sock->flags &= ~(COAP_SOCKET_CONNECTED | COAP_SOCKET_MULTICAST);
601 #ifdef COAP_SUPPORT_SOCKET_BROADCAST
602 sock->flags &= ~(COAP_SOCKET_BROADCAST);
603 #endif
604 sock->fd = socket(connect_addr.addr.sa.sa_family, SOCK_DGRAM, 0);
605
606 if (sock->fd == COAP_INVALID_SOCKET) {
607 coap_log(LOG_WARNING, "coap_socket_connect_udp: socket: %s\n",
608 coap_socket_strerror());
609 goto error;
610 }
611 #ifdef COAP_SUPPORT_SOCKET_BROADCAST
612 coap_log(LOG_DEBUG, "coap_socket_connect_udp setsockopt socket %d\n", sock->fd);
613 if (setsockopt(sock->fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(int)) < 0) {
614 coap_log(LOG_ERR, "not support broadcast or setsocketopt fail\n");
615 goto error;
616 }
617 #endif
618
619 #ifdef _WIN32
620 if (ioctlsocket(sock->fd, FIONBIO, &u_on) == COAP_SOCKET_ERROR) {
621 #else
622 if (ioctl(sock->fd, FIONBIO, &on) == COAP_SOCKET_ERROR) {
623 #endif
624 coap_log(LOG_WARNING, "coap_socket_connect_udp: ioctl FIONBIO: %s\n",
625 coap_socket_strerror());
626 }
627
628 switch (connect_addr.addr.sa.sa_family) {
629 case AF_INET:
630 if (connect_addr.addr.sin.sin_port == 0)
631 connect_addr.addr.sin.sin_port = htons(default_port);
632 break;
633 case AF_INET6:
634 if (connect_addr.addr.sin6.sin6_port == 0)
635 connect_addr.addr.sin6.sin6_port = htons(default_port);
636 /* Configure the socket as dual-stacked */
637 if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, OPTVAL_T(&off), sizeof(off)) == COAP_SOCKET_ERROR)
638 coap_log(LOG_WARNING,
639 "coap_socket_connect_udp: setsockopt IPV6_V6ONLY: %s\n",
640 coap_socket_strerror());
641 break;
642 default:
643 coap_log(LOG_ALERT, "coap_socket_connect_udp: unsupported sa_family\n");
644 break;
645 }
646
647 if (local_if && local_if->addr.sa.sa_family) {
648 if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on)) == COAP_SOCKET_ERROR)
649 coap_log(LOG_WARNING,
650 "coap_socket_connect_udp: setsockopt SO_REUSEADDR: %s\n",
651 coap_socket_strerror());
652 if (bind(sock->fd, &local_if->addr.sa,
653 local_if->addr.sa.sa_family == AF_INET ?
654 sizeof(struct sockaddr_in) :
655 local_if->size) == COAP_SOCKET_ERROR) {
656 coap_log(LOG_WARNING, "coap_socket_connect_udp: bind: %s\n",
657 coap_socket_strerror());
658 goto error;
659 }
660 #ifdef COAP_SUPPORT_SOCKET_BROADCAST
661 int ret = bind_to_device(sock->fd, (struct sockaddr_in *)(&local_if->addr.sa));
662 if (ret == -1) {
663 goto error;
664 }
665 #endif
666 }
667
668 /* special treatment for sockets that are used for multicast communication */
669 if (is_mcast) {
670 if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) {
671 coap_log(LOG_WARNING,
672 "coap_socket_connect_udp: getsockname for multicast socket: %s\n",
673 coap_socket_strerror());
674 }
675 coap_address_copy(remote_addr, &connect_addr);
676 sock->flags |= COAP_SOCKET_MULTICAST;
677 return 1;
678 }
679 #ifdef COAP_SUPPORT_SOCKET_BROADCAST
680 if (is_bcast) {
681 if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) {
682 coap_log(LOG_WARNING, "coap_socket_connect_udp: getsockname for broadcast socket: %s\n",
683 coap_socket_strerror());
684 }
685
686 sock->flags |= COAP_SOCKET_BROADCAST;
687 return 1;
688 }
689 #endif
690 if (connect(sock->fd, &connect_addr.addr.sa, connect_addr.size) == COAP_SOCKET_ERROR) {
691 coap_log(LOG_WARNING, "coap_socket_connect_udp: connect: %s\n",
692 coap_socket_strerror());
693 goto error;
694 }
695
696 if (getsockname(sock->fd, &local_addr->addr.sa, &local_addr->size) == COAP_SOCKET_ERROR) {
697 coap_log(LOG_WARNING, "coap_socket_connect_udp: getsockname: %s\n",
698 coap_socket_strerror());
699 }
700
701 if (getpeername(sock->fd, &remote_addr->addr.sa, &remote_addr->size) == COAP_SOCKET_ERROR) {
702 coap_log(LOG_WARNING, "coap_socket_connect_udp: getpeername: %s\n",
703 coap_socket_strerror());
704 }
705
706 sock->flags |= COAP_SOCKET_CONNECTED;
707 return 1;
708
709 error:
710 coap_socket_close(sock);
711 return 0;
712 }
713
714 void coap_socket_close(coap_socket_t *sock) {
715 if (sock->fd != COAP_INVALID_SOCKET) {
716 #ifdef COAP_EPOLL_SUPPORT
717 coap_context_t *context = sock->session ? sock->session->context :
718 sock->endpoint ? sock->endpoint->context : NULL;
719 if (context != NULL) {
720 int ret;
721 struct epoll_event event;
722
723 /* Kernels prior to 2.6.9 expect non NULL event parameter */
724 ret = epoll_ctl(context->epfd, EPOLL_CTL_DEL, sock->fd, &event);
725 if (ret == -1) {
726 coap_log(LOG_ERR,
727 "%s: epoll_ctl DEL failed: %s (%d)\n",
728 "coap_socket_close",
729 coap_socket_strerror(), errno);
730 }
731 }
732 #endif /* COAP_EPOLL_SUPPORT */
733 sock->endpoint = NULL;
734 sock->session = NULL;
735 coap_closesocket(sock->fd);
736 sock->fd = COAP_INVALID_SOCKET;
737 }
738 sock->flags = COAP_SOCKET_EMPTY;
739 }
740
741 #ifdef COAP_EPOLL_SUPPORT
742 void
743 coap_epoll_ctl_mod(coap_socket_t *sock,
744 uint32_t events,
745 const char *func
746 ) {
747 int ret;
748 struct epoll_event event;
749 coap_context_t *context;
750
751 if (sock == NULL)
752 return;
753
754 context = sock->session ? sock->session->context :
755 sock->endpoint ? sock->endpoint->context : NULL;
756 if (context == NULL)
757 return;
758
759 event.events = events;
760 event.data.ptr = sock;
761
762 ret = epoll_ctl(context->epfd, EPOLL_CTL_MOD, sock->fd, &event);
763 if (ret == -1) {
764 coap_log(LOG_ERR,
765 "%s: epoll_ctl MOD failed: %s (%d)\n",
766 func,
767 coap_socket_strerror(), errno);
768 }
769 }
770 #endif /* COAP_EPOLL_SUPPORT */
771
772 ssize_t
773 coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len) {
774 ssize_t r;
775
776 sock->flags &= ~(COAP_SOCKET_WANT_WRITE | COAP_SOCKET_CAN_WRITE);
777 #ifdef _WIN32
778 r = send(sock->fd, (const char *)data, (int)data_len, 0);
779 #else
780 r = send(sock->fd, data, data_len, 0);
781 #endif
782 if (r == COAP_SOCKET_ERROR) {
783 #ifdef _WIN32
784 if (WSAGetLastError() == WSAEWOULDBLOCK) {
785 #elif EAGAIN != EWOULDBLOCK
786 if (errno==EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
787 #else
788 if (errno==EAGAIN || errno == EINTR) {
789 #endif
790 sock->flags |= COAP_SOCKET_WANT_WRITE;
791 #ifdef COAP_EPOLL_SUPPORT
792 coap_epoll_ctl_mod(sock,
793 EPOLLOUT |
794 ((sock->flags & COAP_SOCKET_WANT_READ) ?
795 EPOLLIN : 0),
796 __func__);
797 #endif /* COAP_EPOLL_SUPPORT */
798 return 0;
799 }
800 coap_log(LOG_WARNING, "coap_socket_write: send: %s\n",
801 coap_socket_strerror());
802 return -1;
803 }
804 if (r < (ssize_t)data_len) {
805 sock->flags |= COAP_SOCKET_WANT_WRITE;
806 #ifdef COAP_EPOLL_SUPPORT
807 coap_epoll_ctl_mod(sock,
808 EPOLLOUT |
809 ((sock->flags & COAP_SOCKET_WANT_READ) ?
810 EPOLLIN : 0),
811 __func__);
812 #endif /* COAP_EPOLL_SUPPORT */
813 }
814 return r;
815 }
816
817 ssize_t
818 coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len) {
819 ssize_t r;
820 #ifdef _WIN32
821 int error;
822 #endif
823
824 #ifdef _WIN32
825 r = recv(sock->fd, (char *)data, (int)data_len, 0);
826 #else
827 r = recv(sock->fd, data, data_len, 0);
828 #endif
829 if (r == 0) {
830 /* graceful shutdown */
831 sock->flags &= ~COAP_SOCKET_CAN_READ;
832 return -1;
833 } else if (r == COAP_SOCKET_ERROR) {
834 sock->flags &= ~COAP_SOCKET_CAN_READ;
835 #ifdef _WIN32
836 error = WSAGetLastError();
837 if (error == WSAEWOULDBLOCK) {
838 #elif EAGAIN != EWOULDBLOCK
839 if (errno==EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
840 #else
841 if (errno==EAGAIN || errno == EINTR) {
842 #endif
843 return 0;
844 }
845 #ifdef _WIN32
846 if (error != WSAECONNRESET)
847 #else
848 if (errno != ECONNRESET)
849 #endif
850 coap_log(LOG_WARNING, "coap_socket_read: recv: %s\n",
851 coap_socket_strerror());
852 return -1;
853 }
854 if (r < (ssize_t)data_len)
855 sock->flags &= ~COAP_SOCKET_CAN_READ;
856 return r;
857 }
858
859 #endif /* WITH_CONTIKI */
860
861 #if (!defined(WITH_CONTIKI)) != ( defined(HAVE_NETINET_IN_H) || defined(HAVE_WS2TCPIP_H) )
862 /* define struct in6_pktinfo and struct in_pktinfo if not available
863 FIXME: check with configure
864 */
865 struct in6_pktinfo {
866 struct in6_addr ipi6_addr; /* src/dst IPv6 address */
867 unsigned int ipi6_ifindex; /* send/recv interface index */
868 };
869
870 struct in_pktinfo {
871 int ipi_ifindex;
872 struct in_addr ipi_spec_dst;
873 struct in_addr ipi_addr;
874 };
875 #endif
876
877 #if !defined(WITH_CONTIKI) && !defined(SOL_IP)
878 /* Solaris expects level IPPROTO_IP for ancillary data. */
879 #define SOL_IP IPPROTO_IP
880 #endif
881
882 #ifdef __GNUC__
883 #define UNUSED_PARAM __attribute__ ((unused))
884 #else /* not a GCC */
885 #define UNUSED_PARAM
886 #endif /* GCC */
887
888 #if defined(_WIN32)
889 #include <mswsock.h>
890 static __declspec(thread) LPFN_WSARECVMSG lpWSARecvMsg = NULL;
891 /* Map struct WSABUF fields to their posix counterpart */
892 #define msghdr _WSAMSG
893 #define msg_name name
894 #define msg_namelen namelen
895 #define msg_iov lpBuffers
896 #define msg_iovlen dwBufferCount
897 #define msg_control Control.buf
898 #define msg_controllen Control.len
899 #define iovec _WSABUF
900 #define iov_base buf
901 #define iov_len len
902 #define iov_len_t u_long
903 #undef CMSG_DATA
904 #define CMSG_DATA WSA_CMSG_DATA
905 #define ipi_spec_dst ipi_addr
906 #else
907 #define iov_len_t size_t
908 #endif
909
910 ssize_t
911 coap_network_send(coap_socket_t *sock, const coap_session_t *session, const uint8_t *data, size_t datalen) {
912 ssize_t bytes_written = 0;
913
914 if (!coap_debug_send_packet()) {
915 bytes_written = (ssize_t)datalen;
916 #ifndef WITH_CONTIKI
917 } else if (sock->flags & COAP_SOCKET_CONNECTED) {
918 #ifdef _WIN32
919 bytes_written = send(sock->fd, (const char *)data, (int)datalen, 0);
920 #else
921 bytes_written = send(sock->fd, data, datalen, 0);
922 #endif
923 #endif
924 } else {
925 #ifndef WITH_CONTIKI
926 #ifdef _WIN32
927 DWORD dwNumberOfBytesSent = 0;
928 int r;
929 #endif
930 #ifdef HAVE_STRUCT_CMSGHDR
931 /* a buffer large enough to hold all packet info types, ipv6 is the largest */
932 char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
933 struct msghdr mhdr;
934 struct iovec iov[1];
935 const void *addr = &session->addr_info.remote.addr;
936
937 assert(session);
938
939 memcpy (&iov[0].iov_base, &data, sizeof (iov[0].iov_base));
940 iov[0].iov_len = (iov_len_t)datalen;
941
942 memset(buf, 0, sizeof (buf));
943
944 memset(&mhdr, 0, sizeof(struct msghdr));
945 memcpy (&mhdr.msg_name, &addr, sizeof (mhdr.msg_name));
946 mhdr.msg_namelen = session->addr_info.remote.size;
947
948 mhdr.msg_iov = iov;
949 mhdr.msg_iovlen = 1;
950
951 if (!coap_address_isany(&session->addr_info.local) &&
952 !coap_is_mcast(&session->addr_info.local))
953 switch (session->addr_info.local.addr.sa.sa_family) {
954 case AF_INET6:
955 {
956 struct cmsghdr *cmsg;
957
958 if (IN6_IS_ADDR_V4MAPPED(&session->addr_info.local.addr.sin6.sin6_addr)) {
959 #if defined(IP_PKTINFO)
960 struct in_pktinfo *pktinfo;
961 mhdr.msg_control = buf;
962 mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
963
964 cmsg = CMSG_FIRSTHDR(&mhdr);
965 cmsg->cmsg_level = SOL_IP;
966 cmsg->cmsg_type = IP_PKTINFO;
967 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
968
969 pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
970
971 pktinfo->ipi_ifindex = session->ifindex;
972 memcpy(&pktinfo->ipi_spec_dst,
973 session->addr_info.local.addr.sin6.sin6_addr.s6_addr + 12,
974 sizeof(pktinfo->ipi_spec_dst));
975 #elif defined(IP_SENDSRCADDR)
976 mhdr.msg_control = buf;
977 mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_addr));
978
979 cmsg = CMSG_FIRSTHDR(&mhdr);
980 cmsg->cmsg_level = IPPROTO_IP;
981 cmsg->cmsg_type = IP_SENDSRCADDR;
982 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
983
984 memcpy(CMSG_DATA(cmsg),
985 session->addr_info.local.addr.sin6.sin6_addr.s6_addr + 12,
986 sizeof(struct in_addr));
987 #endif /* IP_PKTINFO */
988 } else {
989 struct in6_pktinfo *pktinfo;
990 mhdr.msg_control = buf;
991 mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
992
993 cmsg = CMSG_FIRSTHDR(&mhdr);
994 cmsg->cmsg_level = IPPROTO_IPV6;
995 cmsg->cmsg_type = IPV6_PKTINFO;
996 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
997
998 pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
999
1000 pktinfo->ipi6_ifindex = session->ifindex;
1001 memcpy(&pktinfo->ipi6_addr,
1002 &session->addr_info.local.addr.sin6.sin6_addr,
1003 sizeof(pktinfo->ipi6_addr));
1004 }
1005 break;
1006 }
1007 case AF_INET:
1008 {
1009 #if defined(IP_PKTINFO)
1010 struct cmsghdr *cmsg;
1011 struct in_pktinfo *pktinfo;
1012
1013 mhdr.msg_control = buf;
1014 mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
1015
1016 cmsg = CMSG_FIRSTHDR(&mhdr);
1017 cmsg->cmsg_level = SOL_IP;
1018 cmsg->cmsg_type = IP_PKTINFO;
1019 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
1020
1021 pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
1022
1023 pktinfo->ipi_ifindex = session->ifindex;
1024 memcpy(&pktinfo->ipi_spec_dst,
1025 &session->addr_info.local.addr.sin.sin_addr,
1026 sizeof(pktinfo->ipi_spec_dst));
1027 #elif defined(IP_SENDSRCADDR)
1028 struct cmsghdr *cmsg;
1029 mhdr.msg_control = buf;
1030 mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_addr));
1031
1032 cmsg = CMSG_FIRSTHDR(&mhdr);
1033 cmsg->cmsg_level = IPPROTO_IP;
1034 cmsg->cmsg_type = IP_SENDSRCADDR;
1035 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
1036
1037 memcpy(CMSG_DATA(cmsg),
1038 &session->addr_info.local.addr.sin.sin_addr,
1039 sizeof(struct in_addr));
1040 #endif /* IP_PKTINFO */
1041 break;
1042 }
1043 default:
1044 /* error */
1045 coap_log(LOG_WARNING, "protocol not supported\n");
1046 bytes_written = -1;
1047 }
1048 #endif /* HAVE_STRUCT_CMSGHDR */
1049
1050 #ifdef _WIN32
1051 r = WSASendMsg(sock->fd, &mhdr, 0 /*dwFlags*/, &dwNumberOfBytesSent, NULL /*lpOverlapped*/, NULL /*lpCompletionRoutine*/);
1052 if (r == 0)
1053 bytes_written = (ssize_t)dwNumberOfBytesSent;
1054 else
1055 bytes_written = -1;
1056 #else
1057 #ifdef HAVE_STRUCT_CMSGHDR
1058 bytes_written = sendmsg(sock->fd, &mhdr, 0);
1059 #else /* ! HAVE_STRUCT_CMSGHDR */
1060 bytes_written = sendto(sock->fd, data, datalen, 0,
1061 &session->addr_info.remote.addr.sa,
1062 session->addr_info.remote.size);
1063 #endif /* ! HAVE_STRUCT_CMSGHDR */
1064 #endif
1065 #else /* WITH_CONTIKI */
1066 /* FIXME: untested */
1067 /* FIXME: is there a way to check if send was successful? */
1068 (void)datalen;
1069 (void)data;
1070 uip_udp_packet_sendto((struct uip_udp_conn *)sock->conn, data, datalen,
1071 &session->addr_info.remote.addr, session->addr_info.remote.port);
1072 bytes_written = datalen;
1073 #endif /* WITH_CONTIKI */
1074 }
1075
1076 if (bytes_written < 0)
1077 coap_log(LOG_CRIT, "coap_network_send: %s\n", coap_socket_strerror());
1078
1079 return bytes_written;
1080 }
1081
1082 #define SIN6(A) ((struct sockaddr_in6 *)(A))
1083
1084 void
1085 coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length) {
1086 *address = packet->payload;
1087 *length = packet->length;
1088 }
1089
1090 ssize_t
1091 coap_network_read(coap_socket_t *sock, coap_packet_t *packet) {
1092 ssize_t len = -1;
1093
1094 assert(sock);
1095 assert(packet);
1096
1097 if ((sock->flags & COAP_SOCKET_CAN_READ) == 0) {
1098 return -1;
1099 } else {
1100 /* clear has-data flag */
1101 sock->flags &= ~COAP_SOCKET_CAN_READ;
1102 }
1103
1104 #ifndef WITH_CONTIKI
1105 if (sock->flags & COAP_SOCKET_CONNECTED) {
1106 #ifdef _WIN32
1107 len = recv(sock->fd, (char *)packet->payload, COAP_RXBUFFER_SIZE, 0);
1108 #else
1109 len = recv(sock->fd, packet->payload, COAP_RXBUFFER_SIZE, 0);
1110 #endif
1111 if (len < 0) {
1112 #ifdef _WIN32
1113 if (WSAGetLastError() == WSAECONNRESET) {
1114 #else
1115 if (errno == ECONNREFUSED) {
1116 #endif
1117 /* client-side ICMP destination unreachable, ignore it */
1118 coap_log(LOG_WARNING, "coap_network_read: unreachable\n");
1119 return -2;
1120 }
1121 coap_log(LOG_WARNING, "coap_network_read: %s\n", coap_socket_strerror());
1122 goto error;
1123 } else if (len > 0) {
1124 packet->length = (size_t)len;
1125 }
1126 } else {
1127 #endif /* WITH_CONTIKI */
1128 #if defined(_WIN32)
1129 DWORD dwNumberOfBytesRecvd = 0;
1130 int r;
1131 #endif
1132 #if !defined(WITH_CONTIKI)
1133 #ifdef HAVE_STRUCT_CMSGHDR
1134 /* a buffer large enough to hold all packet info types, ipv6 is the largest */
1135 char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
1136 struct cmsghdr *cmsg;
1137 struct msghdr mhdr;
1138 struct iovec iov[1];
1139
1140 iov[0].iov_base = packet->payload;
1141 iov[0].iov_len = (iov_len_t)COAP_RXBUFFER_SIZE;
1142
1143 memset(&mhdr, 0, sizeof(struct msghdr));
1144
1145 mhdr.msg_name = (struct sockaddr*)&packet->addr_info.remote.addr;
1146 mhdr.msg_namelen = sizeof(packet->addr_info.remote.addr);
1147
1148 mhdr.msg_iov = iov;
1149 mhdr.msg_iovlen = 1;
1150
1151 mhdr.msg_control = buf;
1152 mhdr.msg_controllen = sizeof(buf);
1153 /* set a big first length incase recvmsg() does not implement updating
1154 msg_control as well as preset the first cmsg with bad data */
1155 cmsg = (struct cmsghdr *)buf;
1156 cmsg->cmsg_len = CMSG_LEN(sizeof(buf));
1157 cmsg->cmsg_level = -1;
1158 cmsg->cmsg_type = -1;
1159
1160 #if defined(_WIN32)
1161 if (!lpWSARecvMsg) {
1162 GUID wsaid = WSAID_WSARECVMSG;
1163 DWORD cbBytesReturned = 0;
1164 if (WSAIoctl(sock->fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &wsaid, sizeof(wsaid), &lpWSARecvMsg, sizeof(lpWSARecvMsg), &cbBytesReturned, NULL, NULL) != 0) {
1165 coap_log(LOG_WARNING, "coap_network_read: no WSARecvMsg\n");
1166 return -1;
1167 }
1168 }
1169 r = lpWSARecvMsg(sock->fd, &mhdr, &dwNumberOfBytesRecvd, NULL /* LPWSAOVERLAPPED */, NULL /* LPWSAOVERLAPPED_COMPLETION_ROUTINE */);
1170 if (r == 0)
1171 len = (ssize_t)dwNumberOfBytesRecvd;
1172 #else
1173 len = recvmsg(sock->fd, &mhdr, 0);
1174 #endif
1175
1176 #else /* ! HAVE_STRUCT_CMSGHDR */
1177 len = recvfrom(sock->fd, packet->payload, COAP_RXBUFFER_SIZE, 0,
1178 &packet->addr_info.remote.addr.sa,
1179 &packet->addr_info.remote.size);
1180 #endif /* ! HAVE_STRUCT_CMSGHDR */
1181
1182 if (len < 0) {
1183 #ifdef _WIN32
1184 if (WSAGetLastError() == WSAECONNRESET) {
1185 #else
1186 if (errno == ECONNREFUSED) {
1187 #endif
1188 /* server-side ICMP destination unreachable, ignore it. The destination address is in msg_name. */
1189 return 0;
1190 }
1191 coap_log(LOG_WARNING, "coap_network_read: %s\n", coap_socket_strerror());
1192 goto error;
1193 } else {
1194 #ifdef HAVE_STRUCT_CMSGHDR
1195 int dst_found = 0;
1196
1197 packet->addr_info.remote.size = mhdr.msg_namelen;
1198 packet->length = (size_t)len;
1199
1200 /* Walk through ancillary data records until the local interface
1201 * is found where the data was received. */
1202 for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg; cmsg = CMSG_NXTHDR(&mhdr, cmsg)) {
1203
1204 /* get the local interface for IPv6 */
1205 if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
1206 union {
1207 uint8_t *c;
1208 struct in6_pktinfo *p;
1209 } u;
1210 u.c = CMSG_DATA(cmsg);
1211 packet->ifindex = (int)(u.p->ipi6_ifindex);
1212 memcpy(&packet->addr_info.local.addr.sin6.sin6_addr,
1213 &u.p->ipi6_addr, sizeof(struct in6_addr));
1214 dst_found = 1;
1215 break;
1216 }
1217
1218 /* local interface for IPv4 */
1219 #if defined(IP_PKTINFO)
1220 if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO) {
1221 union {
1222 uint8_t *c;
1223 struct in_pktinfo *p;
1224 } u;
1225 u.c = CMSG_DATA(cmsg);
1226 packet->ifindex = u.p->ipi_ifindex;
1227 if (packet->addr_info.local.addr.sa.sa_family == AF_INET6) {
1228 memset(packet->addr_info.local.addr.sin6.sin6_addr.s6_addr, 0, 10);
1229 packet->addr_info.local.addr.sin6.sin6_addr.s6_addr[10] = 0xff;
1230 packet->addr_info.local.addr.sin6.sin6_addr.s6_addr[11] = 0xff;
1231 memcpy(packet->addr_info.local.addr.sin6.sin6_addr.s6_addr + 12,
1232 &u.p->ipi_addr, sizeof(struct in_addr));
1233 } else {
1234 memcpy(&packet->addr_info.local.addr.sin.sin_addr,
1235 &u.p->ipi_addr, sizeof(struct in_addr));
1236 }
1237 dst_found = 1;
1238 break;
1239 }
1240 #elif defined(IP_RECVDSTADDR)
1241 if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) {
1242 packet->ifindex = sock->fd;
1243 memcpy(&packet->addr_info.local.addr.sin.sin_addr,
1244 CMSG_DATA(cmsg), sizeof(struct in_addr));
1245 dst_found = 1;
1246 break;
1247 }
1248 #endif /* IP_PKTINFO */
1249 if (!dst_found) {
1250 /* cmsg_level / cmsg_type combination we do not understand
1251 (ignore preset case for bad recvmsg() not updating cmsg) */
1252 if (cmsg->cmsg_level != -1 && cmsg->cmsg_type != -1) {
1253 coap_log(LOG_DEBUG,
1254 "cmsg_level = %d and cmsg_type = %d not supported - fix\n",
1255 cmsg->cmsg_level, cmsg->cmsg_type);
1256 }
1257 }
1258 }
1259 if (!dst_found) {
1260 /* Not expected, but cmsg_level and cmsg_type don't match above and
1261 may need a new case */
1262 packet->ifindex = sock->fd;
1263 if (getsockname(sock->fd, &packet->addr_info.local.addr.sa,
1264 &packet->addr_info.local.size) < 0) {
1265 coap_log(LOG_DEBUG, "Cannot determine local port\n");
1266 }
1267 }
1268 #else /* ! HAVE_STRUCT_CMSGHDR */
1269 packet->length = (size_t)len;
1270 packet->ifindex = 0;
1271 if (getsockname(sock->fd, &packet->addr_info.local.addr.sa,
1272 &packet->addr_info.local.size) < 0) {
1273 coap_log(LOG_DEBUG, "Cannot determine local port\n");
1274 goto error;
1275 }
1276 #endif /* ! HAVE_STRUCT_CMSGHDR */
1277 }
1278 #endif /* !defined(WITH_CONTIKI) */
1279 #ifdef WITH_CONTIKI
1280 /* FIXME: untested, make this work */
1281 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
1282 #define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN])
1283
1284 if (uip_newdata()) {
1285 uip_ipaddr_copy(&packet->addr_info.remote.addr, &UIP_IP_BUF->srcipaddr);
1286 packet->addr_info.remote.port = UIP_UDP_BUF->srcport;
1287 uip_ipaddr_copy(&(packet)->addr_info.local.addr, &UIP_IP_BUF->destipaddr);
1288 packet->addr_info.local.port = UIP_UDP_BUF->destport;
1289
1290 len = uip_datalen();
1291
1292 if (len > COAP_RXBUFFER_SIZE) {
1293 /* FIXME: we might want to send back a response */
1294 coap_log(LOG_WARNING, "discarded oversized packet\n");
1295 return -1;
1296 }
1297
1298 ((char *)uip_appdata)[len] = 0;
1299 if (LOG_DEBUG <= coap_get_log_level()) {
1300 #ifndef INET6_ADDRSTRLEN
1301 #define INET6_ADDRSTRLEN 40
1302 #endif
1303 unsigned char addr_str[INET6_ADDRSTRLEN + 8];
1304
1305 if (coap_print_addr(&packet->addr_info.remote, addr_str,
1306 INET6_ADDRSTRLEN + 8)) {
1307 coap_log(LOG_DEBUG, "received %zd bytes from %s\n", len, addr_str);
1308 }
1309 }
1310
1311 packet->length = len;
1312 memcpy(&packet->payload, uip_appdata, len);
1313 }
1314
1315 #undef UIP_IP_BUF
1316 #undef UIP_UDP_BUF
1317 #endif /* WITH_CONTIKI */
1318 #ifndef WITH_CONTIKI
1319 }
1320 #endif /* WITH_CONTIKI */
1321
1322 if (len >= 0)
1323 return len;
1324 #if !defined(WITH_CONTIKI)
1325 error:
1326 #endif
1327 return -1;
1328 }
1329
1330 unsigned int
1331 coap_io_prepare_epoll(coap_context_t *ctx, coap_tick_t now) {
1332 #ifndef COAP_EPOLL_SUPPORT
1333 (void)ctx;
1334 (void)now;
1335 coap_log(LOG_EMERG,
1336 "coap_io_prepare_epoll() requires libcoap compiled for using epoll\n");
1337 return 0;
1338 #else /* COAP_EPOLL_SUPPORT */
1339 coap_socket_t *sockets[1];
1340 unsigned int max_sockets = sizeof(sockets)/sizeof(sockets[0]);
1341 unsigned int num_sockets;
1342 unsigned int timeout;
1343
1344 /* Use the common logic */
1345 timeout = coap_write(ctx, sockets, max_sockets, &num_sockets, now);
1346 /* Save when the next expected I/O is to take place */
1347 ctx->next_timeout = timeout ? now + timeout : 0;
1348 if (ctx->eptimerfd != -1) {
1349 struct itimerspec new_value;
1350 int ret;
1351
1352 memset(&new_value, 0, sizeof(new_value));
1353 coap_ticks(&now);
1354 if (ctx->next_timeout != 0 && ctx->next_timeout > now) {
1355 coap_tick_t rem_timeout = ctx->next_timeout - now;
1356 /* Need to trigger an event on ctx->epfd in the future */
1357 new_value.it_value.tv_sec = rem_timeout / COAP_TICKS_PER_SECOND;
1358 new_value.it_value.tv_nsec = (rem_timeout % COAP_TICKS_PER_SECOND) *
1359 1000000;
1360 }
1361 /* reset, or specify a future time for eptimerfd to trigger */
1362 ret = timerfd_settime(ctx->eptimerfd, 0, &new_value, NULL);
1363 if (ret == -1) {
1364 coap_log(LOG_ERR,
1365 "%s: timerfd_settime failed: %s (%d)\n",
1366 "coap_io_prepare_epoll",
1367 coap_socket_strerror(), errno);
1368 }
1369 }
1370 return timeout;
1371 #endif /* COAP_EPOLL_SUPPORT */
1372 }
1373
1374 #if !defined(WITH_CONTIKI)
1375 #ifndef COAP_EPOLL_SUPPORT
1376 static void
1377 coap_updata_ep_sockets(coap_context_t *ctx,
1378 coap_socket_t *sockets[],
1379 unsigned int max_sockets,
1380 unsigned int *num_sockets)
1381 {
1382 coap_endpoint_t *ep;
1383 coap_session_t *s, *rtmp;
1384
1385 LL_FOREACH(ctx->endpoint, ep) {
1386 if (ep->sock.flags & (COAP_SOCKET_WANT_READ | COAP_SOCKET_WANT_WRITE | COAP_SOCKET_WANT_ACCEPT)) {
1387 sockets[(*num_sockets)++] = &ep->sock;
1388 if (*num_sockets >= max_sockets) {
1389 return;
1390 }
1391 }
1392 SESSIONS_ITER_SAFE(ep->sessions, s, rtmp) {
1393 if (s->sock.flags & (COAP_SOCKET_WANT_READ | COAP_SOCKET_WANT_WRITE)) {
1394 sockets[(*num_sockets)++] = &s->sock;
1395 if (*num_sockets >= max_sockets) {
1396 return;
1397 }
1398 }
1399 }
1400 }
1401
1402 SESSIONS_ITER_SAFE(ctx->sessions, s, rtmp) {
1403 if (s->sock.flags & (COAP_SOCKET_WANT_READ | COAP_SOCKET_WANT_WRITE | COAP_SOCKET_WANT_CONNECT)) {
1404 sockets[(*num_sockets)++] = &s->sock;
1405 if (*num_sockets >= max_sockets) {
1406 return;
1407 }
1408 }
1409 }
1410 }
1411 #endif /* ! COAP_EPOLL_SUPPORT */
1412
1413 unsigned int
1414 coap_write(coap_context_t *ctx,
1415 coap_socket_t *sockets[],
1416 unsigned int max_sockets,
1417 unsigned int *num_sockets,
1418 coap_tick_t now)
1419 {
1420 coap_queue_t *nextpdu;
1421 coap_endpoint_t *ep;
1422 coap_session_t *s, *rtmp;
1423 coap_tick_t session_timeout;
1424 coap_tick_t timeout = 0;
1425 #ifdef COAP_EPOLL_SUPPORT
1426 (void)sockets;
1427 (void)max_sockets;
1428 #endif /* COAP_EPOLL_SUPPORT */
1429
1430 *num_sockets = 0;
1431
1432 /* Check to see if we need to send off any Observe requests */
1433 coap_check_notify(ctx);
1434
1435 if (ctx->session_timeout > 0)
1436 session_timeout = ctx->session_timeout * COAP_TICKS_PER_SECOND;
1437 else
1438 session_timeout = COAP_DEFAULT_SESSION_TIMEOUT * COAP_TICKS_PER_SECOND;
1439
1440 LL_FOREACH(ctx->endpoint, ep) {
1441 SESSIONS_ITER_SAFE(ep->sessions, s, rtmp) {
1442 if (s->type == COAP_SESSION_TYPE_SERVER && s->ref == 0 &&
1443 s->delayqueue == NULL &&
1444 (s->last_rx_tx + session_timeout <= now ||
1445 s->state == COAP_SESSION_STATE_NONE)) {
1446 coap_session_free(s);
1447 } else {
1448 if (s->type == COAP_SESSION_TYPE_SERVER && s->ref == 0 && s->delayqueue == NULL) {
1449 coap_tick_t s_timeout = (s->last_rx_tx + session_timeout) - now;
1450 if (timeout == 0 || s_timeout < timeout)
1451 timeout = s_timeout;
1452 }
1453 }
1454 }
1455 }
1456 SESSIONS_ITER_SAFE(ctx->sessions, s, rtmp) {
1457 if (
1458 s->type == COAP_SESSION_TYPE_CLIENT
1459 && s->state == COAP_SESSION_STATE_ESTABLISHED
1460 && ctx->ping_timeout > 0
1461 ) {
1462 coap_tick_t s_timeout;
1463 if (s->last_rx_tx + ctx->ping_timeout * COAP_TICKS_PER_SECOND <= now) {
1464 if ((s->last_ping > 0 && s->last_pong < s->last_ping)
1465 || ((s->last_ping_mid = coap_session_send_ping(s)) == COAP_INVALID_TID))
1466 {
1467 /* Make sure the session object is not deleted in the callback */
1468 coap_session_reference(s);
1469 coap_session_disconnected(s, COAP_NACK_NOT_DELIVERABLE);
1470 coap_session_release(s);
1471 continue;
1472 }
1473 s->last_rx_tx = now;
1474 s->last_ping = now;
1475 }
1476 s_timeout = (s->last_rx_tx + ctx->ping_timeout * COAP_TICKS_PER_SECOND) - now;
1477 if (timeout == 0 || s_timeout < timeout)
1478 timeout = s_timeout;
1479 }
1480
1481 if (
1482 s->type == COAP_SESSION_TYPE_CLIENT
1483 && COAP_PROTO_RELIABLE(s->proto)
1484 && s->state == COAP_SESSION_STATE_CSM
1485 && ctx->csm_timeout > 0
1486 ) {
1487 coap_tick_t s_timeout;
1488 if (s->csm_tx == 0) {
1489 s->csm_tx = now;
1490 } else if (s->csm_tx + ctx->csm_timeout * COAP_TICKS_PER_SECOND <= now) {
1491 /* Make sure the session object is not deleted in the callback */
1492 coap_session_reference(s);
1493 coap_session_disconnected(s, COAP_NACK_NOT_DELIVERABLE);
1494 coap_session_release(s);
1495 continue;
1496 }
1497 s_timeout = (s->csm_tx + ctx->csm_timeout * COAP_TICKS_PER_SECOND) - now;
1498 if (timeout == 0 || s_timeout < timeout)
1499 timeout = s_timeout;
1500 }
1501 }
1502
1503 nextpdu = coap_peek_next(ctx);
1504
1505 while (nextpdu && now >= ctx->sendqueue_basetime && nextpdu->t <= now - ctx->sendqueue_basetime) {
1506 coap_retransmit(ctx, coap_pop_next(ctx));
1507 nextpdu = coap_peek_next(ctx);
1508 }
1509
1510 if (nextpdu && (timeout == 0 || nextpdu->t - ( now - ctx->sendqueue_basetime ) < timeout))
1511 timeout = nextpdu->t - (now - ctx->sendqueue_basetime);
1512
1513 #ifndef COAP_EPOLL_SUPPORT
1514 coap_updata_ep_sockets(ctx, sockets, max_sockets,num_sockets);
1515 #endif /* ! COAP_EPOLL_SUPPORT */
1516 if (ctx->dtls_context) {
1517 if (coap_dtls_is_context_timeout()) {
1518 coap_tick_t tls_timeout = coap_dtls_get_context_timeout(ctx->dtls_context);
1519 if (tls_timeout > 0) {
1520 if (tls_timeout < now + COAP_TICKS_PER_SECOND / 10)
1521 tls_timeout = now + COAP_TICKS_PER_SECOND / 10;
1522 coap_log(LOG_DEBUG, "** DTLS global timeout set to %dms\n",
1523 (int)((tls_timeout - now) * 1000 / COAP_TICKS_PER_SECOND));
1524 if (timeout == 0 || tls_timeout - now < timeout)
1525 timeout = tls_timeout - now;
1526 }
1527 } else {
1528 LL_FOREACH(ctx->endpoint, ep) {
1529 if (ep->proto == COAP_PROTO_DTLS) {
1530 SESSIONS_ITER(ep->sessions, s, rtmp) {
1531 if (s->proto == COAP_PROTO_DTLS && s->tls) {
1532 coap_tick_t tls_timeout = coap_dtls_get_timeout(s, now);
1533 while (tls_timeout > 0 && tls_timeout <= now) {
1534 coap_log(LOG_DEBUG, "** %s: DTLS retransmit timeout\n",
1535 coap_session_str(s));
1536 coap_dtls_handle_timeout(s);
1537 if (s->tls)
1538 tls_timeout = coap_dtls_get_timeout(s, now);
1539 else {
1540 tls_timeout = 0;
1541 timeout = 1;
1542 }
1543 }
1544 if (tls_timeout > 0 && (timeout == 0 || tls_timeout - now < timeout))
1545 timeout = tls_timeout - now;
1546 }
1547 }
1548 }
1549 }
1550 SESSIONS_ITER(ctx->sessions, s, rtmp) {
1551 if (s->proto == COAP_PROTO_DTLS && s->tls) {
1552 coap_tick_t tls_timeout = coap_dtls_get_timeout(s, now);
1553 while (tls_timeout > 0 && tls_timeout <= now) {
1554 coap_log(LOG_DEBUG, "** %s: DTLS retransmit timeout\n", coap_session_str(s));
1555 coap_dtls_handle_timeout(s);
1556 if (s->tls)
1557 tls_timeout = coap_dtls_get_timeout(s, now);
1558 else {
1559 tls_timeout = 0;
1560 timeout = 1;
1561 }
1562 }
1563 if (tls_timeout > 0 && (timeout == 0 || tls_timeout - now < timeout))
1564 timeout = tls_timeout - now;
1565 }
1566 }
1567 }
1568 }
1569
1570 return (unsigned int)((timeout * 1000 + COAP_TICKS_PER_SECOND - 1) / COAP_TICKS_PER_SECOND);
1571 }
1572
1573 int
1574 coap_run_once(coap_context_t *ctx, unsigned timeout_ms) {
1575 #if COAP_CONSTRAINED_STACK
1576 static coap_mutex_t static_mutex = COAP_MUTEX_INITIALIZER;
1577 # ifndef COAP_EPOLL_SUPPORT
1578 static fd_set readfds, writefds, exceptfds;
1579 static coap_socket_t *sockets[64];
1580 unsigned int num_sockets = 0;
1581 # endif /* ! COAP_EPOLL_SUPPORT */
1582 #else /* ! COAP_CONSTRAINED_STACK */
1583 # ifndef COAP_EPOLL_SUPPORT
1584 fd_set readfds, writefds, exceptfds;
1585 coap_socket_t *sockets[64];
1586 unsigned int num_sockets = 0;
1587 # endif /* ! COAP_EPOLL_SUPPORT */
1588 #endif /* ! COAP_CONSTRAINED_STACK */
1589 coap_fd_t nfds = 0;
1590 coap_tick_t before, now;
1591 unsigned int timeout;
1592 #ifndef COAP_EPOLL_SUPPORT
1593 struct timeval tv;
1594 int result;
1595 unsigned int i;
1596 #endif /* ! COAP_EPOLL_SUPPORT */
1597
1598 #if COAP_CONSTRAINED_STACK
1599 coap_mutex_lock(&static_mutex);
1600 #endif /* COAP_CONSTRAINED_STACK */
1601
1602 coap_ticks(&before);
1603
1604 #ifndef COAP_EPOLL_SUPPORT
1605 timeout = coap_write(ctx, sockets, (unsigned int)(sizeof(sockets) / sizeof(sockets[0])), &num_sockets, before);
1606 if (timeout == 0 || timeout_ms < timeout)
1607 timeout = timeout_ms;
1608
1609 FD_ZERO(&readfds);
1610 FD_ZERO(&writefds);
1611 FD_ZERO(&exceptfds);
1612 for (i = 0; i < num_sockets; i++) {
1613 if (sockets[i]->fd + 1 > nfds)
1614 nfds = sockets[i]->fd + 1;
1615 if (sockets[i]->flags & COAP_SOCKET_WANT_READ)
1616 FD_SET(sockets[i]->fd, &readfds);
1617 if (sockets[i]->flags & COAP_SOCKET_WANT_WRITE)
1618 FD_SET(sockets[i]->fd, &writefds);
1619 if (sockets[i]->flags & COAP_SOCKET_WANT_ACCEPT)
1620 FD_SET(sockets[i]->fd, &readfds);
1621 if (sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) {
1622 FD_SET(sockets[i]->fd, &writefds);
1623 FD_SET(sockets[i]->fd, &exceptfds);
1624 }
1625 }
1626
1627 if ( timeout > 0 ) {
1628 if (timeout == COAP_RUN_NONBLOCK)
1629 timeout = 0;
1630 tv.tv_usec = (timeout % 1000) * 1000;
1631 tv.tv_sec = (long)(timeout / 1000);
1632 }
1633
1634 result = select(nfds, &readfds, &writefds, &exceptfds, timeout > 0 ? &tv : NULL);
1635
1636 if (result < 0) { /* error */
1637 #ifdef _WIN32
1638 if (WSAGetLastError() != WSAEINVAL) { /* May happen because of ICMP */
1639 #else
1640 if (errno != EINTR) {
1641 #endif
1642 coap_log(LOG_DEBUG, "%s", coap_socket_strerror());
1643 #if COAP_CONSTRAINED_STACK
1644 coap_mutex_unlock(&static_mutex);
1645 #endif /* COAP_CONSTRAINED_STACK */
1646 return -1;
1647 }
1648 }
1649
1650 if (result > 0) {
1651 for (i = 0; i < num_sockets; i++) {
1652 if ((sockets[i]->flags & COAP_SOCKET_WANT_READ) && FD_ISSET(sockets[i]->fd, &readfds))
1653 sockets[i]->flags |= COAP_SOCKET_CAN_READ;
1654 if ((sockets[i]->flags & COAP_SOCKET_WANT_ACCEPT) && FD_ISSET(sockets[i]->fd, &readfds))
1655 sockets[i]->flags |= COAP_SOCKET_CAN_ACCEPT;
1656 if ((sockets[i]->flags & COAP_SOCKET_WANT_WRITE) && FD_ISSET(sockets[i]->fd, &writefds))
1657 sockets[i]->flags |= COAP_SOCKET_CAN_WRITE;
1658 if ((sockets[i]->flags & COAP_SOCKET_WANT_CONNECT) && (FD_ISSET(sockets[i]->fd, &writefds) || FD_ISSET(sockets[i]->fd, &exceptfds)))
1659 sockets[i]->flags |= COAP_SOCKET_CAN_CONNECT;
1660 }
1661 }
1662
1663 coap_ticks(&now);
1664 coap_read(ctx, now);
1665
1666 #else /* COAP_EPOLL_SUPPORT */
1667 timeout = coap_io_prepare_epoll(ctx, before);
1668
1669 if (timeout == 0 || timeout_ms < timeout)
1670 timeout = timeout_ms;
1671
1672 do {
1673 struct epoll_event events[COAP_MAX_EPOLL_EVENTS];
1674 int etimeout = timeout;
1675
1676 /* Potentially adjust based on what the caller wants */
1677 if (timeout_ms == COAP_RUN_BLOCK)
1678 etimeout = -1;
1679 else if (timeout_ms == COAP_RUN_NONBLOCK)
1680 etimeout = 0;
1681
1682 nfds = epoll_wait(ctx->epfd, events, COAP_MAX_EPOLL_EVENTS, etimeout);
1683 if (nfds < 0) {
1684 if (errno != EINTR) {
1685 coap_log (LOG_ERR, "epoll_wait: unexpected error: %s (%d)\n",
1686 coap_socket_strerror(), nfds);
1687 }
1688 break;
1689 }
1690
1691 coap_io_do_events(ctx, events, nfds);
1692
1693 /*
1694 * reset to COAP_RUN_NONBLOCK (which causes etimeout to become 0)
1695 * incase we have to do another iteration
1696 * (COAP_MAX_EPOLL_EVENTS insufficient)
1697 */
1698 timeout_ms = COAP_RUN_NONBLOCK;
1699
1700 /* Keep retrying until less than COAP_MAX_EPOLL_EVENTS are returned */
1701 } while (nfds == COAP_MAX_EPOLL_EVENTS);
1702
1703 coap_ticks(&now);
1704 #endif /* COAP_EPOLL_SUPPORT */
1705
1706 #if COAP_CONSTRAINED_STACK
1707 coap_mutex_unlock(&static_mutex);
1708 #endif /* COAP_CONSTRAINED_STACK */
1709
1710 return (int)(((now - before) * 1000) / COAP_TICKS_PER_SECOND);
1711 }
1712
1713 #else /* WITH_CONTIKI */
1714 int coap_run_once(coap_context_t *ctx, unsigned int timeout_ms) {
1715 coap_tick_t now;
1716
1717 coap_ticks(&now);
1718 /* There is something to read on the endpoint */
1719 ctx->endpoint->sock.flags |= COAP_SOCKET_CAN_READ;
1720 /* read in, and send off any responses */
1721 coap_read(ctx, now); /* read received data */
1722 return -1;
1723 }
1724
1725 unsigned int
1726 coap_write(coap_context_t *ctx,
1727 coap_socket_t *sockets[],
1728 unsigned int max_sockets,
1729 unsigned int *num_sockets,
1730 coap_tick_t now)
1731 {
1732 *num_sockets = 0;
1733 return 0;
1734 }
1735 #endif /* WITH_CONTIKI */
1736
1737 #ifdef _WIN32
1738 static const char *coap_socket_format_errno(int error) {
1739 static char szError[256];
1740 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD)error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)szError, (DWORD)sizeof(szError), NULL) == 0)
1741 strcpy(szError, "Unknown error");
1742 return szError;
1743 }
1744
1745 const char *coap_socket_strerror(void) {
1746 return coap_socket_format_errno(WSAGetLastError());
1747 }
1748 #else
1749 #ifndef WITH_CONTIKI
1750 static const char *coap_socket_format_errno(int error) {
1751 return strerror(error);
1752 }
1753 #endif /* WITH_CONTIKI */
1754
1755 const char *coap_socket_strerror(void) {
1756 return strerror(errno);
1757 }
1758 #endif
1759
1760 ssize_t
1761 coap_socket_send(coap_socket_t *sock, coap_session_t *session,
1762 const uint8_t *data, size_t data_len) {
1763 return session->context->network_send(sock, session, data, data_len);
1764 }
1765
1766 #undef SIN6
1767