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-2024 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 2.4.4
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 
42 //Check TCP/IP stack configuration
43 #if (COAP_CLIENT_SUPPORT == ENABLED && COAP_CLIENT_OBSERVE_SUPPORT == ENABLED)
44 
45 
46 /**
47  * @brief Process notification response
48  * @param[in] request CoAP request handle
49  * @param[in] response Pointer to the response message
50  * @return Error code
51  **/
52 
54  const CoapMessage *response)
55 {
56  error_t error;
57  uint32_t value;
59 
60  //The only difference between a notification and a normal response
61  //is the presence of the Observe option
62  error = coapGetUintOption(response, COAP_OPT_OBSERVE, 0, &value);
63 
64  //Observe option included in the response?
65  if(!error)
66  {
67  //Get current time
69 
70  //Check the order of arrival for incoming notification
72  {
73  //Save the value of the Observe option
74  request->observeSeqNum = value;
75  //Save the time at which the notification was received
76  request->retransmitStartTime = time;
77 
78  //Search the CoAP response for a Max-Age option
79  error = coapGetUintOption(response, COAP_OPT_MAX_AGE, 0, &value);
80 
81  //Max-Age option not included in the response?
82  if(error)
83  {
84  //A default value of 60 seconds is assumed in the absence of the
85  //option in a response
87  }
88 
89  //A notification is considered fresh while its age is not greater
90  //than the value indicated by the Max-Age option
91  request->retransmitTimeout = value * 1000;
92 
93  //Additionally, the client should at least wait for a random amount
94  //of time between 5 and 15 seconds after Max-Age expired to reduce
95  //collisions with other clients (refer to RFC 7641, section 3.3.1)
96  request->retransmitTimeout += netGetRandRange(COAP_CLIENT_RAND_DELAY_MIN,
98 
99  //The user is notified of changes to the resource state
100  error = coapClientChangeRequestState(request,
102  }
103  else
104  {
105  //Drop the incoming notification...
106  TRACE_INFO("Out-of-order notification received!\r\n");
107  }
108  }
109  else
110  {
111  //The client is notified of changes to the resource state
113 
114  //The observation has been canceled
116  }
117 
118  //Return status code
119  return error;
120 }
121 
122 
123 /**
124  * @brief Check the order of arrival for incoming notification
125  * @param[in] request CoAP request handle
126  * @param[in] v2 Value of the Observe option in the incoming notification
127  * @param[in] t2 Client-local timestamp for the incoming notification
128  * @return TRUE if the incoming notification was sent more recently than the
129  * freshest notification so far. Otherwise FALSE is returned
130  **/
131 
133  uint32_t v2, systime_t t2)
134 {
135  uint32_t v1;
136  systime_t t1;
137  bool_t valid;
138 
139  //Check current state
140  if(request->state != COAP_REQ_STATE_OBSERVE)
141  {
142  //The first notification has been received
143  valid = TRUE;
144  }
145  else
146  {
147  //Value of the Observe option in the freshest notification so far
148  v1 = request->observeSeqNum;
149  //Client-local timestamp for the freshest notification so far
150  t1 = request->retransmitStartTime;
151 
152  //An incoming notification was sent more recently than the freshest
153  //notification so far when one of the following conditions is met
154  if(v1 < v2 && (v2 - v1) < 0x00800000)
155  {
156  //V1 is less than V2 in 24-bit serial number arithmetic
157  valid = TRUE;
158  }
159  else if(v1 > v2 && (v1 - v2) > 0x00800000)
160  {
161  //V1 is less than V2 in 24-bit serial number arithmetic
162  valid = TRUE;
163  }
164  else if(timeCompare(t2, t1 + 128000) > 0)
165  {
166  //After 128 seconds have elapsed without any notification, a client
167  //does not need to check the sequence numbers to assume that an
168  //incoming notification was sent more recently than the freshest
169  //notification it has received so far
170  valid = TRUE;
171  }
172  else
173  {
174  //An out-of-order sequence number has been detected
175  valid = FALSE;
176  }
177  }
178 
179  //Return TRUE if the incoming notification was sent more recently than the
180  //freshest notification so far
181  return valid;
182 }
183 
184 #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:53
uint32_t netGetRandRange(uint32_t min, uint32_t max)
Generate a random value in the specified range.
Definition: net.c:413
#define TRUE
Definition: os_port.h:50
#define timeCompare(t1, t2)
Definition: os_port.h:40
error_t coapClientChangeRequestState(CoapClientRequest *request, CoapRequestState newState)
Update CoAP request state.
#define CoapClientRequest
Definition: coap_client.h:148
#define FALSE
Definition: os_port.h:46
@ COAP_REQ_STATE_OBSERVE
error_t
Error codes.
Definition: error.h:43
CoAP message.
Definition: coap_message.h:56
CoAP client.
bool_t coapClientCheckSequenceNumber(CoapClientRequest *request, uint32_t v2, systime_t t2)
Check the order of arrival for incoming notification.
@ COAP_OPT_OBSERVE
Definition: coap_option.h:96
#define COAP_DEFAULT_MAX_AGE
Definition: coap_option.h:54
uint32_t t2
#define TRACE_INFO(...)
Definition: debug.h:95
@ COAP_REQ_STATE_CANCELED
error_t coapClientProcessNotification(CoapClientRequest *request, const CoapMessage *response)
Process notification response.
uint32_t systime_t
System time.
Helper functions for CoAP client.
uint32_t time
uint32_t t1
@ COAP_OPT_MAX_AGE
Definition: coap_option.h:101
uint8_t value[]
Definition: tcp.h:369
#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
Debugging facilities.
systime_t osGetSystemTime(void)
Retrieve system time.