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