1c87c5fbaSopenharmony_ci// -*- mode:doc; -*-
2c87c5fbaSopenharmony_ci// vim: set syntax=asciidoc tw=0
3c87c5fbaSopenharmony_ci
4c87c5fbaSopenharmony_cicoap_cache(3)
5c87c5fbaSopenharmony_ci=============
6c87c5fbaSopenharmony_ci:doctype: manpage
7c87c5fbaSopenharmony_ci:man source:   coap_cache
8c87c5fbaSopenharmony_ci:man version:  @PACKAGE_VERSION@
9c87c5fbaSopenharmony_ci:man manual:   libcoap Manual
10c87c5fbaSopenharmony_ci
11c87c5fbaSopenharmony_ciNAME
12c87c5fbaSopenharmony_ci----
13c87c5fbaSopenharmony_cicoap_cache,
14c87c5fbaSopenharmony_cicoap_cache_derive_key,
15c87c5fbaSopenharmony_cicoap_cache_derive_key_w_ignore,
16c87c5fbaSopenharmony_cicoap_delete_cache_key,
17c87c5fbaSopenharmony_cicoap_cache_ignore_options,
18c87c5fbaSopenharmony_cicoap_new_cache_entry,
19c87c5fbaSopenharmony_cicoap_delete_cache_entry,
20c87c5fbaSopenharmony_cicoap_cache_get_by_key,
21c87c5fbaSopenharmony_cicoap_cache_get_by_pdu,
22c87c5fbaSopenharmony_cicoap_cache_get_pdu,
23c87c5fbaSopenharmony_cicoap_cache_set_app_data,
24c87c5fbaSopenharmony_cicoap_cache_get_app_data
25c87c5fbaSopenharmony_ci- Work with CoAP cache functions
26c87c5fbaSopenharmony_ci
27c87c5fbaSopenharmony_ciSYNOPSIS
28c87c5fbaSopenharmony_ci--------
29c87c5fbaSopenharmony_ci*#include <coap@LIBCOAP_API_VERSION@/coap.h>*
30c87c5fbaSopenharmony_ci
31c87c5fbaSopenharmony_ci*coap_cache_key_t *coap_cache_derive_key(const coap_session_t *_session_,
32c87c5fbaSopenharmony_ciconst coap_pdu_t *_pdu_, coap_cache_session_based_t _session_based_);*
33c87c5fbaSopenharmony_ci
34c87c5fbaSopenharmony_ci*coap_cache_key_t *coap_cache_derive_key_w_ignore(
35c87c5fbaSopenharmony_ciconst coap_session_t *_session_, const coap_pdu_t *_pdu_,
36c87c5fbaSopenharmony_cicoap_cache_session_based_t _session_based_,
37c87c5fbaSopenharmony_ciconst uint16_t *_ignore_options_, size_t _ignore_count_);*
38c87c5fbaSopenharmony_ci
39c87c5fbaSopenharmony_ci*void coap_delete_cache_key(coap_cache_key_t *_cache_key_);*
40c87c5fbaSopenharmony_ci
41c87c5fbaSopenharmony_ci*int coap_cache_ignore_options(coap_context_t *_context_,
42c87c5fbaSopenharmony_ciconst uint16_t *_options_, size_t _count_);*
43c87c5fbaSopenharmony_ci
44c87c5fbaSopenharmony_ci*coap_cache_entry_t *coap_new_cache_entry(coap_session_t *_session_,
45c87c5fbaSopenharmony_ciconst coap_pdu_t *_pdu_, coap_cache_record_pdu_t _record_pdu_,
46c87c5fbaSopenharmony_cicoap_cache_session_based_t _session_based_, unsigned int _idle_timeout_);*
47c87c5fbaSopenharmony_ci
48c87c5fbaSopenharmony_ci*void coap_delete_cache_entry(coap_context_t *_context_,
49c87c5fbaSopenharmony_cicoap_cache_entry_t *_cache_entry_);*
50c87c5fbaSopenharmony_ci
51c87c5fbaSopenharmony_ci*coap_cache_entry_t *coap_cache_get_by_key(coap_context_t *_context_,
52c87c5fbaSopenharmony_ciconst coap_cache_key_t *_cache_key_);*
53c87c5fbaSopenharmony_ci
54c87c5fbaSopenharmony_ci*coap_cache_entry_t *coap_cache_get_by_pdu(coap_session_t *_session_,
55c87c5fbaSopenharmony_ciconst coap_pdu_t *_pdu_, coap_cache_session_based_t _session_based_);*
56c87c5fbaSopenharmony_ci
57c87c5fbaSopenharmony_ci*const coap_pdu_t *coap_cache_get_pdu(const coap_cache_entry_t *_cache_entry_);*
58c87c5fbaSopenharmony_ci
59c87c5fbaSopenharmony_ci*void coap_cache_set_app_data(coap_cache_entry_t *_cache_entry_, void *_data_,
60c87c5fbaSopenharmony_cicoap_cache_app_data_free_callback_t _callback_);*
61c87c5fbaSopenharmony_ci
62c87c5fbaSopenharmony_ci*void *coap_cache_get_app_data(const coap_cache_entry_t *_cache_entry_);*
63c87c5fbaSopenharmony_ci
64c87c5fbaSopenharmony_ciFor specific (D)TLS library support, link with
65c87c5fbaSopenharmony_ci*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*,
66c87c5fbaSopenharmony_ci*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls*
67c87c5fbaSopenharmony_cior *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*.   Otherwise, link with
68c87c5fbaSopenharmony_ci*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support.
69c87c5fbaSopenharmony_ci
70c87c5fbaSopenharmony_ciDESCRIPTION
71c87c5fbaSopenharmony_ci-----------
72c87c5fbaSopenharmony_ci
73c87c5fbaSopenharmony_ciThe CoAP Cache provides support for two opaque objects that can be used for
74c87c5fbaSopenharmony_citracking requests and responses.
75c87c5fbaSopenharmony_ci
76c87c5fbaSopenharmony_ciThe first is the ability to derive a Cache Key from the cacheable parts of a
77c87c5fbaSopenharmony_ciCoAP PDU as defined in
78c87c5fbaSopenharmony_ci"https://rfc-editor.org/rfc/rfc7252#section-5.6[RFC7252 5.6. Caching]"
79c87c5fbaSopenharmony_ciupdated by
80c87c5fbaSopenharmony_ci"https://rfc-editor.org/rfc/rfc7641#section-2[RFC7641 2. The Observe Option]"
81c87c5fbaSopenharmony_ciand
82c87c5fbaSopenharmony_ci"https://rfc-editor.org/rfc/rfc8132#section-2[RFC8132 2. Fetch Method]".
83c87c5fbaSopenharmony_ci
84c87c5fbaSopenharmony_ciThe Cache Key is a SHA256 digest if libcoap was built with TLS support,
85c87c5fbaSopenharmony_ciotherwise it uses the internal coap_hash() function, using the information
86c87c5fbaSopenharmony_ciabstracted from the PDU and (optionally) the CoAP session.
87c87c5fbaSopenharmony_ci
88c87c5fbaSopenharmony_ciThis Cache Key can then be used to match against incoming PDUs and then
89c87c5fbaSopenharmony_ciappropriate action logic can take place.
90c87c5fbaSopenharmony_ci
91c87c5fbaSopenharmony_ciThere is support for excluding specific CoAP options from the Cache Key.
92c87c5fbaSopenharmony_ciExamples could be to exclude CoAP BLOCK1 and BLOCK2 Options for the client or
93c87c5fbaSopenharmony_ciserver for ease of tracking a large PUT or GET response, but to not exclude
94c87c5fbaSopenharmony_cithese CoAP options in a proxy where it makes sense to cache the individual
95c87c5fbaSopenharmony_ciblocks.
96c87c5fbaSopenharmony_ci
97c87c5fbaSopenharmony_ciThe second is providing Cache Entries (which can be looked up by PDU and hence
98c87c5fbaSopenharmony_ciby Cache Key) which hold additional information to make information tracking
99c87c5fbaSopenharmony_cisimpler.  These Cache Entries are automatically deleted when a session closes
100c87c5fbaSopenharmony_cior a context is deleted. These Cache Entries are maintained on a hashed list
101c87c5fbaSopenharmony_cifor speed of lookup.
102c87c5fbaSopenharmony_ci
103c87c5fbaSopenharmony_ciThe following enums are defined.
104c87c5fbaSopenharmony_ci
105c87c5fbaSopenharmony_ci[source, c]
106c87c5fbaSopenharmony_ci----
107c87c5fbaSopenharmony_citypedef enum coap_cache_session_based_t {
108c87c5fbaSopenharmony_ci  COAP_CACHE_NOT_SESSION_BASED,
109c87c5fbaSopenharmony_ci  COAP_CACHE_IS_SESSION_BASED
110c87c5fbaSopenharmony_ci} coap_cache_session_based_t;
111c87c5fbaSopenharmony_ci
112c87c5fbaSopenharmony_citypedef enum coap_cache_record_pdu_t {
113c87c5fbaSopenharmony_ci  COAP_CACHE_NOT_RECORD_PDU,
114c87c5fbaSopenharmony_ci  COAP_CACHE_RECORD_PDU
115c87c5fbaSopenharmony_ci} coap_cache_record_pdu_t;
116c87c5fbaSopenharmony_ci----
117c87c5fbaSopenharmony_ci
118c87c5fbaSopenharmony_ciFUNCTIONS
119c87c5fbaSopenharmony_ci---------
120c87c5fbaSopenharmony_ci
121c87c5fbaSopenharmony_ci*Function: coap_cache_derive_key()*
122c87c5fbaSopenharmony_ci
123c87c5fbaSopenharmony_ciThe *coap_cache_derive_key*() function abstracts all the non NoCacheKey CoAP
124c87c5fbaSopenharmony_cioptions, ignores the CoAP Observe option and includes a FETCH body from _pdu_.
125c87c5fbaSopenharmony_ciIf _session_based_ is COAP_CACHE_IS_SESSION_BASED, then _session_ pointer is
126c87c5fbaSopenharmony_cialso included. CoAP options can be specifically ignored by the use of
127c87c5fbaSopenharmony_ci*coap_cache_ignore_options*().  A digest is then built from all of the
128c87c5fbaSopenharmony_ciinformation and returned. NULL is returned on error.
129c87c5fbaSopenharmony_ci
130c87c5fbaSopenharmony_ci*Function: coap_cache_derive_key_w_ignore()*
131c87c5fbaSopenharmony_ci
132c87c5fbaSopenharmony_ciThe *coap_cache_derive_key_w_ignore*() function abstracts all the non
133c87c5fbaSopenharmony_ciNoCacheKey CoAP options, ignores the CoAP Observe option and includes a FETCH
134c87c5fbaSopenharmony_cibody from _pdu_. Further options to ignore are specified by the _ignore_count_
135c87c5fbaSopenharmony_ciof _ignore_options_.  If _session_based_ is COAP_CACHE_IS_SESSION_BASED, then
136c87c5fbaSopenharmony_ci_session_ pointer is also included. A digest is then built from all of the
137c87c5fbaSopenharmony_ciinformation and returned. NULL is returned on error.
138c87c5fbaSopenharmony_ci
139c87c5fbaSopenharmony_ci*Function: coap_delete_cache_key()*
140c87c5fbaSopenharmony_ci
141c87c5fbaSopenharmony_ciThe *coap_delete_cache_key*() function deletes the _cache_key_ that was
142c87c5fbaSopenharmony_cireturned from a *coap_cache_derive_key*() or
143c87c5fbaSopenharmony_ci*coap_cache_derive_key_w_ignore*() call.
144c87c5fbaSopenharmony_ci
145c87c5fbaSopenharmony_ci*Function: coap_cache_ignore_options()*
146c87c5fbaSopenharmony_ci
147c87c5fbaSopenharmony_ciThe *coap_cache_ignore_options*() function is used to store in _context_ a
148c87c5fbaSopenharmony_cilist of _count_ options held in _options_.  The specified _options_ will not
149c87c5fbaSopenharmony_cibe included in the data used for the *coap_cache_derive_key*() function.
150c87c5fbaSopenharmony_ci
151c87c5fbaSopenharmony_ci*Function: coap_new_cache_entry()*
152c87c5fbaSopenharmony_ci
153c87c5fbaSopenharmony_ciThe *coap_new_cache_entry*() function will create a new Cache Entry based on
154c87c5fbaSopenharmony_cithe Cache Key derived from the _pdu_, _session_based_ and _session_. If
155c87c5fbaSopenharmony_ci_record_pdu_ is COAP_CACHE_RECORD_PDU, then a copy of the _pdu_ is stored in
156c87c5fbaSopenharmony_cithe Cache Entry for subsequent retrieval. The Cache Entry can also store
157c87c5fbaSopenharmony_ciapplication specific data (*coap_cache_set_app_data*() and
158c87c5fbaSopenharmony_ci*coap_cache_get_app_data*()).  _idle_timeout_ in seconds defines the length of
159c87c5fbaSopenharmony_citime not being used before it gets deleted.  If _idle_timeout_ is set to
160c87c5fbaSopenharmony_ci0, then the Cache Entry will not get idle expired. The created Cache
161c87c5fbaSopenharmony_ciEntry is returned, or NULL on error.
162c87c5fbaSopenharmony_ci
163c87c5fbaSopenharmony_ci*Function: coap_delete_cache_entry()*
164c87c5fbaSopenharmony_ci
165c87c5fbaSopenharmony_ciThe *coap_delete_cache_entry*() function can be used to delete the Cache Entry
166c87c5fbaSopenharmony_ci_cache_entry_ held within _context_.  This will remove the Cache Entry from
167c87c5fbaSopenharmony_cithe hash lookup list and
168c87c5fbaSopenharmony_cifree off any internally held data.  If the Cache Entry is session based, then
169c87c5fbaSopenharmony_ciit will automatically get deleted when the session is freed off or when the
170c87c5fbaSopenharmony_ciidle timeout expires.
171c87c5fbaSopenharmony_ci
172c87c5fbaSopenharmony_ci*Function: coap_cache_get_by_key()*
173c87c5fbaSopenharmony_ci
174c87c5fbaSopenharmony_ciThe *coap_cache_get_by_key*() function will locate the Cache Entry held in the
175c87c5fbaSopenharmony_ci_context_ environment that has Cache Key _cache_key_.  Returns NULL if the
176c87c5fbaSopenharmony_ciCache Key was not found.
177c87c5fbaSopenharmony_ci
178c87c5fbaSopenharmony_ci*Function: coap_cache_get_by_pdu()*
179c87c5fbaSopenharmony_ci
180c87c5fbaSopenharmony_ciThe *coap_cache_get_by_pdu*() function will locate the Cache Entry held in the
181c87c5fbaSopenharmony_ci_session_ environment that has a Cache Key derived from the _pdu_ and
182c87c5fbaSopenharmony_ciwhether _session_based_ or not. This function calls *coap_cache_derive_key*()
183c87c5fbaSopenharmony_ciinternally, and so normally *coap_cache_ignore_options*() would have
184c87c5fbaSopenharmony_cipreviously been called with COAP_OPTION_BLOCK1 or COAP_OPTION_BLOCK2 to
185c87c5fbaSopenharmony_ciignore the values held within these options.
186c87c5fbaSopenharmony_ci
187c87c5fbaSopenharmony_ci*Function: coap_cache_get_pdu()*
188c87c5fbaSopenharmony_ci
189c87c5fbaSopenharmony_ciThe *coap_cache_get_pdu*() function returns the PDU that was stored with the
190c87c5fbaSopenharmony_ciCache Entry when it was created with *coap_new_cache_entry*() and _record_pdu_
191c87c5fbaSopenharmony_ciwas set to COAP_CACHE_RECORD_PDU.  If a PDU was not initially stored, NULL is
192c87c5fbaSopenharmony_cireturned. +
193c87c5fbaSopenharmony_ci*NOTE:* A copy of the returned PDU must be taken for use in sending a CoAP
194c87c5fbaSopenharmony_cipacket using *coap_pdu_duplicate*().
195c87c5fbaSopenharmony_ci
196c87c5fbaSopenharmony_ci*Function: coap_cache_set_app_data()*
197c87c5fbaSopenharmony_ci
198c87c5fbaSopenharmony_ciThe *coap_cache_set_app_data*() function is used to associate _data_ with the
199c87c5fbaSopenharmony_ci_cache_entry_.  If _callback_ is not NULL, it points to a function to free off
200c87c5fbaSopenharmony_ci_data_ when the _cache_entry_ is deleted.  If any data has been previously
201c87c5fbaSopenharmony_cistored in the _cache_entry_, the pointer to the old data will get overwritten,
202c87c5fbaSopenharmony_cibut the old data will not get freed off.
203c87c5fbaSopenharmony_ci
204c87c5fbaSopenharmony_ciThe _callback_ handler function prototype is defined as:
205c87c5fbaSopenharmony_ci[source, c]
206c87c5fbaSopenharmony_ci----
207c87c5fbaSopenharmony_citypedef void (*coap_cache_app_data_free_callback_t)(void *data);
208c87c5fbaSopenharmony_ci----
209c87c5fbaSopenharmony_ciwhere _data_ is passed into the callback function whenever the Cache Entry is
210c87c5fbaSopenharmony_cideleted.
211c87c5fbaSopenharmony_ci
212c87c5fbaSopenharmony_ci*Function: coap_cache_get_app_data()*
213c87c5fbaSopenharmony_ci
214c87c5fbaSopenharmony_ciThe *coap_cache_get_app_data*() function is used to get the previously stored
215c87c5fbaSopenharmony_ci_data_ in the _cache_entry_.
216c87c5fbaSopenharmony_ci
217c87c5fbaSopenharmony_ciRETURN VALUES
218c87c5fbaSopenharmony_ci-------------
219c87c5fbaSopenharmony_ci*coap_cache_derive_key*() and *coap_cache_derive_key_w_ignore*()
220c87c5fbaSopenharmony_cireturns a newly created Cache Key or NULL if there is a creation failure.
221c87c5fbaSopenharmony_ci
222c87c5fbaSopenharmony_ci*coap_cache_ignore_options*() returns 1 if success, 0 on failure.
223c87c5fbaSopenharmony_ci
224c87c5fbaSopenharmony_ci*coap_new_cache_entry*(), *coap_cache_get_by_key*() and
225c87c5fbaSopenharmony_ci*coap_cache_get_by_pdu*() return the Cache Entry or NULL if there
226c87c5fbaSopenharmony_ciis a failure.
227c87c5fbaSopenharmony_ci
228c87c5fbaSopenharmony_ci*coap_cache_get_pdu*() returns the PDU that is held within the Cache Entry or
229c87c5fbaSopenharmony_ciNULL if there is no PDU available.
230c87c5fbaSopenharmony_ci
231c87c5fbaSopenharmony_ci*coap_cache_get_app_data*() returns the application data value
232c87c5fbaSopenharmony_cipreviously set by the *coap_cache_set_app_data*() function or NULL.
233c87c5fbaSopenharmony_ci
234c87c5fbaSopenharmony_ciEXAMPLES
235c87c5fbaSopenharmony_ci--------
236c87c5fbaSopenharmony_ci*PUT Handler supporting BLOCK1*
237c87c5fbaSopenharmony_ci
238c87c5fbaSopenharmony_ci[source, c]
239c87c5fbaSopenharmony_ci----
240c87c5fbaSopenharmony_ci#include <coap@LIBCOAP_API_VERSION@/coap.h>
241c87c5fbaSopenharmony_ci
242c87c5fbaSopenharmony_cistatic coap_binary_t *example_data_ptr = NULL;
243c87c5fbaSopenharmony_cistatic int example_data_media_type = COAP_MEDIATYPE_TEXT_PLAIN;
244c87c5fbaSopenharmony_ci
245c87c5fbaSopenharmony_cistatic void
246c87c5fbaSopenharmony_cicache_free_app_data(void *data) {
247c87c5fbaSopenharmony_ci  coap_binary_t *bdata = (coap_binary_t*)data;
248c87c5fbaSopenharmony_ci  coap_delete_binary(bdata);
249c87c5fbaSopenharmony_ci}
250c87c5fbaSopenharmony_ci
251c87c5fbaSopenharmony_ci/*
252c87c5fbaSopenharmony_ci * Large Data PUT handler
253c87c5fbaSopenharmony_ci */
254c87c5fbaSopenharmony_ci
255c87c5fbaSopenharmony_cistatic void
256c87c5fbaSopenharmony_cihnd_put_example_data(coap_context_t *ctx,
257c87c5fbaSopenharmony_ci        coap_resource_t *resource,
258c87c5fbaSopenharmony_ci        coap_session_t *session,
259c87c5fbaSopenharmony_ci        coap_pdu_t *request,
260c87c5fbaSopenharmony_ci        coap_binary_t *token,
261c87c5fbaSopenharmony_ci        coap_string_t *query,
262c87c5fbaSopenharmony_ci        coap_pdu_t *response
263c87c5fbaSopenharmony_ci) {
264c87c5fbaSopenharmony_ci  size_t size;
265c87c5fbaSopenharmony_ci  const uint8_t *data;
266c87c5fbaSopenharmony_ci  coap_opt_iterator_t opt_iter;
267c87c5fbaSopenharmony_ci  coap_opt_t *option;
268c87c5fbaSopenharmony_ci  size_t offset;
269c87c5fbaSopenharmony_ci  size_t total;
270c87c5fbaSopenharmony_ci  coap_binary_t *data_so_far;
271c87c5fbaSopenharmony_ci
272c87c5fbaSopenharmony_ci  /* Remove (void) definition if variable is used */
273c87c5fbaSopenharmony_ci  (void)ctx;
274c87c5fbaSopenharmony_ci  (void)token;
275c87c5fbaSopenharmony_ci  (void)query;
276c87c5fbaSopenharmony_ci
277c87c5fbaSopenharmony_ci  if (coap_get_data_large(request, &size, &data, &offset, &total) &&
278c87c5fbaSopenharmony_ci    size != total) {
279c87c5fbaSopenharmony_ci    /*
280c87c5fbaSopenharmony_ci     * A part of the data has been received (COAP_BLOCK_SINGLE_BODY not set).
281c87c5fbaSopenharmony_ci     * However, total unfortunately is only an indication, so it is not safe to
282c87c5fbaSopenharmony_ci     * allocate a block based on total.  As per
283c87c5fbaSopenharmony_ci     * https://rfc-editor.org/rfc/rfc7959#section-4
284c87c5fbaSopenharmony_ci     *   o  In a request carrying a Block1 Option, to indicate the current
285c87c5fbaSopenharmony_ci     *         estimate the client has of the total size of the resource
286c87c5fbaSopenharmony_ci     *         representation, measured in bytes ("size indication").
287c87c5fbaSopenharmony_ci     *
288c87c5fbaSopenharmony_ci     * coap_cache_ignore_options() must have previously been called with at
289c87c5fbaSopenharmony_ci     * least COAP_OPTION_BLOCK1 set as the option value will change per block.
290c87c5fbaSopenharmony_ci     */
291c87c5fbaSopenharmony_ci    coap_cache_entry_t *cache_entry = coap_cache_get_by_pdu(session,
292c87c5fbaSopenharmony_ci                                                            request,
293c87c5fbaSopenharmony_ci                                              COAP_CACHE_IS_SESSION_BASED);
294c87c5fbaSopenharmony_ci
295c87c5fbaSopenharmony_ci    if (offset == 0) {
296c87c5fbaSopenharmony_ci      if (!cache_entry) {
297c87c5fbaSopenharmony_ci        /*
298c87c5fbaSopenharmony_ci         * Set idle_timeout parameter to COAP_MAX_TRANSMIT_WAIT if you want
299c87c5fbaSopenharmony_ci         * early removal on transmission failure. 0 means only delete when
300c87c5fbaSopenharmony_ci         * the session is deleted as session_based is set here.
301c87c5fbaSopenharmony_ci         */
302c87c5fbaSopenharmony_ci        cache_entry = coap_new_cache_entry(session, request,
303c87c5fbaSopenharmony_ci                                         COAP_CACHE_NOT_RECORD_PDU,
304c87c5fbaSopenharmony_ci                                         COAP_CACHE_IS_SESSION_BASED, 0);
305c87c5fbaSopenharmony_ci      }
306c87c5fbaSopenharmony_ci      else {
307c87c5fbaSopenharmony_ci        data_so_far = coap_cache_get_app_data(cache_entry);
308c87c5fbaSopenharmony_ci        if (data_so_far) {
309c87c5fbaSopenharmony_ci          coap_delete_binary(data_so_far);
310c87c5fbaSopenharmony_ci          data_so_far = NULL;
311c87c5fbaSopenharmony_ci        }
312c87c5fbaSopenharmony_ci        coap_cache_set_app_data(cache_entry, NULL, NULL);
313c87c5fbaSopenharmony_ci      }
314c87c5fbaSopenharmony_ci    }
315c87c5fbaSopenharmony_ci    if (!cache_entry) {
316c87c5fbaSopenharmony_ci      if (offset == 0) {
317c87c5fbaSopenharmony_ci        coap_log_warn("Unable to create a new cache entry\n");
318c87c5fbaSopenharmony_ci      }
319c87c5fbaSopenharmony_ci      else {
320c87c5fbaSopenharmony_ci        coap_log_warn(
321c87c5fbaSopenharmony_ci                 "No cache entry available for the non-first BLOCK\n");
322c87c5fbaSopenharmony_ci      }
323c87c5fbaSopenharmony_ci      coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR);
324c87c5fbaSopenharmony_ci      return;
325c87c5fbaSopenharmony_ci    }
326c87c5fbaSopenharmony_ci
327c87c5fbaSopenharmony_ci    if (size) {
328c87c5fbaSopenharmony_ci      /* Add in the new data to cache entry */
329c87c5fbaSopenharmony_ci      data_so_far = coap_cache_get_app_data(cache_entry);
330c87c5fbaSopenharmony_ci      data_so_far = coap_block_build_body(data_so_far, size, data,
331c87c5fbaSopenharmony_ci                                          offset, total);
332c87c5fbaSopenharmony_ci      /* Yes, data_so_far can be NULL if error */
333c87c5fbaSopenharmony_ci      coap_cache_set_app_data(cache_entry, data_so_far, cache_free_app_data);
334c87c5fbaSopenharmony_ci    }
335c87c5fbaSopenharmony_ci    if (offset + size == total) {
336c87c5fbaSopenharmony_ci      /* All the data is now in */
337c87c5fbaSopenharmony_ci      data_so_far = coap_cache_get_app_data(cache_entry);
338c87c5fbaSopenharmony_ci      coap_cache_set_app_data(cache_entry, NULL, NULL);
339c87c5fbaSopenharmony_ci    }
340c87c5fbaSopenharmony_ci    else {
341c87c5fbaSopenharmony_ci      /* Give us the next block response */
342c87c5fbaSopenharmony_ci      coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTINUE);
343c87c5fbaSopenharmony_ci      return;
344c87c5fbaSopenharmony_ci    }
345c87c5fbaSopenharmony_ci  }
346c87c5fbaSopenharmony_ci  else {
347c87c5fbaSopenharmony_ci    /* single body of data received */
348c87c5fbaSopenharmony_ci    data_so_far = coap_new_binary(size);
349c87c5fbaSopenharmony_ci    if (data_so_far) {
350c87c5fbaSopenharmony_ci      memcpy(data_so_far->s, data, size);
351c87c5fbaSopenharmony_ci    }
352c87c5fbaSopenharmony_ci  }
353c87c5fbaSopenharmony_ci
354c87c5fbaSopenharmony_ci  if (example_data_ptr) {
355c87c5fbaSopenharmony_ci    /* pre-existed response */
356c87c5fbaSopenharmony_ci    coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED);
357c87c5fbaSopenharmony_ci    coap_delete_binary(example_data_ptr);
358c87c5fbaSopenharmony_ci  }
359c87c5fbaSopenharmony_ci  else
360c87c5fbaSopenharmony_ci    /* just generated response */
361c87c5fbaSopenharmony_ci    coap_pdu_set_code(response, COAP_RESPONSE_CODE_CREATED);
362c87c5fbaSopenharmony_ci
363c87c5fbaSopenharmony_ci  example_data_ptr = data_so_far;
364c87c5fbaSopenharmony_ci  if ((option = coap_check_option(request, COAP_OPTION_CONTENT_FORMAT,
365c87c5fbaSopenharmony_ci                                  &opt_iter)) != NULL) {
366c87c5fbaSopenharmony_ci    example_data_media_type =
367c87c5fbaSopenharmony_ci            coap_decode_var_bytes (coap_opt_value (option),
368c87c5fbaSopenharmony_ci                                   coap_opt_length (option));
369c87c5fbaSopenharmony_ci  }
370c87c5fbaSopenharmony_ci  else {
371c87c5fbaSopenharmony_ci    example_data_media_type = COAP_MEDIATYPE_TEXT_PLAIN;
372c87c5fbaSopenharmony_ci  }
373c87c5fbaSopenharmony_ci
374c87c5fbaSopenharmony_ci  coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED);
375c87c5fbaSopenharmony_ci  coap_resource_notify_observers(resource, NULL);
376c87c5fbaSopenharmony_ci}
377c87c5fbaSopenharmony_ci
378c87c5fbaSopenharmony_ciint
379c87c5fbaSopenharmony_cimain(int argc, char* argv[]) {
380c87c5fbaSopenharmony_ci  coap_context_t *ctx = NULL;  /* Set up as normal */
381c87c5fbaSopenharmony_ci  /* ... */
382c87c5fbaSopenharmony_ci  uint16_t cache_ignore_options[] = { COAP_OPTION_BLOCK1,
383c87c5fbaSopenharmony_ci                                      COAP_OPTION_BLOCK2 };
384c87c5fbaSopenharmony_ci
385c87c5fbaSopenharmony_ci  /* Initialize libcoap library */
386c87c5fbaSopenharmony_ci  coap_startup();
387c87c5fbaSopenharmony_ci
388c87c5fbaSopenharmony_ci  /* Remove (void) definition if variable is used */
389c87c5fbaSopenharmony_ci  (void)argc;
390c87c5fbaSopenharmony_ci  (void)argv;
391c87c5fbaSopenharmony_ci
392c87c5fbaSopenharmony_ci  /* ... */
393c87c5fbaSopenharmony_ci
394c87c5fbaSopenharmony_ci  /** Define the options to ignore when setting up cache-keys */
395c87c5fbaSopenharmony_ci  coap_cache_ignore_options(ctx, cache_ignore_options,
396c87c5fbaSopenharmony_ci             sizeof(cache_ignore_options)/sizeof(cache_ignore_options[0]));
397c87c5fbaSopenharmony_ci
398c87c5fbaSopenharmony_ci  /* ... */
399c87c5fbaSopenharmony_ci  coap_cleanup();
400c87c5fbaSopenharmony_ci
401c87c5fbaSopenharmony_ci}
402c87c5fbaSopenharmony_ci----
403c87c5fbaSopenharmony_ci
404c87c5fbaSopenharmony_ciSEE ALSO
405c87c5fbaSopenharmony_ci--------
406c87c5fbaSopenharmony_ci*coap_block*(3), *coap_init*(3), *coap_pdu_setup*(3), *coap_resource*(3)
407c87c5fbaSopenharmony_ciand *coap_string*(3)
408c87c5fbaSopenharmony_ci
409c87c5fbaSopenharmony_ciFURTHER INFORMATION
410c87c5fbaSopenharmony_ci-------------------
411c87c5fbaSopenharmony_ciSee
412c87c5fbaSopenharmony_ci
413c87c5fbaSopenharmony_ci"https://rfc-editor.org/rfc/rfc7252[RFC7252: The Constrained Application Protocol (CoAP)]"
414c87c5fbaSopenharmony_ci
415c87c5fbaSopenharmony_ci"https://rfc-editor.org/rfc/rfc7959[RFC7959: Block-Wise Transfers in the Constrained Application Protocol (CoAP)]"
416c87c5fbaSopenharmony_ci
417c87c5fbaSopenharmony_cifor further information.
418c87c5fbaSopenharmony_ci
419c87c5fbaSopenharmony_ciBUGS
420c87c5fbaSopenharmony_ci----
421c87c5fbaSopenharmony_ciPlease report bugs on the mailing list for libcoap:
422c87c5fbaSopenharmony_cilibcoap-developers@lists.sourceforge.net or raise an issue on GitHub at
423c87c5fbaSopenharmony_cihttps://github.com/obgm/libcoap/issues
424c87c5fbaSopenharmony_ci
425c87c5fbaSopenharmony_ciAUTHORS
426c87c5fbaSopenharmony_ci-------
427c87c5fbaSopenharmony_ciThe libcoap project <libcoap-developers@lists.sourceforge.net>
428