*** empty log message ***

This commit is contained in:
Arvid Norberg 2003-11-09 18:17:09 +00:00
parent 01d9d10157
commit 420ab6bff2
16 changed files with 310 additions and 180 deletions

View File

@ -1,5 +1,4 @@
project boost : $(BOOST_ROOT) ;
SOURCES =
entry.cpp
@ -7,7 +6,6 @@ SOURCES =
piece_picker.cpp
policy.cpp
session.cpp
# socket_bsd.cpp
socket_win.cpp
stat.cpp
storage.cpp
@ -20,6 +18,9 @@ SOURCES =
lib torrent
: src/$(SOURCES)
zlib//zlib
$(BOOST_ROOT)/libs/filesystem/build//boost_filesystem
$(BOOST_ROOT)/libs/thread/build//boost_thread
: <include>$(BOOST_ROOT)
<sysinclude>$(BOOST_ROOT)
<include>./include
@ -32,9 +33,7 @@ lib torrent
exe client_test
: examples/client_test.cpp
<lib>torrent
@boost/libs/filesystem/build/boost_filesystem
@boost/libs/thread/build/boost_thread
torrent
: <include>$(BOOST_ROOT)
<sysinclude>$(BOOST_ROOT)
<include>./include

View File

@ -56,6 +56,7 @@ The current state includes the following features:
<li>queues torrents for file check, instead of checking all of them in parallel.
<li>uses separate threads for checking files and for main downloader, with a fool-proof
thread-safe library interface. (i.e. There's no way for the user to cause a deadlock).
<li>can limit the upload bandwidth usage
</ul>
<p>
@ -64,12 +65,12 @@ Functions that are yet to be implemented:
<ul>
<li>optimistic unchoke
<li>upload speed cap
<li>Snubbing
<li>end game mode
<li>new allocation model
<li>fast resume
<li>file-level piece priority
<li>a good upload speed cap
</ul>
<p>
@ -159,6 +160,7 @@ class session: public boost::noncopyable
void remove_torrent(const torrent_handle&amp; h);
void set_http_settings(const http_settings&amp; settings);
void set_upload_rate_limit(int bytes_per_second);
};
</pre>
@ -188,6 +190,20 @@ identify the client. If the string is longer than 7 characters it will
be trimmed down to 7 characters. The default is an empty string.
</p>
<p>
<tt>set_upload_rate_limit()</tt> set the maximum number of bytes allowed to be
sent to peers per second. This bandwidth is distributed among all the peers. If
you don't want to limit upload rate, you can set this to -1 (the default).
</p>
<p>
The destructor of session will notify all trackers that our torrents has been shut down.
If some trackers are down, they will timout. All this before the destructor of session
returns. So, it's adviced that any kind of interface (such as windows) are closed before
destructing the sessoin object. Because it can take a few second for it to finish. The
timeout can be set with <tt>set_http_settings()</tt>.
</p>
<p>
How to parse a torrent file and create a <tt>torrent_info</tt> object is described below.
</p>
@ -655,6 +671,7 @@ struct peer_info
unsigned int total_upload;
peer_id id;
std::vector&lt;bool&gt; pieces;
int upload_limit;
};
</pre>
@ -695,6 +712,11 @@ in the torrent. Each boolean tells you if the peer has that piece (if it's set t
or if the peer miss that piece (set to false).
</p>
<p>
<tt>upload_limit</tt> is the number of bytes per second we are allowed to send to this
peer every second. It may be -1 if there's no limit.
</p>
<p>
TODO: address
</p>
@ -724,7 +746,7 @@ struct http_settings
<p>
<tt>tracker_timeout</tt> is the number of seconds the tracker connection will
wait until it considers the tracker to have timed-out. Default value is 30
wait until it considers the tracker to have timed-out. Default value is 10
seconds.
</p>

View File

@ -44,6 +44,11 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/http_settings.hpp"
#ifdef WIN32
#if defined(_MSC_VER)
# define for if (false) {} else for
#endif
#include <windows.h>
#include <conio.h>
@ -164,7 +169,7 @@ int main(int argc, char* argv[])
{
std::vector<torrent_handle> handles;
session s(6881, "E\x1");
s.set_upload_rate_limit(10240);
s.set_http_settings(settings);
for (int i = 0; i < argc-1; ++i)
{

View File

@ -68,7 +68,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/entry.hpp"
#if defined(_MSC_VER) && _MSC_VER < 1300
#if defined(_MSC_VER)
namespace std
{
using ::isdigit;

View File

@ -77,6 +77,12 @@ namespace libtorrent
virtual ~logger() {}
};
struct null_logger: libtorrent::logger
{
public:
virtual void log(const char* text) {}
};
struct cout_logger: libtorrent::logger
{
public:

View File

@ -151,13 +151,36 @@ namespace libtorrent
const stat& statistics() const { return m_statistics; }
// is called once every second by the main loop
void second_tick() { m_statistics.second_tick(); }
void second_tick()
{
m_statistics.second_tick();
m_send_quota_left = m_send_quota;
if (m_send_quota > 0) send_buffer_updated();
}
boost::shared_ptr<libtorrent::socket> get_socket() const { return m_socket; }
const peer_id& get_peer_id() const { return m_peer_id; }
const std::vector<bool>& get_bitfield() const { return m_have_piece; }
// sets the number of bytes this peer
// is allowed to send until it should
// stop sending. When it stops sending
// it will simply wait for another call
// to second_tick() where it will get
// more send quota.
void set_send_quota(int num_bytes);
// returns the send quota this peer has
// left until will stop sending.
// if the send_quota is -1, it means the
// quota is unlimited.
int send_quota_left() const { return m_send_quota_left; }
// returns the send quota assigned to this
// peer.
int send_quota() const { return m_send_quota; }
#ifndef NDEBUG
boost::shared_ptr<logger> m_logger;
#endif
@ -176,7 +199,7 @@ namespace libtorrent
enum state
{
read_protocol_length = 0,
read_protocol_version,
read_protocol_string,
read_info_hash,
read_peer_id,
@ -264,6 +287,20 @@ namespace libtorrent
std::vector<piece_block> m_download_queue;
stat m_statistics;
// this is used to limit upload bandwidth.
// it is reset to the allowed number of
// bytes to send frequently. Every time
// thie peer send some data,
// m_send_quota_left variable will be decreased
// so it can limit the number of bytes next
// time it sends data. when it reaches zero
// the client will stop send data and await
// more quota. if it is set to -1, the peer
// will ignore the qouta and send at maximum
// speed
int m_send_quota;
int m_send_quota_left;
};
// this is called each time this peer generates some
@ -271,8 +308,18 @@ namespace libtorrent
// the writibility monitor in the selector.
inline void peer_connection::send_buffer_updated()
{
if (!has_data()) return;
if (!has_data())
{
if (m_added_to_selector)
{
m_selector.remove_writable(m_socket);
m_added_to_selector = false;
}
assert(!m_selector.is_writability_monitored(m_socket));
return;
}
assert(has_data());
if (!m_added_to_selector)
{
m_selector.monitor_writability(m_socket);

View File

@ -56,6 +56,7 @@ namespace libtorrent
unsigned int total_upload;
peer_id id;
std::vector<bool> pieces;
int upload_limit;
};
}

View File

@ -173,16 +173,18 @@ namespace libtorrent
// the settings for the client
http_settings m_settings;
// set to true when the session object
// is being destructed and the thread
// should exit
volatile bool m_abort;
#ifndef NDEBUG
boost::shared_ptr<logger> create_log(std::string name)
{
name = "libtorrent_log_" + name + ".log";
// current options are file_logger and cout_logger
return boost::shared_ptr<logger>(new file_logger(name.c_str()));
}
// maximum upload rate given in
// bytes per second. -1 means
// unlimited
int m_upload_rate;
#ifndef NDEBUG
boost::shared_ptr<logger> create_log(std::string name);
boost::shared_ptr<logger> m_logger;
#endif
};
@ -208,6 +210,7 @@ namespace libtorrent
void remove_torrent(const torrent_handle& h);
void set_http_settings(const http_settings& s);
void set_upload_rate_limit(int bytes_per_second);
private:

0
project-root.jam Executable file
View File

View File

@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/entry.hpp"
#if defined(_MSC_VER) && _MSV_CER < 1300
#if defined(_MSC_VER)
namespace std
{
using ::isprint;

View File

@ -37,7 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/peer_connection.hpp"
#include "libtorrent/session.hpp"
#if defined(_MSC_VER) && _MSC_VER < 1300
#if defined(_MSC_VER)
#define for if (false) {} else for
#endif
@ -94,10 +94,12 @@ libtorrent::peer_connection::peer_connection(
, m_peer_choked(true)
, m_interesting(false)
, m_choked(true)
, m_send_quota(-1)
, m_send_quota_left(-1)
{
assert(m_torrent != 0);
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
m_logger = m_ses->create_log(s->sender().as_string().c_str());
#endif
@ -135,9 +137,11 @@ libtorrent::peer_connection::peer_connection(
, m_peer_choked(true)
, m_interesting(false)
, m_choked(true)
, m_send_quota(-1)
, m_send_quota_left(-1)
{
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
m_logger = m_ses->create_log(s->sender().as_string().c_str());
#endif
@ -156,20 +160,57 @@ libtorrent::peer_connection::~peer_connection()
if (m_torrent) m_torrent->remove_peer(this);
}
void libtorrent::peer_connection::set_send_quota(int num_bytes)
{
assert(num_bytes >= 0);
m_send_quota = num_bytes;
m_send_quota_left = num_bytes;
send_buffer_updated();
}
void libtorrent::peer_connection::send_handshake()
{
assert(m_send_buffer.size() == 0);
// add handshake to the send buffer
m_send_buffer.resize(68);
const char* version_string = "BitTorrent protocol";
m_send_buffer[0] = 19;
std::copy(version_string, version_string+19, m_send_buffer.begin()+1);
std::fill(m_send_buffer.begin() + 20, m_send_buffer.begin() + 28, 0);
std::copy(m_torrent->torrent_file().info_hash().begin(), m_torrent->torrent_file().info_hash().end(), m_send_buffer.begin() + 28);
std::copy(m_ses->get_peer_id().begin(), m_ses->get_peer_id().end(), m_send_buffer.begin() + 48);
const char version_string[] = "BitTorrent protocol";
const int string_len = sizeof(version_string)-1;
int pos = 1;
#if defined(TORRENT_VERBOSE_LOGGING)
m_send_buffer.resize(1 + string_len + 8 + 20 + 20);
// length of version string
m_send_buffer[0] = string_len;
// version string itself
std::copy(
version_string
, version_string+string_len
, m_send_buffer.begin()+pos);
pos += string_len;
// 8 zeroes
std::fill(
m_send_buffer.begin() + pos
, m_send_buffer.begin() + pos + 8
, 0);
pos += 8;
// info hash
std::copy(
m_torrent->torrent_file().info_hash().begin()
, m_torrent->torrent_file().info_hash().end()
, m_send_buffer.begin() + pos);
pos += 20;
// peer id
std::copy(
m_ses->get_peer_id().begin()
, m_ses->get_peer_id().end()
, m_send_buffer.begin() + pos);
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " ==> HANDSHAKE\n";
#endif
@ -187,7 +228,7 @@ bool libtorrent::peer_connection::dispatch_message()
// *************** CHOKE ***************
case msg_choke:
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " <== CHOKE\n";
#endif
m_peer_choked = true;
@ -211,7 +252,7 @@ bool libtorrent::peer_connection::dispatch_message()
// *************** UNCHOKE ***************
case msg_unchoke:
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " <== UNCHOKE\n";
#endif
m_peer_choked = false;
@ -221,7 +262,7 @@ bool libtorrent::peer_connection::dispatch_message()
// *************** INTERESTED ***************
case msg_interested:
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " <== INTERESTED\n";
#endif
m_peer_interested = true;
@ -231,7 +272,7 @@ bool libtorrent::peer_connection::dispatch_message()
// *************** NOT INTERESTED ***************
case msg_not_interested:
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " <== NOT_INTERESTED\n";
#endif
m_peer_interested = false;
@ -248,13 +289,13 @@ bool libtorrent::peer_connection::dispatch_message()
if (index >= m_have_piece.size())
return false;
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " <== HAVE [ piece: " << index << "]\n";
#endif
if (m_have_piece[index])
{
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " oops.. we already knew that: " << index << "\n";
#endif
}
@ -276,7 +317,7 @@ bool libtorrent::peer_connection::dispatch_message()
if (m_packet_size - 1 != (m_have_piece.size() + 7) / 8)
return false;
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " <== BITFIELD\n";
#endif
bool interesting = false;
@ -298,7 +339,7 @@ bool libtorrent::peer_connection::dispatch_message()
}
if (is_seed)
{
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " *** THIS IS A SEED ***\n";
#endif
}
@ -323,7 +364,7 @@ bool libtorrent::peer_connection::dispatch_message()
send_buffer_updated();
}
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " <== REQUEST [ piece: " << r.piece << " | s: " << r.start << " | l: " << r.length << " ]\n";
#endif
@ -338,7 +379,7 @@ bool libtorrent::peer_connection::dispatch_message()
std::size_t index = read_int(&m_recv_buffer[1]);
if (index < 0 || index >= m_torrent->torrent_file().num_pieces())
{
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " piece index invalid\n";
#endif
return false;
@ -348,7 +389,7 @@ bool libtorrent::peer_connection::dispatch_message()
if (offset < 0)
{
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " offset < 0\n";
#endif
return false;
@ -356,7 +397,7 @@ bool libtorrent::peer_connection::dispatch_message()
if (offset + len > m_torrent->torrent_file().piece_size(index))
{
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " piece packet contains more data than the piece size\n";
#endif
return false;
@ -364,7 +405,7 @@ bool libtorrent::peer_connection::dispatch_message()
if (offset % m_torrent->block_size() != 0)
{
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " piece packet contains unaligned offset\n";
#endif
return false;
@ -373,7 +414,7 @@ bool libtorrent::peer_connection::dispatch_message()
piece_block req = m_download_queue.front();
if (req.piece_index != index)
{
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " piece packet contains unrequested index\n";
#endif
return false;
@ -381,13 +422,13 @@ bool libtorrent::peer_connection::dispatch_message()
if (req.block_index != offset / m_torrent->block_size())
{
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " piece packet contains unrequested offset\n";
#endif
return false;
}
*/
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " <== PIECE [ piece: " << index << " | s: " << offset << " | l: " << len << " ]\n";
#endif
@ -479,7 +520,7 @@ bool libtorrent::peer_connection::dispatch_message()
m_selector.remove_writable(m_socket);
}
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " <== CANCEL [ piece: " << r.piece << " | s: " << r.start << " | l: " << r.length << " ]\n";
#endif
break;
@ -530,7 +571,7 @@ void libtorrent::peer_connection::cancel_block(piece_block block)
// length
write_int(block_size, &m_send_buffer[start_offset]);
start_offset += 4;
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " ==> CANCEL [ piece: " << block.piece_index << " | s: " << block_offset << " | l: " << block_size << " | " << block.block_index << " ]\n";
#endif
assert(start_offset == m_send_buffer.size());
@ -577,7 +618,7 @@ void libtorrent::peer_connection::request_block(piece_block block)
// length
write_int(block_size, &m_send_buffer[start_offset]);
start_offset += 4;
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " ==> REQUEST [ piece: " << block.piece_index << " | s: " << block_offset << " | l: " << block_size << " | " << block.block_index << " ]\n";
#endif
assert(start_offset == m_send_buffer.size());
@ -587,7 +628,7 @@ void libtorrent::peer_connection::request_block(piece_block block)
void libtorrent::peer_connection::send_bitfield()
{
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " ==> BITFIELD\n";
#endif
const int packet_size = (m_have_piece.size() + 7) / 8 + 5;
@ -610,7 +651,7 @@ void libtorrent::peer_connection::choke()
char msg[] = {0,0,0,1,msg_choke};
m_send_buffer.insert(m_send_buffer.end(), msg, msg+sizeof(msg));
m_choked = true;
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " ==> CHOKE\n";
#endif
send_buffer_updated();
@ -622,7 +663,7 @@ void libtorrent::peer_connection::unchoke()
char msg[] = {0,0,0,1,msg_unchoke};
m_send_buffer.insert(m_send_buffer.end(), msg, msg+sizeof(msg));
m_choked = false;
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " ==> UNCHOKE\n";
#endif
send_buffer_updated();
@ -634,7 +675,7 @@ void libtorrent::peer_connection::interested()
char msg[] = {0,0,0,1,msg_interested};
m_send_buffer.insert(m_send_buffer.end(), msg, msg+sizeof(msg));
m_interesting = true;
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " ==> INTERESTED\n";
#endif
send_buffer_updated();
@ -646,7 +687,7 @@ void libtorrent::peer_connection::not_interested()
char msg[] = {0,0,0,1,msg_not_interested};
m_send_buffer.insert(m_send_buffer.end(), msg, msg+sizeof(msg));
m_interesting = false;
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " ==> NOT_INTERESTED\n";
#endif
send_buffer_updated();
@ -657,7 +698,7 @@ void libtorrent::peer_connection::send_have(int index)
char msg[9] = {0,0,0,5,msg_have};
write_int(index, msg+5);
m_send_buffer.insert(m_send_buffer.end(), msg, msg+9);
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " ==> HAVE [ piece: " << index << " ]\n";
#endif
send_buffer_updated();
@ -681,11 +722,13 @@ void libtorrent::peer_connection::receive_data()
// an error
if (received < 0)
{
// would block means that no data was ready to be received
// would_block means that no data was ready to be received
// this should never happen, since we have a selector
//assert(m_socket->last_error() != socket::would_block);
if (m_socket->last_error() == socket::would_block) return;
// the connection was closed
throw network_error(0);
throw network_error(m_socket->last_error());
}
if (received > 0)
@ -701,28 +744,25 @@ void libtorrent::peer_connection::receive_data()
{
case read_protocol_length:
m_packet_size = reinterpret_cast<unsigned char&>(m_recv_buffer[0]);
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " protocol length: " << m_packet_size << "\n";
#endif
m_state = read_protocol_version;
if (m_packet_size != 19)
throw network_error(0);
m_state = read_protocol_string;
m_recv_buffer.resize(m_packet_size);
m_recv_pos = 0;
break;
case read_protocol_version:
case read_protocol_string:
{
const char* protocol_version = "BitTorrent protocol";
#if defined(TORRENT_VERBOSE_LOGGING)
(*m_logger) << m_socket->sender().as_string() << " protocol name: " << std::string(m_recv_buffer.begin(), m_recv_buffer.end()) << "\n";
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " protocol: '" << std::string(m_recv_buffer.begin(), m_recv_buffer.end()) << "'\n";
#endif
if (!std::equal(m_recv_buffer.begin(), m_recv_buffer.end(), protocol_version))
{
// unknown protocol, close connection
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))
throw network_error(0);
}
m_state = read_info_hash;
m_packet_size = 28;
m_recv_pos = 0;
@ -738,7 +778,11 @@ void libtorrent::peer_connection::receive_data()
if (m_torrent == 0)
{
// no, we have to see if there's a torrent with the
// TODO: if the protocol is to be extended
// these 8 bytes would be used to describe the
// extensions available on the other side
// now, we have to see if there's a torrent with the
// info_hash we got from the peer
sha1_hash info_hash;
std::copy(m_recv_buffer.begin()+8, m_recv_buffer.begin() + 28, (char*)info_hash.begin());
@ -747,7 +791,7 @@ void libtorrent::peer_connection::receive_data()
if (m_torrent == 0)
{
// we couldn't find the torrent!
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " couldn't find a torrent with the given info_hash\n";
#endif
throw network_error(0);
@ -769,7 +813,7 @@ void libtorrent::peer_connection::receive_data()
// verify info hash
if (!std::equal(m_recv_buffer.begin()+8, m_recv_buffer.begin() + 28, (const char*)m_torrent->torrent_file().info_hash().begin()))
{
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " received invalid info_hash\n";
#endif
throw network_error(0);
@ -780,7 +824,7 @@ void libtorrent::peer_connection::receive_data()
m_packet_size = 20;
m_recv_pos = 0;
m_recv_buffer.resize(20);
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " info_hash received\n";
#endif
break;
@ -796,7 +840,7 @@ void libtorrent::peer_connection::receive_data()
// can this be correct?
if (!std::equal(m_recv_buffer.begin(), m_recv_buffer.begin() + 20, (const char*)m_peer_id.begin()))
{
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " invalid peer_id (it doesn't equal the one from the tracker)\n";
#endif
throw network_error(0);
@ -809,7 +853,7 @@ void libtorrent::peer_connection::receive_data()
std::copy(m_recv_buffer.begin(), m_recv_buffer.begin() + 20, (char*)m_peer_id.begin());
if (m_torrent->num_connections(m_peer_id) > 1)
{
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " duplicate connection, closing\n";
#endif
throw network_error(0);
@ -820,7 +864,7 @@ void libtorrent::peer_connection::receive_data()
m_packet_size = 4;
m_recv_pos = 0;
m_recv_buffer.resize(4);
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " received peer_id\n";
#endif
break;
@ -833,7 +877,7 @@ void libtorrent::peer_connection::receive_data()
// don't accept packets larger than 1 MB
if (m_packet_size > 1024*1024 || m_packet_size < 0)
{
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " packet too large (packet_size > 1 Megabyte), abort\n";
#endif
// packet too large
@ -857,7 +901,7 @@ void libtorrent::peer_connection::receive_data()
case read_packet:
if (!dispatch_message())
{
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " received invalid packet\n";
#endif
// invalid message
@ -880,7 +924,10 @@ bool libtorrent::peer_connection::has_data() const throw()
{
// if we have requests or pending data to be sent or announcements to be made
// we want to send data
return (!m_requests.empty() && !m_choked) || !m_send_buffer.empty() || !m_announce_queue.empty();
return ((!m_requests.empty() && !m_choked)
|| !m_send_buffer.empty()
|| !m_announce_queue.empty())
&& m_send_quota_left != 0;
}
// --------------------------
@ -913,18 +960,19 @@ void libtorrent::peer_connection::send_data()
throw network_error(0);
}
if (m_sending_piece.index() != r.piece)
{
m_sending_piece.open(
m_torrent->filesystem()
, r.piece
, piece_file::in
, r.start);
m_sending_piece.open(
m_torrent->filesystem()
, r.piece
, piece_file::in
, r.start);
#ifndef NDEBUG
assert(m_torrent->filesystem()->verify_piece(m_sending_piece) && "internal error");
m_sending_piece.open(m_torrent->filesystem(), r.piece, piece_file::in);
assert(m_torrent->filesystem()->verify_piece(m_sending_piece) && "internal error");
m_sending_piece.open(
m_torrent->filesystem()
, r.piece
, piece_file::in
, r.start);
#endif
}
const int send_buffer_offset = m_send_buffer.size();
const int packet_size = 4 + 5 + 4 + r.length;
m_send_buffer.resize(send_buffer_offset + packet_size);
@ -936,7 +984,7 @@ void libtorrent::peer_connection::send_data()
assert(r.start == m_sending_piece.tell());
m_sending_piece.read(&m_send_buffer[send_buffer_offset+13], r.length);
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " ==> PIECE [ piece: " << r.piece << " | s: " << r.start << " | l: " << r.length << " ]\n";
#endif
// let the torrent keep track of how much we have uploaded
@ -944,7 +992,7 @@ void libtorrent::peer_connection::send_data()
}
else
{
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string()
<< " *** WARNING [ illegal piece request idx: " << r.piece
<< " | s: " << r.start
@ -970,22 +1018,33 @@ void libtorrent::peer_connection::send_data()
m_announce_queue.clear();
}
assert(m_send_quota_left != 0);
// send the actual buffer
if (!m_send_buffer.empty())
{
int amount_to_send = m_send_buffer.size();
assert(m_send_quota_left != 0);
if (m_send_quota_left > 0)
amount_to_send = std::min(m_send_quota_left, amount_to_send);
// we have data that's scheduled for sending
int sent = m_socket->send(
&m_send_buffer[0]
, m_send_buffer.size());
, amount_to_send);
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " ==> SENT [ length: " << sent << " ]\n";
#endif
if (sent > 0)
{
m_statistics.sent_bytes(sent);
if (m_send_quota_left != -1)
{
assert(m_send_quota_left >= sent);
m_send_quota_left -= sent;
}
// empty the entire buffer at once or if
// only a part of the buffer could be sent
@ -1011,13 +1070,9 @@ void libtorrent::peer_connection::send_data()
}
assert(m_added_to_selector);
if (!has_data())
{
m_selector.remove_writable(m_socket);
m_added_to_selector = false;
}
send_buffer_updated();
#ifndef NDEBUG
else
if (has_data())
{
if (m_socket->is_writable())
{
@ -1037,7 +1092,7 @@ void libtorrent::peer_connection::keep_alive()
char noop[] = {0,0,0,0};
m_send_buffer.insert(m_send_buffer.end(), noop, noop+4);
m_last_sent = boost::posix_time::second_clock::local_time();
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " ==> NOP\n";
#endif
send_buffer_updated();

View File

@ -40,7 +40,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/peer_connection.hpp"
#endif
#if defined(_MSC_VER) && _MSC_VER < 1300
#if defined(_MSC_VER)
#define for if (false) {} else for
#endif

View File

@ -59,20 +59,6 @@ namespace std
};
#endif
/*
DESIGN OVERVIEW AND RATIONALE
The main goal of this library is to be efficient, primarily memory-wise
but also CPU-wise. This goal has a number of implications:
* It must handle multiple torrents (multiple processes uses much more memory)
* It relies on a well working disk chache, since it will download directly to disk. This is
to scale better when having many peer connections.
*
*/
namespace libtorrent
{
namespace detail
@ -149,6 +135,7 @@ namespace libtorrent
: m_abort(false)
, m_tracker_manager(m_settings)
, m_listen_port(listen_port)
, m_upload_rate(-1)
{
// ---- generate a peer id ----
@ -178,11 +165,9 @@ namespace libtorrent
void session_impl::operator()()
{
eh_initializer();
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
m_logger = create_log("main session");
#endif
try
{
boost::shared_ptr<socket> listener(new socket(socket::tcp, false));
int max_port = m_listen_port + 9;
@ -206,7 +191,7 @@ namespace libtorrent
break;
}
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << "listening on port: " << m_listen_port << "\n";
#endif
m_selector.monitor_readability(listener);
@ -233,6 +218,17 @@ namespace libtorrent
for(;;)
{
#ifndef NDEBUG
for (connection_map::iterator i = m_connections.begin();
i != m_connections.end();
++i)
{
assert(i->second->has_data() == m_selector.is_writability_monitored(i->first));
}
#endif
// if nothing happens within 500000 microseconds (0.5 seconds)
// do the loop anyway to check if anything else has changed
// (*m_logger) << "sleeping\n";
@ -264,9 +260,6 @@ namespace libtorrent
// RECEIVE SOCKETS
// ************************
// TODO: once every second or so, all sockets should receive_data() to purge connections
// that has been closed. Otherwise we have to wait 2 minutes for their timeout
// let the readable clients receive data
for (std::vector<boost::shared_ptr<socket> >::iterator i = readable_clients.begin();
i != readable_clients.end();
@ -280,14 +273,16 @@ namespace libtorrent
if (s)
{
// we got a connection request!
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << s->sender().as_string() << " <== INCOMING CONNECTION\n";
#endif
// TODO: the send buffer size should be controllable from the outside
// s->set_send_bufsize(2048);
// TODO: add some possibility to filter IP:s
boost::shared_ptr<peer_connection> c(new peer_connection(this, m_selector, s));
boost::shared_ptr<peer_connection> c(
new peer_connection(this, m_selector, s));
if (m_upload_rate != -1) c->set_send_quota(100);
m_connections.insert(std::make_pair(s, c));
m_selector.monitor_readability(s);
m_selector.monitor_errors(s);
@ -378,51 +373,10 @@ namespace libtorrent
++i)
{
assert(i->second->has_data() == m_selector.is_writability_monitored(i->first));
// if (m_selector.is_writability_monitored(i->first))
// assert(i->second->has_data());
}
#endif
// clear all writablility monitors and add
// the ones who still has data to send
/* m_selector.clear_writable();
// ************************
// BUILD WRITER LIST
// ************************
// TODO: REWRITE THIS! DON'T GO THROUGH THIS LOOP EVERY TIME!
// loop over all clients and purge the ones that has timed out
// and check if they have pending data to be sent
for (connection_map::iterator i = m_connections.begin();
i != m_connections.end();)
{
connection_map::iterator j = i;
++i;
if (j->second->has_timed_out())
{
m_selector.remove(j->first);
m_connections.erase(j);
}
else
{
j->second->keep_alive();
if (j->second->has_data())
{
// (*m_logger) << j->first->sender().as_string() << " has data\n";
m_selector.monitor_writability(j->first);
}
else
{
// (*m_logger) << j->first->sender().as_string() << " has NO data\n";
}
}
}
*/
// (*m_logger) << "time: " << std::clock()-timer << "\n";
boost::posix_time::time_duration d = boost::posix_time::second_clock::local_time() - timer;
if (d.seconds() < 1) continue;
timer = boost::posix_time::second_clock::local_time();
@ -432,6 +386,23 @@ namespace libtorrent
// THE SECTION BELOW IS EXECUTED ONCE EVERY SECOND
// ************************
// distribute the maximum upload rate among the peers
// TODO: implement an intelligent algorithm that
// will shift bandwidth from the peers that can't
// utilize all their assigned bandwidth to the peers
// that actually can maintain the upload rate.
if (m_upload_rate != -1 && !m_connections.empty())
{
assert(m_upload_rate >= 0);
int share = m_upload_rate / m_connections.size();
for (connection_map::iterator i = m_connections.begin();
i != m_connections.end();
++i)
{
i->second->set_send_quota(share);
}
}
// do the second_tick() on each connection
// this will update their statistics (download and upload speeds)
// also purge sockets that have timed out
@ -481,7 +452,7 @@ namespace libtorrent
}
m_tracker_manager.tick();
#if defined(TORRENT_VERBOSE_LOGGING)
#ifndef NDEBUG
(*m_logger) << "peers: " << m_connections.size() << " \n";
for (connection_map::iterator i = m_connections.begin();
i != m_connections.end();
@ -503,17 +474,6 @@ namespace libtorrent
t.nsec += 1000000;
boost::thread::sleep(t);
}
}
catch(const std::exception& e)
{
std::cerr << e.what() << "\n";
}
catch(...)
{
std::cerr << "error\n";
}
}
@ -527,6 +487,19 @@ namespace libtorrent
return 0;
}
#ifndef NDEBUG
boost::shared_ptr<logger> session_impl::create_log(std::string name)
{
name = "libtorrent_log_" + name + ".log";
// current options are file_logger and cout_logger
#if defined(TORRENT_VERBOSE_LOGGING)
return boost::shared_ptr<logger>(new file_logger(name.c_str()));
#else
return boost::shared_ptr<logger>(new null_logger());
#endif
}
#endif
}
session::session(int listen_port, const std::string& fingerprint)
@ -627,6 +600,22 @@ namespace libtorrent
m_checker_thread.join();
}
void session::set_upload_rate_limit(int bytes_per_second)
{
assert(bytes_per_second > 0);
boost::mutex::scoped_lock l(m_impl.m_mutex);
m_impl.m_upload_rate = bytes_per_second;
if (m_impl.m_upload_rate != -1 || !m_impl.m_connections.empty())
return;
for (detail::session_impl::connection_map::iterator i
= m_impl.m_connections.begin();
i != m_impl.m_connections.end();)
{
i->second->set_send_quota(-1);
}
}
// TODO: document
// TODO: if the first 4 charachters are printable
// maybe they should be considered a fingerprint?

View File

@ -48,7 +48,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/hasher.hpp"
#include "libtorrent/session.hpp"
#if defined(_MSC_VER) && _MSV_CER < 1300
#if defined(_MSC_VER)
#define for if (false) {} else for
#endif

View File

@ -347,6 +347,7 @@ namespace libtorrent
, this
, s
, id));
if (m_ses->m_upload_rate != -1) c->set_send_quota(100);
detail::session_impl::connection_map::iterator p =
m_ses->m_connections.insert(std::make_pair(s, c)).first;
attach_peer(boost::get_pointer(p->second));

View File

@ -139,6 +139,8 @@ namespace libtorrent
p.total_download = statistics.total_download();
p.total_upload = statistics.total_upload();
p.upload_limit = peer->send_quota();
p.flags = 0;
if (peer->is_interesting()) p.flags |= peer_info::interesting;
if (peer->has_choked()) p.flags |= peer_info::choked;