--- /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_