*** empty log message ***

This commit is contained in:
Arvid Norberg 2004-02-26 00:27:06 +00:00
parent 7af8beff02
commit 2d363127e9
15 changed files with 139 additions and 63 deletions

21
Jamfile
View File

@ -13,14 +13,6 @@ use-project /boost/date_time : $(BOOST_ROOT)/libs/date_time/build ;
project torrent project torrent
: requirements : requirements
<use>/boost/thread
<use>/boost/date_time
<use>/boost/filesystem
<library>/boost/thread
<library>/boost/date_time
<library>/boost/filesystem
: usage-requirements : usage-requirements
<include>./include <include>./include
@ -49,6 +41,7 @@ SOURCES =
piece_picker.cpp piece_picker.cpp
policy.cpp policy.cpp
session.cpp session.cpp
socket.cpp
stat.cpp stat.cpp
storage.cpp storage.cpp
torrent.cpp torrent.cpp
@ -63,15 +56,6 @@ SOURCES =
# use different versions of some files for # use different versions of some files for
# windows # windows
if [ modules.peek : NT ]
{
SOURCES += socket_win.cpp ;
}
else
{
SOURCES += socket_bsd.cpp ;
}
if [ modules.peek : NT ] && toolset != msvc-6 if [ modules.peek : NT ] && toolset != msvc-6
{ {
SOURCES += file_win.cpp ; SOURCES += file_win.cpp ;
@ -86,6 +70,9 @@ lib torrent
: :
zlib//zlib zlib//zlib
src/$(SOURCES) src/$(SOURCES)
/boost/thread//boost_thread/<link>shared
/boost/date_time//boost_date_time/<link>static
/boost/filesystem//boost_filesystem/<link>static
: :
<include>./include <include>./include
<threading>multi <threading>multi

View File

@ -69,11 +69,11 @@ libtorrent has been successfully compiled and tested on:
* Windows 2000 vc7.1 * Windows 2000 vc7.1
* Linux x86 (debian) GCC 3.0.4, GCC 3.2.3 * Linux x86 (debian) GCC 3.0.4, GCC 3.2.3
* Windows 2000, msvc6 sp5 (does not support 64-bit values due to problems with operator<<(ostream&, __int64)) * Windows 2000, msvc6 sp5 (does not support 64-bit values due to problems with operator<<(ostream&, __int64))
* Cygwin GCC 3.3.1
Fails on: Fails on:
* GCC 2.95.4 (``std::ios_base`` is missing) * GCC 2.95.4 (``std::ios_base`` is missing)
* Cygwin GCC 3.3.1 (builds but crashes)
libtorrent is released under the BSD-license_. libtorrent is released under the BSD-license_.
@ -116,11 +116,7 @@ version of boost, `boost 1.30.2`__.
__ http://sourceforge.net/project/showfiles.php?group_id=7586&package_id=8041&release_id=178835 __ http://sourceforge.net/project/showfiles.php?group_id=7586&package_id=8041&release_id=178835
There are two versions of the socket code, one that works with unix systems (and bsd-sockets) and There are two versions of the file abstraction. There's one ``file_win.cpp`` which
one that uses winsock. If you're building in windows, the file ``socket_win.cpp`` is supposed to
be included in the build while ``socket_bsd.cpp`` is supposed to be excluded.
The file abstraction has the same kind of separation. There's one ``file_win.cpp`` which
relies on windows file API that supports files larger than 2 Gigabytes. This does not work relies on windows file API that supports files larger than 2 Gigabytes. This does not work
in vc6 for some reason, possibly because it may require windows NT and above. The other file, in vc6 for some reason, possibly because it may require windows NT and above. The other file,
``file.cpp`` is the default implementation that simply relies on the standard library's fstream, ``file.cpp`` is the default implementation that simply relies on the standard library's fstream,
@ -189,8 +185,12 @@ The ``session`` class has the following synopsis::
class session: public boost::noncopyable class session: public boost::noncopyable
{ {
session(std::pair<int, int> listen_port_range, const fingerprint& print);
session(std::pair<int, int> listen_port_range); session(std::pair<int, int> listen_port_range);
session(
std::pair<int, int> listen_port_range
, const fingerprint& print
, const char* listen_interface = 0);
torrent_handle add_torrent( torrent_handle add_torrent(
const torrent_info& t const torrent_info& t
@ -250,7 +250,11 @@ increase the port number by one and try again. If it still fails it will continu
increasing the port number until it succeeds or has reached the end of the range. If it 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 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 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. it and possibly try again or change the port range. The listen interaface string is
the name (ip address) of the interface you want to listen on. If this is left as
0, the os will decide which interface to listen on (works in most cases). All torrents
will use this interface to open outgoing connections on by default. You can change
which interface to use for outgoing connections on a per torrent basis. See torrent_handle_.
For information about the ``pop_alert()`` function, see alerts_. For information about the ``pop_alert()`` function, see alerts_.
@ -527,6 +531,8 @@ Its declaration looks like this::
void set_tracker_login(std::string const& username, std::string const& password); void set_tracker_login(std::string const& username, std::string const& password);
void use_interface(const char* net_interface);
boost::filsystem::path save_path() const; boost::filsystem::path save_path() const;
void set_max_uploads(int max_uploads); void set_max_uploads(int max_uploads);
@ -568,6 +574,9 @@ as a standard client.
``set_tracker_login()`` sets a username and password that will be sent along in the HTTP-request ``set_tracker_login()`` sets a username and password that will be sent along in the HTTP-request
of the tracker announce. Set this if the tracker requires authorization. of the tracker announce. Set this if the tracker requires authorization.
``use_interface()`` sets the network interface this torrent will use when it opens outgoing
connections. By default, it uses the same interface as the session_ uses to listen on.
``info_hash()`` returns the info hash for the torrent. ``info_hash()`` returns the info hash for the torrent.
``set_max_uploads()`` sets the maximum number of peers that's unchoked at the same time on this ``set_max_uploads()`` sets the maximum number of peers that's unchoked at the same time on this

View File

@ -240,7 +240,10 @@ int main(int argc, char* argv[])
try try
{ {
std::vector<torrent_handle> handles; std::vector<torrent_handle> handles;
session ses(std::make_pair(6881, 6889)); session ses(
std::make_pair(6881, 6889)
, fingerprint("LT", 0, 1, 0, 0)
, "192.168.0.1");
ses.set_upload_rate_limit(20 * 1024); ses.set_upload_rate_limit(20 * 1024);
ses.set_http_settings(settings); ses.set_http_settings(settings);

View File

@ -159,7 +159,8 @@ namespace libtorrent
session_impl( session_impl(
std::pair<int, int> listen_port_range std::pair<int, int> listen_port_range
, const fingerprint& cl_fprint); , const fingerprint& cl_fprint
, const char* listen_interface);
void operator()(); void operator()();
@ -189,8 +190,12 @@ namespace libtorrent
// the range of ports we try to listen on // the range of ports we try to listen on
std::pair<int, int> m_listen_port_range; std::pair<int, int> m_listen_port_range;
// the port we are listening on for connections // the ip-address of the interface
int m_listen_port; // we are supposed to listen on.
// if the ip is set to zero, it means
// that we should let the os decide which
// interface to listen on
address m_listen_interface;
// this is where all active sockets are stored. // this is where all active sockets are stored.
// the selector can sleep while there's no activity on // the selector can sleep while there's no activity on
@ -238,8 +243,11 @@ namespace libtorrent
{ {
public: public:
session(std::pair<int, int> listen_port_range, const fingerprint& print);
session(std::pair<int, int> listen_port_range); session(std::pair<int, int> listen_port_range);
session(
std::pair<int, int> listen_port_range
, const fingerprint& print
, const char* listen_interface = 0);
~session(); ~session();

View File

@ -40,6 +40,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <boost/cstdint.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
@ -51,6 +52,9 @@ POSSIBILITY OF SUCH DAMAGE.
#include <string> #include <string>
// TODO: support ToS // TODO: support ToS
// TODO: support binding to selected interface
// Distinguish between binding listen sockets and
// outgoing connections.
namespace libtorrent namespace libtorrent
{ {
@ -60,6 +64,8 @@ namespace libtorrent
public: public:
network_error(int error_code): m_error_code(error_code) {} network_error(int error_code): m_error_code(error_code) {}
virtual const char* what() const throw(); virtual const char* what() const throw();
int error_code() const
{ return m_error_code; }
private: private:
int m_error_code; int m_error_code;
}; };
@ -80,25 +86,28 @@ namespace libtorrent
address(unsigned int addr, unsigned short port); address(unsigned int addr, unsigned short port);
address(const std::string& addr, unsigned short port); address(const char* addr, unsigned short port);
address(const address& a); address(const address& a);
~address(); ~address();
std::string as_string() const; std::string as_string() const;
unsigned int ip() const { return m_ip; } unsigned int ip() const { return m_ip; }
unsigned short port() const { return m_port; }
bool operator<(const address& a) const bool operator<(const address& a) const
{ if (ip() == a.ip()) return port() < a.port(); else return ip() < a.ip(); } { if (ip() == a.ip()) return port < a.port; else return ip() < a.ip(); }
bool operator!=(const address& a) const bool operator!=(const address& a) const
{ return ip() != a.ip() || port() != a.port(); } { return ip() != a.ip() || port != a.port; }
bool operator==(const address& a) const bool operator==(const address& a) const
{ return ip() == a.ip() && port() == a.port(); } { return ip() == a.ip() && port == a.port; }
unsigned short port;
const static unsigned short any_port = 0;
const static unsigned int any_addr = 0;
private: private:
unsigned int m_ip; unsigned int m_ip;
unsigned short m_port;
}; };
class socket: public boost::noncopyable class socket: public boost::noncopyable
@ -116,7 +125,10 @@ namespace libtorrent
socket(type t, bool blocking = true, unsigned short receive_port = 0); socket(type t, bool blocking = true, unsigned short receive_port = 0);
virtual ~socket(); virtual ~socket();
void connect(const address& addr); void connect(
const address& addr
, address const& bind_to
= address(address::any_addr, address::any_port));
void close(); void close();
void set_blocking(bool blocking); void set_blocking(bool blocking);
@ -125,7 +137,7 @@ namespace libtorrent
const address& sender() const { return m_sender; } const address& sender() const { return m_sender; }
address name() const; address name() const;
void listen(unsigned short port, int queue); void listen(libtorrent::address const& iface, int queue);
boost::shared_ptr<libtorrent::socket> accept(); boost::shared_ptr<libtorrent::socket> accept();
template<class T> int send(const T& buffer); template<class T> int send(const T& buffer);

View File

@ -124,6 +124,9 @@ namespace libtorrent
size_type total_protocol_upload() const { return m_total_upload_protocol; } size_type total_protocol_upload() const { return m_total_upload_protocol; }
size_type total_protocol_download() const { return m_total_download_protocol; } size_type total_protocol_download() const { return m_total_download_protocol; }
// this is used to offset the statistics when a
// peer_connection is opened and have some previous
// transfers from earlier connections.
void add_stat(size_type downloaded, size_type uploaded) void add_stat(size_type downloaded, size_type uploaded)
{ {
m_total_download_payload += downloaded; m_total_download_payload += downloaded;

View File

@ -86,7 +86,8 @@ namespace libtorrent
torrent( torrent(
detail::session_impl& ses detail::session_impl& ses
, const torrent_info& torrent_file , const torrent_info& torrent_file
, const boost::filesystem::path& save_path); , const boost::filesystem::path& save_path
, address const& net_interface);
~torrent(); ~torrent();
@ -122,6 +123,7 @@ namespace libtorrent
torrent_status status() const; torrent_status status() const;
void use_interface(const char* net_interface);
peer_connection& connect_to_peer(const address& a); peer_connection& connect_to_peer(const address& a);
const torrent_info& torrent_file() const const torrent_info& torrent_file() const
@ -357,6 +359,7 @@ namespace libtorrent
std::string m_username; std::string m_username;
std::string m_password; std::string m_password;
address m_net_interface;
}; };
} }

View File

@ -151,6 +151,10 @@ namespace libtorrent
const torrent_info& get_torrent_info() const; const torrent_info& get_torrent_info() const;
bool is_valid() const; bool is_valid() const;
// set the interface to bind outgoing connections
// to.
void use_interface(const char* net_interface);
// TODO: there must be a way to get resume data and // TODO: there must be a way to get resume data and
// shut down the torrent in one atomic operation // shut down the torrent in one atomic operation
entry write_resume_data() const; entry write_resume_data() const;

View File

@ -341,4 +341,4 @@ namespace libtorrent
} }
} }
} }

