blob: f12e2d50906c3a4e63b6f750e6e2f681ab453aae [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 Zhud4924312012-12-28 11:35:12 -080031CcnxTunnel::sendInterest (const std::string &interest, const DataCallback &dataCallback, int retry, const TimeoutCallback &timeoutCallback)
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -080032{
33 string tunneledInterest = queryRoutableName(interest);
Zhenkai Zhud4924312012-12-28 11:35:12 -080034 ClosurePass *cp = new TunnelClosurePass(retry, dataCallback, timeoutCallback, this, interest);
35 CcnxWrapper::sendInterest(tunneledInterest, cp);
36}
37
38void
39CcnxTunnel::handleTunneledData(const string &name, const Bytes &tunneledData, const DataCallback &originalDataCallback)
40{
41 ParsedContentObject pco(tunneledData);
42 originalDataCallback(pco.name(), pco.content());
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -080043}
44
45int
Zhenkai Zhud4924312012-12-28 11:35:12 -080046CcnxTunnel::publishData(const string &name, const char *buf, size_t len, int freshness)
Zhenkai Zhu0f054122012-12-25 22:22:50 -080047{
Zhenkai Zhud4924312012-12-28 11:35:12 -080048 Bytes content = createContentObject(name, buf, len, freshness);
49 storeContentObject(name, content);
Zhenkai Zhu0f054122012-12-25 22:22:50 -080050
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -080051 string tunneledName = m_localPrefix + name;
Zhenkai Zhud4924312012-12-28 11:35:12 -080052 Bytes tunneledCo = createContentObject(tunneledName, (const char*)&content[0], content.size(), freshness);
Zhenkai Zhu0f054122012-12-25 22:22:50 -080053
54 return putToCcnd(tunneledCo);
55}
56
57void
Zhenkai Zhud4924312012-12-28 11:35:12 -080058CcnxTunnel::handleTunneledInterest(const string &tunneledInterest)
Zhenkai Zhu0f054122012-12-25 22:22:50 -080059{
60 // The interest must have m_localPrefix as a prefix (component-wise), otherwise ccnd would not deliver it to us
61 string interest = (m_localPrefix == "/")
62 ? tunneledInterest
Zhenkai Zhud4924312012-12-28 11:35:12 -080063 : tunneledInterest.substr(m_localPrefix.size());
Zhenkai Zhu0f054122012-12-25 22:22:50 -080064
65 ReadLock(m_ritLock);
66
67 // 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)
68 for (RitIter it = m_rit.begin(); it != m_rit.end(); it++)
69 {
70 // evoke callback for any prefix that is the prefix of the interest
Zhenkai Zhud4924312012-12-28 11:35:12 -080071 if (isPrefix(it->first, interest))
Zhenkai Zhu0f054122012-12-25 22:22:50 -080072 {
Zhenkai Zhud4924312012-12-28 11:35:12 -080073 (it->second)(interest);
Zhenkai Zhu0f054122012-12-25 22:22:50 -080074 }
75 }
76}
77
78bool
Zhenkai Zhud4924312012-12-28 11:35:12 -080079CcnxTunnel::isPrefix(const string &prefix, const string &name)
Zhenkai Zhu0f054122012-12-25 22:22:50 -080080{
81 // prefix is literally prefix of name
82 if (name.find(prefix) == 0)
83 {
84 // name and prefix are exactly the same, or the next character in name
85 // is '/'; in both case, prefix is the ccnx prefix of name (component-wise)
86 if (name.size() == prefix.size() || name.at(prefix.size()) == '/')
87 {
88 return true;
89 }
90 }
91 return false;
92}
93
94int
95CcnxTunnel::setInterestFilter(const string &prefix, const InterestCallback &interestCallback)
96{
97 WriteLock(m_ritLock);
Zhenkai Zhud4924312012-12-28 11:35:12 -080098 // make sure copy constructor for boost::function works properly
99 m_rit.insert(make_pair(prefix, interestCallback));
Zhenkai Zhu0f054122012-12-25 22:22:50 -0800100 return 0;
101}
102
103void
104CcnxTunnel::clearInterestFilter(const string &prefix)
105{
106 WriteLock(m_ritLock);
107 // remove all
108 m_rit.erase(prefix);
109}
110
Zhenkai Zhud4924312012-12-28 11:35:12 -0800111TunnelClosurePass::TunnelClosurePass(int retry, const CcnxWrapper::DataCallback &dataCallback, const CcnxWrapper::TimeoutCallback &timeoutCallback, CcnxTunnel *tunnel, const string &originalInterest)
112 : ClosurePass(retry, dataCallback, timeoutCallback)
113 , m_tunnel(tunnel)
114 , m_originalInterest(originalInterest)
115{
Zhenkai Zhu0f054122012-12-25 22:22:50 -0800116}
117
Zhenkai Zhud4924312012-12-28 11:35:12 -0800118void
119TunnelClosurePass::runDataCallback(const string &name, const Bytes &content)
120{
121 if (m_tunnel != NULL)
122 {
123 m_tunnel->handleTunneledData(name, content, (*m_dataCallback));
124 }
125}
126
127CcnxWrapper::TimeoutCallbackReturnValue
128TunnelClosurePass::runTimeoutCallback(const string &interest)
129{
130 return ClosurePass::runTimeoutCallback(m_originalInterest);
131}
132
133} // Ccnx