servlib/prophet/ProphetTLV.h
changeset 0 2b3e5ec03512
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servlib/prophet/ProphetTLV.h	Thu Apr 21 14:57:45 2011 +0100
@@ -0,0 +1,259 @@
+/*
+ *    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 _PROPHET_TLV_H_
+#define _PROPHET_TLV_H_
+
+#include <string>
+#include <list>
+#include "BaseTLV.h"
+
+namespace prophet {
+
+class ProphetTLV 
+{
+public:
+    typedef std::list<BaseTLV*> List;
+    typedef std::list<BaseTLV*>::iterator iterator;
+    typedef std::list<BaseTLV*>::const_iterator const_iterator;
+
+    /**
+     * Header Definition
+     * p. 21, 4.2
+     */
+    struct ProphetHeader {
+        u_int8_t version; ///< This version of the PRoPHET Protocol = 1.
+        u_int8_t flags; ///< TBD
+        /**
+         * Field  that is used to indicate whether a response is required
+         * to the request message if the outcome is successful.  A value of
+         * "NoSuccessAck" indicates that the request message does not
+         * expect a response if the outcome is successful, and a value of
+         * "AckAll" indicates that a response is expected if the outcome is
+         * successful.  In both cases a failure response MUST be generated
+         * if the request fails.<br><br>
+         * In a response message, the result field can have two values:
+         * "Success," and "Failure".  The "Success" results indicates a
+         * success response.  All messages that belong to the same success
+         * response will have the same Transaction Identifier.  The
+         * "Success" result indicates a success response that may be
+         * contained in a single message or the final message of a success
+         * response spanning multiple messages.<br><br>
+         * ReturnReceipt is a result field used to indicate that an
+         * acknowledgement is required for the message.  The default for
+         * Messages is that the controller will not acknowledge responses.
+         * In the case where an acknowledgement is required, it will set
+         * the Result Field to ReturnReceipt in the header of the Message.
+         * <br><br>
+         * The encoding of the result field is:<br>
+         * <br>
+         *            NoSuccessAck:       Result = 1<br>
+         *            AckAll:             Result = 2<br>
+         *            Success:            Result = 3<br>
+         *            Failure:            Result = 4<br>
+         *            ReturnReceipt       Result = 5<br>
+         * <br>
+         */
+        u_int8_t result;
+        /**
+         * Field gives further information concerning the result in a
+         * response message.  It is mostly used to pass an error code in a
+         * failure response but can also be used to give further
+         * information in a success response message or an event message.
+         * In a request message, the code field is not used and is set to
+         * zero.<br><br>
+         * If the Code field indicates that the Error TLV is included in
+         * the message, further information on the error will be found in
+         * the Error TLV, which MUST be the the first TLV after the header.
+         * <br><br>
+         * The encoding is:<br>
+         * <br>
+         *     PRoPHET Error messages       0x000 - 0x099<br>
+         *     Reserved                     0x0A0 - 0x0FE<br>
+         *     Error TLV in message             0x0FF<br>
+         * 
+         */
+        u_int8_t code;
+        /**
+         * For messages during the Hello phase with the Hello SYN, Hello
+         * SYNACK, and Hello ACK functions, it is the sender's instance
+         * number for the link.  It is used to detect when the link comes
+         * back up after going down or when the identity of the entity at
+         * the other end of the link changes.  The instance number is a 16-
+         * bit number that is guaranteed to be unique within the recent
+         * past and to change when the link or node comes back up after
+         * going down.  Zero is not a valid instance number.  For the
+         * RSTACK function, the Sender Instance field is set to the value
+         * of the Receiver Instance field from the incoming message that
+         * caused the RSTACK function to be generated.  Messages sent after
+         * the Hello phase is completed should use the sender's instance
+         * number for the link.
+         */
+        u_int16_t sender_instance;
+        /**
+         * For messages during the Hello phase with the Hello SYN, Hello
+         * SYNACK, and Hello ACK functions, is what the sender believes is
+         * the current instance number for the link, allocated by the
+         * entity at the far end of the link.  If the sender of the message
+         * does not know the current instance number at the far end of the
+         * link, this field SHOULD be set to zero.  For the RSTACK message,
+         * the Receiver Instance field is set to the value of the Sender
+         * Instance field from the incoming message that caused the RSTACK
+         * message to be generated.  Messages sent after the Hello phase is
+         * completed should use what the sender believes is the current
+         * instance number for the link, allocated by the entity at the far
+         * end of the link.
+         */
+        u_int16_t receiver_instance;
+        /**
+         * Used to associate a message with its response message.  This
+         * should be set in request messages to a value that is unique for
+         * the sending host within the recent past.  Reply messages contain
+         * the Transaction Indentifier of the request they are responding to.
+         */
+        u_int32_t transaction_id;
+        /**
+         * If S is set then the SubMessage Number field indicates the total
+         * number of SubMessage segments that compose the entire message.
+         * If it is not set then the SubMessage  Number field indicates the
+         * sequence number of this SubMessage segment within the whole
+         * message. the S field will only be set in the first sub-message
+         * of a sequence.
+         */
+        u_int16_t submessage_flag:1;
+        /**
+         * When a message is segmented because it exceeds the MTU of the
+         * link layer, each segment will include a submessage number to
+         * indicate its position.  Alternatively, if it is the first
+         * submessage in a sequence of submessages, the S flag will be set
+         * and this field will contain the total count of submessage
+         * segments.
+         */
+        u_int16_t submessage_num:15;
+        /**
+         * Length in octets of this message including headers and message
+         * body.  If the message is fragmented, this field contains the
+         * length of this submessage.
+         */
+        u_int16_t length;
+    } __attribute__((packed));
+
+    /**
+     * Legal values for ProphetHeader.result field
+     * p. 22, 4.2
+     */
+    typedef enum {
+        UnknownResult = 0x0,
+        NoSuccessAck  = 0x1,
+        AckAll        = 0x2,
+        Success       = 0x3,
+        Failure       = 0x4,
+        ReturnReceipt = 0x5
+    } header_result_t;
+
+    static const size_t ProphetHeaderSize = sizeof(struct ProphetHeader);
+
+    /**
+     * Pretty print function for header_result_t.
+     */
+    static const char* result_to_str(header_result_t hr)
+    {
+        switch(hr) {
+            case NoSuccessAck:  return "NoSuccessAck";
+            case AckAll:        return "AckAll";
+            case Success:       return "Success";
+            case Failure:       return "Failure";
+            case ReturnReceipt: return "ReturnReceipt";
+            case UnknownResult:
+            default:            return "Unknown header result";
+        }
+    }
+
+    /**
+     * Constructor
+     */
+    ProphetTLV(const std::string& src,
+               const std::string& dst,
+               header_result_t result,
+               u_int16_t local_instance,
+               u_int16_t remote_instance,
+               u_int32_t tid);
+
+    /**
+     * Copy constructor
+     */
+    ProphetTLV(const ProphetTLV& tlv);
+
+    /**
+     * Destructor
+     */
+    virtual ~ProphetTLV();
+
+    /**
+     * Write ProphetTLV out to no more than len bytes of buffer; return
+     * bytes written
+     */
+    size_t serialize(u_char* bp, size_t len) const;
+
+    /**
+     * Read ProphetTLV in from no more than len bytes of buffer; return
+     * bytes read
+     */
+    static ProphetTLV* deserialize(const std::string& src,
+                                   const std::string& dst,
+                                   const u_char* bp, size_t len);
+
+    /**
+     * Place TLV on list for serialization into next outbound ProphetTLV.
+     * ProphetTLV assumes ownership of memory on submitted pointer,
+     * on success.
+     */
+    bool add_tlv(BaseTLV* tlv);
+
+    /**
+     * Remove next TLV from list. Caller assumes ownership of memory
+     * pointed to by returned pointer (if non-NULL).
+     */
+    BaseTLV* get_tlv();
+
+    ///@{ Accessors
+    const std::string& source()         const { return src_; }
+    const std::string& destination()    const { return dst_; }
+    header_result_t result()            const { return result_; }
+    u_int16_t       sender_instance()   const { return sender_instance_; }
+    u_int16_t       receiver_instance() const { return receiver_instance_; }
+    u_int32_t       transaction_id()    const { return tid_; }
+    u_int16_t       length()            const { return length_; }
+    size_t          size()              const { return list_.size(); }
+    const List&     list()              const { return list_; }
+    ///@}
+
+protected:
+    ProphetTLV();
+
+    std::string src_; ///< destination id for TLV source (from Bundle metadata)
+    std::string dst_; ///< destination id for TLV destination (from Bundle ")
+    header_result_t result_; ///< Disposition of this Prophet TLV 
+    u_int16_t sender_instance_; ///< Local node's index for this encounter
+    u_int16_t receiver_instance_; ///< Peer's index for this encounter
+    u_int32_t tid_; ///< Transaction ID for this TLV
+    mutable u_int16_t length_; ///< Serialized length of this TLV
+    List list_; ///< Linked list of TLVs embedded in this Prophet TLV
+
+}; // class ProphetTLV
+
+}; // namespace prophet
+#endif //  _PROPHET_TLV_H_