14  CoAP Block and Discovery Contracts

coap
block-wise-transfer
discovery
caching

14.1 Start With the Broken Firmware Download

The device asks for a firmware image, receives several blocks, loses one packet, then wakes later behind a proxy that may still have cached metadata. A working demo is not enough; the transfer needs block size, numbering, retry, resume, hash, discovery, and freshness evidence.

This contract page keeps those proof points together so block-wise transfer and resource discovery remain reviewable when the network is constrained and intermittent.

14.2 Learning Objectives

After this page, you should be able to:

  • Choose Block1 or Block2 and record block size, retry, resume, and hash-verification evidence for a large CoAP transfer.
  • Decode Block option NUM, M, and SZX fields and check them against byte offsets in a trace.
  • Describe /.well-known/core discovery, CoRE Link Format attributes, filtered discovery queries, and Content-Format 40.
  • Review Max-Age, ETag revalidation, and proxy caching decisions for constrained CoAP resources.

14.3 Why This Contract Comes After Advanced Features

CoAP Advanced Features introduces block-wise transfer, resource discovery, transport alternatives, and security. This page narrows in on the contracts most likely to fail during implementation: block sizing, partial-transfer recovery, resource metadata, and cache freshness across proxies.

Keep the CoAP advanced context visible: these are still the advanced CoAP features from the parent chapter, only recast as evidence a reviewer can check.

Use it when a device downloads firmware, uploads logs, exposes /.well-known/core, advertises observable resources, or relies on a proxy to shield a sleepy origin from repeated reads.

Overview: Block-wise Transfer Moves Big Payloads Through Small Datagrams

CoAP normally puts one message in one UDP datagram. That is perfect for a temperature reading but hopeless for a firmware image or a large configuration document: those exceed what a single datagram can carry, and relying on IP-layer fragmentation is fragile on lossy constrained links because losing one fragment discards the whole packet. Block-wise transfer (RFC 7959) solves this at the CoAP layer by splitting a single logical transfer into numbered blocks.

The key benefit is failure isolation. Each block is carried in its own request/response exchange with its own Message ID, so a lost block is retransmitted alone rather than forcing the entire payload to restart. Two options drive it: Block2 (option 23) governs a large response body, such as a big GET result, and Block1 (option 27) governs a large request body, such as a PUT or POST upload.

In a real maintenance window, that isolation changes the rollout plan. Suppose a pump controller downloads a 96 KB safety-profile image over a 6LoWPAN mesh using 256-byte Block2 chunks. The transfer has 384 numbered blocks. If interference drops block 177, the controller repeats only GET Block2:177; blocks 0 through 176 stay valid in the reassembly buffer. The review evidence should record the chosen block size, retry cap, resume point, hash check, and the condition that triggers rollback to the previous profile.

CoAP block-wise transfer of a firmware image split into numbered blocks with per-block requests and responses.
A large image is fetched as numbered Block2 blocks; each block is an independent exchange, so a single lost block retransmits by itself.

Block2 (option 23)

Fragments a large response body. The client walks block 0, 1, 2, ... until the server clears the More flag.

Block1 (option 27)

Fragments a large request body for PUT/POST uploads, one block per message.

Failure isolation

Each block is its own exchange, so loss costs one block, not the whole transfer.

No IP fragmentation

Splitting at the CoAP layer avoids brittle IP fragmentation on constrained networks.

Practitioner: The Block Option Encodes NUM, More, and a Size Exponent

A Block1 or Block2 option value packs three fields. NUM is the block number within the transfer. M (the More flag) is 1 while further blocks follow and 0 on the last block. SZX is a 3-bit size exponent, and the block size is 2^(SZX + 4) bytes — so SZX 0 is 16 bytes, SZX 4 is 256 bytes, and SZX 6 is the maximum 1024 bytes. Either endpoint can negotiate down to a smaller SZX if its buffers are tight; the smallest size that both accept wins.

For a concrete encoding check, take an 18 KB log upload from a meter concentrator. With SZX 4 the client sends 256-byte Block1 chunks, so it needs ceil(18,432 / 256) = 72 blocks. Block 31 carries NUM=31, M=1, and SZX=4; the last block carries NUM=71, M=0, and the same SZX unless the server negotiated down. A good trace review checks those fields against the byte offsets rather than trusting the library call.

