forked from premiere/premiere-libtorrent
*** empty log message ***
This commit is contained in:
parent
b716a40795
commit
fc74e19224
|
@ -181,8 +181,8 @@ The ``session`` class has the following synopsis::
|
||||||
|
|
||||||
class session: public boost::noncopyable
|
class session: public boost::noncopyable
|
||||||
{
|
{
|
||||||
session(int listen_port, const fingerprint& print);
|
session(std::pair<int, int> listen_port_range, const fingerprint& print);
|
||||||
session(int listen_port);
|
session(std::pair<int, int> listen_port_range);
|
||||||
|
|
||||||
torrent_handle add_torrent(
|
torrent_handle add_torrent(
|
||||||
const torrent_info& t
|
const torrent_info& t
|
||||||
|
@ -237,10 +237,12 @@ timeout can be set with ``set_http_settings()``.
|
||||||
The torrent_handle_ returned by ``add_torrent`` can be used to retrieve information
|
The torrent_handle_ returned by ``add_torrent`` can be used to retrieve information
|
||||||
about the torrent's progress, its peers etc. It is also used to abort a torrent.
|
about the torrent's progress, its peers etc. It is also used to abort a torrent.
|
||||||
|
|
||||||
The constructor takes a listen port as argument, if the given port is busy it will
|
The constructor takes a range of listen ports as argument, if the first port is busy it will
|
||||||
increase the port number by one and try again. If it still fails it will continue
|
increase the port number by one and try again. If it still fails it will continue
|
||||||
increasing the port number until it succeeds or has failed 9 ports. *This will
|
increasing the port number until it succeeds or has reached the end of the range. If it
|
||||||
change in the future to give more control of the listen-port.*
|
fails with all ports, a listen_failed_alert_ will be posted and the session thread will
|
||||||
|
exit. The only thing you can do with your session if this alert is posted is to destruct
|
||||||
|
it and possibly try again or change the port range.
|
||||||
|
|
||||||
For information about the ``pop_alert()`` function, see alerts_.
|
For information about the ``pop_alert()`` function, see alerts_.
|
||||||
|
|
||||||
|
@ -1104,6 +1106,43 @@ user in different ways.
|
||||||
The specific alerts, that all derives from ``alert``, are:
|
The specific alerts, that all derives from ``alert``, are:
|
||||||
|
|
||||||
|
|
||||||
|
listen_failed_alert
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
This alert is generated when none of the ports, given in the port range, to
|
||||||
|
session_ can be opened for listening. Without a listening port the session
|
||||||
|
object will exit its thread. This alert is generated as severity level ``fatal``.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
struct listen_failed_alert: alert
|
||||||
|
{
|
||||||
|
listen_failed_alert(const std::string& msg);
|
||||||
|
virtual std::auto_ptr<alert> clone() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
file_error_alert
|
||||||
|
----------------
|
||||||
|
|
||||||
|
If the storage fails to read or write files that it needs access to, this alert is
|
||||||
|
generated and the torrent is aborted. It is generated as severity level ``fatal``.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
struct file_error_alert: alert
|
||||||
|
{
|
||||||
|
file_error_alert(
|
||||||
|
const torrent_handle& h
|
||||||
|
, const std::string& msg);
|
||||||
|
|
||||||
|
virtual std::auto_ptr<alert> clone() const;
|
||||||
|
|
||||||
|
torrent_handle handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
tracker_alert
|
tracker_alert
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
@ -1415,7 +1454,7 @@ This is a simple client. It doesn't have much output to keep it simple::
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
session s(6881);
|
session s(std::make_pair(6881, 6889));
|
||||||
|
|
||||||
std::ifstream in(argv[1], std::ios_base::binary);
|
std::ifstream in(argv[1], std::ios_base::binary);
|
||||||
in.unsetf(std::ios_base::skipws);
|
in.unsetf(std::ios_base::skipws);
|
||||||
|
|
|
@ -236,7 +236,7 @@ int main(int argc, char* argv[])
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
std::vector<torrent_handle> handles;
|
std::vector<torrent_handle> handles;
|
||||||
session ses(6881);
|
session ses(std::make_pair(6881, 6889));
|
||||||
|
|
||||||
// ses.set_upload_rate_limit(30 * 1024);
|
// ses.set_upload_rate_limit(30 * 1024);
|
||||||
ses.set_http_settings(settings);
|
ses.set_http_settings(settings);
|
||||||
|
|
|
@ -56,7 +56,7 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
session s(6881);
|
session s(std::make_pair(6881, 6889));
|
||||||
|
|
||||||
std::ifstream in(argv[1], std::ios_base::binary);
|
std::ifstream in(argv[1], std::ios_base::binary);
|
||||||
in.unsetf(std::ios_base::skipws);
|
in.unsetf(std::ios_base::skipws);
|
||||||
|
|
|
@ -140,7 +140,6 @@ namespace libtorrent
|
||||||
torrent_handle handle;
|
torrent_handle handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: document and test
|
|
||||||
struct file_error_alert: alert
|
struct file_error_alert: alert
|
||||||
{
|
{
|
||||||
file_error_alert(
|
file_error_alert(
|
||||||
|
@ -155,6 +154,17 @@ namespace libtorrent
|
||||||
|
|
||||||
torrent_handle handle;
|
torrent_handle handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct listen_failed_alert: alert
|
||||||
|
{
|
||||||
|
listen_failed_alert(
|
||||||
|
const std::string& msg)
|
||||||
|
: alert(alert::fatal, msg)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual std::auto_ptr<alert> clone() const
|
||||||
|
{ return std::auto_ptr<alert>(new listen_failed_alert(*this)); }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -166,7 +166,9 @@ namespace libtorrent
|
||||||
break;
|
break;
|
||||||
case entry::dictionary_t:
|
case entry::dictionary_t:
|
||||||
*out = 'd'; ++out;
|
*out = 'd'; ++out;
|
||||||
for (entry::dictionary_type::const_iterator i = e.dict().begin(); i != e.dict().end(); ++i)
|
for (entry::dictionary_type::const_iterator i = e.dict().begin();
|
||||||
|
i != e.dict().end();
|
||||||
|
++i)
|
||||||
{
|
{
|
||||||
// write key
|
// write key
|
||||||
write_integer(out, i->first.length());
|
write_integer(out, i->first.length());
|
||||||
|
|
|
@ -86,7 +86,7 @@ namespace libtorrent
|
||||||
inline T read_impl(InIt& start, type<T>)
|
inline T read_impl(InIt& start, type<T>)
|
||||||
{
|
{
|
||||||
T ret = 0;
|
T ret = 0;
|
||||||
for (int i = 0; i < sizeof(T); ++i)
|
for (int i = 0; i < (int)sizeof(T); ++i)
|
||||||
{
|
{
|
||||||
ret <<= 8;
|
ret <<= 8;
|
||||||
ret |= static_cast<unsigned char>(*start);
|
ret |= static_cast<unsigned char>(*start);
|
||||||
|
@ -98,7 +98,7 @@ namespace libtorrent
|
||||||
template <class T, class OutIt>
|
template <class T, class OutIt>
|
||||||
inline void write_impl(T val, OutIt& start)
|
inline void write_impl(T val, OutIt& start)
|
||||||
{
|
{
|
||||||
for (int i = sizeof(T)-1; i >= 0; --i)
|
for (int i = (int)sizeof(T)-1; i >= 0; --i)
|
||||||
{
|
{
|
||||||
*start = static_cast<unsigned char>((val >> (i * 8)) & 0xff);
|
*start = static_cast<unsigned char>((val >> (i * 8)) & 0xff);
|
||||||
++start;
|
++start;
|
||||||
|
|
|
@ -275,7 +275,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
assert(index >= 0);
|
assert(index >= 0);
|
||||||
assert(index < (int)m_piece_map.size());
|
assert(index < (int)m_piece_map.size());
|
||||||
if (index+1 == m_piece_map.size())
|
if (index+1 == (int)m_piece_map.size())
|
||||||
return m_blocks_in_last_piece;
|
return m_blocks_in_last_piece;
|
||||||
else
|
else
|
||||||
return m_blocks_per_piece;
|
return m_blocks_per_piece;
|
||||||
|
|
|
@ -156,7 +156,10 @@ namespace libtorrent
|
||||||
friend class invariant_access;
|
friend class invariant_access;
|
||||||
typedef std::map<boost::shared_ptr<socket>, boost::shared_ptr<peer_connection> > connection_map;
|
typedef std::map<boost::shared_ptr<socket>, boost::shared_ptr<peer_connection> > connection_map;
|
||||||
|
|
||||||
session_impl(int listen_port, const fingerprint& cl_fprint);
|
session_impl(
|
||||||
|
std::pair<int, int> listen_port_range
|
||||||
|
, const fingerprint& cl_fprint);
|
||||||
|
|
||||||
void operator()();
|
void operator()();
|
||||||
|
|
||||||
// must be locked to access the data
|
// must be locked to access the data
|
||||||
|
@ -182,6 +185,9 @@ namespace libtorrent
|
||||||
// the peer id that is generated at the start of each torrent
|
// the peer id that is generated at the start of each torrent
|
||||||
peer_id m_peer_id;
|
peer_id m_peer_id;
|
||||||
|
|
||||||
|
// the range of ports we try to listen on
|
||||||
|
std::pair<int, int> m_listen_port_range;
|
||||||
|
|
||||||
// the port we are listening on for connections
|
// the port we are listening on for connections
|
||||||
int m_listen_port;
|
int m_listen_port;
|
||||||
|
|
||||||
|
@ -231,8 +237,8 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
session(int listen_port, const fingerprint& print);
|
session(std::pair<int, int> listen_port_range, const fingerprint& print);
|
||||||
session(int listen_port);
|
session(std::pair<int, int> listen_port_range);
|
||||||
|
|
||||||
~session();
|
~session();
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ namespace libtorrent
|
||||||
|
|
||||||
// TODO: add a check to see if filenames are accepted on the
|
// TODO: add a check to see if filenames are accepted on the
|
||||||
// current platform.
|
// current platform.
|
||||||
// TODO: add a filename converter function that will transform
|
// also add a filename converter function that will transform
|
||||||
// invalid filenames to valid filenames on the current platform
|
// invalid filenames to valid filenames on the current platform
|
||||||
|
|
||||||
class torrent_info
|
class torrent_info
|
||||||
|
|
|
@ -474,7 +474,7 @@ namespace libtorrent
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
assert(received > 0);
|
assert(received > 0);
|
||||||
if (m_packet_size - 1 != (m_have_piece.size() + 7) / 8)
|
if (m_packet_size - 1 != ((int)m_have_piece.size() + 7) / 8)
|
||||||
throw protocol_error("bitfield with invalid size");
|
throw protocol_error("bitfield with invalid size");
|
||||||
m_statistics.received_bytes(0, received);
|
m_statistics.received_bytes(0, received);
|
||||||
if (m_recv_pos < m_packet_size) return;
|
if (m_recv_pos < m_packet_size) return;
|
||||||
|
@ -1353,7 +1353,6 @@ namespace libtorrent
|
||||||
(*m_logger) << " protocol: '" << std::string(m_recv_buffer.begin(), m_recv_buffer.end()) << "'\n";
|
(*m_logger) << " protocol: '" << std::string(m_recv_buffer.begin(), m_recv_buffer.end()) << "'\n";
|
||||||
#endif
|
#endif
|
||||||
const char protocol_string[] = "BitTorrent protocol";
|
const char protocol_string[] = "BitTorrent protocol";
|
||||||
const int protocol_len = sizeof(protocol_string) - 1;
|
|
||||||
if (!std::equal(m_recv_buffer.begin(), m_recv_buffer.end(), protocol_string))
|
if (!std::equal(m_recv_buffer.begin(), m_recv_buffer.end(), protocol_string))
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
@ -1555,9 +1554,6 @@ namespace libtorrent
|
||||||
|
|
||||||
// only add new piece-chunks if the send buffer is small enough
|
// only add new piece-chunks if the send buffer is small enough
|
||||||
// otherwise there will be no end to how large it will be!
|
// otherwise there will be no end to how large it will be!
|
||||||
// TODO: make this a bit better. Don't always read the entire
|
|
||||||
// requested block. Have a limit of how much of the requested
|
|
||||||
// block is actually read at a time.
|
|
||||||
while (!m_requests.empty()
|
while (!m_requests.empty()
|
||||||
&& ((int)m_send_buffer.size() < m_torrent->block_size())
|
&& ((int)m_send_buffer.size() < m_torrent->block_size())
|
||||||
&& !m_choked)
|
&& !m_choked)
|
||||||
|
@ -1680,7 +1676,7 @@ namespace libtorrent
|
||||||
// empty the entire buffer at once or if
|
// empty the entire buffer at once or if
|
||||||
// only a part of the buffer could be sent
|
// only a part of the buffer could be sent
|
||||||
// remove the part that was sent from the buffer
|
// remove the part that was sent from the buffer
|
||||||
if (sent == m_send_buffer.size())
|
if (sent == (int)m_send_buffer.size())
|
||||||
{
|
{
|
||||||
m_send_buffer.clear();
|
m_send_buffer.clear();
|
||||||
}
|
}
|
||||||
|
@ -1749,6 +1745,6 @@ namespace libtorrent
|
||||||
bool peer_connection::is_seed() const
|
bool peer_connection::is_seed() const
|
||||||
{
|
{
|
||||||
return std::count(m_have_piece.begin(), m_have_piece.end(), true)
|
return std::count(m_have_piece.begin(), m_have_piece.end(), true)
|
||||||
== m_have_piece.size();
|
== (int)m_have_piece.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,9 +144,8 @@ namespace libtorrent
|
||||||
assert(sizeof(piece_pos) == 4);
|
assert(sizeof(piece_pos) == 4);
|
||||||
|
|
||||||
if (t != 0)
|
if (t != 0)
|
||||||
assert(m_piece_map.size() == t->torrent_file().num_pieces());
|
assert((int)m_piece_map.size() == t->torrent_file().num_pieces());
|
||||||
|
|
||||||
int last_val = 0;
|
|
||||||
for (std::vector<piece_pos>::const_iterator i = m_piece_map.begin();
|
for (std::vector<piece_pos>::const_iterator i = m_piece_map.begin();
|
||||||
i != m_piece_map.end();
|
i != m_piece_map.end();
|
||||||
++i)
|
++i)
|
||||||
|
@ -163,7 +162,7 @@ namespace libtorrent
|
||||||
if (peer->second->has_piece(index)) actual_peer_count++;
|
if (peer->second->has_piece(index)) actual_peer_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(i->peer_count == actual_peer_count);
|
assert((int)i->peer_count == actual_peer_count);
|
||||||
/*
|
/*
|
||||||
int num_downloaders = 0;
|
int num_downloaders = 0;
|
||||||
for (std::vector<peer_connection*>::const_iterator peer = t->begin();
|
for (std::vector<peer_connection*>::const_iterator peer = t->begin();
|
||||||
|
@ -262,7 +261,7 @@ namespace libtorrent
|
||||||
// update the piece_map
|
// update the piece_map
|
||||||
piece_pos& p = m_piece_map[index];
|
piece_pos& p = m_piece_map[index];
|
||||||
|
|
||||||
assert(p.downloading != downloading || p.peer_count != peer_count);
|
assert(p.downloading != downloading || (int)p.peer_count != peer_count);
|
||||||
|
|
||||||
std::vector<std::vector<int> >& dst_vec = (p.downloading)?m_downloading_piece_info:m_piece_info;
|
std::vector<std::vector<int> >& dst_vec = (p.downloading)?m_downloading_piece_info:m_piece_info;
|
||||||
|
|
||||||
|
@ -286,13 +285,13 @@ namespace libtorrent
|
||||||
m_piece_map[replace_index].index = elem_index;
|
m_piece_map[replace_index].index = elem_index;
|
||||||
|
|
||||||
assert((int)src_vec[peer_count].size() > elem_index);
|
assert((int)src_vec[peer_count].size() > elem_index);
|
||||||
assert(m_piece_map[replace_index].peer_count == peer_count);
|
assert((int)m_piece_map[replace_index].peer_count == peer_count);
|
||||||
assert(m_piece_map[replace_index].index == elem_index);
|
assert((int)m_piece_map[replace_index].index == elem_index);
|
||||||
assert(src_vec[peer_count][elem_index] == replace_index);
|
assert(src_vec[peer_count][elem_index] == replace_index);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(src_vec[peer_count].size() == elem_index+1);
|
assert((int)src_vec[peer_count].size() == elem_index+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
src_vec[peer_count].pop_back();
|
src_vec[peer_count].pop_back();
|
||||||
|
@ -519,9 +518,9 @@ namespace libtorrent
|
||||||
assert(i != m_downloads.end());
|
assert(i != m_downloads.end());
|
||||||
assert((int)i->finished_blocks.count() <= m_blocks_per_piece);
|
assert((int)i->finished_blocks.count() <= m_blocks_per_piece);
|
||||||
int max_blocks = blocks_in_piece(index);
|
int max_blocks = blocks_in_piece(index);
|
||||||
if (i->finished_blocks.count() != max_blocks) return false;
|
if ((int)i->finished_blocks.count() != max_blocks) return false;
|
||||||
|
|
||||||
assert(i->requested_blocks.count() == max_blocks);
|
assert((int)i->requested_blocks.count() == max_blocks);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -761,7 +761,7 @@ namespace libtorrent
|
||||||
const std::vector<bool>& peer_has = i->connection->get_bitfield();
|
const std::vector<bool>& peer_has = i->connection->get_bitfield();
|
||||||
const std::vector<bool>& we_have = m_torrent->pieces();
|
const std::vector<bool>& we_have = m_torrent->pieces();
|
||||||
assert(we_have.size() == peer_has.size());
|
assert(we_have.size() == peer_has.size());
|
||||||
for (int j = 0; j != we_have.size(); ++j)
|
for (int j = 0; j != (int)we_have.size(); ++j)
|
||||||
{
|
{
|
||||||
if (!we_have[j] && peer_has[j])
|
if (!we_have[j] && peer_has[j])
|
||||||
{
|
{
|
||||||
|
|
|
@ -357,15 +357,18 @@ namespace libtorrent
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
session_impl::session_impl(int listen_port,
|
session_impl::session_impl(std::pair<int, int> listen_port_range,
|
||||||
const fingerprint& cl_fprint)
|
const fingerprint& cl_fprint)
|
||||||
: m_abort(false)
|
: m_tracker_manager(m_settings)
|
||||||
, m_tracker_manager(m_settings)
|
, m_listen_port_range(listen_port_range)
|
||||||
, m_listen_port(listen_port)
|
, m_listen_port(listen_port_range.first)
|
||||||
|
, m_abort(false)
|
||||||
, m_upload_rate(-1)
|
, m_upload_rate(-1)
|
||||||
, m_incoming_connection(false)
|
, m_incoming_connection(false)
|
||||||
{
|
{
|
||||||
assert(listen_port > 0);
|
assert(listen_port_range.first > 0);
|
||||||
|
assert(listen_port_range.first < listen_port_range.second);
|
||||||
|
assert(m_listen_port > 0);
|
||||||
|
|
||||||
// ---- generate a peer id ----
|
// ---- generate a peer id ----
|
||||||
|
|
||||||
|
@ -395,7 +398,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
m_connections.erase(m_disconnect_peer.back());
|
m_connections.erase(m_disconnect_peer.back());
|
||||||
m_disconnect_peer.pop_back();
|
m_disconnect_peer.pop_back();
|
||||||
assert(m_selector.count_read_monitors() == m_connections.size() + 1);
|
assert(m_selector.count_read_monitors() == (int)m_connections.size() + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,11 +411,8 @@ namespace libtorrent
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
boost::shared_ptr<socket> listener(new socket(socket::tcp, false));
|
|
||||||
int max_port = m_listen_port + 9;
|
|
||||||
|
|
||||||
|
|
||||||
// create listener socket
|
// create listener socket
|
||||||
|
boost::shared_ptr<socket> listener(new socket(socket::tcp, false));
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
|
@ -422,9 +422,13 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
catch (std::exception&)
|
catch (std::exception&)
|
||||||
{
|
{
|
||||||
if (m_listen_port > max_port)
|
|
||||||
throw;
|
|
||||||
m_listen_port++;
|
m_listen_port++;
|
||||||
|
if (m_listen_port > m_listen_port_range.second)
|
||||||
|
{
|
||||||
|
m_alerts.post_alert(listen_failed_alert(
|
||||||
|
"none of the ports in the given range could be opened"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -470,7 +474,7 @@ namespace libtorrent
|
||||||
boost::mutex::scoped_lock l(m_mutex);
|
boost::mutex::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
// +1 for the listen socket
|
// +1 for the listen socket
|
||||||
assert(m_selector.count_read_monitors() == m_connections.size() + 1);
|
assert(m_selector.count_read_monitors() == (int)m_connections.size() + 1);
|
||||||
|
|
||||||
if (m_abort)
|
if (m_abort)
|
||||||
{
|
{
|
||||||
|
@ -520,17 +524,21 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
catch (file_error& e)
|
catch (file_error& e)
|
||||||
{
|
{
|
||||||
|
torrent* t = p->second->associated_torrent();
|
||||||
|
assert(t != 0);
|
||||||
|
|
||||||
if (m_alerts.should_post(alert::fatal))
|
if (m_alerts.should_post(alert::fatal))
|
||||||
{
|
{
|
||||||
m_alerts.post_alert(
|
m_alerts.post_alert(
|
||||||
file_error_alert(
|
file_error_alert(
|
||||||
p->second->associated_torrent()->get_handle()
|
t->get_handle()
|
||||||
, e.what()));
|
, e.what()));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_selector.remove(*i);
|
m_selector.remove(*i);
|
||||||
m_connections.erase(p);
|
m_connections.erase(p);
|
||||||
assert(m_selector.count_read_monitors() == m_connections.size() + 1);
|
assert(m_selector.count_read_monitors() == (int)m_connections.size() + 1);
|
||||||
|
t->abort();
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
|
@ -544,7 +552,7 @@ namespace libtorrent
|
||||||
|
|
||||||
m_selector.remove(*i);
|
m_selector.remove(*i);
|
||||||
m_connections.erase(p);
|
m_connections.erase(p);
|
||||||
assert(m_selector.count_read_monitors() == m_connections.size() + 1);
|
assert(m_selector.count_read_monitors() == (int)m_connections.size() + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -600,17 +608,21 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
catch (file_error& e)
|
catch (file_error& e)
|
||||||
{
|
{
|
||||||
|
torrent* t = p->second->associated_torrent();
|
||||||
|
assert(t != 0);
|
||||||
|
|
||||||
if (m_alerts.should_post(alert::fatal))
|
if (m_alerts.should_post(alert::fatal))
|
||||||
{
|
{
|
||||||
m_alerts.post_alert(
|
m_alerts.post_alert(
|
||||||
file_error_alert(
|
file_error_alert(
|
||||||
p->second->associated_torrent()->get_handle()
|
t->get_handle()
|
||||||
, e.what()));
|
, e.what()));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_selector.remove(*i);
|
m_selector.remove(*i);
|
||||||
m_connections.erase(p);
|
m_connections.erase(p);
|
||||||
assert(m_selector.count_read_monitors() == m_connections.size() + 1);
|
assert(m_selector.count_read_monitors() == (int)m_connections.size() + 1);
|
||||||
|
t->abort();
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
|
@ -623,7 +635,7 @@ namespace libtorrent
|
||||||
// from the connection-list
|
// from the connection-list
|
||||||
m_selector.remove(*i);
|
m_selector.remove(*i);
|
||||||
m_connections.erase(p);
|
m_connections.erase(p);
|
||||||
assert(m_selector.count_read_monitors() == m_connections.size() + 1);
|
assert(m_selector.count_read_monitors() == (int)m_connections.size() + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -656,7 +668,7 @@ namespace libtorrent
|
||||||
if (p != m_connections.end())
|
if (p != m_connections.end())
|
||||||
{
|
{
|
||||||
m_connections.erase(p);
|
m_connections.erase(p);
|
||||||
assert(m_selector.count_read_monitors() == m_connections.size() + 1);
|
assert(m_selector.count_read_monitors() == (int)m_connections.size() + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -692,7 +704,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
m_selector.remove(j->first);
|
m_selector.remove(j->first);
|
||||||
m_connections.erase(j);
|
m_connections.erase(j);
|
||||||
assert(m_selector.count_read_monitors() == m_connections.size() + 1);
|
assert(m_selector.count_read_monitors() == (int)m_connections.size() + 1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -822,13 +834,14 @@ namespace libtorrent
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: take a port range instead!
|
session::session(std::pair<int, int> listen_port_range, const fingerprint& id)
|
||||||
session::session(int listen_port, const fingerprint& id)
|
: m_impl(listen_port_range, id)
|
||||||
: m_impl(listen_port, id)
|
|
||||||
, m_checker_impl(m_impl)
|
, m_checker_impl(m_impl)
|
||||||
, m_thread(boost::ref(m_impl))
|
, m_thread(boost::ref(m_impl))
|
||||||
, m_checker_thread(boost::ref(m_checker_impl))
|
, m_checker_thread(boost::ref(m_checker_impl))
|
||||||
{
|
{
|
||||||
|
assert(listen_port_range.first > 0);
|
||||||
|
assert(listen_port_range.first < listen_port_range.second);
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// this test was added after it came to my attention
|
// this test was added after it came to my attention
|
||||||
// that devstudios managed c++ failed to generate
|
// that devstudios managed c++ failed to generate
|
||||||
|
@ -838,12 +851,14 @@ namespace libtorrent
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
session::session(int listen_port)
|
session::session(std::pair<int, int> listen_port_range)
|
||||||
: m_impl(listen_port, fingerprint("LT",0,0,1,0))
|
: m_impl(listen_port_range, fingerprint("LT",0,0,1,0))
|
||||||
, m_checker_impl(m_impl)
|
, m_checker_impl(m_impl)
|
||||||
, m_thread(boost::ref(m_impl))
|
, m_thread(boost::ref(m_impl))
|
||||||
, m_checker_thread(boost::ref(m_checker_impl))
|
, m_checker_thread(boost::ref(m_checker_impl))
|
||||||
{
|
{
|
||||||
|
assert(listen_port_range.first > 0);
|
||||||
|
assert(listen_port_range.first < listen_port_range.second);
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
boost::function0<void> test = boost::ref(m_impl);
|
boost::function0<void> test = boost::ref(m_impl);
|
||||||
assert(!test.empty());
|
assert(!test.empty());
|
||||||
|
@ -1071,7 +1086,7 @@ namespace libtorrent
|
||||||
const std::string& bitmask = i->dict()["bitmask"].string();
|
const std::string& bitmask = i->dict()["bitmask"].string();
|
||||||
|
|
||||||
const int num_bitmask_bytes = std::max(num_blocks_per_piece / 8, 1);
|
const int num_bitmask_bytes = std::max(num_blocks_per_piece / 8, 1);
|
||||||
if (bitmask.size() != num_bitmask_bytes) return;
|
if ((int)bitmask.size() != num_bitmask_bytes) return;
|
||||||
for (int j = 0; j < num_bitmask_bytes; ++j)
|
for (int j = 0; j < num_bitmask_bytes; ++j)
|
||||||
{
|
{
|
||||||
unsigned char bits = bitmask[j];
|
unsigned char bits = bitmask[j];
|
||||||
|
|
|
@ -144,7 +144,7 @@ namespace libtorrent
|
||||||
, const boost::filesystem::path& p
|
, const boost::filesystem::path& p
|
||||||
, const std::vector<size_type>& sizes)
|
, const std::vector<size_type>& sizes)
|
||||||
{
|
{
|
||||||
if (sizes.size() != t.num_files()) return false;
|
if ((int)sizes.size() != t.num_files()) return false;
|
||||||
|
|
||||||
std::vector<size_type>::const_iterator s = sizes.begin();
|
std::vector<size_type>::const_iterator s = sizes.begin();
|
||||||
for (torrent_info::file_iterator i = t.begin_files();
|
for (torrent_info::file_iterator i = t.begin_files();
|
||||||
|
@ -326,6 +326,7 @@ namespace libtorrent
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// throws file_error if it fails to write
|
||||||
void storage::write(
|
void storage::write(
|
||||||
const char* buf
|
const char* buf
|
||||||
, int slot
|
, int slot
|
||||||
|
@ -356,26 +357,18 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path path(m_pimpl->save_path / file_iter->path / file_iter->filename);
|
fs::path path(m_pimpl->save_path / file_iter->path / file_iter->filename);
|
||||||
/*
|
|
||||||
fs::ofstream out;
|
|
||||||
|
|
||||||
if (fs::exists(path))
|
|
||||||
out.open(path, std::ios_base::binary | std::ios_base::in);
|
|
||||||
else
|
|
||||||
out.open(path, std::ios_base::binary);
|
|
||||||
*/
|
|
||||||
file out(path, file::out);
|
file out(path, file::out);
|
||||||
|
|
||||||
assert(file_offset < file_iter->size);
|
assert(file_offset < file_iter->size);
|
||||||
|
|
||||||
// out.seekp(file_offset);
|
|
||||||
out.seek(file_offset);
|
out.seek(file_offset);
|
||||||
|
|
||||||
// assert(file_offset == out.tellp());
|
if (out.tell() != file_offset)
|
||||||
#ifndef NDEBUG
|
{
|
||||||
size_type out_tell = out.tell();
|
std::stringstream s;
|
||||||
assert(file_offset == out_tell);
|
s << "no storage for slot " << slot;
|
||||||
#endif
|
throw file_error(s.str());
|
||||||
|
}
|
||||||
|
|
||||||
int left_to_write = size;
|
int left_to_write = size;
|
||||||
int slot_size = m_pimpl->info.piece_size(slot);
|
int slot_size = m_pimpl->info.piece_size(slot);
|
||||||
|
@ -387,8 +380,6 @@ namespace libtorrent
|
||||||
|
|
||||||
int buf_pos = 0;
|
int buf_pos = 0;
|
||||||
|
|
||||||
// TODO
|
|
||||||
// handle case when we can't write size bytes.
|
|
||||||
while (left_to_write > 0)
|
while (left_to_write > 0)
|
||||||
{
|
{
|
||||||
int write_bytes = left_to_write;
|
int write_bytes = left_to_write;
|
||||||
|
@ -400,7 +391,14 @@ namespace libtorrent
|
||||||
|
|
||||||
assert(buf_pos >= 0);
|
assert(buf_pos >= 0);
|
||||||
assert(write_bytes > 0);
|
assert(write_bytes > 0);
|
||||||
out.write(buf + buf_pos, write_bytes);
|
size_type written = out.write(buf + buf_pos, write_bytes);
|
||||||
|
|
||||||
|
if (written != write_bytes)
|
||||||
|
{
|
||||||
|
std::stringstream s;
|
||||||
|
s << "no storage for slot " << slot;
|
||||||
|
throw file_error(s.str());
|
||||||
|
}
|
||||||
|
|
||||||
left_to_write -= write_bytes;
|
left_to_write -= write_bytes;
|
||||||
buf_pos += write_bytes;
|
buf_pos += write_bytes;
|
||||||
|
@ -926,9 +924,6 @@ namespace libtorrent
|
||||||
|
|
||||||
int found_piece = -1;
|
int found_piece = -1;
|
||||||
|
|
||||||
// TODO: there's still potential problems if some
|
|
||||||
// pieces have the same hash
|
|
||||||
// for the file not to be corrupt, piece_index <= slot_index
|
|
||||||
for (int i = current_slot; i < m_info.num_pieces(); ++i)
|
for (int i = current_slot; i < m_info.num_pieces(); ++i)
|
||||||
{
|
{
|
||||||
if (pieces[i] && i != current_slot) continue;
|
if (pieces[i] && i != current_slot) continue;
|
||||||
|
@ -1038,7 +1033,7 @@ namespace libtorrent
|
||||||
, std::vector<bool>& have_pieces
|
, std::vector<bool>& have_pieces
|
||||||
, const std::multimap<sha1_hash, int>& hash_to_piece)
|
, const std::multimap<sha1_hash, int>& hash_to_piece)
|
||||||
{
|
{
|
||||||
assert(have_pieces.size() == m_info.num_pieces());
|
assert((int)have_pieces.size() == m_info.num_pieces());
|
||||||
|
|
||||||
const int piece_size = m_info.piece_length();
|
const int piece_size = m_info.piece_length();
|
||||||
const int last_piece_size = m_info.piece_size(
|
const int last_piece_size = m_info.piece_size(
|
||||||
|
@ -1234,9 +1229,6 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<char> piece_data(m_info.piece_length());
|
std::vector<char> piece_data(m_info.piece_length());
|
||||||
const int piece_size = m_info.piece_length();
|
|
||||||
const int last_piece_size = m_info.piece_size(
|
|
||||||
m_info.num_pieces() - 1);
|
|
||||||
|
|
||||||
std::multimap<sha1_hash, int> hash_to_piece;
|
std::multimap<sha1_hash, int> hash_to_piece;
|
||||||
// build the hash-map, that maps hashes to pieces
|
// build the hash-map, that maps hashes to pieces
|
||||||
|
@ -1329,7 +1321,7 @@ namespace libtorrent
|
||||||
|
|
||||||
if (m_free_slots.empty())
|
if (m_free_slots.empty())
|
||||||
{
|
{
|
||||||
allocate_slots(5);
|
allocate_slots(1);
|
||||||
assert(!m_free_slots.empty());
|
assert(!m_free_slots.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1349,9 +1341,9 @@ namespace libtorrent
|
||||||
if (*iter == m_info.num_pieces() - 1 && piece_index != *iter)
|
if (*iter == m_info.num_pieces() - 1 && piece_index != *iter)
|
||||||
{
|
{
|
||||||
if (m_free_slots.size() == 1)
|
if (m_free_slots.size() == 1)
|
||||||
allocate_slots(5);
|
allocate_slots(1);
|
||||||
assert(m_free_slots.size() > 1);
|
assert(m_free_slots.size() > 1);
|
||||||
// TODO: assumes that all allocated slots
|
// assumes that all allocated slots
|
||||||
// are put at the end of the free_slots vector
|
// are put at the end of the free_slots vector
|
||||||
iter = m_free_slots.end() - 1;
|
iter = m_free_slots.end() - 1;
|
||||||
}
|
}
|
||||||
|
@ -1422,42 +1414,48 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
// this is used to notify potential other
|
// this is used to notify potential other
|
||||||
// threads that the allocation-function has exited
|
// threads that the allocation-function has exited
|
||||||
struct allocation_cleanup
|
struct allocation_syncronization
|
||||||
{
|
{
|
||||||
allocation_cleanup(bool& flag, boost::condition& cond)
|
allocation_syncronization(
|
||||||
|
bool& flag
|
||||||
|
, boost::condition& cond
|
||||||
|
, boost::mutex& monitor)
|
||||||
: m_flag(flag)
|
: m_flag(flag)
|
||||||
, m_cond(cond)
|
, m_cond(cond)
|
||||||
{}
|
, m_monitor(monitor)
|
||||||
|
|
||||||
~allocation_cleanup()
|
|
||||||
{
|
{
|
||||||
|
boost::mutex::scoped_lock lock(m_monitor);
|
||||||
|
|
||||||
|
while (m_flag)
|
||||||
|
m_cond.wait(lock);
|
||||||
|
|
||||||
|
m_flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
~allocation_syncronization()
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock(m_monitor);
|
||||||
m_flag = false;
|
m_flag = false;
|
||||||
m_cond.notify_one();
|
m_cond.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool& m_flag;
|
bool& m_flag;
|
||||||
boost::condition& m_cond;
|
boost::condition& m_cond;
|
||||||
|
boost::mutex& m_monitor;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: signal the m_allocating_condition on exit!
|
|
||||||
void piece_manager::impl::allocate_slots(int num_slots)
|
void piece_manager::impl::allocate_slots(int num_slots)
|
||||||
{
|
{
|
||||||
assert(num_slots > 0);
|
assert(num_slots > 0);
|
||||||
|
|
||||||
{
|
// this object will syncronize the allocation with
|
||||||
boost::mutex::scoped_lock lock(m_allocating_monitor);
|
// potential other threads
|
||||||
|
allocation_syncronization sync_obj(
|
||||||
while (m_allocating)
|
m_allocating
|
||||||
m_allocating_condition.wait(lock);
|
, m_allocating_condition
|
||||||
|
, m_allocating_monitor);
|
||||||
m_allocating = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// this object will signal the other threads and
|
|
||||||
// set m_allocating to false upon exit
|
|
||||||
allocation_cleanup clean_obj(m_allocating, m_allocating_condition);
|
|
||||||
|
|
||||||
// synchronization ------------------------------------------------------
|
// synchronization ------------------------------------------------------
|
||||||
boost::recursive_mutex::scoped_lock lock(m_mutex);
|
boost::recursive_mutex::scoped_lock lock(m_mutex);
|
||||||
|
@ -1476,7 +1474,7 @@ namespace libtorrent
|
||||||
++i)
|
++i)
|
||||||
{
|
{
|
||||||
int pos = m_unallocated_slots.front();
|
int pos = m_unallocated_slots.front();
|
||||||
int piece_pos = pos;
|
// int piece_pos = pos;
|
||||||
|
|
||||||
int new_free_slot = pos;
|
int new_free_slot = pos;
|
||||||
if (m_piece_to_slot[pos] != has_no_slot)
|
if (m_piece_to_slot[pos] != has_no_slot)
|
||||||
|
@ -1516,8 +1514,8 @@ namespace libtorrent
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
if (m_piece_to_slot.empty()) return;
|
if (m_piece_to_slot.empty()) return;
|
||||||
|
|
||||||
assert(m_piece_to_slot.size() == m_info.num_pieces());
|
assert((int)m_piece_to_slot.size() == m_info.num_pieces());
|
||||||
assert(m_slot_to_piece.size() == m_info.num_pieces());
|
assert((int)m_slot_to_piece.size() == m_info.num_pieces());
|
||||||
|
|
||||||
for (std::vector<int>::const_iterator i = m_free_slots.begin();
|
for (std::vector<int>::const_iterator i = m_free_slots.begin();
|
||||||
i != m_free_slots.end();
|
i != m_free_slots.end();
|
||||||
|
|
|
@ -745,7 +745,7 @@ namespace libtorrent
|
||||||
|
|
||||||
if (m_got_tracker_response == false)
|
if (m_got_tracker_response == false)
|
||||||
st.state = torrent_status::connecting_to_tracker;
|
st.state = torrent_status::connecting_to_tracker;
|
||||||
else if (m_num_pieces == m_have_pieces.size())
|
else if (m_num_pieces == (int)m_have_pieces.size())
|
||||||
st.state = torrent_status::seeding;
|
st.state = torrent_status::seeding;
|
||||||
else
|
else
|
||||||
st.state = torrent_status::downloading;
|
st.state = torrent_status::downloading;
|
||||||
|
@ -774,9 +774,7 @@ namespace libtorrent
|
||||||
try_next_tracker();
|
try_next_tracker();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this function should also take the
|
// TODO: with some response codes, we should just consider
|
||||||
// HTTP-response code as an argument.
|
|
||||||
// with some codes, we should just consider
|
|
||||||
// the tracker as a failure and not retry
|
// the tracker as a failure and not retry
|
||||||
// it anymore
|
// it anymore
|
||||||
void torrent::tracker_request_error(int response_code, const std::string& str)
|
void torrent::tracker_request_error(int response_code, const std::string& str)
|
||||||
|
|
|
@ -209,7 +209,9 @@ namespace libtorrent
|
||||||
m_piece_hash.resize(num_pieces);
|
m_piece_hash.resize(num_pieces);
|
||||||
|
|
||||||
const std::string& hash_string = i->second.string();
|
const std::string& hash_string = i->second.string();
|
||||||
if (hash_string.length() != num_pieces * 20) throw invalid_torrent_file();
|
if ((int)hash_string.length() != num_pieces * 20)
|
||||||
|
throw invalid_torrent_file();
|
||||||
|
|
||||||
for (int i = 0; i < num_pieces; ++i)
|
for (int i = 0; i < num_pieces; ++i)
|
||||||
std::copy(hash_string.begin() + i*20, hash_string.begin() + (i+1)*20, m_piece_hash[i].begin());
|
std::copy(hash_string.begin() + i*20, hash_string.begin() + (i+1)*20, m_piece_hash[i].begin());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue