blob: cb4750a24524af6a7ce331240d138de70a598aaa [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
Alexander Afanasyev09c613f2014-01-29 00:23:58 -080021#include "face.hpp"
22
Wentao Shang38d79682014-01-15 15:55:52 -080023class Consumer
24{
25public:
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070026 Consumer(const std::string& data_name, int pipe_size, int total_seg, int scope = -1, bool mustBeFresh = true)
27 : m_data_name (data_name)
28 , m_pipe_size (pipe_size)
29 , m_total_seg (total_seg)
30 , m_next_seg (0)
31 , m_total_size (0)
32 , m_output (false)
33 , m_scope(scope)
34 , m_mustBeFresh(mustBeFresh)
Wentao Shang38d79682014-01-15 15:55:52 -080035 {
36 }
37
38 inline void
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070039 enable_output()
Wentao Shang38d79682014-01-15 15:55:52 -080040 {
41 m_output = true;
42 }
43
44 void
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070045 run();
46
Wentao Shang38d79682014-01-15 15:55:52 -080047private:
48 void
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070049 on_data(const ndn::Interest& interest, ndn::Data& data);
Wentao Shang38d79682014-01-15 15:55:52 -080050
51 void
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070052 on_timeout(const ndn::Interest& interest);
53
Wentao Shang38d79682014-01-15 15:55:52 -080054 ndn::Face m_face;
55 ndn::Name m_data_name;
56 int m_pipe_size;
57 int m_total_seg;
58 int m_next_seg;
59 int m_total_size;
60 bool m_output; // set to false by default
Alexander Afanasyevc1ebbe92014-01-16 22:24:34 -080061
62 int m_scope;
63 bool m_mustBeFresh;
Wentao Shang38d79682014-01-15 15:55:52 -080064};
65
66void
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070067Consumer::run()
Wentao Shang38d79682014-01-15 15:55:52 -080068{
69 try
70 {
71 for (int i = 0; i < m_pipe_size; i++)
72 {
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070073 ndn::Interest interest(ndn::Name(m_data_name).appendSegment (m_next_seg++));
74 interest.setInterestLifetime(ndn::time::milliseconds(4000));
Alexander Afanasyevc1ebbe92014-01-16 22:24:34 -080075 if (m_scope >= 0)
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070076 interest.setScope(m_scope);
77 interest.setMustBeFresh(m_mustBeFresh);
78
79 m_face.expressInterest (interest,
80 ndn::bind(&Consumer::on_data, this, _1, _2),
81 ndn::bind(&Consumer::on_timeout, this, _1));
Wentao Shang38d79682014-01-15 15:55:52 -080082 }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070083
Wentao Shang38d79682014-01-15 15:55:52 -080084 // processEvents will block until the requested data received or timeout occurs
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070085 m_face.processEvents();
Wentao Shang38d79682014-01-15 15:55:52 -080086 }
87 catch (std::exception& e)
88 {
89 std::cerr << "ERROR: " << e.what () << std::endl;
90 }
91}
92
93void
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070094Consumer::on_data(const ndn::Interest& interest, ndn::Data& data)
Wentao Shang38d79682014-01-15 15:55:52 -080095{
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -070096 const ndn::Block& content = data.getContent();
97 const ndn::Name& name = data.getName();
Wentao Shang38d79682014-01-15 15:55:52 -080098
99 if (m_output)
100 {
101 std::cout.write(reinterpret_cast<const char*>(content.value()), content.value_size());
102 }
103
104 m_total_size += content.value_size ();
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700105
106 if ((int)(name.rbegin ()->toSegment ()) + 1 == m_total_seg)
Wentao Shang38d79682014-01-15 15:55:52 -0800107 {
108 std::cerr << "Last segment received." << std::endl;
109 std::cerr << "Total # bytes of content received: " << m_total_size << std::endl;
110 }
111 else
112 {
113 // Send interest for next segment
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700114 ndn::Interest interest(ndn::Name(m_data_name).appendSegment (m_next_seg++));
115 if (m_scope >= 0)
116 interest.setScope(m_scope);
117 interest.setInterestLifetime(ndn::time::milliseconds(4000));
118 interest.setMustBeFresh(m_mustBeFresh);
119
120 m_face.expressInterest (interest,
121 ndn::bind(&Consumer::on_data, this, _1, _2),
122 ndn::bind(&Consumer::on_timeout, this, _1));
Wentao Shang38d79682014-01-15 15:55:52 -0800123 }
124}
125
126
127void
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700128Consumer::on_timeout(const ndn::Interest& interest)
Wentao Shang38d79682014-01-15 15:55:52 -0800129{
130 //XXX: currently no retrans
131 std::cerr << "TIMEOUT: last interest sent for segment #" << (m_next_seg - 1) << std::endl;
132}
133
134
135int
136usage(const std::string &filename)
137{
138 std::cerr << "Usage: \n " << filename << " [-p pipe_size] [-c total_segment] [-o] /ndn/name\n";
139 return 1;
140}
141
142
143int
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700144main(int argc, char **argv)
Wentao Shang38d79682014-01-15 15:55:52 -0800145{
146 std::string name;
147 int pipe_size = 1;
148 int total_seg = std::numeric_limits<int>::max();
149 bool output = false;
150
151 int opt;
152 while ((opt = getopt(argc, argv, "op:c:")) != -1)
153 {
154 switch (opt)
155 {
156 case 'p':
157 pipe_size = atoi (optarg);
158 if (pipe_size <= 0)
159 pipe_size = 1;
160 std::cerr << "main (): set pipe size = " << pipe_size << std::endl;
161 break;
162 case 'c':
163 total_seg = atoi (optarg);
164 if (total_seg <= 0)
165 total_seg = 1;
166 std::cerr << "main (): set total seg = " << total_seg << std::endl;
167 break;
168 case 'o':
169 output = true;
170 break;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700171 default:
Wentao Shang38d79682014-01-15 15:55:52 -0800172 return usage(argv[0]);
173 }
174 }
175
176 if (optind < argc)
177 {
178 name = argv[optind];
179 }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700180
Wentao Shang38d79682014-01-15 15:55:52 -0800181 if (name.empty())
182 {
183 return usage(argv[0]);
184 }
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700185
Wentao Shang38d79682014-01-15 15:55:52 -0800186 Consumer consumer (name, pipe_size, total_seg);
187
188 if (output)
189 consumer.enable_output ();
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700190
Wentao Shang38d79682014-01-15 15:55:52 -0800191 consumer.run ();
192
193 return 0;
194}