mbed 5.4 with sleep mode

Dependencies:  

Committer:
ranaumarnaeem
Date:
Wed May 24 07:51:33 2017 +0000
Revision:
38:f1bc6e867fcf
Parent:
34:d6ce8f961b8b
lss

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ranaumarnaeem 34:d6ce8f961b8b 1 /*
ranaumarnaeem 34:d6ce8f961b8b 2 * Copyright (c) 2015 Keith Cullen.
ranaumarnaeem 34:d6ce8f961b8b 3 * All Rights Reserved.
ranaumarnaeem 34:d6ce8f961b8b 4 *
ranaumarnaeem 34:d6ce8f961b8b 5 * Redistribution and use in source and binary forms, with or without
ranaumarnaeem 34:d6ce8f961b8b 6 * modification, are permitted provided that the following conditions
ranaumarnaeem 34:d6ce8f961b8b 7 * are met:
ranaumarnaeem 34:d6ce8f961b8b 8 * 1. Redistributions of source code must retain the above copyright
ranaumarnaeem 34:d6ce8f961b8b 9 * notice, this list of conditions and the following disclaimer.
ranaumarnaeem 34:d6ce8f961b8b 10 * 2. Redistributions in binary form must reproduce the above copyright
ranaumarnaeem 34:d6ce8f961b8b 11 * notice, this list of conditions and the following disclaimer in the
ranaumarnaeem 34:d6ce8f961b8b 12 * documentation and/or other materials provided with the distribution.
ranaumarnaeem 34:d6ce8f961b8b 13 * 3. The name of the author may not be used to endorse or promote products
ranaumarnaeem 34:d6ce8f961b8b 14 * derived from this software without specific prior written permission.
ranaumarnaeem 34:d6ce8f961b8b 15 *
ranaumarnaeem 34:d6ce8f961b8b 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
ranaumarnaeem 34:d6ce8f961b8b 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
ranaumarnaeem 34:d6ce8f961b8b 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
ranaumarnaeem 34:d6ce8f961b8b 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
ranaumarnaeem 34:d6ce8f961b8b 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
ranaumarnaeem 34:d6ce8f961b8b 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
ranaumarnaeem 34:d6ce8f961b8b 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
ranaumarnaeem 34:d6ce8f961b8b 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
ranaumarnaeem 34:d6ce8f961b8b 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ranaumarnaeem 34:d6ce8f961b8b 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ranaumarnaeem 34:d6ce8f961b8b 26 */
ranaumarnaeem 34:d6ce8f961b8b 27
ranaumarnaeem 34:d6ce8f961b8b 28 /**
ranaumarnaeem 34:d6ce8f961b8b 29 * @file coap_msg.c
ranaumarnaeem 34:d6ce8f961b8b 30 *
ranaumarnaeem 34:d6ce8f961b8b 31 * @brief Source file for the FreeCoAP message parser/formatter library
ranaumarnaeem 34:d6ce8f961b8b 32 */
ranaumarnaeem 34:d6ce8f961b8b 33
ranaumarnaeem 34:d6ce8f961b8b 34 #include <stdlib.h>
ranaumarnaeem 34:d6ce8f961b8b 35 #include <string.h>
ranaumarnaeem 34:d6ce8f961b8b 36 #include <stdint.h>
ranaumarnaeem 34:d6ce8f961b8b 37 #include <time.h>
ranaumarnaeem 34:d6ce8f961b8b 38 #include <errno.h>
ranaumarnaeem 34:d6ce8f961b8b 39 #include "coap_msg.h"
ranaumarnaeem 34:d6ce8f961b8b 40 #include "coap_client.h"
ranaumarnaeem 34:d6ce8f961b8b 41
ranaumarnaeem 34:d6ce8f961b8b 42 #define coap_msg_op_list_get_first(list) ((list)->first) /**< Get the first option from an option linked-list */
ranaumarnaeem 34:d6ce8f961b8b 43 #define coap_msg_op_list_get_last(list) ((list)->last) /**< Get the last option in an option linked-list */
ranaumarnaeem 34:d6ce8f961b8b 44 #define coap_msg_op_list_is_empty(list) ((list)->first == NULL) /**< Indicate whether or not an option linked-list is empty */
ranaumarnaeem 34:d6ce8f961b8b 45
ranaumarnaeem 34:d6ce8f961b8b 46 static int coap_msg_rand_init = 0; /**< Indicates whether or not the random number generator has been initialised */
ranaumarnaeem 34:d6ce8f961b8b 47
ranaumarnaeem 34:d6ce8f961b8b 48 void coap_msg_gen_rand_str(char *buf, size_t len)
ranaumarnaeem 34:d6ce8f961b8b 49 {
ranaumarnaeem 34:d6ce8f961b8b 50 size_t i = 0;
ranaumarnaeem 34:d6ce8f961b8b 51
ranaumarnaeem 34:d6ce8f961b8b 52 if (!coap_msg_rand_init)
ranaumarnaeem 34:d6ce8f961b8b 53 {
ranaumarnaeem 34:d6ce8f961b8b 54 srand(time(NULL));
ranaumarnaeem 34:d6ce8f961b8b 55 coap_msg_rand_init = 1;
ranaumarnaeem 34:d6ce8f961b8b 56 }
ranaumarnaeem 34:d6ce8f961b8b 57 for (i = 0; i < len; i++)
ranaumarnaeem 34:d6ce8f961b8b 58 {
ranaumarnaeem 34:d6ce8f961b8b 59 buf[i] = rand() & 0x000000ff;
ranaumarnaeem 34:d6ce8f961b8b 60 }
ranaumarnaeem 34:d6ce8f961b8b 61 }
ranaumarnaeem 34:d6ce8f961b8b 62
ranaumarnaeem 34:d6ce8f961b8b 63 int coap_msg_op_num_is_recognized(unsigned num)
ranaumarnaeem 34:d6ce8f961b8b 64 {
ranaumarnaeem 34:d6ce8f961b8b 65 switch (num)
ranaumarnaeem 34:d6ce8f961b8b 66 {
ranaumarnaeem 34:d6ce8f961b8b 67 case COAP_MSG_IF_MATCH:
ranaumarnaeem 34:d6ce8f961b8b 68 case COAP_MSG_URI_HOST:
ranaumarnaeem 34:d6ce8f961b8b 69 case COAP_MSG_ETAG:
ranaumarnaeem 34:d6ce8f961b8b 70 case COAP_MSG_IF_NONE_MATCH:
ranaumarnaeem 34:d6ce8f961b8b 71 case COAP_MSG_URI_PORT:
ranaumarnaeem 34:d6ce8f961b8b 72 case COAP_MSG_LOCATION_PATH:
ranaumarnaeem 34:d6ce8f961b8b 73 case COAP_MSG_URI_PATH:
ranaumarnaeem 34:d6ce8f961b8b 74 case COAP_MSG_CONTENT_FORMAT:
ranaumarnaeem 34:d6ce8f961b8b 75 case COAP_MSG_MAX_AGE:
ranaumarnaeem 34:d6ce8f961b8b 76 case COAP_MSG_URI_QUERY:
ranaumarnaeem 34:d6ce8f961b8b 77 case COAP_MSG_ACCEPT:
ranaumarnaeem 34:d6ce8f961b8b 78 case COAP_MSG_LOCATION_QUERY:
ranaumarnaeem 34:d6ce8f961b8b 79 case COAP_MSG_PROXY_URI:
ranaumarnaeem 34:d6ce8f961b8b 80 case COAP_MSG_PROXY_SCHEME:
ranaumarnaeem 34:d6ce8f961b8b 81 case COAP_MSG_SIZE1:
ranaumarnaeem 34:d6ce8f961b8b 82 return 1;
ranaumarnaeem 34:d6ce8f961b8b 83 }
ranaumarnaeem 34:d6ce8f961b8b 84 return 0;
ranaumarnaeem 34:d6ce8f961b8b 85 }
ranaumarnaeem 34:d6ce8f961b8b 86
ranaumarnaeem 34:d6ce8f961b8b 87 /**
ranaumarnaeem 34:d6ce8f961b8b 88 * @brief Allocate an option structure
ranaumarnaeem 34:d6ce8f961b8b 89 *
ranaumarnaeem 34:d6ce8f961b8b 90 * @param[in] num Option number
ranaumarnaeem 34:d6ce8f961b8b 91 * @param[in] len Option length
ranaumarnaeem 34:d6ce8f961b8b 92 * @param[in] val Pointer to the option value
ranaumarnaeem 34:d6ce8f961b8b 93 *
ranaumarnaeem 34:d6ce8f961b8b 94 * @returns Pointer to the option structure
ranaumarnaeem 34:d6ce8f961b8b 95 * @retval NULL Out-of-memory
ranaumarnaeem 34:d6ce8f961b8b 96 */
ranaumarnaeem 34:d6ce8f961b8b 97 static coap_msg_op_t *coap_msg_op_new(unsigned num, unsigned len, const char *val)
ranaumarnaeem 34:d6ce8f961b8b 98 {
ranaumarnaeem 34:d6ce8f961b8b 99 coap_msg_op_t *op = NULL;
ranaumarnaeem 34:d6ce8f961b8b 100
ranaumarnaeem 34:d6ce8f961b8b 101 op = (coap_msg_op_t *)malloc(sizeof(coap_msg_op_t));
ranaumarnaeem 34:d6ce8f961b8b 102 if (op == NULL)
ranaumarnaeem 34:d6ce8f961b8b 103 {
ranaumarnaeem 34:d6ce8f961b8b 104 return NULL;
ranaumarnaeem 34:d6ce8f961b8b 105 }
ranaumarnaeem 34:d6ce8f961b8b 106 op->num = num;
ranaumarnaeem 34:d6ce8f961b8b 107 op->len = len;
ranaumarnaeem 34:d6ce8f961b8b 108 op->val = (char *)malloc(len);
ranaumarnaeem 34:d6ce8f961b8b 109 if (op->val == NULL)
ranaumarnaeem 34:d6ce8f961b8b 110 {
ranaumarnaeem 34:d6ce8f961b8b 111 free(op);
ranaumarnaeem 34:d6ce8f961b8b 112 return NULL;
ranaumarnaeem 34:d6ce8f961b8b 113 }
ranaumarnaeem 34:d6ce8f961b8b 114 memcpy(op->val, val, len);
ranaumarnaeem 34:d6ce8f961b8b 115 op->next = NULL;
ranaumarnaeem 34:d6ce8f961b8b 116 return op;
ranaumarnaeem 34:d6ce8f961b8b 117 }
ranaumarnaeem 34:d6ce8f961b8b 118
ranaumarnaeem 34:d6ce8f961b8b 119 /**
ranaumarnaeem 34:d6ce8f961b8b 120 * @brief Free an option structure that was allocated by coap_msg_op_new
ranaumarnaeem 34:d6ce8f961b8b 121 *
ranaumarnaeem 34:d6ce8f961b8b 122 * @param[in,out] op Pointer to the option structure
ranaumarnaeem 34:d6ce8f961b8b 123 */
ranaumarnaeem 34:d6ce8f961b8b 124 static void coap_msg_op_delete(coap_msg_op_t *op)
ranaumarnaeem 34:d6ce8f961b8b 125 {
ranaumarnaeem 34:d6ce8f961b8b 126 free(op->val);
ranaumarnaeem 34:d6ce8f961b8b 127 free(op);
ranaumarnaeem 34:d6ce8f961b8b 128 }
ranaumarnaeem 34:d6ce8f961b8b 129
ranaumarnaeem 34:d6ce8f961b8b 130 /**
ranaumarnaeem 34:d6ce8f961b8b 131 * @brief Initialise an option linked-list structure
ranaumarnaeem 34:d6ce8f961b8b 132 *
ranaumarnaeem 34:d6ce8f961b8b 133 * @param[out] list Pointer to an option linked-list structure
ranaumarnaeem 34:d6ce8f961b8b 134 */
ranaumarnaeem 34:d6ce8f961b8b 135 static void coap_msg_op_list_create(coap_msg_op_list_t *list)
ranaumarnaeem 34:d6ce8f961b8b 136 {
ranaumarnaeem 34:d6ce8f961b8b 137 memset(list, 0, sizeof(coap_msg_op_list_t));
ranaumarnaeem 34:d6ce8f961b8b 138 }
ranaumarnaeem 34:d6ce8f961b8b 139
ranaumarnaeem 34:d6ce8f961b8b 140 /**
ranaumarnaeem 34:d6ce8f961b8b 141 * @brief Deinitialise an option linked-list structure
ranaumarnaeem 34:d6ce8f961b8b 142 *
ranaumarnaeem 34:d6ce8f961b8b 143 * @param[in,out] list Pointer to an option linked-list structure
ranaumarnaeem 34:d6ce8f961b8b 144 */
ranaumarnaeem 34:d6ce8f961b8b 145 static void coap_msg_op_list_destroy(coap_msg_op_list_t *list)
ranaumarnaeem 34:d6ce8f961b8b 146 {
ranaumarnaeem 34:d6ce8f961b8b 147 coap_msg_op_t *prev = NULL;
ranaumarnaeem 34:d6ce8f961b8b 148 coap_msg_op_t *op = NULL;
ranaumarnaeem 34:d6ce8f961b8b 149
ranaumarnaeem 34:d6ce8f961b8b 150 op = list->first;
ranaumarnaeem 34:d6ce8f961b8b 151 while (op != NULL)
ranaumarnaeem 34:d6ce8f961b8b 152 {
ranaumarnaeem 34:d6ce8f961b8b 153 prev = op;
ranaumarnaeem 34:d6ce8f961b8b 154 op = op->next;
ranaumarnaeem 34:d6ce8f961b8b 155 coap_msg_op_delete(prev);
ranaumarnaeem 34:d6ce8f961b8b 156 }
ranaumarnaeem 34:d6ce8f961b8b 157 memset(list, 0, sizeof(coap_msg_op_list_t));
ranaumarnaeem 34:d6ce8f961b8b 158 }
ranaumarnaeem 34:d6ce8f961b8b 159
ranaumarnaeem 34:d6ce8f961b8b 160 /**
ranaumarnaeem 34:d6ce8f961b8b 161 * @brief Allocate an option structure and add it to the end of an option linked-list structure
ranaumarnaeem 34:d6ce8f961b8b 162 *
ranaumarnaeem 34:d6ce8f961b8b 163 * @param[in,out] list Pointer to an option linked-list structure
ranaumarnaeem 34:d6ce8f961b8b 164 * @param[in] num Option number
ranaumarnaeem 34:d6ce8f961b8b 165 * @param[in] len Option length
ranaumarnaeem 34:d6ce8f961b8b 166 * @param[in] val Pointer to a buffer containing the option value
ranaumarnaeem 34:d6ce8f961b8b 167 *
ranaumarnaeem 34:d6ce8f961b8b 168 * @returns Operation status
ranaumarnaeem 34:d6ce8f961b8b 169 * @retval 0 Success
ranaumarnaeem 34:d6ce8f961b8b 170 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 171 */
ranaumarnaeem 34:d6ce8f961b8b 172 static int coap_msg_op_list_add_last(coap_msg_op_list_t *list, unsigned num, unsigned len, const char *val)
ranaumarnaeem 34:d6ce8f961b8b 173 {
ranaumarnaeem 34:d6ce8f961b8b 174 coap_msg_op_t *op = NULL;
ranaumarnaeem 34:d6ce8f961b8b 175
ranaumarnaeem 34:d6ce8f961b8b 176 op = coap_msg_op_new(num, len, val);
ranaumarnaeem 34:d6ce8f961b8b 177 if (op == NULL)
ranaumarnaeem 34:d6ce8f961b8b 178 {
ranaumarnaeem 34:d6ce8f961b8b 179 return -ENOMEM;
ranaumarnaeem 34:d6ce8f961b8b 180 }
ranaumarnaeem 34:d6ce8f961b8b 181 if (list->first == NULL)
ranaumarnaeem 34:d6ce8f961b8b 182 {
ranaumarnaeem 34:d6ce8f961b8b 183 list->first = op;
ranaumarnaeem 34:d6ce8f961b8b 184 list->last = op;
ranaumarnaeem 34:d6ce8f961b8b 185 }
ranaumarnaeem 34:d6ce8f961b8b 186 else
ranaumarnaeem 34:d6ce8f961b8b 187 {
ranaumarnaeem 34:d6ce8f961b8b 188 list->last->next = op;
ranaumarnaeem 34:d6ce8f961b8b 189 list->last = op;
ranaumarnaeem 34:d6ce8f961b8b 190 }
ranaumarnaeem 34:d6ce8f961b8b 191 return 0;
ranaumarnaeem 34:d6ce8f961b8b 192 }
ranaumarnaeem 34:d6ce8f961b8b 193
ranaumarnaeem 34:d6ce8f961b8b 194 /**
ranaumarnaeem 34:d6ce8f961b8b 195 * @brief Allocate an option structure and add it to an option linked-list structure
ranaumarnaeem 34:d6ce8f961b8b 196 *
ranaumarnaeem 34:d6ce8f961b8b 197 * The option is added to the list at a position determined by the option number.
ranaumarnaeem 34:d6ce8f961b8b 198 *
ranaumarnaeem 34:d6ce8f961b8b 199 * @param[in,out] list Pointer to an option linked-list structure
ranaumarnaeem 34:d6ce8f961b8b 200 * @param[in] num Option number
ranaumarnaeem 34:d6ce8f961b8b 201 * @param[in] len Option length
ranaumarnaeem 34:d6ce8f961b8b 202 * @param[in] val Pointer to a buffer containing the option value
ranaumarnaeem 34:d6ce8f961b8b 203 *
ranaumarnaeem 34:d6ce8f961b8b 204 * @returns Operation status
ranaumarnaeem 34:d6ce8f961b8b 205 * @retval 0 Success
ranaumarnaeem 34:d6ce8f961b8b 206 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 207 */
ranaumarnaeem 34:d6ce8f961b8b 208 static int coap_msg_op_list_add(coap_msg_op_list_t *list, unsigned num, unsigned len, const char *val)
ranaumarnaeem 34:d6ce8f961b8b 209 {
ranaumarnaeem 34:d6ce8f961b8b 210 coap_msg_op_t *prev = NULL;
ranaumarnaeem 34:d6ce8f961b8b 211 coap_msg_op_t *op = NULL;
ranaumarnaeem 34:d6ce8f961b8b 212
ranaumarnaeem 34:d6ce8f961b8b 213 op = coap_msg_op_new(num, len, val);
ranaumarnaeem 34:d6ce8f961b8b 214 if (op == NULL)
ranaumarnaeem 34:d6ce8f961b8b 215 {
ranaumarnaeem 34:d6ce8f961b8b 216 return -ENOMEM;
ranaumarnaeem 34:d6ce8f961b8b 217 }
ranaumarnaeem 34:d6ce8f961b8b 218 if (list->first == NULL)
ranaumarnaeem 34:d6ce8f961b8b 219 {
ranaumarnaeem 34:d6ce8f961b8b 220 /* empty list */
ranaumarnaeem 34:d6ce8f961b8b 221 list->first = op;
ranaumarnaeem 34:d6ce8f961b8b 222 list->last = op;
ranaumarnaeem 34:d6ce8f961b8b 223 return 0;
ranaumarnaeem 34:d6ce8f961b8b 224 }
ranaumarnaeem 34:d6ce8f961b8b 225 if (op->num < list->first->num)
ranaumarnaeem 34:d6ce8f961b8b 226 {
ranaumarnaeem 34:d6ce8f961b8b 227 /* start of the list */
ranaumarnaeem 34:d6ce8f961b8b 228 op->next = list->first;
ranaumarnaeem 34:d6ce8f961b8b 229 list->first = op;
ranaumarnaeem 34:d6ce8f961b8b 230 return 0;
ranaumarnaeem 34:d6ce8f961b8b 231 }
ranaumarnaeem 34:d6ce8f961b8b 232 prev = list->first;
ranaumarnaeem 34:d6ce8f961b8b 233 while (prev != list->last)
ranaumarnaeem 34:d6ce8f961b8b 234 {
ranaumarnaeem 34:d6ce8f961b8b 235 /* middle of the list */
ranaumarnaeem 34:d6ce8f961b8b 236 if ((prev->num <= op->num) && (op->num < prev->next->num))
ranaumarnaeem 34:d6ce8f961b8b 237 {
ranaumarnaeem 34:d6ce8f961b8b 238 op->next = prev->next;
ranaumarnaeem 34:d6ce8f961b8b 239 prev->next = op;
ranaumarnaeem 34:d6ce8f961b8b 240 return 0;
ranaumarnaeem 34:d6ce8f961b8b 241 }
ranaumarnaeem 34:d6ce8f961b8b 242 prev = prev->next;
ranaumarnaeem 34:d6ce8f961b8b 243 }
ranaumarnaeem 34:d6ce8f961b8b 244 /* end of the list */
ranaumarnaeem 34:d6ce8f961b8b 245 list->last->next = op;
ranaumarnaeem 34:d6ce8f961b8b 246 list->last = op;
ranaumarnaeem 34:d6ce8f961b8b 247 return 0;
ranaumarnaeem 34:d6ce8f961b8b 248 }
ranaumarnaeem 34:d6ce8f961b8b 249
ranaumarnaeem 34:d6ce8f961b8b 250 void coap_msg_create(coap_msg_t *msg)
ranaumarnaeem 34:d6ce8f961b8b 251 {
ranaumarnaeem 34:d6ce8f961b8b 252 memset(msg, 0, sizeof(coap_msg_t));
ranaumarnaeem 34:d6ce8f961b8b 253 msg->ver = COAP_MSG_VER;
ranaumarnaeem 34:d6ce8f961b8b 254 coap_msg_op_list_create(&msg->op_list);
ranaumarnaeem 34:d6ce8f961b8b 255 }
ranaumarnaeem 34:d6ce8f961b8b 256
ranaumarnaeem 34:d6ce8f961b8b 257 void coap_msg_destroy(coap_msg_t *msg)
ranaumarnaeem 34:d6ce8f961b8b 258 {
ranaumarnaeem 34:d6ce8f961b8b 259 coap_msg_op_list_destroy(&msg->op_list);
ranaumarnaeem 34:d6ce8f961b8b 260 if (msg->payload != NULL)
ranaumarnaeem 34:d6ce8f961b8b 261 {
ranaumarnaeem 34:d6ce8f961b8b 262 free(msg->payload);
ranaumarnaeem 34:d6ce8f961b8b 263 }
ranaumarnaeem 34:d6ce8f961b8b 264 memset(msg, 0, sizeof(coap_msg_t));
ranaumarnaeem 34:d6ce8f961b8b 265 }
ranaumarnaeem 34:d6ce8f961b8b 266
ranaumarnaeem 34:d6ce8f961b8b 267 void coap_msg_reset(coap_msg_t *msg)
ranaumarnaeem 34:d6ce8f961b8b 268 {
ranaumarnaeem 34:d6ce8f961b8b 269 coap_msg_destroy(msg);
ranaumarnaeem 34:d6ce8f961b8b 270 coap_msg_create(msg);
ranaumarnaeem 34:d6ce8f961b8b 271 }
ranaumarnaeem 34:d6ce8f961b8b 272
ranaumarnaeem 34:d6ce8f961b8b 273 /**
ranaumarnaeem 34:d6ce8f961b8b 274 * @brief Check a message for correctness
ranaumarnaeem 34:d6ce8f961b8b 275 *
ranaumarnaeem 34:d6ce8f961b8b 276 * The following checks from RFC7252 are performed:
ranaumarnaeem 34:d6ce8f961b8b 277 *
ranaumarnaeem 34:d6ce8f961b8b 278 * An Empty message has the Code field set to 0.00. The Token Length
ranaumarnaeem 34:d6ce8f961b8b 279 * field MUST be set to 0 and bytes of data MUST NOT be present after
ranaumarnaeem 34:d6ce8f961b8b 280 * the Message ID field. If there are any bytes, they MUST be processed
ranaumarnaeem 34:d6ce8f961b8b 281 * as a message format error.
ranaumarnaeem 34:d6ce8f961b8b 282 *
ranaumarnaeem 34:d6ce8f961b8b 283 * The Reset message MUST echo the Message ID of the Confirmable message
ranaumarnaeem 34:d6ce8f961b8b 284 * and MUST be Empty.
ranaumarnaeem 34:d6ce8f961b8b 285 *
ranaumarnaeem 34:d6ce8f961b8b 286 * A Non-confirmable message always carries either a request or response
ranaumarnaeem 34:d6ce8f961b8b 287 * and MUST NOT be Empty.
ranaumarnaeem 34:d6ce8f961b8b 288 *
ranaumarnaeem 34:d6ce8f961b8b 289 * @param[in] msg Pointer to a message structure
ranaumarnaeem 34:d6ce8f961b8b 290 * @returns Operation status
ranaumarnaeem 34:d6ce8f961b8b 291 * @retval 0 Success
ranaumarnaeem 34:d6ce8f961b8b 292 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 293 */
ranaumarnaeem 34:d6ce8f961b8b 294 static int coap_msg_check(coap_msg_t *msg)
ranaumarnaeem 34:d6ce8f961b8b 295 {
ranaumarnaeem 34:d6ce8f961b8b 296 if ((msg->code_class == 0) && (msg->code_detail == 0))
ranaumarnaeem 34:d6ce8f961b8b 297 {
ranaumarnaeem 34:d6ce8f961b8b 298 /* empty message */
ranaumarnaeem 34:d6ce8f961b8b 299 if ((msg->type == COAP_MSG_NON)
ranaumarnaeem 34:d6ce8f961b8b 300 || (msg->token_len != 0)
ranaumarnaeem 34:d6ce8f961b8b 301 || (!coap_msg_op_list_is_empty(&msg->op_list))
ranaumarnaeem 34:d6ce8f961b8b 302 || (msg->payload_len != 0))
ranaumarnaeem 34:d6ce8f961b8b 303 {
ranaumarnaeem 34:d6ce8f961b8b 304 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 305 }
ranaumarnaeem 34:d6ce8f961b8b 306 }
ranaumarnaeem 34:d6ce8f961b8b 307 else
ranaumarnaeem 34:d6ce8f961b8b 308 {
ranaumarnaeem 34:d6ce8f961b8b 309 /* non-empty message */
ranaumarnaeem 34:d6ce8f961b8b 310 if (msg->type == COAP_MSG_RST)
ranaumarnaeem 34:d6ce8f961b8b 311 {
ranaumarnaeem 34:d6ce8f961b8b 312 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 313 }
ranaumarnaeem 34:d6ce8f961b8b 314 }
ranaumarnaeem 34:d6ce8f961b8b 315 return 0;
ranaumarnaeem 34:d6ce8f961b8b 316 }
ranaumarnaeem 34:d6ce8f961b8b 317
ranaumarnaeem 34:d6ce8f961b8b 318 unsigned coap_msg_check_critical_ops(coap_msg_t *msg)
ranaumarnaeem 34:d6ce8f961b8b 319 {
ranaumarnaeem 34:d6ce8f961b8b 320 coap_msg_op_t *op = NULL;
ranaumarnaeem 34:d6ce8f961b8b 321 unsigned num = 0;
ranaumarnaeem 34:d6ce8f961b8b 322
ranaumarnaeem 34:d6ce8f961b8b 323 op = coap_msg_get_first_op(msg);
ranaumarnaeem 34:d6ce8f961b8b 324 while (op != NULL)
ranaumarnaeem 34:d6ce8f961b8b 325 {
ranaumarnaeem 34:d6ce8f961b8b 326 num = coap_msg_op_get_num(op);
ranaumarnaeem 34:d6ce8f961b8b 327 if ((coap_msg_op_num_is_critical(num))
ranaumarnaeem 34:d6ce8f961b8b 328 && (!coap_msg_op_num_is_recognized(num)))
ranaumarnaeem 34:d6ce8f961b8b 329 {
ranaumarnaeem 34:d6ce8f961b8b 330 return num; /* fail */
ranaumarnaeem 34:d6ce8f961b8b 331 }
ranaumarnaeem 34:d6ce8f961b8b 332 op = coap_msg_op_get_next(op);
ranaumarnaeem 34:d6ce8f961b8b 333 }
ranaumarnaeem 34:d6ce8f961b8b 334 return 0; /* pass */
ranaumarnaeem 34:d6ce8f961b8b 335 }
ranaumarnaeem 34:d6ce8f961b8b 336
ranaumarnaeem 34:d6ce8f961b8b 337 unsigned coap_msg_check_unsafe_ops(coap_msg_t *msg)
ranaumarnaeem 34:d6ce8f961b8b 338 {
ranaumarnaeem 34:d6ce8f961b8b 339 coap_msg_op_t *op = NULL;
ranaumarnaeem 34:d6ce8f961b8b 340 unsigned num = 0;
ranaumarnaeem 34:d6ce8f961b8b 341
ranaumarnaeem 34:d6ce8f961b8b 342 op = coap_msg_get_first_op(msg);
ranaumarnaeem 34:d6ce8f961b8b 343 while (op != NULL)
ranaumarnaeem 34:d6ce8f961b8b 344 {
ranaumarnaeem 34:d6ce8f961b8b 345 num = coap_msg_op_get_num(op);
ranaumarnaeem 34:d6ce8f961b8b 346 if ((coap_msg_op_num_is_unsafe(num))
ranaumarnaeem 34:d6ce8f961b8b 347 && (!coap_msg_op_num_is_recognized(num)))
ranaumarnaeem 34:d6ce8f961b8b 348 {
ranaumarnaeem 34:d6ce8f961b8b 349 return num; /* fail */
ranaumarnaeem 34:d6ce8f961b8b 350 }
ranaumarnaeem 34:d6ce8f961b8b 351 op = coap_msg_op_get_next(op);
ranaumarnaeem 34:d6ce8f961b8b 352 }
ranaumarnaeem 34:d6ce8f961b8b 353 return 0; /* pass */
ranaumarnaeem 34:d6ce8f961b8b 354 }
ranaumarnaeem 34:d6ce8f961b8b 355
ranaumarnaeem 34:d6ce8f961b8b 356 int coap_msg_parse_type_msg_id(char *buf, size_t len, unsigned *type, unsigned *msg_id)
ranaumarnaeem 34:d6ce8f961b8b 357 {
ranaumarnaeem 34:d6ce8f961b8b 358 if (len < 4)
ranaumarnaeem 34:d6ce8f961b8b 359 {
ranaumarnaeem 34:d6ce8f961b8b 360 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 361 }
ranaumarnaeem 34:d6ce8f961b8b 362 *type = (buf[0] >> 4) & 0x03;
ranaumarnaeem 34:d6ce8f961b8b 363 *msg_id = ntohs(*((uint16_t *)(&buf[2])));
ranaumarnaeem 34:d6ce8f961b8b 364 return 0;
ranaumarnaeem 34:d6ce8f961b8b 365 }
ranaumarnaeem 34:d6ce8f961b8b 366
ranaumarnaeem 34:d6ce8f961b8b 367 /**
ranaumarnaeem 34:d6ce8f961b8b 368 * @brief Parse the header in a message
ranaumarnaeem 34:d6ce8f961b8b 369 *
ranaumarnaeem 34:d6ce8f961b8b 370 * @param[out] msg Pointer to a message structure
ranaumarnaeem 34:d6ce8f961b8b 371 * @param[in] buf Pointer to a buffer containing the message
ranaumarnaeem 34:d6ce8f961b8b 372 * @param[in] len Length of the buffer
ranaumarnaeem 34:d6ce8f961b8b 373 *
ranaumarnaeem 34:d6ce8f961b8b 374 * @returns Number of bytes parsed or error code
ranaumarnaeem 34:d6ce8f961b8b 375 * @retval >0 Number of bytes parsed
ranaumarnaeem 34:d6ce8f961b8b 376 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 377 */
ranaumarnaeem 34:d6ce8f961b8b 378 static int coap_msg_parse_hdr(coap_msg_t *msg, char *buf, size_t len)
ranaumarnaeem 34:d6ce8f961b8b 379 {
ranaumarnaeem 34:d6ce8f961b8b 380 char *p = buf;
ranaumarnaeem 34:d6ce8f961b8b 381
ranaumarnaeem 34:d6ce8f961b8b 382 if (len < 4)
ranaumarnaeem 34:d6ce8f961b8b 383 {
ranaumarnaeem 34:d6ce8f961b8b 384 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 385 }
ranaumarnaeem 34:d6ce8f961b8b 386 msg->ver = (p[0] >> 6) & 0x03;
ranaumarnaeem 34:d6ce8f961b8b 387 if (msg->ver != COAP_MSG_VER)
ranaumarnaeem 34:d6ce8f961b8b 388 {
ranaumarnaeem 34:d6ce8f961b8b 389 return -EINVAL;
ranaumarnaeem 34:d6ce8f961b8b 390 }
ranaumarnaeem 34:d6ce8f961b8b 391 msg->type = (p[0] >> 4) & 0x03;
ranaumarnaeem 34:d6ce8f961b8b 392 msg->token_len = p[0] & 0x0f;
ranaumarnaeem 34:d6ce8f961b8b 393 if (msg->token_len > sizeof(msg->token))
ranaumarnaeem 34:d6ce8f961b8b 394 {
ranaumarnaeem 34:d6ce8f961b8b 395 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 396 }
ranaumarnaeem 34:d6ce8f961b8b 397 msg->code_detail = p[1] & 0x1f;
ranaumarnaeem 34:d6ce8f961b8b 398 msg->code_class = (p[1] >> 5) & 0x07;
ranaumarnaeem 34:d6ce8f961b8b 399 if ((msg->code_class != COAP_MSG_REQ)
ranaumarnaeem 34:d6ce8f961b8b 400 && (msg->code_class != COAP_MSG_SUCCESS)
ranaumarnaeem 34:d6ce8f961b8b 401 && (msg->code_class != COAP_MSG_CLIENT_ERR)
ranaumarnaeem 34:d6ce8f961b8b 402 && (msg->code_class != COAP_MSG_SERVER_ERR))
ranaumarnaeem 34:d6ce8f961b8b 403 {
ranaumarnaeem 34:d6ce8f961b8b 404 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 405 }
ranaumarnaeem 34:d6ce8f961b8b 406 msg->msg_id = ntohs(*((uint16_t *)(&p[2])));
ranaumarnaeem 34:d6ce8f961b8b 407 p += 4;
ranaumarnaeem 34:d6ce8f961b8b 408 len -= 4;
ranaumarnaeem 34:d6ce8f961b8b 409 return p - buf;
ranaumarnaeem 34:d6ce8f961b8b 410 }
ranaumarnaeem 34:d6ce8f961b8b 411
ranaumarnaeem 34:d6ce8f961b8b 412 /**
ranaumarnaeem 34:d6ce8f961b8b 413 * @brief Parse the token in a message
ranaumarnaeem 34:d6ce8f961b8b 414 *
ranaumarnaeem 34:d6ce8f961b8b 415 * @param[out] msg Pointer to a message structure
ranaumarnaeem 34:d6ce8f961b8b 416 * @param[in] buf Pointer to a buffer containing the message
ranaumarnaeem 34:d6ce8f961b8b 417 * @param[in] len Length of the buffer
ranaumarnaeem 34:d6ce8f961b8b 418 *
ranaumarnaeem 34:d6ce8f961b8b 419 * @returns Number of bytes parsed or error code
ranaumarnaeem 34:d6ce8f961b8b 420 * @retval >0 Number of bytes parsed
ranaumarnaeem 34:d6ce8f961b8b 421 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 422 */
ranaumarnaeem 34:d6ce8f961b8b 423 static int coap_msg_parse_token(coap_msg_t *msg, char *buf, size_t len)
ranaumarnaeem 34:d6ce8f961b8b 424 {
ranaumarnaeem 34:d6ce8f961b8b 425 if (len < msg->token_len)
ranaumarnaeem 34:d6ce8f961b8b 426 {
ranaumarnaeem 34:d6ce8f961b8b 427 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 428 }
ranaumarnaeem 34:d6ce8f961b8b 429 memcpy(msg->token, buf, msg->token_len);
ranaumarnaeem 34:d6ce8f961b8b 430 return msg->token_len;
ranaumarnaeem 34:d6ce8f961b8b 431 }
ranaumarnaeem 34:d6ce8f961b8b 432
ranaumarnaeem 34:d6ce8f961b8b 433 /**
ranaumarnaeem 34:d6ce8f961b8b 434 * @brief Parse an option in a message
ranaumarnaeem 34:d6ce8f961b8b 435 *
ranaumarnaeem 34:d6ce8f961b8b 436 * @param[in,out] msg Pointer to a message structure
ranaumarnaeem 34:d6ce8f961b8b 437 * @param[in] buf Pointer to a buffer containing the message
ranaumarnaeem 34:d6ce8f961b8b 438 * @param[in] len Length of the buffer
ranaumarnaeem 34:d6ce8f961b8b 439 *
ranaumarnaeem 34:d6ce8f961b8b 440 * @returns Number of bytes parsed or error code
ranaumarnaeem 34:d6ce8f961b8b 441 * @retval >0 Number of bytes parsed
ranaumarnaeem 34:d6ce8f961b8b 442 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 443 */
ranaumarnaeem 34:d6ce8f961b8b 444 static int coap_msg_parse_op(coap_msg_t *msg, char *buf, size_t len)
ranaumarnaeem 34:d6ce8f961b8b 445 {
ranaumarnaeem 34:d6ce8f961b8b 446 coap_msg_op_t *prev = NULL;
ranaumarnaeem 34:d6ce8f961b8b 447 unsigned op_delta = 0;
ranaumarnaeem 34:d6ce8f961b8b 448 unsigned op_len = 0;
ranaumarnaeem 34:d6ce8f961b8b 449 unsigned op_num = 0;
ranaumarnaeem 34:d6ce8f961b8b 450 char *p = buf;
ranaumarnaeem 34:d6ce8f961b8b 451 int ret = 0;
ranaumarnaeem 34:d6ce8f961b8b 452
ranaumarnaeem 34:d6ce8f961b8b 453 if (len < 1)
ranaumarnaeem 34:d6ce8f961b8b 454 {
ranaumarnaeem 34:d6ce8f961b8b 455 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 456 }
ranaumarnaeem 34:d6ce8f961b8b 457 op_delta = (p[0] >> 4) & 0x0f;
ranaumarnaeem 34:d6ce8f961b8b 458 op_len = p[0] & 0x0f;
ranaumarnaeem 34:d6ce8f961b8b 459 if ((op_delta == 15) || (op_len == 15))
ranaumarnaeem 34:d6ce8f961b8b 460 {
ranaumarnaeem 34:d6ce8f961b8b 461 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 462 }
ranaumarnaeem 34:d6ce8f961b8b 463 p++;
ranaumarnaeem 34:d6ce8f961b8b 464 len--;
ranaumarnaeem 34:d6ce8f961b8b 465 if (op_delta == 13)
ranaumarnaeem 34:d6ce8f961b8b 466 {
ranaumarnaeem 34:d6ce8f961b8b 467 if (len < 1)
ranaumarnaeem 34:d6ce8f961b8b 468 {
ranaumarnaeem 34:d6ce8f961b8b 469 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 470 }
ranaumarnaeem 34:d6ce8f961b8b 471 op_delta += p[0];
ranaumarnaeem 34:d6ce8f961b8b 472 p++;
ranaumarnaeem 34:d6ce8f961b8b 473 len--;
ranaumarnaeem 34:d6ce8f961b8b 474 }
ranaumarnaeem 34:d6ce8f961b8b 475 else if (op_delta == 14)
ranaumarnaeem 34:d6ce8f961b8b 476 {
ranaumarnaeem 34:d6ce8f961b8b 477 if (len < 2)
ranaumarnaeem 34:d6ce8f961b8b 478 {
ranaumarnaeem 34:d6ce8f961b8b 479 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 480 }
ranaumarnaeem 34:d6ce8f961b8b 481 op_delta = 269 + ntohs(*((uint16_t *)(&p[0])));
ranaumarnaeem 34:d6ce8f961b8b 482 p += 2;
ranaumarnaeem 34:d6ce8f961b8b 483 len -= 2;
ranaumarnaeem 34:d6ce8f961b8b 484 }
ranaumarnaeem 34:d6ce8f961b8b 485 if (op_len == 13)
ranaumarnaeem 34:d6ce8f961b8b 486 {
ranaumarnaeem 34:d6ce8f961b8b 487 if (len < 1)
ranaumarnaeem 34:d6ce8f961b8b 488 {
ranaumarnaeem 34:d6ce8f961b8b 489 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 490 }
ranaumarnaeem 34:d6ce8f961b8b 491 op_len += p[0];
ranaumarnaeem 34:d6ce8f961b8b 492 p++;
ranaumarnaeem 34:d6ce8f961b8b 493 len--;
ranaumarnaeem 34:d6ce8f961b8b 494 }
ranaumarnaeem 34:d6ce8f961b8b 495 else if (op_len == 14)
ranaumarnaeem 34:d6ce8f961b8b 496 {
ranaumarnaeem 34:d6ce8f961b8b 497 if (len < 2)
ranaumarnaeem 34:d6ce8f961b8b 498 {
ranaumarnaeem 34:d6ce8f961b8b 499 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 500 }
ranaumarnaeem 34:d6ce8f961b8b 501 op_len = 269 + ntohs(*((uint16_t *)(&p[0])));
ranaumarnaeem 34:d6ce8f961b8b 502 p += 2;
ranaumarnaeem 34:d6ce8f961b8b 503 len -= 2;
ranaumarnaeem 34:d6ce8f961b8b 504 }
ranaumarnaeem 34:d6ce8f961b8b 505 if (len < op_len)
ranaumarnaeem 34:d6ce8f961b8b 506 {
ranaumarnaeem 34:d6ce8f961b8b 507 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 508 }
ranaumarnaeem 34:d6ce8f961b8b 509 prev = coap_msg_op_list_get_last(&msg->op_list);
ranaumarnaeem 34:d6ce8f961b8b 510 if (prev == NULL)
ranaumarnaeem 34:d6ce8f961b8b 511 {
ranaumarnaeem 34:d6ce8f961b8b 512 op_num = op_delta;
ranaumarnaeem 34:d6ce8f961b8b 513 }
ranaumarnaeem 34:d6ce8f961b8b 514 else
ranaumarnaeem 34:d6ce8f961b8b 515 {
ranaumarnaeem 34:d6ce8f961b8b 516 op_num = coap_msg_op_get_num(prev) + op_delta;
ranaumarnaeem 34:d6ce8f961b8b 517 }
ranaumarnaeem 34:d6ce8f961b8b 518 ret = coap_msg_op_list_add_last(&msg->op_list, op_num, op_len, p);
ranaumarnaeem 34:d6ce8f961b8b 519 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 520 {
ranaumarnaeem 34:d6ce8f961b8b 521 return ret;
ranaumarnaeem 34:d6ce8f961b8b 522 }
ranaumarnaeem 34:d6ce8f961b8b 523 p += op_len;
ranaumarnaeem 34:d6ce8f961b8b 524 return p - buf;
ranaumarnaeem 34:d6ce8f961b8b 525 }
ranaumarnaeem 34:d6ce8f961b8b 526
ranaumarnaeem 34:d6ce8f961b8b 527 /**
ranaumarnaeem 34:d6ce8f961b8b 528 * @brief Parse the options in a message
ranaumarnaeem 34:d6ce8f961b8b 529 *
ranaumarnaeem 34:d6ce8f961b8b 530 * @param[in,out] msg Pointer to a message structure
ranaumarnaeem 34:d6ce8f961b8b 531 * @param[in] buf Pointer to a buffer containing the message
ranaumarnaeem 34:d6ce8f961b8b 532 * @param[in] len Length of the buffer
ranaumarnaeem 34:d6ce8f961b8b 533 *
ranaumarnaeem 34:d6ce8f961b8b 534 * @returns Number of bytes parsed or error code
ranaumarnaeem 34:d6ce8f961b8b 535 * @retval >0 Number of bytes parsed
ranaumarnaeem 34:d6ce8f961b8b 536 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 537 */
ranaumarnaeem 34:d6ce8f961b8b 538 static int coap_msg_parse_ops(coap_msg_t *msg, char *buf, size_t len)
ranaumarnaeem 34:d6ce8f961b8b 539 {
ranaumarnaeem 34:d6ce8f961b8b 540 int num = 0;
ranaumarnaeem 34:d6ce8f961b8b 541 char *p = buf;
ranaumarnaeem 34:d6ce8f961b8b 542
ranaumarnaeem 34:d6ce8f961b8b 543 while (1)
ranaumarnaeem 34:d6ce8f961b8b 544 {
ranaumarnaeem 34:d6ce8f961b8b 545 if (((p[0] & 0xff) == 0xff) || (len == 0))
ranaumarnaeem 34:d6ce8f961b8b 546 {
ranaumarnaeem 34:d6ce8f961b8b 547 break;
ranaumarnaeem 34:d6ce8f961b8b 548 }
ranaumarnaeem 34:d6ce8f961b8b 549 num = coap_msg_parse_op(msg, p, len);
ranaumarnaeem 34:d6ce8f961b8b 550 if (num < 0)
ranaumarnaeem 34:d6ce8f961b8b 551 {
ranaumarnaeem 34:d6ce8f961b8b 552 return num;
ranaumarnaeem 34:d6ce8f961b8b 553 }
ranaumarnaeem 34:d6ce8f961b8b 554 p += num;
ranaumarnaeem 34:d6ce8f961b8b 555 len -= num;
ranaumarnaeem 34:d6ce8f961b8b 556 }
ranaumarnaeem 34:d6ce8f961b8b 557 return p - buf;
ranaumarnaeem 34:d6ce8f961b8b 558 }
ranaumarnaeem 34:d6ce8f961b8b 559
ranaumarnaeem 34:d6ce8f961b8b 560 /**
ranaumarnaeem 34:d6ce8f961b8b 561 * @brief Parse the payload in a message
ranaumarnaeem 34:d6ce8f961b8b 562 *
ranaumarnaeem 34:d6ce8f961b8b 563 * @param[out] msg Pointer to a message structure
ranaumarnaeem 34:d6ce8f961b8b 564 * @param[in] buf Pointer to a buffer containing the message
ranaumarnaeem 34:d6ce8f961b8b 565 * @param[in] len Length of the buffer
ranaumarnaeem 34:d6ce8f961b8b 566 *
ranaumarnaeem 34:d6ce8f961b8b 567 * @returns Number of bytes parsed or error code
ranaumarnaeem 34:d6ce8f961b8b 568 * @retval >0 Number of bytes parsed
ranaumarnaeem 34:d6ce8f961b8b 569 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 570 */
ranaumarnaeem 34:d6ce8f961b8b 571 static int coap_msg_parse_payload(coap_msg_t *msg, char *buf, size_t len)
ranaumarnaeem 34:d6ce8f961b8b 572 {
ranaumarnaeem 34:d6ce8f961b8b 573 char *p = buf;
ranaumarnaeem 34:d6ce8f961b8b 574
ranaumarnaeem 34:d6ce8f961b8b 575 if (len == 0)
ranaumarnaeem 34:d6ce8f961b8b 576 {
ranaumarnaeem 34:d6ce8f961b8b 577 return 0;
ranaumarnaeem 34:d6ce8f961b8b 578 }
ranaumarnaeem 34:d6ce8f961b8b 579 if ((p[0] & 0xff) != 0xff)
ranaumarnaeem 34:d6ce8f961b8b 580 {
ranaumarnaeem 34:d6ce8f961b8b 581 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 582 }
ranaumarnaeem 34:d6ce8f961b8b 583 p++;
ranaumarnaeem 34:d6ce8f961b8b 584 len--;
ranaumarnaeem 34:d6ce8f961b8b 585 if (len == 0)
ranaumarnaeem 34:d6ce8f961b8b 586 {
ranaumarnaeem 34:d6ce8f961b8b 587 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 588 }
ranaumarnaeem 34:d6ce8f961b8b 589 msg->payload = (char *)malloc(len);
ranaumarnaeem 34:d6ce8f961b8b 590 if (msg->payload == NULL)
ranaumarnaeem 34:d6ce8f961b8b 591 {
ranaumarnaeem 34:d6ce8f961b8b 592 return -ENOMEM;
ranaumarnaeem 34:d6ce8f961b8b 593 }
ranaumarnaeem 34:d6ce8f961b8b 594 memcpy(msg->payload, p, len);
ranaumarnaeem 34:d6ce8f961b8b 595 msg->payload_len = len;
ranaumarnaeem 34:d6ce8f961b8b 596 p += len;
ranaumarnaeem 34:d6ce8f961b8b 597 return p - buf;
ranaumarnaeem 34:d6ce8f961b8b 598 }
ranaumarnaeem 34:d6ce8f961b8b 599
ranaumarnaeem 34:d6ce8f961b8b 600 int coap_msg_parse(coap_msg_t *msg, char *buf, size_t len)
ranaumarnaeem 34:d6ce8f961b8b 601 {
ranaumarnaeem 34:d6ce8f961b8b 602 int num = 0;
ranaumarnaeem 34:d6ce8f961b8b 603 char *p = buf;
ranaumarnaeem 34:d6ce8f961b8b 604
ranaumarnaeem 34:d6ce8f961b8b 605 coap_msg_reset(msg);
ranaumarnaeem 34:d6ce8f961b8b 606 num = coap_msg_parse_hdr(msg, p, len);
ranaumarnaeem 34:d6ce8f961b8b 607 if (num < 0)
ranaumarnaeem 34:d6ce8f961b8b 608 {
ranaumarnaeem 34:d6ce8f961b8b 609 coap_msg_destroy(msg);
ranaumarnaeem 34:d6ce8f961b8b 610 return num;
ranaumarnaeem 34:d6ce8f961b8b 611 }
ranaumarnaeem 34:d6ce8f961b8b 612 p += num;
ranaumarnaeem 34:d6ce8f961b8b 613 len -= num;
ranaumarnaeem 34:d6ce8f961b8b 614 num = coap_msg_parse_token(msg, p, len);
ranaumarnaeem 34:d6ce8f961b8b 615 if (num < 0)
ranaumarnaeem 34:d6ce8f961b8b 616 {
ranaumarnaeem 34:d6ce8f961b8b 617 coap_msg_destroy(msg);
ranaumarnaeem 34:d6ce8f961b8b 618 return num;
ranaumarnaeem 34:d6ce8f961b8b 619 }
ranaumarnaeem 34:d6ce8f961b8b 620 p += num;
ranaumarnaeem 34:d6ce8f961b8b 621 len -= num;
ranaumarnaeem 34:d6ce8f961b8b 622 num = coap_msg_parse_ops(msg, p, len);
ranaumarnaeem 34:d6ce8f961b8b 623 if (num < 0)
ranaumarnaeem 34:d6ce8f961b8b 624 {
ranaumarnaeem 34:d6ce8f961b8b 625 coap_msg_destroy(msg);
ranaumarnaeem 34:d6ce8f961b8b 626 return num;
ranaumarnaeem 34:d6ce8f961b8b 627 }
ranaumarnaeem 34:d6ce8f961b8b 628 p += num;
ranaumarnaeem 34:d6ce8f961b8b 629 len -= num;
ranaumarnaeem 34:d6ce8f961b8b 630 num = coap_msg_parse_payload(msg, p, len);
ranaumarnaeem 34:d6ce8f961b8b 631 if (num < 0)
ranaumarnaeem 34:d6ce8f961b8b 632 {
ranaumarnaeem 34:d6ce8f961b8b 633 coap_msg_destroy(msg);
ranaumarnaeem 34:d6ce8f961b8b 634 return num;
ranaumarnaeem 34:d6ce8f961b8b 635 }
ranaumarnaeem 34:d6ce8f961b8b 636 return coap_msg_check(msg);
ranaumarnaeem 34:d6ce8f961b8b 637 }
ranaumarnaeem 34:d6ce8f961b8b 638
ranaumarnaeem 34:d6ce8f961b8b 639 int coap_msg_set_type(coap_msg_t *msg, unsigned type)
ranaumarnaeem 34:d6ce8f961b8b 640 {
ranaumarnaeem 34:d6ce8f961b8b 641 if ((type != COAP_MSG_CON)
ranaumarnaeem 34:d6ce8f961b8b 642 && (type != COAP_MSG_NON)
ranaumarnaeem 34:d6ce8f961b8b 643 && (type != COAP_MSG_ACK)
ranaumarnaeem 34:d6ce8f961b8b 644 && (type != COAP_MSG_RST))
ranaumarnaeem 34:d6ce8f961b8b 645 {
ranaumarnaeem 34:d6ce8f961b8b 646 return -EINVAL;
ranaumarnaeem 34:d6ce8f961b8b 647 }
ranaumarnaeem 34:d6ce8f961b8b 648 msg->type = type;
ranaumarnaeem 34:d6ce8f961b8b 649 return 0;
ranaumarnaeem 34:d6ce8f961b8b 650 }
ranaumarnaeem 34:d6ce8f961b8b 651
ranaumarnaeem 34:d6ce8f961b8b 652 int coap_msg_set_code(coap_msg_t *msg, unsigned code_class, unsigned code_detail)
ranaumarnaeem 34:d6ce8f961b8b 653 {
ranaumarnaeem 34:d6ce8f961b8b 654 if (code_class > COAP_MSG_MAX_CODE_CLASS)
ranaumarnaeem 34:d6ce8f961b8b 655 {
ranaumarnaeem 34:d6ce8f961b8b 656 return -EINVAL;
ranaumarnaeem 34:d6ce8f961b8b 657 }
ranaumarnaeem 34:d6ce8f961b8b 658 if (code_detail > COAP_MSG_MAX_CODE_DETAIL)
ranaumarnaeem 34:d6ce8f961b8b 659 {
ranaumarnaeem 34:d6ce8f961b8b 660 return -EINVAL;
ranaumarnaeem 34:d6ce8f961b8b 661 }
ranaumarnaeem 34:d6ce8f961b8b 662 msg->code_class = code_class;
ranaumarnaeem 34:d6ce8f961b8b 663 msg->code_detail = code_detail;
ranaumarnaeem 34:d6ce8f961b8b 664 return 0;
ranaumarnaeem 34:d6ce8f961b8b 665 }
ranaumarnaeem 34:d6ce8f961b8b 666
ranaumarnaeem 34:d6ce8f961b8b 667 int coap_msg_set_msg_id(coap_msg_t *msg, unsigned msg_id)
ranaumarnaeem 34:d6ce8f961b8b 668 {
ranaumarnaeem 34:d6ce8f961b8b 669 if (msg_id > COAP_MSG_MAX_MSG_ID)
ranaumarnaeem 34:d6ce8f961b8b 670 {
ranaumarnaeem 34:d6ce8f961b8b 671 return -EINVAL;
ranaumarnaeem 34:d6ce8f961b8b 672 }
ranaumarnaeem 34:d6ce8f961b8b 673 msg->msg_id = msg_id;
ranaumarnaeem 34:d6ce8f961b8b 674 return 0;
ranaumarnaeem 34:d6ce8f961b8b 675 }
ranaumarnaeem 34:d6ce8f961b8b 676
ranaumarnaeem 34:d6ce8f961b8b 677 int coap_msg_set_token(coap_msg_t *msg, char *buf, size_t len)
ranaumarnaeem 34:d6ce8f961b8b 678 {
ranaumarnaeem 34:d6ce8f961b8b 679 if (len > COAP_MSG_MAX_TOKEN_LEN)
ranaumarnaeem 34:d6ce8f961b8b 680 {
ranaumarnaeem 34:d6ce8f961b8b 681 return -EINVAL;
ranaumarnaeem 34:d6ce8f961b8b 682 }
ranaumarnaeem 34:d6ce8f961b8b 683 memcpy(msg->token, buf, len);
ranaumarnaeem 34:d6ce8f961b8b 684 msg->token_len = len;
ranaumarnaeem 34:d6ce8f961b8b 685 return 0;
ranaumarnaeem 34:d6ce8f961b8b 686 }
ranaumarnaeem 34:d6ce8f961b8b 687
ranaumarnaeem 34:d6ce8f961b8b 688 int coap_msg_add_op(coap_msg_t *msg, unsigned num, unsigned len, const char *val)
ranaumarnaeem 34:d6ce8f961b8b 689 {
ranaumarnaeem 34:d6ce8f961b8b 690 return coap_msg_op_list_add(&msg->op_list, num, len, val);
ranaumarnaeem 34:d6ce8f961b8b 691 }
ranaumarnaeem 34:d6ce8f961b8b 692
ranaumarnaeem 34:d6ce8f961b8b 693 int coap_msg_set_payload(coap_msg_t *msg, char *buf, size_t len)
ranaumarnaeem 34:d6ce8f961b8b 694 {
ranaumarnaeem 34:d6ce8f961b8b 695 msg->payload_len = 0;
ranaumarnaeem 34:d6ce8f961b8b 696 if (msg->payload != NULL)
ranaumarnaeem 34:d6ce8f961b8b 697 {
ranaumarnaeem 34:d6ce8f961b8b 698 free(msg->payload);
ranaumarnaeem 34:d6ce8f961b8b 699 msg->payload = NULL;
ranaumarnaeem 34:d6ce8f961b8b 700 }
ranaumarnaeem 34:d6ce8f961b8b 701 if (len > 0)
ranaumarnaeem 34:d6ce8f961b8b 702 {
ranaumarnaeem 34:d6ce8f961b8b 703 msg->payload = (char *)malloc(len);
ranaumarnaeem 34:d6ce8f961b8b 704 if (msg->payload == NULL)
ranaumarnaeem 34:d6ce8f961b8b 705 {
ranaumarnaeem 34:d6ce8f961b8b 706 return -ENOMEM;
ranaumarnaeem 34:d6ce8f961b8b 707 }
ranaumarnaeem 34:d6ce8f961b8b 708 memcpy(msg->payload, buf, len);
ranaumarnaeem 34:d6ce8f961b8b 709 msg->payload_len = len;
ranaumarnaeem 34:d6ce8f961b8b 710 }
ranaumarnaeem 34:d6ce8f961b8b 711 return 0;
ranaumarnaeem 34:d6ce8f961b8b 712 }
ranaumarnaeem 34:d6ce8f961b8b 713
ranaumarnaeem 34:d6ce8f961b8b 714 /**
ranaumarnaeem 34:d6ce8f961b8b 715 * @brief Format the header in a message
ranaumarnaeem 34:d6ce8f961b8b 716 *
ranaumarnaeem 34:d6ce8f961b8b 717 * @param[in] msg Pointer to a message structure
ranaumarnaeem 34:d6ce8f961b8b 718 * @param[out] buf Pointer to a buffer to contain the formatted message
ranaumarnaeem 34:d6ce8f961b8b 719 * @param[in] len Length of the buffer
ranaumarnaeem 34:d6ce8f961b8b 720 *
ranaumarnaeem 34:d6ce8f961b8b 721 * @returns Length of the formatted message or error code
ranaumarnaeem 34:d6ce8f961b8b 722 * @retval >0 Length of the formatted message
ranaumarnaeem 34:d6ce8f961b8b 723 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 724 */
ranaumarnaeem 34:d6ce8f961b8b 725 static int coap_msg_format_hdr(coap_msg_t *msg, char *buf, size_t len)
ranaumarnaeem 34:d6ce8f961b8b 726 {
ranaumarnaeem 34:d6ce8f961b8b 727 uint16_t msg_id = 0;
ranaumarnaeem 34:d6ce8f961b8b 728
ranaumarnaeem 34:d6ce8f961b8b 729 if (len < 4)
ranaumarnaeem 34:d6ce8f961b8b 730 {
ranaumarnaeem 34:d6ce8f961b8b 731 return -ENOSPC;
ranaumarnaeem 34:d6ce8f961b8b 732 }
ranaumarnaeem 34:d6ce8f961b8b 733 buf[0] = (char)((COAP_MSG_VER << 6)
ranaumarnaeem 34:d6ce8f961b8b 734 | ((msg->type & 0x03) << 4)
ranaumarnaeem 34:d6ce8f961b8b 735 | (msg->token_len & 0x0f));
ranaumarnaeem 34:d6ce8f961b8b 736 buf[1] = (char)(((msg->code_class & 0x07) << 5)
ranaumarnaeem 34:d6ce8f961b8b 737 | (msg->code_detail & 0x1f));
ranaumarnaeem 34:d6ce8f961b8b 738 msg_id = htons(msg->msg_id);
ranaumarnaeem 34:d6ce8f961b8b 739 memcpy(&buf[2], &msg_id, 2);
ranaumarnaeem 34:d6ce8f961b8b 740 return 4;
ranaumarnaeem 34:d6ce8f961b8b 741 }
ranaumarnaeem 34:d6ce8f961b8b 742
ranaumarnaeem 34:d6ce8f961b8b 743 /**
ranaumarnaeem 34:d6ce8f961b8b 744 * @brief Format the token in a message
ranaumarnaeem 34:d6ce8f961b8b 745 *
ranaumarnaeem 34:d6ce8f961b8b 746 * @param[in] msg Pointer to a message structure
ranaumarnaeem 34:d6ce8f961b8b 747 * @param[out] buf Pointer to a buffer to contain the formatted message
ranaumarnaeem 34:d6ce8f961b8b 748 * @param[in] len Length of the buffer
ranaumarnaeem 34:d6ce8f961b8b 749 *
ranaumarnaeem 34:d6ce8f961b8b 750 * @returns Length of the formatted message or error code
ranaumarnaeem 34:d6ce8f961b8b 751 * @retval >0 Length of the formatted message
ranaumarnaeem 34:d6ce8f961b8b 752 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 753 */
ranaumarnaeem 34:d6ce8f961b8b 754 static int coap_msg_format_token(coap_msg_t *msg, char *buf, size_t len)
ranaumarnaeem 34:d6ce8f961b8b 755 {
ranaumarnaeem 34:d6ce8f961b8b 756 if (len < msg->token_len)
ranaumarnaeem 34:d6ce8f961b8b 757 {
ranaumarnaeem 34:d6ce8f961b8b 758 return -ENOSPC;
ranaumarnaeem 34:d6ce8f961b8b 759 }
ranaumarnaeem 34:d6ce8f961b8b 760 memcpy(buf, msg->token, msg->token_len);
ranaumarnaeem 34:d6ce8f961b8b 761 return msg->token_len;
ranaumarnaeem 34:d6ce8f961b8b 762 }
ranaumarnaeem 34:d6ce8f961b8b 763
ranaumarnaeem 34:d6ce8f961b8b 764 /**
ranaumarnaeem 34:d6ce8f961b8b 765 * @brief Format an option in a message
ranaumarnaeem 34:d6ce8f961b8b 766 *
ranaumarnaeem 34:d6ce8f961b8b 767 * @param[in] op Pointer to an option structure
ranaumarnaeem 34:d6ce8f961b8b 768 * @param[in] prev_num option number of the previous option
ranaumarnaeem 34:d6ce8f961b8b 769 * @param[out] buf Pointer to a buffer to contain the formatted message
ranaumarnaeem 34:d6ce8f961b8b 770 * @param[in] len Length of the buffer
ranaumarnaeem 34:d6ce8f961b8b 771 *
ranaumarnaeem 34:d6ce8f961b8b 772 * @returns Length of the formatted message or error code
ranaumarnaeem 34:d6ce8f961b8b 773 * @retval >0 Length of the formatted message
ranaumarnaeem 34:d6ce8f961b8b 774 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 775 */
ranaumarnaeem 34:d6ce8f961b8b 776 static int coap_msg_format_op(coap_msg_op_t *op, unsigned prev_num, char *buf, size_t len)
ranaumarnaeem 34:d6ce8f961b8b 777 {
ranaumarnaeem 34:d6ce8f961b8b 778 unsigned op_delta = 0;
ranaumarnaeem 34:d6ce8f961b8b 779 unsigned num = 0;
ranaumarnaeem 34:d6ce8f961b8b 780 uint16_t val = 0;
ranaumarnaeem 34:d6ce8f961b8b 781 char *p = buf;
ranaumarnaeem 34:d6ce8f961b8b 782
ranaumarnaeem 34:d6ce8f961b8b 783 op_delta = op->num - prev_num;
ranaumarnaeem 34:d6ce8f961b8b 784 num++;
ranaumarnaeem 34:d6ce8f961b8b 785
ranaumarnaeem 34:d6ce8f961b8b 786 /* option delta */
ranaumarnaeem 34:d6ce8f961b8b 787 if (op_delta >= 269)
ranaumarnaeem 34:d6ce8f961b8b 788 {
ranaumarnaeem 34:d6ce8f961b8b 789 num += 2;
ranaumarnaeem 34:d6ce8f961b8b 790 }
ranaumarnaeem 34:d6ce8f961b8b 791 else if (op_delta >= 13)
ranaumarnaeem 34:d6ce8f961b8b 792 {
ranaumarnaeem 34:d6ce8f961b8b 793 num += 1;
ranaumarnaeem 34:d6ce8f961b8b 794 }
ranaumarnaeem 34:d6ce8f961b8b 795
ranaumarnaeem 34:d6ce8f961b8b 796 /* option length */
ranaumarnaeem 34:d6ce8f961b8b 797 if (op->len >= 269)
ranaumarnaeem 34:d6ce8f961b8b 798 {
ranaumarnaeem 34:d6ce8f961b8b 799 num += 2;
ranaumarnaeem 34:d6ce8f961b8b 800 }
ranaumarnaeem 34:d6ce8f961b8b 801 else if (op->num >= 13)
ranaumarnaeem 34:d6ce8f961b8b 802 {
ranaumarnaeem 34:d6ce8f961b8b 803 num += 1;
ranaumarnaeem 34:d6ce8f961b8b 804 }
ranaumarnaeem 34:d6ce8f961b8b 805
ranaumarnaeem 34:d6ce8f961b8b 806 /* option value */
ranaumarnaeem 34:d6ce8f961b8b 807 num += op->len;
ranaumarnaeem 34:d6ce8f961b8b 808 if (num > len)
ranaumarnaeem 34:d6ce8f961b8b 809 {
ranaumarnaeem 34:d6ce8f961b8b 810 return -ENOSPC;
ranaumarnaeem 34:d6ce8f961b8b 811 }
ranaumarnaeem 34:d6ce8f961b8b 812
ranaumarnaeem 34:d6ce8f961b8b 813 /* option delta */
ranaumarnaeem 34:d6ce8f961b8b 814 if (op_delta >= 269)
ranaumarnaeem 34:d6ce8f961b8b 815 {
ranaumarnaeem 34:d6ce8f961b8b 816 p[0] = 14 << 4;
ranaumarnaeem 34:d6ce8f961b8b 817 }
ranaumarnaeem 34:d6ce8f961b8b 818 else if (op_delta >= 13)
ranaumarnaeem 34:d6ce8f961b8b 819 {
ranaumarnaeem 34:d6ce8f961b8b 820 p[0] = 13 << 4;
ranaumarnaeem 34:d6ce8f961b8b 821 }
ranaumarnaeem 34:d6ce8f961b8b 822 else
ranaumarnaeem 34:d6ce8f961b8b 823 {
ranaumarnaeem 34:d6ce8f961b8b 824 p[0] = op_delta << 4;
ranaumarnaeem 34:d6ce8f961b8b 825 }
ranaumarnaeem 34:d6ce8f961b8b 826
ranaumarnaeem 34:d6ce8f961b8b 827 /* option length */
ranaumarnaeem 34:d6ce8f961b8b 828 if (op->len >= 269)
ranaumarnaeem 34:d6ce8f961b8b 829 {
ranaumarnaeem 34:d6ce8f961b8b 830 p[0] |= 14;
ranaumarnaeem 34:d6ce8f961b8b 831 }
ranaumarnaeem 34:d6ce8f961b8b 832 else if (op->len >= 13)
ranaumarnaeem 34:d6ce8f961b8b 833 {
ranaumarnaeem 34:d6ce8f961b8b 834 p[0] |= 13;
ranaumarnaeem 34:d6ce8f961b8b 835 }
ranaumarnaeem 34:d6ce8f961b8b 836 else
ranaumarnaeem 34:d6ce8f961b8b 837 {
ranaumarnaeem 34:d6ce8f961b8b 838 p[0] |= op->len;
ranaumarnaeem 34:d6ce8f961b8b 839 }
ranaumarnaeem 34:d6ce8f961b8b 840 p++;
ranaumarnaeem 34:d6ce8f961b8b 841 len--;
ranaumarnaeem 34:d6ce8f961b8b 842
ranaumarnaeem 34:d6ce8f961b8b 843 /* option delta extended */
ranaumarnaeem 34:d6ce8f961b8b 844 if (op_delta >= 269)
ranaumarnaeem 34:d6ce8f961b8b 845 {
ranaumarnaeem 34:d6ce8f961b8b 846 val = htons(op_delta - 269);
ranaumarnaeem 34:d6ce8f961b8b 847 memcpy(p, &val, 2);
ranaumarnaeem 34:d6ce8f961b8b 848 p += 2;
ranaumarnaeem 34:d6ce8f961b8b 849 len -= 2;
ranaumarnaeem 34:d6ce8f961b8b 850 }
ranaumarnaeem 34:d6ce8f961b8b 851 else if (op_delta >= 13)
ranaumarnaeem 34:d6ce8f961b8b 852 {
ranaumarnaeem 34:d6ce8f961b8b 853 p[0] = op_delta - 13;
ranaumarnaeem 34:d6ce8f961b8b 854 p++;
ranaumarnaeem 34:d6ce8f961b8b 855 len--;
ranaumarnaeem 34:d6ce8f961b8b 856 }
ranaumarnaeem 34:d6ce8f961b8b 857
ranaumarnaeem 34:d6ce8f961b8b 858 /* option length extended */
ranaumarnaeem 34:d6ce8f961b8b 859 if (op->len >= 269)
ranaumarnaeem 34:d6ce8f961b8b 860 {
ranaumarnaeem 34:d6ce8f961b8b 861 val = htons(op->len - 269);
ranaumarnaeem 34:d6ce8f961b8b 862 memcpy(p, &val, 2);
ranaumarnaeem 34:d6ce8f961b8b 863 p += 2;
ranaumarnaeem 34:d6ce8f961b8b 864 len -= 2;
ranaumarnaeem 34:d6ce8f961b8b 865 }
ranaumarnaeem 34:d6ce8f961b8b 866 else if (op->len >= 13)
ranaumarnaeem 34:d6ce8f961b8b 867 {
ranaumarnaeem 34:d6ce8f961b8b 868 p[0] = op->len - 13;
ranaumarnaeem 34:d6ce8f961b8b 869 p++;
ranaumarnaeem 34:d6ce8f961b8b 870 len--;
ranaumarnaeem 34:d6ce8f961b8b 871 }
ranaumarnaeem 34:d6ce8f961b8b 872
ranaumarnaeem 34:d6ce8f961b8b 873 /* option value */
ranaumarnaeem 34:d6ce8f961b8b 874 memcpy(p, op->val, op->len);
ranaumarnaeem 34:d6ce8f961b8b 875 p += op->len;
ranaumarnaeem 34:d6ce8f961b8b 876
ranaumarnaeem 34:d6ce8f961b8b 877 return p - buf;
ranaumarnaeem 34:d6ce8f961b8b 878 }
ranaumarnaeem 34:d6ce8f961b8b 879
ranaumarnaeem 34:d6ce8f961b8b 880 /**
ranaumarnaeem 34:d6ce8f961b8b 881 * @brief Format the options in a message
ranaumarnaeem 34:d6ce8f961b8b 882 *
ranaumarnaeem 34:d6ce8f961b8b 883 * @param[in] msg Pointer to a message structure
ranaumarnaeem 34:d6ce8f961b8b 884 * @param[out] buf Pointer to a buffer to contain the formatted message
ranaumarnaeem 34:d6ce8f961b8b 885 * @param[in] len Length of the buffer
ranaumarnaeem 34:d6ce8f961b8b 886 *
ranaumarnaeem 34:d6ce8f961b8b 887 * @returns Length of the formatted message or error code
ranaumarnaeem 34:d6ce8f961b8b 888 * @retval >0 Length of the formatted message
ranaumarnaeem 34:d6ce8f961b8b 889 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 890 */
ranaumarnaeem 34:d6ce8f961b8b 891 static int coap_msg_format_ops(coap_msg_t *msg, char *buf, size_t len)
ranaumarnaeem 34:d6ce8f961b8b 892 {
ranaumarnaeem 34:d6ce8f961b8b 893 coap_msg_op_t *op = NULL;
ranaumarnaeem 34:d6ce8f961b8b 894 unsigned prev_num = 0;
ranaumarnaeem 34:d6ce8f961b8b 895 int num = 0;
ranaumarnaeem 34:d6ce8f961b8b 896 char *p = buf;
ranaumarnaeem 34:d6ce8f961b8b 897
ranaumarnaeem 34:d6ce8f961b8b 898 op = coap_msg_op_list_get_first(&msg->op_list);
ranaumarnaeem 34:d6ce8f961b8b 899 while (op != NULL)
ranaumarnaeem 34:d6ce8f961b8b 900 {
ranaumarnaeem 34:d6ce8f961b8b 901 num = coap_msg_format_op(op, prev_num, p, len);
ranaumarnaeem 34:d6ce8f961b8b 902 if (num < 0)
ranaumarnaeem 34:d6ce8f961b8b 903 {
ranaumarnaeem 34:d6ce8f961b8b 904 return num;
ranaumarnaeem 34:d6ce8f961b8b 905 }
ranaumarnaeem 34:d6ce8f961b8b 906 p += num;
ranaumarnaeem 34:d6ce8f961b8b 907 len -= num;
ranaumarnaeem 34:d6ce8f961b8b 908 prev_num = coap_msg_op_get_num(op);
ranaumarnaeem 34:d6ce8f961b8b 909 op = coap_msg_op_get_next(op);
ranaumarnaeem 34:d6ce8f961b8b 910 }
ranaumarnaeem 34:d6ce8f961b8b 911 return p - buf;
ranaumarnaeem 34:d6ce8f961b8b 912 }
ranaumarnaeem 34:d6ce8f961b8b 913
ranaumarnaeem 34:d6ce8f961b8b 914 /**
ranaumarnaeem 34:d6ce8f961b8b 915 * @brief Format the payload in a message
ranaumarnaeem 34:d6ce8f961b8b 916 *
ranaumarnaeem 34:d6ce8f961b8b 917 * @param[in] msg Pointer to a message structure
ranaumarnaeem 34:d6ce8f961b8b 918 * @param[out] buf Pointer to a buffer to contain the formatted message
ranaumarnaeem 34:d6ce8f961b8b 919 * @param[in] len Length of the buffer
ranaumarnaeem 34:d6ce8f961b8b 920 *
ranaumarnaeem 34:d6ce8f961b8b 921 * @returns Length of the formatted message or error code
ranaumarnaeem 34:d6ce8f961b8b 922 * @retval >0 Length of the formatted message
ranaumarnaeem 34:d6ce8f961b8b 923 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 924 */
ranaumarnaeem 34:d6ce8f961b8b 925 static int coap_msg_format_payload(coap_msg_t *msg, char *buf, size_t len)
ranaumarnaeem 34:d6ce8f961b8b 926 {
ranaumarnaeem 34:d6ce8f961b8b 927 if (msg->payload_len == 0)
ranaumarnaeem 34:d6ce8f961b8b 928 {
ranaumarnaeem 34:d6ce8f961b8b 929 return 0;
ranaumarnaeem 34:d6ce8f961b8b 930 }
ranaumarnaeem 34:d6ce8f961b8b 931 if (msg->payload_len + 1 > len)
ranaumarnaeem 34:d6ce8f961b8b 932 {
ranaumarnaeem 34:d6ce8f961b8b 933 return -ENOSPC;
ranaumarnaeem 34:d6ce8f961b8b 934 }
ranaumarnaeem 34:d6ce8f961b8b 935 buf[0] = 0xff;
ranaumarnaeem 34:d6ce8f961b8b 936 memcpy(&buf[1], msg->payload, msg->payload_len);
ranaumarnaeem 34:d6ce8f961b8b 937 return msg->payload_len + 1;
ranaumarnaeem 34:d6ce8f961b8b 938 }
ranaumarnaeem 34:d6ce8f961b8b 939
ranaumarnaeem 34:d6ce8f961b8b 940 int coap_msg_format(coap_msg_t *msg, char *buf, size_t len)
ranaumarnaeem 34:d6ce8f961b8b 941 {
ranaumarnaeem 34:d6ce8f961b8b 942 int num = 0;
ranaumarnaeem 34:d6ce8f961b8b 943 char *p = buf;
ranaumarnaeem 34:d6ce8f961b8b 944 int ret = 0;
ranaumarnaeem 34:d6ce8f961b8b 945
ranaumarnaeem 34:d6ce8f961b8b 946 ret = coap_msg_check(msg);
ranaumarnaeem 34:d6ce8f961b8b 947 if (ret != 0)
ranaumarnaeem 34:d6ce8f961b8b 948 {
ranaumarnaeem 34:d6ce8f961b8b 949 return ret;
ranaumarnaeem 34:d6ce8f961b8b 950 }
ranaumarnaeem 34:d6ce8f961b8b 951 num = coap_msg_format_hdr(msg, p, len);
ranaumarnaeem 34:d6ce8f961b8b 952 if (num < 0)
ranaumarnaeem 34:d6ce8f961b8b 953 {
ranaumarnaeem 34:d6ce8f961b8b 954 return num;
ranaumarnaeem 34:d6ce8f961b8b 955 }
ranaumarnaeem 34:d6ce8f961b8b 956 p += num;
ranaumarnaeem 34:d6ce8f961b8b 957 len -= num;
ranaumarnaeem 34:d6ce8f961b8b 958 num = coap_msg_format_token(msg, p, len);
ranaumarnaeem 34:d6ce8f961b8b 959 if (num < 0)
ranaumarnaeem 34:d6ce8f961b8b 960 {
ranaumarnaeem 34:d6ce8f961b8b 961 return num;
ranaumarnaeem 34:d6ce8f961b8b 962 }
ranaumarnaeem 34:d6ce8f961b8b 963 p += num;
ranaumarnaeem 34:d6ce8f961b8b 964 len -= num;
ranaumarnaeem 34:d6ce8f961b8b 965 num = coap_msg_format_ops(msg, p, len);
ranaumarnaeem 34:d6ce8f961b8b 966 if (num < 0)
ranaumarnaeem 34:d6ce8f961b8b 967 {
ranaumarnaeem 34:d6ce8f961b8b 968 return num;
ranaumarnaeem 34:d6ce8f961b8b 969 }
ranaumarnaeem 34:d6ce8f961b8b 970 p += num;
ranaumarnaeem 34:d6ce8f961b8b 971 len -= num;
ranaumarnaeem 34:d6ce8f961b8b 972 num = coap_msg_format_payload(msg, p, len);
ranaumarnaeem 34:d6ce8f961b8b 973 if (num < 0)
ranaumarnaeem 34:d6ce8f961b8b 974 {
ranaumarnaeem 34:d6ce8f961b8b 975 return num;
ranaumarnaeem 34:d6ce8f961b8b 976 }
ranaumarnaeem 34:d6ce8f961b8b 977 p += num;
ranaumarnaeem 34:d6ce8f961b8b 978 return p - buf;
ranaumarnaeem 34:d6ce8f961b8b 979 }
ranaumarnaeem 34:d6ce8f961b8b 980
ranaumarnaeem 34:d6ce8f961b8b 981 int coap_msg_copy(coap_msg_t *dst, coap_msg_t *src)
ranaumarnaeem 34:d6ce8f961b8b 982 {
ranaumarnaeem 34:d6ce8f961b8b 983 coap_msg_op_t *op = NULL;
ranaumarnaeem 34:d6ce8f961b8b 984 int ret = 0;
ranaumarnaeem 34:d6ce8f961b8b 985
ranaumarnaeem 34:d6ce8f961b8b 986 dst->ver = src->ver;
ranaumarnaeem 34:d6ce8f961b8b 987 ret = coap_msg_set_type(dst, coap_msg_get_type(src));
ranaumarnaeem 34:d6ce8f961b8b 988 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 989 {
ranaumarnaeem 34:d6ce8f961b8b 990 return ret;
ranaumarnaeem 34:d6ce8f961b8b 991 }
ranaumarnaeem 34:d6ce8f961b8b 992 ret = coap_msg_set_code(dst, coap_msg_get_code_class(src), coap_msg_get_code_detail(src));
ranaumarnaeem 34:d6ce8f961b8b 993 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 994 {
ranaumarnaeem 34:d6ce8f961b8b 995 return ret;
ranaumarnaeem 34:d6ce8f961b8b 996 }
ranaumarnaeem 34:d6ce8f961b8b 997 ret = coap_msg_set_msg_id(dst, coap_msg_get_msg_id(src));
ranaumarnaeem 34:d6ce8f961b8b 998 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 999 {
ranaumarnaeem 34:d6ce8f961b8b 1000 return ret;
ranaumarnaeem 34:d6ce8f961b8b 1001 }
ranaumarnaeem 34:d6ce8f961b8b 1002 ret = coap_msg_set_token(dst, coap_msg_get_token(src), coap_msg_get_token_len(src));
ranaumarnaeem 34:d6ce8f961b8b 1003 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 1004 {
ranaumarnaeem 34:d6ce8f961b8b 1005 return ret;
ranaumarnaeem 34:d6ce8f961b8b 1006 }
ranaumarnaeem 34:d6ce8f961b8b 1007 op = coap_msg_get_first_op(src);
ranaumarnaeem 34:d6ce8f961b8b 1008 while (op != NULL)
ranaumarnaeem 34:d6ce8f961b8b 1009 {
ranaumarnaeem 34:d6ce8f961b8b 1010 ret = coap_msg_add_op(dst, coap_msg_op_get_num(op), coap_msg_op_get_len(op), coap_msg_op_get_val(op));
ranaumarnaeem 34:d6ce8f961b8b 1011 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 1012 {
ranaumarnaeem 34:d6ce8f961b8b 1013 return ret;
ranaumarnaeem 34:d6ce8f961b8b 1014 }
ranaumarnaeem 34:d6ce8f961b8b 1015 op = coap_msg_op_get_next(op);
ranaumarnaeem 34:d6ce8f961b8b 1016 }
ranaumarnaeem 34:d6ce8f961b8b 1017 ret = coap_msg_set_payload(dst, coap_msg_get_payload(src), coap_msg_get_payload_len(src));
ranaumarnaeem 34:d6ce8f961b8b 1018 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 1019 {
ranaumarnaeem 34:d6ce8f961b8b 1020 return ret;
ranaumarnaeem 34:d6ce8f961b8b 1021 }
ranaumarnaeem 34:d6ce8f961b8b 1022 return 0;
ranaumarnaeem 34:d6ce8f961b8b 1023 }
ranaumarnaeem 34:d6ce8f961b8b 1024