diff --git a/contrib/yss7/interface.cpp b/contrib/yss7/interface.cpp index dc476c8c..290f79ec 100644 --- a/contrib/yss7/interface.cpp +++ b/contrib/yss7/interface.cpp @@ -40,12 +40,19 @@ void SignallingInterface::attach(SignallingReceiver* receiver) bool SignallingInterface::control(Operation oper, NamedList* params) { + DDebug(engine(),DebugInfo,"Unhandled SignallingInterface::control(%d,%p) [%p]", + oper,params,this); return false; } -bool SignallingInterface::receivedPacket() +bool SignallingInterface::receivedPacket(const DataBlock& packet) { - return m_receiver && m_receiver->receivedPacket(); + return m_receiver && m_receiver->receivedPacket(packet); +} + +bool SignallingInterface::notify(Notification event) +{ + return m_receiver && m_receiver->notify(event); } @@ -61,4 +68,10 @@ void SignallingReceiver::attach(SignallingInterface* iface) Debug("STUB",DebugWarn,"Please implement SignallingReceiver::attach()"); } +bool SignallingReceiver::notify(SignallingInterface::Notification event) +{ + DDebug(engine(),DebugInfo,"Unhandled SignallingReceiver::notify(%d) [%p]",event,this); + return false; +} + /* vi: set ts=8 sw=4 sts=4 noet: */ diff --git a/contrib/yss7/layer2.cpp b/contrib/yss7/layer2.cpp index 0ea7d683..f94c8c15 100644 --- a/contrib/yss7/layer2.cpp +++ b/contrib/yss7/layer2.cpp @@ -26,19 +26,93 @@ using namespace TelEngine; -bool SS7MTP2::receivedMSU() +SS7MTP2::SS7MTP2() + : Mutex(false), m_bsn(0), m_fsn(0), m_bib(false), m_fib(false) { - Debug("STUB",DebugWarn,"Please implement SS7MTP2::receivedMSU()"); } -bool SS7MTP2::transmitMSU() +// Transmit a MSU retaining a copy for retransmissions +bool SS7MTP2::transmitMSU(const DataBlock& msu) { - Debug("STUB",DebugWarn,"Please implement SS7MTP2::transmitMSU()"); + if (msu.length() < 3) { + Debug(engine(),DebugMild,"Asked to send MSU of length %u [%p]", + msu.length(),this); + return false; + } + XDebug(engine(),DebugAll,"SS7MTP2::transmitMSU(%p) len=%u [%p]", + &msu,msu.length(),this); + // if we don't have an attached interface don't bother + if (!iface()) + return false; + + DataBlock* packet = new DataBlock(0,3); + *packet += msu; + + // set BSN+BIB, FSN+FIB, LENGTH in the 3 extra bytes + unsigned char* buf = (unsigned char*)packet->data(); + buf[2] = (msu.length() > 0x3f) ? 0x3f : msu.length() & 0x3f; + // lock the object so we can safely use member variables + Lock lock(this); + buf[0] = m_bib ? m_bsn | 0x80 : m_bsn; + buf[1] = m_fib ? m_fsn | 0x80 : m_fsn; + ++m_fsn; + m_queue.append(packet); + return transmitPacket(*packet,false); } -bool SS7MTP2::receivedPacket() +// Decode a received packet into signalling units +bool SS7MTP2::receivedPacket(const DataBlock& packet) { Debug("STUB",DebugWarn,"Please implement SS7MTP2::receivedPacket()"); + if (packet.length() < 3) { + XDebug(engine(),DebugMild,"Received short packet of length %u [%p]", + packet.length(),this) + return false; + } + const unsigned char* buf = (const unsigned char*)packet.data(); + unsigned int len = buf[2] & 0x3f; + if ((len == 0x3f) && (packet.length() > 0x42)) + len = packet.length() - 3; + else if (len != (packet.length() - 3)) { + XDebug(engine(),DebugMild,"Received packet with length indicator %u but length %u [%p]", + len,packet.length(),this); + return false; + } + bool ok = true; + // packet length is valid, check sequence numbers + unsigned char bsn = buf[0] & 0x7f; + bool bib = (buf[0] & 0x80) != 0; + unsigned char fsn = buf[1] & 0x7f; + bool fib = (buf[1] & 0x80) != 0; + + //TODO: implement Q.703 6.3.1 + + switch (len) { + case 2: +// processLSSU(buf[3]); +// break; + case 1: + processLSSU(buf[3]); + return ok; + case 0: + processFISU(); + return ok; + } + DataBlock msu((void*)(buf+3),len,false); + ok = receivedMSU(msu); + msu.clear(false); + return ok; +} + +// Process incoming FISU +void SS7MTP2::processFISU() +{ +} + +// Process incoming LSSU +void SS7MTP2::processLSSU(unsigned int status) +{ + Debug("STUB",DebugWarn,"Please implement SS7MTP2::processLSSU()"); } /* vi: set ts=8 sw=4 sts=4 noet: */ diff --git a/contrib/yss7/layer3.cpp b/contrib/yss7/layer3.cpp index 0793e8b1..48d51965 100644 --- a/contrib/yss7/layer3.cpp +++ b/contrib/yss7/layer3.cpp @@ -32,7 +32,7 @@ void SS7MTP3::attach(SS7Layer2* link) SignallingComponent::insert(link); } -bool SS7MTP3::receivedMSU() +bool SS7MTP3::receivedMSU(const DataBlock& msu) { Debug("STUB",DebugWarn,"Please implement SS7MTP3::receivedMSU()"); } diff --git a/contrib/yss7/yatess7.h b/contrib/yss7/yatess7.h index 82d48520..8344edd0 100644 --- a/contrib/yss7/yatess7.h +++ b/contrib/yss7/yatess7.h @@ -244,6 +244,22 @@ public: Query = 0xc0 }; + /** + * Interface generated notifications + */ + enum Notification { + HardwareError, + TxClockError, + RxClockError, + AlignError, + CksumError, + TxOversize, + RxOversize, + TxOverflow, + RxOverflow, + TxUnderrun, + }; + /** * Destructor, stops and detaches the interface */ @@ -276,15 +292,26 @@ public: protected: /** * Transmit a packet over the hardware interface + * @param packet Packet data to send + * @param repeat Continuously send a copy of the packet while no other + * data is available for transmission * @return True if the interface accepted the packet */ - virtual bool transmitPacket() = 0; + virtual bool transmitPacket(const DataBlock& packet, bool repeat) = 0; /** - * Push a received Signalling Packet up the protocol stack + * Push a valid received Signalling Packet up the protocol stack. + * The starting and ending flags and any CRC are not part of the data. * @return True if packet was successfully delivered to the receiver */ - bool receivedPacket(); + bool receivedPacket(const DataBlock& packet); + + /** + * Generate a notification event to the attached receiver + * @param event Notification event to be reported + * @return True if notification was accepted by the receiver + */ + bool notify(Notification event); private: SignallingReceiver* m_receiver; @@ -330,16 +357,26 @@ public: protected: /** * Send a packet to the attached interface for transmission + * @param packet Packet data to send + * @param repeat Continuously send a copy of the packet while no other + * data is available for transmission * @return True if the interface accepted the packet */ - inline bool transmitPacket() - { return m_interface && m_interface->transmitPacket(); } + inline bool transmitPacket(const DataBlock& packet, bool repeat) + { return m_interface && m_interface->transmitPacket(packet,repeat); } /** * Process a Signalling Packet received by the interface * @return True if message was successfully processed */ - virtual bool receivedPacket() = 0; + virtual bool receivedPacket(const DataBlock& packet) = 0; + + /** + * Process a notification generated by the attached interface + * @param event Notification event reported by the interface + * @return True if notification was processed + */ + virtual bool notify(SignallingInterface::Notification event); private: SignallingInterface* m_interface; @@ -468,9 +505,10 @@ public: protected: /** * Process a MSU received from the Layer 2 component + * @param msu Message data, starting with Service Indicator Octet * @return True if the MSU was processed */ - virtual bool receivedMSU() = 0; + virtual bool receivedMSU(const DataBlock& msu) = 0; }; /** @@ -487,10 +525,11 @@ public: }; /** - * Push a Message Signalling Unit down the protocol stack + * Push a Message Signal Unit down the protocol stack + * @param msu Message data, starting with Service Indicator Octet * @return True if message was successfully queued */ - virtual bool transmitMSU() = 0; + virtual bool transmitMSU(const DataBlock& msu) = 0; /** * Attach a Layer 2 user component to the data link @@ -508,11 +547,12 @@ public: protected: /** - * Push a received Message Signalling Unit up the protocol stack + * Push a received Message Signal Unit up the protocol stack + * @param msu Message data, starting with Service Indicator Octet * @return True if message was successfully delivered to the user component */ - inline bool receivedMSU() - { return m_l2user && m_l2user->receivedMSU(); } + inline bool receivedMSU(const DataBlock& msu) + { return m_l2user && m_l2user->receivedMSU(msu); } private: SS7L2User* m_l2user; @@ -633,28 +673,45 @@ class YSS7_API SS7M3UA : public SS7Layer3, public SIGTRAN * Q.703 SS7 Layer 2 (Data Link) implementation on top of a hardware interface * @short SS7 Layer 2 implementation on top of a hardware interface */ -class YSS7_API SS7MTP2 : public SS7Layer2, public SignallingReceiver +class YSS7_API SS7MTP2 : public SS7Layer2, public SignallingReceiver, public Mutex { public: /** - * Push a Message Signalling Unit down the protocol stack + * Constructor + */ + SS7MTP2(); + + /** + * Push a Message Signal Unit down the protocol stack * @return True if message was successfully queued */ - virtual bool transmitMSU(); + virtual bool transmitMSU(const DataBlock& msu); protected: - /** - * Process a MSU received from the Layer 2 component - * @return True if the MSU was processed - */ - virtual bool receivedMSU(); /** * Process a Signalling Packet received by the hardware interface * @return True if message was successfully processed */ - virtual bool receivedPacket(); + virtual bool receivedPacket(const DataBlock& packet); + /** + * Process a received Fill-In Signal Unit + */ + virtual void processFISU(); + + /** + * Process a received Link Status Signal Unit + */ + virtual void processLSSU(unsigned int status); + +private: + // sent but yet unacknowledged packets + ObjList m_queue; + // backward and forward sqeuence numbers + unsigned char m_bsn, m_fsn; + // backward and forward indicator bits + bool m_bib, m_fib; }; /** @@ -673,9 +730,10 @@ public: protected: /** * Process a MSU received from the Layer 2 component + * @param msu Message data, starting with Service Indicator Octet * @return True if the MSU was processed */ - virtual bool receivedMSU(); + virtual bool receivedMSU(const DataBlock& msu); ObjList m_links; };