~ubuntu-branches/ubuntu/trusty/miro/trusty

« back to all changes in this revision

Viewing changes to portable/libtorrent/src/create_torrent.cpp

  • Committer: Daniel Hahler
  • Date: 2010-04-13 18:51:35 UTC
  • mfrom: (1.2.10 upstream)
  • Revision ID: ubuntu-launchpad@thequod.de-20100413185135-xi24v1diqg8w406x
Merging shared upstream rev into target branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 
3
 
Copyright (c) 2008, Arvid Norberg
4
 
All rights reserved.
5
 
 
6
 
Redistribution and use in source and binary forms, with or without
7
 
modification, are permitted provided that the following conditions
8
 
are met:
9
 
 
10
 
    * Redistributions of source code must retain the above copyright
11
 
      notice, this list of conditions and the following disclaimer.
12
 
    * Redistributions in binary form must reproduce the above copyright
13
 
      notice, this list of conditions and the following disclaimer in
14
 
      the documentation and/or other materials provided with the distribution.
15
 
    * Neither the name of the author nor the names of its
16
 
      contributors may be used to endorse or promote products derived
17
 
      from this software without specific prior written permission.
18
 
 
19
 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23
 
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
 
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
 
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
 
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
 
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
 
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
 
POSSIBILITY OF SUCH DAMAGE.
30
 
 
31
 
*/
32
 
 
33
 
#include "libtorrent/create_torrent.hpp"
34
 
#include "libtorrent/file_pool.hpp"
35
 
#include "libtorrent/storage.hpp"
36
 
 
37
 
#include <boost/date_time/posix_time/posix_time.hpp>
38
 
#include <boost/date_time/gregorian/gregorian.hpp>
39
 
#include <boost/bind.hpp>
40
 
 
41
 
namespace gr = boost::gregorian;
42
 
 
43
 
namespace libtorrent
44
 
{
45
 
        create_torrent::create_torrent(file_storage& fs, int size)
46
 
                : m_files(fs)
47
 
                , m_creation_date(pt::second_clock::universal_time())
48
 
                , m_multifile(fs.num_files() > 1)
49
 
                , m_private(false)
50
 
        {
51
 
                TORRENT_ASSERT(fs.num_files() > 0);
52
 
#if BOOST_VERSION < 103600
53
 
                if (!m_multifile && m_files.at(0).path.has_branch_path()) m_multifile = true;
54
 
#else
55
 
                if (!m_multifile && m_files.at(0).path.has_parent_path()) m_multifile = true;
56
 
#endif
57
 
 
58
 
                // make sure the size is an even power of 2
59
 
#ifndef NDEBUG
60
 
                for (int i = 0; i < 32; ++i)
61
 
                {
62
 
                        if (size & (1 << i))
63
 
                        {
64
 
                                TORRENT_ASSERT((size & ~(1 << i)) == 0);
65
 
                                break;
66
 
                        }
67
 
                }
68
 
#endif
69
 
                m_files.set_piece_length(size);
70
 
                m_files.set_num_pieces(static_cast<int>(
71
 
                        (m_files.total_size() + m_files.piece_length() - 1) / m_files.piece_length()));
72
 
                m_piece_hash.resize(m_files.num_pieces());
73
 
        }
74
 
 
75
 
        create_torrent::create_torrent(file_storage& fs)
76
 
                : m_files(fs)
77
 
                , m_creation_date(pt::second_clock::universal_time())
78
 
                , m_multifile(fs.num_files() > 1)
79
 
                , m_private(false)
80
 
        {
81
 
                TORRENT_ASSERT(fs.num_files() > 0);
82
 
#if BOOST_VERSION < 103600
83
 
                if (!m_multifile && m_files.at(0).path.has_branch_path()) m_multifile = true;
84
 
#else
85
 
                if (!m_multifile && m_files.at(0).path.has_parent_path()) m_multifile = true;
86
 
#endif
87
 
 
88
 
                const int target_size = 40 * 1024;
89
 
                int size = fs.total_size() / (target_size / 20);
90
 
        
91
 
                for (int i = 4*1024*1024; i > 16*1024; i /= 2)
92
 
                {
93
 
                        if (size < i) continue;
94
 
                        size = i;
95
 
                        break;
96
 
                }
97
 
 
98
 
                m_files.set_piece_length(size);
99
 
                m_files.set_num_pieces(static_cast<int>(
100
 
                        (m_files.total_size() + m_files.piece_length() - 1) / m_files.piece_length()));
101
 
                m_piece_hash.resize(m_files.num_pieces());
102
 
        }
103
 
        entry create_torrent::generate() const
104
 
        {
105
 
                TORRENT_ASSERT(m_files.piece_length() > 0);
106
 
 
107
 
                if (m_files.num_files() == 0)
108
 
                {
109
 
                        // TODO: throw something here
110
 
                        // throw
111
 
                        return entry();
112
 
                }
113
 
 
114
 
                entry dict;
115
 
 
116
 
                if (!m_urls.empty()) dict["announce"] = m_urls.front().first;
117
 
                
118
 
                if (!m_nodes.empty())
119
 
                {
120
 
                        entry& nodes = dict["nodes"];
121
 
                        entry::list_type& nodes_list = nodes.list();
122
 
                        for (nodes_t::const_iterator i = m_nodes.begin()
123
 
                                , end(m_nodes.end()); i != end; ++i)
124
 
                        {
125
 
                                entry::list_type node;
126
 
                                node.push_back(entry(i->first));
127
 
                                node.push_back(entry(i->second));
128
 
                                nodes_list.push_back(entry(node));
129
 
                        }
130
 
                }
131
 
 
132
 
                if (m_urls.size() > 1)
133
 
                {
134
 
                        entry trackers(entry::list_t);
135
 
                        entry tier(entry::list_t);
136
 
                        int current_tier = m_urls.front().second;
137
 
                        for (std::vector<announce_entry>::const_iterator i = m_urls.begin();
138
 
                                i != m_urls.end(); ++i)
139
 
                        {
140
 
                                if (i->second != current_tier)
141
 
                                {
142
 
                                        current_tier = i->second;
143
 
                                        trackers.list().push_back(tier);
144
 
                                        tier.list().clear();
145
 
                                }
146
 
                                tier.list().push_back(entry(i->first));
147
 
                        }
148
 
                        trackers.list().push_back(tier);
149
 
                        dict["announce-list"] = trackers;
150
 
                }
151
 
 
152
 
                if (!m_comment.empty())
153
 
                        dict["comment"] = m_comment;
154
 
 
155
 
                dict["creation date"] =
156
 
                        (m_creation_date - pt::ptime(gr::date(1970, gr::Jan, 1))).total_seconds();
157
 
 
158
 
                if (!m_created_by.empty())
159
 
                        dict["created by"] = m_created_by;
160
 
                        
161
 
                if (!m_url_seeds.empty())
162
 
                {
163
 
                        if (m_url_seeds.size() == 1)
164
 
                        {
165
 
                                dict["url-list"] = m_url_seeds.front();
166
 
                        }
167
 
                        else
168
 
                        {
169
 
                                entry& list = dict["url-list"];
170
 
                                for (std::vector<std::string>::const_iterator i
171
 
                                        = m_url_seeds.begin(); i != m_url_seeds.end(); ++i)
172
 
                                {
173
 
                                        list.list().push_back(entry(*i));
174
 
                                }
175
 
                        }
176
 
                }
177
 
 
178
 
                entry& info = dict["info"];
179
 
                info["name"] = m_files.name();
180
 
 
181
 
                if (m_private) info["private"] = 1;
182
 
 
183
 
                if (!m_multifile)
184
 
                {
185
 
                        info["length"] = m_files.at(0).size;
186
 
                }
187
 
                else
188
 
                {
189
 
                        if (!info.find_key("files"))
190
 
                        {
191
 
                                entry& files = info["files"];
192
 
 
193
 
                                for (file_storage::iterator i = m_files.begin();
194
 
                                        i != m_files.end(); ++i)
195
 
                                {
196
 
                                        files.list().push_back(entry());
197
 
                                        entry& file_e = files.list().back();
198
 
                                        file_e["length"] = i->size;
199
 
                                        entry& path_e = file_e["path"];
200
 
 
201
 
#if BOOST_VERSION < 103600
202
 
                                        TORRENT_ASSERT(i->path.has_branch_path());
203
 
#else
204
 
                                        TORRENT_ASSERT(i->path.has_parent_path());
205
 
#endif
206
 
                                        TORRENT_ASSERT(*i->path.begin() == m_files.name());
207
 
 
208
 
                                        for (fs::path::iterator j = boost::next(i->path.begin());
209
 
                                                j != i->path.end(); ++j)
210
 
                                        {
211
 
                                                path_e.list().push_back(entry(*j));
212
 
                                        }
213
 
                                }
214
 
                        }
215
 
                }
216
 
 
217
 
                info["piece length"] = m_files.piece_length();
218
 
                entry& pieces = info["pieces"];
219
 
 
220
 
                std::string& p = pieces.string();
221
 
 
222
 
                for (std::vector<sha1_hash>::const_iterator i = m_piece_hash.begin();
223
 
                        i != m_piece_hash.end(); ++i)
224
 
                {
225
 
                        p.append((char*)i->begin(), (char*)i->end());
226
 
                }
227
 
 
228
 
                std::vector<char> buf;
229
 
                bencode(std::back_inserter(buf), info);
230
 
                m_info_hash = hasher(&buf[0], buf.size()).final();
231
 
 
232
 
                return dict;
233
 
        
234
 
        }
235
 
 
236
 
        void create_torrent::add_tracker(std::string const& url, int tier)
237
 
        {
238
 
                m_urls.push_back(announce_entry(url, tier));
239
 
 
240
 
                using boost::bind;
241
 
                std::sort(m_urls.begin(), m_urls.end()
242
 
                        , bind(&announce_entry::second, _1) < bind(&announce_entry::second, _2));
243
 
        }
244
 
 
245
 
        void create_torrent::set_hash(int index, sha1_hash const& h)
246
 
        {
247
 
                TORRENT_ASSERT(index >= 0);
248
 
                TORRENT_ASSERT(index < (int)m_piece_hash.size());
249
 
                m_piece_hash[index] = h;
250
 
        }
251
 
 
252
 
        void create_torrent::add_node(std::pair<std::string, int> const& node)
253
 
        {
254
 
                m_nodes.push_back(node);
255
 
        }
256
 
 
257
 
        void create_torrent::add_url_seed(std::string const& url)
258
 
        {
259
 
                m_url_seeds.push_back(url);
260
 
        }
261
 
 
262
 
        void create_torrent::set_comment(char const* str)
263
 
        {
264
 
                m_comment = str;
265
 
        }
266
 
 
267
 
        void create_torrent::set_creator(char const* str)
268
 
        {
269
 
                m_created_by = str;
270
 
        }
271
 
 
272
 
}
273