Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
IfCan.hxx
Go to the documentation of this file.
1
35#ifndef _OPENLCB_IFCAN_HXX_
36#define _OPENLCB_IFCAN_HXX_
37
38#include <memory>
39
41#include "openlcb/If.hxx"
43#include "openlcb/Defs.hxx"
44#include "utils/CanIf.hxx"
45
46namespace openlcb
47{
48
49class IfCan;
50
53extern size_t g_alias_use_conflicts;
54
55class AliasAllocator;
56class IfCan;
57
64class IfCan : public If, public CanIf
65{
66public:
86 int local_alias_cache_size, int remote_alias_cache_size,
87 int local_nodes_count);
88
89 ~IfCan();
90
94
97 {
99 return &localAliases_;
100 }
101
104 {
106 return &remoteAliases_;
107 }
108
111 {
112 return aliasAllocator_.get();
113 }
114
117
125 void send_global_alias_enquiry(Node *source);
126
127 void add_owned_flow(Executable *e) override;
128
129 bool matching_node(NodeHandle expected, NodeHandle actual) override;
130
131 void delete_local_node(Node *node) override;
132
133 Node *lookup_local_node_handle(NodeHandle handle) override;
134
135 NodeID get_default_node_id() override;
136
137private:
138 void canonicalize_handle(NodeHandle *h) override;
139
140 friend class CanFrameWriteFlow; // accesses the device and the hubport.
141
152
154 std::vector<std::unique_ptr<Executable>> ownedFlows_;
155
157 std::unique_ptr<AliasAllocator> aliasAllocator_;
158
160};
161
163class CanFrameStateFlow : public StateFlow<Buffer<CanMessageData>, QList<1>>
164{
165public:
166 CanFrameStateFlow(IfCan *service)
168 {
169 }
170
171 IfCan *if_can()
172 {
173 return static_cast<IfCan *>(service());
174 }
175};
176
179{
183 {
184 srcNode = node;
185 this->handle = handle;
186 resultCode = 0;
187 }
188
195
201};
202
206 : public StateFlow<Buffer<NodeCanonicalizeRequest>, QList<1>>
207{
208public:
215
217 Action entry() override
218 {
219 if (input()->handle.id != 0)
220 {
221 return return_ok();
222 }
223 if (input()->handle.alias == 0)
224 {
225 // This is an empty handle, say that's OK.
226 return return_ok();
227 }
228 NodeID id = iface()->remote_aliases()->lookup(input()->handle.alias);
229 if (!id)
230 {
231 id = iface()->local_aliases()->lookup(input()->handle.alias);
232 }
233 if (id)
234 {
235 input()->handle.id = id;
236 return return_ok();
237 }
238 return allocate_and_call(
239 iface()->addressed_message_write_flow(), STATE(send_request));
240 }
241
242private:
245 {
246 auto *b =
247 get_allocation_result(iface()->addressed_message_write_flow());
248 b->data()->reset(Defs::MTI_VERIFY_NODE_ID_ADDRESSED,
249 input()->srcNode->node_id(), input()->handle, EMPTY_PAYLOAD);
250 replyHandler_.set_alias_waiting(input()->handle.alias);
252
253 return sleep_and_call(&timer_, MSEC_TO_NSEC(700), STATE(reply_timeout));
254 }
255
259 {
260 replyHandler_.set_alias_waiting(0);
261 if (!timer_.is_triggered())
262 {
263 return return_with_error(Defs::ERROR_OPENLCB_TIMEOUT);
264 }
265 if (!input()->handle.id)
266 {
267 return return_with_error(Defs::ERROR_OPENMRN_NOT_FOUND);
268 }
269 return return_ok();
270 }
271
274 {
275 public:
284
291
293 void send(Buffer<GenMessage> *message, unsigned priority) OVERRIDE
294 {
296 if (aliasWaiting_ == 0)
297 return;
298
299 GenMessage *msg = message->data();
300 if (msg->src.alias != aliasWaiting_)
301 return;
302
303 if (msg->src.id != 0)
304 {
305 parent_->input()->handle.id = msg->src.id;
306 }
307 else if (msg->payload.size() == 6)
308 {
309 parent_->input()->handle.id =
310 data_to_node_id(msg->payload.data());
311 }
312 else
313 {
314 // Node ID verified with no source data. Problem.
315 }
317 parent_->timer_.trigger();
318 }
319
323 {
324 aliasWaiting_ = a;
325 }
326
327 private:
332 } replyHandler_{this};
333
334 friend class ReplyHandler;
335
338 {
339 return return_with_error(0);
340 }
341
344 {
345 input()->resultCode = error;
347 return exit();
348 }
349
352 {
353 return message()->data();
354 }
355
358 {
359 return static_cast<IfCan *>(service());
360 }
361
365 StateFlowTimer timer_{this};
366};
367
368} // namespace openlcb
369
370#endif // _OPENLCB_IFCAN_HXX_
std::unique_ptr< Buffer< T >, BufferDelete< T > > AutoReleaseBuffer
This class will automatically unref a Buffer when going out of scope.
Definition Buffer.hxx:256
#define STATE(_fn)
Turns a function name into an argument to be supplied to functions expecting a state.
Definition StateFlow.hxx:61
A BarrierNotifiable allows to create a number of child Notifiable and wait for all of them to finish.
Base class for all QMember types that hold data in an expandable format.
Definition Buffer.hxx:195
Interface class for the asynchronous frame write flow.
Definition CanIf.hxx:130
Interface class for CANbus-based protocols.
Definition CanIf.hxx:185
CanHubFlow * device()
Definition CanIf.hxx:249
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.
Definition Executor.hxx:64
void assert_current()
Die if we are not on the current executor.
Definition Executor.hxx:160
virtual void send(MessageType *message, unsigned priority=UINT_MAX)=0
Entry point to the flow.
A list of queues.
Definition Queue.hxx:466
ExecutorBase * executor()
State flow with a given typed input queue.
Base::Action Action
Allows using Action without having StateFlowBase:: prefix in front of it.
MessageType * message()
void return_buffer()
For state flows that are operated using invoke_subflow_and_wait this is a way to hand back the buffer...
This state flow is responsible for reserving node ID aliases.
Cache of alias to node id mappings.
NodeAlias lookup(NodeID id)
Lookup a node's alias based on its Node ID.
Base class for incoming CAN frame handlers.
Definition IfCan.hxx:164
Implementation of the OpenLCB interface abstraction for the CAN-bus interface standard.
Definition IfCan.hxx:65
std::vector< std::unique_ptr< Executable > > ownedFlows_
Various implementation control flows that this interface owns.
Definition IfCan.hxx:154
void add_addressed_message_support()
Adds support to this interface for addressed NMRAnet messages (both sending and receiving).
Definition IfCan.cxx:783
Node * lookup_local_node_handle(NodeHandle handle) override
Looks up a node ID in the local nodes' registry.
Definition IfCan.cxx:846
void send_global_alias_enquiry(Node *source)
Sends a global alias enquiry packet.
Definition IfCan.cxx:756
void set_alias_allocator(AliasAllocator *a)
Sets the alias allocator for this If. Takes ownership of pointer.
Definition IfCan.cxx:751
AliasCache localAliases_
Aliases we know are owned by local (virtual or proxied) nodes.
Definition IfCan.hxx:146
NodeID get_default_node_id() override
Definition IfCan.cxx:855
bool matching_node(NodeHandle expected, NodeHandle actual) override
Definition IfCan.cxx:828
std::unique_ptr< AliasAllocator > aliasAllocator_
Owns the alias allocator module.
Definition IfCan.hxx:157
AliasCache remoteAliases_
Aliases we know are owned by remote nodes on this If.
Definition IfCan.hxx:151
AliasCache * local_aliases()
Definition IfCan.hxx:96
void delete_local_node(Node *node) override
Removes a local node from this interface.
Definition IfCan.cxx:793
AliasAllocator * alias_allocator()
Definition IfCan.hxx:110
AliasCache * remote_aliases()
Definition IfCan.hxx:103
void add_owned_flow(Executable *e) override
Transfers ownership of a module to the interface.
Definition IfCan.cxx:746
void canonicalize_handle(NodeHandle *h) override
Canonicalizes the node handle: fills in id and/or alias from the maps the interface holds internally.
Definition IfCan.cxx:806
Abstract class representing an OpenLCB Interface.
Definition If.hxx:185
MessageDispatchFlow * dispatcher()
Definition If.hxx:224
MessageHandler * addressed_message_write_flow()
Definition If.hxx:210
Class for listening to the ping response packets.
Definition IfCan.hxx:274
void send(Buffer< GenMessage > *message, unsigned priority) OVERRIDE
Handler callback for incoming messages.
Definition IfCan.hxx:293
NodeIdLookupFlow * parent_
Flow owning *this.
Definition IfCan.hxx:331
ReplyHandler(NodeIdLookupFlow *parent)
Constructor.
Definition IfCan.hxx:278
void set_alias_waiting(NodeAlias a)
The parent flow calls this function when the handler needs to be activated.
Definition IfCan.hxx:322
NodeAlias aliasWaiting_
Which node alias we are listening for a reply from.
Definition IfCan.hxx:329
~ReplyHandler()
Destructor. Unregisters the handler.
Definition IfCan.hxx:286
Child flow to be used in parents that need translation from node alias to node id.
Definition IfCan.hxx:207
NodeCanonicalizeRequest * input()
Definition IfCan.hxx:351
Action send_request()
Send out a ping request to the destination alias.
Definition IfCan.hxx:244
Action return_ok()
Terminates the current subflow with no error.
Definition IfCan.hxx:337
Action entry() override
Starts processing an incoming request.
Definition IfCan.hxx:217
StateFlowTimer timer_
Helper object for timed wait.
Definition IfCan.hxx:365
Action return_with_error(int error)
Terminates the current subflow with an error code.
Definition IfCan.hxx:343
Action reply_timeout()
Called when a reply arrives or the timeout expires.
Definition IfCan.hxx:258
NodeIdLookupFlow(IfCan *iface)
Constructor.
Definition IfCan.hxx:211
BarrierNotifiable bn_
Helper object for calling subflows.
Definition IfCan.hxx:363
Base class for NMRAnet nodes conforming to the asynchronous interface.
Definition Node.hxx:52
#define OVERRIDE
Function attribute for virtual functions declaring that this funciton is overriding a funciton that s...
Definition macros.h:180
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Removes default copy-constructor and assignment added by C++.
Definition macros.h:171
string EMPTY_PAYLOAD
A global class / variable for empty or not-yet-initialized payloads.
Definition If.cxx:152
NodeID data_to_node_id(const void *d)
Converts 6 bytes of big-endian data to a node ID.
Definition If.cxx:59
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.
Definition IfCan.cxx:47
uint16_t NodeAlias
Alias to a 48-bit NMRAnet Node ID type.
#define MSEC_TO_NSEC(_msec)
Convert a millisecond value to a nanosecond value.
Definition os.h:268
@ MTI_VERIFY_NODE_ID_ADDRESSED
verify a Node ID
@ MTI_EXACT
match mask for a single MTI
@ MTI_VERIFIED_NODE_ID_NUMBER
respond to a verify Node ID request
This class is used in the dispatching of incoming or outgoing NMRAnet messages to the message handler...
Definition If.hxx:72
NodeHandle src
Source node.
Definition If.hxx:104
string payload
Data content in the message body.
Definition If.hxx:113
Request object for the NodeIdLookupFlow.
Definition IfCan.hxx:179
NodeHandle handle
Destination node handle to canonicalize.
Definition IfCan.hxx:194
int resultCode
Set to 0 on success, or an OpenLCB or OpenMRN error code in case of a failure.
Definition IfCan.hxx:200
Node * srcNode
Caller node (in order to talk to the bus)
Definition IfCan.hxx:190
void reset(Node *node, NodeHandle handle)
Requests a NodeHandle to be canonicalized, i.e.
Definition IfCan.hxx:182
BarrierNotifiable done
Needed for receiveing replies by the customer.
Definition IfCan.hxx:197
Container of both a NodeID and NodeAlias.
NodeID id
48-bit NMRAnet Node ID
NodeAlias alias
alias to NMRAnet Node ID