coap_client_observe.c
Go to the documentation of this file.
1 /**
2  * @file coap_client_observe.c
3  * @brief CoAP observe
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 1.9.8
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL COAP_TRACE_LEVEL
33 
34 //Dependencies
35 #include <stdlib.h>
36 #include "core/net.h"
37 #include "coap/coap_client.h"
39 #include "coap/coap_client_misc.h"
40 #include "debug.h"
41 #include "error.h"
42 
43 //Check TCP/IP stack configuration
44 #if (COAP_CLIENT_SUPPORT == ENABLED && COAP_CLIENT_OBSERVE_SUPPORT == ENABLED)
45 
46 
47 /**
48  * @brief Process notification response
49  * @param[in] request CoAP request handle
50  * @param[in] response Pointer to the response message
51  * @return Error code
52  **/
53 
55  const CoapMessage *response)
56 {
57  error_t error;
58  uint32_t value;
60 
61  //The only difference between a notification and a normal response
62  //is the presence of the Observe option
63  error = coapGetUintOption(response, COAP_OPT_OBSERVE, 0, &value);
64 
65  //Observe option included in the response?
66  if(!error)
67  {
68  //Get current time
70 
71  //Check the order of arrival for incoming notification
73  {
74  //Save the value of the Observe option
75  request->observeSeqNum = value;
76  //Save the time at which the notification was received
77  request->retransmitStartTime = time;
78 
79  //Search the CoAP response for a Max-Age option
80  error = coapGetUintOption(response, COAP_OPT_MAX_AGE, 0, &value);
81 
82  //Max-Age option not included in the response?
83  if(error)
84  {
85  //A default value of 60 seconds is assumed in the absence of the
86  //option in a response
88  }
89 
90  //A notification is considered fresh while its age is not greater
91  //than the value indicated by the Max-Age option
92  request->retransmitTimeout = value * 1000;
93 
94  //Additionally, the client should at least wait for a random amount
95  //of time between 5 and 15 seconds after Max-Age expired to reduce
96  //collisions with other clients (refer to RFC 7641, section 3.3.1)
97  request->retransmitTimeout += netGetRandRange(COAP_CLIENT_RAND_DELAY_MIN,
99 
100  //The user is notified of changes to the resource state
101  error = coapClientChangeRequestState(request,
103  }
104  else
105  {
106  //Drop the incoming notification...
107  TRACE_INFO("Out-of-order notification received!\r\n");
108  }
109  }
110  else
111  {
112  //The client is notified of changes to the resource state
114 
115  //The observation has been canceled
117  }
118 
119  //Return status code
120  return error;
121 }
122 
123 
124 /**
125  * @brief Check the order of arrival for incoming notification
126  * @param[in] request CoAP request handle
127  * @param[in] v2 Value of the Observe option in the incoming notification
128  * @param[in] t2 Client-local timestamp for the incoming notification
129  * @return TRUE if the incoming notification was sent more recently than the
130  * freshest notification so far. Otherwise FALSE is returned
131  **/
132 
134  uint32_t v2, systime_t t2)
135 {
136  uint32_t v1;
137  systime_t t1;
138  bool_t valid;
139 
140  //Check current state
141  if(request->state != COAP_REQ_STATE_OBSERVE)
142  {
143  //The first notification has been received
144  valid = TRUE;
145  }
146  else
147  {
148  //Value of the Observe option in the freshest notification so far
149  v1 = request->observeSeqNum;
150  //Client-local timestamp for the freshest notification so far
151  t1 = request->retransmitStartTime;
152 
153  //An incoming notification was sent more recently than the freshest
154  //notification so far when one of the following conditions is met
155  if(v1 < v2 && (v2 - v1) < 0x00800000)
156  {
157  //V1 is less than V2 in 24-bit serial number arithmetic
158  valid = TRUE;
159  }
160  else if(v1 > v2 && (v1 - v2) > 0x00800000)
161  {
162  //V1 is less than V2 in 24-bit serial number arithmetic
163  valid = TRUE;
164  }
165  else if(timeCompare(t2, t1 + 128000) > 0)
166  {
167  //After 128 seconds have elapsed without any notification, a client
168  //does not need to check the sequence numbers to assume that an
169  //incoming notification was sent more recently than the freshest
170  //notification it has received so far
171  valid = TRUE;
172  }
173  else
174  {
175  //An out-of-order sequence number has been detected
176  valid = FALSE;
177  }
178  }
179 
180  //Return TRUE if the incoming notification was sent more recently than the
181  //freshest notification so far
182  return valid;
183 }
184 
185 #endif
error_t coapGetUintOption(const CoapMessage *message, uint16_t optionNum, uint_t optionIndex, uint32_t *optionValue)
Get the value of the specified uint option.
Definition: coap_option.c:651
int bool_t
Definition: compiler_port.h:49
#define TRUE
Definition: os_port.h:50
#define timeCompare(t1, t2)
Definition: os_port.h:42
error_t coapClientChangeRequestState(CoapClientRequest *request, CoapRequestState newState)
Update CoAP request state.
#define CoapClientRequest
Definition: coap_client.h:143
#define FALSE
Definition: os_port.h:46
error_t
Error codes.
Definition: error.h:42
uint8_t value[]
Definition: tcp.h:332
CoAP message.
Definition: coap_message.h:55
CoAP client.
bool_t coapClientCheckSequenceNumber(CoapClientRequest *request, uint32_t v2, systime_t t2)
Check the order of arrival for incoming notification.
Error codes description.
#define COAP_DEFAULT_MAX_AGE
Definition: coap_option.h:54
uint32_t t2
#define TRACE_INFO(...)
Definition: debug.h:95
error_t coapClientProcessNotification(CoapClientRequest *request, const CoapMessage *response)
Process notification response.
int32_t netGetRandRange(int32_t min, int32_t max)
Get a random value in the specified range.
Definition: net.c:1432
Helper functions for CoAP client.
uint32_t time
uint32_t t1
#define COAP_CLIENT_RAND_DELAY_MAX
Definition: coap_client.h:119
TCP/IP stack core.
#define COAP_CLIENT_RAND_DELAY_MIN
Definition: coap_client.h:112
uint32_t systime_t
Definition: compiler_port.h:46
Debugging facilities.
systime_t osGetSystemTime(void)
Retrieve system time.