forked from premiere/premiere-libtorrent
*** empty log message ***
This commit is contained in:
parent
5cde50ee01
commit
95026395f3
|
@ -203,7 +203,15 @@ int main(int argc, char* argv[])
|
|||
entry e = bdecode(std::istream_iterator<char>(in), std::istream_iterator<char>());
|
||||
torrent_info t(e);
|
||||
t.print(std::cout);
|
||||
handles.push_back(ses.add_torrent(t, ""));
|
||||
|
||||
std::ifstream resume_file("test.fastresume", std::ios_base::binary);
|
||||
resume_file.unsetf(std::ios_base::skipws);
|
||||
std::vector<char> resume_data;
|
||||
std::copy(std::istream_iterator<char>(resume_file)
|
||||
, std::istream_iterator<char>()
|
||||
, std::back_inserter(resume_data));
|
||||
|
||||
handles.push_back(ses.add_torrent(t, "", resume_data));
|
||||
handles.back().set_max_uploads(40);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
|
@ -220,7 +228,16 @@ int main(int argc, char* argv[])
|
|||
char c;
|
||||
if (sleep_and_input(&c))
|
||||
{
|
||||
if (c == 'q') break;
|
||||
if (c == 'q')
|
||||
{
|
||||
std::vector<char> data;
|
||||
handles.front().write_resume_data(data);
|
||||
|
||||
std::ofstream out("test.fastresume", std::ios_base::binary);
|
||||
out.unsetf(std::ios_base::skipws);
|
||||
std::copy(data.begin(), data.end(), std::ostream_iterator<char>(out));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::auto_ptr<alert> a;
|
||||
|
|
|
@ -75,6 +75,44 @@ namespace libtorrent
|
|||
namespace detail
|
||||
{
|
||||
struct session_impl;
|
||||
|
||||
// reads an integer from a byte stream
|
||||
// in big endian byte order and converts
|
||||
// it to native endianess
|
||||
template<class InIt>
|
||||
unsigned int read_uint(InIt& start)
|
||||
{
|
||||
unsigned int val = 0;
|
||||
val |= static_cast<unsigned char>(*start) << 24; ++start;
|
||||
val |= static_cast<unsigned char>(*start) << 16; ++start;
|
||||
val |= static_cast<unsigned char>(*start) << 8; ++start;
|
||||
val |= static_cast<unsigned char>(*start); ++start;
|
||||
return val;
|
||||
}
|
||||
|
||||
template<class InIt>
|
||||
inline int read_int(InIt& start)
|
||||
{
|
||||
return static_cast<int>(read_uint(start));
|
||||
}
|
||||
|
||||
// reads an integer to a byte stream
|
||||
// and converts it from native endianess
|
||||
template<class OutIt>
|
||||
void write_uint(unsigned int val, OutIt& start)
|
||||
{
|
||||
*start = static_cast<unsigned char>((val >> 24) & 0xff); ++start;
|
||||
*start = static_cast<unsigned char>((val >> 16) & 0xff); ++start;
|
||||
*start = static_cast<unsigned char>((val >> 8) & 0xff); ++start;
|
||||
*start = static_cast<unsigned char>((val) & 0xff); ++start;
|
||||
}
|
||||
|
||||
template<class OutIt>
|
||||
inline void write_int(int val, OutIt& start)
|
||||
{
|
||||
write_uint(reinterpret_cast<unsigned int&>(val), start);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct protocol_error: std::runtime_error
|
||||
|
|
|
@ -59,10 +59,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/fingerprint.hpp"
|
||||
#include "libtorrent/debug.hpp"
|
||||
|
||||
#if defined(_MSC_VER) && !defined(NDEBUG)
|
||||
|
||||
#include <eh.h>
|
||||
|
||||
#if !defined(NDEBUG) && defined(_MSC_VER)
|
||||
# include <float.h>
|
||||
# include <eh.h>
|
||||
#endif
|
||||
|
||||
// TODO: if we're a seed and the peer is a seed, close the connections
|
||||
|
@ -75,12 +74,15 @@ namespace libtorrent
|
|||
// workaround for microsofts
|
||||
// hardware exceptions that makes
|
||||
// it hard to debug stuff
|
||||
#if defined(_MSC_VER) && !defined(NDEBUG)
|
||||
|
||||
#if !defined(NDEBUG) && defined(MSC_VER)
|
||||
struct eh_initializer
|
||||
{
|
||||
eh_initializer()
|
||||
{ ::_set_se_translator(straight_to_debugger); }
|
||||
{
|
||||
_clearfp();
|
||||
_controlfp(_EM_INEXACT | _EM_UNDERFLOW, _MCW_EM );
|
||||
::_set_se_translator(straight_to_debugger);
|
||||
}
|
||||
|
||||
static void straight_to_debugger(unsigned int, _EXCEPTION_POINTERS*)
|
||||
{ throw; }
|
||||
|
@ -100,6 +102,12 @@ namespace libtorrent
|
|||
|
||||
sha1_hash info_hash;
|
||||
|
||||
void parse_resume_data(
|
||||
const std::vector<char>* rd
|
||||
, const torrent_info& info);
|
||||
std::vector<int> piece_map;
|
||||
std::vector<piece_picker::downloading_piece> unfinished_pieces;
|
||||
|
||||
// is filled in by storage::initialize_pieces()
|
||||
// and represents the progress. It should be a
|
||||
// value in the range [0, 1]
|
||||
|
@ -206,7 +214,19 @@ namespace libtorrent
|
|||
// all torrent_handles must be destructed before the session is destructed!
|
||||
torrent_handle add_torrent(
|
||||
const torrent_info& ti
|
||||
, const boost::filesystem::path& save_path);
|
||||
, const boost::filesystem::path& save_path)
|
||||
{
|
||||
return add_torrent_impl(ti, save_path, 0);
|
||||
}
|
||||
|
||||
torrent_handle add_torrent(
|
||||
const torrent_info& ti
|
||||
, const boost::filesystem::path& save_path
|
||||
, const std::vector<char>& resume_data)
|
||||
{
|
||||
return add_torrent_impl(ti, save_path, &resume_data);
|
||||
}
|
||||
|
||||
void remove_torrent(const torrent_handle& h);
|
||||
|
||||
void set_http_settings(const http_settings& s);
|
||||
|
@ -219,6 +239,11 @@ namespace libtorrent
|
|||
|
||||
private:
|
||||
|
||||
torrent_handle add_torrent_impl(
|
||||
const torrent_info& ti
|
||||
, const boost::filesystem::path& save_path
|
||||
, const std::vector<char>* resume_data);
|
||||
|
||||
// data shared between the main thread
|
||||
// and the working thread
|
||||
detail::session_impl m_impl;
|
||||
|
|
|
@ -231,7 +231,7 @@ namespace libtorrent
|
|||
, std::vector<boost::shared_ptr<socket> >& writable
|
||||
, std::vector<boost::shared_ptr<socket> >& error);
|
||||
|
||||
int count_read_monitors() const { return m_readable.size(); }
|
||||
int count_read_monitors() const { return (int)m_readable.size(); }
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -101,7 +101,8 @@ namespace libtorrent
|
|||
|
||||
// fills the vector that maps all allocated
|
||||
// slots to the piece that is stored (or
|
||||
// partially stored) there
|
||||
// partially stored) there. -2 is the index
|
||||
// of unassigned pieces and -1 is unallocated
|
||||
void export_piece_map(std::vector<int>& pieces) const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -133,6 +133,8 @@ namespace libtorrent
|
|||
const torrent_info& get_torrent_info() const;
|
||||
bool is_valid() const;
|
||||
|
||||
void write_resume_data(std::vector<char>& buf);
|
||||
|
||||
// TODO: add force reannounce
|
||||
|
||||
// TODO: add a feature where the user can ask the torrent
|
||||
|
|
|
@ -106,7 +106,7 @@ namespace libtorrent
|
|||
reverse_file_iterator rend_files() const { return m_files.rend(); }
|
||||
|
||||
std::size_t num_files() const { return m_files.size(); }
|
||||
const file& file_at(int index) const { assert(index >= 0 && index < m_files.size()); return m_files[index]; }
|
||||
const file& file_at(int index) const { assert(index >= 0 && index < (int)m_files.size()); return m_files[index]; }
|
||||
|
||||
const std::vector<announce_entry>& trackers() const { return m_urls; }
|
||||
|
||||
|
@ -117,7 +117,7 @@ namespace libtorrent
|
|||
|
||||
entry::integer_type total_size() const { return m_total_size; }
|
||||
entry::integer_type piece_length() const { return m_piece_length; }
|
||||
std::size_t num_pieces() const { return m_piece_hash.size(); }
|
||||
int num_pieces() const { return (int)m_piece_hash.size(); }
|
||||
const sha1_hash& info_hash() const { return m_info_hash; }
|
||||
const std::string& name() const { return m_name; }
|
||||
void print(std::ostream& os) const;
|
||||
|
|
|
@ -46,32 +46,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
using namespace libtorrent;
|
||||
|
||||
namespace
|
||||
{
|
||||
// reads an integer from a byte stream
|
||||
// in big endian byte order and converts
|
||||
// it to native endianess
|
||||
unsigned int read_int(const char* buf)
|
||||
{
|
||||
unsigned int val = 0;
|
||||
val |= static_cast<unsigned char>(buf[0]) << 24;
|
||||
val |= static_cast<unsigned char>(buf[1]) << 16;
|
||||
val |= static_cast<unsigned char>(buf[2]) << 8;
|
||||
val |= static_cast<unsigned char>(buf[3]);
|
||||
return val;
|
||||
}
|
||||
|
||||
void write_int(unsigned int val, char* buf)
|
||||
{
|
||||
buf[0] = static_cast<unsigned char>(val >> 24);
|
||||
buf[1] = static_cast<unsigned char>(val >> 16);
|
||||
buf[2] = static_cast<unsigned char>(val >> 8);
|
||||
buf[3] = static_cast<unsigned char>(val);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
libtorrent::peer_connection::peer_connection(
|
||||
detail::session_impl& ses
|
||||
, selector& sel
|
||||
|
@ -241,8 +215,9 @@ boost::optional<piece_block_progress> libtorrent::peer_connection::downloading_p
|
|||
|| m_recv_buffer[0] != msg_piece)
|
||||
return boost::optional<piece_block_progress>();
|
||||
|
||||
int piece_index = read_int(&m_recv_buffer[1]);
|
||||
int offset = read_int(&m_recv_buffer[5]);
|
||||
const char* ptr = &m_recv_buffer[1];
|
||||
int piece_index = detail::read_int(ptr);
|
||||
int offset = detail::read_int(ptr);
|
||||
int len = m_packet_size - 9;
|
||||
|
||||
// is any of the piece message header data invalid?
|
||||
|
@ -363,9 +338,10 @@ bool libtorrent::peer_connection::dispatch_message(int received)
|
|||
m_statistics.received_bytes(0, received);
|
||||
if (m_recv_pos < m_packet_size) return false;
|
||||
|
||||
std::size_t index = read_int(&m_recv_buffer[1]);
|
||||
const char* ptr = &m_recv_buffer[1];
|
||||
int index = detail::read_int(ptr);
|
||||
// if we got an invalid message, abort
|
||||
if (index >= m_have_piece.size())
|
||||
if (index >= m_have_piece.size() || index < 0)
|
||||
throw protocol_error("have message with higher index than the number of pieces");
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
@ -458,9 +434,10 @@ bool libtorrent::peer_connection::dispatch_message(int received)
|
|||
if (m_recv_pos < m_packet_size) return false;
|
||||
|
||||
peer_request r;
|
||||
r.piece = read_int(&m_recv_buffer[1]);
|
||||
r.start = read_int(&m_recv_buffer[5]);
|
||||
r.length = read_int(&m_recv_buffer[9]);
|
||||
const char* ptr = &m_recv_buffer[1];
|
||||
r.piece = detail::read_int(ptr);
|
||||
r.start = detail::read_int(ptr);
|
||||
r.length = detail::read_int(ptr);
|
||||
|
||||
// make sure this request
|
||||
// is legal and taht the peer
|
||||
|
@ -515,7 +492,8 @@ bool libtorrent::peer_connection::dispatch_message(int received)
|
|||
|
||||
if (m_recv_pos < m_packet_size) return false;
|
||||
|
||||
std::size_t index = read_int(&m_recv_buffer[1]);
|
||||
const char* ptr = &m_recv_buffer[1];
|
||||
int index = detail::read_int(ptr);
|
||||
if (index < 0 || index >= m_torrent->torrent_file().num_pieces())
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
|
@ -523,7 +501,7 @@ bool libtorrent::peer_connection::dispatch_message(int received)
|
|||
#endif
|
||||
throw protocol_error("invalid piece index in piece message");
|
||||
}
|
||||
int offset = read_int(&m_recv_buffer[5]);
|
||||
int offset = detail::read_int(ptr);
|
||||
int len = m_packet_size - 9;
|
||||
|
||||
if (offset < 0)
|
||||
|
@ -629,9 +607,10 @@ bool libtorrent::peer_connection::dispatch_message(int received)
|
|||
if (m_recv_pos < m_packet_size) return false;
|
||||
|
||||
peer_request r;
|
||||
r.piece = read_int(&m_recv_buffer[1]);
|
||||
r.start = read_int(&m_recv_buffer[5]);
|
||||
r.length = read_int(&m_recv_buffer[9]);
|
||||
const char* ptr = &m_recv_buffer[1];
|
||||
r.piece = detail::read_int(ptr);
|
||||
r.start = detail::read_int(ptr);
|
||||
r.length = detail::read_int(ptr);
|
||||
|
||||
std::deque<peer_request>::iterator i
|
||||
= std::find(m_requests.begin(), m_requests.end(), r);
|
||||
|
@ -686,21 +665,18 @@ void libtorrent::peer_connection::cancel_block(piece_block block)
|
|||
std::copy(buf, buf + 5, m_send_buffer.begin()+start_offset);
|
||||
start_offset += 5;
|
||||
|
||||
char* ptr = &m_send_buffer[start_offset];
|
||||
|
||||
// index
|
||||
write_int(block.piece_index, &m_send_buffer[start_offset]);
|
||||
start_offset += 4;
|
||||
|
||||
detail::write_int(block.piece_index, ptr);
|
||||
// begin
|
||||
write_int(block_offset, &m_send_buffer[start_offset]);
|
||||
start_offset += 4;
|
||||
|
||||
detail::write_int(block_offset, ptr);
|
||||
// length
|
||||
write_int(block_size, &m_send_buffer[start_offset]);
|
||||
start_offset += 4;
|
||||
detail::write_int(block_size, ptr);
|
||||
|
||||
#ifndef NDEBUG
|
||||
(*m_logger) << m_socket->sender().as_string() << " ==> CANCEL [ piece: " << block.piece_index << " | s: " << block_offset << " | l: " << block_size << " | " << block.block_index << " ]\n";
|
||||
#endif
|
||||
assert(start_offset == m_send_buffer.size());
|
||||
|
||||
send_buffer_updated();
|
||||
}
|
||||
|
@ -728,23 +704,20 @@ void libtorrent::peer_connection::request_block(piece_block block)
|
|||
m_send_buffer.resize(start_offset + 17);
|
||||
|
||||
std::copy(buf, buf + 5, m_send_buffer.begin()+start_offset);
|
||||
start_offset +=5;
|
||||
|
||||
char* ptr = &m_send_buffer[start_offset+5];
|
||||
// index
|
||||
write_int(block.piece_index, &m_send_buffer[start_offset]);
|
||||
start_offset += 4;
|
||||
detail::write_int(block.piece_index, ptr);
|
||||
|
||||
// begin
|
||||
write_int(block_offset, &m_send_buffer[start_offset]);
|
||||
start_offset += 4;
|
||||
detail::write_int(block_offset, ptr);
|
||||
|
||||
// length
|
||||
write_int(block_size, &m_send_buffer[start_offset]);
|
||||
start_offset += 4;
|
||||
detail::write_int(block_size, ptr);
|
||||
|
||||
#ifndef NDEBUG
|
||||
(*m_logger) << m_socket->sender().as_string() << " ==> REQUEST [ piece: " << block.piece_index << " | s: " << block_offset << " | l: " << block_size << " | " << block.block_index << " ]\n";
|
||||
#endif
|
||||
assert(start_offset == m_send_buffer.size());
|
||||
|
||||
send_buffer_updated();
|
||||
}
|
||||
|
@ -757,7 +730,8 @@ void libtorrent::peer_connection::send_bitfield()
|
|||
const int packet_size = (m_have_piece.size() + 7) / 8 + 5;
|
||||
const int old_size = m_send_buffer.size();
|
||||
m_send_buffer.resize(old_size + packet_size);
|
||||
write_int(packet_size - 4, &m_send_buffer[old_size]);
|
||||
char* ptr = &m_send_buffer[old_size];
|
||||
detail::write_int(packet_size - 4, ptr);
|
||||
m_send_buffer[old_size+4] = msg_bitfield;
|
||||
std::fill(m_send_buffer.begin()+old_size+5, m_send_buffer.end(), 0);
|
||||
for (std::size_t i = 0; i < m_have_piece.size(); ++i)
|
||||
|
@ -821,7 +795,8 @@ void libtorrent::peer_connection::send_have(int index)
|
|||
{
|
||||
const int packet_size = 9;
|
||||
char msg[packet_size] = {0,0,0,5,msg_have};
|
||||
write_int(index, msg+5);
|
||||
char* ptr = msg+5;
|
||||
detail::write_int(index, ptr);
|
||||
m_send_buffer.insert(m_send_buffer.end(), msg, msg + packet_size);
|
||||
#ifndef NDEBUG
|
||||
(*m_logger) << m_socket->sender().as_string() << " ==> HAVE [ piece: " << index << " ]\n";
|
||||
|
@ -1082,12 +1057,14 @@ void libtorrent::peer_connection::receive_data()
|
|||
|
||||
|
||||
case read_packet_size:
|
||||
{
|
||||
m_statistics.received_bytes(0, received);
|
||||
if (m_recv_pos < m_packet_size) break;
|
||||
assert(m_recv_pos == m_packet_size);
|
||||
|
||||
// convert from big endian to native byte order
|
||||
m_packet_size = read_int(&m_recv_buffer[0]);
|
||||
const char* ptr = &m_recv_buffer[0];
|
||||
m_packet_size = detail::read_int(ptr);
|
||||
// don't accept packets larger than 1 MB
|
||||
if (m_packet_size > 1024*1024 || m_packet_size < 0)
|
||||
{
|
||||
|
@ -1112,7 +1089,7 @@ void libtorrent::peer_connection::receive_data()
|
|||
m_recv_pos = 0;
|
||||
assert(m_packet_size > 0);
|
||||
break;
|
||||
|
||||
}
|
||||
case read_packet:
|
||||
|
||||
if (dispatch_message(received))
|
||||
|
@ -1183,10 +1160,11 @@ void libtorrent::peer_connection::send_data()
|
|||
const int send_buffer_offset = m_send_buffer.size();
|
||||
const int packet_size = 4 + 5 + 4 + r.length;
|
||||
m_send_buffer.resize(send_buffer_offset + packet_size);
|
||||
write_int(packet_size-4, &m_send_buffer[send_buffer_offset]);
|
||||
m_send_buffer[send_buffer_offset+4] = msg_piece;
|
||||
write_int(r.piece, &m_send_buffer[send_buffer_offset+5]);
|
||||
write_int(r.start, &m_send_buffer[send_buffer_offset+9]);
|
||||
char* ptr = &m_send_buffer[send_buffer_offset];
|
||||
detail::write_int(packet_size-4, ptr);
|
||||
*ptr = msg_piece; ++ptr;
|
||||
detail::write_int(r.piece, ptr);
|
||||
detail::write_int(r.start, ptr);
|
||||
|
||||
m_torrent->filesystem().read(
|
||||
&m_send_buffer[send_buffer_offset+13]
|
||||
|
|
|
@ -87,6 +87,7 @@ namespace
|
|||
}
|
||||
}
|
||||
assert(false);
|
||||
return piece_block(-1, -1);
|
||||
}
|
||||
|
||||
void request_a_block(torrent& t, peer_connection& c)
|
||||
|
|
|
@ -746,9 +746,10 @@ namespace libtorrent
|
|||
// TODO: add a check to see if filenames are accepted on the
|
||||
// current platform.
|
||||
// if the torrent already exists, this will throw duplicate_torrent
|
||||
torrent_handle session::add_torrent(
|
||||
torrent_handle session::add_torrent_impl(
|
||||
const torrent_info& ti
|
||||
, const boost::filesystem::path& save_path)
|
||||
, const boost::filesystem::path& save_path
|
||||
, const std::vector<char>* resume_data)
|
||||
{
|
||||
|
||||
{
|
||||
|
@ -772,13 +773,15 @@ namespace libtorrent
|
|||
// create the torrent and the data associated with
|
||||
// the checker thread and store it before starting
|
||||
// the thread
|
||||
boost::shared_ptr<torrent> torrent_ptr(new torrent(m_impl, ti, save_path));
|
||||
boost::shared_ptr<torrent> torrent_ptr(
|
||||
new torrent(m_impl, ti, save_path));
|
||||
|
||||
detail::piece_checker_data d;
|
||||
d.torrent_ptr = torrent_ptr;
|
||||
d.save_path = save_path;
|
||||
d.info_hash = ti.info_hash();
|
||||
|
||||
d.parse_resume_data(resume_data, torrent_ptr->torrent_file());
|
||||
|
||||
// lock the checker thread
|
||||
boost::mutex::scoped_lock l(m_checker_impl.m_mutex);
|
||||
|
||||
|
@ -877,4 +880,66 @@ namespace libtorrent
|
|||
m_impl.m_alerts.set_severity(s);
|
||||
}
|
||||
|
||||
void detail::piece_checker_data::parse_resume_data(
|
||||
const std::vector<char>* rd
|
||||
, const torrent_info& info)
|
||||
{
|
||||
piece_map.clear();
|
||||
unfinished_pieces.clear();
|
||||
|
||||
std::vector<int> tmp_pieces;
|
||||
std::vector<piece_picker::downloading_piece> tmp_unfinished;
|
||||
|
||||
if (rd == 0) return;
|
||||
|
||||
const std::vector<char>& data = *rd;
|
||||
|
||||
if (data.size() < 3 * 4) return;
|
||||
std::vector<char>::const_iterator ptr = data.begin();
|
||||
|
||||
int num_slots = detail::read_int(ptr);
|
||||
if (num_slots < 0) return;
|
||||
if (data.size() < (3 + num_slots) * 4) return;
|
||||
|
||||
tmp_pieces.reserve(num_slots);
|
||||
for (int i = 0; i < num_slots; ++i)
|
||||
{
|
||||
int index = read_int(ptr);
|
||||
if (index >= info.num_pieces() || index < -2)
|
||||
return;
|
||||
tmp_pieces.push_back(index);
|
||||
}
|
||||
|
||||
int num_blocks_per_piece = read_int(ptr);
|
||||
if (num_blocks_per_piece > 128 || num_blocks_per_piece < 0)
|
||||
return;
|
||||
|
||||
int num_unfinished = read_int(ptr);
|
||||
if (num_unfinished < 0) return;
|
||||
if (data.size() != (3 + num_slots + 1 + num_unfinished) * 4)
|
||||
return;
|
||||
|
||||
tmp_unfinished.reserve(num_unfinished);
|
||||
for (int i = 0; i < num_unfinished; ++i)
|
||||
{
|
||||
piece_picker::downloading_piece p;
|
||||
p.index = detail::read_int(ptr);
|
||||
p.finished_blocks.reset();
|
||||
p.requested_blocks.reset();
|
||||
|
||||
if (p.index < 0
|
||||
|| p.index >= info.num_pieces())
|
||||
return;
|
||||
|
||||
for (int j = 0; j < num_blocks_per_piece / 32; ++j)
|
||||
{
|
||||
unsigned int bits = read_int(ptr);
|
||||
for (int k = 0; k < 32; ++k) p.finished_blocks[j * 32 + k] = true;
|
||||
}
|
||||
tmp_unfinished.push_back(p);
|
||||
}
|
||||
|
||||
piece_map.swap(tmp_pieces);
|
||||
unfinished_pieces.swap(tmp_unfinished);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,10 +105,6 @@ namespace {
|
|||
|
||||
}
|
||||
|
||||
// TODO: implement fast resume. i.e. the possibility to
|
||||
// supply additional information about which pieces are
|
||||
// assigned to which slots.
|
||||
|
||||
namespace libtorrent {
|
||||
|
||||
struct thread_safe_storage
|
||||
|
|
|
@ -128,7 +128,7 @@ namespace
|
|||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
if (std::isalnum(static_cast<unsigned char>(*str))
|
||||
|| std::find(
|
||||
|| std::count(
|
||||
special_chars
|
||||
, special_chars+sizeof(special_chars)-1
|
||||
, *str))
|
||||
|
|
|
@ -51,16 +51,19 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/hasher.hpp"
|
||||
#include "libtorrent/entry.hpp"
|
||||
#include "libtorrent/session.hpp"
|
||||
// TODO: peer_connection is only used because of detail::write_int
|
||||
// and detail::read_int, they should probably be moved to a common
|
||||
// header.
|
||||
#include "libtorrent/peer_connection.hpp"
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1300
|
||||
namespace std
|
||||
{
|
||||
using ::srand;
|
||||
using ::isprint;
|
||||
using ::isalnum;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
|
@ -167,6 +170,71 @@ namespace libtorrent
|
|||
return false;
|
||||
}
|
||||
|
||||
void torrent_handle::write_resume_data(std::vector<char>& buf)
|
||||
{
|
||||
buf.clear();
|
||||
std::vector<int> piece_index;
|
||||
if (m_ses == 0) return;
|
||||
|
||||
boost::mutex::scoped_lock l(m_ses->m_mutex);
|
||||
torrent* t = m_ses->find_torrent(m_info_hash);
|
||||
if (t == 0) return;
|
||||
|
||||
t->filesystem().export_piece_map(piece_index);
|
||||
|
||||
std::back_insert_iterator<std::vector<char> > out(buf);
|
||||
|
||||
// TODO: write file header
|
||||
// TODO: write info hash
|
||||
|
||||
// number of slots
|
||||
int num_slots = piece_index.size();
|
||||
detail::write_int(num_slots, out);
|
||||
|
||||
// the piece indices for each slot (-1 means no index assigned)
|
||||
for (std::vector<int>::iterator i = piece_index.begin();
|
||||
i != piece_index.end();
|
||||
++i)
|
||||
{
|
||||
detail::write_int(*i, out);
|
||||
assert(*i >= -2);
|
||||
assert(*i < t->torrent_file().num_pieces());
|
||||
}
|
||||
|
||||
const piece_picker& p = t->picker();
|
||||
|
||||
const std::vector<piece_picker::downloading_piece>& q
|
||||
= p.get_download_queue();
|
||||
|
||||
// blocks per piece
|
||||
int num_blocks_per_piece =
|
||||
t->torrent_file().piece_length() / t->block_size();
|
||||
detail::write_int(num_blocks_per_piece, out);
|
||||
|
||||
// num unfinished pieces
|
||||
int num_unfinished = q.size();
|
||||
detail::write_int(num_unfinished, out);
|
||||
|
||||
// info for each unfinished piece
|
||||
for (std::vector<piece_picker::downloading_piece>::const_iterator i
|
||||
= q.begin();
|
||||
i != q.end();
|
||||
++i)
|
||||
{
|
||||
// the unsinished piece's index
|
||||
detail::write_int(i->index, out);
|
||||
|
||||
// write
|
||||
for (int j = 0; j < num_blocks_per_piece / 32; ++j)
|
||||
{
|
||||
unsigned int v = 0;
|
||||
for (int k = 0; k < 32; ++k) v |= i->finished_blocks[j*32+k]?(1 << k):0;
|
||||
detail::write_int(v, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boost::filesystem::path torrent_handle::save_path() const
|
||||
{
|
||||
if (m_ses == 0) throw invalid_handle();
|
||||
|
|
|
@ -99,7 +99,7 @@ namespace libtorrent
|
|||
for (entry::list_type::const_iterator k = ll.begin(); k != ll.end(); ++k)
|
||||
{
|
||||
announce_entry e;
|
||||
e.tier = j - l.begin();
|
||||
e.tier = (int)(j - l.begin());
|
||||
e.url = k->string();
|
||||
m_urls.push_back(e);
|
||||
}
|
||||
|
@ -235,7 +235,7 @@ namespace libtorrent
|
|||
|
||||
int torrent_info::prioritize_tracker(int index)
|
||||
{
|
||||
if (index > m_urls.size()) return m_urls.size()-1;
|
||||
if (index > (int)m_urls.size()) return (int)m_urls.size()-1;
|
||||
|
||||
while (index > 0 && m_urls[index].tier == m_urls[index-1].tier)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue