Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
openlcb::DatagramClientImpl Class Reference

Datagram client implementation for CANbus-based datagram protocol. More...

#include <DatagramImpl.hxx>

Inheritance diagram for openlcb::DatagramClientImpl:
openlcb::DatagramClient StateFlowBase LinkedObject< DatagramClientImpl > QMember Executable Notifiable QMember Destructable

Classes

class  ReplyListener
 This object is registered to receive response messages at the interface level. More...
 

Public Member Functions

 DatagramClientImpl (If *iface, MessageHandler *send_flow)
 Constructor.
 
void write_datagram (Buffer< GenMessage > *b, unsigned priority) OVERRIDE
 Triggers sending a datagram.
 
void cancel () OVERRIDE
 Requests cancelling the datagram send operation.
 
- Public Member Functions inherited from openlcb::DatagramClient
uint32_t result ()
 Returns a bitmask of ResultCodes for the transmission operation.
 
- Public Member Functions inherited from QMember
void init ()
 Initiailize a QMember, in place of a public placement construction.
 
- Public Member Functions inherited from StateFlowBase
void run () override
 Callback from the executor.
 
void notify () override
 Wakeup call arrived.
 
Serviceservice ()
 Return a pointer to the service I am bound to.
 
- Public Member Functions inherited from Executable
void test_deletion ()
 
- Public Member Functions inherited from LinkedObject< DatagramClientImpl >
DatagramClientImpl * link_next ()
 

Private Types

enum  {
  MTI_1a = Defs::MTI_TERMINATE_DUE_TO_ERROR , MTI_1b = Defs::MTI_OPTIONAL_INTERACTION_REJECTED , MASK_1 = ~(MTI_1a ^ MTI_1b) , MTI_1 = MTI_1a ,
  MTI_2a = Defs::MTI_DATAGRAM_OK , MTI_2b = Defs::MTI_DATAGRAM_REJECTED , MASK_2 = ~(MTI_2a ^ MTI_2b) , MTI_2 = MTI_2a ,
  MTI_3 = Defs::MTI_INITIALIZATION_COMPLETE , MASK_3 = Defs::MTI_EXACT
}
 

Private Member Functions

void reset_message (Buffer< GenMessage > *b, unsigned priority)
 Equivalent to enqueuing a new datagram to send.
 
Action start_send ()
 Entry point to the flow processing.
 
Action acquire_srcdst_lock ()
 Ensures that there is no other datagram client with the same src:dst pair.
 
Action do_send ()
 Hands off the datagram to the send flow.
 
void register_handlers ()
 
Action timeout_looking_for_dst ()
 
Action timeout_waiting_for_dg_response ()
 
void unregister_response_handler ()
 
Action datagram_finalize ()
 
void handle_response (GenMessage *message)
 Callback when a matching response comes in on the bus.
 
void stop_waiting_for_response ()
 To be called from the handler.
 
void notify () override
 Overrides the default notify implementation to make sure we obey the priority values.
 
void set_priority (unsigned p)
 Sets the stateflow priority.
 
Ififace ()
 

Private Attributes

Buffer< GenMessage > * message_ {nullptr}
 Datagram message we are trying to send now. We own it.
 
BarrierNotifiabledone_ {nullptr}
 This notifiable is saved from the datagram buffer.
 
NodeHandle src_
 Source of the datagram we are currently sending.
 
NodeHandle dst_
 Destination of the datagram we are currently sending.
 
MessageHandlersendFlow_
 Addressed datagram send flow from the interface. Externally owned.
 
ReplyListener listener_
 Instance of the listener object.
 
StateFlowTimer timer_ {this}
 Helper object for sleep.
 
TypedQueue< ExecutablewaitingClients_
 List of other datagram clients that are trying to send to the same target node.
 
unsigned isSleeping_: 1
 1 when we are in the sleep call waiting for the datagram Ack or Reject message.
 
unsigned hasResponse_: 1
 
unsigned sendPending_: 1
 1 when we have the handlers registered.
 
unsigned priority_: 24
 Priority in the executor.
 

Static Private Attributes

static constexpr unsigned MAX_PRIORITY = (1 << 24) - 1
 Constant used to clamp the incoming priority value to something that first in priority_ bit field.
 

Additional Inherited Members