SZX
Block size
Blocks for a 4 KB image
Trade-off
2
64 bytes
64 blocks
Tiny buffers, but many round trips.
4
256 bytes
16 blocks
Balanced for many 6LoWPAN links.
6
1024 bytes
4 blocks
Fewest exchanges; needs the largest buffer/MTU.

For a large upload, the client sends Block1 blocks and the server answers each non-final block with 2.31 Continue, meaning "block stored, send the next," then returns 2.01 Created or 2.04 Changed on the last block. If blocks arrive out of order or a needed one is missing, the server replies 4.08 Request Entity Incomplete; if a block exceeds what the server will accept it may reply 4.13 Request Entity Too Large, often carrying a smaller SZX hint. Pairing a transfer with an ETag lets both sides detect the resource changing mid-transfer so they do not stitch together inconsistent blocks.

Under the Hood: Discovery via CoRE Link Format, and Caching Through Proxies

Before a client can use a resource it usually has to find it. CoAP standardizes this with a well-known URI: a GET to /.well-known/core returns a document in the CoRE Link Format (RFC 6690), sent with Content-Format 40 (application/link-format). The body is a comma-separated list of links with attributes, for example </sensors/temp>;rt="temperature";if="sensor";ct=50;obs. Here rt is the resource type, if is the interface description, ct is the content-format the resource speaks (50 = JSON), and obs marks it observable. A client can narrow the query — GET /.well-known/core?rt=temperature returns only temperature links — which keeps discovery cheap on a large node.

Once resources are known, caching reduces how often a sleepy node is disturbed. Every response carries an implicit or explicit Max-Age (option 14, default 60 seconds) stating how long it stays fresh. A caching CoAP proxy — forward or reverse — can store a response and serve it to other clients until Max-Age expires, so ten dashboards observing one sensor need not each wake the device. When freshness lapses, an ETag (option 4) lets the proxy revalidate: it repeats the ETag, and if nothing changed the origin answers 2.03 Valid with no body, saving the payload entirely.

For example, a greenhouse gateway may discover </zone/3/temp>;rt="temperature";if="sensor";ct=60;obs and </zone/3/valve>;rt="irrigation";if="actuator";ct=50 from the same node. It can cache the temperature reading for 45 seconds because the sensor publishes slow environmental data, but it should not cache the valve control response as if it were harmless telemetry. The evidence record should show the discovery query, Link Format body, Max-Age value, ETag revalidation result, and which resources are excluded from shared caching.

/.well-known/core

The standard discovery endpoint returning a link-format list of a node's resources.

Link attributes

rt, if, ct, sz, and obs describe each resource so clients bind by capability, not guesswork.

Max-Age caching

A proxy reuses a stored response until Max-Age expires, sparing the origin device.

ETag revalidation

A repeated ETag lets the origin answer 2.03 Valid with no payload when nothing changed.

14.4 Release Checklist

Before shipping a CoAP block-transfer or discovery design, verify these records:

  • Transfer plan names Block1 or Block2, payload size, negotiated SZX, block count, retry cap, timeout policy, and resume point after loss.
  • Trace review checks NUM, M, and SZX against expected byte offsets, and confirms only the missing block is retried after loss.
  • Completion evidence includes final block detection, ETag or version consistency, checksum/hash verification, and rollback behavior for a failed firmware or profile update.
  • Discovery endpoint returns /.well-known/core as Content-Format 40 with rt, if, ct, sz, and obs attributes where relevant.
  • Filtered discovery queries such as ?rt=temperature and ?obs are tested on large nodes so clients avoid scanning irrelevant resources.
  • Cache policy records Max-Age values, ETag revalidation, 2.03 Valid handling, and resources excluded from shared caching.
  • Proxy evidence distinguishes forward/reverse proxy behavior from origin-node behavior so stale readings and unsafe actuator responses are not cached by accident.

14.5 See Also

14.6 Next

Return to CoAP Advanced Features, then continue to CoAP Security and Applications for securing block transfers and discovered resources.