asciidoctor-rfc 0.2.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +116 -6
  3. data/asciidoctor-rfc.gemspec +15 -1
  4. data/lib/asciidoctor/rfc/common/base.rb +74 -7
  5. data/lib/asciidoctor/rfc/common/front.rb +1 -1
  6. data/lib/asciidoctor/rfc/v2/base.rb +87 -38
  7. data/lib/asciidoctor/rfc/v2/blocks.rb +29 -2
  8. data/lib/asciidoctor/rfc/v2/converter.rb +0 -1
  9. data/lib/asciidoctor/rfc/v2/inline_anchor.rb +2 -8
  10. data/lib/asciidoctor/rfc/v2/lists.rb +7 -4
  11. data/lib/asciidoctor/rfc/v2/table.rb +1 -1
  12. data/lib/asciidoctor/rfc/v3/base.rb +41 -43
  13. data/lib/asciidoctor/rfc/v3/blocks.rb +29 -2
  14. data/lib/asciidoctor/rfc/v3/converter.rb +0 -2
  15. data/lib/asciidoctor/rfc/v3/inline_anchor.rb +2 -6
  16. data/lib/asciidoctor/rfc/version.rb +1 -1
  17. data/spec/asciidoctor/rfc/v2/comments_spec.rb +7 -3
  18. data/spec/asciidoctor/rfc/v2/date_spec.rb +23 -0
  19. data/spec/asciidoctor/rfc/v2/dlist_spec.rb +107 -9
  20. data/spec/asciidoctor/rfc/v2/image_spec.rb +17 -0
  21. data/spec/asciidoctor/rfc/v2/inline_formatting_spec.rb +12 -0
  22. data/spec/asciidoctor/rfc/v2/listing_spec.rb +22 -0
  23. data/spec/asciidoctor/rfc/v2/literal_spec.rb +22 -2
  24. data/spec/asciidoctor/rfc/v2/preamble_spec.rb +72 -0
  25. data/spec/asciidoctor/rfc/v2/references_spec.rb +3 -1
  26. data/spec/asciidoctor/rfc/v2/table_spec.rb +104 -4
  27. data/spec/asciidoctor/rfc/v2/text_spec.rb +89 -0
  28. data/spec/asciidoctor/rfc/v2/ulist_spec.rb +40 -0
  29. data/spec/asciidoctor/rfc/v3/dlist_spec.rb +103 -1
  30. data/spec/asciidoctor/rfc/v3/image_spec.rb +18 -0
  31. data/spec/asciidoctor/rfc/v3/listing_spec.rb +26 -0
  32. data/spec/asciidoctor/rfc/v3/literal_spec.rb +20 -1
  33. data/spec/asciidoctor/rfc/v3/preamble_spec.rb +150 -0
  34. data/spec/asciidoctor/rfc/v3/references_spec.rb +35 -34
  35. data/spec/asciidoctor/rfc/v3/series_info_spec.rb +39 -0
  36. data/spec/examples/README.adoc +162 -0
  37. data/spec/examples/davies-template-bare-06.adoc +3 -0
  38. data/spec/examples/draft-ietf-core-block-xx.mkd +935 -0
  39. data/spec/examples/draft-ietf-core-block-xx.mkd.adoc +1013 -0
  40. data/spec/examples/draft-ietf-core-block-xx.xml.orig +1251 -0
  41. data/spec/examples/example-v2.adoc +6 -2
  42. data/spec/examples/example-v3.adoc +5 -1
  43. data/spec/examples/hoffmanv2.xml.adoc +247 -0
  44. data/spec/examples/hoffmanv2.xml.orig +339 -0
  45. data/spec/examples/hoffmanv3.xml.orig +346 -0
  46. data/spec/examples/mib-doc-template-xml-06.adoc +5 -1
  47. data/spec/examples/rfc2100.md.adoc +2 -3
  48. data/spec/examples/rfc3514.md.adoc +3 -2
  49. data/spec/examples/rfc5841.md.adoc +1 -1
  50. data/spec/examples/rfc748.md.adoc +7 -6
  51. data/spec/examples/rfc7511.md.adoc +15 -15
  52. data/spec/examples/skel.mkd +32 -0
  53. data/spec/examples/skel.mkd.adoc +50 -0
  54. data/spec/examples/skel.xml.orig +105 -0
  55. data/spec/examples/stupid-s.mkd +569 -0
  56. data/spec/examples/stupid-s.mkd.adoc +771 -0
  57. data/spec/examples/stupid-s.xml.orig +880 -0
  58. data/spec/spec_helper.rb +1 -1
  59. metadata +32 -4
@@ -148,4 +148,43 @@ describe Asciidoctor::RFC::V3::Converter do
148
148
  </rfc>
149
149
  OUTPUT
150
150
  end
151
+ it "sets seriesInfo attributes for RFC with illegal intended status" do
152
+ expect(Asciidoctor.convert(<<~'INPUT', backend: :rfc3, header_footer: true)).to be_equivalent_to <<~'OUTPUT'
153
+ = Document title
154
+ Author
155
+ :doctype: internet-draft
156
+ :name: draft-xxx
157
+ :status: full-standard
158
+ :intended-series: illegal
159
+ :submission-type: IRTF
160
+
161
+ == Section 1
162
+ Text
163
+ INPUT
164
+ <?xml version="1.0" encoding="US-ASCII"?>
165
+ <!DOCTYPE rfc SYSTEM "rfc2629.dtd">
166
+ <?rfc strict="yes"?>
167
+ <?rfc toc="yes"?>
168
+ <?rfc tocdepth="4"?>
169
+ <?rfc symrefs=""?>
170
+ <?rfc sortrefs=""?>
171
+ <?rfc compact="yes"?>
172
+ <?rfc subcompact="no"?>
173
+ <rfc submissionType="IRTF" prepTime="2000-01-01T05:00:00Z" version="3">
174
+ <front>
175
+ <title>Document title</title>
176
+ <seriesInfo name="Internet-Draft" status="full-standard" stream="IRTF" value="draft-xxx"/>
177
+ <seriesInfo name="" status="illegal" value="draft-xxx"/>
178
+ <author fullname="Author"/>
179
+ <date day="1" month="January" year="2000"/>
180
+
181
+ </front><middle>
182
+ <section anchor="_section_1" numbered="false">
183
+ <name>Section 1</name>
184
+ <t>Text</t>
185
+ </section>
186
+ </middle>
187
+ </rfc>
188
+ OUTPUT
189
+ end
151
190
  end
