*** empty log message ***

This commit is contained in:
Arvid Norberg 2004-01-13 03:08:59 +00:00
parent b6c826c6af
commit abbedbf104
13 changed files with 234 additions and 124 deletions

View File

@ -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>

View File

@ -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,8 +1395,8 @@ 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 |
| | layout: | | | layout: |
@ -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. | |
| | +-------------+--------------------------------------------+ | | | +-------------+--------------------------------------------+ |
| | |
+----------------------+--------------------------------------------------------------+ +----------------------+--------------------------------------------------------------+

View File

@ -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)
out.unsetf(std::ios_base::skipws); {
bencode(std::ostream_iterator<char>(out), data); 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);
bencode(std::ostream_iterator<char>(out), data);
}
break; break;
} }
} }

View File

@ -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(

View File

@ -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;

View File

@ -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;
}; };

View File

@ -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.

View File

@ -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,13 +656,32 @@ 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);
picker.mark_as_finished(block_finished, m_socket->sender()); picker.mark_as_finished(block_finished, m_socket->sender());
@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;
} }

View File

@ -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
++i; // it will remove itself from this torrent
m_ses.m_connections.erase(j); // and from the list we're iterating over.
assert(m_connections.size() + 1 == num_connections); // so we need to increment the iterator riht
assert(std::find(m_connections.begin(), m_connections.end(), pc) == m_connections.end()); // away.
} ++i;
else
{ m_ses.m_connections.erase(j);
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();

View File

@ -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