coap_client_misc.c
Go to the documentation of this file.
1 /**
2  * @file coap_client_misc.c
3  * @brief Helper functions for CoAP client
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"
38 #include "coap/coap_client_misc.h"
39 #include "coap/coap_common.h"
40 #include "coap/coap_debug.h"
41 #include "debug.h"
42 #include "error.h"
43 
44 //Check TCP/IP stack configuration
45 #if (COAP_CLIENT_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief Process CoAP client events
50  * @param[in] context Pointer to the CoAP client context
51  * @param[in] timeout Maximum time to wait before returning
52  * @return Error code
53  **/
54 
56 {
57  error_t error;
58  uint_t i;
59  systime_t d;
60  systime_t startTime;
61  systime_t currentTime;
62 
63  //Flush receive buffer
64  context->response.length = 0;
65 
66  //Save current time
67  currentTime = osGetSystemTime();
68  startTime = currentTime;
69 
70  //Process events
71  do
72  {
73  //Maximum time to wait for an incoming datagram
74  if(timeCompare(startTime + timeout, currentTime) > 0)
75  d = startTime + timeout - currentTime;
76  else
77  d = 0;
78 
79  //Limit the delay
81 
82  //Wait for incoming traffic
83  coapClientWaitForDatagram(context, d);
84 
85  //Get current time
86  currentTime = osGetSystemTime();
87 
88  //Receive datagram, if any
89  error = coapClientReceiveDatagram(context, context->response.buffer,
90  COAP_MAX_MSG_SIZE, &context->response.length);
91 
92  //Any datagram received?
93  if(error == NO_ERROR)
94  {
95  //Parse the received datagram
96  error = coapClientParseMessage(&context->response);
97 
98  //Check status code
99  if(error == NO_ERROR)
100  {
101  //Rewind to the beginning of the buffer
102  context->response.pos = 0;
103  //Terminate the payload with a NULL character
104  context->response.buffer[context->response.length] = '\0';
105 
106  //Debug message
107  TRACE_INFO("CoAP message received (%" PRIuSIZE " bytes)...\r\n",
108  context->response.length);
109 
110  //Dump the contents of the message for debugging purpose
111  coapDumpMessage(context->response.buffer,
112  context->response.length);
113 
114  //Try to match the response with an outstanding request
115  for(i = 0; i < COAP_CLIENT_NSTART; i++)
116  {
117  //Apply request/response matching rules
118  error = coapClientMatchResponse(&context->request[i],
119  &context->response);
120 
121  //Test if the response matches the current request
122  if(error != ERROR_UNEXPECTED_MESSAGE)
123  break;
124  }
125 
126  //Check status code
127  if(error == NO_ERROR)
128  {
129  //Process the received CoAP message
130  error = coapClientProcessResponse(&context->request[i],
131  &context->response);
132  }
133  else if(error == ERROR_UNEXPECTED_MESSAGE)
134  {
135  //Reject the received CoAP message
136  error = coapClientRejectResponse(context, &context->response);
137  }
138  else
139  {
140  //Just for sanity
141  }
142  }
143  else
144  {
145  //Debug message
146  TRACE_DEBUG("Invalid CoAP message received!\r\n");
147  //Silently discard the received datagram
148  error = NO_ERROR;
149  }
150  }
151  else if(error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
152  {
153  //No datagram has been received
154  error = NO_ERROR;
155  }
156  else
157  {
158  //Just for sanity
159  }
160 
161  //Check status code
162  if(error == NO_ERROR)
163  {
164  //Process request-specific events
165  for(i = 0; i < COAP_CLIENT_NSTART; i++)
166  {
167  //Manage retransmission for the current request
168  error = coapClientProcessRequestEvents(&context->request[i]);
169  //Any error to report?
170  if(error)
171  break;
172  }
173  }
174 
175  //Check whether the timeout has elapsed
176  } while(error == NO_ERROR && context->response.length == 0 && d > 0);
177 
178  //Return status code
179  return error;
180 }
181 
182 
183 /**
184  * @brief Process request-specific events
185  * @param[in] request CoAP request handle
186  * @return Error code
187  **/
188 
190 {
191  error_t error;
192  systime_t time;
193  CoapClientContext *context;
194  CoapMessageHeader *header;
195 
196  //Initialize status code
197  error = NO_ERROR;
198 
199  //Get current time
200  time = osGetSystemTime();
201 
202  //Point to the CoAP client context
203  context = request->context;
204  //Point to the CoAP message header
205  header = (CoapMessageHeader *) request->message.buffer;
206 
207  //Check current state
208  if(request->state == COAP_REQ_STATE_TRANSMIT)
209  {
210  //Debug message
211  TRACE_INFO("Sending CoAP message (%" PRIuSIZE " bytes)...\r\n",
212  request->message.length);
213 
214  //Dump the contents of the message for debugging purpose
215  coapDumpMessage(request->message.buffer, request->message.length);
216 
217  //Send CoAP request
218  error = coapClientSendDatagram(context, request->message.buffer,
219  request->message.length);
220 
221  //Save the time at which the message was sent
222  request->retransmitStartTime = osGetSystemTime();
223 
224  //Check retransmission counter
225  if(request->retransmitCount == 0)
226  {
227  //Save request start time
228  request->startTime = request->retransmitStartTime;
229 
230  //The initial timeout is set to a random duration
231  request->retransmitTimeout = netGetRandRange(COAP_CLIENT_ACK_TIMEOUT_MIN,
233  }
234  else
235  {
236  //The timeout is doubled
237  request->retransmitTimeout *= 2;
238  }
239 
240  //Increment retransmission counter
241  request->retransmitCount++;
242 
243  //Wait for a response to be received
245  }
246  else if(request->state == COAP_REQ_STATE_RECEIVE)
247  {
248  //Check whether the timeout has elapsed
249  if(timeCompare(time, request->startTime + request->timeout) >= 0)
250  {
251  //Report a timeout error
253  }
254  else if(timeCompare(time, request->retransmitStartTime +
255  request->retransmitTimeout) >= 0)
256  {
257  //The reliable transmission of a message is initiated by marking the
258  //message as Confirmable in the CoAP header
259  if(header->type == COAP_TYPE_CON)
260  {
261  //The sender retransmits the Confirmable message at exponentially
262  //increasing intervals, until it receives an acknowledgment or
263  //runs out of attempts (refer to RFC 7252, section 4.2)
264  if(request->retransmitCount < COAP_CLIENT_MAX_RETRANSMIT)
265  {
266  //When the timeout is triggered and the retransmission counter is
267  //less than MAX_RETRANSMIT, the message is retransmitted
268  error = coapClientChangeRequestState(request,
270  }
271  else
272  {
273  //If the retransmission counter reaches MAX_RETRANSMIT on a
274  //timeout, then the attempt to transmit the message is canceled
275  //and the application process informed of failure
276  error = coapClientChangeRequestState(request,
278  }
279  }
280  }
281  else
282  {
283  //Just for sanity
284  }
285  }
286  else if(request->state == COAP_REQ_STATE_SEPARATE)
287  {
288  //Check whether the timeout has elapsed
289  if(timeCompare(time, request->startTime + request->timeout) >= 0)
290  {
291  //Report a timeout error
293  }
294  }
295  else if(request->state == COAP_REQ_STATE_OBSERVE)
296  {
297  //Check whether the timeout has elapsed
298  if(timeCompare(time, request->retransmitStartTime +
299  request->retransmitTimeout) >= 0)
300  {
301  //Point to the CoAP message header
302  header = (CoapMessageHeader *) request->message.buffer;
303 
304  //The message ID is a 16-bit unsigned integer that is generated by
305  //the sender of a Confirmable or Non-confirmable message
306  coapClientGenerateMessageId(context, header);
307 
308  //Reset retransmission counter
309  request->retransmitCount = 0;
310 
311  //To re-register its interest in a resource, a client may issue a
312  //new GET request with the same token as the original
314  }
315  }
316  else
317  {
318  //Just for sanity
319  }
320 
321  //Return status code
322  return error;
323 }
324 
325 
326 /**
327  * @brief Update CoAP request state
328  * @param[in] request CoAP request handle
329  * @param[in] newState New state to switch to
330  * @return Error code
331  **/
332 
334  CoapRequestState newState)
335 {
336  error_t error;
337  CoapRequestStatus status;
338  CoapClientContext *context;
339 
340  //Initialize status code
341  error = NO_ERROR;
342 
343  //Point to the CoAP client context
344  context = request->context;
345 
346  //Switch to the new state
347  request->state = newState;
348 
349  //Check whether a request is ready to be transmitted
350  if(newState == COAP_REQ_STATE_TRANSMIT)
351  {
352  //Notify the CoAP client
353  osSetEvent(&context->event);
354  }
355 
356  //The CoAP client operates in asynchronous mode when a callback function
357  //has been defined
358  if(request->callback != NULL)
359  {
360  //Check whether the request has terminated
361  if(newState == COAP_REQ_STATE_OBSERVE ||
362  newState == COAP_REQ_STATE_DONE ||
363  newState == COAP_REQ_STATE_RESET ||
364  newState == COAP_REQ_STATE_TIMEOUT ||
365  newState == COAP_REQ_STATE_CANCELED)
366  {
367  //Get the status of the request
368  if(newState == COAP_REQ_STATE_RESET)
369  {
370  //A Reset message has been received
371  status = COAP_REQUEST_STATUS_RESET;
372  }
373  else if(newState == COAP_REQ_STATE_TIMEOUT)
374  {
375  //A timeout error has occurred
377  }
378  else if(newState == COAP_REQ_STATE_CANCELED)
379  {
380  //The request has been canceled
382  }
383  else
384  {
385  //The request has successfully completed
387  }
388 
389  //Release exclusive access to the CoAP client context
390  osReleaseMutex(&context->mutex);
391  //Invoke callback function
392  error = request->callback(context, request, status, request->param);
393  //Acquire exclusive access to the CoAP client context
394  osAcquireMutex(&context->mutex);
395  }
396 
397  //Asynchronous requests are automatically released
398  if(newState == COAP_REQ_STATE_DONE ||
399  newState == COAP_REQ_STATE_RESET ||
400  newState == COAP_REQ_STATE_TIMEOUT ||
401  newState == COAP_REQ_STATE_CANCELED)
402  {
403  if(request->state != COAP_REQ_STATE_TRANSMIT)
404  {
405  //Release the resources associated with a CoAP request
406  request->state = COAP_REQ_STATE_UNUSED;
407  }
408  }
409  }
410 
411  //Return status code
412  return error;
413 }
414 
415 
416 /**
417  * @brief Check whether a response matches the specified request
418  * @param[in] request CoAP request handle
419  * @param[in] response Pointer to the response message
420  * @return Error code
421  **/
422 
424  const CoapMessage *response)
425 {
426  error_t error;
427  const CoapMessageHeader *reqHeader;
428  const CoapMessageHeader *respHeader;
429 
430  //Get CoAP request and response headers
431  reqHeader = (CoapMessageHeader *) request->message.buffer;
432  respHeader = (CoapMessageHeader *) response->buffer;
433 
434  //Initialize status code
435  error = ERROR_UNEXPECTED_MESSAGE;
436 
437  //Check request state
438  if(request->state == COAP_REQ_STATE_RECEIVE)
439  {
440  //Confirmable request?
441  if(reqHeader->type == COAP_TYPE_CON)
442  {
443  //Check the type of the response
444  if(respHeader->type == COAP_TYPE_CON ||
445  respHeader->type == COAP_TYPE_NON)
446  {
447  //Tokens are used to match a response with a request
448  if(coapCompareToken(respHeader, reqHeader))
449  {
450  //A matching response has been received
451  error = NO_ERROR;
452  }
453  }
454  else if(respHeader->type == COAP_TYPE_ACK)
455  {
456  //The message ID of the Acknowledgment must match the message ID
457  //of the Confirmable message
458  if(respHeader->mid == reqHeader->mid)
459  {
460  //Empty ACK received?
461  if(respHeader->code == COAP_CODE_EMPTY)
462  {
463  //When a Confirmable message carrying a request is acknowledged
464  //with an Empty message, a separate response is sent in a
465  //separate message exchange
466  error = NO_ERROR;
467  }
468  else
469  {
470  //In a piggybacked response, the message ID of the Confirmable
471  //request and the Acknowledgment must match, and the tokens of
472  //the response and original request must match
473  if(coapCompareToken(respHeader, reqHeader))
474  {
475  //A matching response has been received
476  error = NO_ERROR;
477  }
478  }
479  }
480  }
481  else if(respHeader->code == COAP_TYPE_RST)
482  {
483  //The message ID of the Reset must match the message ID of
484  //the Confirmable message
485  if(respHeader->mid == reqHeader->mid)
486  {
487  //A Reset message indicates that the request was received by the
488  //server, but some context is missing to properly process it
489  error = NO_ERROR;
490  }
491  }
492  else
493  {
494  //Just for sanity
495  }
496  }
497  //Non-Confirmable request?
498  else
499  {
500  //If a request is sent in a Non-confirmable message, then the response
501  //is sent using a new Non-confirmable message, although the server may
502  //instead send a Confirmable message (refer to RFC 7252, section 2.2)
503  if(respHeader->type == COAP_TYPE_CON ||
504  respHeader->type == COAP_TYPE_NON)
505  {
506  //Tokens are used to match a response with a request
507  if(coapCompareToken(respHeader, reqHeader))
508  {
509  //A matching response has been received
510  error = NO_ERROR;
511  }
512  }
513  else if(respHeader->type == COAP_TYPE_RST)
514  {
515  //The message ID of the Reset must match the message ID of
516  //the Non-confirmable message
517  if(respHeader->mid == reqHeader->mid)
518  {
519  //A matching response has been received
520  error = NO_ERROR;
521  }
522  }
523  else
524  {
525  //Just for sanity
526  }
527  }
528  }
529  else if(request->state == COAP_REQ_STATE_SEPARATE ||
530  request->state == COAP_REQ_STATE_OBSERVE)
531  {
532  //Check the type of the response
533  if(respHeader->type == COAP_TYPE_CON ||
534  respHeader->type == COAP_TYPE_NON)
535  {
536  //Tokens are used to match a response with a request
537  if(coapCompareToken(respHeader, reqHeader))
538  {
539  //A matching response has been received
540  error = NO_ERROR;
541  }
542  }
543  }
544  else
545  {
546  //Just for sanity
547  }
548 
549  //Return status code
550  return error;
551 }
552 
553 
554 /**
555  * @brief Process CoAP response
556  * @param[in] request CoAP request handle
557  * @param[in] response Pointer to the response message
558  * @return Error code
559  **/
560 
562  const CoapMessage *response)
563 {
564  error_t error;
565  uint32_t value;
566  CoapClientContext *context;
567  const CoapMessageHeader *header;
568 
569  //Point to the CoAP client context
570  context = request->context;
571  //Point to CoAP response header
572  header = (CoapMessageHeader *) response->buffer;
573 
574  //Confirmable response received?
575  if(header->type == COAP_TYPE_CON)
576  {
577  //The Acknowledgment message must echo the message ID of the
578  //Confirmable message
579  coapClientSendAck(context, ntohs(header->mid));
580  }
581 
582  //Check the type of the response
583  if(header->type == COAP_TYPE_ACK &&
584  header->code == COAP_CODE_EMPTY)
585  {
586  //When a Confirmable message carrying a request is acknowledged with
587  //an Empty message, a separate response is sent in a separate message
588  //exchange
590  }
591  else if(header->type == COAP_TYPE_CON ||
592  header->type == COAP_TYPE_NON ||
593  header->type == COAP_TYPE_ACK)
594  {
595 #if (COAP_CLIENT_OBSERVE_SUPPORT == ENABLED)
596  //Search the CoAP request for an Observe option
597  error = coapGetUintOption(&request->message, COAP_OPT_OBSERVE, 0, &value);
598 
599  //Observe option included in the request?
600  if(!error)
601  {
602  //The client requests the server to add or remove an entry in the
603  //list of observers of the resource depending on the option value
605  {
606  //Process notification response
607  error = coapClientProcessNotification(request, response);
608  }
609  else
610  {
611  //When the client deregisters, it is considered no longer
612  //interested in the resource
613  error = coapClientChangeRequestState(request,
615  }
616  }
617  else
618 #endif
619  {
620  //The request has successfully completed
622  }
623  }
624  else if(header->type == COAP_TYPE_RST)
625  {
626  //A Reset message indicates that the request was received by the server,
627  //but some context is missing to properly process it
629  }
630  else
631  {
632  //Report an error
633  error = ERROR_INVALID_TYPE;
634  }
635 
636  //Return status code
637  return error;
638 }
639 
640 
641 /**
642  * @brief Reject a CoAP response
643  * @param[in] context Pointer to the CoAP client context
644  * @param[in] response Pointer to the response message to be rejected
645  * @return Error code
646  **/
647 
649  const CoapMessage *response)
650 {
651  error_t error;
652  const CoapMessageHeader *header;
653 
654  //Debug message
655  TRACE_INFO("Rejecting CoAP message...\r\n");
656 
657  //Point to the CoAP message header
658  header = (CoapMessageHeader *) response;
659 
660  //Check the type of the response
661  if(header->type == COAP_TYPE_CON)
662  {
663  //Rejecting a Confirmable message is effected by sending a matching
664  //Reset message
665  error = coapClientSendReset(context, ntohs(header->mid));
666  }
667  else if(header->type == COAP_TYPE_NON)
668  {
669  //Rejecting a Non-confirmable message may involve sending a matching
670  //Reset message, and apart from the Reset message the rejected message
671  //must be silently ignored (refer to RFC 7252, section 4.3)
672  error = NO_ERROR;
673  }
674  else
675  {
676  //Rejecting an Acknowledgment or Reset message is effected by
677  //silently ignoring it (refer to RFC 7252, section 4.2)
678  error = NO_ERROR;
679  }
680 
681  //Return status code
682  return error;
683 }
684 
685 
686 /**
687  * @brief Send Acknowledgment message
688  * @param[in] context Pointer to the CoAP client context
689  * @param[in] mid Message ID
690  * @return Error code
691  **/
692 
694 {
696 
697  //Format Acknowledgment message
698  message.version = COAP_VERSION_1;
699  message.type = COAP_TYPE_ACK;
700  message.tokenLen = 0;
701  message.code = COAP_CODE_EMPTY;
702 
703  //The Acknowledgment message message must echo the message ID of the
704  //confirmable message and must be empty
705  message.mid = htons(mid);
706 
707  //Debug message
708  TRACE_INFO("Sending Acknowledgment message (%" PRIuSIZE " bytes)...\r\n",
709  sizeof(message));
710 
711  //Dump the contents of the message for debugging purpose
712  coapDumpMessage(&message, sizeof(message));
713 
714  //Send CoAP message
715  return coapClientSendDatagram(context, &message, sizeof(message));
716 }
717 
718 
719 /**
720  * @brief Send Reset message
721  * @param[in] context Pointer to the CoAP client context
722  * @param[in] mid Message ID
723  * @return Error code
724  **/
725 
727 {
729 
730  //Format Reset message
731  message.version = COAP_VERSION_1;
732  message.type = COAP_TYPE_RST;
733  message.tokenLen = 0;
734  message.code = COAP_CODE_EMPTY;
735 
736  //The Reset message message must echo the message ID of the confirmable
737  //message and must be empty
738  message.mid = htons(mid);
739 
740  //Debug message
741  TRACE_INFO("Sending Reset message (%" PRIuSIZE " bytes)...\r\n",
742  sizeof(message));
743 
744  //Dump the contents of the message for debugging purpose
745  coapDumpMessage(&message, sizeof(message));
746 
747  //Send CoAP message
748  return coapClientSendDatagram(context, &message, sizeof(message));
749 }
750 
751 
752 /**
753  * @brief Generate a new message identifier
754  * @param[in] context Pointer to the CoAP client context
755  * @param[in] header Pointer to the CoAP message header
756  **/
757 
759  CoapMessageHeader *header)
760 {
761  //The message ID is a 16-bit unsigned integer that is generated by
762  //the sender of a Confirmable or Non-confirmable message
763  header->mid = htons(context->mid);
764 
765  //Increment message identifier
766  context->mid++;
767 }
768 
769 
770 /**
771  * @brief Generate a new token
772  * @param[in] context Pointer to the CoAP client context
773  * @param[in] header Pointer to the CoAP message header
774  **/
775 
777  CoapMessageHeader *header)
778 {
779  uint8_t i;
780 
781  //Generate a random token
782  for(i = 0; i < header->tokenLen; i++)
783  {
784  header->token[i] = (uint8_t) netGetRand();
785  }
786 }
787 
788 #endif
error_t coapClientSendAck(CoapClientContext *context, uint16_t mid)
Send Acknowledgment message.
uint32_t systime_t
Definition: compiler_port.h:44
error_t coapDumpMessage(const void *message, size_t length)
Dump CoAP message for debugging purpose.
Definition: coap_debug.c:121
#define timeCompare(t1, t2)
Definition: os_port.h:40
Helper functions for CoAP client.
systime_t osGetSystemTime(void)
Retrieve system time.
uint32_t time
TCP/IP stack core.
Reset message.
Definition: coap_common.h:95
Debugging facilities.
CoAP message.
Definition: coap_message.h:53
uint8_t message[]
Definition: chap.h:150
error_t coapClientRejectResponse(CoapClientContext *context, const CoapMessage *response)
Reject a CoAP response.
error_t coapClientReceiveDatagram(CoapClientContext *context, void *data, size_t size, size_t *received)
Receive a datagram.
#define htons(value)
Definition: cpu_endian.h:390
error_t coapClientSendDatagram(CoapClientContext *context, const void *data, size_t length)
Send a datagram.
#define COAP_CLIENT_MAX_RETRANSMIT
Definition: coap_client.h:89
error_t coapClientChangeRequestState(CoapClientRequest *request, CoapRequestState newState)
Update CoAP request state.
Error codes description.
CoAP version 1.
Definition: coap_common.h:72
#define ntohs(value)
Definition: cpu_endian.h:396
error_t coapClientProcessEvents(CoapClientContext *context, systime_t timeout)
Process CoAP client events.
uint32_t netGetRand(void)
Get a random value.
Definition: net.c:1523
void coapClientGenerateToken(CoapClientContext *context, CoapMessageHeader *header)
Generate a new token.
Definitions common to CoAP client and server.
Confirmable message.
Definition: coap_common.h:92
error_t coapClientProcessNotification(CoapClientRequest *request, const CoapMessage *response)
Process notification response.
error_t coapClientProcessResponse(CoapClientRequest *request, const CoapMessage *response)
Process CoAP response.
bool_t coapCompareToken(const CoapMessageHeader *header1, const CoapMessageHeader *header2)
Token comparison.
Definition: coap_message.c:545
#define COAP_MAX_MSG_SIZE
Definition: coap_common.h:37
#define MIN(a, b)
Definition: os_port.h:60
error_t coapClientMatchResponse(const CoapClientRequest *request, const CoapMessage *response)
Check whether a response matches the specified request.
#define TRACE_INFO(...)
Definition: debug.h:86
#define COAP_CLIENT_ACK_TIMEOUT_MIN
Definition: coap_client.h:96
Success.
Definition: error.h:42
uint8_t buffer[COAP_MAX_MSG_SIZE]
Definition: coap_message.h:55
int32_t netGetRandRange(int32_t min, int32_t max)
Get a random value in the specified range.
Definition: net.c:1554
void coapClientGenerateMessageId(CoapClientContext *context, CoapMessageHeader *header)
Generate a new message identifier.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
error_t
Error codes.
Definition: error.h:40
CoAP observe.
unsigned int uint_t
Definition: compiler_port.h:43
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
CoapRequestState
CoAP request states.
#define PRIuSIZE
Definition: compiler_port.h:72
uint16_t mid
Definition: coap_common.h:180
uint8_t value[]
Definition: dtls_misc.h:141
error_t coapClientWaitForDatagram(CoapClientContext *context, systime_t timeout)
Wait for incoming datagrams.
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
Acknowledgment message.
Definition: coap_common.h:94
CoAP client.
Data logging functions for debugging purpose (CoAP)
error_t coapClientProcessRequestEvents(CoapClientRequest *request)
Process request-specific events.
error_t coapClientParseMessage(const CoapMessage *message)
Parse CoAP message.
Definition: coap_message.c:49
CoapRequestStatus
Request status.
#define COAP_CLIENT_NSTART
Definition: coap_client.h:82
__start_packed struct @110 CoapMessageHeader
CoAP message format.
#define CoapClientRequest
Definition: coap_client.h:141
Transport protocol abstraction layer.
error_t coapClientSendReset(CoapClientContext *context, uint16_t mid)
Send Reset message.
#define COAP_CLIENT_TICK_INTERVAL
Definition: coap_client.h:68
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
Non-confirmable message.
Definition: coap_common.h:93
#define COAP_CLIENT_ACK_TIMEOUT_MAX
Definition: coap_client.h:103
#define TRACE_DEBUG(...)
Definition: debug.h:98
#define CoapClientContext
Definition: coap_client.h:137