- Public Types inherited from openlcb::DatagramClient
enum  ResultCodes {
  PERMANENT_ERROR = 0x1000 , RESEND_OK = 0x2000 , TRANSPORT_ERROR = 0x4000 , BUFFER_UNAVAILABLE = 0x0020 ,
  OUT_OF_ORDER = 0x0040 , SOURCE_NOT_PERMITTED = 0x0020 , DATAGRAMS_NOT_ACCEPTED = 0x0040 , OPERATION_SUCCESS = 0x10000 ,
  OPERATION_PENDING = 0x20000 , DST_NOT_FOUND = Defs::ERROR_DST_NOT_FOUND , TIMEOUT = Defs::OPENMRN_TIMEOUT , DST_REBOOT = Defs::ERROR_DST_REBOOT ,
  RESPONSE_FLAGS_SHIFT = 24 , RESPONSE_CODE_MASK = (1<<RESPONSE_FLAGS_SHIFT) - 1 , OK_REPLY_PENDING = (1 << 31)
}
 Known result codes from the DatagramClient. More...
 
enum  ResponseFlag { REPLY_PENDING = 0x80 , REPLY_TIMEOUT_SEC = 0x1 , REPLY_TIMEOUT_MASK = 0xf }
 
- Static Public Member Functions inherited from StateFlowBase
template<class T , typename... Args>
static void invoke_subflow_and_ignore_result (FlowInterface< Buffer< T > > *target_flow, Args &&... args)
 Calls a helper flow to perform some actions.
 
- Static Public Member Functions inherited from LinkedObject< DatagramClientImpl >
static DatagramClientImpl * link_head ()
 
static Atomichead_mu ()
 Locks the list for modification (at any entry!).
 
- Protected Types inherited from StateFlowBase
typedef Action(StateFlowBase::* Callback) ()
 State Flow callback prototype.
 
- Protected Member Functions inherited from QMember
 QMember ()
 Constructor.
 
 ~QMember ()
 Destructor.
 
- Protected Member Functions inherited from StateFlowBase
 StateFlowBase (Service *service)
 Constructor.
 
 ~StateFlowBase ()
 Destructor.
 
void reset_flow (Callback c)
 Resets the flow to the specified state.
 
bool is_state (Callback c)
 
bool is_terminated ()
 
void start_flow (Callback c)
 Resets the flow to the specified state and starts it.
 
Action again ()
 Call the current state again via call_immediately.
 
Action exit ()
 Terminate current StateFlow activity.
 
Action delete_this ()
 Terminates the flow and deletes *this.
 
Action set_terminated ()
 Sets the flow to terminated state.
 
Action call_immediately (Callback c)
 Imediately call the next state upon return.
 
Action wait ()
 Wait for an asynchronous call.
 
Action wait_and_call (Callback c)
 Wait for resource to become available before proceeding to next state.
 
template<class T >
Action allocate_and_call (FlowInterface< Buffer< T > > *target_flow, Callback c, Pool *pool=nullptr)
 Allocates a buffer from a pool and proceed to the next state when allocation is successful.
 
Action allocate_and_call (Callback c, QAsync *queue)
 Allocates an entry from an asynchronous queue, and transitions to a state once the allocation is complete.
 
template<class T >
Buffer< T > * full_allocation_result (FlowInterface< Buffer< T > > *target_flow)
 Takes the result of the asynchronous allocation without resetting the object.
 
template<class T >
T * full_allocation_result (TypedQAsync< T > *queue)
 Takes the result of the asynchronous allocation without resetting the object.
 
template<class T >
void cast_allocation_result (T **member)
 Takes the result of the asynchronous allocation without resetting the object.
 
template<class T >
Buffer< T > * get_allocation_result (FlowInterface< Buffer< T > > *target_flow)
 Takes the result of the asynchronous allocation.
 
Action yield_and_call (Callback c)
 Place the current flow to the back of the executor, and transition to a new state after we get the CPU again.
 
Action yield ()
 Place the current flow to the back of the executor, and re-try the current state after we get the CPU again.
 
Action sleep_and_call (::Timer *timer, long long timeout_nsec, Callback c)
 Suspends execution of this control flow for a specified time.
 
template<class T , typename... Args>
Action invoke_subflow_and_wait (FlowInterface< Buffer< T > > *target_flow, Callback c, Args &&... args)
 Calls a helper flow to perform some actions.
 
Action read_repeated (StateFlowSelectHelper *helper, int fd, void *buf, size_t size, Callback c, unsigned priority=Selectable::MAX_PRIO)
 Blocks until size bytes are read and then invokes the next state.
 
Action read_single (StateFlowSelectHelper *helper, int fd, void *buf, size_t size, Callback c, unsigned priority=Selectable::MAX_PRIO)
 Attempts to read at most size_t bytes, and blocks the caller until at least one byte is read.
 
Action read_nonblocking (StateFlowSelectHelper *helper, int fd, void *buf, size_t size, Callback c, unsigned priority=Selectable::MAX_PRIO)
 Attempts to read at most size bytes, and then invokes the next state, even if only zero bytes are available right now.
 
Action read_repeated_with_timeout (StateFlowTimedSelectHelper *helper, long long timeout_nsec, int fd, void *buf, size_t size, Callback c, unsigned priority=Selectable::MAX_PRIO)
 Blocks until size bytes are read, or a timeout expires.
 
Action internal_try_read ()
 Implementation state that gets repeatedly called upon every wakeup and tries to make progress on reading.
 
Action write_repeated (StateFlowSelectHelper *helper, int fd, const void *buf, size_t size, Callback c, unsigned priority=Selectable::MAX_PRIO)
 Writes some data into a file descriptor, repeating the operation as necessary until all bytes are written.
 
Action internal_try_write ()
 Implementation state that gets repeatedly called upon every wakeup and tries to make progress on writing.
 
- Protected Member Functions inherited from LinkedObject< DatagramClientImpl >
DatagramClientImpl * link_this ()
 
 LinkedObject ()
 Constructor. Puts *this on the linked list.
 
 ~LinkedObject ()
 Constructor. Removes *this from the linked list.
 
- Protected Attributes inherited from openlcb::DatagramClient
uint32_t result_
 
- Protected Attributes inherited from QMember
QMembernext
 pointer to the next member in the queue
 
- Protected Attributes inherited from LinkedObject< DatagramClientImpl >
DatagramClientImpl * link_
 Linked list pointer.
 
- Static Protected Attributes inherited from LinkedObject< DatagramClientImpl >
static DatagramClientImpl * head_
 Beginning of the list.
 

Detailed Description

Datagram client implementation for CANbus-based datagram protocol.

This flow is responsible for the outgoing CAN datagram framing, and listens for incoming datagram response messages.

The base class of AddressedCanMessageWriteFlow is responsible for the discovery and address resolution of the destination node.

Definition at line 52 of file DatagramImpl.hxx.

Member Enumeration Documentation

◆ anonymous enum

anonymous enum
private

Definition at line 159 of file DatagramImpl.hxx.

Constructor & Destructor Documentation

◆ DatagramClientImpl()

openlcb::DatagramClientImpl::DatagramClientImpl ( If iface,
MessageHandler send_flow 
)
inline

Constructor.

Parameters
ifaceis the service on which to run this flow
send_flowcan receive an (addressed) Datagram message and send it to the appropriate destination – takes care of fragmenting etc.

Definition at line 61 of file DatagramImpl.hxx.

Member Function Documentation

◆ acquire_srcdst_lock()

Action openlcb::DatagramClientImpl::acquire_srcdst_lock ( )
inlineprivate

Ensures that there is no other datagram client with the same src:dst pair.

This is required by the standard.

Returns
next state

Definition at line 113 of file DatagramImpl.hxx.

◆ cancel()

void openlcb::DatagramClientImpl::cancel ( )
inlinevirtual

Requests cancelling the datagram send operation.

Will notify the done callback when the canceling is completed.

Implements openlcb::DatagramClient.

Definition at line 84 of file DatagramImpl.hxx.

◆ datagram_finalize()

Action openlcb::DatagramClientImpl::datagram_finalize ( )
inlineprivate

Definition at line 223 of file DatagramImpl.hxx.

◆ do_send()

Action openlcb::DatagramClientImpl::do_send ( )
inlineprivate

Hands off the datagram to the send flow.

Returns
next state.

Definition at line 141 of file DatagramImpl.hxx.

◆ handle_response()

void openlcb::DatagramClientImpl::handle_response ( GenMessage message)
inlineprivate

Callback when a matching response comes in on the bus.

Parameters
messageis the incoming generic message (from the response buffer).

Definition at line 259 of file DatagramImpl.hxx.

◆ iface()

If * openlcb::DatagramClientImpl::iface ( )
inlineprivate
Returns
the interface service we are running on.

Definition at line 392 of file DatagramImpl.hxx.

◆ notify()

void openlcb::DatagramClientImpl::notify ( )
inlineoverrideprivatevirtual

Overrides the default notify implementation to make sure we obey the priority values.

Implements Notifiable.

Definition at line 379 of file DatagramImpl.hxx.

◆ register_handlers()

void openlcb::DatagramClientImpl::register_handlers ( )
inlineprivate

Definition at line 173 of file DatagramImpl.hxx.

◆ reset_message()

void openlcb::DatagramClientImpl::reset_message ( Buffer< GenMessage > *  b,
unsigned  priority 
)
inlineprivate

Equivalent to enqueuing a new datagram to send.

Parameters
bdatagram to send.
priorityexecutor priority.

Definition at line 93 of file DatagramImpl.hxx.

◆ set_priority()

void openlcb::DatagramClientImpl::set_priority ( unsigned  p)
inlineprivate

Sets the stateflow priority.

Parameters
pthe stateflow's priority on the executor.

Definition at line 386 of file DatagramImpl.hxx.

◆ start_send()

