*** empty log message ***

This commit is contained in:
Arvid Norberg 2004-01-26 10:29:00 +00:00
parent b716a40795
commit fc74e19224
16 changed files with 180 additions and 115 deletions

View File

@ -181,8 +181,8 @@ The ``session`` class has the following synopsis::
class session: public boost::noncopyable
{
session(int listen_port, const fingerprint& print);
session(int listen_port);
session(std::pair<int, int> listen_port_range, const fingerprint& print);
session(std::pair<int, int> listen_port_range);
torrent_handle add_torrent(
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
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
increasing the port number until it succeeds or has failed 9 ports. *This will
change in the future to give more control of the listen-port.*
increasing the port number until it succeeds or has reached the end of the range. If it
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_.
@ -1104,6 +1106,43 @@ user in different ways.
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
-------------
@ -1415,7 +1454,7 @@ This is a simple client. It doesn't have much output to keep it simple::
try
{
session s(6881);
session s(std::make_pair(6881, 6889));
std::ifstream in(argv[1], std::ios_base::binary);
in.unsetf(std::ios_base::skipws);

View File

@ -236,7 +236,7 @@ int main(int argc, char* argv[])
try
{
std::vector<torrent_handle> handles;
session ses(6881);
session ses(std::make_pair(6881, 6889));
// ses.set_upload_rate_limit(30 * 1024);
ses.set_http_settings(settings);

View File

@ -56,7 +56,7 @@ int main(int argc, char* argv[])
try
{
session s(6881);
session s(std::make_pair(6881, 6889));
std::ifstream in(argv[1], std::ios_base::binary);
in.unsetf(std::ios_base::skipws);

View File

@ -140,7 +140,6 @@ namespace libtorrent
torrent_handle handle;
};
// TODO: document and test
struct file_error_alert: alert
{
file_error_alert(
@ -155,6 +154,17 @@ namespace libtorrent
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)); }
};
}

View File

@ -166,7 +166,9 @@ namespace libtorrent
break;
case entry::dictionary_t:
*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_integer(out, i->first.length());

View File

@ -86,7 +86,7 @@ namespace libtorrent
inline T read_impl(InIt& start, type<T>)
{
T ret = 0;
for (int i = 0; i < sizeof(T); ++i)
for (int i = 0; i < (int)sizeof(T); ++i)
{
ret <<= 8;
ret |= static_cast<unsigned char>(*start);
@ -98,7 +98,7 @@ namespace libtorrent
template <class T, class OutIt>
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;

View File

@ -275,7 +275,7 @@ namespace libtorrent
{
assert(index >= 0);
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;
else
return m_blocks_per_piece;

View File

@ -156,7 +156,10 @@ namespace libtorrent
friend class invariant_access;
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()();
// 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
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
int m_listen_port;
@ -231,8 +237,8 @@ namespace libtorrent
{
public:
session(int listen_port, const fingerprint& print);
session(int listen_port);
session(std::pair<int, int> listen_port_range, const fingerprint& print);
session(std::pair<int, int> listen_port_range);
~session();

View File

@ -84,7 +84,7 @@ namespace libtorrent
// TODO: add a check to see if filenames are accepted on the
// 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
class torrent_info

View File

@ -474,7 +474,7 @@ namespace libtorrent
INVARIANT_CHECK;
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");
m_statistics.received_bytes(0, received);
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";
#endif
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))
{
#ifndef NDEBUG
@ -1555,9 +1554,6 @@ namespace libtorrent
// only add new piece-chunks if the send buffer is small enough
// 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()
&& ((int)m_send_buffer.size() < m_torrent->block_size())
&& !m_choked)
@ -1680,7 +1676,7 @@ namespace libtorrent
// empty the entire buffer at once or if
// only a part of the buffer could be sent
// 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();
}
@ -1749,6 +1745,6 @@ namespace libtorrent
bool peer_connection::is_seed() const
{
return std::count(m_have_piece.begin(), m_have_piece.end(), true)
== m_have_piece.size();
== (int)m_have_piece.size();
}
}

View File

@ -144,9 +144,8 @@ namespace libtorrent
assert(sizeof(piece_pos) == 4);
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();
i != m_piece_map.end();
++i)
@ -163,7 +162,7 @@ namespace libtorrent
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;
for (std::vector<peer_connection*>::const_iterator peer = t->begin();
@ -262,7 +261,7 @@ namespace libtorrent
// update the piece_map
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;
@ -286,13 +285,13 @@ namespace libtorrent
m_piece_map[replace_index].index = elem_index;
assert((int)src_vec[peer_count].size() > elem_index);
assert(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].peer_count == peer_count);
assert((int)m_piece_map[replace_index].index == elem_index);
assert(src_vec[peer_count][elem_index] == replace_index);
}
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();
@ -519,9 +518,9 @@ namespace libtorrent
assert(i != m_downloads.end());
assert((int)i->finished_blocks.count() <= m_blocks_per_piece);
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;
}

