libuav original

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers transfer_listener.hpp Source File

transfer_listener.hpp

00001 /*
00002  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
00003  */
00004 
00005 #ifndef UAVCAN_TRANSPORT_TRANSFER_LISTENER_HPP_INCLUDED
00006 #define UAVCAN_TRANSPORT_TRANSFER_LISTENER_HPP_INCLUDED
00007 
00008 #include <cassert>
00009 #include <uavcan/error.hpp>
00010 #include <uavcan/std.hpp>
00011 #include <uavcan/transport/transfer_receiver.hpp>
00012 #include <uavcan/transport/perf_counter.hpp>
00013 #include <uavcan/util/linked_list.hpp>
00014 #include <uavcan/util/map.hpp>
00015 #include <uavcan/debug.hpp>
00016 #include <uavcan/transport/crc.hpp>
00017 #include <uavcan/data_type.hpp>
00018 
00019 namespace uavcan
00020 {
00021 /**
00022  * Container for received transfer.
00023  */
00024 class UAVCAN_EXPORT IncomingTransfer : public ITransferBuffer
00025 {
00026     MonotonicTime ts_mono_;
00027     UtcTime ts_utc_;
00028     TransferPriority transfer_priority_;
00029     TransferType transfer_type_;
00030     TransferID transfer_id_;
00031     NodeID src_node_id_;
00032     uint8_t iface_index_;
00033 
00034     /// That's a no-op, asserts in debug builds
00035     virtual int write(unsigned offset, const uint8_t* data, unsigned len);
00036 
00037 protected:
00038     IncomingTransfer(MonotonicTime ts_mono, UtcTime ts_utc, TransferPriority transfer_priority,
00039                      TransferType transfer_type, TransferID transfer_id, NodeID source_node_id,
00040                      uint8_t iface_index)
00041         : ts_mono_(ts_mono)
00042         , ts_utc_(ts_utc)
00043         , transfer_priority_(transfer_priority)
00044         , transfer_type_(transfer_type)
00045         , transfer_id_(transfer_id)
00046         , src_node_id_(source_node_id)
00047         , iface_index_(iface_index)
00048     { }
00049 
00050 public:
00051     /**
00052      * Dispose the payload buffer. Further calls to read() will not be possible.
00053      */
00054     virtual void release() { }
00055 
00056     /**
00057      * Whether this is a anonymous transfer
00058      */
00059     virtual bool isAnonymousTransfer() const { return false; }
00060 
00061     MonotonicTime getMonotonicTimestamp() const { return ts_mono_; }
00062     UtcTime getUtcTimestamp()             const { return ts_utc_; }
00063     TransferPriority getPriority()        const { return transfer_priority_; }
00064     TransferType getTransferType()        const { return transfer_type_; }
00065     TransferID getTransferID()            const { return transfer_id_; }
00066     NodeID getSrcNodeID()                 const { return src_node_id_; }
00067     uint8_t getIfaceIndex()               const { return iface_index_; }
00068 };
00069 
00070 /**
00071  * Internal.
00072  */
00073 class UAVCAN_EXPORT SingleFrameIncomingTransfer : public IncomingTransfer
00074 {
00075     const uint8_t* const payload_;
00076     const uint8_t payload_len_;
00077 public:
00078     explicit SingleFrameIncomingTransfer(const RxFrame& frm);
00079     virtual int read(unsigned offset, uint8_t* data, unsigned len) const;
00080     virtual bool isAnonymousTransfer() const;
00081 };
00082 
00083 /**
00084  * Internal.
00085  */
00086 class UAVCAN_EXPORT MultiFrameIncomingTransfer : public IncomingTransfer, Noncopyable
00087 {
00088     TransferBufferAccessor& buf_acc_;
00089 public:
00090     MultiFrameIncomingTransfer(MonotonicTime ts_mono, UtcTime ts_utc, const RxFrame& last_frame,
00091                                TransferBufferAccessor& tba);
00092     virtual int read(unsigned offset, uint8_t* data, unsigned len) const;
00093     virtual void release() { buf_acc_.remove(); }
00094 };
00095 
00096 /**
00097  * Internal, refer to the transport dispatcher class.
00098  */
00099 class UAVCAN_EXPORT TransferListener : public LinkedListNode<TransferListener>
00100 {
00101     const DataTypeDescriptor& data_type_;
00102     TransferBufferManager bufmgr_;
00103     Map<TransferBufferManagerKey, TransferReceiver>  receivers_;
00104     TransferPerfCounter& perf_;
00105     const TransferCRC crc_base_;                      ///< Pre-initialized with data type hash, thus constant
00106     bool allow_anonymous_transfers_;
00107 
00108     class TimedOutReceiverPredicate
00109     {
00110         const MonotonicTime ts_;
00111         TransferBufferManager& parent_bufmgr_;
00112 
00113     public:
00114         TimedOutReceiverPredicate(MonotonicTime arg_ts, TransferBufferManager& arg_bufmgr)
00115             : ts_(arg_ts)
00116             , parent_bufmgr_(arg_bufmgr)
00117         { }
00118 
00119         bool operator()(const TransferBufferManagerKey& key, const TransferReceiver& value) const;
00120     };
00121 
00122     bool checkPayloadCrc(const uint16_t compare_with, const ITransferBuffer& tbb) const;
00123 
00124 protected:
00125     void handleReception(TransferReceiver& receiver, const RxFrame& frame, TransferBufferAccessor& tba);
00126     void handleAnonymousTransferReception(const RxFrame& frame);
00127 
00128     virtual void handleIncomingTransfer(IncomingTransfer& transfer) = 0;
00129 
00130 public:
00131     TransferListener(TransferPerfCounter& perf, const DataTypeDescriptor& data_type,
00132                      uint16_t max_buffer_size, IPoolAllocator& allocator)
00133         : data_type_(data_type)
00134         , bufmgr_(max_buffer_size, allocator)
00135         , receivers_(allocator)
00136         , perf_(perf)
00137         , crc_base_(data_type.getSignature().toTransferCRC())
00138         , allow_anonymous_transfers_(false)
00139     { }
00140 
00141     virtual ~TransferListener();
00142 
00143     const DataTypeDescriptor& getDataTypeDescriptor() const { return data_type_; }
00144 
00145     /**
00146      * By default, anonymous transfers will be ignored.
00147      * This option allows to enable reception of anonymous transfers.
00148      */
00149     void allowAnonymousTransfers() { allow_anonymous_transfers_ = true; }
00150 
00151     void cleanup(MonotonicTime ts);
00152 
00153     virtual void handleFrame(const RxFrame& frame);
00154 };
00155 
00156 /**
00157  * This class is used by transfer listener to decide if the frame should be accepted or ignored.
00158  */
00159 class ITransferAcceptanceFilter
00160 {
00161 public:
00162     /**
00163      * If it returns false, the frame will be ignored, otherwise accepted.
00164      */
00165     virtual bool shouldAcceptFrame(const RxFrame& frame) const = 0;
00166 
00167     virtual ~ITransferAcceptanceFilter() { }
00168 };
00169 
00170 /**
00171  * This class should be derived by callers.
00172  */
00173 class UAVCAN_EXPORT TransferListenerWithFilter : public TransferListener
00174 {
00175     const ITransferAcceptanceFilter* filter_;
00176 
00177     virtual void handleFrame(const RxFrame& frame);
00178 
00179 public:
00180     TransferListenerWithFilter(TransferPerfCounter& perf, const DataTypeDescriptor& data_type,
00181                                uint16_t max_buffer_size, IPoolAllocator& allocator)
00182         : TransferListener(perf, data_type, max_buffer_size, allocator)
00183         , filter_(UAVCAN_NULLPTR)
00184     { }
00185 
00186     void installAcceptanceFilter(const ITransferAcceptanceFilter* acceptance_filter)
00187     {
00188         filter_ = acceptance_filter;
00189     }
00190 };
00191 
00192 }
00193 
00194 #endif // UAVCAN_TRANSPORT_TRANSFER_LISTENER_HPP_INCLUDED