First steps in CCNx packet coding. ccnx_encode* routines rewritten in NS3 style (using NS3::Buffer)
diff --git a/in-progress/ccnx-pit.h b/in-progress/ccnx-pit.h
new file mode 100644
index 0000000..83fad09
--- /dev/null
+++ b/in-progress/ccnx-pit.h
@@ -0,0 +1,276 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+//
+// Copyright (c) 2010,2011 UCLA
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation;
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// Author:
+//
+
+#ifndef CCNX_PIT_H
+#define CCNX_PIT_H
+
+#include "ns3/nstime.h"
+#include "hash-helper.h"
+#include <list>
+
+namespace ns3 {
+
+class Ccnx;
+class PitEntry;
+class PitIncomingInterest;
+typedef pair<PitEntry*,PitIncomingInterest*> PitExpirationEntry;
+typedef list<PitExpirationEntry>::iterator PitExpirationIterator;
+
+struct PitIncomingInterest
+{
+ int interfaceIndex; // interface index of the incoming Interest
+ Time expireTime; // life time of the incoming Interest
+ int nonce; // nonce of the last received incoming Interest on this interface
+
+ PitExpirationIterator expirationPosition;
+
+public:
+PitIncomingInterest( int _interface, clocktype _expire, int _nonce )
+: interfaceIndex(_interface)
+, expireTime(_expire)
+ , nonce(_nonce)
+ { };
+
+ bool operator==( const PitIncomingInterest &dst ) { return interfaceIndex==dst.interfaceIndex; }
+ bool operator==( int interface ) { return interfaceIndex==interface; }
+};
+
+struct PitOutgoingInterest
+{
+ int interfaceIndex;
+ clocktype sendTime; //time when the first outgoing interest is sent
+ int retxNum; //number of retransmission
+ int nonce; //nonce of the outgoing Interest
+ bool outstanding; //flag to indicate that this interest is currently pending
+ bool waitingInVain; //when flag is set, we do not expect data for this interest, only a small hope that it will happen
+
+public:
+PitOutgoingInterest( int interface, clocktype time, int nonce )
+: interfaceIndex(interface)
+, sendTime( time )
+ , retxNum( 0 )
+ , nonce( nonce )
+ , outstanding( true )
+ , waitingInVain( false )
+ { };
+
+ bool operator==( const PitIncomingInterest &dst ) { return interfaceIndex==dst.interfaceIndex; }
+ bool operator==( int interface ) { return interfaceIndex==interface; }
+};
+
+
+//structure for PIT entry
+struct PitEntry
+{
+ string contentName;
+ list<PitIncomingInterest> incomingInterests;
+ list<PitOutgoingInterest> outgoingInterests;
+
+ bool timerExpired;
+ int counterExpirations; //whether timer is expired (+ number of times timer expired)
+
+ /**
+ * This variable provides a list of interfaces that will be tried to propagate interest
+ *
+ * It should be initialized with all available interfaces upon reception of first or
+ * any retransmitted (i.e., after STO expired), but not duplicate interests
+ *
+ * Reaction to duplicate interests depends on strategy.
+ *
+ * In case of flooding, this variable should always be empty (it is filled initially with
+ * all avaialble interfaces and then immediately emptied by interest flooding)
+ *
+ * In case of routing strategies, this list will guide (and limit) the local recovery process
+ */
+ list<int> availableInterfaces;
+
+ Message *timerMsg; //the timer message, used to cancel message if data is received
+
+ // Changing PIT removal policy. From now on it will be deleted only when all outgoing
+ // interests are satisfied
+ //
+ // bool dontDeleteOnFirstData; //don't delete when first data packet comes
+ // //(PIT will be deleted only upon timeout or reception data
+ // //packets or prunes for all outgoing interests)
+
+public:
+PitEntry()
+: timerExpired( false )
+, counterExpirations( 0 )
+ , timerMsg( NULL )
+ { }
+
+ inline void fillAvailableInterfacesFromFIB( const FibEntry &fe );
+
+ // Find best candidate, skipping `skip' first candidates (modulo availableInterfaces.size())
+ // !!! assert( availableInterfaces.size()>0 ) !!!
+ inline int findBestCandidate( int skip = 0 );
+
+ // Get number of outgoing interests that we're expecting data from
+ inline size_t numberOfPromisingInterests( ) const;
+};
+
+typedef string_key_hash_t<PitEntry>::point_iterator PitIterator;
+typedef string_key_hash_t<PitEntry>::iterator PitRangeIterator;
+
+typedef list<PitIncomingInterest>::iterator PitIncomingIterator;
+typedef list<PitOutgoingInterest>::iterator PitOutgoingIterator;
+typedef list<PitOutgoingInterest>::const_iterator PitOutgoingConstIterator;
+
+typedef map<int,int> PitCounter;
+typedef map<int,int>::iterator PitCounterIterator;
+
+typedef map<int,double> PitBucket;
+typedef map<int,double>::iterator PitBucketIterator;
+
+
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+
+// class implementing Pending Interests Table
+class CcnxPit
+{
+ public:
+ /**
+ * PIT constructor
+ */
+ CcnxPit( Ccnx &node );
+ virtual ~CcnxPit( );
+
+ //Find corresponding PIT entry for the given content name
+ PitIterator lookup( const string &prefix );
+ bool isValid( const PitIterator &it ) { return it!=_pit.end(); }
+
+ inline PitIncomingIterator findIncoming( PitEntry &pe, int interfaceIndex );
+ inline bool isValid( PitEntry &pe, PitIncomingIterator it );
+ inline PitOutgoingIterator findOutgoing( PitEntry &pe, int interfaceIndex );
+ inline bool isValid( PitEntry &pe, PitOutgoingIterator it );
+
+ // Add a new PIT entry and a correspondent new incoming interest
+ bool add( const string &contentName, const PitIncomingInterest &interest );
+
+ // Add a new outgoing interest
+ int add( PitEntry &pe, const PitOutgoingInterest &interest );
+
+ // remove a PIT entry
+ void erase( const string &contentName );
+
+ // inline bool InterestAlreadyForwarded( PitEntry &pe, int interfaceIndex );
+
+ // Remove expired records from PIT
+ void cleanExpired( clocktype time );
+
+ // Dump content store entries
+ void dump( );
+
+ // Reset pending state in outgoing interests
+ void resetPendingState( PitEntry &pe );
+
+ // // Check if there are any interfaces that we haven't sent data to yet
+ // bool areFreeInterfaces( PitEntry &pe, int interface );
+
+ // Periodically generate pre-calculated number of tokens (leak buckets)
+ void leakBuckets( );
+
+ // Selectively leak a bucket
+ void leakBucket( int interface, int amount );
+
+ // Delete incoming interest for the interface
+ bool deleteIncomingInterest( PitEntry &pe, int interfaceIndex );
+
+ // Remove all incoming interests
+ void deleteAllIncomingInterests( PitEntry &pe );
+
+ public:
+ PitBucket maxBucketsPerInterface; // maximum number of buckets. Automatically computed based on link capacity
+ // averaging over 1 second (bandwidth * 1second)
+ PitBucket leakSize; // size of a periodic bucket leak
+
+ private:
+ bool add( PitEntry &pe, const PitIncomingInterest &interest );
+ void deleteIncomingInterest( PitEntry &pe, PitIncomingIterator it );
+
+ private:
+ Ccnx &_node;
+
+ string_key_hash_t<PitEntry> _pit;
+
+ list<PitExpirationEntry> _pitExpirationList; //list of incoming Interests sorted by expiration time
+
+ PitBucket _bucketsPerInterface; // pending interface counter per interface
+
+ QNThreadMutex _pitMutex; // just to make sure
+};
+
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+
+PitIncomingIterator CcnxPit::findIncoming( PitEntry &pe, int interfaceIndex )
+{
+ return find( pe.incomingInterests.begin( ),
+ pe.incomingInterests.end( ),
+ interfaceIndex );
+}
+
+PitOutgoingIterator CcnxPit::findOutgoing( PitEntry &pe, int interfaceIndex )
+{
+ return find( pe.outgoingInterests.begin( ),
+ pe.outgoingInterests.end( ),
+ interfaceIndex );
+}
+
+bool CcnxPit::isValid( PitEntry &pe, PitIncomingIterator it )
+{
+ return it!=pe.incomingInterests.end( );
+}
+
+bool CcnxPit::isValid( PitEntry &pe, PitOutgoingIterator it )
+{
+ return it!=pe.outgoingInterests.end( );
+}
+
+int PitEntry::findBestCandidate( int skip/* = 0*/ )
+{
+ assert( availableInterfaces.size()>0 );
+
+ skip = skip % availableInterfaces.size();
+ list<int>::iterator candidate = availableInterfaces.begin( );
+ while( skip>0 /* && candidate!=availableInterfaces.end() */ ) { skip--; candidate++; }
+
+ return *candidate;
+}
+
+size_t PitEntry::numberOfPromisingInterests( ) const
+{
+ size_t count = 0;
+
+ for( PitOutgoingConstIterator i = outgoingInterests.begin();
+ i!=outgoingInterests.end();
+ i++ )
+ {
+ if( !i->waitingInVain ) count++;
+ }
+
+ return count;
+}
+
+} // namespace ns3
+
+#endif /* CCNX_PIT_H */