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.
- checksums.yaml +4 -4
- data/README.adoc +116 -6
- data/asciidoctor-rfc.gemspec +15 -1
- data/lib/asciidoctor/rfc/common/base.rb +74 -7
- data/lib/asciidoctor/rfc/common/front.rb +1 -1
- data/lib/asciidoctor/rfc/v2/base.rb +87 -38
- data/lib/asciidoctor/rfc/v2/blocks.rb +29 -2
- data/lib/asciidoctor/rfc/v2/converter.rb +0 -1
- data/lib/asciidoctor/rfc/v2/inline_anchor.rb +2 -8
- data/lib/asciidoctor/rfc/v2/lists.rb +7 -4
- data/lib/asciidoctor/rfc/v2/table.rb +1 -1
- data/lib/asciidoctor/rfc/v3/base.rb +41 -43
- data/lib/asciidoctor/rfc/v3/blocks.rb +29 -2
- data/lib/asciidoctor/rfc/v3/converter.rb +0 -2
- data/lib/asciidoctor/rfc/v3/inline_anchor.rb +2 -6
- data/lib/asciidoctor/rfc/version.rb +1 -1
- data/spec/asciidoctor/rfc/v2/comments_spec.rb +7 -3
- data/spec/asciidoctor/rfc/v2/date_spec.rb +23 -0
- data/spec/asciidoctor/rfc/v2/dlist_spec.rb +107 -9
- data/spec/asciidoctor/rfc/v2/image_spec.rb +17 -0
- data/spec/asciidoctor/rfc/v2/inline_formatting_spec.rb +12 -0
- data/spec/asciidoctor/rfc/v2/listing_spec.rb +22 -0
- data/spec/asciidoctor/rfc/v2/literal_spec.rb +22 -2
- data/spec/asciidoctor/rfc/v2/preamble_spec.rb +72 -0
- data/spec/asciidoctor/rfc/v2/references_spec.rb +3 -1
- data/spec/asciidoctor/rfc/v2/table_spec.rb +104 -4
- data/spec/asciidoctor/rfc/v2/text_spec.rb +89 -0
- data/spec/asciidoctor/rfc/v2/ulist_spec.rb +40 -0
- data/spec/asciidoctor/rfc/v3/dlist_spec.rb +103 -1
- data/spec/asciidoctor/rfc/v3/image_spec.rb +18 -0
- data/spec/asciidoctor/rfc/v3/listing_spec.rb +26 -0
- data/spec/asciidoctor/rfc/v3/literal_spec.rb +20 -1
- data/spec/asciidoctor/rfc/v3/preamble_spec.rb +150 -0
- data/spec/asciidoctor/rfc/v3/references_spec.rb +35 -34
- data/spec/asciidoctor/rfc/v3/series_info_spec.rb +39 -0
- data/spec/examples/README.adoc +162 -0
- data/spec/examples/davies-template-bare-06.adoc +3 -0
- data/spec/examples/draft-ietf-core-block-xx.mkd +935 -0
- data/spec/examples/draft-ietf-core-block-xx.mkd.adoc +1013 -0
- data/spec/examples/draft-ietf-core-block-xx.xml.orig +1251 -0
- data/spec/examples/example-v2.adoc +6 -2
- data/spec/examples/example-v3.adoc +5 -1
- data/spec/examples/hoffmanv2.xml.adoc +247 -0
- data/spec/examples/hoffmanv2.xml.orig +339 -0
- data/spec/examples/hoffmanv3.xml.orig +346 -0
- data/spec/examples/mib-doc-template-xml-06.adoc +5 -1
- data/spec/examples/rfc2100.md.adoc +2 -3
- data/spec/examples/rfc3514.md.adoc +3 -2
- data/spec/examples/rfc5841.md.adoc +1 -1
- data/spec/examples/rfc748.md.adoc +7 -6
- data/spec/examples/rfc7511.md.adoc +15 -15
- data/spec/examples/skel.mkd +32 -0
- data/spec/examples/skel.mkd.adoc +50 -0
- data/spec/examples/skel.xml.orig +105 -0
- data/spec/examples/stupid-s.mkd +569 -0
- data/spec/examples/stupid-s.mkd.adoc +771 -0
- data/spec/examples/stupid-s.xml.orig +880 -0
- data/spec/spec_helper.rb +1 -1
- 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 `**`.
|
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
|
+
-->
|