blob: b36b03082ee5da424ca7ba628f0a97284de48e31 [file] [log] [blame]
Zhenkai Zhu0f054122012-12-25 22:22:50 -08001#include "ccnx-tunnel.h"
Zhenkai Zhud4924312012-12-28 11:35:12 -08002#include "ccnx-pco.h"
Zhenkai Zhu0f054122012-12-25 22:22:50 -08003
4namespace Ccnx
5{
6
7CcnxTunnel::CcnxTunnel()
8 : CcnxWrapper()
9 , m_localPrefix("/")
10{
11 refreshLocalPrefix();
12}
13
14CcnxTunnel::~CcnxTunnel()
15{
16}
17
Zhenkai Zhud4924312012-12-28 11:35:12 -080018void
Zhenkai Zhu0f054122012-12-25 22:22:50 -080019CcnxTunnel::refreshLocalPrefix()
20{
21 string newPrefix = getLocalPrefix();
22 if (!newPrefix.empty() && m_localPrefix != newPrefix)
23 {
24 CcnxWrapper::clearInterestFilter(m_localPrefix);
25 CcnxWrapper::setInterestFilter(newPrefix, bind(&CcnxTunnel::handleTunneledInterest, this, _1));
26 m_localPrefix = newPrefix;
27 }
28}
29
30int
Zhenkai Zhu9bad2bf2012-12-28 15:31:46 -080031CcnxTunnel::sendInterest (const Interest &interest, Closure *closure)
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -080032{
Zhenkai Zhu9bad2bf2012-12-28 15:31:46 -080033 string strInterest = interest.name();
34 string tunneledInterest = queryRoutableName(strInterest);
35 Closure *cp = new TunnelClosure(closure, this, strInterest);
Zhenkai Zhu974c5a62012-12-28 14:15:30 -080036 sendInterest(tunneledInterest, cp);
Zhenkai Zhud4924312012-12-28 11:35:12 -080037}
38
39void
Zhenkai Zhu974c5a62012-12-28 14:15:30 -080040CcnxTunnel::handleTunneledData(const string &name, const Bytes &tunneledData, const Closure::DataCallback &originalDataCallback)
Zhenkai Zhud4924312012-12-28 11:35:12 -080041{
42 ParsedContentObject pco(tunneledData);
43 originalDataCallback(pco.name(), pco.content());
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -080044}
45
46int
Zhenkai Zhu974c5a62012-12-28 14:15:30 -080047CcnxTunnel::publishData(const string &name, const unsigned char *buf, size_t len, int freshness)
Zhenkai Zhu0f054122012-12-25 22:22:50 -080048{
Zhenkai Zhud4924312012-12-28 11:35:12 -080049 Bytes content = createContentObject(name, buf, len, freshness);
50 storeContentObject(name, content);
Zhenkai Zhu0f054122012-12-25 22:22:50 -080051
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -080052 string tunneledName = m_localPrefix + name;
Zhenkai Zhu974c5a62012-12-28 14:15:30 -080053 Bytes tunneledCo = createContentObject(tunneledName, head(content), content.size(), freshness);
Zhenkai Zhu0f054122012-12-25 22:22:50 -080054
55 return putToCcnd(tunneledCo);
56}
57
58void
Zhenkai Zhud4924312012-12-28 11:35:12 -080059CcnxTunnel::handleTunneledInterest(const string &tunneledInterest)
Zhenkai Zhu0f054122012-12-25 22:22:50 -080060{
61 // The interest must have m_localPrefix as a prefix (component-wise), otherwise ccnd would not deliver it to us
62 string interest = (m_localPrefix == "/")
63 ? tunneledInterest
Zhenkai Zhud4924312012-12-28 11:35:12 -080064 : tunneledInterest.substr(m_localPrefix.size());
Zhenkai Zhu0f054122012-12-25 22:22:50 -080065
66 ReadLock(m_ritLock);
67
68 // This is linear scan, but should be acceptable under the assumption that the caller wouldn't be listening to a lot prefixes (as of now, most app listen to one or two prefixes)
69 for (RitIter it = m_rit.begin(); it != m_rit.end(); it++)
70 {
71 // evoke callback for any prefix that is the prefix of the interest
Zhenkai Zhud4924312012-12-28 11:35:12 -080072 if (isPrefix(it->first, interest))
Zhenkai Zhu0f054122012-12-25 22:22:50 -080073 {
Zhenkai Zhud4924312012-12-28 11:35:12 -080074 (it->second)(interest);
Zhenkai Zhu0f054122012-12-25 22:22:50 -080075 }
76 }
77}
78
79bool
Zhenkai Zhud4924312012-12-28 11:35:12 -080080CcnxTunnel::isPrefix(const string &prefix, const string &name)
Zhenkai Zhu0f054122012-12-25 22:22:50 -080081{
82 // prefix is literally prefix of name
83 if (name.find(prefix) == 0)
84 {
85 // name and prefix are exactly the same, or the next character in name
86 // is '/'; in both case, prefix is the ccnx prefix of name (component-wise)
87 if (name.size() == prefix.size() || name.at(prefix.size()) == '/')
88 {
89 return true;
90 }
91 }
92 return false;
93}
94
95int
96CcnxTunnel::setInterestFilter(const string &prefix, const InterestCallback &interestCallback)
97{
98 WriteLock(m_ritLock);
Zhenkai Zhud4924312012-12-28 11:35:12 -080099 // make sure copy constructor for boost::function works properly
100 m_rit.insert(make_pair(prefix, interestCallback));
Zhenkai Zhu0f054122012-12-25 22:22:50 -0800101 return 0;
102}
103
104void
105CcnxTunnel::clearInterestFilter(const string &prefix)
106{
107 WriteLock(m_ritLock);
108 // remove all
109 m_rit.erase(prefix);
110}
111
Zhenkai Zhu974c5a62012-12-28 14:15:30 -0800112TunnelClosure::TunnelClosure(int retry, const DataCallback &dataCallback, const TimeoutCallback &timeoutCallback, CcnxTunnel *tunnel, const string &originalInterest)
113 : Closure(retry, dataCallback, timeoutCallback)
Zhenkai Zhud4924312012-12-28 11:35:12 -0800114 , m_tunnel(tunnel)
115 , m_originalInterest(originalInterest)
116{
Zhenkai Zhu0f054122012-12-25 22:22:50 -0800117}
118
Zhenkai Zhu974c5a62012-12-28 14:15:30 -0800119TunnelClosure::TunnelClosure(const Closure *closure, CcnxTunnel *tunnel, const string &originalInterest)
120 : Closure(*closure)
121 , m_tunnel(tunnel)
122{
123}
124
Zhenkai Zhud4924312012-12-28 11:35:12 -0800125void
Zhenkai Zhu974c5a62012-12-28 14:15:30 -0800126TunnelClosure::runDataCallback(const string &name, const Bytes &content)
Zhenkai Zhud4924312012-12-28 11:35:12 -0800127{
128 if (m_tunnel != NULL)
129 {
130 m_tunnel->handleTunneledData(name, content, (*m_dataCallback));
131 }
132}
133
Zhenkai Zhu974c5a62012-12-28 14:15:30 -0800134Closure::TimeoutCallbackReturnValue
135TunnelClosure::runTimeoutCallback(const string &interest)
Zhenkai Zhud4924312012-12-28 11:35:12 -0800136{
Zhenkai Zhu974c5a62012-12-28 14:15:30 -0800137 return Closure::runTimeoutCallback(m_originalInterest);
Zhenkai Zhud4924312012-12-28 11:35:12 -0800138}
139
140} // Ccnx