Action openlcb::DatagramClientImpl::start_send ( )
inlineprivate

Entry point to the flow processing.

Returns
next state

Definition at line 101 of file DatagramImpl.hxx.

◆ stop_waiting_for_response()

void openlcb::DatagramClientImpl::stop_waiting_for_response ( )
inlineprivate

To be called from the handler.

Wakes up main flow and terminates it (with whatever is in the result_ code right now).

@TODO(balazs.racz) Here we might want to decide whether to start a retry.

Definition at line 360 of file DatagramImpl.hxx.

◆ timeout_looking_for_dst()

Action openlcb::DatagramClientImpl::timeout_looking_for_dst ( )
inlineprivate
Todo:
In IfCanImpl.hxx there is a timeout_looking_for_dst action. It should trigger a 'terminate due to error' response message, and when that arrives in the handle_response() function below, this is the code that we need to trigger.

Definition at line 187 of file DatagramImpl.hxx.

◆ timeout_waiting_for_dg_response()

Action openlcb::DatagramClientImpl::timeout_waiting_for_dg_response ( )
inlineprivate

Definition at line 194 of file DatagramImpl.hxx.

◆ unregister_response_handler()

void openlcb::DatagramClientImpl::unregister_response_handler ( )
inlineprivate

Definition at line 206 of file DatagramImpl.hxx.

◆ write_datagram()

void openlcb::DatagramClientImpl::write_datagram ( Buffer< GenMessage > *  b,
unsigned  priority 
)
inlinevirtual

Triggers sending a datagram.

Parameters
bis the datagra buffer.
priorityis the priority of the datagram client in the executor.

Callers should set the done closure of the Buffer. After that closure is notified, the caller must ensure that the datagram client is released back to the freelist.

@TODO(balazs.racz): revisit the type of DatagramPayload and ensure that there will be no extra copy of the data happening.

Implements openlcb::DatagramClient.

Definition at line 70 of file DatagramImpl.hxx.

Member Data Documentation

◆ done_

BarrierNotifiable* openlcb::DatagramClientImpl::done_ {nullptr}
private

This notifiable is saved from the datagram buffer.

Will be notified when the entire interaction is completed, but the buffer itself is transferred to the send flow.

Definition at line 402 of file DatagramImpl.hxx.

◆ dst_

NodeHandle openlcb::DatagramClientImpl::dst_
private

Destination of the datagram we are currently sending.

Definition at line 406 of file DatagramImpl.hxx.

◆ hasResponse_

unsigned openlcb::DatagramClientImpl::hasResponse_
private

Definition at line 420 of file DatagramImpl.hxx.

◆ isSleeping_

unsigned openlcb::DatagramClientImpl::isSleeping_
private

1 when we are in the sleep call waiting for the datagram Ack or Reject message.

Definition at line 419 of file DatagramImpl.hxx.

◆ listener_

ReplyListener openlcb::DatagramClientImpl::listener_
private

Instance of the listener object.

Definition at line 410 of file DatagramImpl.hxx.

◆ MAX_PRIORITY

constexpr unsigned openlcb::DatagramClientImpl::MAX_PRIORITY = (1 << 24) - 1
staticconstexprprivate

Constant used to clamp the incoming priority value to something that first in priority_ bit field.

Definition at line 428 of file DatagramImpl.hxx.

◆ message_

Buffer<GenMessage>* openlcb::DatagramClientImpl::message_ {nullptr}
private

Datagram message we are trying to send now. We own it.

Definition at line 398 of file DatagramImpl.hxx.

◆ priority_

unsigned openlcb::DatagramClientImpl::priority_
private

Priority in the executor.

Definition at line 425 of file DatagramImpl.hxx.

◆ sendFlow_

MessageHandler* openlcb::DatagramClientImpl::sendFlow_
private

Addressed datagram send flow from the interface. Externally owned.

Definition at line 408 of file DatagramImpl.hxx.

◆ sendPending_

unsigned openlcb::DatagramClientImpl::sendPending_
private

1 when we have the handlers registered.

During this time we have exclusive lock on the specific src/dst node pair.

Definition at line 423 of file DatagramImpl.hxx.

◆ src_

NodeHandle openlcb::DatagramClientImpl::src_
private

Source of the datagram we are currently sending.

Definition at line 404 of file DatagramImpl.hxx.

◆ timer_

StateFlowTimer openlcb::DatagramClientImpl::timer_ {this}
private

Helper object for sleep.

Definition at line 412 of file DatagramImpl.hxx.

◆ waitingClients_

TypedQueue<Executable> openlcb::DatagramClientImpl::waitingClients_
private

List of other datagram clients that are trying to send to the same target node.

We need to wake up one of this list when we are done sending.

Definition at line 416 of file DatagramImpl.hxx.


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