// [License] // The Ariba-Underlay Copyright // // Copyright (c) 2008-2009, Institute of Telematics, Universität Karlsruhe (TH) // // Institute of Telematics // Universität Karlsruhe (TH) // Zirkel 2, 76128 Karlsruhe // Germany // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation // are those of the authors and should not be interpreted as representing // official policies, either expressed or implied, of the Institute of // Telematics. // [License] #ifndef OVERLAY_MSG_H__ #define OVERLAY_MSG_H__ #include #include "ariba/utility/messages.h" #include "ariba/utility/serialization.h" #include "ariba/utility/types/ServiceID.h" #include "ariba/utility/types/NodeID.h" #include "ariba/utility/types/LinkID.h" // #include #include "ariba/overlay/SequenceNumber.h" namespace ariba { namespace overlay { using ariba::utility::LinkID; using ariba::utility::NodeID; using ariba::utility::ServiceID; using ariba::utility::Message; //using ariba::communication::EndpointDescriptor; using_serialization; /** * A general purpose overlay message that is used to exchange messages * between nodes. * * @author Sebastian Mies , Mario Hock */ class OverlayMsg: public Message { VSERIALIZEABLE; public: /// message types, is: uint8_t enum type_ { // is: uint8_t typeInvalid = 0x00, ///< invalid, unspecified type // data transfer maskTransfer = 0x10, ///< bit mask for transfer messages typeData = 0x11, ///< message contains data for higher layers typeMessageLost = 0x12, ///< message contains info about a dropped message // join signaling maskJoin = 0x20, ///< bit mask for join messages typeJoinRequest = 0x21, ///< join request typeJoinReply = 0x22, ///< join reply // link messages maskLink = 0x30, ///< bit mask for link messages typeLinkRequest = 0x31, ///< request a new link typeLinkReply = 0x32, ///< link request reply typeLinkUpdate = 0x33, ///< update message for link association typeLinkDirect = 0x34, ///< direct connection has been established typeKeepAlive = 0x35, ///< keep-alive message typeKeepAliveReply = 0x36, ///< keep-alive message (replay) typeLinkClose = 0x37, /// DHT routed messages /// @deprecated because the DHT has been moved into a separate service maskDHT = 0x40, ///< bit mask for dht messages typeDHTPut = 0x41, ///< DHT put operation typeDHTGet = 0x42, ///< DHT get operation typeDHTRemove = 0x43, ///< DHT remove operation /// DHT response messages /// @deprecated because the DHT has been moved into a separate service maskDHTResponse = 0x50, ///< bit mask for dht responses typeDHTData = 0x51, ///< DHT get data /// misc message types typePing = 0x44, typePong = 0x45, // topology signaling typeSignalingStart = 0x80, ///< start of the signaling types typeSignalingEnd = 0xFF ///< end of the signaling types }; /// message flags (uint8_t) enum flags_ { flagRelayed = 1 << 0, flagRegisterRelay = 1 << 1, flagRouteRecord = 1 << 2, flagSeqNum1 = 1 << 3, flagSeqNum2 = 1 << 4, flagAutoLink = 1 << 5, flagLinkMessage = 1 << 6, flagHasMoreFlags = 1 << 7 }; /// default constructor OverlayMsg( uint8_t type = typeInvalid, const ServiceID& _service = ServiceID::UNSPECIFIED, const NodeID& _sourceNode = NodeID::UNSPECIFIED, const NodeID& _destinationNode = NodeID::UNSPECIFIED, const LinkID& _sourceLink = LinkID::UNSPECIFIED, const LinkID& _destinationLink = LinkID::UNSPECIFIED ) : type(type), flags(0), extended_flags(0), hops(0), ttl(10), priority(0), service(_service), sourceNode(_sourceNode), destinationNode(_destinationNode), sourceLink(_sourceLink), destinationLink(_destinationLink), routeRecord() { if (!_sourceLink.isUnspecified() || !_destinationLink.isUnspecified()) setLinkMessage(true); } // copy constructor OverlayMsg(const OverlayMsg& rhs) : type(rhs.type), flags(rhs.flags), extended_flags(rhs.extended_flags), hops(rhs.hops), ttl(rhs.ttl), priority(rhs.priority), service(rhs.service), sourceNode(rhs.sourceNode), destinationNode(rhs.destinationNode), sourceLink(rhs.sourceLink), destinationLink(rhs.destinationLink), routeRecord(rhs.routeRecord) { } /// destructor ~OverlayMsg(); /// type ------------------------------------------------------------------- type_ getType() const { return (type_) type; } void setType( type_ type ) { this->type = type; } bool hasTypeMask( type_ mask ) const { return (type & (uint8_t)mask) == (uint8_t)mask; } /// priority ------------------------------------------------------------------ uint8_t getPriority() const { return priority; } void setPriority(uint8_t priority) { this->priority = priority; } /// flags ------------------------------------------------------------------ bool isRelayed() const { return (flags & flagRelayed)!=0; } void setRelayed( bool relayed = true ) { if (relayed) flags |= flagRelayed; else flags &= ~flagRelayed; } bool isRegisterRelay() const { return (flags & flagRegisterRelay)!=0; } void setRegisterRelay( bool relayed = true ) { if (relayed) flags |= flagRegisterRelay; else flags &= ~flagRegisterRelay; } bool isRouteRecord() const { return (flags & flagRouteRecord)!=0; } void setRouteRecord( bool route_record = true ) { if (route_record) flags |= flagRouteRecord; else flags &= ~flagRouteRecord; } bool isAutoLink() const { return (flags & flagAutoLink) == flagAutoLink; } void setAutoLink(bool auto_link = true ) { if (auto_link) flags |= flagAutoLink; else flags &= ~flagAutoLink; } bool isLinkMessage() const { return (flags & flagLinkMessage)!=0; } void setLinkMessage(bool link_info = true ) { if (link_info) flags |= flagLinkMessage; else flags &= ~flagLinkMessage; } bool hasExtendedFlags() const { return (flags & flagHasMoreFlags) == flagHasMoreFlags; } /// number of hops and time to live ---------------------------------------- uint8_t getNumHops() const { return hops; } void setNumHops( uint8_t hops ) { this->hops = hops; } uint8_t increaseNumHops() { hops++; return hops; } uint8_t getTimeToLive() const { return ttl; } void setTimeToLive( uint8_t ttl ) { this->ttl = ttl; } /// addresses and links ---------------------------------------------------- const ServiceID& getService() const { return service; } void setService( const ServiceID& service ) { this->service = service; } const NodeID& getSourceNode() const { return sourceNode; } void setSourceNode( const NodeID& node ) { this->sourceNode = node; } const NodeID& getDestinationNode() const { return destinationNode; } void setDestinationNode( const NodeID& node ) { this->destinationNode = node; } const LinkID& getSourceLink() const { return sourceLink; } void setSourceLink( const LinkID& link ) { this->sourceLink = link; setLinkMessage(); } const LinkID& getDestinationLink() const { return destinationLink; } void setDestinationLink( const LinkID& link ) { this->destinationLink = link; setLinkMessage(); } /// swaps source and destination void swapRoles() { NodeID dummyNode = sourceNode; sourceNode = destinationNode; destinationNode = dummyNode; LinkID dummyLink = sourceLink; sourceLink = destinationLink; destinationLink = dummyLink; hops = 0; routeRecord.clear(); } const vector getRouteRecord() const { return routeRecord; } void addRouteRecord( const NodeID& node ) { if (isRouteRecord()) routeRecord.push_back(node); } /// sequence numbers bool hasShortSeqNum() const { return (flags & (flagSeqNum1 | flagSeqNum2)) == flagSeqNum1; } bool hasLongSeqNum() const { return (flags & (flagSeqNum1 | flagSeqNum2)) == flagSeqNum2; } void setSeqNum(const SequenceNumber& sequence_number) { this->seqnum = sequence_number; // short seqnum if ( sequence_number.isShortSeqNum() ) { flags |= flagSeqNum1; flags &= ~flagSeqNum2; } // longseqnum else if ( sequence_number.isShortSeqNum() ) { flags &= ~flagSeqNum1; flags |= flagSeqNum2; } // no seqnum else { flags &= ~flagSeqNum1; flags &= ~flagSeqNum2; } } const SequenceNumber& getSeqNum() const { return seqnum; } private: uint8_t type, flags, extended_flags, hops, ttl, priority; ServiceID service; NodeID sourceNode; NodeID destinationNode; LinkID sourceLink; LinkID destinationLink; // EndpointDescriptor sourceEndpoint; vector routeRecord; SequenceNumber seqnum; }; }} // ariba::overlay /// serialization sznBeginDefault( ariba::overlay::OverlayMsg, X ){ // header X && type && flags; if ( hasExtendedFlags() ) X && extended_flags; X && hops && ttl; // addresses X && &service && &sourceNode && &destinationNode; // priority X && priority; // message is associated with a end-to-end link if (isLinkMessage()) X && &sourceLink && &destinationLink; /* seqnum */ // serialize if ( X.isSerializer() ) { if ( hasShortSeqNum() ) { uint32_t short_seqnum; short_seqnum = seqnum.getShortSeqNum(); X && short_seqnum; } if ( hasLongSeqNum() ) { uint64_t long_seqnum; long_seqnum = seqnum.getLongSeqNum(); X && long_seqnum; } } // deserialize else { if ( hasShortSeqNum() ) { uint32_t short_seqnum; X && short_seqnum; seqnum = ariba::overlay::SequenceNumber(short_seqnum); } if ( hasLongSeqNum() ) { uint64_t long_seqnum; X && long_seqnum; seqnum = ariba::overlay::SequenceNumber(long_seqnum); } } // message should record its route if (isRouteRecord()) { uint8_t size = routeRecord.size(); X && size; if (X.isDeserializer()) routeRecord.resize(size); for (uint8_t i=0;i