servlib/prophet/BundleTLVEntry.h
changeset 0 2b3e5ec03512
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servlib/prophet/BundleTLVEntry.h	Thu Apr 21 14:57:45 2011 +0100
@@ -0,0 +1,321 @@
+/*
+ *    Copyright 2007 Baylor University
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#ifndef _BUNDLE_TLV_ENTRY_H_
+#define _BUNDLE_TLV_ENTRY_H_
+
+#include <sys/types.h>
+
+#include "PointerList.h"
+
+namespace prophet 
+{
+
+/**
+ * BundleTLVEntry is the in-memory representation of an element
+ * listed within the Bundle Offer and Response TLV, p. 30, 4.4.5
+ */
+class BundleTLVEntry
+{
+public:
+    /**
+     * A BundleTLVEntry can represent either an OFFER or a RESPONSE,
+     * depending on what is inferred from the flags
+     */
+    typedef enum
+    {
+        UNDEFINED = 0, ///< no valid type has been specified
+        OFFER,         ///< Bundle OFFER
+        RESPONSE,      ///< Bundle RESPONSE
+    } bundle_entry_t;
+
+    /**
+     * Convenience function
+     */
+    static const char* type_to_str(bundle_entry_t type)
+    {
+        switch(type) {
+        case OFFER:    return "OFFER"; 
+        case RESPONSE: return "RESPONSE";
+        case UNDEFINED:
+        default: break;
+        }
+        return "UNDEFINED";
+    }
+
+    /**
+     * Factory method for convenience
+     */
+    static inline BundleTLVEntry* create_entry(u_int32_t cts, u_int32_t seq,
+                                               u_int16_t sid, bool custody,
+                                               bool accept, bool ack);
+
+protected:
+    /**
+     * Default constructor, only used by friend classes
+     */
+    BundleTLVEntry(bundle_entry_t type = UNDEFINED)
+        : cts_(0), seq_(0), sid_(0), custody_(false),
+          accept_(false), ack_(false), type_(type) {}
+
+    /**
+     * Constructor, only to be used by factory methods and friend classes
+     */
+    BundleTLVEntry(u_int32_t cts, u_int32_t seq, u_int16_t sid,
+                bool custody=false, bool accept=false, bool ack=false,
+                bundle_entry_t type=UNDEFINED)
+        : cts_(cts), seq_(seq), sid_(sid), custody_(custody),
+          accept_(accept), ack_(ack), type_(type)
+    {
+        init_type(type);
+    }
+
+public:
+    /**
+     * Copy constructor
+     */
+    BundleTLVEntry(const BundleTLVEntry& b)
+        : cts_(b.cts_), seq_(b.seq_), sid_(b.sid_), custody_(b.custody_),
+          accept_(b.accept_), ack_(b.ack_), type_(b.type_)
+    {
+        init_type(b.type_);
+    }
+
+    /**
+     * Assignment operator
+     */
+    BundleTLVEntry& operator= (const BundleTLVEntry& b) 
+    {
+        cts_     = b.cts_;
+        seq_     = b.seq_;
+        sid_     = b.sid_;
+        custody_ = b.custody_;
+        accept_  = b.accept_;
+        ack_     = b.ack_;
+        type_    = b.type_;
+        init_type(b.type_); // sanity check
+        return *this;
+    }
+
+    /**
+     * Destructor
+     */
+    virtual ~BundleTLVEntry() {}
+
+    /**
+     * Comparison operator to facilitate STL sorting
+     */
+    bool operator< (const BundleTLVEntry& b) const 
+    {
+        // if (type_ != b.type_) ... ignore difference
+        if (sid_ == b.sid_)
+        {
+            if (cts_ == b.cts_)
+                return seq_ < b.seq_;
+            else
+                return (cts_ < b.cts_);
+        }
+        return (sid_ < b.sid_);
+    }
+
+    ///@{ Accessors
+    u_int32_t creation_ts() const { return cts_; }
+    u_int32_t seqno() const { return seq_; }
+    u_int16_t sid() const { return sid_; }
+    bool custody() const { return custody_; }
+    bool accept() const { return accept_; }
+    bool ack() const { return ack_; }
+    virtual bundle_entry_t type() const { return type_; }
+    ///@}
+
+    /**
+     * Utility function to decipher which Bundle_X_Entry type 
+     * based on the combination of flags
+     */
+    static bundle_entry_t decode_flags(bool custody, bool accept, bool ack) 
+    {
+        // this combination makes no sense
+        if ( accept && ack )
+            return UNDEFINED;
+
+        // infer OFFER from !accept and some combos of custody and ack
+        if (! accept)
+        {
+            // It doesn't make any sense to offer custody
+            // on ACK
+            if (custody && ack)
+                return UNDEFINED;
+
+            // The other three combos of custody and ack are legal for OFFER
+            return OFFER;
+        }
+
+        // infer RESPONSE from this combo
+        if ( (custody || accept) && (! ack))
+        {
+            // It doesn't make any sense to offer custody 
+            // on a bundle unless we accept it
+            if (custody && !accept)
+                return UNDEFINED;
+
+            return RESPONSE;
+        }
+
+        // failed to decode
+        return UNDEFINED;
+    }
+
+protected:
+    /**
+     * Initialization routine used by constructors and assignment operator
+     */
+    void init_type(bundle_entry_t type)
+    {
+        bundle_entry_t df = decode_flags(custody_,accept_,ack_);
+
+        // Three values to compare: The initial value
+        // of "type_", the incoming parameter "type",
+        // and the inferred value "df". 
+
+        // One value to set: class member "type_"
+
+        // If type_ == UNDEFINED, then df and type must match
+        // and type_ is set to their shared value.
+        // If type_ == UNDEFINED, and df and type do not match,
+        // type_ does not change
+        // If type_ != UNDEFINED, then df and type must match type_
+        // else type_ gets set to UNDEFINED
+
+        if (type_ == UNDEFINED)
+        {
+            if (df == type) type_ = type;
+            // else type_ = UNDEFINED
+            return;
+        }
+        // else if (type_ != UNDEFINED)
+        if ((df == type && df == type_))
+            return;
+
+        // logical fault
+        type_ = UNDEFINED;
+    }
+
+    u_int32_t cts_; ///< Creation timestamp
+    u_int32_t seq_; ///< sub-second sequence number
+    u_int16_t sid_; ///< string id of bundle destination
+    bool      custody_; ///< whether this node accepts custody
+    bool      accept_;  ///< whether this Bundle Entry is accepted
+    bool      ack_; ///< represents successful Prophet delivery for bundle
+    bundle_entry_t type_; ///< indicates whether offer or response TLV
+
+}; // class BundleTLVEntry
+
+/**
+ * BundleOfferEntry represents one Bundle, a single entry in a Bundle TLV
+ * sent by a Prophet router in the WAIT_RIB or OFFER state.
+ */
+class BundleOfferEntry : public BundleTLVEntry
+{
+public:
+    /**
+     * Constructor
+     */
+    BundleOfferEntry(u_int32_t cts, u_int32_t seq, u_int16_t sid,
+                  bool custody, bool ack)
+        : BundleTLVEntry(cts,seq,sid,custody,false,ack,BundleTLVEntry::OFFER)
+    {}
+
+    /**
+     * Copy constructor.
+     */
+    BundleOfferEntry(const BundleOfferEntry& b)
+        : BundleTLVEntry(b) {}
+
+    /**
+     * Destructor
+     */
+    virtual ~BundleOfferEntry() {}
+
+protected:
+    friend class PointerList<BundleOfferEntry>;
+
+    /**
+     * Default constructor, only used by friend classes
+     */
+    BundleOfferEntry()
+    {
+        BundleTLVEntry::type_ = BundleTLVEntry::UNDEFINED;
+    }
+}; // class BundleOfferEntry
+
+/**
+ * BundleResponseEntry represents one Bundle, a single entry in a Bundle TLV
+ * sent by a Prophet router in the REQUEST state.
+ */
+class BundleResponseEntry : public BundleTLVEntry
+{
+public:
+    /**
+     * Constructor
+     */
+    BundleResponseEntry(u_int32_t cts, u_int32_t seq, u_int16_t sid,
+                  bool custody, bool accept)
+        : BundleTLVEntry(cts,seq,sid,custody,accept,false,BundleTLVEntry::RESPONSE)
+    {}
+
+    /**
+     * Copy constructor.
+     */
+    BundleResponseEntry(const BundleResponseEntry& b)
+        : BundleTLVEntry(b) {}
+
+    /**
+     * Destructor
+     */
+    virtual ~BundleResponseEntry() {}
+
+protected:
+    friend class PointerList<BundleResponseEntry>;
+
+    /**
+     * Default constructor, only used by friend classes
+     */
+    BundleResponseEntry()
+    {
+        BundleTLVEntry::type_ = BundleTLVEntry::UNDEFINED;
+    }
+}; // class BundleResponseEntry
+
+BundleTLVEntry*
+BundleTLVEntry::create_entry(u_int32_t cts, u_int32_t seq, u_int16_t sid, 
+                             bool custody, bool accept, bool ack) 
+{
+    switch (decode_flags(custody,accept,ack))
+    {
+        case OFFER:
+            return new BundleOfferEntry(cts,seq,sid,custody,ack);
+        case RESPONSE:
+            return new BundleResponseEntry(cts,seq,sid,custody,accept);
+        case UNDEFINED:
+        default:
+            return NULL;
+    }
+    return NULL; // not reached
+}
+
+}; // namespace
+
+#endif // _BUNDLE_TLV_ENTRY_H_