CoAP¶
Overview¶
The Constrained Application Protocol (CoAP) is a specialized web transfer protocol for use with constrained nodes and constrained (e.g., low-power, lossy) networks. It provides a convenient API for RESTful Web services that support CoAP’s features. For more information about the protocol itself, see IETF RFC7252 The Constrained Application Protocol.
Zephyr provides a CoAP library which supports client and server roles. The library is configurable as per user needs. The Zephyr CoAP library is implemented using plain buffers. Users of the API create sockets for communication and pass the buffer to the library for parsing and other purposes. The library itself doesn’t create any sockets for users.
On top of CoAP, Zephyr has support for LWM2M “Lightweight Machine 2 Machine” protocol, a simple, low-cost remote management and service enablement mechanism. See Lightweight M2M (LWM2M) for more information.
Supported RFCs:
Supported RFCs:
RFC6690: Constrained RESTful Environments (CoRE) Link Format
RFC7959: Block-Wise Transfers in the Constrained Application Protocol (CoAP)
RFC7641: Observing Resources in the Constrained Application Protocol (CoAP)
Note
Not all parts of these RFCs are supported. Features are supported based on Zephyr requirements.
Sample Usage¶
CoAP Server¶
To create a CoAP server, resources for the server need to be defined.
The .well-known/core
resource should be added before all other
resources that should be included in the responses of the .well-known/core
resource.
static struct coap_resource resources[] = {
{ .get = well_known_core_get,
.path = COAP_WELL_KNOWN_CORE_PATH,
},
{ .get = sample_get,
.post = sample_post,
.del = sample_del,
.put = sample_put,
.path = sample_path
},
{ },
};
An application reads data from the socket and passes the buffer to the CoAP library to parse the message. If the CoAP message is proper, the library uses the buffer along with resources defined above to call the correct callback function to handle the CoAP request from the client. It’s the callback function’s responsibility to either reply or act according to CoAP request.
coap_packet_parse(&request, data, data_len, options, opt_num);
...
coap_handle_request(&request, resources, options, opt_num,
client_addr, client_addr_len);
CoAP Client¶
If the CoAP client knows about resources in the CoAP server, the client can start
prepare CoAP requests and wait for responses. If the client doesn’t know
about resources in the CoAP server, it can request resources through
the .well-known/core
CoAP message.
/* Initialize the CoAP message */
char *path = "test";
struct coap_packet request;
u8_t data[100];
u8_t payload[20];
coap_packet_init(&request, data, sizeof(data),
1, COAP_TYPE_CON, 8, coap_next_token(),
COAP_METHOD_GET, coap_next_id());
/* Append options */
coap_packet_append_option(&request, COAP_OPTION_URI_PATH,
path, strlen(path));
/* Append Payload marker if you are going to add payload */
coap_packet_append_payload_marker(&request);
/* Append payload */
coap_packet_append_payload(&request, (u8_t *)payload,
sizeof(payload) - 1);
/* send over sockets */
Testing¶
There are various ways to test Zephyr CoAP library.
libcoap¶
libcoap implements a lightweight application-protocol for devices that are
resource constrained, such as by computing power, RF range, memory, bandwidth,
or network packet sizes. Sources can be found here libcoap.
libcoap has a script (examples/etsi_coaptest.sh
) to test coap-server functionality
in Zephyr.
See the net-tools project for more details
The CoAP Server sample can be built and executed on QEMU as described in Networking with QEMU.
Use this command on the host to run the libcoap implementation of the ETSI test cases:
sudo ./libcoap/examples/etsi_coaptest.sh -i tap0 2001:db8::1
TTCN3¶
Eclipse has TTCN3 based tests to run against CoAP implementations.
Install eclipse-titan and set symbolic links for titan tools
sudo apt-get install eclipse-titan
cd /usr/share/titan
sudo ln -s /usr/bin bin
sudo ln /usr/bin/titanver bin
sudo ln -s /usr/bin/mctr_cli bin
sudo ln -s /usr/include/titan include
sudo ln -s /usr/lib/titan lib
export TTCN3_DIR=/usr/share/titan
git clone https://github.com/eclipse/titan.misc.git
cd titan.misc
Follow the instruction to setup CoAP test suite from here:
After the build is complete, the CoAP Server sample can be built and executed on QEMU as described in Networking with QEMU.
Change the client (test suite) and server (Zephyr coap-server sample) addresses in coap.cfg file as per your setup.
Execute the test cases with following command.
ttcn3_start coaptests coap.cfg
Sample output of ttcn3 tests looks like this.
Verdict statistics: 0 none (0.00 %), 10 pass (100.00 %), 0 inconc (0.00 %), 0 fail (0.00 %), 0 error (0.00 %).
Test execution summary: 10 test cases were executed. Overall verdict: pass
API Reference¶
-
group
coap
COAP library.
Defines
-
COAP_REQUEST_MASK
¶
-
coap_make_response_code
(class, det)¶
-
COAP_CODE_EMPTY
¶
-
COAP_WELL_KNOWN_CORE_PATH
¶ This resource should be added before all other resources that should be included in the responses of the .well-known/core resource.
Typedefs
-
typedef
coap_method_t
¶ Type of the callback being called when a resource’s method is invoked by the remote entity.
-
typedef
coap_notify_t
¶ Type of the callback being called when a resource’s has observers to be informed when an update happens.
-
typedef
coap_reply_t
¶ Helper function to be called when a response matches the a pending request.
Enums
-
enum
coap_option_num
¶ Set of CoAP packet options we are aware of.
Users may add options other than these to their packets, provided they know how to format them correctly. The only restriction is that all options must be added to a packet in numeric order.
Refer to RFC 7252, section 12.2 for more information.
Values:
-
COAP_OPTION_IF_MATCH
= 1¶
-
COAP_OPTION_URI_HOST
= 3¶
-
COAP_OPTION_ETAG
= 4¶
-
COAP_OPTION_IF_NONE_MATCH
= 5¶
-
COAP_OPTION_OBSERVE
= 6¶
-
COAP_OPTION_URI_PORT
= 7¶
-
COAP_OPTION_LOCATION_PATH
= 8¶
-
COAP_OPTION_URI_PATH
= 11¶
-
COAP_OPTION_CONTENT_FORMAT
= 12¶
-
COAP_OPTION_MAX_AGE
= 14¶
-
COAP_OPTION_URI_QUERY
= 15¶
-
COAP_OPTION_ACCEPT
= 17¶
-
COAP_OPTION_LOCATION_QUERY
= 20¶
-
COAP_OPTION_BLOCK2
= 23¶
-
COAP_OPTION_BLOCK1
= 27¶
-
COAP_OPTION_SIZE2
= 28¶
-
COAP_OPTION_PROXY_URI
= 35¶
-
COAP_OPTION_PROXY_SCHEME
= 39¶
-
COAP_OPTION_SIZE1
= 60¶
-
-
enum
coap_method
¶ Available request methods.
To be used when creating a request or a response.
Values:
-
COAP_METHOD_GET
= 1¶
-
COAP_METHOD_POST
= 2¶
-
COAP_METHOD_PUT
= 3¶
-
COAP_METHOD_DELETE
= 4¶
-
-
enum
coap_msgtype
¶ CoAP packets may be of one of these types.
Values:
-
COAP_TYPE_CON
= 0¶ Confirmable message.
The packet is a request or response the destination end-point must acknowledge.
-
COAP_TYPE_NON_CON
= 1¶ Non-confirmable message.
The packet is a request or response that doesn’t require acknowledgements.
-
COAP_TYPE_ACK
= 2¶ Acknowledge.
Response to a confirmable message.
-
COAP_TYPE_RESET
= 3¶ Reset.
Rejecting a packet for any reason is done by sending a message of this type.
-
-
enum
coap_response_code
¶ Set of response codes available for a response packet.
To be used when creating a response.
Values:
-
COAP_RESPONSE_CODE_OK
= ((2 << 5) | (0))¶
-
COAP_RESPONSE_CODE_CREATED
= ((2 << 5) | (1))¶
-
COAP_RESPONSE_CODE_DELETED
= ((2 << 5) | (2))¶
-
COAP_RESPONSE_CODE_VALID
= ((2 << 5) | (3))¶
-
COAP_RESPONSE_CODE_CHANGED
= ((2 << 5) | (4))¶
-
COAP_RESPONSE_CODE_CONTENT
= ((2 << 5) | (5))¶
-
COAP_RESPONSE_CODE_CONTINUE
= ((2 << 5) | (31))¶
-
COAP_RESPONSE_CODE_BAD_REQUEST
= ((4 << 5) | (0))¶
-
COAP_RESPONSE_CODE_UNAUTHORIZED
= ((4 << 5) | (1))¶
-
COAP_RESPONSE_CODE_BAD_OPTION
= ((4 << 5) | (2))¶
-
COAP_RESPONSE_CODE_FORBIDDEN
= ((4 << 5) | (3))¶
-
COAP_RESPONSE_CODE_NOT_FOUND
= ((4 << 5) | (4))¶
-
COAP_RESPONSE_CODE_NOT_ALLOWED
= ((4 << 5) | (5))¶
-
COAP_RESPONSE_CODE_NOT_ACCEPTABLE
= ((4 << 5) | (6))¶
-
COAP_RESPONSE_CODE_INCOMPLETE
= ((4 << 5) | (8))¶
-
COAP_RESPONSE_CODE_PRECONDITION_FAILED
= ((4 << 5) | (12))¶
-
COAP_RESPONSE_CODE_REQUEST_TOO_LARGE
= ((4 << 5) | (13))¶
-
COAP_RESPONSE_CODE_UNSUPPORTED_CONTENT_FORMAT
= ((4 << 5) | (15))¶
-
COAP_RESPONSE_CODE_INTERNAL_ERROR
= ((5 << 5) | (0))¶
-
COAP_RESPONSE_CODE_NOT_IMPLEMENTED
= ((5 << 5) | (1))¶
-
COAP_RESPONSE_CODE_BAD_GATEWAY
= ((5 << 5) | (2))¶
-
COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE
= ((5 << 5) | (3))¶
-
COAP_RESPONSE_CODE_GATEWAY_TIMEOUT
= ((5 << 5) | (4))¶
-
COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED
= ((5 << 5) | (5))¶
-
-
enum
coap_block_size
¶ Represents the size of each block that will be transferred using block-wise transfers [RFC7959]:
Each entry maps directly to the value that is used in the wire.
https://tools.ietf.org/html/rfc7959
Values:
-
COAP_BLOCK_16
¶
-
COAP_BLOCK_32
¶
-
COAP_BLOCK_64
¶
-
COAP_BLOCK_128
¶
-
COAP_BLOCK_256
¶
-
COAP_BLOCK_512
¶
-
COAP_BLOCK_1024
¶
-
Functions
-
u8_t
coap_header_get_version
(const struct coap_packet *cpkt)¶ Returns the version present in a CoAP packet.
- Return
the CoAP version in packet
- Parameters
cpkt
: CoAP packet representation
-
u8_t
coap_header_get_type
(const struct coap_packet *cpkt)¶ Returns the type of the CoAP packet.
- Return
the type of the packet
- Parameters
cpkt
: CoAP packet representation
-
u8_t
coap_header_get_token
(const struct coap_packet *cpkt, u8_t *token)¶ Returns the token (if any) in the CoAP packet.
- Return
Token length in the CoAP packet.
- Parameters
cpkt
: CoAP packet representationtoken
: Where to store the token
-
u8_t
coap_header_get_code
(const struct coap_packet *cpkt)¶ Returns the code of the CoAP packet.
- Return
the code present in the packet
- Parameters
cpkt
: CoAP packet representation
-
u16_t
coap_header_get_id
(const struct coap_packet *cpkt)¶ Returns the message id associated with the CoAP packet.
- Return
the message id present in the packet
- Parameters
cpkt
: CoAP packet representation
-
const u8_t *
coap_packet_get_payload
(const struct coap_packet *cpkt, u16_t *len)¶ Returns the data pointer and length of the CoAP packet.
- Return
data pointer and length if payload exists NULL pointer and length set to 0 in case there is no payload
- Parameters
cpkt
: CoAP packet representationlen
: Total length of CoAP payload
-
int
coap_packet_parse
(struct coap_packet *cpkt, u8_t *data, u16_t len, struct coap_option *options, u8_t opt_num)¶ Parses the CoAP packet in data, validating it and initializing cpkt. data must remain valid while cpkt is used.
- Return
0 in case of success or negative in case of error.
- Parameters
cpkt
: Packet to be initialized from received data.data
: Data containing a CoAP packet, its data pointer is positioned on the start of the CoAP packet.len
: Length of the dataoptions
: Parse options and cache its details.opt_num
: Number of options
-
int
coap_packet_init
(struct coap_packet *cpkt, u8_t *data, u16_t max_len, u8_t ver, u8_t type, u8_t token_len, u8_t *token, u8_t code, u16_t id)¶ Creates a new CoAP Packet from input data.
- Return
0 in case of success or negative in case of error.
- Parameters
cpkt
: New packet to be initialized using the storage from data.data
: Data that will contain a CoAP packet informationmax_len
: Maximum allowable length of dataver
: CoAP header versiontype
: CoAP header typetoken_len
: CoAP header token lengthtoken
: CoAP header tokencode
: CoAP header codeid
: CoAP header message id
-
u8_t *
coap_next_token
(void)¶ Returns a randomly generated array of 8 bytes, that can be used as a message’s token.
- Return
a 8-byte pseudo-random token.
-
u16_t
coap_next_id
(void)¶ Helper to generate message ids.
- Return
a new message id
-
int
coap_find_options
(const struct coap_packet *cpkt, u16_t code, struct coap_option *options, u16_t veclen)¶ Return the values associated with the option of value code.
- Return
The number of options found in packet matching code, negative on error.
- Parameters
cpkt
: CoAP packet representationcode
: Option number to look foroptions
: Array of coap_option where to store the value of the options foundveclen
: Number of elements in the options array
-
int
coap_packet_append_option
(struct coap_packet *cpkt, u16_t code, const u8_t *value, u16_t len)¶ Appends an option to the packet.
Note: options must be added in numeric order of their codes. Otherwise error will be returned. TODO: Add support for placing options according to its delta value.
- Return
0 in case of success or negative in case of error.
- Parameters
cpkt
: Packet to be updatedcode
: Option code to add to the packet, see coap_option_numvalue
: Pointer to the value of the option, will be copied to the packetlen
: Size of the data to be added
-
unsigned int
coap_option_value_to_int
(const struct coap_option *option)¶ Converts an option to its integer representation.
Assumes that the number is encoded in the network byte order in the option.
- Return
The integer representation of the option
- Parameters
option
: Pointer to the option value, retrieved by coap_find_options()
-
int
coap_append_option_int
(struct coap_packet *cpkt, u16_t code, unsigned int val)¶ Appends an integer value option to the packet.
The option must be added in numeric order of their codes, and the least amount of bytes will be used to encode the value.
- Return
0 in case of success or negative in case of error.
- Parameters
cpkt
: Packet to be updatedcode
: Option code to add to the packet, see coap_option_numval
: Integer value to be added
-
int
coap_packet_append_payload_marker
(struct coap_packet *cpkt)¶ Append payload marker to CoAP packet.
- Return
0 in case of success or negative in case of error.
- Parameters
cpkt
: Packet to append the payload marker (0xFF)
-
int
coap_packet_append_payload
(struct coap_packet *cpkt, u8_t *payload, u16_t payload_len)¶ Append payload to CoAP packet.
- Return
0 in case of success or negative in case of error.
- Parameters
cpkt
: Packet to append the payloadpayload
: CoAP packet payloadpayload_len
: CoAP packet payload len
-
int
coap_handle_request
(struct coap_packet *cpkt, struct coap_resource *resources, struct coap_option *options, u8_t opt_num, struct sockaddr *addr, socklen_t addr_len)¶ When a request is received, call the appropriate methods of the matching resources.
- Return
0 in case of success or negative in case of error.
- Parameters
cpkt
: Packet receivedresources
: Array of known resourcesoptions
: Parsed options from coap_packet_parse()opt_num
: Number of optionsaddr
: Peer addressaddr_len
: Peer address length
-
static u16_t
coap_block_size_to_bytes
(enum coap_block_size block_size)¶ Helper for converting the enumeration to the size expressed in bytes.
- Return
The size in bytes that the block_size represents
- Parameters
block_size
: The block size to be converted
-
int
coap_block_transfer_init
(struct coap_block_context *ctx, enum coap_block_size block_size, size_t total_size)¶ Initializes the context of a block-wise transfer.
- Return
0 in case of success or negative in case of error.
- Parameters
ctx
: The context to be initializedblock_size
: The size of the blocktotal_size
: The total size of the transfer, if known
-
int
coap_append_block1_option
(struct coap_packet *cpkt, struct coap_block_context *ctx)¶ Append BLOCK1 option to the packet.
- Return
0 in case of success or negative in case of error.
- Parameters
cpkt
: Packet to be updatedctx
: Block context from which to retrieve the information for the Block1 option
-
int
coap_append_block2_option
(struct coap_packet *cpkt, struct coap_block_context *ctx)¶ Append BLOCK2 option to the packet.
- Return
0 in case of success or negative in case of error.
- Parameters
cpkt
: Packet to be updatedctx
: Block context from which to retrieve the information for the Block2 option
-
int
coap_append_size1_option
(struct coap_packet *cpkt, struct coap_block_context *ctx)¶ Append SIZE1 option to the packet.
- Return
0 in case of success or negative in case of error.
- Parameters
cpkt
: Packet to be updatedctx
: Block context from which to retrieve the information for the Size1 option
-
int
coap_append_size2_option
(struct coap_packet *cpkt, struct coap_block_context *ctx)¶ Append SIZE2 option to the packet.
- Return
0 in case of success or negative in case of error.
- Parameters
cpkt
: Packet to be updatedctx
: Block context from which to retrieve the information for the Size2 option
-
int
coap_update_from_block
(const struct coap_packet *cpkt, struct coap_block_context *ctx)¶ Retrieves BLOCK{1,2} and SIZE{1,2} from cpkt and updates ctx accordingly.
- Return
0 in case of success or negative in case of error.
- Parameters
cpkt
: Packet in which to look for block-wise transfers optionsctx
: Block context to be updated
-
size_t
coap_next_block
(const struct coap_packet *cpkt, struct coap_block_context *ctx)¶ Updates ctx so after this is called the current entry indicates the correct offset in the body of data being transferred.
- Return
The offset in the block-wise transfer, 0 if the transfer has finished.
- Parameters
cpkt
: Packet in which to look for block-wise transfers optionsctx
: Block context to be updated
-
void
coap_observer_init
(struct coap_observer *observer, const struct coap_packet *request, const struct sockaddr *addr)¶ Indicates that the remote device referenced by addr, with request, wants to observe a resource.
- Parameters
observer
: Observer to be initializedrequest
: Request on which the observer will be basedaddr
: Address of the remote device
-
bool
coap_register_observer
(struct coap_resource *resource, struct coap_observer *observer)¶ After the observer is initialized, associate the observer with an resource.
- Return
true if this is the first observer added to this resource.
- Parameters
resource
: Resource to add an observerobserver
: Observer to be added
-
void
coap_remove_observer
(struct coap_resource *resource, struct coap_observer *observer)¶ Remove this observer from the list of registered observers of that resource.
- Parameters
resource
: Resource in which to remove the observerobserver
: Observer to be removed
-
struct coap_observer *
coap_find_observer_by_addr
(struct coap_observer *observers, size_t len, const struct sockaddr *addr)¶ Returns the observer that matches address addr.
- Return
A pointer to a observer if a match is found, NULL otherwise.
- Parameters
observers
: Pointer to the array of observerslen
: Size of the array of observersaddr
: Address of the endpoint observing a resource
-
struct coap_observer *
coap_observer_next_unused
(struct coap_observer *observers, size_t len)¶ Returns the next available observer representation.
- Return
A pointer to a observer if there’s an available observer, NULL otherwise.
- Parameters
observers
: Pointer to the array of observerslen
: Size of the array of observers
-
void
coap_reply_init
(struct coap_reply *reply, const struct coap_packet *request)¶ Indicates that a reply is expected for request.
- Parameters
reply
: Reply structure to be initializedrequest
: Request from which reply will be based
-
int
coap_pending_init
(struct coap_pending *pending, const struct coap_packet *request, const struct sockaddr *addr)¶ Initialize a pending request with a request.
The request’s fields are copied into the pending struct, so request doesn’t have to live for as long as the pending struct lives, but “data” that needs to live for at least that long.
- Return
0 in case of success or negative in case of error.
- Parameters
pending
: Structure representing the waiting for a confirmation message, initialized with data from requestrequest
: Message waiting for confirmationaddr
: Address to send the retransmission
-
struct coap_pending *
coap_pending_next_unused
(struct coap_pending *pendings, size_t len)¶ Returns the next available pending struct, that can be used to track the retransmission status of a request.
- Return
pointer to a free coap_pending structure, NULL in case none could be found.
- Parameters
pendings
: Pointer to the array of coap_pending structureslen
: Size of the array of coap_pending structures
-
struct coap_reply *
coap_reply_next_unused
(struct coap_reply *replies, size_t len)¶ Returns the next available reply struct, so it can be used to track replies and notifications received.
- Return
pointer to a free coap_reply structure, NULL in case none could be found.
- Parameters
replies
: Pointer to the array of coap_reply structureslen
: Size of the array of coap_reply structures
-
struct coap_pending *
coap_pending_received
(const struct coap_packet *response, struct coap_pending *pendings, size_t len)¶ After a response is received, returns if there is any matching pending request exits. User has to clear all pending retransmissions related to that response by calling coap_pending_clear().
- Return
pointer to the associated coap_pending structure, NULL in case none could be found.
- Parameters
response
: The received responsependings
: Pointer to the array of coap_reply structureslen
: Size of the array of coap_reply structures
-
struct coap_reply *
coap_response_received
(const struct coap_packet *response, const struct sockaddr *from, struct coap_reply *replies, size_t len)¶ After a response is received, call coap_reply_t handler registered in coap_reply structure.
- Return
Pointer to the reply matching the packet received, NULL if none could be found.
- Parameters
response
: A response receivedfrom
: Address from which the response was receivedreplies
: Pointer to the array of coap_reply structureslen
: Size of the array of coap_reply structures
-
struct coap_pending *
coap_pending_next_to_expire
(struct coap_pending *pendings, size_t len)¶ Returns the next pending about to expire, pending->timeout informs how many ms to next expiration.
- Return
The next coap_pending to expire, NULL if none is about to expire.
- Parameters
pendings
: Pointer to the array of coap_pending structureslen
: Size of the array of coap_pending structures
-
bool
coap_pending_cycle
(struct coap_pending *pending)¶ After a request is sent, user may want to cycle the pending retransmission so the timeout is updated.
- Return
false if this is the last retransmission.
- Parameters
pending
: Pending representation to have its timeout updated
-
void
coap_pending_clear
(struct coap_pending *pending)¶ Cancels the pending retransmission, so it again becomes available.
- Parameters
pending
: Pending representation to be canceled
-
void
coap_reply_clear
(struct coap_reply *reply)¶ Cancels awaiting for this reply, so it becomes available again. User responsibility to free the memory associated with data.
- Parameters
reply
: The reply to be canceled
-
int
coap_resource_notify
(struct coap_resource *resource)¶ Indicates that this resource was updated and that the notify callback should be called for every registered observer.
- Return
0 in case of success or negative in case of error.
- Parameters
resource
: Resource that was updated
-
bool
coap_request_is_observe
(const struct coap_packet *request)¶ Returns if this request is enabling observing a resource.
- Return
True if the request is enabling observing a resource, False otherwise
- Parameters
request
: Request to be checked
-
int
coap_well_known_core_get
(struct coap_resource *resource, struct coap_packet *request, struct coap_packet *response, u8_t *data, u16_t len)¶
-
struct
coap_resource
¶ - #include <coap.h>
Description of CoAP resource.
CoAP servers often want to register resources, so that clients can act on them, by fetching their state or requesting updates to them.
-
struct
coap_observer
¶ - #include <coap.h>
Represents a remote device that is observing a local resource.
-
struct
coap_packet
¶ - #include <coap.h>
Representation of a CoAP Packet.
-
struct
coap_pending
¶ - #include <coap.h>
Represents a request awaiting for an acknowledgment (ACK).
-
struct
coap_reply
¶ - #include <coap.h>
Represents the handler for the reply of a request, it is also used when observing resources.
-
struct
coap_block_context
¶ - #include <coap.h>
Represents the current state of a block-wise transaction.
-
struct
coap_core_metadata
¶ - #include <coap_link_format.h>
In case you want to add attributes to the resources included in the ‘well-known/core’ “virtual” resource, the ‘user_data’ field should point to a valid coap_core_metadata structure.
-