terence zhang / wakaama-core
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers er-coap-13.c Source File

er-coap-13.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the Institute nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  *
00029  * This file is part of the Contiki operating system.
00030  */
00031 
00032 /**
00033  * \file
00034  *      An implementation of the Constrained Application Protocol (draft 12)
00035  * \author
00036  *      Matthias Kovatsch <kovatsch@inf.ethz.ch>
00037  * \contributors
00038  *    David Navarro, Intel Corporation - Adapt to usage in liblwm2m
00039  */
00040 
00041 
00042 #include <stdlib.h>
00043 
00044 #include <string.h>
00045 #include <stdio.h>
00046 
00047 #include "er-coap-13.h"
00048 
00049 #include "liblwm2m.h" /* for lwm2m_malloc() and lwm2m_free() */
00050 
00051 #define DEBUG 0
00052 #if DEBUG
00053 #include <stdio.h>
00054 #define PRINTF(...) printf(__VA_ARGS__)
00055 #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])
00056 #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])
00057 #else
00058 #define PRINTF(...)
00059 #define PRINT6ADDR(addr)
00060 #define PRINTLLADDR(addr)
00061 #endif
00062 
00063 /*-----------------------------------------------------------------------------------*/
00064 /*- Variables -----------------------------------------------------------------------*/
00065 /*-----------------------------------------------------------------------------------*/
00066 static uint16_t current_mid = 0;
00067 
00068 coap_status_t coap_error_code = NO_ERROR;
00069 const char *coap_error_message = "";
00070 /*-----------------------------------------------------------------------------------*/
00071 /*- LOCAL HELP FUNCTIONS ------------------------------------------------------------*/
00072 /*-----------------------------------------------------------------------------------*/
00073 static
00074 uint16_t
00075 coap_log_2(uint16_t value)
00076 {
00077   uint16_t result = 0;
00078   do {
00079     value = value >> 1;
00080     result++;
00081   } while (value);
00082 
00083   return result ? result - 1 : result;
00084 }
00085 /*-----------------------------------------------------------------------------------*/
00086 static
00087 uint32_t
00088 coap_parse_int_option(uint8_t *bytes, size_t length)
00089 {
00090   uint32_t var = 0;
00091   size_t i = 0;
00092   while (i<length)
00093   {
00094     var <<= 8;
00095     var |= bytes[i++];
00096   }
00097   return var;
00098 }
00099 /*-----------------------------------------------------------------------------------*/
00100 static
00101 uint8_t
00102 coap_option_nibble(unsigned int value)
00103 {
00104   if (value<13)
00105   {
00106     return value;
00107   }
00108   else if (value<=0xFF+13)
00109   {
00110     return 13;
00111   }
00112   else
00113   {
00114     return 14;
00115   }
00116 }
00117 /*-----------------------------------------------------------------------------------*/
00118 static
00119 size_t
00120 coap_set_option_header(unsigned int delta, size_t length, uint8_t *buffer)
00121 {
00122   size_t written = 0;
00123   unsigned int *x = &delta;
00124 
00125   buffer[0] = coap_option_nibble(delta)<<4 | coap_option_nibble(length);
00126 
00127   /* avoids code duplication without function overhead */
00128   do
00129   {
00130     if (*x>268)
00131     {
00132       buffer[++written] = (*x-269)>>8;
00133       buffer[++written] = (*x-269);
00134     }
00135     else if (*x>12)
00136     {
00137       buffer[++written] = (*x-13);
00138     }
00139   }
00140   while (x!=(unsigned int *)&length && (x=(unsigned int *)&length));
00141 
00142   PRINTF("WRITTEN %u B opt header\n", written);
00143 
00144   return ++written;
00145 }
00146 /*-----------------------------------------------------------------------------------*/
00147 static
00148 size_t
00149 coap_serialize_int_option(unsigned int number, unsigned int current_number, uint8_t *buffer, uint32_t value)
00150 {
00151   size_t i = 0;
00152 
00153   if (0xFF000000 & value) ++i;
00154   if (0xFFFF0000 & value) ++i;
00155   if (0xFFFFFF00 & value) ++i;
00156   if (0xFFFFFFFF & value) ++i;
00157 
00158   PRINTF("OPTION %u (delta %u, len %u)\n", number, number - current_number, i);
00159 
00160   i = coap_set_option_header(number - current_number, i, buffer);
00161 
00162   if (0xFF000000 & value) buffer[i++] = (uint8_t) (value>>24);
00163   if (0xFFFF0000 & value) buffer[i++] = (uint8_t) (value>>16);
00164   if (0xFFFFFF00 & value) buffer[i++] = (uint8_t) (value>>8);
00165   if (0xFFFFFFFF & value) buffer[i++] = (uint8_t) (value);
00166 
00167   return i;
00168 }
00169 /*-----------------------------------------------------------------------------------*/
00170 static
00171 size_t
00172 coap_serialize_array_option(unsigned int number, unsigned int current_number, uint8_t *buffer, uint8_t *array, size_t length, char split_char)
00173 {
00174   size_t i = 0;
00175 
00176   if (split_char!='\0')
00177   {
00178     size_t j;
00179     uint8_t *part_start = array;
00180     uint8_t *part_end = NULL;
00181     size_t temp_length;
00182 
00183     for (j = 0; j<=length; ++j)
00184     {
00185       if (array[j]==split_char || j==length)
00186       {
00187         part_end = array + j;
00188         temp_length = part_end-part_start;
00189 
00190         i += coap_set_option_header(number - current_number, temp_length, &buffer[i]);
00191         memcpy(&buffer[i], part_start, temp_length);
00192         i += temp_length;
00193 
00194         PRINTF("OPTION type %u, delta %u, len %u, part [%.*s]\n", number, number - current_number, i, temp_length, part_start);
00195 
00196         ++j; /* skip the splitter */
00197         current_number = number;
00198         part_start = array + j;
00199       }
00200     } /* for */
00201   }
00202   else
00203   {
00204     i += coap_set_option_header(number - current_number, length, &buffer[i]);
00205     memcpy(&buffer[i], array, length);
00206     i += length;
00207 
00208     PRINTF("OPTION type %u, delta %u, len %u\n", number, number - current_number, length);
00209   }
00210 
00211   return i;
00212 }
00213 /*-----------------------------------------------------------------------------------*/
00214 static
00215 size_t
00216 coap_serialize_multi_option(unsigned int number, unsigned int current_number, uint8_t *buffer, multi_option_t *array)
00217 {
00218   size_t i = 0;
00219   multi_option_t * j;
00220 
00221   for (j = array; j != NULL; j= j->next)
00222   {
00223      i += coap_set_option_header(number - current_number, j->len, &buffer[i]);
00224      current_number = number;
00225      memcpy(&buffer[i], j->data, j->len);
00226      i += j->len;
00227   } /* for */
00228 
00229   return i;
00230 }
00231 /*-----------------------------------------------------------------------------------*/
00232 static
00233 void
00234 coap_merge_multi_option(uint8_t **dst, size_t *dst_len, uint8_t *option, size_t option_len, char separator)
00235 {
00236   /* Merge multiple options. */
00237   if (*dst_len > 0)
00238   {
00239     /* dst already contains an option: concatenate */
00240     (*dst)[*dst_len] = separator;
00241     *dst_len += 1;
00242 
00243     /* memmove handles 2-byte option headers */
00244     memmove((*dst)+(*dst_len), option, option_len);
00245 
00246     *dst_len += option_len;
00247   }
00248   else
00249   {
00250     /* dst is empty: set to option */
00251     *dst = option;
00252     *dst_len = option_len;
00253   }
00254 }
00255 
00256 void
00257 coap_add_multi_option(multi_option_t **dst, uint8_t *option, size_t option_len, uint8_t is_static)
00258 {
00259   multi_option_t *opt = (multi_option_t *)lwm2m_malloc(sizeof(multi_option_t));
00260 
00261   if (opt)
00262   {
00263     opt->next = NULL;
00264     opt->len = (uint8_t)option_len;
00265     if (is_static)
00266     {
00267       opt->data = option;
00268       opt->is_static = 1;
00269     }
00270     else
00271     {
00272         opt->is_static = 0;
00273         opt->data = (uint8_t *)lwm2m_malloc(option_len);
00274         if (opt->data == NULL)
00275         {
00276             lwm2m_free(opt);
00277             return;
00278         }
00279         memcpy(opt->data, option, option_len);
00280     }
00281 
00282     if (*dst)
00283     {
00284       multi_option_t * i = *dst;
00285       while (i->next)
00286       {
00287         i = i->next;
00288       }
00289       i->next = opt;
00290     }
00291     else
00292     {
00293       *dst = opt;
00294     }
00295   }
00296 }
00297 
00298 void
00299 free_multi_option(multi_option_t *dst)
00300 {
00301   if (dst)
00302   {
00303     multi_option_t *n = dst->next;
00304     dst->next = NULL;
00305     if (dst->is_static == 0)
00306     {
00307         lwm2m_free(dst->data);
00308     }
00309     lwm2m_free(dst);
00310     free_multi_option(n);
00311   }
00312 }
00313 
00314 char * coap_get_multi_option_as_string(multi_option_t * option)
00315 {
00316     size_t len = 0;
00317     multi_option_t * opt;
00318     char * output;
00319 
00320     for (opt = option; opt != NULL; opt = opt->next)
00321     {
00322        len += opt->len + 1;     // for separator
00323     }
00324 
00325     output = lwm2m_malloc(len + 1); // for String terminator
00326     if (output != NULL)
00327     {
00328         size_t i = 0;
00329 
00330         for (opt = option; opt != NULL; opt = opt->next)
00331         {
00332             output[i] = '/';
00333             i += 1;
00334 
00335             memmove(output + i, opt->data, opt->len);
00336             i += opt->len;
00337         }
00338         output[i] = 0;
00339     }
00340 
00341     return output;
00342 }
00343 
00344 /*-----------------------------------------------------------------------------------*/
00345 static
00346 int
00347 coap_get_variable(const uint8_t *buffer, size_t length, const char *name, const char **output)
00348 {
00349   const uint8_t *start = NULL;
00350   const uint8_t *end = NULL;
00351   const uint8_t *value_end = NULL;
00352   size_t name_len = 0;
00353 
00354   /*initialize the output buffer first*/
00355   *output = 0;
00356 
00357   name_len = strlen(name);
00358   end = buffer + length;
00359 
00360   for (start = buffer; start + name_len < end; ++start){
00361     if ((start == buffer || start[-1] == '&') && start[name_len] == '=' &&
00362         strncmp(name, (char *)start, name_len)==0) {
00363 
00364       /* Point start to variable value */
00365       start += name_len + 1;
00366 
00367       /* Point end to the end of the value */
00368       value_end = (const uint8_t *) memchr(start, '&', end - start);
00369       if (value_end == NULL) {
00370         value_end = end;
00371       }
00372 
00373       *output = (char *)start;
00374 
00375       return (value_end - start);
00376     }
00377   }
00378 
00379   return 0;
00380 }
00381 
00382 /*-----------------------------------------------------------------------------------*/
00383 uint16_t
00384 coap_get_mid()
00385 {
00386   return ++current_mid;
00387 }
00388 /*-----------------------------------------------------------------------------------*/
00389 /*- MEASSAGE PROCESSING -------------------------------------------------------------*/
00390 /*-----------------------------------------------------------------------------------*/
00391 void
00392 coap_init_message(void *packet, coap_message_type_t type, uint8_t code, uint16_t mid)
00393 {
00394   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
00395 
00396   /* Important thing */
00397   memset(coap_pkt, 0, sizeof(coap_packet_t));
00398 
00399   coap_pkt->type = type;
00400   coap_pkt->code = code;
00401   coap_pkt->mid = mid;
00402 }
00403 
00404 void
00405 coap_free_header(void *packet)
00406 {
00407     coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
00408 
00409     free_multi_option(coap_pkt->uri_path);
00410     free_multi_option(coap_pkt->uri_query);
00411     free_multi_option(coap_pkt->location_path);
00412     coap_pkt->uri_path = NULL;
00413     coap_pkt->uri_query = NULL;
00414     coap_pkt->location_path = NULL;
00415 }
00416 
00417 /*-----------------------------------------------------------------------------------*/
00418 size_t coap_serialize_get_size(void *packet)
00419 {
00420     coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
00421     size_t length = 0;
00422 
00423     length = COAP_HEADER_LEN + coap_pkt->payload_len + coap_pkt->token_len;
00424 
00425     if (IS_OPTION(coap_pkt, COAP_OPTION_IF_MATCH))
00426     {
00427         length += COAP_MAX_OPTION_HEADER_LEN + coap_pkt->if_match_len;
00428     }
00429     if (IS_OPTION(coap_pkt, COAP_OPTION_URI_HOST))
00430     {
00431         length += COAP_MAX_OPTION_HEADER_LEN + coap_pkt->uri_host_len;
00432     }
00433     if (IS_OPTION(coap_pkt, COAP_OPTION_ETAG))
00434     {
00435         length += COAP_MAX_OPTION_HEADER_LEN + coap_pkt->etag_len;
00436     }
00437     if (IS_OPTION(coap_pkt, COAP_OPTION_IF_NONE_MATCH))
00438     {
00439         // can be stored in extended fields
00440         length += COAP_MAX_OPTION_HEADER_LEN;
00441     }
00442     if (IS_OPTION(coap_pkt, COAP_OPTION_OBSERVE))
00443     {
00444         // can be stored in extended fields
00445         length += COAP_MAX_OPTION_HEADER_LEN;
00446     }
00447     if (IS_OPTION(coap_pkt, COAP_OPTION_URI_PORT))
00448     {
00449         // can be stored in extended fields
00450         length += COAP_MAX_OPTION_HEADER_LEN;
00451     }
00452     if (IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_PATH))
00453     {
00454         multi_option_t * optP;
00455 
00456         for (optP = coap_pkt->location_path ; optP != NULL ; optP = optP->next)
00457         {
00458             length += COAP_MAX_OPTION_HEADER_LEN + optP->len;
00459         }
00460     }
00461     if (IS_OPTION(coap_pkt, COAP_OPTION_URI_PATH))
00462     {
00463         multi_option_t * optP;
00464 
00465         for (optP = coap_pkt->uri_path ; optP != NULL ; optP = optP->next)
00466         {
00467             length += COAP_MAX_OPTION_HEADER_LEN + optP->len;
00468         }
00469     }
00470     if (IS_OPTION(coap_pkt, COAP_OPTION_CONTENT_TYPE))
00471     {
00472         // can be stored in extended fields
00473         length += COAP_MAX_OPTION_HEADER_LEN;
00474     }
00475     if (IS_OPTION(coap_pkt, COAP_OPTION_MAX_AGE))
00476     {
00477         // can be stored in extended fields
00478         length += COAP_MAX_OPTION_HEADER_LEN;
00479     }
00480     if (IS_OPTION(coap_pkt, COAP_OPTION_URI_QUERY))
00481     {
00482         multi_option_t * optP;
00483 
00484         for (optP = coap_pkt->uri_query ; optP != NULL ; optP = optP->next)
00485         {
00486             length += COAP_MAX_OPTION_HEADER_LEN + optP->len;
00487         }
00488     }
00489     if (IS_OPTION(coap_pkt, COAP_OPTION_ACCEPT))
00490     {
00491         length += coap_pkt->accept_num * COAP_MAX_OPTION_HEADER_LEN;
00492     }
00493     if (IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_QUERY))
00494     {
00495         length += COAP_MAX_OPTION_HEADER_LEN + coap_pkt->location_query_len;
00496     }
00497     if (IS_OPTION(coap_pkt, COAP_OPTION_BLOCK2))
00498     {
00499         // can be stored in extended fields
00500         length += COAP_MAX_OPTION_HEADER_LEN;
00501     }
00502     if (IS_OPTION(coap_pkt, COAP_OPTION_BLOCK1))
00503     {
00504         // can be stored in extended fields
00505         length += COAP_MAX_OPTION_HEADER_LEN;
00506     }
00507     if (IS_OPTION(coap_pkt, COAP_OPTION_SIZE))
00508     {
00509         // can be stored in extended fields
00510         length += COAP_MAX_OPTION_HEADER_LEN;
00511     }
00512     if (IS_OPTION(coap_pkt, COAP_OPTION_PROXY_URI))
00513     {
00514         length += COAP_MAX_OPTION_HEADER_LEN + coap_pkt->proxy_uri_len;
00515     }
00516 
00517     return length;
00518 }
00519 
00520 /*-----------------------------------------------------------------------------------*/
00521 size_t
00522 coap_serialize_message(void *packet, uint8_t *buffer)
00523 {
00524   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
00525   uint8_t *option;
00526   unsigned int current_number = 0;
00527 
00528   /* Initialize */
00529   coap_pkt->buffer = buffer;
00530   coap_pkt->version = 1;
00531 
00532   PRINTF("-Serializing MID %u to %p, ", coap_pkt->mid, coap_pkt->buffer);
00533 
00534   /* set header fields */
00535   coap_pkt->buffer[0]  = 0x00;
00536   coap_pkt->buffer[0] |= COAP_HEADER_VERSION_MASK & (coap_pkt->version)<<COAP_HEADER_VERSION_POSITION;
00537   coap_pkt->buffer[0] |= COAP_HEADER_TYPE_MASK & (coap_pkt->type)<<COAP_HEADER_TYPE_POSITION;
00538   coap_pkt->buffer[0] |= COAP_HEADER_TOKEN_LEN_MASK & (coap_pkt->token_len)<<COAP_HEADER_TOKEN_LEN_POSITION;
00539   coap_pkt->buffer[1] = coap_pkt->code;
00540   coap_pkt->buffer[2] = (uint8_t) ((coap_pkt->mid)>>8);
00541   coap_pkt->buffer[3] = (uint8_t) (coap_pkt->mid);
00542 
00543   /* set Token */
00544   PRINTF("Token (len %u)", coap_pkt->token_len);
00545   option = coap_pkt->buffer + COAP_HEADER_LEN;
00546   for (current_number=0; current_number<coap_pkt->token_len; ++current_number)
00547   {
00548     PRINTF(" %02X", coap_pkt->token[current_number]);
00549     *option = coap_pkt->token[current_number];
00550     ++option;
00551   }
00552   PRINTF("-\n");
00553 
00554   /* Serialize options */
00555   current_number = 0;
00556 
00557   PRINTF("-Serializing options at %p-\n", option);
00558 
00559   /* The options must be serialized in the order of their number */
00560   COAP_SERIALIZE_BYTE_OPTION(   COAP_OPTION_IF_MATCH,       if_match, "If-Match")
00561   COAP_SERIALIZE_STRING_OPTION( COAP_OPTION_URI_HOST,       uri_host, '\0', "Uri-Host")
00562   COAP_SERIALIZE_BYTE_OPTION(   COAP_OPTION_ETAG,           etag, "ETag")
00563   COAP_SERIALIZE_INT_OPTION(    COAP_OPTION_IF_NONE_MATCH,  content_type-coap_pkt->content_type, "If-None-Match") /* hack to get a zero field */
00564   COAP_SERIALIZE_INT_OPTION(    COAP_OPTION_OBSERVE,        observe, "Observe")
00565   COAP_SERIALIZE_INT_OPTION(    COAP_OPTION_URI_PORT,       uri_port, "Uri-Port")
00566   COAP_SERIALIZE_MULTI_OPTION(  COAP_OPTION_LOCATION_PATH,  location_path, "Location-Path")
00567   COAP_SERIALIZE_MULTI_OPTION(  COAP_OPTION_URI_PATH,       uri_path, "Uri-Path")
00568   COAP_SERIALIZE_INT_OPTION(    COAP_OPTION_CONTENT_TYPE,   content_type, "Content-Format")
00569   COAP_SERIALIZE_INT_OPTION(    COAP_OPTION_MAX_AGE,        max_age, "Max-Age")
00570   COAP_SERIALIZE_MULTI_OPTION(  COAP_OPTION_URI_QUERY,      uri_query, "Uri-Query")
00571   COAP_SERIALIZE_ACCEPT_OPTION( COAP_OPTION_ACCEPT,         accept, "Accept")
00572   COAP_SERIALIZE_STRING_OPTION( COAP_OPTION_LOCATION_QUERY, location_query, '&', "Location-Query")
00573   COAP_SERIALIZE_BLOCK_OPTION(  COAP_OPTION_BLOCK2,         block2, "Block2")
00574   COAP_SERIALIZE_BLOCK_OPTION(  COAP_OPTION_BLOCK1,         block1, "Block1")
00575   COAP_SERIALIZE_INT_OPTION(    COAP_OPTION_SIZE,           size, "Size")
00576   COAP_SERIALIZE_STRING_OPTION( COAP_OPTION_PROXY_URI,      proxy_uri, '\0', "Proxy-Uri")
00577 
00578   PRINTF("-Done serializing at %p----\n", option);
00579 
00580   /* Free allocated header fields */
00581   coap_free_header(packet);
00582 
00583   /* Pack payload */
00584   /* Payload marker */
00585   if (coap_pkt->payload_len)
00586   {
00587     *option = 0xFF;
00588     ++option;
00589   }
00590 
00591   memmove(option, coap_pkt->payload, coap_pkt->payload_len);
00592 
00593   PRINTF("-Done %u B (header len %u, payload len %u)-\n", coap_pkt->payload_len + option - buffer, option - buffer, coap_pkt->payload_len);
00594 
00595   PRINTF("Dump [0x%02X %02X %02X %02X  %02X %02X %02X %02X]\n",
00596       coap_pkt->buffer[0],
00597       coap_pkt->buffer[1],
00598       coap_pkt->buffer[2],
00599       coap_pkt->buffer[3],
00600       coap_pkt->buffer[4],
00601       coap_pkt->buffer[5],
00602       coap_pkt->buffer[6],
00603       coap_pkt->buffer[7]
00604     );
00605 
00606   return (option - buffer) + coap_pkt->payload_len; /* packet length */
00607 }
00608 /*-----------------------------------------------------------------------------------*/
00609 coap_status_t
00610 coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
00611 {
00612   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
00613   uint8_t *current_option;
00614   unsigned int option_number = 0;
00615   unsigned int option_delta = 0;
00616   size_t option_length = 0;
00617   unsigned int *x;
00618 
00619   /* Initialize packet */
00620   memset(coap_pkt, 0, sizeof(coap_packet_t));
00621 
00622   /* pointer to packet bytes */
00623   coap_pkt->buffer = data;
00624 
00625   /* parse header fields */
00626   coap_pkt->version = (COAP_HEADER_VERSION_MASK & coap_pkt->buffer[0])>>COAP_HEADER_VERSION_POSITION;
00627   coap_pkt->type = (COAP_HEADER_TYPE_MASK & coap_pkt->buffer[0])>>COAP_HEADER_TYPE_POSITION;
00628   coap_pkt->token_len = MIN(COAP_TOKEN_LEN, (COAP_HEADER_TOKEN_LEN_MASK & coap_pkt->buffer[0])>>COAP_HEADER_TOKEN_LEN_POSITION);
00629   coap_pkt->code = coap_pkt->buffer[1];
00630   coap_pkt->mid = coap_pkt->buffer[2]<<8 | coap_pkt->buffer[3];
00631 
00632   if (coap_pkt->version != 1)
00633   {
00634     coap_error_message = "CoAP version must be 1";
00635     return BAD_REQUEST_4_00;
00636   }
00637 
00638   current_option = data + COAP_HEADER_LEN;
00639 
00640   if (coap_pkt->token_len != 0)
00641   {
00642       memcpy(coap_pkt->token, current_option, coap_pkt->token_len);
00643       SET_OPTION(coap_pkt, COAP_OPTION_TOKEN);
00644 
00645       PRINTF("Token (len %u) [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", coap_pkt->token_len,
00646         coap_pkt->token[0],
00647         coap_pkt->token[1],
00648         coap_pkt->token[2],
00649         coap_pkt->token[3],
00650         coap_pkt->token[4],
00651         coap_pkt->token[5],
00652         coap_pkt->token[6],
00653         coap_pkt->token[7]
00654       ); /*FIXME always prints 8 bytes */
00655   }
00656 
00657   /* parse options */
00658   current_option += coap_pkt->token_len;
00659 
00660   while (current_option < data+data_len)
00661   {
00662     /* Payload marker 0xFF, currently only checking for 0xF* because rest is reserved */
00663     if ((current_option[0] & 0xF0)==0xF0)
00664     {
00665       coap_pkt->payload = ++current_option;
00666       coap_pkt->payload_len = data_len - (coap_pkt->payload - data);
00667 
00668       break;
00669     }
00670 
00671     option_delta = current_option[0]>>4;
00672     option_length = current_option[0] & 0x0F;
00673     ++current_option;
00674 
00675     /* avoids code duplication without function overhead */
00676     x = &option_delta;
00677     do
00678     {
00679       if (*x==13)
00680       {
00681         *x += current_option[0];
00682         ++current_option;
00683       }
00684       else if (*x==14)
00685       {
00686         *x += 255;
00687         *x += current_option[0]<<8;
00688         ++current_option;
00689         *x += current_option[0];
00690         ++current_option;
00691       }
00692     }
00693     while (x!=(unsigned int *)&option_length && (x=(unsigned int *)&option_length));
00694 
00695     option_number += option_delta;
00696 
00697     PRINTF("OPTION %u (delta %u, len %u): ", option_number, option_delta, option_length);
00698 
00699     SET_OPTION(coap_pkt, option_number);
00700 
00701     switch (option_number)
00702     {
00703       case COAP_OPTION_CONTENT_TYPE:
00704         coap_pkt->content_type = coap_parse_int_option(current_option, option_length);
00705         PRINTF("Content-Format [%u]\n", coap_pkt->content_type);
00706         break;
00707       case COAP_OPTION_MAX_AGE:
00708         coap_pkt->max_age = coap_parse_int_option(current_option, option_length);
00709         PRINTF("Max-Age [%lu]\n", coap_pkt->max_age);
00710         break;
00711       case COAP_OPTION_ETAG:
00712         coap_pkt->etag_len = (uint8_t)(MIN(COAP_ETAG_LEN, option_length));
00713         memcpy(coap_pkt->etag, current_option, coap_pkt->etag_len);
00714         PRINTF("ETag %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", coap_pkt->etag_len,
00715           coap_pkt->etag[0],
00716           coap_pkt->etag[1],
00717           coap_pkt->etag[2],
00718           coap_pkt->etag[3],
00719           coap_pkt->etag[4],
00720           coap_pkt->etag[5],
00721           coap_pkt->etag[6],
00722           coap_pkt->etag[7]
00723         ); /*FIXME always prints 8 bytes */
00724         break;
00725       case COAP_OPTION_ACCEPT:
00726         if (coap_pkt->accept_num < COAP_MAX_ACCEPT_NUM)
00727         {
00728           coap_pkt->accept[coap_pkt->accept_num] = coap_parse_int_option(current_option, option_length);
00729           coap_pkt->accept_num += 1;
00730           PRINTF("Accept [%u]\n", coap_pkt->content_type);
00731         }
00732         break;
00733       case COAP_OPTION_IF_MATCH:
00734         /*FIXME support multiple ETags */
00735         coap_pkt->if_match_len = (uint8_t)(MIN(COAP_ETAG_LEN, option_length));
00736         memcpy(coap_pkt->if_match, current_option, coap_pkt->if_match_len);
00737         PRINTF("If-Match %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", coap_pkt->if_match_len,
00738           coap_pkt->if_match[0],
00739           coap_pkt->if_match[1],
00740           coap_pkt->if_match[2],
00741           coap_pkt->if_match[3],
00742           coap_pkt->if_match[4],
00743           coap_pkt->if_match[5],
00744           coap_pkt->if_match[6],
00745           coap_pkt->if_match[7]
00746         ); /*FIXME always prints 8 bytes */
00747         break;
00748       case COAP_OPTION_IF_NONE_MATCH:
00749         coap_pkt->if_none_match = 1;
00750         PRINTF("If-None-Match\n");
00751         break;
00752 
00753       case COAP_OPTION_URI_HOST:
00754         coap_pkt->uri_host = current_option;
00755         coap_pkt->uri_host_len = option_length;
00756         PRINTF("Uri-Host [%.*s]\n", coap_pkt->uri_host_len, coap_pkt->uri_host);
00757         break;
00758       case COAP_OPTION_URI_PORT:
00759         coap_pkt->uri_port = coap_parse_int_option(current_option, option_length);
00760         PRINTF("Uri-Port [%u]\n", coap_pkt->uri_port);
00761         break;
00762       case COAP_OPTION_URI_PATH:
00763         /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */
00764         // coap_merge_multi_option( (char **) &(coap_pkt->uri_path), &(coap_pkt->uri_path_len), current_option, option_length, 0);
00765         coap_add_multi_option( &(coap_pkt->uri_path), current_option, option_length, 1);
00766         PRINTF("Uri-Path [%.*s]\n", option_length, current_option);
00767         break;
00768       case COAP_OPTION_URI_QUERY:
00769         /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */
00770         // coap_merge_multi_option( (char **) &(coap_pkt->uri_query), &(coap_pkt->uri_query_len), current_option, option_length, '&');
00771         coap_add_multi_option( &(coap_pkt->uri_query), current_option, option_length, 1);
00772         PRINTF("Uri-Query [%.*s]\n", option_length, current_option);
00773         break;
00774 
00775       case COAP_OPTION_LOCATION_PATH:
00776         coap_add_multi_option( &(coap_pkt->location_path), current_option, option_length, 1);
00777         break;
00778       case COAP_OPTION_LOCATION_QUERY:
00779         /* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */
00780         coap_merge_multi_option( &(coap_pkt->location_query), &(coap_pkt->location_query_len), current_option, option_length, '&');
00781         PRINTF("Location-Query [%.*s]\n", option_length, current_option);
00782         break;
00783 
00784       case COAP_OPTION_PROXY_URI:
00785         /*FIXME check for own end-point */
00786         coap_pkt->proxy_uri = current_option;
00787         coap_pkt->proxy_uri_len = option_length;
00788         /*TODO length > 270 not implemented (actually not required) */
00789         PRINTF("Proxy-Uri NOT IMPLEMENTED [%.*s]\n", coap_pkt->proxy_uri_len, coap_pkt->proxy_uri);
00790         coap_error_message = "This is a constrained server (Contiki)";
00791         return PROXYING_NOT_SUPPORTED_5_05;
00792         break;
00793 
00794       case COAP_OPTION_OBSERVE:
00795         coap_pkt->observe = coap_parse_int_option(current_option, option_length);
00796         PRINTF("Observe [%lu]\n", coap_pkt->observe);
00797         break;
00798       case COAP_OPTION_BLOCK2:
00799         coap_pkt->block2_num = coap_parse_int_option(current_option, option_length);
00800         coap_pkt->block2_more = (coap_pkt->block2_num & 0x08)>>3;
00801         coap_pkt->block2_size = 16 << (coap_pkt->block2_num & 0x07);
00802         coap_pkt->block2_offset = (coap_pkt->block2_num & ~0x0000000F)<<(coap_pkt->block2_num & 0x07);
00803         coap_pkt->block2_num >>= 4;
00804         PRINTF("Block2 [%lu%s (%u B/blk)]\n", coap_pkt->block2_num, coap_pkt->block2_more ? "+" : "", coap_pkt->block2_size);
00805         break;
00806       case COAP_OPTION_BLOCK1:
00807         coap_pkt->block1_num = coap_parse_int_option(current_option, option_length);
00808         coap_pkt->block1_more = (coap_pkt->block1_num & 0x08)>>3;
00809         coap_pkt->block1_size = 16 << (coap_pkt->block1_num & 0x07);
00810         coap_pkt->block1_offset = (coap_pkt->block1_num & ~0x0000000F)<<(coap_pkt->block1_num & 0x07);
00811         coap_pkt->block1_num >>= 4;
00812         PRINTF("Block1 [%lu%s (%u B/blk)]\n", coap_pkt->block1_num, coap_pkt->block1_more ? "+" : "", coap_pkt->block1_size);
00813         break;
00814       case COAP_OPTION_SIZE:
00815         coap_pkt->size = coap_parse_int_option(current_option, option_length);
00816         PRINTF("Size [%lu]\n", coap_pkt->size);
00817         break;
00818       default:
00819         PRINTF("unknown (%u)\n", option_number);
00820         /* Check if critical (odd) */
00821         if (option_number & 1)
00822         {
00823           coap_error_message = "Unsupported critical option";
00824           return BAD_OPTION_4_02;
00825         }
00826     }
00827 
00828     current_option += option_length;
00829   } /* for */
00830   PRINTF("-Done parsing-------\n");
00831 
00832 
00833 
00834   return NO_ERROR;
00835 }
00836 /*-----------------------------------------------------------------------------------*/
00837 /*- REST FRAMEWORK FUNCTIONS --------------------------------------------------------*/
00838 /*-----------------------------------------------------------------------------------*/
00839 int
00840 coap_get_query_variable(void *packet, const char *name, const char **output)
00841 {
00842 /*
00843   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
00844 
00845   if (IS_OPTION(coap_pkt, COAP_OPTION_URI_QUERY)) {
00846     return coap_get_variable(coap_pkt->uri_query, coap_pkt->uri_query_len, name, output);
00847   }
00848 */
00849   return 0;
00850 }
00851 
00852 int
00853 coap_get_post_variable(void *packet, const char *name, const char **output)
00854 {
00855   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
00856 
00857   if (coap_pkt->payload_len) {
00858     return coap_get_variable(coap_pkt->payload, coap_pkt->payload_len, name, output);
00859   }
00860   return 0;
00861 }
00862 /*-----------------------------------------------------------------------------------*/
00863 int
00864 coap_set_status_code(void *packet, unsigned int code)
00865 {
00866   if (code <= 0xFF)
00867   {
00868     ((coap_packet_t *)packet)->code = (uint8_t) code;
00869     return 1;
00870   }
00871   else
00872   {
00873     return 0;
00874   }
00875 }
00876 /*-----------------------------------------------------------------------------------*/
00877 /*- HEADER OPTION GETTERS AND SETTERS -----------------------------------------------*/
00878 /*-----------------------------------------------------------------------------------*/
00879 unsigned int
00880 coap_get_header_content_type(void *packet)
00881 {
00882   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
00883 
00884   if (!IS_OPTION(coap_pkt, COAP_OPTION_CONTENT_TYPE)) return -1;
00885 
00886   return coap_pkt->content_type;
00887 }
00888 
00889 int
00890 coap_set_header_content_type(void *packet, unsigned int content_type)
00891 {
00892   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
00893 
00894   coap_pkt->content_type = (coap_content_type_t) content_type;
00895   SET_OPTION(coap_pkt, COAP_OPTION_CONTENT_TYPE);
00896   return 1;
00897 }
00898 /*-----------------------------------------------------------------------------------*/
00899 int
00900 coap_get_header_accept(void *packet, const uint16_t **accept)
00901 {
00902   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
00903 
00904   if (!IS_OPTION(coap_pkt, COAP_OPTION_ACCEPT)) return 0;
00905 
00906   *accept = coap_pkt->accept;
00907   return coap_pkt->accept_num;
00908 }
00909 
00910 int
00911 coap_set_header_accept(void *packet, uint16_t accept)
00912 {
00913   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
00914 
00915   if (coap_pkt->accept_num < COAP_MAX_ACCEPT_NUM)
00916   {
00917     coap_pkt->accept[coap_pkt->accept_num] = accept;
00918     coap_pkt->accept_num += 1;
00919 
00920     SET_OPTION(coap_pkt, COAP_OPTION_ACCEPT);
00921   }
00922   return coap_pkt->accept_num;
00923 }
00924 /*-----------------------------------------------------------------------------------*/
00925 int
00926 coap_get_header_max_age(void *packet, uint32_t *age)
00927 {
00928   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
00929 
00930   if (!IS_OPTION(coap_pkt, COAP_OPTION_MAX_AGE)) {
00931     *age = COAP_DEFAULT_MAX_AGE;
00932   } else {
00933     *age = coap_pkt->max_age;
00934   }
00935   return 1;
00936 }
00937 
00938 int
00939 coap_set_header_max_age(void *packet, uint32_t age)
00940 {
00941   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
00942 
00943   coap_pkt->max_age = age;
00944   SET_OPTION(coap_pkt, COAP_OPTION_MAX_AGE);
00945   return 1;
00946 }
00947 /*-----------------------------------------------------------------------------------*/
00948 int
00949 coap_get_header_etag(void *packet, const uint8_t **etag)
00950 {
00951   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
00952 
00953   if (!IS_OPTION(coap_pkt, COAP_OPTION_ETAG)) return 0;
00954 
00955   *etag = coap_pkt->etag;
00956   return coap_pkt->etag_len;
00957 }
00958 
00959 int
00960 coap_set_header_etag(void *packet, const uint8_t *etag, size_t etag_len)
00961 {
00962   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
00963 
00964   coap_pkt->etag_len = (uint8_t)(MIN(COAP_ETAG_LEN, etag_len));
00965   memcpy(coap_pkt->etag, etag, coap_pkt->etag_len);
00966 
00967   SET_OPTION(coap_pkt, COAP_OPTION_ETAG);
00968   return coap_pkt->etag_len;
00969 }
00970 /*-----------------------------------------------------------------------------------*/
00971 /*FIXME support multiple ETags */
00972 int
00973 coap_get_header_if_match(void *packet, const uint8_t **etag)
00974 {
00975   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
00976 
00977   if (!IS_OPTION(coap_pkt, COAP_OPTION_IF_MATCH)) return 0;
00978 
00979   *etag = coap_pkt->if_match;
00980   return coap_pkt->if_match_len;
00981 }
00982 
00983 int
00984 coap_set_header_if_match(void *packet, const uint8_t *etag, size_t etag_len)
00985 {
00986   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
00987 
00988   coap_pkt->if_match_len = (uint8_t)(MIN(COAP_ETAG_LEN, etag_len));
00989   memcpy(coap_pkt->if_match, etag, coap_pkt->if_match_len);
00990 
00991   SET_OPTION(coap_pkt, COAP_OPTION_IF_MATCH);
00992   return coap_pkt->if_match_len;
00993 }
00994 /*-----------------------------------------------------------------------------------*/
00995 int
00996 coap_get_header_if_none_match(void *packet)
00997 {
00998   return IS_OPTION((coap_packet_t *)packet, COAP_OPTION_IF_NONE_MATCH) ? 1 : 0;
00999 }
01000 
01001 int
01002 coap_set_header_if_none_match(void *packet)
01003 {
01004   SET_OPTION((coap_packet_t *)packet, COAP_OPTION_IF_NONE_MATCH);
01005   return 1;
01006 }
01007 /*-----------------------------------------------------------------------------------*/
01008 int
01009 coap_get_header_token(void *packet, const uint8_t **token)
01010 {
01011   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01012 
01013   if (!IS_OPTION(coap_pkt, COAP_OPTION_TOKEN)) return 0;
01014 
01015   *token = coap_pkt->token;
01016   return coap_pkt->token_len;
01017 }
01018 
01019 int
01020 coap_set_header_token(void *packet, const uint8_t *token, size_t token_len)
01021 {
01022   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01023 
01024   coap_pkt->token_len = (uint8_t)(MIN(COAP_TOKEN_LEN, token_len));
01025   memcpy(coap_pkt->token, token, coap_pkt->token_len);
01026 
01027   SET_OPTION(coap_pkt, COAP_OPTION_TOKEN);
01028   return coap_pkt->token_len;
01029 }
01030 /*-----------------------------------------------------------------------------------*/
01031 int
01032 coap_get_header_proxy_uri(void *packet, const char **uri)
01033 {
01034   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01035 
01036   if (!IS_OPTION(coap_pkt, COAP_OPTION_PROXY_URI)) return 0;
01037 
01038   *uri = (const char *)coap_pkt->proxy_uri;
01039   return coap_pkt->proxy_uri_len;
01040 }
01041 
01042 int
01043 coap_set_header_proxy_uri(void *packet, const char *uri)
01044 {
01045   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01046 
01047   coap_pkt->proxy_uri = (uint8_t *)uri;
01048   coap_pkt->proxy_uri_len = strlen(uri);
01049 
01050   SET_OPTION(coap_pkt, COAP_OPTION_PROXY_URI);
01051   return coap_pkt->proxy_uri_len;
01052 }
01053 /*-----------------------------------------------------------------------------------*/
01054 int
01055 coap_get_header_uri_host(void *packet, const char **host)
01056 {
01057   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01058 
01059   if (!IS_OPTION(coap_pkt, COAP_OPTION_URI_HOST)) return 0;
01060 
01061   *host = (char *)coap_pkt->uri_host;
01062   return coap_pkt->uri_host_len;
01063 }
01064 
01065 int
01066 coap_set_header_uri_host(void *packet, const char *host)
01067 {
01068   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01069 
01070   coap_pkt->uri_host = (uint8_t *)host;
01071   coap_pkt->uri_host_len = strlen(host);
01072 
01073   SET_OPTION(coap_pkt, COAP_OPTION_URI_HOST);
01074   return coap_pkt->uri_host_len;
01075 }
01076 /*-----------------------------------------------------------------------------------*/
01077 int
01078 coap_get_header_uri_path(void *packet, const char **path)
01079 {
01080   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01081 
01082   if (!IS_OPTION(coap_pkt, COAP_OPTION_URI_PATH)) return 0;
01083 
01084   *path = NULL; //coap_pkt->uri_path;
01085   return 0; //coap_pkt->uri_path_len;
01086 }
01087 
01088 int
01089 coap_set_header_uri_path(void *packet, const char *path)
01090 {
01091   coap_packet_t *coap_pkt = (coap_packet_t *) packet;
01092   int length = 0;
01093 
01094   free_multi_option(coap_pkt->uri_path);
01095   coap_pkt->uri_path = NULL;
01096 
01097   if (path[0]=='/') ++path;
01098 
01099   do
01100   {
01101       int i = 0;
01102 
01103       while (path[i] != 0 && path[i] != '/') i++;
01104       coap_add_multi_option(&(coap_pkt->uri_path), (uint8_t *)path, i, 0);
01105 
01106       if (path[i] == '/') i++;
01107       path += i;
01108       length += i;
01109   } while (path[0] != 0);
01110 
01111   SET_OPTION(coap_pkt, COAP_OPTION_URI_PATH);
01112   return length;
01113 }
01114 
01115 int
01116 coap_set_header_uri_path_segment(void *packet, const char *segment)
01117 {
01118   coap_packet_t *coap_pkt = (coap_packet_t *) packet;
01119   int length;
01120 
01121   if (segment == NULL || segment[0] == 0)
01122   {
01123       coap_add_multi_option(&(coap_pkt->uri_path), NULL, 0, 1);
01124       length = 0;
01125   }
01126   else
01127   {
01128       length = strlen(segment);
01129       coap_add_multi_option(&(coap_pkt->uri_path), (uint8_t *)segment, length, 0);
01130   }
01131 
01132   SET_OPTION(coap_pkt, COAP_OPTION_URI_PATH);
01133   return length;
01134 }
01135 /*-----------------------------------------------------------------------------------*/
01136 int
01137 coap_get_header_uri_query(void *packet, const char **query)
01138 {
01139   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01140 
01141   if (!IS_OPTION(coap_pkt, COAP_OPTION_URI_QUERY)) return 0;
01142 
01143   *query = NULL; //coap_pkt->uri_query;
01144   return 0; //coap_pkt->uri_query_len;
01145 }
01146 
01147 int
01148 coap_set_header_uri_query(void *packet, const char *query)
01149 {
01150     int length = 0;
01151     coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01152 
01153     free_multi_option(coap_pkt->uri_query);
01154     coap_pkt->uri_query = NULL;
01155 
01156     if (query[0]=='?') ++query;
01157 
01158     do
01159     {
01160         int i = 0;
01161 
01162         while (query[i] != 0 && query[i] != '&') i++;
01163         coap_add_multi_option(&(coap_pkt->uri_query), (uint8_t *)query, i, 0);
01164 
01165         if (query[i] == '&') i++;
01166         query += i;
01167         length += i;
01168     } while (query[0] != 0);
01169 
01170     SET_OPTION(coap_pkt, COAP_OPTION_URI_QUERY);
01171     return length;
01172  }
01173 /*-----------------------------------------------------------------------------------*/
01174 int
01175 coap_get_header_location_path(void *packet, const char **path)
01176 {
01177   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01178 
01179   if (!IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_PATH)) return 0;
01180 
01181   *path = NULL; //coap_pkt->location_path;
01182   return 0; //coap_pkt->location_path_len;
01183 }
01184 
01185 int
01186 coap_set_header_location_path(void *packet, const char *path)
01187 {
01188     coap_packet_t *coap_pkt = (coap_packet_t *) packet;
01189     int length = 0;
01190 
01191     free_multi_option(coap_pkt->location_path);
01192     coap_pkt->location_path = NULL;
01193 
01194     if (path[0]=='/') ++path;
01195 
01196     do
01197     {
01198         int i = 0;
01199 
01200         while (path[i] != 0 && path[i] != '/') i++;
01201         coap_add_multi_option(&(coap_pkt->location_path), (uint8_t *)path, i, 0);
01202 
01203         if (path[i] == '/') i++;
01204         path += i;
01205         length += i;
01206     } while (path[0] != 0);
01207 
01208     SET_OPTION(coap_pkt, COAP_OPTION_LOCATION_PATH);
01209     return length;
01210 }
01211 /*-----------------------------------------------------------------------------------*/
01212 int
01213 coap_get_header_location_query(void *packet, const char **query)
01214 {
01215   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01216 
01217   if (!IS_OPTION(coap_pkt, COAP_OPTION_LOCATION_QUERY)) return 0;
01218 
01219   *query = (const char*)coap_pkt->location_query;
01220   return coap_pkt->location_query_len;
01221 }
01222 
01223 int
01224 coap_set_header_location_query(void *packet, char *query)
01225 {
01226   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01227 
01228   while (query[0]=='?') ++query;
01229 
01230   coap_pkt->location_query = (uint8_t *)query;
01231   coap_pkt->location_query_len = strlen(query);
01232 
01233   SET_OPTION(coap_pkt, COAP_OPTION_LOCATION_QUERY);
01234   return coap_pkt->location_query_len;
01235 }
01236 /*-----------------------------------------------------------------------------------*/
01237 int
01238 coap_get_header_observe(void *packet, uint32_t *observe)
01239 {
01240   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01241 
01242   if (!IS_OPTION(coap_pkt, COAP_OPTION_OBSERVE)) return 0;
01243 
01244   *observe = coap_pkt->observe;
01245   return 1;
01246 }
01247 
01248 int
01249 coap_set_header_observe(void *packet, uint32_t observe)
01250 {
01251   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01252 
01253   coap_pkt->observe = 0x00FFFFFF & observe;
01254   SET_OPTION(coap_pkt, COAP_OPTION_OBSERVE);
01255   return 1;
01256 }
01257 /*-----------------------------------------------------------------------------------*/
01258 int
01259 coap_get_header_block2(void *packet, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset)
01260 {
01261   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01262 
01263   if (!IS_OPTION(coap_pkt, COAP_OPTION_BLOCK2)) return 0;
01264 
01265   /* pointers may be NULL to get only specific block parameters */
01266   if (num!=NULL) *num = coap_pkt->block2_num;
01267   if (more!=NULL) *more = coap_pkt->block2_more;
01268   if (size!=NULL) *size = coap_pkt->block2_size;
01269   if (offset!=NULL) *offset = coap_pkt->block2_offset;
01270 
01271   return 1;
01272 }
01273 
01274 int
01275 coap_set_header_block2(void *packet, uint32_t num, uint8_t more, uint16_t size)
01276 {
01277   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01278 
01279   if (size<16) return 0;
01280   if (size>2048) return 0;
01281   if (num>0x0FFFFF) return 0;
01282 
01283   coap_pkt->block2_num = num;
01284   coap_pkt->block2_more = more ? 1 : 0;
01285   coap_pkt->block2_size = size;
01286 
01287   SET_OPTION(coap_pkt, COAP_OPTION_BLOCK2);
01288   return 1;
01289 }
01290 /*-----------------------------------------------------------------------------------*/
01291 int
01292 coap_get_header_block1(void *packet, uint32_t *num, uint8_t *more, uint16_t *size, uint32_t *offset)
01293 {
01294   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01295 
01296   if (!IS_OPTION(coap_pkt, COAP_OPTION_BLOCK1)) return 0;
01297 
01298   /* pointers may be NULL to get only specific block parameters */
01299   if (num!=NULL) *num = coap_pkt->block1_num;
01300   if (more!=NULL) *more = coap_pkt->block1_more;
01301   if (size!=NULL) *size = coap_pkt->block1_size;
01302   if (offset!=NULL) *offset = coap_pkt->block1_offset;
01303 
01304   return 1;
01305 }
01306 
01307 int
01308 coap_set_header_block1(void *packet, uint32_t num, uint8_t more, uint16_t size)
01309 {
01310   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01311 
01312   if (size<16) return 0;
01313   if (size>2048) return 0;
01314   if (num>0x0FFFFF) return 0;
01315 
01316   coap_pkt->block1_num = num;
01317   coap_pkt->block1_more = more;
01318   coap_pkt->block1_size = size;
01319 
01320   SET_OPTION(coap_pkt, COAP_OPTION_BLOCK1);
01321   return 1;
01322 }
01323 /*-----------------------------------------------------------------------------------*/
01324 int
01325 coap_get_header_size(void *packet, uint32_t *size)
01326 {
01327   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01328 
01329   if (!IS_OPTION(coap_pkt, COAP_OPTION_SIZE)) return 0;
01330   
01331   *size = coap_pkt->size;
01332   return 1;
01333 }
01334 
01335 int
01336 coap_set_header_size(void *packet, uint32_t size)
01337 {
01338   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01339 
01340   coap_pkt->size = size;
01341   SET_OPTION(coap_pkt, COAP_OPTION_SIZE);
01342   return 1;
01343 }
01344 /*-----------------------------------------------------------------------------------*/
01345 /*- PAYLOAD -------------------------------------------------------------------------*/
01346 /*-----------------------------------------------------------------------------------*/
01347 int
01348 coap_get_payload(void *packet, const uint8_t **payload)
01349 {
01350   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01351 
01352   if (coap_pkt->payload) {
01353     *payload = coap_pkt->payload;
01354     return coap_pkt->payload_len;
01355   } else {
01356     *payload = NULL;
01357     return 0;
01358   }
01359 }
01360 
01361 int
01362 coap_set_payload(void *packet, const void *payload, size_t length)
01363 {
01364   coap_packet_t *const coap_pkt = (coap_packet_t *) packet;
01365 
01366   coap_pkt->payload = (uint8_t *) payload;
01367   coap_pkt->payload_len = (uint16_t)(length);
01368 
01369   return coap_pkt->payload_len;
01370 }
01371 /*-----------------------------------------------------------------------------------*/