102 this, 0, ~((1 << 30) - 1));
108 this, 0, ~((1 << 30) - 1));
114 uint32_t
id = GET_CAN_FRAME_ID_EFF(*
message()->data());
145 return allocate_and_call(
160 return allocate_and_call(
170 auto *b = get_allocation_result(if_can()->frame_write_flow());
172 struct can_frame *f = b->data();
187 get_allocation_result(if_can()->frame_write_flow()));
200 struct can_frame *f = b->data();
230 this, CAN_FILTER, CAN_MASK);
236 this, CAN_FILTER, CAN_MASK);
241 struct can_frame *f =
message()->data();
242 uint32_t
id = GET_CAN_FRAME_ID_EFF(*f);
244 return release_and_exit();
249 return release_and_exit();
256 switch (control_field)
262 return release_and_exit();
266 if (old_alias == alias)
269 return release_and_exit();
276 return release_and_exit();
284 if (old_alias && old_alias != alias)
290 return release_and_exit();
296 return release_and_exit();
318 this, CAN_FILTER, CAN_MASK);
324 this, CAN_FILTER, CAN_MASK);
329 struct can_frame *f =
message()->data();
330 uint32_t
id = GET_CAN_FRAME_ID_EFF(*f);
332 return release_and_exit();}
334 return release_and_exit();}
342 return release_and_exit();
345 if (!node_id || !local_alias)
347 return release_and_exit();
351 SET_CAN_FRAME_ID_EFF(*b->data()->mutable_frame(),
id);
368 this, CAN_FILTER, CAN_MASK);
374 this, CAN_FILTER, CAN_MASK);
405 struct can_frame *f = msg->
data();
429 while (
nextIndex_ < if_can()->local_aliases()->size())
432 if (if_can()->local_aliases()->retrieve(
nextIndex_, &n,
nullptr) &&
433 ((n >> (5 * 8)) != 0))
436 if_can()->frame_write_flow(),
STATE(fill_response));
450 Action fill_response()
455 if (if_can()->local_aliases()->retrieve(
nextIndex_, &node, &alias))
457 struct can_frame *f = b->data()->mutable_frame();
458 SET_CAN_FRAME_ID_EFF(
507 this, CAN_FILTER, CAN_MASK);
513 this, CAN_FILTER, CAN_MASK);
519 struct can_frame *f =
message()->data();
520 id_ = GET_CAN_FRAME_ID_EFF(*f);
523 buf_.assign((
const char *)(&f->data[0]), f->can_dlc);
531 return allocate_and_call(if_can()->dispatcher(),
STATE(send_to_if));
536 auto *b = get_allocation_result(if_can()->dispatcher());
586 this, CAN_FILTER, CAN_MASK);
592 this, CAN_FILTER, CAN_MASK);
598 struct can_frame *f =
message()->data();
599 id_ = GET_CAN_FRAME_ID_EFF(*f);
603 LOG(
WARNING,
"Incoming can frame addressed message without payload."
604 " can ID %08x data length %d",
605 (
unsigned)id_, f->can_dlc);
607 return release_and_exit();
610 dstHandle_.
alias = (((unsigned)f->data[0] & 0xf) << 8) | f->data[1];
614 LOG(
VERBOSE,
"Dropping addressed message not for local destination."
615 "id %08x Alias %03x",
616 (
unsigned)id_, dstHandle_.
alias);
618 return release_and_exit();
621 if (f->data[0] & (CanDefs::NOT_FIRST_FRAME | CanDefs::NOT_LAST_FRAME))
623 uint64_t buffer_key = dstHandle_.
alias;
631 if ((f->data[0] & CanDefs::NOT_FIRST_FRAME) == 0)
634 if (!mapped_buffer->empty())
636 LOG(
WARNING,
"Received multi-frame message when a previous "
637 "multi-frame message has not been flushed "
638 "yet. frame ID=%08x, fddd=%02x%02x",
639 (
unsigned)id_, f->data[0], f->data[1]);
641 mapped_buffer->clear();
645 mapped_buffer->append(
646 (
const char *)(f->data + 2), f->can_dlc - 2);
648 if (f->data[0] & CanDefs::NOT_LAST_FRAME)
651 return release_and_exit();
656 mapped_buffer->swap(buf_);
665 buf_.assign((
const char *)(f->data + 2), f->can_dlc - 2);
675 return allocate_and_call(if_can()->dispatcher(),
STATE(send_to_if));
680 auto *b = get_allocation_result(if_can()->dispatcher());
703 NodeHandle dstHandle_;
709 int local_alias_cache_size,
int remote_alias_cache_size,
710 int local_nodes_count)
711 :
If(executor, local_nodes_count)
712 ,
CanIf(this, device)
713 , localAliases_(0, local_alias_cache_size)
714 , remoteAliases_(0, remote_alias_cache_size)
748 ownedFlows_.push_back(std::unique_ptr<Executable>(e));
760 LOG_ERROR(
"Tried to send global AME from not initialized node.");
766 LOG_ERROR(
"Tried to send global AME without a local alias.");
794 remove_local_node_from_map(node);
832 if (expected.
id && actual.
id)
834 return expected.
id == actual.
id;
841 LOG(
VERBOSE,
"Cannot reconcile expected and actual NodeHandles for "
842 "equality testing.");
BufferPtr< T > get_buffer_deleter(Buffer< T > *b)
Helper function to create a BufferPtr of an appropriate type without having to explicitly specify the...
std::unique_ptr< Buffer< T >, BufferDelete< T > > AutoReleaseBuffer
This class will automatically unref a Buffer when going out of scope.
#define STATE(_fn)
Turns a function name into an argument to be supplied to functions expecting a state.
A BarrierNotifiable allows to create a number of child Notifiable and wait for all of them to finish.
BarrierNotifiable * reset(Notifiable *done)
Resets the barrier. Returns &*this. Asserts that is_done().
Base class for all QMember types that hold data in an expandable format.
T * data()
get a pointer to the start of the data.
Interface class for CANbus-based protocols.
FrameDispatchFlow * frame_dispatcher()
OutgoingFrameHandler * frame_write_flow()
void register_handler(HandlerType *handler, ID id, ID mask)
Adds a new handler to this dispatcher.
void unregister_handler(HandlerType *handler, ID id, ID mask)
Removes a specific instance of a handler from this dispatcher.
An object that can be scheduled on an executor to run.
This class implements an execution of tasks pulled off an input queue.
Abstract class for message recipients.
virtual void send(MessageType *message, unsigned priority=UINT_MAX)=0
Entry point to the flow.
MessageType * alloc()
Synchronously allocates a message buffer from the pool of this flow.
Base class for state machines.
Service * service()
Return a pointer to the service I am bound to.
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.
StateFlowBase()
Default constructor.
Action exit()
Terminate current StateFlow activity.
void start_flow(Callback c)
Resets the flow to the specified state and starts it.
Buffer< T > * get_allocation_result(FlowInterface< Buffer< T > > *target_flow)
Takes the result of the asynchronous allocation.
Action call_immediately(Callback c)
Imediately call the next state upon return.
Action wait_and_call(Callback c)
Wait for resource to become available before proceeding to next state.
Though at the surface, this may seem like an unnecessary abstraction of std::map, it has the purpose ...
size_t erase(Key key)
Remove an element from the tree.
void release() OVERRIDE
Unrefs the current buffer.
Base::Action Action
Allows using Action without having StateFlowBase:: prefix in front of it.
void send(MessageType *msg, unsigned priority=UINT_MAX) OVERRIDE
Sends a message to the state flow for processing.
MessageType * transfer_message()
Releases ownership of the current message.
This class listens for Alias Mapping Enquiry frames with no destination node ID (aka global alias enq...
unsigned nextIndex_
Which alias entry index we take next.
BarrierNotifiable n_
Helper object to wait for frame to be sent.
void send(MessageType *msg, unsigned priority=UINT_MAX) override
Sends a message to the state flow for processing.
bool needRerun_
This boolean will be set to true when a full re-run of all sent frames is necessary.
This class listens for alias mapping enquiry frames targeted for local nodes, and replies with AMD fr...
Action entry() OVERRIDE
Entry into the StateFlow activity.
The addressed write flow is responsible for sending addressed messages to the CANbus.
This state flow is responsible for reserving node ID aliases.
void remove(NodeAlias alias)
Remove an alias from an alias cache.
NodeAlias lookup(NodeID id)
Lookup a node's alias based on its Node ID.
void clear()
Reinitializes the entire map.
void add(NodeID id, NodeAlias alias)
Add an alias to an alias cache.
This class listens for incoming CAN messages, and if it sees a local alias conflict,...
unsigned alias_
Alias being checked.
Action send_release_alias()
Sends an AMR (alias mapping release) frame with the alias alias_ and the local node ID that we have f...
Action entry() override
Handler callback for incoming messages.
Action send_reserved_alias()
Sends an RID with the alias alias_.
Base class for incoming CAN frame handlers.
Implements the write-side conversion logic from generic messages to CAN frames.
Action send_to_hardware() override
This function will be called (on the main executor) to initiate sending this message to the hardware.
This class listens for incoming CAN frames of regular addressed OpenLCB messages destined for local n...
Action entry() override
Handler entry for incoming messages.
StlMap< uint32_t, Payload > pendingBuffers_
Reassembly buffers for multi-frame messages.
This class listens for incoming CAN frames of regular unaddressed global OpenLCB messages,...
string buf_
Payload for the MTI message.
uint32_t id_
CAN frame ID, saved from the incoming frame.
Action entry() OVERRIDE
Handler entry for incoming messages.
This write flow inherits all the business logic from the parent, just maintains a separate allocation...
Action send_finished() override
Virtual method called after the send is completed, i.e., all the frames are generated and sent to the...
Action entry() override
Entry into the StateFlow activity.
Implementation of the OpenLCB interface abstraction for the CAN-bus interface standard.
std::vector< std::unique_ptr< Executable > > ownedFlows_
Various implementation control flows that this interface owns.
void add_addressed_message_support()
Adds support to this interface for addressed NMRAnet messages (both sending and receiving).
Node * lookup_local_node_handle(NodeHandle handle) override
Looks up a node ID in the local nodes' registry.
void send_global_alias_enquiry(Node *source)
Sends a global alias enquiry packet.
void set_alias_allocator(AliasAllocator *a)
Sets the alias allocator for this If. Takes ownership of pointer.
AliasCache localAliases_
Aliases we know are owned by local (virtual or proxied) nodes.
NodeID get_default_node_id() override
bool matching_node(NodeHandle expected, NodeHandle actual) override
IfCan(ExecutorBase *executor, CanHubFlow *device, int local_alias_cache_size, int remote_alias_cache_size, int local_nodes_count)
Creates a CAN interface.
std::unique_ptr< AliasAllocator > aliasAllocator_
Owns the alias allocator module.
AliasCache * local_aliases()
void delete_local_node(Node *node) override
Removes a local node from this interface.
AliasCache * remote_aliases()
void add_owned_flow(Executable *e) override
Transfers ownership of a module to the interface.
void canonicalize_handle(NodeHandle *h) override
Canonicalizes the node handle: fills in id and/or alias from the maps the interface holds internally.
Abstract class representing an OpenLCB Interface.
MessageDispatchFlow * dispatcher()
MessageHandler * addressedWriteFlow_
Allocator containing the addressed write flows.
Node * lookup_local_node(NodeID id)
Looks up a node ID in the local nodes' registry.
MessageHandler * globalWriteFlow_
Allocator containing the global write flows.
Base class for NMRAnet nodes conforming to the asynchronous interface.
virtual bool is_initialized()=0
This class listens for alias mapping frames and updates the remote alias cache with the incoming info...
Action entry() OVERRIDE
Entry into the StateFlow activity.
Message handler that is registered as a fallback handler in the interface's message dispatcher.
This handler handles VerifyNodeId messages (both addressed and global) on the interface level.
Action global_entry()
Global write flows should return to this state AFTER sending the message to the hardware.
#define LOG(level, message...)
Conditionally write a message to the logging output.
static const int VERBOSE
Loglevel that is usually not printed, reporting debugging information.
static const int WARNING
Loglevel that is always printed, reporting a warning or a retryable error.
#define LOG_ERROR(message...)
Shorthand for LOG(LEVEL_ERROR, message...). See LOG.
#define OVERRIDE
Function attribute for virtual functions declaring that this funciton is overriding a funciton that s...
void node_id_to_data(NodeID id, void *data)
Convenience function to render a 48-bit NMRAnet node ID into an existing buffer.
NodeID data_to_node_id(const void *d)
Converts 6 bytes of big-endian data to a node ID.
uint64_t NodeID
48-bit NMRAnet Node ID type
size_t g_alias_use_conflicts
Counts the number of alias conflicts that we see for aliases that we already reserved.
string Payload
Container that carries the data bytes in an NMRAnet message.
uint16_t NodeAlias
Alias to a 48-bit NMRAnet Node ID type.
long long ADDRESSED_MESSAGE_LOOKUP_TIMEOUT_NSEC
Specifies how long to wait for a response to an alias mapping enquiry message when trying to send an ...
#define SEC_TO_NSEC(_sec)
Convert a second value to a nanosecond value.
static const uint32_t CAN_EXT_FRAME_MASK
Mask to OR onto a can mask to tell the dispatcher to only consider extended can frames.
static const uint32_t CAN_EXT_FRAME_FILTER
Filter to OR onto a can ID to tell the dispatcher to only consider extended can frames.
static bool is_cid_frame(uint32_t can_id)
Tests if the incoming frame is a CID frame.
static NodeID get_reserved_alias_node_id(NodeAlias alias)
Computes a reserved alias node ID for the local alias cache map.
@ NMRANET_MSG
normal NMRAnet message
@ CONTROL_MSG
CAN control frame message.
static ControlField get_control_field(uint32_t can_id)
Get the control field of a can control frame.
static void control_init(struct can_frame &frame, NodeAlias src, uint16_t field, int sequence)
Initialize a control frame CAN ID and set DLC to 0.
static NodeAlias get_dst(uint32_t can_id)
Get the destination field value of the CAN ID.
static FrameType get_frame_type(uint32_t can_id)
Get the frame type field value of the CAN ID.
static uint32_t set_control_fields(NodeAlias src, uint16_t field, int sequence)
Initialize a control frame CAN ID and set DLC to 0.
static CanMTI get_mti(uint32_t can_id)
Get the MTI field value of the CAN ID.
@ AMD_FRAME
Alias Map Definition frame.
@ AME_FRAME
Alias Mapping Enquiry.
@ RID_FRAME
Reserve ID Frame.
@ AMR_FRAME
Alias Map Reset.
static Priority get_priority(uint32_t can_id)
Get the priority field value of the CAN ID.
static bool is_reserved_alias_node_id(NodeID id)
Tests if a node ID is a reserved alias Node ID.
@ GLOBAL_ADDRESSED
most CAN frame types fall in this category
@ NORMAL_PRIORITY
normal priority CAN message
static NodeAlias get_src(uint32_t can_id)
Get the source field value of the CAN ID.
static bool is_stream_frame(uint32_t can_id)
Tests if the incoming frame is a stream data send frame.
@ FRAME_TYPE_MASK
mask for frame type field of CAN ID
@ SRC_MASK
mask for source field of CAN ID
@ FRAME_TYPE_SHIFT
shift for frame type field of CAN ID
@ CONTROL_FIELD_MASK
control field data mask
@ MTI_MASK
mask for MTI field of CAN ID
@ CONTROL_FIELD_SHIFT
control field data shift
@ CAN_FRAME_TYPE_SHIFT
shift for can frame type field of CAN ID
@ CAN_FRAME_TYPE_MASK
mask for can frame type field of CAN ID
@ PRIORITY_SHIFT
shift for priority field of CAN ID
@ PRIORITY_MASK
mask for priority field of CAN ID
@ MTI_SHIFT
shift for MTI field of CAN ID
MTI
Known Message type indicators.
@ MTI_ADDRESS_MASK
Address present mask.
This class is used in the dispatching of incoming or outgoing NMRAnet messages to the message handler...
NodeHandle dst
Destination node.
Node * dstNode
If the destination node is local, this value is non-NULL.
NodeHandle src
Source node.
Defs::MTI mti
OpenLCB MTI of the incoming message.
string payload
Data content in the message body.
Container of both a NodeID and NodeAlias.
NodeID id
48-bit NMRAnet Node ID
NodeAlias alias
alias to NMRAnet Node ID