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