blob: e318f19219ceffba421d298709a4c9c6087d7a54 [file] [log] [blame]
Alexander Afanasyevf278db32013-01-21 14:41:01 -08001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2013 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 * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
20 */
21
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -080022#include "ccnx-wrapper.h"
Zhenkai Zhu43eb2732012-12-28 00:48:26 -080023extern "C" {
24#include <ccn/fetch.h>
25}
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -080026#include <poll.h>
27#include <boost/throw_exception.hpp>
28#include <boost/date_time/posix_time/posix_time.hpp>
29#include <boost/random.hpp>
Alexander Afanasyevf278db32013-01-21 14:41:01 -080030#include <boost/make_shared.hpp>
Zhenkai Zhucbbb8882013-01-25 13:49:12 -080031#include <boost/algorithm/string.hpp>
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -080032#include <sstream>
33
Zhenkai Zhu746d4442013-03-13 17:06:54 -070034#include "ccnx-verifier.h"
Alexander Afanasyev9c9c3012013-01-25 23:44:25 -080035#include "logging.h"
36
37INIT_LOGGER ("Ccnx.Wrapper");
38
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -080039typedef boost::error_info<struct tag_errmsg, std::string> errmsg_info_str;
40typedef boost::error_info<struct tag_errmsg, int> errmsg_info_int;
41
42using namespace std;
43using namespace boost;
44
45namespace Ccnx {
46
Alexander Afanasyev848a8e42013-02-07 21:19:18 -080047// hack to enable fake signatures
48// min length for signature field is 16, as defined in ccn_buf_decoder.c:728
49const int DEFAULT_SIGNATURE_SIZE = 16;
50
51// Although ccn_buf_decoder.c:745 defines minimum length 16, something else is checking and only 32-byte fake value is accepted by ccnd
52const int PUBLISHER_KEY_SIZE = 32;
53
Zhenkai Zhu5acebd72013-02-07 19:59:25 -080054static int
Alexander Afanasyev848a8e42013-02-07 21:19:18 -080055ccn_encode_garbage_Signature(struct ccn_charbuf *buf)
Zhenkai Zhu5acebd72013-02-07 19:59:25 -080056{
57 int res = 0;
58
Zhenkai Zhu5acebd72013-02-07 19:59:25 -080059 res |= ccn_charbuf_append_tt(buf, CCN_DTAG_Signature, CCN_DTAG);
60
Alexander Afanasyev848a8e42013-02-07 21:19:18 -080061 // Let's cheat more. Default signing algorithm in ccnd is SHA256, so we just need add 32 bytes of garbage
62 static char garbage [DEFAULT_SIGNATURE_SIZE];
Zhenkai Zhu5acebd72013-02-07 19:59:25 -080063
Alexander Afanasyev848a8e42013-02-07 21:19:18 -080064 // digest and witness fields are optional, so use default ones
Zhenkai Zhu5acebd72013-02-07 19:59:25 -080065
66 res |= ccn_charbuf_append_tt(buf, CCN_DTAG_SignatureBits, CCN_DTAG);
Alexander Afanasyev848a8e42013-02-07 21:19:18 -080067 res |= ccn_charbuf_append_tt(buf, DEFAULT_SIGNATURE_SIZE, CCN_BLOB);
68 res |= ccn_charbuf_append(buf, garbage, DEFAULT_SIGNATURE_SIZE);
Zhenkai Zhu5acebd72013-02-07 19:59:25 -080069 res |= ccn_charbuf_append_closer(buf);
Alexander Afanasyev848a8e42013-02-07 21:19:18 -080070
Zhenkai Zhu5acebd72013-02-07 19:59:25 -080071 res |= ccn_charbuf_append_closer(buf);
72
73 return(res == 0 ? 0 : -1);
74}
75
76static int
Alexander Afanasyev848a8e42013-02-07 21:19:18 -080077ccn_pack_unsigned_ContentObject(struct ccn_charbuf *buf,
78 const struct ccn_charbuf *Name,
79 const struct ccn_charbuf *SignedInfo,
80 const void *data,
81 size_t size)
Zhenkai Zhu5acebd72013-02-07 19:59:25 -080082{
83 int res = 0;
Zhenkai Zhu5acebd72013-02-07 19:59:25 -080084 struct ccn_charbuf *content_header;
85 size_t closer_start;
86
87 content_header = ccn_charbuf_create();
88 res |= ccn_charbuf_append_tt(content_header, CCN_DTAG_Content, CCN_DTAG);
89 if (size != 0)
90 res |= ccn_charbuf_append_tt(content_header, size, CCN_BLOB);
91 closer_start = content_header->length;
92 res |= ccn_charbuf_append_closer(content_header);
93 if (res < 0)
94 return(-1);
Alexander Afanasyev848a8e42013-02-07 21:19:18 -080095
Zhenkai Zhu5acebd72013-02-07 19:59:25 -080096 res |= ccn_charbuf_append_tt(buf, CCN_DTAG_ContentObject, CCN_DTAG);
97
Alexander Afanasyev848a8e42013-02-07 21:19:18 -080098 res |= ccn_encode_garbage_Signature(buf);
99
Zhenkai Zhu5acebd72013-02-07 19:59:25 -0800100 res |= ccn_charbuf_append_charbuf(buf, Name);
101 res |= ccn_charbuf_append_charbuf(buf, SignedInfo);
102 res |= ccnb_append_tagged_blob(buf, CCN_DTAG_Content, data, size);
103 res |= ccn_charbuf_append_closer(buf);
Alexander Afanasyev848a8e42013-02-07 21:19:18 -0800104
Zhenkai Zhu5acebd72013-02-07 19:59:25 -0800105 ccn_charbuf_destroy(&content_header);
106 return(res == 0 ? 0 : -1);
107}
108
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800109CcnxWrapper::CcnxWrapper()
110 : m_handle (0)
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800111 , m_running (true)
112 , m_connected (false)
Zhenkai Zhu1888f742013-01-28 12:47:33 -0800113 , m_executor (new Executor(1))
Zhenkai Zhu746d4442013-03-13 17:06:54 -0700114 , m_verifier(new Verifier(this))
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800115{
Alexander Afanasyev1d1cc832013-02-05 20:03:36 -0800116 start ();
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800117}
118
119void
120CcnxWrapper::connectCcnd()
121{
Alexander Afanasyev17ae9e32013-02-19 18:09:08 -0800122 if (m_handle != 0) {
123 ccn_disconnect (m_handle);
Zhenkai Zhu3b82d432013-01-03 22:48:40 -0800124 //ccn_destroy (&m_handle);
Alexander Afanasyev17ae9e32013-02-19 18:09:08 -0800125 }
126 else
127 {
128 m_handle = ccn_create ();
129 }
Zhenkai Zhu0d8f5d52012-12-30 12:54:07 -0800130
Alexander Afanasyev17ae9e32013-02-19 18:09:08 -0800131 UniqueRecLock lock(m_mutex);
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800132 if (ccn_connect(m_handle, NULL) < 0)
133 {
134 BOOST_THROW_EXCEPTION (CcnxOperationException() << errmsg_info_str("connection to ccnd failed"));
135 }
136 m_connected = true;
137
Alexander Afanasyev17ae9e32013-02-19 18:09:08 -0800138 if (!m_registeredInterests.empty())
139 {
140 for (map<Name, InterestCallback>::const_iterator it = m_registeredInterests.begin(); it != m_registeredInterests.end(); ++it)
141 {
142 clearInterestFilter(it->first, false);
143 setInterestFilter(it->first, it->second, false);
144 }
145 }
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800146}
147
148CcnxWrapper::~CcnxWrapper()
149{
Alexander Afanasyev1d1cc832013-02-05 20:03:36 -0800150 shutdown ();
Zhenkai Zhu746d4442013-03-13 17:06:54 -0700151 if (m_verifier != 0)
152 {
153 delete m_verifier;
154 m_verifier = 0;
155 }
Alexander Afanasyev1d1cc832013-02-05 20:03:36 -0800156}
157
158void
159CcnxWrapper::start () // called automatically in constructor
160{
161 connectCcnd();
162 m_thread = thread (&CcnxWrapper::ccnLoop, this);
163 m_executor->start();
164}
165
166void
167CcnxWrapper::shutdown () // called in destructor, but can called manually
168{
169 m_executor->shutdown();
170
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800171 {
Alexander Afanasyev20bc8e22013-01-17 10:56:04 -0800172 UniqueRecLock lock(m_mutex);
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800173 m_running = false;
174 }
Zhenkai Zhu0d8f5d52012-12-30 12:54:07 -0800175
Alexander Afanasyev1d1cc832013-02-05 20:03:36 -0800176 _LOG_DEBUG ("+++++++++SHUTDOWN+++++++");
177 if (m_connected)
178 {
179 m_thread.join ();
Zhenkai Zhu1888f742013-01-28 12:47:33 -0800180
Alexander Afanasyev1d1cc832013-02-05 20:03:36 -0800181 ccn_disconnect (m_handle);
182 //ccn_destroy (&m_handle);
183 m_connected = false;
184 }
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800185}
186
187void
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800188CcnxWrapper::ccnLoop ()
189{
190 static boost::mt19937 randomGenerator (static_cast<unsigned int> (std::time (0)));
191 static boost::variate_generator<boost::mt19937&, boost::uniform_int<> > rangeUniformRandom (randomGenerator, uniform_int<> (0,1000));
192
193 while (m_running)
194 {
195 try
196 {
197 int res = 0;
198 {
Alexander Afanasyev20bc8e22013-01-17 10:56:04 -0800199 UniqueRecLock lock(m_mutex);
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800200 res = ccn_run (m_handle, 0);
201 }
202
203 if (!m_running) break;
Zhenkai Zhu0d8f5d52012-12-30 12:54:07 -0800204
Alexander Afanasyev9c9c3012013-01-25 23:44:25 -0800205 if (res < 0) {
206 _LOG_ERROR ("ccn_run returned negative status: " << res);
Alexander Afanasyev17ae9e32013-02-19 18:09:08 -0800207
208 BOOST_THROW_EXCEPTION (CcnxOperationException()
209 << errmsg_info_str("ccn_run returned error"));
Alexander Afanasyev9c9c3012013-01-25 23:44:25 -0800210 }
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800211
212
213 pollfd pfds[1];
214 {
Alexander Afanasyev20bc8e22013-01-17 10:56:04 -0800215 UniqueRecLock lock(m_mutex);
Zhenkai Zhu0d8f5d52012-12-30 12:54:07 -0800216
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800217 pfds[0].fd = ccn_get_connection_fd (m_handle);
218 pfds[0].events = POLLIN;
219 if (ccn_output_is_pending (m_handle))
220 pfds[0].events |= POLLOUT;
221 }
Zhenkai Zhu0d8f5d52012-12-30 12:54:07 -0800222
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800223 int ret = poll (pfds, 1, 1);
224 if (ret < 0)
225 {
226 BOOST_THROW_EXCEPTION (CcnxOperationException() << errmsg_info_str("ccnd socket failed (probably ccnd got stopped)"));
227 }
228 }
229 catch (CcnxOperationException &e)
230 {
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800231 m_connected = false;
232 // probably ccnd has been stopped
233 // try reconnect with sleep
234 int interval = 1;
235 int maxInterval = 32;
236 while (m_running)
237 {
238 try
239 {
Alexander Afanasyev17ae9e32013-02-19 18:09:08 -0800240 this_thread::sleep (boost::get_system_time () + boost::posix_time::seconds (interval) + boost::posix_time::milliseconds (rangeUniformRandom ()));
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800241
Alexander Afanasyev17ae9e32013-02-19 18:09:08 -0800242 connectCcnd ();
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800243 _LOG_DEBUG("reconnect to ccnd succeeded");
244 break;
245 }
246 catch (CcnxOperationException &e)
247 {
Alexander Afanasyev17ae9e32013-02-19 18:09:08 -0800248 this_thread::sleep (boost::get_system_time () + boost::posix_time::seconds (interval) + boost::posix_time::milliseconds (rangeUniformRandom ()));
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800249
250 // do exponential backup for reconnect interval
251 if (interval < maxInterval)
252 {
253 interval *= 2;
254 }
255 }
256 }
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800257 }
258 catch (const std::exception &exc)
259 {
260 // catch anything thrown within try block that derives from std::exception
261 std::cerr << exc.what();
262 }
263 catch (...)
264 {
Zhenkai Zhu0d8f5d52012-12-30 12:54:07 -0800265 cout << "UNKNOWN EXCEPTION !!!" << endl;
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800266 }
Zhenkai Zhu0d8f5d52012-12-30 12:54:07 -0800267 }
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800268}
269
Zhenkai Zhu43eb2732012-12-28 00:48:26 -0800270Bytes
Zhenkai Zhu704a6582013-03-13 16:44:42 -0700271CcnxWrapper::createContentObject(const Name &name, const void *buf, size_t len, int freshness, const Name &keyNameParam)
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800272{
Alexander Afanasyev1d1cc832013-02-05 20:03:36 -0800273 {
274 UniqueRecLock lock(m_mutex);
275 if (!m_running || !m_connected)
276 {
277 _LOG_TRACE ("<< not running or connected");
278 return Bytes ();
279 }
280 }
281
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800282 CcnxCharbufPtr ptr = name.toCcnxCharbuf();
283 ccn_charbuf *pname = ptr->getBuf();
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800284 ccn_charbuf *content = ccn_charbuf_create();
285
Zhenkai Zhud9d03f62013-01-04 16:57:46 -0800286 struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
287 sp.freshness = freshness;
288
Zhenkai Zhu704a6582013-03-13 16:44:42 -0700289 Name keyName;
290
291 if (keyNameParam.size() == 0)
Zhenkai Zhu589be8e2013-02-24 20:51:12 -0800292 {
Zhenkai Zhu704a6582013-03-13 16:44:42 -0700293 // use default key name
294 CcnxCharbufPtr defaultKeyNamePtr = boost::make_shared<CcnxCharbuf>();
295 ccn_get_public_key_and_name(m_handle, &sp, NULL, NULL, defaultKeyNamePtr->getBuf());
296 keyName = Name(*defaultKeyNamePtr);
Zhenkai Zhu589be8e2013-02-24 20:51:12 -0800297 }
Zhenkai Zhu704a6582013-03-13 16:44:42 -0700298 else
299 {
300 keyName = keyNameParam;
301 }
302
303 if (sp.template_ccnb == NULL)
304 {
305 sp.template_ccnb = ccn_charbuf_create();
306 ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG);
307 }
308 // no idea what the following 3 lines do, but it was there
309 else if (sp.template_ccnb->length > 0) {
310 sp.template_ccnb->length--;
311 }
312 ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_KeyLocator, CCN_DTAG);
313 ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_KeyName, CCN_DTAG);
314 CcnxCharbufPtr keyPtr = keyName.toCcnxCharbuf();
315 ccn_charbuf *keyBuf = keyPtr->getBuf();
316 ccn_charbuf_append(sp.template_ccnb, keyBuf->buf, keyBuf->length);
317 ccn_charbuf_append_closer(sp.template_ccnb); // </KeyName>
318 ccn_charbuf_append_closer(sp.template_ccnb); // </KeyLocator>
319 sp.sp_flags |= CCN_SP_TEMPL_KEY_LOCATOR;
320 ccn_charbuf_append_closer(sp.template_ccnb); // </SignedInfo>
Zhenkai Zhu589be8e2013-02-24 20:51:12 -0800321
Zhenkai Zhud9d03f62013-01-04 16:57:46 -0800322 if (ccn_sign_content(m_handle, content, pname, &sp, buf, len) != 0)
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800323 {
Zhenkai Zhud9d03f62013-01-04 16:57:46 -0800324 BOOST_THROW_EXCEPTION(CcnxOperationException() << errmsg_info_str("sign content failed"));
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800325 }
Zhenkai Zhu43eb2732012-12-28 00:48:26 -0800326
327 Bytes bytes;
328 readRaw(bytes, content->buf, content->length);
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800329
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800330 ccn_charbuf_destroy (&content);
Zhenkai Zhu589be8e2013-02-24 20:51:12 -0800331 if (sp.template_ccnb != NULL)
332 {
333 ccn_charbuf_destroy (&sp.template_ccnb);
334 }
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800335
Zhenkai Zhu43eb2732012-12-28 00:48:26 -0800336 return bytes;
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800337}
338
339int
Zhenkai Zhubad089c2012-12-28 10:28:27 -0800340CcnxWrapper::putToCcnd (const Bytes &contentObject)
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800341{
Alexander Afanasyevd9826662013-01-28 11:18:06 -0800342 _LOG_TRACE (">> putToCcnd");
Alexander Afanasyev20bc8e22013-01-17 10:56:04 -0800343 UniqueRecLock lock(m_mutex);
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800344 if (!m_running || !m_connected)
Alexander Afanasyevd9826662013-01-28 11:18:06 -0800345 {
346 _LOG_TRACE ("<< not running or connected");
347 return -1;
348 }
Zhenkai Zhu0d8f5d52012-12-30 12:54:07 -0800349
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800350
Zhenkai Zhu974c5a62012-12-28 14:15:30 -0800351 if (ccn_put(m_handle, head(contentObject), contentObject.size()) < 0)
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800352 {
Alexander Afanasyevd9826662013-01-28 11:18:06 -0800353 _LOG_ERROR ("ccn_put failed");
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800354 // BOOST_THROW_EXCEPTION(CcnxOperationException() << errmsg_info_str("ccnput failed"));
355 }
Alexander Afanasyevd9826662013-01-28 11:18:06 -0800356 else
357 {
358 _LOG_DEBUG ("<< putToCcnd");
359 }
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800360
361 return 0;
362}
363
364int
Zhenkai Zhu589be8e2013-02-24 20:51:12 -0800365CcnxWrapper::publishData (const Name &name, const unsigned char *buf, size_t len, int freshness, const Name &keyName)
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800366{
Zhenkai Zhu589be8e2013-02-24 20:51:12 -0800367 Bytes co = createContentObject(name, buf, len, freshness, keyName);
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800368 return putToCcnd(co);
369}
370
Zhenkai Zhu43eb2732012-12-28 00:48:26 -0800371int
Zhenkai Zhu5acebd72013-02-07 19:59:25 -0800372CcnxWrapper::publishUnsignedData(const Name &name, const unsigned char *buf, size_t len, int freshness)
373{
374 {
375 UniqueRecLock lock(m_mutex);
376 if (!m_running || !m_connected)
377 {
378 _LOG_TRACE ("<< not running or connected");
379 return -1;
380 }
381 }
382
383 CcnxCharbufPtr ptr = name.toCcnxCharbuf();
384 ccn_charbuf *pname = ptr->getBuf();
385 ccn_charbuf *content = ccn_charbuf_create();
386 ccn_charbuf *signed_info = ccn_charbuf_create();
387
Alexander Afanasyev848a8e42013-02-07 21:19:18 -0800388 static char fakeKey[PUBLISHER_KEY_SIZE];
Zhenkai Zhu5acebd72013-02-07 19:59:25 -0800389
390 int res = ccn_signed_info_create(signed_info,
Alexander Afanasyev848a8e42013-02-07 21:19:18 -0800391 fakeKey, PUBLISHER_KEY_SIZE,
392 NULL,
393 CCN_CONTENT_DATA,
394 freshness,
395 NULL,
396 NULL // ccnd is happy with absent key locator and key itself... ha ha
397 );
398 ccn_pack_unsigned_ContentObject(content, pname, signed_info, buf, len);
Zhenkai Zhu5acebd72013-02-07 19:59:25 -0800399
400 Bytes bytes;
401 readRaw(bytes, content->buf, content->length);
402
403 ccn_charbuf_destroy (&content);
404 ccn_charbuf_destroy (&signed_info);
405
406 return putToCcnd (bytes);
407}
408
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800409
Alexander Afanasyev816251e2013-01-28 16:16:49 -0800410static void
411deleterInInterestTuple (tuple<CcnxWrapper::InterestCallback *, ExecutorPtr> *tuple)
412{
413 delete tuple->get<0> ();
414 delete tuple;
415}
416
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800417static ccn_upcall_res
418incomingInterest(ccn_closure *selfp,
419 ccn_upcall_kind kind,
420 ccn_upcall_info *info)
421{
Alexander Afanasyev816251e2013-01-28 16:16:49 -0800422 CcnxWrapper::InterestCallback *f;
423 ExecutorPtr executor;
424 tuple<CcnxWrapper::InterestCallback *, ExecutorPtr> *realData = reinterpret_cast< tuple<CcnxWrapper::InterestCallback *, ExecutorPtr>* > (selfp->data);
425 tie (f, executor) = *realData;
426
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800427 switch (kind)
428 {
429 case CCN_UPCALL_FINAL: // effective in unit tests
Alexander Afanasyev816251e2013-01-28 16:16:49 -0800430 // delete closure;
431 executor->execute (bind (deleterInInterestTuple, realData));
432
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800433 delete selfp;
Alexander Afanasyevd9826662013-01-28 11:18:06 -0800434 _LOG_TRACE ("<< incomingInterest with CCN_UPCALL_FINAL");
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800435 return CCN_UPCALL_RESULT_OK;
436
437 case CCN_UPCALL_INTEREST:
Alexander Afanasyev6aec3bf2013-02-05 11:25:52 -0800438 _LOG_TRACE (">> incomingInterest upcall: " << Name(info->interest_ccnb, info->interest_comps));
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800439 break;
440
441 default:
Alexander Afanasyev6aec3bf2013-02-05 11:25:52 -0800442 _LOG_TRACE ("<< incomingInterest with CCN_UPCALL_RESULT_OK: " << Name(info->interest_ccnb, info->interest_comps));
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800443 return CCN_UPCALL_RESULT_OK;
444 }
445
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800446 Name interest(info->interest_ccnb, info->interest_comps);
Zhenkai Zhuff4fa8a2013-01-28 22:02:40 -0800447 Selectors selectors(info->pi);
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800448
Zhenkai Zhuff4fa8a2013-01-28 22:02:40 -0800449 executor->execute (bind (*f, interest, selectors));
Zhenkai Zhu1888f742013-01-28 12:47:33 -0800450 // this will be run in executor
Alexander Afanasyev816251e2013-01-28 16:16:49 -0800451 // (*f) (interest);
452 // closure->runInterestCallback(interest);
Alexander Afanasyevd9826662013-01-28 11:18:06 -0800453
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800454 return CCN_UPCALL_RESULT_OK;
455}
456
Alexander Afanasyev816251e2013-01-28 16:16:49 -0800457static void
Zhenkai Zhuff4fa8a2013-01-28 22:02:40 -0800458deleterInDataTuple (tuple<Closure *, ExecutorPtr, Selectors> *tuple)
Alexander Afanasyev816251e2013-01-28 16:16:49 -0800459{
460 delete tuple->get<0> ();
461 delete tuple;
462}
463
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800464static ccn_upcall_res
465incomingData(ccn_closure *selfp,
466 ccn_upcall_kind kind,
467 ccn_upcall_info *info)
468{
Alexander Afanasyev816251e2013-01-28 16:16:49 -0800469 // Closure *cp = static_cast<Closure *> (selfp->data);
470 Closure *cp;
471 ExecutorPtr executor;
Zhenkai Zhuff4fa8a2013-01-28 22:02:40 -0800472 Selectors selectors;
473 tuple<Closure *, ExecutorPtr, Selectors> *realData = reinterpret_cast< tuple<Closure*, ExecutorPtr, Selectors>* > (selfp->data);
474 tie (cp, executor, selectors) = *realData;
Alexander Afanasyev816251e2013-01-28 16:16:49 -0800475
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -0700476 bool checked = false;
Zhenkai Zhu79264a42013-02-07 21:49:42 -0800477
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800478 switch (kind)
479 {
480 case CCN_UPCALL_FINAL: // effecitve in unit tests
Alexander Afanasyev816251e2013-01-28 16:16:49 -0800481 executor->execute (bind (deleterInDataTuple, realData));
482
Zhenkai Zhu19f81de2013-01-04 22:27:47 -0800483 cp = NULL;
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800484 delete selfp;
Alexander Afanasyevd9826662013-01-28 11:18:06 -0800485 _LOG_TRACE ("<< incomingData with CCN_UPCALL_FINAL");
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800486 return CCN_UPCALL_RESULT_OK;
487
488 case CCN_UPCALL_CONTENT:
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -0700489 checked = true;
Alexander Afanasyev6aec3bf2013-02-05 11:25:52 -0800490 _LOG_TRACE (">> incomingData content upcall: " << Name (info->content_ccnb, info->content_comps));
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800491 break;
492
Zhenkai Zhu5acebd72013-02-07 19:59:25 -0800493 case CCN_UPCALL_CONTENT_UNVERIFIED:
494 _LOG_TRACE (">> incomingData content unverified upcall: " << Name (info->content_ccnb, info->content_comps));
495 break;
496
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800497 case CCN_UPCALL_INTEREST_TIMED_OUT: {
Zhenkai Zhu8339e912013-01-18 18:10:17 -0800498 if (cp != NULL)
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800499 {
Zhenkai Zhu8339e912013-01-18 18:10:17 -0800500 Name interest(info->interest_ccnb, info->interest_comps);
Alexander Afanasyev6aec3bf2013-02-05 11:25:52 -0800501 _LOG_TRACE ("<< incomingData timeout: " << Name (info->interest_ccnb, info->interest_comps));
Zhenkai Zhuff4fa8a2013-01-28 22:02:40 -0800502 executor->execute (bind (&Closure::runTimeoutCallback, cp, interest, *cp, selectors));
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800503 }
Alexander Afanasyevd9826662013-01-28 11:18:06 -0800504 else
505 {
Alexander Afanasyev6aec3bf2013-02-05 11:25:52 -0800506 _LOG_TRACE ("<< incomingData timeout, but callback is not set...: " << Name (info->interest_ccnb, info->interest_comps));
Alexander Afanasyevd9826662013-01-28 11:18:06 -0800507 }
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800508 return CCN_UPCALL_RESULT_OK;
509 }
510
511 default:
Zhenkai Zhu5acebd72013-02-07 19:59:25 -0800512 _LOG_TRACE(">> unknown upcall type");
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800513 return CCN_UPCALL_RESULT_OK;
514 }
515
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -0700516 PcoPtr pco = make_shared<ParsedContentObject> (info->content_ccnb, info->pco->offset[CCN_PCO_E], checked);
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800517
Zhenkai Zhu1888f742013-01-28 12:47:33 -0800518 // this will be run in executor
Alexander Afanasyev816251e2013-01-28 16:16:49 -0800519 executor->execute (bind (&Closure::runDataCallback, cp, pco->name (), pco));
Alexander Afanasyevd9826662013-01-28 11:18:06 -0800520 _LOG_TRACE (">> incomingData");
521
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800522 return CCN_UPCALL_RESULT_OK;
523}
524
Alexander Afanasyevd6c2a902013-01-19 21:24:30 -0800525int CcnxWrapper::sendInterest (const Name &interest, const Closure &closure, const Selectors &selectors)
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800526{
Alexander Afanasyev6aec3bf2013-02-05 11:25:52 -0800527 _LOG_TRACE (">> sendInterest: " << interest);
Zhenkai Zhu7599db42013-01-28 10:32:53 -0800528 {
529 UniqueRecLock lock(m_mutex);
530 if (!m_running || !m_connected)
Alexander Afanasyevb3d4cd52013-01-28 11:20:52 -0800531 {
532 _LOG_ERROR ("<< sendInterest: not running or connected");
533 return -1;
534 }
Zhenkai Zhu7599db42013-01-28 10:32:53 -0800535 }
Zhenkai Zhu0d8f5d52012-12-30 12:54:07 -0800536
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800537 CcnxCharbufPtr namePtr = interest.toCcnxCharbuf();
538 ccn_charbuf *pname = namePtr->getBuf();
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800539 ccn_closure *dataClosure = new ccn_closure;
540
Alexander Afanasyev816251e2013-01-28 16:16:49 -0800541 // Closure *myClosure = new ExecutorClosure(closure, m_executor);
542 Closure *myClosure = closure.dup ();
Zhenkai Zhuff4fa8a2013-01-28 22:02:40 -0800543 dataClosure->data = new tuple<Closure*, ExecutorPtr, Selectors> (myClosure, m_executor, selectors);
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800544
545 dataClosure->p = &incomingData;
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800546
547 CcnxCharbufPtr selectorsPtr = selectors.toCcnxCharbuf();
548 ccn_charbuf *templ = NULL;
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800549 if (selectorsPtr)
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800550 {
551 templ = selectorsPtr->getBuf();
552 }
553
Zhenkai Zhu7599db42013-01-28 10:32:53 -0800554 UniqueRecLock lock(m_mutex);
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800555 if (ccn_express_interest (m_handle, pname, dataClosure, templ) < 0)
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800556 {
Alexander Afanasyevd9826662013-01-28 11:18:06 -0800557 _LOG_ERROR ("<< sendInterest: ccn_express_interest FAILED!!!");
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800558 }
559
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800560 return 0;
561}
562
Alexander Afanasyev17ae9e32013-02-19 18:09:08 -0800563int CcnxWrapper::setInterestFilter (const Name &prefix, const InterestCallback &interestCallback, bool record/* = true*/)
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800564{
Alexander Afanasyevd9826662013-01-28 11:18:06 -0800565 _LOG_TRACE (">> setInterestFilter");
Alexander Afanasyev20bc8e22013-01-17 10:56:04 -0800566 UniqueRecLock lock(m_mutex);
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800567 if (!m_running || !m_connected)
Zhenkai Zhu1888f742013-01-28 12:47:33 -0800568 {
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800569 return -1;
Zhenkai Zhu7599db42013-01-28 10:32:53 -0800570 }
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800571
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800572 CcnxCharbufPtr ptr = prefix.toCcnxCharbuf();
573 ccn_charbuf *pname = ptr->getBuf();
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800574 ccn_closure *interestClosure = new ccn_closure;
575
Alexander Afanasyev816251e2013-01-28 16:16:49 -0800576 // interestClosure->data = new ExecutorInterestClosure(interestCallback, m_executor);
577
578 interestClosure->data = new tuple<CcnxWrapper::InterestCallback *, ExecutorPtr> (new InterestCallback (interestCallback), m_executor); // should be removed when closure is removed
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800579 interestClosure->p = &incomingInterest;
Zhenkai Zhu7599db42013-01-28 10:32:53 -0800580
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800581 int ret = ccn_set_interest_filter (m_handle, pname, interestClosure);
582 if (ret < 0)
583 {
Alexander Afanasyevd9826662013-01-28 11:18:06 -0800584 _LOG_ERROR ("<< setInterestFilter: ccn_set_interest_filter FAILED");
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800585 }
586
Alexander Afanasyev17ae9e32013-02-19 18:09:08 -0800587 if (record)
588 {
589 m_registeredInterests.insert(pair<Name, InterestCallback>(prefix, interestCallback));
590 }
Alexander Afanasyev816251e2013-01-28 16:16:49 -0800591
Alexander Afanasyevd9826662013-01-28 11:18:06 -0800592 _LOG_TRACE ("<< setInterestFilter");
Alexander Afanasyevdcfa9632013-01-07 16:38:19 -0800593
594 return ret;
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800595}
596
597void
Alexander Afanasyev17ae9e32013-02-19 18:09:08 -0800598CcnxWrapper::clearInterestFilter (const Name &prefix, bool record/* = true*/)
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800599{
Alexander Afanasyevd9826662013-01-28 11:18:06 -0800600 _LOG_TRACE (">> clearInterestFilter");
Alexander Afanasyev20bc8e22013-01-17 10:56:04 -0800601 UniqueRecLock lock(m_mutex);
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800602 if (!m_running || !m_connected)
603 return;
604
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800605 CcnxCharbufPtr ptr = prefix.toCcnxCharbuf();
606 ccn_charbuf *pname = ptr->getBuf();
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800607
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800608 int ret = ccn_set_interest_filter (m_handle, pname, 0);
609 if (ret < 0)
610 {
611 }
612
Alexander Afanasyev17ae9e32013-02-19 18:09:08 -0800613 if (record)
614 {
615 m_registeredInterests.erase(prefix);
616 }
Alexander Afanasyevd9826662013-01-28 11:18:06 -0800617
618 _LOG_TRACE ("<< clearInterestFilter");
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800619}
620
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800621Name
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800622CcnxWrapper::getLocalPrefix ()
623{
624 struct ccn * tmp_handle = ccn_create ();
625 int res = ccn_connect (tmp_handle, NULL);
626 if (res < 0)
627 {
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800628 return Name();
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800629 }
Zhenkai Zhu0d8f5d52012-12-30 12:54:07 -0800630
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800631 string retval = "";
Zhenkai Zhu0d8f5d52012-12-30 12:54:07 -0800632
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800633 struct ccn_charbuf *templ = ccn_charbuf_create();
634 ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
635 ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
636 ccn_charbuf_append_closer(templ); /* </Name> */
637 // XXX - use pubid if possible
638 ccn_charbuf_append_tt(templ, CCN_DTAG_MaxSuffixComponents, CCN_DTAG);
639 ccnb_append_number(templ, 1);
640 ccn_charbuf_append_closer(templ); /* </MaxSuffixComponents> */
641 ccnb_tagged_putf(templ, CCN_DTAG_Scope, "%d", 2);
642 ccn_charbuf_append_closer(templ); /* </Interest> */
643
644 struct ccn_charbuf *name = ccn_charbuf_create ();
645 res = ccn_name_from_uri (name, "/local/ndn/prefix");
646 if (res < 0) {
647 }
648 else
649 {
650 struct ccn_fetch *fetch = ccn_fetch_new (tmp_handle);
Zhenkai Zhu0d8f5d52012-12-30 12:54:07 -0800651
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800652 struct ccn_fetch_stream *stream = ccn_fetch_open (fetch, name, "/local/ndn/prefix",
Zhenkai Zhu0d8f5d52012-12-30 12:54:07 -0800653 NULL, 4, CCN_V_HIGHEST, 0);
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800654 if (stream == NULL) {
655 }
656 else
657 {
658 ostringstream os;
659
660 int counter = 0;
661 char buf[256];
662 while (true) {
663 res = ccn_fetch_read (stream, buf, sizeof(buf));
Zhenkai Zhu0d8f5d52012-12-30 12:54:07 -0800664
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800665 if (res == 0) {
666 break;
667 }
Zhenkai Zhu0d8f5d52012-12-30 12:54:07 -0800668
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800669 if (res > 0) {
670 os << string(buf, res);
671 } else if (res == CCN_FETCH_READ_NONE) {
672 if (counter < 2)
673 {
674 ccn_run(tmp_handle, 1000);
675 counter ++;
676 }
677 else
678 {
679 break;
680 }
681 } else if (res == CCN_FETCH_READ_END) {
682 break;
683 } else if (res == CCN_FETCH_READ_TIMEOUT) {
684 break;
685 } else {
686 break;
687 }
688 }
689 retval = os.str ();
690 stream = ccn_fetch_close(stream);
691 }
692 fetch = ccn_fetch_destroy(fetch);
693 }
694
695 ccn_charbuf_destroy (&name);
696
697 ccn_disconnect (tmp_handle);
698 ccn_destroy (&tmp_handle);
Zhenkai Zhu0d8f5d52012-12-30 12:54:07 -0800699
Zhenkai Zhucbbb8882013-01-25 13:49:12 -0800700 boost::algorithm::trim(retval);
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800701 return Name(retval);
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800702}
703
Zhenkai Zhu79264a42013-02-07 21:49:42 -0800704bool
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -0700705CcnxWrapper::checkPcoIntegrity(PcoPtr &pco)
Zhenkai Zhu79264a42013-02-07 21:49:42 -0800706{
Zhenkai Zhudd1f14d2013-03-13 12:04:28 -0700707 bool checked = (ccn_verify_content(m_handle, pco->msg(), (ccn_parsed_ContentObject *)pco->pco()) == 0);
708 pco->setIntegrityChecked(checked);
709 return checked;
Zhenkai Zhu79264a42013-02-07 21:49:42 -0800710}
711
Zhenkai Zhu746d4442013-03-13 17:06:54 -0700712bool
713CcnxWrapper::verifyKey(PcoPtr &pco)
714{
715 return m_verifier->verify(pco);
716}
717
Jared Lindblomf83ff942013-03-01 00:01:49 -0800718// This is needed just for get function implementation
719struct GetState
720{
721 GetState (double maxWait)
722 {
723 double intPart, fraction;
724 fraction = modf (std::abs(maxWait), &intPart);
725
726 m_maxWait = date_time::second_clock<boost::posix_time::ptime>::universal_time()
727 + boost::posix_time::seconds (intPart)
728 + boost::posix_time::microseconds (fraction * 1000000);
729 }
730
731 PcoPtr
732 WaitForResult ()
733 {
734 boost::unique_lock<boost::mutex> lock (m_mutex);
735 m_cond.timed_wait (lock, m_maxWait);
736
737 return m_retval;
738 }
739
740 void
741 DataCallback (Name name, PcoPtr pco)
742 {
743 m_retval = pco;
744
745 boost::unique_lock<boost::mutex> lock (m_mutex);
746 m_cond.notify_one ();
747 }
748
749 void
750 TimeoutCallback (Name name)
751 {
752 boost::unique_lock<boost::mutex> lock (m_mutex);
753 m_cond.notify_one ();
754 }
755
756private:
757 boost::posix_time::ptime m_maxWait;
758
759 boost::mutex m_mutex;
760 boost::condition_variable m_cond;
761
762 PcoPtr m_retval;
763};
764
765
766PcoPtr
767CcnxWrapper::get(const Name &interest, const Selectors &selectors, double maxWait/* = 4.0*/)
768{
769 _LOG_TRACE (">> get: " << interest);
770 {
771 UniqueRecLock lock(m_mutex);
772 if (!m_running || !m_connected)
773 {
774 _LOG_ERROR ("<< get: not running or connected");
775 return PcoPtr ();
776 }
777 }
778
779 GetState state (maxWait);
780 this->sendInterest (interest, Closure (boost::bind (&GetState::DataCallback, &state, _1, _2),
781 boost::bind (&GetState::TimeoutCallback, &state, _1)),
782 selectors);
783 return state.WaitForResult ();
784}
785
Zhenkai Zhu1ddeb6f2012-12-27 14:04:18 -0800786}