libcoap  4.0.3
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
net.c
Go to the documentation of this file.
1 /* net.c -- CoAP network interface
2  *
3  * Copyright (C) 2010--2012 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 "config.h"
10 
11 #include <ctype.h>
12 #include <stdio.h>
13 #ifdef HAVE_UNISTD_H
14 #include <unistd.h>
15 #elif HAVE_SYS_UNISTD_H
16 #include <sys/unistd.h>
17 #endif
18 #include <sys/types.h>
19 #ifdef HAVE_SYS_SOCKET_H
20 #include <sys/socket.h>
21 #endif
22 #ifdef HAVE_NETINET_IN_H
23 #include <netinet/in.h>
24 #endif
25 #ifdef HAVE_ARPA_INET_H
26 #include <arpa/inet.h>
27 #endif
28 
29 #include "debug.h"
30 #include "mem.h"
31 #include "str.h"
32 #include "async.h"
33 #include "resource.h"
34 #include "option.h"
35 #include "encode.h"
36 #include "net.h"
37 
38 #ifndef WITH_CONTIKI
39 
40 time_t clock_offset;
41 
42 static inline coap_queue_t *
44  return (coap_queue_t *)coap_malloc(sizeof(coap_queue_t));
45 }
46 
47 static inline void
49  coap_free(node);
50 }
51 #else /* WITH_CONTIKI */
52 # ifndef DEBUG
53 # define DEBUG DEBUG_PRINT
54 # endif /* DEBUG */
55 
56 #include "memb.h"
57 #include "net/uip-debug.h"
58 
59 clock_time_t clock_offset;
60 
61 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
62 #define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN])
63 
64 void coap_resources_init();
65 void coap_pdu_resources_init();
66 
67 unsigned char initialized = 0;
68 coap_context_t the_coap_context;
69 
70 MEMB(node_storage, coap_queue_t, COAP_PDU_MAXCNT);
71 
72 PROCESS(coap_retransmit_process, "message retransmit process");
73 
74 static inline coap_queue_t *
76  return (coap_queue_t *)memb_alloc(&node_storage);
77 }
78 
79 static inline void
81  memb_free(&node_storage, node);
82 }
83 #endif /* WITH_CONTIKI */
84 
85 int print_wellknown(coap_context_t *, unsigned char *, size_t *, coap_opt_t *);
86 
88  const str *);
89 
90 int
92  int (*order)(coap_queue_t *, coap_queue_t *node) ) {
93  coap_queue_t *p, *q;
94  if ( !queue || !node )
95  return 0;
96 
97  /* set queue head if empty */
98  if ( !*queue ) {
99  *queue = node;
100  return 1;
101  }
102 
103  /* replace queue head if PDU's time is less than head's time */
104  q = *queue;
105  if ( order( node, q ) < 0) {
106  node->next = q;
107  *queue = node;
108  return 1;
109  }
110 
111  /* search for right place to insert */
112  do {
113  p = q;
114  q = q->next;
115  } while ( q && order( node, q ) >= 0 );
116 
117  /* insert new item */
118  node->next = q;
119  p->next = node;
120  return 1;
121 }
122 
123 int
125  if ( !node )
126  return 0;
127 
128  coap_delete_pdu(node->pdu);
129  coap_free_node(node);
130 
131  return 1;
132 }
133 
134 void
136  if ( !queue )
137  return;
138 
139  coap_delete_all( queue->next );
140  coap_delete_node( queue );
141 }
142 
143 coap_queue_t *
145  coap_queue_t *node;
146  node = coap_malloc_node();
147 
148  if ( ! node ) {
149 #ifndef NDEBUG
150  coap_log(LOG_WARN, "coap_new_node: malloc");
151 #endif
152  return NULL;
153  }
154 
155  memset(node, 0, sizeof *node );
156  return node;
157 }
158 
159 coap_queue_t *
161  if ( !context || !context->sendqueue )
162  return NULL;
163 
164  return context->sendqueue;
165 }
166 
167 coap_queue_t *
169  coap_queue_t *next;
170 
171  if ( !context || !context->sendqueue )
172  return NULL;
173 
174  next = context->sendqueue;
175  context->sendqueue = context->sendqueue->next;
176  next->next = NULL;
177  return next;
178 }
179 
180 #ifdef COAP_DEFAULT_WKC_HASHKEY
181 
182 #define is_wkc(Key) \
183  (memcmp((Key), COAP_DEFAULT_WKC_HASHKEY, sizeof(coap_key_t)) == 0)
184 #else
185 /* Implements a singleton to store a hash key for the .wellknown/core
186  * resources. */
187 int
188 is_wkc(coap_key_t k) {
189  static coap_key_t wkc;
190  static unsigned char _initialized = 0;
191  if (!_initialized) {
192  _initialized = coap_hash_path((unsigned char *)COAP_DEFAULT_URI_WELLKNOWN,
193  sizeof(COAP_DEFAULT_URI_WELLKNOWN) - 1, wkc);
194  }
195  return memcmp(k, wkc, sizeof(coap_key_t)) == 0;
196 }
197 #endif
198 
200 coap_new_context(const coap_address_t *listen_addr) {
201 #ifndef WITH_CONTIKI
202  coap_context_t *c = coap_malloc( sizeof( coap_context_t ) );
203  int reuse = 1;
204 #else /* WITH_CONTIKI */
205  coap_context_t *c;
206 
207  if (initialized)
208  return NULL;
209 #endif /* WITH_CONTIKI */
210 
211  if (!listen_addr) {
212  coap_log(LOG_EMERG, "no listen address specified\n");
213  return NULL;
214  }
215 
216  coap_clock_init();
217  prng_init((unsigned long)listen_addr ^ clock_offset);
218 
219 #ifndef WITH_CONTIKI
220  if ( !c ) {
221 #ifndef NDEBUG
222  coap_log(LOG_EMERG, "coap_init: malloc:");
223 #endif
224  return NULL;
225  }
226 #else /* WITH_CONTIKI */
227  coap_resources_init();
228  coap_pdu_resources_init();
229 
230  c = &the_coap_context;
231  initialized = 1;
232 #endif /* WITH_CONTIKI */
233 
234  memset(c, 0, sizeof( coap_context_t ) );
235 
236  /* initialize message id */
237  prng((unsigned char *)&c->message_id, sizeof(unsigned short));
238 
239  /* register the critical options that we know */
249 
250 #ifndef WITH_CONTIKI
251  c->sockfd = socket(listen_addr->addr.sa.sa_family, SOCK_DGRAM, 0);
252  if ( c->sockfd < 0 ) {
253 #ifndef NDEBUG
254  coap_log(LOG_EMERG, "coap_new_context: socket");
255 #endif
256  goto onerror;
257  }
258 
259  if ( setsockopt( c->sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse) ) < 0 ) {
260 #ifndef NDEBUG
261  coap_log(LOG_WARN, "setsockopt SO_REUSEADDR");
262 #endif
263  }
264 
265  if (bind(c->sockfd, &listen_addr->addr.sa, listen_addr->size) < 0) {
266 #ifndef NDEBUG
267  coap_log(LOG_EMERG, "coap_new_context: bind");
268 #endif
269  goto onerror;
270  }
271 
272  return c;
273 
274  onerror:
275  if ( c->sockfd >= 0 )
276  close ( c->sockfd );
277  coap_free( c );
278  return NULL;
279 
280 #else /* WITH_CONTIKI */
281  c->conn = udp_new(NULL, 0, NULL);
282  udp_bind(c->conn, listen_addr->port);
283 
284  process_start(&coap_retransmit_process, (char *)c);
285 
286  PROCESS_CONTEXT_BEGIN(&coap_retransmit_process);
287 #ifndef WITHOUT_OBSERVE
288  etimer_set(&c->notify_timer, COAP_RESOURCE_CHECK_TIME * COAP_TICKS_PER_SECOND);
289 #endif /* WITHOUT_OBSERVE */
290  /* the retransmit timer must be initialized to some large value */
291  etimer_set(&the_coap_context.retransmit_timer, 0xFFFF);
292  PROCESS_CONTEXT_END(&coap_retransmit_process);
293  return c;
294 #endif /* WITH_CONTIKI */
295 }
296 
297 void
299 #ifndef WITH_CONTIKI
300  coap_resource_t *res, *rtmp;
301 #endif /* WITH_CONTIKI */
302  if ( !context )
303  return;
304 
305  coap_delete_all(context->recvqueue);
306  coap_delete_all(context->sendqueue);
307 
308 #ifndef WITH_CONTIKI
309  HASH_ITER(hh, context->resources, res, rtmp) {
310  coap_delete_resource(context, res->key);
311  }
312 
313  /* coap_delete_list(context->subscriptions); */
314  close( context->sockfd );
315  coap_free( context );
316 #else /* WITH_CONTIKI */
317  memset(&the_coap_context, 0, sizeof(coap_context_t));
318  initialized = 0;
319 #endif /* WITH_CONTIKI */
320 }
321 
322 int
324  coap_pdu_t *pdu,
325  coap_opt_filter_t unknown) {
326 
327  coap_opt_iterator_t opt_iter;
328  int ok = 1;
329 
330  coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL);
331 
332  while (coap_option_next(&opt_iter)) {
333 
334  /* The following condition makes use of the fact that
335  * coap_option_getb() returns -1 if type exceeds the bit-vector
336  * filter. As the vector is supposed to be large enough to hold
337  * the largest known option, we know that everything beyond is
338  * bad.
339  */
340  if (opt_iter.type & 0x01 &&
341  coap_option_getb(ctx->known_options, opt_iter.type) < 1) {
342  debug("unknown critical option %d\n", opt_iter.type);
343 
344  ok = 0;
345 
346  /* When opt_iter.type is beyond our known option range,
347  * coap_option_setb() will return -1 and we are safe to leave
348  * this loop. */
349  if (coap_option_setb(unknown, opt_iter.type) == -1)
350  break;
351  }
352  }
353 
354  return ok;
355 }
356 
357 void
359  coap_tid_t *id) {
360  coap_key_t h;
361 
362  memset(h, 0, sizeof(coap_key_t));
363 
364  /* Compare the complete address structure in case of IPv4. For IPv6,
365  * we need to look at the transport address only. */
366 
367 #ifndef WITH_CONTIKI
368  switch (peer->addr.sa.sa_family) {
369  case AF_INET:
370  coap_hash((const unsigned char *)&peer->addr.sa, peer->size, h);
371  break;
372  case AF_INET6:
373  coap_hash((const unsigned char *)&peer->addr.sin6.sin6_port,
374  sizeof(peer->addr.sin6.sin6_port), h);
375  coap_hash((const unsigned char *)&peer->addr.sin6.sin6_addr,
376  sizeof(peer->addr.sin6.sin6_addr), h);
377  break;
378  default:
379  return;
380  }
381 #else /* WITH_CONTIKI */
382  coap_hash((const unsigned char *)&peer->port, sizeof(peer->port), h);
383  coap_hash((const unsigned char *)&peer->addr, sizeof(peer->addr), h);
384 #endif /* WITH_CONTIKI */
385 
386  coap_hash((const unsigned char *)&pdu->hdr->id, sizeof(unsigned short), h);
387 
388  *id = ((h[0] << 8) | h[1]) ^ ((h[2] << 8) | h[3]);
389 }
390 
393  const coap_address_t *dst,
394  coap_pdu_t *request) {
395  coap_pdu_t *response;
396  coap_tid_t result = COAP_INVALID_TID;
397 
398  if (request && request->hdr->type == COAP_MESSAGE_CON) {
399  response = coap_pdu_init(COAP_MESSAGE_ACK, 0, request->hdr->id,
400  sizeof(coap_pdu_t));
401  if (response) {
402  result = coap_send(context, dst, response);
403  coap_delete_pdu(response);
404  }
405  }
406  return result;
407 }
408 
409 #ifndef WITH_CONTIKI
410 /* releases space allocated by PDU if free_pdu is set */
413  const coap_address_t *dst,
414  coap_pdu_t *pdu) {
415  ssize_t bytes_written;
417 
418  if ( !context || !dst || !pdu )
419  return id;
420 
421  bytes_written = sendto( context->sockfd, pdu->hdr, pdu->length, 0,
422  &dst->addr.sa, dst->size);
423 
424  if (bytes_written >= 0) {
425  coap_transaction_id(dst, pdu, &id);
426  } else {
427  coap_log(LOG_CRIT, "coap_send: sendto");
428  }
429 
430  return id;
431 }
432 #else /* WITH_CONTIKI */
433 /* releases space allocated by PDU if free_pdu is set */
436  const coap_address_t *dst,
437  coap_pdu_t *pdu) {
439 
440  if ( !context || !dst || !pdu )
441  return id;
442 
443  /* FIXME: is there a way to check if send was successful? */
444  uip_udp_packet_sendto(context->conn, pdu->hdr, pdu->length,
445  &dst->addr, dst->port);
446 
447  coap_transaction_id(dst, pdu, &id);
448 
449  return id;
450 }
451 #endif /* WITH_CONTIKI */
452 
453 coap_tid_t
455  const coap_address_t *dst,
456  coap_pdu_t *pdu) {
457  return coap_send_impl(context, dst, pdu);
458 }
459 
462  coap_pdu_t *request,
463  const coap_address_t *dst,
464  unsigned char code,
465  coap_opt_filter_t opts) {
466  coap_pdu_t *response;
467  coap_tid_t result = COAP_INVALID_TID;
468 
469  assert(request);
470  assert(dst);
471 
472  response = coap_new_error_response(request, code, opts);
473  if (response) {
474  result = coap_send(context, dst, response);
475  coap_delete_pdu(response);
476  }
477 
478  return result;
479 }
480 
483  const coap_address_t *dst,
484  coap_pdu_t *request,
485  unsigned char type) {
486  coap_pdu_t *response;
487  coap_tid_t result = COAP_INVALID_TID;
488 
489  if (request) {
490  response = coap_pdu_init(type, 0, request->hdr->id, sizeof(coap_pdu_t));
491  if (response) {
492  result = coap_send(context, dst, response);
493  coap_delete_pdu(response);
494  }
495  }
496  return result;
497 }
498 
499 int
501  return lhs && rhs && ( lhs->t < rhs->t ) ? -1 : 1;
502 }
503 
506  const coap_address_t *dst,
507  coap_pdu_t *pdu) {
508  coap_queue_t *node;
509  coap_tick_t now;
510  int r;
511 
512  node = coap_new_node();
513  if (!node) {
514  debug("coap_send_confirmed: insufficient memory\n");
515  return COAP_INVALID_TID;
516  }
517 
518  node->id = coap_send_impl(context, dst, pdu);
519  if (COAP_INVALID_TID == node->id) {
520  debug("coap_send_confirmed: error sending pdu\n");
521  coap_free_node(node);
522  return COAP_INVALID_TID;
523  }
524 
525  prng((unsigned char *)&r,sizeof(r));
526  coap_ticks(&now);
527  node->t = now;
528 
529  /* add randomized RESPONSE_TIMEOUT to determine retransmission timeout */
532  ((COAP_TICKS_PER_SECOND * (r & 0xFF)) >> 8);
533  node->t += node->timeout;
534 
535  memcpy(&node->remote, dst, sizeof(coap_address_t));
536  node->pdu = pdu;
537 
538  assert(&context->sendqueue);
539  coap_insert_node(&context->sendqueue, node, _order_timestamp);
540 
541 #ifdef WITH_CONTIKI
542  { /* (re-)initialize retransmission timer */
543  coap_queue_t *nextpdu;
544 
545  nextpdu = coap_peek_next(context);
546  assert(nextpdu); /* we have just inserted a node */
547 
548  /* must set timer within the context of the retransmit process */
549  PROCESS_CONTEXT_BEGIN(&coap_retransmit_process);
550  etimer_set(&context->retransmit_timer,
551  now < nextpdu->t ? nextpdu->t - now : 0);
552  PROCESS_CONTEXT_END(&coap_retransmit_process);
553  }
554 #endif /* WITH_CONTIKI */
555 
556  return node->id;
557 }
558 
561  if ( !context || !node )
562  return COAP_INVALID_TID;
563 
564  /* re-initialize timeout when maximum number of retransmissions are not reached yet */
566  node->retransmit_cnt++;
567  node->t += ( node->timeout << node->retransmit_cnt );
568  coap_insert_node( &context->sendqueue, node, _order_timestamp );
569 
570 #ifndef WITH_CONTIKI
571  debug("** retransmission #%d of transaction %d\n",
572  node->retransmit_cnt, ntohs(node->pdu->hdr->id));
573 #else /* WITH_CONTIKI */
574  debug("** retransmission #%u of transaction %u\n",
575  node->retransmit_cnt, uip_ntohs(node->pdu->hdr->id));
576 #endif /* WITH_CONTIKI */
577 
578  node->id = coap_send_impl(context, &node->remote, node->pdu);
579  return node->id;
580  }
581 
582  /* no more retransmissions, remove node from system */
583 
584 #ifndef WITH_CONTIKI
585  debug("** removed transaction %d\n", ntohs(node->id));
586 #endif
587 
588 #ifndef WITHOUT_OBSERVE
589  /* Check if subscriptions exist that should be canceled after
590  COAP_MAX_NOTIFY_FAILURES */
591  if (node->pdu->hdr->code >= 64) {
592  str token = { 0, NULL };
593 
594  token.length = node->pdu->hdr->token_length;
595  token.s = node->pdu->hdr->token;
596 
597  coap_handle_failed_notify(context, &node->remote, &token);
598  }
599 #endif /* WITHOUT_OBSERVE */
600 
601  /* And finally delete the node */
602  coap_delete_node( node );
603  return COAP_INVALID_TID;
604 }
605 
606 int
608  return ( lhs && rhs && lhs->pdu && rhs->pdu &&
609  ( lhs->id < rhs->id ) )
610  ? -1
611  : 1;
612 }
613 
619 static inline int
620 check_opt_size(coap_opt_t *opt, unsigned char *maxpos) {
621  if (opt && opt < maxpos) {
622  if (((*opt & 0x0f) < 0x0f) || (opt + 1 < maxpos))
623  return opt + COAP_OPT_SIZE(opt) < maxpos;
624  }
625  return 0;
626 }
627 
628 int
630 #ifndef WITH_CONTIKI
631  static char buf[COAP_MAX_PDU_SIZE];
632  coap_hdr_t *pdu = (coap_hdr_t *)buf;
633 #else /* WITH_CONTIKI */
634  char *buf;
635  coap_hdr_t *pdu;
636 #endif /* WITH_CONTIKI */
637  ssize_t bytes_read = -1;
638  coap_address_t src, dst;
639  coap_queue_t *node;
640 
641 #ifdef WITH_CONTIKI
642  buf = uip_appdata;
643  pdu = (coap_hdr_t *)buf;
644 #endif /* WITH_CONTIKI */
645 
646  coap_address_init(&src);
647 
648 #ifndef WITH_CONTIKI
649  bytes_read = recvfrom(ctx->sockfd, buf, sizeof(buf), 0,
650  &src.addr.sa, &src.size);
651 #else /* WITH_CONTIKI */
652  if(uip_newdata()) {
653  uip_ipaddr_copy(&src.addr, &UIP_IP_BUF->srcipaddr);
654  src.port = UIP_UDP_BUF->srcport;
655  uip_ipaddr_copy(&dst.addr, &UIP_IP_BUF->destipaddr);
656  dst.port = UIP_UDP_BUF->destport;
657 
658  bytes_read = uip_datalen();
659  ((char *)uip_appdata)[bytes_read] = 0;
660  PRINTF("Server received %d bytes from [", (int)bytes_read);
661  PRINT6ADDR(&src.addr);
662  PRINTF("]:%d\n", uip_ntohs(src.port));
663  }
664 #endif /* WITH_CONTIKI */
665 
666  if ( bytes_read < 0 ) {
667  warn("coap_read: recvfrom");
668  return -1;
669  }
670 
671  if ( (size_t)bytes_read < sizeof(coap_hdr_t) ) {
672  debug("coap_read: discarded invalid frame\n" );
673  return -1;
674  }
675 
676  if ( pdu->version != COAP_DEFAULT_VERSION ) {
677  debug("coap_read: unknown protocol version\n" );
678  return -1;
679  }
680 
681  node = coap_new_node();
682  if ( !node )
683  return -1;
684 
685  node->pdu = coap_pdu_init(0, 0, 0, bytes_read);
686  if (!node->pdu)
687  goto error;
688 
689  coap_ticks( &node->t );
690  memcpy(&node->local, &dst, sizeof(coap_address_t));
691  memcpy(&node->remote, &src, sizeof(coap_address_t));
692 
693 if (!coap_pdu_parse((unsigned char *)buf, bytes_read, node->pdu)) {
694  warn("discard malformed PDU");
695  goto error;
696  }
697 
698  /* and add new node to receive queue */
699  coap_transaction_id(&node->remote, node->pdu, &node->id);
701 
702 #ifndef NDEBUG
703  if (LOG_DEBUG <= coap_get_log_level()) {
704 #ifndef INET6_ADDRSTRLEN
705 #define INET6_ADDRSTRLEN 40
706 #endif
707  unsigned char addr[INET6_ADDRSTRLEN+8];
708 
709  if (coap_print_addr(&src, addr, INET6_ADDRSTRLEN+8))
710  debug("** received %d bytes from %s:\n", (int)bytes_read, addr);
711 
712  coap_show_pdu( node->pdu );
713  }
714 #endif
715 
716  return 0;
717  error:
718  /* FIXME: send back RST? */
719  coap_delete_node(node);
720  return -1;
721 }
722 
723 int
725  coap_queue_t *p, *q;
726 
727  if ( !queue || !*queue)
728  return 0;
729 
730  /* replace queue head if PDU's time is less than head's time */
731 
732  if ( id == (*queue)->id ) { /* found transaction */
733  *node = *queue;
734  *queue = (*queue)->next;
735  (*node)->next = NULL;
736  /* coap_delete_node( q ); */
737  debug("*** removed transaction %u\n", id);
738  return 1;
739  }
740 
741  /* search transaction to remove (only first occurence will be removed) */
742  q = *queue;
743  do {
744  p = q;
745  q = q->next;
746  } while ( q && id != q->id );
747 
748  if ( q ) { /* found transaction */
749  p->next = q->next;
750  q->next = NULL;
751  *node = q;
752  /* coap_delete_node( q ); */
753  debug("*** removed transaction %u\n", id);
754  return 1;
755  }
756 
757  return 0;
758 
759 }
760 
761 static inline int
762 token_match(const unsigned char *a, size_t alen,
763  const unsigned char *b, size_t blen) {
764  return alen == blen && (alen == 0 || memcmp(a, b, alen) == 0);
765 }
766 
767 void
769  const unsigned char *token, size_t token_length) {
770  /* cancel all messages in sendqueue that are for dst
771  * and use the specified token */
772  coap_queue_t *p, *q;
773 
774  debug("cancel_all_messages\n");
775  while (context->sendqueue &&
776  coap_address_equals(dst, &context->sendqueue->remote) &&
777  token_match(token, token_length,
778  context->sendqueue->pdu->hdr->token,
779  context->sendqueue->pdu->hdr->token_length)) {
780  q = context->sendqueue;
781  context->sendqueue = q->next;
782  debug("**** removed transaction %d\n", ntohs(q->pdu->hdr->id));
783  coap_delete_node(q);
784  }
785 
786  if (!context->sendqueue)
787  return;
788 
789  p = context->sendqueue;
790  q = p->next;
791 
792  /* when q is not NULL, it does not match (dst, token), so we can skip it */
793  while (q) {
794  if (coap_address_equals(dst, &q->remote) &&
795  token_match(token, token_length,
796  q->pdu->hdr->token, q->pdu->hdr->token_length)) {
797  p->next = q->next;
798  debug("**** removed transaction %d\n", ntohs(q->pdu->hdr->id));
799  coap_delete_node(q);
800  q = p->next;
801  } else {
802  p = q;
803  q = q->next;
804  }
805  }
806 }
807 
808 coap_queue_t *
810  while (queue && queue->id != id)
811  queue = queue->next;
812 
813  return queue;
814 }
815 
816 coap_pdu_t *
817 coap_new_error_response(coap_pdu_t *request, unsigned char code,
818  coap_opt_filter_t opts) {
819  coap_opt_iterator_t opt_iter;
820  coap_pdu_t *response;
821  size_t size = sizeof(coap_hdr_t) + request->hdr->token_length;
822  int type;
823  coap_opt_t *option;
824  unsigned short opt_type = 0; /* used for calculating delta-storage */
825 
827  char *phrase = coap_response_phrase(code);
828 
829  /* Need some more space for the error phrase and payload start marker */
830  if (phrase)
831  size += strlen(phrase) + 1;
832 #endif
833 
834  assert(request);
835 
836  /* cannot send ACK if original request was not confirmable */
837  type = request->hdr->type == COAP_MESSAGE_CON
840 
841  /* Estimate how much space we need for options to copy from
842  * request. We always need the Token, for 4.02 the unknown critical
843  * options must be included as well. */
844  coap_option_clrb(opts, COAP_OPTION_CONTENT_TYPE); /* we do not want this */
845 
846  coap_option_iterator_init(request, &opt_iter, opts);
847 
848  /* Add size of each unknown critical option. As known critical
849  options as well as elective options are not copied, the delta
850  value might grow.
851  */
852  while((option = coap_option_next(&opt_iter))) {
853  unsigned short delta = opt_iter.type - opt_type;
854  /* calculate space required to encode (opt_iter.type - opt_type) */
855  if (delta < 13) {
856  size++;
857  } else if (delta < 269) {
858  size += 2;
859  } else {
860  size += 3;
861  }
862 
863  /* add coap_opt_length(option) and the number of additional bytes
864  * required to encode the option length */
865 
866  size += coap_opt_length(option);
867  switch (*option & 0x0f) {
868  case 0x0e:
869  size++;
870  /* fall through */
871  case 0x0d:
872  size++;
873  break;
874  default:
875  ;
876  }
877 
878  opt_type = opt_iter.type;
879  }
880 
881  /* Now create the response and fill with options and payload data. */
882  response = coap_pdu_init(type, code, request->hdr->id, size);
883  if (response) {
884  /* copy token */
885  if (!coap_add_token(response, request->hdr->token_length,
886  request->hdr->token)) {
887  debug("cannot add token to error response\n");
888  coap_delete_pdu(response);
889  return NULL;
890  }
891 
892  /* copy all options */
893  coap_option_iterator_init(request, &opt_iter, opts);
894  while((option = coap_option_next(&opt_iter)))
895  coap_add_option(response, opt_iter.type,
896  COAP_OPT_LENGTH(option),
897  COAP_OPT_VALUE(option));
898 
899 #if COAP_ERROR_PHRASE_LENGTH > 0
900  /* note that diagnostic messages do not need a Content-Format option. */
901  if (phrase)
902  coap_add_data(response, strlen(phrase), (unsigned char *)phrase);
903 #endif
904  }
905 
906  return response;
907 }
908 
909 coap_pdu_t *
911  coap_pdu_t *resp;
912  coap_opt_iterator_t opt_iter;
913  size_t len;
914  unsigned char buf[2];
915 
916  resp = coap_pdu_init(request->hdr->type == COAP_MESSAGE_CON
919  COAP_RESPONSE_CODE(205),
920  request->hdr->id, COAP_MAX_PDU_SIZE);
921  if (!resp) {
922  debug("wellknown_response: cannot create PDU\n");
923  return NULL;
924  }
925 
926  if (!coap_add_token(resp, request->hdr->token_length, request->hdr->token)) {
927  debug("wellknown_response: cannot add token\n");
928  goto error;
929  }
930 
931  /* Check if there is sufficient space to add Content-Format option
932  * and data. We do this before adding the Content-Format option to
933  * avoid sending error responses with that option but no actual
934  * content. */
935  if (resp->max_size <= (size_t)resp->length + 3) {
936  debug("wellknown_response: insufficient storage space\n");
937  goto error;
938  }
939 
940  /* Add Content-Format. As we have checked for available storage,
941  * nothing should go wrong here. */
942  assert(coap_encode_var_bytes(buf,
947 
948  /* Manually set payload of response to let print_wellknown() write,
949  * into our buffer without copying data. */
950 
951  resp->data = (unsigned char *)resp->hdr + resp->length;
952  *resp->data = COAP_PAYLOAD_START;
953  resp->data++;
954  resp->length++;
955  len = resp->max_size - resp->length;
956 
957  if (!print_wellknown(context, resp->data, &len,
958  coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter))) {
959  debug("print_wellknown failed\n");
960  goto error;
961  }
962 
963  resp->length += len;
964  return resp;
965 
966  error:
967  /* set error code 5.03 and remove all options and data from response */
968  resp->hdr->code = COAP_RESPONSE_CODE(503);
969  resp->length = sizeof(coap_hdr_t) + resp->hdr->token_length;
970  return resp;
971 }
972 
973 #define WANT_WKC(Pdu,Key) \
974  (((Pdu)->hdr->code == COAP_REQUEST_GET) && is_wkc(Key))
975 
976 void
978  coap_method_handler_t h = NULL;
979  coap_pdu_t *response = NULL;
980  coap_opt_filter_t opt_filter;
982  coap_key_t key;
983 
984  coap_option_filter_clear(opt_filter);
985 
986  /* try to find the resource from the request URI */
987  coap_hash_request_uri(node->pdu, key);
988  resource = coap_get_resource_from_key(context, key);
989 
990  if (!resource) {
991  /* The resource was not found. Check if the request URI happens to
992  * be the well-known URI. In that case, we generate a default
993  * response, otherwise, we return 4.04 */
994 
995  switch(node->pdu->hdr->code) {
996 
997  case COAP_REQUEST_GET:
998  if (is_wkc(key)) { /* GET request for .well-known/core */
999  info("create default response for %s\n", COAP_DEFAULT_URI_WELLKNOWN);
1000  response = wellknown_response(context, node->pdu);
1001 
1002  } else { /* GET request for any another resource, return 4.04 */
1003 
1004  debug("GET for unknown resource 0x%02x%02x%02x%02x, return 4.04\n",
1005  key[0], key[1], key[2], key[3]);
1006  response =
1008  opt_filter);
1009  }
1010  break;
1011 
1012  default: /* any other request type */
1013 
1014  debug("unhandled request for unknown resource 0x%02x%02x%02x%02x\r\n",
1015  key[0], key[1], key[2], key[3]);
1016  if (!coap_is_mcast(&node->local))
1017  response = coap_new_error_response(node->pdu, COAP_RESPONSE_CODE(405),
1018  opt_filter);
1019  }
1020 
1021  if (response && coap_send(context, &node->remote, response) == COAP_INVALID_TID) {
1022  warn("cannot send response for transaction %u\n", node->id);
1023  }
1024  coap_delete_pdu(response);
1025 
1026  return;
1027  }
1028 
1029  /* the resource was found, check if there is a registered handler */
1030  if ((size_t)node->pdu->hdr->code - 1 <
1031  sizeof(resource->handler)/sizeof(coap_method_handler_t))
1032  h = resource->handler[node->pdu->hdr->code - 1];
1033 
1034  if (h) {
1035  debug("call custom handler for resource 0x%02x%02x%02x%02x\n",
1036  key[0], key[1], key[2], key[3]);
1037  response = coap_pdu_init(node->pdu->hdr->type == COAP_MESSAGE_CON
1039  : COAP_MESSAGE_NON,
1040  0, node->pdu->hdr->id, COAP_MAX_PDU_SIZE);
1041 
1042  /* Implementation detail: coap_add_token() immediately returns 0
1043  if response == NULL */
1044  if (coap_add_token(response, node->pdu->hdr->token_length,
1045  node->pdu->hdr->token)) {
1046  str token = { node->pdu->hdr->token_length, node->pdu->hdr->token };
1047 
1048  h(context, resource, &node->remote,
1049  node->pdu, &token, response);
1050  if (response->hdr->type != COAP_MESSAGE_NON ||
1051  (response->hdr->code >= 64
1052  && !coap_is_mcast(&node->local))) {
1053  if (coap_send(context, &node->remote, response) == COAP_INVALID_TID) {
1054  debug("cannot send response for message %d\n", node->pdu->hdr->id);
1055  }
1056  }
1057 
1058  coap_delete_pdu(response);
1059  } else {
1060  warn("cannot generate response\r\n");
1061  }
1062  } else {
1063  if (WANT_WKC(node->pdu, key)) {
1064  debug("create default response for %s\n", COAP_DEFAULT_URI_WELLKNOWN);
1065  response = wellknown_response(context, node->pdu);
1066  } else
1067  response = coap_new_error_response(node->pdu, COAP_RESPONSE_CODE(405),
1068  opt_filter);
1069 
1070  if (!response || (coap_send(context, &node->remote, response)
1071  == COAP_INVALID_TID)) {
1072  debug("cannot send response for transaction %u\n", node->id);
1073  }
1074  coap_delete_pdu(response);
1075  }
1076 }
1077 
1078 static inline void
1080  coap_queue_t *sent, coap_queue_t *rcvd) {
1081 
1082  /* Call application-specific reponse handler when available. If
1083  * not, we must acknowledge confirmable messages. */
1084  if (context->response_handler) {
1085  context->response_handler(context,
1086  &rcvd->remote, sent ? sent->pdu : NULL,
1087  rcvd->pdu, rcvd->id);
1088  } else {
1089  /* send ACK if rcvd is confirmable (i.e. a separate response) */
1090  coap_send_ack(context, &rcvd->remote, rcvd->pdu);
1091  }
1092 }
1093 
1094 static inline int
1095 #ifdef __GNUC__
1096 handle_locally(coap_context_t *context __attribute__ ((unused)),
1097  coap_queue_t *node __attribute__ ((unused))) {
1098 #else /* not a GCC */
1100 #endif /* GCC */
1101  /* this function can be used to check if node->pdu is really for us */
1102  return 1;
1103 }
1104 
1109 static void
1111 #ifndef WITHOUT_OBSERVE
1112  coap_resource_t *r, *tmp;
1113  str token = { 0, NULL };
1114 
1115  /* remove observer for this resource, if any
1116  * get token from sent and try to find a matching resource. Uh!
1117  */
1118 
1119  COAP_SET_STR(&token, sent->pdu->hdr->token_length, sent->pdu->hdr->token);
1120 
1121 #ifndef WITH_CONTIKI
1122  HASH_ITER(hh, context->resources, r, tmp) {
1123  coap_delete_observer(r, &sent->remote, &token);
1124  coap_cancel_all_messages(context, &sent->remote, token.s, token.length);
1125  }
1126 #else /* WITH_CONTIKI */
1127  r = (coap_resource_t *)resource_storage.mem;
1128  for (i = 0; i < resource_storage.num; ++i, ++r) {
1129  if (resource_storage.count[i]) {
1130  coap_delete_observer(r, &sent->remote, &token);
1131  coap_cancel_all_messages(context, &sent->remote, token.s, token.length);
1132  }
1133  }
1134 #endif /* WITH_CONTIKI */
1135 #endif /* WITOUT_OBSERVE */
1136 }
1137 
1138 void
1140  coap_queue_t *rcvd = NULL, *sent = NULL;
1141  coap_pdu_t *response;
1142  coap_opt_filter_t opt_filter;
1143 
1144  if (!context)
1145  return;
1146 
1147  memset(opt_filter, 0, sizeof(coap_opt_filter_t));
1148 
1149  while ( context->recvqueue ) {
1150  rcvd = context->recvqueue;
1151 
1152  /* remove node from recvqueue */
1153  context->recvqueue = context->recvqueue->next;
1154  rcvd->next = NULL;
1155 
1156  if ( rcvd->pdu->hdr->version != COAP_DEFAULT_VERSION ) {
1157  debug("dropped packet with unknown version %u\n", rcvd->pdu->hdr->version);
1158  goto cleanup;
1159  }
1160 
1161  switch ( rcvd->pdu->hdr->type ) {
1162  case COAP_MESSAGE_ACK:
1163  /* find transaction in sendqueue to stop retransmission */
1164  coap_remove_from_queue(&context->sendqueue, rcvd->id, &sent);
1165 
1166  if (rcvd->pdu->hdr->code == 0)
1167  goto cleanup;
1168 
1169  /* FIXME: if sent code was >= 64 the message might have been a
1170  * notification. Then, we must flag the observer to be alive
1171  * by setting obs->fail_cnt = 0. */
1172  if (sent && COAP_RESPONSE_CLASS(sent->pdu->hdr->code) == 2) {
1173  const str token =
1174  { sent->pdu->hdr->token_length, sent->pdu->hdr->token };
1175  coap_touch_observer(context, &sent->remote, &token);
1176  }
1177  break;
1178 
1179  case COAP_MESSAGE_RST :
1180  /* We have sent something the receiver disliked, so we remove
1181  * not only the transaction but also the subscriptions we might
1182  * have. */
1183 
1184 #ifndef WITH_CONTIKI
1185  coap_log(LOG_ALERT, "got RST for message %u\n", ntohs(rcvd->pdu->hdr->id));
1186 #else /* WITH_CONTIKI */
1187  coap_log(LOG_ALERT, "got RST for message %u\n", uip_ntohs(rcvd->pdu->hdr->id));
1188 #endif /* WITH_CONTIKI */
1189  coap_remove_from_queue(&context->sendqueue, rcvd->id, &sent);
1190 
1191  if (sent)
1192  coap_handle_rst(context, sent);
1193  goto cleanup;
1194 
1195  case COAP_MESSAGE_NON : /* check for unknown critical options */
1196  if (coap_option_check_critical(context, rcvd->pdu, opt_filter) == 0)
1197  goto cleanup;
1198  break;
1199 
1200  case COAP_MESSAGE_CON : /* check for unknown critical options */
1201  if (coap_option_check_critical(context, rcvd->pdu, opt_filter) == 0) {
1202 
1203  /* FIXME: send response only if we have received a request. Otherwise,
1204  * send RST. */
1205  response =
1206  coap_new_error_response(rcvd->pdu, COAP_RESPONSE_CODE(402), opt_filter);
1207 
1208  if (!response)
1209  warn("coap_dispatch: cannot create error reponse\n");
1210  else {
1211  if (coap_send(context, &rcvd->remote, response)
1212  == COAP_INVALID_TID) {
1213  warn("coap_dispatch: error sending reponse\n");
1214  }
1215  coap_delete_pdu(response);
1216  }
1217 
1218  goto cleanup;
1219  }
1220  break;
1221  }
1222 
1223  /* Pass message to upper layer if a specific handler was
1224  * registered for a request that should be handled locally. */
1225  if (handle_locally(context, rcvd)) {
1226  if (COAP_MESSAGE_IS_REQUEST(rcvd->pdu->hdr))
1227  handle_request(context, rcvd);
1228  else if (COAP_MESSAGE_IS_RESPONSE(rcvd->pdu->hdr))
1229  handle_response(context, sent, rcvd);
1230  else {
1231  debug("dropped message with invalid code\n");
1232  coap_send_message_type(context, &rcvd->remote, rcvd->pdu,
1234  }
1235  }
1236 
1237  cleanup:
1238  coap_delete_node(sent);
1239  coap_delete_node(rcvd);
1240  }
1241 }
1242 
1243 int
1245  return !context || (context->recvqueue == NULL && context->sendqueue == NULL);
1246 }
1247 
1248 #ifdef WITH_CONTIKI
1249 
1250 /*---------------------------------------------------------------------------*/
1251 /* CoAP message retransmission */
1252 /*---------------------------------------------------------------------------*/
1253 PROCESS_THREAD(coap_retransmit_process, ev, data)
1254 {
1255  coap_tick_t now;
1256  coap_queue_t *nextpdu;
1257 
1258  PROCESS_BEGIN();
1259 
1260  debug("Started retransmit process\r\n");
1261 
1262  while(1) {
1263  PROCESS_YIELD();
1264  if (ev == PROCESS_EVENT_TIMER) {
1265  if (etimer_expired(&the_coap_context.retransmit_timer)) {
1266 
1267  nextpdu = coap_peek_next(&the_coap_context);
1268 
1269  coap_ticks(&now);
1270  while (nextpdu && nextpdu->t <= now) {
1271  coap_retransmit(&the_coap_context, coap_pop_next(&the_coap_context));
1272  nextpdu = coap_peek_next(&the_coap_context);
1273  }
1274 
1275  /* need to set timer to some value even if no nextpdu is available */
1276  etimer_set(&the_coap_context.retransmit_timer,
1277  nextpdu ? nextpdu->t - now : 0xFFFF);
1278  }
1279 #ifndef WITHOUT_OBSERVE
1280  if (etimer_expired(&the_coap_context.notify_timer)) {
1281  coap_check_notify(&the_coap_context);
1282  etimer_reset(&the_coap_context.notify_timer);
1283  }
1284 #endif /* WITHOUT_OBSERVE */
1285  }
1286  }
1287 
1288  PROCESS_END();
1289 }
1290 /*---------------------------------------------------------------------------*/
1291 
1292 #endif /* WITH_CONTIKI */