--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/servlib/prophet/TLVCreator.h Thu Apr 21 14:57:45 2011 +0100
@@ -0,0 +1,230 @@
+/*
+ * 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_CREATOR_H_
+#define _PROPHET_TLV_CREATOR_H_
+
+#include "Table.h"
+#include "BundleCore.h"
+#include "BundleList.h"
+#include "Dictionary.h"
+#include "RIBDTLV.h"
+#include "RIBTLV.h"
+#include "OfferTLV.h"
+#include "BundleTLVEntryList.h"
+#include "BundleOffer.h"
+#include "Oracle.h"
+#include <string>
+
+namespace prophet
+{
+
+struct TLVCreator
+{
+ static RIBDTLV* ribd(BundleCore* core,
+ const Table* nodes,
+ const std::string& sender,
+ const std::string& receiver)
+ {
+ // reject the oddball
+ if (core == NULL || nodes == NULL) return NULL;
+
+ Dictionary ribd(sender,receiver);
+ for (Table::const_iterator i = nodes->begin(); i != nodes->end(); i++)
+ {
+ // grab the route from the iterator
+ std::string dest = i->first;
+ std::string eid = core->get_route(dest);
+ // attempt to insert, fail out if unsuccessful
+ if (ribd.insert(eid) == Dictionary::INVALID_SID &&
+ ribd.find(eid) == Dictionary::INVALID_SID) return NULL;
+ }
+
+ ribd.dump(core,__FILE__,__LINE__);
+ return new RIBDTLV(ribd);
+ }
+
+ static RIBTLV* rib(Oracle* oracle,
+ const Dictionary& ribd,
+ bool relay_node,
+ bool accept_custody,
+ bool internet_gw = false)
+ {
+ // reject the oddball
+ if (oracle == NULL) return NULL;
+
+ const Table* nodes = oracle->nodes();
+ std::string sender = ribd.find(0);
+ std::string receiver = ribd.find(1);
+
+ RIBNodeList list;
+ for (Table::const_iterator i = nodes->begin(); i != nodes->end(); i++)
+ {
+ const std::string eid = i->first;
+ if (eid == sender || eid == receiver) continue;
+ const Node* n = i->second;
+ u_int16_t sid = ribd.find(eid);
+ if (sid == Dictionary::INVALID_SID)
+ return NULL; // log error?
+ oracle->core()->print_log("rib",BundleCore::LOG_DEBUG,
+ "%s (%u) -> %.2f",eid.c_str(),sid,n->p_value());
+ list.push_back(new RIBNode(n,sid));
+ }
+
+ ribd.dump(oracle->core(),__FILE__,__LINE__);
+ return new RIBTLV(list,relay_node,accept_custody,internet_gw);
+ }
+
+ static OfferTLV* offer(Oracle* oracle,
+ const Link* nexthop,
+ const Dictionary& ribd,
+ const Table& remote)
+ {
+ // reject the oddball
+ if (oracle == NULL) return NULL;
+
+ // create comp
+ FwdStrategyComp* comp = FwdStrategy::strategy(
+ oracle->params()->fs(),
+ oracle->nodes(),
+ &remote);
+
+ // create decider
+ Decider* d = Decider::decider(
+ oracle->params()->fs(),
+ nexthop,
+ oracle->core(),
+ oracle->nodes(),
+ &remote,
+ oracle->stats(),
+ oracle->params()->max_forward(),
+ oracle->params()->relay_node());
+
+ // offer's destructor will clean up comp and d
+ BundleOffer offer(oracle->core(),oracle->core()->bundles(),comp,d);
+
+ // Create a reduced list of ACKs by only tacking on those that
+ // haven't already been sent
+
+ PointerList<Ack> acklist; // list of clones from oracle's ACKs
+ AckList acks; // reduced list to send to get_bundle_offer
+ AckList* link_acks = const_cast<Link*>(nexthop)->acks();
+
+ oracle->acks()->clone(acklist);
+ for(PointerList<Ack>::iterator i = acklist.begin();
+ i != acklist.end(); i++)
+ {
+ // returns false if already exists in list (meaning, already sent)
+ if (link_acks->insert(*i))
+ acks.insert(*i);
+ }
+
+ BundleOfferList list = offer.get_bundle_offer(ribd,&acks);
+
+ if (list.empty())
+ oracle->core()->print_log("offer",BundleCore::LOG_DEBUG,
+ "empty bundle offer");
+ else
+ {
+ for (BundleOfferList::const_iterator i = list.begin();
+ i != list.end(); i++)
+ {
+ oracle->core()->print_log("offer",BundleCore::LOG_DEBUG,
+ "%u %u %u %s%s%s",
+ (*i)->creation_ts(),
+ (*i)->seqno(),
+ (*i)->sid(),
+ (*i)->custody() ? "C" : "-",
+ (*i)->accept() ? "A" : "-",
+ (*i)->ack() ? "K" : "-");
+ }
+ }
+
+ return new OfferTLV(list);
+ }
+
+ static ResponseTLV* response(Oracle* oracle,
+ const BundleOfferList& offers,
+ BundleResponseList& list,
+ const Dictionary& ribd)
+ {
+ // reject the oddball
+ if (oracle == NULL) return NULL;
+
+ ribd.dump(oracle->core(),__FILE__,__LINE__);
+
+ for (BundleOfferList::const_iterator i = offers.begin();
+ i != offers.end(); i++)
+ {
+ // pull out the three-way tuple that uniquely identifies bundles
+ u_int32_t cts = (*i)->creation_ts();
+ u_int32_t seq = (*i)->seqno();
+ u_int16_t sid = (*i)->sid();
+ std::string eid = ribd.find(sid);
+
+ // First delete any ACK'd bundles, and store the ACK
+ const Bundle* b = oracle->core()->find(
+ oracle->core()->bundles(),eid,cts,seq);
+ if ((*i)->ack())
+ {
+ oracle->core()->print_log("response",BundleCore::LOG_DEBUG,
+ "ACK %s %u:%u",eid.c_str(),cts,seq);
+
+ if (b != NULL)
+ oracle->ack(b);
+ else
+ oracle->acks()->insert(eid,cts,seq);
+
+ // also remember that it came from this link, so as not
+ // to propagate this ACK over this link again
+
+ }
+ else
+ // only request the bundle if not already present in host storage
+ // and if no ACK exists for the bundle
+ if (b == NULL)
+ {
+ // no need to request bundles that have already been delivered
+ if (oracle->acks()->is_ackd(eid,cts,seq))
+ {
+ oracle->core()->print_log("response",BundleCore::LOG_DEBUG,
+ "not requesting ACK'd bundle: %s %u %u",
+ eid.c_str(),cts,seq);
+ continue;
+ }
+
+ // Logically AND local settings for custody accept with
+ // remote's request for custody transfer
+ bool custody = (*i)->custody() &&
+ oracle->core()->custody_accepted();
+ if (list.add_response(cts,seq,sid,custody))
+ {
+ const BundleResponseEntry* bre = list.back();
+ oracle->core()->print_log("response",BundleCore::LOG_DEBUG,
+ "%s (%u) %u %u",eid.c_str(),bre->sid(),
+ bre->creation_ts(),bre->seqno());
+ }
+ }
+ }
+
+ return new ResponseTLV(list);
+ }
+
+}; // struct TLVCreator
+
+}; // namespace prophet
+
+#endif // _PROPHET_TLV_CREATOR_H_