libcoap  4.1.1
 All Data Structures Files Functions Variables Typedefs Macros Groups Pages
etsi_iot_01.c
Go to the documentation of this file.
1 /* CoAP server for first ETSI CoAP plugtest, March 2012
2  *
3  * Copyright (C) 2012--2013 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 <string.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <stdio.h>
13 #include <ctype.h>
14 #include <sys/select.h>
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
19 #include <netdb.h>
20 #include <sys/stat.h>
21 #include <dirent.h>
22 #include <errno.h>
23 #include <signal.h>
24 
25 #include "config.h"
26 #include "uthash.h"
27 #include "coap.h"
28 
29 #define COAP_RESOURCE_CHECK_TIME_SEC 1
30 
31 #ifndef min
32 #define min(a,b) ((a) < (b) ? (a) : (b))
33 #endif
34 
35 /* temporary storage for dynamic resource representations */
36 static int quit = 0;
37 
38 #define COAP_OPT_BLOCK_SZX_MAX 6
40 #define REQUIRE_ETAG 0x01 /* flag for coap_payload_t: require ETag option */
41 typedef struct {
43  coap_key_t resource_key; /* foreign key that points into resource space */
44  unsigned int flags; /* some flags to control behavior */
45  size_t max_data; /* maximum size allocated for @p data */
46  uint16_t media_type; /* media type for this object */
47  size_t length; /* length of data */
48  unsigned char data[]; /* the actual contents */
50 
52 
57 typedef struct {
59  coap_key_t resource_key; /* foreign key that points into resource space */
60  size_t length; /* length of data */
61  unsigned char data[]; /* the actual contents */
63 
65 
66 /* This variable is used to mimic long-running tasks that require
67  * asynchronous responses. */
68 static coap_async_state_t *async = NULL;
69 
70 /* SIGINT handler: set quit to 1 for graceful termination */
71 void
72 handle_sigint(int signum) {
73  quit = 1;
74 }
75 
76 #define INDEX "libcoap server for ETSI CoAP Plugtest, March 2012, Paris\n" \
77  "Copyright (C) 2012 Olaf Bergmann <bergmann@tzi.org>\n\n"
78 
80 coap_new_payload(size_t size) {
81  coap_payload_t *p;
82  p = (coap_payload_t *)coap_malloc(sizeof(coap_payload_t) + size);
83  if (p) {
84  memset(p, 0, sizeof(coap_payload_t));
85  p->max_data = size;
86  }
87 
88  return p;
89 }
90 
91 static inline coap_payload_t *
93  coap_payload_t *p;
94  HASH_FIND(hh, test_resources, key, sizeof(coap_key_t), p);
95  return p;
96 }
97 
98 static inline void
101  assert(payload);
102 
103  memcpy(payload->resource_key, key, sizeof(coap_key_t));
104  HASH_ADD(hh, test_resources, resource_key, sizeof(coap_key_t), payload);
105 
106  if (uri) {
107  memcpy(uri->resource_key, key, sizeof(coap_key_t));
108  HASH_ADD(hh, test_dynamic_uris, resource_key, sizeof(coap_key_t), uri);
109  }
110 }
111 
112 static inline void
114  if (payload) {
116  HASH_FIND(hh, test_dynamic_uris,
117  payload->resource_key, sizeof(coap_key_t), uri);
118  if (uri) {
119  HASH_DELETE(hh, test_dynamic_uris, uri);
120  coap_free(uri);
121  }
122  }
123 
124  HASH_DELETE(hh, test_resources, payload);
125  coap_free(payload);
126 }
127 
128 void
130  coap_address_t *peer, coap_pdu_t *request, str *token,
131  coap_pdu_t *response) {
132  unsigned char buf[3];
133 
134  response->hdr->code = COAP_RESPONSE_CODE(205);
135 
138 
140  coap_encode_var_bytes(buf, 0x2ffff), buf);
141 
142  coap_add_data(response, strlen(INDEX), (unsigned char *)INDEX);
143 }
144 
145 
146 void
148  coap_address_t *peer, coap_pdu_t *request, str *token,
149  coap_pdu_t *response) {
150  coap_key_t etag;
151  unsigned char buf[2];
152  coap_payload_t *test_payload;
154 
155  test_payload = coap_find_payload(resource->key);
156  if (!test_payload) {
157  response->hdr->code = COAP_RESPONSE_CODE(500);
158 
159  return;
160  }
161 
162  response->hdr->code = COAP_RESPONSE_CODE(205);
163 
165  coap_encode_var_bytes(buf, test_payload->media_type), buf);
166 
167  /* add etag for the resource */
168  if (test_payload->flags & REQUIRE_ETAG) {
169  memset(etag, 0, sizeof(etag));
170  coap_hash(test_payload->data, test_payload->length, etag);
171  coap_add_option(response, COAP_OPTION_ETAG, sizeof(etag), etag);
172  }
173 
174  if (request) {
175  int res;
176 
177  if (coap_get_block(request, COAP_OPTION_BLOCK2, &block)) {
178  res = coap_write_block_opt(&block, COAP_OPTION_BLOCK2, response,
179  test_payload->length);
180 
181  switch (res) {
182  case -2: /* illegal block */
183  response->hdr->code = COAP_RESPONSE_CODE(400);
184  goto error;
185  case -1: /* should really not happen */
186  assert(0);
187  /* fall through if assert is a no-op */
188  case -3: /* cannot handle request */
189  response->hdr->code = COAP_RESPONSE_CODE(500);
190  goto error;
191  default: /* everything is good */
192  ;
193  }
194 
195  coap_add_block(response, test_payload->length, test_payload->data,
196  block.num, block.szx);
197  } else {
198  if (!coap_add_data(response, test_payload->length, test_payload->data)) {
199  /* set initial block size, will be lowered by
200  * coap_write_block_opt) automatically */
201  block.szx = 6;
202  coap_write_block_opt(&block, COAP_OPTION_BLOCK2, response,
203  test_payload->length);
204 
205  coap_add_block(response, test_payload->length, test_payload->data,
206  block.num, block.szx);
207  }
208  }
209  } else { /* this is a notification, block is 0 */
210  /* FIXME: need to store block size with subscription */
211  }
212 
213  return;
214 
215  error:
216  coap_add_data(response,
217  strlen(coap_response_phrase(response->hdr->code)),
218  (unsigned char *)coap_response_phrase(response->hdr->code));
219 }
220 
221 /* DELETE handler for dynamic resources created by POST /test */
222 void
224  coap_address_t *peer, coap_pdu_t *request, str *token,
225  coap_pdu_t *response) {
227 
228  payload = coap_find_payload(resource->key);
229 
230  if (payload)
231  coap_delete_payload(payload);
232 
233  coap_delete_resource(ctx, resource->key);
234 
235  response->hdr->code = COAP_RESPONSE_CODE(202);
236 }
237 
238 void
240  coap_address_t *peer, coap_pdu_t *request, str *token,
241  coap_pdu_t *response) {
242  coap_opt_iterator_t opt_iter;
243  coap_opt_t *option;
244  coap_payload_t *test_payload;
245  size_t len;
246  size_t l = 6 + sizeof(void *);
248  unsigned char *data;
249 
250 #define BUFSIZE 20
251  int res;
252  unsigned char _buf[BUFSIZE];
253  unsigned char *buf = _buf;
254  size_t buflen = BUFSIZE;
255 
256  coap_get_data(request, &len, &data);
257 
258  /* allocate storage for resource and to hold URI */
259  test_payload = coap_new_payload(len);
260  uri = (coap_dynamic_uri_t *)coap_malloc(sizeof(coap_dynamic_uri_t) + l);
261  if (!(test_payload && uri)) {
262  coap_log(LOG_CRIT, "cannot allocate new resource under /test");
263  response->hdr->code = COAP_RESPONSE_CODE(500);
264  coap_free(test_payload);
265  coap_free(uri);
266  } else {
267  coap_resource_t *r;
268 
269  memset(uri, 0, sizeof(coap_dynamic_uri_t));
270  uri->length = min(l, snprintf((char *)uri->data, l, "test/%p", test_payload));
271  test_payload->length = len;
272 
273  memcpy(test_payload->data, data, len);
274 
275  r = coap_resource_init(uri->data, uri->length, 0);
278 
279  /* set media_type if available */
280  option = coap_check_option(request, COAP_OPTION_CONTENT_TYPE, &opt_iter);
281  if (option) {
282  test_payload->media_type =
284  }
285 
286  coap_add_resource(ctx, r);
287  coap_add_payload(r->key, test_payload, uri);
288 
289  /* add Location-Path */
290  res = coap_split_path(uri->data, uri->length, buf, &buflen);
291 
292  while (res--) {
294  COAP_OPT_LENGTH(buf), COAP_OPT_VALUE(buf));
295 
296  buf += COAP_OPT_SIZE(buf);
297  }
298 
299  response->hdr->code = COAP_RESPONSE_CODE(201);
300  }
301 
302 }
303 
304 void
306  coap_address_t *peer, coap_pdu_t *request, str *token,
307  coap_pdu_t *response) {
308  coap_opt_iterator_t opt_iter;
309  coap_opt_t *option;
311  size_t len;
312  unsigned char *data;
313 
314  response->hdr->code = COAP_RESPONSE_CODE(204);
315 
316  coap_get_data(request, &len, &data);
317 
318  payload = coap_find_payload(resource->key);
319  if (payload && payload->max_data < len) { /* need more storage */
320  coap_delete_payload(payload);
321  payload = NULL;
322  /* bug: when subsequent coap_new_payload() fails, our old contents
323  is gone */
324  }
325 
326  if (!payload) { /* create new payload */
327  payload = coap_new_payload(len);
328  if (!payload)
329  goto error;
330 
331  coap_add_payload(resource->key, payload, NULL);
332  }
333  payload->length = len;
334  memcpy(payload->data, data, len);
335 
336  option = coap_check_option(request, COAP_OPTION_CONTENT_TYPE, &opt_iter);
337  if (option) {
338  /* set media type given in request */
339  payload->media_type =
341  } else {
342  /* set default value */
344  }
345  /* FIXME: need to change attribute ct of resource.
346  To do so, we need dynamic management of the attribute value
347  */
348 
349  return;
350  error:
351  warn("cannot modify resource\n");
352  response->hdr->code = COAP_RESPONSE_CODE(500);
353 }
354 
355 void
357  coap_address_t *peer, coap_pdu_t *request, str *token,
358  coap_pdu_t *response) {
359  /* the ETSI validation tool does not like empty resources... */
360 #if 0
362  payload = coap_find_payload(resource->key);
363 
364  if (payload)
365  payload->length = 0;
366 #endif
367 
368  response->hdr->code = COAP_RESPONSE_CODE(202);
369 }
370 
371 void
373  coap_address_t *peer, coap_pdu_t *request, str *token,
374  coap_pdu_t *response) {
375  coap_opt_iterator_t opt_iter;
377  coap_opt_t *q;
378  size_t len, L;
379  unsigned char buf[70];
380 
381  response->hdr->code = COAP_RESPONSE_CODE(205);
382 
385 
388 
389  coap_option_iterator_init(request, &opt_iter, f);
390 
391  len = 0;
392  while ((len < sizeof(buf)) && (q = coap_option_next(&opt_iter))) {
393  L = min(sizeof(buf) - len, 11);
394  memcpy(buf + len, "Uri-Query: ", L);
395  len += L;
396 
397  L = min(sizeof(buf) - len, COAP_OPT_LENGTH(q));
398  memcpy(buf + len, COAP_OPT_VALUE(q), L);
399  len += L;
400 
401  if (len < sizeof(buf))
402  buf[len++] = '\n';
403  }
404 
405  coap_add_data(response, len, buf);
406 }
407 
408 /* handler for TD_COAP_CORE_16 */
409 void
411  coap_address_t *peer, coap_pdu_t *request, str *token,
412  coap_pdu_t *response) {
413  coap_opt_iterator_t opt_iter;
414  coap_opt_t *option;
416  unsigned long delay = 5;
417 
418  if (async) {
419  if (async->id != request->hdr->id) {
422  response->hdr->code = COAP_RESPONSE_CODE(503);
423  }
424  return;
425  }
426 
427  /* search for option delay in query list */
430 
431  coap_option_iterator_init(request, &opt_iter, f);
432 
433  while ((option = coap_option_next(&opt_iter))) {
434  if (strncmp("delay=", (char *)COAP_OPT_VALUE(option), 6) == 0) {
435  int i;
436  unsigned long d = 0;
437 
438  for (i = 6; i < COAP_OPT_LENGTH(option); ++i)
439  d = d * 10 + COAP_OPT_VALUE(option)[i] - '0';
440 
441  /* don't allow delay to be less than COAP_RESOURCE_CHECK_TIME*/
442  delay = d < COAP_RESOURCE_CHECK_TIME_SEC
444  : d;
445  debug("set delay to %lu\n", delay);
446  break;
447  }
448  }
449 
450  async = coap_register_async(ctx, peer, request, COAP_ASYNC_SEPARATE,
451  (void *)(COAP_TICKS_PER_SECOND * delay));
452 }
453 
454 void
455 check_async(coap_context_t *ctx, coap_tick_t now) {
456  coap_pdu_t *response;
457  coap_async_state_t *tmp;
458  unsigned char buf[2];
459  size_t size = sizeof(coap_hdr_t) + 8;
460 
461  if (!async || now < async->created + (unsigned long)async->appdata)
462  return;
463 
464  size += async->tokenlen;
465 
466  response = coap_pdu_init(async->flags & COAP_ASYNC_CONFIRM
468  : COAP_MESSAGE_NON,
469  COAP_RESPONSE_CODE(205), 0, size);
470  if (!response) {
471  debug("check_async: insufficient memory, we'll try later\n");
472  async->appdata =
473  (void *)((unsigned long)async->appdata + 15 * COAP_TICKS_PER_SECOND);
474  return;
475  }
476 
477  response->hdr->id = coap_new_message_id(ctx);
478 
479  if (async->tokenlen)
480  coap_add_token(response, async->tokenlen, async->token);
481 
484 
485  coap_add_data(response, 4, (unsigned char *)"done");
486 
487  if (coap_send(ctx, &async->peer, response) == COAP_INVALID_TID) {
488  debug("check_async: cannot send response for message %d\n",
489  response->hdr->id);
490  }
491  coap_delete_pdu(response);
492 
493  coap_remove_async(ctx, async->id, &tmp);
494  coap_free_async(async);
495  async = NULL;
496 }
497 
499 make_large(char *filename) {
501  FILE *inputfile = NULL;
502  struct stat statbuf;
503 
504  if (!filename)
505  return NULL;
506 
507  /* read from specified input file */
508  if (stat(filename, &statbuf) < 0) {
509  warn("cannot stat file %s\n", filename);
510  return NULL;
511  }
512 
513  payload = coap_new_payload(statbuf.st_size);
514  if (!payload)
515  return NULL;
516 
517  inputfile = fopen(filename, "r");
518  if ( !inputfile ) {
519  warn("cannot read file %s\n", filename);
520  coap_free(payload);
521  return NULL;
522  }
523 
524  payload->length = fread(payload->data, 1, statbuf.st_size, inputfile);
525  payload->media_type = 41;
526 
527  fclose(inputfile);
528 
529  return payload;
530 }
531 
532 void
534  coap_resource_t *r;
535  coap_payload_t *test_payload;
536 
537  test_payload = coap_new_payload(200);
538  if (!test_payload)
539  coap_log(LOG_CRIT, "cannot allocate resource /test");
540  else {
541  test_payload->length = 13;
542  memcpy(test_payload->data, "put data here", test_payload->length);
543  /* test_payload->media_type is 0 anyway */
544 
545  r = coap_resource_init((unsigned char *)"test", 4, 0);
550 
551  coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0);
552  coap_add_attr(r, (unsigned char *)"rt", 2, (unsigned char *)"test", 4, 0);
553  coap_add_attr(r, (unsigned char *)"if", 2, (unsigned char *)"core#b", 6, 0);
554 #if 0
555  coap_add_attr(r, (unsigned char *)"obs", 3, NULL, 0, 0);
556 #endif
557  coap_add_resource(ctx, r);
558  coap_add_payload(r->key, test_payload, NULL);
559  }
560 
561  /* TD_COAP_BLOCK_01
562  * TD_COAP_BLOCK_02 */
563  test_payload = make_large("etsi_iot_01_largedata.txt");
564  if (!test_payload)
565  coap_log(LOG_CRIT, "cannot allocate resource /large\n");
566  else {
567  r = coap_resource_init((unsigned char *)"large", 5, 0);
569 
570  coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"41", 2, 0);
571  coap_add_attr(r, (unsigned char *)"rt", 2, (unsigned char *)"large", 5, 0);
572  coap_add_resource(ctx, r);
573 
574  test_payload->flags |= REQUIRE_ETAG;
575 
576  coap_add_payload(r->key, test_payload, NULL);
577  }
578 
579  /* For TD_COAP_CORE_12 */
580  test_payload = coap_new_payload(20);
581  if (!test_payload)
582  coap_log(LOG_CRIT, "cannot allocate resource /seg1/seg2/seg3\n");
583  else {
584  test_payload->length = 10;
585  memcpy(test_payload->data, "segsegseg!", test_payload->length);
586  /* test_payload->media_type is 0 anyway */
587 
588  r = coap_resource_init((unsigned char *)"seg1/seg2/seg3", 14, 0);
590 
591  coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0);
592  coap_add_resource(ctx, r);
593 
594  coap_add_payload(r->key, test_payload, NULL);
595  }
596 
597  /* For TD_COAP_CORE_13 */
598  r = coap_resource_init((unsigned char *)"query", 5, 0);
600 
601  coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0);
602  coap_add_resource(ctx, r);
603 
604  /* For TD_COAP_CORE_16 */
605  r = coap_resource_init((unsigned char *)"separate", 8, 0);
607 
608  coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0);
609  coap_add_attr(r, (unsigned char *)"rt", 2, (unsigned char *)"separate", 8, 0);
610  coap_add_resource(ctx, r);
611 }
612 
613 void
614 usage( const char *program, const char *version) {
615  const char *p;
616 
617  p = strrchr( program, '/' );
618  if ( p )
619  program = ++p;
620 
621  fprintf( stderr, "%s v%s -- ETSI CoAP plugtest server\n"
622  "(c) 2012 Olaf Bergmann <bergmann@tzi.org>\n\n"
623  "usage: %s [-A address] [-p port]\n\n"
624  "\t-A address\tinterface address to bind to\n"
625  "\t-p port\t\tlisten on specified port\n"
626  "\t-v num\t\tverbosity level (default: 3)\n",
627  program, version, program );
628 }
629 
631 get_context(const char *node, const char *port) {
632  coap_context_t *ctx = NULL;
633  int s;
634  struct addrinfo hints;
635  struct addrinfo *result, *rp;
636 
637  memset(&hints, 0, sizeof(struct addrinfo));
638  hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
639  hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */
640  hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
641 
642  s = getaddrinfo(node, port, &hints, &result);
643  if ( s != 0 ) {
644  fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
645  return NULL;
646  }
647 
648  /* iterate through results until success */
649  for (rp = result; rp != NULL; rp = rp->ai_next) {
650  coap_address_t addr;
651 
652  if (rp->ai_addrlen <= sizeof(addr.addr)) {
653  coap_address_init(&addr);
654  addr.size = rp->ai_addrlen;
655  memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen);
656 
657  ctx = coap_new_context(&addr);
658  if (ctx) {
659  /* TODO: output address:port for successful binding */
660  goto finish;
661  }
662  }
663  }
664 
665  fprintf(stderr, "no context available for interface '%s'\n", node);
666 
667  finish:
668  freeaddrinfo(result);
669  return ctx;
670 }
671 
672 int
673 main(int argc, char **argv) {
674  coap_context_t *ctx;
675  fd_set readfds;
676  struct timeval tv, *timeout;
677  int result;
678  coap_tick_t now;
679  coap_queue_t *nextpdu;
680  char addr_str[NI_MAXHOST] = "::";
681  char port_str[NI_MAXSERV] = "5683";
682  int opt;
683  coap_log_t log_level = LOG_WARNING;
684 
685  while ((opt = getopt(argc, argv, "A:p:v:")) != -1) {
686  switch (opt) {
687  case 'A' :
688  strncpy(addr_str, optarg, NI_MAXHOST-1);
689  addr_str[NI_MAXHOST - 1] = '\0';
690  break;
691  case 'p' :
692  strncpy(port_str, optarg, NI_MAXSERV-1);
693  port_str[NI_MAXSERV - 1] = '\0';
694  break;
695  case 'v' :
696  log_level = strtol(optarg, NULL, 10);
697  break;
698  default:
699  usage( argv[0], PACKAGE_VERSION );
700  exit( 1 );
701  }
702  }
703 
704  coap_set_log_level(log_level);
705 
706  ctx = get_context(addr_str, port_str);
707  if (!ctx)
708  return -1;
709 
711 
712  init_resources(ctx);
713 
714  signal(SIGINT, handle_sigint);
715 
716  while ( !quit ) {
717  FD_ZERO(&readfds);
718  FD_SET( ctx->sockfd, &readfds );
719 
720  nextpdu = coap_peek_next( ctx );
721 
722  coap_ticks(&now);
723  while ( nextpdu && nextpdu->t <= now ) {
724  coap_retransmit( ctx, coap_pop_next( ctx ) );
725  nextpdu = coap_peek_next( ctx );
726  }
727 
728  if ( nextpdu && nextpdu->t <= now + COAP_RESOURCE_CHECK_TIME_SEC ) {
729  /* set timeout if there is a pdu to send before our automatic timeout occurs */
730  tv.tv_usec = ((nextpdu->t - now) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND;
731  tv.tv_sec = (nextpdu->t - now) / COAP_TICKS_PER_SECOND;
732  timeout = &tv;
733  } else {
734  tv.tv_usec = 0;
735  tv.tv_sec = COAP_RESOURCE_CHECK_TIME_SEC;
736  timeout = &tv;
737  }
738  result = select( FD_SETSIZE, &readfds, 0, 0, timeout );
739 
740  if ( result < 0 ) { /* error */
741  if (errno != EINTR)
742  perror("select");
743  } else if ( result > 0 ) { /* read from socket */
744  if ( FD_ISSET( ctx->sockfd, &readfds ) ) {
745  coap_read( ctx ); /* read received data */
746  coap_dispatch( ctx ); /* and dispatch PDUs from receivequeue */
747  }
748  } else { /* timeout */
749  /* coap_check_resource_list( ctx ); */
750  }
751 
752  /* check if we have to send asynchronous responses */
753  check_async(ctx, now);
754  }
755 
756  coap_free_context( ctx );
757 
758  return 0;
759 }
int coap_get_block(coap_pdu_t *pdu, unsigned short type, coap_block_t *block)
Initializes block from pdu.
Definition: block.c:41
#define COAP_RESOURCE_CHECK_TIME_SEC
Definition: etsi_iot_01.c:29
#define COAP_REQUEST_POST
Definition: pdu.h:51
void hnd_get_index(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response)
Definition: etsi_iot_01.c:129
void * appdata
This field can be used to register opaque application data with the asynchronous state object...
Definition: async.h:45
int coap_write_block_opt(coap_block_t *block, unsigned short type, coap_pdu_t *pdu, size_t data_length)
Writes a block option of type type to message pdu.
Definition: block.c:60
unsigned char coap_key_t[4]
Definition: hashkey.h:19
#define warn(...)
Definition: debug.h:54
#define COAP_RESPONSE_CODE(N)
Definition: pdu.h:92
void coap_dispatch(coap_context_t *context)
Dispatches the PDUs from the receive queue in given context.
Definition: net.c:1452
#define min(a, b)
Definition: etsi_iot_01.c:32
int coap_delete_resource(coap_context_t *context, coap_key_t key)
Deletes a resource identified by key.
Definition: resource.c:451
coap_payload_t * coap_new_payload(size_t size)
Definition: etsi_iot_01.c:80
unsigned short id
Definition: pdu.h:173
coap_payload_t * test_resources
Definition: etsi_iot_01.c:51
#define COAP_REQUEST_GET
Definition: pdu.h:50
int coap_add_token(coap_pdu_t *pdu, size_t len, const unsigned char *data)
Adds token of length len to pdu.
Definition: pdu.c:157
unsigned char flags
holds the flags to control behaviour
Definition: async.h:33
coap_opt_t * coap_check_option(coap_pdu_t *pdu, unsigned char type, coap_opt_iterator_t *oi)
Retrieves the first option of type type from pdu.
Definition: option.c:207
static coap_payload_t * coap_find_payload(const coap_key_t key)
Definition: etsi_iot_01.c:92
coap_context_t * get_context(const char *node, const char *port)
Definition: etsi_iot_01.c:631
void hnd_delete_test(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response)
Definition: etsi_iot_01.c:356
#define COAP_MESSAGE_NON
Definition: pdu.h:44
static void coap_register_option(coap_context_t *ctx, unsigned char type)
Registers the option type type with the given context object ctx.
Definition: net.h:167
#define COAP_OPTION_ETAG
Definition: pdu.h:59
short coap_log_t
Definition: debug.h:24
void hnd_get_query(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response)
Definition: etsi_iot_01.c:372
coap_address_t peer
the peer to notify
Definition: async.h:52
int coap_get_data(coap_pdu_t *pdu, size_t *len, unsigned char **data)
Retrieves the length and data pointer of specified PDU.
Definition: pdu.c:261
#define BUFSIZE
#define COAP_OPTION_MAXAGE
Definition: pdu.h:66
#define coap_malloc(size)
Definition: mem.h:15
void handle_sigint(int signum)
Definition: etsi_iot_01.c:72
unsigned char data[]
Definition: etsi_iot_01.c:61
size_t max_data
Definition: etsi_iot_01.c:45
#define REQUIRE_ETAG
Definition: etsi_iot_01.c:40
void check_async(coap_context_t *ctx, coap_tick_t now)
Definition: etsi_iot_01.c:455
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
coap_payload_t * make_large(char *filename)
Definition: etsi_iot_01.c:499
#define COAP_OPTION_CONTENT_TYPE
Definition: pdu.h:65
static coap_uri_t uri
Definition: client.c:36
coap_block_t block
Definition: client.c:53
static int coap_option_setb(coap_opt_filter_t filter, unsigned short type)
Sets the corresponding bit for type in filter.
Definition: option.h:119
coap_hdr_t * hdr
Definition: pdu.h:209
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:296
static coap_async_state_t * async
Definition: etsi_iot_01.c:68
coap_queue_t * coap_peek_next(coap_context_t *context)
Returns the next pdu to send without removing from sendqeue.
Definition: net.c:253
void hnd_delete_resource(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response)
Definition: etsi_iot_01.c:223
static void coap_delete_payload(coap_payload_t *payload)
Definition: etsi_iot_01.c:113
unsigned int flags
Definition: etsi_iot_01.c:44
#define debug(...)
Definition: debug.h:55
coap_tick_t t
when to send PDU for the next time
Definition: net.h:54
coap_tid_t id
transaction id
Definition: async.h:48
#define HASH_DELETE(hh, head, delptr)
Definition: uthash.h:194
#define COAP_INVALID_TID
Definition: pdu.h:156
coap_attr_t * coap_add_attr(coap_resource_t *resource, const unsigned char *name, size_t nlen, const unsigned char *val, size_t vlen, int flags)
Registers a new attribute with the given resource.
Definition: resource.c:341
void hnd_put_test(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response)
Definition: etsi_iot_01.c:305
void coap_ticks(coap_tick_t *)
Returns the current value of an internal tick counter.
unsigned int code
Definition: pdu.h:172
#define coap_free(size)
Definition: mem.h:16
Header structure for CoAP PDUs.
Definition: pdu.h:206
coap_opt_iterator_t * coap_option_iterator_init(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's option list...
Definition: option.c:118
coap_key_t key
the actual key bytes for this resource
Definition: resource.h:75
UT_hash_handle hh
Definition: etsi_iot_01.c:58
static void coap_add_payload(const coap_key_t key, coap_payload_t *payload, coap_dynamic_uri_t *uri)
Definition: etsi_iot_01.c:99
coap_async_state_t * coap_register_async(coap_context_t *context, coap_address_t *peer, coap_pdu_t *request, unsigned char flags, void *data)
Allocates a new coap_async_state_t object and fills its fields according to the given request...
Definition: async.c:25
unsigned int coap_encode_var_bytes(unsigned char *buf, unsigned int val)
Encodes multiple-length byte sequences.
Definition: encode.c:34
static int quit
Definition: etsi_iot_01.c:36
static void coap_register_handler(coap_resource_t *resource, unsigned char method, coap_method_handler_t handler)
Registers the specified handler as message handler for the request type method.
Definition: resource.h:227
#define COAP_ASYNC_CONFIRM
send confirmable response
Definition: async.h:59
void hnd_post_test(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response)
Definition: etsi_iot_01.c:239
int coap_add_block(coap_pdu_t *pdu, unsigned int len, const unsigned char *data, unsigned int block_num, unsigned char block_szx)
Adds the block_num block of size 1 << (block_szx + 4) from source data to pdu.
Definition: block.c:121
void coap_add_resource(coap_context_t *context, coap_resource_t *resource)
Registers the given resource for context.
Definition: resource.c:440
coap_key_t resource_key
Definition: etsi_iot_01.c:59
int coap_split_path(const unsigned char *s, size_t length, unsigned char *buf, size_t *buflen)
Splits the given URI path into segments.
Definition: uri.c:354
Iterator to run through PDU options.
Definition: option.h:169
#define COAP_MESSAGE_CON
Definition: pdu.h:43
size_t coap_add_option(coap_pdu_t *pdu, unsigned short type, unsigned int len, const unsigned char *data)
de-duplicate code with coap_add_option_later
Definition: pdu.c:175
UT_hash_handle hh
Definition: etsi_iot_01.c:42
coap_key_t resource_key
Definition: etsi_iot_01.c:43
#define COAP_OPT_SIZE(opt)
Definition: option.h:65
unsigned char coap_opt_filter_t[(COAP_MAX_OPT >> 3)+1]
Fixed-size bit-vector we use for option filtering.
Definition: option.h:93
int coap_add_data(coap_pdu_t *pdu, unsigned int len, const unsigned char *data)
Adds given data to the pdu that is passed as first parameter.
Definition: pdu.c:238
#define coap_hash(String, Length, Result)
Definition: hashkey.h:34
#define COAP_ASYNC_SEPARATE
send separate response
Definition: async.h:60
#define COAP_REQUEST_DELETE
Definition: pdu.h:53
coap_tid_t coap_send(coap_context_t *context, const coap_address_t *dst, coap_pdu_t *pdu)
Sends a non-confirmed CoAP message to given destination.
Definition: net.c:653
#define COAP_OPTION_BLOCK2
Definition: pdu.h:81
#define COAP_OPTION_LOCATION_PATH
Definition: pdu.h:62
void coap_delete_pdu(coap_pdu_t *pdu)
Definition: pdu.c:143
static void coap_address_init(coap_address_t *addr)
Resets the given coap_address_t object addr to its default values.
Definition: address.h:134
coap_pdu_t * coap_pdu_init(unsigned char type, unsigned char code, unsigned short id, size_t size)
Creates a new CoAP PDU of given size (must be large enough to hold the basic CoAP message header (coa...
Definition: pdu.c:82
Structure of Block options.
Definition: block.h:37
static void coap_option_filter_clear(coap_opt_filter_t f)
Clears filter f.
Definition: option.h:104
int coap_remove_async(coap_context_t *context, coap_tid_t id, coap_async_state_t **s)
Removes the state object identified by id from context.
Definition: async.c:81
Definition: str.h:14
void coap_free_async(coap_async_state_t *s)
Releases the memory that was allocated by coap_async_state_init() for the object s.
Definition: async.c:93
void coap_free_context(coap_context_t *context)
Definition: net.c:419
#define COAP_OPT_LENGTH(opt)
Definition: option.h:305
size_t tokenlen
length of the token
Definition: async.h:53
static unsigned short coap_new_message_id(coap_context_t *context)
Returns a new message id and updates context->message_id accordingly.
Definition: net.h:197
This structure is used to store URIs for dynamically allocated resources, usually by POST or PUT...
Definition: etsi_iot_01.c:57
coap_resource_t * coap_resource_init(const unsigned char *uri, size_t len, int flags)
Creates a new resource object and initializes the link field to the string of length len...
Definition: resource.c:307
void init_resources(coap_context_t *ctx)
Definition: etsi_iot_01.c:533
#define COAP_MEDIATYPE_TEXT_PLAIN
Definition: pdu.h:141
uint16_t media_type
Definition: etsi_iot_01.c:46
#define HASH_ADD(hh, head, fieldname, keylen_in, add)
Definition: uthash.h:149
int main(int argc, char **argv)
Definition: etsi_iot_01.c:673
void coap_set_log_level(coap_log_t level)
Sets the log level to the specified value.
Definition: debug.c:46
unsigned char token[]
the token to use in a response
Definition: async.h:54
#define COAP_OPTION_URI_QUERY
Definition: pdu.h:67
void hnd_get_separate(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response)
Definition: etsi_iot_01.c:410
unsigned char coap_opt_t
Use byte-oriented access methods here because sliding a complex struct coap_opt_t over the data buffe...
Definition: option.h:26
#define COAP_REQUEST_PUT
Definition: pdu.h:52
#define PACKAGE_VERSION
Definition: config.h:108
#define coap_log(...)
Definition: debug.h:47
char * coap_response_phrase(unsigned char code)
Returns a human-readable response phrase for the specified CoAP response code.
Definition: pdu.c:310
static str payload
Definition: client.c:46
unsigned char data[]
Definition: etsi_iot_01.c:48
int coap_read(coap_context_t *ctx)
Reads data from the network and tries to parse as CoAP PDU.
Definition: net.c:831
#define INDEX
Definition: etsi_iot_01.c:76
#define HASH_FIND(hh, head, keyptr, keylen, out)
Definition: uthash.h:84
void usage(const char *program, const char *version)
Definition: etsi_iot_01.c:614
coap_tid_t coap_retransmit(coap_context_t *context, coap_queue_t *node)
Handles retransmissions of confirmable messages.
Definition: net.c:771
void hnd_get_resource(coap_context_t *ctx, struct coap_resource_t *resource, coap_address_t *peer, coap_pdu_t *request, str *token, coap_pdu_t *response)
Definition: etsi_iot_01.c:147
unsigned int coap_decode_var_bytes(unsigned char *buf, unsigned int len)
Decodes multiple-length byte sequences.
Definition: encode.c:25
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:261
coap_dynamic_uri_t * test_dynamic_uris
Definition: etsi_iot_01.c:64
#define COAP_OPT_VALUE(opt)
Definition: option.h:318
The CoAP stack's global state is stored in a coap_context_t object.
Definition: net.h:97
unsigned int szx
block size
Definition: block.h:40
unsigned int num
block number
Definition: block.h:38