View File

@ -761,7 +761,7 @@ namespace libtorrent
const std::vector<bool>& peer_has = i->connection->get_bitfield();
const std::vector<bool>& we_have = m_torrent->pieces();
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])
{

View File

@ -357,15 +357,18 @@ namespace libtorrent
return 0;
}
session_impl::session_impl(int listen_port,
session_impl::session_impl(std::pair<int, int> listen_port_range,
const fingerprint& cl_fprint)
: m_abort(false)
, m_tracker_manager(m_settings)
, m_listen_port(listen_port)
: m_tracker_manager(m_settings)
, m_listen_port_range(listen_port_range)
, m_listen_port(listen_port_range.first)
, m_abort(false)
, m_upload_rate(-1)
, 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 ----
@ -395,7 +398,7 @@ namespace libtorrent
{
m_connections.erase(m_disconnect_peer.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
{
#endif
boost::shared_ptr<socket> listener(new socket(socket::tcp, false));
int max_port = m_listen_port + 9;
// create listener socket
boost::shared_ptr<socket> listener(new socket(socket::tcp, false));
for(;;)
{
@ -422,9 +422,13 @@ namespace libtorrent
}
catch (std::exception&)
{
if (m_listen_port > max_port)
throw;
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;
}
break;
@ -470,7 +474,7 @@ namespace libtorrent
boost::mutex::scoped_lock l(m_mutex);
// +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)
{
@ -520,17 +524,21 @@ namespace libtorrent
}
catch (file_error& e)
{
torrent* t = p->second->associated_torrent();
assert(t != 0);
if (m_alerts.should_post(alert::fatal))
{
m_alerts.post_alert(
file_error_alert(
p->second->associated_torrent()->get_handle()
t->get_handle()
, e.what()));
}
m_selector.remove(*i);
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)
{
@ -544,7 +552,7 @@ namespace libtorrent
m_selector.remove(*i);
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)
{
torrent* t = p->second->associated_torrent();
assert(t != 0);
if (m_alerts.should_post(alert::fatal))
{
m_alerts.post_alert(
file_error_alert(
p->second->associated_torrent()->get_handle()
t->get_handle()
, e.what()));
}
m_selector.remove(*i);
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)
{
@ -623,7 +635,7 @@ namespace libtorrent
// from the connection-list
m_selector.remove(*i);
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())
{
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_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;
}
@ -822,13 +834,14 @@ namespace libtorrent
}
// TODO: take a port range instead!
session::session(int listen_port, const fingerprint& id)
: m_impl(listen_port, id)
session::session(std::pair<int, int> listen_port_range, const fingerprint& id)
: m_impl(listen_port_range, id)
, m_checker_impl(m_impl)
, m_thread(boost::ref(m_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
// this test was added after it came to my attention
// that devstudios managed c++ failed to generate
@ -838,12 +851,14 @@ namespace libtorrent
#endif
}
session::session(int listen_port)
: m_impl(listen_port, fingerprint("LT",0,0,1,0))
session::session(std::pair<int, int> listen_port_range)
: m_impl(listen_port_range, fingerprint("LT",0,0,1,0))
, m_checker_impl(m_impl)
, m_thread(boost::ref(m_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
boost::function0<void> test = boost::ref(m_impl);
assert(!test.empty());
@ -1071,7 +1086,7 @@ namespace libtorrent
const std::string& bitmask = i->dict()["bitmask"].string();
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)
{
unsigned char bits = bitmask[j];

View File

@ -144,7 +144,7 @@ namespace libtorrent
, const boost::filesystem::path& p
, 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();
for (torrent_info::file_iterator i = t.begin_files();
@ -326,6 +326,7 @@ namespace libtorrent
return result;
}
// throws file_error if it fails to write
void storage::write(
const char* buf
, int slot
@ -356,26 +357,18 @@ namespace libtorrent
}
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);
assert(file_offset < file_iter->size);
// out.seekp(file_offset);
out.seek(file_offset);
// assert(file_offset == out.tellp());
#ifndef NDEBUG
size_type out_tell = out.tell();
assert(file_offset == out_tell);
#endif
if (out.tell() != file_offset)
{
std::stringstream s;
s << "no storage for slot " << slot;
throw file_error(s.str());
}
int left_to_write = size;
int slot_size = m_pimpl->info.piece_size(slot);
@ -387,8 +380,6 @@ namespace libtorrent
int buf_pos = 0;
// TODO
// handle case when we can't write size bytes.
while (left_to_write > 0)
{
int write_bytes = left_to_write;
@ -400,7 +391,14 @@ namespace libtorrent
assert(buf_pos >= 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;
buf_pos += write_bytes;
@ -926,9 +924,6 @@ namespace libtorrent
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)
{
if (pieces[i] && i != current_slot) continue;
@ -1038,7 +1033,7 @@ namespace libtorrent
, std::vector<bool>& have_pieces
, 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 last_piece_size = m_info.piece_size(
@ -1234,9 +1229,6 @@ namespace libtorrent
}
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;
// build the hash-map, that maps hashes to pieces
@ -1329,7 +1321,7 @@ namespace libtorrent
if (m_free_slots.empty())
{
allocate_slots(5);
allocate_slots(1);
assert(!m_free_slots.empty());
}
@ -1349,9 +1341,9 @@ namespace libtorrent
if (*iter == m_info.num_pieces() - 1 && piece_index != *iter)
{
if (m_free_slots.size() == 1)
allocate_slots(5);
allocate_slots(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
iter = m_free_slots.end() - 1;
}
@ -1422,42 +1414,48 @@ namespace libtorrent
{
// this is used to notify potential other
// 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_cond(cond)
{}
~allocation_cleanup()
, m_monitor(monitor)
{
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_cond.notify_one();
}
bool& m_flag;
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)
{
assert(num_slots > 0);
{
boost::mutex::scoped_lock lock(m_allocating_monitor);
while (m_allocating)
m_allocating_condition.wait(lock);
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);
// this object will syncronize the allocation with
// potential other threads
allocation_syncronization sync_obj(
m_allocating
, m_allocating_condition
, m_allocating_monitor);
// synchronization ------------------------------------------------------
boost::recursive_mutex::scoped_lock lock(m_mutex);
@ -1476,7 +1474,7 @@ namespace libtorrent
++i)
{
int pos = m_unallocated_slots.front();
int piece_pos = pos;
// int piece_pos = pos;
int new_free_slot = pos;
if (m_piece_to_slot[pos] != has_no_slot)
@ -1516,8 +1514,8 @@ namespace libtorrent
// ----------------------------------------------------------------------
if (m_piece_to_slot.empty()) return;
assert(m_piece_to_slot.size() == m_info.num_pieces());
assert(m_slot_to_piece.size() == m_info.num_pieces());
assert((int)m_piece_to_slot.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();
i != m_free_slots.end();

View File

@ -745,7 +745,7 @@ namespace libtorrent
if (m_got_tracker_response == false)
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;
else
st.state = torrent_status::downloading;
@ -774,9 +774,7 @@ namespace libtorrent
try_next_tracker();
}
// TODO: this function should also take the
// HTTP-response code as an argument.
// with some codes, we should just consider
// TODO: with some response codes, we should just consider
// the tracker as a failure and not retry
// it anymore
void torrent::tracker_request_error(int response_code, const std::string& str)

View File

@ -209,7 +209,9 @@ namespace libtorrent
m_piece_hash.resize(num_pieces);
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)
std::copy(hash_string.begin() + i*20, hash_string.begin() + (i+1)*20, m_piece_hash[i].begin());
}