Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: C027_Support mbed-dev
Fork of C027_SupportTest_coap by
Revision 39:4f3f7463e55f, committed 2017-05-25
- Comitter:
- ranaumarnaeem
- Date:
- Thu May 25 11:53:45 2017 +0000
- Parent:
- 38:f1bc6e867fcf
- Commit message:
- mbed 5.4 with sleep mode
Changed in this revision
--- 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;
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Coap/coap_client.cpp Thu May 25 11:53:45 2017 +0000
@@ -0,0 +1,1026 @@
+/*
+ * 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,char* returncode)
+{
+ 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,returncode);
+ //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,char* returncode)
+{
+ //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);
+
+ if(strcmp(str,"Received:") == 0)
+ {
+ for (i = 0; i < coap_msg_get_payload_len(msg); i++)
+ {
+ printf("%c", payload[i]);
+ returncode[i] = payload[i];
+ }
+ returncode[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,char* returncode)
+{
+ 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,returncode);
+ print_coap_msg("Received:", resp,returncode);
+
+ 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;
+}
--- a/Coap/coap_client.h Wed May 24 07:51:33 2017 +0000 +++ b/Coap/coap_client.h Thu May 25 11:53:45 2017 +0000 @@ -45,8 +45,6 @@ #define COAP_CLIENT_HOST_BUF_LEN 128 /* Buffer length for host addresses */ #define COAP_CLIENT_PORT_BUF_LEN 8 /* Buffer length for port numbers */ -//unsigned char ucReturnCode[10]; //Return code array - /** * @brief Test result enumeration */ @@ -158,12 +156,12 @@ **/ int coap_client_exchange(coap_client_t *client, coap_msg_t *req, coap_msg_t *resp); -test_result_t test_exchange_func(char* buf,int buf_len); +test_result_t test_exchange_func(char* buf,int buf_len,char* returncode); test_result_t check_resp(test_coap_client_msg_t *test_resp, coap_msg_t *resp); test_result_t compare_ver_token(coap_msg_t *req, coap_msg_t *resp); -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 exchange(coap_client_t *client, test_coap_client_msg_t *test_req, coap_msg_t *req, coap_msg_t *resp,char* returncode); test_result_t populate_req(test_coap_client_msg_t *test_req, coap_msg_t *req); -void print_coap_msg(const char *str, coap_msg_t *msg); +void print_coap_msg(const char *str, coap_msg_t *msg,char* returncode);
--- a/Coap/coap_msg.c Wed May 24 07:51:33 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1024 +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_msg.c
- *
- * @brief Source file for the FreeCoAP message parser/formatter library
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <time.h>
-#include <errno.h>
-#include "coap_msg.h"
-#include "coap_client.h"
-
-#define coap_msg_op_list_get_first(list) ((list)->first) /**< Get the first option from an option linked-list */
-#define coap_msg_op_list_get_last(list) ((list)->last) /**< Get the last option in an option linked-list */
-#define coap_msg_op_list_is_empty(list) ((list)->first == NULL) /**< Indicate whether or not an option linked-list is empty */
-
-static int coap_msg_rand_init = 0; /**< Indicates whether or not the random number generator has been initialised */
-
-void coap_msg_gen_rand_str(char *buf, size_t len)
-{
- size_t i = 0;
-
- if (!coap_msg_rand_init)
- {
- srand(time(NULL));
- coap_msg_rand_init = 1;
- }
- for (i = 0; i < len; i++)
- {
- buf[i] = rand() & 0x000000ff;
- }
-}
-
-int coap_msg_op_num_is_recognized(unsigned num)
-{
- switch (num)
- {
- case COAP_MSG_IF_MATCH:
- case COAP_MSG_URI_HOST:
- case COAP_MSG_ETAG:
- case COAP_MSG_IF_NONE_MATCH:
- case COAP_MSG_URI_PORT:
- case COAP_MSG_LOCATION_PATH:
- case COAP_MSG_URI_PATH:
- case COAP_MSG_CONTENT_FORMAT:
- case COAP_MSG_MAX_AGE:
- case COAP_MSG_URI_QUERY:
- case COAP_MSG_ACCEPT:
- case COAP_MSG_LOCATION_QUERY:
- case COAP_MSG_PROXY_URI:
- case COAP_MSG_PROXY_SCHEME:
- case COAP_MSG_SIZE1:
- return 1;
- }
- return 0;
-}
-
-/**
- * @brief Allocate an option structure
- *
- * @param[in] num Option number
- * @param[in] len Option length
- * @param[in] val Pointer to the option value
- *
- * @returns Pointer to the option structure
- * @retval NULL Out-of-memory
- */
-static coap_msg_op_t *coap_msg_op_new(unsigned num, unsigned len, const char *val)
-{
- coap_msg_op_t *op = NULL;
-
- op = (coap_msg_op_t *)malloc(sizeof(coap_msg_op_t));
- if (op == NULL)
- {
- return NULL;
- }
- op->num = num;
- op->len = len;
- op->val = (char *)malloc(len);
- if (op->val == NULL)
- {
- free(op);
- return NULL;
- }
- memcpy(op->val, val, len);
- op->next = NULL;
- return op;
-}
-
-/**
- * @brief Free an option structure that was allocated by coap_msg_op_new
- *
- * @param[in,out] op Pointer to the option structure
- */
-static void coap_msg_op_delete(coap_msg_op_t *op)
-{
- free(op->val);
- free(op);
-}
-
-/**
- * @brief Initialise an option linked-list structure
- *
- * @param[out] list Pointer to an option linked-list structure
- */
-static void coap_msg_op_list_create(coap_msg_op_list_t *list)
-{
- memset(list, 0, sizeof(coap_msg_op_list_t));
-}
-
-/**
- * @brief Deinitialise an option linked-list structure
- *
- * @param[in,out] list Pointer to an option linked-list structure
- */
-static void coap_msg_op_list_destroy(coap_msg_op_list_t *list)
-{
- coap_msg_op_t *prev = NULL;
- coap_msg_op_t *op = NULL;
-
- op = list->first;
- while (op != NULL)
- {
- prev = op;
- op = op->next;
- coap_msg_op_delete(prev);
- }
- memset(list, 0, sizeof(coap_msg_op_list_t));
-}
-
-/**
- * @brief Allocate an option structure and add it to the end of an option linked-list structure
- *
- * @param[in,out] list Pointer to an option linked-list structure
- * @param[in] num Option number
- * @param[in] len Option length
- * @param[in] val Pointer to a buffer containing the option value
- *
- * @returns Operation status
- * @retval 0 Success
- * @retval <0 Error
- */
-static int coap_msg_op_list_add_last(coap_msg_op_list_t *list, unsigned num, unsigned len, const char *val)
-{
- coap_msg_op_t *op = NULL;
-
- op = coap_msg_op_new(num, len, val);
- if (op == NULL)
- {
- return -ENOMEM;
- }
- if (list->first == NULL)
- {
- list->first = op;
- list->last = op;
- }
- else
- {
- list->last->next = op;
- list->last = op;
- }
- return 0;
-}
-
-/**
- * @brief Allocate an option structure and add it to an option linked-list structure
- *
- * The option is added to the list at a position determined by the option number.
- *
- * @param[in,out] list Pointer to an option linked-list structure
- * @param[in] num Option number
- * @param[in] len Option length
- * @param[in] val Pointer to a buffer containing the option value
- *
- * @returns Operation status
- * @retval 0 Success
- * @retval <0 Error
- */
-static int coap_msg_op_list_add(coap_msg_op_list_t *list, unsigned num, unsigned len, const char *val)
-{
- coap_msg_op_t *prev = NULL;
- coap_msg_op_t *op = NULL;
-
- op = coap_msg_op_new(num, len, val);
- if (op == NULL)
- {
- return -ENOMEM;
- }
- if (list->first == NULL)
- {
- /* empty list */
- list->first = op;
- list->last = op;
- return 0;
- }
- if (op->num < list->first->num)
- {
- /* start of the list */
- op->next = list->first;
- list->first = op;
- return 0;
- }
- prev = list->first;
- while (prev != list->last)
- {
- /* middle of the list */
- if ((prev->num <= op->num) && (op->num < prev->next->num))
- {
- op->next = prev->next;
- prev->next = op;
- return 0;
- }
- prev = prev->next;
- }
- /* end of the list */
- list->last->next = op;
- list->last = op;
- return 0;
-}
-
-void coap_msg_create(coap_msg_t *msg)
-{
- memset(msg, 0, sizeof(coap_msg_t));
- msg->ver = COAP_MSG_VER;
- coap_msg_op_list_create(&msg->op_list);
-}
-
-void coap_msg_destroy(coap_msg_t *msg)
-{
- coap_msg_op_list_destroy(&msg->op_list);
- if (msg->payload != NULL)
- {
- free(msg->payload);
- }
- memset(msg, 0, sizeof(coap_msg_t));
-}
-
-void coap_msg_reset(coap_msg_t *msg)
-{
- coap_msg_destroy(msg);
- coap_msg_create(msg);
-}
-
-/**
- * @brief Check a message for correctness
- *
- * The following checks from RFC7252 are performed:
- *
- * An Empty message has the Code field set to 0.00. The Token Length
- * field MUST be set to 0 and bytes of data MUST NOT be present after
- * the Message ID field. If there are any bytes, they MUST be processed
- * as a message format error.
- *
- * The Reset message MUST echo the Message ID of the Confirmable message
- * and MUST be Empty.
- *
- * A Non-confirmable message always carries either a request or response
- * and MUST NOT be Empty.
- *
- * @param[in] msg Pointer to a message structure
- * @returns Operation status
- * @retval 0 Success
- * @retval <0 Error
- */
-static int coap_msg_check(coap_msg_t *msg)
-{
- if ((msg->code_class == 0) && (msg->code_detail == 0))
- {
- /* empty message */
- if ((msg->type == COAP_MSG_NON)
- || (msg->token_len != 0)
- || (!coap_msg_op_list_is_empty(&msg->op_list))
- || (msg->payload_len != 0))
- {
- return -EBADMSG;
- }
- }
- else
- {
- /* non-empty message */
- if (msg->type == COAP_MSG_RST)
- {
- return -EBADMSG;
- }
- }
- return 0;
-}
-
-unsigned coap_msg_check_critical_ops(coap_msg_t *msg)
-{
- coap_msg_op_t *op = NULL;
- unsigned num = 0;
-
- op = coap_msg_get_first_op(msg);
- while (op != NULL)
- {
- num = coap_msg_op_get_num(op);
- if ((coap_msg_op_num_is_critical(num))
- && (!coap_msg_op_num_is_recognized(num)))
- {
- return num; /* fail */
- }
- op = coap_msg_op_get_next(op);
- }
- return 0; /* pass */
-}
-
-unsigned coap_msg_check_unsafe_ops(coap_msg_t *msg)
-{
- coap_msg_op_t *op = NULL;
- unsigned num = 0;
-
- op = coap_msg_get_first_op(msg);
- while (op != NULL)
- {
- num = coap_msg_op_get_num(op);
- if ((coap_msg_op_num_is_unsafe(num))
- && (!coap_msg_op_num_is_recognized(num)))
- {
- return num; /* fail */
- }
- op = coap_msg_op_get_next(op);
- }
- return 0; /* pass */
-}
-
-int coap_msg_parse_type_msg_id(char *buf, size_t len, unsigned *type, unsigned *msg_id)
-{
- if (len < 4)
- {
- return -EBADMSG;
- }
- *type = (buf[0] >> 4) & 0x03;
- *msg_id = ntohs(*((uint16_t *)(&buf[2])));
- return 0;
-}
-
-/**
- * @brief Parse the header in a message
- *
- * @param[out] msg Pointer to a message structure
- * @param[in] buf Pointer to a buffer containing the message
- * @param[in] len Length of the buffer
- *
- * @returns Number of bytes parsed or error code
- * @retval >0 Number of bytes parsed
- * @retval <0 Error
- */
-static int coap_msg_parse_hdr(coap_msg_t *msg, char *buf, size_t len)
-{
- char *p = buf;
-
- if (len < 4)
- {
- return -EBADMSG;
- }
- msg->ver = (p[0] >> 6) & 0x03;
- if (msg->ver != COAP_MSG_VER)
- {
- return -EINVAL;
- }
- msg->type = (p[0] >> 4) & 0x03;
- msg->token_len = p[0] & 0x0f;
- if (msg->token_len > sizeof(msg->token))
- {
- return -EBADMSG;
- }
- msg->code_detail = p[1] & 0x1f;
- msg->code_class = (p[1] >> 5) & 0x07;
- if ((msg->code_class != COAP_MSG_REQ)
- && (msg->code_class != COAP_MSG_SUCCESS)
- && (msg->code_class != COAP_MSG_CLIENT_ERR)
- && (msg->code_class != COAP_MSG_SERVER_ERR))
- {
- return -EBADMSG;
- }
- msg->msg_id = ntohs(*((uint16_t *)(&p[2])));
- p += 4;
- len -= 4;
- return p - buf;
-}
-
-/**
- * @brief Parse the token in a message
- *
- * @param[out] msg Pointer to a message structure
- * @param[in] buf Pointer to a buffer containing the message
- * @param[in] len Length of the buffer
- *
- * @returns Number of bytes parsed or error code
- * @retval >0 Number of bytes parsed
- * @retval <0 Error
- */
-static int coap_msg_parse_token(coap_msg_t *msg, char *buf, size_t len)
-{
- if (len < msg->token_len)
- {
- return -EBADMSG;
- }
- memcpy(msg->token, buf, msg->token_len);
- return msg->token_len;
-}
-
-/**
- * @brief Parse an option in a message
- *
- * @param[in,out] msg Pointer to a message structure
- * @param[in] buf Pointer to a buffer containing the message
- * @param[in] len Length of the buffer
- *
- * @returns Number of bytes parsed or error code
- * @retval >0 Number of bytes parsed
- * @retval <0 Error
- */
-static int coap_msg_parse_op(coap_msg_t *msg, char *buf, size_t len)
-{
- coap_msg_op_t *prev = NULL;
- unsigned op_delta = 0;
- unsigned op_len = 0;
- unsigned op_num = 0;
- char *p = buf;
- int ret = 0;
-
- if (len < 1)
- {
- return -EBADMSG;
- }
- op_delta = (p[0] >> 4) & 0x0f;
- op_len = p[0] & 0x0f;
- if ((op_delta == 15) || (op_len == 15))
- {
- return -EBADMSG;
- }
- p++;
- len--;
- if (op_delta == 13)
- {
- if (len < 1)
- {
- return -EBADMSG;
- }
- op_delta += p[0];
- p++;
- len--;
- }
- else if (op_delta == 14)
- {
- if (len < 2)
- {
- return -EBADMSG;
- }
- op_delta = 269 + ntohs(*((uint16_t *)(&p[0])));
- p += 2;
- len -= 2;
- }
- if (op_len == 13)
- {
- if (len < 1)
- {
- return -EBADMSG;
- }
- op_len += p[0];
- p++;
- len--;
- }
- else if (op_len == 14)
- {
- if (len < 2)
- {
- return -EBADMSG;
- }
- op_len = 269 + ntohs(*((uint16_t *)(&p[0])));
- p += 2;
- len -= 2;
- }
- if (len < op_len)
- {
- return -EBADMSG;
- }
- prev = coap_msg_op_list_get_last(&msg->op_list);
- if (prev == NULL)
- {
- op_num = op_delta;
- }
- else
- {
- op_num = coap_msg_op_get_num(prev) + op_delta;
- }
- ret = coap_msg_op_list_add_last(&msg->op_list, op_num, op_len, p);
- if (ret < 0)
- {
- return ret;
- }
- p += op_len;
- return p - buf;
-}
-
-/**
- * @brief Parse the options in a message
- *
- * @param[in,out] msg Pointer to a message structure
- * @param[in] buf Pointer to a buffer containing the message
- * @param[in] len Length of the buffer
- *
- * @returns Number of bytes parsed or error code
- * @retval >0 Number of bytes parsed
- * @retval <0 Error
- */
-static int coap_msg_parse_ops(coap_msg_t *msg, char *buf, size_t len)
-{
- int num = 0;
- char *p = buf;
-
- while (1)
- {
- if (((p[0] & 0xff) == 0xff) || (len == 0))
- {
- break;
- }
- num = coap_msg_parse_op(msg, p, len);
- if (num < 0)
- {
- return num;
- }
- p += num;
- len -= num;
- }
- return p - buf;
-}
-
-/**
- * @brief Parse the payload in a message
- *
- * @param[out] msg Pointer to a message structure
- * @param[in] buf Pointer to a buffer containing the message
- * @param[in] len Length of the buffer
- *
- * @returns Number of bytes parsed or error code
- * @retval >0 Number of bytes parsed
- * @retval <0 Error
- */
-static int coap_msg_parse_payload(coap_msg_t *msg, char *buf, size_t len)
-{
- char *p = buf;
-
- if (len == 0)
- {
- return 0;
- }
- if ((p[0] & 0xff) != 0xff)
- {
- return -EBADMSG;
- }
- p++;
- len--;
- if (len == 0)
- {
- return -EBADMSG;
- }
- msg->payload = (char *)malloc(len);
- if (msg->payload == NULL)
- {
- return -ENOMEM;
- }
- memcpy(msg->payload, p, len);
- msg->payload_len = len;
- p += len;
- return p - buf;
-}
-
-int coap_msg_parse(coap_msg_t *msg, char *buf, size_t len)
-{
- int num = 0;
- char *p = buf;
-
- coap_msg_reset(msg);
- num = coap_msg_parse_hdr(msg, p, len);
- if (num < 0)
- {
- coap_msg_destroy(msg);
- return num;
- }
- p += num;
- len -= num;
- num = coap_msg_parse_token(msg, p, len);
- if (num < 0)
- {
- coap_msg_destroy(msg);
- return num;
- }
- p += num;
- len -= num;
- num = coap_msg_parse_ops(msg, p, len);
- if (num < 0)
- {
- coap_msg_destroy(msg);
- return num;
- }
- p += num;
- len -= num;
- num = coap_msg_parse_payload(msg, p, len);
- if (num < 0)
- {
- coap_msg_destroy(msg);
- return num;
- }
- return coap_msg_check(msg);
-}
-
-int coap_msg_set_type(coap_msg_t *msg, unsigned type)
-{
- if ((type != COAP_MSG_CON)
- && (type != COAP_MSG_NON)
- && (type != COAP_MSG_ACK)
- && (type != COAP_MSG_RST))
- {
- return -EINVAL;
- }
- msg->type = type;
- return 0;
-}
-
-int coap_msg_set_code(coap_msg_t *msg, unsigned code_class, unsigned code_detail)
-{
- if (code_class > COAP_MSG_MAX_CODE_CLASS)
- {
- return -EINVAL;
- }
- if (code_detail > COAP_MSG_MAX_CODE_DETAIL)
- {
- return -EINVAL;
- }
- msg->code_class = code_class;
- msg->code_detail = code_detail;
- return 0;
-}
-
-int coap_msg_set_msg_id(coap_msg_t *msg, unsigned msg_id)
-{
- if (msg_id > COAP_MSG_MAX_MSG_ID)
- {
- return -EINVAL;
- }
- msg->msg_id = msg_id;
- return 0;
-}
-
-int coap_msg_set_token(coap_msg_t *msg, char *buf, size_t len)
-{
- if (len > COAP_MSG_MAX_TOKEN_LEN)
- {
- return -EINVAL;
- }
- memcpy(msg->token, buf, len);
- msg->token_len = len;
- return 0;
-}
-
-int coap_msg_add_op(coap_msg_t *msg, unsigned num, unsigned len, const char *val)
-{
- return coap_msg_op_list_add(&msg->op_list, num, len, val);
-}
-
-int coap_msg_set_payload(coap_msg_t *msg, char *buf, size_t len)
-{
- msg->payload_len = 0;
- if (msg->payload != NULL)
- {
- free(msg->payload);
- msg->payload = NULL;
- }
- if (len > 0)
- {
- msg->payload = (char *)malloc(len);
- if (msg->payload == NULL)
- {
- return -ENOMEM;
- }
- memcpy(msg->payload, buf, len);
- msg->payload_len = len;
- }
- return 0;
-}
-
-/**
- * @brief Format the header in a message
- *
- * @param[in] msg Pointer to a message structure
- * @param[out] buf Pointer to a buffer to contain the formatted message
- * @param[in] len Length of the buffer
- *
- * @returns Length of the formatted message or error code
- * @retval >0 Length of the formatted message
- * @retval <0 Error
- */
-static int coap_msg_format_hdr(coap_msg_t *msg, char *buf, size_t len)
-{
- uint16_t msg_id = 0;
-
- if (len < 4)
- {
- return -ENOSPC;
- }
- buf[0] = (char)((COAP_MSG_VER << 6)
- | ((msg->type & 0x03) << 4)
- | (msg->token_len & 0x0f));
- buf[1] = (char)(((msg->code_class & 0x07) << 5)
- | (msg->code_detail & 0x1f));
- msg_id = htons(msg->msg_id);
- memcpy(&buf[2], &msg_id, 2);
- return 4;
-}
-
-/**
- * @brief Format the token in a message
- *
- * @param[in] msg Pointer to a message structure
- * @param[out] buf Pointer to a buffer to contain the formatted message
- * @param[in] len Length of the buffer
- *
- * @returns Length of the formatted message or error code
- * @retval >0 Length of the formatted message
- * @retval <0 Error
- */
-static int coap_msg_format_token(coap_msg_t *msg, char *buf, size_t len)
-{
- if (len < msg->token_len)
- {
- return -ENOSPC;
- }
- memcpy(buf, msg->token, msg->token_len);
- return msg->token_len;
-}
-
-/**
- * @brief Format an option in a message
- *
- * @param[in] op Pointer to an option structure
- * @param[in] prev_num option number of the previous option
- * @param[out] buf Pointer to a buffer to contain the formatted message
- * @param[in] len Length of the buffer
- *
- * @returns Length of the formatted message or error code
- * @retval >0 Length of the formatted message
- * @retval <0 Error
- */
-static int coap_msg_format_op(coap_msg_op_t *op, unsigned prev_num, char *buf, size_t len)
-{
- unsigned op_delta = 0;
- unsigned num = 0;
- uint16_t val = 0;
- char *p = buf;
-
- op_delta = op->num - prev_num;
- num++;
-
- /* option delta */
- if (op_delta >= 269)
- {
- num += 2;
- }
- else if (op_delta >= 13)
- {
- num += 1;
- }
-
- /* option length */
- if (op->len >= 269)
- {
- num += 2;
- }
- else if (op->num >= 13)
- {
- num += 1;
- }
-
- /* option value */
- num += op->len;
- if (num > len)
- {
- return -ENOSPC;
- }
-
- /* option delta */
- if (op_delta >= 269)
- {
- p[0] = 14 << 4;
- }
- else if (op_delta >= 13)
- {
- p[0] = 13 << 4;
- }
- else
- {
- p[0] = op_delta << 4;
- }
-
- /* option length */
- if (op->len >= 269)
- {
- p[0] |= 14;
- }
- else if (op->len >= 13)
- {
- p[0] |= 13;
- }
- else
- {
- p[0] |= op->len;
- }
- p++;
- len--;
-
- /* option delta extended */
- if (op_delta >= 269)
- {
- val = htons(op_delta - 269);
- memcpy(p, &val, 2);
- p += 2;
- len -= 2;
- }
- else if (op_delta >= 13)
- {
- p[0] = op_delta - 13;
- p++;
- len--;
- }
-
- /* option length extended */
- if (op->len >= 269)
- {
- val = htons(op->len - 269);
- memcpy(p, &val, 2);
- p += 2;
- len -= 2;
- }
- else if (op->len >= 13)
- {
- p[0] = op->len - 13;
- p++;
- len--;
- }
-
- /* option value */
- memcpy(p, op->val, op->len);
- p += op->len;
-
- return p - buf;
-}
-
-/**
- * @brief Format the options in a message
- *
- * @param[in] msg Pointer to a message structure
- * @param[out] buf Pointer to a buffer to contain the formatted message
- * @param[in] len Length of the buffer
- *
- * @returns Length of the formatted message or error code
- * @retval >0 Length of the formatted message
- * @retval <0 Error
- */
-static int coap_msg_format_ops(coap_msg_t *msg, char *buf, size_t len)
-{
- coap_msg_op_t *op = NULL;
- unsigned prev_num = 0;
- int num = 0;
- char *p = buf;
-
- op = coap_msg_op_list_get_first(&msg->op_list);
- while (op != NULL)
- {
- num = coap_msg_format_op(op, prev_num, p, len);
- if (num < 0)
- {
- return num;
- }
- p += num;
- len -= num;
- prev_num = coap_msg_op_get_num(op);
- op = coap_msg_op_get_next(op);
- }
- return p - buf;
-}
-
-/**
- * @brief Format the payload in a message
- *
- * @param[in] msg Pointer to a message structure
- * @param[out] buf Pointer to a buffer to contain the formatted message
- * @param[in] len Length of the buffer
- *
- * @returns Length of the formatted message or error code
- * @retval >0 Length of the formatted message
- * @retval <0 Error
- */
-static int coap_msg_format_payload(coap_msg_t *msg, char *buf, size_t len)
-{
- if (msg->payload_len == 0)
- {
- return 0;
- }
- if (msg->payload_len + 1 > len)
- {
- return -ENOSPC;
- }
- buf[0] = 0xff;
- memcpy(&buf[1], msg->payload, msg->payload_len);
- return msg->payload_len + 1;
-}
-
-int coap_msg_format(coap_msg_t *msg, char *buf, size_t len)
-{
- int num = 0;
- char *p = buf;
- int ret = 0;
-
- ret = coap_msg_check(msg);
- if (ret != 0)
- {
- return ret;
- }
- num = coap_msg_format_hdr(msg, p, len);
- if (num < 0)
- {
- return num;
- }
- p += num;
- len -= num;
- num = coap_msg_format_token(msg, p, len);
- if (num < 0)
- {
- return num;
- }
- p += num;
- len -= num;
- num = coap_msg_format_ops(msg, p, len);
- if (num < 0)
- {
- return num;
- }
- p += num;
- len -= num;
- num = coap_msg_format_payload(msg, p, len);
- if (num < 0)
- {
- return num;
- }
- p += num;
- return p - buf;
-}
-
-int coap_msg_copy(coap_msg_t *dst, coap_msg_t *src)
-{
- coap_msg_op_t *op = NULL;
- int ret = 0;
-
- dst->ver = src->ver;
- ret = coap_msg_set_type(dst, coap_msg_get_type(src));
- if (ret < 0)
- {
- return ret;
- }
- ret = coap_msg_set_code(dst, coap_msg_get_code_class(src), coap_msg_get_code_detail(src));
- if (ret < 0)
- {
- return ret;
- }
- ret = coap_msg_set_msg_id(dst, coap_msg_get_msg_id(src));
- if (ret < 0)
- {
- return ret;
- }
- ret = coap_msg_set_token(dst, coap_msg_get_token(src), coap_msg_get_token_len(src));
- if (ret < 0)
- {
- return ret;
- }
- op = coap_msg_get_first_op(src);
- while (op != NULL)
- {
- ret = coap_msg_add_op(dst, coap_msg_op_get_num(op), coap_msg_op_get_len(op), coap_msg_op_get_val(op));
- if (ret < 0)
- {
- return ret;
- }
- op = coap_msg_op_get_next(op);
- }
- ret = coap_msg_set_payload(dst, coap_msg_get_payload(src), coap_msg_get_payload_len(src));
- if (ret < 0)
- {
- return ret;
- }
- return 0;
-}
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Coap/coap_msg.cpp Thu May 25 11:53:45 2017 +0000
@@ -0,0 +1,1024 @@
+/*
+ * 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_msg.c
+ *
+ * @brief Source file for the FreeCoAP message parser/formatter library
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <time.h>
+#include <errno.h>
+#include "coap_msg.h"
+#include "coap_client.h"
+
+#define coap_msg_op_list_get_first(list) ((list)->first) /**< Get the first option from an option linked-list */
+#define coap_msg_op_list_get_last(list) ((list)->last) /**< Get the last option in an option linked-list */
+#define coap_msg_op_list_is_empty(list) ((list)->first == NULL) /**< Indicate whether or not an option linked-list is empty */
+
+static int coap_msg_rand_init = 0; /**< Indicates whether or not the random number generator has been initialised */
+
+void coap_msg_gen_rand_str(char *buf, size_t len)
+{
+ size_t i = 0;
+
+ if (!coap_msg_rand_init)
+ {
+ srand(time(NULL));
+ coap_msg_rand_init = 1;
+ }
+ for (i = 0; i < len; i++)
+ {
+ buf[i] = rand() & 0x000000ff;
+ }
+}
+
+int coap_msg_op_num_is_recognized(unsigned num)
+{
+ switch (num)
+ {
+ case COAP_MSG_IF_MATCH:
+ case COAP_MSG_URI_HOST:
+ case COAP_MSG_ETAG:
+ case COAP_MSG_IF_NONE_MATCH:
+ case COAP_MSG_URI_PORT:
+ case COAP_MSG_LOCATION_PATH:
+ case COAP_MSG_URI_PATH:
+ case COAP_MSG_CONTENT_FORMAT:
+ case COAP_MSG_MAX_AGE:
+ case COAP_MSG_URI_QUERY:
+ case COAP_MSG_ACCEPT:
+ case COAP_MSG_LOCATION_QUERY:
+ case COAP_MSG_PROXY_URI:
+ case COAP_MSG_PROXY_SCHEME:
+ case COAP_MSG_SIZE1:
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * @brief Allocate an option structure
+ *
+ * @param[in] num Option number
+ * @param[in] len Option length
+ * @param[in] val Pointer to the option value
+ *
+ * @returns Pointer to the option structure
+ * @retval NULL Out-of-memory
+ */
+static coap_msg_op_t *coap_msg_op_new(unsigned num, unsigned len, const char *val)
+{
+ coap_msg_op_t *op = NULL;
+
+ op = (coap_msg_op_t *)malloc(sizeof(coap_msg_op_t));
+ if (op == NULL)
+ {
+ return NULL;
+ }
+ op->num = num;
+ op->len = len;
+ op->val = (char *)malloc(len);
+ if (op->val == NULL)
+ {
+ free(op);
+ return NULL;
+ }
+ memcpy(op->val, val, len);
+ op->next = NULL;
+ return op;
+}
+
+/**
+ * @brief Free an option structure that was allocated by coap_msg_op_new
+ *
+ * @param[in,out] op Pointer to the option structure
+ */
+static void coap_msg_op_delete(coap_msg_op_t *op)
+{
+ free(op->val);
+ free(op);
+}
+
+/**
+ * @brief Initialise an option linked-list structure
+ *
+ * @param[out] list Pointer to an option linked-list structure
+ */
+static void coap_msg_op_list_create(coap_msg_op_list_t *list)
+{
+ memset(list, 0, sizeof(coap_msg_op_list_t));
+}
+
+/**
+ * @brief Deinitialise an option linked-list structure
+ *
+ * @param[in,out] list Pointer to an option linked-list structure
+ */
+static void coap_msg_op_list_destroy(coap_msg_op_list_t *list)
+{
+ coap_msg_op_t *prev = NULL;
+ coap_msg_op_t *op = NULL;
+
+ op = list->first;
+ while (op != NULL)
+ {
+ prev = op;
+ op = op->next;
+ coap_msg_op_delete(prev);
+ }
+ memset(list, 0, sizeof(coap_msg_op_list_t));
+}
+
+/**
+ * @brief Allocate an option structure and add it to the end of an option linked-list structure
+ *
+ * @param[in,out] list Pointer to an option linked-list structure
+ * @param[in] num Option number
+ * @param[in] len Option length
+ * @param[in] val Pointer to a buffer containing the option value
+ *
+ * @returns Operation status
+ * @retval 0 Success
+ * @retval <0 Error
+ */
+static int coap_msg_op_list_add_last(coap_msg_op_list_t *list, unsigned num, unsigned len, const char *val)
+{
+ coap_msg_op_t *op = NULL;
+
+ op = coap_msg_op_new(num, len, val);
+ if (op == NULL)
+ {
+ return -ENOMEM;
+ }
+ if (list->first == NULL)
+ {
+ list->first = op;
+ list->last = op;
+ }
+ else
+ {
+ list->last->next = op;
+ list->last = op;
+ }
+ return 0;
+}
+
+/**
+ * @brief Allocate an option structure and add it to an option linked-list structure
+ *
+ * The option is added to the list at a position determined by the option number.
+ *
+ * @param[in,out] list Pointer to an option linked-list structure
+ * @param[in] num Option number
+ * @param[in] len Option length
+ * @param[in] val Pointer to a buffer containing the option value
+ *
+ * @returns Operation status
+ * @retval 0 Success
+ * @retval <0 Error
+ */
+static int coap_msg_op_list_add(coap_msg_op_list_t *list, unsigned num, unsigned len, const char *val)
+{
+ coap_msg_op_t *prev = NULL;
+ coap_msg_op_t *op = NULL;
+
+ op = coap_msg_op_new(num, len, val);
+ if (op == NULL)
+ {
+ return -ENOMEM;
+ }
+ if (list->first == NULL)
+ {
+ /* empty list */
+ list->first = op;
+ list->last = op;
+ return 0;
+ }
+ if (op->num < list->first->num)
+ {
+ /* start of the list */
+ op->next = list->first;
+ list->first = op;
+ return 0;
+ }
+ prev = list->first;
+ while (prev != list->last)
+ {
+ /* middle of the list */
+ if ((prev->num <= op->num) && (op->num < prev->next->num))
+ {
+ op->next = prev->next;
+ prev->next = op;
+ return 0;
+ }
+ prev = prev->next;
+ }
+ /* end of the list */
+ list->last->next = op;
+ list->last = op;
+ return 0;
+}
+
+void coap_msg_create(coap_msg_t *msg)
+{
+ memset(msg, 0, sizeof(coap_msg_t));
+ msg->ver = COAP_MSG_VER;
+ coap_msg_op_list_create(&msg->op_list);
+}
+
+void coap_msg_destroy(coap_msg_t *msg)
+{
+ coap_msg_op_list_destroy(&msg->op_list);
+ if (msg->payload != NULL)
+ {
+ free(msg->payload);
+ }
+ memset(msg, 0, sizeof(coap_msg_t));
+}
+
+void coap_msg_reset(coap_msg_t *msg)
+{
+ coap_msg_destroy(msg);
+ coap_msg_create(msg);
+}
+
+/**
+ * @brief Check a message for correctness
+ *
+ * The following checks from RFC7252 are performed:
+ *
+ * An Empty message has the Code field set to 0.00. The Token Length
+ * field MUST be set to 0 and bytes of data MUST NOT be present after
+ * the Message ID field. If there are any bytes, they MUST be processed
+ * as a message format error.
+ *
+ * The Reset message MUST echo the Message ID of the Confirmable message
+ * and MUST be Empty.
+ *
+ * A Non-confirmable message always carries either a request or response
+ * and MUST NOT be Empty.
+ *
+ * @param[in] msg Pointer to a message structure
+ * @returns Operation status
+ * @retval 0 Success
+ * @retval <0 Error
+ */
+static int coap_msg_check(coap_msg_t *msg)
+{
+ if ((msg->code_class == 0) && (msg->code_detail == 0))
+ {
+ /* empty message */
+ if ((msg->type == COAP_MSG_NON)
+ || (msg->token_len != 0)
+ || (!coap_msg_op_list_is_empty(&msg->op_list))
+ || (msg->payload_len != 0))
+ {
+ return -EBADMSG;
+ }
+ }
+ else
+ {
+ /* non-empty message */
+ if (msg->type == COAP_MSG_RST)
+ {
+ return -EBADMSG;
+ }
+ }
+ return 0;
+}
+
+unsigned coap_msg_check_critical_ops(coap_msg_t *msg)
+{
+ coap_msg_op_t *op = NULL;
+ unsigned num = 0;
+
+ op = coap_msg_get_first_op(msg);
+ while (op != NULL)
+ {
+ num = coap_msg_op_get_num(op);
+ if ((coap_msg_op_num_is_critical(num))
+ && (!coap_msg_op_num_is_recognized(num)))
+ {
+ return num; /* fail */
+ }
+ op = coap_msg_op_get_next(op);
+ }
+ return 0; /* pass */
+}
+
+unsigned coap_msg_check_unsafe_ops(coap_msg_t *msg)
+{
+ coap_msg_op_t *op = NULL;
+ unsigned num = 0;
+
+ op = coap_msg_get_first_op(msg);
+ while (op != NULL)
+ {
+ num = coap_msg_op_get_num(op);
+ if ((coap_msg_op_num_is_unsafe(num))
+ && (!coap_msg_op_num_is_recognized(num)))
+ {
+ return num; /* fail */
+ }
+ op = coap_msg_op_get_next(op);
+ }
+ return 0; /* pass */
+}
+
+int coap_msg_parse_type_msg_id(char *buf, size_t len, unsigned *type, unsigned *msg_id)
+{
+ if (len < 4)
+ {
+ return -EBADMSG;
+ }
+ *type = (buf[0] >> 4) & 0x03;
+ *msg_id = ntohs(*((uint16_t *)(&buf[2])));
+ return 0;
+}
+
+/**
+ * @brief Parse the header in a message
+ *
+ * @param[out] msg Pointer to a message structure
+ * @param[in] buf Pointer to a buffer containing the message
+ * @param[in] len Length of the buffer
+ *
+ * @returns Number of bytes parsed or error code
+ * @retval >0 Number of bytes parsed
+ * @retval <0 Error
+ */
+static int coap_msg_parse_hdr(coap_msg_t *msg, char *buf, size_t len)
+{
+ char *p = buf;
+
+ if (len < 4)
+ {
+ return -EBADMSG;
+ }
+ msg->ver = (p[0] >> 6) & 0x03;
+ if (msg->ver != COAP_MSG_VER)
+ {
+ return -EINVAL;
+ }
+ msg->type = (coap_msg_type_t)((p[0] >> 4) & 0x03);
+ msg->token_len = p[0] & 0x0f;
+ if (msg->token_len > sizeof(msg->token))
+ {
+ return -EBADMSG;
+ }
+ msg->code_detail = p[1] & 0x1f;
+ msg->code_class = (p[1] >> 5) & 0x07;
+ if ((msg->code_class != COAP_MSG_REQ)
+ && (msg->code_class != COAP_MSG_SUCCESS)
+ && (msg->code_class != COAP_MSG_CLIENT_ERR)
+ && (msg->code_class != COAP_MSG_SERVER_ERR))
+ {
+ return -EBADMSG;
+ }
+ msg->msg_id = ntohs(*((uint16_t *)(&p[2])));
+ p += 4;
+ len -= 4;
+ return p - buf;
+}
+
+/**
+ * @brief Parse the token in a message
+ *
+ * @param[out] msg Pointer to a message structure
+ * @param[in] buf Pointer to a buffer containing the message
+ * @param[in] len Length of the buffer
+ *
+ * @returns Number of bytes parsed or error code
+ * @retval >0 Number of bytes parsed
+ * @retval <0 Error
+ */
+static int coap_msg_parse_token(coap_msg_t *msg, char *buf, size_t len)
+{
+ if (len < msg->token_len)
+ {
+ return -EBADMSG;
+ }
+ memcpy(msg->token, buf, msg->token_len);
+ return msg->token_len;
+}
+
+/**
+ * @brief Parse an option in a message
+ *
+ * @param[in,out] msg Pointer to a message structure
+ * @param[in] buf Pointer to a buffer containing the message
+ * @param[in] len Length of the buffer
+ *
+ * @returns Number of bytes parsed or error code
+ * @retval >0 Number of bytes parsed
+ * @retval <0 Error
+ */
+static int coap_msg_parse_op(coap_msg_t *msg, char *buf, size_t len)
+{
+ coap_msg_op_t *prev = NULL;
+ unsigned op_delta = 0;
+ unsigned op_len = 0;
+ unsigned op_num = 0;
+ char *p = buf;
+ int ret = 0;
+
+ if (len < 1)
+ {
+ return -EBADMSG;
+ }
+ op_delta = (p[0] >> 4) & 0x0f;
+ op_len = p[0] & 0x0f;
+ if ((op_delta == 15) || (op_len == 15))
+ {
+ return -EBADMSG;
+ }
+ p++;
+ len--;
+ if (op_delta == 13)
+ {
+ if (len < 1)
+ {
+ return -EBADMSG;
+ }
+ op_delta += p[0];
+ p++;
+ len--;
+ }
+ else if (op_delta == 14)
+ {
+ if (len < 2)
+ {
+ return -EBADMSG;
+ }
+ op_delta = 269 + ntohs(*((uint16_t *)(&p[0])));
+ p += 2;
+ len -= 2;
+ }
+ if (op_len == 13)
+ {
+ if (len < 1)
+ {
+ return -EBADMSG;
+ }
+ op_len += p[0];
+ p++;
+ len--;
+ }
+ else if (op_len == 14)
+ {
+ if (len < 2)
+ {
+ return -EBADMSG;
+ }
+ op_len = 269 + ntohs(*((uint16_t *)(&p[0])));
+ p += 2;
+ len -= 2;
+ }
+ if (len < op_len)
+ {
+ return -EBADMSG;
+ }
+ prev = coap_msg_op_list_get_last(&msg->op_list);
+ if (prev == NULL)
+ {
+ op_num = op_delta;
+ }
+ else
+ {
+ op_num = coap_msg_op_get_num(prev) + op_delta;
+ }
+ ret = coap_msg_op_list_add_last(&msg->op_list, op_num, op_len, p);
+ if (ret < 0)
+ {
+ return ret;
+ }
+ p += op_len;
+ return p - buf;
+}
+
+/**
+ * @brief Parse the options in a message
+ *
+ * @param[in,out] msg Pointer to a message structure
+ * @param[in] buf Pointer to a buffer containing the message
+ * @param[in] len Length of the buffer
+ *
+ * @returns Number of bytes parsed or error code
+ * @retval >0 Number of bytes parsed
+ * @retval <0 Error
+ */
+static int coap_msg_parse_ops(coap_msg_t *msg, char *buf, size_t len)
+{
+ int num = 0;
+ char *p = buf;
+
+ while (1)
+ {
+ if (((p[0] & 0xff) == 0xff) || (len == 0))
+ {
+ break;
+ }
+ num = coap_msg_parse_op(msg, p, len);
+ if (num < 0)
+ {
+ return num;
+ }
+ p += num;
+ len -= num;
+ }
+ return p - buf;
+}
+
+/**
+ * @brief Parse the payload in a message
+ *
+ * @param[out] msg Pointer to a message structure
+ * @param[in] buf Pointer to a buffer containing the message
+ * @param[in] len Length of the buffer
+ *
+ * @returns Number of bytes parsed or error code
+ * @retval >0 Number of bytes parsed
+ * @retval <0 Error
+ */
+static int coap_msg_parse_payload(coap_msg_t *msg, char *buf, size_t len)
+{
+ char *p = buf;
+
+ if (len == 0)
+ {
+ return 0;
+ }
+ if ((p[0] & 0xff) != 0xff)
+ {
+ return -EBADMSG;
+ }
+ p++;
+ len--;
+ if (len == 0)
+ {
+ return -EBADMSG;
+ }
+ msg->payload = (char *)malloc(len);
+ if (msg->payload == NULL)
+ {
+ return -ENOMEM;
+ }
+ memcpy(msg->payload, p, len);
+ msg->payload_len = len;
+ p += len;
+ return p - buf;
+}
+
+int coap_msg_parse(coap_msg_t *msg, char *buf, size_t len)
+{
+ int num = 0;
+ char *p = buf;
+
+ coap_msg_reset(msg);
+ num = coap_msg_parse_hdr(msg, p, len);
+ if (num < 0)
+ {
+ coap_msg_destroy(msg);
+ return num;
+ }
+ p += num;
+ len -= num;
+ num = coap_msg_parse_token(msg, p, len);
+ if (num < 0)
+ {
+ coap_msg_destroy(msg);
+ return num;
+ }
+ p += num;
+ len -= num;
+ num = coap_msg_parse_ops(msg, p, len);
+ if (num < 0)
+ {
+ coap_msg_destroy(msg);
+ return num;
+ }
+ p += num;
+ len -= num;
+ num = coap_msg_parse_payload(msg, p, len);
+ if (num < 0)
+ {
+ coap_msg_destroy(msg);
+ return num;
+ }
+ return coap_msg_check(msg);
+}
+
+int coap_msg_set_type(coap_msg_t *msg, unsigned type)
+{
+ if ((type != COAP_MSG_CON)
+ && (type != COAP_MSG_NON)
+ && (type != COAP_MSG_ACK)
+ && (type != COAP_MSG_RST))
+ {
+ return -EINVAL;
+ }
+ msg->type = (coap_msg_type_t)type;
+ return 0;
+}
+
+int coap_msg_set_code(coap_msg_t *msg, unsigned code_class, unsigned code_detail)
+{
+ if (code_class > COAP_MSG_MAX_CODE_CLASS)
+ {
+ return -EINVAL;
+ }
+ if (code_detail > COAP_MSG_MAX_CODE_DETAIL)
+ {
+ return -EINVAL;
+ }
+ msg->code_class = code_class;
+ msg->code_detail = code_detail;
+ return 0;
+}
+
+int coap_msg_set_msg_id(coap_msg_t *msg, unsigned msg_id)
+{
+ if (msg_id > COAP_MSG_MAX_MSG_ID)
+ {
+ return -EINVAL;
+ }
+ msg->msg_id = msg_id;
+ return 0;
+}
+
+int coap_msg_set_token(coap_msg_t *msg, char *buf, size_t len)
+{
+ if (len > COAP_MSG_MAX_TOKEN_LEN)
+ {
+ return -EINVAL;
+ }
+ memcpy(msg->token, buf, len);
+ msg->token_len = len;
+ return 0;
+}
+
+int coap_msg_add_op(coap_msg_t *msg, unsigned num, unsigned len, const char *val)
+{
+ return coap_msg_op_list_add(&msg->op_list, num, len, val);
+}
+
+int coap_msg_set_payload(coap_msg_t *msg, char *buf, size_t len)
+{
+ msg->payload_len = 0;
+ if (msg->payload != NULL)
+ {
+ free(msg->payload);
+ msg->payload = NULL;
+ }
+ if (len > 0)
+ {
+ msg->payload = (char *)malloc(len);
+ if (msg->payload == NULL)
+ {
+ return -ENOMEM;
+ }
+ memcpy(msg->payload, buf, len);
+ msg->payload_len = len;
+ }
+ return 0;
+}
+
+/**
+ * @brief Format the header in a message
+ *
+ * @param[in] msg Pointer to a message structure
+ * @param[out] buf Pointer to a buffer to contain the formatted message
+ * @param[in] len Length of the buffer
+ *
+ * @returns Length of the formatted message or error code
+ * @retval >0 Length of the formatted message
+ * @retval <0 Error
+ */
+static int coap_msg_format_hdr(coap_msg_t *msg, char *buf, size_t len)
+{
+ uint16_t msg_id = 0;
+
+ if (len < 4)
+ {
+ return -ENOSPC;
+ }
+ buf[0] = (char)((COAP_MSG_VER << 6)
+ | ((msg->type & 0x03) << 4)
+ | (msg->token_len & 0x0f));
+ buf[1] = (char)(((msg->code_class & 0x07) << 5)
+ | (msg->code_detail & 0x1f));
+ msg_id = htons(msg->msg_id);
+ memcpy(&buf[2], &msg_id, 2);
+ return 4;
+}
+
+/**
+ * @brief Format the token in a message
+ *
+ * @param[in] msg Pointer to a message structure
+ * @param[out] buf Pointer to a buffer to contain the formatted message
+ * @param[in] len Length of the buffer
+ *
+ * @returns Length of the formatted message or error code
+ * @retval >0 Length of the formatted message
+ * @retval <0 Error
+ */
+static int coap_msg_format_token(coap_msg_t *msg, char *buf, size_t len)
+{
+ if (len < msg->token_len)
+ {
+ return -ENOSPC;
+ }
+ memcpy(buf, msg->token, msg->token_len);
+ return msg->token_len;
+}
+
+/**
+ * @brief Format an option in a message
+ *
+ * @param[in] op Pointer to an option structure
+ * @param[in] prev_num option number of the previous option
+ * @param[out] buf Pointer to a buffer to contain the formatted message
+ * @param[in] len Length of the buffer
+ *
+ * @returns Length of the formatted message or error code
+ * @retval >0 Length of the formatted message
+ * @retval <0 Error
+ */
+static int coap_msg_format_op(coap_msg_op_t *op, unsigned prev_num, char *buf, size_t len)
+{
+ unsigned op_delta = 0;
+ unsigned num = 0;
+ uint16_t val = 0;
+ char *p = buf;
+
+ op_delta = op->num - prev_num;
+ num++;
+
+ /* option delta */
+ if (op_delta >= 269)
+ {
+ num += 2;
+ }
+ else if (op_delta >= 13)
+ {
+ num += 1;
+ }
+
+ /* option length */
+ if (op->len >= 269)
+ {
+ num += 2;
+ }
+ else if (op->num >= 13)
+ {
+ num += 1;
+ }
+
+ /* option value */
+ num += op->len;
+ if (num > len)
+ {
+ return -ENOSPC;
+ }
+
+ /* option delta */
+ if (op_delta >= 269)
+ {
+ p[0] = 14 << 4;
+ }
+ else if (op_delta >= 13)
+ {
+ p[0] = 13 << 4;
+ }
+ else
+ {
+ p[0] = op_delta << 4;
+ }
+
+ /* option length */
+ if (op->len >= 269)
+ {
+ p[0] |= 14;
+ }
+ else if (op->len >= 13)
+ {
+ p[0] |= 13;
+ }
+ else
+ {
+ p[0] |= op->len;
+ }
+ p++;
+ len--;
+
+ /* option delta extended */
+ if (op_delta >= 269)
+ {
+ val = htons(op_delta - 269);
+ memcpy(p, &val, 2);
+ p += 2;
+ len -= 2;
+ }
+ else if (op_delta >= 13)
+ {
+ p[0] = op_delta - 13;
+ p++;
+ len--;
+ }
+
+ /* option length extended */
+ if (op->len >= 269)
+ {
+ val = htons(op->len - 269);
+ memcpy(p, &val, 2);
+ p += 2;
+ len -= 2;
+ }
+ else if (op->len >= 13)
+ {
+ p[0] = op->len - 13;
+ p++;
+ len--;
+ }
+
+ /* option value */
+ memcpy(p, op->val, op->len);
+ p += op->len;
+
+ return p - buf;
+}
+
+/**
+ * @brief Format the options in a message
+ *
+ * @param[in] msg Pointer to a message structure
+ * @param[out] buf Pointer to a buffer to contain the formatted message
+ * @param[in] len Length of the buffer
+ *
+ * @returns Length of the formatted message or error code
+ * @retval >0 Length of the formatted message
+ * @retval <0 Error
+ */
+static int coap_msg_format_ops(coap_msg_t *msg, char *buf, size_t len)
+{
+ coap_msg_op_t *op = NULL;
+ unsigned prev_num = 0;
+ int num = 0;
+ char *p = buf;
+
+ op = coap_msg_op_list_get_first(&msg->op_list);
+ while (op != NULL)
+ {
+ num = coap_msg_format_op(op, prev_num, p, len);
+ if (num < 0)
+ {
+ return num;
+ }
+ p += num;
+ len -= num;
+ prev_num = coap_msg_op_get_num(op);
+ op = coap_msg_op_get_next(op);
+ }
+ return p - buf;
+}
+
+/**
+ * @brief Format the payload in a message
+ *
+ * @param[in] msg Pointer to a message structure
+ * @param[out] buf Pointer to a buffer to contain the formatted message
+ * @param[in] len Length of the buffer
+ *
+ * @returns Length of the formatted message or error code
+ * @retval >0 Length of the formatted message
+ * @retval <0 Error
+ */
+static int coap_msg_format_payload(coap_msg_t *msg, char *buf, size_t len)
+{
+ if (msg->payload_len == 0)
+ {
+ return 0;
+ }
+ if (msg->payload_len + 1 > len)
+ {
+ return -ENOSPC;
+ }
+ buf[0] = 0xff;
+ memcpy(&buf[1], msg->payload, msg->payload_len);
+ return msg->payload_len + 1;
+}
+
+int coap_msg_format(coap_msg_t *msg, char *buf, size_t len)
+{
+ int num = 0;
+ char *p = buf;
+ int ret = 0;
+
+ ret = coap_msg_check(msg);
+ if (ret != 0)
+ {
+ return ret;
+ }
+ num = coap_msg_format_hdr(msg, p, len);
+ if (num < 0)
+ {
+ return num;
+ }
+ p += num;
+ len -= num;
+ num = coap_msg_format_token(msg, p, len);
+ if (num < 0)
+ {
+ return num;
+ }
+ p += num;
+ len -= num;
+ num = coap_msg_format_ops(msg, p, len);
+ if (num < 0)
+ {
+ return num;
+ }
+ p += num;
+ len -= num;
+ num = coap_msg_format_payload(msg, p, len);
+ if (num < 0)
+ {
+ return num;
+ }
+ p += num;
+ return p - buf;
+}
+
+int coap_msg_copy(coap_msg_t *dst, coap_msg_t *src)
+{
+ coap_msg_op_t *op = NULL;
+ int ret = 0;
+
+ dst->ver = src->ver;
+ ret = coap_msg_set_type(dst, coap_msg_get_type(src));
+ if (ret < 0)
+ {
+ return ret;
+ }
+ ret = coap_msg_set_code(dst, coap_msg_get_code_class(src), coap_msg_get_code_detail(src));
+ if (ret < 0)
+ {
+ return ret;
+ }
+ ret = coap_msg_set_msg_id(dst, coap_msg_get_msg_id(src));
+ if (ret < 0)
+ {
+ return ret;
+ }
+ ret = coap_msg_set_token(dst, coap_msg_get_token(src), coap_msg_get_token_len(src));
+ if (ret < 0)
+ {
+ return ret;
+ }
+ op = coap_msg_get_first_op(src);
+ while (op != NULL)
+ {
+ ret = coap_msg_add_op(dst, coap_msg_op_get_num(op), coap_msg_op_get_len(op), coap_msg_op_get_val(op));
+ if (ret < 0)
+ {
+ return ret;
+ }
+ op = coap_msg_op_get_next(op);
+ }
+ ret = coap_msg_set_payload(dst, coap_msg_get_payload(src), coap_msg_get_payload_len(src));
+ if (ret < 0)
+ {
+ return ret;
+ }
+ return 0;
+}
+
--- a/main.cpp Wed May 24 07:51:33 2017 +0000
+++ b/main.cpp Thu May 25 11:53:45 2017 +0000
@@ -7,10 +7,11 @@
#include "GPS.h"
#include "MDM.h"
#include "main.h"
-
+#include "coap_msg.h"
+#include "coap_client.h"
+
extern "C" {
- #include "coap_msg.h"
- #include "coap_client.h"
+
#include "rtc_api.h"
}
//
@@ -31,7 +32,7 @@
unsigned long ulGSMRxCntr=0, ulGSMTxCntr=0 ; //-- Asset
unsigned long ulTotalRxCntr=0,ulTotalTxCntr=0; //-- Asset
char caLssFinalAssetMsg[150];
-double dLatitude=0,dLongitude=0;
+double dLatitude=31.47691,dLongitude=74.34259;
static unsigned int uiWakeupCounter=0,uiWatchdogCounter=0;
unsigned char ucBtteryLevel=0;
MDMParser::DevStatus devStatus={};
@@ -43,6 +44,9 @@
//unsigned int uiAlarmIntervalCounter = 0;
//unsigned int uiHeartBeatCounter = 0;
+
+char ucReturnCode[10]; //Return code array
+int alarmtime = 1495698480;//2017-3-29-11:56:7
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
/*
@@ -50,7 +54,7 @@
{
LPC_SC->PCONP |=1<1; //timer0 power on
LPC_TIM0->MR0 = sec * 23980000; //1sec * sec
- LPC_TIM0->MCR = 3; //interrupt and reset control
+ LPC_TIM0->MCR = 1; //interrupt and reset control
//3 = Interrupt & reset timer0 on match
//1 = Interrupt only, no reset of timer0
NVIC_EnableIRQ(TIMER0_IRQn); //enable timer0 interrupt
@@ -63,33 +67,34 @@
if((LPC_TIM0->IR & 0x01) == 0x01) // if MR0 interrupt, proceed
{
LPC_TIM0->IR |= 1 << 0; // Clear MR0 interrupt flag
-
- uiAlarmIntervalCounter++;
- if(uiAlarmIntervalCounter >= 10)//20 sec
- {
- bAlarmIntervalFlag = true;
- uiAlarmIntervalCounter = 0;
- printf("Alarm Packet time...\r\n");
- }
-
- uiHeartBeatCounter++;
- if(uiHeartBeatCounter >= 60)//2 min
- {
- bHeartBeatFlag = true;
- uiHeartBeatCounter = 0;
- printf("Heartbeat Packet time...\r\n");
- }
+ printf("Timer 0 interrupt generated 10 sec\r\n");
+ LPC_TIM0->TCR = 0;
}
}
*/
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
-void rtc_setup(void)
+void rtc_setup(time_t t, unsigned int sec)
{
+ struct tm *timeinfo = localtime(&t);
+ unsigned int min;
+
rtc_init();
- rtc_write(1490788567);//2017-3-29-11:56:7
+ rtc_write(alarmtime);//2017-3-29-11:56:7
+
+ //min = sec/60;
+ //sec = sec%60;
+ //set alarm time
+ LPC_RTC->ALSEC = timeinfo->tm_sec+sec;//10 sec
+ //LPC_RTC->ALMIN = timeinfo->tm_min+min;//10 sec
+
+ LPC_RTC->AMR &= (~(1 << 0)) & 0xFF;
+
+ LPC_RTC->ILR = (1 << 0) | (1 << 1);
+
+ printf("RTC Alarm Time Set\r\n");
NVIC_EnableIRQ(RTC_IRQn);
@@ -130,7 +135,7 @@
MDMSerial mdm;
gmdm = &mdm;
us_ticker_init();
- //timer0_init(2);
+
while(1)
{
@@ -142,10 +147,8 @@
if(bSendingDataFlag)//&& bAlarmIntervalFlag)
{
//bAlarmIntervalFlag = false;
- unsigned int counter = 50;
- while( (ret = gps.getMessage(buf, sizeof(buf))) > 0 || counter > 0)
+ while( (ret = gps.getMessage(buf, sizeof(buf))) > 0)
{
- counter--;
int len = LENGTH(ret);
ulGPSRxCntr = len;
if( (PROTOCOL(ret)==GPSParser::NMEA) && (len > 6) )
@@ -200,13 +203,13 @@
sprintf( caLssFinalAssetMsg, "$AQLSS,02,%s,%s*xx",devStatus.imei,devStatus.imsi);
printf( "HeartBeat: %s\r\n", caLssFinalAssetMsg );
}
-
+
ssocket = mdm.socketSocket(MDMParser::IPPROTO_UDP, pport);
if( ssocket >= 0 )
{
mdm.socketSetBlocking(ssocket, 10);
ipp = 0x97092263;//0x052753CE;
- if (PASS == test_exchange_func(caLssFinalAssetMsg,strlen(caLssFinalAssetMsg)))
+ if (PASS == test_exchange_func(caLssFinalAssetMsg,strlen(caLssFinalAssetMsg),ucReturnCode))
{
printf("\r\n-----------------<pass>-----------------\n");
}
@@ -215,22 +218,26 @@
mdm.socketFree(ssocket);
responce_checker();
- }
+ }
mdm.disconnect();
- mdm.powerOff();
+ /*mdm.powerOff();*/
+
if(bSleepModeFlag)
{
- rtc_setup();
- hal_deepsleep();
- //sleep_mode();
- //uiWakeupCounter++;
+ rtc_setup(alarmtime,10);
+ printf("Enter Sleep Mode\r\n");
+ hal_sleep();
+ printf("Exit Sleep Mode\r\n");
+ myled = !myled;
+ uiWakeupCounter++;
}
- if(bSendingDataFlag)
+
+ /*if(bSendingDataFlag)
wait( 10 );
else
wait( 60 );
- myled = !myled;
+ myled = !myled;*/
}
//}
}
@@ -295,17 +302,9 @@
printf("Ussd Got Answer: \"%s\"\r\n", buffer);
}
*/
-void sleep_mode(void)
-{
- /* Deep-Sleep Mode, set SLEEPDEEP bit */
- //SCB->SCR |= 0x4;
- LPC_SC->PCON = 0x9;
- __WFI();
- //SystemInit();
-}
void responce_checker(void)
-{/*
+{
if(!strcmp((const char*)ucReturnCode,"RC 000"))
{
printf("Acknowledged RC 000\r\n");
@@ -350,5 +349,5 @@
else if(!strcmp((const char*)ucReturnCode,"EC 002"))
{
printf("Error Code 002 Received Payload is corrupted\r\n");
- }*/
+ }
}
