2003-10-23 01:00:57 +02:00
|
|
|
/*
|
|
|
|
|
|
|
|
Copyright (c) 2003, Arvid Norberg
|
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions
|
|
|
|
are met:
|
|
|
|
|
|
|
|
* Redistributions of source code must retain the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in
|
|
|
|
the documentation and/or other materials provided with the distribution.
|
|
|
|
* Neither the name of the author nor the names of its
|
|
|
|
contributors may be used to endorse or promote products derived
|
|
|
|
from this software without specific prior written permission.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
|
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
implemented
|
|
|
|
|
|
|
|
* http-proxy authentication for tracker requests
|
|
|
|
* multitracker support
|
|
|
|
* spawns separate temporary threads for file checking
|
|
|
|
*
|
|
|
|
|
|
|
|
missing
|
|
|
|
|
|
|
|
* endgame-mode
|
|
|
|
* correct algorithm for choking and unchoking
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2003-10-26 18:35:23 +01:00
|
|
|
#ifndef TORRENT_SESSION_HPP_INCLUDED
|
2003-10-23 01:00:57 +02:00
|
|
|
#define TORRENT_SESSION_HPP_INCLUDED
|
|
|
|
|
|
|
|
#include <ctime>
|
|
|
|
#include <algorithm>
|
|
|
|
#include <vector>
|
|
|
|
#include <set>
|
|
|
|
#include <list>
|
2003-10-31 05:02:51 +01:00
|
|
|
#include <deque>
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
#include <boost/limits.hpp>
|
|
|
|
#include <boost/tuple/tuple.hpp>
|
|
|
|
#include <boost/filesystem/path.hpp>
|
|
|
|
#include <boost/thread.hpp>
|
|
|
|
|
2003-10-26 18:35:23 +01:00
|
|
|
#include "libtorrent/torrent_handle.hpp"
|
2003-10-23 01:00:57 +02:00
|
|
|
#include "libtorrent/torrent.hpp"
|
|
|
|
#include "libtorrent/entry.hpp"
|
|
|
|
#include "libtorrent/torrent_info.hpp"
|
|
|
|
#include "libtorrent/socket.hpp"
|
|
|
|
#include "libtorrent/peer_connection.hpp"
|
|
|
|
#include "libtorrent/peer_id.hpp"
|
|
|
|
#include "libtorrent/policy.hpp"
|
|
|
|
#include "libtorrent/url_handler.hpp"
|
|
|
|
#include "libtorrent/peer_info.hpp"
|
|
|
|
#include "libtorrent/debug.hpp"
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: if we're not interested and the peer isn't interested, close the connections
|
|
|
|
// TODO: instead of implementing end-game mode, have an algorithm that
|
|
|
|
// constantly prioritizes high-bandwidth sources.
|
|
|
|
|
|
|
|
namespace libtorrent
|
|
|
|
{
|
|
|
|
|
|
|
|
namespace detail
|
|
|
|
{
|
2003-11-05 18:42:27 +01:00
|
|
|
// workaround for microsofts
|
|
|
|
// hardware exceptions that makes
|
|
|
|
// it hard to debug stuff
|
2003-11-06 11:44:19 +01:00
|
|
|
#if defined(_MSC_VER) && !defined(NDEBUG)
|
2003-11-05 18:42:27 +01:00
|
|
|
struct eh_initializer
|
|
|
|
{
|
|
|
|
eh_initializer()
|
|
|
|
{ _set_se_translator(straight_to_debugger); }
|
|
|
|
|
|
|
|
static void straight_to_debugger(unsigned int, EXCEPTION_POINTERS*)
|
|
|
|
{ throw; }
|
|
|
|
};
|
|
|
|
#else
|
|
|
|
struct eh_initializer {};
|
|
|
|
#endif
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2003-10-30 00:28:09 +01:00
|
|
|
// this data is shared between the main thread and the
|
|
|
|
// thread that initialize pieces
|
2003-10-23 01:00:57 +02:00
|
|
|
struct piece_checker_data
|
|
|
|
{
|
2003-10-31 05:02:51 +01:00
|
|
|
piece_checker_data(): progress(0.f), abort(false) {}
|
2003-10-30 00:28:09 +01:00
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
boost::shared_ptr<torrent> torrent_ptr;
|
2003-11-07 02:44:30 +01:00
|
|
|
boost::filesystem::path save_path;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
sha1_hash info_hash;
|
|
|
|
|
2003-10-30 00:28:09 +01:00
|
|
|
// is filled in by storage::initialize_pieces()
|
|
|
|
// and represents the progress. It should be a
|
|
|
|
// value in the range [0, 1]
|
2003-10-31 16:06:32 +01:00
|
|
|
volatile float progress;
|
2003-10-30 00:28:09 +01:00
|
|
|
|
|
|
|
// abort defaults to false and is typically
|
|
|
|
// filled in by torrent_handle when the user
|
|
|
|
// aborts the torrent
|
2003-10-31 16:06:32 +01:00
|
|
|
volatile bool abort;
|
2003-10-23 01:00:57 +02:00
|
|
|
};
|
|
|
|
|
2003-10-31 05:02:51 +01:00
|
|
|
struct checker_impl: boost::noncopyable
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
2003-10-31 05:02:51 +01:00
|
|
|
checker_impl(session_impl* s): m_ses(s), m_abort(false) {}
|
2003-10-23 01:00:57 +02:00
|
|
|
void operator()();
|
2003-10-31 05:02:51 +01:00
|
|
|
piece_checker_data* find_torrent(const sha1_hash& info_hash);
|
|
|
|
|
|
|
|
// when the files has been checked
|
|
|
|
// the torrent is added to the session
|
|
|
|
session_impl* m_ses;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2003-10-31 05:02:51 +01:00
|
|
|
boost::mutex m_mutex;
|
|
|
|
boost::condition m_cond;
|
|
|
|
|
|
|
|
// a list of all torrents that are currently checking
|
|
|
|
// their files (in separate threads)
|
|
|
|
std::deque<piece_checker_data> m_torrents;
|
|
|
|
|
|
|
|
bool m_abort;
|
|
|
|
};
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
// this is the link between the main thread and the
|
|
|
|
// thread started to run the main downloader loop
|
2003-10-31 05:02:51 +01:00
|
|
|
struct session_impl: boost::noncopyable
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
|
|
|
typedef std::map<boost::shared_ptr<socket>, boost::shared_ptr<peer_connection> > connection_map;
|
|
|
|
|
2003-10-31 05:02:51 +01:00
|
|
|
session_impl(int listen_port, const std::string& fingerprint);
|
|
|
|
void operator()();
|
2003-10-25 03:31:06 +02:00
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
// must be locked to access the data
|
|
|
|
// in this struct
|
|
|
|
boost::mutex m_mutex;
|
2003-10-31 05:02:51 +01:00
|
|
|
torrent* find_torrent(const sha1_hash& info_hash);
|
|
|
|
const peer_id& get_peer_id() const { return m_peer_id; }
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
tracker_manager m_tracker_manager;
|
|
|
|
std::map<sha1_hash, boost::shared_ptr<torrent> > m_torrents;
|
|
|
|
connection_map m_connections;
|
|
|
|
|
|
|
|
// the peer id that is generated at the start of each torrent
|
|
|
|
peer_id m_peer_id;
|
|
|
|
|
2003-10-31 05:02:51 +01:00
|
|
|
// the port we are listening on for connections
|
|
|
|
int m_listen_port;
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
// this is where all active sockets are stored.
|
|
|
|
// the selector can sleep while there's no activity on
|
|
|
|
// them
|
|
|
|
selector m_selector;
|
|
|
|
|
2003-10-25 03:31:06 +02:00
|
|
|
// the settings for the client
|
|
|
|
http_settings m_settings;
|
|
|
|
|
2003-10-31 16:06:32 +01:00
|
|
|
volatile bool m_abort;
|
2003-10-23 01:00:57 +02:00
|
|
|
|
2003-11-08 03:16:26 +01:00
|
|
|
#ifndef NDEBUG
|
2003-10-25 03:31:06 +02:00
|
|
|
boost::shared_ptr<logger> create_log(std::string name)
|
|
|
|
{
|
2003-10-28 02:20:50 +01:00
|
|
|
name = "libtorrent_log_" + name + ".log";
|
2003-10-25 03:31:06 +02:00
|
|
|
// current options are file_logger and cout_logger
|
|
|
|
return boost::shared_ptr<logger>(new file_logger(name.c_str()));
|
|
|
|
}
|
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
boost::shared_ptr<logger> m_logger;
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
struct http_settings;
|
|
|
|
|
2003-10-25 03:31:06 +02:00
|
|
|
std::string extract_fingerprint(const peer_id& p);
|
|
|
|
|
2003-11-05 18:42:27 +01:00
|
|
|
class session: public boost::noncopyable, detail::eh_initializer
|
2003-10-23 01:00:57 +02:00
|
|
|
{
|
|
|
|
public:
|
2003-10-25 03:31:06 +02:00
|
|
|
|
2003-11-07 02:44:30 +01:00
|
|
|
session(int listen_port, const std::string& fingerprint = std::string());
|
2003-10-25 03:31:06 +02:00
|
|
|
|
2003-10-23 01:00:57 +02:00
|
|
|
~session();
|
|
|
|
|
|
|
|
// all torrent_handles must be destructed before the session is destructed!
|
2003-11-07 02:44:30 +01:00
|
|
|
torrent_handle add_torrent(
|
|
|
|
const torrent_info& ti
|
|
|
|
, const boost::filesystem::path& save_path);
|
2003-11-08 03:16:26 +01:00
|
|
|
void remove_torrent(const torrent_handle& h);
|
2003-10-23 01:00:57 +02:00
|
|
|
|
|
|
|
void set_http_settings(const http_settings& s);
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
2003-10-31 05:02:51 +01:00
|
|
|
// data shared between the main thread
|
|
|
|
// and the working thread
|
2003-10-23 01:00:57 +02:00
|
|
|
detail::session_impl m_impl;
|
|
|
|
|
2003-10-31 05:02:51 +01:00
|
|
|
// data shared between the main thread
|
|
|
|
// and the checker thread
|
|
|
|
detail::checker_impl m_checker_impl;
|
|
|
|
|
2003-10-30 00:28:09 +01:00
|
|
|
// the main working thread
|
2003-10-23 01:00:57 +02:00
|
|
|
boost::thread m_thread;
|
2003-10-31 05:02:51 +01:00
|
|
|
|
|
|
|
// the thread that calls initialize_pieces()
|
|
|
|
// on all torrents before they start downloading
|
|
|
|
boost::thread m_checker_thread;
|
2003-10-23 01:00:57 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // TORRENT_SESSION_HPP_INCLUDED
|