@@ -0,0 +1,162 @@
1
+ = Examples
2
+ The examples in this directory are found RFC XML documents in various markup schemes
3
+ (RFC XML source, MMark Markdown, Krmdown Markdown), with Asciidoc equivalents which
4
+ we have supplied. The RFC XML derived from these sources is compared with the RFC
5
+ XML derived from Asciidoc during Rspec: for v2 RFC XML, this is done using xml2rfc,
6
+ and comparing the resulting txt files.
7
+
8
+ Examples are taken from the following sources:
9
+
10
+ == RFC XML v1
11
+ https://tools.ietf.org/tools/templates/
12
+
13
+ * `davies-template-bare-06.xml.orig`
14
+ * `mib-doc-template-xml-06.xml.orig`
15
+
16
+ The equivalent asciidoc is
17
+
18
+ * `davies-template-bare-06.adoc`
19
+ * `mib-doc-template-xml-06.adoc`
20
+
21
+ As these are document templates in v1, they are not good exemplars of RFC XML usage.
22
+
23
+ The following discrepancies should be noted between xml2rfc output from the XML source,
24
+ and xml2rfc output from XML generated from our asciidoc should be noted:
25
+
26
+ `davies-template-bare-06.adoc`::
27
+ +
28
+ --
29
+ * Asciidoc does not support table preambles and postambles; the table preamble and postamble
30
+ text is unindented in the output, and the postamble follows the table caption.
31
+ --
32
+
33
+ `mib-doc-template-xml-06.adoc`::
34
+ +
35
+ --
36
+ * The asciidoc automatically tages hyperlinks; this is reflected in the RFC XML
37
+ output as `eref`, and in the xml2rfc output as angle brackets.
38
+ --
39
+
40
+ == RFC XML v2
41
+ https://www.ietf.org/archive/id/draft-hoffman-rfcexamples-04.txt
42
+
43
+ * `hoffmanv2.xml.orig`
44
+
45
+ The equivalent asciidoc is
46
+
47
+ * `hoffmanv2.xml.adoc`
48
+
49
+ The following discrepancies should be noted between xml2rfc output from the XML source,
50
+ and xml2rfc output from XML generated from our asciidoc should be noted:
51
+
52
+ `hoffmanv2.xml.adoc`::
53
+ +
54
+ --
55
+ * The source xml has set the `subcompact` document directive; the directive cannot be set
56
+ from Asciidoc.
57
+ * Table preambles and postambles are not supported in Asciidoc.
58
+ --
59
+
60
+ == MMark
61
+ https://github.com/miekg/mmark/tree/master/rfc
62
+
63
+ The RFC XML v2 documents (`*.md.2.xml`) and RFC XML v3 documents (`*.md.3.xml`)
64
+ have been generated from the MMark source (`*.md`) using the current version of MMark:
65
+
66
+ * `rfc1149.md`
67
+ * `rfc2100.md`
68
+ * `rfc3514.md`
69
+ * `rfc5841.md`
70
+ * `rfc748.md`
71
+ * `rfc7511.md`
72
+
73
+ The equivalent asciidoc is
74
+
75
+ * `rfc1149.md.adoc`
76
+ * `rfc2100.md.adoc`
77
+ * `rfc3514.md.adoc`
78
+ * `rfc5841.md.adoc`
79
+ * `rfc748.md.adoc`
80
+ * `rfc7511.md.adoc`
81
+
82
+ The following discrepancies should be noted between xml2rfc output from the XML source,
83
+ and xml2rfc output from XML generated from our asciidoc should be noted:
84
+
85
+ `rfc1149.md`:: No discrepancy
86
+
87
+ `rfc2100.md`::
88
+ +
89
+ --
90
+ * The MMark has tagged the doggerel in this RFC as `artwork`. We have chosen to use Asciidoc
91
+ `verse`, which in RFC XML 2 preserves linebreaks, but not the indentation of even-numbered
92
+ verses, or of the concluding stanza.
93
+ --
94
+
95
+ `rfc3514.adoc`::
96
+ +
97
+ --
98
+ * The MMark separates definition list terms from definitions, with a line break (`<vspace/>`).
99
+ This gem consistently inserts one blank line between definition list terms
100
+ and definitions (`<vspace blankLines="1"/>`).
101
+ --
102
+
103
+ `rfc5841.md`:: No discrepancy
104
+ `rfc748.md`:: No discrepancy
105
+
106
+ `rfc7511.md`::
107
+ +
108
+ --
109
+ * The MMark has specified an external reference to a specific section by giving the section
110
+ number in text: `Section 4.2 of RFC 2460 [@!RFC2460]`, rendered as
111
+ `Section 4.2 of RFC 2460 <xref target="RFC2460"/>`. The asciidoc takes advantage of
112
+ the `relref` construction of external section references, even though `relref` is a v3
113
+ RFC XML feature: `<<RFC2460,4.2 of>>`, which is rendered in v2 RFC XML as
114
+ `<xref target="RFC2460">Section 4.2 of [RFC2460]</xref>`.
115
+ --
116
+
117
+ == Kramdown
118
+ https://github.com/cabo/kramdown-rfc2629/tree/master/examples
119
+
120
+ The RFC XML v2 documents (`*.mkd.xml`)
121
+ have been generated from the Kramdown source (`*.mkd`) using the current version of Kramdown:
122
+
123
+ * `draft-ietf-core-block-xx.mkd`
124
+ * `skel.mkd`
125
+ * `stupid-s.mkd`
126
+
127
+ The equivalent asciidoc is
128
+
129
+ * `draft-ietf-core-block-xx.mkd.adoc`
130
+ * `skel.mkd.adoc`
131
+ * `stupid-s.mkd.adoc`
132
+
133
+ The following discrepancies should be noted between xml2rfc output from the XML source,
134
+ and xml2rfc output from XML generated from our asciidoc should be noted:
135
+
136
+ `draft-ietf-core-block-xx.mkd`::
137
+ +
138
+ --
139
+ * The Kramdown document references itself through an entity. The Asciidoc uses a
140
+ cross-reference, which takes up one more space for the same reference text.
141
+ * Asciidoc requires an extra space for a definition list term ending in a colon,
142
+ since the term delimiter itself involves colons:
143
+ `SZX: :: `
144
+ * Note that `**` needs to be escape in Asciidoc as `\\**`, in order not to be misinterpreted
145
+ as formatting. On occasionl, the escaping is ignored, and the exponentiation operator
146
+ has had to be entered as `&#42;&#42;`.
147
+ --
148
+
149
+ `skel.mkd`::
150
+ +
151
+ --
152
+ * Kramdown inserts a leading zero in day numbers; our gem does not.
153
+ --
154
+
155
+ `stupid-s.mkd`::
156
+ +
157
+ --
158
+ * Kramdown inserts a leading zero in day numbers; our gem does not.
159
+ * The asciidoc automatically tages hyperlinks; this is reflected in the RFC XML
160
+ output as `eref`, and in the xml2rfc output as angle brackets.
161
+ --
162
+
@@ -18,6 +18,9 @@ Elwyn Davies <elwynd@dial.pipex.com>
18
18
  :area: General
19
19
  :workgroup: Internet Engineering Task Force
20
20
  :keyword: template
21
+ :inline-definition-lists: true
22
+ :compact: yes
23
+ :subcompact: no
21
24
 
22
25
  [abstract]
23
26
  Insert an abstract: MANDATORY. This template is for creating an
