blob: 6bfb07a225293381239b0fbbb74cd420253b01e8 [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
22#include <ndn-cpp/face.hpp>
23#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:
34 Consumer (const std::string &data_name, int pipe_size, int total_seg)
35 : 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)
37 {
38 }
39
40 inline void
41 enable_output ()
42 {
43 m_output = true;
44 }
45
46 void
47 run ();
48
49private:
50 void
51 on_data (const ndn::ptr_lib::shared_ptr<const ndn::Interest> &interest,
52 const ndn::ptr_lib::shared_ptr<ndn::Data> &data);
53
54 void
55 on_timeout (const ndn::ptr_lib::shared_ptr<const ndn::Interest> &interest);
56
57 ndn::Face m_face;
58 ndn::Name m_data_name;
59 int m_pipe_size;
60 int m_total_seg;
61 int m_next_seg;
62 int m_total_size;
63 bool m_output; // set to false by default
64};
65
66void
67Consumer::run ()
68{
69 try
70 {
71 for (int i = 0; i < m_pipe_size; i++)
72 {
73 ndn::Interest inst (ndn::Name(m_data_name).appendSegment (m_next_seg++));
74 inst.setScope (1);
75 inst.setInterestLifetime (1000);
76 inst.setMustBeFresh (true);
77
78 m_face.expressInterest (inst,
79 ndn::func_lib::bind (&Consumer::on_data, this, _1, _2),
80 ndn::func_lib::bind (&Consumer::on_timeout, this, _1));
81 }
82
83 // processEvents will block until the requested data received or timeout occurs
84 m_face.processEvents ();
85 }
86 catch (std::exception& e)
87 {
88 std::cerr << "ERROR: " << e.what () << std::endl;
89 }
90}
91
92void
93Consumer::on_data (const ndn::ptr_lib::shared_ptr<const ndn::Interest>& interest, const ndn::ptr_lib::shared_ptr<ndn::Data>& data)
94{
95 const ndn::Block& content = data->getContent ();
96 const ndn::Name& name = data->getName ();
97
98 if (m_output)
99 {
100 std::cout.write(reinterpret_cast<const char*>(content.value()), content.value_size());
101 }
102
103 m_total_size += content.value_size ();
104
105 if ((int) (name.rbegin ()->toSegment ()) + 1 == m_total_seg)
106 {
107 std::cerr << "Last segment received." << std::endl;
108 std::cerr << "Total # bytes of content received: " << m_total_size << std::endl;
109 }
110 else
111 {
112 // Send interest for next segment
113 ndn::Interest inst (ndn::Name(m_data_name).appendSegment (m_next_seg++));
114 inst.setScope (1);
115 inst.setInterestLifetime (1000);
116 inst.setMustBeFresh (true);
117
118 m_face.expressInterest (inst,
119 ndn::func_lib::bind (&Consumer::on_data, this, _1, _2),
120 ndn::func_lib::bind (&Consumer::on_timeout, this, _1));
121 }
122}
123
124
125void
126Consumer::on_timeout (const ndn::ptr_lib::shared_ptr<const ndn::Interest>& interest)
127{
128 //XXX: currently no retrans
129 std::cerr << "TIMEOUT: last interest sent for segment #" << (m_next_seg - 1) << std::endl;
130}
131
132
133int
134usage(const std::string &filename)
135{
136 std::cerr << "Usage: \n " << filename << " [-p pipe_size] [-c total_segment] [-o] /ndn/name\n";
137 return 1;
138}
139
140
141int
142main (int argc, char **argv)
143{
144 std::string name;
145 int pipe_size = 1;
146 int total_seg = std::numeric_limits<int>::max();
147 bool output = false;
148
149 int opt;
150 while ((opt = getopt(argc, argv, "op:c:")) != -1)
151 {
152 switch (opt)
153 {
154 case 'p':
155 pipe_size = atoi (optarg);
156 if (pipe_size <= 0)
157 pipe_size = 1;
158 std::cerr << "main (): set pipe size = " << pipe_size << std::endl;
159 break;
160 case 'c':
161 total_seg = atoi (optarg);
162 if (total_seg <= 0)
163 total_seg = 1;
164 std::cerr << "main (): set total seg = " << total_seg << std::endl;
165 break;
166 case 'o':
167 output = true;
168 break;
169 default:
170 return usage(argv[0]);
171 }
172 }
173
174 if (optind < argc)
175 {
176 name = argv[optind];
177 }
178
179 if (name.empty())
180 {
181 return usage(argv[0]);
182 }
183
184 Consumer consumer (name, pipe_size, total_seg);
185
186 if (output)
187 consumer.enable_output ();
188
189 consumer.run ();
190
191 return 0;
192}