View File

@ -108,7 +108,7 @@ namespace libtorrent
// TODO: this is a problem. DNS-lookup is blocking! // TODO: this is a problem. DNS-lookup is blocking!
// (may block up to 5 seconds) // (may block up to 5 seconds)
address a(*connect_to_host, port); address a(connect_to_host->c_str(), port);
boost::shared_ptr<socket> s(new socket(socket::tcp, false)); boost::shared_ptr<socket> s(new socket(socket::tcp, false));
s->connect(a); s->connect(a);

View File

@ -733,7 +733,7 @@ namespace libtorrent
void policy::peer_from_tracker(const address& remote, const peer_id& id) void policy::peer_from_tracker(const address& remote, const peer_id& id)
{ {
// just ignore the obviously invalid entries from the tracker // just ignore the obviously invalid entries from the tracker
if(remote.ip() == 0 || remote.port() == 0) if(remote.ip() == 0 || remote.port == 0)
return; return;
try try

View File

@ -248,18 +248,20 @@ namespace libtorrent
return 0; return 0;
} }
session_impl::session_impl(std::pair<int, int> listen_port_range, session_impl::session_impl(
const fingerprint& cl_fprint) std::pair<int, int> listen_port_range
, const fingerprint& cl_fprint
, const char* listen_interface = 0)
: m_tracker_manager(m_settings) : m_tracker_manager(m_settings)
, m_listen_port_range(listen_port_range) , m_listen_port_range(listen_port_range)
, m_listen_port(listen_port_range.first) , m_listen_interface(listen_interface, listen_port_range.first)
, m_abort(false) , m_abort(false)
, m_upload_rate(-1) , m_upload_rate(-1)
, m_incoming_connection(false) , m_incoming_connection(false)
{ {
assert(listen_port_range.first > 0); assert(listen_port_range.first > 0);
assert(listen_port_range.first < listen_port_range.second); assert(listen_port_range.first < listen_port_range.second);
assert(m_listen_port > 0); assert(m_listen_interface.port > 0);
// ---- generate a peer id ---- // ---- generate a peer id ----
@ -309,12 +311,18 @@ namespace libtorrent
{ {
try try
{ {
listener->listen(m_listen_port, 5); listener->listen(m_listen_interface, 10);
} }
catch (std::exception&) catch (network_error& e)
{ {
m_listen_port++; if (e.error_code() == socket::address_not_available)
if (m_listen_port > m_listen_port_range.second) {
std::string msg = "cannot listen on the given interface '" + m_listen_interface.as_string() + "'";
m_alerts.post_alert(listen_failed_alert(msg));
return;
}
m_listen_interface.port++;
if (m_listen_interface.port > m_listen_port_range.second)
{ {
m_alerts.post_alert(listen_failed_alert( m_alerts.post_alert(listen_failed_alert(
"none of the ports in the given range could be opened")); "none of the ports in the given range could be opened"));
@ -326,7 +334,7 @@ namespace libtorrent
} }
#ifndef NDEBUG #ifndef NDEBUG
(*m_logger) << "listening on port: " << m_listen_port << "\n"; (*m_logger) << "listening on port: " << m_listen_interface.port << "\n";
#endif #endif
m_selector.monitor_readability(listener); m_selector.monitor_readability(listener);
m_selector.monitor_errors(listener); m_selector.monitor_errors(listener);
@ -376,7 +384,7 @@ namespace libtorrent
++i) ++i)
{ {
i->second->abort(); i->second->abort();
m_tracker_manager.queue_request(i->second->generate_tracker_request(m_listen_port)); m_tracker_manager.queue_request(i->second->generate_tracker_request(m_listen_interface.port));
} }
m_connections.clear(); m_connections.clear();
m_torrents.clear(); m_torrents.clear();
@ -621,7 +629,7 @@ namespace libtorrent
if (i->second->is_aborted()) if (i->second->is_aborted())
{ {
m_tracker_manager.queue_request( m_tracker_manager.queue_request(
i->second->generate_tracker_request(m_listen_port)); i->second->generate_tracker_request(m_listen_interface.port));
i->second->disconnect_all(); i->second->disconnect_all();
#ifndef NDEBUG #ifndef NDEBUG
sha1_hash i_hash = i->second->torrent_file().info_hash(); sha1_hash i_hash = i->second->torrent_file().info_hash();
@ -635,7 +643,7 @@ namespace libtorrent
else if (i->second->should_request()) else if (i->second->should_request())
{ {
m_tracker_manager.queue_request( m_tracker_manager.queue_request(
i->second->generate_tracker_request(m_listen_port) i->second->generate_tracker_request(m_listen_interface.port)
, boost::get_pointer(i->second)); , boost::get_pointer(i->second));
} }
@ -740,8 +748,11 @@ namespace libtorrent
} }
session::session(std::pair<int, int> listen_port_range, const fingerprint& id) session::session(
: m_impl(listen_port_range, id) std::pair<int, int> listen_port_range
, const fingerprint& id
, const char* listen_interface)
: m_impl(listen_port_range, id, listen_interface)
, 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))
@ -802,7 +813,7 @@ namespace libtorrent
// the checker thread and store it before starting // the checker thread and store it before starting
// the thread // the thread
boost::shared_ptr<torrent> torrent_ptr( boost::shared_ptr<torrent> torrent_ptr(
new torrent(m_impl, ti, save_path)); new torrent(m_impl, ti, save_path, m_impl.m_listen_interface));
detail::piece_checker_data d; detail::piece_checker_data d;
d.torrent_ptr = torrent_ptr; d.torrent_ptr = torrent_ptr;
@ -943,7 +954,7 @@ namespace libtorrent
++i) ++i)
{ {
address a( address a(
i->dict()["ip"].string() i->dict()["ip"].string().c_str()
, (unsigned short)i->dict()["port"].integer()); , (unsigned short)i->dict()["port"].integer());
tmp_peers.push_back(a); tmp_peers.push_back(a);
} }

