diff -r 000000000000 -r 2b3e5ec03512 servlib/prophet/ResponseTLV.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlib/prophet/ResponseTLV.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 // for hton[ls] and ntoh[ls] +#include "ResponseTLV.h" + +namespace prophet +{ + +ResponseTLV::ResponseTLV() + : BundleTLV(BaseTLV::RESPONSE_TLV) {} + +ResponseTLV::ResponseTLV(const BundleResponseList& bl) + : BundleTLV(BaseTLV::RESPONSE_TLV,0,bl.guess_size(BundleEntrySize)), + list_(bl) {} + +size_t +ResponseTLV::serialize(u_char* bp, size_t len) const +{ + // weed out the oddball + if (bp == NULL) return 0; + if (typecode_ != BaseTLV::RESPONSE_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::RESPONSE_TLV; + hdr->flags = 0; + hdr->offer_count = htons(list_.size()); + + length_ += BundleTLVHeaderSize; + bp += BundleTLVHeaderSize; + len -= BundleTLVHeaderSize; + + // write out each Bundle offer + for (BundleResponseList::const_iterator i = list_.begin(); + i != list_.end(); + i++) + { + BundleResponseEntry* 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 +ResponseTLV::deserialize(const u_char* bp, size_t len) +{ + // weed out the oddball + if (bp == NULL) return false; + if (typecode_ != RESPONSE_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::RESPONSE) + return false; + + if (! list_.add_response(cts,seq,sid,custody,accept)) + return false; + + // account for what's been read + amt_read += bytes_read; + len -= bytes_read; + bp += bytes_read; + } + + return (amt_read == length_); +} + +}; // namespace prophet