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