View File

@ -216,7 +216,8 @@ namespace libtorrent
torrent::torrent( torrent::torrent(
detail::session_impl& ses detail::session_impl& ses
, const torrent_info& torrent_file , const torrent_info& torrent_file
, const boost::filesystem::path& save_path) , const boost::filesystem::path& save_path
, address const& net_interface)
: m_block_size(calculate_block_size(torrent_file)) : m_block_size(calculate_block_size(torrent_file))
, m_abort(false) , m_abort(false)
, m_event(tracker_request::started) , m_event(tracker_request::started)
@ -235,6 +236,7 @@ namespace libtorrent
, m_num_pieces(0) , m_num_pieces(0)
, m_got_tracker_response(false) , m_got_tracker_response(false)
, m_ratio(0.f) , m_ratio(0.f)
, m_net_interface(net_interface)
{ {
assert(torrent_file.begin_files() != torrent_file.end_files()); assert(torrent_file.begin_files() != torrent_file.end_files());
m_have_pieces.resize(torrent_file.num_pieces(), false); m_have_pieces.resize(torrent_file.num_pieces(), false);
@ -245,6 +247,11 @@ namespace libtorrent
if (m_ses.m_abort) m_abort = true; if (m_ses.m_abort) m_abort = true;
} }
void torrent::use_interface(const char* net_interface)
{
m_net_interface = address(net_interface, address::any_port);
}
void torrent::tracker_response( void torrent::tracker_response(
std::vector<peer_entry>& peer_list std::vector<peer_entry>& peer_list
, int interval) , int interval)
@ -290,7 +297,7 @@ namespace libtorrent
if (i->id == m_ses.get_peer_id()) if (i->id == m_ses.get_peer_id())
continue; continue;
address a(i->ip, i->port); address a(i->ip.c_str(), i->port);
m_policy->peer_from_tracker(a, i->id); m_policy->peer_from_tracker(a, i->id);
} }
@ -530,7 +537,7 @@ namespace libtorrent
peer_connection& torrent::connect_to_peer(const address& a) peer_connection& torrent::connect_to_peer(const address& a)
{ {
boost::shared_ptr<socket> s(new socket(socket::tcp, false)); boost::shared_ptr<socket> s(new socket(socket::tcp, false));
s->connect(a); s->connect(a, m_net_interface);
boost::shared_ptr<peer_connection> c(new peer_connection( boost::shared_ptr<peer_connection> c(new peer_connection(
m_ses m_ses
, m_ses.m_selector , m_ses.m_selector

View File

@ -102,6 +102,35 @@ namespace libtorrent
throw invalid_handle(); throw invalid_handle();
} }
void torrent_handle::use_interface(const char* net_interface)
{
if (m_ses == 0) throw invalid_handle();
{
boost::mutex::scoped_lock l(m_ses->m_mutex);
torrent* t = m_ses->find_torrent(m_info_hash);
if (t != 0)
{
t->use_interface(net_interface);
return;
}
}
if (m_chk)
{
boost::mutex::scoped_lock l(m_chk->m_mutex);
detail::piece_checker_data* d = m_chk->find_torrent(m_info_hash);
if (d != 0)
{
d->torrent_ptr->use_interface(net_interface);
return;
}
}
throw invalid_handle();
}
void torrent_handle::set_max_connections(int max_connections) void torrent_handle::set_max_connections(int max_connections)
{ {
assert(max_connections > 2 || max_connections == -1); assert(max_connections > 2 || max_connections == -1);
@ -320,7 +349,7 @@ namespace libtorrent
address ip = i->second->get_socket()->sender(); address ip = i->second->get_socket()->sender();
entry::dictionary_type peer; entry::dictionary_type peer;
peer["ip"] = ip.as_string(); peer["ip"] = ip.as_string();
peer["port"] = ip.port(); peer["port"] = ip.port;
peer_list.push_back(peer); peer_list.push_back(peer);
} }

View File

@ -73,7 +73,7 @@ namespace libtorrent
{ {
// TODO: this is a problem. DNS-lookup is blocking! // TODO: this is a problem. DNS-lookup is blocking!
// (may block up to 5 seconds) // (may block up to 5 seconds)
address a(hostname, port); address a(hostname.c_str(), port);
m_socket.reset(new socket(socket::udp, false)); m_socket.reset(new socket(socket::udp, false));
m_socket->connect(a); m_socket->connect(a);