36#ifndef _OPENLCB_CANROUTNGHUB_HXX_
37#define _OPENLCB_CANROUTNGHUB_HXX_
66 : deliveryFlow_(s,
this)
73 void *port = b->
data()->skipMember_;
74 auto it =
ports_.find(port);
77 LOG(
INFO,
"Arrived packet to routing hub without recognized source "
78 "designation (%p). Dropped packet.",
79 b->
data()->skipMember_);
83 const string &p = *b->
data();
84 for (
unsigned i = 0; i < p.size(); ++i)
86 if (it->second.segmenter_.consume_byte(p[i]))
90 it->second.segmenter_.frame_buffer(&ret);
91 LOG(
VERBOSE,
"sending frame: %s", ret.c_str());
92 auto *cb = deliveryFlow_.
alloc();
93 HASSERT(it->second.segmenter_.parse_frame_to_output(
94 cb->data()->mutable_frame()));
95 cb->data()->skipMember_ =
reinterpret_cast<
97 b->
data()->skipMember_);
109 return &deliveryFlow_;
116 ports_[port].hubPort_ = port;
122 auto it =
ports_.find(port);
125 LOG(
INFO,
"Trying to remove a nonexistant port: %p", port);
128 it->second.inactive_ =
true;
134 typedef std::map<void *, PortParser> PortsMap;
144 const struct can_frame &frame,
unsigned old_priority)
175 const struct can_frame &frame =
message()->data()->frame();
176 if (IS_CAN_FRAME_ERR(frame) || IS_CAN_FRAME_RTR(frame))
178 return release_and_exit();
182 if (srcAddress_ != 0)
184 parent_->routingTable_.add_node_id_to_route(
185 message()->data()->skipMember_, srcAddress_);
190 if (forwardType_ ==
ADDRESSED && dstAddress_ != 0)
193 parent_->routingTable_.lookup_port_for_address(dstAddress_);
194 nextIt_ = parent_->
ports_.find(port);
195 if (nextIt_ != parent_->
ports_.end())
198 return call_immediately(
STATE(forward_addressed));
206 nextIt_ = parent_->
ports_.begin();
208 return call_immediately(
STATE(try_next_entry));
217 if (!IS_CAN_FRAME_EFF(frame))
222 uint32_t can_id = GET_CAN_FRAME_ID_EFF(frame);
262 dstAddress_ = frame.data[0] & 0xf;
264 dstAddress_ |= frame.data[1];
268 bool has_event =
false;
274 if (mti == Defs::MTI_EVENT_REPORT && has_event)
276 forwardType_ =
EVENT;
284 ~Defs::MTI_MODIFIER_MASK:
285 parent_->routingTable_.register_consumer(
286 message()->data()->skipMember_, event_);
289 ~Defs::MTI_MODIFIER_MASK:
290 parent_->routingTable_.register_producer(
291 message()->data()->skipMember_, event_);
299 parent_->routingTable_.register_producer_range(
300 message()->data()->skipMember_, event_);
303 parent_->routingTable_.register_consumer_range(
304 message()->data()->skipMember_, event_);
318 if (nextIt_ == parent_->
ports_.end())
320 return done_processing();
323 if (forwardType_ ==
EVENT)
325 if (parent_->routingTable_.check_pcer(
342 Action forward_addressed()
346 return done_processing();
356 return release_and_exit();
359 void forward_to_port()
361 if (nextIt_->second.inactive_)
363 if (nextIt_->second.canPort_)
365 if (nextIt_->second.canPort_ ==
message()->data()->skipMember_)
367 nextIt_->second.canPort_->send(
message()->ref(), priority());
371 HASSERT(nextIt_->second.hubPort_);
374 nextIt_->second.hubPort_);
375 if (hpi ==
message()->data()->skipMember_)
377 ensure_gc_buf_available();
378 nextIt_->second.hubPort_->send(
gcBuf_->ref());
382 void ensure_gc_buf_available()
389 gcBuf_->data()->assign(buf, end - buf);
391 message()->data()->skipMember_);
409 PortsMap::iterator nextIt_;
DynamicPool * mainBufferPool
main buffer pool instance
#define STATE(_fn)
Turns a function name into an argument to be supplied to functions expecting a state.
Base class for all QMember types that hold data in an expandable format.
void unref()
Decrement count.
T * data()
get a pointer to the start of the data.
MessageType * alloc()
Synchronously allocates a message buffer from the pool of this flow.
Parses a sequence of characters; finds GridConnect protocol packet boundaries in the sequence of pack...
Data type wrapper for sending data through a Hub.
Class to allow convenient locking and unlocking of mutexes in a C context.
This class provides a mutex API.
void alloc(Buffer< BufferType > **result, Executable *flow=NULL)
Get a free item out of the pool.
Collection of related state machines that pend on incoming messages.
State flow with a given typed input queue.
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.
Flow responsible for queuing outgoing CAN frames as well as sending out the actual frames to the reci...
void classify_frame(const can_frame &frame)
Classifies the incoming frame and sets the class variables determining what to do with it.
Action entry() override
Entry into the StateFlow activity.
@ ADDRESSED
Addressed packet that needs to check the routing table.
@ EVENT
Event report packet that needs to check the routing table.
@ FORWARD_ALL
Broadcast packet that needs to go out to all ports, unfiltered.
Buffer< HubData > * gcBuf_
Gridconnect-rendered frame.
A hub flow that accepts string HUB ports sending CAN frames via the GridConnect protocol,...
unsigned reprioritize_frame(const struct can_frame &frame, unsigned old_priority)
Computes the desired priority of a CAN frame.
void send(Buffer< HubData > *b, unsigned priority=UINT_MAX) override
Entry point to the flow.
CanHubPortInterface * can_hub()
std::map< void *, PortParser > ports_
Keyed by the skipMember_ value of the incoming data from a given port.
std::vector< void * > pendingRemove_
Due to race conditions involving iteration and add/remove calls, we delay applying unregister request...
Routing table for gateways and routers in OpenLCB.
#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 INFO
Loglevel that is printed by default, reporting some status information.
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
uint64_t data_to_eventid(const void *data)
Takes 8 bytes (big-endian) from *data, and returns the event id they represent.
uint16_t NodeAlias
Alias to a 48-bit NMRAnet Node ID type.
static bool is_cid_frame(uint32_t can_id)
Tests if the incoming frame is a CID frame.
static CanFrameType get_can_frame_type(uint32_t can_id)
Get the CAN frame type field value of the CAN ID.
@ CONTROL_MSG
CAN control frame message.
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 CanMTI get_mti(uint32_t can_id)
Get the MTI field value of the CAN ID.
@ GLOBAL_ADDRESSED
most CAN frame types fall in this category
static NodeAlias get_src(uint32_t can_id)
Get the source field value of the CAN ID.
The generic interface for NMRAnet network interfaces.
MTI
Known Message type indicators.
@ MTI_PRODUCER_IDENTIFIED_RANGE
producer broadcast about a range of producers
@ MTI_MODIFIER_MASK
modifier within Priority/Type mask
@ MTI_PRODUCER_IDENTIFIED_VALID
producer broadcast, valid state
@ MTI_CONSUMER_IDENTIFIED_VALID
consumer broadcast, valid state
@ MTI_CONSUMER_IDENTIFIED_RANGE
consumer broadcast about a range of consumers
static bool get_mti_event(MTI mti)
Get the MTI event present value field.
static bool get_mti_address(MTI mti)
Get the MTI address present value field.
Data and objects we keep for each port.
bool inactive_
If true, we must not send any data to this target, because it has been unregistered.