Contiki 3.x
er-coap.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  */
31 
32 /**
33  * \file
34  * An implementation of the Constrained Application Protocol (RFC).
35  * \author
36  * Matthias Kovatsch <kovatsch@inf.ethz.ch>
37  */
38 
39 #include <string.h>
40 #include <stdio.h>
41 #include "contiki.h"
42 #include "sys/cc.h"
43 #include "contiki-net.h"
44 
45 #include "er-coap.h"
46 #include "er-coap-transactions.h"
47 
48 #define DEBUG 0
49 #if DEBUG
50 #include <stdio.h>
51 #define PRINTF(...) printf(__VA_ARGS__)
52 #define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
53 #define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5])
54 #else
55 #define PRINTF(...)
56 #define PRINT6ADDR(addr)
57 #define PRINTLLADDR(addr)
58 #endif
59 
60 /*---------------------------------------------------------------------------*/
61 /*- Variables ---------------------------------------------------------------*/
62 /*---------------------------------------------------------------------------*/
63 static struct uip_udp_conn *udp_conn = NULL;
64 static uint16_t current_mid = 0;
65 
66 coap_status_t erbium_status_code = NO_ERROR;
67 char *coap_error_message = "";
68 /*---------------------------------------------------------------------------*/
69 /*- Local helper functions --------------------------------------------------*/
70 /*---------------------------------------------------------------------------*/
71 static uint16_t
72 coap_log_2(uint16_t value)
73 {
74  uint16_t result = 0;
75 
76  do {
77  value = value >> 1;
78  result++;
79  } while(value);
80 
81  return result ? result - 1 : result;
82 }
83 /*---------------------------------------------------------------------------*/
84 static uint32_t
85 coap_parse_int_option(uint8_t *bytes, size_t length)
86 {
87  uint32_t var = 0;
88  int i = 0;
89 
90  while(i < length) {
91  var <<= 8;
92  var |= bytes[i++];
93  }
94  return var;
95 }
96 /*---------------------------------------------------------------------------*/
97 static uint8_t
98 coap_option_nibble(unsigned int value)
99 {
100  if(value < 13) {
101  return value;
102  } else if(value <= 0xFF + 13) {
103  return 13;
104  } else {
105  return 14;
106  }
107 }
108 /*---------------------------------------------------------------------------*/
109 static size_t
110 coap_set_option_header(unsigned int delta, size_t length, uint8_t *buffer)
111 {
112  size_t written = 0;
113 
114  buffer[0] = coap_option_nibble(delta) << 4 | coap_option_nibble(length);
115 
116  if(delta > 268) {
117  buffer[++written] = ((delta - 269) >> 8) & 0xff;
118  buffer[++written] = (delta - 269) & 0xff;
119  } else if(delta > 12) {
120  buffer[++written] = (delta - 13);
121  }
122 
123  if(length > 268) {
124  buffer[++written] = ((length - 269) >> 8) & 0xff;
125  buffer[++written] = (length - 269) & 0xff;
126  } else if(length > 12) {
127  buffer[++written] = (length - 13);
128  }
129 
130  PRINTF("WRITTEN %zu B opt header\n", 1 + written);
131 
132  return ++written;
133 }
134 /*---------------------------------------------------------------------------*/
135 static size_t
136 coap_serialize_int_option(unsigned int number, unsigned int current_number,
137  uint8_t *buffer, uint32_t value)
138 {
139  size_t i = 0;
140 
141  if(0xFF000000 & value) {
142  ++i;
143  }
144  if(0xFFFF0000 & value) {
145  ++i;
146  }
147  if(0xFFFFFF00 & value) {
148  ++i;
149  }
150  if(0xFFFFFFFF & value) {
151  ++i;
152  }
153  PRINTF("OPTION %u (delta %u, len %zu)\n", number, number - current_number,
154  i);
155 
156  i = coap_set_option_header(number - current_number, i, buffer);
157 
158  if(0xFF000000 & value) {
159  buffer[i++] = (uint8_t)(value >> 24);
160  }
161  if(0xFFFF0000 & value) {
162  buffer[i++] = (uint8_t)(value >> 16);
163  }
164  if(0xFFFFFF00 & value) {
165  buffer[i++] = (uint8_t)(value >> 8);
166  }
167  if(0xFFFFFFFF & value) {
168  buffer[i++] = (uint8_t)(value);
169  }
170  return i;
171 }
172 /*---------------------------------------------------------------------------*/
173 static size_t
174 coap_serialize_array_option(unsigned int number, unsigned int current_number,
175  uint8_t *buffer, uint8_t *array, size_t length,
176  char split_char)
177 {
178  size_t i = 0;
179 
180  PRINTF("ARRAY type %u, len %zu, full [%.*s]\n", number, length,
181  (int)length, array);
182 
183  if(split_char != '\0') {
184  int j;
185  uint8_t *part_start = array;
186  uint8_t *part_end = NULL;
187  size_t temp_length;
188 
189  for(j = 0; j <= length + 1; ++j) {
190  PRINTF("STEP %u/%zu (%c)\n", j, length, array[j]);
191  if(array[j] == split_char || j == length) {
192  part_end = array + j;
193  temp_length = part_end - part_start;
194 
195  i += coap_set_option_header(number - current_number, temp_length,
196  &buffer[i]);
197  memcpy(&buffer[i], part_start, temp_length);
198  i += temp_length;
199 
200  PRINTF("OPTION type %u, delta %u, len %zu, part [%.*s]\n", number,
201  number - current_number, i, (int)temp_length, part_start);
202 
203  ++j; /* skip the splitter */
204  current_number = number;
205  part_start = array + j;
206  }
207  } /* for */
208  } else {
209  i += coap_set_option_header(number - current_number, length, &buffer[i]);
210  memcpy(&buffer[i], array, length);
211  i += length;
212 
213  PRINTF("OPTION type %u, delta %u, len %zu\n", number,
214  number - current_number, length);
215  }
216 
217  return i;
218 }
219 /*---------------------------------------------------------------------------*/
220 static void
221 coap_merge_multi_option(char **dst, size_t *dst_len, uint8_t *option,
222  size_t option_len, char separator)
223 {
224  /* merge multiple options */
225  if(*dst_len > 0) {
226  /* dst already contains an option: concatenate */
227  (*dst)[*dst_len] = separator;
228  *dst_len += 1;
229 
230  /* memmove handles 2-byte option headers */
231  memmove((*dst) + (*dst_len), option, option_len);
232 
233  *dst_len += option_len;
234  } else {
235  /* dst is empty: set to option */
236  *dst = (char *)option;
237  *dst_len = option_len;
238  }
239 }
240 /*---------------------------------------------------------------------------*/
241 static int
242 coap_get_variable(const char *buffer, size_t length, const char *name,
243  const char **output)
244 {
245  const char *start = NULL;
246  const char *end = NULL;
247  const char *value_end = NULL;
248  size_t name_len = 0;
249 
250  /*initialize the output buffer first */
251  *output = 0;
252 
253  name_len = strlen(name);
254  end = buffer + length;
255 
256  for(start = buffer; start + name_len < end; ++start) {
257  if((start == buffer || start[-1] == '&') && start[name_len] == '='
258  && strncmp(name, start, name_len) == 0) {
259 
260  /* Point start to variable value */
261  start += name_len + 1;
262 
263  /* Point end to the end of the value */
264  value_end = (const char *)memchr(start, '&', end - start);
265  if(value_end == NULL) {
266  value_end = end;
267  }
268  *output = start;
269 
270  return value_end - start;
271  }
272  }
273  return 0;
274 }
275 /*---------------------------------------------------------------------------*/
276 /*- Internal API ------------------------------------------------------------*/
277 /*---------------------------------------------------------------------------*/
278 void
279 coap_init_connection(uint16_t port)
280 {
281  /* new connection with remote host */
282  udp_conn = udp_new(NULL, 0, NULL);
283  udp_bind(udp_conn, port);
284  PRINTF("Listening on port %u\n", uip_ntohs(udp_conn->lport));
285 
286  /* initialize transaction ID */
287  current_mid = random_rand();
288 }
289 /*---------------------------------------------------------------------------*/
290 uint16_t
291 coap_get_mid()
292 {
293  return ++current_mid;
294 }
295 /*---------------------------------------------------------------------------*/
296 void
297 coap_init_message(void *packet, coap_message_type_t type, uint8_t code,
298  uint16_t mid)
299 {
300  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
301 
302  /* Important thing */
303  memset(coap_pkt, 0, sizeof(coap_packet_t));
304 
305  coap_pkt->type = type;
306  coap_pkt->code = code;
307  coap_pkt->mid = mid;
308 }
309 /*---------------------------------------------------------------------------*/
310 size_t
311 coap_serialize_message(void *packet, uint8_t *buffer)
312 {
313  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
314  uint8_t *option;
315  unsigned int current_number = 0;
316 
317  /* Initialize */
318  coap_pkt->buffer = buffer;
319  coap_pkt->version = 1;
320 
321  PRINTF("-Serializing MID %u to %p, ", coap_pkt->mid, coap_pkt->buffer);
322 
323  /* set header fields */
324  coap_pkt->buffer[0] = 0x00;
325  coap_pkt->buffer[0] |= COAP_HEADER_VERSION_MASK
326  & (coap_pkt->version) << COAP_HEADER_VERSION_POSITION;
327  coap_pkt->buffer[0] |= COAP_HEADER_TYPE_MASK
328  & (coap_pkt->type) << COAP_HEADER_TYPE_POSITION;
329  coap_pkt->buffer[0] |= COAP_HEADER_TOKEN_LEN_MASK
330  & (coap_pkt->token_len) << COAP_HEADER_TOKEN_LEN_POSITION;
331  coap_pkt->buffer[1] = coap_pkt->code;
332  coap_pkt->buffer[2] = (uint8_t)((coap_pkt->mid) >> 8);
333  coap_pkt->buffer[3] = (uint8_t)(coap_pkt->mid);
334 
335  /* empty packet, dont need to do more stuff */
336  if(!coap_pkt->code) {
337  PRINTF("-Done serializing empty message at %p-\n", coap_pkt->buffer);
338  return 4;
339  }
340 
341  /* set Token */
342  PRINTF("Token (len %u)", coap_pkt->token_len);
343  option = coap_pkt->buffer + COAP_HEADER_LEN;
344  for(current_number = 0; current_number < coap_pkt->token_len;
345  ++current_number) {
346  PRINTF(" %02X", coap_pkt->token[current_number]);
347  *option = coap_pkt->token[current_number];
348  ++option;
349  }
350  PRINTF("-\n");
351 
352  /* Serialize options */
353  current_number = 0;
354 
355  PRINTF("-Serializing options at %p-\n", option);
356 
357  /* The options must be serialized in the order of their number */
358  COAP_SERIALIZE_BYTE_OPTION(COAP_OPTION_IF_MATCH, if_match, "If-Match");
359  COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_HOST, uri_host, '\0',
360  "Uri-Host");
361  COAP_SERIALIZE_BYTE_OPTION(COAP_OPTION_ETAG, etag, "ETag");
362  COAP_SERIALIZE_INT_OPTION(COAP_OPTION_IF_NONE_MATCH,
363  content_format -
364  coap_pkt->
365  content_format /* hack to get a zero field */,
366  "If-None-Match");
367  COAP_SERIALIZE_INT_OPTION(COAP_OPTION_OBSERVE, observe, "Observe");
368  COAP_SERIALIZE_INT_OPTION(COAP_OPTION_URI_PORT, uri_port, "Uri-Port");
369  COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_LOCATION_PATH, location_path, '/',
370  "Location-Path");
371  COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_PATH, uri_path, '/',
372  "Uri-Path");
373  PRINTF("Serialize content format: %d\n", coap_pkt->content_format);
374  COAP_SERIALIZE_INT_OPTION(COAP_OPTION_CONTENT_FORMAT, content_format,
375  "Content-Format");
376  COAP_SERIALIZE_INT_OPTION(COAP_OPTION_MAX_AGE, max_age, "Max-Age");
377  COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_QUERY, uri_query, '&',
378  "Uri-Query");
379  COAP_SERIALIZE_INT_OPTION(COAP_OPTION_ACCEPT, accept, "Accept");
380  COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_LOCATION_QUERY, location_query,
381  '&', "Location-Query");
382  COAP_SERIALIZE_BLOCK_OPTION(COAP_OPTION_BLOCK2, block2, "Block2");
383  COAP_SERIALIZE_BLOCK_OPTION(COAP_OPTION_BLOCK1, block1, "Block1");
384  COAP_SERIALIZE_INT_OPTION(COAP_OPTION_SIZE2, size2, "Size2");
385  COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_PROXY_URI, proxy_uri, '\0',
386  "Proxy-Uri");
387  COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_PROXY_SCHEME, proxy_scheme, '\0',
388  "Proxy-Scheme");
389  COAP_SERIALIZE_INT_OPTION(COAP_OPTION_SIZE1, size1, "Size1");
390 
391  PRINTF("-Done serializing at %p----\n", option);
392 
393  /* Pack payload */
394  if((option - coap_pkt->buffer) <= COAP_MAX_HEADER_SIZE) {
395  /* Payload marker */
396  if(coap_pkt->payload_len) {
397  *option = 0xFF;
398  ++option;
399  }
400  memmove(option, coap_pkt->payload, coap_pkt->payload_len);
401  } else {
402  /* an error occurred: caller must check for !=0 */
403  coap_pkt->buffer = NULL;
404  coap_error_message = "Serialized header exceeds COAP_MAX_HEADER_SIZE";
405  return 0;
406  }
407 
408  PRINTF("-Done %u B (header len %u, payload len %u)-\n",
409  (unsigned int)(coap_pkt->payload_len + option - buffer),
410  (unsigned int)(option - buffer),
411  (unsigned int)coap_pkt->payload_len);
412 
413  PRINTF("Dump [0x%02X %02X %02X %02X %02X %02X %02X %02X]\n",
414  coap_pkt->buffer[0],
415  coap_pkt->buffer[1],
416  coap_pkt->buffer[2],
417  coap_pkt->buffer[3],
418  coap_pkt->buffer[4],
419  coap_pkt->buffer[5], coap_pkt->buffer[6], coap_pkt->buffer[7]
420  );
421 
422  return (option - buffer) + coap_pkt->payload_len; /* packet length */
423 }
424 /*---------------------------------------------------------------------------*/
425 void
426 coap_send_message(uip_ipaddr_t *addr, uint16_t port, uint8_t *data,
427  uint16_t length)
428 {
429  /* configure connection to reply to client */
430  uip_ipaddr_copy(&udp_conn->ripaddr, addr);
431  udp_conn->rport = port;
432 
433  uip_udp_packet_send(udp_conn, data, length);
434 
435  PRINTF("-sent UDP datagram (%u)-\n", length);
436 
437  /* restore server socket to allow data from any node */
438  memset(&udp_conn->ripaddr, 0, sizeof(udp_conn->ripaddr));
439  udp_conn->rport = 0;
440 }
441 /*---------------------------------------------------------------------------*/
442 coap_status_t
443 coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
444 {
445  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
446 
447  /* initialize packet */
448  memset(coap_pkt, 0, sizeof(coap_packet_t));
449 
450  /* pointer to packet bytes */
451  coap_pkt->buffer = data;
452 
453  /* parse header fields */
454  coap_pkt->version = (COAP_HEADER_VERSION_MASK & coap_pkt->buffer[0])
455  >> COAP_HEADER_VERSION_POSITION;
456  coap_pkt->type = (COAP_HEADER_TYPE_MASK & coap_pkt->buffer[0])
457  >> COAP_HEADER_TYPE_POSITION;
458  coap_pkt->token_len = (COAP_HEADER_TOKEN_LEN_MASK & coap_pkt->buffer[0])
459  >> COAP_HEADER_TOKEN_LEN_POSITION;
460  coap_pkt->code = coap_pkt->buffer[1];
461  coap_pkt->mid = coap_pkt->buffer[2] << 8 | coap_pkt->buffer[3];
462 
463  if(coap_pkt->version != 1) {
464  coap_error_message = "CoAP version must be 1";
465  return BAD_REQUEST_4_00;
466  }
467 
468  if(coap_pkt->token_len > COAP_TOKEN_LEN) {
469  coap_error_message = "Token Length must not be more than 8";
470  return BAD_REQUEST_4_00;
471  }
472 
473  uint8_t *current_option = data + COAP_HEADER_LEN;
474 
475  memcpy(coap_pkt->token, current_option, coap_pkt->token_len);
476  PRINTF("Token (len %u) [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n",
477  coap_pkt->token_len, coap_pkt->token[0], coap_pkt->token[1],
478  coap_pkt->token[2], coap_pkt->token[3], coap_pkt->token[4],
479  coap_pkt->token[5], coap_pkt->token[6], coap_pkt->token[7]
480  ); /*FIXME always prints 8 bytes */
481 
482  /* parse options */
483  memset(coap_pkt->options, 0, sizeof(coap_pkt->options));
484  current_option += coap_pkt->token_len;
485 
486  unsigned int option_number = 0;
487  unsigned int option_delta = 0;
488  size_t option_length = 0;
489 
490  while(current_option < data + data_len) {
491  /* payload marker 0xFF, currently only checking for 0xF* because rest is reserved */
492  if((current_option[0] & 0xF0) == 0xF0) {
493  coap_pkt->payload = ++current_option;
494  coap_pkt->payload_len = data_len - (coap_pkt->payload - data);
495 
496  /* also for receiving, the Erbium upper bound is REST_MAX_CHUNK_SIZE */
497  if(coap_pkt->payload_len > REST_MAX_CHUNK_SIZE) {
498  coap_pkt->payload_len = REST_MAX_CHUNK_SIZE;
499  /* null-terminate payload */
500  }
501  coap_pkt->payload[coap_pkt->payload_len] = '\0';
502 
503  break;
504  }
505 
506  option_delta = current_option[0] >> 4;
507  option_length = current_option[0] & 0x0F;
508  ++current_option;
509 
510  if(option_delta == 13) {
511  option_delta += current_option[0];
512  ++current_option;
513  } else if(option_delta == 14) {
514  option_delta += 255;
515  option_delta += current_option[0] << 8;
516  ++current_option;
517  option_delta += current_option[0];
518  ++current_option;
519  }
520 
521  if(option_length == 13) {
522  option_length += current_option[0];
523  ++current_option;
524  } else if(option_length == 14) {
525  option_length += 255;
526  option_length += current_option[0] << 8;
527  ++current_option;
528  option_length += current_option[0];
529  ++current_option;
530  }
531 
532  option_number += option_delta;
533 
534  PRINTF("OPTION %u (delta %u, len %zu): ", option_number, option_delta,
535  option_length);
536 
537  SET_OPTION(coap_pkt, option_number);
538 
539  switch(option_number) {
540  case COAP_OPTION_CONTENT_FORMAT:
541  coap_pkt->content_format = coap_parse_int_option(current_option,
542  option_length);
543  PRINTF("Content-Format [%u]\n", coap_pkt->content_format);
544  break;
545  case COAP_OPTION_MAX_AGE:
546  coap_pkt->max_age = coap_parse_int_option(current_option,
547  option_length);
548  PRINTF("Max-Age [%lu]\n", (unsigned long)coap_pkt->max_age);
549  break;
550  case COAP_OPTION_ETAG:
551  coap_pkt->etag_len = MIN(COAP_ETAG_LEN, option_length);
552  memcpy(coap_pkt->etag, current_option, coap_pkt->etag_len);
553  PRINTF("ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n",
554  coap_pkt->etag_len, coap_pkt->etag[0], coap_pkt->etag[1],
555  coap_pkt->etag[2], coap_pkt->etag[3], coap_pkt->etag[4],
556  coap_pkt->etag[5], coap_pkt->etag[6], coap_pkt->etag[7]
557  ); /*FIXME always prints 8 bytes */
558  break;
559  case COAP_OPTION_ACCEPT:
560  coap_pkt->accept = coap_parse_int_option(current_option, option_length);
561  PRINTF("Accept [%u]\n", coap_pkt->accept);
562  break;
563  case COAP_OPTION_IF_MATCH:
564  /* TODO support multiple ETags */
565  coap_pkt->if_match_len = MIN(COAP_ETAG_LEN, option_length);
566  memcpy(coap_pkt->if_match, current_option, coap_pkt->if_match_len);
567  PRINTF("If-Match %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n",
568  coap_pkt->if_match_len, coap_pkt->if_match[0],
569  coap_pkt->if_match[1], coap_pkt->if_match[2],
570  coap_pkt->if_match[3], coap_pkt->if_match[4],
571  coap_pkt->if_match[5], coap_pkt->if_match[6],
572  coap_pkt->if_match[7]
573  ); /* FIXME always prints 8 bytes */
574  break;
575  case COAP_OPTION_IF_NONE_MATCH:
576  coap_pkt->if_none_match = 1;
577  PRINTF("If-None-Match\n");
578  break;
579 
580  case COAP_OPTION_PROXY_URI:
581 #if COAP_PROXY_OPTION_PROCESSING
582  coap_pkt->proxy_uri = (char *)current_option;
583  coap_pkt->proxy_uri_len = option_length;
584 #endif
585  PRINTF("Proxy-Uri NOT IMPLEMENTED [%.*s]\n", (int)coap_pkt->proxy_uri_len,
586  coap_pkt->proxy_uri);
587  coap_error_message = "This is a constrained server (Contiki)";
588  return PROXYING_NOT_SUPPORTED_5_05;
589  break;
590  case COAP_OPTION_PROXY_SCHEME:
591 #if COAP_PROXY_OPTION_PROCESSING
592  coap_pkt->proxy_scheme = (char *)current_option;
593  coap_pkt->proxy_scheme_len = option_length;
594 #endif
595  PRINTF("Proxy-Scheme NOT IMPLEMENTED [%.*s]\n",
596  (int)coap_pkt->proxy_scheme_len, coap_pkt->proxy_scheme);
597  coap_error_message = "This is a constrained server (Contiki)";
598  return PROXYING_NOT_SUPPORTED_5_05;
599  break;
600 
601  case COAP_OPTION_URI_HOST:
602  coap_pkt->uri_host = (char *)current_option;
603  coap_pkt->uri_host_len = option_length;
604  PRINTF("Uri-Host [%.*s]\n", (int)coap_pkt->uri_host_len,
605  coap_pkt->uri_host);
606  break;
607  case COAP_OPTION_URI_PORT:
608  coap_pkt->uri_port = coap_parse_int_option(current_option,
609  option_length);
610  PRINTF("Uri-Port [%u]\n", coap_pkt->uri_port);
611  break;
612  case COAP_OPTION_URI_PATH:
613  /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */
614  coap_merge_multi_option((char **)&(coap_pkt->uri_path),
615  &(coap_pkt->uri_path_len), current_option,
616  option_length, '/');
617  PRINTF("Uri-Path [%.*s]\n", (int)coap_pkt->uri_path_len, coap_pkt->uri_path);
618  break;
619  case COAP_OPTION_URI_QUERY:
620  /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */
621  coap_merge_multi_option((char **)&(coap_pkt->uri_query),
622  &(coap_pkt->uri_query_len), current_option,
623  option_length, '&');
624  PRINTF("Uri-Query [%.*s]\n", (int)coap_pkt->uri_query_len,
625  coap_pkt->uri_query);
626  break;
627 
628  case COAP_OPTION_LOCATION_PATH:
629  /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */
630  coap_merge_multi_option((char **)&(coap_pkt->location_path),
631  &(coap_pkt->location_path_len), current_option,
632  option_length, '/');
633  PRINTF("Location-Path [%.*s]\n", (int)coap_pkt->location_path_len,
634  coap_pkt->location_path);
635  break;
636  case COAP_OPTION_LOCATION_QUERY:
637  /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */
638  coap_merge_multi_option((char **)&(coap_pkt->location_query),
639  &(coap_pkt->location_query_len), current_option,
640  option_length, '&');
641  PRINTF("Location-Query [%.*s]\n", (int)coap_pkt->location_query_len,
642  coap_pkt->location_query);
643  break;
644 
645  case COAP_OPTION_OBSERVE:
646  coap_pkt->observe = coap_parse_int_option(current_option,
647  option_length);
648  PRINTF("Observe [%lu]\n", (unsigned long)coap_pkt->observe);
649  break;
650  case COAP_OPTION_BLOCK2:
651  coap_pkt->block2_num = coap_parse_int_option(current_option,
652  option_length);
653  coap_pkt->block2_more = (coap_pkt->block2_num & 0x08) >> 3;
654  coap_pkt->block2_size = 16 << (coap_pkt->block2_num & 0x07);
655  coap_pkt->block2_offset = (coap_pkt->block2_num & ~0x0000000F)
656  << (coap_pkt->block2_num & 0x07);
657  coap_pkt->block2_num >>= 4;
658  PRINTF("Block2 [%lu%s (%u B/blk)]\n",
659  (unsigned long)coap_pkt->block2_num,
660  coap_pkt->block2_more ? "+" : "", coap_pkt->block2_size);
661  break;
662  case COAP_OPTION_BLOCK1:
663  coap_pkt->block1_num = coap_parse_int_option(current_option,
664  option_length);
665  coap_pkt->block1_more = (coap_pkt->block1_num & 0x08) >> 3;
666  coap_pkt->block1_size = 16 << (coap_pkt->block1_num & 0x07);
667  coap_pkt->block1_offset = (coap_pkt->block1_num & ~0x0000000F)
668  << (coap_pkt->block1_num & 0x07);
669  coap_pkt->block1_num >>= 4;
670  PRINTF("Block1 [%lu%s (%u B/blk)]\n",
671  (unsigned long)coap_pkt->block1_num,
672  coap_pkt->block1_more ? "+" : "", coap_pkt->block1_size);
673  break;
674  case COAP_OPTION_SIZE2:
675  coap_pkt->size2 = coap_parse_int_option(current_option, option_length);
676  PRINTF("Size2 [%lu]\n", (unsigned long)coap_pkt->size2);
677  break;
678  case COAP_OPTION_SIZE1:
679  coap_pkt->size1 = coap_parse_int_option(current_option, option_length);
680  PRINTF("Size1 [%lu]\n", (unsigned long)coap_pkt->size1);
681  break;
682  default:
683  PRINTF("unknown (%u)\n", option_number);
684  /* check if critical (odd) */
685  if(option_number & 1) {
686  coap_error_message = "Unsupported critical option";
687  return BAD_OPTION_4_02;
688  }
689  }
690 
691  current_option += option_length;
692  } /* for */
693  PRINTF("-Done parsing-------\n");
694 
695  return NO_ERROR;
696 }
697 /*---------------------------------------------------------------------------*/
698 /*- REST Engine API ---------------------------------------------------------*/
699 /*---------------------------------------------------------------------------*/
700 int
701 coap_get_query_variable(void *packet, const char *name, const char **output)
702 {
703  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
704 
705  if(IS_OPTION(coap_pkt, COAP_OPTION_URI_QUERY)) {
706  return coap_get_variable(coap_pkt->uri_query, coap_pkt->uri_query_len,
707  name, output);
708  }
709  return 0;
710 }
711 int
712 coap_get_post_variable(void *packet, const char *name, const char **output)
713 {
714  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
715 
716  if(coap_pkt->payload_len) {
717  return coap_get_variable((const char *)coap_pkt->payload,
718  coap_pkt->payload_len, name, output);
719  }
720  return 0;
721 }
722 /*---------------------------------------------------------------------------*/
723 int
724 coap_set_status_code(void *packet, unsigned int code)
725 {
726  if(code <= 0xFF) {
727  ((coap_packet_t *)packet)->code = (uint8_t)code;
728  return 1;
729  } else {
730  return 0;
731  }
732 }
733 /*---------------------------------------------------------------------------*/
734 int
735 coap_set_token(void *packet, const uint8_t *token, size_t token_len)
736 {
737  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
738 
739  coap_pkt->token_len = MIN(COAP_TOKEN_LEN, token_len);
740  memcpy(coap_pkt->token, token, coap_pkt->token_len);
741 
742  return coap_pkt->token_len;
743 }
744 /*---------------------------------------------------------------------------*/
745 /*- CoAP REST Implementation API --------------------------------------------*/
746 /*---------------------------------------------------------------------------*/
747 int
748 coap_get_header_content_format(void *packet, unsigned int *format)
749 {
750  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
751 
752  if(!IS_OPTION(coap_pkt, COAP_OPTION_CONTENT_FORMAT)) {
753  return 0;
754  }
755  *format = coap_pkt->content_format;
756  return 1;
757 }
758 int
759 coap_set_header_content_format(void *packet, unsigned int format)
760 {
761  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
762 
763  coap_pkt->content_format = format;
764  SET_OPTION(coap_pkt, COAP_OPTION_CONTENT_FORMAT);
765  return 1;
766 }
767 /*---------------------------------------------------------------------------*/
768 int
769 coap_get_header_accept(void *packet, unsigned int *accept)
770 {
771  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
772 
773  if(!IS_OPTION(coap_pkt, COAP_OPTION_ACCEPT)) {
774  return 0;
775  }
776  *accept = coap_pkt->accept;
777  return 1;
778 }
779 int
780 coap_set_header_accept(void *packet, unsigned int accept)
781 {
782  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
783 
784  coap_pkt->accept = accept;
785  SET_OPTION(coap_pkt, COAP_OPTION_ACCEPT);
786  return 1;
787 }
788 /*---------------------------------------------------------------------------*/
789 int
790 coap_get_header_max_age(void *packet, uint32_t *age)
791 {
792  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
793 
794  if(!IS_OPTION(coap_pkt, COAP_OPTION_MAX_AGE)) {
795  *age = COAP_DEFAULT_MAX_AGE;
796  } else {
797  *age = coap_pkt->max_age;
798  } return 1;
799 }
800 int
801 coap_set_header_max_age(void *packet, uint32_t age)
802 {
803  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
804 
805  coap_pkt->max_age = age;
806  SET_OPTION(coap_pkt, COAP_OPTION_MAX_AGE);
807  return 1;
808 }
809 /*---------------------------------------------------------------------------*/
810 int
811 coap_get_header_etag(void *packet, const uint8_t **etag)
812 {
813  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
814 
815  if(!IS_OPTION(coap_pkt, COAP_OPTION_ETAG)) {
816  return 0;
817  }
818  *etag = coap_pkt->etag;
819  return coap_pkt->etag_len;
820 }
821 int
822 coap_set_header_etag(void *packet, const uint8_t *etag, size_t etag_len)
823 {
824  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
825 
826  coap_pkt->etag_len = MIN(COAP_ETAG_LEN, etag_len);
827  memcpy(coap_pkt->etag, etag, coap_pkt->etag_len);
828 
829  SET_OPTION(coap_pkt, COAP_OPTION_ETAG);
830  return coap_pkt->etag_len;
831 }
832 /*---------------------------------------------------------------------------*/
833 /*FIXME support multiple ETags */
834 int
835 coap_get_header_if_match(void *packet, const uint8_t **etag)
836 {
837  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
838 
839  if(!IS_OPTION(coap_pkt, COAP_OPTION_IF_MATCH)) {
840  return 0;
841  }
842  *etag = coap_pkt->if_match;
843  return coap_pkt->if_match_len;
844 }
845 int
846 coap_set_header_if_match(void *packet, const uint8_t *etag, size_t etag_len)
847 {
848  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
849 
850  coap_pkt->if_match_len = MIN(COAP_ETAG_LEN, etag_len);
851  memcpy(coap_pkt->if_match, etag, coap_pkt->if_match_len);
852 
853  SET_OPTION(coap_pkt, COAP_OPTION_IF_MATCH);
854  return coap_pkt->if_match_len;
855 }
856 /*---------------------------------------------------------------------------*/
857 int
858 coap_get_header_if_none_match(void *packet)
859 {
860  return IS_OPTION((coap_packet_t *)packet,
861  COAP_OPTION_IF_NONE_MATCH) ? 1 : 0;
862 }
863 int
864 coap_set_header_if_none_match(void *packet)
865 {
866  SET_OPTION((coap_packet_t *)packet, COAP_OPTION_IF_NONE_MATCH);
867  return 1;
868 }
869 /*---------------------------------------------------------------------------*/
870 int
871 coap_get_header_proxy_uri(void *packet, const char **uri)
872 {
873  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
874 
875  if(!IS_OPTION(coap_pkt, COAP_OPTION_PROXY_URI)) {
876  return 0;
877  }
878  *uri = coap_pkt->proxy_uri;
879  return coap_pkt->proxy_uri_len;
880 }
881 int
882 coap_set_header_proxy_uri(void *packet, const char *uri)
883 {
884  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
885 
886  /*TODO Provide alternative that sets Proxy-Scheme and Uri-* options and provide er-coap-conf define */
887 
888  coap_pkt->proxy_uri = uri;
889  coap_pkt->proxy_uri_len = strlen(uri);
890 
891  SET_OPTION(coap_pkt, COAP_OPTION_PROXY_URI);
892  return coap_pkt->proxy_uri_len;
893 }
894 /*---------------------------------------------------------------------------*/
895 int
896 coap_get_header_uri_host(void *packet, const char **host)
897 {
898  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
899 
900  if(!IS_OPTION(coap_pkt, COAP_OPTION_URI_HOST)) {
901  return 0;
902  }
903  *host = coap_pkt->uri_host;
904  return coap_pkt->uri_host_len;
905 }
906 int
907 coap_set_header_uri_host(void *packet, const char *host)
908 {
909  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
910 
911  coap_pkt->uri_host = host;
912  coap_pkt->uri_host_len = strlen(host);
913 
914  SET_OPTION(coap_pkt, COAP_OPTION_URI_HOST);
915  return coap_pkt->uri_host_len;
916 }
917 /*---------------------------------------------------------------------------*/
918 int
919 coap_get_header_uri_path(void *packet, const char **path)
920 {
921  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
922 
923  if(!IS_OPTION(coap_pkt, COAP_OPTION_URI_PATH)) {
924  return 0;
925  }
926  *path = coap_pkt->uri_path;
927  return coap_pkt->uri_path_len;
928 }
929 int
930 coap_set_header_uri_path(void *packet, const char *path)
931 {
932  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
933 
934  while(path[0] == '/')
935  ++path;
936 
937  coap_pkt->uri_path = path;
938  coap_pkt->uri_path_len = strlen(path);
939 
940  SET_OPTION(coap_pkt, COAP_OPTION_URI_PATH);
941  return coap_pkt->uri_path_len;
942 }
943 /*---------------------------------------------------------------------------*/
944 int
945 coap_get_header_uri_query(void *packet, const char **query)
946 {
947  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
948 
949  if(!IS_OPTION(coap_pkt, COAP_OPTION_URI_QUERY)) {
950  return 0;
951  }
952  *query = coap_pkt->uri_query;
953  return coap_pkt->uri_query_len;
954 }
955 int
956 coap_set_header_uri_query(void *packet, const char *query)
957 {
958  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
959 
960  while(query[0] == '?')
961  ++query;
962 
963  coap_pkt->uri_query = query;
964  coap_pkt->uri_query_len = strlen(query);
965 
966  SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
967  return coap_pkt->uri_query_len;
968 }
969 /*---------------------------------------------------------------------------*/
970 int
971 coap_get_header_location_path(void *packet, const char **path)
972 {
973  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
974 
975  if(!IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_PATH)) {
976  return 0;
977  }
978  *path = coap_pkt->location_path;
979  return coap_pkt->location_path_len;
980 }
981 int
982 coap_set_header_location_path(void *packet, const char *path)
983 {
984  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
985 
986  char *query;
987 
988  while(path[0] == '/')
989  ++path;
990 
991  if((query = strchr(path, '?'))) {
992  coap_set_header_location_query(packet, query + 1);
993  coap_pkt->location_path_len = query - path;
994  } else {
995  coap_pkt->location_path_len = strlen(path);
996  } coap_pkt->location_path = path;
997 
998  if(coap_pkt->location_path_len > 0) {
999  SET_OPTION(coap_pkt, COAP_OPTION_LOCATION_PATH);
1000  }
1001  return coap_pkt->location_path_len;
1002 }
1003 /*---------------------------------------------------------------------------*/
1004 int
1005 coap_get_header_location_query(void *packet, const char **query)
1006 {
1007  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
1008 
1009  if(!IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_QUERY)) {
1010  return 0;
1011  }
1012  *query = coap_pkt->location_query;
1013  return coap_pkt->location_query_len;
1014 }
1015 int
1016 coap_set_header_location_query(void *packet, const char *query)
1017 {
1018  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
1019 
1020  while(query[0] == '?')
1021  ++query;
1022 
1023  coap_pkt->location_query = query;
1024  coap_pkt->location_query_len = strlen(query);
1025 
1026  SET_OPTION(coap_pkt, COAP_OPTION_LOCATION_QUERY);
1027  return coap_pkt->location_query_len;
1028 }
1029 /*---------------------------------------------------------------------------*/
1030 int
1031 coap_get_header_observe(void *packet, uint32_t *observe)
1032 {
1033  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
1034 
1035  if(!IS_OPTION(coap_pkt, COAP_OPTION_OBSERVE)) {
1036  return 0;
1037  }
1038  *observe = coap_pkt->observe;
1039  return 1;
1040 }
1041 int
1042 coap_set_header_observe(void *packet, uint32_t observe)
1043 {
1044  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
1045 
1046  coap_pkt->observe = observe;
1047  SET_OPTION(coap_pkt, COAP_OPTION_OBSERVE);
1048  return 1;
1049 }
1050 /*---------------------------------------------------------------------------*/
1051 int
1052 coap_get_header_block2(void *packet, uint32_t *num, uint8_t *more,
1053  uint16_t *size, uint32_t *offset)
1054 {
1055  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
1056 
1057  if(!IS_OPTION(coap_pkt, COAP_OPTION_BLOCK2)) {
1058  return 0;
1059  }
1060  /* pointers may be NULL to get only specific block parameters */
1061  if(num != NULL) {
1062  *num = coap_pkt->block2_num;
1063  }
1064  if(more != NULL) {
1065  *more = coap_pkt->block2_more;
1066  }
1067  if(size != NULL) {
1068  *size = coap_pkt->block2_size;
1069  }
1070  if(offset != NULL) {
1071  *offset = coap_pkt->block2_offset;
1072  }
1073  return 1;
1074 }
1075 int
1076 coap_set_header_block2(void *packet, uint32_t num, uint8_t more,
1077  uint16_t size)
1078 {
1079  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
1080 
1081  if(size < 16) {
1082  return 0;
1083  }
1084  if(size > 2048) {
1085  return 0;
1086  }
1087  if(num > 0x0FFFFF) {
1088  return 0;
1089  }
1090  coap_pkt->block2_num = num;
1091  coap_pkt->block2_more = more ? 1 : 0;
1092  coap_pkt->block2_size = size;
1093 
1094  SET_OPTION(coap_pkt, COAP_OPTION_BLOCK2);
1095  return 1;
1096 }
1097 /*---------------------------------------------------------------------------*/
1098 int
1099 coap_get_header_block1(void *packet, uint32_t *num, uint8_t *more,
1100  uint16_t *size, uint32_t *offset)
1101 {
1102  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
1103 
1104  if(!IS_OPTION(coap_pkt, COAP_OPTION_BLOCK1)) {
1105  return 0;
1106  }
1107  /* pointers may be NULL to get only specific block parameters */
1108  if(num != NULL) {
1109  *num = coap_pkt->block1_num;
1110  }
1111  if(more != NULL) {
1112  *more = coap_pkt->block1_more;
1113  }
1114  if(size != NULL) {
1115  *size = coap_pkt->block1_size;
1116  }
1117  if(offset != NULL) {
1118  *offset = coap_pkt->block1_offset;
1119  }
1120  return 1;
1121 }
1122 int
1123 coap_set_header_block1(void *packet, uint32_t num, uint8_t more,
1124  uint16_t size)
1125 {
1126  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
1127 
1128  if(size < 16) {
1129  return 0;
1130  }
1131  if(size > 2048) {
1132  return 0;
1133  }
1134  if(num > 0x0FFFFF) {
1135  return 0;
1136  }
1137  coap_pkt->block1_num = num;
1138  coap_pkt->block1_more = more;
1139  coap_pkt->block1_size = size;
1140 
1141  SET_OPTION(coap_pkt, COAP_OPTION_BLOCK1);
1142  return 1;
1143 }
1144 /*---------------------------------------------------------------------------*/
1145 int
1146 coap_get_header_size2(void *packet, uint32_t *size)
1147 {
1148  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
1149 
1150  if(!IS_OPTION(coap_pkt, COAP_OPTION_SIZE2)) {
1151  return 0;
1152  }
1153  *size = coap_pkt->size2;
1154  return 1;
1155 }
1156 int
1157 coap_set_header_size2(void *packet, uint32_t size)
1158 {
1159  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
1160 
1161  coap_pkt->size2 = size;
1162  SET_OPTION(coap_pkt, COAP_OPTION_SIZE2);
1163  return 1;
1164 }
1165 /*---------------------------------------------------------------------------*/
1166 int
1167 coap_get_header_size1(void *packet, uint32_t *size)
1168 {
1169  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
1170 
1171  if(!IS_OPTION(coap_pkt, COAP_OPTION_SIZE1)) {
1172  return 0;
1173  }
1174  *size = coap_pkt->size1;
1175  return 1;
1176 }
1177 int
1178 coap_set_header_size1(void *packet, uint32_t size)
1179 {
1180  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
1181 
1182  coap_pkt->size1 = size;
1183  SET_OPTION(coap_pkt, COAP_OPTION_SIZE1);
1184  return 1;
1185 }
1186 /*---------------------------------------------------------------------------*/
1187 int
1188 coap_get_payload(void *packet, const uint8_t **payload)
1189 {
1190  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
1191 
1192  if(coap_pkt->payload) {
1193  *payload = coap_pkt->payload;
1194  return coap_pkt->payload_len;
1195  } else {
1196  *payload = NULL;
1197  return 0;
1198  }
1199 }
1200 int
1201 coap_set_payload(void *packet, const void *payload, size_t length)
1202 {
1203  coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
1204 
1205  coap_pkt->payload = (uint8_t *)payload;
1206  coap_pkt->payload_len = MIN(REST_MAX_CHUNK_SIZE, length);
1207 
1208  return coap_pkt->payload_len;
1209 }
1210 /*---------------------------------------------------------------------------*/
uip_ipaddr_t ripaddr
The IP address of the remote peer.
Definition: uip.h:1406
static void start(void)
Start measurement.
static uip_ds6_addr_t * addr
Pointer to a router list entry.
Definition: uip-nd6.c:124
Default definitions of C compiler quirk work-arounds.
Representation of a uIP UDP connection.
Definition: uip.h:1405
CoAP module for reliable transport
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
Definition: uip.h:1027
#define udp_bind(conn, port)
Bind a UDP connection to a local port.
Definition: tcpip.h:262
struct uip_udp_conn * udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
Create a new UDP connection.
Definition: tcpip.c:304
#define NULL
The null pointer.
unsigned short random_rand(void)
Generates a new random number using the cc2538 RNG.
Definition: random.c:47
uint16_t rport
The remote port number in network byte order.
Definition: uip.h:1408
An implementation of the Constrained Application Protocol (RFC).
uint16_t lport
The local port number in network byte order.
Definition: uip.h:1407
static uint8_t output(const uip_lladdr_t *localdest)
Take an IP packet and format it to be sent on an 802.15.4 network using 6lowpan.
Definition: sicslowpan.c:1275
static uint8_t accept(uint8_t in)
Processes an incoming or outgoing multicast message and determines whether it should be dropped or ac...
Definition: roll-tm.c:894