mbed 5.4 with sleep mode
Dependencies: C027_Support mbed-dev
Fork of C027_SupportTest_coap by
Coap/coap_client.c
- Committer:
- ranaumarnaeem
- Date:
- 2017-03-24
- Revision:
- 34:d6ce8f961b8b
File content as of revision 34:d6ce8f961b8b:
/* * 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 * ****************************************************************************************************/ int coap_client_create(coap_client_t *client, const char *host, const char *port) { strncpy(client->server_host, host, sizeof(client->server_host) - 1); strncpy(client->server_port, port, sizeof(client->server_port) - 1); printf("Connected to host %s and port %s", client->server_host, client->server_port); return 0; } 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; } printf("Sent to host %s and port %s\n", client->server_host, client->server_port); 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; } printf("Received from host %s and port %s\n", client->server_host, client->server_port); 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 host %s and port %s\n", client->server_host, client->server_port); 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; /* 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) { int start_time = getseconds(); while(1) { num = coap_client_recv(client, resp); if (num < 0) { return num; } else if(num > 0) { break; } int stop_time = getseconds(); if((stop_time - start_time) > 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; /* wait for piggy-backed response in ack message * or ack message and separate response message */ printf("Expecting acknowledgement from host %s and port %s\n", client->server_host, client->server_port); while (1) { int start_time = getseconds(); while(1) { num = coap_client_recv(client, resp); if (num < 0) { return num; } else if(num > 0) { break; } int stop_time = getseconds(); if((stop_time - start_time) > COAP_CLIENT_ACK_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) { 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; printf("Expecting response from host %s and port %s\n", client->server_host, client->server_port); while (1) { int start_time = getseconds(); while(1) { num = coap_client_recv(client, resp); if (num < 0) { return num; } else if(num > 0) { break; } int stop_time = getseconds(); if((stop_time - start_time) > 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; } if (coap_msg_get_type(req) == COAP_MSG_CON) { printf("Sending confirmable request to host %s and port %s\n", client->server_host, client->server_port); } else if (coap_msg_get_type(req) == COAP_MSG_NON) { printf("Sending non-confirmable request to host %s and port %s\n", client->server_host, client->server_port); } 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----------------------------------------\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 = "test 1: send a confirmable request 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); ret = coap_client_create(&client, test1_data.host, test1_data.port); 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]); } 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; } if (test_resp->payload_len != coap_msg_get_payload_len(resp)) { return FAIL; } else if (memcmp(test_resp->payload, coap_msg_get_payload(resp), test_resp->payload_len)) { return FAIL; } return PASS; }