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

View File

@ -69,11 +69,11 @@ libtorrent has been successfully compiled and tested on:
* Windows 2000 vc7.1
* 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))
* Cygwin GCC 3.3.1
Fails on:
* GCC 2.95.4 (``std::ios_base`` is missing)
* Cygwin GCC 3.3.1 (builds but crashes)
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
There are two versions of the socket code, one that works with unix systems (and bsd-sockets) and
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
There are two versions of the file abstraction. There's one ``file_win.cpp`` which
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,
``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
{
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
, const fingerprint& print
, const char* listen_interface = 0);
torrent_handle add_torrent(
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
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.
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_.
@ -527,6 +531,8 @@ Its declaration looks like this::
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;
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
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.
``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
{
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_http_settings(settings);

View File

@ -159,7 +159,8 @@ namespace libtorrent
session_impl(
std::pair<int, int> listen_port_range
, const fingerprint& cl_fprint);
, const fingerprint& cl_fprint
, const char* listen_interface);
void operator()();
@ -189,8 +190,12 @@ namespace libtorrent
// 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;
// the ip-address of the interface
// 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.
// the selector can sleep while there's no activity on
@ -238,8 +243,11 @@ namespace libtorrent
{
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
, const fingerprint& print
, const char* listen_interface = 0);
~session();

View File

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

View File

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

View File

@ -151,6 +151,10 @@ namespace libtorrent
const torrent_info& get_torrent_info() 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
// shut down the torrent in one atomic operation
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!
// (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));
s->connect(a);

View File

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

View File

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

View File

@ -216,7 +216,8 @@ namespace libtorrent
torrent::torrent(
detail::session_impl& ses
, 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_abort(false)
, m_event(tracker_request::started)
@ -235,6 +236,7 @@ namespace libtorrent
, m_num_pieces(0)
, m_got_tracker_response(false)
, m_ratio(0.f)
, m_net_interface(net_interface)
{
assert(torrent_file.begin_files() != torrent_file.end_files());
m_have_pieces.resize(torrent_file.num_pieces(), false);
@ -245,6 +247,11 @@ namespace libtorrent
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(
std::vector<peer_entry>& peer_list
, int interval)
@ -290,7 +297,7 @@ namespace libtorrent
if (i->id == m_ses.get_peer_id())
continue;
address a(i->ip, i->port);
address a(i->ip.c_str(), i->port);
m_policy->peer_from_tracker(a, i->id);
}
@ -530,7 +537,7 @@ namespace libtorrent
peer_connection& torrent::connect_to_peer(const address& a)
{
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(
m_ses
, m_ses.m_selector

View File

@ -102,6 +102,35 @@ namespace libtorrent
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)
{
assert(max_connections > 2 || max_connections == -1);
@ -320,7 +349,7 @@ namespace libtorrent
address ip = i->second->get_socket()->sender();
entry::dictionary_type peer;
peer["ip"] = ip.as_string();
peer["port"] = ip.port();
peer["port"] = ip.port;
peer_list.push_back(peer);
}

View File

@ -73,7 +73,7 @@ namespace libtorrent
{
// TODO: this is a problem. DNS-lookup is blocking!
// (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->connect(a);