blob: 6bac64acae5aa9a8b450e95049f43ab6042f09c7 [file] [log] [blame]
Wentao Shang38d79682014-01-15 15:55:52 -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: Wentao Shang <wentao@cs.ucla.edu>
19 */
20
21
Alexander Afanasyev09c613f2014-01-29 00:23:58 -080022#include "face.hpp"
23
Wentao Shang38d79682014-01-15 15:55:52 -080024#include <stdexcept>
25#include <iostream>
26
27#if NDN_CPP_HAVE_CXX11
28// In the std library, the placeholders are in a different namespace than boost.
29using namespace ndn::func_lib::placeholders;
30#endif
31
32class Consumer
33{
34public:
Alexander Afanasyev89a889c2014-01-17 16:13:38 -080035 Consumer (const std::string &data_name, int pipe_size, int total_seg, int scope = -1, bool mustBeFresh = true)
Wentao Shang38d79682014-01-15 15:55:52 -080036 : m_data_name (data_name), m_pipe_size (pipe_size), m_total_seg (total_seg),
37 m_next_seg (0), m_total_size (0), m_output (false)
Alexander Afanasyevc1ebbe92014-01-16 22:24:34 -080038 , m_scope(scope)
39 , m_mustBeFresh(mustBeFresh)
Wentao Shang38d79682014-01-15 15:55:52 -080040 {
41 }
42
43 inline void
44 enable_output ()
45 {
46 m_output = true;
47 }
48
49 void
50 run ();
51
52private:
53 void
54 on_data (const ndn::ptr_lib::shared_ptr<const ndn::Interest> &interest,
55 const ndn::ptr_lib::shared_ptr<ndn::Data> &data);
56
57 void
58 on_timeout (const ndn::ptr_lib::shared_ptr<const ndn::Interest> &interest);
59
60 ndn::Face m_face;
61 ndn::Name m_data_name;
62 int m_pipe_size;
63 int m_total_seg;
64 int m_next_seg;
65 int m_total_size;
66 bool m_output; // set to false by default
Alexander Afanasyevc1ebbe92014-01-16 22:24:34 -080067
68 int m_scope;
69 bool m_mustBeFresh;
Wentao Shang38d79682014-01-15 15:55:52 -080070};
71
72void
73Consumer::run ()
74{
75 try
76 {
77 for (int i = 0; i < m_pipe_size; i++)
78 {
79 ndn::Interest inst (ndn::Name(m_data_name).appendSegment (m_next_seg++));
Alexander Afanasyevc1ebbe92014-01-16 22:24:34 -080080 inst.setInterestLifetime (4000);
81 if (m_scope >= 0)
82 inst.setScope (m_scope);
83 inst.setMustBeFresh (m_mustBeFresh);
Wentao Shang38d79682014-01-15 15:55:52 -080084
85 m_face.expressInterest (inst,
86 ndn::func_lib::bind (&Consumer::on_data, this, _1, _2),
87 ndn::func_lib::bind (&Consumer::on_timeout, this, _1));
88 }
89
90 // processEvents will block until the requested data received or timeout occurs
91 m_face.processEvents ();
92 }
93 catch (std::exception& e)
94 {
95 std::cerr << "ERROR: " << e.what () << std::endl;
96 }
97}
98
99void
100Consumer::on_data (const ndn::ptr_lib::shared_ptr<const ndn::Interest>& interest, const ndn::ptr_lib::shared_ptr<ndn::Data>& data)
101{
102 const ndn::Block& content = data->getContent ();
103 const ndn::Name& name = data->getName ();
104
105 if (m_output)
106 {
107 std::cout.write(reinterpret_cast<const char*>(content.value()), content.value_size());
108 }
109
110 m_total_size += content.value_size ();
111
112 if ((int) (name.rbegin ()->toSegment ()) + 1 == m_total_seg)
113 {
114 std::cerr << "Last segment received." << std::endl;
115 std::cerr << "Total # bytes of content received: " << m_total_size << std::endl;
116 }
117 else
118 {
119 // Send interest for next segment
120 ndn::Interest inst (ndn::Name(m_data_name).appendSegment (m_next_seg++));
Alexander Afanasyevc1ebbe92014-01-16 22:24:34 -0800121 if (m_scope >= 0)
122 inst.setScope (m_scope);
123 inst.setInterestLifetime (4000);
124 inst.setMustBeFresh (m_mustBeFresh);
Wentao Shang38d79682014-01-15 15:55:52 -0800125
126 m_face.expressInterest (inst,
127 ndn::func_lib::bind (&Consumer::on_data, this, _1, _2),
128 ndn::func_lib::bind (&Consumer::on_timeout, this, _1));
129 }
130}
131
132
133void
134Consumer::on_timeout (const ndn::ptr_lib::shared_ptr<const ndn::Interest>& interest)
135{
136 //XXX: currently no retrans
137 std::cerr << "TIMEOUT: last interest sent for segment #" << (m_next_seg - 1) << std::endl;
138}
139
140
141int
142usage(const std::string &filename)
143{
144 std::cerr << "Usage: \n " << filename << " [-p pipe_size] [-c total_segment] [-o] /ndn/name\n";
145 return 1;
146}
147
148
149int
150main (int argc, char **argv)
151{
152 std::string name;
153 int pipe_size = 1;
154 int total_seg = std::numeric_limits<int>::max();
155 bool output = false;
156
157 int opt;
158 while ((opt = getopt(argc, argv, "op:c:")) != -1)
159 {
160 switch (opt)
161 {
162 case 'p':
163 pipe_size = atoi (optarg);
164 if (pipe_size <= 0)
165 pipe_size = 1;
166 std::cerr << "main (): set pipe size = " << pipe_size << std::endl;
167 break;
168 case 'c':
169 total_seg = atoi (optarg);
170 if (total_seg <= 0)
171 total_seg = 1;
172 std::cerr << "main (): set total seg = " << total_seg << std::endl;
173 break;
174 case 'o':
175 output = true;
176 break;
177 default:
178 return usage(argv[0]);
179 }
180 }
181
182 if (optind < argc)
183 {
184 name = argv[optind];
185 }
186
187 if (name.empty())
188 {
189 return usage(argv[0]);
190 }
191
192 Consumer consumer (name, pipe_size, total_seg);
193
194 if (output)
195 consumer.enable_output ();
196
197 consumer.run ();
198
199 return 0;
200}