@@ -0,0 +1,935 @@
1
+ ---
2
+ title: Blockwise transfers in CoAP
3
+ # abbrev: CoAP-Block
4
+ docname: draft-ietf-core-block-05
5
+ date: 2012-01-13
6
+ # date: 2012-01
7
+ # date: 2012
8
+
9
+ # stand_alone: true
10
+
11
+ ipr: trust200902
12
+ area: Applications
13
+ wg: CoRE Working Group
14
+ kw: Internet-Draft
15
+ cat: std
16
+
17
+ coding: us-ascii
18
+ pi: # can use array (if all yes) or hash here
19
+ # - toc
20
+ # - sortrefs
21
+ # - symrefs
22
+ toc: yes
23
+ sortrefs: # defaults to yes
24
+ symrefs: yes
25
+
26
+ author:
27
+ -
28
+ ins: C. Bormann
29
+ name: Carsten Bormann
30
+ org: Universitaet Bremen TZI
31
+ # abbrev: TZI
32
+ # street:
33
+ # - Postfach 330440
34
+ # - Bibliothekstr. 1
35
+ street: Postfach 330440
36
+ city: Bremen
37
+ code: D-28359
38
+ country: Germany
39
+ phone: +49-421-218-63921
40
+ facsimile: +49-421-218-7000
41
+ email: cabo@tzi.org
42
+ -
43
+ ins: Z. Shelby
44
+ name: Zach Shelby
45
+ org: Sensinode
46
+ role: editor
47
+ street: Kidekuja 2
48
+ city: Vuokatti
49
+ code: 88600
50
+ country: Finland
51
+ phone: "+358407796297"
52
+ email: zach@sensinode.com
53
+
54
+ normative:
55
+ # - rfc2119
56
+ # - rfc2616
57
+ # - I-D.ietf-core-coap
58
+ RFC2119:
59
+ RFC2616:
60
+ I-D.ietf-core-coap:
61
+
62
+ informative:
63
+ REST:
64
+ title: Architectural Styles and the Design of Network-based Software Architectures
65
+ author:
66
+ # -
67
+ ins: R. Fielding
68
+ name: Roy Fielding
69
+ org: University of California, Irvine
70
+ date: 2000
71
+
72
+ entity:
73
+ SELF: "[RFCXXXX]"
74
+
75
+ # --- note_IESG_Note
76
+ #
77
+ # bla bla bla
78
+
79
+ --- abstract
80
+
81
+
82
+ CoAP is a RESTful transfer protocol for constrained nodes and networks.
83
+ Basic CoAP messages work well for the small payloads we expect
84
+ from temperature sensors, light switches, and similar
85
+ building-automation devices.
86
+ Occasionally, however, applications will need to transfer
87
+ larger payloads --- for instance, for firmware updates. With
88
+ HTTP, TCP does the grunt work of slicing large payloads up
89
+ into multiple packets and ensuring that they all arrive and
90
+ are handled in the right order.
91
+
92
+ CoAP is based on datagram transports such as UDP or DTLS,
93
+ which limits the maximum size of resource representations that
94
+ can be transferred without too much fragmentation.
95
+ Although UDP supports larger payloads through IP
96
+ fragmentation, it is limited to 64 KiB and, more importantly,
97
+ doesn't really work well for constrained applications and
98
+ networks.
99
+
100
+ Instead of relying on IP fragmentation, this specification
101
+ extends basic CoAP with a pair of "Block" options, for
102
+ transferring multiple blocks of information from a resource
103
+ representation in multiple request-response pairs. In many
104
+ important cases, the Block options enable a server to be truly
105
+ stateless: the server can handle each block transfer
106
+ separately, with no need for a connection setup or other
107
+ server-side memory of previous block transfers.
108
+
109
+ In summary, the Block options provide a minimal way to
110
+ transfer larger representations in a block-wise fashion.
111
+
112
+
113
+ --- middle
114
+
115
+ Introduction {#problems}
116
+ ============
117
+
118
+ The CoRE WG is tasked with standardizing an
119
+ Application Protocol for Constrained Networks/Nodes, CoAP.
120
+ This protocol is intended to provide RESTful {{REST}} services not
121
+ unlike HTTP {{RFC2616}},
122
+ while reducing the complexity of implementation as well as the size of
123
+ packets exchanged in order to make these services useful in a highly
124
+ constrained network of themselves highly constrained nodes.
125
+
126
+ This objective requires restraint in a number of sometimes conflicting ways:
127
+
128
+ - reducing implementation complexity in order to minimize code size,
129
+ - reducing message sizes in order to minimize the number of fragments
130
+ needed for each message (in turn to maximize the probability of
131
+ delivery of the message), the amount of transmission power needed
132
+ and the loading of the limited-bandwidth channel,
133
+ - reducing requirements on the environment such as stable storage,
134
+ good sources of randomness or user interaction capabilities.
135
+
136
+ CoAP is based on datagram transports such as UDP, which limit the
137
+ maximum size of resource representations that can be transferred
138
+ without creating unreasonable levels of IP fragmentation. In
139
+ addition, not all resource representations will fit into a single link
140
+ layer packet of a constrained network, which may cause adaptation
141
+ layer fragmentation even if IP layer fragmentation is not required.
142
+ Using fragmentation (either at the adaptation layer or at the IP
143
+ layer) to enable the transport of larger representations is possible
144
+ up to the maximum size of the underlying datagram protocol (such as
145
+ UDP), but the fragmentation/reassembly process loads the lower layers
146
+ with conversation state that is better managed in the application
147
+ layer.
148
+
149
+ This specification defines a pair of CoAP options to enable *block-wise* access to
150
+ resource representations.
151
+ The Block options provide a minimal way to transfer larger
152
+ resource representations in a block-wise fashion.
153
+ The overriding objective is to avoid
154
+ creating conversation state at the server for block-wise GET requests.
155
+ (It is impossible to fully avoid creating conversation state for
156
+ POST/PUT, if the creation/replacement of resources is to be atomic;
157
+ where that property is not needed, there is no need to create server
158
+ conversation state in this case, either.)
159
+
160
+
161
+ In summary, this specification adds a pair of Block options to CoAP that
162
+ can be used for block-wise transfers. Benefits of using these options
163
+ include:
164
+
165
+ * Transfers larger than can be accommodated in constrained-network
166
+ link-layer packets can be performed in smaller blocks.
167
+ * No hard-to-manage conversation state is created at the adaptation
168
+ layer or IP layer for fragmentation.
169
+ * The transfer of each block is acknowledged, enabling retransmission
170
+ if required.
171
+ * Both sides have a say in the block size that actually will be used.
172
+ * The resulting exchanges are easy to understand using packet
173
+ analyzer tools and thus quite accessible to debugging.
174
+ * If needed, the Block options can also be used as is to provide random
175
+ access to power-of-two sized blocks within a resource representation.
176
+
177
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
178
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
179
+ document are to be interpreted as described in RFC 2119, BCP 14
180
+ {{RFC2119}} and indicate requirement levels for compliant CoAP
181
+ implementations.
182
+
183
+ In this document, the term "byte" is used in its now customary sense
184
+ as a synonym for "octet".
185
+
186
+ Where bit arithmetic is explained, this document uses the notation
187
+ familiar from the programming language C, except that the operator "\*\*"
188
+ stands for exponentiation.
189
+
190
+ Block-wise transfers
191
+ ====================
192
+
193
+ As discussed in the introduction, there are good reasons to limit the
194
+ size datagrams in constrained networks:
195
+
196
+ * by the maximum datagram size (~ 64 KiB for UDP)
197
+ * by the desire to avoid IP fragmentation (MTU of 1280 for IPv6)
198
+ * by the desire to avoid adaptation layer fragmentation (60--80 bytes
199
+ for 6LoWPAN)
200
+
201
+ When a resource representation is larger than can be comfortably
202
+ transferred in the payload of a single CoAP datagram, a Block option
203
+ can be used to indicate a block-wise transfer. As payloads can be
204
+ sent both with requests and with responses, this specification
205
+ provides two separate options for each direction of payload transfer.
206
+
207
+ In the following, the term "payload" will be used for the actual
208
+ content of a single CoAP message, i.e. a single block being
209
+ transferred, while the term "body" will be used for the entire
210
+ resource representation that is being transferred in a block-wise
211
+ fashion.
212
+
213
+ In most cases, all blocks being transferred for a body will be of the
214
+ same size. The block size is not fixed by the protocol. To keep the
215
+ implementation as simple as possible, the Block options support only a
216
+ small range of power-of-two block sizes, from 2\*\*4 (16) to 2\*\*10
217
+ (1024) bytes. As bodies often will not evenly divide into the
218
+ power-of-two block size chosen, the size need not be reached in the
219
+ final block; still this size will be given as the block size even for
220
+ the final block.
221
+
222
+ The Block Options {#block-option}
223
+ ----------------
224
+
225
+ | Type | C/E | Name | Format | Length | Default |
226
+ |------:+----------+--------+--------+--------+---------------|
227
+ | 19 | Critical | Block1 | uint | 1-3 B | 0 (see below) |
228
+ | 17 | Critical | Block2 | uint | 1-3 B | 0 (see below) |
229
+ {: #block-option-numbers title="Block Option Numbers"}
230
+
231
+ Both Block1 and Block2 options can be present both in request and
232
+ response messages. In either case, the Block1 Option pertains to the
233
+ request payload, and the Block2 Option pertains to the response payload.
234
+
235
+ Hence, for the methods defined in {{I-D.ietf-core-coap}}, Block1 is
236
+ useful with the payload-bearing POST and PUT requests and their
237
+ responses. Block2 is useful with GET, POST, and PUT requests and
238
+ their payload-bearing responses (2.01, 2.02, 2.04, 2.05 --- see
239
+ section "Payload" of {{I-D.ietf-core-coap}}).
240
+
241
+ (As a memory aid: Block_1_ pertains to the payload of the _1st_ part
242
+ of the request-response exchange, i.e. the request, and Block_2_
243
+ pertains to the payload of the _2nd_ part of the request-response
244
+ exchange, i.e. the response.)
245
+
246
+ Where Block1 is present in a request or Block2 in a response (i.e., in
247
+ that message to the payload of which it pertains) it indicates a
248
+ block-wise transfer and describes how this block-wise payload forms
249
+ part of the entire body being transferred ("descriptive usage").
250
+ Where it is present in the opposite direction, it provides additional
251
+ control on how that payload will be formed or was processed ("control usage").
252
+
253
+ Implementation of either Block option is intended to be optional.
254
+ However, when it is present in a CoAP message, it MUST be processed
255
+ (or the message rejected);
256
+ therefore it is identified as a critical option.
257
+
258
+ Three items of information may need to be transferred in a Block
259
+ option:
260
+
261
+ * The size of the block (SZX);
262
+ * whether more blocks are following (M);
263
+ * the relative number of the block (NUM) within a sequence of blocks
264
+ with the given size.
265
+
266
+ The value of the option is a 1-, 2- or 3-byte integer which encodes
267
+ these three fields, see {{block}}.
268
+
269
+ 0
270
+ 0 1 2 3 4 5 6 7
271
+ +-+-+-+-+-+-+-+-+
272
+ | NUM |M| SZX |
273
+ +-+-+-+-+-+-+-+-+
274
+
275
+ 0 1
276
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
277
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
278
+ | NUM |M| SZX |
279
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
280
+
281
+ 0 1 2
282
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
283
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
284
+ | NUM |M| SZX |
285
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
286
+ {: #block title="Block option value"}
287
+
288
+
289
+ The block size is encoded as a three-bit unsigned integer (0 for 2\*\*4 to 6
290
+ for 2\*\*10 bytes), which we call the `SZX` (size exponent); the
291
+ actual block size is then `2**(SZX + 4)`. SZX is transferred in the
292
+ three least significant bits of the option value (i.e., `val & 7`
293
+ where `val` is the value of the option).
294
+
295
+ The fourth least significant bit, the M or "more" bit (`val & 8`),
296
+ indicates whether more blocks are following or the current block-wise
297
+ transfer is the last block being transferred.
298
+
299
+ The option value divided by sixteen (the NUM field) is the sequence
300
+ number of the block currently being transferred, starting from
301
+ zero. The current transfer is therefore about the `size` bytes
302
+ starting at byte `NUM << (SZX + 4)`. (Note that, as an implementation
303
+ convenience, `(val & ~0xF) << (val & 7)`, i.e. the option value with
304
+ the last 4 bits masked out, shifted to the left by the value of SZX,
305
+ gives the byte position of the block.)
306
+
307
+ The default value of both the Block1 and the Block2 Option is zero,
308
+ indicating that the current block is the first and only block of the
309
+ transfer (block number 0, M bit not set); however, there is no
310
+ explicit size implied by this default value.
311
+
312
+ More specifically, within the option value of a Block1 or Block2
313
+ Option, the meaning of the option fields is defined as follows:
314
+
315
+ NUM:
316
+ : Block Number. The block number is a variable-size (4, 12, or 20 bit)
317
+ unsigned integer (uint, see Appendix A of {{I-D.ietf-core-coap}})
318
+ indicating the block number being requested or provided. Block
319
+ number 0 indicates the first block of a body.
320
+
321
+ M:
322
+ : More Flag (not last block). For descriptive usage, this flag, if
323
+ unset, indicates that the payload in this message is the last block
324
+ in the body; when set it indicates that there are one or more
325
+ additional blocks available. When a Block2 Option is used in a
326
+ request to retrieve a specific block number ("control usage"), the M
327
+ bit MUST be sent as zero and ignored on reception. (In a Block1
328
+ Option in a response, the M flag is used to indicate atomicity, see
329
+ below.)
330
+
331
+ SZX:
332
+ : Block Size. The block size is a three-bit unsigned integer indicating the size of a block to
333
+ the power of two. Thus block size = 2\*\*(SZX + 4). The allowed
334
+ values of SZX are 0 to 6, i.e., the minimum block size is 2\*\*(0+4) = 16
335
+ and the maximum is 2\*\*(6+4) = 1024.
336
+ The value 7 for SZX (which would indicate a block size of 2048) is
337
+ reserved, i.e. MUST NOT be sent and MUST lead to a 4.00 Bad Request
338
+ response code upon reception in a request.
339
+
340
+ The Block options are used in one of three roles:
341
+
342
+ - In descriptive usage, i.e. a Block2 Option in a response (e.g., a
343
+ 2.05 response for GET), or a Block1 Option in a request (e.g., PUT
344
+ or POST):
345
+ - The NUM field in the option value describes what block number is
346
+ contained in the payload of this message.
347
+ - The M bit indicates whether further
348
+ blocks are required to complete the transfer of that body.
349
+ - The block size given by SZX MUST match the size of the payload in
350
+ bytes, if the M bit is set. (The block size given is irrelevant if
351
+ M is unset). For Block2, if the request suggested a larger value
352
+ of SZX, the next request MUST move SZX down to the size given
353
+ here. (The effect is that, if the server uses the smaller of its
354
+ preferred block size and the one requested, all blocks for a body
355
+ use the same block size.)
356
+
357
+ - A Block2 Option in control usage in a request (e.g., GET):
358
+ - The NUM field in the Block2 Option gives the block number of the
359
+ payload that is being requested to be returned in the response.
360
+ - In this case, the M bit has no function and MUST be set to zero.
361
+ - The block size given (SZX) suggests a block size (in the case of
362
+ block number 0) or repeats the block size of previous blocks
363
+ received (in the case of block numbers other than 0).
364
+
365
+ - A Block1 Option in control usage in a response (e.g., a 2.xx
366
+ response for a PUT or POST request):
367
+ - The NUM field of the Block1 Option indicates what block number is
368
+ being acknowledged.
369
+ - If the M bit was set in the request, the server can choose whether
370
+ to act on each block separately, with no memory, or whether to
371
+ handle the request for the entire body atomically, or any mix of
372
+ the two. If the M bit is also set in the response, it indicates
373
+ that this response does not carry the final response code to the
374
+ request, i.e. the server collects further blocks and plans to
375
+ implement the request atomically (e.g., acts only upon reception
376
+ of the last block of payload). Conversely, if the M bit is unset
377
+ even though it was set in the request, it indicates the block-wise
378
+ request was enacted now specifically for this block, and the
379
+ response carries the final response to this request (and to any
380
+ previous ones with the M bit set in the response's Block1 Option
381
+ in this sequence of block-wise transfers); the client is still
382
+ expected to continue sending further blocks, the request method
383
+ for which may or may not also be enacted per-block.
384
+ - Finally, the SZX block size given in a control Block1 Option
385
+ indicates the largest block size preferred by the server for
386
+ transfers toward the resource that is the same or smaller than the
387
+ one used in the initial exchange; the client SHOULD use this block
388
+ size or a smaller one in all further requests in the transfer
389
+ sequence, even if that means changing the block size (and possibly
390
+ scaling the block number accordingly) from now on.
391
+
392
+ Using the Block Options {#block-usage}
393
+ -----------------------
394
+
395
+ Using one or both Block options, a single REST operation can be split
396
+ into multiple CoAP message exchanges. As specified in
397
+ {{I-D.ietf-core-coap}}, each of these message exchanges uses their own
398
+ CoAP Message ID.
399
+
400
+ When a request is answered with a response carrying a Block2 Option with
401
+ the M bit set, the requester may retrieve additional blocks of the
402
+ resource representation by sending further
403
+ requests with the same options and a Block2 Option giving the block
404
+ number and block size desired. In a request, the client MUST set the M bit of a Block2 Option
405
+ to zero and the server MUST ignore it on reception.
406
+
407
+ To influence the block size used in a response, the
408
+ requester also uses the Block2 Option, giving the desired size, a block
409
+ number of zero and an M bit of zero. A server MUST use the block
410
+ size indicated or a smaller size. Any further block-wise requests for
411
+ blocks beyond the first one MUST indicate the same block size that was
412
+ used by the server in the
413
+ response for the first request that gave a desired size using a Block2
414
+ Option.
415
+
416
+ Once the Block2 Option is used by the requester, all requests in a
417
+ single block-wise transfer
418
+ MUST ultimately use the same size, except that there may not be enough
419
+ content to fill the last block (the one returned with the M bit not
420
+ set).
421
+ (Note that the client may start using the Block2 Option in a second
422
+ request after a first request without a Block2 Option resulted in a
423
+ Block option in the response.)
424
+ The server SHOULD use the block
425
+ size indicated in the request option or a smaller size, but the
426
+ requester MUST take note of the actual block size used in the response
427
+ it receives
428
+ to its initial request and proceed to use it in subsequent requests. The
429
+ server behavior MUST ensure that this client behavior results in the
430
+ same block size for all responses in a sequence (except for the last
431
+ one with the M bit not set, and possibly the first one if the initial
432
+ request did not contain a Block2 Option).
433
+
434
+ Block-wise transfers can be used to GET resources the representations
435
+ of which are entirely static (not changing over time at all, such as
436
+ in a schema describing a device), or for dynamically changing
437
+ resources. In the latter case, the Block2 Option SHOULD be used in
438
+ conjunction with the ETag Option, to ensure that the blocks being
439
+ reassembled are from the same version of the representation: The
440
+ server SHOULD include an ETag option in each response. If an ETag
441
+ option is available, the client's reassembler, when reassembling the
442
+ representation from the blocks being exchanged, MUST compare ETag
443
+ Options. If the ETag Options do not match in a GET transfer, the
444
+ requester has the option of attempting to retrieve fresh values for
445
+ the blocks it retrieved first. To minimize the resulting
446
+ inefficiency, the server MAY cache the current value of a
447
+ representation for an ongoing sequence of requests. The client MAY
448
+ facilitate identifying the sequence by using the Token Option with a
449
+ non-default value. Note well that this specification makes no
450
+ requirement for the server to establish any state; however, servers
451
+ that offer quickly changing resources may thereby make it impossible
452
+ for a client to ever retrieve a consistent set of blocks.
453
+
454
+ In a request with a request payload (e.g., PUT or POST), the Block1
455
+ Option refers to the payload in the request (descriptive usage).
456
+
457
+ In response to a request with a payload (e.g., a PUT or POST
458
+ transfer), the block size given in the Block1 Option indicates the
459
+ block size preference of the server for this resource (control usage).
460
+ Obviously, at this point the first block has already been transferred
461
+ by the client without benefit of this knowledge. Still, the client
462
+ SHOULD heed the preference and, for all further blocks, use the block
463
+ size preferred by the server or a smaller one. Note that any
464
+ reduction in the block size may mean that the second request starts
465
+ with a block number larger than one, as the first request already
466
+ transferred multiple blocks as counted in the smaller size.
467
+
468
+ To counter the effects of adaptation layer fragmentation on packet
469
+ delivery probability, a client may want to give up retransmitting a
470
+ request with a relatively large payload even before MAX_RETRANSMIT has
471
+ been reached, and try restating the request as a block-wise transfer
472
+ with a smaller payload. Note that this new attempt is then a new
473
+ message-layer transaction and requires a new Message ID.
474
+ (Because of the uncertainty whether the request or the acknowledgement
475
+ was lost, this strategy is useful mostly for idempotent requests.)
476
+
477
+ In a blockwise transfer of a request payload (e.g., a PUT or POST) that is intended to be implemented in an
478
+ atomic fashion at the server, the actual creation/replacement takes
479
+ place at the time the final block, i.e. a block with the M bit unset
480
+ in the Block1 Option, is received. If not
481
+ all previous blocks are available at the server at this time, the
482
+ transfer fails and error code 4.08 (Request Entity Incomplete) MUST be returned. The error
483
+ code 4.13 (Request Entity Too Large) can be returned at any time by a server that does not
484
+ currently have the resources to store blocks for a block-wise request payload transfer that it would intend to implement in an atomic fashion.
485
+
486
+ If multiple concurrently proceeding block-wise request payload
487
+ transfer (e.g., PUT or POST) operations
488
+ are possible, the requester SHOULD use the Token Option to clearly separate the different sequences.
489
+ In this case, when reassembling the representation from the blocks
490
+ being exchanged to enable atomic processing, the reassembler MUST
491
+ compare any Token Options present (and, as usual, taking an absent Token Option
492
+ to default to the empty Token).
493
+ If atomic processing is not desired, there is no need to process the
494
+ Token Option (but it is still returned in the response as usual).
495
+
496
+ Examples
497
+ ========
498
+
499
+ This section gives a number of short examples with message flows for a
500
+ block-wise GET, and for a PUT or POST.
501
+ These examples demonstrate the basic operation, the operation in the
502
+ presence of retransmissions, and examples for the operation of the
503
+ block size negotiation.
504
+
505
+ In all these examples, a Block option is shown in a decomposed way
506
+ separating the kind of Block option (1 or 2), block number (NUM), more bit (M), and block size exponent
507
+ (2\*\*(SZX+4)) by slashes. E.g., a Block2 Option value of 33 would be shown as
508
+ 2/2/0/32), or a Block1 Option value of 59 would be shown as 1/3/1/128.
509
+
510
+ The first example ({{simple-get}}) shows a GET request that is split
511
+ into three blocks.
512
+ The server proposes a block size of 128, and the client agrees.
513
+ The first two ACKs contain 128 bytes of payload each, and third ACK
514
+ contains between 1 and 128 bytes.
515
+
516
+ ~~~~~~~~~~~
517
+ CLIENT SERVER
518
+ | |
519
+ | CON [MID=1234], GET, /status ------> |
520
+ | |
521
+ | <------ ACK [MID=1234], 2.05 Content, 2/0/1/128 |
522
+ | |
523
+ | CON [MID=1235], GET, /status, 2/1/0/128 ------> |
524
+ | |
525
+ | <------ ACK [MID=1235], 2.05 Content, 2/1/1/128 |
526
+ | |
527
+ | CON [MID=1236], GET, /status, 2/2/0/128 ------> |
528
+ | |
529
+ | <------ ACK [MID=1236], 2.05 Content, 2/2/0/128 |
530
+ ~~~~~~~~~~~
531
+ {: #simple-get title="Simple blockwise GET"}
532
+
533
+
534
+ In the second example ({{early-get}}), the client anticipates the blockwise transfer
535
+ (e.g., because of a size indication in the link-format description)
536
+ and sends a size proposal. All ACK messages except for the last carry
537
+ 64 bytes of payload; the last one carries between 1 and 64 bytes.
538
+
539
+
540
+ ~~~~~~~~~~~
541
+ CLIENT SERVER
542
+ | |
543
+ | CON [MID=1234], GET, /status, 2/0/0/64 ------> |
544
+ | |
545
+ | <------ ACK [MID=1234], 2.05 Content, 2/0/1/64 |
546
+ | |
547
+ | CON [MID=1235], GET, /status, 2/1/0/64 ------> |
548
+ | |
549
+ | <------ ACK [MID=1235], 2.05 Content, 2/1/1/64 |
550
+ : :
551
+ : ... :
552
+ : :
553
+ | CON [MID=1238], GET, /status, 2/4/0/64 ------> |
554
+ | |
555
+ | <------ ACK [MID=1238], 2.05 Content, 2/4/1/64 |
556
+ | |
557
+ | CON [MID=1239], GET, /status, 2/5/0/64 ------> |
558
+ | |
559
+ | <------ ACK [MID=1239], 2.05 Content, 2/5/0/64 |
560
+ ~~~~~~~~~~~
561
+ {: #early-get title="Blockwise GET with early negotiation" }
562
+
563
+ In the third example ({{late-get}}), the client is surprised by the
564
+ need for a blockwise transfer, and unhappy with the size chosen
565
+ unilaterally by the server. As it did not send a size proposal
566
+ initially, the negotiation only influences the size from the second
567
+ message exchange onward. Since the client already obtained both the first and
568
+ second 64-byte block in the first 128-byte exchange, it goes on
569
+ requesting the third 64-byte block ("2/0/64"). None of this is (or
570
+ needs to be) understood by the server, which simply responds to the
571
+ requests as it best can.
572
+
573
+
574
+ ~~~~~~~~~~~
575
+ CLIENT SERVER
576
+ | |
577
+ | CON [MID=1234], GET, /status ------> |
578
+ | |
579
+ | <------ ACK [MID=1234], 2.05 Content, 2/0/1/128 |
580
+ | |
581
+ | CON [MID=1235], GET, /status, 2/2/0/64 ------> |
582
+ | |
583
+ | <------ ACK [MID=1235], 2.05 Content, 2/2/1/64 |
584
+ | |
585
+ | CON [MID=1236], GET, /status, 2/3/0/64 ------> |
586
+ | |
587
+ | <------ ACK [MID=1236], 2.05 Content, 2/3/1/64 |
588
+ | |
589
+ | CON [MID=1237], GET, /status, 2/4/0/64 ------> |
590
+ | |
591
+ | <------ ACK [MID=1237], 2.05 Content, 2/4/1/64 |
592
+ | |
593
+ | CON [MID=1238], GET, /status, 2/5/0/64 ------> |
594
+ | |
595
+ | <------ ACK [MID=1238], 2.05 Content, 2/5/0/64 |
596
+ ~~~~~~~~~~~
597
+ {: #late-get title="Blockwise GET with late negotiation" }
598
+
599
+ In all these (and the following) cases, retransmissions are handled by
600
+ the CoAP message exchange layer, so they don't influence the block
601
+ operations ({{late-get-lost-con}}, {{late-get-lost-ack}}).
602
+
603
+
604
+ ~~~~~~~~~~~
605
+ CLIENT SERVER
606
+ | |
607
+ | CON [MID=1234], GET, /status ------> |
608
+ | |
609
+ | <------ ACK [MID=1234], 2.05 Content, 2/0/1/128 |
610
+ | |
611
+ | CON [MID=1235], GE///////////////////////// |
612
+ | |
613
+ | (timeout) |
614
+ | |
615
+ | CON [MID=1235], GET, /status, 2/2/0/64 ------> |
616
+ | |
617
+ | <------ ACK [MID=1235], 2.05 Content, 2/2/1/64 |
618
+ : :
619
+ : ... :
620
+ : :
621
+ | CON [MID=1238], GET, /status, 2/5/0/64 ------> |
622
+ | |
623
+ | <------ ACK [MID=1238], 2.05 Content, 2/5/0/64 |
624
+ ~~~~~~~~~~~
625
+ {: #late-get-lost-con title="Blockwise GET with late negotiation and
626
+ lost CON" }
627
+
628
+
629
+ ~~~~~~~~~~~
630
+ CLIENT SERVER
631
+ | |
632
+ | CON [MID=1234], GET, /status ------> |
633
+ | |
634
+ | <------ ACK [MID=1234], 2.05 Content, 2/0/1/128 |
635
+ | |
636
+ | CON [MID=1235], GET, /status, 2/2/0/64 ------> |
637
+ | |
638
+ | //////////////////////////////////tent, 2/2/1/64 |
639
+ | |
640
+ | (timeout) |
641
+ | |
642
+ | CON [MID=1235], GET, /status, 2/2/0/64 ------> |
643
+ | |
644
+ | <------ ACK [MID=1235], 2.05 Content, 2/2/1/64 |
645
+ : :
646
+ : ... :
647
+ : :
648
+ | CON [MID=1238], GET, /status, 2/5/0/64 ------> |
649
+ | |
650
+ | <------ ACK [MID=1238], 2.05 Content, 2/5/0/64 |
651
+ ~~~~~~~~~~~
652
+ {: #late-get-lost-ack title="Blockwise GET with late negotiation and
653
+ lost ACK" }
654
+
655
+ The following examples demonstrate a PUT exchange; a POST exchange
656
+ looks the same, with different requirements on atomicity/idempotence.
657
+ To ensure that the blocks relate to the same version of the resource
658
+ representation carried in the request, the client in
659
+ {{simple-put-atomic}} sets the Token to
660
+ "v17" in all requests. Note that, as with the GET, the responses to
661
+ the requests that have a more bit in the request Block2 Option are
662
+ provisional; only the final response tells the client that the PUT
663
+ succeeded.
664
+
665
+
666
+ ~~~~~~~~~~~
667
+ CLIENT SERVER
668
+ | |
669
+ | CON [MID=1234], PUT, /options, v17, 1/0/1/128 ------> |
670
+ | |
671
+ | <------ ACK [MID=1234], 2.04 Changed, 1/0/1/128 |
672
+ | |
673
+ | CON [MID=1235], PUT, /options, v17, 1/1/1/128 ------> |
674
+ | |
675
+ | <------ ACK [MID=1235], 2.04 Changed, 1/1/1/128 |
676
+ | |
677
+ | CON [MID=1236], PUT, /options, v17, 1/2/0/128 ------> |
678
+ | |
679
+ | <------ ACK [MID=1236], 2.04 Changed, 1/2/0/128 |
680
+ ~~~~~~~~~~~
681
+ {: #simple-put-atomic title="Simple atomic blockwise PUT" }
682
+
683
+ A stateless server that simply builds/updates the resource in place
684
+ (statelessly) may indicate this by not setting the more bit in the
685
+ response ({{simple-put-stateless}}); in this case, the response codes are valid separately for
686
+ each block being updated. This is of course only an acceptable
687
+ behavior of the server if the potential inconsistency present during
688
+ the run of the message exchange sequence does not lead to problems,
689
+ e.g. because the resource being created or changed is not yet or not currently in
690
+ use.
691
+
692
+
693
+ ~~~~~~~~~~~
694
+ CLIENT SERVER
695
+ | |
696
+ | CON [MID=1234], PUT, /options, v17, 1/0/1/128 ------> |
697
+ | |
698
+ | <------ ACK [MID=1234], 2.04 Changed, 1/0/0/128 |
699
+ | |
700
+ | CON [MID=1235], PUT, /options, v17, 1/1/1/128 ------> |
701
+ | |
702
+ | <------ ACK [MID=1235], 2.04 Changed, 1/1/0/128 |
703
+ | |
704
+ | CON [MID=1236], PUT, /options, v17, 1/2/0/128 ------> |
705
+ | |
706
+ | <------ ACK [MID=1236], 2.04 Changed, 1/2/0/128 |
707
+ ~~~~~~~~~~~
708
+ {: #simple-put-stateless title="Simple stateless blockwise PUT" }
709
+
710
+ Finally, a server receiving a blockwise PUT or POST may want to indicate a
711
+ smaller block size preference ({{simple-put-atomic-nego}}).
712
+ In this case, the client SHOULD continue with a smaller block size; if
713
+ it does, it MUST adjust the block number to properly count in that smaller size.
714
+
715
+
716
+
717
+ ~~~~~~~~~~~
718
+ CLIENT SERVER
719
+ | |
720
+ | CON [MID=1234], PUT, /options, v17, 1/0/1/128 ------> |
721
+ | |
722
+ | <------ ACK [MID=1234], 2.04 Changed, 1/0/1/32 |
723
+ | |
724
+ | CON [MID=1235], PUT, /options, v17, 1/4/1/32 ------> |
725
+ | |
726
+ | <------ ACK [MID=1235], 2.04 Changed, 1/4/1/32 |
727
+ | |
728
+ | CON [MID=1236], PUT, /options, v17, 1/5/1/32 ------> |
729
+ | |
730
+ | <------ ACK [MID=1235], 2.04 Changed, 1/5/1/32 |
731
+ | |
732
+ | CON [MID=1237], PUT, /options, v17, 1/6/0/32 ------> |
733
+ | |
734
+ | <------ ACK [MID=1236], 2.04 Changed, 1/6/0/32 |
735
+ ~~~~~~~~~~~
736
+ {: #simple-put-atomic-nego title="Simple atomic blockwise PUT with
737
+ negotiation" }
738
+
739
+
740
+ HTTP Mapping Considerations {#http-mapping}
741
+ ===========================
742
+
743
+
744
+ In this subsection, we give some brief examples for the influence the
745
+ Block options might have on intermediaries that map between CoAP and
746
+ HTTP.
747
+
748
+ For mapping CoAP requests to HTTP, the intermediary may want to map
749
+ the sequence of block-wise transfers into a single HTTP transfer.
750
+ E.g., for a GET request, the intermediary could perform the HTTP
751
+ request once the first block has been requested and could then fulfill
752
+ all further block requests out of its cache.
753
+ A constrained implementation may not be able to cache the entire
754
+ object and may use a combination of TCP flow control and (in
755
+ particular if timeouts occur) HTTP range requests to obtain the
756
+ information necessary for the next block transfer at the right time.
757
+
758
+ For PUT or POST requests, there is more variation in how HTTP servers
759
+ might implement ranges. Some WebDAV servers do, but in general the
760
+ CoAP-to-HTTP intermediary will have to try sending the payload of all
761
+ the blocks of a block-wise transfer within one HTTP request. If
762
+ enough buffering is available, this request can be started when the
763
+ last CoAP block is received. A constrained implementation may want to
764
+ relieve its buffering by already starting to send the HTTP request at
765
+ the time the first CoAP block is received; any HTTP 408 status code
766
+ that indicates that the HTTP server became impatient with the
767
+ resulting transfer can then be mapped into a CoAP 4.08 response code
768
+ (similarly, 413 maps to 4.13).
769
+
770
+ For mapping HTTP to CoAP, the intermediary may want to map a single
771
+ HTTP transfer into a sequence of block-wise transfers.
772
+ If the HTTP client is too slow delivering a request body on a PUT or
773
+ POST, the CoAP server might time out and return a 4.08
774
+ response code, which in turn maps well to an HTTP 408 status code
775
+ (again, 4.13 maps to 413).
776
+ HTTP range requests received on the HTTP side may be served out of a
777
+ cache and/or mapped to GET
778
+ requests that request a sequence of blocks overlapping the range.
779
+
780
+ (Note that, while the semantics of CoAP 4.08 and HTTP 408 differ, this
781
+ difference is largely due to the different way the two protocols are
782
+ mapped to transport. HTTP has an underlying TCP connection, which
783
+ supplies connection state, so a HTTP 408 status code can immediately
784
+ be used to indicate that a timeout occurred during transmitting a
785
+ request through that active TCP connection.
786
+ The CoAP 4.08 response code indicates one or more missing blocks,
787
+ which may be due to timeouts or resource constraints; as there is no
788
+ connection state, there is no way to deliver such a response
789
+ immediately; instead, it is delivered on the next block transfer.
790
+ Still, HTTP 408 is probably the best mapping back to HTTP, as the
791
+ timeout is the most likely cause for a CoAP 4.08.
792
+ Note that there is no way to distinguish a timeout from a missing
793
+ block for a server without creating additional state, the need for
794
+ which we want to avoid.)
795
+
796
+
797
+ IANA Considerations
798
+ ===================
799
+
800
+ This draft adds the following option numbers to the CoAP Option
801
+ Numbers registry of
802
+ {{I-D.ietf-core-coap}}:
803
+
804
+ | Number | Name | Reference |
805
+ |-------:+--------+----------- |
806
+ | 17 | Block2 | {{&SELF}} |
807
+ | 19 | Block1 | {{&SELF}} |
808
+ {: #tab-option-registry title="CoAP Option Numbers"}
809
+
810
+
811
+ This draft adds the following response code to the CoAP Response Codes registry of
812
+ {{I-D.ietf-core-coap}}:
813
+
814
+ | Code | Description | Reference |
815
+ |-----:+--------------------------------+----------- |
816
+ | 136 | 4.08 Request Entity Incomplete | {{&SELF}} |
817
+ {: #tab-response-code-registry title="CoAP Response Codes"}
818
+
819
+
820
+ Security Considerations
821
+ =======================
822
+
823
+ Providing access to blocks within a resource may lead to
824
+ surprising vulnerabilities.
825
+ Where requests are not implemented atomically, an attacker may be able
826
+ to exploit a race condition or confuse a server by inducing it to use
827
+ a partially updated resource representation.
828
+ Partial transfers may also make certain problematic data invisible to
829
+ intrusion detection systems; it is RECOMMENDED that an intrusion
830
+ detection system (IDS) that analyzes resource representations transferred by
831
+ CoAP implement the Block options to gain access to entire resource representations.
832
+ Still, approaches such as transferring even-numbered blocks on one path and odd-numbered
833
+ blocks on another path, or even transferring blocks multiple times
834
+ with different content and
835
+ obtaining a different interpretation of temporal order at the IDS than
836
+ at the server, may prevent an IDS from seeing the whole picture.
837
+ These kinds of attacks are well understood from IP fragmentation and
838
+ TCP segmentation; CoAP does not add fundamentally new considerations.
839
+
840
+ Where access to a resource is only granted to clients making use of a specific security
841
+ association, all blocks of that resource MUST be subject to the same
842
+ security checks; it MUST NOT be possible for unprotected exchanges to
843
+ influence blocks of an otherwise protected resource.
844
+ As a related consideration, where object security is employed,
845
+ PUT/POST should be implemented in the atomic fashion, unless the
846
+ object security operation is performed on each access and the
847
+ creation of unusable resources can be tolerated.
848
+
849
+ Mitigating Resource Exhaustion Attacks {#mitigating-exhaustion-attacks}
850
+ --------------------------------------
851
+
852
+ Certain blockwise requests may induce the server to create state, e.g. to
853
+ create a snapshot for the blockwise GET of a fast-changing resource
854
+ to enable consistent access to the same
855
+ version of a resource for all blocks, or to create temporary
856
+ resource representations that are collected until pressed into
857
+ service by a final PUT or POST with the more bit unset.
858
+ All mechanisms that induce a server to create state that cannot simply
859
+ be cleaned up create opportunities for denial-of-service attacks.
860
+ Servers SHOULD avoid being subject to resource exhaustion based on state
861
+ created by untrusted sources.
862
+ But even if this is done, the mitigation may cause a denial-of-service
863
+ to a legitimate request when it is drowned out by other state-creating
864
+ requests.
865
+ Wherever possible, servers should therefore minimize the opportunities
866
+ to create state for untrusted sources, e.g. by using stateless approaches.
867
+
868
+ Performing segmentation at the application layer is almost always
869
+ better in this respect than at the transport layer or lower (IP fragmentation,
870
+ adaptation layer fragmentation), e.g. because there is application
871
+ layer semantics that can be used for mitigation or because lower
872
+ layers provide security associations that can prevent attacks.
873
+ However, it is less common to apply timeouts and keepalive mechanisms
874
+ at the application layer than at lower layers. Servers MAY want to
875
+ clean up accumulated state by timing it out (cf. response code 4.08), and
876
+ clients SHOULD be prepared to run blockwise transfers in an expedient
877
+ way to minimize the likelihood of running into such a timeout.
878
+
879
+ Mitigating Amplification Attacks {#mitigating-amplification-attacks}
880
+ --------------------------------
881
+
882
+ {{I-D.ietf-core-coap}} discusses the susceptibility of
883
+ CoAP end-points for use in amplification attacks.
884
+
885
+ A CoAP server can reduce the amount of amplification it provides to an
886
+ attacker by offering large resource representations only in relatively
887
+ small blocks. With this, e.g., for a 1000 byte resource, a 10-byte request might
888
+ result in an 80-byte response (with a 64-byte block) instead of a
889
+ 1016-byte response, considerably reducing the amplification provided.
890
+
891
+
892
+ Acknowledgements
893
+ ================
894
+
895
+ Much of the content of this draft is the result of
896
+ discussions with the {{I-D.ietf-core-coap}} authors, and via many CoRE
897
+ WG discussions. Tokens were suggested by Gilman Tolle and refined by
898
+ Klaus Hartke.
899
+
900
+ Charles Palmer provided extensive editorial comments to a previous
901
+ version of this draft, some of which the authors hope to have covered
902
+ in this version.
903
+
904
+
905
+
906
+ --- back
907
+
908
+ Historical Note {#compat}
909
+ ===============
910
+
911
+ (This appendix to be deleted by the RFC editor.)
912
+
913
+ An earlier version of this draft used a single option:
914
+
915
+ | Type | C/E | Name | Format | Length | Default |
916
+ |-----:+----------+-------+--------+--------+--------------- |
917
+ | 13 | Critical | Block | uint | 1-3 B | 0 (see below) |
918
+
919
+
920
+ Note that this option number has since been reallocated in
921
+ {{I-D.ietf-core-coap}}; no backwards compatibility is provided after
922
+ July 1st, 2011.
923
+
924
+ --- fluff
925
+
926
+ <!-- LocalWords: CoAP datagram CoRE WG RESTful IP ETag reassembler
927
+ -->
928
+ <!-- LocalWords: blockwise idempotence statelessly keepalive SZX
929
+ -->
930
+ <!-- LocalWords: acknowledgement retransmissions ACKs ACK untrusted
931
+ -->
932
+ <!-- LocalWords: acknowledgements interoperability retransmission
933
+ -->
934
+ <!-- LocalWords: BCP atomicity NUM WebDAV IANA
935
+ -->