First steps in CCNx packet coding. ccnx_encode* routines rewritten in NS3 style (using NS3::Buffer)

diff --git a/in-progress/ccnx-contentstore.cc b/in-progress/ccnx-contentstore.cc
new file mode 100644
index 0000000..61d6452
--- /dev/null
+++ b/in-progress/ccnx-contentstore.cc
@@ -0,0 +1,123 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * 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: Ilya Moiseenko <iliamo@cs.ucla.edu>
+ */
+
+#include "ndn_contentstore.h"
+
+namespace ns3
+{
+namespace NDNabstraction
+{
+    
+ContentStore::ContentStore( int maxSize )
+: m_maxSize(maxSize) { }
+
+
+ContentStore::~ContentStore( ) 
+{ }
+
+//Find corresponding CS entry for the given content name
+CsEntry* 
+ContentStore::Lookup(const char *prefix )
+{
+	CriticalSection section(m_csMutex);
+    
+    struct CsEntry *result = NULL;
+    
+    HASH_FIND_STR (m_contentStore, prefix, result);
+    
+    if(result != NULL)
+        Promote (*result);
+    
+	return result;
+}
+
+
+
+//Add entry to content store, if content store is full, use LRU replacement
+void 
+ContentStore::Add( const char *contentName, int contentSize )
+{
+    CriticalSection section(m_csMutex);
+    
+    // removing the old record
+    struct CsEntry *tmp = NULL;
+    HASH_FIND_STR (m_contentStore, contentName, tmp);
+    HASH_DELETE (hh, m_contentStore,tmp);
+    //free(tmp);
+    
+    int size = (int)HASH_COUNT(m_contentStore);
+    
+	if(size == m_maxSize )
+	{
+		CsEntry *entry = m_LRU.back();
+        HASH_DELETE (hh, m_contentStore,entry);//_cs.erase( entry->contentName );
+		m_LRU.pop_back( );
+	}
+    
+	struct CsEntry *ce = (struct CsEntry*)malloc(sizeof(struct CsEntry));
+	ce->contentName = (char*)contentName;
+	ce->contentSize = contentSize;
+    
+	//_cs[ contentName ] = ce;
+    HASH_ADD_KEYPTR (hh, m_contentStore, ce->contentName, strlen(ce->contentName), ce);
+    
+	//CsEntry *ce_in_hash = &(_cs[ contentName ]);
+    struct CsEntry *ce_in_hash = NULL;
+    HASH_FIND_STR (m_contentStore, contentName, ce_in_hash);
+	m_LRU.push_front( ce_in_hash );
+	ce_in_hash->lruPosition = m_LRU.begin( );
+}
+
+
+//move the given CS entry to the head of the list
+void 
+ContentStore::Promote(CsEntry &ce )
+{
+	// should not lock mutex. Otherwise deadlocks will be welcome
+	if( m_LRU.front() == &ce ) return;
+    
+	//assert( *(ce.lruPosition)==&ce ); // should point to the same object
+    
+	// swaping positions in _lru
+	m_LRU.erase( ce.lruPosition );
+	m_LRU.push_front( &ce );
+	ce.lruPosition = m_LRU.begin( );
+    
+	//assert( *(ce.lruPosition)==&ce ); // should point to the same object
+}
+
+void 
+ContentStore::Dump()
+{
+	CriticalSection section(m_csMutex);
+    
+    struct CsEntry *s, *tmp;
+    
+    HASH_ITER(hh, m_contentStore, s, tmp) 
+    {
+        printf("-%s-", s->contentName);
+        /* ... it is safe to delete and free s here */
+    }
+    
+    printf("\n");
+    
+}
+}
+}
diff --git a/in-progress/ccnx-contentstore.h b/in-progress/ccnx-contentstore.h
new file mode 100644
index 0000000..7e49fb6
--- /dev/null
+++ b/in-progress/ccnx-contentstore.h
@@ -0,0 +1,83 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * 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: Ilya Moiseenko <iliamo@cs.ucla.edu>
+ */
+
+#ifndef ndn_contentstore_h
+#define	ndn_contentstore_h
+
+#include <ns3/system-mutex.h>
+#include <list>
+#include <string>
+#include "uthash.h"
+
+using namespace std;
+
+//size of content store
+#define NDN_CONTENT_STORE_SIZE 100
+
+namespace  ns3
+{
+namespace NDNabstraction
+{
+    
+class CsEntry;
+typedef list<CsEntry*>::iterator CsLruIterator;
+    
+//structure for CS entry
+struct CsEntry
+{
+    char *contentName;
+    int contentSize;
+    
+	CsLruIterator lruPosition;
+    UT_hash_handle hh;         /* makes this structure hashable */
+};
+
+
+class ContentStore
+{
+public:
+	ContentStore( int max_size=NDN_CONTENT_STORE_SIZE );
+	virtual ~ContentStore( );
+    
+	// Find corresponding CS entry for the given content name
+	CsEntry* Lookup( const char *prefix );
+	//bool isValid( const CsIterator &it ) { return it!=_cs.end(); }
+	
+	// Add new content to the content store. Old content will be replaced
+	void Add( const char *contentName, int contentSize );
+    
+	// Dump content store entries
+	void Dump( );
+    
+protected:
+	//move the given CS entry to the head of the list
+	void Promote( CsEntry &entry );
+    
+private:
+	int                   m_maxSize; // maximum number of entries in cache
+    
+    struct CsEntry  *m_contentStore;     // actual content store
+	list<CsEntry*>			  m_LRU;	// LRU index of the content store
+	SystemMutex				m_csMutex;   // just to make sure we are not
+};
+    
+}
+}
+#endif
diff --git a/in-progress/ccnx-cs.cpp b/in-progress/ccnx-cs.cpp
new file mode 100644
index 0000000..c102cd5
--- /dev/null
+++ b/in-progress/ccnx-cs.cpp
@@ -0,0 +1,90 @@
+/* 
+ * File:   ndn_cs.cpp
+ * Author: cawka
+ * 
+ * Created on December 15, 2010, 2:17 PM
+ */
+
+#include "ndn_cs.h"
+
+NdnCs::NdnCs( int maxSize )
+: _maxSize(maxSize) { }
+
+//NdnCs::NdnCs( constNdnCs& orig ) { }
+
+NdnCs::~NdnCs( ) { }
+
+//Find corresponding CS entry for the given content name
+CsIterator NdnCs::lookup( const string &prefix )
+{
+	QNThreadLock lock( &_csMutex );
+
+	CsIterator entry=_cs.find( prefix );
+	if( entry!=_cs.end() ) promote( entry->second );
+	return entry;
+}
+
+
+
+//Add entry to content store, if content store is full, use LRU replacement
+void NdnCs::add( const string &contentName, int contentSize )
+{
+	QNThreadLock lock( &_csMutex );
+
+	_cs.erase( contentName ); // removing the old record
+
+	if( _cs.size()==_maxSize )
+	{
+		CsEntry *entry=_lru.back();
+		_cs.erase( entry->contentName );
+		_lru.pop_back( );
+	}
+
+	CsEntry ce;
+	ce.contentName = contentName;
+	ce.contentSize = contentSize;
+
+	_cs[ contentName ] = ce;
+
+	CsEntry *ce_in_hash = &(_cs[ contentName ]);
+	_lru.push_front( ce_in_hash );
+	ce_in_hash->lruPosition = _lru.begin( );
+}
+
+
+//move the given CS entry to the head of the list
+void NdnCs::promote( CsEntry &ce )
+{
+	// should not lock mutex. Otherwise deadlocks will be welcome
+	if( _lru.front() == &ce ) return;
+
+	assert( *(ce.lruPosition)==&ce ); // should point to the same object
+
+	// swaping positions in _lru
+	_lru.erase( ce.lruPosition );
+	_lru.push_front( &ce );
+	ce.lruPosition = _lru.begin( );
+
+	assert( *(ce.lruPosition)==&ce ); // should point to the same object
+}
+
+void NdnCs::dump()
+{
+	QNThreadLock lock( &_csMutex );
+
+	for( CsRangeIterator it=_cs.begin(); it!=_cs.end(); ++it )
+	{
+		printf("-%s-", it->second.contentName.c_str() );
+	}
+
+    printf("\n");
+//    list<CsEntry *>::reverse_iterator rit;
+//
+//    for (rit = contentList->rbegin(); rit != contentList->rend(); rit ++)
+//    {
+//        temp = *rit;
+//        printf("=%s=", temp->contentName);
+//    }
+//
+//    printf("\n");
+}
diff --git a/in-progress/ccnx-cs.h b/in-progress/ccnx-cs.h
new file mode 100644
index 0000000..096b0c0
--- /dev/null
+++ b/in-progress/ccnx-cs.h
@@ -0,0 +1,65 @@
+/* 
+ * File:   ndn_cs.h
+ * Author: cawka
+ *
+ * Created on December 15, 2010, 2:17 PM
+ */
+
+#ifndef NDN_CS_H
+#define	NDN_CS_H
+
+#include "ndn_common.h"
+#include "hash_helper.h"
+#include <qualnet_mutex.h>
+#include <list>
+#include <string>
+
+using namespace std;
+
+class CsEntry;
+typedef list<CsEntry*>::iterator CsLruIterator;
+
+//structure for CS entry
+struct CsEntry
+{
+    string contentName;
+    int contentSize;
+
+	CsLruIterator lruPosition;
+};
+
+typedef string_key_hash_t<CsEntry>::point_iterator CsIterator;
+typedef string_key_hash_t<CsEntry>::iterator CsRangeIterator;
+
+// class implementing NDN content store
+class NdnCs
+{
+public:
+	NdnCs( int max_size=NDN_CONTENT_STORE_SIZE );
+	virtual ~NdnCs( );
+
+	// Find corresponding CS entry for the given content name
+	CsIterator lookup( const string &prefix );
+	bool isValid( const CsIterator &it ) { return it!=_cs.end(); }
+	
+	// Add new content to the content store. Old content will be replaced
+	void add( const string &contentName, int contentSize );
+
+	// Dump content store entries
+	void dump( );
+
+protected:
+	//move the given CS entry to the head of the list
+	void promote( CsEntry &entry );
+
+private:
+	int							_maxSize; // maximum number of entries in cache
+
+	string_key_hash_t<CsEntry>	_cs;	// actual content store
+
+	list<CsEntry*>				_lru;	// LRU index of the content store
+	QNThreadMutex				_csMutex; // just to make sure we are not
+										  // getting problems with multiple threads
+};
+
+#endif	/* NDN_CS_H */
diff --git a/in-progress/ccnx-fib.cpp b/in-progress/ccnx-fib.cpp
new file mode 100644
index 0000000..a8adbd0
--- /dev/null
+++ b/in-progress/ccnx-fib.cpp
@@ -0,0 +1,300 @@
+/* 
+ * File:   ndn_fib.cpp
+ * Author: cawka
+ * 
+ * Created on December 15, 2010, 1:54 PM
+ */
+
+#include "ndn.h"
+#include "ndn_fib.h"
+
+#include <node.h>
+#include <buffer.h>
+#include <network_ip.h>
+#include <partition.h>
+#include <routing_ospfv2.h>
+#include <routing_bgp.h>
+
+//#define NDN_DEBUG_OSPF	0
+//#define NDN_DEBUG_OSPF_NODES 0
+
+//#define NDN_DUMP_FIB		0
+
+
+NdnFib::NdnFib( Ndn &node ) : _node(node) { }
+
+NdnFib::~NdnFib( ) { }
+
+
+//Find corresponding FIB entry for the given content name
+//Longest match is performed
+FibIterator NdnFib::lookup( const string &name )
+{
+	string prefix=name;
+
+	FibIterator entry;
+	do
+	{
+		entry=_fib.find( prefix );
+
+		prefix = GetLongestNamePrefix( prefix );
+	} while( !isValid(entry) && prefix.size()>0 );
+
+	return entry;
+}
+
+bool NdnFibNexthopSorter::operator()( const FibNexthop &first, const FibNexthop &second )
+{
+	// Right now is a very simple logic.
+	// Probably this logic should be changed later
+	if( first. cost==NETWORK_UNREACHABLE && second.cost>=0 ) return false;
+	if( second.cost==NETWORK_UNREACHABLE && first. cost>=0 ) return true;
+	return  first.cost < second.cost;
+}
+
+/**
+ * Update FIB entry
+ * If the entry exists, metric will be updated. Otherwise, new entry will be created
+ * 
+ * @param name				Prefix
+ * @param interfaceIndex	Forwarding interface
+ * @param metric			Routing metric
+ * @param nextHop			Nexthop node address (IPv4)
+ * @return true if a new entry created, false otherwise
+ */
+bool NdnFib::update( const string &name, int interfaceIndex, int metric, NodeAddress nextHop )
+{
+	FibIterator entry = _fib.find( name );
+	if( isValid(entry) )
+	{
+		FibNexthopIterator nh = VALUE(entry).findNexthop( interfaceIndex );
+
+		if( !VALUE(entry).isValid(nh) )
+		{
+			nh = VALUE(entry).forwardingList.insert( VALUE(entry).forwardingList.begin(),
+											 FibNexthop(interfaceIndex,nextHop,metric) );
+		}
+		else
+		{
+			nh->cost = metric;
+			nh->nextHop = nextHop;
+		}
+
+		VALUE(entry).forwardingList.sort( NdnFibNexthopSorter() );
+
+		return false;
+	}
+
+	FibEntry &new_entry = _fib[name];
+	new_entry.forwardingList.push_back( FibNexthop(interfaceIndex,nextHop,metric) );
+
+	for( int interface=0; interface < _node.getNode()->numberInterfaces; interface++ )
+	{
+		NodeAddress src = NetworkIpGetInterfaceAddress( _node.getNode(), interface );
+
+		if( isValidLink(src) && interface!=interfaceIndex )
+		{
+			new_entry.forwardingList.push_back( FibNexthop(interface,0,NETWORK_UNREACHABLE) );
+		}
+	}
+
+	return true;
+}
+
+// helper for update call
+bool NdnFib::update( NodeAddress nodeId, int metric, NodeAddress nextHop )
+{
+	ostringstream os;
+	os << (int)nodeId;
+
+	int interface = NetworkIpGetInterfaceIndexForNextHop( _node.getNode(), nextHop );
+
+	return update( os.str(), interface, metric, nextHop );
+}
+
+// helper for update call
+bool NdnFib::update( NodeAddress nodeId, int interfaceIndex, int metric, NodeAddress nextHop )
+{
+	ostringstream os;
+	os << (int)nodeId;
+
+	int interface = NetworkIpGetInterfaceIndexForNextHop( _node.getNode(), nextHop );
+
+	return update( os.str(), interface, metric, nextHop ); //unknown metric
+}
+
+/**
+ * Invalidate entries in FIB
+ */
+void NdnFib::invalidate( )
+{
+	for( FibRangeIterator fib=_fib.begin(); fib!=_fib.end(); fib++ )
+	{
+		for( FibNexthopIterator nh=VALUE(fib).forwardingList.begin(); nh!=VALUE(fib).forwardingList.end(); nh++ )
+		{
+			nh->cost = NETWORK_UNREACHABLE;
+		}
+	}
+}
+
+//compute and update STO value for Fib Entry (similar to RFC 2988)
+//for now we pick the maximum rto of all forwardings
+void FibEntry::updateSto( )
+{
+    assert( forwardingList.size() > 0 );
+
+    clocktype max = 0;
+
+    for( FibNexthopIterator it = forwardingList.begin();
+		 it != forwardingList.end();
+		 it++ )
+    {
+        clocktype sto = it->srtt + NDN_RTO_K * it->rttvar;
+
+        if( sto > max )
+			max = sto;
+    }
+
+    this->sto = max;
+}
+
+
+/**
+ * Updating FIB using data from OSPF
+ * @param node
+ * @param interface	-2	Invalid OSPF (to purge FIB)
+ *					-1	Normal OSPF
+ *					0-N	SPF was calcylated using only interface `interface'
+ *
+ * @bug	All local networks will always appear in routing table with cost == 1
+ */
+void NdnFib::updateFibFromOSPFv2( int interface )
+{
+    Ospfv2Data* ospf = (Ospfv2Data*)NetworkIpGetRoutingProtocol(_node.getNode(), ROUTING_PROTOCOL_OSPFv2);
+
+	if( interface==-2 ) invalidate( );
+
+#ifdef NDN_DEBUG_OSPF
+	if( interface==-1 ) printf( "Routing/interface costs\n" );
+#endif // NDN_DEBUG_OSPF
+
+#ifdef NDN_DEBUG_OSPF_NODES
+	printf( "-- Node %d (interface %d) --\n", _node.getNode()->nodeId, interface );
+#endif // NDN_DEBUG_OSPF_NODES
+
+    Ospfv2RoutingTableRow* rowPtr = (Ospfv2RoutingTableRow*)
+            BUFFER_GetData(&ospf->routingTable.buffer);
+
+    for (int i = 0; i < ospf->routingTable.numRows; i++)
+    {
+		NodeAddress destNodeId = Ipv4ToNodeId( rowPtr[i].destAddr );
+
+		if( destNodeId!=-1 ) update( destNodeId, rowPtr[i].metric, rowPtr[i].nextHop );
+    }
+
+#ifdef NDN_DUMP_FIB
+	if( interface==-1 ) dump( );
+#endif
+}
+
+void NdnFib::updateFibFromBGP( )
+{
+	BgpData* bgp=(BgpData*)_node.getNode()->appData.exteriorGatewayVar;
+
+	assert( bgp->ip_version == NETWORK_IPV4 );
+
+	invalidate( );
+
+	int i=0;
+	int numEntriesInAdjRibIn=BUFFER_GetCurrentSize( &( bgp->adjRibIn ) )
+			/ sizeof(BgpRoutingInformationBase );
+
+	BgpRoutingInformationBase* adjRibInPtr=(BgpRoutingInformationBase*)
+			BUFFER_GetData( &( bgp->adjRibIn ) );
+
+	for( i=0; i < numEntriesInAdjRibIn; i++ )
+	{
+		assert( adjRibInPtr[i].nextHop.networkType == NETWORK_IPV4 );
+
+		NodeAddress destNodeId = Ipv4ToNodeId( GetIPv4Address(adjRibInPtr[i].destAddress.prefix) );
+
+		if( destNodeId!=-1 && adjRibInPtr[i].isValid != FALSE )
+		{
+			char destNodeStr[NDN_MAX_NAME_LENGTH];
+			memset(destNodeStr, 0, NDN_MAX_NAME_LENGTH);
+			sprintf(destNodeStr, "%d", destNodeId);
+
+			update( destNodeId,
+					adjRibInPtr[i].asPathList->pathSegmentLength / 2,
+					GetIPv4Address(adjRibInPtr[i].nextHop) );
+		}
+	}
+
+#ifdef NDN_DUMP_FIB
+	dump( );
+#endif
+}
+
+void NdnFib::updateFibFromIpRouting( )
+{
+	invalidate( );
+
+	for (int i = 0; i < _node.getNode()->partitionData->numNodes; i ++)
+    {
+		if( !_node.getNode()->networkData.networkVar->ndnEnabled ) continue;
+
+        NodeAddress destNode = _node.getNode()->partitionData->nodeData[i]->nodeId;
+		NodeAddress ipv4subnet = NodeIdToIpv4( destNode );
+
+		int interfaceIndex;
+		NodeAddress nextHopAddr;
+        NetworkGetInterfaceAndNextHopFromForwardingTable(
+			_node.getNode(), ipv4subnet, &interfaceIndex, &nextHopAddr );
+
+        if( interfaceIndex != NETWORK_UNREACHABLE )
+        {
+			update( destNode, interfaceIndex, 1, nextHopAddr );
+        }
+    }
+}
+
+
+
+void NdnFib::dump( )
+{
+	if( _node.getNode()->numberInterfaces==1 ) return;  // do not dump FIB for `virtual' nodes
+
+	printf( "Node %s: FIB\n", _node.getPrefix().c_str() );
+	printf( "  Dest prefix      Interfaces(Costs)                  \n" );
+	printf( "+-------------+--------------------------------------+\n" );
+
+	for( FibRangeIterator fib=_fib.begin(); fib!=_fib.end(); fib++ )
+	{
+		dump( fib );
+	}
+}
+
+void NdnFib::dump( const FibIterator &fib )
+{
+	printf( " %8s ", fib->first.c_str() );
+	for( FibNexthopIterator nh=VALUE(fib).forwardingList.begin(); nh!=VALUE(fib).forwardingList.end(); nh++ )
+	{
+		if( nh!=VALUE(fib).forwardingList.begin() ) printf( "," );
+		printf( "i%d(%d)", nh->interfaceIndex, nh->cost );
+	}
+	printf( "\n" );
+}
+
+void NdnFib::resetProbing()
+{
+    for(FibRangeIterator fib = _fib.begin(); fib != _fib.end(); fib++)
+        VALUE(fib).needsProbing = true;
+}
+
+void NdnFib::updateInterfaceStatus( int interface, int status )
+{
+	for( FibRangeIterator fib = _fib.begin(); fib!=_fib.end(); fib++ )
+	{
+		VALUE(fib).updateStatus( interface, status );
+	}
+}
\ No newline at end of file
diff --git a/in-progress/ccnx-fib.h b/in-progress/ccnx-fib.h
new file mode 100644
index 0000000..9a1c3d6
--- /dev/null
+++ b/in-progress/ccnx-fib.h
@@ -0,0 +1,193 @@
+/* 
+ * File:   ndn_fib.h
+ * Author: cawka
+ *
+ * Created on December 15, 2010, 1:54 PM
+ */
+
+#ifndef NDN_FIB_H
+#define	NDN_FIB_H
+
+#include "hash_helper.h"
+#include <clock.h>
+#include <main.h>
+
+class Ndn;
+
+const int NDN_FIB_GREEN = 1;
+const int NDN_FIB_YELLOW = 2;
+const int NDN_FIB_RED = 3;
+
+//structure for Fib outgoing interface
+struct FibNexthop
+{
+    int interfaceIndex;     //interface index of the node
+	NodeAddress nextHop;	//next-hop
+	int cost;				//routing protocol cost to route an interest via this interface
+    int packetCount;        //record the number of packets forwarded using this interface
+
+	clocktype srtt;         //smoothed round-trip time
+    clocktype rttvar;       //round-trip time variation
+	
+	int status;				// Status of the next hop: 
+							//		- #NDN_FIB_GREEN
+							//		- #NDN_FIB_YELLOW
+							//		- #NDN_FIB_RED
+
+	bool operator==( int interface ) const { return interfaceIndex==interface; }
+	FibNexthop( ) {}
+	FibNexthop( int _interface, int _nextHop, int _cost )
+			: interfaceIndex(_interface), nextHop(_nextHop), cost(_cost)
+			, packetCount(1), srtt(0), rttvar(0), status(NDN_FIB_YELLOW) { }
+};
+
+typedef list<FibNexthop>::iterator FibNexthopIterator;
+typedef list<FibNexthop>::const_iterator FibNexthopConstIterator;
+
+//structure for FIB table entry
+struct FibEntry
+{
+    list<FibNexthop> forwardingList;
+    clocktype sto;	  //retransmission time out
+
+	bool needsProbing;      //set to true when probing timer goes out
+
+	FibEntry( ) : sto(0), needsProbing(false) { }
+
+	// Find nexthop record
+	inline FibNexthopIterator findNexthop( int interfaceIndex );
+	bool isValid( const FibNexthopIterator &nh )
+		{ return nh!=forwardingList.end(); }
+
+	// Compute and update RTO value for Fib Entry (RFC 2988)
+	// (for now we pick the maximum RTO of all forwardings)
+	void updateSto( );
+	
+	// Update status of FIB next hop
+	inline void updateStatus( int interface, int status );
+};
+
+typedef string_key_hash_t<FibEntry>::point_iterator FibIterator;
+typedef string_key_hash_t<FibEntry>::iterator FibRangeIterator;
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+// Class implementing FIB functionality
+class NdnFib
+{
+public:
+	NdnFib( Ndn &node );
+	virtual ~NdnFib( );
+
+	// Invalidate entries in FIB
+	// Will leave FIB records in hash, but assign metric=NETWORK_UNREACHABLE
+	void invalidate( );
+
+	//Find corresponding FIB entry for the given content name
+	//Longest match is performed
+	FibIterator lookup( const string &name );
+	bool isValid( const FibIterator &it ) { return it!=_fib.end(); }
+
+	/**
+	 * Update FIB entry
+	 * If the entry exists, metric will be updated. Otherwise, new entry will be created
+	 *
+	 * Entries in FIB never deleted. They can be invalidated with metric==NETWORK_UNREACHABLE
+	 *
+	 * @param name				Prefix
+	 * @param interfaceIndex	Forwarding interface
+	 * @param metric			Routing metric
+	 * @param nextHop			Nexthop node address (IPv4)
+	 * @return true if a new entry created, false otherwise
+	 */
+	bool update( const string &name, int interfaceIndex, int metric, NodeAddress nextHop );
+	bool update( NodeAddress nodeId, int interfaceIndex, int metric, NodeAddress nextHop );
+	bool update( NodeAddress nodeId, int metric, NodeAddress nextHop );
+
+	// Update Fib from OSPF routing table (through a hack in OSPF algorithm)
+	void updateFibFromOSPFv2( int interface );
+
+	// Update Fib from BGP routing table (using info from RibIn)
+	void updateFibFromBGP( );
+
+	// Update Fib from IP routing table
+	void updateFibFromIpRouting( );
+
+	// Update the status for all FIB records for the specified interface
+	void updateInterfaceStatus( int interface, int status );
+	
+	void dump( );
+	void dump( const FibIterator &fib );
+
+    void resetProbing();    //reset needsProbing field for every FibEntry
+private:
+
+private:
+	Ndn &_node;
+
+	string_key_hash_t<FibEntry> _fib;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+class NdnFibNexthopSorter
+{
+public:
+	bool operator()( const FibNexthop &first, const FibNexthop &second );
+};
+
+FibNexthopIterator FibEntry::findNexthop( int interfaceIndex )
+{
+	return find( forwardingList.begin( ),
+				 forwardingList.end( ),
+				 interfaceIndex );
+}
+
+//inline FibNexthopIterator FibEntry::findBestNexthop( int bestNum, int excludeInterface )
+//{
+//	// First adjust number of available interfaces (to make sure we have correct ranking function)
+//	int num_valid_interfaces = forwardingList.size();
+//	FibNexthopIterator nh;
+//	for( nh=forwardingList.begin(); nh!=forwardingList.end(); nh++ )
+//	{
+//		if( nh->interfaceIndex==excludeInterface ) num_valid_interfaces--;
+//	}
+//
+//	if( num_valid_interfaces==0 ) return forwardingList.end();
+//
+//	bestNum = bestNum % num_valid_interfaces;
+//	int i=0;
+//	for( nh=forwardingList.begin(); nh!=forwardingList.end(); nh++ ) // skip bestNum % size() FIB records
+//	{
+//		if( nh->interfaceIndex==excludeInterface ) continue;
+//		if( i==bestNum ) break;
+//
+//		i++;
+//	}
+//
+//	if( nh!=forwardingList.end() )
+//	{
+//		assert( nh->interfaceIndex!=excludeInterface );
+//// 		printf( "%d best => i%d\n", bestNum, nh->interfaceIndex );
+//	}
+//// 	else
+//// 	{
+//// 		printf( "No other hops available\n" );
+//// 	}
+//
+//
+//	return nh;
+//}
+
+void FibEntry::updateStatus( int interface, int status )
+{
+	FibNexthopIterator nh = findNexthop( interface );
+	if( isValid(nh) )
+	{
+		nh->status = status;
+	}
+}
+
+#endif	/* NDN_FIB_H */
diff --git a/in-progress/ccnx-pit.cpp b/in-progress/ccnx-pit.cpp
new file mode 100644
index 0000000..5d10b90
--- /dev/null
+++ b/in-progress/ccnx-pit.cpp
@@ -0,0 +1,243 @@
+/* -*- 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: 
+//
+
+#include "ccnx-pit.h"
+#include <algorithm>
+
+CcnxPit::CcnxPit( Ccnx &node )
+: _node(node)
+{
+};
+
+CcnxPit::~CcnxPit( ) { }
+
+//Find corresponding CS entry for the given content name
+PitIterator CcnxPit::lookup( const string &prefix )
+{
+	QNThreadLock lock( &_pitMutex );
+
+	PitIterator entry=_pit.find( prefix );
+	return entry;
+}
+
+// add new PIT entry
+bool CcnxPit::add( const string &name, const PitIncomingInterest &interest )
+{
+	QNThreadLock lock( &_pitMutex );
+
+	PitEntry *entry=NULL;
+
+	PitIterator existent_entry = _pit.find( name );
+	if( isValid(existent_entry) )
+	{
+		if( VALUE(existent_entry).timerExpired )
+		{
+			_node.fillAvailableInterfacesInPitEntry( VALUE(existent_entry) );
+		}
+
+		add( VALUE(existent_entry), interest );
+	}
+	else
+	{
+		PitEntry &entry = _pit[ name ];
+		entry.contentName  = name;
+
+		_node.fillAvailableInterfacesInPitEntry( entry );
+
+		add( entry, interest );
+	}
+}
+
+// Remove expired records from PIT
+void CcnxPit::cleanExpired( clocktype time )
+{
+	QNThreadLock lock( &_pitMutex );
+
+    while( !_pitExpirationList.empty() )
+    {
+		PitExpirationIterator entry = _pitExpirationList.begin( );
+
+        if( VALUE(entry)->expireTime <= time )
+        {
+			deleteIncomingInterest( *(KEY(entry)), VALUE(entry)->interfaceIndex );
+
+			// delete entry if all incoming interests expired
+			if( KEY(entry)->incomingInterests.size()==0 )
+			{
+				_pit.erase( KEY(entry)->contentName );
+			}
+        }
+        else
+            break;
+    }
+}
+
+//delete PIT entry
+void CcnxPit::erase( const string &name )
+{
+	// should not call `lookup' method !!!
+	
+	QNThreadLock lock( &_pitMutex );
+
+    PitIterator pe = _pit.find( name );
+	
+	if( !isValid(pe) ) return;
+
+	if( VALUE(pe).timerMsg ) MESSAGE_CancelSelfMsg( _node.getNode(), VALUE(pe).timerMsg );
+
+	PitIncomingIterator it = VALUE(pe).incomingInterests.begin();
+	while( it!=VALUE(pe).incomingInterests.end() )
+	{
+		deleteIncomingInterest( VALUE(pe), it );
+
+		it = VALUE(pe).incomingInterests.begin();
+	}
+
+	resetPendingState( VALUE(pe) );
+
+	_pit.erase( name );
+}
+
+//delete incoming interest from PIT entry
+//return 0 if interest does not exist, 1 otherwise
+bool CcnxPit::deleteIncomingInterest( PitEntry &pe, int interfaceIndex )
+{
+	// should not lock thread !!! Otherwise there will be a deadlock
+    if( pe.incomingInterests.size()==0 ) return false; //nothing to delete. Can happen when duplicate data arrives to the node
+
+    PitIncomingIterator it = findIncoming( pe, interfaceIndex );
+
+	if( !isValid(pe, it) ) return false;
+
+	deleteIncomingInterest( pe, it );
+
+    return true;
+}
+
+void CcnxPit::deleteAllIncomingInterests( PitEntry &pe )
+{
+	PitIncomingIterator it = pe.incomingInterests.begin();
+	while( it!=pe.incomingInterests.end() )
+	{
+		deleteIncomingInterest( pe, it );
+
+		it = pe.incomingInterests.begin();
+	}
+}
+
+void CcnxPit::deleteIncomingInterest( PitEntry &pe, PitIncomingIterator it )
+{
+	assert( KEY(it->expirationPosition)==&pe );
+	assert( VALUE(it->expirationPosition)->interfaceIndex==it->interfaceIndex );
+
+	_pitExpirationList.erase( it->expirationPosition );
+	pe.incomingInterests.erase( it );
+}
+
+//add new incoming interest to PIT entry
+//returns false if interface already exists, true otherwise
+bool CcnxPit::add( PitEntry &pe, const PitIncomingInterest &interest )
+{
+	pe.availableInterfaces.remove( interest.interfaceIndex );
+
+    PitIncomingIterator it=findIncoming( pe, interest.interfaceIndex );
+
+	if( isValid(pe, it) )
+	{
+		//update expiration time
+		it->expireTime = interest.expireTime;
+		it->nonce = interest.nonce;
+
+		//move Interest to the end of the node's Interest list
+		_pitExpirationList.erase( it->expirationPosition );
+		_pitExpirationList.push_back( PitExpirationEntry(&pe,&(*it)) );
+		
+		it->expirationPosition = --_pitExpirationList.end();
+		return false;
+	}
+
+	pe.incomingInterests.push_back( interest );
+	PitIncomingInterest *incoming = &pe.incomingInterests.back();
+
+    //Add to the end of the node's Interest list
+	_pitExpirationList.push_back( PitExpirationEntry(&pe,incoming) );
+	incoming->expirationPosition = -- _pitExpirationList.end();
+
+    return true;
+}
+
+//add new outgoing interest to PIT entry
+//returns false  interface limit reached or interest exists and is still marked as outstanding (nonce will not be changed)
+//		  true otherwise
+int CcnxPit::add( PitEntry &pe, const PitOutgoingInterest &interest )
+{
+	if( _node.isRateLimit && _bucketsPerInterface[interest.interfaceIndex]+1.0 >= maxBucketsPerInterface[interest.interfaceIndex] )
+	{
+//		printf( "DEBUG: bucket overflow. Should not forward anything to interface %d\n", interest.interfaceIndex );
+		return false;
+	}
+
+	_bucketsPerInterface[interest.interfaceIndex] = _bucketsPerInterface[interest.interfaceIndex] + 1.0;
+	pe.availableInterfaces.remove( interest.interfaceIndex );
+
+	PitOutgoingIterator it = findOutgoing(pe, interest.interfaceIndex);
+	if( isValid(pe, it) )
+    {
+		if( it->outstanding ) return false;
+
+        it->retxNum ++;
+        it->nonce = interest.nonce;
+		it->outstanding = true;
+		it->waitingInVain = false;
+    }
+	else
+	{
+		//add to the head of the list
+		pe.outgoingInterests.push_front( interest );
+	}
+	
+    return true;
+}
+
+void CcnxPit::resetPendingState( PitEntry &pe )
+{
+	for( PitOutgoingIterator it = pe.outgoingInterests.begin();
+		 it != pe.outgoingInterests.end();
+		 it++ )
+	{
+		it->outstanding = false;
+	}
+}
+
+void CcnxPit::leakBuckets( )
+{
+	for( PitBucketIterator it=_bucketsPerInterface.begin(); 
+		 it != _bucketsPerInterface.end();
+		 it++ )
+	{
+		it->second = max( 0.0, it->second - leakSize[it->first] );
+	}
+}
+
+void CcnxPit::leakBucket( int interface, int amount )
+{
+	_bucketsPerInterface[interface] = 
+			max( 0.0, _bucketsPerInterface[interface] - amount );
+}
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 */
diff --git a/in-progress/ccnx-rit.cpp b/in-progress/ccnx-rit.cpp
new file mode 100644
index 0000000..b84f9d0
--- /dev/null
+++ b/in-progress/ccnx-rit.cpp
@@ -0,0 +1,64 @@
+/* 
+ * File:   ndn_rit.cpp
+ * Author: cawka
+ * 
+ * Created on December 15, 2010, 2:02 PM
+ */
+
+#include "ndn_rit.h"
+
+NdnRit::NdnRit( ) { }
+
+NdnRit::~NdnRit( ) { }
+
+
+//find corresponding RIT entry for the given nonce
+RitIterator NdnRit::lookup( int nonce )
+{
+	QNThreadLock lock( &_ritMutex );
+
+	RitIterator entry=_rit.find( nonce );
+	return entry;
+}
+
+
+// add new RIT entry
+// returns false if entry already exists, otherwise returns true
+bool NdnRit::add( int nonce, clocktype expire )
+{
+	QNThreadLock lock( &_ritMutex );
+
+	RitIterator entry=_rit.find( nonce );
+	if( isValid(entry) ) return false;
+
+    RitEntry re;
+    re.nonce = nonce;
+	re.expireTime = expire;
+
+	_rit[ nonce ] = re;
+
+	_ritExpirationList.push_back( &(_rit[nonce]) );
+}
+
+
+void NdnRit::cleanExpired( clocktype time )
+{
+	QNThreadLock lock( &_ritMutex );
+
+	while( !_ritExpirationList.empty() )
+    {
+        RitEntry *head = _ritExpirationList.front( );
+
+        if( head->expireTime <= time )
+		{
+			//delete the head RIT entry
+			_rit.erase( head->nonce );
+			_ritExpirationList.pop_front( );
+		}
+        else
+            break;
+    }
+    //printf("Node %d: RIT entries\n", node->nodeId);
+    //PrintRitEntries(ndn->riList);
+}
+
diff --git a/in-progress/ccnx-rit.h b/in-progress/ccnx-rit.h
new file mode 100644
index 0000000..4a03bda
--- /dev/null
+++ b/in-progress/ccnx-rit.h
@@ -0,0 +1,52 @@
+/* 
+ * File:   ndn_rit.h
+ * Author: cawka
+ *
+ * Created on December 15, 2010, 2:02 PM
+ */
+
+#ifndef NDN_RIT_H
+#define	NDN_RIT_H
+
+#include "hash_helper.h"
+#include <qualnet_mutex.h>
+#include <clock.h>
+#include <list>
+using namespace std;
+
+//recent interest
+struct RitEntry
+{
+    int nonce;
+    clocktype expireTime;  //RIT entries will stay in the table for a while before being cleaned out
+};
+
+typedef int_key_hash_t<RitEntry>::point_iterator RitIterator;
+typedef int_key_hash_t<RitEntry>::iterator RitRangeIterator;
+
+class NdnRit
+{
+public:
+	NdnRit( );
+	virtual ~NdnRit( );
+
+	//Find corresponding RIT entry for the given content name
+	RitIterator lookup( int nonce );
+	bool isValid( const RitIterator &it ) { return it!=_rit.end(); }
+
+	//add new RIT entry
+	bool add( int nonce, clocktype expireTime );
+
+	// Delete expired records
+	void cleanExpired( clocktype time );
+	
+private:
+	int_key_hash_t<RitEntry> _rit;
+
+	list<RitEntry*> _ritExpirationList;
+
+	QNThreadMutex   _ritMutex;
+};
+
+#endif	/* NdnRit_H */
+