blob: 4c7cc100cffb3f7235f55b949473a63b4fb7cdd1 [file] [log] [blame]
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -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: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -070019 */
20
21#include "ndn-api-face.h"
Alexander Afanasyev79606062013-07-11 00:57:28 -070022#include "detail/filter-entry.h"
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -070023
Alexander Afanasyev79606062013-07-11 00:57:28 -070024#include <ns3/random-variable.h>
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -070025
Alexander Afanasyev79606062013-07-11 00:57:28 -070026#include <ns3/ndn-l3-protocol.h>
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -070027#include <ns3/ndn-interest.h>
28#include <ns3/ndn-content-object.h>
29#include <ns3/ndn-face.h>
30#include <ns3/ndn-fib.h>
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -070031
Alexander Afanasyev79606062013-07-11 00:57:28 -070032#include <ns3/packet.h>
33#include <ns3/log.h>
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -070034
35using namespace std;
36using namespace boost;
37using namespace ns3;
38
Alexander Afanasyev79606062013-07-11 00:57:28 -070039NS_LOG_COMPONENT_DEFINE ("ndn.ApiFace");
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -070040
41namespace ns3 {
42namespace ndn {
43
Alexander Afanasyev79606062013-07-11 00:57:28 -070044class ApiFacePriv
45{
46public:
47 ApiFacePriv ()
48 : m_rand (0, std::numeric_limits<uint32_t>::max ())
49 {
50 }
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -070051
Alexander Afanasyev79606062013-07-11 00:57:28 -070052 ns3::UniformVariable m_rand; // nonce generator
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -070053
Alexander Afanasyev79606062013-07-11 00:57:28 -070054 FilterEntryContainer<ApiFace::DataCallback, Interest> m_pendingInterests;
55 FilterEntryContainer<ApiFace::InterestCallback, Name> m_expectedInterests;
56};
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -070057
58
Alexander Afanasyev79606062013-07-11 00:57:28 -070059ApiFace::ApiFace (Ptr<Node> node)
60 : Face (node)
61 , m_this (new ApiFacePriv ())
62{
63 NS_ASSERT_MSG (GetNode ()->GetObject<L3Protocol> () != 0,
64 "NDN stack should be installed on the node " << GetNode ());
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -070065
Alexander Afanasyev79606062013-07-11 00:57:28 -070066 GetNode ()->GetObject<L3Protocol> ()->AddFace (this);
67 this->SetUp (true);
68 this->SetFlags (APPLICATION);
69}
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -070070
Alexander Afanasyev79606062013-07-11 00:57:28 -070071ApiFace::~ApiFace ()
72{
73 delete m_this;
74}
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -070075
Alexander Afanasyev79606062013-07-11 00:57:28 -070076void
77ApiFace::ExpressInterest (Ptr<Interest> interest,
78 DataCallback onData,
79 TimeoutCallback onTimeout/* = MakeNullCallback< void, Ptr<Interest> > ()*/)
80{
81 NS_LOG_INFO (">> I " << interest->GetName ());
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -070082
Alexander Afanasyev79606062013-07-11 00:57:28 -070083 if (interest->GetNonce () == 0)
84 {
85 interest->SetNonce (m_this->m_rand.GetValue ());
86 }
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -070087
Alexander Afanasyev79606062013-07-11 00:57:28 -070088 // Record the callback
89 FilterEntryContainer<DataCallback, Interest>::iterator entry =
90 m_this->m_pendingInterests.find_exact (interest->GetName ());
91 if (entry == m_this->m_pendingInterests.end ())
92 {
93 pair<FilterEntryContainer<DataCallback, Interest>::iterator, bool> status =
94 m_this->m_pendingInterests.insert (interest->GetName (), Create< FilterEntry<DataCallback, Interest> > (interest));
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -070095
Alexander Afanasyev79606062013-07-11 00:57:28 -070096 entry = status.first;
97 }
98 entry->payload ()->AddCallback (onData);
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -070099
Alexander Afanasyev79606062013-07-11 00:57:28 -0700100 ReceiveInterest (interest);
101}
102
103void
104ApiFace::SetInterestFilter (Ptr<const Name> prefix, InterestCallback onInterest)
105{
106 NS_LOG_DEBUG ("== setInterestFilter " << *prefix << " (" << GetNode ()->GetId () << ")");
107
108 FilterEntryContainer<InterestCallback, Name>::iterator entry = m_this->m_expectedInterests.find_exact (*prefix);
109 if (entry == m_this->m_expectedInterests.end ())
110 {
111 pair<FilterEntryContainer<InterestCallback, Name>::iterator, bool> status =
112 m_this->m_expectedInterests.insert (*prefix, Create < FilterEntry<InterestCallback, Name> > (prefix));
113
114 entry = status.first;
115 }
116
117 entry->payload ()->AddCallback (onInterest);
118
119 // creating actual face
120 Ptr<ndn::Fib> fib = GetNode ()->GetObject<ndn::Fib> ();
121 Ptr<ndn::fib::Entry> fibEntry = fib->Add (prefix, this, 0);
122 fibEntry->UpdateStatus (this, ndn::fib::FaceMetric::NDN_FIB_GREEN);
123}
124
125void
126ApiFace::ClearInterestFilter (Ptr<const Name> prefix)
127{
128 FilterEntryContainer<InterestCallback, Name>::iterator entry = m_this->m_expectedInterests.find_exact (*prefix);
129 if (entry == m_this->m_expectedInterests.end ())
130 return;
131
132 entry->payload ()->ClearCallback ();
133 m_this->m_expectedInterests.erase (entry);
134}
135
136void
137ApiFace::Put (Ptr<ContentObject> data)
138{
139 NS_LOG_INFO (">> D " << data->GetName ());
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -0700140
Alexander Afanasyev79606062013-07-11 00:57:28 -0700141 ReceiveData (data);
142}
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -0700143
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -0700144
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -0700145
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -0700146
Alexander Afanasyev79606062013-07-11 00:57:28 -0700147///////////////////////////////////////////////
148// private stuff
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -0700149
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -0700150
Alexander Afanasyev79606062013-07-11 00:57:28 -0700151bool
152ApiFace::SendInterest (Ptr<const Interest> interest)
153{
154 NS_LOG_FUNCTION (this << interest);
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -0700155
Alexander Afanasyev79606062013-07-11 00:57:28 -0700156 NS_LOG_DEBUG ("<< I " << interest->GetName ());
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -0700157
Alexander Afanasyev79606062013-07-11 00:57:28 -0700158 if (!IsUp ())
159 {
160 return false;
161 }
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -0700162
Alexander Afanasyev79606062013-07-11 00:57:28 -0700163 // the app cannot set several filters for the same prefix
164 FilterEntryContainer<InterestCallback, Name>::iterator entry =
165 m_this->m_expectedInterests.longest_prefix_match (interest->GetName ());
166 if (entry == m_this->m_expectedInterests.end ())
167 {
168 return false;
169 }
170
171 entry->payload ()->m_callback (entry->payload ()->GetPayload (), interest);
172 return true;
173}
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -0700174
Alexander Afanasyev79606062013-07-11 00:57:28 -0700175bool
176ApiFace::SendData (Ptr<const ContentObject> data)
177{
178 // data has been send out from NDN stack towards the application
179 NS_LOG_DEBUG ("<< D " << data->GetName ());
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -0700180
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -0700181
Alexander Afanasyev79606062013-07-11 00:57:28 -0700182 NS_LOG_FUNCTION (this << data);
183
184 if (!IsUp ())
185 {
186 return false;
187 }
188
189 FilterEntryContainer<DataCallback, Interest>::iterator entry =
190 m_this->m_pendingInterests.longest_prefix_match (data->GetName ());
191 if (entry == m_this->m_pendingInterests.end ())
192 {
193 return false;
194 }
195
196 while (entry != m_this->m_pendingInterests.end ())
197 {
198 entry->payload ()->m_callback (entry->payload ()->GetPayload (), data);
199 m_this->m_pendingInterests.erase (entry);
200
201 entry = m_this->m_pendingInterests.longest_prefix_match (data->GetName ());
202 }
203 m_this->m_pendingInterests.erase (entry);
204
205 return true;
206}
207
208std::ostream&
209ApiFace::Print (std::ostream &os) const
210{
211 os << "dev=ApiFace(" << GetId () << ")";
212 return os;
213}
214
Alexander Afanasyev5bee19e2013-07-10 14:33:57 -0700215
216}
217}