|
SatCat5
|
CoAP request/response handling for a single client-server connection.
This class implements automatic retry & cache logic for the request and response layer of the Constrained Applications Protocol (CoAP): https://www.rfc-editor.org/rfc/rfc7252
Because CoAP uses UDP, messages may be lost in transit. Outgoing requests must retry after a timeout, repeating until a response is received. Therefore, some care is required to ensure that requests are idempotent, i.e., side effects are executed exactly once. CoAP achieves this with a response cache, where repeated requests replay the cached response instead of re-executing the request.
The coap::Connection class implements either of these functions: retry of outgoing requests (Section 4.2) and/or cached-replay of outgoing responses (Section 4.4). Either mode requires a buffer equal to the max outgoing message size (i.e., SATCAT5_COAP_BUFFSIZE).
Due to packet loss and reordering, there are many possible edge-cases that must be handled gracefully. A particularly useful reference is Angelo Castellani's "Learning CoAP separate responses by example": https://www.ietf.org/proceedings/83/slides/slides-83-lwig-3.pdf
Because CoAP allows only one in-progress request/response at a time (Section 4.7), one buffer is sufficient for any given client/server pair. As such, simple clients may only need a single coap::Connection object, but more complex client/server endpoints may need one for each concurrent connection, incoming or outgoing.
Because there may be multiple coap::Connection objects servicing the same UDP port, both coap::Connection and coap::Endpoint must cooperate in order to service all possible incoming messages.
Definition at line 60 of file coap_connection.h.
#include <coap_connection.h>
Public Member Functions | |
| bool | is_idle () const |
| < Idle and ready for use? | |
| bool | is_match_addr () const |
| < Match reply endpoint? | |
| bool | is_match_coap (const satcat5::coap::ReadHeader *msg) const |
| bool | is_match_reuse () const |
| Idle or continue same connection. | |
| bool | is_await () const |
| < Awaiting initial response? | |
| bool | is_connecting () const |
| < Connection in progress? | |
| bool | is_request () const |
| < Any request state? | |
| bool | is_response () const |
| < Any response state? | |
| bool | is_separate () const |
| < Awaiting separate response? | |
| u16 | msg_id () const |
| < Most recent message ID | |
| u64 | token () const |
| < Most recent message token | |
| u8 | tkl () const |
| < Most recent token length | |
| void | close () |
| Close any open connections and reset state. | |
| bool | ping (u16 msg_id) |
| If able, send a ping request to the remote client. More... | |
| u32 | get_proxy_token () const |
| Query the most recent proxy token. More... | |
| void | set_proxy_token (u32 token) |
| Set identifier for matching incoming proxy responses. More... | |
| bool | ready () const |
| Ready to send a request? | |
| satcat5::io::Writeable * | open_request () |
| If able, send a request to the current remote server. More... | |
| satcat5::io::Writeable * | open_response () |
| If able, accept an incoming request from a remote client. More... | |
| bool | open_separate (const satcat5::coap::ReadHeader *msg) |
| If able, send the first half of a separated response. More... | |
| satcat5::io::Writeable * | continue_separate () |
| If able, send the second half of a separated response. More... | |
| satcat5::io::Writeable * | open_response_auto () |
| Automatically call open_response() or continue_separate(). More... | |
| bool | error_response (satcat5::coap::Code code, const char *why=0) |
| If able, return an error in response to an incoming request from a remote client. More... | |
| u8 | response_type () const |
| Determine the expected response type for an incoming request. | |
| bool | test_inject (unsigned len, const void *data) |
| Test only: Send a message using the active connection. More... | |
Protected Member Functions | |
| Connection (satcat5::coap::Endpoint *endpoint, satcat5::net::Address *addr) | |
| Constructor is only accessible to child classes. More... | |
| void | init (satcat5::coap::Endpoint *endpoint) |
| Deferred initialization of the upstream interface. More... | |
| bool | deliver (satcat5::coap::Reader *msg) |
| void | frame_rcvd (satcat5::io::LimitedRead &src) override |
| Dispatch calls frame_rcvd(...) for each incoming frame with with a matching net::Type value. More... | |
| void | timer_event () override |
| Child class MUST override this method. | |
| bool | write_finalize () override |
| Mark end of frame and release temporary working data. More... | |
| bool | connected (bool allow_reuse) |
| void | error_event () |
| int | match_history (const satcat5::coap::ReadHeader *msg) const |
| void | push_history (const satcat5::coap::ReadHeader *msg) |
| void | reset_hard () |
| void | reset_soft () |
| bool | send_buffer () |
| bool | send_empty (u8 typ, u16 id) |
| bool | send_first () |
| void | timer_rand (u32 base_msec) |
| void | timer_once (unsigned msec) |
| Configure a one-time notification after X milliseconds. | |
| void | timer_every (unsigned msec) |
| Configure a repeating notification every X milliseconds. | |
| void | timer_stop () |
| Stop all future notifications. | |
| unsigned | timer_interval () const |
| Accessor for recurring timer interval, if one is set. | |
| unsigned | timer_remaining () const |
| Accessor for time to next event, if one is set. | |
| unsigned | get_write_space () const override |
| How many bytes can be written without blocking? More... | |
| void | write_abort () override |
| If possible, abort the current partially-written packet. More... | |
| void | write_overflow () override |
| Optional error handling for write overflow. More... | |
| const u8 * | buffer () const |
| Read-only access to the working buffer. | |
| unsigned | written_len () const |
| Report total length after write_finalize() is called. | |
| void | write_u8 (u8 data) |
| One of many functions for writing integer/floating point values, see details. More... | |
| virtual void | write_bytes (unsigned nbytes, const void *src) |
| Write 0 or more bytes from a buffer. More... | |
| void | write_str (const char *str) |
| Write the contents of a null-terminated string. More... | |
| template<class T > | |
| void | write_obj (const T &obj) |
Templated wrapper for any object with the following method: void write_to(satcat5::io::Writeable* wr) const; | |
Static Protected Member Functions | |
| static unsigned | count_timer () |
| Count all objects of this type, including idle timers. | |
Protected Attributes | |
| satcat5::coap::Endpoint * | m_coap |
| satcat5::net::Address *const | m_addr |
| State | m_state |
| u32 | m_proxy_token |
| u8 | m_allow_reuse |
| u8 | m_tx_count |
| u8 | m_meta_idx |
| u8 | m_meta_count |
| u8 | m_flags [SATCAT5_COAP_HISTORY] |
| u16 | m_msgid [SATCAT5_COAP_HISTORY] |
| u64 | m_token [SATCAT5_COAP_HISTORY] |
| satcat5::net::Type | m_filter |
| Incoming packet filter. | |
| friend | LimitedWrite |
| friend | WriteableBroadcast |
| friend | WriteableRedirect |
Private Member Functions | |
| void | query (unsigned elapsed_msec) |
| void | write_next (u8 data) override |
| Write the next byte to the underlying buffer or device. More... | |
Private Attributes | |
| satcat5::coap::Connection * | m_next |
| unsigned | m_trem |
| unsigned | m_tnext |
| u8 | m_buff [SIZE] |
| u8 *const | m_dst |
| const unsigned | m_len |
| bool | m_ovr |
| unsigned | m_wridx |
| unsigned | m_wrlen |
|
protected |
Constructor is only accessible to child classes.
The child class MUST allocate a net::Address object. The Endpoint pointer MAY be null.
Definition at line 60 of file coap_connection.cc.
| Writeable * Connection::continue_separate | ( | ) |
If able, send the second half of a separated response.
Return Writeable for preparing the pseudo-request, or null on error.
Definition at line 176 of file coap_connection.cc.
| bool Connection::error_response | ( | satcat5::coap::Code | code, |
| const char * | why = 0 |
||
| ) |
If able, return an error in response to an incoming request from a remote client.
Sends an ACK with a Client or Server Error code (4.xx or 5.xx) with an optional string payload diagnostic message
Definition at line 184 of file coap_connection.cc.
|
overrideprotectedvirtual |
Dispatch calls frame_rcvd(...) for each incoming frame with with a matching net::Type value.
The child class SHOULD read the frame contents from the provided "src" object, which is only valid until the function returns.
To send a reply:
The child class MUST override this method.
Implements satcat5::net::Protocol.
Definition at line 216 of file coap_connection.cc.
|
inline |
Query the most recent proxy token.
Definition at line 115 of file coap_connection.h.
|
overridevirtualinherited |
How many bytes can be written without blocking?
Child objects of io::Writeable MUST override this method.
Implements satcat5::io::Writeable.
Definition at line 189 of file io_writeable.cc.
|
protected |
Deferred initialization of the upstream interface.
Used infrequently. If the constructor's Endpoint argument is null, use this method to later assign the missing interface.
Definition at line 88 of file coap_connection.cc.
| bool Connection::is_match_coap | ( | const satcat5::coap::ReadHeader * | msg | ) | const |
| msg | Match message ID & token? |
Definition at line 95 of file coap_connection.cc.
| Writeable * Connection::open_request | ( | ) |
If able, send a request to the current remote server.
Definition at line 148 of file coap_connection.cc.
| Writeable * Connection::open_response | ( | ) |
If able, accept an incoming request from a remote client.
Use this method to send a piggybacked response or the first message in a separated response. (See "open_separate".) Return Writeable for preparing the response, or null on error.
Definition at line 156 of file coap_connection.cc.
|
inline |
Automatically call open_response() or continue_separate().
Return Writeable for preparing the response, or null on error.
Definition at line 148 of file coap_connection.h.
| bool Connection::open_separate | ( | const satcat5::coap::ReadHeader * | msg | ) |
If able, send the first half of a separated response.
Returns true if successful, and automatically sends the initial ACK.
Definition at line 164 of file coap_connection.cc.
| bool Connection::ping | ( | u16 | msg_id | ) |
If able, send a ping request to the remote client.
(Use child's connect() method to set the target address.)
Definition at line 136 of file coap_connection.cc.
|
inline |
Set identifier for matching incoming proxy responses.
This token is set by the coap::ProxyServer, sent with the forwarded request, then used to route incoming responses. It is unrelated to the incoming message,
Definition at line 122 of file coap_connection.h.
| bool Connection::test_inject | ( | unsigned | len, |
| const void * | data | ||
| ) |
Test only: Send a message using the active connection.
Users should not call this method in production logic.
Definition at line 208 of file coap_connection.cc.
|
overridevirtualinherited |
If possible, abort the current partially-written packet.
Child objects of io::Writeable SHOULD override this method if it is practical to prevent in-progress data from being relayed downstream.
Reimplemented from satcat5::io::Writeable.
Definition at line 193 of file io_writeable.cc.
|
virtualinherited |
Write 0 or more bytes from a buffer.
Child objects of io::Writeable MAY override write_bytes as needed for performance.
Reimplemented in satcat5::port::MailmapAligned, satcat5::port::Mailmap, satcat5::io::PacketBuffer, satcat5::io::MultiWriter, satcat5::io::MultiPacket::Overwriter, satcat5::io::NullWrite, satcat5::io::WriteableRedirect, satcat5::io::LimitedWrite, satcat5::io::CounterInline, satcat5::io::WriteableBroadcast, and satcat5::io::FileWriter.
Definition at line 170 of file io_writeable.cc.
|
overrideprotectedvirtual |
Mark end of frame and release temporary working data.
Child objects of io::Writeable SHOULD override this method to mark frame bounds.
Reimplemented from satcat5::io::Writeable.
Definition at line 459 of file coap_connection.cc.
|
overrideprivatevirtualinherited |
Write the next byte to the underlying buffer or device.
Child objects of io::Writeable MUST override this method.
Implements satcat5::io::Writeable.
Definition at line 211 of file io_writeable.cc.
|
overridevirtualinherited |
Optional error handling for write overflow.
Child objects of io::Writeable MAY override this method for error handling.
Reimplemented from satcat5::io::Writeable.
Definition at line 207 of file io_writeable.cc.
|
inherited |
Write the contents of a null-terminated string.
Note: Null-termination is not copied to the output.
Definition at line 180 of file io_writeable.cc.
|
inherited |
One of many functions for writing integer/floating point values, see details.
Several functions are provided for reading and writing scalar types to/from io::Readable and io::Writeable instances. Since there are many of these that are frequently inherited, they are hidden from documentation. These functions follow a shared template:
read_ or write_ prefix.u for unsigned, s for signed, f for floating-point.l suffix if little-endian, no suffix if big-endian.Example: write_s48l is "Write 48 bits (6 bytes) to this
io::Writeable as a signed value in little-endian order".
Definition at line 20 of file io_writeable.cc.