*** empty log message ***
This commit is contained in:
parent
b6c826c6af
commit
abbedbf104
|
@ -1305,10 +1305,8 @@ tells which piece is on which slot. If piece index is -2 it
|
||||||
means it is free, that there's no piece there. If it is -1,
|
means it is free, that there's no piece there. If it is -1,
|
||||||
means the slot isn't allocated on disk yet. The pieces have
|
means the slot isn't allocated on disk yet. The pieces have
|
||||||
to meet the following requirement:</p>
|
to meet the following requirement:</p>
|
||||||
<ul class="last simple">
|
<p class="last">If there's a slot at the position of the piece index,
|
||||||
<li>if there's a slot at the position of the piece index,
|
the piece must be located in that slot.</p>
|
||||||
the piece must be located in that slot.</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr><td><tt class="literal"><span class="pre">peers</span></tt></td>
|
<tr><td><tt class="literal"><span class="pre">peers</span></tt></td>
|
||||||
|
|
|
@ -1104,6 +1104,29 @@ as severity level ``debug``.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
invalid_request_alert
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Thie is a debug alert that is generated by an incoming invalid piece request.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
struct invalid_request_alert: alert
|
||||||
|
{
|
||||||
|
invalid_request_alert(
|
||||||
|
const peer_request& r
|
||||||
|
, const torrent_handle& h
|
||||||
|
, const peer_id& send
|
||||||
|
, const std::string& msg);
|
||||||
|
|
||||||
|
virtual std::auto_ptr<alert> clone() const;
|
||||||
|
|
||||||
|
torrent_handle handle;
|
||||||
|
peer_id sender;
|
||||||
|
peer_request request;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
chat_message_alert
|
chat_message_alert
|
||||||
------------------
|
------------------
|
||||||
|
@ -1372,7 +1395,7 @@ The file format is a bencoded dictionary containing the following fields:
|
||||||
| | means the slot isn't allocated on disk yet. The pieces have |
|
| | means the slot isn't allocated on disk yet. The pieces have |
|
||||||
| | to meet the following requirement: |
|
| | to meet the following requirement: |
|
||||||
| | |
|
| | |
|
||||||
| | * if there's a slot at the position of the piece index, |
|
| | If there's a slot at the position of the piece index, |
|
||||||
| | the piece must be located in that slot. |
|
| | the piece must be located in that slot. |
|
||||||
+----------------------+--------------------------------------------------------------+
|
+----------------------+--------------------------------------------------------------+
|
||||||
| ``peers`` | list of dictionaries. Each dictionary has the following |
|
| ``peers`` | list of dictionaries. Each dictionary has the following |
|
||||||
|
@ -1398,6 +1421,7 @@ The file format is a bencoded dictionary containing the following fields:
|
||||||
| | | | blocks that have been downloaded in this | |
|
| | | | blocks that have been downloaded in this | |
|
||||||
| | | | piece. | |
|
| | | | piece. | |
|
||||||
| | +-------------+--------------------------------------------+ |
|
| | +-------------+--------------------------------------------+ |
|
||||||
|
| | |
|
||||||
+----------------------+--------------------------------------------------------------+
|
+----------------------+--------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
|
||||||
#include "libtorrent/entry.hpp"
|
#include "libtorrent/entry.hpp"
|
||||||
#include "libtorrent/bencode.hpp"
|
#include "libtorrent/bencode.hpp"
|
||||||
|
@ -186,9 +187,9 @@ std::string add_suffix(float val)
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < num_prefix; ++i)
|
for (i = 0; i < num_prefix; ++i)
|
||||||
{
|
{
|
||||||
if (fabs(val) < 1024.f)
|
if (fabs(val) < 1000.f)
|
||||||
return to_string(val, i==0?7:6) + prefix[i];
|
return to_string(val, i==0?7:6) + prefix[i];
|
||||||
val /= 1024.f;
|
val /= 1000.f;
|
||||||
}
|
}
|
||||||
return to_string(val, 6) + prefix[i];
|
return to_string(val, 6) + prefix[i];
|
||||||
}
|
}
|
||||||
|
@ -233,11 +234,13 @@ int main(int argc, char* argv[])
|
||||||
torrent_info t(e);
|
torrent_info t(e);
|
||||||
t.print(std::cout);
|
t.print(std::cout);
|
||||||
|
|
||||||
|
boost::filesystem::path save_path("");
|
||||||
entry resume_data;
|
entry resume_data;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// TODO: use a torrent-specific name here
|
std::stringstream s;
|
||||||
std::ifstream resume_file("test.fastresume", std::ios_base::binary);
|
s << t.name() << ".fastresume";
|
||||||
|
boost::filesystem::ifstream resume_file(save_path / s.str(), std::ios_base::binary);
|
||||||
resume_file.unsetf(std::ios_base::skipws);
|
resume_file.unsetf(std::ios_base::skipws);
|
||||||
resume_data = bdecode(std::istream_iterator<char>(resume_file)
|
resume_data = bdecode(std::istream_iterator<char>(resume_file)
|
||||||
, std::istream_iterator<char>());
|
, std::istream_iterator<char>());
|
||||||
|
@ -245,7 +248,7 @@ int main(int argc, char* argv[])
|
||||||
catch (invalid_encoding&)
|
catch (invalid_encoding&)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
handles.push_back(ses.add_torrent(t, "", resume_data));
|
handles.push_back(ses.add_torrent(t, save_path, resume_data));
|
||||||
handles.back().set_max_uploads(7);
|
handles.back().set_max_uploads(7);
|
||||||
handles.back().set_ratio(1);
|
handles.back().set_ratio(1);
|
||||||
}
|
}
|
||||||
|
@ -265,11 +268,18 @@ int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
if (c == 'q')
|
if (c == 'q')
|
||||||
{
|
{
|
||||||
entry data = handles.front().write_resume_data();
|
for (std::vector<torrent_handle>::iterator i = handles.begin();
|
||||||
// TODO: use a torrent-specific name here
|
i != handles.end();
|
||||||
std::ofstream out("test.fastresume", std::ios_base::binary);
|
++i)
|
||||||
|
{
|
||||||
|
torrent_handle h = *i;
|
||||||
|
entry data = h.write_resume_data();
|
||||||
|
std::stringstream s;
|
||||||
|
s << h.get_torrent_info().name() << ".fastresume";
|
||||||
|
boost::filesystem::ofstream out(h.save_path() / s.str(), std::ios_base::binary);
|
||||||
out.unsetf(std::ios_base::skipws);
|
out.unsetf(std::ios_base::skipws);
|
||||||
bencode(std::ostream_iterator<char>(out), data);
|
bencode(std::ostream_iterator<char>(out), data);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,7 +168,6 @@ namespace libtorrent
|
||||||
peer_id sender;
|
peer_id sender;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: document
|
|
||||||
struct invalid_request_alert: alert
|
struct invalid_request_alert: alert
|
||||||
{
|
{
|
||||||
invalid_request_alert(
|
invalid_request_alert(
|
||||||
|
|
|
@ -37,6 +37,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
#include "libtorrent/peer_id.hpp"
|
#include "libtorrent/peer_id.hpp"
|
||||||
#include "libtorrent/socket.hpp"
|
#include "libtorrent/socket.hpp"
|
||||||
|
|
||||||
|
@ -166,10 +168,13 @@ namespace libtorrent
|
||||||
// the hash-check yet
|
// the hash-check yet
|
||||||
int unverified_blocks() const;
|
int unverified_blocks() const;
|
||||||
|
|
||||||
void get_downloaders(std::vector<address>& d, int index);
|
void get_downloaders(std::vector<address>& d, int index) const;
|
||||||
|
|
||||||
const std::vector<downloading_piece>& get_download_queue() const
|
const std::vector<downloading_piece>& get_download_queue() const
|
||||||
{ return m_downloads; }
|
{ return m_downloads; }
|
||||||
|
|
||||||
|
boost::optional<address> get_downloader(piece_block block) const;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// used in debug mode
|
// used in debug mode
|
||||||
void integrity_check(const torrent* t = 0) const;
|
void integrity_check(const torrent* t = 0) const;
|
||||||
|
|
|
@ -55,7 +55,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
file_allocation_failed(const char* error_msg): m_msg(error_msg) {}
|
file_allocation_failed(const char* error_msg): m_msg(error_msg) {}
|
||||||
virtual const char* what() const throw() { return m_msg.c_str(); }
|
virtual const char* what() const throw() { return m_msg.c_str(); }
|
||||||
virtual ~file_allocation_failed() {}
|
virtual ~file_allocation_failed() throw() {}
|
||||||
std::string m_msg;
|
std::string m_msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -173,6 +173,13 @@ namespace libtorrent
|
||||||
// decreased in the piece_picker
|
// decreased in the piece_picker
|
||||||
void remove_peer(peer_connection* p);
|
void remove_peer(peer_connection* p);
|
||||||
|
|
||||||
|
peer_connection* connection_for(const address& a)
|
||||||
|
{
|
||||||
|
peer_iterator i = m_connections.find(a);
|
||||||
|
if (i == m_connections.end()) return 0;
|
||||||
|
return i->second;
|
||||||
|
}
|
||||||
|
|
||||||
// the number of peers that belong to this torrent
|
// the number of peers that belong to this torrent
|
||||||
int num_peers() const { return m_connections.size(); }
|
int num_peers() const { return m_connections.size(); }
|
||||||
|
|
||||||
|
@ -180,11 +187,11 @@ namespace libtorrent
|
||||||
// to a peer with the given peer_id
|
// to a peer with the given peer_id
|
||||||
bool has_peer(const peer_id& id) const;
|
bool has_peer(const peer_id& id) const;
|
||||||
|
|
||||||
typedef std::vector<peer_connection*>::iterator peer_iterator;
|
typedef std::map<address, peer_connection*>::iterator peer_iterator;
|
||||||
typedef std::vector<peer_connection*>::const_iterator peer_const_iterator;
|
typedef std::map<address, peer_connection*>::const_iterator const_peer_iterator;
|
||||||
|
|
||||||
peer_const_iterator begin() const { return m_connections.begin(); }
|
const_peer_iterator begin() const { return m_connections.begin(); }
|
||||||
peer_const_iterator end() const { return m_connections.end(); }
|
const_peer_iterator end() const { return m_connections.end(); }
|
||||||
|
|
||||||
peer_iterator begin() { return m_connections.begin(); }
|
peer_iterator begin() { return m_connections.begin(); }
|
||||||
peer_iterator end() { return m_connections.end(); }
|
peer_iterator end() { return m_connections.end(); }
|
||||||
|
@ -311,7 +318,10 @@ namespace libtorrent
|
||||||
// from the tracker
|
// from the tracker
|
||||||
int m_duration;
|
int m_duration;
|
||||||
|
|
||||||
std::vector<peer_connection*> m_connections;
|
// TODO: this should be a map, mapping address
|
||||||
|
// to peer_connection*
|
||||||
|
std::map<address, peer_connection*> m_connections;
|
||||||
|
// std::vector<peer_connection*> m_connections;
|
||||||
|
|
||||||
// this is the upload and download statistics for the whole torrent.
|
// this is the upload and download statistics for the whole torrent.
|
||||||
// it's updated from all its peers once every second.
|
// it's updated from all its peers once every second.
|
||||||
|
|
|
@ -33,7 +33,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
#include "libtorrent/peer_connection.hpp"
|
#include "libtorrent/peer_connection.hpp"
|
||||||
|
@ -620,8 +619,8 @@ namespace libtorrent
|
||||||
&& i->block_index == p.start / m_torrent->block_size())
|
&& i->block_index == p.start / m_torrent->block_size())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
(*m_logger) << " <== SKIPPED_PIECE [ piece: " << i->piece_index << " | "
|
(*m_logger) << " *** SKIPPED_PIECE [ piece: " << i->piece_index << " | "
|
||||||
"b: " << i->block_index << " ]\n";
|
"b: " << i->block_index << " ] ***\n";
|
||||||
if (m_torrent->alerts().should_post(alert::debug))
|
if (m_torrent->alerts().should_post(alert::debug))
|
||||||
{
|
{
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
|
@ -640,6 +639,9 @@ namespace libtorrent
|
||||||
piece_picker& picker = m_torrent->picker();
|
piece_picker& picker = m_torrent->picker();
|
||||||
piece_block block_finished(p.piece, p.start / m_torrent->block_size());
|
piece_block block_finished(p.piece, p.start / m_torrent->block_size());
|
||||||
|
|
||||||
|
// if the block we got is already finished, then ignore it
|
||||||
|
if (picker.is_finished(block_finished)) return;
|
||||||
|
|
||||||
std::deque<piece_block>::iterator b
|
std::deque<piece_block>::iterator b
|
||||||
= std::find(
|
= std::find(
|
||||||
m_download_queue.begin()
|
m_download_queue.begin()
|
||||||
|
@ -654,12 +656,31 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO: cancel the block from the
|
// cancel the block from the
|
||||||
// peer that has taken over it.
|
// peer that has taken over it.
|
||||||
|
boost::optional<address> peer = m_torrent->picker().get_downloader(block_finished);
|
||||||
|
if (peer)
|
||||||
|
{
|
||||||
|
peer_connection* pc = m_torrent->connection_for(*peer);
|
||||||
|
if (pc && pc != this)
|
||||||
|
{
|
||||||
|
pc->send_cancel(block_finished);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_torrent->alerts().should_post(alert::debug))
|
||||||
|
{
|
||||||
|
m_torrent->alerts().post_alert(
|
||||||
|
peer_error_alert(
|
||||||
|
m_peer_id
|
||||||
|
, "got a block that was not requested"));
|
||||||
|
}
|
||||||
|
#ifndef NDEBUG
|
||||||
|
(*m_logger) << " *** The block we just got was not requested ***\n";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the block we got is already finished, then ignore it
|
|
||||||
if (picker.is_finished(block_finished)) return;
|
|
||||||
|
|
||||||
m_torrent->filesystem().write(&m_recv_buffer[9], p.piece, p.start, p.length);
|
m_torrent->filesystem().write(&m_recv_buffer[9], p.piece, p.start, p.length);
|
||||||
|
|
||||||
|
@ -1026,7 +1047,6 @@ namespace libtorrent
|
||||||
send_buffer_updated();
|
send_buffer_updated();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: rename to send_choke?
|
|
||||||
void peer_connection::send_choke()
|
void peer_connection::send_choke()
|
||||||
{
|
{
|
||||||
if (m_choked) return;
|
if (m_choked) return;
|
||||||
|
|
|
@ -152,11 +152,11 @@ namespace libtorrent
|
||||||
if (t != 0)
|
if (t != 0)
|
||||||
{
|
{
|
||||||
int actual_peer_count = 0;
|
int actual_peer_count = 0;
|
||||||
for (std::vector<peer_connection*>::const_iterator peer = t->begin();
|
for (torrent::const_peer_iterator peer = t->begin();
|
||||||
peer != t->end();
|
peer != t->end();
|
||||||
++peer)
|
++peer)
|
||||||
{
|
{
|
||||||
if ((*peer)->has_piece(index)) actual_peer_count++;
|
if (peer->second->has_piece(index)) actual_peer_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(i->peer_count == actual_peer_count);
|
assert(i->peer_count == actual_peer_count);
|
||||||
|
@ -518,7 +518,11 @@ namespace libtorrent
|
||||||
|
|
||||||
if (m_piece_map[block.piece_index].downloading == 0) return false;
|
if (m_piece_map[block.piece_index].downloading == 0) return false;
|
||||||
std::vector<downloading_piece>::const_iterator i
|
std::vector<downloading_piece>::const_iterator i
|
||||||
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index));
|
= std::find_if(
|
||||||
|
m_downloads.begin()
|
||||||
|
, m_downloads.end()
|
||||||
|
, has_index(block.piece_index));
|
||||||
|
|
||||||
assert(i != m_downloads.end());
|
assert(i != m_downloads.end());
|
||||||
return i->requested_blocks[block.block_index];
|
return i->requested_blocks[block.block_index];
|
||||||
}
|
}
|
||||||
|
@ -632,9 +636,9 @@ namespace libtorrent
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
void piece_picker::get_downloaders(std::vector<address>& d, int index)
|
void piece_picker::get_downloaders(std::vector<address>& d, int index) const
|
||||||
{
|
{
|
||||||
std::vector<downloading_piece>::iterator i
|
std::vector<downloading_piece>::const_iterator i
|
||||||
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(index));
|
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(index));
|
||||||
assert(i != m_downloads.end());
|
assert(i != m_downloads.end());
|
||||||
|
|
||||||
|
@ -645,6 +649,26 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::optional<address> piece_picker::get_downloader(piece_block block) const
|
||||||
|
{
|
||||||
|
std::vector<downloading_piece>::const_iterator i = std::find_if(
|
||||||
|
m_downloads.begin()
|
||||||
|
, m_downloads.end()
|
||||||
|
, has_index(block.piece_index));
|
||||||
|
|
||||||
|
if (i == m_downloads.end())
|
||||||
|
return boost::optional<address>();
|
||||||
|
|
||||||
|
assert(block.block_index < max_blocks_per_piece);
|
||||||
|
assert(block.block_index >= 0);
|
||||||
|
|
||||||
|
if (i->requested_blocks[block.block_index] == false
|
||||||
|
|| i->finished_blocks[block.block_index] == true)
|
||||||
|
return boost::optional<address>();
|
||||||
|
|
||||||
|
return boost::optional<address>(i->info[block.block_index].peer);
|
||||||
|
}
|
||||||
|
|
||||||
void piece_picker::abort_download(piece_block block)
|
void piece_picker::abort_download(piece_block block)
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
|
|
@ -168,15 +168,15 @@ namespace
|
||||||
i != t.end();
|
i != t.end();
|
||||||
++i)
|
++i)
|
||||||
{
|
{
|
||||||
const std::deque<piece_block>& queue = (*i)->download_queue();
|
const std::deque<piece_block>& queue = i->second->download_queue();
|
||||||
if ((*i)->statistics().down_peak() > down_speed
|
if (i->second->statistics().down_peak() > down_speed
|
||||||
&& has_intersection(busy_pieces.begin(),
|
&& has_intersection(busy_pieces.begin(),
|
||||||
busy_pieces.end(),
|
busy_pieces.end(),
|
||||||
queue.begin(),
|
queue.begin(),
|
||||||
queue.end()))
|
queue.end()))
|
||||||
{
|
{
|
||||||
peer = *i;
|
peer = i->second;
|
||||||
down_speed = (*i)->statistics().down_peak();
|
down_speed = peer->statistics().down_peak();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,12 +209,12 @@ namespace
|
||||||
// want to trade it's surplus uploads for downloads itself
|
// want to trade it's surplus uploads for downloads itself
|
||||||
// (and we should consider it free). If the share diff is
|
// (and we should consider it free). If the share diff is
|
||||||
// negative, there's no free download to get from this peer.
|
// negative, there's no free download to get from this peer.
|
||||||
int diff = (*i)->share_diff();
|
int diff = i->second->share_diff();
|
||||||
if ((*i)->is_peer_interested() || diff <= 0)
|
if (i->second->is_peer_interested() || diff <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
assert(diff > 0);
|
assert(diff > 0);
|
||||||
(*i)->add_free_upload(-diff);
|
i->second->add_free_upload(-diff);
|
||||||
accumulator += diff;
|
accumulator += diff;
|
||||||
assert(accumulator > 0);
|
assert(accumulator > 0);
|
||||||
}
|
}
|
||||||
|
@ -235,8 +235,8 @@ namespace
|
||||||
int total_diff = 0;
|
int total_diff = 0;
|
||||||
for (torrent::peer_iterator i = start; i != end; ++i)
|
for (torrent::peer_iterator i = start; i != end; ++i)
|
||||||
{
|
{
|
||||||
total_diff += (*i)->share_diff();
|
total_diff += i->second->share_diff();
|
||||||
if (!(*i)->is_peer_interested() || (*i)->share_diff() >= 0) continue;
|
if (!i->second->is_peer_interested() || i->second->share_diff() >= 0) continue;
|
||||||
++num_peers;
|
++num_peers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,8 +254,9 @@ namespace
|
||||||
|
|
||||||
for (torrent::peer_iterator i = start; i != end; ++i)
|
for (torrent::peer_iterator i = start; i != end; ++i)
|
||||||
{
|
{
|
||||||
if (!(*i)->is_peer_interested() || (*i)->share_diff() >= 0) continue;
|
peer_connection* p = i->second;
|
||||||
(*i)->add_free_upload(upload_share);
|
if (!p->is_peer_interested() || p->share_diff() >= 0) continue;
|
||||||
|
p->add_free_upload(upload_share);
|
||||||
free_upload -= upload_share;
|
free_upload -= upload_share;
|
||||||
}
|
}
|
||||||
return free_upload;
|
return free_upload;
|
||||||
|
|
|
@ -43,7 +43,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <boost/filesystem/convenience.hpp>
|
#include <boost/filesystem/convenience.hpp>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
#include <boost/thread/mutex.hpp>
|
#include <boost/thread/mutex.hpp>
|
||||||
#include <boost/bind.hpp>
|
|
||||||
#include <boost/ref.hpp>
|
#include <boost/ref.hpp>
|
||||||
|
|
||||||
#include "libtorrent/storage.hpp"
|
#include "libtorrent/storage.hpp"
|
||||||
|
@ -437,6 +436,8 @@ namespace libtorrent {
|
||||||
boost::recursive_mutex::scoped_lock lock(m_mutex);
|
boost::recursive_mutex::scoped_lock lock(m_mutex);
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
check_invariant();
|
||||||
|
|
||||||
p.clear();
|
p.clear();
|
||||||
std::vector<int>::const_reverse_iterator last;
|
std::vector<int>::const_reverse_iterator last;
|
||||||
for (last = m_slot_to_piece.rbegin();
|
for (last = m_slot_to_piece.rbegin();
|
||||||
|
@ -453,6 +454,9 @@ namespace libtorrent {
|
||||||
{
|
{
|
||||||
p.push_back(*i);
|
p.push_back(*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_invariant();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void piece_manager::export_piece_map(
|
void piece_manager::export_piece_map(
|
||||||
|
@ -462,22 +466,30 @@ namespace libtorrent {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: daniel, make sure this function does everything it needs to do
|
// TODO: daniel, make sure this function does everything it needs to do
|
||||||
void piece_manager::impl::mark_failed(int index)
|
void piece_manager::impl::mark_failed(int piece_index)
|
||||||
{
|
{
|
||||||
// synchronization ------------------------------------------------------
|
// synchronization ------------------------------------------------------
|
||||||
boost::recursive_mutex::scoped_lock lock(m_mutex);
|
boost::recursive_mutex::scoped_lock lock(m_mutex);
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
assert(index >= 0 && index < m_piece_to_slot.size());
|
#ifndef NDEBUG
|
||||||
assert(m_piece_to_slot[index] >= 0);
|
check_invariant();
|
||||||
|
#endif
|
||||||
|
assert(piece_index >= 0 && piece_index < m_piece_to_slot.size());
|
||||||
|
assert(m_piece_to_slot[piece_index] >= 0);
|
||||||
|
|
||||||
int slot = m_slot_to_piece[m_piece_to_slot[index]];
|
int slot_index = m_piece_to_slot[piece_index];
|
||||||
|
|
||||||
assert(slot >= 0);
|
assert(slot_index >= 0);
|
||||||
|
|
||||||
|
m_slot_to_piece[slot_index] = -2;
|
||||||
|
m_piece_to_slot[piece_index] = -1;
|
||||||
|
m_free_slots.push_back(slot_index);
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
check_invariant();
|
||||||
|
#endif
|
||||||
|
|
||||||
m_slot_to_piece[m_piece_to_slot[index]] = -2;
|
|
||||||
m_piece_to_slot[index] = -1;
|
|
||||||
m_free_slots.push_back(slot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void piece_manager::mark_failed(int index)
|
void piece_manager::mark_failed(int index)
|
||||||
|
@ -809,6 +821,9 @@ namespace libtorrent {
|
||||||
{
|
{
|
||||||
assert(slot_index >= 0);
|
assert(slot_index >= 0);
|
||||||
assert(slot_index < m_slot_to_piece.size());
|
assert(slot_index < m_slot_to_piece.size());
|
||||||
|
|
||||||
|
check_invariant();
|
||||||
|
|
||||||
return slot_index;
|
return slot_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
124
src/torrent.cpp
124
src/torrent.cpp
|
@ -167,16 +167,6 @@ namespace
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator()(const peer_connection* p) const
|
|
||||||
{
|
|
||||||
if (p->get_peer_id() != id) return false;
|
|
||||||
if (tor != p->associated_torrent()) return false;
|
|
||||||
// have a special case for all zeros. We can have any number
|
|
||||||
// of peers with that id, since it's used to indicate no id.
|
|
||||||
if (std::count(id.begin(), id.end(), 0) == 20) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const peer_id& id;
|
const peer_id& id;
|
||||||
const torrent* tor;
|
const torrent* tor;
|
||||||
};
|
};
|
||||||
|
@ -196,6 +186,23 @@ namespace
|
||||||
const torrent* tor;
|
const torrent* tor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct peer_by_id
|
||||||
|
{
|
||||||
|
peer_by_id(const peer_id& i): id(i) {}
|
||||||
|
|
||||||
|
bool operator()(const std::pair<address, peer_connection*>& p) const
|
||||||
|
{
|
||||||
|
if (p.second->get_peer_id() != id) return false;
|
||||||
|
// have a special case for all zeros. We can have any number
|
||||||
|
// of peers with that id, since it's used to indicate no id.
|
||||||
|
if (std::count(id.begin(), id.end(), 0) == 20) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const peer_id& id;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
|
@ -313,7 +320,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
assert(std::count_if(m_connections.begin()
|
assert(std::count_if(m_connections.begin()
|
||||||
, m_connections.end()
|
, m_connections.end()
|
||||||
, find_peer_by_id(id, this)) <= 1);
|
, peer_by_id(id)) <= 1);
|
||||||
|
|
||||||
// pretend that we are connected to
|
// pretend that we are connected to
|
||||||
// ourself to avoid real connections
|
// ourself to avoid real connections
|
||||||
|
@ -323,7 +330,7 @@ namespace libtorrent
|
||||||
return std::find_if(
|
return std::find_if(
|
||||||
m_connections.begin()
|
m_connections.begin()
|
||||||
, m_connections.end()
|
, m_connections.end()
|
||||||
, find_peer_by_id(id, this))
|
, peer_by_id(id))
|
||||||
!= m_connections.end();
|
!= m_connections.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,20 +367,19 @@ namespace libtorrent
|
||||||
|
|
||||||
// decrease the trust point of all peers that sent
|
// decrease the trust point of all peers that sent
|
||||||
// parts of this piece.
|
// parts of this piece.
|
||||||
// TODO: implement this loop more efficient
|
for (std::vector<address>::iterator i = downloaders.begin();
|
||||||
for (std::vector<peer_connection*>::iterator i = m_connections.begin();
|
i != downloaders.end();
|
||||||
i != m_connections.end();
|
|
||||||
++i)
|
++i)
|
||||||
{
|
{
|
||||||
if (std::find(downloaders.begin(), downloaders.end(), (*i)->get_socket()->sender())
|
peer_iterator p = m_connections.find(*i);
|
||||||
== downloaders.end()) continue;
|
if (p == m_connections.end()) continue;
|
||||||
|
p->second->received_invalid_data();
|
||||||
|
|
||||||
(*i)->received_invalid_data();
|
if (p->second->trust_points() <= -5)
|
||||||
if ((*i)->trust_points() <= -5)
|
|
||||||
{
|
{
|
||||||
// we don't trust this peer anymore
|
// we don't trust this peer anymore
|
||||||
// ban it.
|
// ban it.
|
||||||
m_policy->ban_peer(*(*i));
|
m_policy->ban_peer(*p->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,22 +407,20 @@ namespace libtorrent
|
||||||
|
|
||||||
// increase the trust point of all peers that sent
|
// increase the trust point of all peers that sent
|
||||||
// parts of this piece.
|
// parts of this piece.
|
||||||
// TODO: implement this loop more efficient
|
for (std::vector<address>::iterator i = downloaders.begin();
|
||||||
for (std::vector<peer_connection*>::iterator i = m_connections.begin();
|
i != downloaders.end();
|
||||||
i != m_connections.end();
|
|
||||||
++i)
|
++i)
|
||||||
{
|
{
|
||||||
if (std::find(downloaders.begin(), downloaders.end(), (*i)->get_socket()->sender())
|
peer_iterator p = m_connections.find(*i);
|
||||||
!= downloaders.end())
|
if (p == m_connections.end()) continue;
|
||||||
{
|
p->second->received_valid_data();
|
||||||
(*i)->received_valid_data();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
m_picker.we_have(index);
|
m_picker.we_have(index);
|
||||||
for (std::vector<peer_connection*>::iterator i = m_connections.begin(); i != m_connections.end(); ++i)
|
for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i)
|
||||||
(*i)->announce_piece(index);
|
i->second->announce_piece(index);
|
||||||
|
|
||||||
|
// TODO: if we became a seed, disconnect from all other seeds
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string torrent::generate_tracker_request(int port)
|
std::string torrent::generate_tracker_request(int port)
|
||||||
|
@ -489,7 +493,7 @@ namespace libtorrent
|
||||||
|
|
||||||
void torrent::remove_peer(peer_connection* p)
|
void torrent::remove_peer(peer_connection* p)
|
||||||
{
|
{
|
||||||
std::vector<peer_connection*>::iterator i = std::find(m_connections.begin(), m_connections.end(), p);
|
peer_iterator i = m_connections.find(p->get_socket()->sender());
|
||||||
assert(i != m_connections.end());
|
assert(i != m_connections.end());
|
||||||
|
|
||||||
// if the peer_connection was downloading any pieces
|
// if the peer_connection was downloading any pieces
|
||||||
|
@ -540,18 +544,20 @@ namespace libtorrent
|
||||||
, this
|
, this
|
||||||
, s
|
, s
|
||||||
, id));
|
, id));
|
||||||
|
|
||||||
if (m_ses.m_upload_rate != -1) c->set_send_quota(0);
|
if (m_ses.m_upload_rate != -1) c->set_send_quota(0);
|
||||||
|
|
||||||
detail::session_impl::connection_map::iterator p =
|
detail::session_impl::connection_map::iterator p =
|
||||||
m_ses.m_connections.insert(std::make_pair(s, c)).first;
|
m_ses.m_connections.insert(std::make_pair(s, c)).first;
|
||||||
|
|
||||||
// add the newly connected peer to this torrent's peer list
|
// add the newly connected peer to this torrent's peer list
|
||||||
assert(std::find(
|
assert(m_connections.find(p->second->get_socket()->sender())
|
||||||
m_connections.begin()
|
|
||||||
, m_connections.end()
|
|
||||||
, boost::get_pointer(p->second))
|
|
||||||
== m_connections.end());
|
== m_connections.end());
|
||||||
|
|
||||||
m_connections.push_back(boost::get_pointer(p->second));
|
m_connections.insert(
|
||||||
|
std::make_pair(
|
||||||
|
p->second->get_socket()->sender()
|
||||||
|
, boost::get_pointer(p->second)));
|
||||||
|
|
||||||
m_ses.m_selector.monitor_readability(s);
|
m_ses.m_selector.monitor_readability(s);
|
||||||
m_ses.m_selector.monitor_errors(s);
|
m_ses.m_selector.monitor_errors(s);
|
||||||
|
@ -561,8 +567,10 @@ namespace libtorrent
|
||||||
|
|
||||||
void torrent::attach_peer(peer_connection* p)
|
void torrent::attach_peer(peer_connection* p)
|
||||||
{
|
{
|
||||||
assert(std::find(m_connections.begin(), m_connections.end(), p) == m_connections.end());
|
assert(m_connections.find(p->get_socket()->sender()) == m_connections.end());
|
||||||
m_connections.push_back(p);
|
|
||||||
|
m_connections.insert(std::make_pair(p->get_socket()->sender(), p));
|
||||||
|
|
||||||
detail::session_impl::connection_map::iterator i
|
detail::session_impl::connection_map::iterator i
|
||||||
= m_ses.m_connections.find(p->get_socket());
|
= m_ses.m_connections.find(p->get_socket());
|
||||||
assert(i != m_ses.m_connections.end());
|
assert(i != m_ses.m_connections.end());
|
||||||
|
@ -572,29 +580,25 @@ namespace libtorrent
|
||||||
|
|
||||||
void torrent::close_all_connections()
|
void torrent::close_all_connections()
|
||||||
{
|
{
|
||||||
for (detail::session_impl::connection_map::iterator i = m_ses.m_connections.begin();
|
for (peer_iterator i = m_connections.begin();
|
||||||
i != m_ses.m_connections.end();)
|
i != m_connections.end();)
|
||||||
{
|
{
|
||||||
if (i->second->associated_torrent() == this)
|
assert(i->second->associated_torrent() == this);
|
||||||
{
|
|
||||||
#ifndef NDEBUG
|
detail::session_impl::connection_map::iterator j =
|
||||||
std::size_t num_connections = m_connections.size();
|
m_ses.m_connections.find(i->second->get_socket());
|
||||||
peer_connection* pc = boost::get_pointer(i->second);
|
|
||||||
#endif
|
assert(j != m_ses.m_connections.end());
|
||||||
assert(std::find(m_connections.begin(), m_connections.end(), pc) != m_connections.end());
|
|
||||||
detail::session_impl::connection_map::iterator j = i;
|
// in the destructor of the peer_connection
|
||||||
|
// it will remove itself from this torrent
|
||||||
|
// and from the list we're iterating over.
|
||||||
|
// so we need to increment the iterator riht
|
||||||
|
// away.
|
||||||
++i;
|
++i;
|
||||||
|
|
||||||
m_ses.m_connections.erase(j);
|
m_ses.m_connections.erase(j);
|
||||||
assert(m_connections.size() + 1 == num_connections);
|
|
||||||
assert(std::find(m_connections.begin(), m_connections.end(), pc) == m_connections.end());
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
assert(std::find(m_connections.begin(), m_connections.end(), boost::get_pointer(i->second)) == m_connections.end());
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(m_connections.empty());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -659,11 +663,11 @@ namespace libtorrent
|
||||||
m_policy->pulse();
|
m_policy->pulse();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::vector<peer_connection*>::iterator i = m_connections.begin();
|
for (peer_iterator i = m_connections.begin();
|
||||||
i != m_connections.end();
|
i != m_connections.end();
|
||||||
++i)
|
++i)
|
||||||
{
|
{
|
||||||
peer_connection* p = (*i);
|
peer_connection* p = i->second;
|
||||||
const stat& s = p->statistics();
|
const stat& s = p->statistics();
|
||||||
m_stat += s;
|
m_stat += s;
|
||||||
p->second_tick();
|
p->second_tick();
|
||||||
|
|
|
@ -243,15 +243,15 @@ namespace libtorrent
|
||||||
ret.dict()["peers"] = entry::list_type();
|
ret.dict()["peers"] = entry::list_type();
|
||||||
entry::list_type& peer_list = ret.dict()["peers"].list();
|
entry::list_type& peer_list = ret.dict()["peers"].list();
|
||||||
|
|
||||||
for (torrent::peer_const_iterator i = t->begin();
|
for (torrent::const_peer_iterator i = t->begin();
|
||||||
i != t->end();
|
i != t->end();
|
||||||
++i)
|
++i)
|
||||||
{
|
{
|
||||||
// we cannot save remote connection
|
// we cannot save remote connection
|
||||||
// since we don't know their listen port
|
// since we don't know their listen port
|
||||||
if (!(*i)->is_local()) continue;
|
if (!i->second->is_local()) continue;
|
||||||
|
|
||||||
address ip = (*i)->get_socket()->sender();
|
address ip = i->second->get_socket()->sender();
|
||||||
entry::dictionary_type peer;
|
entry::dictionary_type peer;
|
||||||
peer["ip"] = ip.as_string();
|
peer["ip"] = ip.as_string();
|
||||||
peer["port"] = ip.port();
|
peer["port"] = ip.port();
|
||||||
|
@ -360,11 +360,11 @@ namespace libtorrent
|
||||||
const torrent* t = m_ses->find_torrent(m_info_hash);
|
const torrent* t = m_ses->find_torrent(m_info_hash);
|
||||||
if (t == 0) return;
|
if (t == 0) return;
|
||||||
|
|
||||||
for (std::vector<peer_connection*>::const_iterator i = t->begin();
|
for (torrent::const_peer_iterator i = t->begin();
|
||||||
i != t->end();
|
i != t->end();
|
||||||
++i)
|
++i)
|
||||||
{
|
{
|
||||||
peer_connection* peer = *i;
|
peer_connection* peer = i->second;
|
||||||
|
|
||||||
// peers that hasn't finished the handshake should
|
// peers that hasn't finished the handshake should
|
||||||
// not be included in this list
|
// not be included in this list
|
||||||
|
|
Loading…
Reference in New Issue