mbed 5.4 with sleep mode
Diff: Coap/coap_client.c
- Revision:
- 39:4f3f7463e55f
- Parent:
- 38:f1bc6e867fcf
--- a/Coap/coap_client.c Wed May 24 07:51:33 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1021 +0,0 @@ -/* - * Copyright (c) 2015 Keith Cullen. - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file coap_client.c - * - * @brief Source file for the FreeCoAP client library - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <stdint.h> -#include <errno.h> - -#include "coap_client.h" -#include "main.h" - -#define COAP_CLIENT_ACK_TIMEOUT_SEC 2 /**< Minimum delay to wait before retransmitting a confirmable message */ -#define COAP_CLIENT_MAX_RETRANSMIT 4 /**< Maximum number of times a confirmable message can be retransmitted */ -#define COAP_CLIENT_RESP_TIMEOUT_SEC 30 /**< Maximum amount of time to wait for a response */ - -/**************************************************************************************************** - * coap_client * - ****************************************************************************************************/ -void coap_client_destroy(coap_client_t *client) -{ - memset(client, 0, sizeof(coap_client_t)); -} - -/** - * @brief Send a message to the server - * - * @param[in,out] client Pointer to a client structure - * @param[in] msg Pointer to a message structure - * - * @returns Number of bytes sent or error code - * @retval >0 Number of bytes sent - * @retval <0 Error - */ -static int coap_client_send(coap_client_t *client, coap_msg_t *msg) -{ - int num = 0; - char buf[COAP_MSG_MAX_BUF_LEN] = {0}; - - num = coap_msg_format(msg, buf, sizeof(buf)); - if (num < 0) - { - return num; - } - num = send(client->sd, buf, num); - if (num < 0) - { - printf("send error\n"); - return -errno; - } - - return num; -} - -/** - * @brief Handle a format error in a received message - * - * Special handling for the case where a received - * message could not be parsed due to a format error. - * Extract enough information from the received message - * to form a reset message. - * - * @param[in,out] client Pointer to a client structure - * @param[in] buf Buffer containing the message - * @param[in] len length of the buffer - */ -static void coap_client_handle_format_error(coap_client_t *client, char *buf, size_t len) -{ - coap_msg_t msg = {0}; - unsigned msg_id = 0; - unsigned type = 0; - int ret = 0; - - ret = coap_msg_parse_type_msg_id(buf, len, &type, &msg_id); - if ((ret == 0) && (type == COAP_MSG_CON)) - { - coap_msg_create(&msg); - ret = coap_msg_set_type(&msg, COAP_MSG_RST); - if (ret < 0) - { - coap_msg_destroy(&msg); - return; - } - ret = coap_msg_set_msg_id(&msg, msg_id); - if (ret < 0) - { - coap_msg_destroy(&msg); - return; - } - coap_client_send(client, &msg); - coap_msg_destroy(&msg); - } -} - -/** - * @brief Receive a message from the server - * - * @param[in,out] client Pointer to a client structure - * @param[in] msg Pointer to a message structure - * - * @returns Number of bytes received or error code - * @retval >0 Number of bytes received - * @retval <0 Error - */ -static int coap_client_recv(coap_client_t *client, coap_msg_t *msg) -{ - int num = 0; - int ret = 0; - char buf[COAP_MSG_MAX_BUF_LEN] = {0}; - - num = recv(client->sd, buf, sizeof(buf)); - if (num < 0) - { - return -errno; - } - - ret = coap_msg_parse(msg, buf, num); - if (ret < 0) - { - if (ret == -EBADMSG) - { - coap_client_handle_format_error(client, buf, num); - } - return ret; - } - return num; -} - -/** - * @brief Reject a received confirmable message - * - * Send a reset message to the server. - * - * @param[in,out] client Pointer to a client structure - * @param[in] msg Pointer to a message structure - * - * @returns Operation status - * @retval 0 Success - * @retval <0 Error - */ -static int coap_client_reject_con(coap_client_t *client, coap_msg_t *msg) -{ - coap_msg_t rej = {0}; - int num = 0; - int ret = 0; - - printf("Rejecting confirmable message from host %s and port %s\n", client->server_host, client->server_port); - coap_msg_create(&rej); - ret = coap_msg_set_type(&rej, COAP_MSG_RST); - if (ret < 0) - { - coap_msg_destroy(&rej); - return ret; - } - ret = coap_msg_set_msg_id(&rej, coap_msg_get_msg_id(msg)); - if (ret < 0) - { - coap_msg_destroy(&rej); - return ret; - } - num = coap_client_send(client, &rej); - coap_msg_destroy(&rej); - if (num < 0) - { - return num; - } - return 0; -} - -/** - * @brief Reject a received non-confirmable message - * - * @param[in] client Pointer to a client structure - * @param[in] msg Pointer to a message structure - * - * @returns Operation status - * @retval 0 Success - */ -static int coap_client_reject_non(coap_client_t *client, coap_msg_t *msg) -{ - printf("Rejecting non-confirmable message from host %s and port %s\n", client->server_host, client->server_port); - return 0; -} - -/** - * @brief Reject a received acknowledgement message - * - * @param[in] client Pointer to a client structure - * @param[in] msg Pointer to a message structure - * - * @returns Operation status - * @retval 0 Success - */ -static int coap_client_reject_ack(coap_client_t *client, coap_msg_t *msg) -{ - printf("Rejecting acknowledgement message from host %s and port %s\n", client->server_host, client->server_port); - return 0; -} - -/** - * @brief Reject a received reset message - * - * @param[in] client Pointer to a client structure - * @param[in] msg Pointer to a message structure - * - * @returns Operation status - * @retval 0 Success - */ -static int coap_client_reject_reset(coap_client_t *client, coap_msg_t *msg) -{ - printf("Rejecting reset message from host %s and port %s\n", client->server_host, client->server_port); - return 0; -} - -/** - * @brief Reject a received message - * - * @param[in,out] client Pointer to a client structure - * @param[in] msg Pointer to a message structure - * - * @returns Operation status - * @retval 0 Success - * @retval <0 Error - */ -static int coap_client_reject(coap_client_t *client, coap_msg_t *msg) -{ - if (coap_msg_get_type(msg) == COAP_MSG_CON) - { - return coap_client_reject_con(client, msg); - } - else if (coap_msg_get_type(msg) == COAP_MSG_NON) - { - return coap_client_reject_non(client, msg); - } - else if (coap_msg_get_type(msg) == COAP_MSG_ACK) - { - return coap_client_reject_ack(client, msg); - } - else if (coap_msg_get_type(msg) == COAP_MSG_RST) - { - return coap_client_reject_reset(client, msg); - } - return 0; /* should never arrive here */ -} - -/** - * @brief Send an acknowledgement message to the server - * - * @param[in,out] client Pointer to a client structure - * @param[in] msg Pointer to a message structure - * - * @returns Operation status - * @retval 0 Success - * @retval <0 Error - */ -static int coap_client_send_ack(coap_client_t *client, coap_msg_t *msg) -{ - coap_msg_t ack = {0}; - int num = 0; - int ret = 0; - - printf("Acknowledging confirmable message from host %s and port %s\n", client->server_host, client->server_port); - coap_msg_create(&ack); - ret = coap_msg_set_type(&ack, COAP_MSG_ACK); - if (ret < 0) - { - coap_msg_destroy(&ack); - return ret; - } - ret = coap_msg_set_msg_id(&ack, coap_msg_get_msg_id(msg)); - if (ret < 0) - { - coap_msg_destroy(&ack); - return ret; - } - num = coap_client_send(client, &ack); - coap_msg_destroy(&ack); - if (num < 0) - { - return num; - } - return 0; -} - -/** - * @brief Compare the token values in a request message and a response message - * - * @param[in] req Pointer to the request message - * @param[in] resp Pointer to the response message - * - * @returns Comparison value - * @retval 0 the tokens are not equal - * @retval 1 the tokens are equal - */ -static int coap_client_match_token(coap_msg_t *req, coap_msg_t *resp) -{ - return ((coap_msg_get_token_len(resp) == coap_msg_get_token_len(req)) - && (memcmp(coap_msg_get_token(resp), coap_msg_get_token(req), coap_msg_get_token_len(req)) == 0)); -} - -/** - * @brief Check that all of the options in a message are acceptable - * - * For a proxy, options are acceptable if they are safe to forward or recognized or both. - * For a server, options are acceptable if they are elective or recognized or both. - * - * @param[in] msg Pointer to message structure - * - * @returns Operation status or bad option number - * @retval 0 Success - * @retval >0 Bad option number - */ -static unsigned coap_client_check_options(coap_msg_t *msg) -{ -#ifdef COAP_PROXY - return coap_msg_check_unsafe_ops(msg); -#else /* !COAP_PROXY */ - return coap_msg_check_critical_ops(msg); -#endif /* COAP_PROXY */ -} - -/** - * @brief Handle a received piggy-backed response message - * - * An acknowledgement has been received that contains - * the same token as the request. Check the response - * contained within it. - * - * @param[in,out] client Pointer to a client structure - * @param[in] resp Pointer to the response message - * - * @returns Operation status - * @retval 0 Success - * @retval <0 Error - */ -static int coap_client_handle_piggybacked_response(coap_client_t *client, coap_msg_t *resp) -{ - unsigned op_num = 0; - - op_num = coap_client_check_options(resp); - if (op_num != 0) - { - printf("Found bad option number %u in message from host %s and port %s\n", op_num, client->server_host, client->server_port); - coap_client_reject(client, resp); - return -EBADMSG; - } - printf("Received acknowledgement and response from Server\n"); - return 0; -} - -/** - * @brief Handle a received separate response message - * - * A separate response has been received that contains - * the same token as the request. Check the response - * and send an acknowledgement if necessary. - * - * @param[in,out] client Pointer to a client structure - * @param[in] resp Pointer to the response message - * - * @returns Operation status - * @retval 0 Success - * @retval <0 Error - */ -static int coap_client_handle_sep_response(coap_client_t *client, coap_msg_t *resp) -{ - unsigned op_num = 0; - - if (coap_msg_get_type(resp) == COAP_MSG_CON) - { - printf("Received confirmable response from host %s and port %s\n", client->server_host, client->server_port); - op_num = coap_client_check_options(resp); - if (op_num != 0) - { - printf("Found bad option number %u in message from host %s and port %s\n", op_num, client->server_host, client->server_port); - coap_client_reject(client, resp); - return -EBADMSG; - } - return coap_client_send_ack(client, resp); - } - else if (coap_msg_get_type(resp) == COAP_MSG_NON) - { - printf("Received non-confirmable response from host %s and port %s\n", client->server_host, client->server_port); - op_num = coap_client_check_options(resp); - if (op_num != 0) - { - printf("Found bad option number %u in message from host %s and port %s\n", op_num, client->server_host, client->server_port); - coap_client_reject(client, resp); - return -EBADMSG; - } - return 0; - } - coap_client_reject(client, resp); - return -EBADMSG; -} - -/** - * @brief Handle a separate response to a confirmable request - * - * An acknowledgement has been received. Receive the - * response and send an acknowledgement back to the server. - * - * @param[in,out] client Pointer to a client structure - * @param[in] req Pointer to the request message - * @param[out] resp Pointer to the response message - * - * @returns Operation status - * @retval 0 Success - * @retval <0 Error - */ -static int coap_client_exchange_sep(coap_client_t *client, coap_msg_t *req, coap_msg_t *resp) -{ - int num = 0; - int ret = 0; - int starttimeout,endtimeout; - - /* wait for a separate response to a confirmable request */ - printf("Expecting response from host %s and port %s\n", client->server_host, client->server_port); - while (1) - { - starttimeout = readseconds(); - while(1) - { - num = coap_client_recv(client, resp); - if (num < 0) - { - return num; - } - else if(num > 0) - { - break; - } - endtimeout = readseconds(); - if((endtimeout - starttimeout) > COAP_CLIENT_RESP_TIMEOUT_SEC) - { - printf("Timeout no data received\n"); - return -1; - } - } - - if (coap_msg_get_msg_id(resp) == coap_msg_get_msg_id(req)) - { - if (coap_msg_get_type(resp) == COAP_MSG_ACK) - { - /* message deduplication */ - printf("Received duplicate acknowledgement from host %s and port %s\n", client->server_host, client->server_port); - continue; - } - else if (coap_msg_get_type(resp) == COAP_MSG_RST) - { - return -ECONNRESET; - } - coap_client_reject(client, resp); - return -EBADMSG; - } - if (coap_client_match_token(req, resp)) - { - return coap_client_handle_sep_response(client, resp); - } - /* message deduplication */ - /* we might have received a duplicate message that was already received from the same server */ - /* reject the message and continue listening */ - ret = coap_client_reject(client, resp); - if (ret < 0 ) - { - return ret; - } - } - return 0; -} - -/** - * @brief Handle the response to a confirmable request - * - * A confirmable request has been sent to the server. - * Receive the acknowledgement and response. Send an - * acknowledgement if necessary. - * - * @param[in,out] client Pointer to a client structure - * @param[in] req Pointer to the request message - * @param[out] resp Pointer to the response message - * - * @returns Operation status - * @retval 0 Success - * @retval <0 Error - */ -static int coap_client_exchange_con(coap_client_t *client, coap_msg_t *req, coap_msg_t *resp) -{ - int num = 0; - int ret = 0; - int starttimeout,endtimeout; - /* wait for piggy-backed response in ack message - * or ack message and separate response message - */ - //printf("Expecting acknowledgement from server\r\n"); - client->num_retrans = 0; - while (1) - { - int doubletimeout = COAP_CLIENT_ACK_TIMEOUT_SEC; - starttimeout = readseconds(); - while(1) - { - num = coap_client_recv(client, resp); - if (num < 0) - { - //return num; - } - else if(num > 0) - { - break; - } - endtimeout = readseconds(); - if((endtimeout - starttimeout) > doubletimeout) - { - printf("Timeout no data received after %d seconds\n",endtimeout - starttimeout); - - if (client->num_retrans >= COAP_CLIENT_MAX_RETRANSMIT) - { - printf("Maximum retries reached no ack from server!\r\n"); - return -ETIMEDOUT; - } - - doubletimeout = 2 * doubletimeout; - starttimeout = readseconds(); - client->num_retrans++; - - printf("Retransmitting to server...\r\n"); - num = coap_client_send(client, req); - if (num < 0) - { - printf("Resending Failed to server...\r\n"); - return num; - } - } - } - - if (coap_msg_get_msg_id(resp) == coap_msg_get_msg_id(req)) - { - if (coap_msg_get_type(resp) == COAP_MSG_ACK) - { - if (coap_msg_is_empty(resp)) - { - /* received ack message, wait for separate response message */ - printf("Received acknowledgement from host %s and port %s\n", client->server_host, client->server_port); - return coap_client_exchange_sep(client, req, resp); - } - else if (coap_client_match_token(req, resp)) - { - return coap_client_handle_piggybacked_response(client, resp); - } - } - else if (coap_msg_get_type(resp) == COAP_MSG_RST) - { - return -ECONNRESET; - } - coap_client_reject(client, resp); - return -EBADMSG; - } - else if (coap_client_match_token(req, resp)) - { - /* RFC7252 - * as the underlying datagram transport may not be sequence-preserving, - * the Confirmable message carrying the response may actually arrive - * before or after the Acknowledgement message for the request; for - * the purposes of terminating the retransmission sequence, this also - * serves as an acknowledgement. - */ - return coap_client_handle_sep_response(client, resp); - } - /* message deduplication */ - /* we might have received a duplicate message that was already received from the same server */ - /* reject the message and continue listening */ - ret = coap_client_reject(client, resp); - if (ret < 0 ) - { - return ret; - } - } - return 0; -} - -/** - * @brief Handle the response to a non-confirmable request - * - * A non-confirmable request has been sent to the server. - * Receive the response. - * - * @param[in,out] client Pointer to a client structure - * @param[in] req Pointer to the request message - * @param[out] resp Pointer to the response message - * - * @returns Operation status - * @retval 0 Success - * @retval <0 Error - **/ -static int coap_client_exchange_non(coap_client_t *client, coap_msg_t *req, coap_msg_t *resp) -{ - int num = 0; - int ret = 0; - int starttimeout,endtimeout; - - printf("Expecting response from host %s and port %s\n", client->server_host, client->server_port); - while (1) - { - starttimeout = readseconds(); - while(1) - { - num = coap_client_recv(client, resp); - if (num < 0) - { - return num; - } - else if(num > 0) - { - break; - } - endtimeout = readseconds(); - if((endtimeout - starttimeout) > COAP_CLIENT_RESP_TIMEOUT_SEC) - { - printf("Timeout no data received\n"); - return -1; - } - } - - if (coap_msg_get_msg_id(resp) == coap_msg_get_msg_id(req)) - { - if (coap_msg_get_type(resp) == COAP_MSG_RST) - { - return -ECONNRESET; - } - coap_client_reject(client, resp); - return -EBADMSG; - } - if (coap_client_match_token(req, resp)) - { - return coap_client_handle_sep_response(client, resp); - } - /* message deduplication */ - /* we might have received a duplicate message that was already received from the same server */ - /* reject the message and continue listening */ - ret = coap_client_reject(client, resp); - if (ret < 0 ) - { - return ret; - } - } - return 0; -} - -int coap_client_exchange(coap_client_t *client, coap_msg_t *req, coap_msg_t *resp) -{ - unsigned char msg_id_buf[2] = {0}; - unsigned msg_id = 0; - int num = 0; - char token[4] = {0}; - int ret = 0; - - /* check for a valid request */ - if ((coap_msg_get_type(req) == COAP_MSG_ACK) - || (coap_msg_get_type(req) == COAP_MSG_RST) - || (coap_msg_get_code_class(req) != COAP_MSG_REQ)) - { - return -EINVAL; - } - - /* generate the message ID */ - coap_msg_gen_rand_str((char *)msg_id_buf, sizeof(msg_id_buf)); - msg_id = (((unsigned)msg_id_buf[1]) << 8) | (unsigned)msg_id_buf[0]; - ret = coap_msg_set_msg_id(req, msg_id); - if (ret < 0) - { - return ret; - } - - /* generate the token */ - coap_msg_gen_rand_str(token, sizeof(token)); - ret = coap_msg_set_token(req, token, sizeof(token)); - if (ret < 0) - { - return ret; - } - - num = coap_client_send(client, req); - if (num < 0) - { - return num; - } - - if (coap_msg_get_type(req) == COAP_MSG_CON) - { - return coap_client_exchange_con(client, req, resp); - } - else if (coap_msg_get_type(req) == COAP_MSG_NON) - { - return coap_client_exchange_non(client, req, resp); - } - return -EINVAL; -} -//---------------------------------------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------------------------------------- -/** - * @brief Test an exchange with the server - * - * @param[in] data Pointer to a client test data structure - * - * @returns Test result - */ -test_result_t test_exchange_func(char* buf,int buf_len) -{ - printf("----------------------------------------\n"); - test_result_t result = PASS; - coap_client_t client = {0}; - coap_msg_t resp = {0}; - coap_msg_t req = {0}; - int ret = 0; - - test_coap_client_msg_op_t req_ops; - req_ops.num = COAP_MSG_URI_PATH; - req_ops.len = 8; - req_ops.val = (char*)"resource"; - - test_coap_client_msg_op_t resp_ops; - resp_ops.num = 0; - resp_ops.len = 0; - resp_ops.val = 0; - - test_coap_client_msg_t test1_req; - test1_req.type = COAP_MSG_CON; - test1_req.code_class = COAP_MSG_REQ; - test1_req.code_detail = COAP_MSG_GET; - test1_req.ops = req_ops; - test1_req.num_ops = 1; - test1_req.payload = buf; - test1_req.payload_len = buf_len; - - test_coap_client_msg_t test1_resp; - test1_resp.type = COAP_MSG_ACK; - test1_resp.code_class = COAP_MSG_SUCCESS; - test1_resp.code_detail = COAP_MSG_CONTENT; - test1_resp.ops = resp_ops; - test1_resp.num_ops = 0; - test1_resp.payload = (char*)"Hello Client!"; - test1_resp.payload_len = 13; - - test_coap_client_data_t test1_data; - test1_data.desc = "Send a confirmable request to server and expect a piggy-backed response"; - test1_data.host = HOST; - test1_data.port = PORT; - test1_data.common_name = (char*)"dummy/server"; - test1_data.test_req = test1_req; - test1_data.test_resp = test1_resp; - test1_data.num_msg = 1; - - //printf("%s\n", test1_data.desc); - - if (ret < 0) - { - printf("Error : %s\n",strerror(-ret)); - return FAIL; - } - - coap_msg_create(&req); - coap_msg_create(&resp); - - ret = exchange(&client, &test1_data.test_req, &req, &resp); - //printf("exchange function\n"); - if (ret != PASS) - { - printf("exchange function fail\n"); - coap_msg_destroy(&resp); - coap_msg_destroy(&req); - coap_client_destroy(&client); - return FAIL; - } - - ret = compare_ver_token(&req, &resp); - if (ret != PASS) - { - coap_msg_destroy(&resp); - coap_msg_destroy(&req); - coap_client_destroy(&client); - return FAIL; - } - - ret = check_resp(&test1_data.test_resp, &resp); - if (ret != PASS) - { - coap_msg_destroy(&resp); - coap_msg_destroy(&req); - coap_client_destroy(&client); - return FAIL; - } - - coap_msg_destroy(&resp); - coap_msg_destroy(&req); - coap_client_destroy(&client); - - return result; -} -//---------------------------------------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------------------------------------- -/** - * @brief Print a CoAP message - * - * @param[in] str String to be printed before the message - * @param[in] msg Pointer to a message structure - */ -void print_coap_msg(const char *str, coap_msg_t *msg) -{ - //coap_msg_op_t *op = NULL; - //unsigned num = 0; - //unsigned len = 0; - unsigned i = 0; - //unsigned j = 0; - char *payload = NULL; - char *token = NULL; - //char *val = NULL; - - printf("%s\n", str); - printf("ver: 0x%02x\n", coap_msg_get_ver(msg)); - printf("type: 0x%02x\n", coap_msg_get_type(msg)); - printf("token_len: %d\n", coap_msg_get_token_len(msg)); - printf("code_class: %d\n", coap_msg_get_code_class(msg)); - printf("code_detail: %d\n", coap_msg_get_code_detail(msg)); - printf("msg_id: 0x%04x\n", coap_msg_get_msg_id(msg)); - printf("token: "); - token = coap_msg_get_token(msg); - for (i = 0; i < coap_msg_get_token_len(msg); i++) - { - printf(" 0x%02x", (unsigned char)token[i]); - } - printf("\n"); - /*op = coap_msg_get_first_op(msg); - while (op != NULL) - { - num = coap_msg_op_get_num(op); - len = coap_msg_op_get_len(op); - val = coap_msg_op_get_val(op); - printf("op[%u].num: %u\n", j, num); - printf("op[%u].len: %u\n", j, len); - printf("op[%u].val: ", j); - for (i = 0; i < len; i++) - { - printf(" 0x%02x", (unsigned char)val[i]); - } - printf("\n"); - op = coap_msg_op_get_next(op); - j++; - }*/ - printf("payload: "); - payload = coap_msg_get_payload(msg); - for (i = 0; i < coap_msg_get_payload_len(msg); i++) - { - printf("%c", payload[i]); - //ucReturnCode[i] = payload[i]; - } - //ucReturnCode[i] = '\0'; - printf("\n"); - printf("payload_len: %zu\n", coap_msg_get_payload_len(msg)); -} -//---------------------------------------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------------------------------------- -/** - * @brief Populate a request message with details from a test request message structure - * - * @param[in] test_req Pointer to a test request message structure - * @param[out] req Pointer to a request message structure - * - * @returns Test result - */ -test_result_t populate_req(test_coap_client_msg_t *test_req, coap_msg_t *req) -{ - int ret = 0; - - ret = coap_msg_set_type(req, test_req->type); - if (ret < 0) - { - printf("Error : %s\n",strerror(-ret)); - return FAIL; - } - ret = coap_msg_set_code(req, test_req->code_class, test_req->code_detail); - if (ret < 0) - { - printf("Error : %s\n",strerror(-ret)); - return FAIL; - } - ret = coap_msg_add_op(req, test_req->ops.num, test_req->ops.len, test_req->ops.val); - if (ret < 0) - { - printf("Error : %s\n",strerror(-ret)); - return FAIL; - } - if (test_req->payload) - { - ret = coap_msg_set_payload(req, test_req->payload, test_req->payload_len); - if (ret < 0) - { - printf("Error : %s\n",strerror(-ret)); - return FAIL; - } - } - return PASS; -} -//---------------------------------------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------------------------------------- -/** - * @brief Send a request to the server and receive the response - * - * @param[in,out] client Pointer to a client structure - * @param[in] test_req Pointer to a test request message structure - * @param[out] req Pointer to a request message structure - * @param[out] resp Pointer to a response message structure - * - * @returns Test result - */ -test_result_t exchange(coap_client_t *client, test_coap_client_msg_t *test_req, coap_msg_t *req, coap_msg_t *resp) -{ - test_result_t result = PASS; - int ret = 0; - - result = populate_req(test_req, req); - if (result != PASS) - { - printf("populate_req FAIL\n"); - return result; - } - ret = coap_client_exchange(client, req, resp); - if (ret < 0) - { - printf("coap_client_exchange FAIL\n"); - printf("Error : %s\n",strerror(-ret)); - return FAIL; - } - //printf("coap_client_exchange PASS\n"); - print_coap_msg("Sent:", req); - print_coap_msg("Received:", resp); - - return PASS; -} -//---------------------------------------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------------------------------------- -/** - * @brief Compare the version and token fields in a request message and a response message - * - * @param[out] req Pointer to a request message structure - * @param[out] resp Pointer to a response message structure - * - * @returns Test result - */ -test_result_t compare_ver_token(coap_msg_t *req, coap_msg_t *resp) -{ - if (coap_msg_get_ver(req) != coap_msg_get_ver(resp)) - { - return FAIL; - } - if (coap_msg_get_token_len(req) != coap_msg_get_token_len(resp)) - { - return FAIL; - } - else if (memcmp(coap_msg_get_token(req), coap_msg_get_token(resp), coap_msg_get_token_len(req)) != 0) - { - return FAIL; - } - return PASS; -} -//---------------------------------------------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------------------------------------------- -/** - * @brief Check the fields in a response message against the expected values - * - * @param[out] test_resp Pointer to a test response message structure - * @param[out] resp Pointer to a response message structure - * - * @returns Test result - */ -test_result_t check_resp(test_coap_client_msg_t *test_resp, coap_msg_t *resp) -{ - if (test_resp->type != coap_msg_get_type(resp)) - { - return FAIL; - } - if (test_resp->code_class != coap_msg_get_code_class(resp)) - { - return FAIL; - } - if (test_resp->code_detail != coap_msg_get_code_detail(resp)) - { - return FAIL; - } - return PASS; -}