//@C Copyright Notice //@C ================ //@C This file is part of CPSW. It is subject to the license terms in the LICENSE.txt //@C file found in the top-level directory of this distribution and at //@C https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. //@C //@C No part of CPSW, including this file, may be copied, modified, propagated, or //@C distributed except according to the terms contained in the LICENSE.txt file. #ifndef CPSW_RSSI_H #define CPSW_RSSI_H #include #include #include #include #include #include #include #include #include using cpsw::atomic; #define RSSI_DEBUG 1 // level #include class IRxEventHandler : public IEventHandler { protected: virtual void handleRxEvent(IIntEventSource*) = 0; virtual void handle(IIntEventSource *s) { handleRxEvent(s); } }; class IUsrInputEventHandler : public IEventHandler { protected: virtual void handleUsrInputEvent(IIntEventSource*) = 0; virtual void handle(IIntEventSource *s) { handleUsrInputEvent(s); } }; class IUsrOutputEventHandler : public IEventHandler { protected: virtual void handleUsrOutputEvent(IIntEventSource*) = 0; virtual void handle(IIntEventSource *s) { handleUsrOutputEvent(s); } }; class IRexTimer : public RssiTimer { protected: virtual void processRetransmissionTimeout() = 0; public: IRexTimer(RssiTimerList *l) : RssiTimer("REX", l) {} virtual void process() { RssiTimer::process(); processRetransmissionTimeout(); } }; class IAckTimer : public RssiTimer { protected: virtual void processAckTimeout() = 0; public: IAckTimer(RssiTimerList *l) : RssiTimer("ACK", l) {} virtual void process() { RssiTimer::process(); processAckTimeout(); } }; class INulTimer : public RssiTimer { protected: virtual void processNulTimeout() = 0; public: INulTimer(RssiTimerList *l) : RssiTimer("NUL", l) {} virtual void process() { RssiTimer::process(); processNulTimeout(); } }; // posts events when the state changes class CConnectionStateChangedEventSource : public CIntEventSource { public: static const int CONN_STATE_OPEN = 10; // could support other states static const int CONN_STATE_CLOSED = -1; }; // posts events when the state is changed to // the defined target state (currently: open/closed) class CConnectionStateEventSource : public IIntEventSource { protected: atomic connState_; public: CConnectionStateEventSource(); virtual void connectionStateChanged(int); }; class CConnectionOpenEventSource : public CConnectionStateEventSource { public: CConnectionOpenEventSource(); protected: virtual bool checkForEvent(); }; class CConnectionNotOpenEventSource : public CConnectionStateEventSource { public: CConnectionNotOpenEventSource(); protected: virtual bool checkForEvent(); }; class CConnectionClosedEventSource : public CConnectionStateEventSource { public: CConnectionClosedEventSource(); protected: virtual bool checkForEvent(); }; // Obtain the max. segment size to advertise to the peer // The return value of 'getRxMTU' is the max. size the // system can accept **including** any RSSI headers class IMTUQuerier { public: virtual int getRxMTU() = 0; virtual ~IMTUQuerier() {} }; class CRssi : public CRunnable, public IRxEventHandler, public IUsrInputEventHandler, public IUsrOutputEventHandler, public IRexTimer, public IAckTimer, public INulTimer, public CConnectionStateChangedEventSource, public CConnectionOpenEventSource, public CConnectionNotOpenEventSource, public CConnectionClosedEventSource { public: static const uint8_t LD_MAX_UNACKED_SEGS = 4; static const uint8_t MAX_UNACKED_SEGS = 1< buf_; BufIdx rp_; BufIdx msk_; SeqNo oldest_; public: BufBase(unsigned ldsz) : buf_( (capa_= (1<rp_) {} iterator & operator++() { if ( idx_ != rb_->wp_ ) idx_++; return *this; } BufChain operator*() { if ( idx_ == rb_->wp_ ) return BufChain(); return rb_->buf_.at( (idx_ & rb_->msk_) ); } }; iterator begin() { return iterator(this); } unsigned getSize() { return (unsigned)(wp_ - rp_); } int ack(SeqNo ackNo) { SeqNo cumAck = ackNo - oldest_ + 1; unsigned i; if ( cumAck > getSize() ) { // an error -- misformed packet? // the caller should discard... return -1; } for ( i=0; i capa_ ) { // should never happen since we must // not have more than ossMX outstanding // transmits throw InternalError("RingBuf Overflow"); } buf_[ widx ] = b; wp_++; } void resize(unsigned new_capa) { unsigned i; unsigned sz = getSize(); std::vector tmp( sz ); SeqNo tmpo = getOldest(); for ( i=0; itv_ ) ) throw InternalError("clock_gettime failed"); } virtual void forceACK() { numCak_ = cakMX_; } virtual void * threadBody(); virtual void changeState(STATE *newState); virtual bool threadStop(); }; #endif