servlib/prophet/OfferTLV.cc
changeset 0 2b3e5ec03512
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servlib/prophet/OfferTLV.cc	Thu Apr 21 14:57:45 2011 +0100
@@ -0,0 +1,141 @@
+/*
+ *    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.
+ */
+
+#include <arpa/inet.h> // for hton[ls] and ntoh[ls]
+#include "OfferTLV.h"
+
+namespace prophet
+{
+
+OfferTLV::OfferTLV(const BundleOfferList& bl)
+    : BundleTLV(BaseTLV::OFFER_TLV,0,bl.guess_size(BundleEntrySize)),
+      list_(bl) {}
+
+OfferTLV::OfferTLV()
+    : BundleTLV(BaseTLV::OFFER_TLV) {}
+
+size_t
+OfferTLV::serialize(u_char* bp, size_t len) const
+{
+    // weed out the oddball
+    if (bp == NULL) return 0;
+    if (typecode_ != BaseTLV::OFFER_TLV) return 0;
+
+    // check that lengths match up
+    if (BundleTLVHeaderSize +
+            list_.guess_size(BundleEntrySize) > len)
+        return 0;
+
+    // account for bytes written
+    length_ = 0;
+
+    // start writing out to buffer
+    BundleTLVHeader* hdr = (BundleTLVHeader*) bp;
+    memset(hdr, 0, BundleTLVHeaderSize);
+    hdr->type = BaseTLV::OFFER_TLV;
+    hdr->flags = 0;
+    hdr->offer_count = htons(list_.size());
+
+    length_ += BundleTLVHeaderSize;
+    bp      += BundleTLVHeaderSize;
+    len     -= BundleTLVHeaderSize;
+
+    // write out each Bundle offer
+    for (BundleOfferList::const_iterator i = list_.begin();
+         i != list_.end();
+         i++)
+    {
+        const BundleOfferEntry* b = *i;
+        size_t bytes_written =
+            BundleTLV::write_bundle_entry(b->creation_ts(),
+                                    b->seqno(), b->sid(), b->custody(),
+                                    b->accept(), b->ack(), b->type(),
+                                    bp, len);
+
+        if (BundleEntrySize > bytes_written) break;
+
+        length_ += bytes_written;
+        len     -= bytes_written;
+        bp      += bytes_written;
+    }
+
+    hdr->length = htons(length_);
+    return length_;
+}
+
+bool
+OfferTLV::deserialize(const u_char* bp, size_t len)
+{
+    // weed out the oddball
+    if (bp == NULL) return false;
+    if (typecode_ != OFFER_TLV) return false;
+    if (! list_.empty()) return false;
+
+    // check that lengths match up
+    if (BundleTLVHeaderSize > len) return false;
+
+    // zero out accounting
+    size_t amt_read = 0;
+    length_ = 0;
+
+    // parse the header
+    BundleTLVHeader* b = (BundleTLVHeader*) bp;
+    if (b->type != typecode_) return false;
+    length_ = ntohs(b->length);
+    if (length_ > len) return false;
+    flags_ = b->flags;
+    size_t offer_count = ntohs(b->offer_count);
+
+    // now move past the header
+    bp       += BundleTLVHeaderSize;
+    len      -= BundleTLVHeaderSize;
+    amt_read += BundleTLVHeaderSize;
+
+    while (len >= BundleTLVHeaderSize &&
+           amt_read + BundleTLVHeaderSize <= length_ &&
+           offer_count-- > 0)
+    {
+        u_int32_t cts = 0;
+        u_int32_t seq = 0;
+        u_int16_t sid = 0;
+        bool custody = false,
+             accept = false,
+             ack = false;
+        BundleTLVEntry::bundle_entry_t type = BundleTLVEntry::UNDEFINED;
+
+        size_t bytes_read =
+            BundleTLV::read_bundle_entry(&cts,&seq,&sid,&custody,
+                                         &accept,&ack,&type,bp,len);
+
+        if (BundleEntrySize > bytes_read)
+            return false;
+
+        if (type != BundleTLVEntry::OFFER)
+            return false;
+
+        if (! list_.add_offer(cts,seq,sid,custody,ack))
+            return false;
+
+        // account for what's been read
+        amt_read += bytes_read;
+        len      -= bytes_read;
+        bp       += bytes_read;
+    }
+
+    return (amt_read == length_);
+}
+
+}; // namespace prophet