libcoap  4.2.0
net.c
Go to the documentation of this file.
1 /* net.c -- CoAP network interface
2  *
3  * Copyright (C) 2010--2016 Olaf Bergmann <bergmann@tzi.org>
4  *
5  * This file is part of the CoAP library libcoap. Please see
6  * README for terms of use.
7  */
8 
9 #include "coap_config.h"
10 
11 #include <ctype.h>
12 #include <stdio.h>
13 #include <errno.h>
14 #ifdef HAVE_LIMITS_H
15 #include <limits.h>
16 #endif
17 #ifdef HAVE_UNISTD_H
18 #include <unistd.h>
19 #elif HAVE_SYS_UNISTD_H
20 #include <sys/unistd.h>
21 #endif
22 #ifdef HAVE_SYS_TYPES_H
23 #include <sys/types.h>
24 #endif
25 #ifdef HAVE_SYS_SOCKET_H
26 #include <sys/socket.h>
27 #endif
28 #ifdef HAVE_NETINET_IN_H
29 #include <netinet/in.h>
30 #endif
31 #ifdef HAVE_ARPA_INET_H
32 #include <arpa/inet.h>
33 #endif
34 #ifdef HAVE_WS2TCPIP_H
35 #include <ws2tcpip.h>
36 #endif
37 
38 #ifdef WITH_LWIP
39 #include <lwip/pbuf.h>
40 #include <lwip/udp.h>
41 #include <lwip/timeouts.h>
42 #endif
43 
44 #include "libcoap.h"
45 #include "utlist.h"
46 #include "coap_debug.h"
47 #include "mem.h"
48 #include "str.h"
49 #include "async.h"
50 #include "resource.h"
51 #include "option.h"
52 #include "encode.h"
53 #include "block.h"
54 #include "net.h"
55 #include "utlist.h"
56 
57 #ifndef min
58 #define min(a,b) ((a) < (b) ? (a) : (b))
59 #endif
60 
65 #define FRAC_BITS 6
66 
71 #define MAX_BITS 8
72 
73 #if FRAC_BITS > 8
74 #error FRAC_BITS must be less or equal 8
75 #endif
76 
78 #define Q(frac,fval) ((uint16_t)(((1 << (frac)) * fval.integer_part) + \
79  ((1 << (frac)) * fval.fractional_part + 500)/1000))
80 
82 #define ACK_RANDOM_FACTOR \
83  Q(FRAC_BITS, session->ack_random_factor)
84 
86 #define ACK_TIMEOUT Q(FRAC_BITS, session->ack_timeout)
87 
88 #if !defined(WITH_LWIP) && !defined(WITH_CONTIKI)
89 
93 }
94 
98 }
99 #endif /* !defined(WITH_LWIP) && !defined(WITH_CONTIKI) */
100 
102 
103 #ifdef WITH_LWIP
104 
105 #include <lwip/memp.h>
106 
107 static void coap_retransmittimer_execute(void *arg);
108 static void coap_retransmittimer_restart(coap_context_t *ctx);
109 
112  return (coap_queue_t *)memp_malloc(MEMP_COAP_NODE);
113 }
114 
117  memp_free(MEMP_COAP_NODE, node);
118 }
119 
120 #endif /* WITH_LWIP */
121 #ifdef WITH_CONTIKI
122 # ifndef DEBUG
123 # define DEBUG DEBUG_PRINT
124 # endif /* DEBUG */
125 
126 #include "mem.h"
127 #include "net/ip/uip-debug.h"
128 
129 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
130 #define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN])
131 
132 void coap_resources_init();
133 
134 unsigned char initialized = 0;
135 coap_context_t the_coap_context;
136 
137 PROCESS(coap_retransmit_process, "message retransmit process");
138 
142 }
143 
146  coap_free_type(COAP_NODE, node);
147 }
148 #endif /* WITH_CONTIKI */
149 
150 unsigned int
152  unsigned int result = 0;
153  coap_tick_diff_t delta = now - ctx->sendqueue_basetime;
154 
155  if (ctx->sendqueue) {
156  /* delta < 0 means that the new time stamp is before the old. */
157  if (delta <= 0) {
158  ctx->sendqueue->t -= delta;
159  } else {
160  /* This case is more complex: The time must be advanced forward,
161  * thus possibly leading to timed out elements at the queue's
162  * start. For every element that has timed out, its relative
163  * time is set to zero and the result counter is increased. */
164 
165  coap_queue_t *q = ctx->sendqueue;
166  coap_tick_t t = 0;
167  while (q && (t + q->t < (coap_tick_t)delta)) {
168  t += q->t;
169  q->t = 0;
170  result++;
171  q = q->next;
172  }
173 
174  /* finally adjust the first element that has not expired */
175  if (q) {
176  q->t = (coap_tick_t)delta - t;
177  }
178  }
179  }
180 
181  /* adjust basetime */
182  ctx->sendqueue_basetime += delta;
183 
184  return result;
185 }
186 
187 int
189  coap_queue_t *p, *q;
190  if (!queue || !node)
191  return 0;
192 
193  /* set queue head if empty */
194  if (!*queue) {
195  *queue = node;
196  return 1;
197  }
198 
199  /* replace queue head if PDU's time is less than head's time */
200  q = *queue;
201  if (node->t < q->t) {
202  node->next = q;
203  *queue = node;
204  q->t -= node->t; /* make q->t relative to node->t */
205  return 1;
206  }
207 
208  /* search for right place to insert */
209  do {
210  node->t -= q->t; /* make node-> relative to q->t */
211  p = q;
212  q = q->next;
213  } while (q && q->t <= node->t);
214 
215  /* insert new item */
216  if (q) {
217  q->t -= node->t; /* make q->t relative to node->t */
218  }
219  node->next = q;
220  p->next = node;
221  return 1;
222 }
223 
224 int
226  if (!node)
227  return 0;
228 
229  coap_delete_pdu(node->pdu);
230  if ( node->session ) {
231  /*
232  * Need to remove out of context->sendqueue as added in by coap_wait_ack()
233  */
234  if (node->session->context->sendqueue) {
235  LL_DELETE(node->session->context->sendqueue, node);
236  }
238  }
239  coap_free_node(node);
240 
241  return 1;
242 }
243 
244 void
246  if (!queue)
247  return;
248 
249  coap_delete_all(queue->next);
250  coap_delete_node(queue);
251 }
252 
253 coap_queue_t *
255  coap_queue_t *node;
256  node = coap_malloc_node();
257 
258  if (!node) {
259 #ifndef NDEBUG
260  coap_log(LOG_WARNING, "coap_new_node: malloc\n");
261 #endif
262  return NULL;
263  }
264 
265  memset(node, 0, sizeof(*node));
266  return node;
267 }
268 
269 coap_queue_t *
271  if (!context || !context->sendqueue)
272  return NULL;
273 
274  return context->sendqueue;
275 }
276 
277 coap_queue_t *
279  coap_queue_t *next;
280 
281  if (!context || !context->sendqueue)
282  return NULL;
283 
284  next = context->sendqueue;
285  context->sendqueue = context->sendqueue->next;
286  if (context->sendqueue) {
287  context->sendqueue->t += next->t;
288  }
289  next->next = NULL;
290  return next;
291 }
292 
293 static size_t
295  const coap_session_t *session,
296  const uint8_t *hint, size_t hint_len,
297  uint8_t *identity, size_t *identity_len, size_t max_identity_len,
298  uint8_t *psk, size_t max_psk_len
299 ) {
300  (void)hint;
301  (void)hint_len;
302  if (session->psk_identity && session->psk_identity_len > 0 && session->psk_key && session->psk_key_len > 0) {
303  if (session->psk_identity_len <= max_identity_len && session->psk_key_len <= max_psk_len) {
304  memcpy(identity, session->psk_identity, session->psk_identity_len);
305  memcpy(psk, session->psk_key, session->psk_key_len);
306  *identity_len = session->psk_identity_len;
307  return session->psk_key_len;
308  }
309  } else if (session->context && session->context->psk_key && session->context->psk_key_len > 0) {
310  if (session->context->psk_key_len <= max_psk_len) {
311  *identity_len = 0;
312  memcpy(psk, session->context->psk_key, session->context->psk_key_len);
313  return session->context->psk_key_len;
314  }
315  }
316  *identity_len = 0;
317  return 0;
318 }
319 
320 static size_t
322  const coap_session_t *session,
323  const uint8_t *identity, size_t identity_len,
324  uint8_t *psk, size_t max_psk_len
325 ) {
326  (void)identity;
327  (void)identity_len;
328  const coap_context_t *ctx = session->context;
329  if (ctx && ctx->psk_key && ctx->psk_key_len > 0 && ctx->psk_key_len <= max_psk_len) {
330  memcpy(psk, ctx->psk_key, ctx->psk_key_len);
331  return ctx->psk_key_len;
332  }
333  return 0;
334 }
335 
336 static size_t
338  const coap_session_t *session,
339  uint8_t *hint, size_t max_hint_len
340 ) {
341  const coap_context_t *ctx = session->context;
342  if (ctx && ctx->psk_hint && ctx->psk_hint_len > 0 && ctx->psk_hint_len <= max_hint_len) {
343  memcpy(hint, ctx->psk_hint, ctx->psk_hint_len);
344  return ctx->psk_hint_len;
345  }
346  return 0;
347 }
348 
350  const char *hint,
351  const uint8_t *key, size_t key_len
352 ) {
353 
354  if (ctx->psk_hint)
355  coap_free(ctx->psk_hint);
356  ctx->psk_hint = NULL;
357  ctx->psk_hint_len = 0;
358 
359  if (hint) {
360  size_t hint_len = strlen(hint);
361  ctx->psk_hint = (uint8_t*)coap_malloc(hint_len);
362  if (ctx->psk_hint) {
363  memcpy(ctx->psk_hint, hint, hint_len);
364  ctx->psk_hint_len = hint_len;
365  } else {
366  coap_log(LOG_ERR, "No memory to store PSK hint\n");
367  return 0;
368  }
369  }
370 
371  if (ctx->psk_key)
372  coap_free(ctx->psk_key);
373  ctx->psk_key = NULL;
374  ctx->psk_key_len = 0;
375 
376  if (key && key_len > 0) {
377  ctx->psk_key = (uint8_t *)coap_malloc(key_len);
378  if (ctx->psk_key) {
379  memcpy(ctx->psk_key, key, key_len);
380  ctx->psk_key_len = key_len;
381  } else {
382  coap_log(LOG_ERR, "No memory to store PSK key\n");
383  return 0;
384  }
385  }
386  if (coap_dtls_is_supported()) {
388  }
389  return 0;
390 }
391 
393  coap_dtls_pki_t* setup_data
394 ) {
395  if (!setup_data)
396  return 0;
397  if (setup_data->version != COAP_DTLS_PKI_SETUP_VERSION) {
398  coap_log(LOG_ERR, "coap_context_set_pki: Wrong version of setup_data\n");
399  return 0;
400  }
401  if (coap_dtls_is_supported()) {
402  return coap_dtls_context_set_pki(ctx, setup_data, COAP_DTLS_ROLE_SERVER);
403  }
404  return 0;
405 }
406 
408  const char *ca_file,
409  const char *ca_dir
410 ) {
411  if (coap_dtls_is_supported()) {
412  return coap_dtls_context_set_pki_root_cas(ctx, ca_file, ca_dir);
413  }
414  return 0;
415 }
416 
417 void coap_context_set_keepalive(coap_context_t *context, unsigned int seconds) {
418  context->ping_timeout = seconds;
419 }
420 
423  const coap_address_t *listen_addr) {
424  coap_context_t *c;
425 
426 #ifdef WITH_CONTIKI
427  if (initialized)
428  return NULL;
429 #endif /* WITH_CONTIKI */
430 
431  coap_startup();
432 
433 #ifndef WITH_CONTIKI
435 #endif /* not WITH_CONTIKI */
436 
437 #ifndef WITH_CONTIKI
438  if (!c) {
439 #ifndef NDEBUG
440  coap_log(LOG_EMERG, "coap_init: malloc:\n");
441 #endif
442  return NULL;
443  }
444 #endif /* not WITH_CONTIKI */
445 #ifdef WITH_CONTIKI
446  coap_resources_init();
448 
449  c = &the_coap_context;
450  initialized = 1;
451 #endif /* WITH_CONTIKI */
452 
453  memset(c, 0, sizeof(coap_context_t));
454 
455  if (coap_dtls_is_supported()) {
457  if (!c->dtls_context) {
458  coap_log(LOG_EMERG, "coap_init: no DTLS context available\n");
460  return NULL;
461  }
462  }
463 
464  /* set default CSM timeout */
465  c->csm_timeout = 30;
466 
467  /* initialize message id */
468  prng((unsigned char *)&c->message_id, sizeof(uint16_t));
469 
470  if (listen_addr) {
471  coap_endpoint_t *endpoint = coap_new_endpoint(c, listen_addr, COAP_PROTO_UDP);
472  if (endpoint == NULL) {
473  goto onerror;
474  }
475  }
476 
477 #if !defined(WITH_LWIP)
480 #endif
481 
485 
486 #ifdef WITH_CONTIKI
487  process_start(&coap_retransmit_process, (char *)c);
488 
489  PROCESS_CONTEXT_BEGIN(&coap_retransmit_process);
490 #ifndef WITHOUT_OBSERVE
491  etimer_set(&c->notify_timer, COAP_RESOURCE_CHECK_TIME * COAP_TICKS_PER_SECOND);
492 #endif /* WITHOUT_OBSERVE */
493  /* the retransmit timer must be initialized to some large value */
494  etimer_set(&the_coap_context.retransmit_timer, 0xFFFF);
495  PROCESS_CONTEXT_END(&coap_retransmit_process);
496 #endif /* WITH_CONTIKI */
497 
498  return c;
499 
500 onerror:
502  return NULL;
503 }
504 
505 void
506 coap_set_app_data(coap_context_t *ctx, void *app_data) {
507  assert(ctx);
508  ctx->app = app_data;
509 }
510 
511 void *
513  assert(ctx);
514  return ctx->app;
515 }
516 
517 void
519  coap_endpoint_t *ep, *tmp;
520  coap_session_t *sp, *stmp;
521 
522  if (!context)
523  return;
524 
525  coap_delete_all(context->sendqueue);
526 
527 #ifdef WITH_LWIP
528  context->sendqueue = NULL;
529  coap_retransmittimer_restart(context);
530 #endif
531 
532  coap_delete_all_resources(context);
533 
534  LL_FOREACH_SAFE(context->endpoint, ep, tmp) {
535  coap_free_endpoint(ep);
536  }
537 
538  LL_FOREACH_SAFE(context->sessions, sp, stmp) {
540  }
541 
542  if (context->dtls_context)
544 
545  if (context->psk_hint)
546  coap_free(context->psk_hint);
547 
548  if (context->psk_key)
549  coap_free(context->psk_key);
550 
551 #ifndef WITH_CONTIKI
552  coap_free_type(COAP_CONTEXT, context);
553 #endif/* not WITH_CONTIKI */
554 #ifdef WITH_CONTIKI
555  memset(&the_coap_context, 0, sizeof(coap_context_t));
556  initialized = 0;
557 #endif /* WITH_CONTIKI */
558 }
559 
560 int
562  coap_pdu_t *pdu,
563  coap_opt_filter_t unknown) {
564 
565  coap_opt_iterator_t opt_iter;
566  int ok = 1;
567 
568  coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL);
569 
570  while (coap_option_next(&opt_iter)) {
571 
572  /* The following condition makes use of the fact that
573  * coap_option_getb() returns -1 if type exceeds the bit-vector
574  * filter. As the vector is supposed to be large enough to hold
575  * the largest known option, we know that everything beyond is
576  * bad.
577  */
578  if (opt_iter.type & 0x01) {
579  /* first check the built-in critical options */
580  switch (opt_iter.type) {
587  case COAP_OPTION_ACCEPT:
590  case COAP_OPTION_BLOCK2:
591  case COAP_OPTION_BLOCK1:
592  break;
593  default:
594  if (coap_option_filter_get(ctx->known_options, opt_iter.type) <= 0) {
595  coap_log(LOG_DEBUG, "unknown critical option %d\n", opt_iter.type);
596  ok = 0;
597 
598  /* When opt_iter.type is beyond our known option range,
599  * coap_option_filter_set() will return -1 and we are safe to leave
600  * this loop. */
601  if (coap_option_filter_set(unknown, opt_iter.type) == -1) {
602  break;
603  }
604  }
605  }
606  }
607  }
608 
609  return ok;
610 }
611 
614  coap_pdu_t *response;
615  coap_tid_t result = COAP_INVALID_TID;
616 
617  if (request && request->type == COAP_MESSAGE_CON &&
618  COAP_PROTO_NOT_RELIABLE(session->proto)) {
619  response = coap_pdu_init(COAP_MESSAGE_ACK, 0, request->tid, 0);
620  if (response)
621  result = coap_send(session, response);
622  }
623  return result;
624 }
625 
626 ssize_t
628  ssize_t bytes_written = -1;
629  assert(pdu->hdr_size > 0);
630  switch(session->proto) {
631  case COAP_PROTO_UDP:
632  bytes_written = coap_session_send(session, pdu->token - pdu->hdr_size,
633  pdu->used_size + pdu->hdr_size);
634  break;
635  case COAP_PROTO_DTLS:
636  bytes_written = coap_dtls_send(session, pdu->token - pdu->hdr_size,
637  pdu->used_size + pdu->hdr_size);
638  break;
639  case COAP_PROTO_TCP:
640  bytes_written = coap_session_write(session, pdu->token - pdu->hdr_size,
641  pdu->used_size + pdu->hdr_size);
642  break;
643  case COAP_PROTO_TLS:
644  bytes_written = coap_tls_write(session, pdu->token - pdu->hdr_size,
645  pdu->used_size + pdu->hdr_size);
646  break;
647  default:
648  break;
649  }
650  coap_show_pdu(LOG_DEBUG, pdu);
651  return bytes_written;
652 }
653 
654 static ssize_t
656  ssize_t bytes_written;
657 
658 #ifdef WITH_LWIP
659 
660  coap_socket_t *sock = &session->sock;
661  if (sock->flags == COAP_SOCKET_EMPTY) {
662  assert(session->endpoint != NULL);
663  sock = &session->endpoint->sock;
664  }
665  if (pdu->type == COAP_MESSAGE_CON && COAP_PROTO_NOT_RELIABLE(session->proto))
666  session->con_active++;
667 
668  bytes_written = coap_socket_send_pdu(sock, session, pdu);
669  if (LOG_DEBUG <= coap_get_log_level()) {
670  coap_show_pdu(LOG_DEBUG, pdu);
671  }
672  coap_ticks(&session->last_rx_tx);
673 
674 #else
675 
676  /* Do not send error responses for requests that were received via
677  * IP multicast.
678  * FIXME: If No-Response option indicates interest, these responses
679  * must not be dropped. */
680  if (coap_is_mcast(&session->local_addr) &&
681  COAP_RESPONSE_CLASS(pdu->code) > 2) {
682  return COAP_DROPPED_RESPONSE;
683  }
684 
685  if (session->state == COAP_SESSION_STATE_NONE) {
686  if (session->proto == COAP_PROTO_DTLS && !session->tls) {
687  session->tls = coap_dtls_new_client_session(session);
688  if (session->tls) {
690  return coap_session_delay_pdu(session, pdu, node);
691  }
692  coap_handle_event(session->context, COAP_EVENT_DTLS_ERROR, session);
693  return -1;
694  } else if(COAP_PROTO_RELIABLE(session->proto)) {
696  &session->sock, &session->local_if, &session->remote_addr,
698  &session->local_addr, &session->remote_addr
699  )) {
700  coap_handle_event(session->context, COAP_EVENT_TCP_FAILED, session);
701  return -1;
702  }
703  session->last_ping = 0;
704  session->last_pong = 0;
705  session->csm_tx = 0;
706  coap_ticks( &session->last_rx_tx );
707  if ((session->sock.flags & COAP_SOCKET_WANT_CONNECT) != 0) {
709  return coap_session_delay_pdu(session, pdu, node);
710  }
712  if (session->proto == COAP_PROTO_TLS) {
713  int connected = 0;
715  session->tls = coap_tls_new_client_session(session, &connected);
716  if (session->tls) {
717  if (connected) {
719  coap_session_send_csm(session);
720  }
721  return coap_session_delay_pdu(session, pdu, node);
722  }
723  coap_handle_event(session->context, COAP_EVENT_DTLS_ERROR, session);
725  return -1;
726  } else {
727  coap_session_send_csm(session);
728  }
729  } else {
730  return -1;
731  }
732  }
733 
734  if (session->state != COAP_SESSION_STATE_ESTABLISHED ||
735  (pdu->type == COAP_MESSAGE_CON && session->con_active >= COAP_DEFAULT_NSTART)) {
736  return coap_session_delay_pdu(session, pdu, node);
737  }
738 
739  if ((session->sock.flags & COAP_SOCKET_NOT_EMPTY) &&
740  (session->sock.flags & COAP_SOCKET_WANT_WRITE))
741  return coap_session_delay_pdu(session, pdu, node);
742 
743  if (pdu->type == COAP_MESSAGE_CON && COAP_PROTO_NOT_RELIABLE(session->proto))
744  session->con_active++;
745 
746  bytes_written = coap_session_send_pdu(session, pdu);
747 
748 #endif /* WITH_LWIP */
749 
750  return bytes_written;
751 }
752 
755  coap_pdu_t *request,
756  unsigned char code,
757  coap_opt_filter_t opts) {
758  coap_pdu_t *response;
759  coap_tid_t result = COAP_INVALID_TID;
760 
761  assert(request);
762  assert(session);
763 
764  response = coap_new_error_response(request, code, opts);
765  if (response)
766  result = coap_send(session, response);
767 
768  return result;
769 }
770 
772 coap_send_message_type(coap_session_t *session, coap_pdu_t *request, unsigned char type) {
773  coap_pdu_t *response;
774  coap_tid_t result = COAP_INVALID_TID;
775 
776  if (request) {
777  response = coap_pdu_init(type, 0, request->tid, 0);
778  if (response)
779  result = coap_send(session, response);
780  }
781  return result;
782 }
783 
797 unsigned int
798 coap_calc_timeout(coap_session_t *session, unsigned char r) {
799  unsigned int result;
800 
801  /* The integer 1.0 as a Qx.FRAC_BITS */
802 #define FP1 Q(FRAC_BITS, ((coap_fixed_point_t){1,0}))
803 
804  /* rounds val up and right shifts by frac positions */
805 #define SHR_FP(val,frac) (((val) + (1 << ((frac) - 1))) >> (frac))
806 
807  /* Inner term: multiply ACK_RANDOM_FACTOR by Q0.MAX_BITS[r] and
808  * make the result a rounded Qx.FRAC_BITS */
809  result = SHR_FP((ACK_RANDOM_FACTOR - FP1) * r, MAX_BITS);
810 
811  /* Add 1 to the inner term and multiply with ACK_TIMEOUT, then
812  * make the result a rounded Qx.FRAC_BITS */
813  result = SHR_FP(((result + FP1) * ACK_TIMEOUT), FRAC_BITS);
814 
815  /* Multiply with COAP_TICKS_PER_SECOND to yield system ticks
816  * (yields a Qx.FRAC_BITS) and shift to get an integer */
817  return SHR_FP((COAP_TICKS_PER_SECOND * result), FRAC_BITS);
818 
819 #undef FP1
820 #undef SHR_FP
821 }
822 
825  coap_queue_t *node) {
826  coap_tick_t now;
827 
828  node->session = coap_session_reference(session);
829 
830  /* Set timer for pdu retransmission. If this is the first element in
831  * the retransmission queue, the base time is set to the current
832  * time and the retransmission time is node->timeout. If there is
833  * already an entry in the sendqueue, we must check if this node is
834  * to be retransmitted earlier. Therefore, node->timeout is first
835  * normalized to the base time and then inserted into the queue with
836  * an adjusted relative time.
837  */
838  coap_ticks(&now);
839  if (context->sendqueue == NULL) {
840  node->t = node->timeout;
841  context->sendqueue_basetime = now;
842  } else {
843  /* make node->t relative to context->sendqueue_basetime */
844  node->t = (now - context->sendqueue_basetime) + node->timeout;
845  }
846 
847  coap_insert_node(&context->sendqueue, node);
848 
849 #ifdef WITH_LWIP
850  if (node == context->sendqueue) /* don't bother with timer stuff if there are earlier retransmits */
851  coap_retransmittimer_restart(context);
852 #endif
853 
854 #ifdef WITH_CONTIKI
855  { /* (re-)initialize retransmission timer */
856  coap_queue_t *nextpdu;
857 
858  nextpdu = coap_peek_next(context);
859  assert(nextpdu); /* we have just inserted a node */
860 
861  /* must set timer within the context of the retransmit process */
862  PROCESS_CONTEXT_BEGIN(&coap_retransmit_process);
863  etimer_set(&context->retransmit_timer, nextpdu->t);
864  PROCESS_CONTEXT_END(&coap_retransmit_process);
865  }
866 #endif /* WITH_CONTIKI */
867 
868  coap_log(LOG_DEBUG, "** %s: tid=%d added to retransmit queue (%ums)\n",
869  coap_session_str(node->session), node->id,
870  (unsigned)(node->t * 1000 / COAP_TICKS_PER_SECOND));
871 
872  return node->id;
873 }
874 
877  uint8_t r;
878  ssize_t bytes_written;
879 
880  if (!coap_pdu_encode_header(pdu, session->proto)) {
881  goto error;
882  }
883 
884  bytes_written = coap_send_pdu( session, pdu, NULL );
885 
886  if (bytes_written == COAP_PDU_DELAYED) {
887  /* do not free pdu as it is stored with session for later use */
888  return pdu->tid;
889  }
890 
891  if (bytes_written < 0) {
892  coap_delete_pdu(pdu);
893  return (coap_tid_t)bytes_written;
894  }
895 
896  if (COAP_PROTO_RELIABLE(session->proto) &&
897  (size_t)bytes_written < pdu->used_size + pdu->hdr_size) {
898  if (coap_session_delay_pdu(session, pdu, NULL) == COAP_PDU_DELAYED) {
899  session->partial_write = (size_t)bytes_written;
900  /* do not free pdu as it is stored with session for later use */
901  return pdu->tid;
902  } else {
903  goto error;
904  }
905  }
906 
907  if (pdu->type != COAP_MESSAGE_CON || COAP_PROTO_RELIABLE(session->proto)) {
908  coap_tid_t id = pdu->tid;
909  coap_delete_pdu(pdu);
910  return id;
911  }
912 
913  coap_queue_t *node = coap_new_node();
914  if (!node) {
915  coap_log(LOG_DEBUG, "coap_wait_ack: insufficient memory\n");
916  goto error;
917  }
918 
919  node->id = pdu->tid;
920  node->pdu = pdu;
921  prng(&r, sizeof(r));
922  /* add timeout in range [ACK_TIMEOUT...ACK_TIMEOUT * ACK_RANDOM_FACTOR] */
923  node->timeout = coap_calc_timeout(session, r);
924  return coap_wait_ack(session->context, session, node);
925  error:
926  coap_delete_pdu(pdu);
927  return COAP_INVALID_TID;
928 }
929 
932  if (!context || !node)
933  return COAP_INVALID_TID;
934 
935  /* re-initialize timeout when maximum number of retransmissions are not reached yet */
936  if (node->retransmit_cnt < node->session->max_retransmit) {
937  ssize_t bytes_written;
938  coap_tick_t now;
939 
940  node->retransmit_cnt++;
941  coap_ticks(&now);
942  if (context->sendqueue == NULL) {
943  node->t = node->timeout << node->retransmit_cnt;
944  context->sendqueue_basetime = now;
945  } else {
946  /* make node->t relative to context->sendqueue_basetime */
947  node->t = (now - context->sendqueue_basetime) + (node->timeout << node->retransmit_cnt);
948  }
949  coap_insert_node(&context->sendqueue, node);
950 #ifdef WITH_LWIP
951  if (node == context->sendqueue) /* don't bother with timer stuff if there are earlier retransmits */
952  coap_retransmittimer_restart(context);
953 #endif
954 
955  coap_log(LOG_DEBUG, "** %s: tid=%d: retransmission #%d\n",
956  coap_session_str(node->session), node->id, node->retransmit_cnt);
957 
958  if (node->session->con_active)
959  node->session->con_active--;
960  bytes_written = coap_send_pdu(node->session, node->pdu, node);
961 
962  if (bytes_written == COAP_PDU_DELAYED) {
963  /* PDU was not retransmitted immediately because a new handshake is
964  in progress. node was moved to the send queue of the session. */
965  return node->id;
966  }
967 
968  if (bytes_written < 0)
969  return (int)bytes_written;
970 
971  return node->id;
972  }
973 
974  /* no more retransmissions, remove node from system */
975 
976 #ifndef WITH_CONTIKI
977  coap_log(LOG_DEBUG, "** %s: tid=%d: give up after %d attempts\n",
978  coap_session_str(node->session), node->id, node->retransmit_cnt);
979 #endif
980 
981 #ifndef WITHOUT_OBSERVE
982  /* Check if subscriptions exist that should be canceled after
983  COAP_MAX_NOTIFY_FAILURES */
984  if (node->pdu->code >= 64) {
985  coap_binary_t token = { 0, NULL };
986 
987  token.length = node->pdu->token_length;
988  token.s = node->pdu->token;
989 
990  coap_handle_failed_notify(context, node->session, &token);
991  }
992 #endif /* WITHOUT_OBSERVE */
993  if (node->session->con_active) {
994  node->session->con_active--;
996  /*
997  * As there may be another CON in a different queue entry on the same
998  * session that needs to be immediately released,
999  * coap_session_connected() is called.
1000  * However, there is the possibility coap_wait_ack() may be called for
1001  * this node (queue) and re-added to context->sendqueue.
1002  * coap_delete_node(node) called shortly will handle this and remove it.
1003  */
1005  }
1006  }
1007 
1008  /* And finally delete the node */
1009  if (node->pdu->type == COAP_MESSAGE_CON && context->nack_handler)
1010  context->nack_handler(context, node->session, node->pdu, COAP_NACK_TOO_MANY_RETRIES, node->id);
1011  coap_delete_node(node);
1012  return COAP_INVALID_TID;
1013 }
1014 
1015 #ifdef WITH_LWIP
1016 /* WITH_LWIP, this is handled by coap_recv in a different way */
1017 void
1019  return;
1020 }
1021 #else /* WITH_LWIP */
1022 
1023 static int
1025  uint8_t *data;
1026  size_t data_len;
1027  int result = -1;
1028 
1029  coap_packet_get_memmapped(packet, &data, &data_len);
1030 
1031  if (session->proto == COAP_PROTO_DTLS) {
1032  if (session->type == COAP_SESSION_TYPE_HELLO)
1033  result = coap_dtls_hello(session, data, data_len);
1034  else if (session->tls)
1035  result = coap_dtls_receive(session, data, data_len);
1036  } else if (session->proto == COAP_PROTO_UDP) {
1037  result = coap_handle_dgram(ctx, session, data, data_len);
1038  }
1039  return result;
1040 }
1041 
1042 static void
1044  (void)ctx;
1045  if (coap_socket_connect_tcp2(&session->sock, &session->local_addr, &session->remote_addr)) {
1046  session->last_rx_tx = now;
1048  if (session->proto == COAP_PROTO_TCP) {
1049  coap_session_send_csm(session);
1050  } else if (session->proto == COAP_PROTO_TLS) {
1051  int connected = 0;
1053  session->tls = coap_tls_new_client_session(session, &connected);
1054  if (session->tls) {
1055  if (connected) {
1057  coap_session_send_csm(session);
1058  }
1059  } else {
1060  coap_handle_event(session->context, COAP_EVENT_DTLS_ERROR, session);
1062  }
1063  }
1064  } else {
1065  coap_handle_event(session->context, COAP_EVENT_TCP_FAILED, session);
1067  }
1068 }
1069 
1070 static void
1072  (void)ctx;
1073  assert(session->sock.flags & COAP_SOCKET_CONNECTED);
1074 
1075  while (session->delayqueue) {
1076  ssize_t bytes_written;
1077  coap_queue_t *q = session->delayqueue;
1078  coap_log(LOG_DEBUG, "** %s: tid=%d: transmitted after delay\n",
1079  coap_session_str(session), (int)q->pdu->tid);
1080  assert(session->partial_write < q->pdu->used_size + q->pdu->hdr_size);
1081  switch (session->proto) {
1082  case COAP_PROTO_TCP:
1083  bytes_written = coap_session_write(
1084  session,
1085  q->pdu->token - q->pdu->hdr_size - session->partial_write,
1086  q->pdu->used_size + q->pdu->hdr_size - session->partial_write
1087  );
1088  break;
1089  case COAP_PROTO_TLS:
1090  bytes_written = coap_tls_write(
1091  session,
1092  q->pdu->token - q->pdu->hdr_size - session->partial_write,
1093  q->pdu->used_size + q->pdu->hdr_size - session->partial_write
1094  );
1095  break;
1096  default:
1097  bytes_written = -1;
1098  break;
1099  }
1100  if (bytes_written > 0)
1101  session->last_rx_tx = now;
1102  if (bytes_written <= 0 || (size_t)bytes_written < q->pdu->used_size + q->pdu->hdr_size - session->partial_write) {
1103  if (bytes_written > 0)
1104  session->partial_write += (size_t)bytes_written;
1105  break;
1106  }
1107  session->delayqueue = q->next;
1108  session->partial_write = 0;
1109  coap_delete_node(q);
1110  }
1111 }
1112 
1113 #ifdef WITH_CONTIKI
1115 coap_malloc_packet(void) {
1117 }
1118 
1119 void
1120 coap_free_packet(coap_packet_t *packet) {
1121  coap_free_type(COAP_PACKET, packet);
1122 }
1123 #endif /* WITH_CONTIKI */
1124 
1125 static void
1127 #ifdef WITH_CONTIKI
1128  coap_packet_t *packet = coap_malloc_packet();
1129  if ( !packet )
1130  return;
1131 #else /* WITH_CONTIKI */
1132  coap_packet_t s_packet;
1133  coap_packet_t *packet = &s_packet;
1134 #endif /* WITH_CONTIKI */
1135 
1137 
1138  if (COAP_PROTO_NOT_RELIABLE(session->proto)) {
1139  ssize_t bytes_read;
1140  coap_address_copy(&packet->src, &session->remote_addr);
1141  coap_address_copy(&packet->dst, &session->local_addr);
1142  bytes_read = ctx->network_read(&session->sock, packet);
1143 
1144  if (bytes_read < 0) {
1145  if (bytes_read == -2)
1147  else
1148  coap_log(LOG_WARNING, "* %s: read error\n",
1149  coap_session_str(session));
1150  } else if (bytes_read > 0) {
1151  coap_log(LOG_DEBUG, "* %s: received %zd bytes\n",
1152  coap_session_str(session), bytes_read);
1153  session->last_rx_tx = now;
1154  coap_packet_set_addr(packet, &session->remote_addr, &session->local_addr);
1155  coap_handle_dgram_for_proto(ctx, session, packet);
1156  }
1157  } else {
1158  ssize_t bytes_read = 0;
1159  const uint8_t *p;
1160  int retry;
1161  /* adjust for LWIP */
1162  uint8_t *buf = packet->payload;
1163  size_t buf_len = sizeof(packet->payload);
1164 
1165  do {
1166  if (session->proto == COAP_PROTO_TCP)
1167  bytes_read = coap_socket_read(&session->sock, buf, buf_len);
1168  else if (session->proto == COAP_PROTO_TLS)
1169  bytes_read = coap_tls_read(session, buf, buf_len);
1170  if (bytes_read > 0) {
1171  coap_log(LOG_DEBUG, "* %s: received %zd bytes\n",
1172  coap_session_str(session), bytes_read);
1173  session->last_rx_tx = now;
1174  }
1175  p = buf;
1176  retry = bytes_read == (ssize_t)buf_len;
1177  while (bytes_read > 0) {
1178  if (session->partial_pdu) {
1179  size_t len = session->partial_pdu->used_size
1180  + session->partial_pdu->hdr_size
1181  - session->partial_read;
1182  size_t n = min(len, (size_t)bytes_read);
1183  memcpy(session->partial_pdu->token - session->partial_pdu->hdr_size
1184  + session->partial_read, p, n);
1185  p += n;
1186  bytes_read -= n;
1187  if (n == len) {
1188  if (coap_pdu_parse_header(session->partial_pdu, session->proto)
1189  && coap_pdu_parse_opt(session->partial_pdu)) {
1190  coap_dispatch(ctx, session, session->partial_pdu);
1191  }
1192  coap_delete_pdu(session->partial_pdu);
1193  session->partial_pdu = NULL;
1194  session->partial_read = 0;
1195  } else {
1196  session->partial_read += n;
1197  }
1198  } else if (session->partial_read > 0) {
1199  size_t hdr_size = coap_pdu_parse_header_size(session->proto,
1200  session->read_header);
1201  size_t len = hdr_size - session->partial_read;
1202  size_t n = min(len, (size_t)bytes_read);
1203  memcpy(session->read_header + session->partial_read, p, n);
1204  p += n;
1205  bytes_read -= n;
1206  if (n == len) {
1207  size_t size = coap_pdu_parse_size(session->proto, session->read_header,
1208  hdr_size);
1209  session->partial_pdu = coap_pdu_init(0, 0, 0, size);
1210  if (session->partial_pdu == NULL) {
1211  bytes_read = -1;
1212  break;
1213  }
1214  if (session->partial_pdu->alloc_size < size && !coap_pdu_resize(session->partial_pdu, size)) {
1215  bytes_read = -1;
1216  break;
1217  }
1218  session->partial_pdu->hdr_size = (uint8_t)hdr_size;
1219  session->partial_pdu->used_size = size;
1220  memcpy(session->partial_pdu->token - hdr_size, session->read_header, hdr_size);
1221  session->partial_read = hdr_size;
1222  if (size == 0) {
1223  if (coap_pdu_parse_header(session->partial_pdu, session->proto)) {
1224  coap_dispatch(ctx, session, session->partial_pdu);
1225  }
1226  coap_delete_pdu(session->partial_pdu);
1227  session->partial_pdu = NULL;
1228  session->partial_read = 0;
1229  }
1230  } else {
1231  session->partial_read += bytes_read;
1232  }
1233  } else {
1234  session->read_header[0] = *p++;
1235  bytes_read -= 1;
1236  if (!coap_pdu_parse_header_size(session->proto,
1237  session->read_header)) {
1238  bytes_read = -1;
1239  break;
1240  }
1241  session->partial_read = 1;
1242  }
1243  }
1244  } while (bytes_read == 0 && retry);
1245  if (bytes_read < 0)
1247  }
1248 
1249 #ifdef WITH_CONTIKI
1250  if ( packet )
1251  coap_free_packet( packet );
1252 #endif
1253 }
1254 
1255 static int
1257  ssize_t bytes_read = -1;
1258  int result = -1; /* the value to be returned */
1259 #ifdef WITH_CONTIKI
1260  coap_packet_t *packet = coap_malloc_packet();
1261 #else /* WITH_CONTIKI */
1262  coap_packet_t s_packet;
1263  coap_packet_t *packet = &s_packet;
1264 #endif /* WITH_CONTIKI */
1265 
1266  assert(COAP_PROTO_NOT_RELIABLE(endpoint->proto));
1267  assert(endpoint->sock.flags & COAP_SOCKET_BOUND);
1268 
1269  if (packet) {
1270  coap_address_init(&packet->src);
1271  coap_address_copy(&packet->dst, &endpoint->bind_addr);
1272  bytes_read = ctx->network_read(&endpoint->sock, packet);
1273  }
1274  else {
1275  coap_log(LOG_WARNING, "* %s: Packet allocation failed\n",
1276  coap_endpoint_str(endpoint));
1277  return -1;
1278  }
1279 
1280  if (bytes_read < 0) {
1281  coap_log(LOG_WARNING, "* %s: read failed\n", coap_endpoint_str(endpoint));
1282  } else if (bytes_read > 0) {
1283  coap_session_t *session = coap_endpoint_get_session(endpoint, packet, now);
1284  if (session) {
1285  coap_log(LOG_DEBUG, "* %s: received %zd bytes\n",
1286  coap_session_str(session), bytes_read);
1287  result = coap_handle_dgram_for_proto(ctx, session, packet);
1288  if (endpoint->proto == COAP_PROTO_DTLS && session->type == COAP_SESSION_TYPE_HELLO && result == 1)
1289  coap_endpoint_new_dtls_session(endpoint, packet, now);
1290  }
1291  }
1292 
1293 #ifdef WITH_CONTIKI
1294  if (packet)
1295  coap_free_packet(packet);
1296 #endif
1297 
1298  return result;
1299 }
1300 
1301 static int
1303  (void)ctx;
1304  (void)endpoint;
1305  (void)now;
1306  return 0;
1307 }
1308 
1309 static int
1311  coap_tick_t now) {
1312  coap_session_t *session = coap_new_server_session(ctx, endpoint);
1313  if (session)
1314  session->last_rx_tx = now;
1315  return session != NULL;
1316 }
1317 
1318 void
1320  coap_endpoint_t *ep, *tmp;
1321  coap_session_t *s, *tmp_s;
1322 
1323  LL_FOREACH_SAFE(ctx->endpoint, ep, tmp) {
1324  if ((ep->sock.flags & COAP_SOCKET_CAN_READ) != 0)
1325  coap_read_endpoint(ctx, ep, now);
1326  if ((ep->sock.flags & COAP_SOCKET_CAN_WRITE) != 0)
1327  coap_write_endpoint(ctx, ep, now);
1328  if ((ep->sock.flags & COAP_SOCKET_CAN_ACCEPT) != 0)
1329  coap_accept_endpoint(ctx, ep, now);
1330  LL_FOREACH_SAFE(ep->sessions, s, tmp_s) {
1331  if ((s->sock.flags & COAP_SOCKET_CAN_READ) != 0) {
1332  /* Make sure the session object is not deleted in one of the callbacks */
1334  coap_read_session(ctx, s, now);
1336  }
1337  if ((s->sock.flags & COAP_SOCKET_CAN_WRITE) != 0) {
1338  /* Make sure the session object is not deleted in one of the callbacks */
1340  coap_write_session(ctx, s, now);
1342  }
1343  }
1344  }
1345 
1346  LL_FOREACH_SAFE(ctx->sessions, s, tmp_s) {
1347  if ((s->sock.flags & COAP_SOCKET_CAN_CONNECT) != 0) {
1348  /* Make sure the session object is not deleted in one of the callbacks */
1350  coap_connect_session(ctx, s, now);
1351  coap_session_release( s );
1352  }
1353  if ((s->sock.flags & COAP_SOCKET_CAN_READ) != 0) {
1354  /* Make sure the session object is not deleted in one of the callbacks */
1356  coap_read_session(ctx, s, now);
1358  }
1359  if ((s->sock.flags & COAP_SOCKET_CAN_WRITE) != 0) {
1360  /* Make sure the session object is not deleted in one of the callbacks */
1362  coap_write_session(ctx, s, now);
1363  coap_session_release( s );
1364  }
1365  }
1366 }
1367 
1368 int
1370  uint8_t *msg, size_t msg_len) {
1371 
1372  coap_pdu_t *pdu = NULL;
1373 
1375 
1376  pdu = coap_pdu_init(0, 0, 0, msg_len - 4);
1377  if (!pdu)
1378  goto error;
1379 
1380  if (!coap_pdu_parse(session->proto, msg, msg_len, pdu)) {
1381  coap_log(LOG_WARNING, "discard malformed PDU\n");
1382  goto error;
1383  }
1384 
1385  coap_dispatch(ctx, session, pdu);
1386  coap_delete_pdu(pdu);
1387  return 0;
1388 
1389 error:
1390  /* FIXME: send back RST? */
1391  coap_delete_pdu(pdu);
1392  return -1;
1393 }
1394 #endif /* not WITH_LWIP */
1395 
1396 int
1398  coap_queue_t *p, *q;
1399 
1400  if (!queue || !*queue)
1401  return 0;
1402 
1403  /* replace queue head if PDU's time is less than head's time */
1404 
1405  if (session == (*queue)->session && id == (*queue)->id) { /* found transaction */
1406  *node = *queue;
1407  *queue = (*queue)->next;
1408  if (*queue) { /* adjust relative time of new queue head */
1409  (*queue)->t += (*node)->t;
1410  }
1411  (*node)->next = NULL;
1412  coap_log(LOG_DEBUG, "** %s: tid=%d: removed\n",
1413  coap_session_str(session), id);
1414  return 1;
1415  }
1416 
1417  /* search transaction to remove (only first occurence will be removed) */
1418  q = *queue;
1419  do {
1420  p = q;
1421  q = q->next;
1422  } while (q && (session != q->session || id != q->id));
1423 
1424  if (q) { /* found transaction */
1425  p->next = q->next;
1426  if (p->next) { /* must update relative time of p->next */
1427  p->next->t += q->t;
1428  }
1429  q->next = NULL;
1430  *node = q;
1431  coap_log(LOG_DEBUG, "** %s: tid=%d: removed\n",
1432  coap_session_str(session), id);
1433  return 1;
1434  }
1435 
1436  return 0;
1437 
1438 }
1439 
1441 token_match(const uint8_t *a, size_t alen,
1442  const uint8_t *b, size_t blen) {
1443  return alen == blen && (alen == 0 || memcmp(a, b, alen) == 0);
1444 }
1445 
1446 void
1448  coap_nack_reason_t reason) {
1449  coap_queue_t *p, *q;
1450 
1451  while (context->sendqueue && context->sendqueue->session == session) {
1452  q = context->sendqueue;
1453  context->sendqueue = q->next;
1454  coap_log(LOG_DEBUG, "** %s: tid=%d: removed\n",
1455  coap_session_str(session), q->id);
1456  if (q->pdu->type == COAP_MESSAGE_CON && context->nack_handler)
1457  context->nack_handler(context, session, q->pdu, reason, q->id);
1458  coap_delete_node(q);
1459  }
1460 
1461  if (!context->sendqueue)
1462  return;
1463 
1464  p = context->sendqueue;
1465  q = p->next;
1466 
1467  while (q) {
1468  if (q->session == session) {
1469  p->next = q->next;
1470  coap_log(LOG_DEBUG, "** %s: tid=%d: removed\n",
1471  coap_session_str(session), q->id);
1472  if (q->pdu->type == COAP_MESSAGE_CON && context->nack_handler)
1473  context->nack_handler(context, session, q->pdu, reason, q->id);
1474  coap_delete_node(q);
1475  q = p->next;
1476  } else {
1477  p = q;
1478  q = q->next;
1479  }
1480  }
1481 }
1482 
1483 void
1485  const uint8_t *token, size_t token_length) {
1486  /* cancel all messages in sendqueue that belong to session
1487  * and use the specified token */
1488  coap_queue_t *p, *q;
1489 
1490  while (context->sendqueue && context->sendqueue->session == session &&
1491  token_match(token, token_length,
1492  context->sendqueue->pdu->token,
1493  context->sendqueue->pdu->token_length)) {
1494  q = context->sendqueue;
1495  context->sendqueue = q->next;
1496  coap_log(LOG_DEBUG, "** %s: tid=%d: removed\n",
1497  coap_session_str(session), q->id);
1498  coap_delete_node(q);
1499  }
1500 
1501  if (!context->sendqueue)
1502  return;
1503 
1504  p = context->sendqueue;
1505  q = p->next;
1506 
1507  /* when q is not NULL, it does not match (dst, token), so we can skip it */
1508  while (q) {
1509  if (q->session == session &&
1510  token_match(token, token_length,
1511  q->pdu->token, q->pdu->token_length)) {
1512  p->next = q->next;
1513  coap_log(LOG_DEBUG, "** %s: tid=%d: removed\n",
1514  coap_session_str(session), q->id);
1515  coap_delete_node(q);
1516  q = p->next;
1517  } else {
1518  p = q;
1519  q = q->next;
1520  }
1521  }
1522 }
1523 
1524 coap_queue_t *
1526  while (queue && queue->session != session && queue->id != id)
1527  queue = queue->next;
1528 
1529  return queue;
1530 }
1531 
1532 coap_pdu_t *
1533 coap_new_error_response(coap_pdu_t *request, unsigned char code,
1534  coap_opt_filter_t opts) {
1535  coap_opt_iterator_t opt_iter;
1536  coap_pdu_t *response;
1537  size_t size = request->token_length;
1538  unsigned char type;
1539  coap_opt_t *option;
1540  uint16_t opt_type = 0; /* used for calculating delta-storage */
1541 
1542 #if COAP_ERROR_PHRASE_LENGTH > 0
1543  const char *phrase = coap_response_phrase(code);
1544 
1545  /* Need some more space for the error phrase and payload start marker */
1546  if (phrase)
1547  size += strlen(phrase) + 1;
1548 #endif
1549 
1550  assert(request);
1551 
1552  /* cannot send ACK if original request was not confirmable */
1553  type = request->type == COAP_MESSAGE_CON
1555  : COAP_MESSAGE_NON;
1556 
1557  /* Estimate how much space we need for options to copy from
1558  * request. We always need the Token, for 4.02 the unknown critical
1559  * options must be included as well. */
1560  coap_option_clrb(opts, COAP_OPTION_CONTENT_TYPE); /* we do not want this */
1561 
1562  coap_option_iterator_init(request, &opt_iter, opts);
1563 
1564  /* Add size of each unknown critical option. As known critical
1565  options as well as elective options are not copied, the delta
1566  value might grow.
1567  */
1568  while ((option = coap_option_next(&opt_iter))) {
1569  uint16_t delta = opt_iter.type - opt_type;
1570  /* calculate space required to encode (opt_iter.type - opt_type) */
1571  if (delta < 13) {
1572  size++;
1573  } else if (delta < 269) {
1574  size += 2;
1575  } else {
1576  size += 3;
1577  }
1578 
1579  /* add coap_opt_length(option) and the number of additional bytes
1580  * required to encode the option length */
1581 
1582  size += coap_opt_length(option);
1583  switch (*option & 0x0f) {
1584  case 0x0e:
1585  size++;
1586  /* fall through */
1587  case 0x0d:
1588  size++;
1589  break;
1590  default:
1591  ;
1592  }
1593 
1594  opt_type = opt_iter.type;
1595  }
1596 
1597  /* Now create the response and fill with options and payload data. */
1598  response = coap_pdu_init(type, code, request->tid, size);
1599  if (response) {
1600  /* copy token */
1601  if (!coap_add_token(response, request->token_length,
1602  request->token)) {
1603  coap_log(LOG_DEBUG, "cannot add token to error response\n");
1604  coap_delete_pdu(response);
1605  return NULL;
1606  }
1607 
1608  /* copy all options */
1609  coap_option_iterator_init(request, &opt_iter, opts);
1610  while ((option = coap_option_next(&opt_iter))) {
1611  coap_add_option(response, opt_iter.type,
1612  coap_opt_length(option),
1613  coap_opt_value(option));
1614  }
1615 
1616 #if COAP_ERROR_PHRASE_LENGTH > 0
1617  /* note that diagnostic messages do not need a Content-Format option. */
1618  if (phrase)
1619  coap_add_data(response, (size_t)strlen(phrase), (const uint8_t *)phrase);
1620 #endif
1621  }
1622 
1623  return response;
1624 }
1625 
1630 COAP_STATIC_INLINE size_t
1631 get_wkc_len(coap_context_t *context, coap_opt_t *query_filter) {
1632  unsigned char buf[1];
1633  size_t len = 0;
1634 
1635  if (coap_print_wellknown(context, buf, &len, UINT_MAX, query_filter)
1637  coap_log(LOG_WARNING, "cannot determine length of /.well-known/core\n");
1638  return 0;
1639  }
1640 
1641  coap_log(LOG_DEBUG, "get_wkc_len: coap_print_wellknown() returned %zu\n", len);
1642 
1643  return len;
1644 }
1645 
1646 #define SZX_TO_BYTES(SZX) ((size_t)(1 << ((SZX) + 4)))
1647 
1648 coap_pdu_t *
1650  coap_pdu_t *request) {
1651  coap_pdu_t *resp;
1652  coap_opt_iterator_t opt_iter;
1653  size_t len, wkc_len;
1654  uint8_t buf[2];
1655  int result = 0;
1656  int need_block2 = 0; /* set to 1 if Block2 option is required */
1657  coap_block_t block;
1658  coap_opt_t *query_filter;
1659  size_t offset = 0;
1660  uint8_t *data;
1661 
1662  resp = coap_pdu_init(request->type == COAP_MESSAGE_CON
1664  : COAP_MESSAGE_NON,
1665  COAP_RESPONSE_CODE(205),
1666  request->tid, coap_session_max_pdu_size(session));
1667  if (!resp) {
1668  coap_log(LOG_DEBUG, "coap_wellknown_response: cannot create PDU\n");
1669  return NULL;
1670  }
1671 
1672  if (!coap_add_token(resp, request->token_length, request->token)) {
1673  coap_log(LOG_DEBUG, "coap_wellknown_response: cannot add token\n");
1674  goto error;
1675  }
1676 
1677  query_filter = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter);
1678  wkc_len = get_wkc_len(context, query_filter);
1679 
1680  /* The value of some resources is undefined and get_wkc_len will return 0.*/
1681  if (wkc_len == 0) {
1682  coap_log(LOG_DEBUG, "coap_wellknown_response: undefined resource\n");
1683  /* set error code 4.00 Bad Request*/
1684  resp->code = COAP_RESPONSE_CODE(400);
1685  resp->used_size = resp->token_length;
1686  return resp;
1687  }
1688 
1689  /* check whether the request contains the Block2 option */
1690  if (coap_get_block(request, COAP_OPTION_BLOCK2, &block)) {
1691  coap_log(LOG_DEBUG, "create block\n");
1692  offset = block.num << (block.szx + 4);
1693  if (block.szx > 6) { /* invalid, MUST lead to 4.00 Bad Request */
1694  resp->code = COAP_RESPONSE_CODE(400);
1695  return resp;
1696  } else if (block.szx > COAP_MAX_BLOCK_SZX) {
1697  block.szx = COAP_MAX_BLOCK_SZX;
1698  block.num = (unsigned int)(offset >> (block.szx + 4));
1699  }
1700 
1701  need_block2 = 1;
1702  }
1703 
1704  /* Check if there is sufficient space to add Content-Format option
1705  * and data. We do this before adding the Content-Format option to
1706  * avoid sending error responses with that option but no actual
1707  * content. */
1708  if (resp->max_size && resp->max_size <= resp->used_size + 3) {
1709  coap_log(LOG_DEBUG, "coap_wellknown_response: insufficient storage space\n");
1710  goto error;
1711  }
1712 
1713  /* Add Content-Format. As we have checked for available storage,
1714  * nothing should go wrong here. */
1715  assert(coap_encode_var_safe(buf, sizeof(buf),
1718  coap_encode_var_safe(buf, sizeof(buf),
1720 
1721  /* check if Block2 option is required even if not requested */
1722  if (!need_block2 && resp->max_size && resp->max_size - resp->used_size < wkc_len + 1) {
1723  assert(resp->used_size <= resp->max_size);
1724  const size_t payloadlen = resp->max_size - resp->used_size;
1725  /* yes, need block-wise transfer */
1726  block.num = 0;
1727  block.m = 0; /* the M bit is set by coap_write_block_opt() */
1728  block.szx = COAP_MAX_BLOCK_SZX;
1729  while (payloadlen < SZX_TO_BYTES(block.szx) + 6) {
1730  if (block.szx == 0) {
1732  "coap_wellknown_response: message to small even for szx == 0\n");
1733  goto error;
1734  } else {
1735  block.szx--;
1736  }
1737  }
1738 
1739  need_block2 = 1;
1740  }
1741 
1742  /* write Block2 option if necessary */
1743  if (need_block2) {
1744  if (coap_write_block_opt(&block, COAP_OPTION_BLOCK2, resp, wkc_len) < 0) {
1746  "coap_wellknown_response: cannot add Block2 option\n");
1747  goto error;
1748  }
1749  }
1750 
1751  len = need_block2 ? SZX_TO_BYTES( block.szx ) :
1752  resp->max_size && resp->used_size + wkc_len + 1 > resp->max_size ?
1753  resp->max_size - resp->used_size - 1 : wkc_len;
1754  data = coap_add_data_after(resp, len);
1755  if (!data) {
1756  coap_log(LOG_DEBUG, "coap_wellknown_response: coap_add_data failed\n" );
1757  goto error;
1758  }
1759 
1760  result = coap_print_wellknown(context, data, &len, offset, query_filter);
1761  if ((result & COAP_PRINT_STATUS_ERROR) != 0) {
1762  coap_log(LOG_DEBUG, "coap_print_wellknown failed\n");
1763  goto error;
1764  }
1765 
1766  return resp;
1767 
1768 error:
1769  /* set error code 5.03 and remove all options and data from response */
1770  resp->code = COAP_RESPONSE_CODE(503);
1771  resp->used_size = resp->token_length;
1772  return resp;
1773 }
1774 
1785 static int
1786 coap_cancel(coap_context_t *context, const coap_queue_t *sent) {
1787 #ifndef WITHOUT_OBSERVE
1788  coap_binary_t token = { 0, NULL };
1789  int num_cancelled = 0; /* the number of observers cancelled */
1790 
1791  /* remove observer for this resource, if any
1792  * get token from sent and try to find a matching resource. Uh!
1793  */
1794 
1795  COAP_SET_STR(&token, sent->pdu->token_length, sent->pdu->token);
1796 
1797  RESOURCES_ITER(context->resources, r) {
1798  num_cancelled += coap_delete_observer(r, sent->session, &token);
1799  coap_cancel_all_messages(context, sent->session, token.s, token.length);
1800  }
1801 
1802  return num_cancelled;
1803 #else /* WITOUT_OBSERVE */
1804  return 0;
1805 #endif /* WITOUT_OBSERVE */
1806 }
1807 
1813 
1844 static enum respond_t
1845 no_response(coap_pdu_t *request, coap_pdu_t *response) {
1846  coap_opt_t *nores;
1847  coap_opt_iterator_t opt_iter;
1848  unsigned int val = 0;
1849 
1850  assert(request);
1851  assert(response);
1852 
1853  if (COAP_RESPONSE_CLASS(response->code) > 0) {
1854  nores = coap_check_option(request, COAP_OPTION_NORESPONSE, &opt_iter);
1855 
1856  if (nores) {
1858 
1859  /* The response should be dropped when the bit corresponding to
1860  * the response class is set (cf. table in function
1861  * documentation). When a No-Response option is present and the
1862  * bit is not set, the sender explicitly indicates interest in
1863  * this response. */
1864  if (((1 << (COAP_RESPONSE_CLASS(response->code) - 1)) & val) > 0) {
1865  return RESPONSE_DROP;
1866  } else {
1867  return RESPONSE_SEND;
1868  }
1869  }
1870  }
1871 
1872  /* Default behavior applies when we are not dealing with a response
1873  * (class == 0) or the request did not contain a No-Response option.
1874  */
1875  return RESPONSE_DEFAULT;
1876 }
1877 
1879  { sizeof(COAP_DEFAULT_URI_WELLKNOWN)-1,
1881 
1882 static void
1884  coap_method_handler_t h = NULL;
1885  coap_pdu_t *response = NULL;
1887  coap_resource_t *resource;
1888  /* The respond field indicates whether a response must be treated
1889  * specially due to a No-Response option that declares disinterest
1890  * or interest in a specific response class. DEFAULT indicates that
1891  * No-Response has not been specified. */
1892  enum respond_t respond = RESPONSE_DEFAULT;
1893 
1894  coap_option_filter_clear(opt_filter);
1895 
1896  /* try to find the resource from the request URI */
1897  coap_string_t *uri_path = coap_get_uri_path(pdu);
1898  if (!uri_path)
1899  return;
1900  coap_str_const_t uri_path_c = { uri_path->length, uri_path->s };
1901  resource = coap_get_resource_from_uri_path(context, &uri_path_c);
1902 
1903  if ((resource == NULL) || (resource->is_unknown == 1)) {
1904  /* The resource was not found or there is an unexpected match against the
1905  * resource defined for handling unknown URIs.
1906  * Check if the request URI happens to be the well-known URI, or if the
1907  * unknown resource handler is defined, a PUT or optionally other methods,
1908  * if configured, for the unknown handler.
1909  *
1910  * if well-known URI generate a default response
1911  *
1912  * else if unknown URI handler defined, call the unknown
1913  * URI handler (to allow for potential generation of resource
1914  * [RFC7272 5.8.3]) if the appropriate method is defined.
1915  *
1916  * else if DELETE return 2.02 (RFC7252: 5.8.4. DELETE)
1917  *
1918  * else return 4.04 */
1919 
1920  if (coap_string_equal(uri_path, &coap_default_uri_wellknown)) {
1921  /* request for .well-known/core */
1922  if (pdu->code == COAP_REQUEST_GET) { /* GET */
1923  coap_log(LOG_INFO, "create default response for %s\n",
1925  response = coap_wellknown_response(context, session, pdu);
1926  } else {
1927  coap_log(LOG_DEBUG, "method not allowed for .well-known/core\n");
1928  response = coap_new_error_response(pdu, COAP_RESPONSE_CODE(405),
1929  opt_filter);
1930  }
1931  } else if ((context->unknown_resource != NULL) &&
1932  ((size_t)pdu->code - 1 <
1933  (sizeof(resource->handler) / sizeof(coap_method_handler_t))) &&
1934  (context->unknown_resource->handler[pdu->code - 1])) {
1935  /*
1936  * The unknown_resource can be used to handle undefined resources
1937  * for a PUT request and can support any other registered handler
1938  * defined for it
1939  * Example set up code:-
1940  * r = coap_resource_unknown_init(hnd_put_unknown);
1941  * coap_register_handler(r, COAP_REQUEST_POST, hnd_post_unknown);
1942  * coap_register_handler(r, COAP_REQUEST_GET, hnd_get_unknown);
1943  * coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_unknown);
1944  * coap_add_resource(ctx, r);
1945  *
1946  * Note: It is not possible to observe the unknown_resource, a separate
1947  * resource must be created (by PUT or POST) which has a GET
1948  * handler to be observed
1949  */
1950  resource = context->unknown_resource;
1951  } else if (pdu->code == COAP_REQUEST_DELETE) {
1952  /*
1953  * Request for DELETE on non-existant resource (RFC7252: 5.8.4. DELETE)
1954  */
1955  coap_log(LOG_DEBUG, "request for unknown resource '%*.*s',"
1956  " return 2.02\n",
1957  (int)uri_path->length,
1958  (int)uri_path->length,
1959  uri_path->s);
1960  response =
1962  opt_filter);
1963  } else { /* request for any another resource, return 4.04 */
1964 
1965  coap_log(LOG_DEBUG, "request for unknown resource '%*.*s', return 4.04\n",
1966  (int)uri_path->length, (int)uri_path->length, uri_path->s);
1967  response =
1969  opt_filter);
1970  }
1971 
1972  if (!resource) {
1973  if (response && (no_response(pdu, response) != RESPONSE_DROP)) {
1974  if (coap_send(session, response) == COAP_INVALID_TID)
1975  coap_log(LOG_WARNING, "cannot send response for transaction %u\n",
1976  pdu->tid);
1977  } else {
1978  coap_delete_pdu(response);
1979  }
1980 
1981  response = NULL;
1982 
1983  coap_delete_string(uri_path);
1984  return;
1985  } else {
1986  if (response) {
1987  /* Need to delete unused response - it will get re-created further on */
1988  coap_delete_pdu(response);
1989  }
1990  }
1991  }
1992 
1993  /* the resource was found, check if there is a registered handler */
1994  if ((size_t)pdu->code - 1 <
1995  sizeof(resource->handler) / sizeof(coap_method_handler_t))
1996  h = resource->handler[pdu->code - 1];
1997 
1998  if (h) {
1999  coap_string_t *query = coap_get_query(pdu);
2000  int owns_query = 1;
2001  coap_log(LOG_DEBUG, "call custom handler for resource '%*.*s'\n",
2002  (int)resource->uri_path->length, (int)resource->uri_path->length,
2003  resource->uri_path->s);
2004  response = coap_pdu_init(pdu->type == COAP_MESSAGE_CON
2006  : COAP_MESSAGE_NON,
2007  0, pdu->tid, coap_session_max_pdu_size(session));
2008 
2009  /* Implementation detail: coap_add_token() immediately returns 0
2010  if response == NULL */
2011  if (coap_add_token(response, pdu->token_length, pdu->token)) {
2012  coap_binary_t token = { pdu->token_length, pdu->token };
2013  coap_opt_iterator_t opt_iter;
2014  coap_opt_t *observe = NULL;
2015  int observe_action = COAP_OBSERVE_CANCEL;
2016 
2017  /* check for Observe option */
2018  if (resource->observable) {
2019  observe = coap_check_option(pdu, COAP_OPTION_OBSERVE, &opt_iter);
2020  if (observe) {
2021  observe_action =
2023  coap_opt_length(observe));
2024 
2025  if ((observe_action & COAP_OBSERVE_CANCEL) == 0) {
2026  coap_subscription_t *subscription;
2027  coap_block_t block2;
2028  int has_block2 = 0;
2029 
2030  if (coap_get_block(pdu, COAP_OPTION_BLOCK2, &block2)) {
2031  has_block2 = 1;
2032  }
2033  subscription = coap_add_observer(resource, session, &token, query, has_block2, block2);
2034  owns_query = 0;
2035  if (subscription) {
2036  coap_touch_observer(context, session, &token);
2037  }
2038  } else {
2039  coap_delete_observer(resource, session, &token);
2040  }
2041  }
2042  }
2043 
2044  h(context, resource, session, pdu, &token, query, response);
2045 
2046  if (query && owns_query)
2047  coap_delete_string(query);
2048 
2049  respond = no_response(pdu, response);
2050  if (respond != RESPONSE_DROP) {
2051  if (observe && (COAP_RESPONSE_CLASS(response->code) > 2)) {
2052  coap_delete_observer(resource, session, &token);
2053  }
2054 
2055  /* If original request contained a token, and the registered
2056  * application handler made no changes to the response, then
2057  * this is an empty ACK with a token, which is a malformed
2058  * PDU */
2059  if ((response->type == COAP_MESSAGE_ACK)
2060  && (response->code == 0)) {
2061  /* Remove token from otherwise-empty acknowledgment PDU */
2062  response->token_length = 0;
2063  response->used_size = 0;
2064  }
2065 
2066  if ((respond == RESPONSE_SEND)
2067  || /* RESPOND_DEFAULT */
2068  (response->type != COAP_MESSAGE_NON ||
2069  (response->code >= 64
2070  && !coap_mcast_interface(&node->local_if)))) {
2071 
2072  if (coap_send(session, response) == COAP_INVALID_TID)
2073  coap_log(LOG_DEBUG, "cannot send response for message %d\n",
2074  pdu->tid);
2075  } else {
2076  coap_delete_pdu(response);
2077  }
2078  } else {
2079  coap_delete_pdu(response);
2080  }
2081  response = NULL;
2082  } else {
2083  coap_log(LOG_WARNING, "cannot generate response\r\n");
2084  }
2085  } else {
2086  if (coap_string_equal(uri_path, &coap_default_uri_wellknown)) {
2087  /* request for .well-known/core */
2088  coap_log(LOG_DEBUG, "create default response for %s\n",
2090  response = coap_wellknown_response(context, session, pdu);
2091  coap_log(LOG_DEBUG, "have wellknown response %p\n", (void *)response);
2092  } else
2093  response = coap_new_error_response(pdu, COAP_RESPONSE_CODE(405),
2094  opt_filter);
2095 
2096  if (response && (no_response(pdu, response) != RESPONSE_DROP)) {
2097  if (coap_send(session, response) == COAP_INVALID_TID)
2098  coap_log(LOG_DEBUG, "cannot send response for transaction %d\n",
2099  pdu->tid);
2100  } else {
2101  coap_delete_pdu(response);
2102  }
2103  response = NULL;
2104  }
2105 
2106  assert(response == NULL);
2107  coap_delete_string(uri_path);
2108 }
2109 
2110 static void
2112  coap_pdu_t *sent, coap_pdu_t *rcvd) {
2113 
2114  coap_send_ack(session, rcvd);
2115 
2116  /* In a lossy context, the ACK of a separate response may have
2117  * been lost, so we need to stop retransmitting requests with the
2118  * same token.
2119  */
2120  coap_cancel_all_messages(context, session, rcvd->token, rcvd->token_length);
2121 
2122  /* Call application-specific response handler when available. */
2123  if (context->response_handler) {
2124  context->response_handler(context, session, sent, rcvd, rcvd->tid);
2125  }
2126 }
2127 
2128 static void
2130  coap_pdu_t *pdu) {
2131  coap_opt_iterator_t opt_iter;
2132  coap_opt_t *option;
2133  (void)context;
2134 
2135  coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL);
2136 
2137  if (pdu->code == COAP_SIGNALING_CSM) {
2138  while ((option = coap_option_next(&opt_iter))) {
2139  if (opt_iter.type == COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE) {
2141  coap_opt_length(option)));
2142  } else if (opt_iter.type == COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER) {
2143  /* ... */
2144  }
2145  }
2146  if (session->state == COAP_SESSION_STATE_CSM)
2147  coap_session_connected(session);
2148  } else if (pdu->code == COAP_SIGNALING_PING) {
2150  if (context->ping_handler) {
2151  context->ping_handler(context, session, pdu, pdu->tid);
2152  }
2153  if (pong) {
2155  coap_send(session, pong);
2156  }
2157  } else if (pdu->code == COAP_SIGNALING_PONG) {
2158  session->last_pong = session->last_rx_tx;
2159  if (context->pong_handler) {
2160  context->pong_handler(context, session, pdu, pdu->tid);
2161  }
2162  } else if (pdu->code == COAP_SIGNALING_RELEASE
2163  || pdu->code == COAP_SIGNALING_ABORT) {
2165  }
2166 }
2167 
2168 void
2170  coap_pdu_t *pdu) {
2171  coap_queue_t *sent = NULL;
2172  coap_pdu_t *response;
2174 
2175 #ifndef NDEBUG
2176  if (LOG_DEBUG <= coap_get_log_level()) {
2177 #ifndef INET6_ADDRSTRLEN
2178 #define INET6_ADDRSTRLEN 40
2179 #endif
2180  /* FIXME: get debug to work again **
2181  unsigned char addr[INET6_ADDRSTRLEN+8], localaddr[INET6_ADDRSTRLEN+8];
2182  if (coap_print_addr(remote, addr, INET6_ADDRSTRLEN+8) &&
2183  coap_print_addr(&packet->dst, localaddr, INET6_ADDRSTRLEN+8) )
2184  coap_log(LOG_DEBUG, "** received %d bytes from %s on interface %s:\n",
2185  (int)msg_len, addr, localaddr);
2186 
2187  */
2188  coap_show_pdu(LOG_DEBUG, pdu);
2189  }
2190 #endif
2191 
2192  memset(opt_filter, 0, sizeof(coap_opt_filter_t));
2193 
2194  switch (pdu->type) {
2195  case COAP_MESSAGE_ACK:
2196  /* find transaction in sendqueue to stop retransmission */
2197  coap_remove_from_queue(&context->sendqueue, session, pdu->tid, &sent);
2198 
2199  if (session->con_active) {
2200  session->con_active--;
2201  if (session->state == COAP_SESSION_STATE_ESTABLISHED)
2202  /* Flush out any entries on session->delayqueue */
2203  coap_session_connected(session);
2204  }
2205  if (pdu->code == 0)
2206  goto cleanup;
2207 
2208  /* if sent code was >= 64 the message might have been a
2209  * notification. Then, we must flag the observer to be alive
2210  * by setting obs->fail_cnt = 0. */
2211  if (sent && COAP_RESPONSE_CLASS(sent->pdu->code) == 2) {
2212  const coap_binary_t token =
2213  { sent->pdu->token_length, sent->pdu->token };
2214  coap_touch_observer(context, sent->session, &token);
2215  }
2216  break;
2217 
2218  case COAP_MESSAGE_RST:
2219  /* We have sent something the receiver disliked, so we remove
2220  * not only the transaction but also the subscriptions we might
2221  * have. */
2222 
2223  coap_log(LOG_ALERT, "got RST for message %d\n", pdu->tid);
2224 
2225  if (session->con_active) {
2226  session->con_active--;
2227  if (session->state == COAP_SESSION_STATE_ESTABLISHED)
2228  /* Flush out any entries on session->delayqueue */
2229  coap_session_connected(session);
2230  }
2231 
2232  /* find transaction in sendqueue to stop retransmission */
2233  coap_remove_from_queue(&context->sendqueue, session, pdu->tid, &sent);
2234 
2235  if (sent) {
2236  coap_cancel(context, sent);
2237 
2238  if(sent->pdu->type==COAP_MESSAGE_CON && context->nack_handler)
2239  context->nack_handler(context, sent->session, sent->pdu, COAP_NACK_RST, sent->id);
2240  }
2241  goto cleanup;
2242 
2243  case COAP_MESSAGE_NON: /* check for unknown critical options */
2244  if (coap_option_check_critical(context, pdu, opt_filter) == 0)
2245  goto cleanup;
2246  break;
2247 
2248  case COAP_MESSAGE_CON: /* check for unknown critical options */
2249  if (coap_option_check_critical(context, pdu, opt_filter) == 0) {
2250 
2251  /* FIXME: send response only if we have received a request. Otherwise,
2252  * send RST. */
2253  response =
2254  coap_new_error_response(pdu, COAP_RESPONSE_CODE(402), opt_filter);
2255 
2256  if (!response) {
2258  "coap_dispatch: cannot create error response\n");
2259  } else {
2260  if (coap_send(session, response) == COAP_INVALID_TID)
2261  coap_log(LOG_WARNING, "coap_dispatch: error sending response\n");
2262  }
2263 
2264  goto cleanup;
2265  }
2266  default: break;
2267  }
2268 
2269  /* Pass message to upper layer if a specific handler was
2270  * registered for a request that should be handled locally. */
2271  if (COAP_PDU_IS_SIGNALING(pdu))
2272  handle_signaling(context, session, pdu);
2273  else if (COAP_PDU_IS_REQUEST(pdu))
2274  handle_request(context, session, pdu);
2275  else if (COAP_PDU_IS_RESPONSE(pdu))
2276  handle_response(context, session, sent ? sent->pdu : NULL, pdu);
2277  else {
2278  if (COAP_PDU_IS_EMPTY(pdu)) {
2279  if (context->ping_handler) {
2280  context->ping_handler(context, session,
2281  pdu, pdu->tid);
2282  }
2283  }
2284  coap_log(LOG_DEBUG, "dropped message with invalid code (%d.%02d)\n",
2285  COAP_RESPONSE_CLASS(pdu->code),
2286  pdu->code & 0x1f);
2287 
2288  if (!coap_is_mcast(&session->local_addr)) {
2289  if (COAP_PDU_IS_EMPTY(pdu)) {
2290  if (session->proto != COAP_PROTO_TCP && session->proto != COAP_PROTO_TLS) {
2291  coap_tick_t now;
2292  coap_ticks(&now);
2293  if (session->last_tx_rst + COAP_TICKS_PER_SECOND/4 < now) {
2295  session->last_tx_rst = now;
2296  }
2297  }
2298  }
2299  else {
2301  }
2302  }
2303  }
2304 
2305 cleanup:
2306  coap_delete_node(sent);
2307 }
2308 
2309 int
2311  coap_log(LOG_DEBUG, "***EVENT: 0x%04x\n", event);
2312 
2313  if (context->handle_event) {
2314  return context->handle_event(context, event, session);
2315  } else {
2316  return 0;
2317  }
2318 }
2319 
2320 int
2322  coap_endpoint_t *ep;
2323  coap_session_t *s;
2324  if (!context)
2325  return 1;
2326  if (context->sendqueue)
2327  return 0;
2328  LL_FOREACH(context->endpoint, ep) {
2329  LL_FOREACH(ep->sessions, s) {
2330  if (s->delayqueue)
2331  return 0;
2332  }
2333  }
2334  LL_FOREACH(context->sessions, s) {
2335  if (s->delayqueue)
2336  return 0;
2337  }
2338  return 1;
2339 }
2340 
2341 static int coap_started = 0;
2342 
2343 void coap_startup(void) {
2344  if (coap_started)
2345  return;
2346  coap_started = 1;
2347 #if defined(HAVE_WINSOCK2_H)
2348  WORD wVersionRequested = MAKEWORD(2, 2);
2349  WSADATA wsaData;
2350  WSAStartup(wVersionRequested, &wsaData);
2351 #endif
2352  coap_clock_init();
2353 #if defined(WITH_LWIP)
2354  prng_init(LWIP_RAND());
2355 #elif defined(WITH_CONTIKI)
2356  prng_init(0);
2357 #elif !defined(_WIN32)
2358  prng_init(0);
2359 #endif
2361 }
2362 
2363 void coap_cleanup(void) {
2364 #if defined(HAVE_WINSOCK2_H)
2365  WSACleanup();
2366 #endif
2367 }
2368 
2369 #ifdef WITH_CONTIKI
2370 
2371 /*---------------------------------------------------------------------------*/
2372 /* CoAP message retransmission */
2373 /*---------------------------------------------------------------------------*/
2374 PROCESS_THREAD(coap_retransmit_process, ev, data) {
2375  coap_tick_t now;
2376  coap_queue_t *nextpdu;
2377 
2378  PROCESS_BEGIN();
2379 
2380  coap_log(LOG_DEBUG, "Started retransmit process\n");
2381 
2382  while (1) {
2383  PROCESS_YIELD();
2384  if (ev == PROCESS_EVENT_TIMER) {
2385  if (etimer_expired(&the_coap_context.retransmit_timer)) {
2386 
2387  nextpdu = coap_peek_next(&the_coap_context);
2388 
2389  coap_ticks(&now);
2390  while (nextpdu && nextpdu->t <= now) {
2391  coap_retransmit(&the_coap_context, coap_pop_next(&the_coap_context));
2392  nextpdu = coap_peek_next(&the_coap_context);
2393  }
2394 
2395  /* need to set timer to some value even if no nextpdu is available */
2396  etimer_set(&the_coap_context.retransmit_timer,
2397  nextpdu ? nextpdu->t - now : 0xFFFF);
2398  }
2399 #ifndef WITHOUT_OBSERVE
2400  if (etimer_expired(&the_coap_context.notify_timer)) {
2401  coap_check_notify(&the_coap_context);
2402  etimer_reset(&the_coap_context.notify_timer);
2403  }
2404 #endif /* WITHOUT_OBSERVE */
2405  }
2406  }
2407 
2408  PROCESS_END();
2409 }
2410 /*---------------------------------------------------------------------------*/
2411 
2412 #endif /* WITH_CONTIKI */
2413 
2414 #ifdef WITH_LWIP
2415 /* FIXME: retransmits that are not required any more due to incoming packages
2416  * do *not* get cleared at the moment, the wakeup when the transmission is due
2417  * is silently accepted. this is mainly due to the fact that the required
2418  * checks are similar in two places in the code (when receiving ACK and RST)
2419  * and that they cause more than one patch chunk, as it must be first checked
2420  * whether the sendqueue item to be dropped is the next one pending, and later
2421  * the restart function has to be called. nothing insurmountable, but it can
2422  * also be implemented when things have stabilized, and the performance
2423  * penality is minimal
2424  *
2425  * also, this completely ignores COAP_RESOURCE_CHECK_TIME.
2426  * */
2427 
2428 static void coap_retransmittimer_execute(void *arg) {
2429  coap_context_t *ctx = (coap_context_t*)arg;
2430  coap_tick_t now;
2431  coap_tick_t elapsed;
2432  coap_queue_t *nextinqueue;
2433 
2434  ctx->timer_configured = 0;
2435 
2436  coap_ticks(&now);
2437 
2438  elapsed = now - ctx->sendqueue_basetime; /* that's positive for sure, and unless we haven't been called for a complete wrapping cycle, did not wrap */
2439 
2440  nextinqueue = coap_peek_next(ctx);
2441  while (nextinqueue != NULL) {
2442  if (nextinqueue->t > elapsed) {
2443  nextinqueue->t -= elapsed;
2444  break;
2445  } else {
2446  elapsed -= nextinqueue->t;
2447  coap_retransmit(ctx, coap_pop_next(ctx));
2448  nextinqueue = coap_peek_next(ctx);
2449  }
2450  }
2451 
2452  ctx->sendqueue_basetime = now;
2453 
2454  coap_retransmittimer_restart(ctx);
2455 }
2456 
2457 static void coap_retransmittimer_restart(coap_context_t *ctx) {
2458  coap_tick_t now, elapsed, delay;
2459 
2460  if (ctx->timer_configured) {
2461  printf("clearing\n");
2462  sys_untimeout(coap_retransmittimer_execute, (void*)ctx);
2463  ctx->timer_configured = 0;
2464  }
2465  if (ctx->sendqueue != NULL) {
2466  coap_ticks(&now);
2467  elapsed = now - ctx->sendqueue_basetime;
2468  if (ctx->sendqueue->t >= elapsed) {
2469  delay = ctx->sendqueue->t - elapsed;
2470  } else {
2471  /* a strange situation, but not completely impossible.
2472  *
2473  * this happens, for example, right after
2474  * coap_retransmittimer_execute, when a retransmission
2475  * was *just not yet* due, and the clock ticked before
2476  * our coap_ticks was called.
2477  *
2478  * not trying to retransmit anything now, as it might
2479  * cause uncontrollable recursion; let's just try again
2480  * with the next main loop run.
2481  * */
2482  delay = 0;
2483  }
2484 
2485  printf("scheduling for %d ticks\n", delay);
2486  sys_timeout(delay, coap_retransmittimer_execute, (void*)ctx);
2487  ctx->timer_configured = 1;
2488  }
2489 }
2490 #endif
uint8_t type
message type
Definition: pdu.h:288
uint8_t code
request method (value 1–10) or response code (value 40-255)
Definition: pdu.h:289
void coap_session_send_csm(coap_session_t *session)
Notify session transport has just connected and CSM exchange can now start.
Definition: coap_session.c:290
void coap_show_pdu(coap_log_t level, const coap_pdu_t *pdu)
Display the contents of the specified pdu.
Definition: coap_debug.c:461
#define LL_FOREACH(head, el)
Definition: utlist.h:413
coap_queue_t * sendqueue
Definition: net.h:165
#define COAP_SOCKET_EMPTY
coap_socket_flags_t values
Definition: coap_io.h:54
uint8_t * psk_identity
Definition: coap_session.h:84
int coap_dtls_hello(coap_session_t *session UNUSED, const uint8_t *data UNUSED, size_t data_len UNUSED)
Definition: coap_notls.c:140
static ssize_t coap_send_pdu(coap_session_t *session, coap_pdu_t *pdu, coap_queue_t *node)
Definition: net.c:655
void * coap_get_app_data(const coap_context_t *ctx)
Returns any application-specific data that has been stored with context using the function coap_set_a...
Definition: net.c:512
#define COAP_OPTION_IF_MATCH
Definition: pdu.h:92
coap_tick_t last_rx_tx
Definition: coap_session.h:79
static int coap_accept_endpoint(coap_context_t *ctx, coap_endpoint_t *endpoint, coap_tick_t now)
Definition: net.c:1310
uint8_t coap_opt_t
Use byte-oriented access methods here because sliding a complex struct coap_opt_t over the data buffe...
Definition: option.h:25
uint8_t con_active
Active CON request sent.
Definition: coap_session.h:73
COAP_STATIC_INLINE int coap_option_clrb(coap_opt_filter_t filter, uint16_t type)
Clears the corresponding bit for type in filter.
Definition: option.h:200
#define COAP_SIGNALING_PING
Definition: pdu.h:181
void coap_check_notify(coap_context_t *context)
Checks for all known resources, if they are dirty and notifies subscribed observers.
Definition: resource.c:869
int coap_add_data(coap_pdu_t *pdu, size_t len, const uint8_t *data)
Adds given data to the pdu that is passed as first parameter.
Definition: pdu.c:302
coap_tid_t coap_wait_ack(coap_context_t *context, coap_session_t *session, coap_queue_t *node)
Definition: net.c:824
#define COAP_SIGNALING_CSM
Definition: pdu.h:180
#define COAP_RESPONSE_CODE(N)
Definition: pdu.h:132
#define COAP_DTLS_PKI_SETUP_VERSION
Latest PKI setup version.
Definition: coap_dtls.h:186
coap_ping_handler_t ping_handler
Definition: net.h:190
#define COAP_DEFAULT_URI_WELLKNOWN
well-known resources URI
Definition: pdu.h:68
struct coap_context_t * context
session&#39;s context
Definition: coap_session.h:70
#define COAP_OPTION_PROXY_URI
Definition: pdu.h:106
#define COAP_OPTION_CONTENT_FORMAT
Definition: pdu.h:99
COAP_STATIC_INLINE void coap_free_node(coap_queue_t *node)
Definition: net.c:96
coap_session_t * coap_new_server_session(struct coap_context_t *ctx, coap_endpoint_t *ep)
Creates a new server session for the specified endpoint.
Definition: coap_session.c:780
coap_queue_t * coap_find_transaction(coap_queue_t *queue, coap_session_t *session, coap_tid_t id)
Retrieves transaction from the queue.
Definition: net.c:1525
static void coap_connect_session(coap_context_t *ctx, coap_session_t *session, coap_tick_t now)
Definition: net.c:1043
void * tls
security parameters
Definition: coap_session.h:71
unsigned char retransmit_cnt
retransmission counter, will be removed when zero
Definition: net.h:42
#define COAP_MESSAGE_RST
Definition: pdu.h:75
void coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length)
Given a packet, set msg and msg_len to an address and length of the packet&#39;s data in memory...
Definition: coap_io.c:912
coap_session_t * sessions
list of active sessions
Definition: coap_session.h:308
coap_endpoint_t * endpoint
the endpoints used for listening
Definition: net.h:166
#define COAP_SESSION_STATE_HANDSHAKE
Definition: coap_session.h:52
int coap_dtls_receive(coap_session_t *session UNUSED, const uint8_t *data UNUSED, size_t data_len UNUSED)
Definition: coap_notls.c:132
#define COAP_OPTION_NORESPONSE
Definition: pdu.h:122
#define COAP_SOCKET_CONNECTED
the socket is connected
Definition: coap_io.h:57
#define COAP_SOCKET_BOUND
the socket is bound
Definition: coap_io.h:56
void coap_startup(void)
Definition: net.c:2343
multi-purpose address abstraction
Definition: address.h:62
State management for asynchronous messages.
#define SHR_FP(val, frac)
#define COAP_SOCKET_MULTICAST
socket is used for multicast communication
Definition: coap_io.h:66
int coap_tid_t
coap_tid_t is used to store CoAP transaction id, i.e.
Definition: pdu.h:238
uint8_t * coap_add_data_after(coap_pdu_t *pdu, size_t len)
Adds given data to the pdu that is passed as first parameter but does not copyt it.
Definition: pdu.c:314
#define COAP_REQUEST_GET
Definition: pdu.h:79
size_t psk_key_len
Definition: net.h:211
void coap_session_set_mtu(coap_session_t *session, unsigned mtu)
Set the session MTU.
Definition: coap_session.c:206
void coap_touch_observer(coap_context_t *context, coap_session_t *session, const coap_binary_t *token)
Marks an observer as alive.
Definition: resource.c:690
ssize_t coap_tls_read(coap_session_t *session UNUSED, uint8_t *data UNUSED, size_t data_len UNUSED)
Definition: coap_notls.c:169
#define COAP_OPT_ALL
Pre-defined filter that includes all options.
Definition: option.h:122
COAP_STATIC_INLINE int token_match(const uint8_t *a, size_t alen, const uint8_t *b, size_t blen)
Definition: net.c:1441
uint8_t version
Definition: coap_dtls.h:192
coap_string_t * coap_get_query(const coap_pdu_t *request)
Definition: uri.c:512
unsigned int coap_encode_var_safe(uint8_t *buf, size_t length, unsigned int val)
Encodes multiple-length byte sequences.
Definition: encode.c:45
uint8_t * psk_hint
Definition: net.h:208
#define COAP_PROTO_DTLS
Definition: pdu.h:345
#define COAP_MESSAGE_NON
Definition: pdu.h:73
void * coap_dtls_new_client_session(coap_session_t *session UNUSED)
Definition: coap_notls.c:98
int coap_pdu_parse_header(coap_pdu_t *pdu, coap_proto_t proto)
Decode the protocol specific header for the specified PDU.
Definition: pdu.c:474
coap_endpoint_t * coap_new_endpoint(coap_context_t *context, const coap_address_t *listen_addr, coap_proto_t proto)
Create a new endpoint for communicating with peers.
Definition: coap_session.c:810
coap_tid_t coap_send(coap_session_t *session, coap_pdu_t *pdu)
Sends a CoAP message to given peer.
Definition: net.c:876
COAP_STATIC_INLINE void coap_address_init(coap_address_t *addr)
Resets the given coap_address_t object addr to its default values.
Definition: address.h:104
Internal function invoked for server.
Definition: coap_dtls.h:266
#define COAP_OPTION_OBSERVE
Definition: pdu.h:112
void coap_clock_init(void)
Initializes the internal clock.
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)
Definition: coap_io.c:268
int coap_context_set_pki(coap_context_t *ctx, coap_dtls_pki_t *setup_data)
Set the context&#39;s default PKI information for a server.
Definition: net.c:392
int coap_dtls_is_supported(void)
Check whether DTLS is available.
Definition: coap_dtls.c:891
int coap_dtls_context_set_pki(coap_context_t *ctx UNUSED, coap_dtls_pki_t *setup_data UNUSED, coap_dtls_role_t role UNUSED)
Definition: coap_notls.c:41
ssize_t coap_tls_write(coap_session_t *session UNUSED, const uint8_t *data UNUSED, size_t data_len UNUSED)
Definition: coap_notls.c:162
#define COAP_OPTION_BLOCK1
Definition: pdu.h:118
ssize_t coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len)
Definition: coap_io.c:665
#define COAP_SOCKET_CAN_READ
non blocking socket can now read without blocking
Definition: coap_io.h:62
coap_address_t local_if
optional local interface address
Definition: coap_session.h:64
int coap_delete_observer(coap_resource_t *resource, coap_session_t *session, const coap_binary_t *token)
Removes any subscription for observer from resource and releases the allocated storage.
Definition: resource.c:703
size_t coap_session_max_pdu_size(const coap_session_t *session)
Get maximum acceptable PDU size.
Definition: coap_session.c:189
#define COAP_EVENT_TCP_CONNECTED
TCP events for COAP_PROTO_TCP and COAP_PROTO_TLS.
Definition: coap_event.h:41
ssize_t coap_session_send(coap_session_t *session, const uint8_t *data, size_t datalen)
Function interface for datagram data transmission.
Definition: coap_session.c:218
#define COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER
Definition: pdu.h:188
int coap_option_filter_set(coap_opt_filter_t filter, uint16_t type)
Sets the corresponding entry for type in filter.
Definition: option.c:534
unsigned int is_unknown
resource created for unknown handler
Definition: resource.h:75
int coap_pdu_parse_opt(coap_pdu_t *pdu)
Verify consistency in the given CoAP PDU structure and locate the data.
Definition: pdu.c:506
#define COAP_PDU_DELAYED
Definition: pdu.h:249
#define prng_init(Value)
Called to set the PRNG seed.
Definition: prng.h:122
Debug.
Definition: coap_debug.h:49
coap_nack_handler_t nack_handler
Definition: net.h:189
coap_tid_t coap_send_message_type(coap_session_t *session, coap_pdu_t *request, unsigned char type)
Helper funktion to create and send a message with type (usually ACK or RST).
Definition: net.c:772
coap_opt_t * coap_option_next(coap_opt_iterator_t *oi)
Updates the iterator oi to point to the next option.
Definition: option.c:157
size_t(* get_client_psk)(const coap_session_t *session, const uint8_t *hint, size_t hint_len, uint8_t *identity, size_t *identity_len, size_t max_identity_len, uint8_t *psk, size_t max_psk_len)
Definition: net.h:203
#define COAP_OPTION_CONTENT_TYPE
Definition: pdu.h:100
#define COAP_EVENT_TCP_FAILED
Definition: coap_event.h:43
Helpers for handling options in CoAP PDUs.
coap_nack_reason_t
Definition: coap_io.h:206
static int coap_handle_dgram_for_proto(coap_context_t *ctx, coap_session_t *session, coap_packet_t *packet)
Definition: net.c:1024
unsigned char payload[COAP_RXBUFFER_SIZE]
payload
Definition: coap_io.h:201
ssize_t coap_network_send(coap_socket_t *sock, const coap_session_t *session, const uint8_t *data, size_t datalen)
Definition: coap_io.c:758
coap_context_t * coap_new_context(const coap_address_t *listen_addr)
Creates a new coap_context_t object that will hold the CoAP stack status.
Definition: net.c:422
#define COAP_SOCKET_CAN_ACCEPT
non blocking server socket can now accept without blocking
Definition: coap_io.h:64
coap_session_t * coap_session_reference(coap_session_t *session)
Increment reference counter on a session.
Definition: coap_session.c:71
size_t length
length of string
Definition: str.h:34
uint8_t * s
string data
Definition: str.h:27
const char * coap_endpoint_str(const coap_endpoint_t *endpoint)
Get endpoint description.
Definition: coap_session.c:980
ssize_t(* network_read)(coap_socket_t *sock, struct coap_packet_t *packet)
Definition: net.h:201
coap_queue_t * coap_peek_next(coap_context_t *context)
Returns the next pdu to send without removing from sendqeue.
Definition: net.c:270
void * coap_tls_new_client_session(coap_session_t *session UNUSED, int *connected UNUSED)
Definition: coap_notls.c:151
#define COAP_OPTION_PROXY_SCHEME
Definition: pdu.h:107
Abstraction of virtual endpoint that can be attached to coap_context_t.
Definition: coap_session.h:301
const char * coap_session_str(const coap_session_t *session)
Get session description.
Definition: coap_session.c:943
#define COAP_RESOURCE_CHECK_TIME
The interval in seconds to check if resources have changed.
Definition: resource.h:22
coap_address_t local_addr
local address and port
Definition: coap_session.h:66
int coap_add_token(coap_pdu_t *pdu, size_t len, const uint8_t *data)
Adds token of length len to pdu.
Definition: pdu.c:205
uint16_t type
decoded option type
Definition: option.h:239
int coap_pdu_resize(coap_pdu_t *pdu, size_t new_size)
Dynamically grows the size of pdu to new_size.
Definition: pdu.c:154
#define COAP_SESSION_STATE_ESTABLISHED
Definition: coap_session.h:54
#define SZX_TO_BYTES(SZX)
Definition: net.c:1646
coap_pong_handler_t pong_handler
Definition: net.h:191
coap_tid_t id
CoAP transaction id.
Definition: net.h:46
unsigned int max_retransmit
maximum re-transmit count (default 4)
Definition: coap_session.h:89
#define COAP_PROTO_UDP
Definition: pdu.h:344
int coap_context_set_pki_root_cas(coap_context_t *ctx, const char *ca_file, const char *ca_dir)
Set the context&#39;s default Root CA information for a client or server.
Definition: net.c:407
coap_tick_t sendqueue_basetime
The time stamp in the first element of the sendqeue is relative to sendqueue_basetime.
Definition: net.h:164
COAP_STATIC_INLINE void * coap_malloc(size_t size)
Wrapper function to coap_malloc_type() for backwards compatibility.
Definition: mem.h:75
Coap string data definition.
Definition: str.h:25
coap_tick_t csm_tx
Definition: coap_session.h:83
coap_pdu_t * coap_new_error_response(coap_pdu_t *request, unsigned char code, coap_opt_filter_t opts)
Creates a new ACK PDU with specified error code.
Definition: net.c:1533
Coap string data definition with const data.
Definition: str.h:33
coap_pdu_t * pdu
the CoAP PDU to send
Definition: net.h:47
coap_tick_t t
when to send PDU for the next time
Definition: net.h:41
#define coap_string_equal(string1, string2)
Compares the two strings for equality.
Definition: str.h:115
size_t coap_pdu_encode_header(coap_pdu_t *pdu, coap_proto_t proto)
Compose the protocol specific header for the specified PDU.
Definition: pdu.c:582
unsigned int ping_timeout
Minimum inactivity time before sending a ping message.
Definition: net.h:216
#define COAP_TICKS_PER_SECOND
Use ms resolution on POSIX systems.
Definition: coap_time.h:100
coap_opt_t * coap_check_option(coap_pdu_t *pdu, uint16_t type, coap_opt_iterator_t *oi)
Retrieves the first option of type type from pdu.
Definition: option.c:207
static int coap_write_endpoint(coap_context_t *ctx, coap_endpoint_t *endpoint, coap_tick_t now)
Definition: net.c:1302
#define FRAC_BITS
The number of bits for the fractional part of ACK_TIMEOUT and ACK_RANDOM_FACTOR.
Definition: net.c:65
size_t psk_hint_len
Definition: net.h:209
#define ACK_TIMEOUT
creates a Qx.FRAC_BITS from session&#39;s &#39;ack_timeout&#39;
Definition: net.c:86
void coap_cleanup(void)
Definition: net.c:2363
#define COAP_PDU_IS_RESPONSE(pdu)
Definition: pdu.h:314
#define COAP_INVALID_TID
Indicates an invalid transaction id.
Definition: pdu.h:241
coap_tick_t last_ping
Definition: coap_session.h:81
coap_session_t * coap_endpoint_get_session(coap_endpoint_t *endpoint, const coap_packet_t *packet, coap_tick_t now)
Definition: coap_session.c:447
coap_address_t remote_addr
remote address and port
Definition: coap_session.h:65
#define RESOURCES_ITER(r, tmp)
Definition: resource.h:455
#define COAP_SIGNALING_PONG
Definition: pdu.h:182
static coap_str_const_t coap_default_uri_wellknown
Definition: net.c:1878
coap_address_t src
the packet&#39;s source address
Definition: coap_io.h:197
unsigned int coap_calc_timeout(coap_session_t *session, unsigned char r)
Calculates the initial timeout based on the session CoAP transmission parameters &#39;ack_timeout&#39;, &#39;ack_random_factor&#39;, and COAP_TICKS_PER_SECOND.
Definition: net.c:798
structure for CoAP PDUs token, if any, follows the fixed size header, then options until payload mark...
Definition: pdu.h:287
int coap_option_filter_get(coap_opt_filter_t filter, uint16_t type)
Checks if type is contained in filter.
Definition: option.c:544
int coap_insert_node(coap_queue_t **queue, coap_queue_t *node)
Adds node to given queue, ordered by variable t in node.
Definition: net.c:188
int coap_can_exit(coap_context_t *context)
Returns 1 if there are no messages to send or to dispatch in the context&#39;s queues.
Definition: net.c:2321
static int coap_read_endpoint(coap_context_t *ctx, coap_endpoint_t *endpoint, coap_tick_t now)
Definition: net.c:1256
uint16_t coap_opt_length(const coap_opt_t *opt)
Returns the length of the given option.
Definition: option.c:249
coap_session_t * coap_endpoint_new_dtls_session(coap_endpoint_t *endpoint, const coap_packet_t *packet, coap_tick_t now)
Definition: coap_session.c:527
#define COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE
Definition: pdu.h:187
ssize_t(* network_send)(coap_socket_t *sock, const coap_session_t *session, const uint8_t *data, size_t datalen)
Definition: net.h:199
struct coap_queue_t * delayqueue
list of delayed messages waiting to be sent
Definition: coap_session.h:74
static size_t coap_get_session_client_psk(const coap_session_t *session, const uint8_t *hint, size_t hint_len, uint8_t *identity, size_t *identity_len, size_t max_identity_len, uint8_t *psk, size_t max_psk_len)
Definition: net.c:294
coap_proto_t proto
protocol used
Definition: coap_session.h:58
#define COAP_MAX_BLOCK_SZX
The largest value for the SZX component in a Block option.
Definition: block.h:30
coap_response_handler_t response_handler
Definition: net.h:188
#define COAP_SIGNALING_OPTION_CUSTODY
Definition: pdu.h:190
#define COAP_OPTION_URI_PORT
Definition: pdu.h:96
unsigned int observable
can be observed
Definition: resource.h:73
#define COAP_PDU_IS_EMPTY(pdu)
Definition: pdu.h:312
Warning.
Definition: coap_debug.h:46
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition: coap_time.h:85
#define assert(...)
Definition: mem.c:18
#define COAP_SOCKET_NOT_EMPTY
the socket is not empty
Definition: coap_io.h:55
void coap_packet_set_addr(coap_packet_t *packet, const coap_address_t *src, const coap_address_t *dst)
Definition: coap_io.c:917
int coap_context_set_psk(coap_context_t *ctx, const char *hint, const uint8_t *key, size_t key_len)
Set the context&#39;s default PSK hint and/or key for a server.
Definition: net.c:349
size_t partial_read
if > 0 indicates number of bytes already read for an incoming message
Definition: coap_session.h:77
coap_pdu_t * partial_pdu
incomplete incoming pdu
Definition: coap_session.h:78
ssize_t coap_session_delay_pdu(coap_session_t *session, coap_pdu_t *pdu, coap_queue_t *node)
Definition: coap_session.c:253
size_t used_size
used bytes of storage for token, options and payload
Definition: pdu.h:296
size_t alloc_size
allocated storage for token, options and payload
Definition: pdu.h:295
int coap_socket_connect_tcp2(coap_socket_t *sock, coap_address_t *local_addr, coap_address_t *remote_addr)
Definition: coap_io.c:373
uint8_t * token
first byte of token, if any, or options
Definition: pdu.h:298
size_t max_size
maximum size for token, options and payload, or zero for variable size pdu
Definition: pdu.h:297
struct coap_queue_t * next
Definition: net.h:40
coap_socket_t sock
socket object for the session, if any
Definition: coap_session.h:68
void coap_ticks(coap_tick_t *t)
Sets t to the internal time with COAP_TICKS_PER_SECOND resolution.
#define COAP_RESPONSE_CLASS(C)
Definition: pdu.h:135
coap_event_handler_t handle_event
Callback function that is used to signal events to the application.
Definition: net.h:197
coap_string_t * coap_get_uri_path(const coap_pdu_t *request)
Definition: uri.c:562
#define COAP_OPTION_IF_NONE_MATCH
Definition: pdu.h:95
#define COAPS_DEFAULT_PORT
Definition: pdu.h:29
int coap_handle_dgram(coap_context_t *ctx, coap_session_t *session, uint8_t *msg, size_t msg_len)
Parses and interprets a CoAP datagram with context ctx.
Definition: net.c:1369
#define COAP_OBSERVE_CANCEL
The value COAP_OBSERVE_CANCEL in a GET request indicates that the observe relationship for (sender ad...
Definition: subscribe.h:35
Iterator to run through PDU options.
Definition: option.h:237
int coap_dtls_context_set_psk(coap_context_t *ctx UNUSED, const char *hint UNUSED, coap_dtls_role_t role UNUSED)
Definition: coap_notls.c:57
coap_proto_t proto
protocol used on this interface
Definition: coap_session.h:304
#define COAP_MESSAGE_CON
Definition: pdu.h:72
#define COAP_MEDIATYPE_APPLICATION_LINK_FORMAT
Definition: pdu.h:200
unsigned int timeout
the randomized timeout value
Definition: net.h:44
#define COAP_PROTO_TLS
Definition: pdu.h:347
#define coap_mcast_interface(Local)
Definition: coap_io.h:156
Coap binary data definition.
Definition: str.h:43
Generic resource handling.
COAP_STATIC_INLINE void coap_free(void *object)
Wrapper function to coap_free_type() for backwards compatibility.
Definition: mem.h:82
Error.
Definition: coap_debug.h:45
#define COAP_MESSAGE_ACK
Definition: pdu.h:74
coap_session_type_t type
client or server side socket
Definition: coap_session.h:59
void * dtls_context
Definition: net.h:207
void coap_delete_string(coap_string_t *s)
Deletes the given string and releases any memory allocated.
Definition: str.c:34
static void handle_response(coap_context_t *context, coap_session_t *session, coap_pdu_t *sent, coap_pdu_t *rcvd)
Definition: net.c:2111
#define COAP_DEFAULT_NSTART
The number of simultaneous outstanding interactions that a client maintains to a given server...
Definition: coap_session.h:408
coap_session_state_t state
current state of relationaship with peer
Definition: coap_session.h:60
size_t psk_identity_len
Definition: coap_session.h:85
size_t coap_add_option(coap_pdu_t *pdu, uint16_t type, size_t len, const uint8_t *data)
Adds option of given type to pdu that is passed as first parameter.
Definition: pdu.c:229
#define COAP_REQUEST_DELETE
Definition: pdu.h:82
coap_pdu_t * coap_wellknown_response(coap_context_t *context, coap_session_t *session, coap_pdu_t *request)
Creates a new response for given request with the contents of .well-known/core.
Definition: net.c:1649
void coap_session_release(coap_session_t *session)
Decrement reference counter on a session.
Definition: coap_session.c:77
coap_tick_t last_tx_rst
Definition: coap_session.h:80
int coap_write_block_opt(coap_block_t *block, uint16_t type, coap_pdu_t *pdu, size_t data_length)
Writes a block option of type type to message pdu.
Definition: block.c:74
COAP_STATIC_INLINE void coap_option_filter_clear(coap_opt_filter_t f)
Clears filter f.
Definition: option.h:130
void coap_cancel_all_messages(coap_context_t *context, coap_session_t *session, const uint8_t *token, size_t token_length)
Cancels all outstanding messages for session session that have the specified token.
Definition: net.c:1484
#define COAP_SESSION_TYPE_HELLO
server-side ephemeral session for responding to a client hello
Definition: coap_session.h:44
int coap_remove_from_queue(coap_queue_t **queue, coap_session_t *session, coap_tid_t id, coap_queue_t **node)
This function removes the element with given id from the list given list.
Definition: net.c:1397
#define COAP_STATIC_INLINE
Definition: libcoap.h:38
size_t(* get_server_hint)(const coap_session_t *session, uint8_t *hint, size_t max_hint_len)
Definition: net.h:205
#define COAP_DEFAULT_PORT
Definition: pdu.h:28
coap_tid_t coap_send_ack(coap_session_t *session, coap_pdu_t *request)
Sends an ACK message with code 0 for the specified request to dst.
Definition: net.c:613
#define COAP_PDU_IS_REQUEST(pdu)
Definition: pdu.h:313
size_t partial_write
if > 0 indicates number of bytes already written from the pdu at the head of sendqueue ...
Definition: coap_session.h:75
size_t length
length of string
Definition: str.h:26
#define COAP_EVENT_DTLS_ERROR
Definition: coap_event.h:36
uint16_t coap_opt_filter_t[COAP_OPT_FILTER_SIZE]
Fixed-size vector we use for option filtering.
Definition: option.h:119
static size_t coap_get_context_server_hint(const coap_session_t *session, uint8_t *hint, size_t max_hint_len)
Definition: net.c:337
#define COAP_EVENT_DTLS_CONNECTED
Definition: coap_event.h:34
int coap_handle_event(coap_context_t *context, coap_event_t event, coap_session_t *session)
Invokes the event handler of context for the given event and data.
Definition: net.c:2310
#define COAP_OPTION_BLOCK2
Definition: pdu.h:117
Subscriber information.
Definition: subscribe.h:56
unsigned int coap_event_t
Scalar type to represent different events, e.g.
Definition: coap_event.h:28
void coap_delete_pdu(coap_pdu_t *pdu)
Dispose of an CoAP PDU and frees associated storage.
Definition: pdu.c:141
const char * coap_response_phrase(unsigned char code)
Returns a human-readable response phrase for the specified CoAP response code.
Definition: pdu.c:384
ssize_t coap_session_write(coap_session_t *session, const uint8_t *data, size_t datalen)
Function interface for stream data transmission.
Definition: coap_session.c:239
coap_address_t dst
the packet&#39;s destination address
Definition: coap_io.h:198
void coap_delete_all(coap_queue_t *queue)
Removes all items from given queue and frees the allocated storage.
Definition: net.c:245
Structure of Block options.
Definition: block.h:36
const uint8_t * s
string data
Definition: str.h:35
unsigned int coap_decode_var_bytes(const uint8_t *buf, unsigned int len)
Decodes multiple-length byte sequences.
Definition: encode.c:36
COAP_STATIC_INLINE void coap_address_copy(coap_address_t *dst, const coap_address_t *src)
Definition: address.h:116
void coap_free_context(coap_context_t *context)
CoAP stack context must be released with coap_free_context().
Definition: net.c:518
static void coap_write_session(coap_context_t *ctx, coap_session_t *session, coap_tick_t now)
Definition: net.c:1071
struct coap_resource_t * unknown_resource
can be used for handling unknown resources
Definition: net.h:152
void coap_session_connected(coap_session_t *session)
Notify session that it has just connected or reconnected.
Definition: coap_session.c:326
int coap_pdu_parse(coap_proto_t proto, const uint8_t *data, size_t length, coap_pdu_t *pdu)
Parses data into the CoAP PDU structure given in result.
Definition: pdu.c:557
const uint8_t * coap_opt_value(const coap_opt_t *opt)
Returns a pointer to the value of the given option.
Definition: option.c:286
COAP_STATIC_INLINE coap_queue_t * coap_malloc_node(void)
Definition: net.c:91
void coap_dtls_free_context(struct coap_dtls_context_t *dtls_context)
Definition: coap_dtls.c:901
#define LL_FOREACH_SAFE(head, el, tmp)
Definition: utlist.h:419
#define COAP_PROTO_RELIABLE(p)
Definition: coap_session.h:36
#define COAP_SESSION_STATE_CONNECTING
Definition: coap_session.h:51
int coap_option_check_critical(coap_context_t *ctx, coap_pdu_t *pdu, coap_opt_filter_t unknown)
Verifies that pdu contains no unknown critical options.
Definition: net.c:561
The structure used for defining the PKI setup data to be used.
Definition: coap_dtls.h:191
coap_resource_t * coap_get_resource_from_uri_path(coap_context_t *context, coap_str_const_t *uri_path)
Returns the resource identified by the unique string uri_path.
Definition: resource.c:515
int coap_dtls_context_set_pki_root_cas(struct coap_context_t *ctx UNUSED, const char *ca_file UNUSED, const char *ca_path UNUSED)
Definition: coap_notls.c:49
void coap_delete_all_resources(coap_context_t *context)
Deletes all resources from given context and frees their storage.
Definition: resource.c:494
coap_subscription_t * coap_add_observer(coap_resource_t *resource, coap_session_t *session, const coap_binary_t *token, coap_string_t *query, int has_block2, coap_block_t block2)
Adds the specified peer as observer for resource.
Definition: resource.c:623
unsigned int csm_timeout
Timeout for waiting for a CSM from the remote side.
Definition: net.h:217
void coap_read(coap_context_t *ctx, coap_tick_t now)
For applications with their own message loop, reads all data from the network.
Definition: net.c:1319
struct coap_dtls_context_t * coap_dtls_new_context(struct coap_context_t *coap_context UNUSED)
Definition: coap_dtls.c:896
#define COAP_OPTION_URI_PATH
Definition: pdu.h:98
#define COAP_SOCKET_WANT_CONNECT
non blocking client socket is waiting for connect
Definition: coap_io.h:61
static enum respond_t no_response(coap_pdu_t *request, coap_pdu_t *response)
Checks for No-Response option in given request and returns 1 if response should be suppressed accordi...
Definition: net.c:1845
size_t(* get_server_psk)(const coap_session_t *session, const uint8_t *identity, size_t identity_len, uint8_t *psk, size_t max_psk_len)
Definition: net.h:204
void * coap_malloc_type(coap_memory_tag_t type, size_t size)
Allocates a chunk of size bytes and returns a pointer to the newly allocated memory.
int coap_get_block(coap_pdu_t *pdu, uint16_t type, coap_block_t *block)
Initializes block from pdu.
Definition: block.c:46
#define ACK_RANDOM_FACTOR
creates a Qx.FRAC_BITS from session&#39;s &#39;ack_random_factor&#39;
Definition: net.c:82
#define LL_DELETE(head, del)
Definition: utlist.h:385
uint8_t * psk_key
Definition: net.h:210
void coap_dtls_startup(void)
Initialize the underlying (D)TLS Library layer.
Definition: coap_notls.c:72
#define COAP_SET_STR(st, l, v)
Definition: str.h:38
#define COAP_PRINT_STATUS_ERROR
Definition: resource.h:315
static size_t coap_get_context_server_psk(const coap_session_t *session, const uint8_t *identity, size_t identity_len, uint8_t *psk, size_t max_psk_len)
Definition: net.c:321
#define COAP_PROTO_NOT_RELIABLE(p)
Definition: coap_session.h:35
coap_log_t coap_get_log_level(void)
Get the current logging level.
Definition: coap_debug.c:71
int64_t coap_tick_diff_t
This data type is used to represent the difference between two clock_tick_t values.
Definition: coap_time.h:97
int coap_dtls_send(struct coap_context_t *coap_context UNUSED, struct coap_dtls_session_t *session UNUSED, const unsigned char *data UNUSED, size_t data_len UNUSED)
Definition: coap_dtls.c:912
static void coap_read_session(coap_context_t *ctx, coap_session_t *session, coap_tick_t now)
Definition: net.c:1126
uint8_t hdr_size
actaul size used for protocol-specific header
Definition: pdu.h:291
size_t psk_key_len
Definition: coap_session.h:87
#define COAP_OPTION_URI_QUERY
Definition: pdu.h:102
void * app
application-specific data
Definition: net.h:219
coap_socket_flags_t flags
Definition: coap_io.h:48
#define COAP_SOCKET_CAN_WRITE
non blocking socket can now write without blocking
Definition: coap_io.h:63
size_t coap_pdu_parse_header_size(coap_proto_t proto, const uint8_t *data)
Interprets data to determine the number of bytes in the header.
Definition: pdu.c:419
void coap_session_disconnected(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
Definition: coap_session.c:383
coap_session_t * sessions
client sessions
Definition: net.h:167
void coap_set_app_data(coap_context_t *ctx, void *app_data)
Stores data with the given CoAP context.
Definition: net.c:506
#define coap_log(level,...)
Logging function.
Definition: coap_debug.h:122
coap_tid_t coap_send_error(coap_session_t *session, coap_pdu_t *request, unsigned char code, coap_opt_filter_t opts)
Sends an error response with code code for request request to dst.
Definition: net.c:754
#define COAP_OPTION_ACCEPT
Definition: pdu.h:103
COAP_STATIC_INLINE size_t get_wkc_len(coap_context_t *context, coap_opt_t *query_filter)
Quick hack to determine the size of the resource description for .well-known/core.
Definition: net.c:1631
coap_print_status_t coap_print_wellknown(coap_context_t *context, unsigned char *buf, size_t *buflen, size_t offset, coap_opt_t *query_filter)
Prints the names of all known resources to buf.
Definition: resource.c:169
coap_socket_t sock
socket object for the interface, if any
Definition: coap_session.h:306
#define COAP_SIGNALING_RELEASE
Definition: pdu.h:183
ssize_t coap_session_send_pdu(coap_session_t *session, coap_pdu_t *pdu)
Send a pdu according to the session&#39;s protocol.
Definition: net.c:627
coap_pdu_t * coap_pdu_init(uint8_t type, uint8_t code, uint16_t tid, size_t size)
Creates a new CoAP PDU with at least enough storage space for the given size maximum message size...
Definition: pdu.c:91
void coap_memory_init(void)
Initializes libcoap&#39;s memory management.
void coap_handle_failed_notify(coap_context_t *context, coap_session_t *session, const coap_binary_t *token)
Definition: resource.c:930
#define COAP_PDU_IS_SIGNALING(pdu)
Definition: pdu.h:315
coap_session_t * session
the CoAP session
Definition: net.h:45
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
Definition: mem.h:34
coap_str_const_t * uri_path
Request URI Path for this resource.
Definition: resource.h:96
ssize_t coap_network_read(coap_socket_t *sock, coap_packet_t *packet)
Function interface for reading data.
Definition: coap_io.c:923
size_t length
length of binary data
Definition: str.h:44
void coap_dispatch(coap_context_t *context, coap_session_t *session, coap_pdu_t *pdu)
Dispatches the PDUs from the receive queue in given context.
Definition: net.c:2169
unsigned char uint8_t
Definition: uthash.h:79
void coap_cancel_session_messages(coap_context_t *context, coap_session_t *session, coap_nack_reason_t reason)
Cancels all outstanding messages for session session.
Definition: net.c:1447
void coap_context_set_keepalive(coap_context_t *context, unsigned int seconds)
Set the context keepalive timer for sessions.
Definition: net.c:417
int coap_is_mcast(const coap_address_t *a)
Checks if given address a denotes a multicast address.
Definition: address.c:59
struct coap_endpoint_t * endpoint
session&#39;s endpoint
Definition: coap_session.h:69
void coap_free_endpoint(coap_endpoint_t *ep)
Definition: coap_session.c:901
#define prng(Buf, Length)
Fills Buf with Length bytes of random data.
Definition: prng.h:112
static void handle_request(coap_context_t *context, coap_session_t *session, coap_pdu_t *pdu)
Definition: net.c:1883
static int coap_started
Definition: net.c:2341
Emergency.
Definition: coap_debug.h:42
uint8_t token_length
length of Token
Definition: pdu.h:292
coap_tick_t last_pong
Definition: coap_session.h:82
static int coap_cancel(coap_context_t *context, const coap_queue_t *sent)
This function cancels outstanding messages for the session and token specified in sent...
Definition: net.c:1786
#define min(a, b)
Definition: net.c:58
#define COAP_SOCKET_CAN_CONNECT
non blocking client socket can now connect without blocking
Definition: coap_io.h:65
#define MAX_BITS
The maximum number of bits for fixed point integers that are used for retransmission time calculation...
Definition: net.c:71
void(* coap_method_handler_t)(coap_context_t *, struct coap_resource_t *, coap_session_t *, coap_pdu_t *, coap_binary_t *, coap_string_t *, coap_pdu_t *)
Definition of message handler function (.
Definition: resource.h:36
#define COAP_SESSION_STATE_NONE
coap_session_state_t values
Definition: coap_session.h:50
coap_opt_iterator_t * coap_option_iterator_init(const coap_pdu_t *pdu, coap_opt_iterator_t *oi, const coap_opt_filter_t filter)
Initializes the given option iterator oi to point to the beginning of the pdu&#39;s option list...
Definition: option.c:121
coap_tid_t coap_retransmit(coap_context_t *context, coap_queue_t *node)
Handles retransmissions of confirmable messages.
Definition: net.c:931
uint8_t read_header[8]
storage space for header of incoming message header
Definition: coap_session.h:76
Information.
Definition: coap_debug.h:48
uint8_t * s
binary data
Definition: str.h:45
#define COAP_OPTION_URI_HOST
Definition: pdu.h:93
coap_queue_t * coap_pop_next(coap_context_t *context)
Returns the next pdu to send and removes it from the sendqeue.
Definition: net.c:278
uint16_t message_id
The last message id that was used is stored in this field.
Definition: net.h:186
#define COAP_SIGNALING_ABORT
Definition: pdu.h:184
Queue entry.
Definition: net.h:39
coap_method_handler_t handler[7]
Used to store handlers for the seven coap methods GET, POST, PUT, DELETE, FETCH, PATCH and IPATCH...
Definition: resource.h:84
Alert.
Definition: coap_debug.h:43
coap_queue_t * coap_new_node(void)
Creates a new node suitable for adding to the CoAP sendqueue.
Definition: net.c:254
coap_address_t bind_addr
local interface address
Definition: coap_session.h:307
#define COAP_PROTO_TCP
Definition: pdu.h:346
uint8_t * psk_key
Definition: coap_session.h:86
respond_t
Internal flags to control the treatment of responses (specifically in presence of the No-Response opt...
Definition: net.c:1812
#define FP1
The CoAP stack&#39;s global state is stored in a coap_context_t object.
Definition: net.h:148
uint16_t tid
transaction id, if any, in regular host byte order
Definition: pdu.h:293
int coap_delete_node(coap_queue_t *node)
Destroys specified node.
Definition: net.c:225
struct coap_resource_t * resources
hash table or list of known resources
Definition: net.h:150
size_t coap_pdu_parse_size(coap_proto_t proto, const uint8_t *data, size_t length)
Parses data to extract the message size.
Definition: pdu.c:442
static void handle_signaling(coap_context_t *context, coap_session_t *session, coap_pdu_t *pdu)
Definition: net.c:2129
unsigned int coap_adjust_basetime(coap_context_t *ctx, coap_tick_t now)
Set sendqueue_basetime in the given context object ctx to now.
Definition: net.c:151
#define COAP_SESSION_STATE_CSM
Definition: coap_session.h:53
#define COAP_SOCKET_WANT_WRITE
non blocking socket is waiting for writing
Definition: coap_io.h:59
unsigned int m
1 if more blocks follow, 0 otherwise
Definition: block.h:38
unsigned int szx
block size
Definition: block.h:39
unsigned int num
block number
Definition: block.h:37
coap_opt_filter_t known_options
Definition: net.h:149
#define COAP_DROPPED_RESPONSE
Indicates that a response is suppressed.
Definition: pdu.h:247