mbed 5.4 with sleep mode

Dependencies:   C027_Support mbed-dev

Fork of C027_SupportTest_coap by Umar Naeem

Committer:
ranaumarnaeem
Date:
Fri Mar 24 05:42:34 2017 +0000
Revision:
34:d6ce8f961b8b
0.1

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_client.c
ranaumarnaeem 34:d6ce8f961b8b 30 *
ranaumarnaeem 34:d6ce8f961b8b 31 * @brief Source file for the FreeCoAP client library
ranaumarnaeem 34:d6ce8f961b8b 32 */
ranaumarnaeem 34:d6ce8f961b8b 33
ranaumarnaeem 34:d6ce8f961b8b 34 #include <stdlib.h>
ranaumarnaeem 34:d6ce8f961b8b 35 #include <stdio.h>
ranaumarnaeem 34:d6ce8f961b8b 36 #include <string.h>
ranaumarnaeem 34:d6ce8f961b8b 37 #include <stdint.h>
ranaumarnaeem 34:d6ce8f961b8b 38 #include <errno.h>
ranaumarnaeem 34:d6ce8f961b8b 39
ranaumarnaeem 34:d6ce8f961b8b 40 #include "coap_client.h"
ranaumarnaeem 34:d6ce8f961b8b 41 #include "main.h"
ranaumarnaeem 34:d6ce8f961b8b 42
ranaumarnaeem 34:d6ce8f961b8b 43 #define COAP_CLIENT_ACK_TIMEOUT_SEC 2 /**< Minimum delay to wait before retransmitting a confirmable message */
ranaumarnaeem 34:d6ce8f961b8b 44 #define COAP_CLIENT_MAX_RETRANSMIT 4 /**< Maximum number of times a confirmable message can be retransmitted */
ranaumarnaeem 34:d6ce8f961b8b 45 #define COAP_CLIENT_RESP_TIMEOUT_SEC 30 /**< Maximum amount of time to wait for a response */
ranaumarnaeem 34:d6ce8f961b8b 46
ranaumarnaeem 34:d6ce8f961b8b 47 /****************************************************************************************************
ranaumarnaeem 34:d6ce8f961b8b 48 * coap_client *
ranaumarnaeem 34:d6ce8f961b8b 49 ****************************************************************************************************/
ranaumarnaeem 34:d6ce8f961b8b 50
ranaumarnaeem 34:d6ce8f961b8b 51 int coap_client_create(coap_client_t *client,
ranaumarnaeem 34:d6ce8f961b8b 52 const char *host,
ranaumarnaeem 34:d6ce8f961b8b 53 const char *port)
ranaumarnaeem 34:d6ce8f961b8b 54 {
ranaumarnaeem 34:d6ce8f961b8b 55 strncpy(client->server_host, host, sizeof(client->server_host) - 1);
ranaumarnaeem 34:d6ce8f961b8b 56 strncpy(client->server_port, port, sizeof(client->server_port) - 1);
ranaumarnaeem 34:d6ce8f961b8b 57
ranaumarnaeem 34:d6ce8f961b8b 58 printf("Connected to host %s and port %s", client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 59 return 0;
ranaumarnaeem 34:d6ce8f961b8b 60 }
ranaumarnaeem 34:d6ce8f961b8b 61
ranaumarnaeem 34:d6ce8f961b8b 62 void coap_client_destroy(coap_client_t *client)
ranaumarnaeem 34:d6ce8f961b8b 63 {
ranaumarnaeem 34:d6ce8f961b8b 64 memset(client, 0, sizeof(coap_client_t));
ranaumarnaeem 34:d6ce8f961b8b 65 }
ranaumarnaeem 34:d6ce8f961b8b 66
ranaumarnaeem 34:d6ce8f961b8b 67 /**
ranaumarnaeem 34:d6ce8f961b8b 68 * @brief Send a message to the server
ranaumarnaeem 34:d6ce8f961b8b 69 *
ranaumarnaeem 34:d6ce8f961b8b 70 * @param[in,out] client Pointer to a client structure
ranaumarnaeem 34:d6ce8f961b8b 71 * @param[in] msg Pointer to a message structure
ranaumarnaeem 34:d6ce8f961b8b 72 *
ranaumarnaeem 34:d6ce8f961b8b 73 * @returns Number of bytes sent or error code
ranaumarnaeem 34:d6ce8f961b8b 74 * @retval >0 Number of bytes sent
ranaumarnaeem 34:d6ce8f961b8b 75 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 76 */
ranaumarnaeem 34:d6ce8f961b8b 77 static int coap_client_send(coap_client_t *client, coap_msg_t *msg)
ranaumarnaeem 34:d6ce8f961b8b 78 {
ranaumarnaeem 34:d6ce8f961b8b 79 int num = 0;
ranaumarnaeem 34:d6ce8f961b8b 80 char buf[COAP_MSG_MAX_BUF_LEN] = {0};
ranaumarnaeem 34:d6ce8f961b8b 81
ranaumarnaeem 34:d6ce8f961b8b 82 num = coap_msg_format(msg, buf, sizeof(buf));
ranaumarnaeem 34:d6ce8f961b8b 83 if (num < 0)
ranaumarnaeem 34:d6ce8f961b8b 84 {
ranaumarnaeem 34:d6ce8f961b8b 85 return num;
ranaumarnaeem 34:d6ce8f961b8b 86 }
ranaumarnaeem 34:d6ce8f961b8b 87 num = send(client->sd, buf, num);
ranaumarnaeem 34:d6ce8f961b8b 88 if (num < 0)
ranaumarnaeem 34:d6ce8f961b8b 89 {
ranaumarnaeem 34:d6ce8f961b8b 90 printf("send error\n");
ranaumarnaeem 34:d6ce8f961b8b 91 return -errno;
ranaumarnaeem 34:d6ce8f961b8b 92 }
ranaumarnaeem 34:d6ce8f961b8b 93
ranaumarnaeem 34:d6ce8f961b8b 94 printf("Sent to host %s and port %s\n", client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 95 return num;
ranaumarnaeem 34:d6ce8f961b8b 96 }
ranaumarnaeem 34:d6ce8f961b8b 97
ranaumarnaeem 34:d6ce8f961b8b 98 /**
ranaumarnaeem 34:d6ce8f961b8b 99 * @brief Handle a format error in a received message
ranaumarnaeem 34:d6ce8f961b8b 100 *
ranaumarnaeem 34:d6ce8f961b8b 101 * Special handling for the case where a received
ranaumarnaeem 34:d6ce8f961b8b 102 * message could not be parsed due to a format error.
ranaumarnaeem 34:d6ce8f961b8b 103 * Extract enough information from the received message
ranaumarnaeem 34:d6ce8f961b8b 104 * to form a reset message.
ranaumarnaeem 34:d6ce8f961b8b 105 *
ranaumarnaeem 34:d6ce8f961b8b 106 * @param[in,out] client Pointer to a client structure
ranaumarnaeem 34:d6ce8f961b8b 107 * @param[in] buf Buffer containing the message
ranaumarnaeem 34:d6ce8f961b8b 108 * @param[in] len length of the buffer
ranaumarnaeem 34:d6ce8f961b8b 109 */
ranaumarnaeem 34:d6ce8f961b8b 110 static void coap_client_handle_format_error(coap_client_t *client, char *buf, size_t len)
ranaumarnaeem 34:d6ce8f961b8b 111 {
ranaumarnaeem 34:d6ce8f961b8b 112 coap_msg_t msg = {0};
ranaumarnaeem 34:d6ce8f961b8b 113 unsigned msg_id = 0;
ranaumarnaeem 34:d6ce8f961b8b 114 unsigned type = 0;
ranaumarnaeem 34:d6ce8f961b8b 115 int ret = 0;
ranaumarnaeem 34:d6ce8f961b8b 116
ranaumarnaeem 34:d6ce8f961b8b 117 ret = coap_msg_parse_type_msg_id(buf, len, &type, &msg_id);
ranaumarnaeem 34:d6ce8f961b8b 118 if ((ret == 0) && (type == COAP_MSG_CON))
ranaumarnaeem 34:d6ce8f961b8b 119 {
ranaumarnaeem 34:d6ce8f961b8b 120 coap_msg_create(&msg);
ranaumarnaeem 34:d6ce8f961b8b 121 ret = coap_msg_set_type(&msg, COAP_MSG_RST);
ranaumarnaeem 34:d6ce8f961b8b 122 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 123 {
ranaumarnaeem 34:d6ce8f961b8b 124 coap_msg_destroy(&msg);
ranaumarnaeem 34:d6ce8f961b8b 125 return;
ranaumarnaeem 34:d6ce8f961b8b 126 }
ranaumarnaeem 34:d6ce8f961b8b 127 ret = coap_msg_set_msg_id(&msg, msg_id);
ranaumarnaeem 34:d6ce8f961b8b 128 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 129 {
ranaumarnaeem 34:d6ce8f961b8b 130 coap_msg_destroy(&msg);
ranaumarnaeem 34:d6ce8f961b8b 131 return;
ranaumarnaeem 34:d6ce8f961b8b 132 }
ranaumarnaeem 34:d6ce8f961b8b 133 coap_client_send(client, &msg);
ranaumarnaeem 34:d6ce8f961b8b 134 coap_msg_destroy(&msg);
ranaumarnaeem 34:d6ce8f961b8b 135 }
ranaumarnaeem 34:d6ce8f961b8b 136 }
ranaumarnaeem 34:d6ce8f961b8b 137
ranaumarnaeem 34:d6ce8f961b8b 138 /**
ranaumarnaeem 34:d6ce8f961b8b 139 * @brief Receive a message from the server
ranaumarnaeem 34:d6ce8f961b8b 140 *
ranaumarnaeem 34:d6ce8f961b8b 141 * @param[in,out] client Pointer to a client structure
ranaumarnaeem 34:d6ce8f961b8b 142 * @param[in] msg Pointer to a message structure
ranaumarnaeem 34:d6ce8f961b8b 143 *
ranaumarnaeem 34:d6ce8f961b8b 144 * @returns Number of bytes received or error code
ranaumarnaeem 34:d6ce8f961b8b 145 * @retval >0 Number of bytes received
ranaumarnaeem 34:d6ce8f961b8b 146 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 147 */
ranaumarnaeem 34:d6ce8f961b8b 148 static int coap_client_recv(coap_client_t *client, coap_msg_t *msg)
ranaumarnaeem 34:d6ce8f961b8b 149 {
ranaumarnaeem 34:d6ce8f961b8b 150 int num = 0;
ranaumarnaeem 34:d6ce8f961b8b 151 int ret = 0;
ranaumarnaeem 34:d6ce8f961b8b 152 char buf[COAP_MSG_MAX_BUF_LEN] = {0};
ranaumarnaeem 34:d6ce8f961b8b 153
ranaumarnaeem 34:d6ce8f961b8b 154 num = recv(client->sd, buf, sizeof(buf));
ranaumarnaeem 34:d6ce8f961b8b 155 if (num < 0)
ranaumarnaeem 34:d6ce8f961b8b 156 {
ranaumarnaeem 34:d6ce8f961b8b 157 return -errno;
ranaumarnaeem 34:d6ce8f961b8b 158 }
ranaumarnaeem 34:d6ce8f961b8b 159
ranaumarnaeem 34:d6ce8f961b8b 160 ret = coap_msg_parse(msg, buf, num);
ranaumarnaeem 34:d6ce8f961b8b 161 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 162 {
ranaumarnaeem 34:d6ce8f961b8b 163 if (ret == -EBADMSG)
ranaumarnaeem 34:d6ce8f961b8b 164 {
ranaumarnaeem 34:d6ce8f961b8b 165 coap_client_handle_format_error(client, buf, num);
ranaumarnaeem 34:d6ce8f961b8b 166 }
ranaumarnaeem 34:d6ce8f961b8b 167 return ret;
ranaumarnaeem 34:d6ce8f961b8b 168 }
ranaumarnaeem 34:d6ce8f961b8b 169 printf("Received from host %s and port %s\n", client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 170 return num;
ranaumarnaeem 34:d6ce8f961b8b 171 }
ranaumarnaeem 34:d6ce8f961b8b 172
ranaumarnaeem 34:d6ce8f961b8b 173 /**
ranaumarnaeem 34:d6ce8f961b8b 174 * @brief Reject a received confirmable message
ranaumarnaeem 34:d6ce8f961b8b 175 *
ranaumarnaeem 34:d6ce8f961b8b 176 * Send a reset message to the server.
ranaumarnaeem 34:d6ce8f961b8b 177 *
ranaumarnaeem 34:d6ce8f961b8b 178 * @param[in,out] client Pointer to a client structure
ranaumarnaeem 34:d6ce8f961b8b 179 * @param[in] msg Pointer to a message structure
ranaumarnaeem 34:d6ce8f961b8b 180 *
ranaumarnaeem 34:d6ce8f961b8b 181 * @returns Operation status
ranaumarnaeem 34:d6ce8f961b8b 182 * @retval 0 Success
ranaumarnaeem 34:d6ce8f961b8b 183 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 184 */
ranaumarnaeem 34:d6ce8f961b8b 185 static int coap_client_reject_con(coap_client_t *client, coap_msg_t *msg)
ranaumarnaeem 34:d6ce8f961b8b 186 {
ranaumarnaeem 34:d6ce8f961b8b 187 coap_msg_t rej = {0};
ranaumarnaeem 34:d6ce8f961b8b 188 int num = 0;
ranaumarnaeem 34:d6ce8f961b8b 189 int ret = 0;
ranaumarnaeem 34:d6ce8f961b8b 190
ranaumarnaeem 34:d6ce8f961b8b 191 printf("Rejecting confirmable message from host %s and port %s\n", client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 192 coap_msg_create(&rej);
ranaumarnaeem 34:d6ce8f961b8b 193 ret = coap_msg_set_type(&rej, COAP_MSG_RST);
ranaumarnaeem 34:d6ce8f961b8b 194 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 195 {
ranaumarnaeem 34:d6ce8f961b8b 196 coap_msg_destroy(&rej);
ranaumarnaeem 34:d6ce8f961b8b 197 return ret;
ranaumarnaeem 34:d6ce8f961b8b 198 }
ranaumarnaeem 34:d6ce8f961b8b 199 ret = coap_msg_set_msg_id(&rej, coap_msg_get_msg_id(msg));
ranaumarnaeem 34:d6ce8f961b8b 200 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 201 {
ranaumarnaeem 34:d6ce8f961b8b 202 coap_msg_destroy(&rej);
ranaumarnaeem 34:d6ce8f961b8b 203 return ret;
ranaumarnaeem 34:d6ce8f961b8b 204 }
ranaumarnaeem 34:d6ce8f961b8b 205 num = coap_client_send(client, &rej);
ranaumarnaeem 34:d6ce8f961b8b 206 coap_msg_destroy(&rej);
ranaumarnaeem 34:d6ce8f961b8b 207 if (num < 0)
ranaumarnaeem 34:d6ce8f961b8b 208 {
ranaumarnaeem 34:d6ce8f961b8b 209 return num;
ranaumarnaeem 34:d6ce8f961b8b 210 }
ranaumarnaeem 34:d6ce8f961b8b 211 return 0;
ranaumarnaeem 34:d6ce8f961b8b 212 }
ranaumarnaeem 34:d6ce8f961b8b 213
ranaumarnaeem 34:d6ce8f961b8b 214 /**
ranaumarnaeem 34:d6ce8f961b8b 215 * @brief Reject a received non-confirmable message
ranaumarnaeem 34:d6ce8f961b8b 216 *
ranaumarnaeem 34:d6ce8f961b8b 217 * @param[in] client Pointer to a client structure
ranaumarnaeem 34:d6ce8f961b8b 218 * @param[in] msg Pointer to a message structure
ranaumarnaeem 34:d6ce8f961b8b 219 *
ranaumarnaeem 34:d6ce8f961b8b 220 * @returns Operation status
ranaumarnaeem 34:d6ce8f961b8b 221 * @retval 0 Success
ranaumarnaeem 34:d6ce8f961b8b 222 */
ranaumarnaeem 34:d6ce8f961b8b 223 static int coap_client_reject_non(coap_client_t *client, coap_msg_t *msg)
ranaumarnaeem 34:d6ce8f961b8b 224 {
ranaumarnaeem 34:d6ce8f961b8b 225 printf("Rejecting non-confirmable message from host %s and port %s\n", client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 226 return 0;
ranaumarnaeem 34:d6ce8f961b8b 227 }
ranaumarnaeem 34:d6ce8f961b8b 228
ranaumarnaeem 34:d6ce8f961b8b 229 /**
ranaumarnaeem 34:d6ce8f961b8b 230 * @brief Reject a received acknowledgement message
ranaumarnaeem 34:d6ce8f961b8b 231 *
ranaumarnaeem 34:d6ce8f961b8b 232 * @param[in] client Pointer to a client structure
ranaumarnaeem 34:d6ce8f961b8b 233 * @param[in] msg Pointer to a message structure
ranaumarnaeem 34:d6ce8f961b8b 234 *
ranaumarnaeem 34:d6ce8f961b8b 235 * @returns Operation status
ranaumarnaeem 34:d6ce8f961b8b 236 * @retval 0 Success
ranaumarnaeem 34:d6ce8f961b8b 237 */
ranaumarnaeem 34:d6ce8f961b8b 238 static int coap_client_reject_ack(coap_client_t *client, coap_msg_t *msg)
ranaumarnaeem 34:d6ce8f961b8b 239 {
ranaumarnaeem 34:d6ce8f961b8b 240 printf("Rejecting acknowledgement message from host %s and port %s\n", client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 241 return 0;
ranaumarnaeem 34:d6ce8f961b8b 242 }
ranaumarnaeem 34:d6ce8f961b8b 243
ranaumarnaeem 34:d6ce8f961b8b 244 /**
ranaumarnaeem 34:d6ce8f961b8b 245 * @brief Reject a received reset message
ranaumarnaeem 34:d6ce8f961b8b 246 *
ranaumarnaeem 34:d6ce8f961b8b 247 * @param[in] client Pointer to a client structure
ranaumarnaeem 34:d6ce8f961b8b 248 * @param[in] msg Pointer to a message structure
ranaumarnaeem 34:d6ce8f961b8b 249 *
ranaumarnaeem 34:d6ce8f961b8b 250 * @returns Operation status
ranaumarnaeem 34:d6ce8f961b8b 251 * @retval 0 Success
ranaumarnaeem 34:d6ce8f961b8b 252 */
ranaumarnaeem 34:d6ce8f961b8b 253 static int coap_client_reject_reset(coap_client_t *client, coap_msg_t *msg)
ranaumarnaeem 34:d6ce8f961b8b 254 {
ranaumarnaeem 34:d6ce8f961b8b 255 printf("Rejecting reset message from host %s and port %s\n", client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 256 return 0;
ranaumarnaeem 34:d6ce8f961b8b 257 }
ranaumarnaeem 34:d6ce8f961b8b 258
ranaumarnaeem 34:d6ce8f961b8b 259 /**
ranaumarnaeem 34:d6ce8f961b8b 260 * @brief Reject a received message
ranaumarnaeem 34:d6ce8f961b8b 261 *
ranaumarnaeem 34:d6ce8f961b8b 262 * @param[in,out] client Pointer to a client structure
ranaumarnaeem 34:d6ce8f961b8b 263 * @param[in] msg Pointer to a message structure
ranaumarnaeem 34:d6ce8f961b8b 264 *
ranaumarnaeem 34:d6ce8f961b8b 265 * @returns Operation status
ranaumarnaeem 34:d6ce8f961b8b 266 * @retval 0 Success
ranaumarnaeem 34:d6ce8f961b8b 267 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 268 */
ranaumarnaeem 34:d6ce8f961b8b 269 static int coap_client_reject(coap_client_t *client, coap_msg_t *msg)
ranaumarnaeem 34:d6ce8f961b8b 270 {
ranaumarnaeem 34:d6ce8f961b8b 271 if (coap_msg_get_type(msg) == COAP_MSG_CON)
ranaumarnaeem 34:d6ce8f961b8b 272 {
ranaumarnaeem 34:d6ce8f961b8b 273 return coap_client_reject_con(client, msg);
ranaumarnaeem 34:d6ce8f961b8b 274 }
ranaumarnaeem 34:d6ce8f961b8b 275 else if (coap_msg_get_type(msg) == COAP_MSG_NON)
ranaumarnaeem 34:d6ce8f961b8b 276 {
ranaumarnaeem 34:d6ce8f961b8b 277 return coap_client_reject_non(client, msg);
ranaumarnaeem 34:d6ce8f961b8b 278 }
ranaumarnaeem 34:d6ce8f961b8b 279 else if (coap_msg_get_type(msg) == COAP_MSG_ACK)
ranaumarnaeem 34:d6ce8f961b8b 280 {
ranaumarnaeem 34:d6ce8f961b8b 281 return coap_client_reject_ack(client, msg);
ranaumarnaeem 34:d6ce8f961b8b 282 }
ranaumarnaeem 34:d6ce8f961b8b 283 else if (coap_msg_get_type(msg) == COAP_MSG_RST)
ranaumarnaeem 34:d6ce8f961b8b 284 {
ranaumarnaeem 34:d6ce8f961b8b 285 return coap_client_reject_reset(client, msg);
ranaumarnaeem 34:d6ce8f961b8b 286 }
ranaumarnaeem 34:d6ce8f961b8b 287 return 0; /* should never arrive here */
ranaumarnaeem 34:d6ce8f961b8b 288 }
ranaumarnaeem 34:d6ce8f961b8b 289
ranaumarnaeem 34:d6ce8f961b8b 290 /**
ranaumarnaeem 34:d6ce8f961b8b 291 * @brief Send an acknowledgement message to the server
ranaumarnaeem 34:d6ce8f961b8b 292 *
ranaumarnaeem 34:d6ce8f961b8b 293 * @param[in,out] client Pointer to a client structure
ranaumarnaeem 34:d6ce8f961b8b 294 * @param[in] msg Pointer to a message structure
ranaumarnaeem 34:d6ce8f961b8b 295 *
ranaumarnaeem 34:d6ce8f961b8b 296 * @returns Operation status
ranaumarnaeem 34:d6ce8f961b8b 297 * @retval 0 Success
ranaumarnaeem 34:d6ce8f961b8b 298 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 299 */
ranaumarnaeem 34:d6ce8f961b8b 300 static int coap_client_send_ack(coap_client_t *client, coap_msg_t *msg)
ranaumarnaeem 34:d6ce8f961b8b 301 {
ranaumarnaeem 34:d6ce8f961b8b 302 coap_msg_t ack = {0};
ranaumarnaeem 34:d6ce8f961b8b 303 int num = 0;
ranaumarnaeem 34:d6ce8f961b8b 304 int ret = 0;
ranaumarnaeem 34:d6ce8f961b8b 305
ranaumarnaeem 34:d6ce8f961b8b 306 printf("Acknowledging confirmable message from host %s and port %s\n", client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 307 coap_msg_create(&ack);
ranaumarnaeem 34:d6ce8f961b8b 308 ret = coap_msg_set_type(&ack, COAP_MSG_ACK);
ranaumarnaeem 34:d6ce8f961b8b 309 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 310 {
ranaumarnaeem 34:d6ce8f961b8b 311 coap_msg_destroy(&ack);
ranaumarnaeem 34:d6ce8f961b8b 312 return ret;
ranaumarnaeem 34:d6ce8f961b8b 313 }
ranaumarnaeem 34:d6ce8f961b8b 314 ret = coap_msg_set_msg_id(&ack, coap_msg_get_msg_id(msg));
ranaumarnaeem 34:d6ce8f961b8b 315 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 316 {
ranaumarnaeem 34:d6ce8f961b8b 317 coap_msg_destroy(&ack);
ranaumarnaeem 34:d6ce8f961b8b 318 return ret;
ranaumarnaeem 34:d6ce8f961b8b 319 }
ranaumarnaeem 34:d6ce8f961b8b 320 num = coap_client_send(client, &ack);
ranaumarnaeem 34:d6ce8f961b8b 321 coap_msg_destroy(&ack);
ranaumarnaeem 34:d6ce8f961b8b 322 if (num < 0)
ranaumarnaeem 34:d6ce8f961b8b 323 {
ranaumarnaeem 34:d6ce8f961b8b 324 return num;
ranaumarnaeem 34:d6ce8f961b8b 325 }
ranaumarnaeem 34:d6ce8f961b8b 326 return 0;
ranaumarnaeem 34:d6ce8f961b8b 327 }
ranaumarnaeem 34:d6ce8f961b8b 328
ranaumarnaeem 34:d6ce8f961b8b 329 /**
ranaumarnaeem 34:d6ce8f961b8b 330 * @brief Compare the token values in a request message and a response message
ranaumarnaeem 34:d6ce8f961b8b 331 *
ranaumarnaeem 34:d6ce8f961b8b 332 * @param[in] req Pointer to the request message
ranaumarnaeem 34:d6ce8f961b8b 333 * @param[in] resp Pointer to the response message
ranaumarnaeem 34:d6ce8f961b8b 334 *
ranaumarnaeem 34:d6ce8f961b8b 335 * @returns Comparison value
ranaumarnaeem 34:d6ce8f961b8b 336 * @retval 0 the tokens are not equal
ranaumarnaeem 34:d6ce8f961b8b 337 * @retval 1 the tokens are equal
ranaumarnaeem 34:d6ce8f961b8b 338 */
ranaumarnaeem 34:d6ce8f961b8b 339 static int coap_client_match_token(coap_msg_t *req, coap_msg_t *resp)
ranaumarnaeem 34:d6ce8f961b8b 340 {
ranaumarnaeem 34:d6ce8f961b8b 341 return ((coap_msg_get_token_len(resp) == coap_msg_get_token_len(req))
ranaumarnaeem 34:d6ce8f961b8b 342 && (memcmp(coap_msg_get_token(resp), coap_msg_get_token(req), coap_msg_get_token_len(req)) == 0));
ranaumarnaeem 34:d6ce8f961b8b 343 }
ranaumarnaeem 34:d6ce8f961b8b 344
ranaumarnaeem 34:d6ce8f961b8b 345 /**
ranaumarnaeem 34:d6ce8f961b8b 346 * @brief Check that all of the options in a message are acceptable
ranaumarnaeem 34:d6ce8f961b8b 347 *
ranaumarnaeem 34:d6ce8f961b8b 348 * For a proxy, options are acceptable if they are safe to forward or recognized or both.
ranaumarnaeem 34:d6ce8f961b8b 349 * For a server, options are acceptable if they are elective or recognized or both.
ranaumarnaeem 34:d6ce8f961b8b 350 *
ranaumarnaeem 34:d6ce8f961b8b 351 * @param[in] msg Pointer to message structure
ranaumarnaeem 34:d6ce8f961b8b 352 *
ranaumarnaeem 34:d6ce8f961b8b 353 * @returns Operation status or bad option number
ranaumarnaeem 34:d6ce8f961b8b 354 * @retval 0 Success
ranaumarnaeem 34:d6ce8f961b8b 355 * @retval >0 Bad option number
ranaumarnaeem 34:d6ce8f961b8b 356 */
ranaumarnaeem 34:d6ce8f961b8b 357 static unsigned coap_client_check_options(coap_msg_t *msg)
ranaumarnaeem 34:d6ce8f961b8b 358 {
ranaumarnaeem 34:d6ce8f961b8b 359 #ifdef COAP_PROXY
ranaumarnaeem 34:d6ce8f961b8b 360 return coap_msg_check_unsafe_ops(msg);
ranaumarnaeem 34:d6ce8f961b8b 361 #else /* !COAP_PROXY */
ranaumarnaeem 34:d6ce8f961b8b 362 return coap_msg_check_critical_ops(msg);
ranaumarnaeem 34:d6ce8f961b8b 363 #endif /* COAP_PROXY */
ranaumarnaeem 34:d6ce8f961b8b 364 }
ranaumarnaeem 34:d6ce8f961b8b 365
ranaumarnaeem 34:d6ce8f961b8b 366 /**
ranaumarnaeem 34:d6ce8f961b8b 367 * @brief Handle a received piggy-backed response message
ranaumarnaeem 34:d6ce8f961b8b 368 *
ranaumarnaeem 34:d6ce8f961b8b 369 * An acknowledgement has been received that contains
ranaumarnaeem 34:d6ce8f961b8b 370 * the same token as the request. Check the response
ranaumarnaeem 34:d6ce8f961b8b 371 * contained within it.
ranaumarnaeem 34:d6ce8f961b8b 372 *
ranaumarnaeem 34:d6ce8f961b8b 373 * @param[in,out] client Pointer to a client structure
ranaumarnaeem 34:d6ce8f961b8b 374 * @param[in] resp Pointer to the response message
ranaumarnaeem 34:d6ce8f961b8b 375 *
ranaumarnaeem 34:d6ce8f961b8b 376 * @returns Operation status
ranaumarnaeem 34:d6ce8f961b8b 377 * @retval 0 Success
ranaumarnaeem 34:d6ce8f961b8b 378 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 379 */
ranaumarnaeem 34:d6ce8f961b8b 380 static int coap_client_handle_piggybacked_response(coap_client_t *client, coap_msg_t *resp)
ranaumarnaeem 34:d6ce8f961b8b 381 {
ranaumarnaeem 34:d6ce8f961b8b 382 unsigned op_num = 0;
ranaumarnaeem 34:d6ce8f961b8b 383
ranaumarnaeem 34:d6ce8f961b8b 384 op_num = coap_client_check_options(resp);
ranaumarnaeem 34:d6ce8f961b8b 385 if (op_num != 0)
ranaumarnaeem 34:d6ce8f961b8b 386 {
ranaumarnaeem 34:d6ce8f961b8b 387 printf("Found bad option number %u in message from host %s and port %s\n", op_num, client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 388 coap_client_reject(client, resp);
ranaumarnaeem 34:d6ce8f961b8b 389 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 390 }
ranaumarnaeem 34:d6ce8f961b8b 391 printf("Received acknowledgement and response from host %s and port %s\n", client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 392 return 0;
ranaumarnaeem 34:d6ce8f961b8b 393 }
ranaumarnaeem 34:d6ce8f961b8b 394
ranaumarnaeem 34:d6ce8f961b8b 395 /**
ranaumarnaeem 34:d6ce8f961b8b 396 * @brief Handle a received separate response message
ranaumarnaeem 34:d6ce8f961b8b 397 *
ranaumarnaeem 34:d6ce8f961b8b 398 * A separate response has been received that contains
ranaumarnaeem 34:d6ce8f961b8b 399 * the same token as the request. Check the response
ranaumarnaeem 34:d6ce8f961b8b 400 * and send an acknowledgement if necessary.
ranaumarnaeem 34:d6ce8f961b8b 401 *
ranaumarnaeem 34:d6ce8f961b8b 402 * @param[in,out] client Pointer to a client structure
ranaumarnaeem 34:d6ce8f961b8b 403 * @param[in] resp Pointer to the response message
ranaumarnaeem 34:d6ce8f961b8b 404 *
ranaumarnaeem 34:d6ce8f961b8b 405 * @returns Operation status
ranaumarnaeem 34:d6ce8f961b8b 406 * @retval 0 Success
ranaumarnaeem 34:d6ce8f961b8b 407 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 408 */
ranaumarnaeem 34:d6ce8f961b8b 409 static int coap_client_handle_sep_response(coap_client_t *client, coap_msg_t *resp)
ranaumarnaeem 34:d6ce8f961b8b 410 {
ranaumarnaeem 34:d6ce8f961b8b 411 unsigned op_num = 0;
ranaumarnaeem 34:d6ce8f961b8b 412
ranaumarnaeem 34:d6ce8f961b8b 413 if (coap_msg_get_type(resp) == COAP_MSG_CON)
ranaumarnaeem 34:d6ce8f961b8b 414 {
ranaumarnaeem 34:d6ce8f961b8b 415 printf("Received confirmable response from host %s and port %s\n", client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 416 op_num = coap_client_check_options(resp);
ranaumarnaeem 34:d6ce8f961b8b 417 if (op_num != 0)
ranaumarnaeem 34:d6ce8f961b8b 418 {
ranaumarnaeem 34:d6ce8f961b8b 419 printf("Found bad option number %u in message from host %s and port %s\n", op_num, client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 420 coap_client_reject(client, resp);
ranaumarnaeem 34:d6ce8f961b8b 421 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 422 }
ranaumarnaeem 34:d6ce8f961b8b 423 return coap_client_send_ack(client, resp);
ranaumarnaeem 34:d6ce8f961b8b 424 }
ranaumarnaeem 34:d6ce8f961b8b 425 else if (coap_msg_get_type(resp) == COAP_MSG_NON)
ranaumarnaeem 34:d6ce8f961b8b 426 {
ranaumarnaeem 34:d6ce8f961b8b 427 printf("Received non-confirmable response from host %s and port %s\n", client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 428 op_num = coap_client_check_options(resp);
ranaumarnaeem 34:d6ce8f961b8b 429 if (op_num != 0)
ranaumarnaeem 34:d6ce8f961b8b 430 {
ranaumarnaeem 34:d6ce8f961b8b 431 printf("Found bad option number %u in message from host %s and port %s\n", op_num, client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 432 coap_client_reject(client, resp);
ranaumarnaeem 34:d6ce8f961b8b 433 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 434 }
ranaumarnaeem 34:d6ce8f961b8b 435 return 0;
ranaumarnaeem 34:d6ce8f961b8b 436 }
ranaumarnaeem 34:d6ce8f961b8b 437 coap_client_reject(client, resp);
ranaumarnaeem 34:d6ce8f961b8b 438 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 439 }
ranaumarnaeem 34:d6ce8f961b8b 440
ranaumarnaeem 34:d6ce8f961b8b 441 /**
ranaumarnaeem 34:d6ce8f961b8b 442 * @brief Handle a separate response to a confirmable request
ranaumarnaeem 34:d6ce8f961b8b 443 *
ranaumarnaeem 34:d6ce8f961b8b 444 * An acknowledgement has been received. Receive the
ranaumarnaeem 34:d6ce8f961b8b 445 * response and send an acknowledgement back to the server.
ranaumarnaeem 34:d6ce8f961b8b 446 *
ranaumarnaeem 34:d6ce8f961b8b 447 * @param[in,out] client Pointer to a client structure
ranaumarnaeem 34:d6ce8f961b8b 448 * @param[in] req Pointer to the request message
ranaumarnaeem 34:d6ce8f961b8b 449 * @param[out] resp Pointer to the response message
ranaumarnaeem 34:d6ce8f961b8b 450 *
ranaumarnaeem 34:d6ce8f961b8b 451 * @returns Operation status
ranaumarnaeem 34:d6ce8f961b8b 452 * @retval 0 Success
ranaumarnaeem 34:d6ce8f961b8b 453 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 454 */
ranaumarnaeem 34:d6ce8f961b8b 455 static int coap_client_exchange_sep(coap_client_t *client, coap_msg_t *req, coap_msg_t *resp)
ranaumarnaeem 34:d6ce8f961b8b 456 {
ranaumarnaeem 34:d6ce8f961b8b 457 int num = 0;
ranaumarnaeem 34:d6ce8f961b8b 458 int ret = 0;
ranaumarnaeem 34:d6ce8f961b8b 459
ranaumarnaeem 34:d6ce8f961b8b 460 /* wait for a separate response to a confirmable request */
ranaumarnaeem 34:d6ce8f961b8b 461 printf("Expecting response from host %s and port %s\n", client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 462 while (1)
ranaumarnaeem 34:d6ce8f961b8b 463 {
ranaumarnaeem 34:d6ce8f961b8b 464 int start_time = getseconds();
ranaumarnaeem 34:d6ce8f961b8b 465 while(1)
ranaumarnaeem 34:d6ce8f961b8b 466 {
ranaumarnaeem 34:d6ce8f961b8b 467 num = coap_client_recv(client, resp);
ranaumarnaeem 34:d6ce8f961b8b 468 if (num < 0)
ranaumarnaeem 34:d6ce8f961b8b 469 {
ranaumarnaeem 34:d6ce8f961b8b 470 return num;
ranaumarnaeem 34:d6ce8f961b8b 471 }
ranaumarnaeem 34:d6ce8f961b8b 472 else if(num > 0)
ranaumarnaeem 34:d6ce8f961b8b 473 {
ranaumarnaeem 34:d6ce8f961b8b 474 break;
ranaumarnaeem 34:d6ce8f961b8b 475 }
ranaumarnaeem 34:d6ce8f961b8b 476 int stop_time = getseconds();
ranaumarnaeem 34:d6ce8f961b8b 477 if((stop_time - start_time) > COAP_CLIENT_RESP_TIMEOUT_SEC)
ranaumarnaeem 34:d6ce8f961b8b 478 {
ranaumarnaeem 34:d6ce8f961b8b 479 printf("Timeout no data received\n");
ranaumarnaeem 34:d6ce8f961b8b 480 return -1;
ranaumarnaeem 34:d6ce8f961b8b 481 }
ranaumarnaeem 34:d6ce8f961b8b 482 }
ranaumarnaeem 34:d6ce8f961b8b 483
ranaumarnaeem 34:d6ce8f961b8b 484 if (coap_msg_get_msg_id(resp) == coap_msg_get_msg_id(req))
ranaumarnaeem 34:d6ce8f961b8b 485 {
ranaumarnaeem 34:d6ce8f961b8b 486 if (coap_msg_get_type(resp) == COAP_MSG_ACK)
ranaumarnaeem 34:d6ce8f961b8b 487 {
ranaumarnaeem 34:d6ce8f961b8b 488 /* message deduplication */
ranaumarnaeem 34:d6ce8f961b8b 489 printf("Received duplicate acknowledgement from host %s and port %s\n", client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 490 continue;
ranaumarnaeem 34:d6ce8f961b8b 491 }
ranaumarnaeem 34:d6ce8f961b8b 492 else if (coap_msg_get_type(resp) == COAP_MSG_RST)
ranaumarnaeem 34:d6ce8f961b8b 493 {
ranaumarnaeem 34:d6ce8f961b8b 494 return -ECONNRESET;
ranaumarnaeem 34:d6ce8f961b8b 495 }
ranaumarnaeem 34:d6ce8f961b8b 496 coap_client_reject(client, resp);
ranaumarnaeem 34:d6ce8f961b8b 497 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 498 }
ranaumarnaeem 34:d6ce8f961b8b 499 if (coap_client_match_token(req, resp))
ranaumarnaeem 34:d6ce8f961b8b 500 {
ranaumarnaeem 34:d6ce8f961b8b 501 return coap_client_handle_sep_response(client, resp);
ranaumarnaeem 34:d6ce8f961b8b 502 }
ranaumarnaeem 34:d6ce8f961b8b 503 /* message deduplication */
ranaumarnaeem 34:d6ce8f961b8b 504 /* we might have received a duplicate message that was already received from the same server */
ranaumarnaeem 34:d6ce8f961b8b 505 /* reject the message and continue listening */
ranaumarnaeem 34:d6ce8f961b8b 506 ret = coap_client_reject(client, resp);
ranaumarnaeem 34:d6ce8f961b8b 507 if (ret < 0 )
ranaumarnaeem 34:d6ce8f961b8b 508 {
ranaumarnaeem 34:d6ce8f961b8b 509 return ret;
ranaumarnaeem 34:d6ce8f961b8b 510 }
ranaumarnaeem 34:d6ce8f961b8b 511 }
ranaumarnaeem 34:d6ce8f961b8b 512 return 0;
ranaumarnaeem 34:d6ce8f961b8b 513 }
ranaumarnaeem 34:d6ce8f961b8b 514
ranaumarnaeem 34:d6ce8f961b8b 515 /**
ranaumarnaeem 34:d6ce8f961b8b 516 * @brief Handle the response to a confirmable request
ranaumarnaeem 34:d6ce8f961b8b 517 *
ranaumarnaeem 34:d6ce8f961b8b 518 * A confirmable request has been sent to the server.
ranaumarnaeem 34:d6ce8f961b8b 519 * Receive the acknowledgement and response. Send an
ranaumarnaeem 34:d6ce8f961b8b 520 * acknowledgement if necessary.
ranaumarnaeem 34:d6ce8f961b8b 521 *
ranaumarnaeem 34:d6ce8f961b8b 522 * @param[in,out] client Pointer to a client structure
ranaumarnaeem 34:d6ce8f961b8b 523 * @param[in] req Pointer to the request message
ranaumarnaeem 34:d6ce8f961b8b 524 * @param[out] resp Pointer to the response message
ranaumarnaeem 34:d6ce8f961b8b 525 *
ranaumarnaeem 34:d6ce8f961b8b 526 * @returns Operation status
ranaumarnaeem 34:d6ce8f961b8b 527 * @retval 0 Success
ranaumarnaeem 34:d6ce8f961b8b 528 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 529 */
ranaumarnaeem 34:d6ce8f961b8b 530 static int coap_client_exchange_con(coap_client_t *client, coap_msg_t *req, coap_msg_t *resp)
ranaumarnaeem 34:d6ce8f961b8b 531 {
ranaumarnaeem 34:d6ce8f961b8b 532 int num = 0;
ranaumarnaeem 34:d6ce8f961b8b 533 int ret = 0;
ranaumarnaeem 34:d6ce8f961b8b 534
ranaumarnaeem 34:d6ce8f961b8b 535 /* wait for piggy-backed response in ack message
ranaumarnaeem 34:d6ce8f961b8b 536 * or ack message and separate response message
ranaumarnaeem 34:d6ce8f961b8b 537 */
ranaumarnaeem 34:d6ce8f961b8b 538 printf("Expecting acknowledgement from host %s and port %s\n", client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 539 while (1)
ranaumarnaeem 34:d6ce8f961b8b 540 {
ranaumarnaeem 34:d6ce8f961b8b 541 int start_time = getseconds();
ranaumarnaeem 34:d6ce8f961b8b 542 while(1)
ranaumarnaeem 34:d6ce8f961b8b 543 {
ranaumarnaeem 34:d6ce8f961b8b 544 num = coap_client_recv(client, resp);
ranaumarnaeem 34:d6ce8f961b8b 545 if (num < 0)
ranaumarnaeem 34:d6ce8f961b8b 546 {
ranaumarnaeem 34:d6ce8f961b8b 547 return num;
ranaumarnaeem 34:d6ce8f961b8b 548 }
ranaumarnaeem 34:d6ce8f961b8b 549 else if(num > 0)
ranaumarnaeem 34:d6ce8f961b8b 550 {
ranaumarnaeem 34:d6ce8f961b8b 551 break;
ranaumarnaeem 34:d6ce8f961b8b 552 }
ranaumarnaeem 34:d6ce8f961b8b 553 int stop_time = getseconds();
ranaumarnaeem 34:d6ce8f961b8b 554 if((stop_time - start_time) > COAP_CLIENT_ACK_TIMEOUT_SEC)
ranaumarnaeem 34:d6ce8f961b8b 555 {
ranaumarnaeem 34:d6ce8f961b8b 556 printf("Timeout no data received\n");
ranaumarnaeem 34:d6ce8f961b8b 557 return -1;
ranaumarnaeem 34:d6ce8f961b8b 558 }
ranaumarnaeem 34:d6ce8f961b8b 559 }
ranaumarnaeem 34:d6ce8f961b8b 560
ranaumarnaeem 34:d6ce8f961b8b 561 if (coap_msg_get_msg_id(resp) == coap_msg_get_msg_id(req))
ranaumarnaeem 34:d6ce8f961b8b 562 {
ranaumarnaeem 34:d6ce8f961b8b 563 if (coap_msg_get_type(resp) == COAP_MSG_ACK)
ranaumarnaeem 34:d6ce8f961b8b 564 {
ranaumarnaeem 34:d6ce8f961b8b 565 if (coap_msg_is_empty(resp))
ranaumarnaeem 34:d6ce8f961b8b 566 {
ranaumarnaeem 34:d6ce8f961b8b 567 /* received ack message, wait for separate response message */
ranaumarnaeem 34:d6ce8f961b8b 568 printf("Received acknowledgement from host %s and port %s\n", client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 569 return coap_client_exchange_sep(client, req, resp);
ranaumarnaeem 34:d6ce8f961b8b 570 }
ranaumarnaeem 34:d6ce8f961b8b 571 else if (coap_client_match_token(req, resp))
ranaumarnaeem 34:d6ce8f961b8b 572 {
ranaumarnaeem 34:d6ce8f961b8b 573 return coap_client_handle_piggybacked_response(client, resp);
ranaumarnaeem 34:d6ce8f961b8b 574 }
ranaumarnaeem 34:d6ce8f961b8b 575 }
ranaumarnaeem 34:d6ce8f961b8b 576 else if (coap_msg_get_type(resp) == COAP_MSG_RST)
ranaumarnaeem 34:d6ce8f961b8b 577 {
ranaumarnaeem 34:d6ce8f961b8b 578 return -ECONNRESET;
ranaumarnaeem 34:d6ce8f961b8b 579 }
ranaumarnaeem 34:d6ce8f961b8b 580 coap_client_reject(client, resp);
ranaumarnaeem 34:d6ce8f961b8b 581 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 582 }
ranaumarnaeem 34:d6ce8f961b8b 583 else if (coap_client_match_token(req, resp))
ranaumarnaeem 34:d6ce8f961b8b 584 {
ranaumarnaeem 34:d6ce8f961b8b 585 /* RFC7252
ranaumarnaeem 34:d6ce8f961b8b 586 * as the underlying datagram transport may not be sequence-preserving,
ranaumarnaeem 34:d6ce8f961b8b 587 * the Confirmable message carrying the response may actually arrive
ranaumarnaeem 34:d6ce8f961b8b 588 * before or after the Acknowledgement message for the request; for
ranaumarnaeem 34:d6ce8f961b8b 589 * the purposes of terminating the retransmission sequence, this also
ranaumarnaeem 34:d6ce8f961b8b 590 * serves as an acknowledgement.
ranaumarnaeem 34:d6ce8f961b8b 591 */
ranaumarnaeem 34:d6ce8f961b8b 592 return coap_client_handle_sep_response(client, resp);
ranaumarnaeem 34:d6ce8f961b8b 593 }
ranaumarnaeem 34:d6ce8f961b8b 594 /* message deduplication */
ranaumarnaeem 34:d6ce8f961b8b 595 /* we might have received a duplicate message that was already received from the same server */
ranaumarnaeem 34:d6ce8f961b8b 596 /* reject the message and continue listening */
ranaumarnaeem 34:d6ce8f961b8b 597 ret = coap_client_reject(client, resp);
ranaumarnaeem 34:d6ce8f961b8b 598 if (ret < 0 )
ranaumarnaeem 34:d6ce8f961b8b 599 {
ranaumarnaeem 34:d6ce8f961b8b 600 return ret;
ranaumarnaeem 34:d6ce8f961b8b 601 }
ranaumarnaeem 34:d6ce8f961b8b 602 }
ranaumarnaeem 34:d6ce8f961b8b 603 return 0;
ranaumarnaeem 34:d6ce8f961b8b 604 }
ranaumarnaeem 34:d6ce8f961b8b 605
ranaumarnaeem 34:d6ce8f961b8b 606 /**
ranaumarnaeem 34:d6ce8f961b8b 607 * @brief Handle the response to a non-confirmable request
ranaumarnaeem 34:d6ce8f961b8b 608 *
ranaumarnaeem 34:d6ce8f961b8b 609 * A non-confirmable request has been sent to the server.
ranaumarnaeem 34:d6ce8f961b8b 610 * Receive the response.
ranaumarnaeem 34:d6ce8f961b8b 611 *
ranaumarnaeem 34:d6ce8f961b8b 612 * @param[in,out] client Pointer to a client structure
ranaumarnaeem 34:d6ce8f961b8b 613 * @param[in] req Pointer to the request message
ranaumarnaeem 34:d6ce8f961b8b 614 * @param[out] resp Pointer to the response message
ranaumarnaeem 34:d6ce8f961b8b 615 *
ranaumarnaeem 34:d6ce8f961b8b 616 * @returns Operation status
ranaumarnaeem 34:d6ce8f961b8b 617 * @retval 0 Success
ranaumarnaeem 34:d6ce8f961b8b 618 * @retval <0 Error
ranaumarnaeem 34:d6ce8f961b8b 619 **/
ranaumarnaeem 34:d6ce8f961b8b 620 static int coap_client_exchange_non(coap_client_t *client, coap_msg_t *req, coap_msg_t *resp)
ranaumarnaeem 34:d6ce8f961b8b 621 {
ranaumarnaeem 34:d6ce8f961b8b 622 int num = 0;
ranaumarnaeem 34:d6ce8f961b8b 623 int ret = 0;
ranaumarnaeem 34:d6ce8f961b8b 624
ranaumarnaeem 34:d6ce8f961b8b 625 printf("Expecting response from host %s and port %s\n", client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 626 while (1)
ranaumarnaeem 34:d6ce8f961b8b 627 {
ranaumarnaeem 34:d6ce8f961b8b 628 int start_time = getseconds();
ranaumarnaeem 34:d6ce8f961b8b 629 while(1)
ranaumarnaeem 34:d6ce8f961b8b 630 {
ranaumarnaeem 34:d6ce8f961b8b 631 num = coap_client_recv(client, resp);
ranaumarnaeem 34:d6ce8f961b8b 632 if (num < 0)
ranaumarnaeem 34:d6ce8f961b8b 633 {
ranaumarnaeem 34:d6ce8f961b8b 634 return num;
ranaumarnaeem 34:d6ce8f961b8b 635 }
ranaumarnaeem 34:d6ce8f961b8b 636 else if(num > 0)
ranaumarnaeem 34:d6ce8f961b8b 637 {
ranaumarnaeem 34:d6ce8f961b8b 638 break;
ranaumarnaeem 34:d6ce8f961b8b 639 }
ranaumarnaeem 34:d6ce8f961b8b 640 int stop_time = getseconds();
ranaumarnaeem 34:d6ce8f961b8b 641 if((stop_time - start_time) > COAP_CLIENT_RESP_TIMEOUT_SEC)
ranaumarnaeem 34:d6ce8f961b8b 642 {
ranaumarnaeem 34:d6ce8f961b8b 643 printf("Timeout no data received\n");
ranaumarnaeem 34:d6ce8f961b8b 644 return -1;
ranaumarnaeem 34:d6ce8f961b8b 645 }
ranaumarnaeem 34:d6ce8f961b8b 646 }
ranaumarnaeem 34:d6ce8f961b8b 647
ranaumarnaeem 34:d6ce8f961b8b 648 if (coap_msg_get_msg_id(resp) == coap_msg_get_msg_id(req))
ranaumarnaeem 34:d6ce8f961b8b 649 {
ranaumarnaeem 34:d6ce8f961b8b 650 if (coap_msg_get_type(resp) == COAP_MSG_RST)
ranaumarnaeem 34:d6ce8f961b8b 651 {
ranaumarnaeem 34:d6ce8f961b8b 652 return -ECONNRESET;
ranaumarnaeem 34:d6ce8f961b8b 653 }
ranaumarnaeem 34:d6ce8f961b8b 654 coap_client_reject(client, resp);
ranaumarnaeem 34:d6ce8f961b8b 655 return -EBADMSG;
ranaumarnaeem 34:d6ce8f961b8b 656 }
ranaumarnaeem 34:d6ce8f961b8b 657 if (coap_client_match_token(req, resp))
ranaumarnaeem 34:d6ce8f961b8b 658 {
ranaumarnaeem 34:d6ce8f961b8b 659 return coap_client_handle_sep_response(client, resp);
ranaumarnaeem 34:d6ce8f961b8b 660 }
ranaumarnaeem 34:d6ce8f961b8b 661 /* message deduplication */
ranaumarnaeem 34:d6ce8f961b8b 662 /* we might have received a duplicate message that was already received from the same server */
ranaumarnaeem 34:d6ce8f961b8b 663 /* reject the message and continue listening */
ranaumarnaeem 34:d6ce8f961b8b 664 ret = coap_client_reject(client, resp);
ranaumarnaeem 34:d6ce8f961b8b 665 if (ret < 0 )
ranaumarnaeem 34:d6ce8f961b8b 666 {
ranaumarnaeem 34:d6ce8f961b8b 667 return ret;
ranaumarnaeem 34:d6ce8f961b8b 668 }
ranaumarnaeem 34:d6ce8f961b8b 669 }
ranaumarnaeem 34:d6ce8f961b8b 670 return 0;
ranaumarnaeem 34:d6ce8f961b8b 671 }
ranaumarnaeem 34:d6ce8f961b8b 672
ranaumarnaeem 34:d6ce8f961b8b 673 int coap_client_exchange(coap_client_t *client, coap_msg_t *req, coap_msg_t *resp)
ranaumarnaeem 34:d6ce8f961b8b 674 {
ranaumarnaeem 34:d6ce8f961b8b 675 unsigned char msg_id_buf[2] = {0};
ranaumarnaeem 34:d6ce8f961b8b 676 unsigned msg_id = 0;
ranaumarnaeem 34:d6ce8f961b8b 677 int num = 0;
ranaumarnaeem 34:d6ce8f961b8b 678 char token[4] = {0};
ranaumarnaeem 34:d6ce8f961b8b 679 int ret = 0;
ranaumarnaeem 34:d6ce8f961b8b 680
ranaumarnaeem 34:d6ce8f961b8b 681 /* check for a valid request */
ranaumarnaeem 34:d6ce8f961b8b 682 if ((coap_msg_get_type(req) == COAP_MSG_ACK)
ranaumarnaeem 34:d6ce8f961b8b 683 || (coap_msg_get_type(req) == COAP_MSG_RST)
ranaumarnaeem 34:d6ce8f961b8b 684 || (coap_msg_get_code_class(req) != COAP_MSG_REQ))
ranaumarnaeem 34:d6ce8f961b8b 685 {
ranaumarnaeem 34:d6ce8f961b8b 686 return -EINVAL;
ranaumarnaeem 34:d6ce8f961b8b 687 }
ranaumarnaeem 34:d6ce8f961b8b 688
ranaumarnaeem 34:d6ce8f961b8b 689 /* generate the message ID */
ranaumarnaeem 34:d6ce8f961b8b 690 coap_msg_gen_rand_str((char *)msg_id_buf, sizeof(msg_id_buf));
ranaumarnaeem 34:d6ce8f961b8b 691 msg_id = (((unsigned)msg_id_buf[1]) << 8) | (unsigned)msg_id_buf[0];
ranaumarnaeem 34:d6ce8f961b8b 692 ret = coap_msg_set_msg_id(req, msg_id);
ranaumarnaeem 34:d6ce8f961b8b 693 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 694 {
ranaumarnaeem 34:d6ce8f961b8b 695 return ret;
ranaumarnaeem 34:d6ce8f961b8b 696 }
ranaumarnaeem 34:d6ce8f961b8b 697
ranaumarnaeem 34:d6ce8f961b8b 698 /* generate the token */
ranaumarnaeem 34:d6ce8f961b8b 699 coap_msg_gen_rand_str(token, sizeof(token));
ranaumarnaeem 34:d6ce8f961b8b 700 ret = coap_msg_set_token(req, token, sizeof(token));
ranaumarnaeem 34:d6ce8f961b8b 701 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 702 {
ranaumarnaeem 34:d6ce8f961b8b 703 return ret;
ranaumarnaeem 34:d6ce8f961b8b 704 }
ranaumarnaeem 34:d6ce8f961b8b 705
ranaumarnaeem 34:d6ce8f961b8b 706 if (coap_msg_get_type(req) == COAP_MSG_CON)
ranaumarnaeem 34:d6ce8f961b8b 707 {
ranaumarnaeem 34:d6ce8f961b8b 708 printf("Sending confirmable request to host %s and port %s\n", client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 709 }
ranaumarnaeem 34:d6ce8f961b8b 710 else if (coap_msg_get_type(req) == COAP_MSG_NON)
ranaumarnaeem 34:d6ce8f961b8b 711 {
ranaumarnaeem 34:d6ce8f961b8b 712 printf("Sending non-confirmable request to host %s and port %s\n", client->server_host, client->server_port);
ranaumarnaeem 34:d6ce8f961b8b 713 }
ranaumarnaeem 34:d6ce8f961b8b 714
ranaumarnaeem 34:d6ce8f961b8b 715 num = coap_client_send(client, req);
ranaumarnaeem 34:d6ce8f961b8b 716 if (num < 0)
ranaumarnaeem 34:d6ce8f961b8b 717 {
ranaumarnaeem 34:d6ce8f961b8b 718 return num;
ranaumarnaeem 34:d6ce8f961b8b 719 }
ranaumarnaeem 34:d6ce8f961b8b 720
ranaumarnaeem 34:d6ce8f961b8b 721 if (coap_msg_get_type(req) == COAP_MSG_CON)
ranaumarnaeem 34:d6ce8f961b8b 722 {
ranaumarnaeem 34:d6ce8f961b8b 723 return coap_client_exchange_con(client, req, resp);
ranaumarnaeem 34:d6ce8f961b8b 724 }
ranaumarnaeem 34:d6ce8f961b8b 725 else if (coap_msg_get_type(req) == COAP_MSG_NON)
ranaumarnaeem 34:d6ce8f961b8b 726 {
ranaumarnaeem 34:d6ce8f961b8b 727 return coap_client_exchange_non(client, req, resp);
ranaumarnaeem 34:d6ce8f961b8b 728 }
ranaumarnaeem 34:d6ce8f961b8b 729 return -EINVAL;
ranaumarnaeem 34:d6ce8f961b8b 730 }
ranaumarnaeem 34:d6ce8f961b8b 731 //----------------------------------------------------------------------------------------------------------------------
ranaumarnaeem 34:d6ce8f961b8b 732 //----------------------------------------------------------------------------------------------------------------------
ranaumarnaeem 34:d6ce8f961b8b 733 /**
ranaumarnaeem 34:d6ce8f961b8b 734 * @brief Test an exchange with the server
ranaumarnaeem 34:d6ce8f961b8b 735 *
ranaumarnaeem 34:d6ce8f961b8b 736 * @param[in] data Pointer to a client test data structure
ranaumarnaeem 34:d6ce8f961b8b 737 *
ranaumarnaeem 34:d6ce8f961b8b 738 * @returns Test result
ranaumarnaeem 34:d6ce8f961b8b 739 */
ranaumarnaeem 34:d6ce8f961b8b 740 test_result_t test_exchange_func(char* buf,int buf_len)
ranaumarnaeem 34:d6ce8f961b8b 741 {
ranaumarnaeem 34:d6ce8f961b8b 742 printf("\n----------------------------------------\n");
ranaumarnaeem 34:d6ce8f961b8b 743 test_result_t result = PASS;
ranaumarnaeem 34:d6ce8f961b8b 744 coap_client_t client = {0};
ranaumarnaeem 34:d6ce8f961b8b 745 coap_msg_t resp = {0};
ranaumarnaeem 34:d6ce8f961b8b 746 coap_msg_t req = {0};
ranaumarnaeem 34:d6ce8f961b8b 747 int ret = 0;
ranaumarnaeem 34:d6ce8f961b8b 748
ranaumarnaeem 34:d6ce8f961b8b 749 test_coap_client_msg_op_t req_ops;
ranaumarnaeem 34:d6ce8f961b8b 750 req_ops.num = COAP_MSG_URI_PATH;
ranaumarnaeem 34:d6ce8f961b8b 751 req_ops.len = 8;
ranaumarnaeem 34:d6ce8f961b8b 752 req_ops.val = (char*)"resource";
ranaumarnaeem 34:d6ce8f961b8b 753
ranaumarnaeem 34:d6ce8f961b8b 754 test_coap_client_msg_op_t resp_ops;
ranaumarnaeem 34:d6ce8f961b8b 755 resp_ops.num = 0;
ranaumarnaeem 34:d6ce8f961b8b 756 resp_ops.len = 0;
ranaumarnaeem 34:d6ce8f961b8b 757 resp_ops.val = 0;
ranaumarnaeem 34:d6ce8f961b8b 758
ranaumarnaeem 34:d6ce8f961b8b 759 test_coap_client_msg_t test1_req;
ranaumarnaeem 34:d6ce8f961b8b 760 test1_req.type = COAP_MSG_CON;
ranaumarnaeem 34:d6ce8f961b8b 761 test1_req.code_class = COAP_MSG_REQ;
ranaumarnaeem 34:d6ce8f961b8b 762 test1_req.code_detail = COAP_MSG_GET;
ranaumarnaeem 34:d6ce8f961b8b 763 test1_req.ops = req_ops;
ranaumarnaeem 34:d6ce8f961b8b 764 test1_req.num_ops = 1;
ranaumarnaeem 34:d6ce8f961b8b 765 test1_req.payload = buf;
ranaumarnaeem 34:d6ce8f961b8b 766 test1_req.payload_len = buf_len;
ranaumarnaeem 34:d6ce8f961b8b 767
ranaumarnaeem 34:d6ce8f961b8b 768 test_coap_client_msg_t test1_resp;
ranaumarnaeem 34:d6ce8f961b8b 769 test1_resp.type = COAP_MSG_ACK;
ranaumarnaeem 34:d6ce8f961b8b 770 test1_resp.code_class = COAP_MSG_SUCCESS;
ranaumarnaeem 34:d6ce8f961b8b 771 test1_resp.code_detail = COAP_MSG_CONTENT;
ranaumarnaeem 34:d6ce8f961b8b 772 test1_resp.ops = resp_ops;
ranaumarnaeem 34:d6ce8f961b8b 773 test1_resp.num_ops = 0;
ranaumarnaeem 34:d6ce8f961b8b 774 test1_resp.payload = (char*)"Hello Client!";
ranaumarnaeem 34:d6ce8f961b8b 775 test1_resp.payload_len = 13;
ranaumarnaeem 34:d6ce8f961b8b 776
ranaumarnaeem 34:d6ce8f961b8b 777 test_coap_client_data_t test1_data;
ranaumarnaeem 34:d6ce8f961b8b 778 test1_data.desc = "test 1: send a confirmable request and expect a piggy-backed response";
ranaumarnaeem 34:d6ce8f961b8b 779 test1_data.host = HOST;
ranaumarnaeem 34:d6ce8f961b8b 780 test1_data.port = PORT;
ranaumarnaeem 34:d6ce8f961b8b 781 test1_data.common_name = (char*)"dummy/server";
ranaumarnaeem 34:d6ce8f961b8b 782 test1_data.test_req = test1_req;
ranaumarnaeem 34:d6ce8f961b8b 783 test1_data.test_resp = test1_resp;
ranaumarnaeem 34:d6ce8f961b8b 784 test1_data.num_msg = 1;
ranaumarnaeem 34:d6ce8f961b8b 785
ranaumarnaeem 34:d6ce8f961b8b 786 printf("%s\n", test1_data.desc);
ranaumarnaeem 34:d6ce8f961b8b 787
ranaumarnaeem 34:d6ce8f961b8b 788 ret = coap_client_create(&client,
ranaumarnaeem 34:d6ce8f961b8b 789 test1_data.host,
ranaumarnaeem 34:d6ce8f961b8b 790 test1_data.port);
ranaumarnaeem 34:d6ce8f961b8b 791
ranaumarnaeem 34:d6ce8f961b8b 792 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 793 {
ranaumarnaeem 34:d6ce8f961b8b 794 printf("Error : %s\n",strerror(-ret));
ranaumarnaeem 34:d6ce8f961b8b 795 return FAIL;
ranaumarnaeem 34:d6ce8f961b8b 796 }
ranaumarnaeem 34:d6ce8f961b8b 797
ranaumarnaeem 34:d6ce8f961b8b 798 coap_msg_create(&req);
ranaumarnaeem 34:d6ce8f961b8b 799 coap_msg_create(&resp);
ranaumarnaeem 34:d6ce8f961b8b 800
ranaumarnaeem 34:d6ce8f961b8b 801 ret = exchange(&client, &test1_data.test_req, &req, &resp);
ranaumarnaeem 34:d6ce8f961b8b 802 printf("exchange function\n");
ranaumarnaeem 34:d6ce8f961b8b 803 if (ret != PASS)
ranaumarnaeem 34:d6ce8f961b8b 804 {
ranaumarnaeem 34:d6ce8f961b8b 805 printf("exchange function fail\n");
ranaumarnaeem 34:d6ce8f961b8b 806 coap_msg_destroy(&resp);
ranaumarnaeem 34:d6ce8f961b8b 807 coap_msg_destroy(&req);
ranaumarnaeem 34:d6ce8f961b8b 808 coap_client_destroy(&client);
ranaumarnaeem 34:d6ce8f961b8b 809 return FAIL;
ranaumarnaeem 34:d6ce8f961b8b 810 }
ranaumarnaeem 34:d6ce8f961b8b 811
ranaumarnaeem 34:d6ce8f961b8b 812 ret = compare_ver_token(&req, &resp);
ranaumarnaeem 34:d6ce8f961b8b 813 if (ret != PASS)
ranaumarnaeem 34:d6ce8f961b8b 814 {
ranaumarnaeem 34:d6ce8f961b8b 815 coap_msg_destroy(&resp);
ranaumarnaeem 34:d6ce8f961b8b 816 coap_msg_destroy(&req);
ranaumarnaeem 34:d6ce8f961b8b 817 coap_client_destroy(&client);
ranaumarnaeem 34:d6ce8f961b8b 818 return FAIL;
ranaumarnaeem 34:d6ce8f961b8b 819 }
ranaumarnaeem 34:d6ce8f961b8b 820
ranaumarnaeem 34:d6ce8f961b8b 821 ret = check_resp(&test1_data.test_resp, &resp);
ranaumarnaeem 34:d6ce8f961b8b 822 if (ret != PASS)
ranaumarnaeem 34:d6ce8f961b8b 823 {
ranaumarnaeem 34:d6ce8f961b8b 824 coap_msg_destroy(&resp);
ranaumarnaeem 34:d6ce8f961b8b 825 coap_msg_destroy(&req);
ranaumarnaeem 34:d6ce8f961b8b 826 coap_client_destroy(&client);
ranaumarnaeem 34:d6ce8f961b8b 827 return FAIL;
ranaumarnaeem 34:d6ce8f961b8b 828 }
ranaumarnaeem 34:d6ce8f961b8b 829
ranaumarnaeem 34:d6ce8f961b8b 830 coap_msg_destroy(&resp);
ranaumarnaeem 34:d6ce8f961b8b 831 coap_msg_destroy(&req);
ranaumarnaeem 34:d6ce8f961b8b 832 coap_client_destroy(&client);
ranaumarnaeem 34:d6ce8f961b8b 833
ranaumarnaeem 34:d6ce8f961b8b 834 return result;
ranaumarnaeem 34:d6ce8f961b8b 835 }
ranaumarnaeem 34:d6ce8f961b8b 836 //----------------------------------------------------------------------------------------------------------------------
ranaumarnaeem 34:d6ce8f961b8b 837 //----------------------------------------------------------------------------------------------------------------------
ranaumarnaeem 34:d6ce8f961b8b 838 /**
ranaumarnaeem 34:d6ce8f961b8b 839 * @brief Print a CoAP message
ranaumarnaeem 34:d6ce8f961b8b 840 *
ranaumarnaeem 34:d6ce8f961b8b 841 * @param[in] str String to be printed before the message
ranaumarnaeem 34:d6ce8f961b8b 842 * @param[in] msg Pointer to a message structure
ranaumarnaeem 34:d6ce8f961b8b 843 */
ranaumarnaeem 34:d6ce8f961b8b 844 void print_coap_msg(const char *str, coap_msg_t *msg)
ranaumarnaeem 34:d6ce8f961b8b 845 {
ranaumarnaeem 34:d6ce8f961b8b 846 coap_msg_op_t *op = NULL;
ranaumarnaeem 34:d6ce8f961b8b 847 unsigned num = 0;
ranaumarnaeem 34:d6ce8f961b8b 848 unsigned len = 0;
ranaumarnaeem 34:d6ce8f961b8b 849 unsigned i = 0;
ranaumarnaeem 34:d6ce8f961b8b 850 unsigned j = 0;
ranaumarnaeem 34:d6ce8f961b8b 851 char *payload = NULL;
ranaumarnaeem 34:d6ce8f961b8b 852 char *token = NULL;
ranaumarnaeem 34:d6ce8f961b8b 853 char *val = NULL;
ranaumarnaeem 34:d6ce8f961b8b 854
ranaumarnaeem 34:d6ce8f961b8b 855 printf("%s\n", str);
ranaumarnaeem 34:d6ce8f961b8b 856 printf("ver: 0x%02x\n", coap_msg_get_ver(msg));
ranaumarnaeem 34:d6ce8f961b8b 857 printf("type: 0x%02x\n", coap_msg_get_type(msg));
ranaumarnaeem 34:d6ce8f961b8b 858 printf("token_len: %d\n", coap_msg_get_token_len(msg));
ranaumarnaeem 34:d6ce8f961b8b 859 printf("code_class: %d\n", coap_msg_get_code_class(msg));
ranaumarnaeem 34:d6ce8f961b8b 860 printf("code_detail: %d\n", coap_msg_get_code_detail(msg));
ranaumarnaeem 34:d6ce8f961b8b 861 printf("msg_id: 0x%04x\n", coap_msg_get_msg_id(msg));
ranaumarnaeem 34:d6ce8f961b8b 862 printf("token: ");
ranaumarnaeem 34:d6ce8f961b8b 863 token = coap_msg_get_token(msg);
ranaumarnaeem 34:d6ce8f961b8b 864 for (i = 0; i < coap_msg_get_token_len(msg); i++)
ranaumarnaeem 34:d6ce8f961b8b 865 {
ranaumarnaeem 34:d6ce8f961b8b 866 printf(" 0x%02x", (unsigned char)token[i]);
ranaumarnaeem 34:d6ce8f961b8b 867 }
ranaumarnaeem 34:d6ce8f961b8b 868 printf("\n");
ranaumarnaeem 34:d6ce8f961b8b 869 op = coap_msg_get_first_op(msg);
ranaumarnaeem 34:d6ce8f961b8b 870 while (op != NULL)
ranaumarnaeem 34:d6ce8f961b8b 871 {
ranaumarnaeem 34:d6ce8f961b8b 872 num = coap_msg_op_get_num(op);
ranaumarnaeem 34:d6ce8f961b8b 873 len = coap_msg_op_get_len(op);
ranaumarnaeem 34:d6ce8f961b8b 874 val = coap_msg_op_get_val(op);
ranaumarnaeem 34:d6ce8f961b8b 875 printf("op[%u].num: %u\n", j, num);
ranaumarnaeem 34:d6ce8f961b8b 876 printf("op[%u].len: %u\n", j, len);
ranaumarnaeem 34:d6ce8f961b8b 877 printf("op[%u].val: ", j);
ranaumarnaeem 34:d6ce8f961b8b 878 for (i = 0; i < len; i++)
ranaumarnaeem 34:d6ce8f961b8b 879 {
ranaumarnaeem 34:d6ce8f961b8b 880 printf(" 0x%02x", (unsigned char)val[i]);
ranaumarnaeem 34:d6ce8f961b8b 881 }
ranaumarnaeem 34:d6ce8f961b8b 882 printf("\n");
ranaumarnaeem 34:d6ce8f961b8b 883 op = coap_msg_op_get_next(op);
ranaumarnaeem 34:d6ce8f961b8b 884 j++;
ranaumarnaeem 34:d6ce8f961b8b 885 }
ranaumarnaeem 34:d6ce8f961b8b 886 printf("payload: ");
ranaumarnaeem 34:d6ce8f961b8b 887 payload = coap_msg_get_payload(msg);
ranaumarnaeem 34:d6ce8f961b8b 888 for (i = 0; i < coap_msg_get_payload_len(msg); i++)
ranaumarnaeem 34:d6ce8f961b8b 889 {
ranaumarnaeem 34:d6ce8f961b8b 890 printf("%c", payload[i]);
ranaumarnaeem 34:d6ce8f961b8b 891 }
ranaumarnaeem 34:d6ce8f961b8b 892 printf("\n");
ranaumarnaeem 34:d6ce8f961b8b 893 printf("payload_len: %zu\n", coap_msg_get_payload_len(msg));
ranaumarnaeem 34:d6ce8f961b8b 894 }
ranaumarnaeem 34:d6ce8f961b8b 895 //----------------------------------------------------------------------------------------------------------------------
ranaumarnaeem 34:d6ce8f961b8b 896 //----------------------------------------------------------------------------------------------------------------------
ranaumarnaeem 34:d6ce8f961b8b 897 /**
ranaumarnaeem 34:d6ce8f961b8b 898 * @brief Populate a request message with details from a test request message structure
ranaumarnaeem 34:d6ce8f961b8b 899 *
ranaumarnaeem 34:d6ce8f961b8b 900 * @param[in] test_req Pointer to a test request message structure
ranaumarnaeem 34:d6ce8f961b8b 901 * @param[out] req Pointer to a request message structure
ranaumarnaeem 34:d6ce8f961b8b 902 *
ranaumarnaeem 34:d6ce8f961b8b 903 * @returns Test result
ranaumarnaeem 34:d6ce8f961b8b 904 */
ranaumarnaeem 34:d6ce8f961b8b 905 test_result_t populate_req(test_coap_client_msg_t *test_req, coap_msg_t *req)
ranaumarnaeem 34:d6ce8f961b8b 906 {
ranaumarnaeem 34:d6ce8f961b8b 907 int ret = 0;
ranaumarnaeem 34:d6ce8f961b8b 908
ranaumarnaeem 34:d6ce8f961b8b 909 ret = coap_msg_set_type(req, test_req->type);
ranaumarnaeem 34:d6ce8f961b8b 910 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 911 {
ranaumarnaeem 34:d6ce8f961b8b 912 printf("Error : %s\n",strerror(-ret));
ranaumarnaeem 34:d6ce8f961b8b 913 return FAIL;
ranaumarnaeem 34:d6ce8f961b8b 914 }
ranaumarnaeem 34:d6ce8f961b8b 915 ret = coap_msg_set_code(req, test_req->code_class, test_req->code_detail);
ranaumarnaeem 34:d6ce8f961b8b 916 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 917 {
ranaumarnaeem 34:d6ce8f961b8b 918 printf("Error : %s\n",strerror(-ret));
ranaumarnaeem 34:d6ce8f961b8b 919 return FAIL;
ranaumarnaeem 34:d6ce8f961b8b 920 }
ranaumarnaeem 34:d6ce8f961b8b 921 ret = coap_msg_add_op(req, test_req->ops.num, test_req->ops.len, test_req->ops.val);
ranaumarnaeem 34:d6ce8f961b8b 922 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 923 {
ranaumarnaeem 34:d6ce8f961b8b 924 printf("Error : %s\n",strerror(-ret));
ranaumarnaeem 34:d6ce8f961b8b 925 return FAIL;
ranaumarnaeem 34:d6ce8f961b8b 926 }
ranaumarnaeem 34:d6ce8f961b8b 927 if (test_req->payload)
ranaumarnaeem 34:d6ce8f961b8b 928 {
ranaumarnaeem 34:d6ce8f961b8b 929 ret = coap_msg_set_payload(req, test_req->payload, test_req->payload_len);
ranaumarnaeem 34:d6ce8f961b8b 930 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 931 {
ranaumarnaeem 34:d6ce8f961b8b 932 printf("Error : %s\n",strerror(-ret));
ranaumarnaeem 34:d6ce8f961b8b 933 return FAIL;
ranaumarnaeem 34:d6ce8f961b8b 934 }
ranaumarnaeem 34:d6ce8f961b8b 935 }
ranaumarnaeem 34:d6ce8f961b8b 936 return PASS;
ranaumarnaeem 34:d6ce8f961b8b 937 }
ranaumarnaeem 34:d6ce8f961b8b 938 //----------------------------------------------------------------------------------------------------------------------
ranaumarnaeem 34:d6ce8f961b8b 939 //----------------------------------------------------------------------------------------------------------------------
ranaumarnaeem 34:d6ce8f961b8b 940 /**
ranaumarnaeem 34:d6ce8f961b8b 941 * @brief Send a request to the server and receive the response
ranaumarnaeem 34:d6ce8f961b8b 942 *
ranaumarnaeem 34:d6ce8f961b8b 943 * @param[in,out] client Pointer to a client structure
ranaumarnaeem 34:d6ce8f961b8b 944 * @param[in] test_req Pointer to a test request message structure
ranaumarnaeem 34:d6ce8f961b8b 945 * @param[out] req Pointer to a request message structure
ranaumarnaeem 34:d6ce8f961b8b 946 * @param[out] resp Pointer to a response message structure
ranaumarnaeem 34:d6ce8f961b8b 947 *
ranaumarnaeem 34:d6ce8f961b8b 948 * @returns Test result
ranaumarnaeem 34:d6ce8f961b8b 949 */
ranaumarnaeem 34:d6ce8f961b8b 950 test_result_t exchange(coap_client_t *client, test_coap_client_msg_t *test_req, coap_msg_t *req, coap_msg_t *resp)
ranaumarnaeem 34:d6ce8f961b8b 951 {
ranaumarnaeem 34:d6ce8f961b8b 952 test_result_t result = PASS;
ranaumarnaeem 34:d6ce8f961b8b 953 int ret = 0;
ranaumarnaeem 34:d6ce8f961b8b 954
ranaumarnaeem 34:d6ce8f961b8b 955 result = populate_req(test_req, req);
ranaumarnaeem 34:d6ce8f961b8b 956 if (result != PASS)
ranaumarnaeem 34:d6ce8f961b8b 957 {
ranaumarnaeem 34:d6ce8f961b8b 958 printf("populate_req FAIL\n");
ranaumarnaeem 34:d6ce8f961b8b 959 return result;
ranaumarnaeem 34:d6ce8f961b8b 960 }
ranaumarnaeem 34:d6ce8f961b8b 961 ret = coap_client_exchange(client, req, resp);
ranaumarnaeem 34:d6ce8f961b8b 962 if (ret < 0)
ranaumarnaeem 34:d6ce8f961b8b 963 {
ranaumarnaeem 34:d6ce8f961b8b 964 printf("coap_client_exchange FAIL\n");
ranaumarnaeem 34:d6ce8f961b8b 965 printf("Error : %s\n",strerror(-ret));
ranaumarnaeem 34:d6ce8f961b8b 966 return FAIL;
ranaumarnaeem 34:d6ce8f961b8b 967 }
ranaumarnaeem 34:d6ce8f961b8b 968 printf("coap_client_exchange PASS\n");
ranaumarnaeem 34:d6ce8f961b8b 969 print_coap_msg("Sent:", req);
ranaumarnaeem 34:d6ce8f961b8b 970 print_coap_msg("Received:", resp);
ranaumarnaeem 34:d6ce8f961b8b 971
ranaumarnaeem 34:d6ce8f961b8b 972 return PASS;
ranaumarnaeem 34:d6ce8f961b8b 973 }
ranaumarnaeem 34:d6ce8f961b8b 974 //----------------------------------------------------------------------------------------------------------------------
ranaumarnaeem 34:d6ce8f961b8b 975 //----------------------------------------------------------------------------------------------------------------------
ranaumarnaeem 34:d6ce8f961b8b 976 /**
ranaumarnaeem 34:d6ce8f961b8b 977 * @brief Compare the version and token fields in a request message and a response message
ranaumarnaeem 34:d6ce8f961b8b 978 *
ranaumarnaeem 34:d6ce8f961b8b 979 * @param[out] req Pointer to a request message structure
ranaumarnaeem 34:d6ce8f961b8b 980 * @param[out] resp Pointer to a response message structure
ranaumarnaeem 34:d6ce8f961b8b 981 *
ranaumarnaeem 34:d6ce8f961b8b 982 * @returns Test result
ranaumarnaeem 34:d6ce8f961b8b 983 */
ranaumarnaeem 34:d6ce8f961b8b 984 test_result_t compare_ver_token(coap_msg_t *req, coap_msg_t *resp)
ranaumarnaeem 34:d6ce8f961b8b 985 {
ranaumarnaeem 34:d6ce8f961b8b 986 if (coap_msg_get_ver(req) != coap_msg_get_ver(resp))
ranaumarnaeem 34:d6ce8f961b8b 987 {
ranaumarnaeem 34:d6ce8f961b8b 988 return FAIL;
ranaumarnaeem 34:d6ce8f961b8b 989 }
ranaumarnaeem 34:d6ce8f961b8b 990 if (coap_msg_get_token_len(req) != coap_msg_get_token_len(resp))
ranaumarnaeem 34:d6ce8f961b8b 991 {
ranaumarnaeem 34:d6ce8f961b8b 992 return FAIL;
ranaumarnaeem 34:d6ce8f961b8b 993 }
ranaumarnaeem 34:d6ce8f961b8b 994 else if (memcmp(coap_msg_get_token(req), coap_msg_get_token(resp), coap_msg_get_token_len(req)) != 0)
ranaumarnaeem 34:d6ce8f961b8b 995 {
ranaumarnaeem 34:d6ce8f961b8b 996 return FAIL;
ranaumarnaeem 34:d6ce8f961b8b 997 }
ranaumarnaeem 34:d6ce8f961b8b 998 return PASS;
ranaumarnaeem 34:d6ce8f961b8b 999 }
ranaumarnaeem 34:d6ce8f961b8b 1000 //----------------------------------------------------------------------------------------------------------------------
ranaumarnaeem 34:d6ce8f961b8b 1001 //----------------------------------------------------------------------------------------------------------------------
ranaumarnaeem 34:d6ce8f961b8b 1002 /**
ranaumarnaeem 34:d6ce8f961b8b 1003 * @brief Check the fields in a response message against the expected values
ranaumarnaeem 34:d6ce8f961b8b 1004 *
ranaumarnaeem 34:d6ce8f961b8b 1005 * @param[out] test_resp Pointer to a test response message structure
ranaumarnaeem 34:d6ce8f961b8b 1006 * @param[out] resp Pointer to a response message structure
ranaumarnaeem 34:d6ce8f961b8b 1007 *
ranaumarnaeem 34:d6ce8f961b8b 1008 * @returns Test result
ranaumarnaeem 34:d6ce8f961b8b 1009 */
ranaumarnaeem 34:d6ce8f961b8b 1010 test_result_t check_resp(test_coap_client_msg_t *test_resp, coap_msg_t *resp)
ranaumarnaeem 34:d6ce8f961b8b 1011 {
ranaumarnaeem 34:d6ce8f961b8b 1012 if (test_resp->type != coap_msg_get_type(resp))
ranaumarnaeem 34:d6ce8f961b8b 1013 {
ranaumarnaeem 34:d6ce8f961b8b 1014 return FAIL;
ranaumarnaeem 34:d6ce8f961b8b 1015 }
ranaumarnaeem 34:d6ce8f961b8b 1016 if (test_resp->code_class != coap_msg_get_code_class(resp))
ranaumarnaeem 34:d6ce8f961b8b 1017 {
ranaumarnaeem 34:d6ce8f961b8b 1018 return FAIL;
ranaumarnaeem 34:d6ce8f961b8b 1019 }
ranaumarnaeem 34:d6ce8f961b8b 1020 if (test_resp->code_detail != coap_msg_get_code_detail(resp))
ranaumarnaeem 34:d6ce8f961b8b 1021 {
ranaumarnaeem 34:d6ce8f961b8b 1022 return FAIL;
ranaumarnaeem 34:d6ce8f961b8b 1023 }
ranaumarnaeem 34:d6ce8f961b8b 1024 if (test_resp->payload_len != coap_msg_get_payload_len(resp))
ranaumarnaeem 34:d6ce8f961b8b 1025 {
ranaumarnaeem 34:d6ce8f961b8b 1026 return FAIL;
ranaumarnaeem 34:d6ce8f961b8b 1027 }
ranaumarnaeem 34:d6ce8f961b8b 1028 else if (memcmp(test_resp->payload, coap_msg_get_payload(resp), test_resp->payload_len))
ranaumarnaeem 34:d6ce8f961b8b 1029 {
ranaumarnaeem 34:d6ce8f961b8b 1030 return FAIL;
ranaumarnaeem 34:d6ce8f961b8b 1031 }
ranaumarnaeem 34:d6ce8f961b8b 1032 return PASS;
ranaumarnaeem 34:d6ce8f961b8b 1033 }