Committer:
leothedragon
Date:
Sun Apr 18 15:20:23 2021 +0000
Revision:
0:25fa8795676b
DS

Who changed what in which revision?

UserRevisionLine numberNew contents of line
leothedragon 0:25fa8795676b 1 /*
leothedragon 0:25fa8795676b 2 * Copyright (c) 2011-2015 ARM Limited. All rights reserved.
leothedragon 0:25fa8795676b 3 * SPDX-License-Identifier: Apache-2.0
leothedragon 0:25fa8795676b 4 * Licensed under the Apache License, Version 2.0 (the License); you may
leothedragon 0:25fa8795676b 5 * not use this file except in compliance with the License.
leothedragon 0:25fa8795676b 6 * You may obtain a copy of the License at
leothedragon 0:25fa8795676b 7 *
leothedragon 0:25fa8795676b 8 * http://www.apache.org/licenses/LICENSE-2.0
leothedragon 0:25fa8795676b 9 *
leothedragon 0:25fa8795676b 10 * Unless required by applicable law or agreed to in writing, software
leothedragon 0:25fa8795676b 11 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
leothedragon 0:25fa8795676b 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
leothedragon 0:25fa8795676b 13 * See the License for the specific language governing permissions and
leothedragon 0:25fa8795676b 14 * limitations under the License.
leothedragon 0:25fa8795676b 15 */
leothedragon 0:25fa8795676b 16
leothedragon 0:25fa8795676b 17 /**
leothedragon 0:25fa8795676b 18 *\file sn_coap_parser.c
leothedragon 0:25fa8795676b 19 *
leothedragon 0:25fa8795676b 20 * \brief CoAP Header parser
leothedragon 0:25fa8795676b 21 *
leothedragon 0:25fa8795676b 22 * Functionality: Parses CoAP Header
leothedragon 0:25fa8795676b 23 *
leothedragon 0:25fa8795676b 24 */
leothedragon 0:25fa8795676b 25
leothedragon 0:25fa8795676b 26 /* * * * * * * * * * * * * * */
leothedragon 0:25fa8795676b 27 /* * * * INCLUDE FILES * * * */
leothedragon 0:25fa8795676b 28 /* * * * * * * * * * * * * * */
leothedragon 0:25fa8795676b 29
leothedragon 0:25fa8795676b 30 #include <stdio.h>
leothedragon 0:25fa8795676b 31 #include <string.h> /* For memset() and memcpy() */
leothedragon 0:25fa8795676b 32
leothedragon 0:25fa8795676b 33 #include "ns_types.h"
leothedragon 0:25fa8795676b 34 #include "mbed-coap/sn_coap_header.h"
leothedragon 0:25fa8795676b 35 #include "mbed-coap/sn_coap_protocol.h"
leothedragon 0:25fa8795676b 36 #include "sn_coap_header_internal.h"
leothedragon 0:25fa8795676b 37 #include "sn_coap_protocol_internal.h"
leothedragon 0:25fa8795676b 38 #include "mbed-trace/mbed_trace.h"
leothedragon 0:25fa8795676b 39
leothedragon 0:25fa8795676b 40 #define TRACE_GROUP "coap"
leothedragon 0:25fa8795676b 41 /* * * * * * * * * * * * * * * * * * * * */
leothedragon 0:25fa8795676b 42 /* * * * LOCAL FUNCTION PROTOTYPES * * * */
leothedragon 0:25fa8795676b 43 /* * * * * * * * * * * * * * * * * * * * */
leothedragon 0:25fa8795676b 44
leothedragon 0:25fa8795676b 45 static void sn_coap_parser_header_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, coap_version_e *coap_version_ptr);
leothedragon 0:25fa8795676b 46 static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, uint8_t *packet_data_start_ptr, uint16_t packet_len);
leothedragon 0:25fa8795676b 47 static int8_t sn_coap_parser_options_parse_multiple_options(struct coap_s *handle, uint8_t **packet_data_pptr, uint16_t packet_left_len, uint8_t **dst_pptr, uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint16_t option_number_len);
leothedragon 0:25fa8795676b 48 static int16_t sn_coap_parser_options_count_needed_memory_multiple_option(uint8_t *packet_data_ptr, uint16_t packet_left_len, sn_coap_option_numbers_e option, uint16_t option_number_len);
leothedragon 0:25fa8795676b 49 static int8_t sn_coap_parser_payload_parse(uint16_t packet_data_len, uint8_t *packet_data_start_ptr, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr);
leothedragon 0:25fa8795676b 50
leothedragon 0:25fa8795676b 51 sn_coap_hdr_s *sn_coap_parser_init_message(sn_coap_hdr_s *coap_msg_ptr)
leothedragon 0:25fa8795676b 52 {
leothedragon 0:25fa8795676b 53 /* * * * Check given pointer * * * */
leothedragon 0:25fa8795676b 54 if (coap_msg_ptr == NULL) {
leothedragon 0:25fa8795676b 55 tr_error("sn_coap_parser_init_message - message null!");
leothedragon 0:25fa8795676b 56 return NULL;
leothedragon 0:25fa8795676b 57 }
leothedragon 0:25fa8795676b 58
leothedragon 0:25fa8795676b 59 /* XXX not technically legal to memset pointers to 0 */
leothedragon 0:25fa8795676b 60 memset(coap_msg_ptr, 0x00, sizeof(sn_coap_hdr_s));
leothedragon 0:25fa8795676b 61
leothedragon 0:25fa8795676b 62 coap_msg_ptr->content_format = COAP_CT_NONE;
leothedragon 0:25fa8795676b 63
leothedragon 0:25fa8795676b 64 return coap_msg_ptr;
leothedragon 0:25fa8795676b 65 }
leothedragon 0:25fa8795676b 66
leothedragon 0:25fa8795676b 67 sn_coap_hdr_s *sn_coap_parser_alloc_message(struct coap_s *handle)
leothedragon 0:25fa8795676b 68 {
leothedragon 0:25fa8795676b 69 sn_coap_hdr_s *returned_coap_msg_ptr;
leothedragon 0:25fa8795676b 70
leothedragon 0:25fa8795676b 71 /* * * * Check given pointer * * * */
leothedragon 0:25fa8795676b 72 if (handle == NULL) {
leothedragon 0:25fa8795676b 73 return NULL;
leothedragon 0:25fa8795676b 74 }
leothedragon 0:25fa8795676b 75
leothedragon 0:25fa8795676b 76 /* * * * Allocate memory for returned CoAP message and initialize allocated memory with with default values * * * */
leothedragon 0:25fa8795676b 77 returned_coap_msg_ptr = handle->sn_coap_protocol_malloc(sizeof(sn_coap_hdr_s));
leothedragon 0:25fa8795676b 78
leothedragon 0:25fa8795676b 79 return sn_coap_parser_init_message(returned_coap_msg_ptr);
leothedragon 0:25fa8795676b 80 }
leothedragon 0:25fa8795676b 81
leothedragon 0:25fa8795676b 82 sn_coap_options_list_s *sn_coap_parser_alloc_options(struct coap_s *handle, sn_coap_hdr_s *coap_msg_ptr)
leothedragon 0:25fa8795676b 83 {
leothedragon 0:25fa8795676b 84 /* * * * Check given pointers * * * */
leothedragon 0:25fa8795676b 85 if (handle == NULL || coap_msg_ptr == NULL) {
leothedragon 0:25fa8795676b 86 return NULL;
leothedragon 0:25fa8795676b 87 }
leothedragon 0:25fa8795676b 88
leothedragon 0:25fa8795676b 89 /* * * * If the message already has options, return them * * * */
leothedragon 0:25fa8795676b 90 if (coap_msg_ptr->options_list_ptr) {
leothedragon 0:25fa8795676b 91 return coap_msg_ptr->options_list_ptr;
leothedragon 0:25fa8795676b 92 }
leothedragon 0:25fa8795676b 93
leothedragon 0:25fa8795676b 94 /* * * * Allocate memory for options and initialize allocated memory with with default values * * * */
leothedragon 0:25fa8795676b 95 coap_msg_ptr->options_list_ptr = handle->sn_coap_protocol_malloc(sizeof(sn_coap_options_list_s));
leothedragon 0:25fa8795676b 96
leothedragon 0:25fa8795676b 97 if (coap_msg_ptr->options_list_ptr == NULL) {
leothedragon 0:25fa8795676b 98 tr_error("sn_coap_parser_alloc_options - failed to allocate options list!");
leothedragon 0:25fa8795676b 99 return NULL;
leothedragon 0:25fa8795676b 100 }
leothedragon 0:25fa8795676b 101
leothedragon 0:25fa8795676b 102 /* XXX not technically legal to memset pointers to 0 */
leothedragon 0:25fa8795676b 103 memset(coap_msg_ptr->options_list_ptr, 0x00, sizeof(sn_coap_options_list_s));
leothedragon 0:25fa8795676b 104
leothedragon 0:25fa8795676b 105 coap_msg_ptr->options_list_ptr->max_age = 0;
leothedragon 0:25fa8795676b 106 coap_msg_ptr->options_list_ptr->uri_port = COAP_OPTION_URI_PORT_NONE;
leothedragon 0:25fa8795676b 107 coap_msg_ptr->options_list_ptr->observe = COAP_OBSERVE_NONE;
leothedragon 0:25fa8795676b 108 coap_msg_ptr->options_list_ptr->accept = COAP_CT_NONE;
leothedragon 0:25fa8795676b 109 coap_msg_ptr->options_list_ptr->block2 = COAP_OPTION_BLOCK_NONE;
leothedragon 0:25fa8795676b 110 coap_msg_ptr->options_list_ptr->block1 = COAP_OPTION_BLOCK_NONE;
leothedragon 0:25fa8795676b 111
leothedragon 0:25fa8795676b 112 return coap_msg_ptr->options_list_ptr;
leothedragon 0:25fa8795676b 113 }
leothedragon 0:25fa8795676b 114
leothedragon 0:25fa8795676b 115 sn_coap_hdr_s *sn_coap_parser(struct coap_s *handle, uint16_t packet_data_len, uint8_t *packet_data_ptr, coap_version_e *coap_version_ptr)
leothedragon 0:25fa8795676b 116 {
leothedragon 0:25fa8795676b 117 uint8_t *data_temp_ptr = packet_data_ptr;
leothedragon 0:25fa8795676b 118 sn_coap_hdr_s *parsed_and_returned_coap_msg_ptr = NULL;
leothedragon 0:25fa8795676b 119
leothedragon 0:25fa8795676b 120 /* * * * Check given pointer * * * */
leothedragon 0:25fa8795676b 121 if (packet_data_ptr == NULL || packet_data_len < 4 || handle == NULL) {
leothedragon 0:25fa8795676b 122 return NULL;
leothedragon 0:25fa8795676b 123 }
leothedragon 0:25fa8795676b 124
leothedragon 0:25fa8795676b 125 /* * * * Allocate and initialize CoAP message * * * */
leothedragon 0:25fa8795676b 126 parsed_and_returned_coap_msg_ptr = sn_coap_parser_alloc_message(handle);
leothedragon 0:25fa8795676b 127
leothedragon 0:25fa8795676b 128 if (parsed_and_returned_coap_msg_ptr == NULL) {
leothedragon 0:25fa8795676b 129 tr_error("sn_coap_parser - failed to allocate message!");
leothedragon 0:25fa8795676b 130 return NULL;
leothedragon 0:25fa8795676b 131 }
leothedragon 0:25fa8795676b 132
leothedragon 0:25fa8795676b 133 /* * * * Header parsing, move pointer over the header... * * * */
leothedragon 0:25fa8795676b 134 sn_coap_parser_header_parse(&data_temp_ptr, parsed_and_returned_coap_msg_ptr, coap_version_ptr);
leothedragon 0:25fa8795676b 135
leothedragon 0:25fa8795676b 136 /* * * * Options parsing, move pointer over the options... * * * */
leothedragon 0:25fa8795676b 137 if (sn_coap_parser_options_parse(handle, &data_temp_ptr, parsed_and_returned_coap_msg_ptr, packet_data_ptr, packet_data_len) != 0) {
leothedragon 0:25fa8795676b 138 parsed_and_returned_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_ERROR_IN_HEADER;
leothedragon 0:25fa8795676b 139 return parsed_and_returned_coap_msg_ptr;
leothedragon 0:25fa8795676b 140 }
leothedragon 0:25fa8795676b 141
leothedragon 0:25fa8795676b 142 /* * * * Payload parsing * * * */
leothedragon 0:25fa8795676b 143 if (sn_coap_parser_payload_parse(packet_data_len, packet_data_ptr, &data_temp_ptr, parsed_and_returned_coap_msg_ptr) == -1) {
leothedragon 0:25fa8795676b 144 parsed_and_returned_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_ERROR_IN_HEADER;
leothedragon 0:25fa8795676b 145 return parsed_and_returned_coap_msg_ptr;
leothedragon 0:25fa8795676b 146 }
leothedragon 0:25fa8795676b 147
leothedragon 0:25fa8795676b 148 /* * * * Return parsed CoAP message * * * * */
leothedragon 0:25fa8795676b 149 return parsed_and_returned_coap_msg_ptr;
leothedragon 0:25fa8795676b 150 }
leothedragon 0:25fa8795676b 151
leothedragon 0:25fa8795676b 152 void sn_coap_parser_release_allocated_coap_msg_mem(struct coap_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr)
leothedragon 0:25fa8795676b 153 {
leothedragon 0:25fa8795676b 154 if (handle == NULL) {
leothedragon 0:25fa8795676b 155 return;
leothedragon 0:25fa8795676b 156 }
leothedragon 0:25fa8795676b 157
leothedragon 0:25fa8795676b 158 if (freed_coap_msg_ptr != NULL) {
leothedragon 0:25fa8795676b 159 if (freed_coap_msg_ptr->uri_path_ptr != NULL) {
leothedragon 0:25fa8795676b 160 handle->sn_coap_protocol_free(freed_coap_msg_ptr->uri_path_ptr);
leothedragon 0:25fa8795676b 161 }
leothedragon 0:25fa8795676b 162
leothedragon 0:25fa8795676b 163 if (freed_coap_msg_ptr->token_ptr != NULL) {
leothedragon 0:25fa8795676b 164 handle->sn_coap_protocol_free(freed_coap_msg_ptr->token_ptr);
leothedragon 0:25fa8795676b 165 }
leothedragon 0:25fa8795676b 166
leothedragon 0:25fa8795676b 167 if (freed_coap_msg_ptr->options_list_ptr != NULL) {
leothedragon 0:25fa8795676b 168 if (freed_coap_msg_ptr->options_list_ptr->proxy_uri_ptr != NULL) {
leothedragon 0:25fa8795676b 169 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->proxy_uri_ptr);
leothedragon 0:25fa8795676b 170 }
leothedragon 0:25fa8795676b 171
leothedragon 0:25fa8795676b 172 if (freed_coap_msg_ptr->options_list_ptr->etag_ptr != NULL) {
leothedragon 0:25fa8795676b 173 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->etag_ptr);
leothedragon 0:25fa8795676b 174 }
leothedragon 0:25fa8795676b 175
leothedragon 0:25fa8795676b 176 if (freed_coap_msg_ptr->options_list_ptr->uri_host_ptr != NULL) {
leothedragon 0:25fa8795676b 177 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->uri_host_ptr);
leothedragon 0:25fa8795676b 178 }
leothedragon 0:25fa8795676b 179
leothedragon 0:25fa8795676b 180 if (freed_coap_msg_ptr->options_list_ptr->location_path_ptr != NULL) {
leothedragon 0:25fa8795676b 181 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->location_path_ptr);
leothedragon 0:25fa8795676b 182 }
leothedragon 0:25fa8795676b 183
leothedragon 0:25fa8795676b 184 if (freed_coap_msg_ptr->options_list_ptr->location_query_ptr != NULL) {
leothedragon 0:25fa8795676b 185 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->location_query_ptr);
leothedragon 0:25fa8795676b 186 }
leothedragon 0:25fa8795676b 187
leothedragon 0:25fa8795676b 188 if (freed_coap_msg_ptr->options_list_ptr->uri_query_ptr != NULL) {
leothedragon 0:25fa8795676b 189 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->uri_query_ptr);
leothedragon 0:25fa8795676b 190 }
leothedragon 0:25fa8795676b 191
leothedragon 0:25fa8795676b 192 handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr);
leothedragon 0:25fa8795676b 193 }
leothedragon 0:25fa8795676b 194
leothedragon 0:25fa8795676b 195 handle->sn_coap_protocol_free(freed_coap_msg_ptr);
leothedragon 0:25fa8795676b 196 }
leothedragon 0:25fa8795676b 197 }
leothedragon 0:25fa8795676b 198
leothedragon 0:25fa8795676b 199 /**
leothedragon 0:25fa8795676b 200 * \fn static void sn_coap_parser_header_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, coap_version_e *coap_version_ptr)
leothedragon 0:25fa8795676b 201 *
leothedragon 0:25fa8795676b 202 * \brief Parses CoAP message's Header part from given Packet data
leothedragon 0:25fa8795676b 203 *
leothedragon 0:25fa8795676b 204 * \param **packet_data_ptr is source for Packet data to be parsed to CoAP message
leothedragon 0:25fa8795676b 205 *
leothedragon 0:25fa8795676b 206 * \param *dst_coap_msg_ptr is destination for parsed CoAP message
leothedragon 0:25fa8795676b 207 *
leothedragon 0:25fa8795676b 208 * \param *coap_version_ptr is destination for parsed CoAP specification version
leothedragon 0:25fa8795676b 209 */
leothedragon 0:25fa8795676b 210 static void sn_coap_parser_header_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, coap_version_e *coap_version_ptr)
leothedragon 0:25fa8795676b 211 {
leothedragon 0:25fa8795676b 212 /* Parse CoAP Version and message type*/
leothedragon 0:25fa8795676b 213 *coap_version_ptr = (coap_version_e)(**packet_data_pptr & COAP_HEADER_VERSION_MASK);
leothedragon 0:25fa8795676b 214 dst_coap_msg_ptr->msg_type = (sn_coap_msg_type_e)(**packet_data_pptr & COAP_HEADER_MSG_TYPE_MASK);
leothedragon 0:25fa8795676b 215 (*packet_data_pptr) += 1;
leothedragon 0:25fa8795676b 216
leothedragon 0:25fa8795676b 217 /* Parse Message code */
leothedragon 0:25fa8795676b 218 dst_coap_msg_ptr->msg_code = (sn_coap_msg_code_e) **packet_data_pptr;
leothedragon 0:25fa8795676b 219 (*packet_data_pptr) += 1;
leothedragon 0:25fa8795676b 220
leothedragon 0:25fa8795676b 221 /* Parse Message ID */
leothedragon 0:25fa8795676b 222 dst_coap_msg_ptr->msg_id = *(*packet_data_pptr + 1);
leothedragon 0:25fa8795676b 223 dst_coap_msg_ptr->msg_id += **packet_data_pptr << COAP_HEADER_MSG_ID_MSB_SHIFT;
leothedragon 0:25fa8795676b 224 (*packet_data_pptr) += 2;
leothedragon 0:25fa8795676b 225
leothedragon 0:25fa8795676b 226 }
leothedragon 0:25fa8795676b 227
leothedragon 0:25fa8795676b 228 /**
leothedragon 0:25fa8795676b 229 * \brief Parses a variable-length uint value from an option
leothedragon 0:25fa8795676b 230 *
leothedragon 0:25fa8795676b 231 * \param **packet_data_pptr is source of option data to be parsed
leothedragon 0:25fa8795676b 232 * \param option_len is length of option data (will be 0-4)
leothedragon 0:25fa8795676b 233 *
leothedragon 0:25fa8795676b 234 * \return Return value is value of uint
leothedragon 0:25fa8795676b 235 */
leothedragon 0:25fa8795676b 236 static uint32_t sn_coap_parser_options_parse_uint(uint8_t **packet_data_pptr, uint8_t option_len)
leothedragon 0:25fa8795676b 237 {
leothedragon 0:25fa8795676b 238 uint32_t value = 0;
leothedragon 0:25fa8795676b 239 while (option_len--) {
leothedragon 0:25fa8795676b 240 value <<= 8;
leothedragon 0:25fa8795676b 241 value |= *(*packet_data_pptr)++;
leothedragon 0:25fa8795676b 242 }
leothedragon 0:25fa8795676b 243 return value;
leothedragon 0:25fa8795676b 244 }
leothedragon 0:25fa8795676b 245
leothedragon 0:25fa8795676b 246 /**
leothedragon 0:25fa8795676b 247 * \fn static uint8_t sn_coap_parser_options_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr)
leothedragon 0:25fa8795676b 248 *
leothedragon 0:25fa8795676b 249 * \brief Parses CoAP message's Options part from given Packet data
leothedragon 0:25fa8795676b 250 *
leothedragon 0:25fa8795676b 251 * \param **packet_data_pptr is source of Packet data to be parsed to CoAP message
leothedragon 0:25fa8795676b 252 * \param *dst_coap_msg_ptr is destination for parsed CoAP message
leothedragon 0:25fa8795676b 253 *
leothedragon 0:25fa8795676b 254 * \return Return value is 0 in ok case and -1 in failure case
leothedragon 0:25fa8795676b 255 */
leothedragon 0:25fa8795676b 256 static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, uint8_t *packet_data_start_ptr, uint16_t packet_len)
leothedragon 0:25fa8795676b 257 {
leothedragon 0:25fa8795676b 258 uint8_t previous_option_number = 0;
leothedragon 0:25fa8795676b 259 uint8_t i = 0;
leothedragon 0:25fa8795676b 260 int8_t ret_status = 0;
leothedragon 0:25fa8795676b 261 uint16_t message_left = 0;
leothedragon 0:25fa8795676b 262
leothedragon 0:25fa8795676b 263 /* Parse token, if exists */
leothedragon 0:25fa8795676b 264 dst_coap_msg_ptr->token_len = *packet_data_start_ptr & COAP_HEADER_TOKEN_LENGTH_MASK;
leothedragon 0:25fa8795676b 265
leothedragon 0:25fa8795676b 266 if (dst_coap_msg_ptr->token_len) {
leothedragon 0:25fa8795676b 267 if ((dst_coap_msg_ptr->token_len > 8) || dst_coap_msg_ptr->token_ptr) {
leothedragon 0:25fa8795676b 268 tr_error("sn_coap_parser_options_parse - token not valid!");
leothedragon 0:25fa8795676b 269 return -1;
leothedragon 0:25fa8795676b 270 }
leothedragon 0:25fa8795676b 271
leothedragon 0:25fa8795676b 272 dst_coap_msg_ptr->token_ptr = handle->sn_coap_protocol_malloc(dst_coap_msg_ptr->token_len);
leothedragon 0:25fa8795676b 273
leothedragon 0:25fa8795676b 274 if (dst_coap_msg_ptr->token_ptr == NULL) {
leothedragon 0:25fa8795676b 275 tr_error("sn_coap_parser_options_parse - failed to allocate token!");
leothedragon 0:25fa8795676b 276 return -1;
leothedragon 0:25fa8795676b 277 }
leothedragon 0:25fa8795676b 278
leothedragon 0:25fa8795676b 279 memcpy(dst_coap_msg_ptr->token_ptr, *packet_data_pptr, dst_coap_msg_ptr->token_len);
leothedragon 0:25fa8795676b 280 (*packet_data_pptr) += dst_coap_msg_ptr->token_len;
leothedragon 0:25fa8795676b 281 }
leothedragon 0:25fa8795676b 282
leothedragon 0:25fa8795676b 283 message_left = packet_len - ((*packet_data_pptr) - packet_data_start_ptr);
leothedragon 0:25fa8795676b 284
leothedragon 0:25fa8795676b 285 /* Loop all Options */
leothedragon 0:25fa8795676b 286 while (message_left && (**packet_data_pptr != 0xff)) {
leothedragon 0:25fa8795676b 287
leothedragon 0:25fa8795676b 288 /* Get option length WITHOUT extensions */
leothedragon 0:25fa8795676b 289 uint16_t option_len = (**packet_data_pptr & 0x0F);
leothedragon 0:25fa8795676b 290
leothedragon 0:25fa8795676b 291 /* Resolve option delta */
leothedragon 0:25fa8795676b 292 uint16_t option_number = (**packet_data_pptr >> COAP_OPTIONS_OPTION_NUMBER_SHIFT);
leothedragon 0:25fa8795676b 293
leothedragon 0:25fa8795676b 294 if (option_number == 13) {
leothedragon 0:25fa8795676b 295 option_number = *(*packet_data_pptr + 1) + 13;
leothedragon 0:25fa8795676b 296 (*packet_data_pptr)++;
leothedragon 0:25fa8795676b 297 } else if (option_number == 14) {
leothedragon 0:25fa8795676b 298 option_number = *(*packet_data_pptr + 2);
leothedragon 0:25fa8795676b 299 option_number += (*(*packet_data_pptr + 1) << 8) + 269;
leothedragon 0:25fa8795676b 300 (*packet_data_pptr) += 2;
leothedragon 0:25fa8795676b 301 }
leothedragon 0:25fa8795676b 302 /* Option number 15 reserved for payload marker. This is handled as a error! */
leothedragon 0:25fa8795676b 303 else if (option_number == 15) {
leothedragon 0:25fa8795676b 304 tr_error("sn_coap_parser_options_parse - invalid option number(15)!");
leothedragon 0:25fa8795676b 305 return -1;
leothedragon 0:25fa8795676b 306 }
leothedragon 0:25fa8795676b 307
leothedragon 0:25fa8795676b 308 /* Add previous option to option delta and get option number */
leothedragon 0:25fa8795676b 309 option_number += previous_option_number;
leothedragon 0:25fa8795676b 310
leothedragon 0:25fa8795676b 311 /* Add possible option length extension to resolve full length of the option */
leothedragon 0:25fa8795676b 312 if (option_len == 13) {
leothedragon 0:25fa8795676b 313 option_len = *(*packet_data_pptr + 1) + 13;
leothedragon 0:25fa8795676b 314 (*packet_data_pptr)++;
leothedragon 0:25fa8795676b 315 } else if (option_len == 14) {
leothedragon 0:25fa8795676b 316 option_len = *(*packet_data_pptr + 2);
leothedragon 0:25fa8795676b 317 option_len += (*(*packet_data_pptr + 1) << 8) + 269;
leothedragon 0:25fa8795676b 318 (*packet_data_pptr) += 2;
leothedragon 0:25fa8795676b 319 }
leothedragon 0:25fa8795676b 320 /* Option number length 15 is reserved for the future use - ERROR */
leothedragon 0:25fa8795676b 321 else if (option_len == 15) {
leothedragon 0:25fa8795676b 322 tr_error("sn_coap_parser_options_parse - invalid option len(15)!");
leothedragon 0:25fa8795676b 323 return -1;
leothedragon 0:25fa8795676b 324 }
leothedragon 0:25fa8795676b 325
leothedragon 0:25fa8795676b 326 message_left = packet_len - (*packet_data_pptr - packet_data_start_ptr);
leothedragon 0:25fa8795676b 327
leothedragon 0:25fa8795676b 328 /* * * Parse option itself * * */
leothedragon 0:25fa8795676b 329 /* Some options are handled independently in own functions */
leothedragon 0:25fa8795676b 330 previous_option_number = option_number;
leothedragon 0:25fa8795676b 331 /* Allocate options_list_ptr if needed */
leothedragon 0:25fa8795676b 332 switch (option_number) {
leothedragon 0:25fa8795676b 333 case COAP_OPTION_MAX_AGE:
leothedragon 0:25fa8795676b 334 case COAP_OPTION_PROXY_URI:
leothedragon 0:25fa8795676b 335 case COAP_OPTION_ETAG:
leothedragon 0:25fa8795676b 336 case COAP_OPTION_URI_HOST:
leothedragon 0:25fa8795676b 337 case COAP_OPTION_LOCATION_PATH:
leothedragon 0:25fa8795676b 338 case COAP_OPTION_URI_PORT:
leothedragon 0:25fa8795676b 339 case COAP_OPTION_LOCATION_QUERY:
leothedragon 0:25fa8795676b 340 case COAP_OPTION_OBSERVE:
leothedragon 0:25fa8795676b 341 case COAP_OPTION_URI_QUERY:
leothedragon 0:25fa8795676b 342 case COAP_OPTION_BLOCK2:
leothedragon 0:25fa8795676b 343 case COAP_OPTION_BLOCK1:
leothedragon 0:25fa8795676b 344 case COAP_OPTION_ACCEPT:
leothedragon 0:25fa8795676b 345 case COAP_OPTION_SIZE1:
leothedragon 0:25fa8795676b 346 case COAP_OPTION_SIZE2:
leothedragon 0:25fa8795676b 347 if (sn_coap_parser_alloc_options(handle, dst_coap_msg_ptr) == NULL) {
leothedragon 0:25fa8795676b 348 tr_error("sn_coap_parser_options_parse - failed to allocate options!");
leothedragon 0:25fa8795676b 349 return -1;
leothedragon 0:25fa8795676b 350 }
leothedragon 0:25fa8795676b 351 break;
leothedragon 0:25fa8795676b 352 }
leothedragon 0:25fa8795676b 353
leothedragon 0:25fa8795676b 354 /* Parse option */
leothedragon 0:25fa8795676b 355 switch (option_number) {
leothedragon 0:25fa8795676b 356 case COAP_OPTION_CONTENT_FORMAT:
leothedragon 0:25fa8795676b 357 if ((option_len > 2) || (dst_coap_msg_ptr->content_format != COAP_CT_NONE)) {
leothedragon 0:25fa8795676b 358 tr_error("sn_coap_parser_options_parse - COAP_OPTION_CONTENT_FORMAT not valid!");
leothedragon 0:25fa8795676b 359 return -1;
leothedragon 0:25fa8795676b 360 }
leothedragon 0:25fa8795676b 361 (*packet_data_pptr)++;
leothedragon 0:25fa8795676b 362 dst_coap_msg_ptr->content_format = (sn_coap_content_format_e) sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
leothedragon 0:25fa8795676b 363 break;
leothedragon 0:25fa8795676b 364
leothedragon 0:25fa8795676b 365 case COAP_OPTION_MAX_AGE:
leothedragon 0:25fa8795676b 366 if (option_len > 4) {
leothedragon 0:25fa8795676b 367 tr_error("sn_coap_parser_options_parse - COAP_OPTION_MAX_AGE not valid!");
leothedragon 0:25fa8795676b 368 return -1;
leothedragon 0:25fa8795676b 369 }
leothedragon 0:25fa8795676b 370 (*packet_data_pptr)++;
leothedragon 0:25fa8795676b 371 dst_coap_msg_ptr->options_list_ptr->max_age = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
leothedragon 0:25fa8795676b 372 break;
leothedragon 0:25fa8795676b 373
leothedragon 0:25fa8795676b 374 case COAP_OPTION_PROXY_URI:
leothedragon 0:25fa8795676b 375 if ((option_len > 1034) || (option_len < 1) || dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr) {
leothedragon 0:25fa8795676b 376 tr_error("sn_coap_parser_options_parse - COAP_OPTION_PROXY_URI not valid!");
leothedragon 0:25fa8795676b 377 return -1;
leothedragon 0:25fa8795676b 378 }
leothedragon 0:25fa8795676b 379 dst_coap_msg_ptr->options_list_ptr->proxy_uri_len = option_len;
leothedragon 0:25fa8795676b 380 (*packet_data_pptr)++;
leothedragon 0:25fa8795676b 381
leothedragon 0:25fa8795676b 382 dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr = handle->sn_coap_protocol_malloc(option_len);
leothedragon 0:25fa8795676b 383
leothedragon 0:25fa8795676b 384 if (dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr == NULL) {
leothedragon 0:25fa8795676b 385 tr_error("sn_coap_parser_options_parse - COAP_OPTION_PROXY_URI allocation failed!");
leothedragon 0:25fa8795676b 386 return -1;
leothedragon 0:25fa8795676b 387 }
leothedragon 0:25fa8795676b 388
leothedragon 0:25fa8795676b 389 memcpy(dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr, *packet_data_pptr, option_len);
leothedragon 0:25fa8795676b 390 (*packet_data_pptr) += option_len;
leothedragon 0:25fa8795676b 391
leothedragon 0:25fa8795676b 392 break;
leothedragon 0:25fa8795676b 393
leothedragon 0:25fa8795676b 394 case COAP_OPTION_ETAG:
leothedragon 0:25fa8795676b 395 /* This is managed independently because User gives this option in one character table */
leothedragon 0:25fa8795676b 396
leothedragon 0:25fa8795676b 397 ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr,
leothedragon 0:25fa8795676b 398 message_left,
leothedragon 0:25fa8795676b 399 &dst_coap_msg_ptr->options_list_ptr->etag_ptr,
leothedragon 0:25fa8795676b 400 (uint16_t *)&dst_coap_msg_ptr->options_list_ptr->etag_len,
leothedragon 0:25fa8795676b 401 COAP_OPTION_ETAG, option_len);
leothedragon 0:25fa8795676b 402 if (ret_status >= 0) {
leothedragon 0:25fa8795676b 403 i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
leothedragon 0:25fa8795676b 404 } else {
leothedragon 0:25fa8795676b 405 tr_error("sn_coap_parser_options_parse - COAP_OPTION_ETAG not valid!");
leothedragon 0:25fa8795676b 406 return -1;
leothedragon 0:25fa8795676b 407 }
leothedragon 0:25fa8795676b 408 break;
leothedragon 0:25fa8795676b 409
leothedragon 0:25fa8795676b 410 case COAP_OPTION_URI_HOST:
leothedragon 0:25fa8795676b 411 if ((option_len > 255) || (option_len < 1) || dst_coap_msg_ptr->options_list_ptr->uri_host_ptr) {
leothedragon 0:25fa8795676b 412 tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_HOST not valid!");
leothedragon 0:25fa8795676b 413 return -1;
leothedragon 0:25fa8795676b 414 }
leothedragon 0:25fa8795676b 415 dst_coap_msg_ptr->options_list_ptr->uri_host_len = option_len;
leothedragon 0:25fa8795676b 416 (*packet_data_pptr)++;
leothedragon 0:25fa8795676b 417
leothedragon 0:25fa8795676b 418 dst_coap_msg_ptr->options_list_ptr->uri_host_ptr = handle->sn_coap_protocol_malloc(option_len);
leothedragon 0:25fa8795676b 419
leothedragon 0:25fa8795676b 420 if (dst_coap_msg_ptr->options_list_ptr->uri_host_ptr == NULL) {
leothedragon 0:25fa8795676b 421 tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_HOST allocation failed!");
leothedragon 0:25fa8795676b 422 return -1;
leothedragon 0:25fa8795676b 423 }
leothedragon 0:25fa8795676b 424 memcpy(dst_coap_msg_ptr->options_list_ptr->uri_host_ptr, *packet_data_pptr, option_len);
leothedragon 0:25fa8795676b 425 (*packet_data_pptr) += option_len;
leothedragon 0:25fa8795676b 426
leothedragon 0:25fa8795676b 427 break;
leothedragon 0:25fa8795676b 428
leothedragon 0:25fa8795676b 429 case COAP_OPTION_LOCATION_PATH:
leothedragon 0:25fa8795676b 430 if (dst_coap_msg_ptr->options_list_ptr->location_path_ptr) {
leothedragon 0:25fa8795676b 431 tr_error("sn_coap_parser_options_parse - COAP_OPTION_LOCATION_PATH exists!");
leothedragon 0:25fa8795676b 432 return -1;
leothedragon 0:25fa8795676b 433 }
leothedragon 0:25fa8795676b 434 /* This is managed independently because User gives this option in one character table */
leothedragon 0:25fa8795676b 435 ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left,
leothedragon 0:25fa8795676b 436 &dst_coap_msg_ptr->options_list_ptr->location_path_ptr, &dst_coap_msg_ptr->options_list_ptr->location_path_len,
leothedragon 0:25fa8795676b 437 COAP_OPTION_LOCATION_PATH, option_len);
leothedragon 0:25fa8795676b 438 if (ret_status >= 0) {
leothedragon 0:25fa8795676b 439 i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
leothedragon 0:25fa8795676b 440 } else {
leothedragon 0:25fa8795676b 441 tr_error("sn_coap_parser_options_parse - COAP_OPTION_LOCATION_PATH not valid!");
leothedragon 0:25fa8795676b 442 return -1;
leothedragon 0:25fa8795676b 443 }
leothedragon 0:25fa8795676b 444
leothedragon 0:25fa8795676b 445 break;
leothedragon 0:25fa8795676b 446
leothedragon 0:25fa8795676b 447
leothedragon 0:25fa8795676b 448 case COAP_OPTION_URI_PORT:
leothedragon 0:25fa8795676b 449 if ((option_len > 2) || dst_coap_msg_ptr->options_list_ptr->uri_port != COAP_OPTION_URI_PORT_NONE) {
leothedragon 0:25fa8795676b 450 tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_PORT not valid!");
leothedragon 0:25fa8795676b 451 return -1;
leothedragon 0:25fa8795676b 452 }
leothedragon 0:25fa8795676b 453 (*packet_data_pptr)++;
leothedragon 0:25fa8795676b 454
leothedragon 0:25fa8795676b 455 dst_coap_msg_ptr->options_list_ptr->uri_port = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
leothedragon 0:25fa8795676b 456 break;
leothedragon 0:25fa8795676b 457
leothedragon 0:25fa8795676b 458 case COAP_OPTION_LOCATION_QUERY:
leothedragon 0:25fa8795676b 459 ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left,
leothedragon 0:25fa8795676b 460 &dst_coap_msg_ptr->options_list_ptr->location_query_ptr, &dst_coap_msg_ptr->options_list_ptr->location_query_len,
leothedragon 0:25fa8795676b 461 COAP_OPTION_LOCATION_QUERY, option_len);
leothedragon 0:25fa8795676b 462 if (ret_status >= 0) {
leothedragon 0:25fa8795676b 463 i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
leothedragon 0:25fa8795676b 464 } else {
leothedragon 0:25fa8795676b 465 tr_error("sn_coap_parser_options_parse - COAP_OPTION_LOCATION_QUERY not valid!");
leothedragon 0:25fa8795676b 466 return -1;
leothedragon 0:25fa8795676b 467 }
leothedragon 0:25fa8795676b 468
leothedragon 0:25fa8795676b 469 break;
leothedragon 0:25fa8795676b 470
leothedragon 0:25fa8795676b 471 case COAP_OPTION_URI_PATH:
leothedragon 0:25fa8795676b 472 ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left,
leothedragon 0:25fa8795676b 473 &dst_coap_msg_ptr->uri_path_ptr, &dst_coap_msg_ptr->uri_path_len,
leothedragon 0:25fa8795676b 474 COAP_OPTION_URI_PATH, option_len);
leothedragon 0:25fa8795676b 475 if (ret_status >= 0) {
leothedragon 0:25fa8795676b 476 i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
leothedragon 0:25fa8795676b 477 } else {
leothedragon 0:25fa8795676b 478 tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_PATH not valid!");
leothedragon 0:25fa8795676b 479 return -1;
leothedragon 0:25fa8795676b 480 }
leothedragon 0:25fa8795676b 481
leothedragon 0:25fa8795676b 482 break;
leothedragon 0:25fa8795676b 483
leothedragon 0:25fa8795676b 484 case COAP_OPTION_OBSERVE:
leothedragon 0:25fa8795676b 485 if ((option_len > 2) || dst_coap_msg_ptr->options_list_ptr->observe != COAP_OBSERVE_NONE) {
leothedragon 0:25fa8795676b 486 tr_error("sn_coap_parser_options_parse - COAP_OPTION_OBSERVE not valid!");
leothedragon 0:25fa8795676b 487 return -1;
leothedragon 0:25fa8795676b 488 }
leothedragon 0:25fa8795676b 489
leothedragon 0:25fa8795676b 490 (*packet_data_pptr)++;
leothedragon 0:25fa8795676b 491
leothedragon 0:25fa8795676b 492 dst_coap_msg_ptr->options_list_ptr->observe = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
leothedragon 0:25fa8795676b 493
leothedragon 0:25fa8795676b 494 break;
leothedragon 0:25fa8795676b 495
leothedragon 0:25fa8795676b 496 case COAP_OPTION_URI_QUERY:
leothedragon 0:25fa8795676b 497 ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left,
leothedragon 0:25fa8795676b 498 &dst_coap_msg_ptr->options_list_ptr->uri_query_ptr, &dst_coap_msg_ptr->options_list_ptr->uri_query_len,
leothedragon 0:25fa8795676b 499 COAP_OPTION_URI_QUERY, option_len);
leothedragon 0:25fa8795676b 500 if (ret_status >= 0) {
leothedragon 0:25fa8795676b 501 i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
leothedragon 0:25fa8795676b 502 } else {
leothedragon 0:25fa8795676b 503 tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_QUERY not valid!");
leothedragon 0:25fa8795676b 504 return -1;
leothedragon 0:25fa8795676b 505 }
leothedragon 0:25fa8795676b 506
leothedragon 0:25fa8795676b 507 break;
leothedragon 0:25fa8795676b 508
leothedragon 0:25fa8795676b 509 case COAP_OPTION_BLOCK2:
leothedragon 0:25fa8795676b 510 if ((option_len > 3) || dst_coap_msg_ptr->options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE) {
leothedragon 0:25fa8795676b 511 tr_error("sn_coap_parser_options_parse - COAP_OPTION_BLOCK2 not valid!");
leothedragon 0:25fa8795676b 512 return -1;
leothedragon 0:25fa8795676b 513 }
leothedragon 0:25fa8795676b 514 (*packet_data_pptr)++;
leothedragon 0:25fa8795676b 515
leothedragon 0:25fa8795676b 516 dst_coap_msg_ptr->options_list_ptr->block2 = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
leothedragon 0:25fa8795676b 517
leothedragon 0:25fa8795676b 518 break;
leothedragon 0:25fa8795676b 519
leothedragon 0:25fa8795676b 520 case COAP_OPTION_BLOCK1:
leothedragon 0:25fa8795676b 521 if ((option_len > 3) || dst_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE) {
leothedragon 0:25fa8795676b 522 tr_error("sn_coap_parser_options_parse - COAP_OPTION_BLOCK1 not valid!");
leothedragon 0:25fa8795676b 523 return -1;
leothedragon 0:25fa8795676b 524 }
leothedragon 0:25fa8795676b 525 (*packet_data_pptr)++;
leothedragon 0:25fa8795676b 526
leothedragon 0:25fa8795676b 527 dst_coap_msg_ptr->options_list_ptr->block1 = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
leothedragon 0:25fa8795676b 528
leothedragon 0:25fa8795676b 529 break;
leothedragon 0:25fa8795676b 530
leothedragon 0:25fa8795676b 531 case COAP_OPTION_ACCEPT:
leothedragon 0:25fa8795676b 532 if ((option_len > 2) || (dst_coap_msg_ptr->options_list_ptr->accept != COAP_CT_NONE)) {
leothedragon 0:25fa8795676b 533 tr_error("sn_coap_parser_options_parse - COAP_OPTION_ACCEPT not valid!");
leothedragon 0:25fa8795676b 534 return -1;
leothedragon 0:25fa8795676b 535 }
leothedragon 0:25fa8795676b 536
leothedragon 0:25fa8795676b 537 (*packet_data_pptr)++;
leothedragon 0:25fa8795676b 538
leothedragon 0:25fa8795676b 539 dst_coap_msg_ptr->options_list_ptr->accept = (sn_coap_content_format_e) sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
leothedragon 0:25fa8795676b 540 break;
leothedragon 0:25fa8795676b 541
leothedragon 0:25fa8795676b 542 case COAP_OPTION_SIZE1:
leothedragon 0:25fa8795676b 543 if ((option_len > 4) || dst_coap_msg_ptr->options_list_ptr->use_size1) {
leothedragon 0:25fa8795676b 544 tr_error("sn_coap_parser_options_parse - COAP_OPTION_SIZE1 not valid!");
leothedragon 0:25fa8795676b 545 return -1;
leothedragon 0:25fa8795676b 546 }
leothedragon 0:25fa8795676b 547 dst_coap_msg_ptr->options_list_ptr->use_size1 = true;
leothedragon 0:25fa8795676b 548 (*packet_data_pptr)++;
leothedragon 0:25fa8795676b 549 dst_coap_msg_ptr->options_list_ptr->size1 = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
leothedragon 0:25fa8795676b 550 break;
leothedragon 0:25fa8795676b 551
leothedragon 0:25fa8795676b 552 case COAP_OPTION_SIZE2:
leothedragon 0:25fa8795676b 553 if ((option_len > 4) || dst_coap_msg_ptr->options_list_ptr->use_size2) {
leothedragon 0:25fa8795676b 554 tr_error("sn_coap_parser_options_parse - COAP_OPTION_SIZE2 not valid!");
leothedragon 0:25fa8795676b 555 return -1;
leothedragon 0:25fa8795676b 556 }
leothedragon 0:25fa8795676b 557 dst_coap_msg_ptr->options_list_ptr->use_size2 = true;
leothedragon 0:25fa8795676b 558 (*packet_data_pptr)++;
leothedragon 0:25fa8795676b 559 dst_coap_msg_ptr->options_list_ptr->size2 = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
leothedragon 0:25fa8795676b 560 break;
leothedragon 0:25fa8795676b 561
leothedragon 0:25fa8795676b 562 default:
leothedragon 0:25fa8795676b 563 tr_error("sn_coap_parser_options_parse - unknown option!");
leothedragon 0:25fa8795676b 564 return -1;
leothedragon 0:25fa8795676b 565 }
leothedragon 0:25fa8795676b 566
leothedragon 0:25fa8795676b 567 /* Check for overflow */
leothedragon 0:25fa8795676b 568 if ((*packet_data_pptr - packet_data_start_ptr) > packet_len) {
leothedragon 0:25fa8795676b 569 return -1;
leothedragon 0:25fa8795676b 570 }
leothedragon 0:25fa8795676b 571
leothedragon 0:25fa8795676b 572 message_left = packet_len - (*packet_data_pptr - packet_data_start_ptr);
leothedragon 0:25fa8795676b 573
leothedragon 0:25fa8795676b 574 }
leothedragon 0:25fa8795676b 575
leothedragon 0:25fa8795676b 576 return 0;
leothedragon 0:25fa8795676b 577 }
leothedragon 0:25fa8795676b 578
leothedragon 0:25fa8795676b 579
leothedragon 0:25fa8795676b 580 /**
leothedragon 0:25fa8795676b 581 * \fn static int8_t sn_coap_parser_options_parse_multiple_options(uint8_t **packet_data_pptr, uint8_t options_count_left, uint8_t *previous_option_number_ptr, uint8_t **dst_pptr,
leothedragon 0:25fa8795676b 582 * uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint16_t option_number_len)
leothedragon 0:25fa8795676b 583 *
leothedragon 0:25fa8795676b 584 * \brief Parses CoAP message's Uri-query options
leothedragon 0:25fa8795676b 585 *
leothedragon 0:25fa8795676b 586 * \param **packet_data_pptr is source for Packet data to be parsed to CoAP message
leothedragon 0:25fa8795676b 587 *
leothedragon 0:25fa8795676b 588 * \param *dst_coap_msg_ptr is destination for parsed CoAP message
leothedragon 0:25fa8795676b 589 *
leothedragon 0:25fa8795676b 590 * \param options_count_left tells how many options are unhandled in Packet data
leothedragon 0:25fa8795676b 591 *
leothedragon 0:25fa8795676b 592 * \param *previous_option_number_ptr is pointer to used and returned previous Option number
leothedragon 0:25fa8795676b 593 *
leothedragon 0:25fa8795676b 594 * \return Return value is count of Uri-query optios parsed. In failure case -1 is returned.
leothedragon 0:25fa8795676b 595 */
leothedragon 0:25fa8795676b 596 static int8_t sn_coap_parser_options_parse_multiple_options(struct coap_s *handle, uint8_t **packet_data_pptr, uint16_t packet_left_len, uint8_t **dst_pptr, uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint16_t option_number_len)
leothedragon 0:25fa8795676b 597 {
leothedragon 0:25fa8795676b 598 int16_t uri_query_needed_heap = sn_coap_parser_options_count_needed_memory_multiple_option(*packet_data_pptr, packet_left_len, option, option_number_len);
leothedragon 0:25fa8795676b 599 uint8_t *temp_parsed_uri_query_ptr = NULL;
leothedragon 0:25fa8795676b 600 uint8_t returned_option_counter = 0;
leothedragon 0:25fa8795676b 601
leothedragon 0:25fa8795676b 602 if (uri_query_needed_heap == -1) {
leothedragon 0:25fa8795676b 603 return -1;
leothedragon 0:25fa8795676b 604 }
leothedragon 0:25fa8795676b 605
leothedragon 0:25fa8795676b 606 if (uri_query_needed_heap) {
leothedragon 0:25fa8795676b 607 *dst_pptr = (uint8_t *) handle->sn_coap_protocol_malloc(uri_query_needed_heap);
leothedragon 0:25fa8795676b 608
leothedragon 0:25fa8795676b 609 if (*dst_pptr == NULL) {
leothedragon 0:25fa8795676b 610 tr_error("sn_coap_parser_options_parse_multiple_options - failed to allocate options!");
leothedragon 0:25fa8795676b 611 return -1;
leothedragon 0:25fa8795676b 612 }
leothedragon 0:25fa8795676b 613 }
leothedragon 0:25fa8795676b 614
leothedragon 0:25fa8795676b 615 *dst_len_ptr = uri_query_needed_heap;
leothedragon 0:25fa8795676b 616
leothedragon 0:25fa8795676b 617 temp_parsed_uri_query_ptr = *dst_pptr;
leothedragon 0:25fa8795676b 618
leothedragon 0:25fa8795676b 619 /* Loop all Uri-Query options */
leothedragon 0:25fa8795676b 620 while ((temp_parsed_uri_query_ptr - *dst_pptr) < uri_query_needed_heap) {
leothedragon 0:25fa8795676b 621 /* Check if this is first Uri-Query option */
leothedragon 0:25fa8795676b 622 if (returned_option_counter > 0) {
leothedragon 0:25fa8795676b 623 /* Uri-Query is modified to following format: temp1'\0'temp2'\0'temp3 i.e. */
leothedragon 0:25fa8795676b 624 /* Uri-Path is modified to following format: temp1\temp2\temp3 i.e. */
leothedragon 0:25fa8795676b 625 if (option == COAP_OPTION_URI_QUERY || option == COAP_OPTION_LOCATION_QUERY || option == COAP_OPTION_ETAG || option == COAP_OPTION_ACCEPT) {
leothedragon 0:25fa8795676b 626 memset(temp_parsed_uri_query_ptr, '&', 1);
leothedragon 0:25fa8795676b 627 } else if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) {
leothedragon 0:25fa8795676b 628 memset(temp_parsed_uri_query_ptr, '/', 1);
leothedragon 0:25fa8795676b 629 }
leothedragon 0:25fa8795676b 630
leothedragon 0:25fa8795676b 631 temp_parsed_uri_query_ptr++;
leothedragon 0:25fa8795676b 632 }
leothedragon 0:25fa8795676b 633
leothedragon 0:25fa8795676b 634 returned_option_counter++;
leothedragon 0:25fa8795676b 635
leothedragon 0:25fa8795676b 636 (*packet_data_pptr)++;
leothedragon 0:25fa8795676b 637
leothedragon 0:25fa8795676b 638 if (((temp_parsed_uri_query_ptr - *dst_pptr) + option_number_len) > uri_query_needed_heap) {
leothedragon 0:25fa8795676b 639 return -1;
leothedragon 0:25fa8795676b 640 }
leothedragon 0:25fa8795676b 641
leothedragon 0:25fa8795676b 642 memcpy(temp_parsed_uri_query_ptr, *packet_data_pptr, option_number_len);
leothedragon 0:25fa8795676b 643
leothedragon 0:25fa8795676b 644 (*packet_data_pptr) += option_number_len;
leothedragon 0:25fa8795676b 645 temp_parsed_uri_query_ptr += option_number_len;
leothedragon 0:25fa8795676b 646
leothedragon 0:25fa8795676b 647 if ((temp_parsed_uri_query_ptr - *dst_pptr) >= uri_query_needed_heap || ((**packet_data_pptr >> COAP_OPTIONS_OPTION_NUMBER_SHIFT) != 0)) {
leothedragon 0:25fa8795676b 648 return returned_option_counter;
leothedragon 0:25fa8795676b 649 }
leothedragon 0:25fa8795676b 650
leothedragon 0:25fa8795676b 651 option_number_len = (**packet_data_pptr & 0x0F);
leothedragon 0:25fa8795676b 652 if (option_number_len == 13) {
leothedragon 0:25fa8795676b 653 option_number_len = *(*packet_data_pptr + 1) + 13;
leothedragon 0:25fa8795676b 654 (*packet_data_pptr)++;
leothedragon 0:25fa8795676b 655 } else if (option_number_len == 14) {
leothedragon 0:25fa8795676b 656 option_number_len = *(*packet_data_pptr + 2);
leothedragon 0:25fa8795676b 657 option_number_len += (*(*packet_data_pptr + 1) << 8) + 269;
leothedragon 0:25fa8795676b 658 (*packet_data_pptr) += 2;
leothedragon 0:25fa8795676b 659 }
leothedragon 0:25fa8795676b 660 }
leothedragon 0:25fa8795676b 661
leothedragon 0:25fa8795676b 662 return returned_option_counter;
leothedragon 0:25fa8795676b 663 }
leothedragon 0:25fa8795676b 664
leothedragon 0:25fa8795676b 665
leothedragon 0:25fa8795676b 666
leothedragon 0:25fa8795676b 667
leothedragon 0:25fa8795676b 668 /**
leothedragon 0:25fa8795676b 669 * \fn static uint16_t sn_coap_parser_options_count_needed_memory_multiple_option(uint8_t *packet_data_ptr, uint8_t options_count_left, uint8_t previous_option_number, sn_coap_option_numbers_e option, uint16_t option_number_len)
leothedragon 0:25fa8795676b 670 *
leothedragon 0:25fa8795676b 671 * \brief Counts needed memory for uri query option
leothedragon 0:25fa8795676b 672 *
leothedragon 0:25fa8795676b 673 * \param *packet_data_ptr is start of source for Packet data to be parsed to CoAP message
leothedragon 0:25fa8795676b 674 *
leothedragon 0:25fa8795676b 675 * \param options_count_left tells how many options are unhandled in Packet data
leothedragon 0:25fa8795676b 676 *
leothedragon 0:25fa8795676b 677 * \param previous_option_number is previous Option number
leothedragon 0:25fa8795676b 678 *
leothedragon 0:25fa8795676b 679 * \param sn_coap_option_numbers_e option option number to be calculated
leothedragon 0:25fa8795676b 680 *
leothedragon 0:25fa8795676b 681 * \param uint16_t option_number_len length of the first option part
leothedragon 0:25fa8795676b 682 */
leothedragon 0:25fa8795676b 683 static int16_t sn_coap_parser_options_count_needed_memory_multiple_option(uint8_t *packet_data_ptr, uint16_t packet_left_len, sn_coap_option_numbers_e option, uint16_t option_number_len)
leothedragon 0:25fa8795676b 684 {
leothedragon 0:25fa8795676b 685 uint16_t ret_value = 0;
leothedragon 0:25fa8795676b 686 uint16_t i = 1;
leothedragon 0:25fa8795676b 687
leothedragon 0:25fa8795676b 688 /* Loop all Uri-Query options */
leothedragon 0:25fa8795676b 689 while (i <= packet_left_len) {
leothedragon 0:25fa8795676b 690 if (option == COAP_OPTION_LOCATION_PATH && option_number_len > 255) {
leothedragon 0:25fa8795676b 691 return -1;
leothedragon 0:25fa8795676b 692 }
leothedragon 0:25fa8795676b 693 if (option == COAP_OPTION_URI_PATH && option_number_len > 255) {
leothedragon 0:25fa8795676b 694 return -1;
leothedragon 0:25fa8795676b 695 }
leothedragon 0:25fa8795676b 696 if (option == COAP_OPTION_URI_QUERY && option_number_len > 255) {
leothedragon 0:25fa8795676b 697 return -1;
leothedragon 0:25fa8795676b 698 }
leothedragon 0:25fa8795676b 699 if (option == COAP_OPTION_LOCATION_QUERY && option_number_len > 255) {
leothedragon 0:25fa8795676b 700 return -1;
leothedragon 0:25fa8795676b 701 }
leothedragon 0:25fa8795676b 702 if (option == COAP_OPTION_ACCEPT && option_number_len > 2) {
leothedragon 0:25fa8795676b 703 return -1;
leothedragon 0:25fa8795676b 704 }
leothedragon 0:25fa8795676b 705 if (option == COAP_OPTION_ETAG && option_number_len > 8) {
leothedragon 0:25fa8795676b 706 return -1;
leothedragon 0:25fa8795676b 707 }
leothedragon 0:25fa8795676b 708
leothedragon 0:25fa8795676b 709 i += option_number_len;
leothedragon 0:25fa8795676b 710 ret_value += option_number_len + 1; /* + 1 is for separator */
leothedragon 0:25fa8795676b 711
leothedragon 0:25fa8795676b 712 if( i == packet_left_len ) {
leothedragon 0:25fa8795676b 713 break;
leothedragon 0:25fa8795676b 714 }
leothedragon 0:25fa8795676b 715 else if( i > packet_left_len ) {
leothedragon 0:25fa8795676b 716 return -1;
leothedragon 0:25fa8795676b 717 }
leothedragon 0:25fa8795676b 718
leothedragon 0:25fa8795676b 719 if ((*(packet_data_ptr + i) >> COAP_OPTIONS_OPTION_NUMBER_SHIFT) != 0) {
leothedragon 0:25fa8795676b 720 return (ret_value - 1); /* -1 because last Part path does not include separator */
leothedragon 0:25fa8795676b 721 }
leothedragon 0:25fa8795676b 722
leothedragon 0:25fa8795676b 723 option_number_len = (*(packet_data_ptr + i) & 0x0F);
leothedragon 0:25fa8795676b 724
leothedragon 0:25fa8795676b 725 if (option_number_len == 13) {
leothedragon 0:25fa8795676b 726
leothedragon 0:25fa8795676b 727 if(i + 1 >= packet_left_len) {
leothedragon 0:25fa8795676b 728 return -1;
leothedragon 0:25fa8795676b 729 }
leothedragon 0:25fa8795676b 730
leothedragon 0:25fa8795676b 731 i++;
leothedragon 0:25fa8795676b 732 option_number_len = *(packet_data_ptr + i) + 13;
leothedragon 0:25fa8795676b 733 } else if (option_number_len == 14) {
leothedragon 0:25fa8795676b 734
leothedragon 0:25fa8795676b 735 if(i + 2 >= packet_left_len) {
leothedragon 0:25fa8795676b 736 return -1;
leothedragon 0:25fa8795676b 737 }
leothedragon 0:25fa8795676b 738
leothedragon 0:25fa8795676b 739 option_number_len = *(packet_data_ptr + i + 2);
leothedragon 0:25fa8795676b 740 option_number_len += (*(packet_data_ptr + i + 1) << 8) + 269;
leothedragon 0:25fa8795676b 741 i += 2;
leothedragon 0:25fa8795676b 742 } else if (option_number_len == 15) {
leothedragon 0:25fa8795676b 743 return -1;
leothedragon 0:25fa8795676b 744 }
leothedragon 0:25fa8795676b 745 i++;
leothedragon 0:25fa8795676b 746
leothedragon 0:25fa8795676b 747 }
leothedragon 0:25fa8795676b 748
leothedragon 0:25fa8795676b 749 if (ret_value != 0) {
leothedragon 0:25fa8795676b 750 return (ret_value - 1); /* -1 because last Part path does not include separator */
leothedragon 0:25fa8795676b 751 } else {
leothedragon 0:25fa8795676b 752 return 0;
leothedragon 0:25fa8795676b 753 }
leothedragon 0:25fa8795676b 754 }
leothedragon 0:25fa8795676b 755
leothedragon 0:25fa8795676b 756 /**
leothedragon 0:25fa8795676b 757 * \fn static void sn_coap_parser_payload_parse(uint16_t packet_data_len, uint8_t *packet_data_ptr, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr)
leothedragon 0:25fa8795676b 758 *
leothedragon 0:25fa8795676b 759 * \brief Parses CoAP message's Payload part from given Packet data
leothedragon 0:25fa8795676b 760 *
leothedragon 0:25fa8795676b 761 * \param packet_data_len is length of given Packet data to be parsed to CoAP message
leothedragon 0:25fa8795676b 762 *
leothedragon 0:25fa8795676b 763 * \param *packet_data_ptr is start of source for Packet data to be parsed to CoAP message
leothedragon 0:25fa8795676b 764 *
leothedragon 0:25fa8795676b 765 * \param **packet_data_pptr is source for Packet data to be parsed to CoAP message
leothedragon 0:25fa8795676b 766 *
leothedragon 0:25fa8795676b 767 * \param *dst_coap_msg_ptr is destination for parsed CoAP message
leothedragon 0:25fa8795676b 768 *****************************************************************************/
leothedragon 0:25fa8795676b 769 static int8_t sn_coap_parser_payload_parse(uint16_t packet_data_len, uint8_t *packet_data_start_ptr, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr)
leothedragon 0:25fa8795676b 770 {
leothedragon 0:25fa8795676b 771 /* If there is payload */
leothedragon 0:25fa8795676b 772 if ((*packet_data_pptr - packet_data_start_ptr) < packet_data_len) {
leothedragon 0:25fa8795676b 773 if (**packet_data_pptr == 0xff) {
leothedragon 0:25fa8795676b 774 (*packet_data_pptr)++;
leothedragon 0:25fa8795676b 775 /* Parse Payload length */
leothedragon 0:25fa8795676b 776 dst_coap_msg_ptr->payload_len = packet_data_len - (*packet_data_pptr - packet_data_start_ptr);
leothedragon 0:25fa8795676b 777
leothedragon 0:25fa8795676b 778 /* The presence of a marker followed by a zero-length payload MUST be processed as a message format error */
leothedragon 0:25fa8795676b 779 if (dst_coap_msg_ptr->payload_len == 0) {
leothedragon 0:25fa8795676b 780 return -1;
leothedragon 0:25fa8795676b 781 }
leothedragon 0:25fa8795676b 782
leothedragon 0:25fa8795676b 783 /* Parse Payload by setting CoAP message's payload_ptr to point Payload in Packet data */
leothedragon 0:25fa8795676b 784 dst_coap_msg_ptr->payload_ptr = *packet_data_pptr;
leothedragon 0:25fa8795676b 785 }
leothedragon 0:25fa8795676b 786 /* No payload marker.. */
leothedragon 0:25fa8795676b 787 else {
leothedragon 0:25fa8795676b 788 tr_error("sn_coap_parser_payload_parse - payload marker not found!");
leothedragon 0:25fa8795676b 789 return -1;
leothedragon 0:25fa8795676b 790 }
leothedragon 0:25fa8795676b 791 }
leothedragon 0:25fa8795676b 792 return 0;
leothedragon 0:25fa8795676b 793 }
leothedragon 0:25fa8795676b 794