blob: d0e769a110ef7c734aa52f8864d39522e6f18cee [file] [log] [blame]
Alexander Afanasyev181d7e52012-04-09 13:54:11 -07001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2012 University of California, Los Angeles
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
19 * Chaoyi Bian <bcy@pku.edu.cn>
20 * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
21 */
22
23#include "sync-ccnx-wrapper.h"
24#include "sync-log.h"
25#include <boost/throw_exception.hpp>
26#include <boost/date_time/posix_time/posix_time.hpp>
27#include <boost/lambda/lambda.hpp>
28#include <boost/lambda/bind.hpp>
29
30namespace ll = boost::lambda;
31
Alexander Afanasyev86f428c2012-04-22 13:13:08 -070032#include "../evaluation/type-tag.h"
33
Alexander Afanasyev181d7e52012-04-09 13:54:11 -070034#include <ns3/ccnx-name-components.h>
35#include <ns3/ccnx-interest-header.h>
36#include <ns3/ccnx-content-object-header.h>
37#include <ns3/ccnx-face.h>
38#include <ns3/packet.h>
39#include <ns3/ccnx-fib.h>
40
41typedef boost::error_info<struct tag_errmsg, std::string> errmsg_info_str;
42typedef boost::error_info<struct tag_errmsg, int> errmsg_info_int;
43
44using namespace std;
45using namespace boost;
46using namespace ns3;
47
48INIT_LOGGER ("CcnxWrapper");
49
50namespace Sync {
51
52CcnxWrapper::CcnxWrapper()
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -070053 : m_rand (0, std::numeric_limits<uint32_t>::max ())
Alexander Afanasyev181d7e52012-04-09 13:54:11 -070054{
55}
56
57CcnxWrapper::~CcnxWrapper()
58{
59}
60
61void
62CcnxWrapper::StartApplication ()
63{
64 CcnxApp::StartApplication ();
65}
66
67void
68CcnxWrapper::StopApplication ()
69{
70 CcnxApp::StopApplication ();
71}
72
73int
74CcnxWrapper::publishData (const string &dataName, const string &dataBuffer, int freshness)
75{
76 // NS_LOG_INFO ("Requesting Interest: \n" << interestHeader);
77 _LOG_INFO ("> Data for " << dataName);
78
79 Ptr<CcnxNameComponents> name = Create<CcnxNameComponents> ();
80 istringstream is (dataName);
81 is >> *name;
82
83 static CcnxContentObjectTail trailer;
84
85 CcnxContentObjectHeader data;
86 data.SetName (name);
87 data.SetFreshness (Seconds (freshness));
88
89 Ptr<Packet> packet = Create<Packet> (reinterpret_cast<const uint8_t*> (dataBuffer.c_str ()), dataBuffer.size ());
Alexander Afanasyev86f428c2012-04-22 13:13:08 -070090 packet->AddPacketTag (CreateObject<TypeTag> (TypeTag::DATA));
Alexander Afanasyev181d7e52012-04-09 13:54:11 -070091 packet->AddHeader (data);
92 packet->AddTrailer (trailer);
93
94 m_protocolHandler (packet);
95
96 m_transmittedContentObjects (&data, packet, this, m_face);
97
98 return 0;
99}
100
101int CcnxWrapper::sendInterest (const string &strInterest, const DataCallback &dataCallback)
102{
103 // NS_LOG_INFO ("Requesting Interest: \n" << interestHeader);
104 _LOG_INFO ("> Interest for " << strInterest);
105
106 Ptr<CcnxNameComponents> name = Create<CcnxNameComponents> ();
107 istringstream is (strInterest);
108 is >> *name;
109
110 CcnxInterestHeader interestHeader;
Alexander Afanasyev0ac399e2012-04-27 13:28:28 -0700111 uint32_t nonce = m_rand.GetValue ();
112 _LOG_DEBUG ("Nonce: " << nonce);
113 interestHeader.SetNonce (nonce);
Alexander Afanasyev181d7e52012-04-09 13:54:11 -0700114 interestHeader.SetName (name);
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700115 interestHeader.SetInterestLifetime (Seconds (9.9)); // really long-lived interests
Alexander Afanasyev181d7e52012-04-09 13:54:11 -0700116
117 Ptr<Packet> packet = Create<Packet> ();
Alexander Afanasyev86f428c2012-04-22 13:13:08 -0700118 packet->AddPacketTag (CreateObject<TypeTag> (TypeTag::INTEREST));
Alexander Afanasyev181d7e52012-04-09 13:54:11 -0700119 packet->AddHeader (interestHeader);
120
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700121 // NS_LOG_DEBUG (interestHeader);
122
Alexander Afanasyev181d7e52012-04-09 13:54:11 -0700123 m_protocolHandler (packet);
124
125 m_transmittedInterests (&interestHeader, this, m_face);
126
127 // Record the callback
128 CcnxFilterEntryContainer<DataCallback>::type::iterator entry = m_dataCallbacks.find (*name);
129 if (entry == m_dataCallbacks.end ())
130 {
131 pair<CcnxFilterEntryContainer<DataCallback>::type::iterator, bool> status =
132 m_dataCallbacks.insert (CcnxFilterEntry<DataCallback> (name));
133
134 entry = status.first;
135 }
136 m_dataCallbacks.modify (entry, ll::bind (&CcnxFilterEntry<DataCallback>::AddCallback, ll::_1, dataCallback));
137
138 return 0;
139}
140
141int CcnxWrapper::setInterestFilter (const string &prefix, const InterestCallback &interestCallback)
142{
143 Ptr<CcnxNameComponents> name = Create<CcnxNameComponents> ();
144 istringstream is (prefix);
145 is >> *name;
146
147 CcnxFilterEntryContainer<InterestCallback>::type::iterator entry = m_interestCallbacks.find (*name);
148 if (entry == m_interestCallbacks.end ())
149 {
150 pair<CcnxFilterEntryContainer<InterestCallback>::type::iterator, bool> status =
151 m_interestCallbacks.insert (CcnxFilterEntry<InterestCallback> (name));
152
153 entry = status.first;
154 }
155
156 m_interestCallbacks.modify (entry, ll::bind (&CcnxFilterEntry<InterestCallback>::AddCallback, ll::_1, interestCallback));
157
158 // creating actual face
159
160 Ptr<CcnxFib> fib = GetNode ()->GetObject<CcnxFib> ();
161 CcnxFibEntryContainer::type::iterator fibEntry = fib->Add (*name, m_face, 0);
162
163 // make face green, so it will be used primarily
164 fib->m_fib.modify (fibEntry,
165 ll::bind (&CcnxFibEntry::UpdateStatus,
166 ll::_1, m_face, CcnxFibFaceMetric::NDN_FIB_GREEN));
167
168 return 0;
169}
170
171void
172CcnxWrapper::clearInterestFilter (const std::string &prefix)
173{
174 Ptr<CcnxNameComponents> name = Create<CcnxNameComponents> ();
175 istringstream is (prefix);
176 is >> *name;
177
178 CcnxFilterEntryContainer<InterestCallback>::type::iterator entry = m_interestCallbacks.find (*name);
179 if (entry == m_interestCallbacks.end ())
180 return;
181
182 m_interestCallbacks.modify (entry, ll::bind (&CcnxFilterEntry<InterestCallback>::ClearCallback, ll::_1));
183}
184
185CcnxFilterEntryContainer<CcnxWrapper::InterestCallback>::type::iterator
186CcnxWrapper::InterestCallbackLookup (const ns3::CcnxNameComponents &name)
187{
188 CcnxFilterEntryContainer<InterestCallback>::type::iterator entry = m_interestCallbacks.end ();
189
190 // do the longest prefix match
191 for (size_t componentsCount = name.GetComponents ().size ()+1;
192 componentsCount > 0;
193 componentsCount--)
194 {
195 CcnxNameComponents subPrefix (name.GetSubComponents (componentsCount-1));
196
197 entry = m_interestCallbacks.find (subPrefix);
198 if (entry != m_interestCallbacks.end())
199 return entry;
200 }
201
202 return entry;
203}
204
205CcnxFilterEntryContainer<CcnxWrapper::DataCallback>::type::iterator
206CcnxWrapper::DataCallbackLookup (const ns3::CcnxNameComponents &name)
207{
208 CcnxFilterEntryContainer<DataCallback>::type::iterator entry = m_dataCallbacks.end ();
209
210 // do the longest prefix match
211 for (size_t componentsCount = name.GetComponents ().size ()+1;
212 componentsCount > 0;
213 componentsCount--)
214 {
215 CcnxNameComponents subPrefix (name.GetSubComponents (componentsCount-1));
216
217 entry = m_dataCallbacks.find (subPrefix);
218 if (entry != m_dataCallbacks.end())
219 return entry;
220 }
221
222 return entry;
223}
224
225void
226CcnxWrapper::OnInterest (const Ptr<const CcnxInterestHeader> &interest, Ptr<Packet> packet)
227{
228 CcnxApp::OnInterest (interest, packet);
229
230 CcnxFilterEntryContainer<InterestCallback>::type::iterator entry = InterestCallbackLookup (interest->GetName ());
231 if (entry == m_interestCallbacks.end ())
232 {
233 _LOG_DEBUG ("No Interest callback set");
234 return;
235 }
236
237 entry->m_callback (lexical_cast<string> (interest->GetName ()));
238}
239
240void
241CcnxWrapper::OnContentObject (const Ptr<const CcnxContentObjectHeader> &contentObject,
242 Ptr<Packet> payload)
243{
244 CcnxApp::OnContentObject (contentObject, payload);
245
246 CcnxFilterEntryContainer<DataCallback>::type::iterator entry = DataCallbackLookup (contentObject->GetName ());
247 if (entry == m_dataCallbacks.end ())
248 {
249 _LOG_DEBUG ("No Data callback set");
250 return;
251 }
252
253 ostringstream content;
254 payload->CopyData (&content, payload->GetSize ());
255
256 entry->m_callback (lexical_cast<string> (contentObject->GetName ()), content.str ());
257
258 // i guess it make sense to remove callback when interest is satisfied
259 m_dataCallbacks.erase (entry);
260}
261
262
263}