coap_server_observe.c
Go to the documentation of this file.
1 /**
2  * @file coap_server_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-2026 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.6.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_server.h"
39 #include "coap/coap_server_misc.h"
40 #include "coap/coap_debug.h"
41 #include "debug.h"
42 
43 //Check TCP/IP stack configuration
44 #if (COAP_SERVER_SUPPORT == ENABLED && COAP_SERVER_OBSERVE_SUPPORT == ENABLED)
45 
46 
47 /**
48  * @brief Process observe-related events
49  * @param[in] context Pointer to the CoAP server context
50  **/
51 
53 {
54  uint_t i;
56  CoapObserver *observer;
57 
58  //Get current time
60 
61  //Loop through the list of registered observers
62  for(i = 0; i < context->numObservers; i++)
63  {
64  //Point to the current entry
65  observer = &context->observers[i];
66 
67  //Check the state of the observer
68  if(observer->state == COAP_OBSERVER_STATE_REGISTERED)
69  {
70  //Whenever the state of a resource changes, the server notifies each
71  //client in the list of observers of the resource
72  if(observer->changed)
73  {
74  //Confirmable notification?
75  if(observer->type == COAP_TYPE_CON)
76  {
77  //Start to transmit a confirmable notification
78  coapServerSendNotificationResponse(context, observer);
79 
80  //Check whether the target resource has been deleted
81  if(observer->state == COAP_OBSERVER_STATE_REGISTERED &&
82  observer->resource == NULL)
83  {
84  //Removes the client's entry from the list of observers
85  coapServerDeleteObserver(observer);
86  }
87  }
88  else
89  {
90  //The server should not send more than one non-confirmable
91  //notification per round-trip time (RTT) to a client on average.
92  //If the server cannot maintain an RTT estimate for a client, it
93  //should not send more than one non-confirmable notification
94  //every 3 seconds and should use an even less aggressive rate
95  //when possible (refer to RFC 7641, section 4.5.1)
96  if((time - observer->retransmitTimestamp) >=
98  {
99  //Start to transmit a non-confirmable notification
100  coapServerSendNotificationResponse(context, observer);
101 
102  //Check whether the target resource has been deleted
103  if(observer->state == COAP_OBSERVER_STATE_REGISTERED &&
104  observer->resource == NULL)
105  {
106  //Removes the client's entry from the list of observers
107  coapServerDeleteObserver(observer);
108  }
109  }
110  }
111  }
112  }
113  else if(observer->state == COAP_OBSERVER_STATE_UPDATING)
114  {
115  //Check whether the retransmission timer has expired
116  if((time - observer->retransmitTimestamp) >=
117  observer->retransmitTimeout)
118  {
119  //The sender retransmits the Confirmable message at exponentially
120  //increasing intervals, until it receives an acknowledgement (or
121  //Reset message) or runs out of attempts
122  if(observer->retransmitCount < COAP_SERVER_MAX_RETRANSMIT)
123  {
124  //Retransmit the confirmable notification
125  coapServerSendNotificationResponse(context, observer);
126  }
127  else
128  {
129  //If the server does not receive an acknowledgement in reply to
130  //a confirmable notification, it will assume that the client is
131  //no longer interested and will eventually remove the associated
132  //entry from the list of observers (refer to RFC 7641, section 3.5)
133  coapServerDeleteObserver(observer);
134  }
135  }
136  }
137  else
138  {
139  //Just for sanity
140  }
141  }
142 }
143 
144 
145 /**
146  * @brief Process registration request
147  * @param[in] context Pointer to the CoAP server context
148  * @return Error code
149  **/
150 
152 {
153  error_t error;
154  uint32_t value;
155  CoapResource *resource;
156  CoapObserver *observer;
157  CoapMessageHeader *header;
158 
159  //CoAP uses a short fixed-length binary header (4 bytes)
160  header = (CoapMessageHeader *) context->request.buffer;
161 
162  //When included in a GET request, the Observe option extends the GET method
163  //so it does not only retrieve a current representation of the target
164  //resource, but also requests the server to add or remove an entry in the
165  //list of observers of the resource depending on the option value
166  error = coapGetUintOption(&context->request, COAP_OPT_OBSERVE, 0, &value);
167 
168  //The Observe Option is not critical for processing the request
169  if(!error)
170  {
171  //Search the list of resources for a matching URI
172  resource = coapServerFindResource(context, context->uri);
173 
174  //Matching resource found?
175  if(resource != NULL)
176  {
177  //The entry in the list of observers is keyed by the client endpoint
178  //and the token specified by the client in the request
179  observer = coapServerFindObserver(context, header->token,
180  header->tokenLen);
181 
182  //If an entry with a matching endpoint/token pair is already present
183  //in the list, the server must not add a new entry but must replace or
184  //update the existing one
185  if(observer == NULL)
186  {
187  //Add an entry with the client endpoint and request token to the
188  //list of observers of the target resource
189  observer = coapServerCreateObserver(context, header->token,
190  header->tokenLen, resource);
191  }
192 
193  //Valid entry?
194  if(observer != NULL)
195  {
196  //When included in a response, the Observe Option identifies the
197  //message as a notification. The option value is a sequence number
198  //for reordering detection (refer to RFC 7641, section 2)
199  coapSetUintOption(&context->response, COAP_OPT_OBSERVE, 0,
200  resource->seqNum);
201 
202  //Any registered callback?
203  if(context->observeCallback != NULL)
204  {
205  //Return the current representation of the target resource
206  error = context->observeCallback(context, observer, resource);
207  }
208  else
209  {
210  //No callback function registered
211  error = ERROR_NOT_FOUND;
212  }
213  }
214  else
215  {
216  //If the server is unwilling or unable to add a new entry to the
217  //list of observers, then the request falls back to a normal GET
218  //request and the response does not include the Observe Option
219  error = ERROR_NOT_FOUND;
220  }
221  }
222  else
223  {
224  //The target resource does not exist
225  error = ERROR_NOT_FOUND;
226  }
227  }
228  else
229  {
230  //Process the GET request as usual
231  error = ERROR_NOT_FOUND;
232  }
233 
234  //Return status code
235  return error;
236 }
237 
238 
239 /**
240  * @brief Restore original registration request
241  * @param[in] context Pointer to the CoAP server context
242  * @param[in] observer Pointer to the registered observer
243  **/
244 
246  CoapObserver *observer)
247 {
248  CoapMessageHeader *header;
249 
250  //Point to the CoAP request header
251  header = (CoapMessageHeader *) context->request.buffer;
252 
253  //Format message header
254  header->version = COAP_VERSION_1;
255  header->type = observer->type;
256  header->tokenLen = observer->tokenLen;
257  header->code = COAP_CODE_GET;
258  header->mid = htons(observer->mid);
259 
260  //Copy the token specified by the client
261  osMemcpy(header->token, observer->token, observer->tokenLen);
262 
263  //Set the length of the CoAP message
264  context->request.length = sizeof(CoapMessageHeader) + header->tokenLen;
265  context->request.pos = 0;
266 
267  //Check whether the target resource exists
268  if(observer->resource != NULL)
269  {
270  //Encode the path component into multiple Uri-Path options
271  coapSplitRepeatableOption(&context->request, COAP_OPT_URI_PATH,
272  observer->resource->uri, '/');
273  }
274 
275  //Restore the source and destination IP addresses
276  context->localInterface = observer->interface;
277  context->localIpAddr = observer->serverIpAddr;
278  context->remoteIpAddr = observer->clientIpAddr;
279  context->remotePort = observer->clientPort;
280 }
281 
282 
283 /**
284  * @brief Initialize notification response
285  * @param[in] context Pointer to the CoAP server context
286  * @param[in] observer Pointer to the registered observer
287  **/
288 
290  CoapObserver *observer)
291 {
292  CoapMessageHeader *header;
293 
294  //Point to the CoAP response header
295  header = (CoapMessageHeader *) context->response.buffer;
296 
297  //Format message header
298  header->version = COAP_VERSION_1;
299  header->type = observer->type;
300  header->tokenLen = observer->tokenLen;
301  header->code = COAP_CODE_INTERNAL_SERVER;
302 
303  //A new notification is transmitted with a new message ID
304  if(observer->changed)
305  {
306  //To properly process a Reset message that rejects a non-confirmable
307  //notification, a server needs to remember the message IDs of the
308  //non-confirmable notifications it sends (refer to RFC 7641, section 4.5)
309  observer->mid = context->mid;
310 
311  //Increment message identifier
312  context->mid++;
313  }
314 
315  //The message ID is a 16-bit unsigned integer that is generated by
316  //the sender of a Confirmable or Non-confirmable message
317  header->mid = htons(observer->mid);
318 
319  //Each notification includes the token specified by the client in the
320  //request (refer to RFC 7641, section 3.2)
321  osMemcpy(header->token, observer->token, observer->tokenLen);
322 
323  //Set the length of the CoAP message
324  context->response.length = sizeof(CoapMessageHeader) + header->tokenLen;
325  context->response.pos = 0;
326 }
327 
328 
329 /**
330  * @brief Send notification response
331  * @param[in] context Pointer to the CoAP server context
332  * @param[in] observer Pointer to the registered observer
333  * @return Error code
334  **/
335 
337  CoapObserver *observer)
338 {
339  error_t error;
340  systime_t time;
342  CoapResource *resource;
343 
344  //Initialize status code
345  error = NO_ERROR;
346 
347  //Get current time
348  time = osGetSystemTime();
349 
350  //Restore original registration request
351  coapServerRestoreRegistrationRequest(context, observer);
352  //Initialize notification response
353  coapServerInitNotificationResponse(context, observer);
354 
355  //Point to the resource observed by the client
356  resource = observer->resource;
357 
358  //Check whether the target resource exists
359  if(resource != NULL)
360  {
361  //To provide an order among notifications for the client, the server sets
362  //the value of the Observe Option in each notification to the 24 least
363  //significant bits of a strictly increasing sequence number (refer to
364  //RFC 7641, section 3.4)
365  coapSetUintOption(&context->response, COAP_OPT_OBSERVE, 0,
366  resource->seqNum);
367 
368  //Any registered callback?
369  if(context->observeCallback != NULL)
370  {
371  //Invoke user callback function
372  error = context->observeCallback(context, observer, resource);
373  }
374  else
375  {
376  //No callback function registered
377  error = ERROR_FAILURE;
378  }
379 
380  //Check status code
381  if(!error)
382  {
383  //A notification can be sent in a confirmable or a non-confirmable
384  //message. The message type used is typically application dependent
385  //and may be determined by the server for each notification
386  //individually
387  if(observer->type == COAP_TYPE_CON)
388  {
389  //The server may send a notification in a confirmable CoAP message
390  //to request an acknowledgement from the client
391  coapSetType(&context->response, COAP_TYPE_CON);
392  }
393  else
394  {
395  //A server that transmits notifications mostly in non-confirmable
396  //messages must send a notification in a confirmable message instead
397  //of a non-confirmable message at least every 24 hours. This
398  //prevents a client that went away or is no longer interested from
399  //remaining in the list of observers indefinitely (refer to RFC 7641,
400  //section 3.5)
401  if((time - observer->ackTimestamp) >=
403  {
404  coapSetType(&context->response, COAP_TYPE_CON);
405  }
406  else
407  {
408  coapSetType(&context->response, COAP_TYPE_NON);
409  }
410  }
411  }
412  }
413  else
414  {
415  //When the resource is deleted, the server sends a notification with an
416  //appropriate response code (such as 4.04 Not Found)
417  coapSetCode(&context->response, COAP_CODE_NOT_FOUND);
418 
419  //Send the notification in a confirmable CoAP message to request an
420  //acknowledgement from the client
421  coapSetType(&context->response, COAP_TYPE_CON);
422  }
423 
424  //Check status code
425  if(!error)
426  {
427  //Debug message
428  TRACE_INFO("CoAP Server: Sending CoAP message (%" PRIuSIZE " bytes)...\r\n",
429  context->response.length);
430 
431  //Dump the contents of the message for debugging purpose
432  coapDumpMessage(context->response.buffer, context->response.length);
433 
434  //Send notification response
435  coapServerSendResponse(context, context->response.buffer,
436  context->response.length);
437 
438  //Save the time at which the message was sent
439  observer->retransmitTimestamp = osGetSystemTime();
440 
441  //Retrieve message type
442  coapGetType(&context->response, &type);
443 
444  //Confirmable notification?
445  if(type == COAP_TYPE_CON)
446  {
447  //Initial transmission?
448  if(observer->state == COAP_OBSERVER_STATE_REGISTERED)
449  {
450  //Initialize the transmission parameters
451  observer->retransmitCount = 0;
452 
453  //The initial timeout is set to a random duration
454  observer->retransmitTimeout = netGetRandRange(context->netContext,
456  }
457  else
458  {
459  //The timeout is doubled
460  observer->retransmitTimeout *= 2;
461  }
462 
463  //Increment retransmission counter
464  observer->retransmitCount++;
465 
466  //Update the state of the observer
467  observer->state = COAP_OBSERVER_STATE_UPDATING;
468  }
469  }
470 
471  //Clear flag
472  observer->changed = FALSE;
473 
474  //Return status code
475  return error;
476 }
477 
478 
479 /**
480  * @brief Process Acknowledgement message
481  * @param[in] context Pointer to the CoAP server context
482  * @return Error code
483  **/
484 
486 {
487  error_t error;
488  CoapMessageHeader *header;
489 
490  //Initialize status code
491  error = NO_ERROR;
492 
493  //CoAP uses a short fixed-length binary header (4 bytes)
494  header = (CoapMessageHeader *) context->request.buffer;
495 
496  //Empty message?
497  if(header->code == COAP_CODE_EMPTY)
498  {
499  uint_t i;
500  CoapObserver *observer;
501 
502  //Loop through the list of registered observers
503  for(i = 0; i < context->numObservers; i++)
504  {
505  //Point to the current entry
506  observer = &context->observers[i];
507 
508  //Check the state of the observer
509  if(observer->state == COAP_OBSERVER_STATE_UPDATING)
510  {
511  //The source endpoint of the response must be the same as the
512  //destination endpoint of the original request
513  if(observer->interface == context->localInterface &&
514  ipCompAddr(&observer->serverIpAddr, &context->localIpAddr) &&
515  ipCompAddr(&observer->clientIpAddr, &context->remoteIpAddr) &&
516  observer->clientPort == context->remotePort)
517  {
518  //The message ID of the Acknowledgment must match the message ID
519  //of the Confirmable message
520  if(observer->mid == ntohs(header->mid))
521  {
522  //An acknowledgement message signals to the server that the
523  //client is alive and interested in receiving further
524  //notifications (refer to RFC 7641, section 3.5)
525  observer->ackTimestamp = osGetSystemTime();
526 
527  //The server must stop retransmitting its notification on any
528  //matching Acknowledgement
529  observer->state = COAP_OBSERVER_STATE_REGISTERED;
530 
531  //The server must keep the resource state that is observed by
532  //the client as closely in sync with the actual resource state
533  //as possible
534  if(observer->changed)
535  {
536  //Start to transmit a new notification with a representation
537  //of the current resource state. Should the resource have
538  //changed its state more than once in the meantime, the
539  //notifications for the intermediate states are silently
540  //skipped (refer to RFC 7641, section 4.5.2)
541  coapServerSendNotificationResponse(context, observer);
542  }
543 
544  //Check whether the target resource has been deleted
545  if(observer->state == COAP_OBSERVER_STATE_REGISTERED &&
546  observer->resource == NULL)
547  {
548  //Removes the client's entry from the list of observers
549  coapServerDeleteObserver(observer);
550  }
551  }
552  }
553  }
554  }
555  }
556  else
557  {
558  //Rejecting an Acknowledgement message is effected by silently ignoring
559  //it (refer to RFC 7252, section 4.2)
560  error = ERROR_INVALID_MESSAGE;
561  }
562 
563  //More generally, recipients of Acknowledgement and Reset messages must not
564  //respond with either Acknowledgement or Reset messages
565  context->response.length = 0;
566 
567  //Return status code
568  return error;
569 }
570 
571 
572 /**
573  * @brief Process Reset message
574  * @param[in] context Pointer to the CoAP server context
575  * @return Error code
576  **/
577 
579 {
580  error_t error;
581  CoapMessageHeader *header;
582 
583  //Initialize status code
584  error = NO_ERROR;
585 
586  //CoAP uses a short fixed-length binary header (4 bytes)
587  header = (CoapMessageHeader *) context->request.buffer;
588 
589  //Empty message?
590  if(header->code == COAP_CODE_EMPTY)
591  {
592  uint_t i;
593  CoapObserver *observer;
594 
595  //Loop through the list of registered observers
596  for(i = 0; i < context->numObservers; i++)
597  {
598  //Point to the current entry
599  observer = &context->observers[i];
600 
601  //Check the state of the observer
602  if(observer->state != COAP_OBSERVER_STATE_UNREGISTERED)
603  {
604  //The source endpoint of the response must be the same as the
605  //destination endpoint of the original request
606  if(observer->interface == context->localInterface &&
607  ipCompAddr(&observer->serverIpAddr, &context->localIpAddr) &&
608  ipCompAddr(&observer->clientIpAddr, &context->remoteIpAddr) &&
609  observer->clientPort == context->remotePort)
610  {
611  //The message ID of the Reset must match the message ID of the
612  //Confirmable message
613  if(observer->mid == ntohs(header->mid))
614  {
615  //If a client rejects a notification with a Reset message,
616  //then the client is considered no longer interested and the
617  //server must remove the associated entry from the list of
618  //observers (refer to RFC 7641, section 4.5)
619  coapServerDeleteObserver(observer);
620  }
621  }
622  }
623  }
624  }
625  else
626  {
627  //Rejecting an Reset message is effected by silently ignoring it (refer
628  //to RFC 7252, section 4.2)
629  error = ERROR_INVALID_MESSAGE;
630  }
631 
632  //More generally, recipients of Acknowledgement and Reset messages must not
633  //respond with either Acknowledgement or Reset messages
634  context->response.length = 0;
635 
636  //Return status code
637  return error;
638 }
639 
640 
641 /**
642  * @brief Search the list of resources for a given URI
643  * @param[in] context Pointer to the CoAP server context
644  * @param[in] uri NULL-terminated string containing the path to the resource
645  * @return Pointer to the matching resource
646  **/
647 
649  const char_t *uri)
650 {
651  uint_t i;
652  CoapResource *resource;
653 
654  //Initialize pointer
655  resource = NULL;
656 
657  //Loop through the list of resources
658  for(i = 0; i < context->numResources; i++)
659  {
660  //Valid entry?
661  if(context->resources[i].uri[0] != '\0')
662  {
663  //Matching URI?
664  if(osStrcmp(context->resources[i].uri, uri) == 0)
665  {
666  resource = &context->resources[i];
667  break;
668  }
669  }
670  }
671 
672  //Return a pointer to the matching entry
673  return resource;
674 }
675 
676 
677 /**
678  * @brief Create a new entry in the list of observers
679  * @param[in] context Pointer to the CoAP server context
680  * @param[in] token Pointer to the token specified by the client
681  * @param[in] tokenLen Length of the token, in bytes
682  * @param[in] resource Pointer to the target resource
683  * @return Pointer to the newly created entry
684  **/
685 
687  const uint8_t *token, size_t tokenLen, CoapResource *resource)
688 {
689  uint_t i;
690  systime_t time;
691  CoapObserver *observer;
692 
693  //Get current time
694  time = osGetSystemTime();
695 
696  //Initialize pointer
697  observer = NULL;
698 
699  //Loop through the list of registered observers
700  for(i = 0; i < context->numObservers; i++)
701  {
702  //Check whether the entry is available
703  if(context->observers[i].state == COAP_OBSERVER_STATE_UNREGISTERED)
704  {
705  //Point to the current entry
706  observer = &context->observers[i];
707 
708  //Clear entry
709  osMemset(observer, 0, sizeof(CoapObserver));
710 
711  //Initialize entry
712  observer->resource = resource;
713  observer->interface = context->localInterface;
714  observer->serverIpAddr = context->localIpAddr;
715  observer->clientIpAddr = context->remoteIpAddr;
716  observer->clientPort = context->remotePort;
717  observer->retransmitTimestamp = time;
718  observer->ackTimestamp = time;
719 
720  //All notifications carry the token specified by the client, so the
721  //client can easily correlate them to the request
722  osMemcpy(observer->token, token, tokenLen);
723  observer->tokenLen = tokenLen;
724 
725  //A notification can be confirmable or non-confirmable. The message
726  //type used for a notification is independent of the type used for
727  //the request and of any previous notification (refer to RFC 7641,
728  //section 3.5)
729  observer->type = COAP_TYPE_CON;
730 
731  //Update the state of the observer
732  observer->state = COAP_OBSERVER_STATE_REGISTERED;
733 
734  //We are done
735  break;
736  }
737  }
738 
739  //Return a pointer to the newly created entry
740  return observer;
741 }
742 
743 
744 /**
745  * @brief Search the list of observers for a given entry
746  * @param[in] context Pointer to the CoAP server context
747  * @param[in] token Pointer to the token specified by the client
748  * @param[in] tokenLen Length of the token, in bytes
749  * @return Pointer to the matching entry
750  **/
751 
753  const uint8_t *token, size_t tokenLen)
754 {
755  uint_t i;
756  CoapObserver *observer;
757 
758  //Loop through the list of registered observers
759  for(i = 0; i < context->numObservers; i++)
760  {
761  //Point to the current entry
762  observer = &context->observers[i];
763 
764  //Valid entry?
765  if(observer->state != COAP_OBSERVER_STATE_UNREGISTERED)
766  {
767  //Matching client endpoint?
768  if(observer->interface == context->localInterface &&
769  ipCompAddr(&observer->serverIpAddr, &context->localIpAddr) &&
770  ipCompAddr(&observer->clientIpAddr, &context->remoteIpAddr) &&
771  observer->clientPort == context->remotePort)
772  {
773  //Matching token?
774  if(observer->tokenLen == tokenLen &&
775  osMemcmp(observer->token, token, tokenLen) == 0)
776  {
777  break;
778  }
779  }
780  }
781  }
782 
783  //Return a pointer to the matching entry
784  return (i < context->numObservers) ? observer : NULL;
785 }
786 
787 
788 /**
789  * @brief Remove an entry from the list of observers
790  * @param[in] observer Pointer to the entry to be removed
791  **/
792 
794 {
795  //Check the state of the observer
796  if(observer->state != COAP_OBSERVER_STATE_UNREGISTERED)
797  {
798  //Debug message
799  TRACE_INFO("CoAP Server: Deleting observer...\r\n");
800 
801  //Delete the entry
802  osMemset(observer, 0, sizeof(CoapObserver));
803  }
804 }
805 
806 #endif
#define COAP_SERVER_MAX_CONFIRMABLE_NOTIF_INTERVAL
Definition: coap_server.h:112
error_t coapSetCode(CoapMessage *message, CoapCode code)
Set method or response code.
Definition: coap_message.c:201
#define htons(value)
Definition: cpu_endian.h:413
error_t coapSetUintOption(CoapMessage *message, uint16_t optionNum, uint_t optionIndex, uint32_t optionValue)
Add a uint option to the specified CoAP message.
Definition: coap_option.c:543
error_t coapSetType(CoapMessage *message, CoapMessageType type)
Set message type.
Definition: coap_message.c:151
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
@ ERROR_NOT_FOUND
Definition: error.h:148
void coapServerInitNotificationResponse(CoapServerContext *context, CoapObserver *observer)
Initialize notification response.
void coapServerProcessObserveEvents(CoapServerContext *context)
Process observe-related events.
uint32_t netGetRandRange(NetContext *context, uint32_t min, uint32_t max)
Generate a random value in the specified range.
Definition: net.c:473
error_t coapServerSendResponse(CoapServerContext *context, const void *data, size_t length)
Send CoAP response.
#define CoapObserver
Definition: coap_server.h:176
uint8_t type
Definition: coap_common.h:176
#define osMemcmp(p1, p2, length)
Definition: os_port.h:159
Helper functions for CoAP server.
#define osStrcmp(s1, s2)
Definition: os_port.h:177
@ ERROR_INVALID_MESSAGE
Definition: error.h:105
error_t coapServerProcessReset(CoapServerContext *context)
Process Reset message.
#define CoapResource
Definition: coap_server.h:172
#define COAP_SERVER_ACK_TIMEOUT_MAX
Definition: coap_server.h:98
#define COAP_SERVER_MAX_RETRANSMIT
Definition: coap_server.h:84
@ COAP_OBSERVER_STATE_UNREGISTERED
Definition: coap_server.h:190
@ COAP_VERSION_1
CoAP version 1.
Definition: coap_common.h:69
error_t coapServerProcessRegistrationRequest(CoapServerContext *context)
Process registration request.
#define FALSE
Definition: os_port.h:46
void coapServerDeleteObserver(CoapObserver *observer)
Remove an entry from the list of observers.
@ COAP_OBSERVER_STATE_UPDATING
Definition: coap_server.h:192
#define osMemcpy(dest, src, length)
Definition: os_port.h:147
error_t coapGetType(const CoapMessage *message, CoapMessageType *type)
Get message type.
Definition: coap_message.c:176
error_t
Error codes.
Definition: error.h:43
bool_t ipCompAddr(const IpAddr *ipAddr1, const IpAddr *ipAddr2)
Compare IP addresses.
Definition: ip.c:318
error_t coapServerSendNotificationResponse(CoapServerContext *context, CoapObserver *observer)
Send notification response.
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
@ COAP_OPT_OBSERVE
Definition: coap_option.h:96
@ COAP_CODE_NOT_FOUND
Definition: coap_common.h:132
#define TRACE_INFO(...)
Definition: debug.h:105
@ COAP_TYPE_CON
Confirmable message.
Definition: coap_common.h:89
@ COAP_OPT_URI_PATH
Definition: coap_option.h:99
error_t coapSplitRepeatableOption(CoapMessage *message, uint16_t optionNum, const char_t *optionValue, char_t separator)
Encode a path or query component into multiple repeatable options.
Definition: coap_option.c:822
CoapResource * coapServerFindResource(CoapServerContext *context, const char_t *uri)
Search the list of resources for a given URI.
uint32_t systime_t
System time.
CoAP server.
#define ntohs(value)
Definition: cpu_endian.h:421
char char_t
Definition: compiler_port.h:55
error_t coapServerProcessAck(CoapServerContext *context)
Process Acknowledgement message.
uint32_t time
@ COAP_CODE_GET
Definition: coap_common.h:115
CoapMessageType
CoAP message types.
Definition: coap_common.h:88
@ COAP_OBSERVER_STATE_REGISTERED
Definition: coap_server.h:191
Data logging functions for debugging purpose (CoAP)
#define COAP_SERVER_ACK_TIMEOUT_MIN
Definition: coap_server.h:91
@ COAP_CODE_INTERNAL_SERVER
Definition: coap_common.h:141
#define CoapServerContext
Definition: coap_server.h:164
void coapServerRestoreRegistrationRequest(CoapServerContext *context, CoapObserver *observer)
Restore original registration request.
uint8_t value[]
Definition: tcp.h:376
CoapObserver * coapServerCreateObserver(CoapServerContext *context, const uint8_t *token, size_t tokenLen, CoapResource *resource)
Create a new entry in the list of observers.
@ COAP_CODE_EMPTY
Definition: coap_common.h:114
CoapObserver * coapServerFindObserver(CoapServerContext *context, const uint8_t *token, size_t tokenLen)
Search the list of observers for a given entry.
#define PRIuSIZE
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:141
TCP/IP stack core.
@ COAP_TYPE_NON
Non-confirmable message.
Definition: coap_common.h:90
#define COAP_SERVER_MIN_NON_CONFIRMABLE_NOTIF_INTERVAL
Definition: coap_server.h:105
@ NO_ERROR
Success.
Definition: error.h:44
CoapMessageHeader
Definition: coap_common.h:182
Debugging facilities.
error_t coapDumpMessage(const void *message, size_t length)
Dump CoAP message for debugging purpose.
Definition: coap_debug.c:122
uint8_t token[]
Definition: coap_common.h:181
systime_t osGetSystemTime(void)
Retrieve system time.