Timothy Beight / Mbed 2 deprecated 6_songs-from-the-cloud

Dependencies:   mbed Socket lwip-eth lwip-sys lwip

Fork of 6_songs-from-the-cloud by MakingMusicWorkshop

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sn_coap_builder.c Source File

sn_coap_builder.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011-2015 ARM Limited. All rights reserved.
00003  * SPDX-License-Identifier: Apache-2.0
00004  * Licensed under the Apache License, Version 2.0 (the License); you may
00005  * not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 /**
00018  * \file sn_coap_builder.c
00019  *
00020  * \brief CoAP Message builder
00021  *
00022  * Functionality: Builds CoAP message
00023  *
00024  */
00025 
00026 /* * * * * * * * * * * * * * */
00027 /* * * * INCLUDE FILES * * * */
00028 /* * * * * * * * * * * * * * */
00029 
00030 #include <string.h> /* For memset() and memcpy() */
00031 
00032 #include "ns_types.h"
00033 #include "sn_nsdl.h"
00034 #include "sn_coap_header.h"
00035 #include "sn_coap_header_internal.h"
00036 #include "sn_coap_protocol_internal.h"
00037 
00038 /* * * * LOCAL FUNCTION PROTOTYPES * * * */
00039 static int8_t   sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr);
00040 static int8_t   sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr);
00041 static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option);
00042 static int16_t  sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_len, uint8_t *option_ptr, sn_coap_option_numbers_e option_number);
00043 static int16_t  sn_coap_builder_options_build_add_zero_length_option(uint8_t **dst_packet_data_pptr, uint8_t option_length, uint8_t option_exist, sn_coap_option_numbers_e option_number);
00044 static int16_t  sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, uint8_t **src_pptr, uint16_t *src_len_ptr, sn_coap_option_numbers_e option);
00045 static uint8_t  sn_coap_builder_options_get_option_part_count(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option);
00046 static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint16_t query_len, uint8_t *query_ptr, uint8_t query_index, sn_coap_option_numbers_e option);
00047 static int16_t  sn_coap_builder_options_get_option_part_position(uint16_t query_len, uint8_t *query_ptr, uint8_t query_index, sn_coap_option_numbers_e option);
00048 static void     sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr);
00049 static uint8_t  sn_coap_builder_options_calculate_jump_need(sn_coap_hdr_s *src_coap_msg_ptr, uint8_t block_option);
00050 
00051 /* * * * GLOBAL DECLARATIONS * * * */
00052 static uint16_t global_previous_option_number = 0;      /* Previous Option number in CoAP message */
00053 
00054 /* * * * EXTERN VARIABLES * * * */
00055 #if SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE
00056 extern uint16_t     sn_coap_block_data_size;                /* From sn_coap_protocol_ieft_draft_12.c */
00057 #endif
00058 
00059 sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code)
00060 {
00061     sn_coap_hdr_s *coap_res_ptr;
00062 
00063     if (!coap_packet_ptr || !handle) {
00064         return NULL;
00065     }
00066 
00067     coap_res_ptr = handle->sn_coap_protocol_malloc(sizeof(sn_coap_hdr_s));
00068     if (!coap_res_ptr) {
00069         return NULL;
00070     }
00071 
00072     memset(coap_res_ptr, 0x00, sizeof(sn_coap_hdr_s));
00073 
00074     if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) {
00075         coap_res_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
00076         coap_res_ptr->msg_code = (sn_coap_msg_code_e)msg_code;
00077         coap_res_ptr->msg_id = coap_packet_ptr->msg_id;
00078     }
00079 
00080     else if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_NON_CONFIRMABLE) {
00081         coap_res_ptr->msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE;
00082         coap_res_ptr->msg_code = (sn_coap_msg_code_e)msg_code;
00083         /* msg_id needs to be set by the caller in this case */
00084     }
00085 
00086     else {
00087         handle->sn_coap_protocol_free( coap_res_ptr );
00088         return NULL;
00089     }
00090 
00091     if (coap_packet_ptr->token_ptr) {
00092         coap_res_ptr->token_len = coap_packet_ptr->token_len;
00093         coap_res_ptr->token_ptr = handle->sn_coap_protocol_malloc(coap_res_ptr->token_len);
00094         if (!coap_res_ptr->token_ptr) {
00095             handle->sn_coap_protocol_free(coap_res_ptr);
00096             return NULL;
00097         }
00098         memcpy(coap_res_ptr->token_ptr, coap_packet_ptr->token_ptr, coap_res_ptr->token_len);
00099     }
00100     return coap_res_ptr;
00101 }
00102 
00103 int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr)
00104 {
00105     uint8_t *base_packet_data_ptr = NULL;
00106 
00107     /* * * * Check given pointers  * * * */
00108     if (dst_packet_data_ptr == NULL || src_coap_msg_ptr == NULL) {
00109         return -2;
00110     }
00111 
00112     /* Initialize given Packet data memory area with zero values */
00113     uint16_t dst_byte_count_to_be_built = sn_coap_builder_calc_needed_packet_data_size(src_coap_msg_ptr);
00114 
00115     if (!dst_byte_count_to_be_built) {
00116         return -1;
00117     }
00118 
00119     memset(dst_packet_data_ptr, 0, dst_byte_count_to_be_built);
00120 
00121     /* * * * Store base (= original) destination Packet data pointer for later usage * * * */
00122     base_packet_data_ptr = dst_packet_data_ptr;
00123 
00124     /* * * * * * * * * * * * * * * * * * */
00125     /* * * * Header part building  * * * */
00126     /* * * * * * * * * * * * * * * * * * */
00127     if (sn_coap_builder_header_build(&dst_packet_data_ptr, src_coap_msg_ptr) != 0) {
00128         /* Header building failed */
00129         return -1;
00130     }
00131 
00132     /* If else than Reset message because Reset message must be empty */
00133     if (src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_RESET) {
00134         /* * * * * * * * * * * * * * * * * * */
00135         /* * * * Options part building * * * */
00136         /* * * * * * * * * * * * * * * * * * */
00137         sn_coap_builder_options_build(&dst_packet_data_ptr, src_coap_msg_ptr);
00138 
00139         /* * * * * * * * * * * * * * * * * * */
00140         /* * * * Payload part building * * * */
00141         /* * * * * * * * * * * * * * * * * * */
00142         sn_coap_builder_payload_build(&dst_packet_data_ptr, src_coap_msg_ptr);
00143     }
00144 
00145     /* * * * Return built Packet data length * * * */
00146     return (dst_packet_data_ptr - base_packet_data_ptr);
00147 }
00148 
00149 uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_msg_ptr)
00150 {
00151     uint16_t returned_byte_count = 0;
00152 
00153     if (!src_coap_msg_ptr) {
00154         return 0;
00155     }
00156 
00157     /* * * * *  HEADER * * * * */
00158 
00159     /* Header size is fixed */
00160     returned_byte_count = COAP_HEADER_LENGTH;
00161 
00162     /* * * * * OPTIONS * * * * */
00163 
00164     /* If else than Reset message because Reset message must be empty */
00165     if (src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_RESET) {
00166         uint16_t repeatable_option_size = 0;
00167 
00168         /* TOKEN - Length is 1-8 bytes */
00169         if (src_coap_msg_ptr->token_ptr != NULL) {
00170             if (src_coap_msg_ptr->token_len > 8 || src_coap_msg_ptr->token_len < 1) { /* Check that option is not longer than defined */
00171                 return 0;
00172             }
00173 
00174             returned_byte_count += src_coap_msg_ptr->token_len;
00175         }
00176 
00177         /* URI PATH - Repeatable option. Length of one option is 0-255 */
00178         if (src_coap_msg_ptr->uri_path_ptr != NULL) {
00179             repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->uri_path_len,
00180                                      src_coap_msg_ptr->uri_path_ptr, COAP_OPTION_URI_PATH);
00181             if (repeatable_option_size) {
00182                 returned_byte_count += repeatable_option_size;
00183             } else {
00184                 return 0;
00185             }
00186         }
00187 
00188         /* CONTENT TYPE - Length of this option is 0-2 bytes */
00189         if (src_coap_msg_ptr->content_type_ptr != NULL) {
00190             returned_byte_count++;
00191             if (src_coap_msg_ptr->content_type_len > 2) {
00192                 return 0;
00193             }
00194 
00195             returned_byte_count += src_coap_msg_ptr->content_type_len;
00196         }
00197 
00198         /* If options list pointer exists */
00199         if (src_coap_msg_ptr->options_list_ptr != NULL) {
00200             /* ACCEPT - Repeatable option. Length of this option is 0-2 bytes */
00201             if (src_coap_msg_ptr->options_list_ptr->accept_ptr != NULL) {
00202                 repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->accept_len,
00203                                          src_coap_msg_ptr->options_list_ptr->accept_ptr, COAP_OPTION_ACCEPT);
00204                 if (repeatable_option_size) {
00205                     returned_byte_count += repeatable_option_size;
00206                 } else {
00207                     return 0;
00208                 }
00209             }
00210 
00211             /* MAX AGE - Length of this option is 0-4 bytes */
00212             if (src_coap_msg_ptr->options_list_ptr->max_age_ptr != NULL) {
00213                 returned_byte_count++;
00214                 if (src_coap_msg_ptr->options_list_ptr->max_age_len > 4) {
00215                     return 0;
00216                 }
00217 
00218                 returned_byte_count += src_coap_msg_ptr->options_list_ptr->max_age_len;
00219             }
00220 
00221             /* PROXY URI - Length of this option is  1-1034 bytes */
00222             if (src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr != NULL) {
00223                 if (src_coap_msg_ptr->options_list_ptr->proxy_uri_len >= 1 && src_coap_msg_ptr->options_list_ptr->proxy_uri_len <= 12) {            /* Add option header byte(s) - depending of option length */
00224                     returned_byte_count++;
00225                 }
00226 
00227                 else if (src_coap_msg_ptr->options_list_ptr->proxy_uri_len >= 13 && src_coap_msg_ptr->options_list_ptr->proxy_uri_len <= 269) {
00228                     returned_byte_count += 2;
00229                 }
00230 
00231                 else if (src_coap_msg_ptr->options_list_ptr->proxy_uri_len >= 270 && src_coap_msg_ptr->options_list_ptr->proxy_uri_len <= 1034) {
00232                     returned_byte_count += 3;
00233                 }
00234 
00235                 else {
00236                     return 0;
00237                 }
00238 
00239                 /* Add needed memory for Option value */
00240                 returned_byte_count += src_coap_msg_ptr->options_list_ptr->proxy_uri_len;
00241             }
00242 
00243             /* ETAG - Repeatable option. Length of this option is 1-8 bytes*/
00244             if (src_coap_msg_ptr->options_list_ptr->etag_ptr != NULL) {
00245                 repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->etag_len,
00246                                          src_coap_msg_ptr->options_list_ptr->etag_ptr, COAP_OPTION_ETAG);
00247                 if (repeatable_option_size) {
00248                     returned_byte_count += repeatable_option_size;
00249                 } else {
00250                     return 0;
00251                 }
00252             }
00253 
00254             /* URI HOST - Length of this option is 1-255 bytes */
00255             if (src_coap_msg_ptr->options_list_ptr->uri_host_ptr != NULL) {
00256                 if (src_coap_msg_ptr->options_list_ptr->uri_host_len > 0 && src_coap_msg_ptr->options_list_ptr->uri_host_len <= 12) {
00257                     returned_byte_count++;
00258                 }
00259 
00260                 else if (src_coap_msg_ptr->options_list_ptr->uri_host_len >= 13 && src_coap_msg_ptr->options_list_ptr->uri_host_len <= 255) {
00261                     returned_byte_count += 2;
00262                 }
00263 
00264                 else {
00265                     return 0;
00266                 }
00267 
00268                 returned_byte_count += src_coap_msg_ptr->options_list_ptr->uri_host_len;
00269             }
00270 
00271             /* LOCATION PATH - Repeatable option. Length of this option is 0-255 bytes*/
00272             if (src_coap_msg_ptr->options_list_ptr->location_path_ptr != NULL) {
00273                 repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->location_path_len,
00274                                          src_coap_msg_ptr->options_list_ptr->location_path_ptr, COAP_OPTION_LOCATION_PATH);
00275                 if (repeatable_option_size) {
00276                     returned_byte_count += repeatable_option_size;
00277                 } else {
00278                     return 0;
00279                 }
00280             }
00281 
00282             /* URI PORT - Length of this option is 0-2 bytes */
00283             if (src_coap_msg_ptr->options_list_ptr->uri_port_ptr != NULL) {
00284                 returned_byte_count++;
00285                 if (src_coap_msg_ptr->options_list_ptr->uri_port_len > 2) {
00286                     return 0;
00287                 }
00288 
00289                 returned_byte_count += src_coap_msg_ptr->options_list_ptr->uri_port_len;
00290             }
00291 
00292             /* lOCATION QUERY - Repeatable option. Length of this option is 0-255 bytes */
00293             if (src_coap_msg_ptr->options_list_ptr->location_query_ptr != NULL) {
00294                 repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->location_query_len,
00295                                          src_coap_msg_ptr->options_list_ptr->location_query_ptr, COAP_OPTION_LOCATION_QUERY);
00296                 if (repeatable_option_size) {
00297                     returned_byte_count += repeatable_option_size;
00298                 } else {
00299                     return 0;
00300                 }
00301             }
00302 
00303             /* OBSERVE - Length of this option is 0-3 bytes */
00304             if (src_coap_msg_ptr->options_list_ptr->observe_ptr != NULL) {
00305                 returned_byte_count++;
00306                 if (src_coap_msg_ptr->options_list_ptr->observe_len > 3) {
00307                     return 0;
00308                 }
00309 
00310                 returned_byte_count += src_coap_msg_ptr->options_list_ptr->observe_len;
00311             } else if (src_coap_msg_ptr->options_list_ptr->observe) {
00312                 returned_byte_count++;
00313             }
00314 
00315             /* URI QUERY - Repeatable option. Length of this option is 1-255 */
00316             if (src_coap_msg_ptr->options_list_ptr->uri_query_ptr != NULL) {
00317                 repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->uri_query_len,
00318                                          src_coap_msg_ptr->options_list_ptr->uri_query_ptr, COAP_OPTION_URI_QUERY);
00319                 if (repeatable_option_size) {
00320                     returned_byte_count += repeatable_option_size;
00321                 } else {
00322                     return 0;
00323                 }
00324             }
00325 
00326             /* BLOCK 1 - Length of this option is 1-3 bytes*/
00327             if (src_coap_msg_ptr->options_list_ptr->block2_ptr != NULL) {
00328                 returned_byte_count++;
00329                 if (src_coap_msg_ptr->options_list_ptr->block2_len > 3 || src_coap_msg_ptr->options_list_ptr->block2_len < 1) {
00330                     return 0;
00331                 }
00332 
00333                 returned_byte_count += src_coap_msg_ptr->options_list_ptr->block2_len;
00334             }
00335 
00336             /* BLOCK 2 - Length of this option is 1-3 bytes*/
00337             if (src_coap_msg_ptr->options_list_ptr->block1_ptr != NULL) {
00338                 returned_byte_count++;
00339 
00340                 if (src_coap_msg_ptr->options_list_ptr->block1_len > 3 || src_coap_msg_ptr->options_list_ptr->block1_len < 1) {
00341                     return 0;
00342                 }
00343 
00344                 returned_byte_count += src_coap_msg_ptr->options_list_ptr->block1_len;
00345             }
00346         }
00347 
00348         /* * * * * PAYLOAD * * * * */
00349 #if SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */
00350         if ((src_coap_msg_ptr->payload_len > sn_coap_block_data_size) && (sn_coap_block_data_size > 0)) {
00351             /* Two bytes for Block option */
00352             returned_byte_count += 2;
00353 
00354             if (src_coap_msg_ptr->msg_code < COAP_MSG_CODE_RESPONSE_CREATED) {
00355                 returned_byte_count += sn_coap_builder_options_calculate_jump_need(src_coap_msg_ptr, 1);
00356             } else { /* Response message */
00357                 returned_byte_count += sn_coap_builder_options_calculate_jump_need(src_coap_msg_ptr, 2);
00358             }
00359             /* Add maximum payload at one Blockwise message */
00360             returned_byte_count += sn_coap_block_data_size;
00361             returned_byte_count ++;                 /* For payload marker */
00362         } else {
00363             returned_byte_count += sn_coap_builder_options_calculate_jump_need(src_coap_msg_ptr, 0);
00364             /* Add wanted payload */
00365 
00366             returned_byte_count += src_coap_msg_ptr->payload_len;
00367 
00368             if (src_coap_msg_ptr->payload_len) {
00369                 returned_byte_count ++;    /* For payload marker */
00370             }
00371 
00372         }
00373 #else
00374         returned_byte_count += src_coap_msg_ptr->payload_len;
00375         if (src_coap_msg_ptr->payload_len) {
00376             returned_byte_count ++;    /* For payload marker */
00377         }
00378         returned_byte_count += sn_coap_builder_options_calculate_jump_need(src_coap_msg_ptr, 0);
00379 #endif
00380     }
00381 
00382     return returned_byte_count;
00383 }
00384 
00385 /**
00386  * \fn static uint8_t sn_coap_builder_options_calculate_jump_need(sn_coap_hdr_s *src_coap_msg_ptr, uint8_t block_option)
00387  *
00388  * \brief Checks if there is need for option jump
00389  *
00390  * \param  *src_coap_msg_ptr is source of checked CoAP message
00391  *
00392  * \param  block option marks if block option is to be added to message later. 0 = no block option, 1 = block1 and 2 = block2
00393  *
00394  * \return Returns bytes needed for jumping
00395  */
00396 
00397 static uint8_t sn_coap_builder_options_calculate_jump_need(sn_coap_hdr_s *src_coap_msg_ptr, uint8_t block_option)
00398 {
00399     uint8_t previous_option_number = 0;
00400     uint8_t needed_space           = 0;
00401 
00402     if (src_coap_msg_ptr->options_list_ptr != NULL) {
00403         /* If option numbers greater than 12 is not used, then jumping is not needed */
00404         if (!src_coap_msg_ptr->options_list_ptr->uri_query_ptr       &&
00405                 !src_coap_msg_ptr->options_list_ptr->accept_ptr         &&
00406                 !src_coap_msg_ptr->options_list_ptr->location_query_ptr &&
00407                 !src_coap_msg_ptr->options_list_ptr->block2_ptr         &&
00408                 !src_coap_msg_ptr->options_list_ptr->block1_ptr         &&
00409                 !src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr      &&
00410                 !block_option                                           &&
00411                 !src_coap_msg_ptr->options_list_ptr->max_age_ptr) {
00412             return 0;
00413         }
00414 
00415         if (src_coap_msg_ptr->options_list_ptr->uri_host_ptr != NULL) {
00416             previous_option_number = (COAP_OPTION_URI_HOST);
00417         }
00418 
00419         if (src_coap_msg_ptr->options_list_ptr->etag_ptr != NULL) {
00420             previous_option_number = (COAP_OPTION_ETAG);
00421         }
00422 
00423         if ((src_coap_msg_ptr->options_list_ptr->observe_ptr != NULL) || (src_coap_msg_ptr->options_list_ptr->observe)) {
00424             previous_option_number = (COAP_OPTION_OBSERVE);
00425         }
00426 
00427         if (src_coap_msg_ptr->options_list_ptr->uri_port_ptr != NULL) {
00428             previous_option_number = (COAP_OPTION_URI_PORT);
00429         }
00430 
00431         if (src_coap_msg_ptr->options_list_ptr->location_path_ptr != NULL) {
00432             previous_option_number = (COAP_OPTION_LOCATION_PATH);
00433         }
00434 
00435         if (src_coap_msg_ptr->uri_path_ptr != NULL) {
00436             previous_option_number = (COAP_OPTION_URI_PATH);
00437         }
00438         if (src_coap_msg_ptr->content_type_ptr != NULL) {
00439             previous_option_number = (COAP_OPTION_CONTENT_FORMAT);
00440         }
00441         if (src_coap_msg_ptr->options_list_ptr->max_age_ptr != NULL) {
00442             if ((COAP_OPTION_MAX_AGE - previous_option_number) > 12) {
00443                 needed_space += 1;
00444             }
00445             previous_option_number = (COAP_OPTION_MAX_AGE);
00446         }
00447 
00448         if (src_coap_msg_ptr->options_list_ptr->uri_query_ptr != NULL) {
00449             if ((COAP_OPTION_URI_QUERY - previous_option_number) > 12) {
00450                 needed_space += 1;
00451             }
00452             previous_option_number = (COAP_OPTION_URI_QUERY);
00453         }
00454         if (src_coap_msg_ptr->options_list_ptr->accept_ptr != NULL) {
00455             if ((COAP_OPTION_ACCEPT - previous_option_number) > 12) {
00456                 needed_space += 1;
00457             }
00458             previous_option_number = (COAP_OPTION_ACCEPT);
00459         }
00460         if (src_coap_msg_ptr->options_list_ptr->location_query_ptr != NULL) {
00461             if ((COAP_OPTION_LOCATION_QUERY - previous_option_number) > 12) {
00462                 needed_space += 1;
00463             }
00464             previous_option_number = (COAP_OPTION_LOCATION_QUERY);
00465         }
00466         if (src_coap_msg_ptr->options_list_ptr->block2_ptr != NULL) {
00467             if ((COAP_OPTION_BLOCK2 - previous_option_number) > 12 || (block_option == 2 && (COAP_OPTION_BLOCK2 - previous_option_number) > 12)) {
00468                 needed_space += 1;
00469             }
00470             previous_option_number = (COAP_OPTION_BLOCK2);
00471         }
00472         if (src_coap_msg_ptr->options_list_ptr->block1_ptr != NULL) {
00473             if ((COAP_OPTION_BLOCK1 - previous_option_number) > 12 || (block_option == 1 && (COAP_OPTION_BLOCK1 - previous_option_number) > 12)) {
00474                 needed_space += 1;
00475             }
00476             previous_option_number = (COAP_OPTION_BLOCK1);
00477         }
00478         if (src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr != NULL) {
00479             if ((COAP_OPTION_PROXY_URI - previous_option_number) > 12) {
00480                 needed_space += 1;
00481             }
00482             if ((COAP_OPTION_PROXY_URI - previous_option_number) > 269) { //Can not happen
00483                 needed_space += 1;
00484             }
00485             previous_option_number = (COAP_OPTION_PROXY_URI);
00486         }
00487     }
00488 
00489     else {
00490         if (src_coap_msg_ptr->uri_path_ptr != 0) {
00491             previous_option_number = (COAP_OPTION_URI_PATH);
00492         }
00493 
00494         if (src_coap_msg_ptr->content_type_ptr != 0) {
00495             previous_option_number = (COAP_OPTION_CONTENT_FORMAT);
00496         }
00497 
00498 #if SN_COAP_BLOCKWISE_MAX_PAYLOAD_SIZE //block_option 1 & 2 only used if this maro is defined
00499         if (block_option == 2) {
00500             if ((COAP_OPTION_BLOCK2 - previous_option_number) > 12) {
00501                 needed_space += 1;
00502             }
00503             previous_option_number = (COAP_OPTION_BLOCK2);
00504         }
00505         if (block_option == 1) {
00506             if ((COAP_OPTION_BLOCK1 - previous_option_number) > 12) {
00507                 needed_space += 1;
00508             }
00509             previous_option_number = (COAP_OPTION_BLOCK1);
00510         }
00511 #endif
00512     }
00513     return needed_space;
00514 }
00515 
00516 /**
00517  * \fn static int8_t sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr)
00518  *
00519  * \brief Builds Header part of Packet data
00520  *
00521  * \param **dst_packet_data_pptr is destination for built Packet data
00522  *
00523  * \param *src_coap_msg_ptr is source for building Packet data
00524  *
00525  * \return Return value is 0 in ok case and -1 in failure case
00526  **************************************************************************** */
00527 static int8_t sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr)
00528 {
00529     /* * * * Check validity of Header values * * * */
00530     if (sn_coap_header_validity_check(src_coap_msg_ptr, COAP_VERSION) != 0) {
00531         return -1;
00532     }
00533 
00534     /* * * Add CoAP Version * * */
00535     **dst_packet_data_pptr += COAP_VERSION;
00536 
00537     /* * * Add Message type * * */
00538     **dst_packet_data_pptr += src_coap_msg_ptr->msg_type;
00539 
00540     /* * * Add Token length * * */
00541     **dst_packet_data_pptr += (src_coap_msg_ptr->token_len);
00542 
00543     (*dst_packet_data_pptr) ++;
00544     /* * * Add Message code * * */
00545     **dst_packet_data_pptr = src_coap_msg_ptr->msg_code;
00546     (*dst_packet_data_pptr) ++;
00547 
00548     /* * * Add Message ID * * */
00549     **dst_packet_data_pptr = (uint8_t)(src_coap_msg_ptr->msg_id >> COAP_HEADER_MSG_ID_MSB_SHIFT); /* MSB part */
00550     (*dst_packet_data_pptr) ++;
00551     **dst_packet_data_pptr = (uint8_t)src_coap_msg_ptr->msg_id;                                   /* LSB part */
00552     (*dst_packet_data_pptr) ++;
00553 
00554     /* Success */
00555     return 0;
00556 }
00557 
00558 /**
00559  * \fn static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr)
00560  *
00561  * \brief Builds Options part of Packet data
00562  *
00563  * \param **dst_packet_data_pptr is destination for built Packet data
00564  *
00565  * \param *src_coap_msg_ptr is source for building Packet data
00566  *
00567  * \return Return value is 0 in every case
00568  */
00569 static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr)
00570 {
00571     int16_t ret_status = 0;
00572 
00573     /* * * * Check if Options are used at all  * * * */
00574     if (src_coap_msg_ptr->uri_path_ptr == NULL && src_coap_msg_ptr->token_ptr == NULL &&
00575             src_coap_msg_ptr->content_type_ptr == NULL && src_coap_msg_ptr->options_list_ptr == NULL) {
00576         return 0;
00577     }
00578 
00579     /* * * * First add Token option  * * * */
00580     if (src_coap_msg_ptr->token_len && src_coap_msg_ptr->token_ptr) {
00581         memcpy(*dst_packet_data_pptr, src_coap_msg_ptr->token_ptr, src_coap_msg_ptr->token_len);
00582     }
00583     (*dst_packet_data_pptr) += src_coap_msg_ptr->token_len;
00584 
00585     /* Then build rest of the options */
00586 
00587     /* * * * Initialize previous Option number for new built message * * * */
00588     global_previous_option_number = 0;
00589 
00590     //missing: COAP_OPTION_IF_MATCH, COAP_OPTION_IF_NONE_MATCH, COAP_OPTION_SIZE
00591 
00592     /* Check if less used options are used at all */
00593     if (src_coap_msg_ptr->options_list_ptr != NULL) {
00594         /* * * * Build Uri-Host option * * * */
00595         sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->uri_host_len,
00596                      src_coap_msg_ptr->options_list_ptr->uri_host_ptr, COAP_OPTION_URI_HOST);
00597 
00598         /* * * * Build ETag option  * * * */
00599         sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->etag_ptr,
00600                      (uint16_t *)&src_coap_msg_ptr->options_list_ptr->etag_len, COAP_OPTION_ETAG);
00601 
00602         /* * * * Build Observe option  * * * * */
00603         ret_status = sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->observe_len,
00604                      src_coap_msg_ptr->options_list_ptr->observe_ptr, COAP_OPTION_OBSERVE);
00605         if (ret_status == 0) {
00606             sn_coap_builder_options_build_add_zero_length_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->observe_len, src_coap_msg_ptr->options_list_ptr->observe, COAP_OPTION_OBSERVE);
00607         }
00608 
00609         /* * * * Build Uri-Port option * * * */
00610         sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->uri_port_len,
00611                      src_coap_msg_ptr->options_list_ptr->uri_port_ptr, COAP_OPTION_URI_PORT);
00612 
00613         /* * * * Build Location-Path option  * * * */
00614         sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->location_path_ptr,
00615                      &src_coap_msg_ptr->options_list_ptr->location_path_len, COAP_OPTION_LOCATION_PATH);
00616     }
00617     /* * * * Build Uri-Path option * * * */
00618     sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->uri_path_ptr,
00619                  &src_coap_msg_ptr->uri_path_len, COAP_OPTION_URI_PATH);
00620 
00621     /* * * * Build Content-Type option * * * */
00622     sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->content_type_len,
00623                  src_coap_msg_ptr->content_type_ptr, COAP_OPTION_CONTENT_FORMAT);
00624 
00625     if (src_coap_msg_ptr->options_list_ptr != NULL) {
00626         /* * * * Build Max-Age option  * * * */
00627         sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->max_age_len,
00628                      src_coap_msg_ptr->options_list_ptr->max_age_ptr, COAP_OPTION_MAX_AGE);
00629 
00630         /* * * * Build Uri-Query option  * * * * */
00631         sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->uri_query_ptr,
00632                      &src_coap_msg_ptr->options_list_ptr->uri_query_len, COAP_OPTION_URI_QUERY);
00633 
00634         /* * * * Build Accept option  * * * * */
00635         sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->accept_ptr,
00636                      (uint16_t *)&src_coap_msg_ptr->options_list_ptr->accept_len, COAP_OPTION_ACCEPT);
00637     }
00638 
00639     if (src_coap_msg_ptr->options_list_ptr != NULL) {
00640         /* * * * Build Location-Query option * * * */
00641         sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->location_query_ptr,
00642                      &src_coap_msg_ptr->options_list_ptr->location_query_len, COAP_OPTION_LOCATION_QUERY);
00643 
00644         /* * * * Build Block2 option * * * * */
00645         sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->block2_len,
00646                      src_coap_msg_ptr->options_list_ptr->block2_ptr, COAP_OPTION_BLOCK2);
00647 
00648         /* * * * Build Block1 option * * * * */
00649         sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->block1_len,
00650                      src_coap_msg_ptr->options_list_ptr->block1_ptr, COAP_OPTION_BLOCK1);
00651 
00652         /* * * * Build Proxy-Uri option * * * */
00653         sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->proxy_uri_len,
00654                      src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr, COAP_OPTION_PROXY_URI);
00655     }
00656 
00657     /* Success */
00658     return 0;
00659 }
00660 
00661 /**
00662  * \fn static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_value_len, uint8_t *option_value_ptr, sn_coap_option_numbers_e option_number)
00663  *
00664  * \brief Adds Options part of Packet data
00665  *
00666  * \param **dst_packet_data_pptr is destination for built Packet data
00667  *
00668  * \param option_value_len is Option value length to be added
00669  *
00670  * \param *option_value_ptr is pointer to Option value data to be added
00671  *
00672  * \param option_number is Option number to be added
00673  *
00674  * \return Return value is 0 if option was not added, 1 if added
00675  */
00676 static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_len,
00677         uint8_t *option_ptr, sn_coap_option_numbers_e option_number)
00678 {
00679     /* Check if there is option at all */
00680     if (option_ptr != NULL) {
00681         uint16_t option_delta;
00682 
00683         option_delta = (option_number - global_previous_option_number);
00684 
00685         /* * * Build option header * * */
00686 
00687         /* First option length without extended part */
00688         if (option_len <= 12) {
00689             **dst_packet_data_pptr = option_len;
00690         }
00691 
00692         else if (option_len > 12 && option_len < 269) {
00693             **dst_packet_data_pptr = 0x0D;
00694         }
00695 
00696         else if (option_len >= 269) {
00697             **dst_packet_data_pptr = 0x0E;
00698         }
00699 
00700         /* Then option delta with extensions, and move pointer */
00701         if (option_delta <= 12) {
00702             **dst_packet_data_pptr += (option_delta << 4);
00703             *dst_packet_data_pptr += 1;
00704         }
00705 
00706         else if (option_delta > 12 && option_delta < 269) {
00707             **dst_packet_data_pptr += 0xD0;
00708             option_delta -= 13;
00709 
00710             *(*dst_packet_data_pptr + 1) = (uint8_t)option_delta;
00711             *dst_packet_data_pptr += 2;
00712         }
00713         //This is currently dead code (but possibly needed in future)
00714         else if (option_delta >= 269) {
00715             **dst_packet_data_pptr += 0xE0;
00716             option_delta -= 269;
00717 
00718             *(*dst_packet_data_pptr + 2) = (uint8_t)option_delta;
00719             *(*dst_packet_data_pptr + 1) = (option_delta >> 8);
00720             *dst_packet_data_pptr += 3;
00721         }
00722 
00723         /* Now option length extensions, if needed */
00724         if (option_len > 12 && option_len < 269) {
00725             **dst_packet_data_pptr = (uint8_t)(option_len - 13);
00726             *dst_packet_data_pptr += 1;
00727         }
00728 
00729         else if (option_len >= 269) {
00730             *(*dst_packet_data_pptr + 1) = (uint8_t)(option_len - 269);
00731             **dst_packet_data_pptr = ((option_len - 269) >> 8);
00732             *dst_packet_data_pptr += 2;
00733         }
00734 
00735         global_previous_option_number = option_number;
00736 
00737         /* Write Option value */
00738         memcpy(*dst_packet_data_pptr, option_ptr, option_len);
00739 
00740         /* Increase destination Packet data pointer */
00741         (*dst_packet_data_pptr) += option_len;
00742 
00743         return 1;
00744     }
00745 
00746     /* Success */
00747     return 0;
00748 }
00749 
00750 /*
00751  * @return 1 if was added 0 otherwise
00752 */
00753 int16_t sn_coap_builder_options_build_add_zero_length_option(uint8_t **dst_packet_data_pptr, uint8_t option_length, uint8_t option_exist, sn_coap_option_numbers_e option_number)
00754 {
00755     if ((option_exist != 0) && (option_length == 0)) {
00756         uint16_t option_delta;
00757 
00758         option_delta = (option_number - global_previous_option_number);
00759 
00760         /* * * Build option header * * */
00761 
00762         /* First option length without extended part */
00763         **dst_packet_data_pptr = 0;
00764 
00765         /* Then option delta with extensions, and move pointer */
00766         if (option_delta <= 12) {
00767             **dst_packet_data_pptr += (option_delta << 4);
00768             *dst_packet_data_pptr += 1;
00769         }
00770         //Cannot happen currently -->
00771         else if (option_delta > 12 && option_delta < 269) {
00772             **dst_packet_data_pptr += 0xD0;
00773             option_delta -= 13;
00774 
00775             *(*dst_packet_data_pptr + 1) = (uint8_t)option_delta;
00776             *dst_packet_data_pptr += 2;
00777         }
00778 
00779         else if (option_delta >= 269) {
00780             **dst_packet_data_pptr += 0xE0;
00781             option_delta -= 269;
00782 
00783             *(*dst_packet_data_pptr + 2) = (uint8_t)option_delta;
00784             *(*dst_packet_data_pptr + 1) = (option_delta >> 8);
00785             *dst_packet_data_pptr += 3;
00786         }
00787         //<-- Cannot happen currently
00788 
00789         global_previous_option_number = option_number;
00790 
00791         return 1;
00792     }
00793     return 0;
00794 }
00795 
00796 /**
00797  * \fn static int16_t sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, uint8_t **src_pptr, uint16_t *src_len_ptr, sn_coap_option_numbers_e option)
00798  *
00799  * \brief Builds Option Uri-Query from given CoAP Header structure to Packet data
00800  *
00801  * \param **dst_packet_data_pptr is destination for built Packet data
00802  *
00803  * \param uint8_t **src_pptr
00804  *
00805  *  \param uint16_t *src_len_ptr
00806  *
00807  *  \paramsn_coap_option_numbers_e option option to be added
00808  *
00809  * \return Return value is 0 always
00810  */
00811 static int16_t sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, uint8_t **src_pptr, uint16_t *src_len_ptr, sn_coap_option_numbers_e option)
00812 {
00813     /* Check if there is option at all */
00814     if (*src_pptr != NULL) {
00815         uint8_t    *query_ptr               = *src_pptr;
00816         uint8_t     query_part_count        = 0;
00817         uint16_t    query_len               = *src_len_ptr;
00818         uint8_t     i                       = 0;
00819         uint16_t    query_part_offset       = 0;
00820 
00821         /* Get query part count */
00822         query_part_count = sn_coap_builder_options_get_option_part_count(query_len, query_ptr, option);
00823 
00824         /* * * * Options by adding all parts to option * * * */
00825         for (i = 0; i < query_part_count; i++) {
00826             /* Get length of query part */
00827             uint16_t one_query_part_len = sn_coap_builder_options_get_option_part_length_from_whole_option_string(query_len, query_ptr, i, option);
00828 
00829             /* Get position of query part */
00830             query_part_offset = sn_coap_builder_options_get_option_part_position(query_len, query_ptr, i, option);
00831 
00832             /* Add Uri-query's one part to Options */
00833             sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, one_query_part_len, *src_pptr + query_part_offset, option);
00834         }
00835     }
00836     /* Success */
00837     return 0;
00838 }
00839 
00840 
00841 /**
00842  * \fn static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option)
00843  *
00844  * \brief Calculates needed Packet data memory size for option
00845  *
00846  * \param path_len is length of calculated strting(s)
00847  *
00848  * \param *path_ptr is pointer to calculated options
00849  *
00850  * \return Return value is count of needed memory as bytes for Uri-query option
00851  */
00852 static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option)
00853 {
00854     uint8_t     query_part_count    = sn_coap_builder_options_get_option_part_count(query_len, query_ptr, option);
00855     uint8_t     i                   = 0;
00856     uint16_t    ret_value           = 0;
00857 
00858     /* * * * * * * * * * * * * * * * * * * * * * * * */
00859     /* * * * Calculate Uri-query options length  * * */
00860     /* * * * * * * * * * * * * * * * * * * * * * * * */
00861     for (i = 0; i < query_part_count; i++) {
00862         /* * * Length of Option number and Option value length * * */
00863 
00864         /* Get length of Query part */
00865         uint16_t one_query_part_len = sn_coap_builder_options_get_option_part_length_from_whole_option_string(query_len, query_ptr, i, option);
00866 
00867         /* Check option length */
00868         switch (option) {
00869             case (COAP_OPTION_ETAG):            /* Length 1-8 */
00870                 if (one_query_part_len < 1 || one_query_part_len > 8) {
00871                     return 0;
00872                 }
00873                 break;
00874             case (COAP_OPTION_LOCATION_PATH):   /* Length 0-255 */
00875             case (COAP_OPTION_URI_PATH):        /* Length 0-255 */
00876             case (COAP_OPTION_LOCATION_QUERY):  /* Length 0-255 */
00877                 if (one_query_part_len > 255) {
00878                     return 0;
00879                 }
00880                 break;
00881             case (COAP_OPTION_URI_QUERY):       /* Length 1-255 */
00882                 if (one_query_part_len < 1 || one_query_part_len > 255) {
00883                     return 0;
00884                 }
00885                 break;
00886             case (COAP_OPTION_ACCEPT):          /* Length 0-2 */
00887                 if (one_query_part_len > 2) {
00888                     return 0;
00889                 }
00890                 break;
00891             default:
00892                 break; //impossible scenario currently
00893         }
00894 
00895         /* Check if 4 bits are enough for writing Option value length */
00896         if (one_query_part_len <= 12) {
00897             /* 4 bits are enough for Option value length */
00898             ret_value++;
00899         } else if (one_query_part_len >= 13 && one_query_part_len < 269) {
00900             /* Extra byte for Option value length is needed */
00901             ret_value += 2;
00902         }
00903         //This can only happen if we are in default case above, currently is not happening
00904         else if (one_query_part_len >= 270 && one_query_part_len < 1034) {
00905             /* Extra bytes for Option value length is needed */
00906             ret_value += 3;
00907         }
00908 
00909 
00910         /* * * Length of Option value * * */
00911 
00912         /* Increase options length */
00913         ret_value += one_query_part_len;
00914     }
00915 
00916     /* Success */
00917     return ret_value;
00918 }
00919 
00920 
00921 
00922 /**
00923  * \fn static uint8_t sn_coap_builder_options_get_option_part_count(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option)
00924  *
00925  * \brief Gets query part count from whole option string
00926  *
00927  * \param query_len is length of whole Path
00928  *
00929  * \param *query_ptr is pointer to the start of whole Path
00930  *
00931  * \return Return value is count of query parts
00932  */
00933 static uint8_t sn_coap_builder_options_get_option_part_count(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option)
00934 {
00935     uint8_t  returned_query_count = 0;
00936     uint16_t query_len_index      = 0;
00937     uint8_t  char_to_search       = '&';
00938 
00939     if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) {
00940         char_to_search = '/';
00941     }
00942 
00943     /* Loop whole query and search '\0' characters (not first and last char) */
00944     for (query_len_index = 1; query_len_index < query_len - 1; query_len_index++) {
00945         /* If new query part starts */
00946         if (*(query_ptr + query_len_index) == char_to_search) { /* If match */
00947             returned_query_count++;
00948         }
00949     }
00950 
00951     returned_query_count++;
00952 
00953     return returned_query_count;
00954 }
00955 
00956 /**
00957  * \fn static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint16_t query_len,
00958                                                                              uint8_t *query_ptr,
00959                                                                              uint8_t query_index, sn_coap_option_numbers_e option)
00960  *
00961  * \brief Gets one's query part length from whole query string
00962  *
00963  * \param query_len is length of whole string
00964  *
00965  * \param *query_ptr is pointer to the start of whole string
00966  *
00967  * \param query_index is query part index to be found
00968  *
00969  * \param sn_coap_option_numbers_e option is option number of the option
00970  *
00971  * \return Return value is length of query part
00972  */
00973 static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint16_t query_len, uint8_t *query_ptr,
00974         uint8_t query_index, sn_coap_option_numbers_e option)
00975 {
00976     uint16_t returned_query_part_len = 0;
00977     uint8_t  temp_query_index        = 0;
00978     uint16_t query_len_index         = 0;
00979     uint8_t  char_to_search          = '&';
00980 
00981     if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) {
00982         char_to_search = '/';
00983     }
00984 
00985     /* Loop whole query and search '\0' characters */
00986     for (query_len_index = 0; query_len_index < query_len; query_len_index++) {
00987         /* Store character to temp_char for helping debugging */
00988         uint8_t temp_char = *query_ptr;
00989 
00990         /* If new query part starts */
00991         if (temp_char == char_to_search && returned_query_part_len > 0) { /* returned_query_part_len > 0 is for querys which start with "\0" */
00992             /* If query part index is wanted */
00993             if (temp_query_index == query_index) {
00994                 /* Return length of query part */
00995                 return returned_query_part_len;
00996             } else {
00997                 /* Reset length of query part because wanted query part finding continues*/
00998                 returned_query_part_len = 0;
00999             }
01000 
01001             /* Next query part is looped */
01002             temp_query_index++;
01003         } else if (temp_char != char_to_search) { /* Else if query part continues */
01004             /* Increase query part length */
01005             returned_query_part_len++;
01006         }
01007 
01008         query_ptr++;
01009     }
01010 
01011     /* Return length of query part in cases that query part does not finish to '\0' character (last query part can be like that) */
01012     return returned_query_part_len;
01013 }
01014 
01015 /**
01016  * \fn static uint16_t sn_coap_builder_options_get_option_part_position(uint16_t query_len,
01017                                                                uint8_t *query_ptr,
01018                                                                uint8_t query_index, sn_coap_option_numbers_e option)
01019  *
01020  * \brief Gets query part position in whole query
01021  *
01022  * \param query_len is length of whole query
01023  *
01024  * \param *query_ptr is pointer to the start of whole query
01025  *
01026  * \param query_index is query part index to be found
01027  *
01028  * \return Return value is position (= offset) of query part in whole query. In
01029  *         fail cases -1 is returned.
01030  */
01031 static int16_t sn_coap_builder_options_get_option_part_position(uint16_t query_len, uint8_t *query_ptr,
01032         uint8_t query_index, sn_coap_option_numbers_e option)
01033 {
01034     uint16_t returned_query_part_offset = 0;
01035     uint8_t  temp_query_index           = 0;
01036     uint16_t query_len_index            = 0;
01037     uint8_t  char_to_search             = '&';
01038 
01039     if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) {
01040         char_to_search = '/';
01041     }
01042 
01043     if (query_index == 0) {
01044         if (*query_ptr == 0 || *query_ptr == char_to_search) {
01045             return 1;
01046         } else {
01047             return 0;
01048         }
01049     }
01050 
01051     /* Loop whole query and search separator characters */
01052     for (query_len_index = 0; query_len_index < query_len; query_len_index++) {
01053         /* Store character to temp_char for helping debugging */
01054         uint8_t temp_char = *query_ptr;
01055 
01056         /* If new query part starts */
01057         if (temp_char == char_to_search && returned_query_part_offset > 0) { /* returned_query_part_offset > 0 is for querys which start with searched char */
01058             /* If query part index is wanted */
01059             if (temp_query_index == (query_index - 1)) {
01060                 /* Return offset of query part */
01061                 return (returned_query_part_offset + 1); /* Plus one is for passing separator */
01062             }
01063 
01064             /* Next query part is looped */
01065             temp_query_index++;
01066         }
01067 
01068         returned_query_part_offset++;
01069 
01070         query_ptr++;
01071     }
01072 
01073     return -1; //Dead code?
01074 }
01075 
01076 
01077 /**
01078  * \fn static void sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr)
01079  *
01080  * \brief Builds Options part of Packet data
01081  *
01082  * \param **dst_packet_data_pptr is destination for built Packet data
01083  *
01084  * \param *src_coap_msg_ptr is source for building Packet data
01085  */
01086 static void sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr)
01087 {
01088     /* Check if Payload is used at all */
01089     if (src_coap_msg_ptr->payload_ptr != NULL) {
01090         /* Write Payload marker */
01091 
01092         **dst_packet_data_pptr = 0xff;
01093         (*dst_packet_data_pptr)++;
01094 
01095         /* Write Payload */
01096         memcpy(*dst_packet_data_pptr, src_coap_msg_ptr->payload_ptr, src_coap_msg_ptr->payload_len);
01097 
01098         /* Increase destination Packet data pointer */
01099         (*dst_packet_data_pptr) += src_coap_msg_ptr->payload_len;
01100     }
01101 }
01102