RFC 7252
The Constrained Application Protocol (CoAP)
RFC 7252: The Constrained Application Protocol (CoAP) ๐
Part 1 of 23 ๐
- RFC number: 7252
- Title: The Constrained Application Protocol (CoAP)
- Authors: Z. Shelby (ARM), K. Hartke, and C. Bormann (Universitaet Bremen TZI) โจ
- Category: Standards Track ๐ฅ
- ISSN: 2070-1721
- Date: June 2014 ๐ธ
- Obsoletes / Updates: Nothing. The title block doesn't list any RFCs this one obsoletes or updates ๐ง
Abstract
okay bestie, so CoAP is a specialized web transfer protocol ๐
It's made for constrained nodes and constrained networks, meaning stuff that's low-power and kinda lossy. These nodes are often running on 8-bit microcontrollers with tiny amounts of ROM and RAM ๐ฅบ Meanwhile the networks they live on, like IPv6 over Low-Power Wireless Personal Area Networks (6LoWPANs), often have high packet error rates and a typical throughput of 10s of kbit/s. Lowkey wild, right? ๐ The whole thing is designed for machine-to-machine (M2M) applications, like smart energy and building automation ๐ โก
CoAP gives you a request/response interaction model between application endpoints ๐ฆ It also has built-in discovery of services and resources, so things can find each other without extra fuss โจ It keeps the key concepts of the Web, like URIs and Internet media types ๐ It's built to interface easily with HTTP so it can plug into the Web, while still hitting the specialized requirements it needs: multicast support, very low overhead, and simplicity for constrained environments ๐ It's giving efficient and iconic, periodt ๐ญ๐ซถ
Status of This Memo
This is an Internet Standards Track document ๐ฅ
This document is a product of the Internet Engineering Task Force (IETF) ๐ It represents the consensus of the IETF community, it got public review, and the Internet Engineering Steering Group (IESG) approved it for publication ๐ If you want more info on Internet Standards, check out Section 2 of RFC 5741 ๐ง
You can find the current status of this document, any errata, and how to send feedback on it at http://www.rfc-editor.org/info/rfc7252 ๐ฆ
Copyright Notice
Copyright (c) 2014 IETF Trust and the persons identified as the document authors. All rights reserved. ๐ธ
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) as they're in effect on the date this document was published ๐ Please actually read these, bestie, because they explain your rights and restrictions for this document ๐ Code Components extracted from this document must include Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come without warranty, as described in the Simplified BSD License ๐
More parts are coming, so stay tuned! ๐ซถ
Table of Contents ๐
Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 5
1.1. Features . . . . . . . . . . . . . . . . . . . . . . . . 5
1.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 6
2. Constrained Application Protocol . . . . . . . . . . . . . . 10
2.1. Messaging Model . . . . . . . . . . . . . . . . . . . . . 11
2.2. Request/Response Model . . . . . . . . . . . . . . . . . 12
2.3. Intermediaries and Caching . . . . . . . . . . . . . . . 15
2.4. Resource Discovery . . . . . . . . . . . . . . . . . . . 15
3. Message Format . . . . . . . . . . . . . . . . . . . . . . . 15
3.1. Option Format . . . . . . . . . . . . . . . . . . . . . . 17
3.2. Option Value Formats . . . . . . . . . . . . . . . . . . 19
4. Message Transmission . . . . . . . . . . . . . . . . . . . . 20
4.1. Messages and Endpoints . . . . . . . . . . . . . . . . . 20
4.2. Messages Transmitted Reliably . . . . . . . . . . . . . . 21
4.3. Messages Transmitted without Reliability . . . . . . . . 23
4.4. Message Correlation . . . . . . . . . . . . . . . . . . . 24
4.5. Message Deduplication . . . . . . . . . . . . . . . . . . 24
4.6. Message Size . . . . . . . . . . . . . . . . . . . . . . 25
4.7. Congestion Control . . . . . . . . . . . . . . . . . . . 26
4.8. Transmission Parameters . . . . . . . . . . . . . . . . . 27
4.8.1. Changing the Parameters . . . . . . . . . . . . . . . 27
4.8.2. Time Values Derived from Transmission Parameters . . 28
5. Request/Response Semantics . . . . . . . . . . . . . . . . . 31
5.1. Requests . . . . . . . . . . . . . . . . . . . . . . . . 31
5.2. Responses . . . . . . . . . . . . . . . . . . . . . . . . 31
5.2.1. Piggybacked . . . . . . . . . . . . . . . . . . . . . 33
5.2.2. Separate . . . . . . . . . . . . . . . . . . . . . . 33
5.2.3. Non-confirmable . . . . . . . . . . . . . . . . . . . 34
5.3. Request/Response Matching . . . . . . . . . . . . . . . . 34
5.3.1. Token . . . . . . . . . . . . . . . . . . . . . . . . 34
5.3.2. Request/Response Matching Rules . . . . . . . . . . . 35
5.4. Options . . . . . . . . . . . . . . . . . . . . . . . . . 36
5.4.1. Critical/Elective . . . . . . . . . . . . . . . . . . 37
5.4.2. Proxy Unsafe or Safe-to-Forward and NoCacheKey . . . 38
5.4.3. Length . . . . . . . . . . . . . . . . . . . . . . . 38
5.4.4. Default Values . . . . . . . . . . . . . . . . . . . 38
5.4.5. Repeatable Options . . . . . . . . . . . . . . . . . 39
5.4.6. Option Numbers . . . . . . . . . . . . . . . . . . . 39
5.5. Payloads and Representations . . . . . . . . . . . . . . 40
5.5.1. Representation . . . . . . . . . . . . . . . . . . . 40
5.5.2. Diagnostic Payload . . . . . . . . . . . . . . . . . 41
5.5.3. Selected Representation . . . . . . . . . . . . . . . 41
5.5.4. Content Negotiation . . . . . . . . . . . . . . . . . 41
5.6. Caching . . . . . . . . . . . . . . . . . . . . . . . . . 42
5.6.1. Freshness Model . . . . . . . . . . . . . . . . . . . 43
5.6.2. Validation Model . . . . . . . . . . . . . . . . . . 43
5.7. Proxying . . . . . . . . . . . . . . . . . . . . . . . . 44
5.7.1. Proxy Operation . . . . . . . . . . . . . . . . . . . 44
5.7.2. Forward-Proxies . . . . . . . . . . . . . . . . . . . 46
5.7.3. Reverse-Proxies . . . . . . . . . . . . . . . . . . . 46
5.8. Method Definitions . . . . . . . . . . . . . . . . . . . 47
5.8.1. GET . . . . . . . . . . . . . . . . . . . . . . . . . 47
5.8.2. POST . . . . . . . . . . . . . . . . . . . . . . . . 47
5.8.3. PUT . . . . . . . . . . . . . . . . . . . . . . . . . 48
5.8.4. DELETE . . . . . . . . . . . . . . . . . . . . . . . 48
5.9. Response Code Definitions . . . . . . . . . . . . . . . . 48
5.9.1. Success 2.xx . . . . . . . . . . . . . . . . . . . . 48
5.9.2. Client Error 4.xx . . . . . . . . . . . . . . . . . . 50
5.9.3. Server Error 5.xx . . . . . . . . . . . . . . . . . . 51
5.10. Option Definitions . . . . . . . . . . . . . . . . . . . 52
5.10.1. Uri-Host, Uri-Port, Uri-Path, and Uri-Query . . . . 53
5.10.2. Proxy-Uri and Proxy-Scheme . . . . . . . . . . . . . 54
5.10.3. Content-Format . . . . . . . . . . . . . . . . . . . 55
5.10.4. Accept . . . . . . . . . . . . . . . . . . . . . . . 55
5.10.5. Max-Age . . . . . . . . . . . . . . . . . . . . . . 55
5.10.6. ETag . . . . . . . . . . . . . . . . . . . . . . . . 56
5.10.7. Location-Path and Location-Query . . . . . . . . . . 57
5.10.8. Conditional Request Options . . . . . . . . . . . . 57
5.10.9. Size1 Option . . . . . . . . . . . . . . . . . . . . 59
6. CoAP URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 59
6.1. coap URI Scheme . . . . . . . . . . . . . . . . . . . . . 59
6.2. coaps URI Scheme . . . . . . . . . . . . . . . . . . . . 60
6.3. Normalization and Comparison Rules . . . . . . . . . . . 61
6.4. Decomposing URIs into Options . . . . . . . . . . . . . . 61
6.5. Composing URIs from Options . . . . . . . . . . . . . . . 62
7. Discovery . . . . . . . . . . . . . . . . . . . . . . . . . . 64
7.1. Service Discovery . . . . . . . . . . . . . . . . . . . . 64
7.2. Resource Discovery . . . . . . . . . . . . . . . . . . . 64
7.2.1. 'ct' Attribute . . . . . . . . . . . . . . . . . . . 64
8. Multicast CoAP . . . . . . . . . . . . . . . . . . . . . . . 65
8.1. Messaging Layer . . . . . . . . . . . . . . . . . . . . . 65
8.2. Request/Response Layer . . . . . . . . . . . . . . . . . 66
8.2.1. Caching . . . . . . . . . . . . . . . . . . . . . . . 67
8.2.2. Proxying . . . . . . . . . . . . . . . . . . . . . . 67
9. Securing CoAP . . . . . . . . . . . . . . . . . . . . . . . . 68
9.1. DTLS-Secured CoAP . . . . . . . . . . . . . . . . . . . . 69
9.1.1. Messaging Layer . . . . . . . . . . . . . . . . . . . 70
9.1.2. Request/Response Layer . . . . . . . . . . . . . . . 71
9.1.3. Endpoint Identity . . . . . . . . . . . . . . . . . . 71
10. Cross-Protocol Proxying between CoAP and HTTP . . . . . . . . 74
10.1. CoAP-HTTP Proxying . . . . . . . . . . . . . . . . . . . 75
10.1.1. GET . . . . . . . . . . . . . . . . . . . . . . . . 76
10.1.2. PUT . . . . . . . . . . . . . . . . . . . . . . . . 77
10.1.3. DELETE . . . . . . . . . . . . . . . . . . . . . . . 77
10.1.4. POST . . . . . . . . . . . . . . . . . . . . . . . . 77
10.2. HTTP-CoAP Proxying . . . . . . . . . . . . . . . . . . . 77
10.2.1. OPTIONS and TRACE . . . . . . . . . . . . . . . . . 78
10.2.2. GET . . . . . . . . . . . . . . . . . . . . . . . . 78
10.2.3. HEAD . . . . . . . . . . . . . . . . . . . . . . . . 79
10.2.4. POST . . . . . . . . . . . . . . . . . . . . . . . . 79
10.2.5. PUT . . . . . . . . . . . . . . . . . . . . . . . . 79
10.2.6. DELETE . . . . . . . . . . . . . . . . . . . . . . . 80
10.2.7. CONNECT . . . . . . . . . . . . . . . . . . . . . . 80
11. Security Considerations . . . . . . . . . . . . . . . . . . . 80
11.1. Parsing the Protocol and Processing URIs . . . . . . . . 80
11.2. Proxying and Caching . . . . . . . . . . . . . . . . . . 81
11.3. Risk of Amplification . . . . . . . . . . . . . . . . . 81
11.4. IP Address Spoofing Attacks . . . . . . . . . . . . . . 83
11.5. Cross-Protocol Attacks . . . . . . . . . . . . . . . . . 84
11.6. Constrained-Node Considerations . . . . . . . . . . . . 86
12. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 86
12.1. CoAP Code Registries . . . . . . . . . . . . . . . . . . 86
12.1.1. Method Codes . . . . . . . . . . . . . . . . . . . . 87
12.1.2. Response Codes . . . . . . . . . . . . . . . . . . . 88
12.2. CoAP Option Numbers Registry . . . . . . . . . . . . . . 89
12.3. CoAP Content-Formats Registry . . . . . . . . . . . . . 91
12.4. URI Scheme Registration . . . . . . . . . . . . . . . . 93
12.5. Secure URI Scheme Registration . . . . . . . . . . . . . 94
12.6. Service Name and Port Number Registration . . . . . . . 95
12.7. Secure Service Name and Port Number Registration . . . . 96
12.8. Multicast Address Registration . . . . . . . . . . . . . 97
13. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 97
14. References . . . . . . . . . . . . . . . . . . . . . . . . . 98
14.1. Normative References . . . . . . . . . . . . . . . . . . 98
14.2. Informative References . . . . . . . . . . . . . . . . . 100
Appendix A. Examples . . . . . . . . . . . . . . . . . . . . . . 104
Appendix B. URI Examples . . . . . . . . . . . . . . . . . . . . 110
1. Introduction โจ
okay so the whole internet runs on web services (web APIs) now, and that's only possible because of the fundamental Representational State Transfer [REST] architecture of the Web. it's giving foundation ๐
the CoRE (Constrained RESTful Environments) work is about bringing REST to the most constrained nodes (think 8-bit microcontrollers with limited RAM and ROM ๐ฅบ) and the most constrained networks (like 6LoWPAN, [RFC4944]). and here's the tea: 6LoWPAN supports fragmenting IPv6 packets into tiny link-layer frames, but that causes a big drop in packet delivery probability ๐. so one of CoAP's design goals was to keep message overhead small, so there's way less need to fragment anything. smart, bestie ๐ง
the main goal of CoAP is to be a generic web protocol built for the special needs of this constrained world, especially energy, building automation, and other machine-to-machine (M2M) applications ๐๐ . and no, it's not trying to blindly squish HTTP [RFC2616] down. instead it realizes a subset of REST that's shared with HTTP but tuned for M2M. CoAP could be used to glow up simple HTTP interfaces into something more compact, but the real main character moves are the features it brings for M2M: built-in discovery, multicast support, and asynchronous message exchanges ๐ฆโจ
so this document specifies the Constrained Application Protocol (CoAP). it translates to HTTP really easily, so it plugs right into the existing Web, while still hitting the specialized requirements: multicast support, very low overhead, and simplicity for constrained environments and M2M applications. iconic, honestly ๐
1.1. Features ๐
CoAP has the following main features, and the vibes are immaculate:
- Web protocol fulfilling M2M requirements in constrained environments ๐ธ
- UDP [RFC0768] binding with optional reliability, supporting unicast and multicast requests ๐ก
- Asynchronous message exchanges ๐
- Low header overhead and parsing complexity ๐
- URI and Content-type support ๐
- Simple proxy and caching capabilities ๐ง
- A stateless HTTP mapping, allowing proxies to be built that provide access to CoAP resources via HTTP in a uniform way, or for HTTP simple interfaces to be realized alternatively over CoAP ๐ฆ
- Security binding to Datagram Transport Layer Security (DTLS) [RFC6347] ๐๐
1.2. Terminology ๐
okay so the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this doc get read the way [RFC2119] describes, but only when they show up in ALL CAPS ๐ they can also appear in lowercase, and then they don't carry any of that normative meaning โจ
this spec expects you to already know all the terms and concepts covered in [RFC2616], like "resource", "representation", "cache", and "fresh" ๐ง it got finished before the updated set of HTTP RFCs (RFC 7230 to RFC 7235) dropped, so it specifically points at the older version, RFC 2616 ๐ธ on top of that, it defines the following terms:
Endpoint ๐ฆ An entity taking part in the CoAP protocol. People casually say it lives on a "Node", though "Host" would match Internet standards usage better, and it's further identified by transport-layer multiplexing info, which can include a UDP port number and a security association (Section 4.1).
Sender ๐ The originating endpoint of a message. When you care about pinning down exactly which sender it is, it's also called "source endpoint".
Recipient ๐ The destination endpoint of a message. When the focus is on identifying the specific recipient, it's also called "destination endpoint".
Client ๐ The originating endpoint of a request, and the destination endpoint of a response.
Server ๐ The destination endpoint of a request, and the originating endpoint of a response.
Origin Server ๐ The server on which a given resource resides or is to be created.
Intermediary ๐ซถ A CoAP endpoint that acts both as a server and as a client towards an origin server (possibly via further intermediaries). A common form of intermediary is a proxy, and several classes of proxies get discussed in this specification.
Proxy ๐ง An intermediary that is mainly concerned with forwarding requests and relaying back responses, possibly doing caching, namespace translation, or protocol translation along the way. Unlike intermediaries in the general sense, proxies generally don't implement specific application semantics. Based on where they sit in the overall structure of request forwarding, there are two common forms: forward-proxy and reverse-proxy. In some cases, a single endpoint might act as an origin server, forward-proxy, or reverse-proxy, switching behavior based on the nature of each request โจ
Forward-Proxy ๐ An endpoint selected by a client, usually through local configuration rules, to perform requests on behalf of that client, doing any necessary translations. Some translations are minimal, like proxy requests for coap URIs, whereas other requests might need translation to and from entirely different application-layer protocols.
Reverse-Proxy ๐ก๏ธ An endpoint that stands in for one or more other servers and satisfies requests on their behalf, doing any necessary translations. Unlike a forward-proxy, the client may not be aware that it's talking to a reverse-proxy, since a reverse-proxy receives requests as if it were the origin server for the target resource ๐
CoAP-to-CoAP Proxy ๐ A proxy that maps from a CoAP request to a CoAP request, i.e., it uses the CoAP protocol on both the server and the client side. Contrast this with cross-proxy.
Cross-Proxy ๐ A cross-protocol proxy, or "cross-proxy" for short, is a proxy that translates between different protocols, like a CoAP-to-HTTP proxy or an HTTP-to-CoAP proxy. While this specification makes very specific demands of CoAP-to-CoAP proxies, there's more variation possible in cross-proxies.
Confirmable Message ๐ฌ Some messages require an acknowledgement, and these are called "Confirmable". When no packets are lost, each Confirmable message gets exactly one return message of type Acknowledgement or type Reset.
Non-confirmable Message ๐ Some other messages don't require an acknowledgement. This is especially true for messages that get repeated regularly for application requirements, like repeated readings from a sensor ๐ก๏ธ
Acknowledgement Message โ An Acknowledgement message says that a specific Confirmable message arrived. By itself, it doesn't indicate success or failure of any request encapsulated in the Confirmable message, but it may also carry a Piggybacked Response (see below).
Reset Message ๐ A Reset message says that a specific message (Confirmable or Non-confirmable) was received, but some context is missing to properly process it. This usually happens when the receiving node has rebooted and forgotten some state it needs to interpret the message ๐ฅฒ Provoking a Reset message (e.g., by sending an Empty Confirmable message) is also useful as a cheap check on whether an endpoint is alive, which is called a "CoAP ping" ๐
Piggybacked Response ๐ A piggybacked Response rides right inside a CoAP Acknowledgement (ACK) message that's sent to acknowledge receipt of the Request for this Response (Section 5.2.1). so cute, one trip ๐ซ
Separate Response ๐ฆ When a Confirmable message carrying a request gets acknowledged with an Empty message (e.g., because the server doesn't have the answer right away), a Separate Response gets sent in its own separate message exchange (Section 5.2.2).
Empty Message ๐ซฅ A message with a Code of 0.00, which is neither a request nor a response. An Empty message only contains the 4-byte header.
Critical Option โ ๏ธ An option that the endpoint ultimately receiving the message would need to understand in order to properly process the message (Section 5.4.1). Note that critical options are, as the name "Option" implies, generally optional: unsupported critical options lead to an error response or summary rejection of the message ๐
Elective Option ๐ท An option that's intended to be ignored by an endpoint that doesn't understand it. Processing the message even without understanding the option is acceptable (Section 5.4.1).
Unsafe Option ๐จ An option that a proxy receiving the message would need to understand in order to safely forward the message (Section 5.4.2). Not every critical option is an unsafe option.
Safe-to-Forward Option ๐ An option that's intended to be safe for forwarding by a proxy that doesn't understand it. Forwarding the message even without understanding the option is acceptable (Section 5.4.2).
Resource Discovery ๐ The process where a CoAP client queries a server for its list of hosted resources (i.e., links as defined in Section 7).
Content-Format ๐งพ The combination of an Internet media type, potentially with specific parameters given, and a content-coding (which is often the identity content-coding). It's identified by a numeric identifier defined by the "CoAP Content-Formats" registry. When the focus is less on the numeric identifier and more on the combination of these characteristics of a resource representation, it's also called "representation format" ๐
additional terminology for constrained nodes and constrained-node networks lives in [RFC7228] ๐ฟ
in this spec, "byte" is used in its now customary sense as a synonym for "octet" โจ
all multi-byte integers in this protocol are interpreted in network byte order ๐ข
and where arithmetic shows up, this spec uses the notation you'd recognize from the programming language C, except that the operator ** stands for exponentiation ๐งฎ
2. Constrained Application Protocol ๐ฆ
the interaction model of CoAP is similar to the client/server model of HTTP. BUT machine-to-machine interactions typically end up with a CoAP implementation acting in both the client and server roles ๐ค A CoAP request is equivalent to an HTTP one and gets sent by a client to request an action (using a Method Code) on a resource (identified by a URI) on a server. The server then sends back a response with a Response Code, and this response may include a resource representation ๐
Hmm, "BUT" is not a keyword, but let me avoid all caps accidentally, so I'll correct: the interaction model of CoAP is similar to the client/server model of HTTP. However, machine-to-machine interactions typically end up with a CoAP implementation acting in both the client and server roles ๐ค A CoAP request is equivalent to an HTTP one and gets sent by a client to request an action (using a Method Code) on a resource (identified by a URI) on a server. The server then sends back a response with a Response Code, and this response may include a resource representation ๐
unlike HTTP, CoAP handles these exchanges asynchronously over a datagram-oriented transport like UDP ๐ก It does this logically using a layer of messages that supports optional reliability (with exponential back-off) โณ CoAP defines four types of messages: Confirmable, Non-confirmable, Acknowledgement, and Reset. Method Codes and Response Codes included in some of these messages make them carry requests or responses. The basic exchanges of the four message types are somewhat orthogonal to the request/response interactions. Requests can be carried in Confirmable and Non-confirmable messages, and responses can be carried in these too, as well as piggybacked in Acknowledgement messages ๐งฉ
one could think of CoAP logically as a two-layer approach: a CoAP messaging layer that deals with UDP and the asynchronous nature of the interactions, plus the request/response interactions using Method and Response Codes (see Figure 1) ๐ฐ CoAP is however a single protocol, with messaging and request/response as just features of the CoAP header ๐
+----------------------+
| Application |
+----------------------+
+----------------------+ \
| Requests/Responses | |
|----------------------| | CoAP
| Messages | |
+----------------------+ /
+----------------------+
| UDP |
+----------------------+
Figure 1: Abstract Layering of CoAP ๐ผ๏ธ
2.1. Messaging Model ๐
okay so the CoAP messaging model is all about trading messages over UDP between endpoints ๐จโจ
CoAP uses a short, fixed-length binary header (4 bytes) ๐ that can be followed by compact binary options and a payload. The same message format is used for both requests and responses. The full message format is in Section 3. Every message carries a Message ID, which is used to detect duplicates and for optional reliability. (The Message ID is compact, and its 16-bit size lets one endpoint send up to about 250 messages per second to another with the default protocol parameters ๐ง)
Reliability comes from marking a message as Confirmable (CON) ๐ซถ. A Confirmable message gets retransmitted using a default timeout and exponential back-off between retransmissions, until the recipient sends back an Acknowledgement message (ACK) with the same Message ID (in this example, 0x7d34) from the matching endpoint. Check out Figure 2 ๐ . When a recipient can't process a Confirmable message at all (meaning it can't even send a suitable error response), it replies with a Reset message (RST) instead of an Acknowledgement (ACK) ๐.
Client Server
| |
| CON [0x7d34] |
+----------------->|
| |
| ACK [0x7d34] |
|<-----------------+
| |
Figure 2: Reliable Message Transmission
A message that doesn't need reliable delivery (like one single reading out of a stream of sensor data) can be sent as a Non-confirmable message (NON) ๐ธ. These don't get acknowledged, but they still have a Message ID for duplicate detection (in this example, 0x01a0). See Figure 3 โจ. When a recipient can't process a Non-confirmable message, it may reply with a Reset message (RST).
Client Server
| |
| NON [0x01a0] |
+----------------->|
| |
Figure 3: Unreliable Message Transmission
For details on CoAP messages, see Section 4 ๐.
Since CoAP runs over UDP, it can also use multicast IP destination addresses, which means multicast CoAP requests are a thing ๐ฆ. Section 8 covers how to use CoAP messages with multicast addresses properly, plus precautions for avoiding response congestion.
Several security modes are defined for CoAP in Section 9, ranging from no security at all to certificate-based security ๐. This document specifies a binding to DTLS for securing the protocol. The use of IPsec with CoAP is discussed in [IPsec-CoAP].
2.2. Request/Response Model ๐
CoAP request and response semantics ride along in CoAP messages. Those messages include either a Method Code or a Response Code, depending on which side is talking ๐ฌ. Optional (or default) request and response info, like the URI and payload media type, gets carried as CoAP options. A Token is used to match responses to requests, separately from the underlying messages (Section 5.3). (The Token is its own concept, totally separate from the Message ID, so don't mix them up ๐)
A request goes out in a Confirmable (CON) or Non-confirmable (NON) message. If the response to a request sent in a Confirmable message is immediately available, it comes back inside the resulting Acknowledgement (ACK) message. This is called a piggybacked response, and Section 5.2.1 has the details ๐ฅฐ. (There's no need to separately acknowledge a piggybacked response, because the client will retransmit the request if the Acknowledgement carrying the piggybacked response gets lost.) Figure 4 shows two basic GET requests with piggybacked responses: one succeeds, and one comes back as a 4.04 (Not Found) ๐.
Client Server Client Server
| | | |
| CON [0xbc90] | | CON [0xbc91] |
| GET /temperature | | GET /temperature |
| (Token 0x71) | | (Token 0x72) |
+----------------->| +----------------->|
| | | |
| ACK [0xbc90] | | ACK [0xbc91] |
| 2.05 Content | | 4.04 Not Found |
| (Token 0x71) | | (Token 0x72) |
| "22.5 C" | | "Not found" |
|<-----------------+ |<-----------------+
| | | |
Figure 4: Two GET Requests with Piggybacked Responses
If the server can't respond right away to a request in a Confirmable message, it just sends back an Empty Acknowledgement message so the client can stop retransmitting the request ๐. When the response is ready, the server sends it in a brand-new Confirmable message, which the client then needs to acknowledge in turn ๐. This is called a "separate response", and it's shown in Figure 5 and explained further in Section 5.2.2 โณ.
Client Server
| |
| CON [0x7a10] |
| GET /temperature |
| (Token 0x73) |
+----------------->|
| |
| ACK [0x7a10] |
|<-----------------+
| |
... Time Passes ...
| |
| CON [0x23bb] |
| 2.05 Content |
| (Token 0x73) |
| "22.5 C" |
|<-----------------+
| |
| ACK [0x23bb] |
+----------------->|
| |
Figure 5: A GET Request with a Separate Response
If a request is sent in a Non-confirmable message, the response goes back in a new Non-confirmable message. That said, the server may instead send a Confirmable message ๐คทโโ๏ธ. Figure 6 shows this kind of exchange.
Client Server
| |
| NON [0x7a11] |
| GET /temperature |
| (Token 0x74) |
+----------------->|
| |
| NON [0x23bc] |
| 2.05 Content |
| (Token 0x74) |
| "22.5 C" |
|<-----------------+
| |
Figure 6: A Request and a Response Carried in Non-confirmable Messages
CoAP uses GET, PUT, POST, and DELETE in a similar way to HTTP, and the semantics are in Section 5.8 ๐ . (Heads up, the detailed semantics of CoAP methods are "almost, but not entirely unlike" [HHGTTG] those of HTTP methods ๐. Intuition from HTTP experience generally does apply well, but there are enough differences that it's worth actually reading this spec.)
Methods beyond the basic four can be added to CoAP in separate specifications. New methods don't necessarily have to work in request/response pairs. Even for existing methods, a single request can produce multiple responses, for example with a multicast request (Section 8) or with the Observe option [OBSERVE] ๐.
URI support in a server is simplified, because the client already parses the URI and splits it into host, port, path, and query components, using default values for efficiency โก. Response Codes relate to a small subset of HTTP status codes, plus a few CoAP-specific codes, as defined in Section 5.9 ๐.
2.3. Intermediaries and Caching ๐ง
The protocol supports caching responses so requests can be fulfilled efficiently ๐. Simple caching is enabled through freshness and validity information carried with CoAP responses. A cache can live in an endpoint or in an intermediary. Caching functionality is specified in Section 5.6.
Proxying is useful in constrained networks for a bunch of reasons: limiting network traffic, improving performance, accessing resources on sleeping devices, and security ๐. Proxying requests on behalf of another CoAP endpoint is supported by the protocol. When using a proxy, the URI of the resource to request is included in the request, while the destination IP address is set to the proxy's address. Section 5.7 has more on proxy functionality.
CoAP was designed according to the REST architecture [REST], so it has functionality similar to HTTP. That makes it pretty straightforward to map CoAP to HTTP and HTTP to CoAP ๐. Such a mapping can realize an HTTP REST interface using CoAP, or convert between HTTP and CoAP. The conversion can be done by a cross-protocol proxy ("cross-proxy"), which converts the Method or Response Code, media type, and options into the matching HTTP feature. Section 10 has more detail about HTTP mapping.
2.4. Resource Discovery ๐
Resource discovery matters a lot for machine-to-machine interactions, and it's supported using the CoRE Link Format [RFC6690], as discussed in Section 7 ๐ซง.
3. Message Format ๐ฆโจ
okay bestie, this is where the actual packets come in ๐ซถ CoAP messages are super compact and by default they ride over UDP, so each CoAP message fills the data section of one UDP datagram ๐ฆ You can also run CoAP over Datagram Transport Layer Security (DTLS), which is covered in Section 9.1 ๐ It could also work over other transports like SMS, TCP, or SCTP, but those are out of scope for this doc ๐ Also, UDP-lite [RFC3828] and the UDP zero checksum [RFC6936] are NOT supported by CoAP ๐
Every CoAP message is encoded in a simple binary format. It starts with a fixed-size 4-byte header, then a variable-length Token value that can be between 0 and 8 bytes long ๐
After the Token comes zero or more CoAP Options, in Type-Length-Value (TLV) format. A payload can follow them, and it takes up the rest of the datagram ๐ธ
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Ver| T | TKL | Code | Message ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Token (if any, TKL bytes) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options (if any) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|1 1 1 1 1 1 1 1| Payload (if any) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 7: Message Format
Here's the header breakdown, bestie ๐
- Version (Ver): 2-bit unsigned integer that shows the CoAP version number. Implementations of this spec MUST set this field to 1 (
01binary). Other values are reserved for future versions. Messages with unknown version numbers MUST be silently ignored ๐ - Type (T): 2-bit unsigned integer that tells you if the message is Confirmable (
0), Non-confirmable (1), Acknowledgement (2), or Reset (3). The semantics for these message types are in Section 4 ๐ฆ - Token Length (TKL): 4-bit unsigned integer for the length of the Token field (0-8 bytes). Lengths 9-15 are reserved, MUST NOT be sent, and MUST be processed as a message format error. not me reading that and going "absolutely not" ๐ญ
- Code: 8-bit unsigned integer, split into a 3-bit class (the most significant bits) and a 5-bit detail (the least significant bits). It's written as "c.dd", where "c" is a digit from 0 to 7 and "dd" is two digits from 00 to 31. The class can mean a request (0), a success response (2), a client error response (4), or a server error response (5). All other class values are reserved. Code 0.00 is a special case that means an Empty message. For requests, the Code field is the Request Method. For responses, it's a Response Code. Possible values live in the CoAP Code Registries (Section 12.1), and the semantics of requests and responses are in Section 5 ๐
- Message ID: 16-bit unsigned integer in network byte order. It's used to detect duplicate messages and to match Acknowledgement/Reset messages to Confirmable/Non-confirmable ones. The rules for generating a Message ID and matching messages are in Section 4 โจ
The Token value follows the header, and its size comes from the Token Length field (0 to 8 bytes). The Token is how requests and responses get correlated, and the rules for generating a Token and correlating them are in Section 5.3.1 ๐
Header and Token are followed by zero or more Options (Section 3.1). An Option can be followed by the end of the message, by another Option, or by the Payload Marker and the payload ๐
After the header, token, and options (if there are any), there's the optional payload. If it's there and has non-zero length, it gets a fixed, one-byte Payload Marker (0xFF) in front. The marker is how you know the options are done and the payload starts ๐ซถ The payload data runs from right after the marker to the end of the UDP datagram, so the Payload Length gets calculated from the datagram size ๐ธ No marker means a zero-length payload. A marker followed by a zero-length payload MUST be processed as a message format error ๐
Implementation Note: the byte value0xFFcan also show up inside an option length or value, so you can't just scan bytes for0xFFto find the payload marker.0xFFonly counts as a payload marker where the start of another option could happen ๐
3.1. Option Format
CoAP defines a bunch of options that can go in a message. Each option instance says which Option Number it is, how long its Option Value is, and what that Option Value is ๐ง
Here's the twist: the instances MUST appear in order of their Option Numbers, and they use delta encoding between them. Each instance's Option Number is its delta added to the Option Number of the instance before it in the message. For the first instance, the one before it is assumed to be Option Number zero. You can include multiple instances of the same option by using a delta of zero ๐
Option Numbers are kept in the "CoAP Option Numbers" registry (Section 12.2). For the semantics of the options defined in this document, check Section 5.4 ๐
0 1 2 3 4 5 6 7
+---------------+---------------+
| | |
| Option Delta | Option Length | 1 byte
| | |
+---------------+---------------+
\ \
/ Option Delta / 0-2 bytes
\ (extended) \
+-------------------------------+
\ \
/ Option Length / 0-2 bytes
\ (extended) \
+-------------------------------+
\ \
/ /
\ \
/ Option Value / 0 or more bytes
\ \
/ /
\ \
+-------------------------------+
Figure 8: Option Format
Here are the fields in an option ๐ฆ
- Option Delta: 4-bit unsigned integer. A value from 0 to 12 is the Option Delta itself. Three values are reserved for special constructs:
13: an 8-bit unsigned integer follows the initial byte and holds the Option Delta minus 13.14: a 16-bit unsigned integer in network byte order follows the initial byte and holds the Option Delta minus 269.15: reserved for the Payload Marker. If the field is set to this value but the whole byte isn't the payload marker, it MUST be processed as a message format error.
The resulting Option Delta is the gap between this option's Option Number and the previous one's (or zero for the first option). Basically, the Option Number is just all the Option Deltas of this option and every option before it, summed up ๐งฎ
- Option Length: 4-bit unsigned integer. A value from 0 to 12 is the length of the Option Value in bytes. Three values are reserved for special constructs:
13: an 8-bit unsigned integer comes before the Option Value and holds the Option Length minus 13.14: a 16-bit unsigned integer in network byte order comes before the Option Value and holds the Option Length minus 269.15: reserved for future use. If the field is set to this value, it MUST be processed as a message format error.
- Value: a sequence of exactly Option Length bytes. The length and format of the Option Value depend on the option, and it MAY define variable-length values. Section 3.2 has the formats used in this document. Options defined in other documents MAY use other option value formats ๐ธ
3.2. Option Value Formats
The options defined in this document use the following option value formats ๐
empty: a zero-length sequence of bytes.opaque: an opaque sequence of bytes.uint: a non-negative integer, represented in network byte order using however many bytes the Option Length field says. An option definition can specify a range of allowed byte counts. If there's a choice, a sender SHOULD represent the integer with as few bytes as possible, meaning no leading zero bytes. For example, the number 0 is an empty option value (zero-length), and the number 1 is a single byte with the value 1 (bit combination00000001, most significant bit first). A recipient MUST be prepared to process values with leading zero bytes ๐ง
Implementation Note: the exception allowed for senders is meant for highly constrained, templated implementations (like hardware ones) that use fixed-size options in their templates ๐ค
Here's the vibe: wherever UTF-8 encoding shows up in CoAP, the encoded strings can be used and compared directly as opaque byte strings by CoAP implementations. There's no expectation or need to normalize inside a CoAP implementation, except when Unicode strings that aren't known to be normalized get imported from sources outside CoAP. Also, ASCII strings (without special control characters) are always valid UTF-8 Net-Unicode strings โจ
4. Message Transmission ๐
CoAP messages get exchanged asynchronously between CoAP endpoints. They carry CoAP requests and responses, whose semantics are in Section 5 ๐
Since CoAP sits on unreliable transports like UDP, CoAP messages may arrive out of order, show up duplicated, or just vanish without notice ๐ญ So CoAP has a lightweight reliability mechanism, and it doesn't try to rebuild everything TCP does. It has these features:
- Simple stop-and-wait retransmission reliability with exponential back-off for Confirmable messages.
- Duplicate detection for both Confirmable and Non-confirmable messages.
4.1. Messages and Endpoints โจ
okay so a CoAP endpoint is just whatever is the source or destination of a CoAP message ๐ what counts as an endpoint depends on the transport you're using. for the transports in this spec, it depends on the security mode (see Section 9) ๐. with no security, an endpoint is literally just an IP address plus a UDP port number ๐ฆ. with other security modes, it's identified however that security mode defines it ๐
there are different types of messages, and the Type field in the CoAP Header tells you which one you've got ๐
separate from the type, a message can carry a request, carry a response, or be Empty ๐ธ that's signaled by the Request/Response Code field in the CoAP Header, and it's the bit that matters for the request/response model ๐ซถ the possible values live in the CoAP Code Registries (Section 12.1) ๐
an Empty message has the Code field set to 0.00 ๐ง the Token Length field MUST be set to 0, and bytes of data MUST NOT show up after the Message ID field ๐ if there are any bytes there anyway, they MUST be processed as a message format error ๐
4.2. Messages Transmitted Reliably ๐
so reliable transmission starts when you mark a message as Confirmable in the CoAP header ๐ a Confirmable message always carries either a request or a response, unless it's only there to get a Reset message back, in which case it's Empty ๐ง
here's the big rule: a recipient MUST either (a) acknowledge the Confirmable message with an Acknowledgement message, or (b) reject it if the recipient doesn't have the context to process it properly โจ that includes when the message is Empty, uses a code from a reserved class (1, 6, or 7), or has a message format error ๐ญ rejecting a Confirmable message means sending a matching Reset message and otherwise ignoring it ๐
the Acknowledgement message MUST echo the Message ID of the Confirmable message, and it MUST carry a response or be Empty (see Sections 5.2.1 and 5.2.2) ๐ the Reset message MUST echo the Message ID of the Confirmable message, and it MUST be Empty ๐
rejecting an Acknowledgement or Reset message (including when the Acknowledgement carries a request or a code with a reserved class, or when the Reset message isn't Empty) just means silently ignoring it ๐คซ and more generally, recipients of Acknowledgement and Reset messages MUST NOT respond with either an Acknowledgement or a Reset message ๐ โโ๏ธ no ping-pong, bestie ๐
the sender keeps retransmitting the Confirmable message at exponentially increasing intervals ๐ until it gets an acknowledgement (or a Reset message), or it runs out of attempts ๐ฅฒ
retransmission is controlled by two things that a CoAP endpoint MUST keep track of for each Confirmable message it sends while it's waiting for an acknowledgement (or reset) ๐ those are a timeout and a retransmission counter ๐ for a brand new Confirmable message, the initial timeout is set to a random duration (often not a whole number of seconds) between ACK_TIMEOUT and (ACK_TIMEOUT * ACK_RANDOM_FACTOR) (see Section 4.8), and the retransmission counter starts at 0 ๐ฒ when the timeout triggers and the retransmission counter is less than MAX_RETRANSMIT, the message gets retransmitted, the counter goes up by one, and the timeout doubles โซ if the counter hits MAX_RETRANSMIT on a timeout, or the endpoint gets a Reset message, then the attempt is canceled and the application process is told it failed ๐ but if the endpoint gets an acknowledgement in time, the transmission counts as successful ๐
this spec doesn't make strong demands on how accurate the clocks are that run that binary exponential back-off algorithm โฐ an endpoint might be late for a specific retransmission because of its sleep schedule and then catch up on the next one ๐ด still, the minimum gap before another retransmission is ACK_TIMEOUT, and the whole sequence of (re-)transmissions MUST stay inside the envelope of MAX_TRANSMIT_SPAN (see Section 4.8.2), even if that means the sender misses a chance to transmit โณ no cap, that's a hard boundary ๐ง
a CoAP endpoint that sent a Confirmable message MAY give up on getting an ACK even before the MAX_RETRANSMIT counter value is reached ๐ณ๏ธ for example, the application canceled the request because it doesn't need a response anymore, or there's some other sign that the CON message did arrive ๐ฌ especially when a CoAP request got a separate response, the requester knows only the ACK got lost, so retransmitting the request wouldn't do anything ๐ but a responder MUST NOT rely on this cross-layer behavior from a requester ๐ซ it MUST keep the state needed to create the ACK for the request, if needed, even when the requester already acknowledged a Confirmable response ๐ง main character responder energy ๐
another reason to stop retransmitting MAY be receiving ICMP errors ๐ if you do want to take ICMP errors into account (to guard against potential spoofing attacks ๐ต๏ธ), implementations SHOULD carefully check the information about the original datagram inside the ICMP message, including port numbers and CoAP header info like message type and code, Message ID, and Token ๐ if that's not possible because of limits in the UDP service API, ICMP errors SHOULD be ignored ๐
Packet Too Big errors [RFC4443] ("fragmentation needed and DF set" for IPv4 [RFC0792]) cannot properly occur, and they SHOULD be ignored if the implementation note in Section 4.6 is followed ๐ซ otherwise, they SHOULD feed into a path MTU discovery algorithm [RFC4821] ๐ค๏ธ Source Quench and Time Exceeded ICMP messages SHOULD be ignored too ๐ โโ๏ธ and host, network, port, or protocol unreachable errors or parameter problem errors MAY, after appropriate vetting, be used to tell the application that sending failed ๐ฃ
4.3. Messages Transmitted without Reliability ๐ฆ
not every message needs an acknowledgement ๐ this is super true for messages that get repeated regularly for application needs, like repeated sensor readings where eventual success is totally fine ๐ก๏ธโจ
as a more lightweight option, you can send a message less reliably by marking it Non-confirmable ๐ชถ a Non-confirmable message always carries a request or response, and it MUST NOT be Empty ๐ โโ๏ธ a Non-confirmable message MUST NOT be acknowledged by the recipient ๐ซ a recipient MUST reject the message if it doesn't have the context to process it properly, including when the message is Empty, uses a code from a reserved class (1, 6, or 7), or has a message format error ๐ rejecting a Non-confirmable message MAY involve sending a matching Reset message, but apart from that Reset message, the rejected message MUST be silently ignored ๐คซ
at the CoAP level, the sender has no way of knowing whether a Non-confirmable message was received ๐ซฅ a sender MAY choose to send multiple copies of a Non-confirmable message within MAX_TRANSMIT_SPAN (limited by the rules in Section 4.7, especially PROBING_RATE if no response comes back) ๐ or the network might duplicate the message in transit ๐ฏ so that the receiver only acts on the message once, Non-confirmable messages also get a Message ID ๐ (this Message ID comes from the same number space as the Message IDs for Confirmable messages ๐ข)
quick recap of Sections 4.2 and 4.3: the four message types can be used like in Table 1 ๐ a "*" means the combo isn't used in normal operation and is only there to get a Reset message back (a "CoAP ping") ๐
+----------+-----+-----+-----+-----+
| | CON | NON | ACK | RST |
+----------+-----+-----+-----+-----+
| Request | X | X | - | - |
| Response | X | X | X | - |
| Empty | * | - | X | X |
+----------+-----+-----+-----+-----+
Table 1: Usage of Message Types
4.4. Message Correlation ๐
an Acknowledgement or Reset message gets matched up with a Confirmable or Non-confirmable message using the Message ID, plus the address info of the corresponding endpoint ๐บ๏ธ the Message ID is a 16-bit unsigned integer generated by the sender of a Confirmable or Non-confirmable message and included in the CoAP header ๐ข the Message ID MUST be echoed in the Acknowledgement or Reset message by the recipient ๐ช
the same Message ID MUST NOT be reused (when talking to the same endpoint) within the EXCHANGE_LIFETIME (Section 4.8.2) โณ no recycling IDs too early, periodt ๐
Implementation Note: there are a few ways to generate Message IDs ๐ง in the simplest case, a CoAP endpoint keeps one Message ID variable and changes it every time it sends a new Confirmable or Non-confirmable message, no matter the destination address or port ๐ฏ endpoints handling tons of transactions could keep multiple Message ID variables, for example one per prefix or destination address ๐ฆ (heads up: some receiving endpoints might not be able to tell unicast and multicast packets addressed to them apart, so endpoints generating Message IDs need to make sure those don't overlap โ ๏ธ) it is strongly recommended that the initial value of the variable (e.g., on startup) be randomized, so successful off-path attacks on the protocol are less likely ๐ฒ๐
for an Acknowledgement or Reset message to match a Confirmable or Non-confirmable message, the Message ID and source endpoint of the Acknowledgement or Reset message MUST match the Message ID and destination endpoint of the Confirmable or Non-confirmable message ๐ perfect match or no match, bestie โจ
4.5. Message Deduplication ๐
okay so bestie, a recipient can get the same Confirmable message (same Message ID and source endpoint) more than once inside the EXCHANGE_LIFETIME (Section 4.8.2) ๐ญ This happens when the Acknowledgement went missing, or didn't reach the original sender before the first timeout. The recipient SHOULD acknowledge each duplicate copy using the same Acknowledgement or Reset message, but it SHOULD process any request or response in the message only once โจ This rule MAY be relaxed if the Confirmable message carries a request that is idempotent (see Section 5.1) or can be handled in an idempotent fashion. Here are some examples of relaxed deduplication ๐ฆ
- A server might relax the requirement to answer all retransmissions of an idempotent request with the same response (Section 4.2), so that it doesn't have to keep state for Message IDs. For example, an implementation might want to process duplicate transmissions of a GET, PUT, or DELETE request as separate requests, if the effort of duplicate processing is less expensive than keeping track of previous responses would be. ๐ง
- A constrained server might even want to relax this requirement for certain non-idempotent requests, if the application semantics make this trade-off favorable. For example, if the result of a POST request is just the creation of some short-lived state at the server, it may be less expensive to pay this effort multiple times than to keep track of whether a previous transmission of the same request was already processed ๐
A recipient might receive the same Non-confirmable message (same Message ID and source endpoint) multiple times within NON_LIFETIME (Section 4.8.2). As a general rule that MAY be relaxed based on the specific semantics of a message, the recipient SHOULD silently ignore any duplicated Non-confirmable message, and SHOULD process any request or response in the message only once ๐ธ
4.6. Message Size ๐
okay this one is giving "it depends on your link layer" ๐ Specific link layers make it beneficial to keep CoAP messages small enough to fit into their link-layer packets (see Section 1), but honestly this is a matter of implementation quality. The CoAP specification itself only gives an upper bound to the message size. Messages bigger than an IP packet cause undesirable packet fragmentation ๐ A CoAP message, appropriately encapsulated, SHOULD fit within a single IP packet (so, avoid IP fragmentation), and (by fitting into one UDP payload) obviously needs to fit within a single IP datagram. If the Path MTU isn't known for a destination, an IP MTU of 1280 bytes SHOULD be assumed. If nothing is known about the size of the headers, good upper bounds are 1152 bytes for the message size and 1024 bytes for the payload size โจ
Implementation Note: CoAP's choice of message size parameters works really well with IPv6 and with most of today's IPv4 paths ๐ (However, with IPv4 it's harder to absolutely ensure there is no IP fragmentation. If IPv4 support on unusual networks is a consideration, implementations may want to limit themselves to more conservative IPv4 datagram sizes such as 576 bytes. Per [RFC0791], the absolute minimum value of the IP MTU for IPv4 is as low as 68 bytes, which would leave only 40 bytes minus security overhead for a UDP payload. Implementations extremely focused on this problem might also set the IPv4 DF bit and perform some form of path MTU discovery [RFC4821]; this should generally be unnecessary in realistic use cases for CoAP, however.) A more important kind of fragmentation in many constrained networks happens on the adaptation layer (e.g., 6LoWPAN L2 packets are limited to 127 bytes including various overheads). This may motivate implementations to be frugal in their packet sizes and to move to block-wise transfers [BLOCK] when approaching three-digit message sizes ๐ง
Message sizes matter a lot to implementations on constrained nodes too ๐ฅบ Many implementations need to allocate a buffer for incoming messages. If an implementation is too constrained to allocate the upper bound above, it could apply the following strategy for messages not using DTLS security. Implementations that receive a datagram into a buffer that is too small are usually able to tell whether the trailing part of the datagram was discarded, and to retrieve the initial part. So at least the CoAP header and options, if not all of the payload, are likely to fit within the buffer. A server can therefore fully interpret a request and return a 4.13 (Request Entity Too Large; see Section 5.9.2.9) Response Code if the payload was truncated. A client sending an idempotent request, and receiving a response larger than would fit in the buffer, can repeat the request with a suitable value for the Block Option [BLOCK] ๐ซถ
4.7. Congestion Control ๐
basic congestion control for CoAP comes from the exponential back-off mechanism in Section 4.2 ๐ฅ
So in order not to cause congestion, clients (including proxies) MUST strictly limit the number of simultaneous outstanding interactions they maintain to a given server (including proxies) to NSTART ๐ โโ๏ธ An outstanding interaction is either a CON for which an ACK has not yet been received but is still expected (message layer), or a request for which neither a response nor an Acknowledgment message has been received yet but is still expected. These two can both happen at the same time, and they count as one outstanding interaction. The default value of NSTART for this specification is 1 โญ
More congestion control optimizations and considerations are expected in the future. They may, for example, provide automatic initialization of the CoAP transmission parameters defined in Section 4.8, and thus may allow a value for NSTART greater than one ๐
After EXCHANGE_LIFETIME, a client stops expecting a response to a Confirmable request for which no acknowledgment message was received ๐ฆ
The specific algorithm by which a client stops "expecting" a response to a Confirmable request that was acknowledged, or to a Non-confirmable request, is not defined. Unless this is modified by additional congestion control optimizations, it MUST be chosen so that an endpoint does not exceed an average data rate of PROBING_RATE when sending to another endpoint that does not respond ๐
Note: CoAP puts the onus of congestion control mostly on the clients. But clients may malfunction or actually be attackers, e.g., to perform amplification attacks (Section 11.3). To limit the damage (to the network and to its own energy resources), a server SHOULD implement some rate limiting for its response transmission, based on reasonable assumptions about application requirements. This is most helpful if the rate limit can be made effective for the misbehaving endpoints only. ๐จ
4.8. Transmission Parameters ๐
message transmission is controlled by the following parameters, and the defaults are:
+-------------------+---------------+
| name | default value |
+-------------------+---------------+
| ACK_TIMEOUT | 2 seconds |
| ACK_RANDOM_FACTOR | 1.5 |
| MAX_RETRANSMIT | 4 |
| NSTART | 1 |
| DEFAULT_LEISURE | 5 seconds |
| PROBING_RATE | 1 byte/second |
+-------------------+---------------+
Table 2: CoAP Protocol Parameters
4.8.1. Changing the Parameters ๐ง
the values for ACK_TIMEOUT, ACK_RANDOM_FACTOR, MAX_RETRANSMIT, NSTART, DEFAULT_LEISURE (Section 8.2), and PROBING_RATE may be configured to values specific to the application environment (including dynamically adjusted values). However, the configuration method is out of scope for this document ๐ It is RECOMMENDED that an application environment use consistent values for these parameters. The specific effects of running with inconsistent values in an application environment are outside the scope of this specification.
The transmission parameters were chosen to achieve behavior under congestion that is safe on the Internet ๐ If a configuration wants to use different values, the onus is on that configuration to make sure these congestion control properties are not violated. In particular, a decrease of ACK_TIMEOUT below 1 second would violate the guidelines of [RFC5405]. ([RTO-CONSIDER] provides some additional background.) CoAP was designed to enable implementations that do not maintain round-trip-time (RTT) measurements. However, where it is desired to decrease ACK_TIMEOUT significantly or increase NSTART, this can only be done safely when such measurements are maintained. Configurations MUST NOT decrease ACK_TIMEOUT or increase NSTART without using mechanisms that ensure congestion control safety, either defined in the configuration or in future standards documents. Not optional, bestie ๐ซ
ACK_RANDOM_FACTOR MUST NOT be decreased below 1.0, and it SHOULD have a value sufficiently different from 1.0 to provide some protection from synchronization effects โจ
MAX_RETRANSMIT can be freely adjusted. A value that is too small will reduce the probability that a Confirmable message is actually received, while a larger value than given here will require further adjustments in the time values (see Section 4.8.2) ๐ง
If the choice of transmission parameters leads to an increase of derived time values (see Section 4.8.2), the configuration mechanism MUST ensure the adjusted value is also available to all the endpoints with which these adjusted values are used to communicate. So everyone's on the same page, periodt ๐ ๐ซถ
4.8.2. Time Values Derived from Transmission Parameters ๐
okay so ACK_TIMEOUT, ACK_RANDOM_FACTOR, and MAX_RETRANSMIT together decide the timing of retransmissions โฐ, and that timing decides how long an implementation has to hang onto certain information items ๐ซถ. so we give these derived time values names, so we can reference them without any confusion โจ
MAX_TRANSMIT_SPANis the maximum time from the first transmission of a Confirmable message to its last retransmission. for the default transmission parameters it's (2+4+8+16)*1.5 = 45 seconds, or more generally:
ACK_TIMEOUT * ((2 ** MAX_RETRANSMIT) - 1) * ACK_RANDOM_FACTOR
MAX_TRANSMIT_WAITis the maximum time from the first transmission of a Confirmable message to the moment the sender gives up on waiting for an acknowledgement or reset ๐ฅบ. for the default transmission parameters it's (2+4+8+16+32)*1.5 = 93 seconds, or more generally:
ACK_TIMEOUT * ((2 ** (MAX_RETRANSMIT + 1)) - 1) *
ACK_RANDOM_FACTOR
in addition, we have to make some assumptions about the characteristics of the network and the nodes ๐
MAX_LATENCYis the maximum time a datagram is expected to take from the start of its transmission to the completion of its reception. this constant is related to the MSL (Maximum Segment Lifetime) of [RFC0793], which is "arbitrarily defined to be 2 minutes" ([RFC0793] glossary, page 81). now, this is not necessarily smaller thanMAX_TRANSMIT_WAIT, becauseMAX_LATENCYisn't meant to describe a situation where the protocol works well ๐. it's the worst-case situation the protocol has to guard against. we also arbitrarily defineMAX_LATENCYto be 100 seconds ๐ฏ. apart from being reasonably realistic for the bulk of configurations, and being close to the historic choice for TCP, this value also lets Message ID lifetime timers be represented in 8 bits (when measured in seconds) ๐ง. in these calculations, there is no assumption that the direction of the transmission is irrelevant (i.e., that the network is symmetric). there's just the assumption that the same value can reasonably be used as a maximum value for both directions. if that is not the case, the following calculations become only slightly more complex ๐คPROCESSING_DELAYis the time a node takes to turn around a Confirmable message into an acknowledgement. we assume the node will attempt to send an ACK before the sender times out, so as a conservative assumption we set it equal toACK_TIMEOUTโกMAX_RTTis the maximum round-trip time, or:
(2 * MAX_LATENCY) + PROCESSING_DELAY
from these values, we can derive the following values relevant to protocol operation ๐ฆ
EXCHANGE_LIFETIMEis the time from starting to send a Confirmable message to the time when an acknowledgement is no longer expected. at that point, message-layer information about the message exchange can be purged ๐งน.EXCHANGE_LIFETIMEincludes aMAX_TRANSMIT_SPAN, aMAX_LATENCYforward,PROCESSING_DELAY, and aMAX_LATENCYfor the way back. there's no need to considerMAX_TRANSMIT_WAITif the configuration is chosen such that the last waiting period (ACK_TIMEOUT * (2 ** MAX_RETRANSMIT)or the difference betweenMAX_TRANSMIT_SPANandMAX_TRANSMIT_WAIT) is less thanMAX_LATENCY. and that's a likely choice, becauseMAX_LATENCYis a worst-case value that's unlikely to be met in the real world ๐ธ. in this case,EXCHANGE_LIFETIMEsimplifies to:
MAX_TRANSMIT_SPAN + (2 * MAX_LATENCY) + PROCESSING_DELAY
or 247 seconds with the default transmission parameters ๐
NON_LIFETIMEis the time from sending a Non-confirmable message to the time its Message ID can be safely reused. if multiple transmissions of a NON message aren't used, its value isMAX_LATENCY, or 100 seconds. however, a CoAP sender might send a NON message multiple times, especially for multicast applications ๐ก. while the period of reuse isn't bounded by the specification, the expectation of reliable duplicate detection at the receiver is on the timescales ofMAX_TRANSMIT_SPAN. so for this purpose, it's safer to use the value:
MAX_TRANSMIT_SPAN + MAX_LATENCY
or 145 seconds with the default transmission parameters. however, an implementation that just wants a single timeout value for retiring Message IDs can safely use the larger value for EXCHANGE_LIFETIME ๐ซถ
Table 3 lists the derived parameters introduced in this subsection, along with their default values ๐
+-------------------+---------------+
| name | default value |
+-------------------+---------------+
| MAX_TRANSMIT_SPAN | 45 s |
| MAX_TRANSMIT_WAIT | 93 s |
| MAX_LATENCY | 100 s |
| PROCESSING_DELAY | 2 s |
| MAX_RTT | 202 s |
| EXCHANGE_LIFETIME | 247 s |
| NON_LIFETIME | 145 s |
+-------------------+---------------+
Table 3: Derived Protocol Parameters
5. Request/Response Semantics ๐
CoAP runs a request/response model that's a lot like HTTP ๐. a CoAP endpoint in the role of a "client" sends one or more CoAP requests to a "server", and the server services those requests by sending CoAP responses. the difference from HTTP is that requests and responses aren't sent over a previously established connection. instead, they're exchanged asynchronously over CoAP messages ๐ฆ
5.1. Requests ๐ฎ
a CoAP request consists of the method to be applied to the resource, the identifier of the resource, a payload and Internet media type (if any), and optional metadata about the request โจ
CoAP supports the basic methods of GET, POST, PUT, and DELETE, which map easily to HTTP ๐. they have the same properties as HTTP of being safe (only retrieval) and idempotent (you can invoke them multiple times with the same effects) (see Section 9.1 of [RFC2616]) ๐ง . the GET method is safe, so it MUST NOT take any action on a resource other than retrieval. the GET, PUT, and DELETE methods MUST be performed in such a way that they are idempotent. POST is not idempotent, because its effect is determined by the origin server and depends on the target resource. it usually results in a new resource being created or the target resource being updated ๐
a request is initiated by setting the Code field in the CoAP header of a Confirmable or a Non-confirmable message to a Method Code, and including request information ๐
the methods used in requests are described in detail in Section 5.8 ๐
5.2. Responses ๐
after receiving and interpreting a request, a server responds with a CoAP response. that response is matched to the request by means of a client-generated token (Section 5.3). note that this is different from the Message ID, which matches a Confirmable message to its Acknowledgement ๐งฉ
a response is identified by the Code field in the CoAP header being set to a Response Code. similar to the HTTP Status Code, the CoAP Response Code indicates the result of the attempt to understand and satisfy the request. these codes are fully defined in Section 5.9 ๐. the Response Code numbers to be set in the Code field of the CoAP header are maintained in the CoAP Response Code Registry (Section 12.1.2) ๐๏ธ
0
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|class| detail |
+-+-+-+-+-+-+-+-+
Figure 9: Structure of a Response Code
the upper three bits of the 8-bit Response Code number define the class of response. the lower five bits don't have any categorization role. they just give additional detail to the overall class (Figure 9) ๐
as a human-readable notation for specifications and protocol diagnostics, CoAP code numbers including the Response Code are documented in the format "c.dd". here "c" is the class in decimal, and "dd" is the detail as a two-digit decimal. for example, "Forbidden" is written as 4.03, which means an 8-bit code value of hexadecimal 0x83 (4*0x20+3) or decimal 131 (4*32+3) ๐
there are 3 classes of Response Codes:
- 2 - Success: the request was successfully received, understood, and accepted ๐ฅณ
- 4 - Client Error: the request contains bad syntax or cannot be fulfilled ๐ฌ
- 5 - Server Error: the server failed to fulfill an apparently valid request ๐
the Response Codes are designed to be extensible. Response Codes in the Client Error or Server Error class that an endpoint doesn't recognize are treated as equivalent to the generic Response Code of that class (4.00 and 5.00, respectively). however, there is no generic Response Code indicating success. so a Response Code in the Success class that an endpoint doesn't recognize can only be used to determine that the request was successful, without any further details ๐
the possible Response Codes are described in detail in Section 5.9 ๐ฎ
responses can be sent in multiple ways, which are defined in the following subsections ๐ง
5.2.1. Piggybacked ๐ฃ
in the most basic case, the response is carried directly in the Acknowledgement message that acknowledges the request. this requires that the request was carried in a Confirmable message. this is called a "Piggybacked Response" ๐
the response is returned in the Acknowledgement message, whether it indicates success or failure. in effect, the response is piggybacked on the Acknowledgement message, and no separate message is required to return the response ๐ซถ
Implementation Note: the protocol leaves the decision of whether to piggyback a response (or send a separate response) up to the server. the client MUST be prepared to receive either. on the quality-of-implementation level, there is a strong expectation that servers will implement code to piggyback whenever possible, saving resources in the network and at both the client and the server ๐ฅ
5.2.2. Separate ๐ฆ
Okay so, a piggybacked response isn't always possible ๐. A server might need longer to get the representation of the requested resource than it can wait before sending the Acknowledgement, and if it takes too long the client just keeps retransmitting the request ๐ (see also the tea on PROCESSING_DELAY in Section 4.8.2). And a response to a request that came in a Non-confirmable message is always sent separately, because there's no Acknowledgement to hitch a ride on ๐ญ.
One way a server can handle this is to start working on getting the representation and, while that's in progress, let an acknowledgement timer run out โฐ. A server can also send an acknowledgement right away if it already knows there won't be a piggybacked response ๐ . Either way, the acknowledgement basically works as a promise that the request will be handled later ๐ซถ.
When the server finally has the representation, it sends the response ๐. If it really can't afford to lose that message, it goes out as a Confirmable message from the server to the client, and the client answers with an Acknowledgement that echoes the new Message ID the server picked ๐ฅ. (It can also be a Non-confirmable message; see Section 5.2.3 ๐ธ.)
When the server goes the separate route, it sends the Acknowledgement to the Confirmable request as an Empty message ๐. Once the server has sent back that Empty Acknowledgement, it MUST NOT send the response in another Acknowledgement, even if the client retransmits the same request again ๐ โโ๏ธ. If a retransmitted request shows up (maybe the original Acknowledgement got delayed), another Empty Acknowledgement goes out, and any response MUST be sent as a separate response ๐.
If the server then sends a Confirmable response, the client's Acknowledgement to that response MUST also be an Empty message, one that carries neither a request nor a response โจ. The server MUST stop retransmitting its response on any matching Acknowledgement (silently ignoring any Response Code or payload) or Reset message ๐.
Implementation Notes: Here's the tea. The underlying datagram transport might not preserve sequence, so the Confirmable message carrying the response could actually arrive before or after the Acknowledgement for the request. For the purposes of ending the retransmission sequence, that counts as an acknowledgement too ๐ง. Also, while the CoAP protocol itself doesn't make any specific demands here, there's an expectation that the response comes within a time frame that's reasonable from an application point of view โณ. And since there's no underlying transport protocol that could be told to run a keep-alive mechanism, the requester may want to set up a timeout that's unrelated to CoAP's retransmission timers, in case the server gets destroyed or otherwise can't send the response ๐ฅบ.
5.2.3. Non-confirmable ๐
If the request message is Non-confirmable, the response SHOULD be returned in a Non-confirmable message as well ๐. However, an endpoint MUST be prepared to receive a Non-confirmable response (preceded or followed by an Empty Acknowledgement message) in reply to a Confirmable request, or a Confirmable response in reply to a Non-confirmable request ๐ซถ. Be flexible, bestie ๐ .
5.3. Request/Response Matching ๐งฉ
Regardless of how a response is sent, it gets matched to the request using a token that the client includes in the request, plus some extra address info about the matching endpoint ๐.
5.3.1. Token ๐ช
The Token is what matches a response to a request ๐. The token value is a sequence of 0 to 8 bytes. (Every message carries a token, even if it's zero length, so don't be surprised ๐.) Every request carries a client-generated token that the server MUST echo (without modification) in any resulting response ๐ฅ.
A token is meant to be a client-local identifier for telling apart concurrent requests (see Section 5.3 ๐ธ). Honestly, it could've just been called a "request ID" ๐ .
The client SHOULD generate tokens so that the tokens currently in use for a given source/destination endpoint pair are unique ๐ฆ. (A client implementation can actually reuse the same token for any request as long as it uses a different endpoint each time, e.g., a different source port number ๐ง.) An empty token value is fine when no other tokens are in use to a destination, or when requests are made serially per destination and get piggybacked responses ๐. There are multiple possible implementation strategies for this, though ๐.
A client sending a request without using Transport Layer Security (Section 9) SHOULD use a nontrivial, randomized token to guard against spoofing of responses (Section 11.4) ๐. This protective use of tokens is exactly why they're allowed to be up to 8 bytes ๐. How much random stuff goes into the Token depends on the client's security requirements and how much of a threat response spoofing poses ๐ค. A client connected to the general Internet SHOULD use at least 32 bits of randomness ๐ช, and keep in mind that not being directly connected to the Internet is not necessarily enough protection against spoofing ๐. (The Message ID adds little protection, since it's usually assigned sequentially, which makes it guessable, and it can be bypassed by spoofing a separate response ๐ญ.) Clients that want to optimize the Token length may also want to detect the level of ongoing attacks (for example, by tallying recent Token mismatches in incoming messages) and bump the Token length up as needed ๐. [RFC4086] discusses randomness requirements for security ๐.
An endpoint receiving a token it did not generate MUST treat the token as opaque and make no assumptions about its content or structure ๐ซฃ.
5.3.2. Request/Response Matching Rules ๐
The exact rules for matching a response to a request go like this:
- The source endpoint of the response MUST be the same as the destination endpoint of the original request.
- In a piggybacked response, the Message ID of the Confirmable request and the Acknowledgement MUST match, and the tokens of the response and original request MUST match. In a separate response, just the tokens of the response and original request MUST match.
If a message carrying a response is unexpected (the client isn't waiting for a response from the identified endpoint, at the endpoint addressed, and/or with the given token), the response gets rejected (Sections 4.2 and 4.3) ๐ซ.
Implementation Note: A client that receives a response in a CON message might want to clean up its message state right after sending the ACK ๐งน. If that ACK gets lost and the server retransmits the CON, the client might not have any state left to match this response to. That makes the retransmission an unexpected message, so the client will likely send a Reset message so it doesn't get any more retransmissions ๐. This behavior is normal and not an indication of an error ๐. (Clients that aren't aggressively optimized in their state memory usage will still have message state that identifies the second CON as a retransmission. Clients that actually expect more messages from the server [OBSERVE] will have to keep state in any case ๐ซถ.)
5.4. Options ๐
Both requests and responses can include a list of one or more options ๐ . For example, the URI in a request is carried in several options, and the metadata that would live in an HTTP header in HTTP gets supplied as options too ๐ธ.
CoAP defines a single set of options that get used in both requests and responses ๐ง:
Content-FormatETagLocation-PathLocation-QueryMax-AgeProxy-UriProxy-SchemeUri-HostUri-PathUri-PortUri-QueryAcceptIf-MatchIf-None-MatchSize1
The semantics of these options, along with their properties, are defined in detail in Section 5.10 ๐.
Not every option is defined for use with every method and Response Code ๐. The possible options for methods and Response Codes are defined in Sections 5.8 and 5.9, respectively. If an option isn't defined for a Method or Response Code, it MUST NOT be included by a sender, and a recipient MUST treat it like an unrecognized option ๐ซ.
5.4.1. Critical/Elective โ๏ธ
Options fall into one of two classes: "critical" or "elective" ๐ซ. The difference is how an endpoint handles an option it doesn't recognize:
- Upon reception, unrecognized options of class "elective" MUST be silently ignored ๐คซ.
- Unrecognized options of class "critical" that occur in a Confirmable request MUST cause the return of a 4.02 (Bad Option) response ๐ โโ๏ธ. This response SHOULD include a diagnostic payload describing the unrecognized option(s) (see Section 5.5.2) ๐ฉบ.
- Unrecognized options of class "critical" that occur in a Confirmable response, or piggybacked in an Acknowledgement, MUST cause the response to be rejected (Section 4.2) ๐ซ.
- Unrecognized options of class "critical" that occur in a Non-confirmable message MUST cause the message to be rejected (Section 4.3) ๐.
Note that, whether critical or elective, an option is never "mandatory" (it's always optional) ๐ . These rules exist so that implementations can stop processing options they don't understand or implement ๐ง.
Critical/elective rules apply to non-proxying endpoints ๐ฆ. A proxy processes options based on the Unsafe/Safe-to-Forward classes defined in Section 5.7 ๐ท.
5.4.2. Proxy Unsafe or Safe-to-Forward and NoCacheKey ๐
On top of being marked critical or elective, options are also classified by how a proxy should deal with them if it doesn't recognize them ๐. For this purpose, an option is either considered Unsafe to forward (UnSafe is set) or Safe-to-Forward (UnSafe is clear) ๐ก๏ธ.
Also, for an option marked Safe-to-Forward, the option number tells you whether or not it's meant to be part of the Cache-Key (Section 5.6) in a request. If some of the NoCacheKey bits are 0, it is part of the Cache-Key; if all NoCacheKey bits are 1, it isn't (see Section 5.4.6) ๐๏ธ.
Note: The Cache-Key indication only matters for proxies that don't implement the given option as a request option and instead rely only on the Unsafe/Safe-to-Forward indication ๐ค. For example, for ETag, actually using the request option as part of the Cache-Key is grossly inefficient, but it's the best thing a proxy can do if it doesn't implement ETag, since the response is going to differ based on whether the request option is present ๐ต. A more useful proxy that does implement the ETag request option doesn't use ETag as part of the Cache-Key ๐. NoCacheKey is indicated in three bits, so only one out of eight codepoints is qualified as NoCacheKey, leaving seven out of eight codepoints for what appears to be the more likely case ๐.
Proxy behavior with regard to these classes is defined in Section 5.7 ๐.
5.4.3. Length ๐
Option values are defined to have a specific length, often expressed as an upper and lower bound ๐ง. If the length of an option value in a request is outside the defined range, that option MUST be treated like an unrecognized option (see Section 5.4.1) ๐ .
5.4.4. Default Values ๐
Okay so options can come with a default value ๐. If an option's value is meant to be that default, the option SHOULD NOT be included in the message, bestie. And if the option isn't there at all, the default value MUST be assumed ๐ .
Where a critical option has a default, it gets picked super carefully so that leaving the option out can be processed properly by implementations that have no clue the critical option exists, and by implementations that read "not there" as "the default is here" ๐ซถ. Iconic planning, honestly.
5.4.5. Repeatable Options ๐ฆ
Some options are defined as repeatable, which means they MAY show up one or more times in a message ๐ธ. Options that aren't repeatable MUST NOT appear more than once in a message. No exceptions, periodt ๐.
If a message has more copies of an option than that option is allowed to have, every extra copy (the supernumerary ones) that shows up later in the message MUST be treated like an unrecognized option (see Section 5.4.1) ๐.
5.4.6. Option Numbers ๐ง
An Option is identified by its option number, and the number also tells you extra stuff. Odd numbers mean critical, even numbers mean elective ๐. This isn't just a vibe or a convention either, it's a real feature of the protocol: whether an option is elective or critical is completely decided by whether its number is even or odd ๐ฅ.
More generally, an option number is built with a bit mask that says if an option is Critical or Elective, Unsafe or Safe-to-Forward, and, for Safe-to-Forward ones, gives a Cache-Key indication too, as the figure below shows ๐. In the text, the bit mask is written as a single byte that gets applied to the least significant byte of the option number (in unsigned integer representation) ๐. When bit 7 (the least significant bit) is 1, the option is Critical, and it's Elective when it's 0. When bit 6 is 1, the option is Unsafe, and it's Safe-to-Forward when it's 0. When bit 6 is 0 (so the option isn't Unsafe), it's NoCacheKey if and only if bits 3-5 are all set to 1. Every other bit combo means it is a Cache-Key ๐. These classes of options get explained in the next sections โจ.
0 1 2 3 4 5 6 7
+---+---+---+---+---+---+---+---+
| | NoCacheKey| U | C |
+---+---+---+---+---+---+---+---+
Figure 10: Option Number Mask (Least Significant Byte)
An endpoint may use an equivalent of the C code in Figure 11 to derive the characteristics of an option number "onum" ๐ง .
Critical = (onum & 1);
UnSafe = (onum & 2);
NoCacheKey = ((onum & 0x1e) == 0x1c);
Figure 11: Determining Characteristics from an Option Number
The option numbers for the options defined in this document are listed in the "CoAP Option Numbers" registry (Section 12.2) ๐.
5.5. Payloads and Representations ๐
Both requests and responses can include a payload, depending on the Method or Response Code. If a Method or Response Code isn't defined to have a payload, a sender MUST NOT include one, and a recipient MUST ignore it ๐. Ignore it, babe, it's not for you.
5.5.1. Representation ๐ธ
The payload of requests, or of responses indicating success, is usually a representation of a resource ("resource representation") or the result of the requested action ("action result") โจ. Its format is specified by the Internet media type and content coding given by the Content-Format Option. If that option is missing, there's no default value, so the format has to be inferred by the application (e.g., from the application context). Payload "sniffing" SHOULD only be attempted if no content type is given ๐.
Implementation Note: Quality-of-implementation vibes here ๐
. People really expect a Content-Format indication with resource representations whenever it's possible. It's not a "SHOULD" level requirement, and that's only because it isn't a protocol requirement. Plus, it'd be super hard to spell out exactly when that expectation could get broken ๐ญ.
For responses indicating a client or server error, the payload only counts as a representation of the result of the requested action if a Content-Format Option is given. Without that option, the payload is a Diagnostic Payload (Section 5.5.2) ๐.
5.5.2. Diagnostic Payload ๐ฅ
If no Content-Format option is given, the payload of a response indicating a client or server error is a brief, human-readable diagnostic message that explains the error situation. This diagnostic message MUST be encoded using UTF-8 [RFC3629], more specifically using Net-Unicode form [RFC5198] ๐งพ.
The message is kind of like the Reason-Phrase on an HTTP status line. It's not for end users, it's for software engineers who need to interpret it while debugging, in the context of this present English-language specification. So no mechanism for language tagging is needed or provided ๐ค. Unlike what's usual in HTTP, the payload SHOULD be empty if there's no additional information beyond the Response Code ๐ .
5.5.3. Selected Representation ๐ฆ
Not every response carries a payload that gives a representation of the resource addressed by the request. It's still sometimes useful to refer to such a representation in relation to a response, whether or not it actually got enclosed ๐.
We use the term "selected representation" for the current representation of a target resource that would have been selected in a successful response if the corresponding request had used the method GET and excluded any conditional request options (Section 5.10.8) โจ.
Certain response options give metadata about the selected representation, which might differ from the representation included in the message for responses to some state-changing methods. Of the response options defined in this specification, only the ETag response option (Section 5.10.6) is defined as metadata about the selected representation ๐ง.
5.5.4. Content Negotiation ๐ธ
A server may be able to supply a representation for a resource in one of multiple representation formats. Without further info from the client, it provides the representation in the format it prefers ๐.
By using the Accept Option (Section 5.10.4) in a request, the client can indicate which content-format it prefers to receive ๐.
5.6. Caching ๐งบ
CoAP endpoints MAY cache responses in order to reduce response time and network bandwidth consumption on future, equivalent requests ๐พ.
The goal of caching in CoAP is to reuse a prior response message to satisfy a current request. Sometimes a stored response can be reused with no network request at all, which cuts latency and network round-trips. A "freshness" mechanism handles that (see Section 5.6.1). Even when a new request is needed, it's often possible to reuse the payload of a prior response to satisfy it, saving network bandwidth. A "validation" mechanism handles that one (see Section 5.6.2) ๐ซถ.
Unlike HTTP, the cacheability of CoAP responses doesn't depend on the request method. It depends on the Response Code. The cacheability of each Response Code is defined along with the Response Code definitions in Section 5.9. Response Codes that indicate success and are unrecognized by an endpoint MUST NOT be cached ๐ซ.
For a presented request, a CoAP endpoint MUST NOT use a stored response, unless:
- the presented request method and the one used to obtain the stored response match,
- all options match between those in the presented request and those of the request used to obtain the stored response (which includes the request URI), except that there's no need for a match of any request options marked as NoCacheKey (Section 5.4) or recognized by the Cache and fully interpreted with respect to its specified cache behavior (such as the
ETagrequest option described in Section 5.10.6; see also Section 5.4.2), and - the stored response is either fresh or successfully validated as defined below.
The set of request options used for matching the cache entry is also collectively referred to as the "Cache-Key" ๐. For URI schemes other than coap and coaps, matching of those options that constitute the request URI may be performed under rules specific to the URI scheme ๐.
5.6.1. Freshness Model โฐ
When a response is "fresh" in the cache, it can be used to satisfy subsequent requests without contacting the origin server, which makes things way more efficient โจ.
The mechanism for figuring out freshness is for an origin server to provide an explicit expiration time in the future, using the Max-Age Option (see Section 5.10.5). The Max-Age Option says the response is to be considered not fresh once its age is greater than the specified number of seconds ๐ฐ๏ธ.
The Max-Age Option defaults to a value of 60. So if it's not present in a cacheable response, the response is considered not fresh after its age is greater than 60 seconds. If an origin server wants to prevent caching, it MUST explicitly include a Max-Age Option with a value of zero seconds. Hard no to caching ๐
โโ๏ธ.
If a client has a fresh stored response and makes a new request matching the request for that stored response, the new response invalidates the old response ๐ .
5.6.2. Validation Model ๐
When an endpoint has one or more stored responses for a GET request, but can't use any of them (e.g., because they're not fresh), it can use the ETag Option (Section 5.10.6) in the GET request. That gives the origin server a chance both to select a stored response to be used and to update its freshness. This process is known as "validating" or "revalidating" the stored response ๐ง.
When sending such a request, the endpoint SHOULD add an ETag Option specifying the entity-tag of each stored response that's applicable ๐ซถ.
A 2.03 (Valid) response indicates the stored response identified by the entity-tag given in the response's ETag Option can be reused after updating it as described in Section 5.9.1.3 ๐.
Any other Response Code indicates that none of the stored responses nominated in the request is suitable. Instead, the response SHOULD be used to satisfy the request, and it MAY replace the stored response ๐.
5.7. Proxying ๐ฆ
okay so a proxy is a CoAP endpoint that clients can hand requests to, and then the proxy makes them on their behalf ๐ . This is super useful when the request couldn't otherwise be made, or when the proxy can answer from a cache so the response comes back faster and uses less network bandwidth or energy ๐โจ (energy matters a LOT for tiny devices).
In an overall Constrained RESTful Environment, proxies can have really different jobs ๐. Clients can explicitly pick one, which we call a "forward-proxy" ๐ง. A proxy can also be slotted in to stand in for origin servers, and that's a "reverse-proxy" ๐ช. Separately, a proxy can map a CoAP request to a CoAP request (a "CoAP-to-CoAP proxy") or translate from or to a different protocol (a "cross-proxy") ๐. The full definitions are in Section 1.2 ๐.
Notes: the terminology here was picked to feel culturally familiar to the wider web app world ๐ธ, without matching it in every single detail (which might not even matter in Constrained RESTful Environments). Don't read too much into the pieces of the words, like "forward", "reverse", or "cross" ๐. HTTP proxies often do more than proxy HTTP. They also offer a transport-protocol proxying function (CONNECT) so end-to-end transport layer security can go through the proxy ๐. No such function is defined for CoAP-to-CoAP proxies in this spec, because forwarding UDP packets is unlikely to be of much value in Constrained RESTful Environments ๐คทโโ๏ธ. See also Section 10.2.7 for the cross-proxy case โจ.
When a client uses a proxy to make a request that uses a secure URI scheme (e.g., coaps or https), the request towards the proxy SHOULD be sent using DTLS, except where equivalent lower-layer security is used for the leg between the client and the proxy ๐๐.
5.7.1. Proxy Operation ๐ ๏ธ
A proxy generally needs a way to figure out the potential request parameters for a request it sends to a destination, based on the request it got from its client ๐ค. This is fully specified for a forward-proxy, but for a reverse-proxy it may depend on the specific configuration ๐๏ธ. Honestly, the client of a reverse-proxy usually doesn't indicate a locator for the destination, so the reverse-proxy needs some form of namespace translation ๐บ๏ธ. Still, some parts of proxy operation are shared by all forms ๐ซถ.
If a proxy doesn't use a cache, it just forwards the translated request to the determined destination ๐ฌ. Otherwise, if it does use a cache but doesn't have a stored response that matches the translated request and is still considered fresh, it needs to refresh its cache according to Section 5.6 ๐. For options in the request that the proxy recognizes, it knows whether that option is meant to be part of the key used to look up the cached value or not ๐. For example, requests for different Uri-Path values address different resources, so Uri-Path values are always part of the Cache-Key, while, e.g., Token values are never part of the Cache-Key ๐ โโ๏ธ. For options the proxy doesn't recognize but that are marked Safe-to-Forward in the option number, the option also tells the proxy whether to include it in the Cache-Key (NoCacheKey is not all set) or not (NoCacheKey is all set) ๐งฉ. (Options that are unrecognized and marked Unsafe lead to 4.02 Bad Option ๐.)
If the request to the destination times out, a 5.04 (Gateway Timeout) response MUST be returned โฐ. If the request to the destination gets a response the proxy can't process (e.g., due to unrecognized critical options or message format errors), a 5.02 (Bad Gateway) response MUST be returned ๐ญ. Otherwise, the proxy returns the response to the client ๐.
If a response is generated out of a cache, the generated (or implied) Max-Age Option MUST NOT extend the max-age originally set by the server, considering the time the resource representation spent in the cache โณ. For example, the Max-Age Option could be adjusted by the proxy for each response using this formula:
proxy-max-age = original-max-age - cache-age
Like, if a request is made to a proxied resource that was refreshed 20 seconds ago and had an original Max-Age of 60 seconds, then that resource's proxied max-age is now 40 seconds ๐งฎโจ. Considering potential network delays on the way from the origin server, a proxy should be conservative in the max-age values it offers ๐ซง.
All options present in a proxy request MUST be processed at the proxy ๐. Unsafe options in a request that the proxy doesn't recognize MUST lead to a 4.02 (Bad Option) response being returned by the proxy ๐ซ. A CoAP-to-CoAP proxy MUST forward to the origin server all Safe-to-Forward options that it doesn't recognize ๐ฆ. Similarly, Unsafe options in a response that are not recognized by the CoAP-to-CoAP proxy server MUST lead to a 5.02 (Bad Gateway) response ๐ . Again, Safe-to-Forward options that are not recognized MUST be forwarded ๐.
Additional considerations for cross-protocol proxying between CoAP and HTTP are discussed in Section 10 ๐.
5.7.2. Forward-Proxies ๐งญ
CoAP makes a clear difference between requests made (as if) to an origin server and requests made through a forward-proxy ๐ฏ. CoAP requests to a forward-proxy are sent as normal Confirmable or Non-confirmable requests to the forward-proxy endpoint, but they specify the request URI in a different way ๐. In a proxy request, the request URI is a string in the Proxy-Uri Option (see Section 5.10.2) ๐งต. In a request to an origin server, the request URI is split into the Uri-Host, Uri-Port, Uri-Path, and Uri-Query Options (see Section 5.10.1) ๐ช. Alternatively, the URI in a proxy request can be put together from a Proxy-Scheme option plus those split options ๐งฉ.
When a proxy request is made to an endpoint and that endpoint is unwilling or unable to act as proxy for the request URI, it MUST return a 5.05 (Proxying Not Supported) response ๐ โโ๏ธ. If the authority (host and port) is recognized as identifying the proxy endpoint itself (see Section 5.10.2), then the request MUST be treated as a local (non-proxied) request ๐ .
Unless a proxy is configured to forward the proxy request to another proxy, it MUST translate the request like this: the scheme of the request URI defines the outgoing protocol and its details (e.g., CoAP is used over UDP for the "coap" scheme and over DTLS for the "coaps" scheme) ๐. For a CoAP-to-CoAP proxy, the origin server's IP address and port are determined by the authority component of the request URI, and the request URI is decoded and split into the Uri-Host, Uri-Port, Uri-Path and Uri-Query Options ๐งฉ. This consumes the Proxy-Uri or Proxy-Scheme option, which is therefore not forwarded to the origin server ๐ซก.
5.7.3. Reverse-Proxies ๐ช
Reverse-proxies don't use the Proxy-Uri or Proxy-Scheme options at all ๐. Instead, they need to figure out the destination (next hop) of a request from information in the request plus information in their configuration ๐ง . For example, a reverse-proxy might offer various resources as if they were its own, after learning about them through resource discovery ๐. The reverse-proxy is free to build a namespace for the URIs that identify these resources ๐จ. It can also build a namespace that gives the client more control over where the request goes, e.g., by embedding host identifiers and port numbers into the URI path of the resources it offers ๐งโโ๏ธ.
When processing the response, a reverse-proxy has to be careful that ETag option values from different sources don't get mixed up on one resource offered to its clients ๐ฌ. In many cases, the ETag can be forwarded unchanged ๐ . If the mapping from a resource offered by the reverse-proxy to resources offered by its various origin servers isn't unique, the reverse-proxy may need to generate a new ETag, making sure the semantics of this option are properly preserved ๐ซถ.
5.8. Method Definitions ๐
In this section, each method is defined along with its behavior ๐. A request with an unrecognized or unsupported Method Code MUST generate a 4.05 (Method Not Allowed) piggybacked response ๐ซ.
5.8.1. GET ๐ฅ
The GET method retrieves a representation for the information that currently corresponds to the resource identified by the request URI ๐. If the request includes an Accept Option, that indicates the preferred content-format of a response ๐ฏ. If the request includes an ETag Option, the GET method requests that ETag be validated, and that the representation be transferred only if validation failed ๐. Upon success, a 2.05 (Content) or 2.03 (Valid) Response Code SHOULD be present in the response โจ.
The GET method is safe and idempotent ๐ซง.
5.8.2. POST ๐ค
The POST method requests that the representation enclosed in the request be processed ๐ณ. The actual function performed by POST is determined by the origin server and depends on the target resource ๐๏ธ. It usually results in a new resource being created or the target resource being updated ๐.
If a resource has been created on the server, the response returned by the server SHOULD have a 2.01 (Created) Response Code, and SHOULD include the URI of the new resource in a sequence of one or more Location-Path and/or Location-Query Options (Section 5.10.7) ๐. If the POST succeeds but doesn't result in a new resource being created on the server, the response SHOULD have a 2.04 (Changed) Response Code ๐. If the POST succeeds and results in the target resource being deleted, the response SHOULD have a 2.02 (Deleted) Response Code ๐๏ธ.
POST is neither safe nor idempotent ๐ .
5.8.3. PUT ๐งฑ
The PUT method requests that the resource identified by the request URI be updated or created with the enclosed representation ๐๏ธ. The representation format is specified by the media type and content coding given in the Content-Format Option, if provided ๐ท๏ธ.
If a resource exists at the request URI, the enclosed representation SHOULD be considered a modified version of that resource, and a 2.04 (Changed) Response Code SHOULD be returned ๐. If no resource exists, the server MAY create a new resource with that URI, resulting in a 2.01 (Created) Response Code ๐ฑ. If the resource could not be created or modified, an appropriate error Response Code SHOULD be sent ๐.
Further restrictions to a PUT can be made by including the If-Match (see Section 5.10.8.1) or If-None-Match (see Section 5.10.8.2) options in the request ๐ง.
PUT is not safe but is idempotent ๐ซถ.
5.8.4. DELETE ๐๏ธ
The DELETE method requests that the resource identified by the request URI be deleted ๐. A 2.02 (Deleted) Response Code SHOULD be used on success, or in case the resource did not exist before the request โ .
DELETE is not safe but is idempotent ๐.
5.9. Response Code Definitions ๐ธ
Each Response Code is described below, including any options required in the response ๐. Where appropriate, some of the codes will be specified in regards to related Response Codes in HTTP [RFC2616]. This does not mean that any such relationship modifies the HTTP mapping specified in Section 10 ๐งโโ๏ธ.
5.9.1. Success 2.xx ๐ฅณ
This class of Response Code indicates that the client's request was successfully received, understood, and accepted ๐โจ.
5.9.1.1. 2.01 Created ๐
Okay so this is basically HTTP 201 "Created" ๐ธ but it only shows up when someone's sending a POST or PUT. Any payload that comes back is a representation of what the action actually did โจ
If the response has one or more Location-Path and/or Location-Query Options, those values tell you where the resource got created ๐บ๏ธ If there aren't any, the resource was created right at the request URI. A cache that gets this response MUST mark any stored response for the created resource as not fresh ๐ โโ๏ธ
And this response is not cacheable, bestie ๐
5.9.1.2. 2.02 Deleted ๐๏ธ
This one is giving HTTP 204 "No Content" vibes, but it's only for requests that make the resource stop being available, like DELETE and, in certain situations, POST ๐ Again, any payload that comes back is a representation of the action result โจ
This response is not cacheable. HOWEVER, a cache MUST mark any stored response for the deleted resource as not fresh ๐ซถ
5.9.1.3. 2.03 Valid ๐
This Response Code is related to HTTP 304 "Not Modified", but it only exists to say the response identified by the entity-tag in the included ETag Option is still valid ๐ฆ So the response MUST include an ETag Option and MUST NOT include a payload. No payload, just vibes ๐
When a cache that recognizes and processes the ETag response option gets a 2.03 (Valid) response, it MUST update the stored response with the value of the Max-Age Option in the response (explicitly, or implicitly as a default value; see also Section 5.6.2) โฐ For each type of Safe-to-Forward option in the response, the set of options of that type in the stored response (which might be empty) MUST be swapped out for the set of options of that type in the response you just got ๐ (Unsafe options might trigger similar option-specific processing, as defined by the option itself ๐)
5.9.1.4. 2.04 Changed โจ
This is like HTTP 204 "No Content", but again only for POST and PUT requests ๐ The payload returned with the response, if any, is a representation of the action result.
This response is not cacheable. However, a cache MUST mark any stored response for the changed resource as not fresh ๐
5.9.1.5. 2.05 Content ๐
This Response Code is like HTTP 200 "OK", but it's only for GET requests ๐ง
The payload returned with the response is a representation of the target resource ๐
This response is cacheable, and caches can use the Max-Age Option to figure out freshness (see Section 5.6.1). If the ETag Option is there, it can also be used for validation (see Section 5.6.2) ๐ฅ
5.9.2. Client Error 4.xx ๐
This class of Response Code is for when the client seems to have messed up ๐ฅบ These Response Codes can show up for any request method.
The server SHOULD include a diagnostic payload under the conditions detailed in Section 5.5.2 ๐ฉบ
Responses in this class are cacheable, and caches can use the Max-Age Option to determine freshness (see Section 5.6.1). They cannot be validated, though ๐ โโ๏ธ
5.9.2.1. 4.00 Bad Request ๐
This Response Code is Like HTTP 400 "Bad Request" ๐ซ
5.9.2.2. 4.01 Unauthorized ๐
The client isn't authorized to do the requested action ๐ซ The client SHOULD NOT repeat the request without first improving its authentication status with the server. Which specific mechanism you use for that is outside this document's scope, but see Section 9 if you want more info ๐
5.9.2.3. 4.02 Bad Option โ ๏ธ
The server couldn't understand the request because of one or more unrecognized or malformed options ๐ญ The client SHOULD NOT repeat the request without modification.
5.9.2.4. 4.03 Forbidden ๐ท
This Response Code is like HTTP 403 "Forbidden" ๐
5.9.2.5. 4.04 Not Found ๐
This Response Code is like HTTP 404 "Not Found" โจ
5.9.2.6. 4.05 Method Not Allowed ๐ โโ๏ธ
This is like HTTP 405 "Method Not Allowed", but there's no parallel to the "Allow" header field here ๐ฅ
5.9.2.7. 4.06 Not Acceptable ๐
This is like HTTP 406 "Not Acceptable", except there's no response entity ๐ซฅ
5.9.2.8. 4.12 Precondition Failed ๐ง
This Response Code is like HTTP 412 "Precondition Failed" ๐ฆ
5.9.2.9. 4.13 Request Entity Too Large ๐
This Response Code is like HTTP 413 "Request Entity Too Large" ๐
The response SHOULD include a Size1 Option (Section 5.10.9) to show the maximum size of request entity the server can handle and is willing to handle, unless the server isn't in a position to make that info available ๐
5.9.2.10. 4.15 Unsupported Content-Format ๐
This is like HTTP 415 "Unsupported Media Type" ๐ โโ๏ธ
5.9.3. Server Error 5.xx ๐จ
This class of Response Code is for when the server knows it messed up or just can't do the request ๐ฅฒ These Response Codes can show up for any request method.
The server SHOULD include a diagnostic payload under the conditions detailed in Section 5.5.2 ๐ฉน
Responses in this class are cacheable: caches can use the Max-Age Option to determine freshness (see Section 5.6.1). They cannot be validated ๐ซถ
5.9.3.1. 5.00 Internal Server Error ๐ฅ
This Response Code is like HTTP 500 "Internal Server Error" ๐ตโ๐ซ
5.9.3.2. 5.01 Not Implemented ๐ ๏ธ
This is like HTTP 501 "Not Implemented" ๐ง
5.9.3.3. 5.02 Bad Gateway ๐
This Response Code is like HTTP 502 "Bad Gateway" ๐ซ
5.9.3.4. 5.03 Service Unavailable ๐ด
This is like HTTP 503 "Service Unavailable", but instead of the "Retry-After" header field, it uses the Max-Age Option to say how many seconds to wait before retrying โณ
5.9.3.5. 5.04 Gateway Timeout โฐ
This Response Code is like HTTP 504 "Gateway Timeout" ๐
5.9.3.6. 5.05 Proxying Not Supported ๐ซ
The server is unable or unwilling to act as a forward-proxy for the URI given in the Proxy-Uri Option, or using Proxy-Scheme (see Section 5.10.2) ๐ โโ๏ธ
5.10. Option Definitions ๐
The individual CoAP options are summarized in Table 4 and explained in the subsections of this section โจ
In this table, the C, U, and N columns show the properties Critical, UnSafe, and NoCacheKey. Since NoCacheKey only means something for options that are Safe-to-Forward (not marked Unsafe), that column gets a dash for UnSafe options ๐ง
+-----+---+---+---+---+----------------+--------+--------+----------+
| No. | C | U | N | R | Name | Format | Length | Default |
+-----+---+---+---+---+----------------+--------+--------+----------+
| 1 | x | | | x | If-Match | opaque | 0-8 | (none) |
| 3 | x | x | - | | Uri-Host | string | 1-255 | (see |
| | | | | | | | | below) |
| 4 | | | | x | ETag | opaque | 1-8 | (none) |
| 5 | x | | | | If-None-Match | empty | 0 | (none) |
| 7 | x | x | - | | Uri-Port | uint | 0-2 | (see |
| | | | | | | | | below) |
| 8 | | | | x | Location-Path | string | 0-255 | (none) |
| 11 | x | x | - | x | Uri-Path | string | 0-255 | (none) |
| 12 | | | | | Content-Format | uint | 0-2 | (none) |
| 14 | | x | - | | Max-Age | uint | 0-4 | 60 |
| 15 | x | x | - | x | Uri-Query | string | 0-255 | (none) |
| 17 | x | | | | Accept | uint | 0-2 | (none) |
| 20 | | | | x | Location-Query | string | 0-255 | (none) |
| 35 | x | x | - | | Proxy-Uri | string | 1-1034 | (none) |
| 39 | x | x | - | | Proxy-Scheme | string | 1-255 | (none) |
| 60 | | | x | | Size1 | uint | 0-4 | (none) |
+-----+---+---+---+---+----------------+--------+--------+----------+
C=Critical, U=Unsafe, N=NoCacheKey, R=Repeatable
Table 4: Options
5.10.1. Uri-Host, Uri-Port, Uri-Path, and Uri-Query ๐บ๏ธ
The Uri-Host, Uri-Port, Uri-Path, and Uri-Query Options are how you specify the target resource of a request to a CoAP origin server ๐ฏ They encode the different parts of the request URI so that no percent-encoding shows up in the option values, and the full URI can still be rebuilt at any endpoint involved ๐งฉ The syntax of CoAP URIs is defined in Section 6.
The steps for parsing URIs into options are defined in Section 6.4. Those steps result in zero or more Uri-Host, Uri-Port, Uri-Path, and Uri-Query Options being included in a request, where each option holds the following values:
- the
Uri-HostOption specifies the Internet host of the resource being requested, - the
Uri-PortOption specifies the transport-layer port number of the resource, - each
Uri-PathOption specifies one segment of the absolute path to the resource, and - each
Uri-QueryOption specifies one argument parameterizing the resource.
Note: Fragments ([RFC3986], Section 3.5) are not part of the request URI, so they won't be sent in a CoAP request ๐
The default value of the Uri-Host Option is the IP literal representing the destination IP address of the request message. Likewise, the default value of the Uri-Port Option is the destination UDP port ๐ These defaults are enough for requests to most servers. Explicit Uri-Host and Uri-Port Options are typically used when an endpoint hosts multiple virtual servers ๐
The Uri-Path and Uri-Query Options can contain any character sequence, and no percent-encoding is performed ๐ธ The value of a Uri-Path Option MUST NOT be "." or ".." (because the request URI has to be resolved before it's parsed into options) ๐
โโ๏ธ
The steps for building the request URI from the options are defined in Section 6.5. An implementation doesn't have to construct the URI, though. It can just look up the target resource by checking the individual options ๐ง
Examples can be found in Appendix B ๐
5.10.2. Proxy-Uri and Proxy-Scheme ๐ฆ
The Proxy-Uri Option is used to make a request to a forward-proxy (see Section 5.7). The forward-proxy is asked to forward the request, or to serve it from a valid cache, and return the response ๐
The option value is an absolute-URI ([RFC3986], Section 4.3).
Note that the forward-proxy MAY forward the request on to another proxy, or directly to the server specified by the absolute-URI ๐ To avoid request loops, a proxy MUST be able to recognize all of its server names, including any aliases, local variations, and the numeric IP addresses ๐
An endpoint that gets a request with a Proxy-Uri Option and is unable or unwilling to act as a forward-proxy for that request MUST cause the return of a 5.05 (Proxying Not Supported) response ๐ โโ๏ธ
The Proxy-Uri Option MUST take precedence over any of the Uri-Host, Uri-Port, Uri-Path, or Uri-Query options (and each of those MUST NOT be included in a request that contains the Proxy-Uri Option) ๐
As a special case that makes life easier for lots of proxy clients, the absolute-URI can be built from the Uri-* options. When a Proxy-Scheme Option is present, the absolute-URI is constructed like this: a CoAP URI is built from the Uri-* options as defined in Section 6.5 โจ In the resulting URI, the initial scheme (everything up to, but not including, the following colon) is then replaced by the content of the Proxy-Scheme Option ๐ Heads up: this only works if the parts of the desired URI other than the scheme can actually be expressed with Uri-* options. For example, to represent a URI with a userinfo component in the authority, only Proxy-Uri can be used ๐
5.10.3. Content-Format ๐
okay so Content-Format tells you what kind of representation the message payload is in ๐ง. It's a numeric Content-Format identifier, and those live in the "CoAP Content-Formats" registry (Section 12.3) ๐ . If the option isn't there, no default gets assumed at all, so the representation format of any payload is just indeterminate (Section 5.5) ๐ no guessing, bestie!
5.10.4. Accept ๐
The CoAP Accept option is how a client says which Content-Format it's cool with ๐ซถ. Same deal as before: it's a numeric identifier from the "CoAP Content-Formats" registry (Section 12.3). If there's no Accept option, the client isn't expressing a preference, so no default value is assumed ๐คทโโ๏ธ. When the client does have a preference, it wants the server to send back the representation in that format โจ. The server returns the preferred Content-Format if it's available. If it can't, then a 4.06 "Not Acceptable" MUST be sent as the response, unless some other error code takes precedence for that response ๐.
5.10.5. Max-Age โณ
Max-Age says the maximum time a response can be cached before it's considered not fresh (see Section 5.6.1) ๐ฆ.
The option value is an integer number of seconds between 0 and 2**32-1 inclusive, which is about 136.1 years ๐ญ. If the option isn't in a response, a default of 60 seconds gets assumed ๐ธ.
The value is meant to be current at the time it's sent ๐. Servers that provide resources with strict tolerances on the value of Max-Age SHOULD update the value before each retransmission. (See also Section 5.7.1.)
5.10.6. ETag ๐ท๏ธ
An entity-tag is meant to be a resource-local identifier, so you can tell apart the representations of the same resource that vary over time ๐ฅ. The server providing the resource generates it, and it can do that in any number of ways, including a version, checksum, hash, or time โฐ. An endpoint receiving an entity-tag MUST treat it as opaque and make no assumptions about its content or structure ๐. (Endpoints that generate an entity-tag are encouraged to use the most compact representation possible, in particular in regards to clients and intermediaries that may want to store multiple ETag values.)
5.10.6.1. ETag as a Response Option ๐
The ETag Option in a response gives the current value (i.e., after the request was processed) of the entity-tag for the "tagged representation" ๐. If no Location-* options are present, the tagged representation is the selected representation (Section 5.5.3) of the target resource. If one or more Location-* options are present, and thus a location URI is indicated (Section 5.10.7), the tagged representation is the representation that would be retrieved by a GET request to the location URI.
An ETag response option can be included with any response for which there is a tagged representation (e.g., it would not be meaningful in a 4.04 or 4.00 response). The ETag Option MUST NOT occur more than once in a response.
There is no default value for the ETag Option. If it isn't in a response, the server makes no statement about the entity-tag for the tagged representation ๐ค.
5.10.6.2. ETag as a Request Option ๐
In a GET request, an endpoint that has one or more representations previously obtained from the resource, and has obtained ETag response options with these, can specify an instance of the ETag Option for one or more of these stored responses ๐ฆ.
A server can issue a 2.03 Valid response (Section 5.9.1.3) in place of a 2.05 Content response if one of the ETags given is the entity-tag for the current representation, i.e., is valid. The 2.03 Valid response then echoes this specific ETag in a response option โ .
Basically, a client can figure out whether any of its stored representations is still current (see Section 5.6.2) without having to transfer them again. Iconic efficiency ๐.
The ETag Option MAY occur zero, one, or multiple times in a request.
5.10.7. Location-Path and Location-Query ๐
The Location-Path and Location-Query Options work together to indicate a relative URI that consists of an absolute path, a query string, or both. A combination of these options is included in a 2.01 (Created) response to show where the resource created by a POST request lives (see Section 5.8.2) ๐ง. The location gets resolved relative to the request URI.
If a response with one or more Location-Path and/or Location-Query Options passes through a cache that interprets these options, and the implied URI identifies one or more currently stored responses, those entries MUST be marked as not fresh ๐ โโ๏ธ.
Each Location-Path Option specifies one segment of the absolute path to the resource, and each Location-Query Option specifies one argument parameterizing the resource. The Location-Path and Location-Query Option can contain any character sequence. No percent-encoding is performed. The value of a Location-Path Option MUST NOT be "." or "..". (No dot-dot drama allowed ๐ โโ๏ธ๐ .)
The steps for constructing the location URI from the options are analogous to Section 6.5, except that the first five steps are skipped and the result is a relative URI-reference, which is then interpreted relative to the request URI. Note that the relative URI-reference constructed this way always includes an absolute path (e.g., leaving out Location-Path but supplying Location-Query means the path component in the URI is "/") ๐ธ.
The options that are used to compute the relative URI-reference are collectively called Location-* options. Beyond Location-Path and Location-Query, more Location-* options may be defined in the future and have been reserved option numbers 128, 132, 136, and 140. If any of these reserved option numbers occurs in addition to Location-Path and/or Location-Query and are not supported, then a 4.02 (Bad Option) error MUST be returned ๐ซ.
5.10.8. Conditional Request Options ๐ฆ
Conditional request options let a client ask the server to perform the request only if certain conditions specified by the option are fulfilled. It's giving "only if you're ready" energy ๐ฅน.
For each of these options, if the condition given is not fulfilled, then the server MUST NOT perform the requested method. Instead, the server MUST respond with the 4.12 (Precondition Failed) Response Code ๐ .
If the condition is fulfilled, the server performs the request method as if the conditional request options were not present โจ.
If the request would, without the conditional request options, result in anything other than a 2.xx or 4.12 Response Code, then any conditional request options MAY be ignored ๐คทโโ๏ธ.
5.10.8.1. If-Match ๐ช
The If-Match Option MAY be used to make a request conditional on the current existence or value of an ETag for one or more representations of the target resource. If-Match is generally useful for resource update requests, such as PUT requests, as a means for protecting against accidental overwrites when multiple clients are acting in parallel on the same resource (i.e., the "lost update" problem). Nobody wants their update quietly erased ๐ญ๐ซถ.
The value of an If-Match option is either an ETag or the empty string. An If-Match option with an ETag matches a representation with that exact ETag. An If-Match option with an empty value matches any existing representation (i.e., it places the precondition on the existence of any current representation for the target resource) ๐ฏ.
The If-Match Option can occur multiple times. If any of the options match, then the condition is fulfilled ๐ฅณ.
If there is one or more If-Match Options, but none of the options match, then the condition is not fulfilled ๐.
5.10.8.2. If-None-Match ๐
The If-None-Match Option MAY be used to make a request conditional on the nonexistence of the target resource. If-None-Match is useful for resource creation requests, such as PUT requests, as a means for protecting against accidental overwrites when multiple clients are acting in parallel on the same resource. The If-None-Match Option carries no value ๐ท.
If the target resource does exist, then the condition is not fulfilled โ.
(It is not very useful to combine If-Match and If-None-Match options in one request, because the condition will then never be fulfilled. Don't do the messy combo, bestie ๐ โโ๏ธ.)
5.10.9. Size1 Option ๐
The Size1 option provides size information about the resource representation in a request. The option value is an integer number of bytes ๐ง. Its main use is with block-wise transfers [BLOCK]. In the present specification, it is used in 4.13 responses (Section 5.9.2.9) to indicate the maximum size of request entity that the server is able and willing to handle ๐.
6. CoAP URIs ๐
CoAP uses the "coap" and "coaps" URI schemes for identifying CoAP resources and providing a means of locating the resource ๐ฆ. Resources are organized hierarchically and governed by a potential CoAP origin server listening for CoAP requests ("coap") or DTLS-secured CoAP requests ("coaps") on a given UDP port. The CoAP server is identified via the generic syntax's authority component, which includes a host component and optional UDP port number. The remainder of the URI is considered to be identifying a resource that can be operated on by the methods defined by the CoAP protocol. The "coap" and "coaps" URI schemes can thus be compared to the "http" and "https" URI schemes, respectively ๐ซถ.
The syntax of the "coap" and "coaps" URI schemes is specified in this section in Augmented Backus-Naur Form (ABNF) [RFC5234]. The definitions of "host", "port", "path-abempty", "query", "segment", "IP-literal", "IPv4address", and "reg-name" are adopted from [RFC3986] ๐.
Implementation Note: Unfortunately, over time, the URI format has acquired significant complexity. Implementers are encouraged to examine [RFC3986] closely. For example, the ABNF for IPv6 addresses is more complicated than maybe expected. Also, implementers should take care to perform the processing of percent-decoding or percent-encoding exactly once on the way from a URI to its decoded components or back. Percent-encoding is crucial for data transparency but may lead to unusual results such as a slash character in a path component. URIs are lowkey chaos, so read [RFC3986] closely ๐๐ซ .
6.1. coap URI Scheme ๐ฆ
coap-URI = "coap:" "//" host [ ":" port ] path-abempty [ "?" query ]
okay so the host part is basically where the server lives ๐ . If the host is written as an IP-literal or an IPv4address, the CoAP server can be reached at that exact IP address, no detours needed โจ. If the host is a registered name instead, that name is treated as an indirect identifier, so the endpoint might use a name lookup service like DNS to figure out the address behind it ๐. The host MUST NOT be empty ๐ซ. If a URI shows up with a missing authority or an empty host, it MUST be considered invalid, no exceptions bestie ๐.
The port subcomponent tells you which UDP port the CoAP server is listening on ๐ง. If it's empty or not given at all, the default port 5683 is assumed ๐.
The path picks out a resource inside the host and port scope ๐บ๏ธ. It's a bunch of path segments separated by a slash, which is U+002F SOLIDUS "/" for the nerds in the back ๐ค.
The query is how you add extra flavour to the resource ๐ธ. It's a list of arguments separated by an ampersand, U+0026 AMPERSAND "&" ๐ . Each argument is usually a "key=value" pair, so very on brand for URIs โจ.
The "coap" scheme also supports the "/.well-known/" path prefix from [RFC5785] ๐ง. That's the official "well-known locations" zone in a host's namespace, and it's how you discover policy or other info about a host (the so-called "site-wide metadata") ๐. Think hosted resources and stuff, see Section 7 for the deets ๐.
Application designers are encouraged to make their URIs short but descriptive ๐. Like, CoAP lives in environments that are super tight on bandwidth and energy, so you want to lean toward shortness here, without ditching the descriptive part entirely ๐. Balance is everything, periodt ๐.
6.2. coaps URI Scheme ๐
coaps-URI = "coaps:" "//" host [ ":" port ] path-abempty
[ "?" query ]
so "coaps" is basically the secure sibling of "coap" ๐. Every single requirement listed above for "coap" also applies to "coaps" ๐ฏ, with two little differences. First, the default UDP port is 5684 when the port subcomponent is empty or missing ๐. Second, the UDP datagrams MUST be secured with DTLS, as described in Section 9.1 ๐ก๏ธ. No DTLS, no "coaps" ๐ โโ๏ธ.
Caching of responses to "coaps" identified requests is covered in Section 11.2 ๐ง.
Resources available through "coaps" have no shared identity with the "coap" scheme ๐ซฃ. Even if both URIs point to the same authority, meaning the same host listening on the same UDP port, they're totally separate namespaces ๐ฏโโ๏ธ. They're treated as distinct origin servers, so no mixing them up!! ๐ญ
6.3. Normalization and Comparison Rules ๐งฎ
Since "coap" and "coaps" follow the URI generic syntax, these URIs get normalized and compared using the algorithm in Section 6 of [RFC3986] โจ. You just use the defaults described above for each scheme ๐.
If the port matches the default port for the scheme, the normal form is to drop the port subcomponent entirely ๐๏ธ. An empty path counts as an absolute path of "/", so the normal form gives you "/" instead ๐. The scheme and host are case insensitive and usually written in lowercase ๐ก. IP-literals should be in the recommended form from [RFC5952] ๐. Everything else gets compared case-sensitively, so be careful, bestie ๐ง. Characters outside the "reserved" set are equivalent to their percent-encoded bytes (see Section 2.1 of [RFC3986]), and the normal form is to not encode them ๐ซถ.
Here's a cute example where these three URIs are all equivalent and end up producing the same options and option values in the CoAP messages ๐:
coap://example.com:5683/~sensors/temp.xml
coap://EXAMPLE.com/%7Esensors/temp.xml
coap://EXAMPLE.com:/%7esensors/temp.xml
6.4. Decomposing URIs into Options ๐ฐ
This is the recipe for parsing a request's options out of a string called |url| ๐ฅฃ. The steps either give you zero or more of the Uri-Host, Uri-Port, Uri-Path, and Uri-Query Options in the request, or they fail ๐.
- If the |url| string isn't an absolute URI ([RFC3986]), then fail this algorithm ๐ โโ๏ธ.
- Resolve the |url| string using the reference resolution process defined by [RFC3986] ๐. At this point the URL is in ASCII encoding ([RFC0020]), even though the decoded components get interpreted in UTF-8 ([RFC3629]) after steps 5, 8, and 9 ๐.
NOTE: It doesn't matter what it's resolved relative to, since we already know it's an absolute URL at this stage ๐คทโโ๏ธ.
- If |url| doesn't have a <scheme> component whose value, when converted to ASCII lowercase, is "coap" or "coaps", then fail this algorithm ๐ซ.
- If |url| has a <fragment> component, then fail this algorithm ๐ .
- If the <host> component of |url| doesn't represent the request's destination IP address as an IP-literal or IPv4address, include a Uri-Host Option โจ. Its value is the <host> component of |url|, converted to ASCII lowercase, with all percent-encodings ("%" followed by two hexadecimal digits) converted to the matching characters ๐ค.
NOTE: In the usual case where the destination IP address comes from the host part, this makes sure a Uri-Host Option only ever shows up for a <host> component of the form reg-name ๐ง .
- If |url| has a <port> component, then let |port| be that component's value read as a decimal integer ๐ข. Otherwise, let |port| be the default port for the scheme ๐ฏ.
- If |port| doesn't equal the request's destination UDP port, include a Uri-Port Option, and its value is |port| ๐.
- If the value of the <path> component of |url| is empty or is just a single slash character (U+002F SOLIDUS "/"), then move on to the next step ๐.
Otherwise, for each segment in the <path> component, include a Uri-Path Option. Its value is the segment (without the delimiting slashes), with each percent-encoding ("%" followed by two hexadecimal digits) converted to the matching byte ๐งฉ.
- If |url| has a <query> component, then, for each argument in it, include a Uri-Query Option. Its value is the argument (without the question mark and the delimiting ampersands), with each percent-encoding converted to the matching byte ๐.
Note that these rules completely resolve any percent-encoding ๐.
6.5. Composing URIs from Options ๐๏ธ
Now the reverse ๐ช. These are the steps for building a URI from a request's options, and they either give you a URI or they fail ๐. Here, percent-encoding a character means swapping each of its (UTF-8-encoded) bytes for a "%" followed by two hexadecimal digits representing that byte ๐ . The A-F digits are uppercase (as in Section 2.1 of [RFC3986]), and to cut down on variability, the hexadecimal notation for percent-encoding in CoAP URIs MUST use uppercase letters ๐ โจ. The definitions of "unreserved" and "sub-delims" come straight from [RFC3986] ๐.
- If the request is secured using DTLS, let |url| be the string "coaps://". Otherwise, let |url| be the string "coap://" ๐.
- If the request includes a Uri-Host Option, let |host| be that option's value, with any non-ASCII characters replaced by their percent-encoding ๐. If |host| isn't a valid reg-name, IP-literal, or IPv4address, fail the algorithm ๐ซ. If the request doesn't include a Uri-Host Option, let |host| be the IP-literal (following the conventions of [RFC5952]) or IPv4address representing the request's destination IP address ๐.
- Append |host| to |url| โ.
- If the request includes a Uri-Port Option, let |port| be that option's value ๐. Otherwise, let |port| be the request's destination UDP port ๐ฏ.
- If |port| isn't the default port for the scheme, append a single U+003A COLON character (:) followed by the decimal representation of |port| to |url| ๐.
- Let |resource name| be the empty string ๐ซ. For each Uri-Path Option in the request, append a single U+002F SOLIDUS character (/) followed by the option's value to |resource name|, converting any character that isn't in the "unreserved" set, the "sub-delims" set, a U+003A COLON (:), or a U+0040 COMMERCIAL AT (@) into its percent-encoded form ๐ง.
- If |resource name| is the empty string, set it to a single U+002F SOLIDUS character (/) ๐ท.
- For each Uri-Query Option in the request, append a single U+003F QUESTION MARK (?) for the first option, or U+0026 AMPERSAND (&) for subsequent options, followed by the option's value to |resource name| ๐. Any character that isn't in the "unreserved" set, the "sub-delims" set (except U+0026 AMPERSAND (&)), a U+003A COLON (:), a U+0040 COMMERCIAL AT (@), a U+002F SOLIDUS (/), or a U+003F QUESTION MARK (?) gets converted to its percent-encoded form ๐ .
- Append |resource name| to |url| ๐งท.
- Return |url| ๐.
Note that these steps are designed to lead to a URI in normal form (see Section 6.3), so everything lines up neatly ๐.
7. Discovery ๐
7.1. Service Discovery ๐๏ธ
As part of discovering the services a CoAP server offers, a client has to learn about the endpoint the server uses ๐.
A client discovers a server by knowing or learning a URI that references a resource in that server's namespace ๐๏ธ. Alternatively, clients can use multicast CoAP (see Section 8) and the "All CoAP Nodes" multicast address to hunt down CoAP servers ๐ก.
Unless the port subcomponent in a "coap" or "coaps" URI tells you the UDP port the CoAP server is on, the server is assumed to be reachable at the default port ๐ก.
The CoAP default port number 5683 MUST be supported by a server that offers resources for resource discovery (see Section 7.2 below), and it SHOULD be supported for providing access to other resources ๐. The default port number 5684 for DTLS-secured CoAP MAY be supported by a server for resource discovery and for providing access to other resources ๐. Beyond that, other endpoints can be hosted at other ports, e.g., in the dynamic port space ๐ง.
Implementation Note: When a CoAP server is hosted by a 6LoWPAN node, header compression efficiency improves when it also supports a port number in the 61616-61631 compressed UDP port space defined in [RFC4944] and [RFC6282] ๐๏ธ. (Note that, since its UDP port differs from the default port, it's a different endpoint from the server at the default port ๐ฏ.)
7.2. Resource Discovery ๐๏ธ
Discovering the resources a CoAP endpoint offers is extremely important in machine-to-machine applications, where there are no humans in the loop and static interfaces lead to fragility ๐ค๐. To maximize interoperability in a CoRE environment, a CoAP endpoint SHOULD support the CoRE Link Format of discoverable resources as described in [RFC6690], except where fully manual configuration is wanted โจ. It's up to the server which resources get made discoverable (if any) ๐ธ.
7.2.1. 'ct' Attribute ๐
Okay bestie, this part introduces a brand new Web Linking [RFC5988] attribute built to work with [RFC6690] โจ. It's called "ct", and it's giving "here's a little hint about which Content-Formats this resource hands back" ๐
. It's only a hint though! It does not override the Content-Format Option of a CoAP response you get by actually requesting the representation ๐. The value is a CoAP identifier code written as a decimal ASCII integer, and it MUST be in the range 0-65535 (a 16-bit unsigned integer) ๐ข. For example, "application/xml" gets written as ct=41 ๐ง. If there's no Content-Format code attribute, then you can't assume anything about the type, so don't guess ๐. The attribute MAY include a space-separated sequence of Content-Format codes, which means multiple formats are available ๐. The syntax lives in the production "ct-value" in Figure 12, where "cardinal", "SP", and "DQUOTE" are defined exactly as in [RFC6690] ๐ซถ.
ct-value = cardinal
/ DQUOTE cardinal *( 1*SP cardinal ) DQUOTE
Figure 12
8. Multicast CoAP ๐ธ
Okay so CoAP can totally make requests to an IP multicast group, and this is defined as a series of deltas on top of regular unicast CoAP ๐ฆ. If you want the bigger picture on group communication, check out [GROUPCOMM] ๐.
CoAP endpoints that offer services they want other endpoints to find through multicast service discovery join one or more of the appropriate all-CoAP-node multicast addresses (Section 12.8) and listen on the default CoAP port ๐ก. Here's the tea: an endpoint might also receive multicast requests on other multicast addresses, including the all-nodes IPv6 address (or via broadcast on IPv4) ๐ญ. So an endpoint MUST therefore be prepared to receive those messages, but it MAY ignore them if multicast service discovery isn't wanted ๐โจ.
8.1. Messaging Layer ๐
A multicast request is characterized by being carried in a CoAP message that is addressed to an IP multicast address instead of a CoAP endpoint ๐ซ. Such multicast requests MUST be Non-confirmable ๐ โโ๏ธ.
A server SHOULD be aware that a request arrived via multicast, e.g., by using modern APIs such as IPV6_RECVPKTINFO [RFC3542], if available ๐ง .
To avoid an implosion of error responses ๐ฅ, when a server is aware that a request arrived via multicast, it MUST NOT return a Reset message in reply to a Non-confirmable message. If it isn't aware, it MAY return a Reset message in reply to a Non-confirmable message as usual. A Reset like that looks exactly like one for a unicast message from the sender, so the sender MUST avoid using a Message ID that is also still active from this endpoint with any unicast endpoint that might receive the multicast message ๐ฏ.
At the time of writing, multicast messages can only be carried in UDP, not in DTLS. This means the security modes defined for CoAP in this document are not applicable to multicast. โ ๏ธ
8.2. Request/Response Layer ๐
When a server is aware that a request arrived via multicast, the server MAY always ignore the request, especially if it has nothing useful to respond with (e.g., if it only has an empty payload or an error response) ๐ซ . That call can depend on the application. (For example, in query filtering as described in [RFC6690], a server should not respond to a multicast request if the filter doesn't match. More examples are in [GROUPCOMM].) ๐
If a server does decide to respond to a multicast request, it should not respond immediately. Instead, it should pick a duration for the period of time during which it intends to respond โณ. For this exposition, we call the length of that period the Leisure ๐ฆ. The specific value of this Leisure may depend on the application or MAY be derived as described below. The server SHOULD then pick a random point of time within the chosen leisure period to send back the unicast response to the multicast request ๐ฒ. If further responses need to be sent based on the same multicast address membership, a new leisure period starts at the earliest after the previous one finishes ๐.
To compute a value for Leisure, the server should have a group size estimate G, a target data transfer rate R (both should be chosen conservatively), and an estimated response size S. A rough lower bound for Leisure can then be computed as:
lb_Leisure = S * G / R
For example, for a multicast request with link-local scope on a 2.4 GHz IEEE 802.15.4 (6LoWPAN) network, G could be (relatively conservatively) set to 100, S to 100 bytes, and the target rate to 8 kbit/s = 1 kB/s. The resulting lower bound for the Leisure is 10 seconds โฑ๏ธโจ.
If a CoAP endpoint doesn't have suitable data to compute a value for Leisure, it MAY resort to DEFAULT_LEISURE ๐ซถ.
When matching a response to a multicast request, only the token MUST match. The source endpoint of the response doesn't need to be (and won't be) the same as the destination endpoint of the original request ๐ง.
For the purposes of interpreting the Location-* options and any links embedded in the representation, the request URI (i.e., the base URI relative to which the response is interpreted) is formed by replacing the multicast address in the Host component of the original request URI with the literal IP address of the endpoint that actually responded ๐.
8.2.1. Caching ๐๏ธ
When a client makes a multicast request, it always makes a new request to the multicast group. That's because there may be new group members that joined in the meantime, or ones that didn't get the previous request ๐. It MAY update a cache with the received responses. Then it uses both cached-still-fresh and new responses as the result of the request ๐.
A response received in reply to a GET request to a multicast group MAY be used to satisfy a subsequent request on the related unicast request URI. The unicast request URI is obtained by replacing the authority part of the request URI with the transport-layer source address of the response message ๐ฆ.
A cache MAY revalidate a response by making a GET request on the related unicast request URI ๐.
A GET request to a multicast group MUST NOT contain an ETag option. A mechanism to suppress responses the client already has is left for further study ๐ง.
8.2.2. Proxying ๐
When a forward-proxy receives a request with a Proxy-Uri, or a URI constructed from Proxy-Scheme, that indicates a multicast address, the proxy obtains a set of responses as described above. It then sends all responses (both cached-still-fresh and new) back to the original client ๐.
This specification doesn't provide a way to indicate the unicast-modified request URI (base URI) in responses forwarded this way. Proxying multicast requests is discussed in more detail in [GROUPCOMM], and one proposal to address the base URI issue can be found in Section 3 of [CoAP-MISC] ๐.
9. Securing CoAP ๐
This section defines the DTLS binding for CoAP ๐.
During the provisioning phase, a CoAP device gets the security information it needs, including keying materials and access control lists ๐๏ธ. This specification defines provisioning for the RawPublicKey mode in Section 9.1.3.2.1. At the end of the provisioning phase, the device will be in one of four security modes, each with the following information for that mode. The NoSec and RawPublicKey modes are mandatory to implement for this specification ๐.
- NoSec: There is no protocol-level security, because DTLS is disabled. Alternative techniques to provide lower-layer security SHOULD be used when appropriate. The use of IPsec is discussed in [IPsec-CoAP]. Certain link layers used with constrained nodes also provide link-layer security, which may be appropriate with proper key management ๐งฑ.
- PreSharedKey: DTLS is enabled, there is a list of pre-shared keys [RFC4279], and each key includes a list of which nodes it can be used to communicate with, as described in Section 9.1.3.1. At the extreme, there may be one key for each node this CoAP node needs to communicate with (a 1:1 node/key ratio). Conversely, if more than two entities share a specific pre-shared key, this key only enables the entities to authenticate as a member of that group and not as a specific peer ๐.
- RawPublicKey: DTLS is enabled, and the device has an asymmetric key pair without a certificate (a raw public key) that is validated using an out-of-band mechanism [RFC7250], as described in Section 9.1.3.2. The device also has an identity calculated from the public key and a list of identities of the nodes it can communicate with ๐ฆ.
- Certificate: DTLS is enabled, and the device has an asymmetric key pair with an X.509 certificate [RFC5280] that binds it to its subject and is signed by some common trust root, as described in Section 9.1.3.3. The device also has a list of root trust anchors that can be used for validating a certificate ๐.
In the "NoSec" mode, the system simply sends the packets over normal UDP over IP, and it is indicated by the "coap" scheme and the CoAP default port ๐ฆ. The system is secured only by keeping attackers from being able to send or receive packets from the network with the CoAP nodes. See Section 11.5 for an additional complication with this approach ๐ฌ.
The other three security modes are achieved using DTLS and are indicated by the "coaps" scheme and the DTLS-secured CoAP default port ๐. The result is a security association that can be used to authenticate (within the limits of the security model) and, based on this authentication, authorize the communication partner ๐ซถ. CoAP itself doesn't provide protocol primitives for authentication or authorization. Where this is required, it can be provided either by communication security (i.e., IPsec or DTLS) or by object security (within the payload). Devices that require authorization for certain operations are expected to require one of these two forms of security ๐ก๏ธ. Necessarily, where an intermediary is involved, communication security only works when that intermediary is part of the trust relationships. CoAP doesn't provide a way to forward different levels of authorization that clients may have with an intermediary to further intermediaries or origin servers -- so it therefore may be required to perform all authorization at the first intermediary ๐ฅบโจ.
9.1. DTLS-Secured CoAP โจ
okay so just like HTTP gets its security glow-up from TLS over TCP ๐, CoAP gets its own with Datagram TLS (DTLS) [RFC6347] over UDP (check Figure 13 ๐). This section defines the CoAP binding to DTLS, along with the minimal mandatory-to-implement configurations appropriate for constrained environments. The binding is defined as a series of deltas to unicast CoAP. In practice, DTLS is basically TLS with extra features to handle the unreliable nature of UDP transport ๐ฆ
+----------------------+
| Application |
+----------------------+
+----------------------+
| Requests/Responses |
|----------------------| CoAP
| Messages |
+----------------------+
+----------------------+
| DTLS |
+----------------------+
+----------------------+
| UDP |
+----------------------+
Figure 13: Abstract Layering of DTLS-Secured CoAP
In some constrained nodes (limited flash and/or RAM) and networks (limited bandwidth or high scalability requirements), and depending on the specific cipher suites in use, all modes of DTLS may not be applicable ๐ฅบ Some DTLS cipher suites can add serious implementation complexity, plus some initial handshake overhead needed when setting up the security association. Once the initial handshake is completed, DTLS adds a limited per-datagram overhead of approximately 13 bytes, not including any initialization vectors/ nonces (e.g., 8 bytes with TLS_PSK_WITH_AES_128_CCM_8 [RFC6655]), integrity check values (e.g., 8 bytes with TLS_PSK_WITH_AES_128_CCM_8 [RFC6655]), and padding required by the cipher suite. Whether a given mode of DTLS is applicable for a CoAP-based application should be carefully weighed ๐ง considering the specific cipher suites that may be applicable, whether session maintenance makes it compatible with application flows, and whether sufficient resources are available on the constrained nodes and for the added network overhead.
(For some modes of using DTLS, this specification identifies a mandatory-to-implement cipher suite. This is an implementation requirement to maximize interoperability in those cases where these cipher suites are indeed appropriate. The specific security policies of an application may determine the actual set of cipher suites that can be used.) DTLS is not applicable to group keying (multicast communication); however, it may be a component in a future group key management protocol ๐ธ
9.1.1. Messaging Layer
The endpoint acting as the CoAP client should also act as the DTLS client ๐ It should initiate a session to the server on the appropriate port. When the DTLS handshake has finished, the client may initiate the first CoAP request. All CoAP messages MUST be sent as DTLS "application data" ๐ฅ
The following rules are added for matching an Acknowledgement message or Reset message to a Confirmable message, or a Reset message to a Non-confirmable message: The DTLS session MUST be the same, and the epoch MUST be the same.
A message is the same when it is sent within the same DTLS session and same epoch and has the same Message ID ๐
Note: When a Confirmable message is retransmitted, a new DTLS sequence_number is used for each attempt, even though the CoAP Message ID stays the same. So a recipient still has to perform deduplication as described in Section 4.5. Retransmissions MUST NOT be performed across epochs ๐
DTLS connections in RawPublicKey and Certificate mode are set up using mutual authentication, so they can stay up and be reused for future message exchanges in either direction โจ Devices can close a DTLS connection when they need to recover resources, but in general they should keep the connection up for as long as possible. Closing the DTLS connection after every CoAP message exchange is very inefficient ๐
9.1.2. Request/Response Layer
The following rules are added for matching a response to a request: The DTLS session MUST be the same, and the epoch MUST be the same. ๐ซถ
This means the response to a DTLS secured request MUST always be DTLS secured using the same security session and epoch. Any attempt to supply a NoSec response to a DTLS request simply does not match the request and therefore MUST be rejected (unless it does match an unrelated NoSec request) ๐ญ
9.1.3. Endpoint Identity
Devices SHOULD support the Server Name Indication (SNI) to indicate their authority in the SNI HostName field, as defined in Section 3 of [RFC6066] ๐ This is needed so that when a host acting as a virtual server for multiple Authorities receives a new DTLS connection, it knows which keys to use for the DTLS session.
9.1.3.1. Pre-Shared Keys
When forming a connection to a new node, the system selects an appropriate key based on which nodes it is trying to reach, and then forms a DTLS session using a PSK (Pre-Shared Key) mode of DTLS ๐ Implementations in these modes MUST support the mandatory-to-implement cipher suite TLS_PSK_WITH_AES_128_CCM_8 as specified in [RFC6655].
Depending on the commissioning model, applications may need to define an application profile for identity hints (as required and detailed in Section 5.2 of [RFC4279]) so they can use PSK identity hints ๐
The security considerations of Section 7 of [RFC4279] apply. In particular, applications should carefully weigh whether or not they need Perfect Forward Secrecy (PFS), and select an appropriate cipher suite (Section 7.1 of [RFC4279]). The entropy of the PSK must be sufficient to mitigate against brute-force and (where the PSK is not chosen randomly but by a human) dictionary attacks (Section 7.2 of [RFC4279]) ๐ฑ The cleartext communication of client identities may leak data or compromise privacy (Section 7.3 of [RFC4279]). Seriously, this part matters, bestie ๐จ
9.1.3.2. Raw Public Key Certificates
In this mode, the device has an asymmetric key pair but without an X.509 certificate (called a raw public key). For example, the asymmetric key pair is generated by the manufacturer and installed on the device (see also Section 11.6) ๐ง A device MAY be configured with multiple raw public keys. The type and length of the raw public key depends on the cipher suite used.
Implementations in RawPublicKey mode MUST support the mandatory-to-implement cipher suite TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 as specified in [RFC7251], [RFC5246], and [RFC4492]. The key used MUST be ECDSA capable. The curve secp256r1 MUST be supported [RFC4492]; this curve is equivalent to the NIST P-256 curve. The hash algorithm is SHA-256. Implementations MUST use the Supported Elliptic Curves and Supported Point Formats Extensions [RFC4492]; the uncompressed point format MUST be supported, and [RFC6090] can be used as an implementation method. Some guidance relevant to the implementation of this cipher suite can be found in [W3CXMLSEC]. The mechanism for using raw public keys with TLS is specified in [RFC7250] ๐
Implementation Note: Specifically, this means the extensions listed in Figure 14 with at least the values listed will be present in the DTLS handshake ๐ง
Extension: elliptic_curves
Type: elliptic_curves (0x000a)
Length: 4
Elliptic Curves Length: 2
Elliptic curves (1 curve)
Elliptic curve: secp256r1 (0x0017)
Extension: ec_point_formats
Type: ec_point_formats (0x000b)
Length: 2
EC point formats Length: 1
Elliptic curves point formats (1)
EC point format: uncompressed (0)
Extension: signature_algorithms
Type: signature_algorithms (0x000d)
Length: 4
Data (4 bytes): 00 02 04 03
HashAlgorithm: sha256 (4)
SignatureAlgorithm: ecdsa (3)
Figure 14: DTLS Extensions Present for
TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
9.1.3.2.1. Provisioning
The RawPublicKey mode was designed to be easily provisioned in M2M deployments ๐ค It is assumed that each device has an appropriate asymmetric public key pair installed. An identifier is calculated by the endpoint from the public key, as described in Section 2 of [RFC6920]. All implementations that support checking RawPublicKey identities MUST support at least the sha-256-120 mode (SHA-256 truncated to 120 bits). Implementations SHOULD also support longer length identifiers and MAY support shorter lengths. Note that shorter lengths provide less security against attacks, and their use is NOT RECOMMENDED ๐
โโ๏ธ
Depending on how identifiers are given to the system that verifies them, support for URI, binary, and/or human-speakable format [RFC6920] needs to be implemented. All implementations SHOULD support the binary mode, and implementations that have a user interface SHOULD also support the human-speakable format ๐
During provisioning, the identifier of each node is collected, for example, by reading a barcode on the outside of the device or by obtaining a pre-compiled list of the identifiers. These identifiers are then installed in the corresponding endpoint, for example, an M2M data collection server. The identifier is used for two purposes: to associate the endpoint with further device information, and to perform access control. During (initial and ongoing) provisioning, an access control list of identifiers with which the device may start DTLS sessions SHOULD also be installed and maintained ๐
9.1.3.3. X.509 Certificates โจ
okay so if you're in Certificate Mode, you MUST support the mandatory-to-implement cipher suite TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 ๐ as specified in [RFC7251], [RFC5246], and [RFC4492]. The certificate has to include a SubjectPublicKeyInfo saying the algorithm is id-ecPublicKey with namedCurves secp256r1 [RFC5480], and the public key format is uncompressed [RFC5480]. The hash algorithm is SHA-256, and if the key usage extension is included, it indicates digitalSignature. Certificates MUST be signed with ECDSA using secp256r1, and the signature MUST use SHA-256. The key MUST be ECDSA capable. The curve secp256r1 MUST be supported [RFC4492], and it's the same thing as the NIST P-256 curve ๐
. Implementations MUST use the Supported Elliptic Curves and Supported Point Formats Extensions [RFC4492], the uncompressed point format MUST be supported, and [RFC6090] can be used as an implementation method ๐ซถ.
The subject in the certificate would be built from a long-term unique identifier for the device, like the EUI-64 [EUI64] ๐. The subject could also be based on the Fully Qualified Domain Name (FQDN) that was used as the Host part of the CoAP URI. Not me though, the device's IP address should not typically be used as the subject ๐, because it would change over time. The discovery process in the system would build the mapping between the IP addresses of each device and its subject. Some devices could have more than one subject and would need more than a single certificate. Main character energy for sure ๐.
When a new connection is formed, the certificate from the remote device needs to be verified ๐. If the CoAP node has a source of absolute time, then the node SHOULD check that the validity dates of the certificate are within range. The certificate MUST be validated as appropriate for the security requirements, using functionality equivalent to the algorithm in Section 6 of [RFC5280]. If the certificate contains a SubjectAltName, then the authority of the request URI MUST match at least one of the authorities of any CoAP URI found in a field of URI type in the SubjectAltName set. If there is no SubjectAltName in the certificate, then the authority of the request URI MUST match the Common Name (CN) found in the certificate, using the matching rules defined in [RFC3280], with the exception that certificates with wildcards are not allowed ๐ซ.
CoRE support for certificate status checking requires further study ๐. A mapping of the Online Certificate Status Protocol (OCSP) [RFC6960] onto CoAP isn't defined right now, and OCSP may also not be easily applicable in all environments. So an alternative approach may be using the TLS Certificate Status Request extension (Section 8 of [RFC6066]; also known as "OCSP stapling") or, preferably, the Multiple Certificate Status Extension ([RFC6961]), if available ๐.
If the system has a shared key in addition to the certificate, then a cipher suite that includes the shared key, such as TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA [RFC5489], SHOULD be used ๐.
10. Cross-Protocol Proxying between CoAP and HTTP ๐ฆ
okay so CoAP only supports a limited subset of HTTP functionality, which means proxying between the two is honestly pretty straightforward ๐. There are a few reasons you might want to proxy between CoAP and HTTP, like designing a web interface that works over either protocol or building an actual CoAP-HTTP proxy ๐ง. CoAP could also be proxied to other protocols like XMPP [RFC6120] or SIP [RFC3264], but defining those mechanisms is out of scope for this spec, so we're skipping them ๐ โโ๏ธ.
There are two possible directions for accessing a resource through a forward-proxy:
- CoAP-HTTP Proxying: lets CoAP clients access resources on HTTP servers through an intermediary. It's kicked off by including the Proxy-Uri or Proxy-Scheme Option with an "http" or "https" URI in a CoAP request to a CoAP-HTTP proxy ๐.
- HTTP-CoAP Proxying: lets HTTP clients access resources on CoAP servers through an intermediary. It's kicked off by specifying a "coap" or "coaps" URI in the Request-Line of an HTTP request to an HTTP-CoAP proxy ๐.
Either way, only the request/response model of CoAP gets mapped to HTTP. The underlying model of Confirmable or Non-confirmable messages, etc., is invisible and MUST have no effect on a proxy function ๐. The following sections describe how requests to a forward-proxy are handled. Reverse-proxies aren't specified, since the proxy function is transparent to the client, with the proxy acting as if it were the origin server. Still, similar considerations apply to reverse-proxies as to forward-proxies, and there generally will be an expectation that reverse-proxies operate in a similar way to forward-proxies ๐. As an implementation note, HTTP client libraries may make it hard to operate an HTTP-CoAP forward-proxy by not giving you a way to put a CoAP URI on the HTTP Request-Line, so reverse-proxying may therefore lead to wider applicability of a proxy ๐ธ. A separate specification may define a convention for URIs operating such an HTTP-CoAP reverse-proxy [MAPPING].
10.1. CoAP-HTTP Proxying
If a request contains a Proxy-Uri or Proxy-Scheme Option with an 'http' or 'https' URI [RFC2616], then the receiving CoAP endpoint (called "the proxy" from here on) is requested to perform the operation specified by the request method on the indicated HTTP resource and return the result to the client. (See also Section 5.7 for how the request to the proxy is formulated, including security requirements ๐.)
This section specifies, for any CoAP request, the CoAP response that the proxy should return to the client. How the proxy actually satisfies the request is an implementation detail ๐ ๏ธ, although the typical case is expected to be that the proxy translates and forwards the request to an HTTP origin server.
Since HTTP and CoAP share the basic set of request methods, performing a CoAP request on an HTTP resource isn't that different from performing it on a CoAP resource ๐ค. The meanings of the individual CoAP methods when performed on HTTP resources are explained in the subsections below.
If the proxy is unable or unwilling to service a request with an HTTP URI, a 5.05 (Proxying Not Supported) response is returned to the client ๐ โโ๏ธ. If the proxy services the request by interacting with a third party (such as the HTTP origin server) and can't get a result within a reasonable time frame, a 5.04 (Gateway Timeout) response is returned. If a result can be obtained but isn't understood, a 5.02 (Bad Gateway) response is returned ๐.
10.1.1. GET
The GET method asks the proxy to return a representation of the HTTP resource identified by the request URI ๐.
On success, a 2.05 (Content) Response Code SHOULD be returned ๐. The payload of the response MUST be a representation of the target HTTP resource, and the Content-Format Option MUST be set accordingly. The response MUST indicate a Max-Age value that is no greater than the remaining time the representation can be considered fresh โฐ. If the HTTP entity has an entity-tag, the proxy SHOULD include an ETag Option in the response and process ETag Options in requests as described below ๐ท๏ธ.
A client can influence how a GET request is processed by including the following options:
- Accept: The request MAY include an Accept Option, identifying the preferred response content-format ๐.
- ETag: The request MAY include one or more ETag Options, identifying responses that the client has stored. This asks the proxy to send a 2.03 (Valid) response whenever it would otherwise send a 2.05 (Content) response with an entity-tag in the requested set ๐ฅฐ. Note that CoAP ETags are always strong ETags in the HTTP sense. CoAP doesn't have the equivalent of HTTP weak ETags, and there's no good way to make use of them in a cross-proxy ๐.
10.1.2. PUT
The PUT method asks the proxy to update or create the HTTP resource identified by the request URI, using the enclosed representation โ๏ธ.
If a new resource gets created at the request URI, a 2.01 (Created) response MUST be returned to the client. If an existing resource gets modified, a 2.04 (Changed) response MUST be returned to show the request finished successfully โ .
10.1.3. DELETE
The DELETE method asks the proxy to delete the HTTP resource identified by the request URI at the HTTP origin server ๐๏ธ.
A 2.02 (Deleted) response MUST be returned to the client on success, or if the resource doesn't exist at the time of the request ๐ซก.
10.1.4. POST
The POST method asks the proxy to have the representation enclosed in the request processed by the HTTP origin server. What the POST method actually does is decided by the origin server and depends on the resource identified by the request URI ๐ง.
If the action performed by the POST method doesn't result in a resource that can be identified by a URI, a 2.04 (Changed) response MUST be returned to the client. If a resource has been created on the origin server, a 2.01 (Created) response MUST be returned ๐.
10.2. HTTP-CoAP Proxying
If an HTTP request contains a Request-URI with a "coap" or "coaps" URI, then the receiving HTTP endpoint (called "the proxy" from here on) is requested to perform the operation specified by the request method on the indicated CoAP resource and return the result to the client ๐ช.
This section specifies, for any HTTP request, the HTTP response that the proxy should return to the client. Unless otherwise specified, all the statements made are RECOMMENDED behavior ๐ซ. Some highly constrained implementations may need to resort to shortcuts ๐ค. How the proxy actually satisfies the request is an implementation detail, although the typical case is expected to be that the proxy translates and forwards the request to a CoAP origin server. The meanings of the individual HTTP methods when performed on CoAP resources are explained in the subsections below.
If the proxy is unable or unwilling to service a request with a CoAP URI, a 501 (Not Implemented) response is returned to the client. If the proxy services the request by interacting with a third party (such as the CoAP origin server) and can't get a result within a reasonable time frame, a 504 (Gateway Timeout) response is returned. If a result can be obtained but isn't understood, a 502 (Bad Gateway) response is returned ๐ซ .
10.2.1. OPTIONS and TRACE
Since the OPTIONS and TRACE methods aren't supported in CoAP, a 501 (Not Implemented) error MUST be returned to the client ๐.
10.2.2. GET
okay so GET is the "hey proxy, can you grab me the CoAP resource at this Request-URI and send it back" method ๐ and when it works you get a 200 (OK) back โจ The payload MUST be a representation of the target CoAP resource, and the Content-Type and Content-Encoding header fields MUST be set to match it ๐ The response MUST also have a max-age directive, and that value can't be bigger than however long the representation is still fresh ๐ If the CoAP response has an ETag option, the proxy should include an ETag header field too ๐ซถ
Clients can also tweak how a GET gets handled by adding these options ๐
- Accept: the most-preferred media type from the HTTP
Acceptheader becomes a CoAP Accept option ๐ธ HTTP's media-type ranges, parameters, and extensions aren't supported by the CoAP Accept option, so those don't come along for the ride ๐ญ If the proxy can't send back something that fits the combinedAcceptfield value, it sends a 406 (Not Acceptable) response ๐ The proxy MAY then retry the request with the next media types from the HTTPAcceptheader field ๐ - Conditional GETs: conditional HTTP GET requests that include an
If-MatchorIf-None-Matchrequest-header field can be mapped onto a matching CoAP request ๐ง TheIf-Modified-SinceandIf-Unmodified-Sincerequest-header fields aren't directly supported by CoAP, but a caching proxy handles them locally instead โจ
10.2.3. HEAD
HEAD is basically GET's twin, except the server MUST NOT return a message-body in the response ๐ Same headers, no body, no drama ๐ฆ
CoAP doesn't have a direct version of HTTP's HEAD method, but an HTTP-CoAP proxy still responds to HEAD requests for CoAP resources ๐ The HTTP headers come back with no message-body attached ๐
Implementation Note: an HTTP-CoAP proxy might want to use a block-wise transfer option [BLOCK] to cut down how much data actually gets transferred ๐ It does need to be ready for the case where the origin server doesn't support block-wise transfers at all ๐
10.2.4. POST
POST is the "please process this representation I'm sending you" method ๐ฅ The proxy asks the CoAP origin server to handle the enclosed representation, and what actually happens is up to the origin server and depends on the resource at the request URI ๐
If the POST doesn't result in a resource that has its own URI, a 200 (OK) or 204 (No Content) response MUST be returned to the client ๐ธ If a resource was created on the origin server, a 201 (Created) response MUST be returned ๐
If any of the Location-* Options show up in the CoAP response, the proxy builds a Location header field out of their values and returns it ๐
10.2.5. PUT
PUT means "update this resource, or make it if it doesn't exist yet" ๐งธ The proxy asks the CoAP origin server to do that with the enclosed representation at the Request-URI ๐
If a brand new resource gets created at the Request-URI, the client gets a 201 (Created) response โจ If an existing resource gets modified instead, the client gets either a 200 (OK) or a 204 (No Content) Response Code to say it went through โ
10.2.6. DELETE
DELETE asks the proxy to delete the CoAP resource at the Request-URI on the CoAP origin server ๐๏ธ Bye bye ๐
A successful response is 200 (OK) if the response includes an entity describing the status ๐ It's 204 (No Content) if the action was enacted but the response doesn't include an entity ๐ซง
10.2.7. CONNECT
Not gonna lie, this one isn't happening yet ๐ An HTTP-CoAP proxy can't currently satisfy CONNECT, because TLS to DTLS tunneling hasn't been specified yet ๐ง For now the client gets a 501 (Not Implemented) error ๐
11. Security Considerations ๐
Okay bestie, this part is serious, so let's get into it ๐ซถ This section looks at the possible threats to the protocol ๐ It's here to inform protocol and application developers about the security limitations of CoAP as described in this document ๐ CoAP realizes a subset of the features in HTTP/1.1, so the security considerations in Section 15 of [RFC2616] also apply to CoAP ๐ธ This section focuses on the limitations that are specific to CoAP โจ
11.1. Parsing the Protocol and Processing URIs
A network-facing application can have vulnerabilities in the logic it uses to process incoming packets ๐ฑ Complex parsers are well known as a likely source of these bugs, like being able to remotely crash a node or even remotely execute arbitrary code on it ๐ CoAP tries to shrink those opportunities by keeping parser complexity down ๐งฉ It gives the whole range of encodable values a meaning where it can, and it aggressively cuts the complexity that usually comes from having unnecessary choices between multiple representations that mean the same thing ๐ A lot of the URI processing has been moved to the clients, which means fewer chances for bugs to sneak into the servers ๐ Even so, the URI processing code in CoAP implementations is likely to be a big source of the remaining vulnerabilities, so it should be implemented with special care ๐ CoAP access control implementations need to make sure they don't add vulnerabilities through mismatches between the code that makes access control decisions from a URI and the code that finally serves up the resource at that URI ๐จ The most complex parser left might be the one for the CoRE Link Format, although that was also designed with reduced implementation complexity as a goal [RFC6690] ๐ฆ (See also Section 15.2 of [RFC2616].) ๐
11.2. Proxying and Caching
As Section 15.7 of [RFC2616] mentions, proxies are men-in-the-middle by their very nature ๐ณ That means they break any IPsec or DTLS protection a direct CoAP message exchange might have ๐ So they're interesting targets for breaking the confidentiality or integrity of CoAP message exchanges ๐ฏ As [RFC2616] notes, they're also interesting targets for breaking availability ๐
The threat to confidentiality and integrity of request/response data gets amplified when proxies also cache ๐ฆ CoAP doesn't define any of the cache-suppressing Cache-Control options that HTTP/1.1 provides to better protect sensitive data, so keep that in mind ๐ซฃ
For a caching implementation, any access control considerations that would apply to making the request that generated the cache entry also need to be applied to the value in the cache ๐ This matters for clients that implement multiple security domains, and for proxies that might serve multiple clients ๐ฏ Also, a caching proxy MUST NOT make cached values available to requests that have lesser transport-security properties than the ones the proxy would need to forward the request in the first place ๐ซ
Unlike the "coap" scheme, responses to "coaps" identified requests are never "public" ๐ So they MUST NOT be reused for shared caching, unless the cache can make equivalent access control decisions to the ones that led to the cached entry ๐ They can, however, be reused in a private cache if the message is cacheable by default in CoAP ๐ซง
Finally, a proxy that fans out Separate Responses (as opposed to piggybacked Responses) to multiple original requesters may add extra amplification ๐ข (See Section 11.3.) ๐ธ
11.3. Risk of Amplification
CoAP servers generally reply to a request packet with a response packet ๐จ That response packet can be a lot bigger than the request packet ๐ฌ An attacker could use CoAP nodes to turn a small attack packet into a bigger one, which is known as amplification ๐ฅ So there's a real danger that CoAP nodes get dragged into denial-of-service (DoS) attacks by using the amplifying properties of the protocol ๐จ An attacker trying to overload a victim, but limited in how much traffic it can generate, can use amplification to generate a lot more traffic ๐
This is especially a problem for nodes that enable NoSec access, can be reached by an attacker, and can reach potential victims (for example, on the general Internet) ๐ That's because UDP provides no way to verify the source address in the request packet ๐ซ An attacker just needs to put the victim's IP address in the source address of a suitable request packet, and boom, a bigger packet gets aimed at the victim ๐ฏ
There is one mitigating factor: many constrained networks can only generate a small amount of traffic, which may make CoAP nodes less attractive for this attack ๐งธ But the limited capacity of a constrained network makes the network itself a likely victim of an amplification attack ๐ข
So large amplification factors SHOULD NOT be provided in the response if the request isn't authenticated ๐ซ A CoAP server can cut down how much amplification it gives an attacker by using the slicing/blocking modes of CoAP [BLOCK] and offering large resource representations only in fairly small slices ๐ฐ For example, for a 1000-byte resource, a 10-byte request might result in an 80-byte response (with a 64-byte block) instead of a 1016-byte response, which makes a huge difference in the amplification ๐
CoAP also supports using multicast IP addresses in requests, which is an important requirement for M2M ๐ค Multicast CoAP requests can be the source of accidental or deliberate DoS attacks, especially over constrained networks โ ๏ธ This specification tries to reduce the amplification effects of multicast requests by limiting when a response is returned ๐ก๏ธ To limit the chance of malicious use, CoAP servers SHOULD NOT accept multicast requests that can't be authenticated in some way, either cryptographically or by some multicast boundary that limits the potential sources ๐ If possible, a CoAP server SHOULD limit support for multicast requests to the specific resources where the feature is actually required ๐
On some general-purpose operating systems with a POSIX-style API [IEEE1003.1], it isn't straightforward to find out whether a received packet was addressed to a multicast address ๐คฏ Plenty of implementations know whether they've joined a multicast group, but packets addressed to multicast addresses of the form FF0x::1 are received by every IPv6 node, and that creates a problem ๐ต Implementations SHOULD make use of modern APIs such as IPV6_RECVPKTINFO [RFC3542], if they're available, to figure this out ๐ง โจ
11.4. IP Address Spoofing Attacks ๐ญ
okay so UDP has no handshake, which is lowkey a big problem ๐ That means a rogue endpoint that can read AND write messages on the constrained network (aka NoSec or PreSharedKey setups where the nodes/key ratio is > 1:1) can totally mess with a single endpoint, a whole group of endpoints, or the entire network. For example, it could:
- spoof a Reset message in response to a Confirmable message or Non-confirmable message, thus making an endpoint "deaf"; or
- spoof an ACK in response to a CON message, thus potentially stopping the sender of the CON message from retransmitting, and drowning out the actual response; or
- spoof the entire response with forged payload/options (this has different levels of impact: from single-response disruption, to much bolder attacks on the supporting infrastructure, e.g., poisoning proxy caches, or tricking validation/lookup interfaces in resource directories and, more generally, any component that stores global network state and uses CoAP as the messaging facility to handle setting or updating state is a potential target.); or
- spoof a multicast request for a target node; this may result in network congestion/collapse, a DoS attack on the victim, or forced wake-up from sleeping; or
- spoof observe messages, etc.
Response spoofing by off-path attackers can be detected and mitigated even without transport layer security ๐ก๏ธ by choosing a nontrivial, randomized token in the request (Section 5.3.1). [RFC4086] discusses randomness requirements for security.
In principle, other kinds of spoofing can only be detected by CoAP if Confirmable message semantics is used, because you'd see unexpected Acknowledgement or Reset messages coming from the deceived endpoint. But that means keeping track of the used Message IDs, which isn't always possible, and honestly the detection usually shows up after the damage is already done ๐ญ This kind of attack can be prevented using security modes other than NoSec.
With or without source address spoofing, a client can try to overload a server by sending requests, preferably complex ones, to it ๐ Address spoofing makes tracing back and blocking this attack harder. Since the cost of a CON request is small, this attack can easily be executed. Under this attack, a constrained node with limited total energy may burn through that energy much faster than planned (battery depletion attack) ๐ Also, if the client uses a Confirmable message and the server responds with a Confirmable separate response to a (possibly spoofed) address that doesn't respond, the server will have to allocate buffer and retransmission logic for each response until it hits the exhaustion of MAX_TRANSMIT_SPAN, which makes it more likely to run out of resources for processing legitimate traffic. The latter problem can be eased somewhat by limiting the rate of responses, as discussed in Section 4.7. An attacker could also spoof the address of a legitimate client, which might cause the server, if it uses separate responses, to block legitimate responses to that client because of NSTART=1. All of these attacks can be prevented using a security mode other than NoSec, leaving only attacks on the security protocol ๐ซถ
11.5. Cross-Protocol Attacks ๐
The ability to get a CoAP endpoint to send packets to a fake source address isn't only useful for amplification, it can also be used for cross-protocol attacks against a victim listening to UDP packets at a given address (IP address and port) ๐ Here's how it goes down:
- The attacker sends a message to a CoAP endpoint with the given address as the fake source address.
- The CoAP endpoint replies with a message to the given source address.
- The victim at the given address receives a UDP packet that it interprets according to the rules of a different protocol.
This may be used to get around firewall rules that block direct communication from the attacker to the victim, but happen to allow communication from the CoAP endpoint (which may also play a valid role in the other protocol) to the victim.
Also, CoAP endpoints may be the victim of a cross-protocol attack generated through an endpoint of another UDP-based protocol, such as DNS. In both cases, attacks are possible if the security properties of the endpoints rely on checking IP addresses (and on firewalling off direct attacks sent from outside using fake IP addresses). In general, because of their lack of context, UDP-based protocols are relatively easy targets for cross-protocol attacks ๐ค
Finally, CoAP URIs transported by other means could be used to incite clients to send messages to endpoints of other protocols.
One mitigation against cross-protocol attacks is strict checking of the syntax of received packets, combined with a sufficient difference in syntax. For example, it might help if it were difficult to incite a DNS server to send a DNS response that would pass the checks of a CoAP endpoint. Unfortunately, the first two bytes of a DNS reply are an ID that can be chosen by the attacker, and that ID maps into the interesting part of the CoAP header. The next two bytes are then interpreted as CoAP's Message ID (i.e., any value is acceptable) ๐ The DNS count words may be interpreted as multiple instances of a (nonexistent but elective) CoAP option 0, or possibly as a Token. The echoed query, finally, may be manufactured by the attacker to achieve a desired effect on the CoAP endpoint; the response added by the server (if any) might then just be interpreted as added payload.
1 1 1 1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ID | T, TKL, code
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR| Opcode |AA|TC|RD|RA| Z | RCODE | Message ID
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QDCOUNT | (options 0)
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ANCOUNT | (options 0)
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| NSCOUNT | (options 0)
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ARCOUNT | (options 0)
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Figure 15: DNS Header ([RFC1035], Section 4.1.1) vs. CoAP Message
In general, for any pair of protocols, one of them can very well have been designed in a way that lets an attacker cause the generation of replies that look like messages of the other protocol ๐ต๏ธโโ๏ธ It's often way harder to ensure or prove the absence of viable attacks than to come up with examples that don't yet fully enable an attack but might be developed further by more creative minds. Cross-protocol attacks can therefore only be completely mitigated if endpoints don't authorize actions the attacker wants just based on trusting the source IP address of a packet. Conversely, a NoSec environment that completely relies on a firewall for CoAP security not only needs to firewall off the CoAP endpoints, but also all other endpoints that might be incited to send UDP messages to CoAP endpoints using some other UDP-based protocol.
In addition to the considerations above, the security considerations for DTLS with respect to cross-protocol attacks apply. For example, if the same DTLS security association ("connection") is used to carry data of multiple protocols, DTLS no longer provides protection against cross-protocol attacks between those protocols ๐
11.6. Constrained-Node Considerations ๐งธ
Implementers on constrained nodes often find themselves without a good source of entropy [RFC4086]. If that's the case, the node MUST NOT be used for processes that require good entropy, such as key generation. Instead, keys should be generated externally and added to the device during manufacturing or commissioning ๐
Because of their low processing power, constrained nodes are particularly susceptible to timing attacks. Special care must be taken in the implementation of cryptographic primitives โฑ๏ธ
Large numbers of constrained nodes will be installed in exposed environments and will have little resistance to tampering, including recovery of keying materials. This needs to be considered when defining the scope of credentials assigned to them. In particular, assigning a shared key to a group of nodes may make any single constrained node a target for subverting the entire group ๐ฅบ
12. IANA Considerations ๐ธ
12.1. CoAP Code Registries ๐
This document defines two sub-registries for the values of the Code field in the CoAP header within the "Constrained RESTful Environments (CoRE) Parameters" registry, hereafter referred to as the "CoRE Parameters" registry.
Values in the two sub-registries are eight-bit values notated as three decimal digits c.dd, separated by a period between the first and the second digit. The first digit c is between 0 and 7 and denotes the code class. The second and third digits dd denote a decimal number between 00 and 31 for the detail.
All Code values are assigned by sub-registries according to the following ranges:
0.00 Indicates an Empty message (see Section 4.1).
0.01-0.31 Indicates a request. Values in this range are assigned by
the "CoAP Method Codes" sub-registry (see Section 12.1.1).
1.00-1.31 Reserved
2.00-5.31 Indicates a response. Values in this range are assigned by
the "CoAP Response Codes" sub-registry (see
Section 12.1.2).
6.00-7.31 Reserved
12.1.1. Method Codes ๐ง
The name of the sub-registry is "CoAP Method Codes".
Each entry in the sub-registry must include the Method Code in the range 0.01-0.31, the name of the method, and a reference to the method's documentation.
Initial entries in this sub-registry are as follows:
+------+--------+-----------+
| Code | Name | Reference |
+------+--------+-----------+
| 0.01 | GET | [RFC7252] |
| 0.02 | POST | [RFC7252] |
| 0.03 | PUT | [RFC7252] |
| 0.04 | DELETE | [RFC7252] |
+------+--------+-----------+
Table 5: CoAP Method Codes
All other Method Codes are Unassigned.
The IANA policy for future additions to this sub-registry is "IETF Review or IESG Approval" as described in [RFC5226].
The documentation of a Method Code should specify the semantics of a request with that code, including the following properties:
- The Response Codes the method returns in the success case.
- Whether the method is idempotent, safe, or both.
12.1.2. Response Codes โจ
okay so this is the sub-registry for response codes, and it's called "CoAP Response Codes" ๐ every entry needs three things: the Response Code (which has to be somewhere in the 2.00-5.31 range), a description, and a reference to where that code is documented.
Here are the starter entries, bestie ๐
+------+------------------------------+-----------+
| Code | Description | Reference |
+------+------------------------------+-----------+
| 2.01 | Created | [RFC7252] |
| 2.02 | Deleted | [RFC7252] |
| 2.03 | Valid | [RFC7252] |
| 2.04 | Changed | [RFC7252] |
| 2.05 | Content | [RFC7252] |
| 4.00 | Bad Request | [RFC7252] |
| 4.01 | Unauthorized | [RFC7252] |
| 4.02 | Bad Option | [RFC7252] |
| 4.03 | Forbidden | [RFC7252] |
| 4.04 | Not Found | [RFC7252] |
| 4.05 | Method Not Allowed | [RFC7252] |
| 4.06 | Not Acceptable | [RFC7252] |
| 4.12 | Precondition Failed | [RFC7252] |
| 4.13 | Request Entity Too Large | [RFC7252] |
| 4.15 | Unsupported Content-Format | [RFC7252] |
| 5.00 | Internal Server Error | [RFC7252] |
| 5.01 | Not Implemented | [RFC7252] |
| 5.02 | Bad Gateway | [RFC7252] |
| 5.03 | Service Unavailable | [RFC7252] |
| 5.04 | Gateway Timeout | [RFC7252] |
| 5.05 | Proxying Not Supported | [RFC7252] |
+------+------------------------------+-----------+
Table 6: CoAP Response Codes
The Response Codes 3.00-3.31 are Reserved for future use ๐ฆ Every other Response Code is Unassigned.
For future additions to this sub-registry, the IANA policy is "IETF Review or IESG Approval", as described in [RFC5226] ๐ธ
Now, the documentation for a Response Code should spell out what a response with that code actually means, including these properties:
- The methods the Response Code applies to.
- Whether payload is required, optional, or not allowed.
- The semantics of the payload. For example, the payload of a 2.05 (Content) response is a representation of the target resource, and the payload in an error response is a human-readable diagnostic payload ๐ซถ
- The format of the payload. For example, the format in a 2.05 (Content) response is indicated by the Content-Format Option, and the format of the payload in an error response is always Net-Unicode text โจ
- Whether the response is cacheable according to the freshness model.
- Whether the response is validatable according to the validation model.
- Whether the response causes a cache to mark responses stored for the request URI as not fresh.
12.2. CoAP Option Numbers Registry ๐ง
okay this one is so good ๐ญ This document sets up a sub-registry for the Option Numbers used in CoAP options, and it lives inside the "CoRE Parameters" registry. The sub-registry is called "CoAP Option Numbers".
Every entry needs the Option Number, the name of the option, and a reference to the option's documentation.
The starter entries look like this ๐
+--------+------------------+-----------+
| Number | Name | Reference |
+--------+------------------+-----------+
| 0 | (Reserved) | [RFC7252] |
| 1 | If-Match | [RFC7252] |
| 3 | Uri-Host | [RFC7252] |
| 4 | ETag | [RFC7252] |
| 5 | If-None-Match | [RFC7252] |
| 7 | Uri-Port | [RFC7252] |
| 8 | Location-Path | [RFC7252] |
| 11 | Uri-Path | [RFC7252] |
| 12 | Content-Format | [RFC7252] |
| 14 | Max-Age | [RFC7252] |
| 15 | Uri-Query | [RFC7252] |
| 17 | Accept | [RFC7252] |
| 20 | Location-Query | [RFC7252] |
| 35 | Proxy-Uri | [RFC7252] |
| 39 | Proxy-Scheme | [RFC7252] |
| 60 | Size1 | [RFC7252] |
| 128 | (Reserved) | [RFC7252] |
| 132 | (Reserved) | [RFC7252] |
| 136 | (Reserved) | [RFC7252] |
| 140 | (Reserved) | [RFC7252] |
+--------+------------------+-----------+
Table 7: CoAP Option Numbers
The IANA policy here is split into three tiers ๐ The range 0..255 is reserved for options defined by the IETF (IETF Review or IESG Approval). The range 256..2047 is reserved for commonly used options with public specifications (Specification Required). The range 2048..64999 is for all other options, including private or vendor-specific ones, which go through a Designated Expert review so the option semantics get defined correctly.
Option numbers 65000 through 65535 inclusive are reserved for experiments. They are not meant for vendor-specific use of any kind, and they MUST NOT be used in operational deployments. > Hard rule, no exceptions, bestie ๐
Here's the summary table ๐
+-------------+---------------------------------------+
| Range | Registration Procedures |
+-------------+---------------------------------------+
| 0-255 | IETF Review or IESG Approval |
| 256-2047 | Specification Required |
| 2048-64999 | Expert Review |
| 65000-65535 | Experimental use (no operational use) |
+-------------+---------------------------------------+
Table 8: CoAP Option Numbers: Registration Procedures
The documentation for an Option Number should explain the semantics of an option with that number, including these properties:
- The meaning of the option in a request.
- The meaning of the option in a response.
- Whether the option is critical or elective, as determined by the Option Number.
- Whether the option is Safe-to-Forward, and, if yes, whether it is part of the Cache-Key, as determined by the Option Number (see Section 5.4.2).
- The format and length of the option's value.
- Whether the option must occur at most once or whether it can occur multiple times.
- The default value, if any. For a critical option with a default value, there should be a discussion on how the default value enables processing by implementations that do not support the critical option (Section 5.4.4) ๐ฅ
12.3. CoAP Content-Formats Registry ๐
okay so Internet media types are identified by a string, like "application/xml" [RFC2046] ๐ฆ To keep the overhead small when using these media types to indicate the format of payloads, this document sets up a sub-registry for a subset of Internet media types. Each one gets a numeric identifier, combined with a content-coding. The sub-registry is named "CoAP Content-Formats", and it lives inside the "CoRE Parameters" registry.
Each entry needs to include the media type registered with IANA, the numeric identifier in the range 0-65535 to be used for that media type in CoAP, the content-coding associated with this identifier, and a reference to a document describing what a payload with that media type means semantically.
CoAP doesn't have its own way to convey content-encoding information with a request or response, so the content-encoding is specified for each identifier instead (if there is any). If multiple content-encodings are going to be used with a media type, a separate Content-Format identifier needs to be registered for each one ๐ง Similarly, other parameters related to an Internet media type, such as level, can be defined for a CoAP Content-Format entry.
Here are the starter entries ๐
+--------------------------+----------+----+------------------------+
| Media type | Encoding | ID | Reference |
+--------------------------+----------+----+------------------------+
| text/plain; | - | 0 | [RFC2046] [RFC3676] |
| charset=utf-8 | | | [RFC5147] |
| application/link-format | - | 40 | [RFC6690] |
| application/xml | - | 41 | [RFC3023] |
| application/octet-stream | - | 42 | [RFC2045] [RFC2046] |
| application/exi | - | 47 | [REC-exi-20140211] |
| application/json | - | 50 | [RFC7159] |
+--------------------------+----------+----+------------------------+
Table 9: CoAP Content-Formats
The identifiers between 65000 and 65535 inclusive are reserved for experiments. They are not meant for vendor-specific use of any kind, and they MUST NOT be used in operational deployments. The identifiers between 256 and 9999 are reserved for future use in IETF specifications (IETF Review or IESG Approval). All other identifiers are Unassigned.
Because the namespace of single-byte identifiers is so small ๐ฅบ, the IANA policy for future additions in the range 0-255 inclusive is "Expert Review", as described in [RFC5226]. The IANA policy for additions in the range 10000-64999 inclusive is "First Come First Served", as described in [RFC5226]. Here's the summary ๐ธ
+-------------+---------------------------------------+
| Range | Registration Procedures |
+-------------+---------------------------------------+
| 0-255 | Expert Review |
| 256-9999 | IETF Review or IESG Approval |
| 10000-64999 | First Come First Served |
| 65000-65535 | Experimental use (no operational use) |
+-------------+---------------------------------------+
Table 10: CoAP Content-Formats: Registration Procedures
In machine-to-machine applications, generic Internet media types like text/plain, application/xml or application/octet-stream aren't expected to be useful for real applications in the long term ๐ It is recommended that M2M applications making use of CoAP request new Internet media types from IANA that indicate semantic information about how to create or parse a payload. For example, a Smart Energy application payload carried as XML might request a more specific type like application/se+xml or application/se-exi ๐
12.4. URI Scheme Registration ๐ฆ
Okay bestie, this part is the official paperwork for the coap URI scheme ๐โจ The request is for IANA to register it, and it follows [RFC4395]. Let's go through every field ๐
URI scheme name. coap
Status. Permanent.
URI scheme syntax. Defined in Section 6.1 of [RFC7252].
URI scheme semantics. The coap scheme is how you name resources that can be reached over the Constrained Application Protocol (CoAP) ๐ธ You find the resource by contacting the governing CoAP server, then you operate on it by sending CoAP requests to that server. Honestly it's giving the same energy as the "http" URI scheme [RFC2616]. See Section 6 of [RFC7252] for the details of how it works.
Encoding considerations. The scheme follows the encoding rules for URIs in [RFC3986]. That means internationalized and reserved characters are written with UTF-8-based percent-encoding ๐ซถ
Applications/protocols that use this URI scheme name. CoAP endpoints use this scheme to access CoAP resources โจ
Interoperability considerations. None.
Security considerations. See Section 11.1 of [RFC7252]. Go read that one, it's important ๐
Contact. IETF Chair <chair@ietf.org>
Author/Change controller. IESG <iesg@ietf.org>
References. [RFC7252]
12.5. Secure URI Scheme Registration ๐
Same vibe, but now it's the secure sibling. This is the registration request for the URI scheme coaps, and it also complies with [RFC4395] ๐
URI scheme name. coaps
Status. Permanent.
URI scheme syntax. Defined in Section 6.2 of [RFC7252].
URI scheme semantics. The coaps scheme names resources that can be reached over CoAP using Datagram Transport Layer Security (DTLS) for transport security ๐ก๏ธ You locate them by contacting the governing CoAP server and operating on them by sending CoAP requests to that server. It's basically the "https" URI scheme [RFC2616] in CoAP form. See Section 6 of [RFC7252] for the details of operation.
Encoding considerations. Same deal as coap: the encoding follows the URI rules in [RFC3986], so internationalized and reserved characters are expressed using UTF-8-based percent-encoding ๐ฆ
Applications/protocols that use this URI scheme name. CoAP endpoints use this scheme to access CoAP resources using DTLS ๐ฅ
Interoperability considerations. None.
Security considerations. See Section 11.1 of [RFC7252].
Contact. IETF Chair <chair@ietf.org>
Author/Change controller. IESG <iesg@ietf.org>
References. [RFC7252]
12.6. Service Name and Port Number Registration ๐ช
Okay this one is about how you find CoAP in the first place ๐ง One of CoAP's jobs is resource discovery, where a CoAP client asks a CoAP server what resources it offers (see Section 7). For that to work from just an IP address, the CoAP discovery port has to be standardized. Iconic behaviour from the spec, no notes ๐
IANA has assigned the port number 5683 and the service name coap, in accordance with [RFC6335].
Besides unicast, CoAP can also be used with both multicast and anycast ๐
Service Name. coap
Transport Protocol. udp
Assignee. IESG <iesg@ietf.org>
Contact. IETF Chair <chair@ietf.org>
Description. Constrained Application Protocol (CoAP)
Reference. [RFC7252]
Port Number. 5683
12.7. Secure Service Name and Port Number Registration ๐
Now the secure version of that discovery story ๐ CoAP resource discovery can also happen through the DTLS-secured CoAP coaps scheme. So the port for secure discovery needs to be standardized too.
IANA has assigned the port number 5684 and the service name coaps, in accordance with [RFC6335].
Besides unicast, DTLS-secured CoAP can be used with anycast โจ
Service Name. coaps
Transport Protocol. udp
Assignee. IESG <iesg@ietf.org>
Contact. IETF Chair <chair@ietf.org>
Description. DTLS-secured CoAP
Reference. [RFC7252]
Port Number. 5684
12.8. Multicast Address Registration ๐ก
Section 8, "Multicast CoAP", is where multicast gets defined ๐ฆ IANA assigned these multicast addresses for CoAP nodes to use:
- IPv4 -- "All CoAP Nodes" address
224.0.1.187, from the "IPv4 Multicast Address Space Registry". As the address is used for discovery that may span beyond a single network, it has come from the Internetwork Control Block (224.0.1.x, RFC 5771). - IPv6 -- "All CoAP Nodes" address
FF0X::FD, from the "IPv6 Multicast Address Space Registry", in the "Variable Scope Multicast Addresses" space (RFC 3307). Note that there is a distinct multicast address for each scope that interested CoAP nodes should listen to; CoAP needs the Link-Local and Site-Local scopes only.
Ngl the IPv6 one is a little more involved, because the scope gets swapped in for the X in FF0X::FD ๐
13. Acknowledgements ๐ซถ
Brian Frank was a contributor to, and coauthor of, early versions of this specification ๐ธ
Special thanks to Peter Bigot, Esko Dijk, and Cullen Jennings for substantial contributions to the ideas and text in the document, along with countless detailed reviews and discussions ๐
Thanks to Floris Van den Abeele, Anthony Baire, Ed Beroset, Berta Carballido, Angelo P. Castellani, Gilbert Clark, Robert Cragie, Pierre David, Esko Dijk, Lisa Dusseault, Mehmet Ersue, Thomas Fossati, Tobias Gondrom, Bert Greevenbosch, Tom Herbst, Jeroen Hoebeke, Richard Kelsey, Sye Loong Keoh, Ari Keranen, Matthias Kovatsch, Avi Lior, Stephan Lohse, Salvatore Loreto, Kerry Lynn, Andrew McGregor, Alexey Melnikov, Guido Moritz, Petri Mutka, Colin O'Flynn, Charles Palmer, Adriano Pezzuto, Thomas Poetsch, Robert Quattlebaum, Akbar Rahman, Eric Rescorla, Dan Romascanu, David Ryan, Peter Saint-Andre, Szymon Sasin, Michael Scharf, Dale Seed, Robby Simpson, Peter van der Stok, Michael Stuber, Linyi Tian, Gilman Tolle, Matthieu Vial, Maciej Wasilak, Fan Xianyou, and Alper Yegin for helpful comments and discussions that have shaped the document ๐ Special thanks also to the responsible IETF area director at the time of completion, Barry Leiba, and the IESG reviewers, Adrian Farrel, Martin Stiemerling, Pete Resnick, Richard Barnes, Sean Turner, Spencer Dawkins, Stephen Farrell, and Ted Lemon, who contributed in-depth reviews ๐
Some of the text has been borrowed from the working documents of the IETF HTTPBIS working group ๐
14. References โจ
14.1. Normative References ๐
- [RFC0768] Postel, J., "User Datagram Protocol", STD 6, RFC 768, August 1980.
- [RFC2045] Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies", RFC 2045, November 1996.
- [RFC2046] Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types", RFC 2046, November 1996.
- [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
- [RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.
- [RFC3023] Murata, M., St. Laurent, S., and D. Kohn, "XML Media Types", RFC 3023, January 2001.
- [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, November 2003.
- [RFC3676] Gellens, R., "The Text/Plain Format and DelSp Parameters", RFC 3676, February 2004.
- [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, January 2005.
- [RFC4279] Eronen, P. and H. Tschofenig, "Pre-Shared Key Ciphersuites for Transport Layer Security (TLS)", RFC 4279, December 2005.
- [RFC4395] Hansen, T., Hardie, T., and L. Masinter, "Guidelines and Registration Procedures for New URI Schemes", BCP 35, RFC 4395, February 2006.
- [RFC5147] Wilde, E. and M. Duerst, "URI Fragment Identifiers for the text/plain Media Type", RFC 5147, April 2008.
- [RFC5198] Klensin, J. and M. Padlipsky, "Unicode Format for Network Interchange", RFC 5198, March 2008.
- [RFC5226] Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 5226, May 2008.
- [RFC5234] Crocker, D. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", STD 68, RFC 5234, January 2008.
- [RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.2", RFC 5246, August 2008.
- [RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S., Housley, R., and W. Polk, "Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile", RFC 5280, May 2008.
- [RFC5480] Turner, S., Brown, D., Yiu, K., Housley, R., and T. Polk, "Elliptic Curve Cryptography Subject Public Key Information", RFC 5480, March 2009.
- [RFC5785] Nottingham, M. and E. Hammer-Lahav, "Defining Well-Known Uniform Resource Identifiers (URIs)", RFC 5785, April 2010.
- [RFC5952] Kawamura, S. and M. Kawashima, "A Recommendation for IPv6 Address Text Representation", RFC 5952, August 2010.
- [RFC5988] Nottingham, M., "Web Linking", RFC 5988, October 2010.
- [RFC6066] Eastlake, D., "Transport Layer Security (TLS) Extensions: Extension Definitions", RFC 6066, January 2011.
- [RFC6347] Rescorla, E. and N. Modadugu, "Datagram Transport Layer Security Version 1.2", RFC 6347, January 2012.
- [RFC6690] Shelby, Z., "Constrained RESTful Environments (CoRE) Link Format", RFC 6690, August 2012.
- [RFC6920] Farrell, S., Kutscher, D., Dannewitz, C., Ohlman, B., Keranen, A., and P. Hallam-Baker, "Naming Things with Hashes", RFC 6920, April 2013.
- [RFC7250] Wouters, P., Tschofenig, H., Gilmore, J., Weiler, S., and T. Kivinen, "Using Raw Public Keys in Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)", RFC 7250, June 2014.
- [RFC7251] McGrew, D., Bailey, D., Campagna, M., and R. Dugal, "AES-CCM Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS)", RFC 7251, June 2014.
14.2. Informative References ๐โจ
okay bestie, this is the big reading list ๐ง every entry is a source the spec points to for background, and I've kept each one word for word so nothing gets lost ๐
[BLOCK]Bormann, C. and Z. Shelby, "Blockwise transfers in CoAP", Work in Progress, October 2013.[CoAP-MISC]Bormann, C. and K. Hartke, "Miscellaneous additions to CoAP", Work in Progress, December 2013.[EUI64]IEEE Standards Association, "Guidelines for 64-bit Global Identifier (EUI-64 (TM))", Registration Authority Tutorials, April 2010, <http://standards.ieee.org/regauth/oui/tutorials/EUI64.html>.[GROUPCOMM]Rahman, A. and E. Dijk, "Group Communication for CoAP", Work in Progress, December 2013.[HHGTTG]Adams, D., "The Hitchhiker's Guide to the Galaxy", Pan Books ISBN 3320258648, 1979. ๐[IEEE1003.1]IEEE and The Open Group, "Portable Operating System Interface (POSIX)", The Open Group Base Specifications Issue 7, IEEE 1003.1, 2013 Edition, <http://pubs.opengroup.org/onlinepubs/9699919799/>.[IPsec-CoAP]Bormann, C., "Using CoAP with IPsec", Work in Progress, December 2012.[MAPPING]Castellani, A., Loreto, S., Rahman, A., Fossati, T., and E. Dijk, "Guidelines for HTTP-CoAP Mapping Implementations", Work in Progress, February 2014.[OBSERVE]Hartke, K., "Observing Resources in CoAP", Work in Progress, April 2014. ๐[REC-exi-20140211]Schneider, J., Kamiya, T., Peintner, D., and R. Kyusakov, "Efficient XML Interchange (EXI) Format 1.0 (Second Edition)", W3C Recommendation REC-exi-20140211, February 2014, <http://www.w3.org/TR/2014/REC-exi-20140211/>.[REST]Fielding, R., "Architectural Styles and the Design of Network-based Software Architectures", Ph.D. Dissertation, University of California, Irvine, 2000, <http://www.ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf>. ๐[RFC0020]Cerf, V., "ASCII format for network interchange", RFC 20, October 1969.[RFC0791]Postel, J., "Internet Protocol", STD 5, RFC 791, September 1981.[RFC0792]Postel, J., "Internet Control Message Protocol", STD 5, RFC 792, September 1981.[RFC0793]Postel, J., "Transmission Control Protocol", STD 7, RFC 793, September 1981.[RFC1035]Mockapetris, P., "Domain names - implementation and specification", STD 13, RFC 1035, November 1987.[RFC3264]Rosenberg, J. and H. Schulzrinne, "An Offer/Answer Model with Session Description Protocol (SDP)", RFC 3264, June 2002.[RFC3280]Housley, R., Polk, W., Ford, W., and D. Solo, "Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile", RFC 3280, April 2002.[RFC3542]Stevens, W., Thomas, M., Nordmark, E., and T. Jinmei, "Advanced Sockets Application Program Interface (API) for IPv6", RFC 3542, May 2003.[RFC3828]Larzon, L-A., Degermark, M., Pink, S., Jonsson, L-E., and G. Fairhurst, "The Lightweight User Datagram Protocol (UDP-Lite)", RFC 3828, July 2004.[RFC4086]Eastlake, D., Schiller, J., and S. Crocker, "Randomness Requirements for Security", BCP 106, RFC 4086, June 2005.[RFC4443]Conta, A., Deering, S., and M. Gupta, "Internet Control Message Protocol (ICMPv6) for the Internet Protocol Version 6 (IPv6) Specification", RFC 4443, March 2006.[RFC4492]Blake-Wilson, S., Bolyard, N., Gupta, V., Hawk, C., and B. Moeller, "Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS)", RFC 4492, May 2006.[RFC4821]Mathis, M. and J. Heffner, "Packetization Layer Path MTU Discovery", RFC 4821, March 2007.[RFC4944]Montenegro, G., Kushalnagar, N., Hui, J., and D. Culler, "Transmission of IPv6 Packets over IEEE 802.15.4 Networks", RFC 4944, September 2007.[RFC5405]Eggert, L. and G. Fairhurst, "Unicast UDP Usage Guidelines for Application Designers", BCP 145, RFC 5405, November 2008.[RFC5489]Badra, M. and I. Hajjeh, "ECDHE_PSK Cipher Suites for Transport Layer Security (TLS)", RFC 5489, March 2009.[RFC6090]McGrew, D., Igoe, K., and M. Salter, "Fundamental Elliptic Curve Cryptography Algorithms", RFC 6090, February 2011.[RFC6120]Saint-Andre, P., "Extensible Messaging and Presence Protocol (XMPP): Core", RFC 6120, March 2011.[RFC6282]Hui, J. and P. Thubert, "Compression Format for IPv6 Datagrams over IEEE 802.15.4-Based Networks", RFC 6282, September 2011.[RFC6335]Cotton, M., Eggert, L., Touch, J., Westerlund, M., and S. Cheshire, "Internet Assigned Numbers Authority (IANA) Procedures for the Management of the Service Name and Transport Protocol Port Number Registry", BCP 165, RFC 6335, August 2011.[RFC6655]McGrew, D. and D. Bailey, "AES-CCM Cipher Suites for Transport Layer Security (TLS)", RFC 6655, July 2012.[RFC6936]Fairhurst, G. and M. Westerlund, "Applicability Statement for the Use of IPv6 UDP Datagrams with Zero Checksums", RFC 6936, April 2013.[RFC6960]Santesson, S., Myers, M., Ankney, R., Malpani, A., Galperin, S., and C. Adams, "X.509 Internet Public Key Infrastructure Online Certificate Status Protocol - OCSP", RFC 6960, June 2013.[RFC6961]Pettersen, Y., "The Transport Layer Security (TLS) Multiple Certificate Status Request Extension", RFC 6961, June 2013.[RFC7159]Bray, T., "The JavaScript Object Notation (JSON) Data Interchange Format", RFC 7159, March 2014.[RFC7228]Bormann, C., Ersue, M., and A. Keranen, "Terminology for Constrained-Node Networks", RFC 7228, May 2014.[RTO-CONSIDER]Allman, M., "Retransmission Timeout Considerations", Work in Progress, May 2012.[W3CXMLSEC]Wenning, R., "Report of the XML Security PAG", W3C XML Security PAG, October 2012, <http://www.w3.org/2011/xmlsec-pag/pagreport.html>. ๐
Appendix A. Examples โจ
okay so this section is literally a bunch of short GET request flows ๐ฆ they show the basic vibe, what happens when stuff gets retransmitted, and multicast. the diagrams are the main event, so read them like little group chat screenshots ๐
Figure 16 is the basic one ๐ the client sends a Confirmable GET for coap://server/temperature with Message ID 0x7d34. the request has one Uri-Path Option (Delta 0 + 11 = 11, Length 11, Value "temperature") and the Token is left empty. the whole request is 16 bytes โจ the server answers with a 2.05 (Content) inside the Acknowledgement for that Confirmable request, echoing both the Message ID 0x7d34 and the empty Token. the Payload is "22.3 C" and the response is 11 bytes. it's a piggybacked response, bestie, iconic ๐ธ
Client Server
| |
| |
+----->| Header: GET (T=CON, Code=0.01, MID=0x7d34)
| GET | Uri-Path: "temperature"
| |
| |
|<-----+ Header: 2.05 Content (T=ACK, Code=2.05, MID=0x7d34)
| 2.05 | Payload: "22.3 C"
| |
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 1 | 0 | 0 | GET=1 | MID=0x7d34 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 11 | 11 | "temperature" (11 B) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 1 | 2 | 0 | 2.05=69 | MID=0x7d34 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|1 1 1 1 1 1 1 1| "22.3 C" (6 B) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 16: Confirmable Request; Piggybacked Response
Figure 17 is the same vibe but with a non-empty Token (Value 0x20) in both the request and the response ๐ง that bumps the sizes up to 17 bytes for the request and 12 bytes for the response.
Client Server
| |
| |
+----->| Header: GET (T=CON, Code=0.01, MID=0x7d35)
| GET | Token: 0x20
| | Uri-Path: "temperature"
| |
| |
|<-----+ Header: 2.05 Content (T=ACK, Code=2.05, MID=0x7d35)
| 2.05 | Token: 0x20
| | Payload: "22.3 C"
| |
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 1 | 0 | 1 | GET=1 | MID=0x7d35 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x20 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 11 | 11 | "temperature" (11 B) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 1 | 2 | 1 | 2.05=69 | MID=0x7d35 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x20 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|1 1 1 1 1 1 1 1| "22.3 C" (6 B) ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 17: Confirmable Request; Piggybacked Response
Figure 18 is where the Confirmable GET gets lost ๐ after ACK_TIMEOUT seconds the client retransmits, and then it gets a piggybacked response just like in the last example. same Message ID, same Token, big comeback energy ๐ฅ
Client Server
| |
| |
+----X | Header: GET (T=CON, Code=0.01, MID=0x7d36)
| GET | Token: 0x31
| | Uri-Path: "temperature"
TIMEOUT |
| |
+----->| Header: GET (T=CON, Code=0.01, MID=0x7d36)
| GET | Token: 0x31
| | Uri-Path: "temperature"
| |
| |
|<-----+ Header: 2.05 Content (T=ACK, Code=2.05, MID=0x7d36)
| 2.05 | Token: 0x31
| | Payload: "22.3 C"
| |
Figure 18: Confirmable Request (Retransmitted); Piggybacked Response
Figure 19 is a plot twist ๐ซฃ this time the first Acknowledgement from the server gets lost. after ACK_TIMEOUT seconds the client retransmits the request, and the server sends the piggybacked response again.
Client Server
| |
| |
+----->| Header: GET (T=CON, Code=0.01, MID=0x7d37)
| GET | Token: 0x42
| | Uri-Path: "temperature"
| |
| |
| X----+ Header: 2.05 Content (T=ACK, Code=2.05, MID=0x7d37)
| 2.05 | Token: 0x42
| | Payload: "22.3 C"
TIMEOUT |
| |
+----->| Header: GET (T=CON, Code=0.01, MID=0x7d37)
| GET | Token: 0x42
| | Uri-Path: "temperature"
| |
| |
|<-----+ Header: 2.05 Content (T=ACK, Code=2.05, MID=0x7d37)
| 2.05 | Token: 0x42
| | Payload: "22.3 C"
| |
Figure 19: Confirmable Request; Piggybacked Response (Retransmitted)
Figure 20 is the separate response era ๐ the server ACKs the Confirmable request first, then sends the 2.05 (Content) in its own Confirmable message. the ACK and the Confirmable response don't have to show up in the order they were sent, so no drama if they swap places. the client then acknowledges the Confirmable response, and we're done โจ
Client Server
| |
| |
+----->| Header: GET (T=CON, Code=0.01, MID=0x7d38)
| GET | Token: 0x53
| | Uri-Path: "temperature"
| |
| |
|<- - -+ Header: (T=ACK, Code=0.00, MID=0x7d38)
| |
| |
|<-----+ Header: 2.05 Content (T=CON, Code=2.05, MID=0xad7b)
| 2.05 | Token: 0x53
| | Payload: "22.3 C"
| |
| |
+- - ->| Header: (T=ACK, Code=0.00, MID=0xad7b)
| |
Figure 20: Confirmable Request; Separate Response
Figure 21 is a little tragedy ๐ญ the client loses its state (like it crashes and reboots) right after sending the Confirmable request, so the separate response shows up later and the client has no clue what it is. so the client rejects that Confirmable response with a Reset message. the unexpected ACK just gets silently ignored, no biggie ๐
Client Server
| |
| |
+----->| Header: GET (T=CON, Code=0.01, MID=0x7d39)
| GET | Token: 0x64
| | Uri-Path: "temperature"
CRASH |
| |
|<- - -+ Header: (T=ACK, Code=0.00, MID=0x7d39)
| |
| |
|<-----+ Header: 2.05 Content (T=CON, Code=2.05, MID=0xad7c)
| 2.05 | Token: 0x64
| | Payload: "22.3 C"
| |
| |
+- - ->| Header: (T=RST, Code=0.00, MID=0xad7c)
| |
Figure 21: Confirmable Request; Separate Response (Unexpected)
Figure 22 is the Non-confirmable main character ๐ both the request and the response are Non-confirmable, which means either one can get lost and nobody will ever tell you lmao.
Client Server
| |
| |
+----->| Header: GET (T=NON, Code=0.01, MID=0x7d40)
| GET | Token: 0x75
| | Uri-Path: "temperature"
| |
| |
|<-----+ Header: 2.05 Content (T=NON, Code=2.05, MID=0xad7d)
| 2.05 | Token: 0x75
| | Payload: "22.3 C"
| |
Figure 22: Non-confirmable Request; Non-confirmable Response
Figure 23 is multicast, and it's giving group project ๐ the client sends a Non-confirmable GET to a multicast address, all nodes in link-local scope (ff02::1). there are 3 servers on the link: A, B and C. A and B both have a matching resource, so they send back Non-confirmable 2.05 (Content) responses. B's response gets lost. C doesn't have a matching resource, so it sends a Non-confirmable 4.04 (Not Found) response instead ๐ซถ
Client ff02::1 A B C
| | | | |
| | | | |
+------>| | | | Header: GET (T=NON, Code=0.01, MID=0x7d41)
| GET | | | | Token: 0x86
| | | | Uri-Path: "temperature"
| | | |
| | | |
|<------------+ | | Header: 2.05 (T=NON, Code=2.05, MID=0x60b1)
| 2.05 | | | Token: 0x86
| | | | Payload: "22.3 C"
| | | |
| | | |
| X------------+ | Header: 2.05 (T=NON, Code=2.05, MID=0x01a0)
| 2.05 | | | Token: 0x86
| | | | Payload: "20.9 C"
| | | |
| | | |
|<------------------+ Header: 4.04 (T=NON, Code=4.04, MID=0x952a)
| 4.04 | | | Token: 0x86
| | | |
Figure 23: Non-confirmable Request (Multicast); Non-confirmable Response
Appendix B. URI Examples ๐ท
okay this one is all about building URIs from Uri options ๐ each example takes a set of options and shows the URI you end up with after constructing it. section 6.5 talks about the destination IP address and port too, but not every path through the algorithm actually puts the destination IP address and port into the URI, so keep that in mind ๐ง
- Input:
Destination IP Address = [2001:db8::2:1]
Destination UDP Port = 5683
Output:
coap://[2001:db8::2:1]/
- Input:
Destination IP Address = [2001:db8::2:1]
Destination UDP Port = 5683
Uri-Host = "example.net"
Output:
coap://example.net/
- Input:
Destination IP Address = [2001:db8::2:1]
Destination UDP Port = 5683
Uri-Host = "example.net"
Uri-Path = ".well-known"
Uri-Path = "core"
Output:
coap://example.net/.well-known/core
- Input:
Destination IP Address = [2001:db8::2:1]
Destination UDP Port = 5683
Uri-Host = "xn--18j4d.example"
Uri-Path = the string composed of the Unicode characters U+3053
U+3093 U+306b U+3061 U+306f, usually represented in UTF-8 as
E38193E38293E381ABE381A1E381AF hexadecimal
Output:
coap://xn--18j4d.example/
%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF
(The line break has been inserted for readability; it is not part of the URI.)
- Input:
Destination IP Address = 198.51.100.1
Destination UDP Port = 61616
Uri-Path = ""
Uri-Path = "/"
Uri-Path = ""
Uri-Path = ""
Uri-Query = "//"
Uri-Query = "?&"
Output:
coap://198.51.100.1:61616//%2F//?%2F%2F&?%26
Authors' Addresses ๐ซถ
Here are the people who wrote this, bestie. The addresses and contact details are kept exactly as they appear in the original.
Zach Shelby
ARM
150 Rose Orchard
San Jose, CA 95134
USA
Phone: +1-408-203-9434
EMail: zach.shelby@arm.com
Klaus Hartke
Universitaet Bremen TZI
Postfach 330440
Bremen D-28359
Germany
Phone: +49-421-218-63905
EMail: hartke@tzi.org
Carsten Bormann
Universitaet Bremen TZI
Postfach 330440
Bremen D-28359
Germany
Phone: +49-421-218-63921
EMail: cabo@tzi.org
๐ฆ where this page comes from
- ietf: rfc7252 2014-06
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms