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