SatCat5
satcat5::coap::Connection Class Reference

Detailed Description

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>

Inheritance diagram for satcat5::coap::Connection:
[legend]
Collaboration diagram for satcat5::coap::Connection:
[legend]

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::Writeableopen_request ()
 If able, send a request to the current remote server. More...
 
satcat5::io::Writeableopen_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::Writeablecontinue_separate ()
 If able, send the second half of a separated response. More...
 
satcat5::io::Writeableopen_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 Types

enum class  State {
  IDLE , ERROR , CONNECT_IDLE , CONNECT_BUSY ,
  WAIT_RESPONSE_U , WAIT_RESPONSE_M , REQUEST_CON , REQUEST_NON ,
  REQUEST_SEP , RESPONSE_CACHE , RESPONSE_DEFER , RESPONSE_SEP1 ,
  RESPONSE_SEP2
}
 

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::Endpointm_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::Connectionm_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
 

Constructor & Destructor Documentation

◆ Connection()

Connection::Connection ( satcat5::coap::Endpoint endpoint,
satcat5::net::Address addr 
)
protected

Constructor is only accessible to child classes.

The child class MUST allocate a net::Address object. The Endpoint pointer MAY be null.

See also
init. The Address pointer MUST NOT be null.

Definition at line 60 of file coap_connection.cc.

Member Function Documentation

◆ continue_separate()

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.

◆ error_response()

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.

◆ frame_rcvd()

void Connection::frame_rcvd ( satcat5::io::LimitedRead src)
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:

  • Call m_iface->open_reply() to obtain a Writable object. (This also writes out any applicable frame headers.)
  • Write frame contents, then call write_finalize().

The child class MUST override this method.

Implements satcat5::net::Protocol.

Definition at line 216 of file coap_connection.cc.

◆ get_proxy_token()

u32 satcat5::coap::Connection::get_proxy_token ( ) const
inline

Query the most recent proxy token.

See also
proxy_set.

Definition at line 115 of file coap_connection.h.

◆ get_write_space()

unsigned ArrayWrite::get_write_space ( ) const
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.

◆ init()

void Connection::init ( satcat5::coap::Endpoint endpoint)
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.

◆ is_match_coap()

bool Connection::is_match_coap ( const satcat5::coap::ReadHeader msg) const
Parameters
msgMatch message ID & token?

Definition at line 95 of file coap_connection.cc.

◆ open_request()

Writeable * Connection::open_request ( )

If able, send a request to the current remote server.

Returns
Writeable for preparing the request, or null on error.

Definition at line 148 of file coap_connection.cc.

◆ open_response()

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.

◆ open_response_auto()

satcat5::io::Writeable* satcat5::coap::Connection::open_response_auto ( )
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.

◆ open_separate()

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.

◆ ping()

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.

◆ set_proxy_token()

void satcat5::coap::Connection::set_proxy_token ( u32  token)
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,

See also
token().

Definition at line 122 of file coap_connection.h.

◆ test_inject()

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.

◆ write_abort()

void ArrayWrite::write_abort ( )
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.

◆ write_bytes()

void Writeable::write_bytes ( unsigned  nbytes,
const void *  src 
)
virtualinherited

◆ write_finalize()

bool Connection::write_finalize ( )
overrideprotectedvirtual

Mark end of frame and release temporary working data.

Child objects of io::Writeable SHOULD override this method to mark frame bounds.

Returns
True if successful, false on error.

Reimplemented from satcat5::io::Writeable.

Definition at line 459 of file coap_connection.cc.

◆ write_next()

void ArrayWrite::write_next ( u8  data)
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.

◆ write_overflow()

void ArrayWrite::write_overflow ( )
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.

◆ write_str()

void Writeable::write_str ( const char *  str)
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.

◆ write_u8()

void Writeable::write_u8 ( u8  data)
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.
  • Data-type width in bits.
    • Available widths for ints: 8/16/24/32/48/64.
    • Available widths for floats: 32/64.
  • 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.


The documentation for this class was generated from the following files: