1c87c5fbaSopenharmony_ci// -*- mode:doc; -*-
2c87c5fbaSopenharmony_ci// vim: set syntax=asciidoc tw=0
3c87c5fbaSopenharmony_ci
4c87c5fbaSopenharmony_cicoap_block(3)
5c87c5fbaSopenharmony_ci=============
6c87c5fbaSopenharmony_ci:doctype: manpage
7c87c5fbaSopenharmony_ci:man source:   coap_block
8c87c5fbaSopenharmony_ci:man version:  @PACKAGE_VERSION@
9c87c5fbaSopenharmony_ci:man manual:   libcoap Manual
10c87c5fbaSopenharmony_ci
11c87c5fbaSopenharmony_ciNAME
12c87c5fbaSopenharmony_ci----
13c87c5fbaSopenharmony_cicoap_block,
14c87c5fbaSopenharmony_cicoap_context_set_block_mode,
15c87c5fbaSopenharmony_cicoap_add_data_large_request,
16c87c5fbaSopenharmony_cicoap_add_data_large_response,
17c87c5fbaSopenharmony_cicoap_get_data_large,
18c87c5fbaSopenharmony_cicoap_block_build_body,
19c87c5fbaSopenharmony_cicoap_q_block_is_supported
20c87c5fbaSopenharmony_ci- Work with CoAP Blocks
21c87c5fbaSopenharmony_ci
22c87c5fbaSopenharmony_ciSYNOPSIS
23c87c5fbaSopenharmony_ci--------
24c87c5fbaSopenharmony_ci*#include <coap@LIBCOAP_API_VERSION@/coap.h>*
25c87c5fbaSopenharmony_ci
26c87c5fbaSopenharmony_ci*void coap_context_set_block_mode(coap_context_t *_context_,
27c87c5fbaSopenharmony_ciuint8_t _block_mode_);*
28c87c5fbaSopenharmony_ci
29c87c5fbaSopenharmony_ci*int coap_add_data_large_request(coap_session_t *_session_,
30c87c5fbaSopenharmony_cicoap_pdu_t *_pdu_, size_t _length_, const uint8_t *_data_,
31c87c5fbaSopenharmony_cicoap_release_large_data_t _release_func_, void *_app_ptr_);*
32c87c5fbaSopenharmony_ci
33c87c5fbaSopenharmony_ci*int coap_add_data_large_response(coap_resource_t *_resource_,
34c87c5fbaSopenharmony_cicoap_session_t *_session_, const coap_pdu_t *_request_, coap_pdu_t *_response_,
35c87c5fbaSopenharmony_ciconst coap_string_t *query, uint16_t _media_type_, int _maxage_,
36c87c5fbaSopenharmony_ciuint64_t etag, size_t _length_, const uint8_t *_data_,
37c87c5fbaSopenharmony_cicoap_release_large_data_t _release_func_, void *_app_ptr_);*
38c87c5fbaSopenharmony_ci
39c87c5fbaSopenharmony_ci*int coap_get_data_large(const coap_pdu_t *_pdu_, size_t *_length,
40c87c5fbaSopenharmony_ciconst uint8_t **_data_, size_t *_offset_, size_t *_total_);*
41c87c5fbaSopenharmony_ci
42c87c5fbaSopenharmony_ci*coap_binary_t *coap_block_build_body(coap_binary_t *_body_data_,
43c87c5fbaSopenharmony_cisize_t _length_, const uint8_t *_data_, size_t _offset_, size_t _total_);*
44c87c5fbaSopenharmony_ci
45c87c5fbaSopenharmony_ci*int coap_q_block_is_supported(void);*
46c87c5fbaSopenharmony_ci
47c87c5fbaSopenharmony_ciFor specific (D)TLS library support, link with
48c87c5fbaSopenharmony_ci*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*,
49c87c5fbaSopenharmony_ci*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls*
50c87c5fbaSopenharmony_cior *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*.   Otherwise, link with
51c87c5fbaSopenharmony_ci*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support.
52c87c5fbaSopenharmony_ci
53c87c5fbaSopenharmony_ciDESCRIPTION
54c87c5fbaSopenharmony_ci-----------
55c87c5fbaSopenharmony_ciRegular setting up of a PDU and transmission is covered in *coap_pdu_setup*(3)
56c87c5fbaSopenharmony_ciwhere all the payload data can fit in a single packet.  This man page covers
57c87c5fbaSopenharmony_cihow to work with PDUs where the overall body of information may need to be
58c87c5fbaSopenharmony_cisplit across several packets by using CoAP Block-Wise Transfers
59c87c5fbaSopenharmony_ci(https://rfc-editor.org/rfc/rfc7959[RFC7959] and
60c87c5fbaSopenharmony_cihttps://rfc-editor.org/rfc/rfc9177[RFC9177]).
61c87c5fbaSopenharmony_ci
62c87c5fbaSopenharmony_ciThe block-wise transfers can be controlled by the application, or libcoap is
63c87c5fbaSopenharmony_ciinstructed to do all the requests for the next blocks and only present the
64c87c5fbaSopenharmony_cifinal body of the result to the application.  In summary, the following three
65c87c5fbaSopenharmony_ciways handle processing a body of data that has to be split across multiple
66c87c5fbaSopenharmony_cipayloads (blocks).
67c87c5fbaSopenharmony_ci
68c87c5fbaSopenharmony_ci1. Application does all the work +
69c87c5fbaSopenharmony_ciIt is the responsibility of the application to analyze each block transmission
70c87c5fbaSopenharmony_ciat receipt and then generate the next request as per
71c87c5fbaSopenharmony_cihttps://rfc-editor.org/rfc/rfc7959[RFC7959].  In this case,
72c87c5fbaSopenharmony_ci*coap_context_set_block_mode*() function must not be called to maintain
73c87c5fbaSopenharmony_cibackward compatibility with applications that did the block handling within the
74c87c5fbaSopenharmony_ciapplication.
75c87c5fbaSopenharmony_ci
76c87c5fbaSopenharmony_ci2. Application sees individual blocks +
77c87c5fbaSopenharmony_ciBy calling *coap_context_set_block_mode(context, COAP_BLOCK_USE_LIBCOAP)* and
78c87c5fbaSopenharmony_ciusing the appropriate functions, the requests for the next block of data is
79c87c5fbaSopenharmony_cihandled automatically by the libcoap layer.  Each individual block of data is
80c87c5fbaSopenharmony_cipresented to the application for processing. +
81c87c5fbaSopenharmony_ciBy calling *coap_get_data_large*(), the application can determine if this is
82c87c5fbaSopenharmony_cithe first block or not (using _offset_ value), whether the first block is all
83c87c5fbaSopenharmony_cithe data (_offset_ = 0, _length_ = _total_) and whether this is the last block
84c87c5fbaSopenharmony_ci(_offset_ + _length_ = _total_). It is the responsibility of the application to
85c87c5fbaSopenharmony_cire-assemble the individual blocks into a single body of data. +
86c87c5fbaSopenharmony_ci*NOTE:* _total_ is only an approximation (it will be > _offset_ + _length_)
87c87c5fbaSopenharmony_ciuntil the final block is received. +
88c87c5fbaSopenharmony_ciIf this is the request handler in a server, the server still needs to return a
89c87c5fbaSopenharmony_ciCOAP_RESPONSE_CODE_CONTINUE 2.31 (Continue) response code if the received data
90c87c5fbaSopenharmony_ciis not for the final block, otherwise a COAP_RESPONSE_CODE_CREATED 2.01
91c87c5fbaSopenharmony_ci(Created) or COAP_RESPONSE_CODE_CHANGED 2.04 (Changed) should be returned.
92c87c5fbaSopenharmony_ci
93c87c5fbaSopenharmony_ci3. Application only sees all of the body +
94c87c5fbaSopenharmony_ciBy calling *coap_context_set_block_mode(context,
95c87c5fbaSopenharmony_ciCOAP_BLOCK_USE_LIBCOAP|COAP_BLOCK_SINGLE_BODY)* and using the appropriate
96c87c5fbaSopenharmony_cifunctions, the requests for all the blocks of data is handled automatically by
97c87c5fbaSopenharmony_cithe libcoap layer.  Only the complete body of the data is presented to the
98c87c5fbaSopenharmony_ciapplication, unless there is an error. +
99c87c5fbaSopenharmony_ci*coap_get_data_large*() will only return the entire body of data (_offset_
100c87c5fbaSopenharmony_cialways 0, _length_ = _total_) and there is no need to re-assemble individual
101c87c5fbaSopenharmony_ciblocks into a large body of data. +
102c87c5fbaSopenharmony_ciIn RAM constrained environments, option 2 may be the preferred method.
103c87c5fbaSopenharmony_ci
104c87c5fbaSopenharmony_ciThis man page focuses on getting libcoap to do all the work, not how to do it
105c87c5fbaSopenharmony_ciall in the application.
106c87c5fbaSopenharmony_ci
107c87c5fbaSopenharmony_ciHowever, if the client supplies a Block1 or Block2 Option in the PDU where the
108c87c5fbaSopenharmony_ciblock number is not 0, this is assumed to be a random access request and any
109c87c5fbaSopenharmony_ciother blocks will not be requested by libcoap even if instructed otherwise.
110c87c5fbaSopenharmony_ci
111c87c5fbaSopenharmony_ciThe functions that are named *_large* are intended as replacements for the
112c87c5fbaSopenharmony_ciequivalent functions as described in *coap_pdu_setup*(3).
113c87c5fbaSopenharmony_ci
114c87c5fbaSopenharmony_ciCALLBACK HANDLER
115c87c5fbaSopenharmony_ci----------------
116c87c5fbaSopenharmony_ci
117c87c5fbaSopenharmony_ci*Callback Type: coap_release_large_data_t*
118c87c5fbaSopenharmony_ci
119c87c5fbaSopenharmony_ci[source, c]
120c87c5fbaSopenharmony_ci----
121c87c5fbaSopenharmony_ci/**
122c87c5fbaSopenharmony_ci * Callback handler for de-allocating the data based on @p app_ptr provided to
123c87c5fbaSopenharmony_ci * coap_add_data_large_*() functions following transmission of the supplied
124c87c5fbaSopenharmony_ci * data.
125c87c5fbaSopenharmony_ci *
126c87c5fbaSopenharmony_ci * @param session The session that this data is associated with
127c87c5fbaSopenharmony_ci * @param app_ptr The application provided pointer to the
128c87c5fbaSopenharmony_ci *                coap_add_data_large_*() functions
129c87c5fbaSopenharmony_ci */
130c87c5fbaSopenharmony_citypedef void (*coap_release_large_data_t)(coap_session_t *session,
131c87c5fbaSopenharmony_ci                                          void *app_ptr);
132c87c5fbaSopenharmony_ci----
133c87c5fbaSopenharmony_ci
134c87c5fbaSopenharmony_ciFUNCTIONS
135c87c5fbaSopenharmony_ci---------
136c87c5fbaSopenharmony_ci
137c87c5fbaSopenharmony_ci*Function: coap_context_set_block_mode()*
138c87c5fbaSopenharmony_ci
139c87c5fbaSopenharmony_ciThe *coap_context_set_block_mode*() function is used to set up the _context_
140c87c5fbaSopenharmony_cilevel _block_mode_ block handling bits for supporting
141c87c5fbaSopenharmony_cihttps://rfc-editor.org/rfc/rfc7959[RFC7959] _block_mode_
142c87c5fbaSopenharmony_ciflows down to a session when a session is created and if the peer does not
143c87c5fbaSopenharmony_cisupport the respective block mode, an appropriate bit may get disabled in the
144c87c5fbaSopenharmony_cisession _block_mode_.
145c87c5fbaSopenharmony_ci
146c87c5fbaSopenharmony_ci[source, c]
147c87c5fbaSopenharmony_ci----
148c87c5fbaSopenharmony_ci#define COAP_BLOCK_USE_LIBCOAP   0x01 /* Use libcoap to do block requests */
149c87c5fbaSopenharmony_ci#define COAP_BLOCK_SINGLE_BODY   0x02 /* Deliver the data as a single body */
150c87c5fbaSopenharmony_ci#define COAP_BLOCK_TRY_Q_BLOCK   0x04 /* Try Q-Block method */
151c87c5fbaSopenharmony_ci#define COAP_BLOCK_USE_M_Q_BLOCK 0x08 /* Use M bit when recovering Q-Block2 */
152c87c5fbaSopenharmony_ci#define COAP_BLOCK_NO_PREEMPTIVE_RTAG 0x10 /* Don't use pre-emptive Request-Tags */
153c87c5fbaSopenharmony_ci----
154c87c5fbaSopenharmony_ci_block_mode_ is an or'd set of zero or more COAP_BLOCK_* definitions.
155c87c5fbaSopenharmony_ci
156c87c5fbaSopenharmony_ciIf *COAP_BLOCK_USE_LIBCOAP* is not set, then everything works as per Option 1
157c87c5fbaSopenharmony_ciabove.
158c87c5fbaSopenharmony_ci
159c87c5fbaSopenharmony_ciIf *COAP_BLOCK_SINGLE_BODY* is set, then the entire body of data is presented to
160c87c5fbaSopenharmony_cithe receiving handler, otherwise each individual block is presented on arrival.
161c87c5fbaSopenharmony_ciTo obtain the data, length and current offset, *coap_get_data_large*() must
162c87c5fbaSopenharmony_cibe used instead of *coap_get_data*().  It may be appropriate not to set
163c87c5fbaSopenharmony_ci*COAP_BLOCK_SINGLE_BODY* if there are RAM limitations.
164c87c5fbaSopenharmony_ci
165c87c5fbaSopenharmony_ci*NOTE:* It is the responsibility of the receiving application to re-assemble
166c87c5fbaSopenharmony_cithe _data_ as appropriate (e.g., using *coap_block_build_body*()) if
167c87c5fbaSopenharmony_ci*COAP_BLOCK_SINGLE_BODY* is not set.
168c87c5fbaSopenharmony_ci
169c87c5fbaSopenharmony_ci*NOTE:* If *COAP_BLOCK_SINGLE_BODY* is not set, then the CoAP server on
170c87c5fbaSopenharmony_cireceiving
171c87c5fbaSopenharmony_cirequest data that is split over multiple data blocks must respond with
172c87c5fbaSopenharmony_ciCOAP_RESPONSE_CODE_CONTINUE 2.31 (Continue) response code if the received data
173c87c5fbaSopenharmony_ciis not for the final block, otherwise a COAP_RESPONSE_CODE_CREATED 2.01
174c87c5fbaSopenharmony_ci(Created) or COAP_RESPONSE_CODE_CHANGED 2.04 (Changed) should be returned.
175c87c5fbaSopenharmony_ci
176c87c5fbaSopenharmony_ciTo indicate support for Q-Block-1 and Q-Block2, *COAP_BLOCK_TRY_Q_BLOCK* needs
177c87c5fbaSopenharmony_cito be set on both the client and server.  *COAP_BLOCK_SINGLE_BODY* is assumed to
178c87c5fbaSopenharmony_cibe set if using Q-Block as the data will always be presented as a single body.
179c87c5fbaSopenharmony_ciIf *COAP_BLOCK_USE_M_Q_BLOCK* is defined, then the 'M' bit version of recovery
180c87c5fbaSopenharmony_ciwill be used if possible.
181c87c5fbaSopenharmony_ci
182c87c5fbaSopenharmony_ciIf *COAP_BLOCK_USE_LIBCOAP* is set, then any PDUs presented to the application
183c87c5fbaSopenharmony_cihandlers will get the tokens set back to the initiating token so that requests
184c87c5fbaSopenharmony_cican be matched with responses even if different tokens had to be used for the
185c87c5fbaSopenharmony_ciseries of packet interchanges.  Furthermore, if *COAP_BLOCK_SINGLE_BODY* is set,
186c87c5fbaSopenharmony_cithen the PDU that presents the entire body will have any BlockX or Q-BlockX
187c87c5fbaSopenharmony_cioption removed.
188c87c5fbaSopenharmony_ci
189c87c5fbaSopenharmony_ci*NOTE:* *COAP_BLOCK_USE_LIBCOAP* must be set if libcoap is to do all the
190c87c5fbaSopenharmony_ciblock tracking and requesting, otherwise the application will have to do all
191c87c5fbaSopenharmony_ciof this work (the default if *coap_context_set_block_mode*() is not called).
192c87c5fbaSopenharmony_ci
193c87c5fbaSopenharmony_ciIf *COAP_BLOCK_NO_PREEMPTIVE_RTAG* is set, then Request-Tag options are only
194c87c5fbaSopenharmony_cisent when a large amount of data is being sent to the server using the Block1
195c87c5fbaSopenharmony_cioption.  Otherwise, a Request-Tag option is sent with any request (apart from
196c87c5fbaSopenharmony_ciDELETE) on the off chance that there may be multiple Block2 based
197c87c5fbaSopenharmony_ciresponses for multiple requests to the same resource that need to be
198c87c5fbaSopenharmony_cidifferentiated between.
199c87c5fbaSopenharmony_ci
200c87c5fbaSopenharmony_ci*Function: coap_add_data_large_request()*
201c87c5fbaSopenharmony_ci
202c87c5fbaSopenharmony_ciThe *coap_add_data_large_request*() function is similar to *coap_add_data*(),
203c87c5fbaSopenharmony_cibut supports the transmission of data that has a body size that is potentially
204c87c5fbaSopenharmony_cilarger than can be fitted into a single client request PDU. The specified
205c87c5fbaSopenharmony_cipayload _data_ of length _length_ is associated with the _session_ with the
206c87c5fbaSopenharmony_cifirst block of data added to the PDU _pdu_ along with the appropriate CoAP
207c87c5fbaSopenharmony_cioptions such as (Q-)Block1, Size1 and Request-Tag if the data does not fit in
208c87c5fbaSopenharmony_cia single PDU.
209c87c5fbaSopenharmony_ci
210c87c5fbaSopenharmony_ciWhen the block receipt has been acknowledged by the peer, the library
211c87c5fbaSopenharmony_ciwill then send the next block of data until all the data has been transmitted.
212c87c5fbaSopenharmony_ci
213c87c5fbaSopenharmony_ciThe _data_ passed to the
214c87c5fbaSopenharmony_cifunction *coap_add_data_large_request*() must exist until all blocks have been
215c87c5fbaSopenharmony_citransmitted. The callback function _release_func_ can be used to release
216c87c5fbaSopenharmony_cistorage that has been dynamically allocated to hold the transmit data. If not
217c87c5fbaSopenharmony_ciNULL, the callback function is called once the final block of _data_ has been
218c87c5fbaSopenharmony_citransmitted. The user-defined parameter _app_ptr_ is the same value that was
219c87c5fbaSopenharmony_cipassed to *coap_add_data_large_request*().
220c87c5fbaSopenharmony_ci
221c87c5fbaSopenharmony_ci*NOTE:* This function must only be called once per _pdu_.
222c87c5fbaSopenharmony_ci
223c87c5fbaSopenharmony_ci*NOTE:* Options cannot be added to the _pdu_ after
224c87c5fbaSopenharmony_cicoap_add_data_large_request() is called.
225c87c5fbaSopenharmony_ci
226c87c5fbaSopenharmony_ci*Function: coap_add_data_large_response()*
227c87c5fbaSopenharmony_ci
228c87c5fbaSopenharmony_ciThe *coap_add_data_large_response*() function is responsible for handling
229c87c5fbaSopenharmony_cithe server's large responses to requests. *coap_add_data_large_response*()
230c87c5fbaSopenharmony_cishould be used as a direct replacement for *coap_add_data*() if it is possible
231c87c5fbaSopenharmony_cithat the _length_ of _data_ will not fit in a single server's response pdu.
232c87c5fbaSopenharmony_ciThis function adds in the initial part of the payload _data_ of length
233c87c5fbaSopenharmony_ci_length_ to the PDU _pdu_.
234c87c5fbaSopenharmony_ci
235c87c5fbaSopenharmony_ciThe _data_ passed to the function
236c87c5fbaSopenharmony_ci*coap_add_data_large_response*() must exist until all blocks have been
237c87c5fbaSopenharmony_citransmitted. The callback function _release_func_ can be used to release
238c87c5fbaSopenharmony_cistorage that has been dynamically allocated to hold the transmit data. If not
239c87c5fbaSopenharmony_ciNULL, the callback function is called once the final block of _data_ has been
240c87c5fbaSopenharmony_citransmitted. The user-defined parameter _app_ptr_ is the same value that was
241c87c5fbaSopenharmony_cipassed to *coap_add_data_large_response*().
242c87c5fbaSopenharmony_ci
243c87c5fbaSopenharmony_ciIt also adds in the appropriate CoAP options such as Block2, Size2 and ETag to
244c87c5fbaSopenharmony_cihandle block-wise transfer if the data does not fit in a single PDU.
245c87c5fbaSopenharmony_ci
246c87c5fbaSopenharmony_ci_resource_, _query_, _session_, _request_, and _response_ are the same
247c87c5fbaSopenharmony_ciparameters as in the called resource handler that invokes
248c87c5fbaSopenharmony_ci*coap_add_data_large_response*(). If _etag_ is 0, then a unique ETag value will
249c87c5fbaSopenharmony_cibe generated, else is the ETag value to use.
250c87c5fbaSopenharmony_ciThe _media_type_ is for the format of the _data_ and _maxage_ defines the
251c87c5fbaSopenharmony_cilifetime of the response.  If _maxage_ is set to -1,  then the Max-Age option
252c87c5fbaSopenharmony_cidoes not get included (which indicates the default value of 60 seconds
253c87c5fbaSopenharmony_ciaccording to
254c87c5fbaSopenharmony_ci"https://rfc-editor.org/rfc/rfc7252#section-5.6.1[RFC7252 5.6.1. Freshness
255c87c5fbaSopenharmony_ciModel]").
256c87c5fbaSopenharmony_ci
257c87c5fbaSopenharmony_ciThe application request handler for the resource is only called once instead of
258c87c5fbaSopenharmony_cipotentially multiple times.
259c87c5fbaSopenharmony_ci
260c87c5fbaSopenharmony_ci*NOTE:* This function must only be called once per _pdu_.
261c87c5fbaSopenharmony_ci
262c87c5fbaSopenharmony_ci*NOTE:* Options cannot be added to the _pdu_ after
263c87c5fbaSopenharmony_cicoap_add_data_large_request() is called.
264c87c5fbaSopenharmony_ci
265c87c5fbaSopenharmony_ci*Function: coap_get_data_large()*
266c87c5fbaSopenharmony_ci
267c87c5fbaSopenharmony_ciThe *coap_get_data_large*() function is used abstract from the _pdu_
268c87c5fbaSopenharmony_ciinformation about the received data by updating _length_ with the length of
269c87c5fbaSopenharmony_cidata available, _data_ with a pointer to where the data is located, _offset_
270c87c5fbaSopenharmony_ciwith where this block of data starts and _total_ with the total amount of data.
271c87c5fbaSopenharmony_ci_offset_ will always be zero if block_mode includes COAP_BLOCK_SINGLE_BODY.
272c87c5fbaSopenharmony_ciAll of the body's data has been received if "_offset_ + _length_ == _total_".
273c87c5fbaSopenharmony_ci
274c87c5fbaSopenharmony_ci*NOTE:* _total_ is potentially only an indication of the total size of the
275c87c5fbaSopenharmony_cibody and is only exact when all of the data has been received.
276c87c5fbaSopenharmony_ci
277c87c5fbaSopenharmony_ci*Function: coap_block_build_body()*
278c87c5fbaSopenharmony_ci
279c87c5fbaSopenharmony_ciThe *coap_block_build_body*() function is used to re-assemble the received
280c87c5fbaSopenharmony_cidata as returned by *coap_get_data_large*() into a single blob of data. Data
281c87c5fbaSopenharmony_cifrom _data_ of length _length_ starting from offset _offset_ is added to
282c87c5fbaSopenharmony_ci_body_data_.  The resultant state of _body_data_ is returned. If _body_data_
283c87c5fbaSopenharmony_ciis NULL, or _total_ is larger than the current size of _body_data_, then
284c87c5fbaSopenharmony_ci_body_data_ is re-allocated and returned.  If there is an error, _body_data_
285c87c5fbaSopenharmony_cigets de-allocated.
286c87c5fbaSopenharmony_ci
287c87c5fbaSopenharmony_ciIf _block_mode_ (as set by *coap_context_set_block_mode*()) includes
288c87c5fbaSopenharmony_ciCOAP_BLOCK_SINGLE_BODY, then the request/response handler will only get called
289c87c5fbaSopenharmony_cionce with the entire body containing the data from all of the individual
290c87c5fbaSopenharmony_ciblocks. If there is a change of data during the blocks receipt (e.g., ETag
291c87c5fbaSopenharmony_civalue changes), then the entire set of data is re-requested and the partial
292c87c5fbaSopenharmony_cibody dropped.
293c87c5fbaSopenharmony_ci
294c87c5fbaSopenharmony_ci*Function: coap_q_block_is_supported()*
295c87c5fbaSopenharmony_ci
296c87c5fbaSopenharmony_ciThe *coap_q_block_is_supported*() function is used to determine whether
297c87c5fbaSopenharmony_cilibcoap has been build with Q-Block support or not.
298c87c5fbaSopenharmony_ci
299c87c5fbaSopenharmony_ciRETURN VALUES
300c87c5fbaSopenharmony_ci-------------
301c87c5fbaSopenharmony_ci*coap_add_data_large_request*(), *coap_add_data_large_response*(), and
302c87c5fbaSopenharmony_ci*coap_get_data_large*() return 0 on failure, 1 on success.
303c87c5fbaSopenharmony_ci
304c87c5fbaSopenharmony_ci*coap_block_build_body*() returns the current state of the body's data
305c87c5fbaSopenharmony_ci(which may have some missing gaps) or NULL on error.
306c87c5fbaSopenharmony_ci
307c87c5fbaSopenharmony_ci*coap_q_block_is_supported*() returns 0 on failure, 1 on success.
308c87c5fbaSopenharmony_ci
309c87c5fbaSopenharmony_ciEXAMPLES
310c87c5fbaSopenharmony_ci--------
311c87c5fbaSopenharmony_ci*Setup PDU and Transmit*
312c87c5fbaSopenharmony_ci
313c87c5fbaSopenharmony_ci[source, c]
314c87c5fbaSopenharmony_ci----
315c87c5fbaSopenharmony_ci#include <coap@LIBCOAP_API_VERSION@/coap.h>
316c87c5fbaSopenharmony_ci
317c87c5fbaSopenharmony_cistatic int
318c87c5fbaSopenharmony_cibuild_send_pdu(coap_context_t *context, coap_session_t *session,
319c87c5fbaSopenharmony_ciuint8_t msgtype, uint8_t request_code, const char *uri, const char *query,
320c87c5fbaSopenharmony_ciunsigned char *data, size_t length, int observe) {
321c87c5fbaSopenharmony_ci
322c87c5fbaSopenharmony_ci  coap_pdu_t *pdu;
323c87c5fbaSopenharmony_ci  uint8_t buf[1024];
324c87c5fbaSopenharmony_ci  size_t buflen;
325c87c5fbaSopenharmony_ci  uint8_t *sbuf = buf;
326c87c5fbaSopenharmony_ci  int res;
327c87c5fbaSopenharmony_ci  coap_optlist_t *optlist_chain = NULL;
328c87c5fbaSopenharmony_ci  /* Remove (void) definition if variable is used */
329c87c5fbaSopenharmony_ci  (void)context;
330c87c5fbaSopenharmony_ci
331c87c5fbaSopenharmony_ci  /* Create the pdu with the appropriate options */
332c87c5fbaSopenharmony_ci  pdu = coap_pdu_init(msgtype, request_code, coap_new_message_id(session),
333c87c5fbaSopenharmony_ci                      coap_session_max_pdu_size(session));
334c87c5fbaSopenharmony_ci  if (!pdu)
335c87c5fbaSopenharmony_ci    return 0;
336c87c5fbaSopenharmony_ci
337c87c5fbaSopenharmony_ci  /*
338c87c5fbaSopenharmony_ci   * Create unique token for this request for handling unsolicited /
339c87c5fbaSopenharmony_ci   * delayed responses
340c87c5fbaSopenharmony_ci   */
341c87c5fbaSopenharmony_ci  coap_session_new_token(session, &buflen, buf);
342c87c5fbaSopenharmony_ci  if (!coap_add_token(pdu, buflen, buf)) {
343c87c5fbaSopenharmony_ci    coap_log_debug("cannot add token to request\n");
344c87c5fbaSopenharmony_ci    goto error;
345c87c5fbaSopenharmony_ci  }
346c87c5fbaSopenharmony_ci
347c87c5fbaSopenharmony_ci  if (uri) {
348c87c5fbaSopenharmony_ci    /* Add in the URI options */
349c87c5fbaSopenharmony_ci    buflen = sizeof(buf);
350c87c5fbaSopenharmony_ci    res = coap_split_path((const uint8_t*)uri, strlen(uri), sbuf, &buflen);
351c87c5fbaSopenharmony_ci    while (res--) {
352c87c5fbaSopenharmony_ci      if (!coap_insert_optlist(&optlist_chain,
353c87c5fbaSopenharmony_ci                               coap_new_optlist(COAP_OPTION_URI_PATH,
354c87c5fbaSopenharmony_ci                        coap_opt_length(sbuf), coap_opt_value(sbuf))))
355c87c5fbaSopenharmony_ci        goto error;
356c87c5fbaSopenharmony_ci      sbuf += coap_opt_size(sbuf);
357c87c5fbaSopenharmony_ci    }
358c87c5fbaSopenharmony_ci  }
359c87c5fbaSopenharmony_ci
360c87c5fbaSopenharmony_ci  if (query) {
361c87c5fbaSopenharmony_ci    /* Add in the QUERY options */
362c87c5fbaSopenharmony_ci    buflen = sizeof(buf);
363c87c5fbaSopenharmony_ci    res = coap_split_query((const uint8_t*)query, strlen(query), sbuf, &buflen);
364c87c5fbaSopenharmony_ci    while (res--) {
365c87c5fbaSopenharmony_ci      if (!coap_insert_optlist(&optlist_chain,
366c87c5fbaSopenharmony_ci                               coap_new_optlist(COAP_OPTION_URI_QUERY,
367c87c5fbaSopenharmony_ci                        coap_opt_length(sbuf), coap_opt_value(sbuf))))
368c87c5fbaSopenharmony_ci        goto error;
369c87c5fbaSopenharmony_ci      sbuf += coap_opt_size(sbuf);
370c87c5fbaSopenharmony_ci    }
371c87c5fbaSopenharmony_ci  }
372c87c5fbaSopenharmony_ci
373c87c5fbaSopenharmony_ci  if (request_code == COAP_REQUEST_GET && observe) {
374c87c5fbaSopenharmony_ci    /* Indicate that we want to observe this resource */
375c87c5fbaSopenharmony_ci    if (!coap_insert_optlist(&optlist_chain,
376c87c5fbaSopenharmony_ci                             coap_new_optlist(COAP_OPTION_OBSERVE,
377c87c5fbaSopenharmony_ci                               coap_encode_var_safe(buf, sizeof(buf),
378c87c5fbaSopenharmony_ci                               COAP_OBSERVE_ESTABLISH), buf)
379c87c5fbaSopenharmony_ci                             ))
380c87c5fbaSopenharmony_ci      goto error;
381c87c5fbaSopenharmony_ci  }
382c87c5fbaSopenharmony_ci
383c87c5fbaSopenharmony_ci  /* ... Other code / options etc. ... */
384c87c5fbaSopenharmony_ci
385c87c5fbaSopenharmony_ci  /* Add in all the options (after internal sorting) to the pdu */
386c87c5fbaSopenharmony_ci  if (!coap_add_optlist_pdu(pdu, &optlist_chain))
387c87c5fbaSopenharmony_ci    goto error;
388c87c5fbaSopenharmony_ci
389c87c5fbaSopenharmony_ci  if (data && length) {
390c87c5fbaSopenharmony_ci    /* Add in the specified data */
391c87c5fbaSopenharmony_ci    if (!coap_add_data_large_request(session, pdu, length, data, NULL, NULL))
392c87c5fbaSopenharmony_ci      goto error;
393c87c5fbaSopenharmony_ci  }
394c87c5fbaSopenharmony_ci
395c87c5fbaSopenharmony_ci  if (coap_send(session, pdu) == COAP_INVALID_MID)
396c87c5fbaSopenharmony_ci    goto error;
397c87c5fbaSopenharmony_ci  return 1;
398c87c5fbaSopenharmony_ci
399c87c5fbaSopenharmony_cierror:
400c87c5fbaSopenharmony_ci
401c87c5fbaSopenharmony_ci  if (pdu)
402c87c5fbaSopenharmony_ci    coap_delete_pdu(pdu);
403c87c5fbaSopenharmony_ci  return 0;
404c87c5fbaSopenharmony_ci
405c87c5fbaSopenharmony_ci}
406c87c5fbaSopenharmony_ci
407c87c5fbaSopenharmony_ciint
408c87c5fbaSopenharmony_cimain(int argc, char *argv[]) {
409c87c5fbaSopenharmony_ci  coap_context_t *context = NULL;
410c87c5fbaSopenharmony_ci  coap_session_t *session = NULL;
411c87c5fbaSopenharmony_ci  unsigned char *data = NULL;
412c87c5fbaSopenharmony_ci  size_t data_length = 0;
413c87c5fbaSopenharmony_ci
414c87c5fbaSopenharmony_ci  (void)argc;
415c87c5fbaSopenharmony_ci  (void)argv;
416c87c5fbaSopenharmony_ci
417c87c5fbaSopenharmony_ci  /* Initialize libcoap library */
418c87c5fbaSopenharmony_ci  coap_startup();
419c87c5fbaSopenharmony_ci
420c87c5fbaSopenharmony_ci  /* ... Set up context, session etc. ... */
421c87c5fbaSopenharmony_ci
422c87c5fbaSopenharmony_ci  /* Set up using libcoap to do the block work */
423c87c5fbaSopenharmony_ci  coap_context_set_block_mode(context,
424c87c5fbaSopenharmony_ci                              COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
425c87c5fbaSopenharmony_ci
426c87c5fbaSopenharmony_ci  /* ... Other code etc. ... */
427c87c5fbaSopenharmony_ci
428c87c5fbaSopenharmony_ci  /* .. build data and define data_length ... */
429c87c5fbaSopenharmony_ci
430c87c5fbaSopenharmony_ci  build_send_pdu(context, session, COAP_MESSAGE_CON, COAP_REQUEST_PUT,
431c87c5fbaSopenharmony_ci                 "/example/uri", NULL, data, data_length, 0);
432c87c5fbaSopenharmony_ci
433c87c5fbaSopenharmony_ci  /* ... Other code etc. ... */
434c87c5fbaSopenharmony_ci
435c87c5fbaSopenharmony_ci  coap_cleanup();
436c87c5fbaSopenharmony_ci  return 0;
437c87c5fbaSopenharmony_ci}
438c87c5fbaSopenharmony_ci----
439c87c5fbaSopenharmony_ci
440c87c5fbaSopenharmony_ci*Resource Request Handler Response PDU Update*
441c87c5fbaSopenharmony_ci
442c87c5fbaSopenharmony_ci[source, c]
443c87c5fbaSopenharmony_ci----
444c87c5fbaSopenharmony_ci#include <coap@LIBCOAP_API_VERSION@/coap.h>
445c87c5fbaSopenharmony_ci
446c87c5fbaSopenharmony_ci#include <stdio.h>
447c87c5fbaSopenharmony_ci
448c87c5fbaSopenharmony_cistatic void
449c87c5fbaSopenharmony_cihnd_get_time(coap_resource_t *resource, coap_session_t *session,
450c87c5fbaSopenharmony_ciconst coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) {
451c87c5fbaSopenharmony_ci
452c87c5fbaSopenharmony_ci  unsigned char buf[40];
453c87c5fbaSopenharmony_ci  size_t len;
454c87c5fbaSopenharmony_ci  time_t now;
455c87c5fbaSopenharmony_ci
456c87c5fbaSopenharmony_ci  /* ... Additional analysis code for resource, request pdu etc.  ... */
457c87c5fbaSopenharmony_ci
458c87c5fbaSopenharmony_ci  /* After analysis, generate a failure response and return if needed */
459c87c5fbaSopenharmony_ci
460c87c5fbaSopenharmony_ci  now = time(NULL);
461c87c5fbaSopenharmony_ci
462c87c5fbaSopenharmony_ci  if (query != NULL && coap_string_equal(query, coap_make_str_const("secs"))) {
463c87c5fbaSopenharmony_ci    /* Output secs since Jan 1 1970 */
464c87c5fbaSopenharmony_ci    len = snprintf((char *)buf, sizeof(buf), "%lu", now);
465c87c5fbaSopenharmony_ci  }
466c87c5fbaSopenharmony_ci  else {
467c87c5fbaSopenharmony_ci    /* Output human-readable time */
468c87c5fbaSopenharmony_ci    struct tm *tmp;
469c87c5fbaSopenharmony_ci    tmp = gmtime(&now);
470c87c5fbaSopenharmony_ci    if (!tmp) {
471c87c5fbaSopenharmony_ci      /* If 'now' is not valid */
472c87c5fbaSopenharmony_ci      coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND);
473c87c5fbaSopenharmony_ci      return;
474c87c5fbaSopenharmony_ci    }
475c87c5fbaSopenharmony_ci    len = strftime((char *)buf, sizeof(buf), "%b %d %H:%M:%S", tmp);
476c87c5fbaSopenharmony_ci  }
477c87c5fbaSopenharmony_ci  coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT);
478c87c5fbaSopenharmony_ci  /*
479c87c5fbaSopenharmony_ci   * Invoke coap_add_data_large_response() to do all the hard work.
480c87c5fbaSopenharmony_ci   * [A good practice, even though ins this case, the amount of data is small]
481c87c5fbaSopenharmony_ci   *
482c87c5fbaSopenharmony_ci   * Define the format - COAP_MEDIATYPE_TEXT_PLAIN - to add in
483c87c5fbaSopenharmony_ci   * Define how long this response is valid for (secs) - 1 - to add in.
484c87c5fbaSopenharmony_ci   *
485c87c5fbaSopenharmony_ci   * Observe Option added internally if needed within the function
486c87c5fbaSopenharmony_ci   * Block2 Option added internally if output too large
487c87c5fbaSopenharmony_ci   * Size2 Option added internally
488c87c5fbaSopenharmony_ci   * ETag Option added internally
489c87c5fbaSopenharmony_ci   */
490c87c5fbaSopenharmony_ci  coap_add_data_large_response(resource, session, request, response,
491c87c5fbaSopenharmony_ci                               query, COAP_MEDIATYPE_TEXT_PLAIN, 1, 0,
492c87c5fbaSopenharmony_ci                               len,
493c87c5fbaSopenharmony_ci                               buf,
494c87c5fbaSopenharmony_ci                               NULL, NULL);
495c87c5fbaSopenharmony_ci  /*
496c87c5fbaSopenharmony_ci   * When request handler returns, the response pdu will get automatically
497c87c5fbaSopenharmony_ci   * sent, unless the pdu code is not updated and this is a NON or TCP based
498c87c5fbaSopenharmony_ci   * request.
499c87c5fbaSopenharmony_ci   */
500c87c5fbaSopenharmony_ci}
501c87c5fbaSopenharmony_ci
502c87c5fbaSopenharmony_ciint
503c87c5fbaSopenharmony_cimain(int argc, char *argv[]) {
504c87c5fbaSopenharmony_ci  coap_context_t *context = NULL;
505c87c5fbaSopenharmony_ci  coap_resource_t *r;
506c87c5fbaSopenharmony_ci  coap_resource_t *time_resource;
507c87c5fbaSopenharmony_ci  int not_exit = 1;
508c87c5fbaSopenharmony_ci
509c87c5fbaSopenharmony_ci  /* Initialize libcoap library */
510c87c5fbaSopenharmony_ci  coap_startup();
511c87c5fbaSopenharmony_ci
512c87c5fbaSopenharmony_ci  (void)argc;
513c87c5fbaSopenharmony_ci  (void)argv;
514c87c5fbaSopenharmony_ci
515c87c5fbaSopenharmony_ci  /* ... Set up context etc. ... */
516c87c5fbaSopenharmony_ci
517c87c5fbaSopenharmony_ci  /* Set up using libcoap to do the block work */
518c87c5fbaSopenharmony_ci  coap_context_set_block_mode(context,
519c87c5fbaSopenharmony_ci                              COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
520c87c5fbaSopenharmony_ci
521c87c5fbaSopenharmony_ci  /* Create a resource to return time */
522c87c5fbaSopenharmony_ci  r = coap_resource_init(coap_make_str_const("time"),
523c87c5fbaSopenharmony_ci                         COAP_RESOURCE_FLAGS_NOTIFY_CON);
524c87c5fbaSopenharmony_ci  coap_resource_set_get_observable(r, 1);
525c87c5fbaSopenharmony_ci  coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_time);
526c87c5fbaSopenharmony_ci
527c87c5fbaSopenharmony_ci  /* Document resource for 'time' request */
528c87c5fbaSopenharmony_ci  coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0);
529c87c5fbaSopenharmony_ci  coap_add_attr(r, coap_make_str_const("title"),
530c87c5fbaSopenharmony_ci                coap_make_str_const("\"Internal Clock\""), 0);
531c87c5fbaSopenharmony_ci  coap_add_attr(r, coap_make_str_const("rt"), coap_make_str_const("\"secs\""),
532c87c5fbaSopenharmony_ci                0);
533c87c5fbaSopenharmony_ci  coap_add_attr(r, coap_make_str_const("if"), coap_make_str_const("\"clock\""),
534c87c5fbaSopenharmony_ci                0);
535c87c5fbaSopenharmony_ci
536c87c5fbaSopenharmony_ci  coap_add_resource(context, r);
537c87c5fbaSopenharmony_ci  time_resource = r;
538c87c5fbaSopenharmony_ci
539c87c5fbaSopenharmony_ci  /* ... Loop waiting for incoming traffic ... */
540c87c5fbaSopenharmony_ci  while (!not_exit) {
541c87c5fbaSopenharmony_ci    coap_io_process(context, 1000);
542c87c5fbaSopenharmony_ci
543c87c5fbaSopenharmony_ci    /* Cause a notification to anyone Observing 'time' */
544c87c5fbaSopenharmony_ci    coap_resource_notify_observers(time_resource, NULL);
545c87c5fbaSopenharmony_ci  }
546c87c5fbaSopenharmony_ci
547c87c5fbaSopenharmony_ci  /* Clean up */
548c87c5fbaSopenharmony_ci
549c87c5fbaSopenharmony_ci  coap_free_context(context);
550c87c5fbaSopenharmony_ci  coap_cleanup();
551c87c5fbaSopenharmony_ci
552c87c5fbaSopenharmony_ci}
553c87c5fbaSopenharmony_ci----
554c87c5fbaSopenharmony_ci
555c87c5fbaSopenharmony_ciSEE ALSO
556c87c5fbaSopenharmony_ci--------
557c87c5fbaSopenharmony_ci*coap_init*(3) *coap_pdu_setup*(3), *coap_observe*(3), and *coap_resource*(3)
558c87c5fbaSopenharmony_ci
559c87c5fbaSopenharmony_ciFURTHER INFORMATION
560c87c5fbaSopenharmony_ci-------------------
561c87c5fbaSopenharmony_ciSee
562c87c5fbaSopenharmony_ci
563c87c5fbaSopenharmony_ci"https://rfc-editor.org/rfc/rfc7252[RFC7252: The Constrained Application Protocol (CoAP)]"
564c87c5fbaSopenharmony_ci
565c87c5fbaSopenharmony_ci"https://rfc-editor.org/rfc/rfc7959[RFC7959: Block-Wise Transfers in the Constrained Application Protocol (CoAP)]"
566c87c5fbaSopenharmony_ci
567c87c5fbaSopenharmony_cifor further information.
568c87c5fbaSopenharmony_ci
569c87c5fbaSopenharmony_ciBUGS
570c87c5fbaSopenharmony_ci----
571c87c5fbaSopenharmony_ciPlease report bugs on the mailing list for libcoap:
572c87c5fbaSopenharmony_cilibcoap-developers@lists.sourceforge.net or raise an issue on GitHub at
573c87c5fbaSopenharmony_cihttps://github.com/obgm/libcoap/issues
574c87c5fbaSopenharmony_ci
575c87c5fbaSopenharmony_ciAUTHORS
576c87c5fbaSopenharmony_ci-------
577c87c5fbaSopenharmony_ciThe libcoap project <libcoap-developers@lists.sourceforge.net>
578