fix shit :P

This commit is contained in:
Marcos Pinto 2008-07-02 03:50:47 +00:00
parent b5e986c3b4
commit f9c2fc0720
101 changed files with 19457 additions and 227 deletions

View File

@ -0,0 +1,180 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
/* GeoIP.h
*
* Copyright (C) 2006 MaxMind LLC
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef GEOIP_H
#define GEOIP_H
#ifdef __cplusplus
extern "C" {
#endif
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <sys/types.h> /* for fstat */
#include <sys/stat.h> /* for fstat */
#define SEGMENT_RECORD_LENGTH 3
#define STANDARD_RECORD_LENGTH 3
#define ORG_RECORD_LENGTH 4
#define MAX_RECORD_LENGTH 4
#define NUM_DB_TYPES 20
typedef struct GeoIPTag {
FILE *GeoIPDatabase;
char *file_path;
unsigned char *cache;
unsigned char *index_cache;
unsigned int *databaseSegments;
char databaseType;
time_t mtime;
int flags;
off_t size;
char record_length;
int charset; /* 0 iso-8859-1 1 utf8 */
int record_iter; /* used in GeoIP_next_record */
int netmask; /* netmask of last lookup - set using depth in _GeoIP_seek_record */
} GeoIP;
typedef enum {
GEOIP_CHARSET_ISO_8859_1 = 0,
GEOIP_CHARSET_UTF8 = 1
} GeoIPCharset;
typedef struct GeoIPRegionTag {
char country_code[3];
char region[3];
} GeoIPRegion;
typedef enum {
GEOIP_STANDARD = 0,
GEOIP_MEMORY_CACHE = 1,
GEOIP_CHECK_CACHE = 2,
GEOIP_INDEX_CACHE = 4,
GEOIP_MMAP_CACHE = 8,
} GeoIPOptions;
typedef enum {
GEOIP_COUNTRY_EDITION = 1,
GEOIP_REGION_EDITION_REV0 = 7,
GEOIP_CITY_EDITION_REV0 = 6,
GEOIP_ORG_EDITION = 5,
GEOIP_ISP_EDITION = 4,
GEOIP_CITY_EDITION_REV1 = 2,
GEOIP_REGION_EDITION_REV1 = 3,
GEOIP_PROXY_EDITION = 8,
GEOIP_ASNUM_EDITION = 9,
GEOIP_NETSPEED_EDITION = 10,
GEOIP_DOMAIN_EDITION = 11
} GeoIPDBTypes;
typedef enum {
GEOIP_ANON_PROXY = 1,
GEOIP_HTTP_X_FORWARDED_FOR_PROXY = 2,
GEOIP_HTTP_CLIENT_IP_PROXY = 3,
} GeoIPProxyTypes;
typedef enum {
GEOIP_UNKNOWN_SPEED = 0,
GEOIP_DIALUP_SPEED = 1,
GEOIP_CABLEDSL_SPEED = 2,
GEOIP_CORPORATE_SPEED = 3,
} GeoIPNetspeedValues;
extern char **GeoIPDBFileName;
extern const char * GeoIPDBDescription[NUM_DB_TYPES];
extern const char *GeoIPCountryDBFileName;
extern const char *GeoIPRegionDBFileName;
extern const char *GeoIPCityDBFileName;
extern const char *GeoIPOrgDBFileName;
extern const char *GeoIPISPDBFileName;
extern const char GeoIP_country_code[253][3];
extern const char GeoIP_country_code3[253][4];
extern const char * GeoIP_country_name[253];
extern const char GeoIP_country_continent[253][3];
#ifdef DLL
#define GEOIP_API __declspec(dllexport)
#else
#define GEOIP_API
#endif /* DLL */
GEOIP_API void GeoIP_setup_custom_directory(char *dir);
GEOIP_API GeoIP* GeoIP_open_type (int type, int flags);
GEOIP_API GeoIP* GeoIP_new(int flags);
GEOIP_API GeoIP* GeoIP_open(const char * filename, int flags);
GEOIP_API int GeoIP_db_avail(int type);
GEOIP_API void GeoIP_delete(GeoIP* gi);
GEOIP_API const char *GeoIP_country_code_by_addr (GeoIP* gi, const char *addr);
GEOIP_API const char *GeoIP_country_code_by_name (GeoIP* gi, const char *host);
GEOIP_API const char *GeoIP_country_code3_by_addr (GeoIP* gi, const char *addr);
GEOIP_API const char *GeoIP_country_code3_by_name (GeoIP* gi, const char *host);
GEOIP_API const char *GeoIP_country_name_by_addr (GeoIP* gi, const char *addr);
GEOIP_API const char *GeoIP_country_name_by_name (GeoIP* gi, const char *host);
GEOIP_API const char *GeoIP_country_name_by_ipnum (GeoIP* gi, unsigned long ipnum);
GEOIP_API const char *GeoIP_country_code_by_ipnum (GeoIP* gi, unsigned long ipnum);
GEOIP_API const char *GeoIP_country_code3_by_ipnum (GeoIP* gi, unsigned long ipnum);
/* Deprecated - for backwards compatibility only */
GEOIP_API int GeoIP_country_id_by_addr (GeoIP* gi, const char *addr);
GEOIP_API int GeoIP_country_id_by_name (GeoIP* gi, const char *host);
GEOIP_API char *GeoIP_org_by_addr (GeoIP* gi, const char *addr);
GEOIP_API char *GeoIP_org_by_name (GeoIP* gi, const char *host);
/* End deprecated */
GEOIP_API int GeoIP_id_by_addr (GeoIP* gi, const char *addr);
GEOIP_API int GeoIP_id_by_name (GeoIP* gi, const char *host);
GEOIP_API int GeoIP_id_by_ipnum (GeoIP* gi, unsigned long ipnum);
GEOIP_API GeoIPRegion * GeoIP_region_by_addr (GeoIP* gi, const char *addr);
GEOIP_API GeoIPRegion * GeoIP_region_by_name (GeoIP* gi, const char *host);
GEOIP_API GeoIPRegion * GeoIP_region_by_ipnum (GeoIP *gi, unsigned long ipnum);
/* Warning - don't call this after GeoIP_assign_region_by_inetaddr calls */
GEOIP_API void GeoIPRegion_delete (GeoIPRegion *gir);
GEOIP_API void GeoIP_assign_region_by_inetaddr(GeoIP* gi, unsigned long inetaddr, GeoIPRegion *gir);
/* Used to query GeoIP Organization, ISP and AS Number databases */
GEOIP_API char *GeoIP_name_by_ipnum (GeoIP* gi, unsigned long ipnum);
GEOIP_API char *GeoIP_name_by_addr (GeoIP* gi, const char *addr);
GEOIP_API char *GeoIP_name_by_name (GeoIP* gi, const char *host);
GEOIP_API char *GeoIP_database_info (GeoIP* gi);
GEOIP_API unsigned char GeoIP_database_edition (GeoIP* gi);
GEOIP_API int GeoIP_charset (GeoIP* gi);
GEOIP_API int GeoIP_set_charset (GeoIP* gi, int charset);
GEOIP_API int GeoIP_last_netmask (GeoIP* gi);
/* Convert region code to region name */
GEOIP_API const char * GeoIP_region_name_by_code(const char *country_code, const char *region_code);
/* Get timezone from country and region code */
GEOIP_API const char * GeoIP_time_zone_by_country_and_region(const char *country_code, const char *region_code);
#ifdef __cplusplus
}
#endif
#endif /* GEOIP_H */

View File

@ -0,0 +1,168 @@
/*
Copyright (c) 2003, Arvid Norberg, Daniel Wallin
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.
*/
#ifndef TORRENT_ALERT_HPP_INCLUDED
#define TORRENT_ALERT_HPP_INCLUDED
#include <memory>
#include <queue>
#include <string>
#include <typeinfo>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/time.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#ifndef TORRENT_MAX_ALERT_TYPES
#define TORRENT_MAX_ALERT_TYPES 15
#endif
namespace libtorrent {
class TORRENT_EXPORT alert
{
public:
enum severity_t { debug, info, warning, critical, fatal, none };
alert(severity_t severity, const std::string& msg);
virtual ~alert();
// a timestamp is automatically created in the constructor
ptime timestamp() const;
std::string const& msg() const;
severity_t severity() const;
virtual std::auto_ptr<alert> clone() const = 0;
private:
std::string m_msg;
severity_t m_severity;
ptime m_timestamp;
};
class TORRENT_EXPORT alert_manager
{
public:
alert_manager();
~alert_manager();
void post_alert(const alert& alert_);
bool pending() const;
std::auto_ptr<alert> get();
void set_severity(alert::severity_t severity);
bool should_post(alert::severity_t severity) const;
alert const* wait_for_alert(time_duration max_wait);
private:
std::queue<alert*> m_alerts;
alert::severity_t m_severity;
mutable boost::mutex m_mutex;
boost::condition m_condition;
};
struct TORRENT_EXPORT unhandled_alert : std::exception
{
unhandled_alert() {}
};
namespace detail {
struct void_;
template<class Handler
, BOOST_PP_ENUM_PARAMS(TORRENT_MAX_ALERT_TYPES, class T)>
void handle_alert_dispatch(
const std::auto_ptr<alert>& alert_, const Handler& handler
, const std::type_info& typeid_
, BOOST_PP_ENUM_BINARY_PARAMS(TORRENT_MAX_ALERT_TYPES, T, *p))
{
if (typeid_ == typeid(T0))
handler(*static_cast<T0*>(alert_.get()));
else
handle_alert_dispatch(alert_, handler, typeid_
, BOOST_PP_ENUM_SHIFTED_PARAMS(
TORRENT_MAX_ALERT_TYPES, p), (void_*)0);
}
template<class Handler>
void handle_alert_dispatch(
const std::auto_ptr<alert>& alert_
, const Handler& handler
, const std::type_info& typeid_
, BOOST_PP_ENUM_PARAMS(TORRENT_MAX_ALERT_TYPES, void_* BOOST_PP_INTERCEPT))
{
throw unhandled_alert();
}
} // namespace detail
template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
TORRENT_MAX_ALERT_TYPES, class T, detail::void_)>
struct TORRENT_EXPORT handle_alert
{
template<class Handler>
handle_alert(const std::auto_ptr<alert>& alert_
, const Handler& handler)
{
#define ALERT_POINTER_TYPE(z, n, text) (BOOST_PP_CAT(T, n)*)0
detail::handle_alert_dispatch(alert_, handler, typeid(*alert_)
, BOOST_PP_ENUM(TORRENT_MAX_ALERT_TYPES, ALERT_POINTER_TYPE, _));
#undef ALERT_POINTER_TYPE
}
};
} // namespace libtorrent
#endif // TORRENT_ALERT_HPP_INCLUDED

View File

@ -0,0 +1,559 @@
/*
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.
*/
#ifndef TORRENT_ALERT_TYPES_HPP_INCLUDED
#define TORRENT_ALERT_TYPES_HPP_INCLUDED
#include "libtorrent/alert.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_connection.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{
struct TORRENT_EXPORT torrent_alert: alert
{
torrent_alert(torrent_handle const& h, alert::severity_t s
, std::string const& msg)
: alert(s, msg)
, handle(h)
{}
torrent_handle handle;
};
struct TORRENT_EXPORT file_renamed_alert: torrent_alert
{
file_renamed_alert(torrent_handle const& h
, std::string const& name_
, std::string const& msg)
: torrent_alert(h, alert::warning, msg)
, name(name_)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new file_renamed_alert(*this)); }
std::string name;
};
struct TORRENT_EXPORT tracker_alert: torrent_alert
{
tracker_alert(torrent_handle const& h
, std::string const& url_
, alert::severity_t s
, std::string const& msg)
: torrent_alert(h, s, msg)
, url(url_)
{}
std::string url;
};
struct TORRENT_EXPORT tracker_error_alert: tracker_alert
{
tracker_error_alert(torrent_handle const& h
, int times
, int status
, std::string const& url
, std::string const& msg)
: tracker_alert(h, url, alert::warning, msg)
, times_in_row(times)
, status_code(status)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new tracker_error_alert(*this)); }
int times_in_row;
int status_code;
};
struct TORRENT_EXPORT tracker_warning_alert: tracker_alert
{
tracker_warning_alert(torrent_handle const& h
, std::string const& url
, std::string const& msg)
: tracker_alert(h, url, alert::warning, msg)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new tracker_warning_alert(*this)); }
};
struct TORRENT_EXPORT scrape_reply_alert: tracker_alert
{
scrape_reply_alert(torrent_handle const& h
, int incomplete_
, int complete_
, std::string const& url
, std::string const& msg)
: tracker_alert(h, url, alert::info, msg)
, incomplete(incomplete_)
, complete(complete_)
{}
int incomplete;
int complete;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new scrape_reply_alert(*this)); }
};
struct TORRENT_EXPORT scrape_failed_alert: tracker_alert
{
scrape_failed_alert(torrent_handle const& h
, std::string const& url
, std::string const& msg)
: tracker_alert(h, url, alert::warning, msg)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new scrape_failed_alert(*this)); }
};
struct TORRENT_EXPORT tracker_reply_alert: tracker_alert
{
tracker_reply_alert(torrent_handle const& h
, int np
, std::string const& url
, std::string const& msg)
: tracker_alert(h, url, alert::info, msg)
, num_peers(np)
{}
int num_peers;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new tracker_reply_alert(*this)); }
};
struct TORRENT_EXPORT tracker_announce_alert: tracker_alert
{
tracker_announce_alert(torrent_handle const& h
, std::string const& url
, std::string const& msg)
: tracker_alert(h, url, alert::info, msg)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new tracker_announce_alert(*this)); }
};
struct TORRENT_EXPORT hash_failed_alert: torrent_alert
{
hash_failed_alert(
torrent_handle const& h
, int index
, std::string const& msg)
: torrent_alert(h, alert::info, msg)
, piece_index(index)
{ TORRENT_ASSERT(index >= 0);}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new hash_failed_alert(*this)); }
int piece_index;
};
struct TORRENT_EXPORT peer_ban_alert: torrent_alert
{
peer_ban_alert(tcp::endpoint const& pip, torrent_handle h, std::string const& msg)
: torrent_alert(h, alert::info, msg)
, ip(pip)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new peer_ban_alert(*this)); }
tcp::endpoint ip;
};
struct TORRENT_EXPORT peer_error_alert: alert
{
peer_error_alert(tcp::endpoint const& pip, peer_id const& pid_, std::string const& msg)
: alert(alert::info, msg)
, ip(pip)
, pid(pid_)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new peer_error_alert(*this)); }
tcp::endpoint ip;
peer_id pid;
};
struct TORRENT_EXPORT peer_disconnected_alert: alert
{
peer_disconnected_alert(tcp::endpoint const& pip, peer_id const& pid_, std::string const& msg)
: alert(alert::debug, msg)
, ip(pip)
, pid(pid_)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new peer_disconnected_alert(*this)); }
tcp::endpoint ip;
peer_id pid;
};
struct TORRENT_EXPORT invalid_request_alert: torrent_alert
{
invalid_request_alert(
peer_request const& r
, torrent_handle const& h
, tcp::endpoint const& sender
, peer_id const& pid_
, std::string const& msg)
: torrent_alert(h, alert::debug, msg)
, ip(sender)
, request(r)
, pid(pid_)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new invalid_request_alert(*this)); }
tcp::endpoint ip;
peer_request request;
peer_id pid;
};
struct TORRENT_EXPORT torrent_finished_alert: torrent_alert
{
torrent_finished_alert(
const torrent_handle& h
, const std::string& msg)
: torrent_alert(h, alert::warning, msg)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new torrent_finished_alert(*this)); }
};
struct TORRENT_EXPORT piece_finished_alert: torrent_alert
{
piece_finished_alert(
const torrent_handle& h
, int piece_num
, const std::string& msg)
: torrent_alert(h, alert::debug, msg)
, piece_index(piece_num)
{ TORRENT_ASSERT(piece_index >= 0);}
int piece_index;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new piece_finished_alert(*this)); }
};
struct TORRENT_EXPORT block_finished_alert: torrent_alert
{
block_finished_alert(
const torrent_handle& h
, int block_num
, int piece_num
, const std::string& msg)
: torrent_alert(h, alert::debug, msg)
, block_index(block_num)
, piece_index(piece_num)
{ TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);}
int block_index;
int piece_index;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new block_finished_alert(*this)); }
};
struct TORRENT_EXPORT block_downloading_alert: torrent_alert
{
block_downloading_alert(
const torrent_handle& h
, char const* speedmsg
, int block_num
, int piece_num
, const std::string& msg)
: torrent_alert(h, alert::debug, msg)
, peer_speedmsg(speedmsg)
, block_index(block_num)
, piece_index(piece_num)
{ TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);}
std::string peer_speedmsg;
int block_index;
int piece_index;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new block_downloading_alert(*this)); }
};
struct TORRENT_EXPORT storage_moved_alert: torrent_alert
{
storage_moved_alert(torrent_handle const& h, std::string const& path)
: torrent_alert(h, alert::warning, path)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new storage_moved_alert(*this)); }
};
struct TORRENT_EXPORT torrent_deleted_alert: torrent_alert
{
torrent_deleted_alert(torrent_handle const& h, std::string const& msg)
: torrent_alert(h, alert::warning, msg)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new torrent_deleted_alert(*this)); }
};
struct TORRENT_EXPORT save_resume_data_alert: torrent_alert
{
save_resume_data_alert(boost::shared_ptr<entry> const& rd
, torrent_handle const& h, std::string const& msg)
: torrent_alert(h, alert::warning, msg)
, resume_data(rd)
{}
boost::shared_ptr<entry> resume_data;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new save_resume_data_alert(*this)); }
};
struct TORRENT_EXPORT torrent_paused_alert: torrent_alert
{
torrent_paused_alert(torrent_handle const& h, std::string const& msg)
: torrent_alert(h, alert::warning, msg)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new torrent_paused_alert(*this)); }
};
struct TORRENT_EXPORT torrent_checked_alert: torrent_alert
{
torrent_checked_alert(torrent_handle const& h, std::string const& msg)
: torrent_alert(h, alert::info, msg)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new torrent_checked_alert(*this)); }
};
struct TORRENT_EXPORT url_seed_alert: torrent_alert
{
url_seed_alert(
torrent_handle const& h
, const std::string& url_
, const std::string& msg)
: torrent_alert(h, alert::warning, msg)
, url(url_)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new url_seed_alert(*this)); }
std::string url;
};
struct TORRENT_EXPORT file_error_alert: torrent_alert
{
file_error_alert(
std::string const& f
, const torrent_handle& h
, const std::string& msg)
: torrent_alert(h, alert::fatal, msg)
, file(f)
{}
std::string file;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new file_error_alert(*this)); }
};
struct TORRENT_EXPORT metadata_failed_alert: torrent_alert
{
metadata_failed_alert(
const torrent_handle& h
, const std::string& msg)
: torrent_alert(h, alert::info, msg)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new metadata_failed_alert(*this)); }
};
struct TORRENT_EXPORT metadata_received_alert: torrent_alert
{
metadata_received_alert(
const torrent_handle& h
, const std::string& msg)
: torrent_alert(h, alert::info, msg)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new metadata_received_alert(*this)); }
};
struct TORRENT_EXPORT udp_error_alert: alert
{
udp_error_alert(
udp::endpoint const& ep
, std::string const& msg)
: alert(alert::info, msg)
, endpoint(ep)
{}
udp::endpoint endpoint;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new udp_error_alert(*this)); }
};
struct TORRENT_EXPORT external_ip_alert: alert
{
external_ip_alert(
address const& ip
, std::string const& msg)
: alert(alert::info, msg)
, external_address(ip)
{}
address external_address;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new external_ip_alert(*this)); }
};
struct TORRENT_EXPORT listen_failed_alert: alert
{
listen_failed_alert(
tcp::endpoint const& ep
, std::string const& msg)
: alert(alert::fatal, msg)
, endpoint(ep)
{}
tcp::endpoint endpoint;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new listen_failed_alert(*this)); }
};
struct TORRENT_EXPORT listen_succeeded_alert: alert
{
listen_succeeded_alert(
tcp::endpoint const& ep
, std::string const& msg)
: alert(alert::fatal, msg)
, endpoint(ep)
{}
tcp::endpoint endpoint;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new listen_succeeded_alert(*this)); }
};
struct TORRENT_EXPORT portmap_error_alert: alert
{
portmap_error_alert(int i, int t, const std::string& msg)
: alert(alert::warning, msg), mapping(i), type(t)
{}
int mapping;
int type;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new portmap_error_alert(*this)); }
};
struct TORRENT_EXPORT portmap_alert: alert
{
portmap_alert(int i, int port, int t, const std::string& msg)
: alert(alert::info, msg), mapping(i), external_port(port), type(t)
{}
int mapping;
int external_port;
int type;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new portmap_alert(*this)); }
};
struct TORRENT_EXPORT fastresume_rejected_alert: torrent_alert
{
fastresume_rejected_alert(torrent_handle const& h
, std::string const& msg)
: torrent_alert(h, alert::warning, msg)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new fastresume_rejected_alert(*this)); }
};
struct TORRENT_EXPORT peer_blocked_alert: alert
{
peer_blocked_alert(address const& ip_
, std::string const& msg)
: alert(alert::info, msg)
, ip(ip_)
{}
address ip;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new peer_blocked_alert(*this)); }
};
struct TORRENT_EXPORT torrent_resumed_alert: torrent_alert
{
torrent_resumed_alert(torrent_handle const& h, std::string const& msg)
: torrent_alert(h, alert::warning, msg)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new torrent_resumed_alert(*this)); }
};
}
#endif

View File

@ -0,0 +1,53 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_ASSERT
#include "libtorrent/config.hpp"
#include <string>
#ifdef __GNUC__
std::string demangle(char const* name);
#endif
#if (defined __linux__ || defined __MACH__) && defined __GNUC__ && !defined(NDEBUG)
TORRENT_EXPORT void assert_fail(const char* expr, int line, char const* file, char const* function);
#define TORRENT_ASSERT(x) if (x) {} else assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__)
#else
#include <cassert>
#define TORRENT_ASSERT(x) assert(x)
#endif
#endif

View File

@ -0,0 +1,677 @@
/*
Copyright (c) 2006, 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.
*/
#ifndef TORRENT_SESSION_IMPL_HPP_INCLUDED
#define TORRENT_SESSION_IMPL_HPP_INCLUDED
#include <ctime>
#include <algorithm>
#include <vector>
#include <set>
#include <list>
#include <deque>
#ifndef TORRENT_DISABLE_GEO_IP
#include "libtorrent/GeoIP.h"
#endif
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/limits.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/thread.hpp>
#include <boost/thread/recursive_mutex.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/torrent_handle.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/tracker_manager.hpp"
#include "libtorrent/peer_info.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/fingerprint.hpp"
#include "libtorrent/debug.hpp"
#include "libtorrent/peer_request.hpp"
#include "libtorrent/piece_block_progress.hpp"
#include "libtorrent/ip_filter.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/kademlia/dht_tracker.hpp"
#include "libtorrent/session_status.hpp"
#include "libtorrent/session.hpp"
#include "libtorrent/stat.hpp"
#include "libtorrent/file_pool.hpp"
#include "libtorrent/bandwidth_manager.hpp"
#include "libtorrent/natpmp.hpp"
#include "libtorrent/upnp.hpp"
#include "libtorrent/lsd.hpp"
#include "libtorrent/socket_type.hpp"
#include "libtorrent/connection_queue.hpp"
#include "libtorrent/disk_io_thread.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{
namespace fs = boost::filesystem;
namespace aux
{
struct session_impl;
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
struct tracker_logger;
#endif
// this is the link between the main thread and the
// thread started to run the main downloader loop
struct session_impl: boost::noncopyable
{
// the size of each allocation that is chained in the send buffer
enum { send_buffer_size = 200 };
#ifndef NDEBUG
friend class ::libtorrent::peer_connection;
#endif
friend struct checker_impl;
friend class invariant_access;
typedef std::set<boost::intrusive_ptr<peer_connection> > connection_map;
typedef std::map<sha1_hash, boost::shared_ptr<torrent> > torrent_map;
session_impl(
std::pair<int, int> listen_port_range
, fingerprint const& cl_fprint
, char const* listen_interface
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
, fs::path const& logpath
#endif
);
~session_impl();
#ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(
torrent*, void*)> ext);
#endif
#ifndef NDEBUG
bool has_peer(peer_connection const* p) const
{
return std::find_if(m_connections.begin(), m_connections.end()
, boost::bind(&boost::intrusive_ptr<peer_connection>::get, _1) == p)
!= m_connections.end();
}
#endif
void operator()();
void open_listen_port();
// if we are listening on an IPv6 interface
// this will return one of the IPv6 addresses on this
// machine, otherwise just an empty endpoint
tcp::endpoint get_ipv6_interface() const;
void async_accept(boost::shared_ptr<socket_acceptor> const& listener);
void on_incoming_connection(boost::shared_ptr<socket_type> const& s
, boost::weak_ptr<socket_acceptor> listener, error_code const& e);
// must be locked to access the data
// in this struct
typedef boost::recursive_mutex mutex_t;
mutable mutex_t m_mutex;
boost::weak_ptr<torrent> find_torrent(const sha1_hash& info_hash);
peer_id const& get_peer_id() const { return m_peer_id; }
void close_connection(peer_connection const* p
, char const* message);
void set_settings(session_settings const& s);
session_settings const& settings() const { return m_settings; }
#ifndef TORRENT_DISABLE_DHT
void add_dht_node(std::pair<std::string, int> const& node);
void add_dht_node(udp::endpoint n);
void add_dht_router(std::pair<std::string, int> const& node);
void set_dht_settings(dht_settings const& s);
dht_settings const& get_dht_settings() const { return m_dht_settings; }
void start_dht(entry const& startup_state);
void stop_dht();
entry dht_state() const;
#endif
#ifndef TORRENT_DISABLE_ENCRYPTION
void set_pe_settings(pe_settings const& settings);
pe_settings const& get_pe_settings() const { return m_pe_settings; }
#endif
// called when a port mapping is successful, or a router returns
// a failure to map a port
void on_port_mapping(int mapping, int port, std::string const& errmsg
, int nat_transport);
bool is_aborted() const { return m_abort; }
bool is_paused() const { return m_paused; }
void pause();
void resume();
void set_ip_filter(ip_filter const& f);
void set_port_filter(port_filter const& f);
bool listen_on(
std::pair<int, int> const& port_range
, const char* net_interface = 0);
bool is_listening() const;
torrent_handle add_torrent(add_torrent_params const&);
void remove_torrent(torrent_handle const& h, int options);
std::vector<torrent_handle> get_torrents();
void check_torrent(boost::shared_ptr<torrent> const& t);
void done_checking(boost::shared_ptr<torrent> const& t);
void set_severity_level(alert::severity_t s);
std::auto_ptr<alert> pop_alert();
alert const* wait_for_alert(time_duration max_wait);
int upload_rate_limit() const;
int download_rate_limit() const;
void set_download_rate_limit(int bytes_per_second);
void set_upload_rate_limit(int bytes_per_second);
void set_max_half_open_connections(int limit);
void set_max_connections(int limit);
void set_max_uploads(int limit);
int max_connections() const { return m_max_connections; }
int max_uploads() const { return m_max_uploads; }
int max_half_open_connections() const { return m_half_open.limit(); }
int num_uploads() const { return m_num_unchoked; }
int num_connections() const
{ return m_connections.size(); }
void unchoke_peer(peer_connection& c)
{
torrent* t = c.associated_torrent().lock().get();
TORRENT_ASSERT(t);
if (t->unchoke_peer(c))
++m_num_unchoked;
}
session_status status() const;
void set_peer_id(peer_id const& id);
void set_key(int key);
unsigned short listen_port() const;
void abort();
torrent_handle find_torrent_handle(sha1_hash const& info_hash);
void announce_lsd(sha1_hash const& ih);
void set_peer_proxy(proxy_settings const& s)
{ m_peer_proxy = s; }
void set_web_seed_proxy(proxy_settings const& s)
{ m_web_seed_proxy = s; }
void set_tracker_proxy(proxy_settings const& s)
{ m_tracker_proxy = s; }
proxy_settings const& peer_proxy() const
{ return m_peer_proxy; }
proxy_settings const& web_seed_proxy() const
{ return m_web_seed_proxy; }
proxy_settings const& tracker_proxy() const
{ return m_tracker_proxy; }
#ifndef TORRENT_DISABLE_DHT
void set_dht_proxy(proxy_settings const& s)
{
m_dht_proxy = s;
m_dht_socket.set_proxy_settings(s);
}
proxy_settings const& dht_proxy() const
{ return m_dht_proxy; }
#endif
#ifndef TORRENT_DISABLE_GEO_IP
std::string as_name_for_ip(address const& a);
int as_for_ip(address const& a);
std::pair<const int, int>* lookup_as(int as);
bool load_asnum_db(char const* file);
bool has_asnum_db() const { return m_asnum_db; }
bool load_country_db(char const* file);
bool has_country_db() const { return m_country_db; }
char const* country_for_ip(address const& a);
#endif
void load_state(entry const& ses_state);
entry state() const;
#ifdef TORRENT_STATS
void log_buffer_usage()
{
int send_buffer_capacity = 0;
int used_send_buffer = 0;
for (connection_map::const_iterator i = m_connections.begin()
, end(m_connections.end()); i != end; ++i)
{
send_buffer_capacity += (*i)->send_buffer_capacity();
used_send_buffer += (*i)->send_buffer_size();
}
TORRENT_ASSERT(send_buffer_capacity >= used_send_buffer);
m_buffer_usage_logger << log_time() << " send_buffer_size: " << send_buffer_capacity << std::endl;
m_buffer_usage_logger << log_time() << " used_send_buffer: " << used_send_buffer << std::endl;
m_buffer_usage_logger << log_time() << " send_buffer_utilization: "
<< (used_send_buffer * 100.f / send_buffer_capacity) << std::endl;
}
#endif
void start_lsd();
natpmp* start_natpmp();
upnp* start_upnp();
void stop_lsd();
void stop_natpmp();
void stop_upnp();
int next_port();
// handles delayed alerts
alert_manager m_alerts;
std::pair<char*, int> allocate_buffer(int size);
void free_buffer(char* buf, int size);
char* allocate_disk_buffer();
void free_disk_buffer(char* buf);
void set_external_address(address const& ip);
address const& external_address() const { return m_external_address; }
// private:
void on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih);
#ifndef TORRENT_DISABLE_POOL_ALLOCATOR
// this pool is used to allocate and recycle send
// buffers from.
boost::pool<> m_send_buffers;
#endif
boost::mutex m_send_buffer_mutex;
// the file pool that all storages in this session's
// torrents uses. It sets a limit on the number of
// open files by this session.
// file pool must be destructed after the torrents
// since they will still have references to it
// when they are destructed.
file_pool m_files;
// this is where all active sockets are stored.
// the selector can sleep while there's no activity on
// them
io_service m_io_service;
// handles disk io requests asynchronously
// peers have pointers into the disk buffer
// pool, and must be destructed before this
// object. The disk thread relies on the file
// pool object, and must be destructed before
// m_files. The disk io thread posts completion
// events to the io service, and needs to be
// constructed after it.
disk_io_thread m_disk_thread;
// this is a list of half-open tcp connections
// (only outgoing connections)
// this has to be one of the last
// members to be destructed
connection_queue m_half_open;
// the bandwidth manager is responsible for
// handing out bandwidth to connections that
// asks for it, it can also throttle the
// rate.
bandwidth_manager<peer_connection, torrent> m_download_channel;
bandwidth_manager<peer_connection, torrent> m_upload_channel;
bandwidth_manager<peer_connection, torrent>* m_bandwidth_manager[2];
tracker_manager m_tracker_manager;
torrent_map m_torrents;
typedef std::list<boost::shared_ptr<torrent> > check_queue_t;
check_queue_t m_queued_for_checking;
// this maps sockets to their peer_connection
// object. It is the complete list of all connected
// peers.
connection_map m_connections;
// filters incoming connections
ip_filter m_ip_filter;
// filters outgoing connections
port_filter m_port_filter;
// the peer id that is generated at the start of the session
peer_id m_peer_id;
// the key is an id that is used to identify the
// client with the tracker only. It is randomized
// at startup
int m_key;
// the number of retries we make when binding the
// listen socket. For each retry the port number
// is incremented by one
int m_listen_port_retries;
// 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
tcp::endpoint m_listen_interface;
// if we're listening on an IPv6 interface
// this is one of the non local IPv6 interfaces
// on this machine
tcp::endpoint m_ipv6_interface;
struct listen_socket_t
{
listen_socket_t(): external_port(0) {}
// this is typically set to the same as the local
// listen port. In case a NAT port forward was
// successfully opened, this will be set to the
// port that is open on the external (NAT) interface
// on the NAT box itself. This is the port that has
// to be published to peers, since this is the port
// the client is reachable through.
int external_port;
// the actual socket
boost::shared_ptr<socket_acceptor> sock;
};
// since we might be listening on multiple interfaces
// we might need more than one listen socket
std::list<listen_socket_t> m_listen_sockets;
listen_socket_t setup_listener(tcp::endpoint ep, int retries, bool v6_only = false);
// the settings for the client
session_settings m_settings;
// the proxy settings for different
// kinds of connections
proxy_settings m_peer_proxy;
proxy_settings m_web_seed_proxy;
proxy_settings m_tracker_proxy;
#ifndef TORRENT_DISABLE_DHT
proxy_settings m_dht_proxy;
#endif
// set to true when the session object
// is being destructed and the thread
// should exit
volatile bool m_abort;
// is true if the session is paused
bool m_paused;
// the max number of unchoked peers as set by the user
int m_max_uploads;
// the number of unchoked peers as set by the auto-unchoker
// this should always be >= m_max_uploads
int m_allowed_upload_slots;
// the max number of connections, as set by the user
int m_max_connections;
// the number of unchoked peers
int m_num_unchoked;
// this is initialized to the unchoke_interval
// session_setting and decreased every second.
// when it reaches zero, it is reset to the
// unchoke_interval and the unchoke set is
// recomputed.
int m_unchoke_time_scaler;
// this is used to decide when to recalculate which
// torrents to keep queued and which to activate
int m_auto_manage_time_scaler;
// works like unchoke_time_scaler but it
// is only decresed when the unchoke set
// is recomputed, and when it reaches zero,
// the optimistic unchoke is moved to another peer.
int m_optimistic_unchoke_time_scaler;
// works like unchoke_time_scaler. Each time
// it reaches 0, and all the connections are
// used, the worst connection will be disconnected
// from the torrent with the most peers
int m_disconnect_time_scaler;
// when this scaler reaches zero, it will
// scrape one of the auto managed, paused,
// torrents.
int m_auto_scrape_time_scaler;
// statistics gathered from all torrents.
stat m_stat;
// is false by default and set to true when
// the first incoming connection is established
// this is used to know if the client is behind
// NAT or not.
bool m_incoming_connection;
void second_tick(error_code const& e);
void recalculate_auto_managed_torrents();
void recalculate_unchoke_slots(int congested_torrents
, int uncongested_torrents);
ptime m_last_tick;
// when outgoing_ports is configured, this is the
// port we'll bind the next outgoing socket to
int m_next_port;
#ifndef TORRENT_DISABLE_DHT
boost::intrusive_ptr<dht::dht_tracker> m_dht;
dht_settings m_dht_settings;
// if this is set to true, the dht listen port
// will be set to the same as the tcp listen port
// and will be synchronlized with it as it changes
// it defaults to true
bool m_dht_same_port;
// see m_external_listen_port. This is the same
// but for the udp port used by the DHT.
int m_external_udp_port;
udp_socket m_dht_socket;
void on_receive_udp(error_code const& e
, udp::endpoint const& ep, char const* buf, int len);
#endif
#ifndef TORRENT_DISABLE_ENCRYPTION
pe_settings m_pe_settings;
#endif
boost::intrusive_ptr<natpmp> m_natpmp;
boost::intrusive_ptr<upnp> m_upnp;
boost::intrusive_ptr<lsd> m_lsd;
// 0 is natpmp 1 is upnp
int m_tcp_mapping[2];
int m_udp_mapping[2];
// the timer used to fire the second_tick
deadline_timer m_timer;
// the index of the torrent that will be offered to
// connect to a peer next time second_tick is called.
// This implements a round robin.
int m_next_connect_torrent;
#ifndef NDEBUG
void check_invariant() const;
#endif
#ifdef TORRENT_STATS
// logger used to write bandwidth usage statistics
std::ofstream m_stats_logger;
int m_second_counter;
// used to log send buffer usage statistics
std::ofstream m_buffer_usage_logger;
// the number of send buffers that are allocated
int m_buffer_allocations;
#endif
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
boost::shared_ptr<logger> create_log(std::string const& name
, int instance, bool append = true);
// this list of tracker loggers serves as tracker_callbacks when
// shutting down. This list is just here to keep them alive during
// whe shutting down process
std::list<boost::shared_ptr<tracker_logger> > m_tracker_loggers;
fs::path m_logpath;
public:
boost::shared_ptr<logger> m_logger;
private:
#endif
address m_external_address;
#ifndef TORRENT_DISABLE_EXTENSIONS
typedef std::list<boost::function<boost::shared_ptr<
torrent_plugin>(torrent*, void*)> > extension_list_t;
extension_list_t m_extensions;
#endif
#ifndef TORRENT_DISABLE_GEO_IP
GeoIP* m_asnum_db;
GeoIP* m_country_db;
// maps AS number to the peak download rate
// we've seen from it. Entries are never removed
// from this map. Pointers to its elements
// are kept in the policy::peer structures.
std::map<int, int> m_as_peak;
#endif
// the main working thread
boost::scoped_ptr<boost::thread> m_thread;
};
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
struct tracker_logger : request_callback
{
tracker_logger(session_impl& ses): m_ses(ses) {}
void tracker_warning(tracker_request const& req
, std::string const& str)
{
debug_log("*** tracker warning: " + str);
}
void tracker_response(tracker_request const&
, std::vector<peer_entry>& peers
, int interval
, int complete
, int incomplete
, address const& external_ip)
{
std::stringstream s;
s << "TRACKER RESPONSE:\n"
"interval: " << interval << "\n"
"peers:\n";
for (std::vector<peer_entry>::const_iterator i = peers.begin();
i != peers.end(); ++i)
{
s << " " << std::setfill(' ') << std::setw(16) << i->ip
<< " " << std::setw(5) << std::dec << i->port << " ";
if (!i->pid.is_all_zeros()) s << " " << i->pid;
s << "\n";
}
s << "external ip: " << external_ip << "\n";
debug_log(s.str());
}
void tracker_request_timed_out(
tracker_request const&)
{
debug_log("*** tracker timed out");
}
void tracker_request_error(
tracker_request const&
, int response_code
, const std::string& str)
{
debug_log(std::string("*** tracker error: ")
+ boost::lexical_cast<std::string>(response_code) + ": "
+ str);
}
void debug_log(const std::string& line)
{
(*m_ses.m_logger) << time_now_string() << " " << line << "\n";
}
session_impl& m_ses;
};
#endif
}
}
#endif

View File

@ -0,0 +1,120 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_BANDWIDTH_LIMIT_HPP_INCLUDED
#define TORRENT_BANDWIDTH_LIMIT_HPP_INCLUDED
#include <boost/integer_traits.hpp>
#include "libtorrent/assert.hpp"
namespace libtorrent {
// member of peer_connection
struct bandwidth_limit
{
static const int inf = boost::integer_traits<int>::const_max;
bandwidth_limit()
: m_quota_left(0)
, m_local_limit(inf)
, m_current_rate(0)
{}
void throttle(int limit)
{
TORRENT_ASSERT(limit > 0);
m_local_limit = limit;
}
int throttle() const
{
return m_local_limit;
}
void assign(int amount)
{
TORRENT_ASSERT(amount >= 0);
m_current_rate += amount;
m_quota_left += amount;
}
void use_quota(int amount)
{
TORRENT_ASSERT(amount <= m_quota_left);
m_quota_left -= amount;
}
int quota_left() const
{
return (std::max)(m_quota_left, 0);
}
void expire(int amount)
{
TORRENT_ASSERT(amount >= 0);
m_current_rate -= amount;
}
int max_assignable() const
{
if (m_local_limit == inf) return inf;
if (m_local_limit <= m_current_rate) return 0;
return m_local_limit - m_current_rate;
}
private:
// this is the amount of bandwidth we have
// been assigned without using yet. i.e.
// the bandwidth that we use up every time
// we receive or send a message. Once this
// hits zero, we need to request more
// bandwidth from the torrent which
// in turn will request bandwidth from
// the bandwidth manager
int m_quota_left;
// the local limit is the number of bytes
// per window size we are allowed to use.
int m_local_limit;
// the current rate is the number of
// bytes we have been assigned within
// the window size.
int m_current_rate;
};
}
#endif

View File

@ -0,0 +1,492 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_BANDWIDTH_MANAGER_HPP_INCLUDED
#define TORRENT_BANDWIDTH_MANAGER_HPP_INCLUDED
#include <boost/shared_ptr.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/integer_traits.hpp>
#include <boost/thread/mutex.hpp>
#include <deque>
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
#include <fstream>
#endif
#include "libtorrent/socket.hpp"
#include "libtorrent/invariant_check.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/bandwidth_limit.hpp"
#include "libtorrent/bandwidth_queue_entry.hpp"
using boost::weak_ptr;
using boost::shared_ptr;
using boost::intrusive_ptr;
using boost::bind;
namespace libtorrent {
// the maximum block of bandwidth quota to
// hand out is 33kB. The block size may
// be smaller on lower limits
enum
{
max_bandwidth_block_size = 33000,
min_bandwidth_block_size = 400
};
const time_duration bw_window_size = seconds(1);
template<class PeerConnection, class Torrent>
struct history_entry
{
history_entry(intrusive_ptr<PeerConnection> p, weak_ptr<Torrent> t
, int a, ptime exp)
: expires_at(exp), amount(a), peer(p), tor(t) {}
history_entry(int a, ptime exp)
: expires_at(exp), amount(a), peer(), tor() {}
ptime expires_at;
int amount;
intrusive_ptr<PeerConnection> peer;
weak_ptr<Torrent> tor;
};
template<class T>
T clamp(T val, T ceiling, T floor)
{
TORRENT_ASSERT(ceiling >= floor);
if (val >= ceiling) return ceiling;
else if (val <= floor) return floor;
return val;
}
template<class T>
struct assign_at_exit
{
assign_at_exit(T& var, T val): var_(var), val_(val) {}
~assign_at_exit() { var_ = val_; }
T& var_;
T val_;
};
template<class PeerConnection, class Torrent>
struct bandwidth_manager
{
bandwidth_manager(io_service& ios, int channel
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
, bool log = false
#endif
)
: m_ios(ios)
, m_history_timer(m_ios)
, m_limit(bandwidth_limit::inf)
, m_drain_quota(0)
, m_current_quota(0)
, m_channel(channel)
, m_in_hand_out_bandwidth(false)
, m_abort(false)
{
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
if (log)
m_log.open("bandwidth_limiter.log", std::ios::trunc);
m_start = time_now();
#endif
}
void drain(int bytes)
{
mutex_t::scoped_lock l(m_mutex);
TORRENT_ASSERT(bytes >= 0);
m_drain_quota += bytes;
if (m_drain_quota > m_limit * 5) m_drain_quota = m_limit * 5;
}
void throttle(int limit)
{
mutex_t::scoped_lock l(m_mutex);
TORRENT_ASSERT(limit >= 0);
m_limit = limit;
}
int throttle() const
{
mutex_t::scoped_lock l(m_mutex);
return m_limit;
}
void close()
{
m_abort = true;
m_queue.clear();
m_history.clear();
m_current_quota = 0;
m_history_timer.cancel();
}
#ifndef NDEBUG
bool is_queued(PeerConnection const* peer) const
{
mutex_t::scoped_lock l(m_mutex);
return is_queued(peer);
}
bool is_queued(PeerConnection const* peer, boost::mutex::scoped_lock& l) const
{
for (typename queue_t::const_iterator i = m_queue.begin()
, end(m_queue.end()); i != end; ++i)
{
if (i->peer.get() == peer) return true;
}
return false;
}
bool is_in_history(PeerConnection const* peer) const
{
mutex_t::scoped_lock l(m_mutex);
return is_in_history(peer, l);
}
bool is_in_history(PeerConnection const* peer, boost::mutex::scoped_lock& l) const
{
for (typename history_t::const_iterator i
= m_history.begin(), end(m_history.end()); i != end; ++i)
{
if (i->peer.get() == peer) return true;
}
return false;
}
#endif
int queue_size() const
{
mutex_t::scoped_lock l(m_mutex);
return m_queue.size();
}
// non prioritized means that, if there's a line for bandwidth,
// others will cut in front of the non-prioritized peers.
// this is used by web seeds
void request_bandwidth(intrusive_ptr<PeerConnection> const& peer
, int blk, int priority)
{
mutex_t::scoped_lock l(m_mutex);
INVARIANT_CHECK;
if (m_abort) return;
TORRENT_ASSERT(blk > 0);
TORRENT_ASSERT(!is_queued(peer.get(), l));
// make sure this peer isn't already in line
// waiting for bandwidth
TORRENT_ASSERT(peer->max_assignable_bandwidth(m_channel) > 0);
typename queue_t::reverse_iterator i(m_queue.rbegin());
while (i != m_queue.rend() && priority > i->priority)
{
++i->priority;
++i;
}
m_queue.insert(i.base(), bw_queue_entry<PeerConnection, Torrent>(peer, blk, priority));
if (!m_queue.empty()) hand_out_bandwidth(l);
}
#ifndef NDEBUG
void check_invariant() const
{
int current_quota = 0;
for (typename history_t::const_iterator i
= m_history.begin(), end(m_history.end()); i != end; ++i)
{
current_quota += i->amount;
}
TORRENT_ASSERT(current_quota == m_current_quota);
typename queue_t::const_iterator j = m_queue.begin();
if (j != m_queue.end())
{
++j;
for (typename queue_t::const_iterator i = m_queue.begin()
, end(m_queue.end()); i != end && j != end; ++i, ++j)
TORRENT_ASSERT(i->priority >= j->priority);
}
}
#endif
private:
void add_history_entry(history_entry<PeerConnection, Torrent> const& e)
{
INVARIANT_CHECK;
m_history.push_front(e);
m_current_quota += e.amount;
// in case the size > 1 there is already a timer
// active that will be invoked, no need to set one up
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
m_log << std::setw(7) << total_milliseconds(time_now() - m_start) << " + "
" queue: " << std::setw(3) << m_queue.size()
<< " used: " << std::setw(7) << m_current_quota
<< " limit: " << std::setw(7) << m_limit
<< " history: " << std::setw(3) << m_history.size()
<< std::endl;
#endif
if (m_history.size() > 1) return;
if (m_abort) return;
error_code ec;
m_history_timer.expires_at(e.expires_at, ec);
m_history_timer.async_wait(bind(&bandwidth_manager::on_history_expire, this, _1));
}
void on_history_expire(error_code const& e)
{
if (e) return;
mutex_t::scoped_lock l(m_mutex);
INVARIANT_CHECK;
if (m_abort) return;
TORRENT_ASSERT(!m_history.empty());
ptime now(time_now());
while (!m_history.empty() && m_history.back().expires_at <= now)
{
history_entry<PeerConnection, Torrent> e = m_history.back();
m_history.pop_back();
m_current_quota -= e.amount;
TORRENT_ASSERT(m_current_quota >= 0);
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
m_log << std::setw(7) << total_milliseconds(time_now() - m_start) << " - "
" queue: " << std::setw(3) << m_queue.size()
<< " used: " << std::setw(7) << m_current_quota
<< " limit: " << std::setw(7) << m_limit
<< " history: " << std::setw(3) << m_history.size()
<< std::endl;
#endif
intrusive_ptr<PeerConnection> c = e.peer;
if (!c) continue;
shared_ptr<Torrent> t = e.tor.lock();
l.unlock();
if (!c->is_disconnecting()) c->expire_bandwidth(m_channel, e.amount);
if (t) t->expire_bandwidth(m_channel, e.amount);
l.lock();
}
// now, wait for the next chunk to expire
if (!m_history.empty() && !m_abort)
{
error_code ec;
m_history_timer.expires_at(m_history.back().expires_at, ec);
m_history_timer.async_wait(bind(&bandwidth_manager::on_history_expire, this, _1));
}
// since some bandwidth just expired, it
// means we can hand out more (in case there
// are still consumers in line)
if (!m_queue.empty()) hand_out_bandwidth(l);
}
void hand_out_bandwidth(boost::mutex::scoped_lock& l)
{
// if we're already handing out bandwidth, just return back
// to the loop further down on the callstack
if (m_in_hand_out_bandwidth) return;
m_in_hand_out_bandwidth = true;
// set it to false when exiting function
assign_at_exit<bool> sg(m_in_hand_out_bandwidth, false);
INVARIANT_CHECK;
ptime now(time_now());
int limit = m_limit;
// available bandwidth to hand out
int amount = limit - m_current_quota;
if (amount <= 0) return;
if (m_drain_quota > 0)
{
int drain_amount = (std::min)(m_drain_quota, amount);
m_drain_quota -= drain_amount;
amount -= drain_amount;
add_history_entry(history_entry<PeerConnection, Torrent>(
drain_amount, now + bw_window_size));
}
queue_t tmp;
while (!m_queue.empty() && amount > 0)
{
bw_queue_entry<PeerConnection, Torrent> qe = m_queue.front();
TORRENT_ASSERT(qe.max_block_size > 0);
m_queue.pop_front();
shared_ptr<Torrent> t = qe.torrent.lock();
if (!t) continue;
if (qe.peer->is_disconnecting())
{
l.unlock();
t->expire_bandwidth(m_channel, qe.max_block_size);
l.lock();
continue;
}
// at this point, max_assignable may actually be zero. Since
// the rate limit of the peer might have changed while it
// was in the queue.
int max_assignable = qe.peer->max_assignable_bandwidth(m_channel);
if (max_assignable == 0)
{
TORRENT_ASSERT(is_in_history(qe.peer.get(), l));
tmp.push_back(qe);
continue;
}
// this is the limit of the block size. It depends on the throttle
// so that it can be closer to optimal. Larger block sizes will give lower
// granularity to the rate but will be more efficient. At high rates
// the block sizes are bigger and at low rates, the granularity
// is more important and block sizes are smaller
// the minimum rate that can be given is the block size, so, the
// block size must be smaller for lower rates. This is because
// the history window is one second, and the block will be forgotten
// after one second.
int block_size = (std::min)(qe.peer->bandwidth_throttle(m_channel)
, limit / 10);
if (block_size < min_bandwidth_block_size)
{
block_size = (std::min)(int(min_bandwidth_block_size), limit);
}
else if (block_size > max_bandwidth_block_size)
{
if (limit == bandwidth_limit::inf)
{
block_size = max_bandwidth_block_size;
}
else
{
// try to make the block_size a divisor of
// m_limit to make the distributions as fair
// as possible
// TODO: move this calculcation to where the limit
// is changed
block_size = limit
/ (limit / max_bandwidth_block_size);
}
}
if (block_size > qe.max_block_size) block_size = qe.max_block_size;
if (amount < block_size / 4)
{
tmp.push_back(qe);
// m_queue.push_front(qe);
break;
}
// so, hand out max_assignable, but no more than
// the available bandwidth (amount) and no more
// than the max_bandwidth_block_size
int hand_out_amount = (std::min)((std::min)(block_size, max_assignable)
, amount);
TORRENT_ASSERT(hand_out_amount > 0);
amount -= hand_out_amount;
TORRENT_ASSERT(hand_out_amount <= qe.max_block_size);
l.unlock();
t->assign_bandwidth(m_channel, hand_out_amount, qe.max_block_size);
qe.peer->assign_bandwidth(m_channel, hand_out_amount);
l.lock();
add_history_entry(history_entry<PeerConnection, Torrent>(
qe.peer, t, hand_out_amount, now + bw_window_size));
}
if (!tmp.empty()) m_queue.insert(m_queue.begin(), tmp.begin(), tmp.end());
}
typedef boost::mutex mutex_t;
mutable mutex_t m_mutex;
// the io_service used for the timer
io_service& m_ios;
// the timer that is waiting for the entries
// in the history queue to expire (slide out
// of the history window)
deadline_timer m_history_timer;
// the rate limit (bytes per second)
int m_limit;
// bytes to drain without handing out to a peer
// used to deduct the IP overhead
int m_drain_quota;
// the sum of all recently handed out bandwidth blocks
int m_current_quota;
// these are the consumers that want bandwidth
typedef std::deque<bw_queue_entry<PeerConnection, Torrent> > queue_t;
queue_t m_queue;
// these are the consumers that have received bandwidth
// that will expire
typedef std::deque<history_entry<PeerConnection, Torrent> > history_t;
history_t m_history;
// this is the channel within the consumers
// that bandwidth is assigned to (upload or download)
int m_channel;
// this is true while we're in the hand_out_bandwidth loop
// to prevent recursive invocations to interfere
bool m_in_hand_out_bandwidth;
bool m_abort;
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
std::ofstream m_log;
ptime m_start;
#endif
};
}
#endif

View File

@ -0,0 +1,56 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_BANDWIDTH_QUEUE_ENTRY_HPP_INCLUDED
#define TORRENT_BANDWIDTH_QUEUE_ENTRY_HPP_INCLUDED
#include <boost/intrusive_ptr.hpp>
namespace libtorrent {
template<class PeerConnection, class Torrent>
struct bw_queue_entry
{
bw_queue_entry(boost::intrusive_ptr<PeerConnection> const& pe
, int blk, int prio)
: peer(pe), torrent(peer->associated_torrent())
, max_block_size(blk), priority(prio) {}
boost::intrusive_ptr<PeerConnection> peer;
boost::weak_ptr<Torrent> torrent;
int max_block_size;
int priority; // 0 is low prio
};
}
#endif

View File

@ -0,0 +1,415 @@
/*
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.
*/
#ifndef TORRENT_BENCODE_HPP_INCLUDED
#define TORRENT_BENCODE_HPP_INCLUDED
/*
* This file declares the following functions:
*
*----------------------------------
* template<class OutIt>
* void libtorrent::bencode(OutIt out, const libtorrent::entry& e);
*
* Encodes a message entry with bencoding into the output
* iterator given. The bencoding is described in the BitTorrent
* protocol description document OutIt must be an OutputIterator
* of type char. This may throw libtorrent::invalid_encoding if
* the entry contains invalid nodes (undefined_t for example).
*
*----------------------------------
* template<class InIt>
* libtorrent::entry libtorrent::bdecode(InIt start, InIt end);
*
* Decodes the buffer given by the start and end iterators
* and returns the decoded entry. InIt must be an InputIterator
* of type char. May throw libtorrent::invalid_encoding if
* the string is not correctly bencoded.
*
*/
#include <cstdlib>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/lexical_cast.hpp>
#include <boost/static_assert.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/entry.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#if defined(_MSC_VER)
namespace std
{
using ::isdigit;
using ::atoi;
};
#define for if (false) {} else for
#endif
namespace libtorrent
{
struct TORRENT_EXPORT invalid_encoding: std::exception
{
virtual const char* what() const throw() { return "invalid bencoding"; }
};
namespace detail
{
template <class OutIt>
int write_string(OutIt& out, const std::string& val)
{
int ret = val.length();
std::string::const_iterator end = val.begin() + ret;
for (std::string::const_iterator i = val.begin()
, end(val.begin() + ret); i != end; ++i)
*out++ = *i;
return ret;
}
TORRENT_EXPORT char const* integer_to_str(char* buf, int size, entry::integer_type val);
template <class OutIt>
int write_integer(OutIt& out, entry::integer_type val)
{
// the stack allocated buffer for keeping the
// decimal representation of the number can
// not hold number bigger than this:
BOOST_STATIC_ASSERT(sizeof(entry::integer_type) <= 8);
char buf[21];
int ret = 0;
for (char const* str = integer_to_str(buf, 21, val);
*str != 0; ++str)
{
*out = *str;
++out;
++ret;
}
return ret;
}
template <class OutIt>
void write_char(OutIt& out, char c)
{
*out = c;
++out;
}
template <class InIt>
std::string read_until(InIt& in, InIt end, char end_token, bool& err)
{
std::string ret;
if (in == end)
{
err = true;
return ret;
}
while (*in != end_token)
{
ret += *in;
++in;
if (in == end)
{
err = true;
return ret;
}
}
return ret;
}
template<class InIt>
void read_string(InIt& in, InIt end, int len, std::string& str, bool& err)
{
TORRENT_ASSERT(len >= 0);
for (int i = 0; i < len; ++i)
{
if (in == end)
{
err = true;
return;
}
str += *in;
++in;
}
}
// returns the number of bytes written
template<class OutIt>
int bencode_recursive(OutIt& out, const entry& e)
{
int ret = 0;
switch(e.type())
{
case entry::int_t:
write_char(out, 'i');
ret += write_integer(out, e.integer());
write_char(out, 'e');
ret += 2;
break;
case entry::string_t:
ret += write_integer(out, e.string().length());
write_char(out, ':');
ret += write_string(out, e.string());
ret += 1;
break;
case entry::list_t:
write_char(out, 'l');
for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i)
ret += bencode_recursive(out, *i);
write_char(out, 'e');
ret += 2;
break;
case entry::dictionary_t:
write_char(out, 'd');
for (entry::dictionary_type::const_iterator i = e.dict().begin();
i != e.dict().end(); ++i)
{
// write key
ret += write_integer(out, i->first.length());
write_char(out, ':');
ret += write_string(out, i->first);
// write value
ret += bencode_recursive(out, i->second);
ret += 1;
}
write_char(out, 'e');
ret += 2;
break;
default:
// do nothing
break;
}
return ret;
}
template<class InIt>
void bdecode_recursive(InIt& in, InIt end, entry& ret, bool& err, int depth)
{
if (depth >= 100)
{
err = true;
return;
}
if (in == end)
{
err = true;
#ifndef NDEBUG
ret.m_type_queried = false;
#endif
return;
}
switch (*in)
{
// ----------------------------------------------
// integer
case 'i':
{
++in; // 'i'
std::string val = read_until(in, end, 'e', err);
if (err) return;
TORRENT_ASSERT(*in == 'e');
++in; // 'e'
ret = entry(entry::int_t);
ret.integer() = boost::lexical_cast<entry::integer_type>(val);
#ifndef NDEBUG
ret.m_type_queried = false;
#endif
} break;
// ----------------------------------------------
// list
case 'l':
{
ret = entry(entry::list_t);
++in; // 'l'
while (*in != 'e')
{
ret.list().push_back(entry());
entry& e = ret.list().back();
bdecode_recursive(in, end, e, err, depth + 1);
if (err)
{
#ifndef NDEBUG
ret.m_type_queried = false;
#endif
return;
}
if (in == end)
{
err = true;
#ifndef NDEBUG
ret.m_type_queried = false;
#endif
return;
}
}
#ifndef NDEBUG
ret.m_type_queried = false;
#endif
TORRENT_ASSERT(*in == 'e');
++in; // 'e'
} break;
// ----------------------------------------------
// dictionary
case 'd':
{
ret = entry(entry::dictionary_t);
++in; // 'd'
while (*in != 'e')
{
entry key;
bdecode_recursive(in, end, key, err, depth + 1);
if (err || key.type() != entry::string_t)
{
#ifndef NDEBUG
ret.m_type_queried = false;
#endif
return;
}
entry& e = ret[key.string()];
bdecode_recursive(in, end, e, err, depth + 1);
if (err)
{
#ifndef NDEBUG
ret.m_type_queried = false;
#endif
return;
}
if (in == end)
{
err = true;
#ifndef NDEBUG
ret.m_type_queried = false;
#endif
return;
}
}
#ifndef NDEBUG
ret.m_type_queried = false;
#endif
TORRENT_ASSERT(*in == 'e');
++in; // 'e'
} break;
// ----------------------------------------------
// string
default:
if (isdigit((unsigned char)*in))
{
std::string len_s = read_until(in, end, ':', err);
if (err)
{
#ifndef NDEBUG
ret.m_type_queried = false;
#endif
return;
}
TORRENT_ASSERT(*in == ':');
++in; // ':'
int len = std::atoi(len_s.c_str());
ret = entry(entry::string_t);
read_string(in, end, len, ret.string(), err);
if (err)
{
#ifndef NDEBUG
ret.m_type_queried = false;
#endif
return;
}
}
else
{
err = true;
#ifndef NDEBUG
ret.m_type_queried = false;
#endif
return;
}
#ifndef NDEBUG
ret.m_type_queried = false;
#endif
}
}
}
template<class OutIt>
int bencode(OutIt out, const entry& e)
{
return detail::bencode_recursive(out, e);
}
template<class InIt>
entry bdecode(InIt start, InIt end)
{
entry e;
bool err = false;
detail::bdecode_recursive(start, end, e, err, 0);
TORRENT_ASSERT(e.m_type_queried == false);
if (err) return entry();
return e;
}
template<class InIt>
entry bdecode(InIt start, InIt end, int& len)
{
entry e;
bool err = false;
InIt s = start;
detail::bdecode_recursive(start, end, e, err, 0);
len = std::distance(s, start);
TORRENT_ASSERT(len >= 0);
if (err) return entry();
return e;
}
}
#endif // TORRENT_BENCODE_HPP_INCLUDED

View File

@ -0,0 +1,241 @@
/*
Copyright (c) 2008, 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.
*/
#ifndef TORRENT_BITFIELD_HPP_INCLUDED
#define TORRENT_BITFIELD_HPP_INCLUDED
#include "libtorrent/assert.hpp"
#include "libtorrent/config.hpp"
namespace libtorrent
{
struct TORRENT_EXPORT bitfield
{
bitfield(): m_bytes(0), m_size(0), m_own(false) {}
bitfield(int bits): m_bytes(0), m_size(0)
{ resize(bits); }
bitfield(int bits, bool val): m_bytes(0), m_size(0)
{ resize(bits, val); }
bitfield(char const* bytes, int bits): m_bytes(0), m_size(0)
{ assign(bytes, bits); }
bitfield(bitfield const& rhs): m_bytes(0), m_size(0), m_own(false)
{ assign(rhs.bytes(), rhs.size()); }
void borrow_bytes(char* bytes, int bits)
{
dealloc();
m_bytes = (unsigned char*)bytes;
m_size = bits;
m_own = false;
}
~bitfield() { dealloc(); }
void assign(char const* bytes, int bits)
{ resize(bits); memcpy(m_bytes, bytes, (bits + 7) / 8); }
bool operator[](int index) const
{ return get_bit(index); }
bool get_bit(int index) const
{
TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < m_size);
return m_bytes[index / 8] & (0x80 >> (index & 7));
}
void clear_bit(int index)
{
TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < m_size);
m_bytes[index / 8] &= ~(0x80 >> (index & 7));
}
void set_bit(int index)
{
TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < m_size);
m_bytes[index / 8] |= (0x80 >> (index & 7));
}
std::size_t size() const { return m_size; }
bool empty() const { return m_size == 0; }
char const* bytes() const { return (char*)m_bytes; }
bitfield& operator=(bitfield const& rhs)
{
assign(rhs.bytes(), rhs.size());
return *this;
}
int count() const
{
// 0000, 0001, 0010, 0011, 0100, 0101, 0110, 0111,
// 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111
const static char num_bits[] =
{
0, 1, 1, 2, 1, 2, 2, 3,
1, 2, 2, 3, 2, 3, 3, 4
};
int ret = 0;
const int num_bytes = m_size / 8;
for (int i = 0; i < num_bytes; ++i)
{
ret += num_bits[m_bytes[i] & 0xf] + num_bits[m_bytes[i] >> 4];
}
int rest = m_size - num_bytes * 8;
for (int i = 0; i < rest; ++i)
{
ret += (m_bytes[num_bytes] >> (7-i)) & 1;
}
TORRENT_ASSERT(ret <= m_size);
TORRENT_ASSERT(ret >= 0);
return ret;
}
struct const_iterator
{
friend struct bitfield;
typedef bool value_type;
typedef ptrdiff_t difference_type;
typedef bool const* pointer;
typedef bool& reference;
typedef std::forward_iterator_tag iterator_category;
bool operator*() { return *byte & bit; }
const_iterator& operator++() { inc(); return *this; }
const_iterator operator++(int)
{ const_iterator ret(*this); inc(); return ret; }
const_iterator& operator--() { dec(); return *this; }
const_iterator operator--(int)
{ const_iterator ret(*this); dec(); return ret; }
const_iterator(): byte(0), bit(0x80) {}
bool operator==(const_iterator const& rhs) const
{ return byte == rhs.byte && bit == rhs.bit; }
bool operator!=(const_iterator const& rhs) const
{ return byte != rhs.byte || bit != rhs.bit; }
private:
void inc()
{
TORRENT_ASSERT(byte);
if (bit == 0x01)
{
bit = 0x80;
++byte;
}
else
{
bit >>= 1;
}
}
void dec()
{
TORRENT_ASSERT(byte);
if (bit == 0x80)
{
bit = 0x01;
--byte;
}
else
{
bit <<= 1;
}
}
const_iterator(unsigned char const* ptr, int offset)
: byte(ptr), bit(0x80 >> offset) {}
unsigned char const* byte;
int bit;
};
const_iterator begin() const { return const_iterator(m_bytes, 0); }
const_iterator end() const { return const_iterator(m_bytes + m_size / 8, m_size & 7); }
void resize(int bits, bool val)
{
resize(bits);
if (val) set_all(); else clear_all();
}
void set_all()
{
memset(m_bytes, 0xff, (m_size + 7) / 8);
}
void clear_all()
{
memset(m_bytes, 0x00, (m_size + 7) / 8);
}
void resize(int bits)
{
const int bytes = (bits + 7) / 8;
if (m_bytes)
{
if (m_own)
{
m_bytes = (unsigned char*)realloc(m_bytes, bytes);
m_own = true;
}
else if (bits > m_size)
{
unsigned char* tmp = (unsigned char*)malloc(bytes);
memcpy(tmp, m_bytes, (std::min)((m_size + 7)/ 8, bytes));
m_bytes = tmp;
m_own = true;
}
}
else
{
m_bytes = (unsigned char*)malloc(bytes);
m_own = true;
}
m_size = bits;
}
private:
void dealloc() { if (m_own) free(m_bytes); m_bytes = 0; }
unsigned char* m_bytes;
int m_size; // in bits
bool m_own;
};
}
#endif // TORRENT_BITFIELD_HPP_INCLUDED

View File

@ -0,0 +1,107 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_BROADCAST_SOCKET_HPP_INCLUDED
#define TORRENT_BROADCAST_SOCKET_HPP_INCLUDED
#include "libtorrent/config.hpp"
#include "libtorrent/socket.hpp"
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <list>
namespace libtorrent
{
TORRENT_EXPORT bool is_local(address const& a);
TORRENT_EXPORT bool is_loopback(address const& addr);
TORRENT_EXPORT bool is_multicast(address const& addr);
TORRENT_EXPORT bool is_any(address const& addr);
TORRENT_EXPORT int cidr_distance(address const& a1, address const& a2);
int common_bits(unsigned char const* b1
, unsigned char const* b2, int n);
TORRENT_EXPORT address guess_local_address(io_service&);
typedef boost::function<void(udp::endpoint const& from
, char* buffer, int size)> receive_handler_t;
class TORRENT_EXPORT broadcast_socket
{
public:
broadcast_socket(io_service& ios, udp::endpoint const& multicast_endpoint
, receive_handler_t const& handler, bool loopback = true);
~broadcast_socket() { close(); }
void send(char const* buffer, int size, error_code& ec);
void close();
private:
struct socket_entry
{
socket_entry(boost::shared_ptr<datagram_socket> const& s): socket(s) {}
boost::shared_ptr<datagram_socket> socket;
char buffer[1024];
udp::endpoint remote;
void close()
{
if (!socket) return;
error_code ec;
socket->close(ec);
}
};
void on_receive(socket_entry* s, error_code const& ec
, std::size_t bytes_transferred);
void open_unicast_socket(io_service& ios, address const& addr);
void open_multicast_socket(io_service& ios, address const& addr
, bool loopback);
// these sockets are used to
// join the multicast group (on each interface)
// and receive multicast messages
std::list<socket_entry> m_sockets;
// these sockets are not bound to any
// specific port and are used to
// send messages to the multicast group
// and receive unicast responses
std::list<socket_entry> m_unicast_sockets;
udp::endpoint m_multicast_endpoint;
receive_handler_t m_on_receive;
};
}
#endif

View File

@ -0,0 +1,424 @@
/*
Copyright (c) 2003 - 2006, Arvid Norberg
Copyright (c) 2007, Arvid Norberg, Un Shyam
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.
*/
#ifndef TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED
#define TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED
#include <ctime>
#include <algorithm>
#include <vector>
#include <deque>
#include <string>
#include "libtorrent/debug.hpp"
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/smart_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <boost/array.hpp>
#include <boost/optional.hpp>
#include <boost/cstdint.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/buffer.hpp"
#include "libtorrent/peer_connection.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/storage.hpp"
#include "libtorrent/stat.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/peer_request.hpp"
#include "libtorrent/piece_block_progress.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/pe_crypto.hpp"
namespace libtorrent
{
class torrent;
namespace detail
{
struct session_impl;
}
class TORRENT_EXPORT bt_peer_connection
: public peer_connection
{
friend class invariant_access;
public:
// this is the constructor where the we are the active part.
// The peer_conenction should handshake and verify that the
// other end has the correct id
bt_peer_connection(
aux::session_impl& ses
, boost::weak_ptr<torrent> t
, boost::shared_ptr<socket_type> s
, tcp::endpoint const& remote
, policy::peer* peerinfo);
// with this constructor we have been contacted and we still don't
// know which torrent the connection belongs to
bt_peer_connection(
aux::session_impl& ses
, boost::shared_ptr<socket_type> s
, tcp::endpoint const& remote
, policy::peer* peerinfo);
void start();
~bt_peer_connection();
#ifndef TORRENT_DISABLE_ENCRYPTION
bool supports_encryption() const
{ return m_encrypted; }
#endif
enum message_type
{
// standard messages
msg_choke = 0,
msg_unchoke,
msg_interested,
msg_not_interested,
msg_have,
msg_bitfield,
msg_request,
msg_piece,
msg_cancel,
// DHT extension
msg_dht_port,
// FAST extension
msg_suggest_piece = 0xd,
msg_have_all,
msg_have_none,
msg_reject_request,
msg_allowed_fast,
// extension protocol message
msg_extended = 20,
num_supported_messages
};
// called from the main loop when this connection has any
// work to do.
void on_sent(error_code const& error
, std::size_t bytes_transferred);
void on_receive(error_code const& error
, std::size_t bytes_transferred);
virtual void get_specific_peer_info(peer_info& p) const;
virtual bool in_handshake() const;
#ifndef TORRENT_DISABLE_EXTENSIONS
bool support_extensions() const { return m_supports_extensions; }
template <class T>
T* supports_extension() const
{
for (extension_list_t::const_iterator i = m_extensions.begin()
, end(m_extensions.end()); i != end; ++i)
{
T* ret = dynamic_cast<T*>(i->get());
if (ret) return ret;
}
return 0;
}
#endif
// the message handlers are called
// each time a recv() returns some new
// data, the last time it will be called
// is when the entire packet has been
// received, then it will no longer
// be called. i.e. most handlers need
// to check how much of the packet they
// have received before any processing
void on_keepalive();
void on_choke(int received);
void on_unchoke(int received);
void on_interested(int received);
void on_not_interested(int received);
void on_have(int received);
void on_bitfield(int received);
void on_request(int received);
void on_piece(int received);
void on_cancel(int received);
// DHT extension
void on_dht_port(int received);
// FAST extension
void on_suggest_piece(int received);
void on_have_all(int received);
void on_have_none(int received);
void on_reject_request(int received);
void on_allowed_fast(int received);
void on_extended(int received);
void on_extended_handshake();
typedef void (bt_peer_connection::*message_handler)(int received);
// the following functions appends messages
// to the send buffer
void write_choke();
void write_unchoke();
void write_interested();
void write_not_interested();
void write_request(peer_request const& r);
void write_cancel(peer_request const& r);
void write_bitfield();
void write_have(int index);
void write_piece(peer_request const& r, disk_buffer_holder& buffer);
void write_handshake();
#ifndef TORRENT_DISABLE_EXTENSIONS
void write_extensions();
#endif
void write_chat_message(const std::string& msg);
void write_metadata(std::pair<int, int> req);
void write_metadata_request(std::pair<int, int> req);
void write_keepalive();
// DHT extension
void write_dht_port(int listen_port);
// FAST extension
void write_have_all();
void write_have_none();
void write_reject_request(peer_request const&);
void write_allow_fast(int piece);
void on_connected();
void on_metadata();
#ifndef NDEBUG
void check_invariant() const;
ptime m_last_choke;
#endif
private:
bool dispatch_message(int received);
// returns the block currently being
// downloaded. And the progress of that
// block. If the peer isn't downloading
// a piece for the moment, the boost::optional
// will be invalid.
boost::optional<piece_block_progress> downloading_piece_progress() const;
#ifndef TORRENT_DISABLE_ENCRYPTION
// if (is_local()), we are 'a' otherwise 'b'
//
// 1. a -> b dhkey, pad
// 2. b -> a dhkey, pad
// 3. a -> b sync, payload
// 4. b -> a sync, payload
// 5. a -> b payload
void write_pe1_2_dhkey();
void write_pe3_sync();
void write_pe4_sync(int crypto_select);
void write_pe_vc_cryptofield(buffer::interval& write_buf,
int crypto_field, int pad_size);
// stream key (info hash of attached torrent)
// secret is the DH shared secret
// initializes m_RC4_handler
void init_pe_RC4_handler(char const* secret, sha1_hash const& stream_key);
public:
// these functions encrypt the send buffer if m_rc4_encrypted
// is true, otherwise it passes the call to the
// peer_connection functions of the same names
void send_buffer(char* buf, int size);
buffer::interval allocate_send_buffer(int size);
template <class Destructor>
void append_send_buffer(char* buffer, int size, Destructor const& destructor)
{
#ifndef TORRENT_DISABLE_ENCRYPTION
if (m_rc4_encrypted)
m_RC4_handler->encrypt(buffer, size);
#endif
peer_connection::append_send_buffer(buffer, size, destructor);
}
void setup_send();
private:
// Returns offset at which bytestream (src, src + src_size)
// matches bytestream(target, target + target_size).
// If no sync found, return -1
int get_syncoffset(char const* src, int src_size,
char const* target, int target_size) const;
#endif
enum state
{
#ifndef TORRENT_DISABLE_ENCRYPTION
read_pe_dhkey = 0,
read_pe_syncvc,
read_pe_synchash,
read_pe_skey_vc,
read_pe_cryptofield,
read_pe_pad,
read_pe_ia,
init_bt_handshake,
read_protocol_identifier,
#else
read_protocol_identifier = 0,
#endif
read_info_hash,
read_peer_id,
// handshake complete
read_packet_size,
read_packet
};
#ifndef TORRENT_DISABLE_ENCRYPTION
enum
{
handshake_len = 68,
dh_key_len = 96
};
#endif
std::string m_client_version;
// state of on_receive
state m_state;
// the timeout in seconds
int m_timeout;
static const message_handler m_message_handler[num_supported_messages];
// this is a queue of ranges that describes
// where in the send buffer actual payload
// data is located. This is currently
// only used to be able to gather statistics
// seperately on payload and protocol data.
struct range
{
range(int s, int l)
: start(s)
, length(l)
{
TORRENT_ASSERT(s >= 0);
TORRENT_ASSERT(l > 0);
}
int start;
int length;
};
static bool range_below_zero(const range& r)
{ return r.start < 0; }
std::deque<range> m_payloads;
#ifndef TORRENT_DISABLE_EXTENSIONS
// this is set to true if the handshake from
// the peer indicated that it supports the
// extension protocol
bool m_supports_extensions;
char m_reserved_bits[20];
#endif
bool m_supports_dht_port;
bool m_supports_fast;
#ifndef TORRENT_DISABLE_ENCRYPTION
// this is set to true after the encryption method has been
// succesfully negotiated (either plaintext or rc4), to signal
// automatic encryption/decryption.
bool m_encrypted;
// true if rc4, false if plaintext
bool m_rc4_encrypted;
// used to disconnect peer if sync points are not found within
// the maximum number of bytes
int m_sync_bytes_read;
// hold information about latest allocated send buffer
// need to check for non zero (begin, end) for operations with this
buffer::interval m_enc_send_buffer;
// initialized during write_pe1_2_dhkey, and destroyed on
// creation of m_RC4_handler. Cannot reinitialize once
// initialized.
boost::scoped_ptr<dh_key_exchange> m_dh_key_exchange;
// if RC4 is negotiated, this is used for
// encryption/decryption during the entire session. Destroyed
// if plaintext is selected
boost::scoped_ptr<RC4_handler> m_RC4_handler;
// (outgoing only) synchronize verification constant with
// remote peer, this will hold RC4_decrypt(vc). Destroyed
// after the sync step.
boost::scoped_array<char> m_sync_vc;
// (incoming only) synchronize hash with remote peer, holds
// the sync hash (hash("req1",secret)). Destroyed after the
// sync step.
boost::scoped_ptr<sha1_hash> m_sync_hash;
#endif // #ifndef TORRENT_DISABLE_ENCRYPTION
#ifndef NDEBUG
// this is set to true when the client's
// bitfield is sent to this peer
bool m_sent_bitfield;
bool m_in_constructor;
bool m_sent_handshake;
#endif
};
}
#endif // TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED

View File

@ -0,0 +1,205 @@
/*
Copyright (c) 2007, 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 Rasterbar Software 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.
*/
#ifndef LIBTORRENT_BUFFER_HPP
#define LIBTORRENT_BUFFER_HPP
#include <memory>
#include <cstring>
#include "libtorrent/invariant_check.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent {
class buffer
{
public:
struct interval
{
interval()
: begin(0)
, end(0)
{}
interval(char* begin, char* end)
: begin(begin)
, end(end)
{}
char operator[](int index) const
{
TORRENT_ASSERT(begin + index < end);
return begin[index];
}
int left() const { TORRENT_ASSERT(end >= begin); return end - begin; }
char* begin;
char* end;
};
struct const_interval
{
const_interval(char const* begin, char const* end)
: begin(begin)
, end(end)
{}
char operator[](int index) const
{
TORRENT_ASSERT(begin + index < end);
return begin[index];
}
bool operator==(const const_interval& p_interval)
{
return (begin == p_interval.begin
&& end == p_interval.end);
}
int left() const { TORRENT_ASSERT(end >= begin); return end - begin; }
char const* begin;
char const* end;
};
buffer(std::size_t n = 0)
: m_begin(0)
, m_end(0)
, m_last(0)
{
if (n) resize(n);
}
buffer(buffer const& b)
: m_begin(0)
, m_end(0)
, m_last(0)
{
if (b.size() == 0) return;
resize(b.size());
std::memcpy(m_begin, b.begin(), b.size());
}
buffer& operator=(buffer const& b)
{
resize(b.size());
std::memcpy(m_begin, b.begin(), b.size());
return *this;
}
~buffer()
{
::operator delete (m_begin);
}
buffer::interval data() { return interval(m_begin, m_end); }
buffer::const_interval data() const { return const_interval(m_begin, m_end); }
void resize(std::size_t n)
{
reserve(n);
m_end = m_begin + n;
}
void insert(char* point, char const* first, char const* last)
{
std::size_t p = point - m_begin;
if (point == m_end)
{
resize(size() + last - first);
std::memcpy(m_begin + p, first, last - first);
return;
}
resize(size() + last - first);
std::memmove(m_begin + p + (last - first), m_begin + p, last - first);
std::memcpy(m_begin + p, first, last - first);
}
void erase(char* begin, char* end)
{
TORRENT_ASSERT(end <= m_end);
TORRENT_ASSERT(begin >= m_begin);
TORRENT_ASSERT(begin <= end);
if (end == m_end)
{
resize(begin - m_begin);
return;
}
std::memmove(begin, end, m_end - end);
m_end = begin + (m_end - end);
}
void clear() { m_end = m_begin; }
std::size_t size() const { return m_end - m_begin; }
std::size_t capacity() const { return m_last - m_begin; }
void reserve(std::size_t n)
{
if (n <= capacity()) return;
TORRENT_ASSERT(n > 0);
char* buf = (char*)::operator new(n);
std::size_t s = size();
std::memcpy(buf, m_begin, s);
::operator delete (m_begin);
m_begin = buf;
m_end = buf + s;
m_last = m_begin + n;
}
bool empty() const { return m_begin == m_end; }
char& operator[](std::size_t i) { TORRENT_ASSERT(i < size()); return m_begin[i]; }
char const& operator[](std::size_t i) const { TORRENT_ASSERT(i < size()); return m_begin[i]; }
char* begin() { return m_begin; }
char const* begin() const { return m_begin; }
char* end() { return m_end; }
char const* end() const { return m_end; }
void swap(buffer& b)
{
using std::swap;
swap(m_begin, b.m_begin);
swap(m_end, b.m_end);
swap(m_last, b.m_last);
}
private:
char* m_begin; // first
char* m_end; // one passed end of size
char* m_last; // one passed end of allocation
};
}
#endif // LIBTORRENT_BUFFER_HPP

View File

@ -0,0 +1,200 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_CHAINED_BUFFER_HPP_INCLUDED
#define TORRENT_CHAINED_BUFFER_HPP_INCLUDED
#include <boost/function.hpp>
#include <boost/version.hpp>
#if BOOST_VERSION < 103500
#include <asio/buffer.hpp>
#else
#include <boost/asio/buffer.hpp>
#endif
#include <list>
#include <cstring>
namespace libtorrent
{
#if BOOST_VERSION >= 103500
namespace asio = boost::asio;
#endif
struct chained_buffer
{
chained_buffer(): m_bytes(0), m_capacity(0) {}
struct buffer_t
{
boost::function<void(char*)> free; // destructs the buffer
char* buf; // the first byte of the buffer
int size; // the total size of the buffer
char* start; // the first byte to send/receive in the buffer
int used_size; // this is the number of bytes to send/receive
};
bool empty() const { return m_bytes == 0; }
int size() const { return m_bytes; }
int capacity() const { return m_capacity; }
void pop_front(int bytes_to_pop)
{
TORRENT_ASSERT(bytes_to_pop <= m_bytes);
while (bytes_to_pop > 0 && !m_vec.empty())
{
buffer_t& b = m_vec.front();
if (b.used_size > bytes_to_pop)
{
b.start += bytes_to_pop;
b.used_size -= bytes_to_pop;
m_bytes -= bytes_to_pop;
TORRENT_ASSERT(m_bytes <= m_capacity);
TORRENT_ASSERT(m_bytes >= 0);
TORRENT_ASSERT(m_capacity >= 0);
break;
}
b.free(b.buf);
m_bytes -= b.used_size;
m_capacity -= b.size;
bytes_to_pop -= b.used_size;
TORRENT_ASSERT(m_bytes >= 0);
TORRENT_ASSERT(m_capacity >= 0);
TORRENT_ASSERT(m_bytes <= m_capacity);
m_vec.pop_front();
}
}
template <class D>
void append_buffer(char* buffer, int size, int used_size, D const& destructor)
{
TORRENT_ASSERT(size >= used_size);
buffer_t b;
b.buf = buffer;
b.size = size;
b.start = buffer;
b.used_size = used_size;
b.free = destructor;
m_vec.push_back(b);
m_bytes += used_size;
m_capacity += size;
TORRENT_ASSERT(m_bytes <= m_capacity);
}
// returns the number of bytes available at the
// end of the last chained buffer.
int space_in_last_buffer()
{
if (m_vec.empty()) return 0;
buffer_t& b = m_vec.back();
return b.size - b.used_size - (b.start - b.buf);
}
// tries to copy the given buffer to the end of the
// last chained buffer. If there's not enough room
// it returns false
bool append(char const* buf, int size)
{
char* insert = allocate_appendix(size);
if (insert == 0) return false;
std::memcpy(insert, buf, size);
return true;
}
// tries to allocate memory from the end
// of the last buffer. If there isn't
// enough room, returns 0
char* allocate_appendix(int size)
{
if (m_vec.empty()) return 0;
buffer_t& b = m_vec.back();
char* insert = b.start + b.used_size;
if (insert + size > b.buf + b.size) return 0;
b.used_size += size;
m_bytes += size;
TORRENT_ASSERT(m_bytes <= m_capacity);
return insert;
}
std::list<asio::const_buffer> const& build_iovec(int to_send)
{
m_tmp_vec.clear();
for (std::list<buffer_t>::iterator i = m_vec.begin()
, end(m_vec.end()); to_send > 0 && i != end; ++i)
{
if (i->used_size > to_send)
{
TORRENT_ASSERT(to_send > 0);
m_tmp_vec.push_back(asio::const_buffer(i->start, to_send));
break;
}
TORRENT_ASSERT(i->used_size > 0);
m_tmp_vec.push_back(asio::const_buffer(i->start, i->used_size));
to_send -= i->used_size;
}
return m_tmp_vec;
}
~chained_buffer()
{
for (std::list<buffer_t>::iterator i = m_vec.begin()
, end(m_vec.end()); i != end; ++i)
{
i->free(i->buf);
}
}
private:
// this is the list of all the buffers we want to
// send
std::list<buffer_t> m_vec;
// this is the number of bytes in the send buf.
// this will always be equal to the sum of the
// size of all buffers in vec
int m_bytes;
// the total size of all buffers in the chain
// including unused space
int m_capacity;
// this is the vector of buffers used when
// invoking the async write call
std::list<asio::const_buffer> m_tmp_vec;
};
}
#endif

View File

@ -0,0 +1,93 @@
/*
Copyright (c) 2005, 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.
*/
#ifndef TORRENT_CONFIG_HPP_INCLUDED
#define TORRENT_CONFIG_HPP_INCLUDED
#include <boost/config.hpp>
#include <boost/version.hpp>
#if defined(__GNUC__) && __GNUC__ >= 4
#define TORRENT_DEPRECATED __attribute__ ((deprecated))
# if defined(TORRENT_BUILDING_SHARED) || defined(TORRENT_LINKING_SHARED)
# define TORRENT_EXPORT __attribute__ ((visibility("default")))
# else
# define TORRENT_EXPORT
# endif
#elif defined(__GNUC__)
# define TORRENT_EXPORT
#elif defined(BOOST_MSVC)
# if defined(TORRENT_BUILDING_SHARED)
# define TORRENT_EXPORT __declspec(dllexport)
# elif defined(TORRENT_LINKING_SHARED)
# define TORRENT_EXPORT __declspec(dllimport)
# else
# define TORRENT_EXPORT
# endif
#else
# define TORRENT_EXPORT
#endif
#ifndef TORRENT_DEPRECATED
#define TORRENT_DEPRECATED
#endif
// set up defines for target environments
#if (defined __APPLE__ && __MACH__) || defined __FreeBSD__ || defined __NetBSD__ \
|| defined __OpenBSD__ || defined __bsdi__ || defined __DragonFly__ \
|| defined __FreeBSD_kernel__
#define TORRENT_BSD
#elif defined __linux__
#define TORRENT_LINUX
#elif defined WIN32
#define TORRENT_WINDOWS
#else
#warning unkown OS, assuming BSD
#define TORRENT_BSD
#endif
// should wpath or path be used?
#if defined UNICODE && !defined BOOST_FILESYSTEM_NARROW_ONLY && BOOST_VERSION >= 103400
#define TORRENT_USE_WPATH 1
#else
#define TORRENT_USE_WPATH 0
#endif
#endif // TORRENT_CONFIG_HPP_INCLUDED

View File

@ -0,0 +1,113 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_CONNECTION_QUEUE
#define TORRENT_CONNECTION_QUEUE
#include <list>
#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include "libtorrent/socket.hpp"
#include "libtorrent/time.hpp"
#ifdef TORRENT_CONNECTION_LOGGING
#include <fstream>
#endif
namespace libtorrent
{
class connection_queue : public boost::noncopyable
{
public:
connection_queue(io_service& ios);
// if there are no free slots, returns the negative
// number of queued up connections
int free_slots() const;
void enqueue(boost::function<void(int)> const& on_connect
, boost::function<void()> const& on_timeout
, time_duration timeout, int priority = 0);
void done(int ticket);
void limit(int limit);
int limit() const;
void close();
#ifndef NDEBUG
void check_invariant() const;
#endif
private:
void try_connect();
void on_timeout(error_code const& e);
struct entry
{
entry(): connecting(false), ticket(0), expires(max_time()), priority(0) {}
// called when the connection is initiated
boost::function<void(int)> on_connect;
// called if done hasn't been called within the timeout
boost::function<void()> on_timeout;
bool connecting;
int ticket;
ptime expires;
time_duration timeout;
int priority;
};
std::list<entry> m_queue;
// the next ticket id a connection will be given
int m_next_ticket;
int m_num_connecting;
int m_half_open_limit;
deadline_timer m_timer;
typedef boost::recursive_mutex mutex_t;
mutable mutex_t m_mutex;
#ifndef NDEBUG
bool m_in_timeout_function;
#endif
#ifdef TORRENT_CONNECTION_LOGGING
std::ofstream m_log;
#endif
};
}
#endif

View File

@ -0,0 +1,200 @@
/*
Copyright (c) 2008, 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.
*/
#ifndef TORRENT_CREATE_TORRENT_HPP_INCLUDED
#define TORRENT_CREATE_TORRENT_HPP_INCLUDED
#include "libtorrent/bencode.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/file_storage.hpp"
#include "libtorrent/file_pool.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/storage.hpp"
#include "libtorrent/hasher.hpp"
#include <vector>
#include <string>
#include <utility>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/optional.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/scoped_ptr.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
namespace libtorrent
{
namespace fs = boost::filesystem;
namespace pt = boost::posix_time;
struct TORRENT_EXPORT create_torrent
{
create_torrent(file_storage& fs, int piece_size);
create_torrent(file_storage& fs);
entry generate() const;
file_storage const& files() const { return m_files; }
void set_comment(char const* str);
void set_creator(char const* str);
void set_hash(int index, sha1_hash const& h);
void add_url_seed(std::string const& url);
void add_node(std::pair<std::string, int> const& node);
void add_tracker(std::string const& url, int tier = 0);
int num_pieces() const { return m_files.num_pieces(); }
int piece_length() const { return m_files.piece_length(); }
int piece_size(int i) const { return m_files.piece_size(i); }
private:
file_storage& m_files;
// the urls to the trackers
typedef std::pair<std::string, int> announce_entry;
std::vector<announce_entry> m_urls;
std::vector<std::string> m_url_seeds;
std::vector<sha1_hash> m_piece_hash;
// dht nodes to add to the routing table/bootstrap from
typedef std::vector<std::pair<std::string, int> > nodes_t;
nodes_t m_nodes;
// the hash that identifies this torrent
// is mutable because it's calculated
// lazily
mutable sha1_hash m_info_hash;
// if a creation date is found in the torrent file
// this will be set to that, otherwise it'll be
// 1970, Jan 1
pt::ptime m_creation_date;
// if a comment is found in the torrent file
// this will be set to that comment
std::string m_comment;
// an optional string naming the software used
// to create the torrent file
std::string m_created_by;
// this is used when creating a torrent. If there's
// only one file there are cases where it's impossible
// to know if it should be written as a multifile torrent
// or not. e.g. test/test there's one file and one directory
// and they have the same name.
bool m_multifile;
// this is true if the torrent is private. i.e., is should not
// be announced on the dht
bool m_private;
};
namespace detail
{
inline bool default_pred(boost::filesystem::path const&) { return true; }
inline void nop(int i) {}
template <class Pred>
void add_files_impl(file_storage& fs, boost::filesystem::path const& p
, boost::filesystem::path const& l, Pred pred)
{
using boost::filesystem::path;
using boost::filesystem::directory_iterator;
std::string const& leaf = l.leaf();
if (leaf == ".." || leaf == ".") return;
if (!pred(l)) return;
path f(p / l);
if (is_directory(f))
{
for (directory_iterator i(f), end; i != end; ++i)
add_files_impl(fs, p, l / i->leaf(), pred);
}
else
{
fs.add_file(l, file_size(f));
}
}
}
template <class Pred>
void add_files(file_storage& fs, boost::filesystem::path const& file, Pred p)
{
detail::add_files_impl(fs, complete(file).branch_path(), file.leaf(), p);
}
inline void add_files(file_storage& fs, boost::filesystem::path const& file)
{
detail::add_files_impl(fs, complete(file).branch_path(), file.leaf(), detail::default_pred);
}
template <class Fun>
void set_piece_hashes(create_torrent& t, boost::filesystem::path const& p, Fun f)
{
file_pool fp;
boost::scoped_ptr<storage_interface> st(
default_storage_constructor(const_cast<file_storage&>(t.files()), p, fp));
// calculate the hash for all pieces
int num = t.num_pieces();
std::vector<char> buf(t.piece_length());
for (int i = 0; i < num; ++i)
{
// read hits the disk and will block. Progress should
// be updated in between reads
st->read(&buf[0], i, 0, t.piece_size(i));
hasher h(&buf[0], t.piece_size(i));
t.set_hash(i, h.final());
f(i);
}
}
inline void set_piece_hashes(create_torrent& t, boost::filesystem::path const& p)
{
set_piece_hashes(t, p, detail::nop);
}
}
#endif

View File

@ -0,0 +1,94 @@
/*
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.
*/
#ifndef TORRENT_DEBUG_HPP_INCLUDED
#define TORRENT_DEBUG_HPP_INCLUDED
#include <string>
#include <fstream>
#include <iostream>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/lexical_cast.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/convenience.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
namespace libtorrent
{
// DEBUG API
namespace fs = boost::filesystem;
struct logger
{
logger(fs::path const& logpath, fs::path const& filename, int instance, bool append = true)
{
#ifndef BOOST_NO_EXCEPTIONS
try
{
#endif
fs::path dir(fs::complete(logpath / ("libtorrent_logs" + boost::lexical_cast<std::string>(instance))));
if (!fs::exists(dir)) fs::create_directories(dir);
m_file.open((dir / filename).string().c_str(), std::ios_base::out | (append ? std::ios_base::app : std::ios_base::out));
*this << "\n\n\n*** starting log ***\n";
#ifndef BOOST_NO_EXCEPTIONS
}
catch (std::exception& e)
{
std::cerr << "failed to create log '" << filename.string() << "': " << e.what() << std::endl;
}
#endif
}
template <class T>
logger& operator<<(T const& v)
{
m_file << v;
m_file.flush();
return *this;
}
std::ofstream m_file;
};
}
#endif // TORRENT_DEBUG_HPP_INCLUDED

View File

@ -0,0 +1,65 @@
/*
Copyright (c) 2008, 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.
*/
#ifndef TORRENT_DISK_BUFFER_HOLDER_HPP_INCLUDED
#define TORRENT_DISK_BUFFER_HOLDER_HPP_INCLUDED
#include "libtorrent/config.hpp"
namespace libtorrent
{
namespace aux { class session_impl; }
class disk_io_thread;
struct TORRENT_EXPORT disk_buffer_holder
{
disk_buffer_holder(aux::session_impl& ses, char* buf);
disk_buffer_holder(disk_io_thread& iothread, char* buf);
~disk_buffer_holder();
char* release();
char* get() const { return m_buf; }
void reset(char* buf = 0);
typedef char* (disk_buffer_holder::*unspecified_bool_type)();
operator unspecified_bool_type() const
{ return m_buf == 0? 0: &disk_buffer_holder::release; }
private:
disk_io_thread& m_iothread;
char* m_buf;
};
}
#endif

View File

@ -0,0 +1,309 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_DISK_IO_THREAD
#define TORRENT_DISK_IO_THREAD
#ifdef TORRENT_DISK_STATS
#include <fstream>
#endif
#include "libtorrent/storage.hpp"
#include <boost/thread/thread.hpp>
#include <boost/function.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_array.hpp>
#include <list>
#include "libtorrent/config.hpp"
#ifndef TORRENT_DISABLE_POOL_ALLOCATOR
#include <boost/pool/pool.hpp>
#endif
namespace libtorrent
{
struct cached_piece_info
{
int piece;
std::vector<bool> blocks;
ptime last_use;
};
struct disk_io_job
{
disk_io_job()
: action(read)
, buffer(0)
, buffer_size(0)
, piece(0)
, offset(0)
, priority(0)
{}
enum action_t
{
read
, write
, hash
, move_storage
, release_files
, delete_files
, check_fastresume
, check_files
, save_resume_data
, rename_file
, abort_thread
};
action_t action;
char* buffer;
int buffer_size;
boost::intrusive_ptr<piece_manager> storage;
// arguments used for read and write
int piece, offset;
// used for move_storage and rename_file. On errors, this is set
// to the error message
std::string str;
// on error, this is set to the path of the
// file the disk operation failed on
std::string error_file;
// priority decides whether or not this
// job will skip entries in the queue or
// not. It always skips in front of entries
// with lower priority
int priority;
boost::shared_ptr<entry> resume_data;
// this is called when operation completes
boost::function<void(int, disk_io_job const&)> callback;
};
struct cache_status
{
cache_status()
: blocks_written(0)
, writes(0)
, blocks_read(0)
, blocks_read_hit(0)
, reads(0)
, cache_size(0)
, read_cache_size(0)
{}
// the number of 16kB blocks written
size_type blocks_written;
// the number of write operations used
size_type writes;
// (blocks_written - writes) / blocks_written represents the
// "cache hit" ratio in the write cache
// the number of blocks read
// the number of blocks passed back to the bittorrent engine
size_type blocks_read;
// the number of blocks that was just copied from the read cache
size_type blocks_read_hit;
// the number of read operations used
size_type reads;
// the number of blocks in the cache (both read and write)
int cache_size;
// the number of blocks in the cache used for read cache
int read_cache_size;
};
// this is a singleton consisting of the thread and a queue
// of disk io jobs
struct disk_io_thread : boost::noncopyable
{
disk_io_thread(io_service& ios, int block_size = 16 * 1024);
~disk_io_thread();
#ifdef TORRENT_STATS
int disk_allocations() const
{ return m_allocations; }
#endif
void join();
// aborts read operations
void stop(boost::intrusive_ptr<piece_manager> s);
void add_job(disk_io_job const& j
, boost::function<void(int, disk_io_job const&)> const& f
= boost::function<void(int, disk_io_job const&)>());
// keep track of the number of bytes in the job queue
// at any given time. i.e. the sum of all buffer_size.
// this is used to slow down the download global download
// speed when the queue buffer size is too big.
size_type queue_buffer_size() const
{ return m_queue_buffer_size; }
void get_cache_info(sha1_hash const& ih
, std::vector<cached_piece_info>& ret) const;
cache_status status() const;
void set_cache_size(int s);
void set_cache_expiry(int ex);
void operator()();
#ifndef NDEBUG
bool is_disk_buffer(char* buffer) const;
#endif
char* allocate_buffer();
void free_buffer(char* buf);
#ifndef NDEBUG
void check_invariant() const;
#endif
private:
struct cached_piece_entry
{
int piece;
// storage this piece belongs to
boost::intrusive_ptr<piece_manager> storage;
// the last time a block was writting to this piece
ptime last_use;
// the number of blocks in the cache for this piece
int num_blocks;
// the pointers to the block data
boost::shared_array<char*> blocks;
};
typedef boost::recursive_mutex mutex_t;
typedef std::list<cached_piece_entry> cache_t;
// cache operations
cache_t::iterator find_cached_piece(
cache_t& cache, disk_io_job const& j
, mutex_t::scoped_lock& l);
// write cache operations
void flush_oldest_piece(mutex_t::scoped_lock& l);
void flush_expired_pieces();
void flush_and_remove(cache_t::iterator i, mutex_t::scoped_lock& l);
void flush(cache_t::iterator i, mutex_t::scoped_lock& l);
void cache_block(disk_io_job& j, mutex_t::scoped_lock& l);
// read cache operations
bool clear_oldest_read_piece(cache_t::iterator ignore
, mutex_t::scoped_lock& l);
int read_into_piece(cached_piece_entry& p, int start_block, mutex_t::scoped_lock& l);
int cache_read_block(disk_io_job const& j, mutex_t::scoped_lock& l);
void free_piece(cached_piece_entry& p, mutex_t::scoped_lock& l);
bool make_room(int num_blocks
, cache_t::iterator ignore
, mutex_t::scoped_lock& l);
int try_read_from_cache(disk_io_job const& j);
// this mutex only protects m_jobs, m_queue_buffer_size
// and m_abort
mutable mutex_t m_queue_mutex;
boost::condition m_signal;
bool m_abort;
std::list<disk_io_job> m_jobs;
size_type m_queue_buffer_size;
// this protects the piece cache and related members
mutable mutex_t m_piece_mutex;
// write cache
cache_t m_pieces;
// read cache
cache_t m_read_pieces;
// total number of blocks in use by both the read
// and the write cache. This is not supposed to
// exceed m_cache_size
cache_status m_cache_stats;
int m_num_cached_blocks;
// in (16kB) blocks
int m_cache_size;
// expiration time of cache entries in seconds
int m_cache_expiry;
// if set to true, each piece flush will allocate
// one piece worth of temporary memory on the heap
// and copy the block data into it, and then perform
// a single write operation from that buffer.
// if memory is constrained, that temporary buffer
// might is avoided by setting this to false.
// in case the allocation fails, the piece flush
// falls back to writing each block separately.
bool m_coalesce_writes;
bool m_coalesce_reads;
bool m_use_read_cache;
// this only protects the pool allocator
mutable mutex_t m_pool_mutex;
#ifndef TORRENT_DISABLE_POOL_ALLOCATOR
// memory pool for read and write operations
// and disk cache
boost::pool<> m_pool;
#endif
// number of bytes per block. The BitTorrent
// protocol defines the block size to 16 KiB.
int m_block_size;
#ifdef TORRENT_DISK_STATS
std::ofstream m_log;
#endif
#ifdef TORRENT_STATS
int m_allocations;
#endif
size_type m_writes;
size_type m_blocks_written;
io_service& m_ios;
// thread for performing blocking disk io operations
boost::thread m_disk_io_thread;
};
}
#endif

View File

@ -0,0 +1,337 @@
/*
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.
*/
#ifndef TORRENT_ENTRY_HPP_INCLUDED
#define TORRENT_ENTRY_HPP_INCLUDED
/*
*
* This file declares the entry class. It is a
* variant-type that can be an integer, list,
* dictionary (map) or a string. This type is
* used to hold bdecoded data (which is the
* encoding BitTorrent messages uses).
*
* it has 4 accessors to access the actual
* type of the object. They are:
* integer()
* string()
* list()
* dict()
* The actual type has to match the type you
* are asking for, otherwise you will get an
* assertion failure.
* When you default construct an entry, it is
* uninitialized. You can initialize it through the
* assignment operator, copy-constructor or
* the constructor that takes a data_type enum.
*
*
*/
#include <iosfwd>
#include <map>
#include <list>
#include <string>
#include <stdexcept>
#include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{
struct TORRENT_EXPORT type_error: std::runtime_error
{
type_error(const char* error): std::runtime_error(error) {}
};
namespace detail
{
template<int v1, int v2>
struct max2 { enum { value = v1>v2?v1:v2 }; };
template<int v1, int v2, int v3>
struct max3
{
enum
{
temp = max2<v1,v2>::value,
value = temp>v3?temp:v3
};
};
template<int v1, int v2, int v3, int v4>
struct max4
{
enum
{
temp = max3<v1,v2, v3>::value,
value = temp>v4?temp:v4
};
};
}
class entry;
class TORRENT_EXPORT entry
{
public:
// the key is always a string. If a generic entry would be allowed
// as a key, sorting would become a problem (e.g. to compare a string
// to a list). The definition doesn't mention such a limit though.
typedef std::map<std::string, entry> dictionary_type;
typedef std::string string_type;
typedef std::list<entry> list_type;
typedef size_type integer_type;
enum data_type
{
int_t,
string_t,
list_t,
dictionary_t,
undefined_t
};
data_type type() const;
entry(dictionary_type const&);
entry(string_type const&);
entry(list_type const&);
entry(integer_type const&);
entry();
entry(data_type t);
entry(entry const& e);
~entry();
bool operator==(entry const& e) const;
void operator=(entry const&);
void operator=(dictionary_type const&);
void operator=(string_type const&);
void operator=(list_type const&);
void operator=(integer_type const&);
integer_type& integer();
const integer_type& integer() const;
string_type& string();
const string_type& string() const;
list_type& list();
const list_type& list() const;
dictionary_type& dict();
const dictionary_type& dict() const;
void swap(entry& e);
// these functions requires that the entry
// is a dictionary, otherwise they will throw
entry& operator[](char const* key);
entry& operator[](std::string const& key);
#ifndef BOOST_NO_EXCEPTIONS
const entry& operator[](char const* key) const;
const entry& operator[](std::string const& key) const;
#endif
entry* find_key(char const* key);
entry const* find_key(char const* key) const;
entry* find_key(std::string const& key);
entry const* find_key(std::string const& key) const;
void print(std::ostream& os, int indent = 0) const;
protected:
void construct(data_type t);
void copy(const entry& e);
void destruct();
private:
data_type m_type;
#if defined(_MSC_VER) && _MSC_VER < 1310
// workaround for msvc-bug.
// assumes sizeof(map<string, char>) == sizeof(map<string, entry>)
// and sizeof(list<char>) == sizeof(list<entry>)
union
{
char data[
detail::max4<sizeof(std::list<char>)
, sizeof(std::map<std::string, char>)
, sizeof(string_type)
, sizeof(integer_type)>::value];
integer_type dummy_aligner;
};
#else
union
{
char data[detail::max4<sizeof(list_type)
, sizeof(dictionary_type)
, sizeof(string_type)
, sizeof(integer_type)>::value];
integer_type dummy_aligner;
};
#endif
#ifndef NDEBUG
public:
// in debug mode this is set to false by bdecode
// to indicate that the program has not yet queried
// the type of this entry, and sould not assume
// that it has a certain type. This is asserted in
// the accessor functions. This does not apply if
// exceptions are used.
mutable bool m_type_queried;
#endif
};
inline std::ostream& operator<<(std::ostream& os, const entry& e)
{
e.print(os, 0);
return os;
}
inline entry::data_type entry::type() const
{
#ifndef NDEBUG
m_type_queried = true;
#endif
return m_type;
}
inline entry::~entry() { destruct(); }
inline void entry::operator=(const entry& e)
{
destruct();
copy(e);
}
inline entry::integer_type& entry::integer()
{
if (m_type == undefined_t) construct(int_t);
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != int_t) throw type_error("invalid type requested from entry");
#elif !defined NDEBUG
TORRENT_ASSERT(m_type_queried);
#endif
TORRENT_ASSERT(m_type == int_t);
return *reinterpret_cast<integer_type*>(data);
}
inline entry::integer_type const& entry::integer() const
{
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != int_t) throw type_error("invalid type requested from entry");
#elif !defined NDEBUG
TORRENT_ASSERT(m_type_queried);
#endif
TORRENT_ASSERT(m_type == int_t);
return *reinterpret_cast<const integer_type*>(data);
}
inline entry::string_type& entry::string()
{
if (m_type == undefined_t) construct(string_t);
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != string_t) throw type_error("invalid type requested from entry");
#elif !defined NDEBUG
TORRENT_ASSERT(m_type_queried);
#endif
TORRENT_ASSERT(m_type == string_t);
return *reinterpret_cast<string_type*>(data);
}
inline entry::string_type const& entry::string() const
{
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != string_t) throw type_error("invalid type requested from entry");
#elif !defined NDEBUG
TORRENT_ASSERT(m_type_queried);
#endif
TORRENT_ASSERT(m_type == string_t);
return *reinterpret_cast<const string_type*>(data);
}
inline entry::list_type& entry::list()
{
if (m_type == undefined_t) construct(list_t);
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != list_t) throw type_error("invalid type requested from entry");
#elif !defined NDEBUG
TORRENT_ASSERT(m_type_queried);
#endif
TORRENT_ASSERT(m_type == list_t);
return *reinterpret_cast<list_type*>(data);
}
inline entry::list_type const& entry::list() const
{
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != list_t) throw type_error("invalid type requested from entry");
#elif !defined NDEBUG
TORRENT_ASSERT(m_type_queried);
#endif
TORRENT_ASSERT(m_type == list_t);
return *reinterpret_cast<const list_type*>(data);
}
inline entry::dictionary_type& entry::dict()
{
if (m_type == undefined_t) construct(dictionary_t);
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != dictionary_t) throw type_error("invalid type requested from entry");
#elif !defined NDEBUG
TORRENT_ASSERT(m_type_queried);
#endif
TORRENT_ASSERT(m_type == dictionary_t);
return *reinterpret_cast<dictionary_type*>(data);
}
inline entry::dictionary_type const& entry::dict() const
{
#ifndef BOOST_NO_EXCEPTIONS
if (m_type != dictionary_t) throw type_error("invalid type requested from entry");
#elif !defined NDEBUG
TORRENT_ASSERT(m_type_queried);
#endif
TORRENT_ASSERT(m_type == dictionary_t);
return *reinterpret_cast<const dictionary_type*>(data);
}
}
#endif // TORRENT_ENTRY_HPP_INCLUDED

View File

@ -0,0 +1,78 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_ENUM_NET_HPP_INCLUDED
#define TORRENT_ENUM_NET_HPP_INCLUDED
#include "libtorrent/config.hpp"
#include "libtorrent/socket.hpp"
namespace libtorrent
{
struct ip_interface
{
address interface_address;
address netmask;
char name[64];
};
struct ip_route
{
address destination;
address netmask;
address gateway;
char name[64];
};
// returns a list of the configured IP interfaces
// on the machine
TORRENT_EXPORT std::vector<ip_interface> enum_net_interfaces(io_service& ios
, error_code& ec);
TORRENT_EXPORT std::vector<ip_route> enum_routes(io_service& ios, error_code& ec);
// returns true if the specified address is on the same
// local network as the specified interface
TORRENT_EXPORT bool in_subnet(address const& addr, ip_interface const& iface);
// returns true if the specified address is on the same
// local network as us
TORRENT_EXPORT bool in_local_network(io_service& ios, address const& addr
, error_code& ec);
TORRENT_EXPORT address get_default_gateway(io_service& ios
, error_code& ec);
}
#endif

View File

@ -0,0 +1,58 @@
/*
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.
*/
#ifndef TORRENT_ESCAPE_STRING_HPP_INCLUDED
#define TORRENT_ESCAPE_STRING_HPP_INCLUDED
#include <string>
#include <boost/optional.hpp>
#include "libtorrent/config.hpp"
namespace libtorrent
{
std::string TORRENT_EXPORT unescape_string(std::string const& s);
std::string TORRENT_EXPORT escape_string(const char* str, int len);
std::string TORRENT_EXPORT escape_path(const char* str, int len);
// encodes a string using the base64 scheme
TORRENT_EXPORT std::string base64encode(std::string const& s);
// encodes a string using the base32 scheme
TORRENT_EXPORT std::string base32encode(std::string const& s);
TORRENT_EXPORT std::string base32decode(std::string const& s);
TORRENT_EXPORT boost::optional<std::string> url_has_argument(
std::string const& url, std::string argument);
TORRENT_EXPORT std::string to_hex(std::string const& s);
}
#endif // TORRENT_ESCAPE_STRING_HPP_INCLUDED

View File

@ -0,0 +1,194 @@
/*
Copyright (c) 2006, 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.
*/
#ifndef TORRENT_EXTENSIONS_HPP_INCLUDED
#define TORRENT_EXTENSIONS_HPP_INCLUDED
#ifndef TORRENT_DISABLE_EXTENSIONS
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/shared_ptr.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include <vector>
#include "libtorrent/config.hpp"
#include "libtorrent/buffer.hpp"
namespace libtorrent
{
struct peer_plugin;
class bt_peer_connection;
struct peer_request;
class peer_connection;
class entry;
struct lazy_entry;
struct disk_buffer_holder;
struct bitfield;
struct TORRENT_EXPORT torrent_plugin
{
virtual ~torrent_plugin() {}
// throwing an exception closes the connection
// returning a 0 pointer is valid and will not add
// the peer_plugin to the peer_connection
virtual boost::shared_ptr<peer_plugin> new_connection(peer_connection*)
{ return boost::shared_ptr<peer_plugin>(); }
virtual void on_piece_pass(int index) {}
virtual void on_piece_failed(int index) {}
// called aproximately once every second
virtual void tick() {}
// if true is returned, it means the handler handled the event,
// and no other plugins will have their handlers called, and the
// default behavior will be skipped
virtual bool on_pause() { return false; }
virtual bool on_resume() { return false;}
// this is called when the initial checking of
// files is completed.
virtual void on_files_checked() {}
};
struct TORRENT_EXPORT peer_plugin
{
virtual ~peer_plugin() {}
// can add entries to the extension handshake
// this is not called for web seeds
virtual void add_handshake(entry&) {}
// throwing an exception from any of the handlers (except add_handshake)
// closes the connection
// this is called when the initial BT handshake is received. Returning false
// means that the other end doesn't support this extension and will remove
// it from the list of plugins.
// this is not called for web seeds
virtual bool on_handshake(char const* reserved_bits) { return true; }
// called when the extension handshake from the other end is received
// if this returns false, it means that this extension isn't
// supported by this peer. It will result in this peer_plugin
// being removed from the peer_connection and destructed.
// this is not called for web seeds
virtual bool on_extension_handshake(lazy_entry const& h) { return true; }
// returning true from any of the message handlers
// indicates that the plugin has handeled the message.
// it will break the plugin chain traversing and not let
// anyone else handle the message, including the default
// handler.
virtual bool on_choke()
{ return false; }
virtual bool on_unchoke()
{ return false; }
virtual bool on_interested()
{ return false; }
virtual bool on_not_interested()
{ return false; }
virtual bool on_have(int index)
{ return false; }
virtual bool on_bitfield(bitfield const& bitfield)
{ return false; }
virtual bool on_have_all()
{ return false; }
virtual bool on_have_none()
{ return false; }
virtual bool on_allowed_fast(int index)
{ return false; }
virtual bool on_request(peer_request const& req)
{ return false; }
virtual bool on_piece(peer_request const& piece, disk_buffer_holder& data)
{ return false; }
virtual bool on_cancel(peer_request const& req)
{ return false; }
virtual bool on_reject(peer_request const& req)
{ return false; }
virtual bool on_suggest(int index)
{ return false; }
// called when an extended message is received. If returning true,
// the message is not processed by any other plugin and if false
// is returned the next plugin in the chain will receive it to
// be able to handle it
// this is not called for web seeds
virtual bool on_extended(int length
, int msg, buffer::const_interval body)
{ return false; }
// this is not called for web seeds
virtual bool on_unknown_message(int length, int msg
, buffer::const_interval body)
{ return false; }
// called when a piece that this peer participated in either
// fails or passes the hash_check
virtual void on_piece_pass(int index) {}
virtual void on_piece_failed(int index) {}
// called aproximately once every second
virtual void tick() {}
// called each time a request message is to be sent. If true
// is returned, the original request message won't be sent and
// no other plugin will have this function called.
virtual bool write_request(peer_request const& r) { return false; }
};
}
#endif
#endif // TORRENT_EXTENSIONS_HPP_INCLUDED

View File

@ -0,0 +1,54 @@
/*
Copyright (c) 2006, 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.
*/
#ifndef TORRENT_LOGGER_HPP_INCLUDED
#define TORRENT_LOGGER_HPP_INCLUDED
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/shared_ptr.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
namespace libtorrent
{
struct torrent_plugin;
class torrent;
boost::shared_ptr<torrent_plugin> create_logger_plugin(torrent*);
}
#endif // TORRENT_LOGGER_HPP_INCLUDED

View File

@ -0,0 +1,55 @@
/*
Copyright (c) 2006, 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.
*/
#ifndef TORRENT_METADATA_TRANSFER_HPP_INCLUDED
#define TORRENT_METADATA_TRANSFER_HPP_INCLUDED
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/shared_ptr.hpp>
#include "libtorrent/config.hpp"
#ifdef _MSC_VER
#pragma warning(pop)
#endif
namespace libtorrent
{
struct torrent_plugin;
class torrent;
TORRENT_EXPORT boost::shared_ptr<torrent_plugin> create_metadata_plugin(torrent*, void*);
}
#endif // TORRENT_METADATA_TRANSFER_HPP_INCLUDED

View File

@ -0,0 +1,55 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_SMART_BAN_HPP_INCLUDED
#define TORRENT_SMART_BAN_HPP_INCLUDED
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/shared_ptr.hpp>
#include "libtorrent/config.hpp"
#ifdef _MSC_VER
#pragma warning(pop)
#endif
namespace libtorrent
{
struct torrent_plugin;
class torrent;
TORRENT_EXPORT boost::shared_ptr<torrent_plugin> create_smart_ban_plugin(torrent*, void*);
}
#endif // TORRENT_SMART_BAN_HPP_INCLUDED

View File

@ -0,0 +1,55 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_UT_METADATA_HPP_INCLUDED
#define TORRENT_UT_METADATA_HPP_INCLUDED
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/shared_ptr.hpp>
#include "libtorrent/config.hpp"
#ifdef _MSC_VER
#pragma warning(pop)
#endif
namespace libtorrent
{
struct torrent_plugin;
class torrent;
TORRENT_EXPORT boost::shared_ptr<torrent_plugin> create_ut_metadata_plugin(torrent*, void*);
}
#endif // TORRENT_UT_METADATA_HPP_INCLUDED

View File

@ -0,0 +1,54 @@
/*
Copyright (c) 2006, MassaRoddel
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.
*/
#ifndef TORRENT_UT_PEX_EXTENSION_HPP_INCLUDED
#define TORRENT_UT_PEX_EXTENSION_HPP_INCLUDED
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/shared_ptr.hpp>
#include "libtorrent/config.hpp"
#ifdef _MSC_VER
#pragma warning(pop)
#endif
namespace libtorrent
{
struct torrent_plugin;
class torrent;
TORRENT_EXPORT boost::shared_ptr<torrent_plugin> create_ut_pex_plugin(torrent*, void*);
}
#endif // TORRENT_UT_PEX_EXTENSION_HPP_INCLUDED

View File

@ -0,0 +1,130 @@
/*
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.
*/
#ifndef TORRENT_FILE_HPP_INCLUDED
#define TORRENT_FILE_HPP_INCLUDED
#include <memory>
#include <string>
#include <vector>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/noncopyable.hpp>
#include <boost/filesystem/path.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp"
namespace libtorrent
{
namespace fs = boost::filesystem;
class TORRENT_EXPORT file: public boost::noncopyable
{
public:
class seek_mode
{
friend class file;
private:
seek_mode(int v): m_val(v) {}
int m_val;
};
static const seek_mode begin;
static const seek_mode end;
class open_mode
{
friend class file;
public:
open_mode(): m_mask(0) {}
open_mode operator|(open_mode m) const
{ return open_mode(m.m_mask | m_mask); }
open_mode operator&(open_mode m) const
{ return open_mode(m.m_mask & m_mask); }
open_mode operator|=(open_mode m)
{
m_mask |= m.m_mask;
return *this;
}
bool operator==(open_mode m) const { return m_mask == m.m_mask; }
bool operator!=(open_mode m) const { return m_mask != m.m_mask; }
private:
open_mode(int val): m_mask(val) {}
int m_mask;
};
static const open_mode in;
static const open_mode out;
file();
file(fs::path const& p, open_mode m);
~file();
bool open(fs::path const& p, open_mode m);
void close();
bool set_size(size_type size);
size_type write(const char*, size_type num_bytes);
size_type read(char*, size_type num_bytes);
size_type seek(size_type pos, seek_mode m = begin);
size_type tell();
std::string const& error() const;
private:
struct impl;
const std::auto_ptr<impl> m_impl;
};
}
#endif // TORRENT_FILE_HPP_INCLUDED

View File

@ -0,0 +1,103 @@
/*
Copyright (c) 2006, 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.
*/
#ifndef TORRENT_FILE_POOL_HPP
#define TORRENT_FILE_POOL_HPP
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/filesystem/path.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/file.hpp"
#include "libtorrent/time.hpp"
namespace libtorrent
{
using boost::multi_index::multi_index_container;
using boost::multi_index::ordered_non_unique;
using boost::multi_index::ordered_unique;
using boost::multi_index::indexed_by;
using boost::multi_index::member;
namespace fs = boost::filesystem;
struct TORRENT_EXPORT file_pool : boost::noncopyable
{
file_pool(int size = 40): m_size(size) {}
boost::shared_ptr<file> open_file(void* st, fs::path const& p
, file::open_mode m, std::string& error);
void release(void* st);
void release(fs::path const& p);
void resize(int size);
private:
int m_size;
struct lru_file_entry
{
lru_file_entry(): last_use(time_now()) {}
mutable boost::shared_ptr<file> file_ptr;
fs::path file_path;
void* key;
ptime last_use;
file::open_mode mode;
};
typedef multi_index_container<
lru_file_entry, indexed_by<
ordered_unique<member<lru_file_entry, fs::path
, &lru_file_entry::file_path> >
, ordered_non_unique<member<lru_file_entry, ptime
, &lru_file_entry::last_use> >
, ordered_non_unique<member<lru_file_entry, void*
, &lru_file_entry::key> >
>
> file_set;
file_set m_files;
boost::mutex m_mutex;
};
}
#endif

View File

@ -0,0 +1,146 @@
/*
Copyright (c) 2003-2008, 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.
*/
#ifndef TORRENT_FILE_STORAGE_HPP_INCLUDED
#define TORRENT_FILE_STORAGE_HPP_INCLUDED
#include <string>
#include <vector>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/filesystem/path.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/size_type.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/peer_request.hpp"
namespace libtorrent
{
namespace fs = boost::filesystem;
struct TORRENT_EXPORT file_entry
{
file_entry(): offset(0), size(0), file_base(0) {}
fs::path path;
size_type offset; // the offset of this file inside the torrent
size_type size; // the size of this file
// the offset in the file where the storage starts.
// This is always 0 unless parts of the torrent is
// compressed into a single file, such as a so-called part file.
size_type file_base;
};
struct TORRENT_EXPORT file_slice
{
int file_index;
size_type offset;
size_type size;
};
class TORRENT_EXPORT file_storage
{
friend class torrent_info;
public:
file_storage();
~file_storage() {}
bool is_valid() const { return m_piece_length > 0; }
void add_file(file_entry const& e);
void add_file(fs::path const& p, size_type size);
void rename_file(int index, std::string const& new_filename);
std::vector<file_slice> map_block(int piece, size_type offset
, int size) const;
peer_request map_file(int file, size_type offset, int size) const;
typedef std::vector<file_entry>::const_iterator iterator;
typedef std::vector<file_entry>::const_reverse_iterator reverse_iterator;
iterator begin() const { return m_files.begin(); }
iterator end() const { return m_files.end(); }
reverse_iterator rbegin() const { return m_files.rbegin(); }
reverse_iterator rend() const { return m_files.rend(); }
int num_files() const
{ return int(m_files.size()); }
file_entry const& at(int index) const
{
TORRENT_ASSERT(index >= 0 && index < int(m_files.size()));
return m_files[index];
}
size_type total_size() const { TORRENT_ASSERT(m_piece_length > 0); return m_total_size; }
void set_num_pieces(int n) { m_num_pieces = n; }
int num_pieces() const { TORRENT_ASSERT(m_piece_length > 0); return m_num_pieces; }
void set_piece_length(int l) { m_piece_length = l; }
int piece_length() const { TORRENT_ASSERT(m_piece_length > 0); return m_piece_length; }
int piece_size(int index) const;
void set_name(std::string const& n) { m_name = n; }
const std::string& name() const { TORRENT_ASSERT(m_piece_length > 0); return m_name; }
void swap(file_storage& ti)
{
using std::swap;
swap(ti.m_piece_length, m_piece_length);
swap(ti.m_files, m_files);
swap(ti.m_total_size, m_total_size);
swap(ti.m_num_pieces, m_num_pieces);
swap(ti.m_name, m_name);
}
private:
int m_piece_length;
// the list of files that this torrent consists of
std::vector<file_entry> m_files;
// the sum of all filesizes
size_type m_total_size;
// the number of pieces in the torrent
int m_num_pieces;
std::string m_name;
};
}
#endif // TORRENT_FILE_STORAGE_HPP_INCLUDED

View File

@ -0,0 +1,95 @@
/*
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.
*/
#ifndef TORRENT_FINGERPRINT_HPP_INCLUDED
#define TORRENT_FINGERPRINT_HPP_INCLUDED
#include <string>
#include <sstream>
#include "libtorrent/peer_id.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{
struct fingerprint
{
fingerprint(const char* id_string, int major, int minor, int revision, int tag)
: major_version(major)
, minor_version(minor)
, revision_version(revision)
, tag_version(tag)
{
TORRENT_ASSERT(id_string);
TORRENT_ASSERT(major >= 0);
TORRENT_ASSERT(minor >= 0);
TORRENT_ASSERT(revision >= 0);
TORRENT_ASSERT(tag >= 0);
TORRENT_ASSERT(std::strlen(id_string) == 2);
name[0] = id_string[0];
name[1] = id_string[1];
}
std::string to_string() const
{
std::stringstream s;
s << "-" << name[0] << name[1]
<< version_to_char(major_version)
<< version_to_char(minor_version)
<< version_to_char(revision_version)
<< version_to_char(tag_version) << "-";
return s.str();
}
char name[2];
int major_version;
int minor_version;
int revision_version;
int tag_version;
private:
char version_to_char(int v) const
{
if (v >= 0 && v < 10) return '0' + v;
else if (v >= 10) return 'A' + (v - 10);
TORRENT_ASSERT(false);
return '0';
}
};
}
#endif // TORRENT_FINGERPRINT_HPP_INCLUDED

View File

@ -0,0 +1,43 @@
/*
Copyright (c) 2007, 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.
*/
namespace libtorrent
{
TORRENT_EXPORT bool inflate_gzip(
char const* in, int size
, std::vector<char>& buffer
, int maximum_size
, std::string& error);
}

View File

@ -0,0 +1,122 @@
/*
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.
*/
#ifndef TORRENT_HASHER_HPP_INCLUDED
#define TORRENT_HASHER_HPP_INCLUDED
#include <boost/cstdint.hpp>
#include "libtorrent/peer_id.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#include "zlib.h"
#ifdef TORRENT_USE_OPENSSL
extern "C"
{
#include <openssl/sha.h>
}
#else
// from sha1.cpp
struct TORRENT_EXPORT SHA_CTX
{
boost::uint32_t state[5];
boost::uint32_t count[2];
boost::uint8_t buffer[64];
};
TORRENT_EXPORT void SHA1_Init(SHA_CTX* context);
TORRENT_EXPORT void SHA1_Update(SHA_CTX* context, boost::uint8_t const* data, boost::uint32_t len);
TORRENT_EXPORT void SHA1_Final(boost::uint8_t* digest, SHA_CTX* context);
#endif
namespace libtorrent
{
class adler32_crc
{
public:
adler32_crc(): m_adler(adler32(0, 0, 0)) {}
void update(const char* data, int len)
{
TORRENT_ASSERT(data != 0);
TORRENT_ASSERT(len > 0);
m_adler = adler32(m_adler, (const Bytef*)data, len);
}
unsigned long final() const { return m_adler; }
void reset() { m_adler = adler32(0, 0, 0); }
private:
unsigned long m_adler;
};
class hasher
{
public:
hasher() { SHA1_Init(&m_context); }
hasher(const char* data, int len)
{
SHA1_Init(&m_context);
TORRENT_ASSERT(data != 0);
TORRENT_ASSERT(len > 0);
SHA1_Update(&m_context, reinterpret_cast<unsigned char const*>(data), len);
}
void update(const char* data, int len)
{
TORRENT_ASSERT(data != 0);
TORRENT_ASSERT(len > 0);
SHA1_Update(&m_context, reinterpret_cast<unsigned char const*>(data), len);
}
sha1_hash final()
{
sha1_hash digest;
SHA1_Final(digest.begin(), &m_context);
return digest;
}
void reset() { SHA1_Init(&m_context); }
private:
SHA_CTX m_context;
};
}
#endif // TORRENT_HASHER_HPP_INCLUDED

View File

@ -0,0 +1,209 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_HTTP_CONNECTION
#define TORRENT_HTTP_CONNECTION
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/noncopyable.hpp>
#include <vector>
#include <list>
#include <string>
#include "libtorrent/socket.hpp"
#include "libtorrent/http_parser.hpp"
#include "libtorrent/time.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/socket_type.hpp"
#include "libtorrent/session_settings.hpp"
#ifdef TORRENT_USE_OPENSSL
#include "libtorrent/ssl_stream.hpp"
#include "libtorrent/variant_stream.hpp"
#endif
namespace libtorrent
{
struct http_connection;
class connection_queue;
typedef boost::function<void(error_code const&
, http_parser const&, char const* data, int size, http_connection&)> http_handler;
typedef boost::function<void(http_connection&)> http_connect_handler;
// TODO: add bind interface
// when bottled, the last two arguments to the handler
// will always be 0
struct http_connection : boost::enable_shared_from_this<http_connection>, boost::noncopyable
{
http_connection(io_service& ios, connection_queue& cc
, http_handler const& handler, bool bottled = true
, http_connect_handler const& ch = http_connect_handler())
: m_sock(ios)
, m_read_pos(0)
, m_resolver(ios)
, m_handler(handler)
, m_connect_handler(ch)
, m_timer(ios)
, m_last_receive(time_now())
, m_bottled(bottled)
, m_called(false)
, m_rate_limit(0)
, m_download_quota(0)
, m_limiter_timer_active(false)
, m_limiter_timer(ios)
, m_redirects(5)
, m_connection_ticket(-1)
, m_cc(cc)
, m_ssl(false)
, m_priority(0)
, m_abort(false)
{
TORRENT_ASSERT(!m_handler.empty());
}
void rate_limit(int limit);
int rate_limit() const
{ return m_rate_limit; }
std::string sendbuffer;
void get(std::string const& url, time_duration timeout = seconds(30)
, int prio = 0, proxy_settings const* ps = 0, int handle_redirects = 5
, std::string const& user_agent = "", address const& bind_addr = address_v4::any());
void start(std::string const& hostname, std::string const& port
, time_duration timeout, int prio = 0, proxy_settings const* ps = 0
, bool ssl = false, int handle_redirect = 5
, address const& bind_addr = address_v4::any());
void close();
#ifdef TORRENT_USE_OPENSSL
variant_stream<socket_type, ssl_stream<socket_type> > const& socket() const { return m_sock; }
#else
socket_type const& socket() const { return m_sock; }
#endif
private:
void on_resolve(error_code const& e
, tcp::resolver::iterator i);
void queue_connect();
void connect(int ticket, tcp::endpoint target_address);
void on_connect_timeout();
void on_connect(error_code const& e);
void on_write(error_code const& e);
void on_read(error_code const& e, std::size_t bytes_transferred);
static void on_timeout(boost::weak_ptr<http_connection> p
, error_code const& e);
void on_assign_bandwidth(error_code const& e);
void callback(error_code const& e, char const* data = 0, int size = 0);
std::vector<char> m_recvbuffer;
#ifdef TORRENT_USE_OPENSSL
variant_stream<socket_type, ssl_stream<socket_type> > m_sock;
#else
socket_type m_sock;
#endif
int m_read_pos;
tcp::resolver m_resolver;
http_parser m_parser;
http_handler m_handler;
http_connect_handler m_connect_handler;
deadline_timer m_timer;
time_duration m_timeout;
ptime m_last_receive;
// bottled means that the handler is called once, when
// everything is received (and buffered in memory).
// non bottled means that once the headers have been
// received, data is streamed to the handler
bool m_bottled;
// set to true the first time the handler is called
bool m_called;
std::string m_hostname;
std::string m_port;
std::string m_url;
std::list<tcp::endpoint> m_endpoints;
// the current download limit, in bytes per second
// 0 is unlimited.
int m_rate_limit;
// the number of bytes we are allowed to receive
int m_download_quota;
// only hand out new quota 4 times a second if the
// quota is 0. If it isn't 0 wait for it to reach
// 0 and continue to hand out quota at that time.
bool m_limiter_timer_active;
// the timer fires every 250 millisecond as long
// as all the quota was used.
deadline_timer m_limiter_timer;
// the number of redirects to follow (in sequence)
int m_redirects;
int m_connection_ticket;
connection_queue& m_cc;
// specifies whether or not the connection is
// configured to use a proxy
proxy_settings m_proxy;
// true if the connection is using ssl
bool m_ssl;
// the address to bind to. address_v4::any()
// means do not bind
address m_bind_addr;
// the priority we have in the connection queue.
// 0 is normal, 1 is high
int m_priority;
bool m_abort;
};
}
#endif

View File

@ -0,0 +1,111 @@
/*
Copyright (c) 2008, 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.
*/
#ifndef TORRENT_HTTP_PARSER_HPP_INCLUDED
#define TORRENT_HTTP_PARSER_HPP_INCLUDED
#include <map>
#include <string>
#include <utility>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/cstdint.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/lexical_cast.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/config.hpp"
#include "libtorrent/buffer.hpp"
#include "libtorrent/size_type.hpp"
namespace libtorrent
{
class http_parser
{
public:
http_parser();
std::string const& header(char const* key) const
{
static std::string empty;
std::map<std::string, std::string>::const_iterator i
= m_header.find(key);
if (i == m_header.end()) return empty;
return i->second;
}
std::string const& protocol() const { return m_protocol; }
int status_code() const { return m_status_code; }
std::string const& method() const { return m_method; }
std::string const& path() const { return m_path; }
std::string const& message() const { return m_server_message; }
buffer::const_interval get_body() const;
bool header_finished() const { return m_state == read_body; }
bool finished() const { return m_finished; }
boost::tuple<int, int> incoming(buffer::const_interval recv_buffer
, bool& error);
int body_start() const { return m_body_start_pos; }
size_type content_length() const { return m_content_length; }
void reset();
std::map<std::string, std::string> const& headers() const { return m_header; }
private:
int m_recv_pos;
int m_status_code;
std::string m_method;
std::string m_path;
std::string m_protocol;
std::string m_server_message;
size_type m_content_length;
enum { read_status, read_header, read_body, error_state } m_state;
std::map<std::string, std::string> m_header;
buffer::const_interval m_recv_buffer;
int m_body_start_pos;
bool m_finished;
};
}
#endif // TORRENT_HTTP_PARSER_HPP_INCLUDED

View File

@ -0,0 +1,102 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_HTTP_STREAM_HPP_INCLUDED
#define TORRENT_HTTP_STREAM_HPP_INCLUDED
#include "libtorrent/proxy_base.hpp"
namespace libtorrent {
class http_stream : public proxy_base
{
public:
explicit http_stream(io_service& io_service)
: proxy_base(io_service)
, m_no_connect(false)
{}
void set_no_connect(bool c) { m_no_connect = c; }
void set_username(std::string const& user
, std::string const& password)
{
m_user = user;
m_password = password;
}
typedef boost::function<void(error_code const&)> handler_type;
template <class Handler>
void async_connect(endpoint_type const& endpoint, Handler const& handler)
{
m_remote_endpoint = endpoint;
// the connect is split up in the following steps:
// 1. resolve name of proxy server
// 2. connect to proxy server
// 3. send HTTP CONNECT method and possibly username+password
// 4. read CONNECT response
// to avoid unnecessary copying of the handler,
// store it in a shaed_ptr
boost::shared_ptr<handler_type> h(new handler_type(handler));
tcp::resolver::query q(m_hostname
, boost::lexical_cast<std::string>(m_port));
m_resolver.async_resolve(q, boost::bind(
&http_stream::name_lookup, this, _1, _2, h));
}
private:
void name_lookup(error_code const& e, tcp::resolver::iterator i
, boost::shared_ptr<handler_type> h);
void connected(error_code const& e, boost::shared_ptr<handler_type> h);
void handshake1(error_code const& e, boost::shared_ptr<handler_type> h);
void handshake2(error_code const& e, boost::shared_ptr<handler_type> h);
// send and receive buffer
std::vector<char> m_buffer;
// proxy authentication
std::string m_user;
std::string m_password;
// this is true if the connection is HTTP based and
// want to talk directly to the proxy
bool m_no_connect;
};
}
#endif

View File

@ -0,0 +1,100 @@
/*
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.
*/
#ifndef TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED
#define TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED
#include <string>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/shared_ptr.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/peer_id.hpp"
#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/config.hpp"
namespace libtorrent
{
struct http_connection;
class entry;
class http_parser;
class connection_queue;
struct session_settings;
class TORRENT_EXPORT http_tracker_connection
: public tracker_connection
{
friend class tracker_manager;
public:
http_tracker_connection(
io_service& ios
, connection_queue& cc
, tracker_manager& man
, tracker_request const& req
, address bind_infc
, boost::weak_ptr<request_callback> c
, session_settings const& stn
, proxy_settings const& ps
, std::string const& password = "");
void close();
private:
boost::intrusive_ptr<http_tracker_connection> self()
{ return boost::intrusive_ptr<http_tracker_connection>(this); }
void on_response(error_code const& ec, http_parser const& parser
, char const* data, int size);
virtual void on_timeout() {}
void parse(int status_code, const entry& e);
bool extract_peer_info(const entry& e, peer_entry& ret);
tracker_manager& m_man;
boost::shared_ptr<http_connection> m_tracker_connection;
};
}
#endif // TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED

View File

@ -0,0 +1,58 @@
/*
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.
*/
#ifndef TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED
#define TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/optional.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/peer_id.hpp"
#include "libtorrent/fingerprint.hpp"
#include "libtorrent/config.hpp"
namespace libtorrent
{
TORRENT_EXPORT std::string identify_client(const peer_id& p);
TORRENT_EXPORT boost::optional<fingerprint> client_fingerprint(peer_id const& p);
}
#endif // TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED

View File

@ -0,0 +1,48 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_INSTANTIATE_CONNECTION
#define TORRENT_INSTANTIATE_CONNECTION
#include "libtorrent/socket_type.hpp"
#include <boost/shared_ptr.hpp>
namespace libtorrent
{
struct proxy_settings;
bool instantiate_connection(io_service& ios
, proxy_settings const& ps, socket_type& s);
}
#endif

View File

@ -0,0 +1,85 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_INTRUSIVE_PTR_BASE
#define TORRENT_INTRUSIVE_PTR_BASE
#include <boost/detail/atomic_count.hpp>
#include <boost/checked_delete.hpp>
#include <boost/intrusive_ptr.hpp>
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{
template<class T>
struct intrusive_ptr_base
{
intrusive_ptr_base(intrusive_ptr_base<T> const&)
: m_refs(0) {}
intrusive_ptr_base& operator=(intrusive_ptr_base const& rhs)
{ return *this; }
friend void intrusive_ptr_add_ref(intrusive_ptr_base<T> const* s)
{
TORRENT_ASSERT(s->m_refs >= 0);
TORRENT_ASSERT(s != 0);
++s->m_refs;
}
friend void intrusive_ptr_release(intrusive_ptr_base<T> const* s)
{
TORRENT_ASSERT(s->m_refs > 0);
TORRENT_ASSERT(s != 0);
if (--s->m_refs == 0)
boost::checked_delete(static_cast<T const*>(s));
}
boost::intrusive_ptr<T> self()
{ return boost::intrusive_ptr<T>((T*)this); }
boost::intrusive_ptr<const T> self() const
{ return boost::intrusive_ptr<const T>((T const*)this); }
int refcount() const { return m_refs; }
intrusive_ptr_base(): m_refs(0) {}
private:
// reference counter for intrusive_ptr
mutable boost::detail::atomic_count m_refs;
};
}
#endif

View File

@ -0,0 +1,78 @@
// Copyright Daniel Wallin 2004. Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef TORRENT_INVARIANT_ACCESS_HPP_INCLUDED
#define TORRENT_INVARIANT_ACCESS_HPP_INCLUDED
#include "libtorrent/assert.hpp"
namespace libtorrent
{
class invariant_access
{
public:
template<class T>
static void check_invariant(T const& self)
{
self.check_invariant();
}
};
template<class T>
void check_invariant(T const& x)
{
invariant_access::check_invariant(x);
}
struct invariant_checker {};
template<class T>
struct invariant_checker_impl : invariant_checker
{
invariant_checker_impl(T const& self_)
: self(self_)
{
try
{
check_invariant(self);
}
catch (...)
{
TORRENT_ASSERT(false);
}
}
~invariant_checker_impl()
{
try
{
check_invariant(self);
}
catch (...)
{
TORRENT_ASSERT(false);
}
}
T const& self;
};
template<class T>
invariant_checker_impl<T> make_invariant_checker(T const& x)
{
return invariant_checker_impl<T>(x);
}
}
#if !defined NDEBUG && !defined TORRENT_DISABLE_INVARIANT_CHECKS
#define INVARIANT_CHECK \
invariant_checker const& _invariant_check = make_invariant_checker(*this); \
(void)_invariant_check; \
do {} while (false)
#else
#define INVARIANT_CHECK do {} while (false)
#endif
#endif // TORRENT_INVARIANT_ACCESS_HPP_INCLUDED

View File

@ -0,0 +1,153 @@
/*
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.
*/
#ifndef TORRENT_IO_HPP_INCLUDED
#define TORRENT_IO_HPP_INCLUDED
#include <boost/cstdint.hpp>
#include <string>
namespace libtorrent
{
namespace detail
{
template <class T> struct type {};
// reads an integer from a byte stream
// in big endian byte order and converts
// it to native endianess
template <class T, class InIt>
inline T read_impl(InIt& start, type<T>)
{
T ret = 0;
for (int i = 0; i < (int)sizeof(T); ++i)
{
ret <<= 8;
ret |= static_cast<unsigned char>(*start);
++start;
}
return ret;
}
template <class T, class OutIt>
inline void write_impl(T val, OutIt& start)
{
for (int i = (int)sizeof(T)-1; i >= 0; --i)
{
*start = static_cast<unsigned char>((val >> (i * 8)) & 0xff);
++start;
}
}
// -- adaptors
template <class InIt>
boost::int64_t read_int64(InIt& start)
{ return read_impl(start, type<boost::int64_t>()); }
template <class InIt>
boost::uint64_t read_uint64(InIt& start)
{ return read_impl(start, type<boost::uint64_t>()); }
template <class InIt>
boost::uint32_t read_uint32(InIt& start)
{ return read_impl(start, type<boost::uint32_t>()); }
template <class InIt>
boost::int32_t read_int32(InIt& start)
{ return read_impl(start, type<boost::int32_t>()); }
template <class InIt>
boost::int16_t read_int16(InIt& start)
{ return read_impl(start, type<boost::int16_t>()); }
template <class InIt>
boost::uint16_t read_uint16(InIt& start)
{ return read_impl(start, type<boost::uint16_t>()); }
template <class InIt>
boost::int8_t read_int8(InIt& start)
{ return read_impl(start, type<boost::int8_t>()); }
template <class InIt>
boost::uint8_t read_uint8(InIt& start)
{ return read_impl(start, type<boost::uint8_t>()); }
template <class OutIt>
void write_uint64(boost::uint64_t val, OutIt& start)
{ write_impl(val, start); }
template <class OutIt>
void write_int64(boost::int64_t val, OutIt& start)
{ write_impl(val, start); }
template <class OutIt>
void write_uint32(boost::uint32_t val, OutIt& start)
{ write_impl(val, start); }
template <class OutIt>
void write_int32(boost::int32_t val, OutIt& start)
{ write_impl(val, start); }
template <class OutIt>
void write_uint16(boost::uint16_t val, OutIt& start)
{ write_impl(val, start); }
template <class OutIt>
void write_int16(boost::int16_t val, OutIt& start)
{ write_impl(val, start); }
template <class OutIt>
void write_uint8(boost::uint8_t val, OutIt& start)
{ write_impl(val, start); }
template <class OutIt>
void write_int8(boost::int8_t val, OutIt& start)
{ write_impl(val, start); }
inline void write_string(std::string const& str, char*& start)
{
std::copy(str.begin(), str.end(), start);
start += str.size();
}
template <class OutIt>
void write_string(std::string const& str, OutIt& start)
{
std::copy(str.begin(), str.end(), start);
}
}
}
#endif // TORRENT_IO_HPP_INCLUDED

View File

@ -0,0 +1,317 @@
/*
Copyright (c) 2005, 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.
*/
#ifndef TORRENT_IP_FILTER_HPP
#define TORRENT_IP_FILTER_HPP
#include <set>
#include <iostream>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/limits.hpp>
#include <boost/utility.hpp>
#include <boost/tuple/tuple.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/config.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{
inline bool operator<=(address const& lhs
, address const& rhs)
{
return lhs < rhs || lhs == rhs;
}
template <class Addr>
struct ip_range
{
Addr first;
Addr last;
int flags;
};
namespace detail
{
template<class Addr>
Addr zero()
{
Addr zero;
std::fill(zero.begin(), zero.end(), 0);
return zero;
}
template<>
inline boost::uint16_t zero<boost::uint16_t>() { return 0; }
template<class Addr>
Addr plus_one(Addr const& a)
{
Addr tmp(a);
typedef typename Addr::reverse_iterator iter;
for (iter i = tmp.rbegin()
, end(tmp.rend()); i != end; ++i)
{
if (*i < (std::numeric_limits<typename iter::value_type>::max)())
{
*i += 1;
break;
}
*i = 0;
}
return tmp;
}
inline boost::uint16_t plus_one(boost::uint16_t val) { return val + 1; }
template<class Addr>
Addr minus_one(Addr const& a)
{
Addr tmp(a);
typedef typename Addr::reverse_iterator iter;
for (iter i = tmp.rbegin()
, end(tmp.rend()); i != end; ++i)
{
if (*i > 0)
{
*i -= 1;
break;
}
*i = (std::numeric_limits<typename iter::value_type>::max)();
}
return tmp;
}
inline boost::uint16_t minus_one(boost::uint16_t val) { return val - 1; }
template<class Addr>
Addr max_addr()
{
Addr tmp;
std::fill(tmp.begin(), tmp.end()
, (std::numeric_limits<typename Addr::value_type>::max)());
return Addr(tmp);
}
template<>
inline boost::uint16_t max_addr<boost::uint16_t>()
{ return (std::numeric_limits<boost::uint16_t>::max)(); }
// this is the generic implementation of
// a filter for a specific address type.
// it works with IPv4 and IPv6
template<class Addr>
class filter_impl
{
public:
filter_impl()
{
// make the entire ip-range non-blocked
m_access_list.insert(range(zero<Addr>(), 0));
}
void add_rule(Addr first, Addr last, int flags)
{
using boost::next;
using boost::prior;
TORRENT_ASSERT(!m_access_list.empty());
TORRENT_ASSERT(first < last || first == last);
typename range_t::iterator i = m_access_list.upper_bound(first);
typename range_t::iterator j = m_access_list.upper_bound(last);
if (i != m_access_list.begin()) --i;
TORRENT_ASSERT(j != m_access_list.begin());
TORRENT_ASSERT(j != i);
int first_access = i->access;
int last_access = prior(j)->access;
if (i->start != first && first_access != flags)
{
i = m_access_list.insert(i, range(first, flags));
}
else if (i != m_access_list.begin() && prior(i)->access == flags)
{
--i;
first_access = i->access;
}
TORRENT_ASSERT(!m_access_list.empty());
TORRENT_ASSERT(i != m_access_list.end());
if (i != j) m_access_list.erase(next(i), j);
if (i->start == first)
{
// we can do this const-cast because we know that the new
// start address will keep the set correctly ordered
const_cast<Addr&>(i->start) = first;
const_cast<int&>(i->access) = flags;
}
else if (first_access != flags)
{
m_access_list.insert(i, range(first, flags));
}
if ((j != m_access_list.end()
&& minus_one(j->start) != last)
|| (j == m_access_list.end()
&& last != max_addr<Addr>()))
{
TORRENT_ASSERT(j == m_access_list.end() || last < minus_one(j->start));
if (last_access != flags)
j = m_access_list.insert(j, range(plus_one(last), last_access));
}
if (j != m_access_list.end() && j->access == flags) m_access_list.erase(j);
TORRENT_ASSERT(!m_access_list.empty());
}
int access(Addr const& addr) const
{
TORRENT_ASSERT(!m_access_list.empty());
typename range_t::const_iterator i = m_access_list.upper_bound(addr);
if (i != m_access_list.begin()) --i;
TORRENT_ASSERT(i != m_access_list.end());
TORRENT_ASSERT(i->start <= addr && (boost::next(i) == m_access_list.end()
|| addr < boost::next(i)->start));
return i->access;
}
template <class ExternalAddressType>
std::vector<ip_range<ExternalAddressType> > export_filter() const
{
std::vector<ip_range<ExternalAddressType> > ret;
ret.reserve(m_access_list.size());
for (typename range_t::const_iterator i = m_access_list.begin()
, end(m_access_list.end()); i != end;)
{
ip_range<ExternalAddressType> r;
r.first = ExternalAddressType(i->start);
r.flags = i->access;
++i;
if (i == end)
r.last = ExternalAddressType(max_addr<Addr>());
else
r.last = ExternalAddressType(minus_one(i->start));
ret.push_back(r);
}
return ret;
}
private:
struct range
{
range(Addr addr, int access = 0): start(addr), access(access) {}
bool operator<(range const& r) const
{ return start < r.start; }
bool operator<(Addr const& a) const
{ return start < a; }
Addr start;
// the end of the range is implicit
// and given by the next entry in the set
int access;
};
typedef std::set<range> range_t;
range_t m_access_list;
};
}
class TORRENT_EXPORT ip_filter
{
public:
enum access_flags
{
blocked = 1
};
// both addresses MUST be of the same type (i.e. both must
// be either IPv4 or both must be IPv6)
void add_rule(address first, address last, int flags);
int access(address const& addr) const;
typedef boost::tuple<std::vector<ip_range<address_v4> >
, std::vector<ip_range<address_v6> > > filter_tuple_t;
filter_tuple_t export_filter() const;
// void print() const;
private:
detail::filter_impl<address_v4::bytes_type> m_filter4;
detail::filter_impl<address_v6::bytes_type> m_filter6;
};
class TORRENT_EXPORT port_filter
{
public:
enum access_flags
{
blocked = 1
};
void add_rule(boost::uint16_t first, boost::uint16_t last, int flags);
int access(boost::uint16_t port) const;
private:
detail::filter_impl<boost::uint16_t> m_filter;
};
}
#endif

View File

@ -0,0 +1,117 @@
/*
Copyright (c) 2006, Arvid Norberg & Daniel Wallin
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.
*/
#ifndef CLOSEST_NODES_050323_HPP
#define CLOSEST_NODES_050323_HPP
#include <vector>
#include <libtorrent/kademlia/traversal_algorithm.hpp>
#include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/routing_table.hpp>
#include <libtorrent/kademlia/observer.hpp>
#include <libtorrent/kademlia/msg.hpp>
#include <boost/function.hpp>
namespace libtorrent { namespace dht
{
class rpc_manager;
// -------- closest nodes -----------
class closest_nodes : public traversal_algorithm
{
public:
typedef boost::function<
void(std::vector<node_entry> const&)
> done_callback;
static void initiate(
node_id target
, int branch_factor
, int max_results
, routing_table& table
, rpc_manager& rpc
, done_callback const& callback
);
private:
void done();
void invoke(node_id const& id, udp::endpoint addr);
closest_nodes(
node_id target
, int branch_factor
, int max_results
, routing_table& table
, rpc_manager& rpc
, done_callback const& callback
);
done_callback m_done_callback;
};
class closest_nodes_observer : public observer
{
public:
closest_nodes_observer(
boost::intrusive_ptr<traversal_algorithm> const& algorithm
, node_id self
, node_id target)
: observer(algorithm->allocator())
, m_algorithm(algorithm)
, m_target(target)
, m_self(self)
{}
~closest_nodes_observer();
void send(msg& p)
{
p.info_hash = m_target;
}
void timeout();
void reply(msg const&);
void abort() { m_algorithm = 0; }
private:
boost::intrusive_ptr<traversal_algorithm> m_algorithm;
node_id const m_target;
node_id const m_self;
};
} } // namespace libtorrent::dht
#endif // CLOSEST_NODES_050323_HPP

View File

@ -0,0 +1,173 @@
/*
Copyright (c) 2006, 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.
*/
#ifndef TORRENT_DISABLE_DHT
#ifndef TORRENT_DHT_TRACKER
#define TORRENT_DHT_TRACKER
#include <fstream>
#include <set>
#include <numeric>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#include <boost/optional.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/detail/atomic_count.hpp>
#include <boost/thread/mutex.hpp>
#include "libtorrent/kademlia/node.hpp"
#include "libtorrent/kademlia/node_id.hpp"
#include "libtorrent/kademlia/traversal_algorithm.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/session_status.hpp"
#include "libtorrent/udp_socket.hpp"
#include "libtorrent/socket.hpp"
namespace libtorrent { namespace dht
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(dht_tracker);
#endif
struct dht_tracker;
TORRENT_EXPORT void intrusive_ptr_add_ref(dht_tracker const*);
TORRENT_EXPORT void intrusive_ptr_release(dht_tracker const*);
struct dht_tracker
{
friend void intrusive_ptr_add_ref(dht_tracker const*);
friend void intrusive_ptr_release(dht_tracker const*);
dht_tracker(udp_socket& sock, dht_settings const& settings
, entry const& bootstrap);
void stop();
void add_node(udp::endpoint node);
void add_node(std::pair<std::string, int> const& node);
void add_router_node(std::pair<std::string, int> const& node);
entry state() const;
void announce(sha1_hash const& ih, int listen_port
, boost::function<void(std::vector<tcp::endpoint> const&
, sha1_hash const&)> f);
void dht_status(session_status& s);
// translate bittorrent kademlia message into the generic kademlia message
// used by the library
void on_receive(udp::endpoint const& ep, char const* pkt, int size);
void on_unreachable(udp::endpoint const& ep);
private:
boost::intrusive_ptr<dht_tracker> self()
{ return boost::intrusive_ptr<dht_tracker>(this); }
void on_name_lookup(error_code const& e
, udp::resolver::iterator host);
void on_router_name_lookup(error_code const& e
, udp::resolver::iterator host);
void connection_timeout(error_code const& e);
void refresh_timeout(error_code const& e);
void tick(error_code const& e);
void on_bootstrap();
void send_packet(msg const& m);
node_impl m_dht;
udp_socket& m_sock;
std::vector<char> m_send_buf;
ptime m_last_new_key;
deadline_timer m_timer;
deadline_timer m_connection_timer;
deadline_timer m_refresh_timer;
dht_settings const& m_settings;
int m_refresh_bucket;
// The mutex is used to abort the dht node
// it's only used to set m_abort to true
typedef boost::mutex mutex_t;
mutable mutex_t m_mutex;
bool m_abort;
// used to resolve hostnames for nodes
udp::resolver m_host_resolver;
// used to ignore abusive dht nodes
struct node_ban_entry
{
node_ban_entry(): count(0) {}
udp::endpoint src;
ptime limit;
int count;
};
enum { num_ban_nodes = 20 };
node_ban_entry m_ban_nodes[num_ban_nodes];
// reference counter for intrusive_ptr
mutable boost::detail::atomic_count m_refs;
#ifdef TORRENT_DHT_VERBOSE_LOGGING
int m_replies_sent[5];
int m_queries_received[5];
int m_replies_bytes_sent[5];
int m_queries_bytes_received[5];
int m_counter;
int m_announces;
int m_failed_announces;
int m_total_message_input;
int m_ut_message_input;
int m_lt_message_input;
int m_mp_message_input;
int m_gr_message_input;
int m_mo_message_input;
int m_total_in_bytes;
int m_total_out_bytes;
int m_queries_out_bytes;
#endif
};
}}
#endif
#endif

View File

@ -0,0 +1,125 @@
/*
Copyright (c) 2006, Arvid Norberg & Daniel Wallin
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.
*/
#ifndef FIND_DATA_050323_HPP
#define FIND_DATA_050323_HPP
#include <vector>
#include <libtorrent/kademlia/traversal_algorithm.hpp>
#include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/routing_table.hpp>
#include <libtorrent/kademlia/rpc_manager.hpp>
#include <libtorrent/kademlia/observer.hpp>
#include <libtorrent/kademlia/msg.hpp>
#include <boost/optional.hpp>
#include <boost/function.hpp>
namespace libtorrent { namespace dht
{
typedef std::vector<char> packet_t;
class rpc_manager;
// -------- find data -----------
class find_data : public traversal_algorithm
{
public:
typedef boost::function<void(msg const*)> done_callback;
static void initiate(
node_id target
, int branch_factor
, int max_results
, routing_table& table
, rpc_manager& rpc
, done_callback const& callback
);
void got_data(msg const* m);
private:
void done();
void invoke(node_id const& id, udp::endpoint addr);
find_data(
node_id target
, int branch_factor
, int max_results
, routing_table& table
, rpc_manager& rpc
, done_callback const& callback
);
done_callback m_done_callback;
boost::shared_ptr<packet_t> m_packet;
bool m_done;
};
class find_data_observer : public observer
{
public:
find_data_observer(
boost::intrusive_ptr<find_data> const& algorithm
, node_id self
, node_id target)
: observer(algorithm->allocator())
, m_algorithm(algorithm)
, m_target(target)
, m_self(self)
{}
~find_data_observer();
void send(msg& m)
{
m.reply = false;
m.message_id = messages::get_peers;
m.info_hash = m_target;
}
void timeout();
void reply(msg const&);
void abort() { m_algorithm = 0; }
private:
boost::intrusive_ptr<find_data> m_algorithm;
node_id const m_target;
node_id const m_self;
};
} } // namespace libtorrent::dht
#endif // FIND_DATA_050323_HPP

View File

@ -0,0 +1,146 @@
/*
Copyright (c) 2006, Arvid Norberg & Daniel Wallin
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.
*/
#ifndef TORRENT_LOGGING_HPP
#define TORRENT_LOGGING_HPP
#include <iostream>
#include <fstream>
namespace libtorrent { namespace dht
{
class log
{
public:
log(char const* id, std::ostream& stream)
: m_id(id)
, m_enabled(true)
, m_stream(stream)
{
}
char const* id() const
{
return m_id;
}
bool enabled() const
{
return m_enabled;
}
void enable(bool e)
{
m_enabled = e;
}
void flush() { m_stream.flush(); }
template<class T>
log& operator<<(T const& x)
{
m_stream << x;
return *this;
}
private:
char const* m_id;
bool m_enabled;
std::ostream& m_stream;
};
class log_event
{
public:
log_event(log& log)
: log_(log)
{
if (log_.enabled())
log_ << '[' << log.id() << "] ";
}
~log_event()
{
if (log_.enabled())
{
log_ << "\n";
log_.flush();
}
}
template<class T>
log_event& operator<<(T const& x)
{
log_ << x;
return *this;
}
operator bool() const
{
return log_.enabled();
}
private:
log& log_;
};
class inverted_log_event : public log_event
{
public:
inverted_log_event(log& log) : log_event(log) {}
operator bool() const
{
return !log_event::operator bool();
}
};
} } // namespace libtorrent::dht
#define TORRENT_DECLARE_LOG(name) \
libtorrent::dht::log& name ## _log()
#define TORRENT_DEFINE_LOG(name) \
libtorrent::dht::log& name ## _log() \
{ \
static std::ofstream log_file("dht.log", std::ios::app); \
static libtorrent::dht::log instance(#name, log_file); \
return instance; \
}
#define TORRENT_LOG(name) \
if (libtorrent::dht::inverted_log_event event_object__ = name ## _log()); \
else static_cast<log_event&>(event_object__)
#endif

View File

@ -0,0 +1,104 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef MSG_HPP
#define MSG_HPP
#include <string>
#include <libtorrent/kademlia/node_id.hpp>
#include "libtorrent/entry.hpp"
#if BOOST_VERSION < 103500
#include <asio/ip/udp.hpp>
#else
#include <boost/asio/ip/udp.hpp>
#endif
namespace libtorrent {
namespace dht {
typedef std::vector<char> packet_t;
namespace messages
{
enum { ping = 0, find_node = 1, get_peers = 2, announce_peer = 3, error = 4 };
char const* const ids[] = { "ping", "find_node", "get_peers", "announce_peer", "error" };
} // namespace messages
struct msg
{
msg() : reply(false), piggy_backed_ping(false)
, message_id(-1), port(0) {}
// true if this message is a reply
bool reply;
// true if this is a reply with a piggy backed ping
bool piggy_backed_ping;
// the kind if message
int message_id;
// if this is a reply, a copy of the transaction id
// from the request. If it's a request, a transaction
// id that should be sent back in the reply
std::string transaction_id;
// if this packet has a piggy backed ping, this
// is the transaction id of that ping
std::string ping_transaction_id;
// the node id of the process sending the message
node_id id;
// the address of the process sending or receiving
// the message.
udp::endpoint addr;
// if this is a nodes response, these are the nodes
typedef std::vector<node_entry> nodes_t;
nodes_t nodes;
typedef std::vector<tcp::endpoint> peers_t;
peers_t peers;
// similar to transaction_id but for write operations.
entry write_token;
// the info has for peer_requests, announce_peer
// and responses
node_id info_hash;
// port for announce_peer messages
int port;
// ERROR MESSAGES
int error_code;
std::string error_msg;
};
} }
#endif

View File

@ -0,0 +1,261 @@
/*
Copyright (c) 2006, 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.
*/
#ifndef NODE_HPP
#define NODE_HPP
#include <algorithm>
#include <map>
#include <set>
#include <libtorrent/kademlia/routing_table.hpp>
#include <libtorrent/kademlia/rpc_manager.hpp>
#include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/msg.hpp>
#include <libtorrent/io.hpp>
#include <libtorrent/session_settings.hpp>
#include <libtorrent/assert.hpp>
#include <boost/cstdint.hpp>
#include <boost/optional.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/ref.hpp>
#include "libtorrent/socket.hpp"
namespace libtorrent { namespace dht
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(node);
#endif
// this is the entry for every peer
// the timestamp is there to make it possible
// to remove stale peers
struct peer_entry
{
tcp::endpoint addr;
ptime added;
};
// this is a group. It contains a set of group members
struct torrent_entry
{
std::set<peer_entry> peers;
};
inline bool operator<(peer_entry const& lhs, peer_entry const& rhs)
{
return lhs.addr.address() == rhs.addr.address()
? lhs.addr.port() < rhs.addr.port()
: lhs.addr.address() < rhs.addr.address();
}
struct null_type {};
class announce_observer : public observer
{
public:
announce_observer(boost::pool<>& allocator
, sha1_hash const& info_hash
, int listen_port
, entry const& write_token)
: observer(allocator)
, m_info_hash(info_hash)
, m_listen_port(listen_port)
, m_token(write_token)
{}
void send(msg& m)
{
m.port = m_listen_port;
m.info_hash = m_info_hash;
m.write_token = m_token;
}
void timeout() {}
void reply(msg const&) {}
void abort() {}
private:
sha1_hash m_info_hash;
int m_listen_port;
entry m_token;
};
class get_peers_observer : public observer
{
public:
get_peers_observer(sha1_hash const& info_hash
, int listen_port
, rpc_manager& rpc
, boost::function<void(std::vector<tcp::endpoint> const&, sha1_hash const&)> f)
: observer(rpc.allocator())
, m_info_hash(info_hash)
, m_listen_port(listen_port)
, m_rpc(rpc)
, m_fun(f)
{}
void send(msg& m)
{
m.port = m_listen_port;
m.info_hash = m_info_hash;
}
void timeout() {}
void reply(msg const& r)
{
observer_ptr o(new (m_rpc.allocator().malloc()) announce_observer(
m_rpc.allocator(), m_info_hash, m_listen_port, r.write_token));
#ifndef NDEBUG
o->m_in_constructor = false;
#endif
m_rpc.invoke(messages::announce_peer, r.addr, o);
m_fun(r.peers, m_info_hash);
}
void abort() {}
private:
sha1_hash m_info_hash;
int m_listen_port;
rpc_manager& m_rpc;
boost::function<void(std::vector<tcp::endpoint> const&, sha1_hash const&)> m_fun;
};
class node_impl : boost::noncopyable
{
typedef std::map<node_id, torrent_entry> table_t;
public:
node_impl(boost::function<void(msg const&)> const& f
, dht_settings const& settings, boost::optional<node_id> node_id);
virtual ~node_impl() {}
void refresh(node_id const& id, boost::function0<void> f);
void bootstrap(std::vector<udp::endpoint> const& nodes
, boost::function0<void> f);
void find_node(node_id const& id, boost::function<
void(std::vector<node_entry> const&)> f);
void add_router_node(udp::endpoint router);
void unreachable(udp::endpoint const& ep);
void incoming(msg const& m);
void refresh();
void refresh_bucket(int bucket);
int bucket_size(int bucket);
typedef routing_table::iterator iterator;
iterator begin() const { return m_table.begin(); }
iterator end() const { return m_table.end(); }
typedef table_t::iterator data_iterator;
node_id const& nid() const { return m_id; }
boost::tuple<int, int> size() const{ return m_table.size(); }
size_type num_global_nodes() const
{ return m_table.num_global_nodes(); }
data_iterator begin_data() { return m_map.begin(); }
data_iterator end_data() { return m_map.end(); }
int data_size() const { return int(m_map.size()); }
#ifdef TORRENT_DHT_VERBOSE_LOGGING
void print_state(std::ostream& os) const
{ m_table.print_state(os); }
#endif
void announce(sha1_hash const& info_hash, int listen_port
, boost::function<void(std::vector<tcp::endpoint> const&
, sha1_hash const&)> f);
bool verify_token(msg const& m);
entry generate_token(msg const& m);
// the returned time is the delay until connection_timeout()
// should be called again the next time
time_duration connection_timeout();
time_duration refresh_timeout();
// generates a new secret number used to generate write tokens
void new_write_key();
// pings the given node, and adds it to
// the routing table if it respons and if the
// bucket is not full.
void add_node(udp::endpoint node);
void replacement_cache(bucket_t& nodes) const
{ m_table.replacement_cache(nodes); }
protected:
// is called when a find data request is received. Should
// return false if the data is not stored on this node. If
// the data is stored, it should be serialized into 'data'.
bool on_find(msg const& m, std::vector<tcp::endpoint>& peers) const;
// this is called when a store request is received. The data
// is store-parameters and the data to be stored.
void on_announce(msg const& m, msg& reply);
dht_settings const& m_settings;
// the maximum number of peers to send in a get_peers
// reply. Ordinary trackers usually limit this to 50.
// 50 => 6 * 50 = 250 bytes + packet overhead
int m_max_peers_reply;
private:
void incoming_request(msg const& h);
node_id m_id;
routing_table m_table;
rpc_manager m_rpc;
table_t m_map;
ptime m_last_tracker_tick;
// secret random numbers used to create write tokens
int m_secret[2];
};
} } // namespace libtorrent::dht
#endif // NODE_HPP

View File

@ -0,0 +1,76 @@
/*
Copyright (c) 2006, 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.
*/
#ifndef KADEMLIA_NODE_ENTRY_HPP
#define KADEMLIA_NODE_ENTRY_HPP
#include "libtorrent/kademlia/node_id.hpp"
#include "libtorrent/socket.hpp"
namespace libtorrent { namespace dht
{
struct node_entry
{
node_entry(node_id const& id_, udp::endpoint addr_)
: id(id_)
, addr(addr_)
, fail_count(0)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
first_seen = time_now();
#endif
}
node_entry(udp::endpoint addr_)
: id(0)
, addr(addr_)
, fail_count(0)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
first_seen = time_now();
#endif
}
node_id id;
udp::endpoint addr;
// the number of times this node has failed to
// respond in a row
int fail_count;
#ifdef TORRENT_DHT_VERBOSE_LOGGING
ptime first_seen;
#endif
};
} } // namespace libtorrent::dht
#endif

View File

@ -0,0 +1,62 @@
/*
Copyright (c) 2006, 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.
*/
#ifndef NODE_ID_HPP
#define NODE_ID_HPP
#include <algorithm>
#include <boost/cstdint.hpp>
#include "libtorrent/peer_id.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent { namespace dht
{
typedef libtorrent::big_number node_id;
// returns the distance between the two nodes
// using the kademlia XOR-metric
node_id distance(node_id const& n1, node_id const& n2);
// returns true if: distance(n1, ref) < distance(n2, ref)
bool compare_ref(node_id const& n1, node_id const& n2, node_id const& ref);
// returns n in: 2^n <= distance(n1, n2) < 2^(n+1)
// usefult for finding out which bucket a node belongs to
int distance_exp(node_id const& n1, node_id const& n2);
node_id generate_id();
} } // namespace libtorrent::dht
#endif // NODE_ID_HPP

View File

@ -0,0 +1,102 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef OBSERVER_HPP
#define OBSERVER_HPP
#include <boost/pool/pool.hpp>
#include <boost/detail/atomic_count.hpp>
#include <boost/intrusive_ptr.hpp>
namespace libtorrent {
namespace dht {
struct observer;
struct msg;
// defined in rpc_manager.cpp
TORRENT_EXPORT void intrusive_ptr_add_ref(observer const*);
TORRENT_EXPORT void intrusive_ptr_release(observer const*);
struct observer : boost::noncopyable
{
friend TORRENT_EXPORT void intrusive_ptr_add_ref(observer const*);
friend TORRENT_EXPORT void intrusive_ptr_release(observer const*);
observer(boost::pool<>& p)
: sent(time_now())
, pool_allocator(p)
, m_refs(0)
{
#ifndef NDEBUG
m_in_constructor = true;
#endif
}
virtual ~observer()
{
TORRENT_ASSERT(!m_in_constructor);
}
// these two callbacks lets the observer add
// information to the message before it's sent
virtual void send(msg& m) = 0;
// this is called when a reply is received
virtual void reply(msg const& m) = 0;
// this is called when no reply has been received within
// some timeout
virtual void timeout() = 0;
// if this is called the destructor should
// not invoke any new messages, and should
// only clean up. It means the rpc-manager
// is being destructed
virtual void abort() = 0;
udp::endpoint target_addr;
ptime sent;
#ifndef NDEBUG
bool m_in_constructor;
#endif
private:
boost::pool<>& pool_allocator;
// reference counter for intrusive_ptr
mutable boost::detail::atomic_count m_refs;
};
typedef boost::intrusive_ptr<observer> observer_ptr;
} }
#endif

View File

@ -0,0 +1,214 @@
/*
Copyright (c) 2006, Arvid Norberg & Daniel Wallin
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.
*/
#ifndef REFRESH_050324_HPP
#define REFRESH_050324_HPP
#include <vector>
#include <libtorrent/kademlia/traversal_algorithm.hpp>
#include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/observer.hpp>
#include <libtorrent/kademlia/msg.hpp>
#include <boost/function.hpp>
namespace libtorrent { namespace dht
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(refresh);
#endif
class routing_table;
class rpc_manager;
class refresh : public traversal_algorithm
{
public:
typedef boost::function<void()> done_callback;
template<class InIt>
static void initiate(
node_id target
, int branch_factor
, int max_active_pings
, int max_results
, routing_table& table
, InIt first
, InIt last
, rpc_manager& rpc
, done_callback const& callback
);
void ping_reply(node_id id);
void ping_timeout(node_id id, bool prevent_request = false);
private:
template<class InIt>
refresh(
node_id target
, int branch_factor
, int max_active_pings
, int max_results
, routing_table& table
, InIt first
, InIt last
, rpc_manager& rpc
, done_callback const& callback
);
void done();
void invoke(node_id const& id, udp::endpoint addr);
void invoke_pings_or_finish(bool prevent_request = false);
int m_max_active_pings;
int m_active_pings;
done_callback m_done_callback;
std::vector<result>::iterator m_leftover_nodes_iterator;
};
class refresh_observer : public observer
{
public:
refresh_observer(
boost::intrusive_ptr<refresh> const& algorithm
, node_id self
, node_id target)
: observer(algorithm->allocator())
, m_target(target)
, m_self(self)
, m_algorithm(algorithm)
{}
~refresh_observer();
void send(msg& m)
{
m.info_hash = m_target;
}
void timeout();
void reply(msg const& m);
void abort() { m_algorithm = 0; }
private:
node_id const m_target;
node_id const m_self;
boost::intrusive_ptr<refresh> m_algorithm;
};
class ping_observer : public observer
{
public:
ping_observer(
boost::intrusive_ptr<refresh> const& algorithm
, node_id self)
: observer(algorithm->allocator())
, m_self(self)
, m_algorithm(algorithm)
{}
~ping_observer();
void send(msg& p) {}
void timeout();
void reply(msg const& m);
void abort() { m_algorithm = 0; }
private:
node_id const m_self;
boost::intrusive_ptr<refresh> m_algorithm;
};
template<class InIt>
inline refresh::refresh(
node_id target
, int branch_factor
, int max_active_pings
, int max_results
, routing_table& table
, InIt first
, InIt last
, rpc_manager& rpc
, done_callback const& callback
)
: traversal_algorithm(
target
, branch_factor
, max_results
, table
, rpc
, first
, last
)
, m_max_active_pings(max_active_pings)
, m_active_pings(0)
, m_done_callback(callback)
{
boost::intrusive_ptr<refresh> self(this);
add_requests();
}
template<class InIt>
inline void refresh::initiate(
node_id target
, int branch_factor
, int max_active_pings
, int max_results
, routing_table& table
, InIt first
, InIt last
, rpc_manager& rpc
, done_callback const& callback
)
{
new refresh(
target
, branch_factor
, max_active_pings
, max_results
, table
, first
, last
, rpc
, callback
);
}
} } // namespace libtorrent::dht
#endif // REFRESH_050324_HPP

View File

@ -0,0 +1,250 @@
/*
Copyright (c) 2006, 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.
*/
#ifndef ROUTING_TABLE_HPP
#define ROUTING_TABLE_HPP
#include <vector>
#include <deque>
#include <boost/cstdint.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/utility.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/array.hpp>
#include <set>
#include <libtorrent/kademlia/logging.hpp>
#include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/node_entry.hpp>
#include <libtorrent/session_settings.hpp>
#include <libtorrent/size_type.hpp>
#include <libtorrent/assert.hpp>
namespace libtorrent { namespace dht
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(table);
#endif
typedef std::vector<node_entry> bucket_t;
// differences in the implementation from the description in
// the paper:
//
// * The routing table tree is not allocated dynamically, there
// are always 160 buckets.
// * Nodes are not marked as being stale, they keep a counter
// that tells how many times in a row they have failed. When
// a new node is to be inserted, the node that has failed
// the most times is replaced. If none of the nodes in the
// bucket has failed, then it is put in the replacement
// cache (just like in the paper).
class routing_table;
namespace aux
{
// Iterates over a flattened routing_table structure.
class routing_table_iterator
: public boost::iterator_facade<
routing_table_iterator
, node_entry const
, boost::forward_traversal_tag
>
{
public:
routing_table_iterator()
{
}
private:
friend class libtorrent::dht::routing_table;
friend class boost::iterator_core_access;
typedef boost::array<std::pair<bucket_t, bucket_t>, 160>::const_iterator
bucket_iterator_t;
routing_table_iterator(
bucket_iterator_t begin
, bucket_iterator_t end)
: m_bucket_iterator(begin)
, m_bucket_end(end)
, m_iterator(begin != end ? begin->first.begin() : bucket_t::const_iterator())
{
if (m_bucket_iterator == m_bucket_end) return;
while (m_iterator == m_bucket_iterator->first.end())
{
if (++m_bucket_iterator == m_bucket_end)
break;
m_iterator = m_bucket_iterator->first.begin();
}
}
bool equal(routing_table_iterator const& other) const
{
return m_bucket_iterator == other.m_bucket_iterator
&& (m_bucket_iterator == m_bucket_end
|| m_iterator == other.m_iterator);
}
void increment()
{
TORRENT_ASSERT(m_bucket_iterator != m_bucket_end);
++m_iterator;
while (m_iterator == m_bucket_iterator->first.end())
{
if (++m_bucket_iterator == m_bucket_end)
break;
m_iterator = m_bucket_iterator->first.begin();
}
}
node_entry const& dereference() const
{
TORRENT_ASSERT(m_bucket_iterator != m_bucket_end);
return *m_iterator;
}
bucket_iterator_t m_bucket_iterator;
bucket_iterator_t m_bucket_end;
bucket_t::const_iterator m_iterator;
};
} // namespace aux
class routing_table
{
public:
typedef aux::routing_table_iterator iterator;
typedef iterator const_iterator;
routing_table(node_id const& id, int bucket_size
, dht_settings const& settings);
void node_failed(node_id const& id);
// adds an endpoint that will never be added to
// the routing table
void add_router_node(udp::endpoint router);
// iterates over the router nodes added
typedef std::set<udp::endpoint>::const_iterator router_iterator;
router_iterator router_begin() const { return m_router_nodes.begin(); }
router_iterator router_end() const { return m_router_nodes.end(); }
// this function is called every time the node sees
// a sign of a node being alive. This node will either
// be inserted in the k-buckets or be moved to the top
// of its bucket.
bool node_seen(node_id const& id, udp::endpoint addr);
// returns time when the given bucket needs another refresh.
// if the given bucket is empty but there are nodes
// in a bucket closer to us, or if the bucket is non-empty and
// the time from the last activity is more than 15 minutes
ptime next_refresh(int bucket);
// fills the vector with the count nodes from our buckets that
// are nearest to the given id.
void find_node(node_id const& id, std::vector<node_entry>& l
, bool include_self, int count = 0);
// returns true if the given node would be placed in a bucket
// that is not full. If the node already exists in the table
// this function returns false
bool need_node(node_id const& id);
// this will set the given bucket's latest activity
// to the current time
void touch_bucket(int bucket);
int bucket_size(int bucket)
{
TORRENT_ASSERT(bucket >= 0 && bucket < 160);
return (int)m_buckets[bucket].first.size();
}
int bucket_size() const { return m_bucket_size; }
iterator begin() const;
iterator end() const;
boost::tuple<int, int> size() const;
size_type num_global_nodes() const;
// returns true if there are no working nodes
// in the routing table
bool need_bootstrap() const;
int num_active_buckets() const
{ return 160 - m_lowest_active_bucket + 1; }
void replacement_cache(bucket_t& nodes) const;
#ifdef TORRENT_DHT_VERBOSE_LOGGING
// used for debug and monitoring purposes. This will print out
// the state of the routing table to the given stream
void print_state(std::ostream& os) const;
#endif
private:
// constant called k in paper
int m_bucket_size;
dht_settings const& m_settings;
// 160 (k-bucket, replacement cache) pairs
typedef boost::array<std::pair<bucket_t, bucket_t>, 160> table_t;
table_t m_buckets;
// timestamps of the last activity in each bucket
typedef boost::array<ptime, 160> table_activity_t;
table_activity_t m_bucket_activity;
node_id m_id; // our own node id
// this is a set of all the endpoints that have
// been identified as router nodes. They will
// be used in searches, but they will never
// be added to the routing table.
std::set<udp::endpoint> m_router_nodes;
// this is the lowest bucket index with nodes in it
int m_lowest_active_bucket;
};
} } // namespace libtorrent::dht
#endif // ROUTING_TABLE_HPP

View File

@ -0,0 +1,141 @@
/*
Copyright (c) 2006, 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.
*/
#ifndef RPC_MANAGER_HPP
#define RPC_MANAGER_HPP
#include <vector>
#include <map>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <boost/cstdint.hpp>
#include <boost/array.hpp>
#include <boost/pool/pool.hpp>
#include <libtorrent/socket.hpp>
#include <libtorrent/entry.hpp>
#include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/logging.hpp>
#include <libtorrent/kademlia/node_entry.hpp>
#include <libtorrent/kademlia/observer.hpp>
#include "libtorrent/time.hpp"
namespace libtorrent { namespace dht
{
struct observer;
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(rpc);
#endif
struct null_observer : public observer
{
null_observer(boost::pool<>& allocator): observer(allocator) {}
virtual void reply(msg const&) {}
virtual void timeout() {}
virtual void send(msg&) {}
void abort() {}
};
class routing_table;
class rpc_manager
{
public:
typedef boost::function1<void, msg const&> fun;
typedef boost::function1<void, msg const&> send_fun;
rpc_manager(fun const& incoming_fun, node_id const& our_id
, routing_table& table, send_fun const& sf);
~rpc_manager();
void unreachable(udp::endpoint const& ep);
// returns true if the node needs a refresh
bool incoming(msg const&);
time_duration tick();
void invoke(int message_id, udp::endpoint target
, observer_ptr o);
void reply(msg& m);
void reply_with_ping(msg& m);
#ifndef NDEBUG
size_t allocation_size() const;
void check_invariant() const;
#endif
boost::pool<>& allocator() const
{ return m_pool_allocator; }
private:
enum { max_transactions = 2048 };
unsigned int new_transaction_id(observer_ptr o);
void update_oldest_transaction_id();
boost::uint32_t calc_connection_id(udp::endpoint addr);
mutable boost::pool<> m_pool_allocator;
typedef boost::array<observer_ptr, max_transactions>
transactions_t;
transactions_t m_transactions;
std::vector<observer_ptr> m_aborted_transactions;
// this is the next transaction id to be used
int m_next_transaction_id;
// this is the oldest transaction id still
// (possibly) in use. This is the transaction
// that will time out first, the one we are
// waiting for to time out
int m_oldest_transaction_id;
fun m_incoming;
send_fun m_send;
node_id m_our_id;
routing_table& m_table;
ptime m_timer;
node_id m_random_number;
bool m_destructing;
};
} } // namespace libtorrent::dht
#endif

View File

@ -0,0 +1,161 @@
/*
Copyright (c) 2006, Arvid Norberg & Daniel Wallin
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.
*/
#ifndef TRAVERSAL_ALGORITHM_050324_HPP
#define TRAVERSAL_ALGORITHM_050324_HPP
#include <vector>
#include <set>
#include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/routing_table.hpp>
#include <libtorrent/kademlia/logging.hpp>
#include <boost/noncopyable.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/pool/pool.hpp>
namespace libtorrent { namespace dht
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(traversal);
#endif
class rpc_manager;
// this class may not be instantiated as a stack object
class traversal_algorithm : boost::noncopyable
{
public:
void traverse(node_id const& id, udp::endpoint addr);
void finished(node_id const& id);
void failed(node_id const& id, bool prevent_request = false);
virtual ~traversal_algorithm() {}
boost::pool<>& allocator() const;
protected:
template<class InIt>
traversal_algorithm(
node_id target
, int branch_factor
, int max_results
, routing_table& table
, rpc_manager& rpc
, InIt start
, InIt end
);
void add_requests();
void add_entry(node_id const& id, udp::endpoint addr, unsigned char flags);
virtual void done() = 0;
virtual void invoke(node_id const& id, udp::endpoint addr) = 0;
struct result
{
result(node_id const& id, udp::endpoint addr, unsigned char f = 0)
: id(id), addr(addr), flags(f) {}
node_id id;
udp::endpoint addr;
enum { queried = 1, initial = 2, no_id = 4 };
unsigned char flags;
};
std::vector<result>::iterator last_iterator();
friend void intrusive_ptr_add_ref(traversal_algorithm* p)
{
p->m_ref_count++;
}
friend void intrusive_ptr_release(traversal_algorithm* p)
{
if (--p->m_ref_count == 0)
delete p;
}
int m_ref_count;
node_id m_target;
int m_branch_factor;
int m_max_results;
std::vector<result> m_results;
std::set<udp::endpoint> m_failed;
routing_table& m_table;
rpc_manager& m_rpc;
int m_invoke_count;
};
template<class InIt>
traversal_algorithm::traversal_algorithm(
node_id target
, int branch_factor
, int max_results
, routing_table& table
, rpc_manager& rpc
, InIt start // <- nodes to initiate traversal with
, InIt end
)
: m_ref_count(0)
, m_target(target)
, m_branch_factor(branch_factor)
, m_max_results(max_results)
, m_table(table)
, m_rpc(rpc)
, m_invoke_count(0)
{
using boost::bind;
for (InIt i = start; i != end; ++i)
{
add_entry(i->id, i->addr, result::initial);
}
// in case the routing table is empty, use the
// router nodes in the table
if (start == end)
{
for (routing_table::router_iterator i = table.router_begin()
, end(table.router_end()); i != end; ++i)
{
add_entry(node_id(0), *i, result::initial);
}
}
}
} } // namespace libtorrent::dht
#endif // TRAVERSAL_ALGORITHM_050324_HPP

View File

@ -0,0 +1,232 @@
/*
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.
*/
#ifndef TORRENT_LAZY_ENTRY_HPP_INCLUDED
#define TORRENT_LAZY_ENTRY_HPP_INCLUDED
#include <utility>
#include <vector>
#include "libtorrent/assert.hpp"
#include "libtorrent/size_type.hpp"
#include <iosfwd>
namespace libtorrent
{
struct lazy_entry;
char const* parse_int(char const* start, char const* end, char delimiter, boost::int64_t& val);
// return 0 = success
int lazy_bdecode(char const* start, char const* end, lazy_entry& ret, int depth_limit = 1000);
struct lazy_entry
{
enum entry_type_t
{
none_t, dict_t, list_t, string_t, int_t
};
lazy_entry() : m_type(none_t), m_begin(0), m_end(0)
{ m_data.start = 0; }
entry_type_t type() const { return m_type; }
// start points to the first decimal digit
// length is the number of digits
void construct_int(char const* start, int length)
{
TORRENT_ASSERT(m_type == none_t);
m_type = int_t;
m_data.start = start;
m_size = length;
m_begin = start - 1; // include 'i'
m_end = start + length + 1; // include 'e'
}
size_type int_value() const;
// string functions
// ================
void construct_string(char const* start, int length);
// the string is not null-terminated!
char const* string_ptr() const
{
TORRENT_ASSERT(m_type == string_t);
return m_data.start;
}
// this will return a null terminated string
// it will write to the source buffer!
char const* string_cstr() const
{
TORRENT_ASSERT(m_type == string_t);
const_cast<char*>(m_data.start)[m_size] = 0;
return m_data.start;
}
std::string string_value() const
{
TORRENT_ASSERT(m_type == string_t);
return std::string(m_data.start, m_size);
}
int string_length() const
{ return m_size; }
// dictionary functions
// ====================
void construct_dict(char const* begin)
{
TORRENT_ASSERT(m_type == none_t);
m_type = dict_t;
m_size = 0;
m_capacity = 0;
m_begin = begin;
}
lazy_entry* dict_append(char const* name);
lazy_entry* dict_find(char const* name);
lazy_entry const* dict_find(char const* name) const
{ return const_cast<lazy_entry*>(this)->dict_find(name); }
std::string dict_find_string_value(char const* name) const;
size_type dict_find_int_value(char const* name, size_type default_val = 0) const;
lazy_entry const* dict_find_dict(char const* name) const;
lazy_entry const* dict_find_list(char const* name) const;
std::pair<std::string, lazy_entry const*> dict_at(int i) const
{
TORRENT_ASSERT(m_type == dict_t);
TORRENT_ASSERT(i < m_size);
std::pair<char const*, lazy_entry> const& e = m_data.dict[i];
return std::make_pair(std::string(e.first, e.second.m_begin - e.first), &e.second);
}
int dict_size() const
{
TORRENT_ASSERT(m_type == dict_t);
return m_size;
}
// list functions
// ==============
void construct_list(char const* begin)
{
TORRENT_ASSERT(m_type == none_t);
m_type = list_t;
m_size = 0;
m_capacity = 0;
m_begin = begin;
}
lazy_entry* list_append();
lazy_entry* list_at(int i)
{
TORRENT_ASSERT(m_type == list_t);
TORRENT_ASSERT(i < m_size);
return &m_data.list[i];
}
lazy_entry const* list_at(int i) const
{ return const_cast<lazy_entry*>(this)->list_at(i); }
std::string list_string_value_at(int i) const;
size_type list_int_value_at(int i, size_type default_val = 0) const;
int list_size() const
{
TORRENT_ASSERT(m_type == list_t);
return m_size;
}
// end points one byte passed last byte
void set_end(char const* end)
{
TORRENT_ASSERT(end > m_begin);
m_end = end;
}
void clear();
// releases ownership of any memory allocated
void release()
{
m_data.start = 0;
m_size = 0;
m_capacity = 0;
m_type = none_t;
}
~lazy_entry()
{ clear(); }
// returns pointers into the source buffer where
// this entry has its bencoded data
std::pair<char const*, int> data_section() const;
void swap(lazy_entry& e)
{
using std::swap;
swap(m_type, e.m_type);
swap(m_data.start, e.m_data.start);
swap(m_size, e.m_size);
swap(m_capacity, e.m_capacity);
swap(m_begin, e.m_begin);
swap(m_end, e.m_end);
}
private:
entry_type_t m_type;
union data_t
{
std::pair<char const*, lazy_entry>* dict;
lazy_entry* list;
char const* start;
} m_data;
int m_size; // if list or dictionary, the number of items
int m_capacity; // if list or dictionary, allocated number of items
// used for dictionaries and lists to record the range
// in the original buffer they are based on
char const* m_begin;
char const* m_end;
};
std::ostream& operator<<(std::ostream& os, lazy_entry const& e);
};
#endif

View File

@ -0,0 +1,98 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_LSD_HPP
#define TORRENT_LSD_HPP
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/broadcast_socket.hpp"
#include "libtorrent/intrusive_ptr_base.hpp"
#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
#include <fstream>
#endif
namespace libtorrent
{
typedef boost::function<void(tcp::endpoint, sha1_hash)> peer_callback_t;
class lsd : public intrusive_ptr_base<lsd>
{
public:
lsd(io_service& ios, address const& listen_interface
, peer_callback_t const& cb);
~lsd();
// void rebind(address const& listen_interface);
void announce(sha1_hash const& ih, int listen_port);
void close();
private:
void resend_announce(error_code const& e, std::string msg);
void on_announce(udp::endpoint const& from, char* buffer
, std::size_t bytes_transferred);
// void setup_receive();
peer_callback_t m_callback;
// current retry count
int m_retry_count;
// the udp socket used to send and receive
// multicast messages on
broadcast_socket m_socket;
// used to resend udp packets in case
// they time out
deadline_timer m_broadcast_timer;
bool m_disabled;
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
std::ofstream m_log;
#endif
};
}
#endif

View File

@ -0,0 +1,59 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_MAGNET_URI_HPP_INCLUDED
#define TORRENT_MAGNET_URI_HPP_INCLUDED
#include <string>
#include "libtorrent/config.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/session.hpp"
#include <boost/filesystem/path.hpp>
namespace libtorrent
{
namespace fs = boost::filesystem;
struct torrent_handle;
std::string TORRENT_EXPORT make_magnet_uri(torrent_handle const& handle);
torrent_handle TORRENT_EXPORT add_magnet_uri(session& ses, std::string const& uri
, fs::path const& save_path
, storage_mode_t storage_mode = storage_mode_sparse
, bool paused = false
, storage_constructor_type sc = default_storage_constructor
, void* userdata = 0);
}
#endif

View File

@ -0,0 +1,162 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_NATPMP_HPP
#define TORRENT_NATPMP_HPP
#include "libtorrent/socket.hpp"
#include "libtorrent/intrusive_ptr_base.hpp"
#include <boost/function.hpp>
#include <boost/thread/mutex.hpp>
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
#include <fstream>
#endif
namespace libtorrent
{
// int: port mapping index
// int: external port
// std::string: error message
typedef boost::function<void(int, int, std::string const&)> portmap_callback_t;
class natpmp : public intrusive_ptr_base<natpmp>
{
public:
natpmp(io_service& ios, address const& listen_interface, portmap_callback_t const& cb);
void rebind(address const& listen_interface);
// maps the ports, if a port is set to 0
// it will not be mapped
enum protocol_type { none = 0, udp = 1, tcp = 2 };
int add_mapping(protocol_type p, int external_port, int local_port);
void delete_mapping(int mapping_index);
void close();
private:
void update_mapping(int i);
void send_map_request(int i);
void resend_request(int i, error_code const& e);
void on_reply(error_code const& e
, std::size_t bytes_transferred);
void try_next_mapping(int i);
void update_expiration_timer();
void mapping_expired(error_code const& e, int i);
void disable(char const* message);
struct mapping_t
{
enum action_t { action_none, action_add, action_delete };
mapping_t()
: action(action_none)
, local_port(0)
, external_port(0)
, protocol(none)
{}
// indicates that the mapping has changed
// and needs an update
int action;
// the time the port mapping will expire
ptime expires;
// the local port for this mapping. If this is set
// to 0, the mapping is not in use
int local_port;
// the external (on the NAT router) port
// for the mapping. This is the port we
// should announce to others
int external_port;
int protocol;
};
portmap_callback_t m_callback;
std::vector<mapping_t> m_mappings;
// the endpoint to the nat router
udp::endpoint m_nat_endpoint;
// this is the mapping that is currently
// being updated. It is -1 in case no
// mapping is being updated at the moment
int m_currently_mapping;
// current retry count
int m_retry_count;
// used to receive responses in
char m_response_buffer[16];
// the endpoint we received the message from
udp::endpoint m_remote;
// the udp socket used to communicate
// with the NAT router
datagram_socket m_socket;
// used to resend udp packets in case
// they time out
deadline_timer m_send_timer;
// timer used to refresh mappings
deadline_timer m_refresh_timer;
// the mapping index that will expire next
int m_next_refresh;
bool m_disabled;
bool m_abort;
typedef boost::mutex mutex_t;
mutex_t m_mutex;
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
std::ofstream m_log;
#endif
};
}
#endif

View File

@ -0,0 +1,59 @@
/*
Copyright (c) 2008, 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.
*/
#ifndef TORRENT_PARSE_URL_HPP_INCLUDED
#define TORRENT_PARSE_URL_HPP_INCLUDED
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/tuple/tuple.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include <string>
#include "libtorrent/config.hpp"
namespace libtorrent
{
TORRENT_EXPORT boost::tuple<std::string, std::string
, std::string, int, std::string, char const*>
parse_url_components(std::string url);
}
#endif

View File

@ -0,0 +1,127 @@
/*
Copyright (c) 2008, 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.
*/
#ifdef BOOST_BUILD_PCH_ENABLED
#include <algorithm>
#include <asio/ip/host_name.hpp>
#include <assert.h>
#include <bitset>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/date_time/gregorian/gregorian_types.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/date_time/posix_time/ptime.hpp>
#include <boost/detail/atomic_count.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/filesystem/convenience.hpp>
#include <boost/filesystem/exception.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/function.hpp>
#include <boost/integer_traits.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator_adaptors.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/limits.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/next_prior.hpp>
#include <boost/noncopyable.hpp>
#include <boost/optional.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
#include <boost/ref.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/static_assert.hpp>
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/utility.hpp>
#include <boost/version.hpp>
#include <boost/weak_ptr.hpp>
#include <cassert>
#include <cctype>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cwchar>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <limits>
#include <list>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stdexcept>
#include <string>
#include <typeinfo>
#include <utility>
#include <vector>
#include <zlib.h>
#ifdef __OBJC__
#define Protocol Protocol_
#endif
#include <asio/ip/tcp.hpp>
#include <asio/ip/udp.hpp>
#include <asio/io_service.hpp>
#include <asio/deadline_timer.hpp>
#include <asio/write.hpp>
#ifdef __OBJC__
#undef Protocol
#endif
#endif

View File

@ -0,0 +1,124 @@
/*
Copyright (c) 2007, Un Shyam
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.
*/
#ifndef TORRENT_DISABLE_ENCRYPTION
#ifndef TORRENT_PE_CRYPTO_HPP_INCLUDED
#define TORRENT_PE_CRYPTO_HPP_INCLUDED
#include <openssl/dh.h>
#include <openssl/engine.h>
#include <openssl/rc4.h>
#include "libtorrent/peer_id.hpp" // For sha1_hash
#include "libtorrent/assert.hpp"
namespace libtorrent
{
class dh_key_exchange
{
public:
dh_key_exchange();
~dh_key_exchange();
bool good() const { return m_dh; }
// Get local public key, always 96 bytes
char const* get_local_key() const;
// read remote_pubkey, generate and store shared secret in
// m_dh_secret.
int compute_secret(const char* remote_pubkey);
const char* get_secret() const;
private:
int get_local_key_size() const
{
TORRENT_ASSERT(m_dh);
return BN_num_bytes(m_dh->pub_key);
}
DH* m_dh;
char m_dh_local_key[96];
char m_dh_secret[96];
};
class RC4_handler // Non copyable
{
public:
// Input longkeys must be 20 bytes
RC4_handler(const sha1_hash& rc4_local_longkey,
const sha1_hash& rc4_remote_longkey)
{
RC4_set_key(&m_local_key, 20,
reinterpret_cast<unsigned char const*>(rc4_local_longkey.begin()));
RC4_set_key(&m_remote_key, 20,
reinterpret_cast<unsigned char const*>(rc4_remote_longkey.begin()));
// Discard first 1024 bytes
char buf[1024];
encrypt(buf, 1024);
decrypt(buf, 1024);
};
~RC4_handler() {};
void encrypt(char* pos, int len)
{
TORRENT_ASSERT(len >= 0);
TORRENT_ASSERT(pos);
RC4 (&m_local_key, len, reinterpret_cast<unsigned char const*>(pos),
reinterpret_cast<unsigned char*>(pos));
}
void decrypt(char* pos, int len)
{
TORRENT_ASSERT(len >= 0);
TORRENT_ASSERT(pos);
RC4 (&m_remote_key, len, reinterpret_cast<unsigned char const*>(pos),
reinterpret_cast<unsigned char*>(pos));
}
private:
RC4_KEY m_local_key; // Key to encrypt outgoing data
RC4_KEY m_remote_key; // Key to decrypt incoming data
};
} // namespace libtorrent
#endif // TORRENT_PE_CRYPTO_HPP_INCLUDED
#endif // TORRENT_DISABLE_ENCRYPTION

View File

@ -0,0 +1,63 @@
/*
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.
*/
#ifndef TORRENT_PEER_HPP_INCLUDED
#define TORRENT_PEER_HPP_INCLUDED
#include <string>
#include "libtorrent/peer_id.hpp"
namespace libtorrent
{
struct TORRENT_EXPORT peer_entry
{
std::string ip;
int port;
peer_id pid;
bool operator==(const peer_entry& p) const
{
return pid == p.pid;
}
bool operator<(const peer_entry& p) const
{
return pid < p.pid;
}
};
}
#endif // TORRENT_PEER_HPP_INCLUDED

View File

@ -0,0 +1,845 @@
/*
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.
*/
#ifndef TORRENT_PEER_CONNECTION_HPP_INCLUDED
#define TORRENT_PEER_CONNECTION_HPP_INCLUDED
#include <ctime>
#include <algorithm>
#include <vector>
#include <deque>
#include <string>
#include "libtorrent/debug.hpp"
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/smart_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <boost/array.hpp>
#include <boost/optional.hpp>
#include <boost/cstdint.hpp>
#include <boost/pool/pool.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/buffer.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/storage.hpp"
#include "libtorrent/stat.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/peer_request.hpp"
#include "libtorrent/piece_block_progress.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/session.hpp"
#include "libtorrent/bandwidth_limit.hpp"
#include "libtorrent/policy.hpp"
#include "libtorrent/socket_type.hpp"
#include "libtorrent/intrusive_ptr_base.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/chained_buffer.hpp"
#include "libtorrent/disk_buffer_holder.hpp"
#include "libtorrent/bitfield.hpp"
namespace libtorrent
{
class torrent;
struct peer_plugin;
namespace detail
{
struct session_impl;
}
struct TORRENT_EXPORT protocol_error: std::runtime_error
{
protocol_error(const std::string& msg): std::runtime_error(msg) {};
};
class TORRENT_EXPORT peer_connection
: public intrusive_ptr_base<peer_connection>
, public boost::noncopyable
{
friend class invariant_access;
public:
enum channels
{
upload_channel,
download_channel,
num_channels
};
// this is the constructor where the we are the active part.
// The peer_conenction should handshake and verify that the
// other end has the correct id
peer_connection(
aux::session_impl& ses
, boost::weak_ptr<torrent> t
, boost::shared_ptr<socket_type> s
, tcp::endpoint const& remote
, policy::peer* peerinfo);
// with this constructor we have been contacted and we still don't
// know which torrent the connection belongs to
peer_connection(
aux::session_impl& ses
, boost::shared_ptr<socket_type> s
, tcp::endpoint const& remote
, policy::peer* peerinfo);
// this function is called after it has been constructed and properly
// reference counted. It is safe to call self() in this function
// and schedule events with references to itself (that is not safe to
// do in the constructor).
virtual void start();
virtual ~peer_connection();
void set_peer_info(policy::peer* pi)
{ m_peer_info = pi; }
policy::peer* peer_info_struct() const
{ return m_peer_info; }
enum peer_speed_t { slow, medium, fast };
peer_speed_t peer_speed();
void send_allowed_set();
#ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::shared_ptr<peer_plugin>);
#endif
// this function is called once the torrent associated
// with this peer connection has retrieved the meta-
// data. If the torrent was spawned with metadata
// this is called from the constructor.
void init();
// this is called when the metadata is retrieved
// and the files has been checked
virtual void on_metadata() {}
void set_upload_limit(int limit);
void set_download_limit(int limit);
int upload_limit() const { return m_upload_limit; }
int download_limit() const { return m_download_limit; }
int prefer_whole_pieces() const
{
if (on_parole()) return 1;
return m_prefer_whole_pieces;
}
bool on_parole() const
{ return peer_info_struct() && peer_info_struct()->on_parole; }
void prefer_whole_pieces(int num)
{ m_prefer_whole_pieces = num; }
bool request_large_blocks() const
{ return m_request_large_blocks; }
void request_large_blocks(bool b)
{ m_request_large_blocks = b; }
void set_priority(int p)
{ m_priority = p; }
void fast_reconnect(bool r);
bool fast_reconnect() const { return m_fast_reconnect; }
// this adds an announcement in the announcement queue
// it will let the peer know that we have the given piece
void announce_piece(int index);
// tells if this connection has data it want to send
// and has enough upload bandwidth quota left to send it.
bool can_write() const;
bool can_read() const;
bool is_seed() const;
void set_upload_only(bool u) { m_upload_only = u; }
bool upload_only() const { return m_upload_only; }
// will send a keep-alive message to the peer
void keep_alive();
peer_id const& pid() const { return m_peer_id; }
void set_pid(const peer_id& pid) { m_peer_id = pid; }
bool has_piece(int i) const;
std::deque<piece_block> const& download_queue() const;
std::deque<piece_block> const& request_queue() const;
std::deque<peer_request> const& upload_queue() const;
bool is_interesting() const { return m_interesting; }
bool is_choked() const { return m_choked; }
bool is_peer_interested() const { return m_peer_interested; }
bool has_peer_choked() const { return m_peer_choked; }
void update_interest();
virtual void get_peer_info(peer_info& p) const;
// returns the torrent this connection is a part of
// may be zero if the connection is an incoming connection
// and it hasn't received enough information to determine
// which torrent it should be associated with
boost::weak_ptr<torrent> associated_torrent() const
{ return m_torrent; }
const stat& statistics() const { return m_statistics; }
void add_stat(size_type downloaded, size_type uploaded);
void calc_ip_overhead();
// is called once every second by the main loop
void second_tick(float tick_interval);
boost::shared_ptr<socket_type> get_socket() const { return m_socket; }
tcp::endpoint const& remote() const { return m_remote; }
bitfield const& get_bitfield() const;
std::vector<int> const& allowed_fast();
std::vector<int> const& suggested_pieces() const { return m_suggested_pieces; }
ptime connected_time() const { return m_connect; }
ptime last_received() const { return m_last_receive; }
void timed_out();
// this will cause this peer_connection to be disconnected.
void disconnect(char const* message, int error = 0);
bool is_disconnecting() const { return m_disconnecting; }
// this is called when the connection attempt has succeeded
// and the peer_connection is supposed to set m_connecting
// to false, and stop monitor writability
void on_connection_complete(error_code const& e);
// returns true if this connection is still waiting to
// finish the connection attempt
bool is_connecting() const { return m_connecting; }
// returns true if the socket of this peer hasn't been
// attempted to connect yet (i.e. it's queued for
// connection attempt).
bool is_queued() const { return m_queued; }
// called when it's time for this peer_conncetion to actually
// initiate the tcp connection. This may be postponed until
// the library isn't using up the limitation of half-open
// tcp connections.
void connect(int ticket);
// This is called for every peer right after the upload
// bandwidth has been distributed among them
// It will reset the used bandwidth to 0.
void reset_upload_quota();
// free upload.
size_type total_free_upload() const;
void add_free_upload(size_type free_upload);
// trust management.
void received_valid_data(int index);
void received_invalid_data(int index);
size_type share_diff() const;
// a connection is local if it was initiated by us.
// if it was an incoming connection, it is remote
bool is_local() const { return m_active; }
bool on_local_network() const;
bool ignore_bandwidth_limits() const
{ return m_ignore_bandwidth_limits; }
bool failed() const { return m_failed; }
int desired_queue_size() const { return m_desired_queue_size; }
// compares this connection against the given connection
// for which one is more eligible for an unchoke.
// returns true if this is more eligible
bool unchoke_compare(boost::intrusive_ptr<peer_connection const> const& p) const;
// resets the byte counters that are used to measure
// the number of bytes transferred within unchoke cycles
void reset_choke_counters();
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
boost::shared_ptr<logger> m_logger;
#endif
// the message handlers are called
// each time a recv() returns some new
// data, the last time it will be called
// is when the entire packet has been
// received, then it will no longer
// be called. i.e. most handlers need
// to check how much of the packet they
// have received before any processing
void incoming_keepalive();
void incoming_choke();
void incoming_unchoke();
void incoming_interested();
void incoming_not_interested();
void incoming_have(int piece_index);
void incoming_bitfield(bitfield const& bits);
void incoming_request(peer_request const& r);
void incoming_piece(peer_request const& p, disk_buffer_holder& data);
void incoming_piece(peer_request const& p, char const* data);
void incoming_piece_fragment();
void incoming_cancel(peer_request const& r);
void incoming_dht_port(int listen_port);
void incoming_reject_request(peer_request const& r);
void incoming_have_all();
void incoming_have_none();
void incoming_allowed_fast(int index);
void incoming_suggest(int index);
// the following functions appends messages
// to the send buffer
void send_choke();
void send_unchoke();
void send_interested();
void send_not_interested();
// adds a block to the request queue
void add_request(piece_block const& b);
// removes a block from the request queue or download queue
// sends a cancel message if appropriate
// refills the request queue, and possibly ignoring pieces requested
// by peers in the ignore list (to avoid recursion)
void cancel_request(piece_block const& b);
void send_block_requests();
int max_assignable_bandwidth(int channel) const
{ return m_bandwidth_limit[channel].max_assignable(); }
int bandwidth_throttle(int channel) const
{ return m_bandwidth_limit[channel].throttle(); }
void assign_bandwidth(int channel, int amount);
void expire_bandwidth(int channel, int amount);
#ifndef NDEBUG
void check_invariant() const;
ptime m_last_choke;
#endif
// is true until we can be sure that the other end
// speaks our protocol (be it bittorrent or http).
virtual bool in_handshake() const = 0;
// returns the block currently being
// downloaded. And the progress of that
// block. If the peer isn't downloading
// a piece for the moment, the boost::optional
// will be invalid.
virtual boost::optional<piece_block_progress>
downloading_piece_progress() const
{
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << "downloading_piece_progress() dispatched to the base class!\n";
#endif
return boost::optional<piece_block_progress>();
}
// these functions are virtual to let bt_peer_connection hook into them
// and encrypt the content
virtual void send_buffer(char const* begin, int size);
virtual buffer::interval allocate_send_buffer(int size);
virtual void setup_send();
template <class Destructor>
void append_send_buffer(char* buffer, int size, Destructor const& destructor)
{
m_send_buffer.append_buffer(buffer, size, size, destructor);
#ifdef TORRENT_STATS
m_ses.m_buffer_usage_logger << log_time() << " append_send_buffer: " << size << std::endl;
m_ses.log_buffer_usage();
#endif
}
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
void set_country(char const* c)
{
TORRENT_ASSERT(strlen(c) == 2);
m_country[0] = c[0];
m_country[1] = c[1];
}
bool has_country() const { return m_country[0] != 0; }
#endif
int send_buffer_size() const
{ return m_send_buffer.size(); }
int send_buffer_capacity() const
{ return m_send_buffer.capacity(); }
int packet_size() const { return m_packet_size; }
bool packet_finished() const
{ return m_packet_size <= m_recv_pos; }
#ifndef NDEBUG
bool piece_failed;
#endif
// upload and download channel state
// enum from peer_info::bw_state
char m_channel_state[2];
protected:
virtual void get_specific_peer_info(peer_info& p) const = 0;
virtual void write_choke() = 0;
virtual void write_unchoke() = 0;
virtual void write_interested() = 0;
virtual void write_not_interested() = 0;
virtual void write_request(peer_request const& r) = 0;
virtual void write_cancel(peer_request const& r) = 0;
virtual void write_have(int index) = 0;
virtual void write_keepalive() = 0;
virtual void write_piece(peer_request const& r, disk_buffer_holder& buffer) = 0;
virtual void write_reject_request(peer_request const& r) = 0;
virtual void write_allow_fast(int piece) = 0;
virtual void on_connected() = 0;
virtual void on_tick() {}
virtual void on_receive(error_code const& error
, std::size_t bytes_transferred) = 0;
virtual void on_sent(error_code const& error
, std::size_t bytes_transferred) = 0;
#ifndef TORRENT_DISABLE_ENCRYPTION
buffer::interval wr_recv_buffer()
{
TORRENT_ASSERT(!m_disk_recv_buffer);
TORRENT_ASSERT(m_disk_recv_buffer_size == 0);
if (m_recv_buffer.empty()) return buffer::interval(0,0);
return buffer::interval(&m_recv_buffer[0]
, &m_recv_buffer[0] + m_recv_pos);
}
std::pair<buffer::interval, buffer::interval> wr_recv_buffers(int bytes);
#endif
buffer::const_interval receive_buffer() const
{
if (m_recv_buffer.empty()) return buffer::const_interval(0,0);
return buffer::const_interval(&m_recv_buffer[0]
, &m_recv_buffer[0] + m_recv_pos);
}
bool allocate_disk_receive_buffer(int disk_buffer_size);
char* release_disk_receive_buffer();
bool has_disk_receive_buffer() const { return m_disk_recv_buffer; }
void cut_receive_buffer(int size, int packet_size);
void reset_recv_buffer(int packet_size);
void setup_receive();
void attach_to_torrent(sha1_hash const& ih);
bool verify_piece(peer_request const& p) const;
// the bandwidth channels, upload and download
// keeps track of the current quotas
bandwidth_limit m_bandwidth_limit[num_channels];
// statistics about upload and download speeds
// and total amount of uploads and downloads for
// this peer
stat m_statistics;
// a back reference to the session
// the peer belongs to.
aux::session_impl& m_ses;
// called from the main loop when this connection has any
// work to do.
void on_send_data(error_code const& error
, std::size_t bytes_transferred);
void on_receive_data(error_code const& error
, std::size_t bytes_transferred);
// this is the limit on the number of outstanding requests
// we have to this peer. This is initialized to the settings
// in the session_settings structure. But it may be lowered
// if the peer is known to require a smaller limit (like BitComet).
// or if the extended handshake sets a limit.
// web seeds also has a limit on the queue size.
int m_max_out_request_queue;
void set_timeout(int s) { m_timeout = s; }
#ifndef TORRENT_DISABLE_EXTENSIONS
typedef std::list<boost::shared_ptr<peer_plugin> > extension_list_t;
extension_list_t m_extensions;
#endif
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
// in case the session settings is set
// to resolve countries, this is set to
// the two character country code this
// peer resides in.
char m_country[2];
#endif
#ifndef NDEBUG
boost::intrusive_ptr<peer_connection> self()
{
TORRENT_ASSERT(!m_in_constructor);
return intrusive_ptr_base<peer_connection>::self();
}
#endif
private:
void fill_send_buffer();
void on_disk_read_complete(int ret, disk_io_job const& j, peer_request r);
void on_disk_write_complete(int ret, disk_io_job const& j
, peer_request r, boost::shared_ptr<torrent> t);
// the time when we last got a part of a
// piece packet from this peer
ptime m_last_piece;
// the time we sent a request to
// this peer the last time
ptime m_last_request;
// the time we received the last
// piece request from the peer
ptime m_last_incoming_request;
// the time when we unchoked this peer
ptime m_last_unchoke;
// timeouts
ptime m_last_receive;
ptime m_last_sent;
// the time when the first entry in the
// request queue was requested, increased
// for each entry that is popped from the
// download queue. Used for request timeout
ptime m_requested;
// a timestamp when the remote download rate
// was last updated
ptime m_remote_dl_update;
// the time when async_connect was called
ptime m_connect;
// the time when this peer sent us a not_interested message
// the last time.
ptime m_became_uninterested;
// the time when we sent a not_interested message to
// this peer the last time.
ptime m_became_uninteresting;
// the amount of data this peer has been given
// as free upload. This is distributed from
// peers from which we get free download
// this will be negative on a peer from which
// we get free download, and positive on peers
// that we give the free upload, to keep the balance.
size_type m_free_upload;
// the total payload download bytes
// at the last unchoke cycle. This is used to
// measure the number of bytes transferred during
// an unchoke cycle, to unchoke peers the more bytes
// they sent us
size_type m_downloaded_at_last_unchoke;
#ifndef TORRENT_DISABLE_GEO_IP
std::string m_inet_as_name;
#endif
buffer m_recv_buffer;
// if this peer is receiving a piece, this
// points to a disk buffer that the data is
// read into. This eliminates a memcopy from
// the receive buffer into the disk buffer
disk_buffer_holder m_disk_recv_buffer;
chained_buffer m_send_buffer;
boost::shared_ptr<socket_type> m_socket;
// this is the peer we're actually talking to
// it may not necessarily be the peer we're
// connected to, in case we use a proxy
tcp::endpoint m_remote;
// this is the torrent this connection is
// associated with. If the connection is an
// incoming conncetion, this is set to zero
// until the info_hash is received. Then it's
// set to the torrent it belongs to.
boost::weak_ptr<torrent> m_torrent;
// remote peer's id
peer_id m_peer_id;
// the pieces the other end have
bitfield m_have_piece;
// the queue of requests we have got
// from this peer
std::deque<peer_request> m_requests;
// the blocks we have reserved in the piece
// picker and will request from this peer.
std::deque<piece_block> m_request_queue;
// the queue of blocks we have requested
// from this peer
std::deque<piece_block> m_download_queue;
// the pieces we will send to the peer
// if requested (regardless of choke state)
std::set<int> m_accept_fast;
// the pieces the peer will send us if
// requested (regardless of choke state)
std::vector<int> m_allowed_fast;
// pieces that has been suggested to be
// downloaded from this peer
std::vector<int> m_suggested_pieces;
// the number of pieces this peer
// has. Must be the same as
// std::count(m_have_piece.begin(),
// m_have_piece.end(), true)
int m_num_pieces;
// the timeout in seconds
int m_timeout;
// the size (in bytes) of the bittorrent message
// we're currently receiving
int m_packet_size;
// the number of bytes of the bittorrent payload
// we've received so far
int m_recv_pos;
int m_disk_recv_buffer_size;
// the number of bytes we are currently reading
// from disk, that will be added to the send
// buffer as soon as they complete
int m_reading_bytes;
// the number of invalid piece-requests
// we have got from this peer. If the request
// queue gets empty, and there have been
// invalid requests, we can assume the
// peer is waiting for those pieces.
// we can then clear its download queue
// by sending choke, unchoke.
int m_num_invalid_requests;
// this is the priority with which this peer gets
// download bandwidth quota assigned to it.
int m_priority;
int m_upload_limit;
int m_download_limit;
// this peer's peer info struct. This may
// be 0, in case the connection is incoming
// and hasn't been added to a torrent yet.
policy::peer* m_peer_info;
// this is a measurement of how fast the peer
// it allows some variance without changing
// back and forth between states
peer_speed_t m_speed;
// the ticket id from the connection queue.
// This is used to identify the connection
// so that it can be removed from the queue
// once the connection completes
int m_connection_ticket;
// bytes downloaded since last second
// timer timeout; used for determining
// approx download rate
int m_remote_bytes_dled;
// approximate peer download rate
int m_remote_dl_rate;
// the number of bytes send to the disk-io
// thread that hasn't yet been completely written.
int m_outstanding_writing_bytes;
// max transfer rates seen on this peer
int m_download_rate_peak;
int m_upload_rate_peak;
// estimated round trip time to this peer
// based on the time from when async_connect
// was called to when on_connection_complete
// was called. The rtt is specified in milliseconds
boost::uint16_t m_rtt;
// if set to non-zero, this peer will always prefer
// to request entire n pieces, rather than blocks.
// where n is the value of this variable.
// if it is 0, the download rate limit setting
// will be used to determine if whole pieces
// are preferred.
boost::uint8_t m_prefer_whole_pieces;
// the number of request we should queue up
// at the remote end.
boost::uint8_t m_desired_queue_size;
// if this is true, the disconnection
// timestamp is not updated when the connection
// is closed. This means the time until we can
// reconnect to this peer is shorter, and likely
// immediate.
bool m_fast_reconnect:1;
// is true if it was we that connected to the peer
// and false if we got an incoming connection
// could be considered: true = local, false = remote
bool m_active:1;
// other side says that it's interested in downloading
// from us.
bool m_peer_interested:1;
// the other side has told us that it won't send anymore
// data to us for a while
bool m_peer_choked:1;
// the peer has pieces we are interested in
bool m_interesting:1;
// we have choked the upload to the peer
bool m_choked:1;
// this is set to true if the connection timed
// out or closed the connection. In that
// case we will not try to reconnect to
// this peer
bool m_failed:1;
// if this is set to true, the peer will not
// request bandwidth from the limiter, but instead
// just send and receive as much as possible.
bool m_ignore_bandwidth_limits:1;
// this is set to true when a have_all
// message is received. This information
// is used to fill the bitmask in init()
bool m_have_all:1;
// if this is true, this peer is assumed to handle all piece
// requests in fifo order. All skipped blocks are re-requested
// immediately instead of having a looser requirement
// where blocks can be sent out of order. The default is to
// allow non-fifo order.
bool m_assume_fifo:1;
// this is true if this connection has been added
// to the list of connections that will be closed.
bool m_disconnecting:1;
// this is true until this socket has become
// writable for the first time (i.e. the
// connection completed). While connecting
// the timeout will not be triggered. This is
// because windows XP SP2 may delay connection
// attempts, which means that the connection
// may not even have been attempted when the
// time out is reached.
bool m_connecting:1;
// This is true until connect is called on the
// peer_connection's socket. It is false on incoming
// connections.
bool m_queued:1;
// if this is true, the blocks picked by the piece
// picker will be merged before passed to the
// request function. i.e. subsequent blocks are
// merged into larger blocks. This is used by
// the http-downloader, to request whole pieces
// at a time.
bool m_request_large_blocks:1;
// set to true when this peer is only uploading
bool m_upload_only:1;
// set to true when a piece request times out. The
// result is that the desired pending queue size
// is set to 1
bool m_snubbed:1;
#ifndef NDEBUG
public:
bool m_in_constructor:1;
#endif
};
}
#endif // TORRENT_PEER_CONNECTION_HPP_INCLUDED

View File

@ -0,0 +1,197 @@
/*
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.
*/
#ifndef TORRENT_PEER_ID_HPP_INCLUDED
#define TORRENT_PEER_ID_HPP_INCLUDED
#include <iostream>
#include <iomanip>
#include <cctype>
#include <algorithm>
#include <string>
#include <cstring>
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{
class TORRENT_EXPORT big_number
{
// the number of bytes of the number
enum { number_size = 20 };
public:
enum { size = number_size };
big_number() {}
explicit big_number(char const* s)
{
if (s == 0) clear();
else std::memcpy(m_number, s, size);
}
explicit big_number(std::string const& s)
{
TORRENT_ASSERT(s.size() >= 20);
int sl = int(s.size()) < size ? int(s.size()) : size;
std::memcpy(m_number, &s[0], sl);
}
void clear()
{
std::fill(m_number,m_number+number_size,0);
}
bool is_all_zeros() const
{
return std::count(m_number,m_number+number_size,0) == number_size;
}
bool operator==(big_number const& n) const
{
return std::equal(n.m_number, n.m_number+number_size, m_number);
}
bool operator!=(big_number const& n) const
{
return !std::equal(n.m_number, n.m_number+number_size, m_number);
}
bool operator<(big_number const& n) const
{
for (int i = 0; i < number_size; ++i)
{
if (m_number[i] < n.m_number[i]) return true;
if (m_number[i] > n.m_number[i]) return false;
}
return false;
}
big_number operator~()
{
big_number ret;
for (int i = 0; i< number_size; ++i)
ret.m_number[i] = ~m_number[i];
return ret;
}
big_number& operator &= (big_number const& n)
{
for (int i = 0; i< number_size; ++i)
m_number[i] &= n.m_number[i];
return *this;
}
big_number& operator |= (big_number const& n)
{
for (int i = 0; i< number_size; ++i)
m_number[i] |= n.m_number[i];
return *this;
}
big_number& operator ^= (big_number const& n)
{
for (int i = 0; i< number_size; ++i)
m_number[i] ^= n.m_number[i];
return *this;
}
unsigned char& operator[](int i)
{ TORRENT_ASSERT(i >= 0 && i < number_size); return m_number[i]; }
unsigned char const& operator[](int i) const
{ TORRENT_ASSERT(i >= 0 && i < number_size); return m_number[i]; }
typedef const unsigned char* const_iterator;
typedef unsigned char* iterator;
const_iterator begin() const { return m_number; }
const_iterator end() const { return m_number+number_size; }
iterator begin() { return m_number; }
iterator end() { return m_number+number_size; }
std::string to_string() const
{ return std::string((char const*)&m_number[0], number_size); }
private:
unsigned char m_number[number_size];
};
typedef big_number peer_id;
typedef big_number sha1_hash;
inline std::ostream& operator<<(std::ostream& os, big_number const& peer)
{
for (big_number::const_iterator i = peer.begin();
i != peer.end(); ++i)
{
os << std::hex << std::setw(2) << std::setfill('0')
<< static_cast<unsigned int>(*i);
}
os << std::dec << std::setfill(' ');
return os;
}
inline std::istream& operator>>(std::istream& is, big_number& peer)
{
using namespace std;
for (big_number::iterator i = peer.begin();
i != peer.end(); ++i)
{
char c[2];
is >> c[0] >> c[1];
c[0] = tolower(c[0]);
c[1] = tolower(c[1]);
if (
((c[0] < '0' || c[0] > '9') && (c[0] < 'a' || c[0] > 'f'))
|| ((c[1] < '0' || c[1] > '9') && (c[1] < 'a' || c[1] > 'f'))
|| is.fail())
{
is.setstate(ios_base::failbit);
return is;
}
*i = ((isdigit(c[0])?c[0]-'0':c[0]-'a'+10) << 4)
+ (isdigit(c[1])?c[1]-'0':c[1]-'a'+10);
}
return is;
}
}
#endif // TORRENT_PEER_ID_HPP_INCLUDED

View File

@ -0,0 +1,210 @@
/*
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.
*/
#ifndef TORRENT_PEER_INFO_HPP_INCLUDED
#define TORRENT_PEER_INFO_HPP_INCLUDED
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/bitfield.hpp"
namespace libtorrent
{
struct TORRENT_EXPORT peer_info
{
enum
{
interesting = 0x1,
choked = 0x2,
remote_interested = 0x4,
remote_choked = 0x8,
supports_extensions = 0x10,
local_connection = 0x20,
handshake = 0x40,
connecting = 0x80,
queued = 0x100,
on_parole = 0x200,
seed = 0x400,
optimistic_unchoke = 0x800,
snubbed = 0x1000
#ifndef TORRENT_DISABLE_ENCRYPTION
, rc4_encrypted = 0x100000,
plaintext_encrypted = 0x200000
#endif
};
unsigned int flags;
enum peer_source_flags
{
tracker = 0x1,
dht = 0x2,
pex = 0x4,
lsd = 0x8,
resume_data = 0x10,
incoming = 0x20
};
int source;
// bw_idle: the channel is not used
// bw_torrent: the channel is waiting for torrent quota
// bw_global: the channel is waiting for global quota
// bw_network: the channel is waiting for an async write
// for read operation to complete
enum bw_state { bw_idle, bw_torrent, bw_global, bw_network };
char read_state;
char write_state;
tcp::endpoint ip;
float up_speed;
float down_speed;
float payload_up_speed;
float payload_down_speed;
size_type total_download;
size_type total_upload;
peer_id pid;
bitfield pieces;
int upload_limit;
int download_limit;
// time since last request
time_duration last_request;
// time since last download or upload
time_duration last_active;
// the number of seconds until the current
// pending request times out
int request_timeout;
// the size of the send buffer for this peer, in bytes
int send_buffer_size;
// the number bytes that's actually used of the send buffer
int used_send_buffer;
int receive_buffer_size;
int used_receive_buffer;
// the number of failed hashes for this peer
int num_hashfails;
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
// in case the session settings is set
// to resolve countries, this is set to
// the two character country code this
// peer resides in.
char country[2];
#endif
#ifndef TORRENT_DISABLE_GEO_IP
// atonomous system this peer belongs to
std::string inet_as_name;
int inet_as;
#endif
size_type load_balancing;
// this is the number of requests
// we have sent to this peer
// that we haven't got a response
// for yet
int download_queue_length;
// the number of requests that is
// tried to be maintained (this is
// typically a function of download speed)
int target_dl_queue_length;
// this is the number of requests
// the peer has sent to us
// that we haven't sent yet
int upload_queue_length;
// the number of times this IP
// has failed to connect
int failcount;
// the currently downloading piece
// if piece index is -1 all associated
// members are just set to 0
int downloading_piece_index;
int downloading_block_index;
int downloading_progress;
int downloading_total;
std::string client;
enum
{
standard_bittorrent = 0,
web_seed = 1
};
int connection_type;
// approximate peer download rate
int remote_dl_rate;
// number of bytes this peer has in
// the disk write queue
int pending_disk_bytes;
// numbers used for bandwidth limiting
int send_quota;
int receive_quota;
// estimated rtt to peer, in milliseconds
int rtt;
// the highest transfer rates seen for this peer
int download_rate_peak;
int upload_rate_peak;
};
struct TORRENT_EXPORT peer_list_entry
{
enum flags_t
{
banned = 1,
};
tcp::endpoint ip;
int flags;
boost::uint8_t failcount;
boost::uint8_t source;
};
}
#endif // TORRENT_PEER_INFO_HPP_INCLUDED

View File

@ -0,0 +1,49 @@
/*
Copyright (c) 2006, 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.
*/
#ifndef TORRENT_PEER_REQUEST_HPP_INCLUDED
#define TORRENT_PEER_REQUEST_HPP_INCLUDED
namespace libtorrent
{
struct TORRENT_EXPORT peer_request
{
int piece;
int start;
int length;
bool operator==(peer_request const& r) const
{ return piece == r.piece && start == r.start && length == r.length; }
};
}
#endif // TORRENT_PEER_REQUEST_HPP_INCLUDED

View File

@ -0,0 +1,57 @@
/*
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.
*/
#ifndef TORRENT_PIECE_BLOCK_PROGRESS_HPP_INCLUDED
#define TORRENT_PIECE_BLOCK_PROGRESS_HPP_INCLUDED
#include "libtorrent/config.hpp"
namespace libtorrent
{
struct TORRENT_EXPORT piece_block_progress
{
// the piece and block index
// determines exactly which
// part of the torrent that
// is currently being downloaded
int piece_index;
int block_index;
// the number of bytes we have received
// of this block
int bytes_downloaded;
// the number of bytes in the block
int full_block_bytes;
};
}
#endif // TORRENT_PIECE_BLOCK_PROGRESS_HPP_INCLUDED

View File

@ -0,0 +1,497 @@
/*
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.
*/
#ifndef TORRENT_PIECE_PICKER_HPP_INCLUDED
#define TORRENT_PIECE_PICKER_HPP_INCLUDED
#include <algorithm>
#include <vector>
#include <bitset>
#include <utility>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/static_assert.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/peer_id.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{
class torrent;
class peer_connection;
class bitfield;
struct TORRENT_EXPORT piece_block
{
piece_block(int p_index, int b_index)
: piece_index(p_index)
, block_index(b_index)
{}
int piece_index;
int block_index;
bool operator<(piece_block const& b) const
{
if (piece_index < b.piece_index) return true;
if (piece_index == b.piece_index) return block_index < b.block_index;
return false;
}
bool operator==(piece_block const& b) const
{ return piece_index == b.piece_index && block_index == b.block_index; }
bool operator!=(piece_block const& b) const
{ return piece_index != b.piece_index || block_index != b.block_index; }
};
class TORRENT_EXPORT piece_picker
{
public:
struct block_info
{
block_info(): peer(0), num_peers(0), state(state_none) {}
// the peer this block was requested or
// downloaded from. This is a pointer to
// a policy::peer object
void* peer;
// the number of peers that has this block in their
// download or request queues
unsigned num_peers:14;
// the state of this block
enum { state_none, state_requested, state_writing, state_finished };
unsigned state:2;
};
// the peers that are downloading this piece
// are considered fast peers or slow peers.
// none is set if the blocks were downloaded
// in a previous session
enum piece_state_t
{ none, slow, medium, fast };
struct downloading_piece
{
downloading_piece(): finished(0), writing(0), requested(0) {}
piece_state_t state;
// the index of the piece
int index;
// info about each block
// this is a pointer into the m_block_info
// vector owned by the piece_picker
block_info* info;
// the number of blocks in the finished state
boost::int16_t finished;
// the number of blocks in the writing state
boost::int16_t writing;
// the number of blocks in the requested state
boost::int16_t requested;
};
piece_picker();
void get_availability(std::vector<int>& avail) const;
void sequential_download(bool sd);
bool sequential_download() const { return m_sequential_download >= 0; }
// increases the peer count for the given piece
// (is used when a HAVE message is received)
void inc_refcount(int index);
void dec_refcount(int index);
// increases the peer count for the given piece
// (is used when a BITFIELD message is received)
void inc_refcount(bitfield const& bitmask);
// decreases the peer count for the given piece
// (used when a peer disconnects)
void dec_refcount(bitfield const& bitmask);
// these will increase and decrease the peer count
// of all pieces. They are used when seeds join
// or leave the swarm.
void inc_refcount_all();
void dec_refcount_all();
// This indicates that we just received this piece
// it means that the refcounter will indicate that
// we are not interested in this piece anymore
// (i.e. we don't have to maintain a refcount)
void we_have(int index);
void we_dont_have(int index);
void init(int blocks_per_piece, int total_num_blocks);
int num_pieces() const { return int(m_piece_map.size()); }
bool have_piece(int index) const
{
TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < int(m_piece_map.size()));
return m_piece_map[index].index == piece_pos::we_have_index;
}
// sets the priority of a piece.
// returns true if the priority was changed from 0 to non-0
// or vice versa
bool set_piece_priority(int index, int prio);
// returns the priority for the piece at 'index'
int piece_priority(int index) const;
// returns the current piece priorities for all pieces
void piece_priorities(std::vector<int>& pieces) const;
// ========== start deprecation ==============
// fills the bitmask with 1's for pieces that are filtered
void filtered_pieces(std::vector<bool>& mask) const;
// ========== end deprecation ==============
// pieces should be the vector that represents the pieces a
// client has. It returns a list of all pieces that this client
// has and that are interesting to download. It returns them in
// priority order. It doesn't care about the download flag.
// The user of this function must lookup if any piece is
// marked as being downloaded. If the user of this function
// decides to download a piece, it must mark it as being downloaded
// itself, by using the mark_as_downloading() member function.
// THIS IS DONE BY THE peer_connection::send_request() MEMBER FUNCTION!
// The last argument is the policy::peer pointer for the peer that
// we'll download from.
void pick_pieces(bitfield const& pieces
, std::vector<piece_block>& interesting_blocks
, int num_pieces, int prefer_whole_pieces
, void* peer, piece_state_t speed
, bool rarest_first, bool on_parole
, std::vector<int> const& suggested_pieces) const;
// picks blocks from each of the pieces in the piece_list
// vector that is also in the piece bitmask. The blocks
// are added to interesting_blocks, and busy blocks are
// added to backup_blocks. num blocks is the number of
// blocks to be picked. Blocks are not picked from pieces
// that are being downloaded
int add_blocks(std::vector<int> const& piece_list
, bitfield const& pieces
, std::vector<piece_block>& interesting_blocks
, int num_blocks, int prefer_whole_pieces
, void* peer, std::vector<int> const& ignore) const;
// picks blocks only from downloading pieces
int add_blocks_downloading(
bitfield const& pieces
, std::vector<piece_block>& interesting_blocks
, std::vector<piece_block>& backup_blocks
, int num_blocks, int prefer_whole_pieces
, void* peer, piece_state_t speed
, bool on_parole) const;
// clears the peer pointer in all downloading pieces with this
// peer pointer
void clear_peer(void* peer);
// returns true if any client is currently downloading this
// piece-block, or if it's queued for downloading by some client
// or if it already has been successfully downloaded
bool is_requested(piece_block block) const;
// returns true if the block has been downloaded
bool is_downloaded(piece_block block) const;
// returns true if the block has been downloaded and written to disk
bool is_finished(piece_block block) const;
// marks this piece-block as queued for downloading
bool mark_as_downloading(piece_block block, void* peer
, piece_state_t s);
void mark_as_writing(piece_block block, void* peer);
void mark_as_finished(piece_block block, void* peer);
void write_failed(piece_block block);
int num_peers(piece_block block) const;
// returns information about the given piece
void piece_info(int index, piece_picker::downloading_piece& st) const;
// if a piece had a hash-failure, it must be restored and
// made available for redownloading
void restore_piece(int index);
// clears the given piece's download flag
// this means that this piece-block can be picked again
void abort_download(piece_block block);
bool is_piece_finished(int index) const;
// returns the number of blocks there is in the given piece
int blocks_in_piece(int index) const;
// the number of downloaded blocks that hasn't passed
// the hash-check yet
int unverified_blocks() const;
void get_downloaders(std::vector<void*>& d, int index) const;
std::vector<downloading_piece> const& get_download_queue() const
{ return m_downloads; }
void* get_downloader(piece_block block) const;
// the number of filtered pieces we don't have
int num_filtered() const { return m_num_filtered; }
// the number of filtered pieces we already have
int num_have_filtered() const { return m_num_have_filtered; }
int num_have() const { return m_num_have; }
#ifndef NDEBUG
// used in debug mode
void verify_priority(int start, int end, int prio) const;
void check_invariant(const torrent* t = 0) const;
void verify_pick(std::vector<piece_block> const& picked
, bitfield const& bits) const;
void print_pieces() const;
#endif
// functor that compares indices on downloading_pieces
struct has_index
{
has_index(int i): index(i) { TORRENT_ASSERT(i >= 0); }
bool operator()(const downloading_piece& p) const
{ return p.index == index; }
int index;
};
int blocks_in_last_piece() const
{ return m_blocks_in_last_piece; }
float distributed_copies() const;
private:
friend struct piece_pos;
bool can_pick(int piece, bitfield const& bitmask) const;
std::pair<int, int> expand_piece(int piece, int whole_pieces
, bitfield const& have) const;
struct piece_pos
{
piece_pos() {}
piece_pos(int peer_count_, int index_)
: peer_count(peer_count_)
, downloading(0)
, piece_priority(1)
, index(index_)
{
TORRENT_ASSERT(peer_count_ >= 0);
TORRENT_ASSERT(index_ >= 0);
}
// the number of peers that has this piece
// (availability)
unsigned peer_count : 10;
// is 1 if the piece is marked as being downloaded
unsigned downloading : 1;
// is 0 if the piece is filtered (not to be downloaded)
// 1 is normal priority (default)
// 2 is higher priority than pieces at the same availability level
// 3 is same priority as partial pieces
// 4 is higher priority than partial pieces
// 5 and 6 same priority as availability 1 (ignores availability)
// 7 is maximum priority (ignores availability)
unsigned piece_priority : 3;
// index in to the piece_info vector
unsigned index : 18;
enum
{
// index is set to this to indicate that we have the
// piece. There is no entry for the piece in the
// buckets if this is the case.
we_have_index = 0x3ffff,
// the priority value that means the piece is filtered
filter_priority = 0,
// the max number the peer count can hold
max_peer_count = 0x3ff
};
bool have() const { return index == we_have_index; }
void set_have() { index = we_have_index; TORRENT_ASSERT(have()); }
void set_not_have() { index = 0; TORRENT_ASSERT(!have()); }
bool filtered() const { return piece_priority == filter_priority; }
void filtered(bool f) { piece_priority = f ? filter_priority : 0; }
int priority(piece_picker const* picker) const
{
if (downloading || filtered()
|| have() || peer_count + picker->m_seeds == 0)
return -1;
// priority 5, 6 and 7 disregards availability of the piece
if (piece_priority > 4) return 7 - piece_priority;
// pieces we are currently downloading have high priority
int prio = peer_count * 4;
// if (prio >= picker->m_prio_limit * 6) prio = picker->m_prio_limit * 6;
return prio + (4 - piece_priority);
}
bool operator!=(piece_pos p) const
{ return index != p.index || peer_count != p.peer_count; }
bool operator==(piece_pos p) const
{ return index == p.index && peer_count == p.peer_count; }
};
BOOST_STATIC_ASSERT(sizeof(piece_pos) == sizeof(char) * 4);
void update_pieces() const;
// fills in the range [start, end) of pieces in
// m_pieces that have priority 'prio'
void priority_range(int prio, int* start, int* end);
// adds the piece 'index' to m_pieces
void add(int index);
// removes the piece with the given priority and the
// elem_index in the m_pieces vector
void remove(int priority, int elem_index);
// updates the position of the piece with the given
// priority and the elem_index in the m_pieces vector
void update(int priority, int elem_index);
// shuffles the given piece inside it's priority range
void shuffle(int priority, int elem_index);
void sort_piece(std::vector<downloading_piece>::iterator dp);
downloading_piece& add_download_piece();
void erase_download_piece(std::vector<downloading_piece>::iterator i);
// the number of seeds. These are not added to
// the availability counters of the pieces
int m_seeds;
// the following vectors are mutable because they sometimes may
// be updated lazily, triggered by const functions
// this vector contains all piece indices that are pickable
// sorted by priority. Pieces are in random random order
// among pieces with the same priority
mutable std::vector<int> m_pieces;
// these are indices to the priority boundries inside
// the m_pieces vector. priority 0 always start at
// 0, priority 1 starts at m_priority_boundries[0] etc.
mutable std::vector<int> m_priority_boundries;
// this maps indices to number of peers that has this piece and
// index into the m_piece_info vectors.
// piece_pos::we_have_index means that we have the piece, so it
// doesn't exist in the piece_info buckets
// pieces with the filtered flag set doesn't have entries in
// the m_piece_info buckets either
mutable std::vector<piece_pos> m_piece_map;
// each piece that's currently being downloaded
// has an entry in this list with block allocations.
// i.e. it says wich parts of the piece that
// is being downloaded
std::vector<downloading_piece> m_downloads;
// this holds the information of the
// blocks in partially downloaded pieces.
// the first m_blocks_per_piece entries
// in the vector belongs to the first
// entry in m_downloads, the second
// m_blocks_per_piece entries to the
// second entry in m_downloads and so on.
std::vector<block_info> m_block_info;
int m_blocks_per_piece;
int m_blocks_in_last_piece;
// the number of filtered pieces that we don't already
// have. total_number_of_pieces - number_of_pieces_we_have
// - num_filtered is supposed to the number of pieces
// we still want to download
int m_num_filtered;
// the number of pieces we have that also are filtered
int m_num_have_filtered;
// the number of pieces we have
int m_num_have;
// -1 means sequential download is not active.
// >= 0 means that pieces are requested in sequential order
// and this variable is the next piece to request.
// in that case m_pieces is cleared and not used.
int m_sequential_download;
// if this is set to true, it means update_pieces()
// has to be called before accessing m_pieces.
mutable bool m_dirty;
public:
enum { max_pieces = piece_pos::we_have_index - 1 };
};
inline int piece_picker::blocks_in_piece(int index) const
{
TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < (int)m_piece_map.size());
if (index+1 == (int)m_piece_map.size())
return m_blocks_in_last_piece;
else
return m_blocks_per_piece;
}
}
#endif // TORRENT_PIECE_PICKER_HPP_INCLUDED

View File

@ -0,0 +1,295 @@
/*
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.
*/
#ifndef TORRENT_POLICY_HPP_INCLUDED
#define TORRENT_POLICY_HPP_INCLUDED
#include <algorithm>
#include <vector>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/peer.hpp"
#include "libtorrent/piece_picker.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/size_type.hpp"
#include "libtorrent/invariant_check.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/time.hpp"
namespace libtorrent
{
class torrent;
class peer_connection;
enum
{
// the limits of the download queue size
min_request_queue = 2,
// the amount of free upload allowed before
// the peer is choked
free_upload_amount = 4 * 16 * 1024
};
void request_a_block(torrent& t, peer_connection& c);
class TORRENT_EXPORT policy
{
public:
policy(torrent* t);
// this is called every 10 seconds to allow
// for peer choking management
void pulse();
struct peer;
// this is called once for every peer we get from
// the tracker, pex, lsd or dht.
policy::peer* peer_from_tracker(const tcp::endpoint& remote, const peer_id& pid
, int source, char flags);
// false means duplicate connection
bool update_peer_port(int port, policy::peer* p, int src);
// called when an incoming connection is accepted
// false means the connection was refused or failed
bool new_connection(peer_connection& c);
// the given connection was just closed
void connection_closed(const peer_connection& c);
// the peer has got at least one interesting piece
void peer_is_interesting(peer_connection& c);
int count_choked() const;
// the peer unchoked us
void unchoked(peer_connection& c);
// the peer is interested in our pieces
void interested(peer_connection& c);
// the peer is not interested in our pieces
void not_interested(peer_connection& c);
void ip_filter_updated();
#ifndef NDEBUG
bool has_connection(const peer_connection* p);
void check_invariant() const;
#endif
struct peer
{
enum connection_type { not_connectable, connectable };
peer(tcp::endpoint const& ip, connection_type t, int src);
size_type total_download() const;
size_type total_upload() const;
// the ip/port pair this peer is or was connected on
tcp::endpoint ip;
#ifndef TORRENT_DISABLE_GEO_IP
#ifndef NDEBUG
// only used in debug mode to assert that
// the first entry in the AS pair keeps the same
boost::uint16_t inet_as_num;
#endif
// The AS this peer belongs to
std::pair<const int, int>* inet_as;
#endif
// the number of failed connection attempts
// this peer has
boost::uint8_t failcount;
// for every valid piece we receive where this
// peer was one of the participants, we increase
// this value. For every invalid piece we receive
// where this peer was a participant, we decrease
// this value. If it sinks below a threshold, its
// considered a bad peer and will be banned.
boost::int8_t trust_points;
// a bitmap combining the peer_source flags
// from peer_info.
boost::uint8_t source;
// the number of times this peer has been
// part of a piece that failed the hash check
boost::uint8_t hashfails;
// type specifies if the connection was incoming
// or outgoing. If we ever saw this peer as connectable
// it will remain as connectable
unsigned type:4;
// the number of times we have allowed a fast
// reconnect for this peer.
unsigned fast_reconnects:4;
#ifndef TORRENT_DISABLE_ENCRYPTION
// Hints encryption support of peer. Only effective
// for and when the outgoing encryption policy
// allows both encrypted and non encrypted
// connections (pe_settings::out_enc_policy
// == enabled). The initial state of this flag
// determines the initial connection attempt
// type (true = encrypted, false = standard).
// This will be toggled everytime either an
// encrypted or non-encrypted handshake fails.
bool pe_support:1;
#endif
// true if this peer currently is unchoked
// because of an optimistic unchoke.
// when the optimistic unchoke is moved to
// another peer, this peer will be choked
// if this is true
bool optimistically_unchoked:1;
// this is true if the peer is a seed
bool seed:1;
// if this is true, the peer has previously
// participated in a piece that failed the piece
// hash check. This will put the peer on parole
// and only request entire pieces. If a piece pass
// that was partially requested from this peer it
// will leave parole mode and continue download
// pieces as normal peers.
bool on_parole:1;
// is set to true if this peer has been banned
bool banned:1;
#ifndef TORRENT_DISABLE_DHT
// this is set to true when this peer as been
// pinged by the DHT
bool added_to_dht:1;
#endif
// if the peer is connected now, this
// will refer to a valid peer_connection
peer_connection* connection;
// this is the accumulated amount of
// uploaded and downloaded data to this
// peer. It only accounts for what was
// shared during the last connection to
// this peer. i.e. These are only updated
// when the connection is closed. For the
// total amount of upload and download
// we'll have to add thes figures with the
// statistics from the peer_connection.
size_type prev_amount_upload;
size_type prev_amount_download;
// the time when this peer was optimistically unchoked
// the last time.
libtorrent::ptime last_optimistically_unchoked;
// the time when the peer connected to us
// or disconnected if it isn't connected right now
libtorrent::ptime connected;
};
int num_peers() const { return m_peers.size(); }
typedef std::multimap<address, peer>::iterator iterator;
typedef std::multimap<address, peer>::const_iterator const_iterator;
iterator begin_peer() { return m_peers.begin(); }
iterator end_peer() { return m_peers.end(); }
const_iterator begin_peer() const { return m_peers.begin(); }
const_iterator end_peer() const { return m_peers.end(); }
bool connect_one_peer();
bool has_peer(policy::peer const* p) const;
int num_seeds() const { return m_num_seeds; }
int num_connect_candidates() const { return m_num_connect_candidates; }
void recalculate_connect_candidates()
{
if (m_num_connect_candidates == 0)
m_num_connect_candidates = 1;
}
void erase_peer(iterator i);
private:
bool compare_peer(policy::peer const& lhs, policy::peer const& rhs
, address const& external_ip) const;
iterator find_connect_candidate();
bool is_connect_candidate(peer const& p, bool finished);
std::multimap<address, peer> m_peers;
// since the peer list can grow too large
// to scan all of it, start at this iterator
iterator m_round_robin;
torrent* m_torrent;
// free download we have got that hasn't
// been distributed yet.
size_type m_available_free_upload;
// The number of peers in our peer list
// that are connect candidates. i.e. they're
// not already connected and they have not
// yet reached their max try count and they
// have the connectable state (we have a listen
// port for them).
int m_num_connect_candidates;
// the number of seeds in the peer list
int m_num_seeds;
};
}
#endif // TORRENT_POLICY_HPP_INCLUDED

View File

@ -0,0 +1,211 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_PROXY_BASE_HPP_INCLUDED
#define TORRENT_PROXY_BASE_HPP_INCLUDED
#include "libtorrent/io.hpp"
#include "libtorrent/socket.hpp"
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/function.hpp>
#if BOOST_VERSION < 103500
#include <asio/read.hpp>
#include <asio/write.hpp>
#else
#include <boost/asio/read.hpp>
#include <boost/asio/write.hpp>
#endif
namespace libtorrent {
class proxy_base : boost::noncopyable
{
public:
typedef stream_socket::lowest_layer_type lowest_layer_type;
typedef stream_socket::endpoint_type endpoint_type;
typedef stream_socket::protocol_type protocol_type;
explicit proxy_base(io_service& io_service)
: m_sock(io_service)
, m_resolver(io_service)
{}
void set_proxy(std::string hostname, int port)
{
m_hostname = hostname;
m_port = port;
}
template <class Mutable_Buffers, class Handler>
void async_read_some(Mutable_Buffers const& buffers, Handler const& handler)
{
m_sock.async_read_some(buffers, handler);
}
template <class Mutable_Buffers>
std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec)
{
return m_sock.read_some(buffers, ec);
}
#ifndef BOOST_NO_EXCEPTIONS
template <class Mutable_Buffers>
std::size_t read_some(Mutable_Buffers const& buffers)
{
return m_sock.read_some(buffers);
}
template <class IO_Control_Command>
void io_control(IO_Control_Command& ioc)
{
m_sock.io_control(ioc);
}
#endif
template <class IO_Control_Command>
void io_control(IO_Control_Command& ioc, error_code& ec)
{
m_sock.io_control(ioc, ec);
}
template <class Const_Buffers, class Handler>
void async_write_some(Const_Buffers const& buffers, Handler const& handler)
{
m_sock.async_write_some(buffers, handler);
}
#ifndef BOOST_NO_EXCEPTIONS
template <class SettableSocketOption>
void set_option(SettableSocketOption const& opt)
{
m_sock.set_option(opt);
}
#endif
template <class SettableSocketOption>
error_code set_option(SettableSocketOption const& opt, error_code& ec)
{
return m_sock.set_option(opt, ec);
}
#ifndef BOOST_NO_EXCEPTIONS
void bind(endpoint_type const& endpoint)
{
m_sock.bind(endpoint);
}
#endif
void bind(endpoint_type const& endpoint, error_code& ec)
{
m_sock.bind(endpoint, ec);
}
#ifndef BOOST_NO_EXCEPTIONS
void open(protocol_type const& p)
{
m_sock.open(p);
}
#endif
void open(protocol_type const& p, error_code& ec)
{
m_sock.open(p, ec);
}
#ifndef BOOST_NO_EXCEPTIONS
void close()
{
m_remote_endpoint = endpoint_type();
m_sock.close();
m_resolver.cancel();
}
#endif
void close(error_code& ec)
{
m_sock.close(ec);
m_resolver.cancel();
}
#ifndef BOOST_NO_EXCEPTIONS
endpoint_type remote_endpoint() const
{
return m_remote_endpoint;
}
#endif
endpoint_type remote_endpoint(error_code& ec) const
{
return m_remote_endpoint;
}
#ifndef BOOST_NO_EXCEPTIONS
endpoint_type local_endpoint() const
{
return m_sock.local_endpoint();
}
#endif
endpoint_type local_endpoint(error_code& ec) const
{
return m_sock.local_endpoint(ec);
}
io_service& get_io_service()
{
return m_sock.get_io_service();
}
lowest_layer_type& lowest_layer()
{
return m_sock.lowest_layer();
}
bool is_open() const { return m_sock.is_open(); }
protected:
stream_socket m_sock;
std::string m_hostname;
int m_port;
endpoint_type m_remote_endpoint;
tcp::resolver m_resolver;
};
}
#endif

View File

@ -0,0 +1,74 @@
/*
Copyright (c) 2006, Arvid Norberg & Daniel Wallin
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.
*/
#ifndef TORRENT_RANDOM_SAMPLE_HPP
#define TORRENT_RANDOM_SAMPLE_HPP
#include <iterator>
#include <cstdlib>
#include "libtorrent/config.hpp"
namespace libtorrent
{
template<class InIter, class OutIter, class Distance>
inline void random_sample_n(InIter start, InIter end
, OutIter out, Distance n)
{
Distance t = 0;
Distance m = 0;
Distance N = std::distance(start, end);
TORRENT_ASSERT(N >= n);
while (m < n)
{
if ((std::rand() / (RAND_MAX + 1.f)) * (N - t) >= n - m)
{
++start;
++t;
}
else
{
*out = *start;
++out;
++start;
++t;
++m;
}
}
}
}
#endif

View File

@ -0,0 +1,350 @@
/*
Copyright (c) 2006, 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.
*/
#ifndef TORRENT_SESSION_HPP_INCLUDED
#define TORRENT_SESSION_HPP_INCLUDED
#include <ctime>
#include <algorithm>
#include <vector>
#include <set>
#include <list>
#include <deque>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/limits.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/thread.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/config.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/session_status.hpp"
#include "libtorrent/version.hpp"
#include "libtorrent/fingerprint.hpp"
#include "libtorrent/time.hpp"
#include "libtorrent/disk_io_thread.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/storage.hpp"
#ifdef _MSC_VER
# include <eh.h>
#endif
namespace libtorrent
{
struct torrent_plugin;
class torrent;
class ip_filter;
class port_filter;
class connection_queue;
class natpmp;
class upnp;
namespace fs = boost::filesystem;
namespace aux
{
// workaround for microsofts
// hardware exceptions that makes
// it hard to debug stuff
#ifdef _MSC_VER
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
struct session_impl;
struct filesystem_init
{
filesystem_init();
};
}
class TORRENT_EXPORT session_proxy
{
friend class session;
public:
session_proxy() {}
private:
session_proxy(boost::shared_ptr<aux::session_impl> impl)
: m_impl(impl) {}
boost::shared_ptr<aux::session_impl> m_impl;
};
struct add_torrent_params
{
add_torrent_params(storage_constructor_type sc = default_storage_constructor)
: tracker_url(0)
, name(0)
, resume_data(0)
, storage_mode(storage_mode_sparse)
, paused(true)
, auto_managed(true)
, duplicate_is_error(false)
, storage(sc)
, userdata(0)
{}
boost::intrusive_ptr<torrent_info> ti;
char const* tracker_url;
sha1_hash info_hash;
char const* name;
fs::path save_path;
std::vector<char>* resume_data;
storage_mode_t storage_mode;
bool paused;
bool auto_managed;
bool duplicate_is_error;
storage_constructor_type storage;
void* userdata;
};
class TORRENT_EXPORT session: public boost::noncopyable, aux::eh_initializer
{
public:
session(fingerprint const& print = fingerprint("LT"
, LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR, 0, 0)
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
, fs::path logpath = "."
#endif
);
session(
fingerprint const& print
, std::pair<int, int> listen_port_range
, char const* listen_interface = "0.0.0.0"
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
, fs::path logpath = "."
#endif
);
~session();
// returns a list of all torrents in this session
std::vector<torrent_handle> get_torrents() const;
// returns an invalid handle in case the torrent doesn't exist
torrent_handle find_torrent(sha1_hash const& info_hash) const;
// all torrent_handles must be destructed before the session is destructed!
torrent_handle add_torrent(add_torrent_params const& params);
// deprecated in 0.14
torrent_handle add_torrent(
torrent_info const& ti
, fs::path const& save_path
, entry const& resume_data = entry()
, storage_mode_t storage_mode = storage_mode_sparse
, bool paused = false
, storage_constructor_type sc = default_storage_constructor) TORRENT_DEPRECATED;
// deprecated in 0.14
torrent_handle add_torrent(
boost::intrusive_ptr<torrent_info> ti
, fs::path const& save_path
, entry const& resume_data = entry()
, storage_mode_t storage_mode = storage_mode_sparse
, bool paused = false
, storage_constructor_type sc = default_storage_constructor
, void* userdata = 0) TORRENT_DEPRECATED;
// deprecated in 0.14
torrent_handle add_torrent(
char const* tracker_url
, sha1_hash const& info_hash
, char const* name
, fs::path const& save_path
, entry const& resume_data = entry()
, storage_mode_t storage_mode = storage_mode_sparse
, bool paused = false
, storage_constructor_type sc = default_storage_constructor
, void* userdata = 0) TORRENT_DEPRECATED;
session_proxy abort() { return session_proxy(m_impl); }
void pause();
void resume();
bool is_paused() const;
session_status status() const;
cache_status get_cache_status() const;
void get_cache_info(sha1_hash const& ih
, std::vector<cached_piece_info>& ret) const;
#ifndef TORRENT_DISABLE_DHT
void start_dht(entry const& startup_state = entry());
void stop_dht();
void set_dht_settings(dht_settings const& settings);
entry dht_state() const;
void add_dht_node(std::pair<std::string, int> const& node);
void add_dht_router(std::pair<std::string, int> const& node);
#endif
#ifndef TORRENT_DISABLE_ENCRYPTION
void set_pe_settings(pe_settings const& settings);
pe_settings const& get_pe_settings() const;
#endif
#ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> ext);
#endif
#ifndef TORRENT_DISABLE_GEO_IP
int as_for_ip(address const& addr);
bool load_asnum_db(char const* file);
bool load_country_db(char const* file);
#endif
void load_state(entry const& ses_state);
entry state() const;
void set_ip_filter(ip_filter const& f);
void set_port_filter(port_filter const& f);
void set_peer_id(peer_id const& pid);
void set_key(int key);
peer_id id() const;
bool is_listening() const;
// if the listen port failed in some way
// you can retry to listen on another port-
// range with this function. If the listener
// succeeded and is currently listening,
// a call to this function will shut down the
// listen port and reopen it using these new
// properties (the given interface and port range).
// As usual, if the interface is left as 0
// this function will return false on failure.
// If it fails, it will also generate alerts describing
// the error. It will return true on success.
bool listen_on(
std::pair<int, int> const& port_range
, const char* net_interface = 0);
// returns the port we ended up listening on
unsigned short listen_port() const;
// Get the number of uploads.
int num_uploads() const;
// Get the number of connections. This number also contains the
// number of half open connections.
int num_connections() const;
enum options_t
{
none = 0,
delete_files = 1
};
void remove_torrent(const torrent_handle& h, int options = none);
void set_settings(session_settings const& s);
session_settings const& settings();
void set_peer_proxy(proxy_settings const& s);
void set_web_seed_proxy(proxy_settings const& s);
void set_tracker_proxy(proxy_settings const& s);
proxy_settings const& peer_proxy() const;
proxy_settings const& web_seed_proxy() const;
proxy_settings const& tracker_proxy() const;
#ifndef TORRENT_DISABLE_DHT
void set_dht_proxy(proxy_settings const& s);
proxy_settings const& dht_proxy() const;
#endif
int upload_rate_limit() const;
int download_rate_limit() const;
int max_half_open_connections() const;
void set_upload_rate_limit(int bytes_per_second);
void set_download_rate_limit(int bytes_per_second);
void set_max_uploads(int limit);
void set_max_connections(int limit);
void set_max_half_open_connections(int limit);
std::auto_ptr<alert> pop_alert();
void set_severity_level(alert::severity_t s);
alert const* wait_for_alert(time_duration max_wait);
connection_queue& get_connection_queue();
// starts/stops UPnP, NATPMP or LSD port mappers
// they are stopped by default
void start_lsd();
natpmp* start_natpmp();
upnp* start_upnp();
void stop_lsd();
void stop_natpmp();
void stop_upnp();
private:
// just a way to initialize boost.filesystem
// before the session_impl is created
aux::filesystem_init m_dummy;
// data shared between the main thread
// and the working thread
boost::shared_ptr<aux::session_impl> m_impl;
};
}
#endif // TORRENT_SESSION_HPP_INCLUDED

View File

@ -0,0 +1,493 @@
/*
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.
*/
#ifndef TORRENT_SESSION_SETTINGS_HPP_INCLUDED
#define TORRENT_SESSION_SETTINGS_HPP_INCLUDED
#include "libtorrent/version.hpp"
#include "libtorrent/config.hpp"
namespace libtorrent
{
struct TORRENT_EXPORT proxy_settings
{
proxy_settings() : port(0), type(none) {}
std::string hostname;
int port;
std::string username;
std::string password;
enum proxy_type
{
// a plain tcp socket is used, and
// the other settings are ignored.
none,
// socks4 server, requires username.
socks4,
// the hostname and port settings are
// used to connect to the proxy. No
// username or password is sent.
socks5,
// the hostname and port are used to
// connect to the proxy. the username
// and password are used to authenticate
// with the proxy server.
socks5_pw,
// the http proxy is only available for
// tracker and web seed traffic
// assumes anonymous access to proxy
http,
// http proxy with basic authentication
// uses username and password
http_pw
};
proxy_type type;
};
struct TORRENT_EXPORT session_settings
{
session_settings(std::string const& user_agent_ = "libtorrent/"
LIBTORRENT_VERSION)
: user_agent(user_agent_)
, tracker_completion_timeout(60)
, tracker_receive_timeout(40)
, stop_tracker_timeout(5)
, tracker_maximum_response_length(1024*1024)
, piece_timeout(10)
, request_timeout(40)
, request_queue_time(3.f)
, max_allowed_in_request_queue(250)
, max_out_request_queue(200)
, whole_pieces_threshold(20)
, peer_timeout(120)
, urlseed_timeout(20)
, urlseed_pipeline_size(5)
, urlseed_wait_retry(30)
, file_pool_size(40)
, allow_multiple_connections_per_ip(false)
, max_failcount(3)
, min_reconnect_time(60)
, peer_connect_timeout(7)
, ignore_limits_on_local_network(true)
, connection_speed(20)
, send_redundant_have(false)
, lazy_bitfields(true)
, inactivity_timeout(600)
, unchoke_interval(15)
, optimistic_unchoke_multiplier(4)
, num_want(200)
, initial_picker_threshold(4)
, allowed_fast_set_size(10)
, max_outstanding_disk_bytes_per_connection(64 * 1024)
, handshake_timeout(10)
#ifndef TORRENT_DISABLE_DHT
, use_dht_as_fallback(true)
#endif
, free_torrent_hashes(true)
, upnp_ignore_nonrouters(true)
, send_buffer_watermark(80 * 1024)
, auto_upload_slots(true)
, cache_size(512)
, cache_expiry(60)
, outgoing_ports(0,0)
, peer_tos(0)
, active_downloads(8)
, active_seeds(5)
, active_limit(15)
, dont_count_slow_torrents(true)
, auto_manage_interval(30)
, share_ratio_limit(2.f)
, seed_time_ratio_limit(7.f)
, seed_time_limit(24 * 60 * 60) // 24 hours
, peer_turnover(1 / 50.f)
, peer_turnover_cutoff(1.f)
, close_redundant_connections(true)
, auto_scrape_interval(1800)
, auto_scrape_min_interval(300)
, max_peerlist_size(8000)
{}
// this is the user agent that will be sent to the tracker
// when doing requests. It is used to identify the client.
// It cannot contain \r or \n
std::string user_agent;
// the number of seconds to wait until giving up on a
// tracker request if it hasn't finished
int tracker_completion_timeout;
// the number of seconds where no data is received
// from the tracker until it should be considered
// as timed out
int tracker_receive_timeout;
// the time to wait when sending a stopped message
// before considering a tracker to have timed out.
// this is usually shorter, to make the client quit
// faster
int stop_tracker_timeout;
// if the content-length is greater than this value
// the tracker connection will be aborted
int tracker_maximum_response_length;
// the number of seconds from a request is sent until
// it times out if no piece response is returned.
int piece_timeout;
// the number of seconds one block (16kB) is expected
// to be received within. If it's not, the block is
// requested from a different peer
int request_timeout;
// the length of the request queue given in the number
// of seconds it should take for the other end to send
// all the pieces. i.e. the actual number of requests
// depends on the download rate and this number.
float request_queue_time;
// the number of outstanding block requests a peer is
// allowed to queue up in the client. If a peer sends
// more requests than this (before the first one has
// been sent) the last request will be dropped.
// the higher this is, the faster upload speeds the
// client can get to a single peer.
int max_allowed_in_request_queue;
// the maximum number of outstanding requests to
// send to a peer. This limit takes precedence over
// request_queue_time.
int max_out_request_queue;
// if a whole piece can be downloaded in this number
// of seconds, or less, the peer_connection will prefer
// to request whole pieces at a time from this peer.
// The benefit of this is to better utilize disk caches by
// doing localized accesses and also to make it easier
// to identify bad peers if a piece fails the hash check.
int whole_pieces_threshold;
// the number of seconds to wait for any activity on
// the peer wire before closing the connectiong due
// to time out.
int peer_timeout;
// same as peer_timeout, but only applies to url-seeds.
// this is usually set lower, because web servers are
// expected to be more reliable.
int urlseed_timeout;
// controls the pipelining size of url-seeds
int urlseed_pipeline_size;
// time to wait until a new retry takes place
int urlseed_wait_retry;
// sets the upper limit on the total number of files this
// session will keep open. The reason why files are
// left open at all is that some anti virus software
// hooks on every file close, and scans the file for
// viruses. deferring the closing of the files will
// be the difference between a usable system and
// a completely hogged down system. Most operating
// systems also has a limit on the total number of
// file descriptors a process may have open. It is
// usually a good idea to find this limit and set the
// number of connections and the number of files
// limits so their sum is slightly below it.
int file_pool_size;
// false to not allow multiple connections from the same
// IP address. true will allow it.
bool allow_multiple_connections_per_ip;
// the number of times we can fail to connect to a peer
// before we stop retrying it.
int max_failcount;
// the number of seconds to wait to reconnect to a peer.
// this time is multiplied with the failcount.
int min_reconnect_time;
// this is the timeout for a connection attempt. If
// the connect does not succeed within this time, the
// connection is dropped. The time is specified in seconds.
int peer_connect_timeout;
// if set to true, upload, download and unchoke limits
// are ignored for peers on the local network.
bool ignore_limits_on_local_network;
// the number of connection attempts that
// are made per second.
int connection_speed;
// if this is set to true, have messages will be sent
// to peers that already have the piece. This is
// typically not necessary, but it might be necessary
// for collecting statistics in some cases. Default is false.
bool send_redundant_have;
// if this is true, outgoing bitfields will never be fuil. If the
// client is seed, a few bits will be set to 0, and later filled
// in with have messages. This is to prevent certain ISPs
// from stopping people from seeding.
bool lazy_bitfields;
// if a peer is uninteresting and uninterested for longer
// than this number of seconds, it will be disconnected.
// default is 10 minutes
int inactivity_timeout;
// the number of seconds between chokes/unchokes
int unchoke_interval;
// the number of unchoke intervals between
// optimistic unchokes
int optimistic_unchoke_multiplier;
// if this is set, this IP will be reported do the
// tracker in the ip= parameter.
address announce_ip;
// the num want sent to trackers
int num_want;
// while we have fewer pieces than this, pick
// random pieces instead of rarest first.
int initial_picker_threshold;
// the number of allowed pieces to send to peers
// that supports the fast extensions
int allowed_fast_set_size;
// the maximum number of bytes a connection may have
// pending in the disk write queue before its download
// rate is being throttled. This prevents fast downloads
// to slow medias to allocate more and more memory
// indefinitely. This should be set to at least 32 kB
// to not completely disrupt normal downloads.
int max_outstanding_disk_bytes_per_connection;
// the number of seconds to wait for a handshake
// response from a peer. If no response is received
// within this time, the peer is disconnected.
int handshake_timeout;
#ifndef TORRENT_DISABLE_DHT
// while this is true, the dht will note be used unless the
// tracker is online
bool use_dht_as_fallback;
#endif
// if this is true, the piece hashes will be freed, in order
// to save memory, once the torrent is seeding. This will
// make the get_torrent_info() function to return an incomplete
// torrent object that cannot be passed back to add_torrent()
bool free_torrent_hashes;
// when this is true, the upnp port mapper will ignore
// any upnp devices that don't have an address that matches
// our currently configured router.
bool upnp_ignore_nonrouters;
// if the send buffer has fewer bytes than this, we'll
// read another 16kB block onto it. If set too small,
// upload rate capacity will suffer. If set too high,
// memory will be wasted.
// The actual watermark may be lower than this in case
// the upload rate is low, this is the upper limit.
int send_buffer_watermark;
// if auto_upload_slots is true, and a global upload
// limit is set and the upload rate is less than 90%
// of the upload limit, on new slot is opened up. If
// the upload rate is >= upload limit for an extended
// period of time, one upload slot is closed. The
// upload slots are never automatically decreased below
// the manual settings, through max_uploads.
bool auto_upload_slots;
// the disk write cache, specified in 16 KiB blocks.
// default is 512 (= 8 MB)
int cache_size;
// the number of seconds a write cache entry sits
// idle in the cache before it's forcefully flushed
// to disk. Default is 60 seconds.
int cache_expiry;
// if != (0, 0), this is the range of ports that
// outgoing connections will be bound to. This
// is useful for users that have routers that
// allow QoS settings based on local port.
std::pair<int, int> outgoing_ports;
// the TOS byte of all peer traffic (including
// web seeds) is set to this value. The default
// is the QBSS scavenger service
// http://qbone.internet2.edu/qbss/
// For unmarked packets, set to 0
char peer_tos;
// for auto managed torrents, these are the limits
// they are subject to. If there are too many torrents
// some of the auto managed ones will be paused until
// some slots free up.
int active_downloads;
int active_seeds;
int active_limit;
// if this is true, torrents that don't have any significant
// transfers are not counted as active when determining which
// auto managed torrents to pause and resume
bool dont_count_slow_torrents;
// the number of seconds in between recalculating which
// torrents to activate and which ones to queue
int auto_manage_interval;
// when a seeding torrent reaches eaither the share ratio
// (bytes up / bytes down) or the seed time ratio
// (seconds as seed / seconds as downloader) or the seed
// time limit (seconds as seed) it is considered
// done, and it will leave room for other torrents
// the default value for share ratio is 2
// the default seed time ratio is 7, because that's a common
// asymmetry ratio on connections
float share_ratio_limit;
float seed_time_ratio_limit;
int seed_time_limit;
// the percentage of peers to disconnect every
// 90 seconds (if we're at the peer limit)
// defaults to 1/50:th
float peer_turnover;
// when we are connected to more than
// limit * peer_turnover_enable peers
// disconnect peer_turnover fraction
// of the peers
float peer_turnover_cutoff;
// if this is true (default) connections where both
// ends have no utility in keeping the connection open
// are closed. for instance if both ends have completed
// their downloads
bool close_redundant_connections;
// the number of seconds between scrapes of
// queued torrents (auto managed and paused)
int auto_scrape_interval;
// the minimum number of seconds between any
// automatic scrape (regardless of torrent)
int auto_scrape_min_interval;
// the max number of peers in the peer list
// per torrent. This is the peers we know
// about, not necessarily connected to.
int max_peerlist_size;
};
#ifndef TORRENT_DISABLE_DHT
struct dht_settings
{
dht_settings()
: max_peers_reply(50)
, search_branching(5)
, service_port(0)
, max_fail_count(20)
{}
// the maximum number of peers to send in a
// reply to get_peers
int max_peers_reply;
// the number of simultanous "connections" when
// searching the DHT.
int search_branching;
// the listen port for the dht. This is a UDP port.
// zero means use the same as the tcp interface
int service_port;
// the maximum number of times a node can fail
// in a row before it is removed from the table.
int max_fail_count;
};
#endif
#ifndef TORRENT_DISABLE_ENCRYPTION
struct pe_settings
{
pe_settings()
: out_enc_policy(enabled)
, in_enc_policy(enabled)
, allowed_enc_level(both)
, prefer_rc4(false)
{}
enum enc_policy
{
forced, // disallow non encrypted connections
enabled, // allow encrypted and non encrypted connections
disabled // disallow encrypted connections
};
enum enc_level
{
plaintext, // use only plaintext encryption
rc4, // use only rc4 encryption
both // allow both
};
enc_policy out_enc_policy;
enc_policy in_enc_policy;
enc_level allowed_enc_level;
// if the allowed encryption level is both, setting this to
// true will prefer rc4 if both methods are offered, plaintext
// otherwise
bool prefer_rc4;
};
#endif
}
#endif

View File

@ -0,0 +1,74 @@
/*
Copyright (c) 2006, 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.
*/
#ifndef TORRENT_SESSION_STATUS_HPP_INCLUDED
#define TORRENT_SESSION_STATUS_HPP_INCLUDED
namespace libtorrent
{
struct TORRENT_EXPORT session_status
{
bool has_incoming_connections;
float upload_rate;
float download_rate;
float payload_upload_rate;
float payload_download_rate;
size_type total_download;
size_type total_upload;
size_type total_payload_download;
size_type total_payload_upload;
int num_peers;
int num_unchoked;
int allowed_upload_slots;
int up_bandwidth_queue;
int down_bandwidth_queue;
#ifndef TORRENT_DISABLE_DHT
int dht_nodes;
int dht_node_cache;
int dht_torrents;
size_type dht_global_nodes;
#endif
};
}
#endif // TORRENT_SESSION_STATUS_HPP_INCLUDED

View File

@ -0,0 +1,52 @@
/*
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.
*/
#ifndef TORRENT_SIZE_TYPE_HPP_INCLUDED
#define TORRENT_SIZE_TYPE_HPP_INCLUDED
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/cstdint.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
namespace libtorrent
{
typedef boost::int64_t size_type;
}
#endif

View File

@ -0,0 +1,233 @@
/*
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.
*/
#ifndef TORRENT_SOCKET_HPP_INCLUDED
#define TORRENT_SOCKET_HPP_INCLUDED
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
// if building as Objective C++, asio's template
// parameters Protocol has to be renamed to avoid
// colliding with keywords
#ifdef __OBJC__
#define Protocol Protocol_
#endif
#include <boost/version.hpp>
#if BOOST_VERSION < 103500
#include <asio/ip/tcp.hpp>
#include <asio/ip/udp.hpp>
#include <asio/io_service.hpp>
#include <asio/deadline_timer.hpp>
#include <asio/write.hpp>
#include <asio/read.hpp>
#include <asio/time_traits.hpp>
#include <asio/basic_deadline_timer.hpp>
#else
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ip/udp.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/write.hpp>
#include <boost/asio/read.hpp>
#include <boost/asio/time_traits.hpp>
#include <boost/asio/basic_deadline_timer.hpp>
#endif
#ifdef __OBJC__
#undef Protocol
#endif
#include "libtorrent/io.hpp"
#include "libtorrent/time.hpp"
#ifdef _MSC_VER
#pragma warning(pop)
#endif
namespace libtorrent
{
#if BOOST_VERSION < 103500
using asio::ip::tcp;
using asio::ip::udp;
using asio::async_write;
using asio::async_read;
typedef asio::ip::tcp::socket stream_socket;
typedef asio::ip::address address;
typedef asio::ip::address_v4 address_v4;
typedef asio::ip::address_v6 address_v6;
typedef asio::ip::udp::socket datagram_socket;
typedef asio::ip::tcp::acceptor socket_acceptor;
typedef asio::io_service io_service;
typedef asio::error_code error_code;
namespace asio = ::asio;
typedef asio::basic_deadline_timer<libtorrent::ptime> deadline_timer;
#else
using boost::system::error_code;
using boost::asio::ip::tcp;
using boost::asio::ip::udp;
using boost::asio::async_write;
using boost::asio::async_read;
typedef boost::asio::ip::tcp::socket stream_socket;
typedef boost::asio::ip::address address;
typedef boost::asio::ip::address_v4 address_v4;
typedef boost::asio::ip::address_v6 address_v6;
typedef boost::asio::ip::udp::socket datagram_socket;
typedef boost::asio::ip::tcp::acceptor socket_acceptor;
typedef boost::asio::io_service io_service;
namespace asio = boost::asio;
typedef boost::asio::basic_deadline_timer<libtorrent::ptime> deadline_timer;
#endif
inline std::ostream& print_address(std::ostream& os, address const& addr)
{
error_code ec;
std::string a = addr.to_string(ec);
if (ec) return os;
os << a;
return os;
}
inline std::ostream& print_endpoint(std::ostream& os, tcp::endpoint const& ep)
{
address const& addr = ep.address();
error_code ec;
std::string a = addr.to_string(ec);
if (ec) return os;
if (addr.is_v6())
os << "[" << a << "]:";
else
os << a << ":";
os << ep.port();
return os;
}
namespace detail
{
template<class OutIt>
void write_address(address const& a, OutIt& out)
{
if (a.is_v4())
{
write_uint32(a.to_v4().to_ulong(), out);
}
else if (a.is_v6())
{
address_v6::bytes_type bytes
= a.to_v6().to_bytes();
std::copy(bytes.begin(), bytes.end(), out);
}
}
template<class InIt>
address read_v4_address(InIt& in)
{
unsigned long ip = read_uint32(in);
return address_v4(ip);
}
template<class InIt>
address read_v6_address(InIt& in)
{
typedef address_v6::bytes_type bytes_t;
bytes_t bytes;
for (bytes_t::iterator i = bytes.begin()
, end(bytes.end()); i != end; ++i)
*i = read_uint8(in);
return address_v6(bytes);
}
template<class Endpoint, class OutIt>
void write_endpoint(Endpoint const& e, OutIt& out)
{
write_address(e.address(), out);
write_uint16(e.port(), out);
}
template<class Endpoint, class InIt>
Endpoint read_v4_endpoint(InIt& in)
{
address addr = read_v4_address(in);
int port = read_uint16(in);
return Endpoint(addr, port);
}
template<class Endpoint, class InIt>
Endpoint read_v6_endpoint(InIt& in)
{
address addr = read_v6_address(in);
int port = read_uint16(in);
return Endpoint(addr, port);
}
}
struct v6only
{
v6only(bool enable): m_value(enable) {}
template<class Protocol>
int level(Protocol const&) const { return IPPROTO_IPV6; }
template<class Protocol>
int name(Protocol const&) const { return IPV6_V6ONLY; }
template<class Protocol>
int const* data(Protocol const&) const { return &m_value; }
template<class Protocol>
size_t size(Protocol const&) const { return sizeof(m_value); }
int m_value;
};
struct type_of_service
{
type_of_service(char val): m_value(val) {}
template<class Protocol>
int level(Protocol const&) const { return IPPROTO_IP; }
template<class Protocol>
int name(Protocol const&) const { return IP_TOS; }
template<class Protocol>
char const* data(Protocol const&) const { return &m_value; }
template<class Protocol>
size_t size(Protocol const&) const { return sizeof(m_value); }
char m_value;
};
}
#endif // TORRENT_SOCKET_HPP_INCLUDED

View File

@ -0,0 +1,51 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_SOCKET_TYPE
#define TORRENT_SOCKET_TYPE
#include "libtorrent/socks5_stream.hpp"
#include "libtorrent/socks4_stream.hpp"
#include "libtorrent/http_stream.hpp"
#include "libtorrent/variant_stream.hpp"
namespace libtorrent
{
typedef variant_stream<
stream_socket
, socks5_stream
, socks4_stream
, http_stream> socket_type;
}
#endif

View File

@ -0,0 +1,92 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_SOCKS4_STREAM_HPP_INCLUDED
#define TORRENT_SOCKS4_STREAM_HPP_INCLUDED
#include "libtorrent/proxy_base.hpp"
namespace libtorrent {
class socks4_stream : public proxy_base
{
public:
explicit socks4_stream(io_service& io_service_)
: proxy_base(io_service_)
{}
void set_username(std::string const& user)
{
m_user = user;
}
typedef boost::function<void(error_code const&)> handler_type;
template <class Handler>
void async_connect(endpoint_type const& endpoint, Handler const& handler)
{
m_remote_endpoint = endpoint;
// the connect is split up in the following steps:
// 1. resolve name of proxy server
// 2. connect to proxy server
// 3. send SOCKS4 CONNECT message
// to avoid unnecessary copying of the handler,
// store it in a shaed_ptr
boost::shared_ptr<handler_type> h(new handler_type(handler));
tcp::resolver::query q(m_hostname
, boost::lexical_cast<std::string>(m_port));
m_resolver.async_resolve(q, boost::bind(
&socks4_stream::name_lookup, this, _1, _2, h));
}
private:
void name_lookup(error_code const& e, tcp::resolver::iterator i
, boost::shared_ptr<handler_type> h);
void connected(error_code const& e, boost::shared_ptr<handler_type> h);
void handshake1(error_code const& e, boost::shared_ptr<handler_type> h);
void handshake2(error_code const& e, boost::shared_ptr<handler_type> h);
// send and receive buffer
std::vector<char> m_buffer;
// proxy authentication
std::string m_user;
};
}
#endif

View File

@ -0,0 +1,104 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_SOCKS5_STREAM_HPP_INCLUDED
#define TORRENT_SOCKS5_STREAM_HPP_INCLUDED
#include "libtorrent/proxy_base.hpp"
namespace libtorrent {
class socks5_stream : public proxy_base
{
public:
explicit socks5_stream(io_service& io_service)
: proxy_base(io_service)
{}
void set_username(std::string const& user
, std::string const& password)
{
m_user = user;
m_password = password;
}
typedef boost::function<void(error_code const&)> handler_type;
template <class Handler>
void async_connect(endpoint_type const& endpoint, Handler const& handler)
{
m_remote_endpoint = endpoint;
// the connect is split up in the following steps:
// 1. resolve name of proxy server
// 2. connect to proxy server
// 3. send SOCKS5 authentication method message
// 4. read SOCKS5 authentication response
// 5. send username+password
// 6. send SOCKS5 CONNECT message
// to avoid unnecessary copying of the handler,
// store it in a shaed_ptr
boost::shared_ptr<handler_type> h(new handler_type(handler));
tcp::resolver::query q(m_hostname
, boost::lexical_cast<std::string>(m_port));
m_resolver.async_resolve(q, boost::bind(
&socks5_stream::name_lookup, this, _1, _2, h));
}
private:
void name_lookup(error_code const& e, tcp::resolver::iterator i
, boost::shared_ptr<handler_type> h);
void connected(error_code const& e, boost::shared_ptr<handler_type> h);
void handshake1(error_code const& e, boost::shared_ptr<handler_type> h);
void handshake2(error_code const& e, boost::shared_ptr<handler_type> h);
void handshake3(error_code const& e, boost::shared_ptr<handler_type> h);
void handshake4(error_code const& e, boost::shared_ptr<handler_type> h);
void socks_connect(boost::shared_ptr<handler_type> h);
void connect1(error_code const& e, boost::shared_ptr<handler_type> h);
void connect2(error_code const& e, boost::shared_ptr<handler_type> h);
void connect3(error_code const& e, boost::shared_ptr<handler_type> h);
// send and receive buffer
std::vector<char> m_buffer;
// proxy authentication
std::string m_user;
std::string m_password;
};
}
#endif

View File

@ -0,0 +1,227 @@
/*
Copyright (c) 2008, 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.
*/
#ifndef TORRENT_SSL_STREAM_HPP_INCLUDED
#define TORRENT_SSL_STREAM_HPP_INCLUDED
#include "libtorrent/socket.hpp"
#if BOOST_VERSION < 103500
#include <asio/ssl.hpp>
#else
#include <boost/asio/ssl.hpp>
#endif
// openssl seems to believe it owns
// this name in every single scope
#undef set_key
namespace libtorrent {
template <class Stream>
class ssl_stream
{
public:
explicit ssl_stream(io_service& io_service)
: m_context(io_service, asio::ssl::context::sslv23_client)
, m_sock(io_service, m_context)
{
m_context.set_verify_mode(asio::ssl::context::verify_none);
}
typedef Stream next_layer_type;
typedef typename Stream::lowest_layer_type lowest_layer_type;
typedef typename Stream::endpoint_type endpoint_type;
typedef typename Stream::protocol_type protocol_type;
typedef typename asio::ssl::stream<Stream> sock_type;
typedef boost::function<void(error_code const&)> handler_type;
template <class Handler>
void async_connect(endpoint_type const& endpoint, Handler const& handler)
{
// the connect is split up in the following steps:
// 1. connect to peer
// 2. perform SSL client handshake
// to avoid unnecessary copying of the handler,
// store it in a shared_ptr
boost::shared_ptr<handler_type> h(new handler_type(handler));
m_sock.next_layer().async_connect(endpoint
, boost::bind(&ssl_stream::connected, this, _1, h));
}
template <class Mutable_Buffers, class Handler>
void async_read_some(Mutable_Buffers const& buffers, Handler const& handler)
{
m_sock.async_read_some(buffers, handler);
}
template <class Mutable_Buffers>
std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec)
{
return m_sock.read_some(buffers, ec);
}
#ifndef BOOST_NO_EXCEPTIONS
template <class Mutable_Buffers>
std::size_t read_some(Mutable_Buffers const& buffers)
{
return m_sock.read_some(buffers);
}
template <class IO_Control_Command>
void io_control(IO_Control_Command& ioc)
{
m_sock.next_layer().io_control(ioc);
}
#endif
template <class IO_Control_Command>
void io_control(IO_Control_Command& ioc, error_code& ec)
{
m_sock.next_layer().io_control(ioc, ec);
}
template <class Const_Buffers, class Handler>
void async_write_some(Const_Buffers const& buffers, Handler const& handler)
{
m_sock.async_write_some(buffers, handler);
}
#ifndef BOOST_NO_EXCEPTIONS
void bind(endpoint_type const& endpoint)
{
m_sock.next_layer().bind(endpoint);
}
#endif
void bind(endpoint_type const& endpoint, error_code& ec)
{
m_sock.next_layer().bind(endpoint, ec);
}
#ifndef BOOST_NO_EXCEPTIONS
void open(protocol_type const& p)
{
m_sock.next_layer().open(p);
}
#endif
void open(protocol_type const& p, error_code& ec)
{
m_sock.next_layer().open(p, ec);
}
bool is_open() const
{
return const_cast<sock_type&>(m_sock).next_layer().is_open();
}
#ifndef BOOST_NO_EXCEPTIONS
void close()
{
m_sock.next_layer().close();
}
#endif
void close(error_code& ec)
{
m_sock.next_layer().close(ec);
}
#ifndef BOOST_NO_EXCEPTIONS
endpoint_type remote_endpoint() const
{
return const_cast<sock_type&>(m_sock).next_layer().remote_endpoint();
}
#endif
endpoint_type remote_endpoint(error_code& ec) const
{
return const_cast<sock_type&>(m_sock).next_layer().remote_endpoint(ec);
}
#ifndef BOOST_NO_EXCEPTIONS
endpoint_type local_endpoint() const
{
return const_cast<sock_type&>(m_sock).next_layer().local_endpoint();
}
#endif
endpoint_type local_endpoint(error_code& ec) const
{
return const_cast<sock_type&>(m_sock).next_layer().local_endpoint(ec);
}
io_service& get_io_service()
{
return m_sock.get_io_service();
}
lowest_layer_type& lowest_layer()
{
return m_sock.lowest_layer();
}
next_layer_type& next_layer()
{
return m_sock.next_layer();
}
private:
void connected(error_code const& e, boost::shared_ptr<handler_type> h)
{
if (e)
{
(*h)(e);
return;
}
m_sock.async_handshake(asio::ssl::stream_base::client
, boost::bind(&ssl_stream::handshake, this, _1, h));
}
void handshake(error_code const& e, boost::shared_ptr<handler_type> h)
{
(*h)(e);
}
asio::ssl::context m_context;
asio::ssl::stream<Stream> m_sock;
};
}
#endif

View File

@ -0,0 +1,241 @@
/*
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.
*/
#ifndef TORRENT_STAT_HPP_INCLUDED
#define TORRENT_STAT_HPP_INCLUDED
#include <algorithm>
#include <vector>
#include <assert.h>
#include <cstring>
#include "libtorrent/size_type.hpp"
#include "libtorrent/invariant_check.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{
class TORRENT_EXPORT stat_channel
{
friend class invariant_access;
public:
enum { history = 10 };
stat_channel()
: m_counter(0)
, m_total_counter(0)
, m_rate_sum(0)
{
std::memset(m_rate_history, 0, sizeof(m_rate_history));
}
void operator+=(stat_channel const& s)
{
m_counter += s.m_counter;
m_total_counter += s.m_counter;
}
void add(int count)
{
TORRENT_ASSERT(count >= 0);
m_counter += count;
m_total_counter += count;
}
// should be called once every second
void second_tick(float tick_interval);
float rate() const { return m_rate_sum / float(history); }
size_type rate_sum() const { return m_rate_sum; }
size_type total() const { return m_total_counter; }
void offset(size_type counter)
{
TORRENT_ASSERT(counter >= 0);
m_total_counter += counter;
}
size_type counter() const { return m_counter; }
private:
#ifndef NDEBUG
void check_invariant() const
{
int sum = 0;
for (int i = 0; i < history; ++i) sum += m_rate_history[i];
TORRENT_ASSERT(m_rate_sum == sum);
TORRENT_ASSERT(m_total_counter >= 0);
}
#endif
// history of rates a few seconds back
int m_rate_history[history];
// the accumulator for this second.
int m_counter;
// total counters
size_type m_total_counter;
// sum of all elements in m_rate_history
size_type m_rate_sum;
};
class TORRENT_EXPORT stat
{
friend class invariant_access;
public:
void operator+=(const stat& s)
{
for (int i = 0; i < num_channels; ++i)
m_stat[i] += s.m_stat[i];
}
void received_bytes(int bytes_payload, int bytes_protocol)
{
TORRENT_ASSERT(bytes_payload >= 0);
TORRENT_ASSERT(bytes_protocol >= 0);
m_stat[download_payload].add(bytes_payload);
m_stat[download_protocol].add(bytes_protocol);
}
void sent_bytes(int bytes_payload, int bytes_protocol)
{
TORRENT_ASSERT(bytes_payload >= 0);
TORRENT_ASSERT(bytes_protocol >= 0);
m_stat[upload_payload].add(bytes_payload);
m_stat[upload_protocol].add(bytes_protocol);
}
// calculate ip protocol overhead
void calc_ip_overhead()
{
int uploaded = m_stat[upload_protocol].counter()
+ m_stat[upload_payload].counter();
int downloaded = m_stat[download_protocol].counter()
+ m_stat[download_payload].counter();
// IP + TCP headers are 40 bytes per MTU (1460)
// bytes of payload, but at least 40 bytes
m_stat[upload_ip_protocol].add((std::max)(uploaded / 1460, uploaded>0?40:0));
m_stat[download_ip_protocol].add((std::max)(downloaded / 1460, downloaded>0?40:0));
// also account for ACK traffic. That adds to the transfers
// in the opposite direction. Even on connections with symmetric
// transfer rates, it seems to add a penalty.
m_stat[upload_ip_protocol].add((std::max)(downloaded * 40 / 1460, downloaded>0?40:0));
m_stat[download_ip_protocol].add((std::max)(uploaded * 40 / 1460, uploaded>0?40:0));
}
int upload_ip_overhead() const { return m_stat[upload_ip_protocol].counter(); }
int download_ip_overhead() const { return m_stat[download_ip_protocol].counter(); }
// should be called once every second
void second_tick(float tick_interval)
{
for (int i = 0; i < num_channels; ++i)
m_stat[i].second_tick(tick_interval);
}
float upload_rate() const
{
return (m_stat[upload_payload].rate_sum()
+ m_stat[upload_protocol].rate_sum()
+ m_stat[upload_ip_protocol].rate_sum())
/ float(stat_channel::history);
}
float download_rate() const
{
return (m_stat[download_payload].rate_sum()
+ m_stat[download_protocol].rate_sum()
+ m_stat[download_ip_protocol].rate_sum())
/ float(stat_channel::history);
}
float upload_payload_rate() const
{ return m_stat[upload_payload].rate(); }
float download_payload_rate() const
{ return m_stat[download_payload].rate(); }
size_type total_payload_upload() const
{ return m_stat[upload_payload].total(); }
size_type total_payload_download() const
{ return m_stat[download_payload].total(); }
size_type total_protocol_upload() const
{ return m_stat[upload_protocol].total(); }
size_type total_protocol_download() const
{ return m_stat[download_protocol].total(); }
// 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)
{
TORRENT_ASSERT(downloaded >= 0);
TORRENT_ASSERT(uploaded >= 0);
m_stat[download_payload].offset(downloaded);
m_stat[upload_payload].offset(uploaded);
}
size_type last_payload_downloaded() const
{ return m_stat[download_payload].counter(); }
size_type last_payload_uploaded() const
{ return m_stat[upload_payload].counter(); }
private:
// these are the channels we keep stats for
enum
{
upload_payload,
upload_protocol,
upload_ip_protocol,
download_payload,
download_protocol,
download_ip_protocol,
num_channels
};
stat_channel m_stat[num_channels];
};
}
#endif // TORRENT_STAT_HPP_INCLUDED

View File

@ -0,0 +1,422 @@
/*
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.
*/
#ifndef TORRENT_STORAGE_HPP_INCLUDE
#define TORRENT_STORAGE_HPP_INCLUDE
#include <vector>
#include <bitset>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/limits.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/filesystem/path.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/torrent_info.hpp"
#include "libtorrent/piece_picker.hpp"
#include "libtorrent/intrusive_ptr_base.hpp"
#include "libtorrent/peer_request.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/buffer.hpp"
namespace libtorrent
{
namespace aux
{
struct piece_checker_data;
}
namespace fs = boost::filesystem;
class session;
struct file_pool;
struct disk_io_job;
struct disk_buffer_holder;
enum storage_mode_t
{
storage_mode_allocate = 0,
storage_mode_sparse,
storage_mode_compact
};
#if defined(_WIN32) && defined(UNICODE)
TORRENT_EXPORT std::wstring safe_convert(std::string const& s);
#endif
TORRENT_EXPORT std::vector<std::pair<size_type, std::time_t> > get_filesizes(
file_storage const& t
, fs::path p);
TORRENT_EXPORT bool match_filesizes(
file_storage const& t
, fs::path p
, std::vector<std::pair<size_type, std::time_t> > const& sizes
, bool compact_mode
, std::string* error = 0);
struct TORRENT_EXPORT file_allocation_failed: std::exception
{
file_allocation_failed(const char* error_msg): m_msg(error_msg) {}
virtual const char* what() const throw() { return m_msg.c_str(); }
virtual ~file_allocation_failed() throw() {}
std::string m_msg;
};
struct TORRENT_EXPORT partial_hash
{
partial_hash(): offset(0) {}
// the number of bytes in the piece that has been hashed
int offset;
// the sha-1 context
hasher h;
};
struct TORRENT_EXPORT storage_interface
{
// create directories and set file sizes
// if allocate_files is true.
// allocate_files is true if allocation mode
// is set to full and sparse files are supported
// false return value indicates an error
virtual bool initialize(bool allocate_files) = 0;
// negative return value indicates an error
virtual int read(char* buf, int slot, int offset, int size) = 0;
// negative return value indicates an error
virtual int write(const char* buf, int slot, int offset, int size) = 0;
// non-zero return value indicates an error
virtual bool move_storage(fs::path save_path) = 0;
// verify storage dependent fast resume entries
virtual bool verify_resume_data(lazy_entry const& rd, std::string& error) = 0;
// write storage dependent fast resume entries
virtual bool write_resume_data(entry& rd) const = 0;
// moves (or copies) the content in src_slot to dst_slot
virtual bool move_slot(int src_slot, int dst_slot) = 0;
// swaps the data in slot1 and slot2
virtual bool swap_slots(int slot1, int slot2) = 0;
// swaps the puts the data in slot1 in slot2, the data in slot2
// in slot3 and the data in slot3 in slot1
virtual bool swap_slots3(int slot1, int slot2, int slot3) = 0;
// returns the sha1-hash for the data at the given slot
virtual sha1_hash hash_for_slot(int slot, partial_hash& h, int piece_size) = 0;
// this will close all open files that are opened for
// writing. This is called when a torrent has finished
// downloading.
// non-zero return value indicates an error
virtual bool release_files() = 0;
// this will rename the file specified by index.
virtual bool rename_file(int index, std::string const& new_filename) = 0;
// this will close all open files and delete them
// non-zero return value indicates an error
virtual bool delete_files() = 0;
void set_error(std::string const& file, std::string const& msg) const
{
m_error_file = file;
m_error = msg;
}
std::string const& error() const { return m_error; }
std::string const& error_file() const { return m_error_file; }
void clear_error() { m_error.clear(); m_error_file.clear(); }
mutable std::string m_error;
mutable std::string m_error_file;
virtual ~storage_interface() {}
};
typedef storage_interface* (&storage_constructor_type)(
file_storage const&, fs::path const&, file_pool&);
TORRENT_EXPORT storage_interface* default_storage_constructor(
file_storage const&, fs::path const&, file_pool&);
TORRENT_EXPORT storage_interface* mapped_storage_constructor(
file_storage const&, fs::path const&, file_pool&);
struct disk_io_thread;
class TORRENT_EXPORT piece_manager
: public intrusive_ptr_base<piece_manager>
, boost::noncopyable
{
friend class invariant_access;
friend struct disk_io_thread;
public:
piece_manager(
boost::shared_ptr<void> const& torrent
, boost::intrusive_ptr<torrent_info const> info
, fs::path const& path
, file_pool& fp
, disk_io_thread& io
, storage_constructor_type sc
, storage_mode_t sm);
~piece_manager();
boost::intrusive_ptr<torrent_info const> info() const { return m_info; }
void write_resume_data(entry& rd) const;
void async_check_fastresume(lazy_entry const* resume_data
, boost::function<void(int, disk_io_job const&)> const& handler);
void async_check_files(boost::function<void(int, disk_io_job const&)> const& handler);
void async_rename_file(int index, std::string const& name
, boost::function<void(int, disk_io_job const&)> const& handler);
void async_read(
peer_request const& r
, boost::function<void(int, disk_io_job const&)> const& handler
, int priority = 0);
void async_write(
peer_request const& r
, disk_buffer_holder& buffer
, boost::function<void(int, disk_io_job const&)> const& f);
void async_hash(int piece, boost::function<void(int, disk_io_job const&)> const& f);
void async_release_files(
boost::function<void(int, disk_io_job const&)> const& handler
= boost::function<void(int, disk_io_job const&)>());
void async_delete_files(
boost::function<void(int, disk_io_job const&)> const& handler
= boost::function<void(int, disk_io_job const&)>());
void async_move_storage(fs::path const& p
, boost::function<void(int, disk_io_job const&)> const& handler);
void async_save_resume_data(
boost::function<void(int, disk_io_job const&)> const& handler);
enum return_t
{
// return values from check_fastresume and check_files
no_error = 0,
need_full_check = -1,
fatal_disk_error = -2,
disk_check_aborted = -3
};
private:
fs::path save_path() const;
bool verify_resume_data(lazy_entry const& rd, std::string& error)
{ return m_storage->verify_resume_data(rd, error); }
bool is_allocating() const
{ return m_state == state_expand_pieces; }
void mark_failed(int index);
std::string const& error() const { return m_storage->error(); }
std::string const& error_file() const { return m_storage->error_file(); }
void clear_error() { m_storage->clear_error(); }
int slot_for(int piece) const;
int piece_for(int slot) const;
// helper functions for check_dastresume
int check_no_fastresume(std::string& error);
int check_init_storage(std::string& error);
// if error is set and return value is 'no_error' or 'need_full_check'
// the error message indicates that the fast resume data was rejected
// if 'fatal_disk_error' is returned, the error message indicates what
// when wrong in the disk access
int check_fastresume(lazy_entry const& rd, std::string& error);
// this function returns true if the checking is complete
int check_files(int& current_slot, int& have_piece, std::string& error);
bool compact_allocation() const
{ return m_storage_mode == storage_mode_compact; }
#ifndef NDEBUG
std::string name() const { return m_info->name(); }
#endif
bool allocate_slots(int num_slots, bool abort_on_disk = false);
int read_impl(
char* buf
, int piece_index
, int offset
, int size);
int write_impl(
const char* buf
, int piece_index
, int offset
, int size);
bool check_one_piece(int& have_piece);
int identify_data(
const std::vector<char>& piece_data
, int current_slot);
void switch_to_full_mode();
sha1_hash hash_for_piece_impl(int piece);
int release_files_impl() { return m_storage->release_files(); }
int delete_files_impl() { return m_storage->delete_files(); }
int rename_file_impl(int index, std::string const& new_filename)
{ return m_storage->rename_file(index, new_filename); }
int move_storage_impl(fs::path const& save_path);
int allocate_slot_for_piece(int piece_index);
#ifndef NDEBUG
void check_invariant() const;
#ifdef TORRENT_STORAGE_DEBUG
void debug_log() const;
#endif
#endif
boost::intrusive_ptr<torrent_info const> m_info;
file_storage const& m_files;
boost::scoped_ptr<storage_interface> m_storage;
storage_mode_t m_storage_mode;
// slots that haven't had any file storage allocated
std::vector<int> m_unallocated_slots;
// slots that have file storage, but isn't assigned to a piece
std::vector<int> m_free_slots;
enum
{
has_no_slot = -3 // the piece has no storage
};
// maps piece indices to slots. If a piece doesn't
// have any storage, it is set to 'has_no_slot'
std::vector<int> m_piece_to_slot;
enum
{
unallocated = -1, // the slot is unallocated
unassigned = -2 // the slot is allocated but not assigned to a piece
};
// maps slots to piece indices, if a slot doesn't have a piece
// it can either be 'unassigned' or 'unallocated'
std::vector<int> m_slot_to_piece;
fs::path m_save_path;
mutable boost::recursive_mutex m_mutex;
enum {
// the default initial state
state_none,
// the file checking is complete
state_finished,
// checking the files
state_full_check,
// move pieces to their final position
state_expand_pieces
} m_state;
int m_current_slot;
// used during check. If any piece is found
// that is not in its final position, this
// is set to true
bool m_out_of_place;
// used to move pieces while expanding
// the storage from compact allocation
// to full allocation
buffer m_scratch_buffer;
buffer m_scratch_buffer2;
// the piece that is in the scratch buffer
int m_scratch_piece;
// this is saved in case we need to instantiate a new
// storage (osed when remapping files)
storage_constructor_type m_storage_constructor;
// temporary buffer used while checking
std::vector<char> m_piece_data;
// this maps a piece hash to piece index. It will be
// build the first time it is used (to save time if it
// isn't needed)
std::multimap<sha1_hash, int> m_hash_to_piece;
// this map contains partial hashes for downloading
// pieces. This is only accessed from within the
// disk-io thread.
std::map<int, partial_hash> m_piece_hasher;
disk_io_thread& m_io_thread;
// the reason for this to be a void pointer
// is to avoid creating a dependency on the
// torrent. This shared_ptr is here only
// to keep the torrent object alive until
// the piece_manager destructs. This is because
// the torrent_info object is owned by the torrent.
boost::shared_ptr<void> m_torrent;
};
}
#endif // TORRENT_STORAGE_HPP_INCLUDED

View File

@ -0,0 +1,410 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_TIME_HPP_INCLUDED
#define TORRENT_TIME_HPP_INCLUDED
#include <ctime>
#include <boost/version.hpp>
#ifndef _WIN32
#include <unistd.h>
#endif
namespace libtorrent
{
inline char const* time_now_string()
{
time_t t = std::time(0);
tm* timeinfo = std::localtime(&t);
static char str[200];
std::strftime(str, 200, "%b %d %X", timeinfo);
return str;
}
std::string log_time();
}
#if (!defined (__MACH__) && !defined (_WIN32) && (!defined(_POSIX_MONOTONIC_CLOCK) \
|| _POSIX_MONOTONIC_CLOCK < 0)) || defined (TORRENT_USE_BOOST_DATE_TIME)
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include "libtorrent/assert.hpp"
namespace libtorrent
{
typedef boost::posix_time::ptime ptime;
typedef boost::posix_time::time_duration time_duration;
inline ptime time_now()
{ return boost::posix_time::microsec_clock::universal_time(); }
inline ptime min_time()
{ return boost::posix_time::ptime(boost::posix_time::min_date_time); }
inline ptime max_time()
{ return boost::posix_time::ptime(boost::posix_time::max_date_time); }
inline time_duration seconds(int s) { return boost::posix_time::seconds(s); }
inline time_duration milliseconds(int s) { return boost::posix_time::milliseconds(s); }
inline time_duration microsec(int s) { return boost::posix_time::microsec(s); }
inline time_duration minutes(int s) { return boost::posix_time::minutes(s); }
inline time_duration hours(int s) { return boost::posix_time::hours(s); }
inline int total_seconds(time_duration td)
{ return td.total_seconds(); }
inline int total_milliseconds(time_duration td)
{ return td.total_milliseconds(); }
inline boost::int64_t total_microseconds(time_duration td)
{ return td.total_microseconds(); }
}
#else
#if BOOST_VERSION < 103500
#include <asio/time_traits.hpp>
#else
#include <boost/asio/time_traits.hpp>
#endif
#include <boost/cstdint.hpp>
#include "libtorrent/assert.hpp"
namespace libtorrent
{
// libtorrent time_duration type
struct time_duration
{
time_duration() {}
time_duration operator/(int rhs) const { return time_duration(diff / rhs); }
explicit time_duration(boost::int64_t d) : diff(d) {}
time_duration& operator-=(time_duration const& c) { diff -= c.diff; return *this; }
time_duration& operator+=(time_duration const& c) { diff += c.diff; return *this; }
time_duration operator+(time_duration const& c) { return time_duration(diff + c.diff); }
boost::int64_t diff;
};
inline bool is_negative(time_duration dt) { return dt.diff < 0; }
inline bool operator<(time_duration lhs, time_duration rhs)
{ return lhs.diff < rhs.diff; }
inline bool operator<=(time_duration lhs, time_duration rhs)
{ return lhs.diff <= rhs.diff; }
inline bool operator>(time_duration lhs, time_duration rhs)
{ return lhs.diff > rhs.diff; }
inline bool operator>=(time_duration lhs, time_duration rhs)
{ return lhs.diff >= rhs.diff; }
// libtorrent time type
struct ptime
{
ptime() {}
explicit ptime(boost::int64_t t): time(t) {}
boost::int64_t time;
};
inline bool operator>(ptime lhs, ptime rhs)
{ return lhs.time > rhs.time; }
inline bool operator>=(ptime lhs, ptime rhs)
{ return lhs.time >= rhs.time; }
inline bool operator<=(ptime lhs, ptime rhs)
{ return lhs.time <= rhs.time; }
inline bool operator<(ptime lhs, ptime rhs)
{ return lhs.time < rhs.time; }
inline bool operator!=(ptime lhs, ptime rhs)
{ return lhs.time != rhs.time;}
inline bool operator==(ptime lhs, ptime rhs)
{ return lhs.time == rhs.time;}
inline time_duration operator-(ptime lhs, ptime rhs)
{ return time_duration(lhs.time - rhs.time); }
inline ptime operator+(ptime lhs, time_duration rhs)
{ return ptime(lhs.time + rhs.diff); }
inline ptime operator+(time_duration lhs, ptime rhs)
{ return ptime(rhs.time + lhs.diff); }
inline ptime operator-(ptime lhs, time_duration rhs)
{ return ptime(lhs.time - rhs.diff); }
ptime time_now();
inline ptime min_time() { return ptime(0); }
inline ptime max_time() { return ptime((std::numeric_limits<boost::int64_t>::max)()); }
int total_seconds(time_duration td);
int total_milliseconds(time_duration td);
boost::int64_t total_microseconds(time_duration td);
}
// asio time_traits
#if BOOST_VERSION >= 103500
namespace boost {
#endif
namespace asio
{
template<>
struct time_traits<libtorrent::ptime>
{
typedef libtorrent::ptime time_type;
typedef libtorrent::time_duration duration_type;
static time_type now()
{ return time_type(libtorrent::time_now()); }
static time_type add(time_type t, duration_type d)
{ return time_type(t.time + d.diff);}
static duration_type subtract(time_type t1, time_type t2)
{ return duration_type(t1 - t2); }
static bool less_than(time_type t1, time_type t2)
{ return t1 < t2; }
static boost::posix_time::time_duration to_posix_duration(
duration_type d)
{ return boost::posix_time::microseconds(libtorrent::total_microseconds(d)); }
};
}
#if BOOST_VERSION >= 103500
}
#endif
#if defined(__MACH__)
#include <mach/mach_time.h>
#include <boost/cstdint.hpp>
#include "libtorrent/assert.hpp"
// high precision timer for darwin intel and ppc
namespace libtorrent
{
namespace aux
{
inline boost::int64_t absolutetime_to_microseconds(boost::int64_t at)
{
static mach_timebase_info_data_t timebase_info = {0,0};
if (timebase_info.denom == 0)
mach_timebase_info(&timebase_info);
// make sure we don't overflow
TORRENT_ASSERT((at >= 0 && at >= at / 1000 * timebase_info.numer / timebase_info.denom)
|| (at < 0 && at < at / 1000 * timebase_info.numer / timebase_info.denom));
return at / 1000 * timebase_info.numer / timebase_info.denom;
}
inline boost::int64_t microseconds_to_absolutetime(boost::int64_t ms)
{
static mach_timebase_info_data_t timebase_info = {0,0};
if (timebase_info.denom == 0)
{
mach_timebase_info(&timebase_info);
TORRENT_ASSERT(timebase_info.numer > 0);
TORRENT_ASSERT(timebase_info.denom > 0);
}
// make sure we don't overflow
TORRENT_ASSERT((ms >= 0 && ms <= ms * timebase_info.denom / timebase_info.numer * 1000)
|| (ms < 0 && ms > ms * timebase_info.denom / timebase_info.numer * 1000));
return ms * timebase_info.denom / timebase_info.numer * 1000;
}
}
inline int total_seconds(time_duration td)
{
return aux::absolutetime_to_microseconds(td.diff)
/ 1000000;
}
inline int total_milliseconds(time_duration td)
{
return aux::absolutetime_to_microseconds(td.diff)
/ 1000;
}
inline boost::int64_t total_microseconds(time_duration td)
{
return aux::absolutetime_to_microseconds(td.diff);
}
inline ptime time_now() { return ptime(mach_absolute_time()); }
inline time_duration microsec(boost::int64_t s)
{
return time_duration(aux::microseconds_to_absolutetime(s));
}
inline time_duration milliseconds(boost::int64_t s)
{
return time_duration(aux::microseconds_to_absolutetime(s * 1000));
}
inline time_duration seconds(boost::int64_t s)
{
return time_duration(aux::microseconds_to_absolutetime(s * 1000000));
}
inline time_duration minutes(boost::int64_t s)
{
return time_duration(aux::microseconds_to_absolutetime(s * 1000000 * 60));
}
inline time_duration hours(boost::int64_t s)
{
return time_duration(aux::microseconds_to_absolutetime(s * 1000000 * 60 * 60));
}
}
#elif defined(_WIN32)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include "libtorrent/assert.hpp"
namespace libtorrent
{
namespace aux
{
inline boost::int64_t performance_counter_to_microseconds(boost::int64_t pc)
{
static LARGE_INTEGER performace_counter_frequency = {0,0};
if (performace_counter_frequency.QuadPart == 0)
QueryPerformanceFrequency(&performace_counter_frequency);
#ifndef NDEBUG
// make sure we don't overflow
boost::int64_t ret = (pc * 1000 / performace_counter_frequency.QuadPart) * 1000;
TORRENT_ASSERT((pc >= 0 && pc >= ret) || (pc < 0 && pc < ret));
#endif
return (pc * 1000 / performace_counter_frequency.QuadPart) * 1000;
}
inline boost::int64_t microseconds_to_performance_counter(boost::int64_t ms)
{
static LARGE_INTEGER performace_counter_frequency = {0,0};
if (performace_counter_frequency.QuadPart == 0)
QueryPerformanceFrequency(&performace_counter_frequency);
#ifndef NDEBUG
// make sure we don't overflow
boost::int64_t ret = (ms / 1000) * performace_counter_frequency.QuadPart / 1000;
TORRENT_ASSERT((ms >= 0 && ms <= ret)
|| (ms < 0 && ms > ret));
#endif
return (ms / 1000) * performace_counter_frequency.QuadPart / 1000;
}
}
inline int total_seconds(time_duration td)
{
return int(aux::performance_counter_to_microseconds(td.diff)
/ 1000000);
}
inline int total_milliseconds(time_duration td)
{
return int(aux::performance_counter_to_microseconds(td.diff)
/ 1000);
}
inline boost::int64_t total_microseconds(time_duration td)
{
return aux::performance_counter_to_microseconds(td.diff);
}
inline ptime time_now()
{
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
return ptime(now.QuadPart);
}
inline time_duration microsec(boost::int64_t s)
{
return time_duration(aux::microseconds_to_performance_counter(s));
}
inline time_duration milliseconds(boost::int64_t s)
{
return time_duration(aux::microseconds_to_performance_counter(
s * 1000));
}
inline time_duration seconds(boost::int64_t s)
{
return time_duration(aux::microseconds_to_performance_counter(
s * 1000000));
}
inline time_duration minutes(boost::int64_t s)
{
return time_duration(aux::microseconds_to_performance_counter(
s * 1000000 * 60));
}
inline time_duration hours(boost::int64_t s)
{
return time_duration(aux::microseconds_to_performance_counter(
s * 1000000 * 60 * 60));
}
}
#elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0
#include <time.h>
#include "libtorrent/assert.hpp"
namespace libtorrent
{
inline int total_seconds(time_duration td)
{
return td.diff / 1000000;
}
inline int total_milliseconds(time_duration td)
{
return td.diff / 1000;
}
inline boost::int64_t total_microseconds(time_duration td)
{
return td.diff;
}
inline ptime time_now()
{
timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ptime(boost::int64_t(ts.tv_sec) * 1000000 + ts.tv_nsec / 1000);
}
inline time_duration microsec(boost::int64_t s)
{
return time_duration(s);
}
inline time_duration milliseconds(boost::int64_t s)
{
return time_duration(s * 1000);
}
inline time_duration seconds(boost::int64_t s)
{
return time_duration(s * 1000000);
}
inline time_duration minutes(boost::int64_t s)
{
return time_duration(s * 1000000 * 60);
}
inline time_duration hours(boost::int64_t s)
{
return time_duration(s * 1000000 * 60 * 60);
}
}
#endif
#endif
#endif

View File

@ -0,0 +1,966 @@
/*
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.
*/
#ifndef TORRENT_TORRENT_HPP_INCLUDE
#define TORRENT_TORRENT_HPP_INCLUDE
#include <algorithm>
#include <vector>
#include <set>
#include <list>
#include <iostream>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/limits.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/intrusive_ptr.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/torrent_info.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/policy.hpp"
#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/stat.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/piece_picker.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/escape_string.hpp"
#include "libtorrent/bandwidth_limit.hpp"
#include "libtorrent/bandwidth_queue_entry.hpp"
#include "libtorrent/storage.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/bitfield.hpp"
namespace libtorrent
{
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
struct logger;
#endif
class piece_manager;
struct torrent_plugin;
struct bitfield;
namespace aux
{
struct session_impl;
struct piece_checker_data;
}
namespace fs = boost::filesystem;
// a torrent is a class that holds information
// for a specific download. It updates itself against
// the tracker
class TORRENT_EXPORT torrent: public request_callback
, public boost::enable_shared_from_this<torrent>
{
public:
torrent(
aux::session_impl& ses
, boost::intrusive_ptr<torrent_info> tf
, fs::path const& save_path
, tcp::endpoint const& net_interface
, storage_mode_t m_storage_mode
, int block_size
, storage_constructor_type sc
, bool paused
, std::vector<char>* resume_data
, int seq
, bool auto_managed);
// used with metadata-less torrents
// (the metadata is downloaded from the peers)
torrent(
aux::session_impl& ses
, char const* tracker_url
, sha1_hash const& info_hash
, char const* name
, fs::path const& save_path
, tcp::endpoint const& net_interface
, storage_mode_t m_storage_mode
, int block_size
, storage_constructor_type sc
, bool paused
, std::vector<char>* resume_data
, int seq
, bool auto_managed);
~torrent();
void parse_resume_data(std::vector<char>* resume_data);
// starts the announce timer
void start();
#ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::shared_ptr<torrent_plugin>);
void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> const& ext
, void* userdata);
#endif
#ifndef NDEBUG
bool has_peer(peer_connection* p) const
{ return m_connections.find(p) != m_connections.end(); }
#endif
// this is called when the torrent has metadata.
// it will initialize the storage and the piece-picker
void init();
void on_resume_data_checked(int ret, disk_io_job const& j);
void on_force_recheck(int ret, disk_io_job const& j);
void on_piece_checked(int ret, disk_io_job const& j);
void files_checked();
void start_checking();
int seed_rank(session_settings const& s) const;
storage_mode_t storage_mode() const { return m_storage_mode; }
// this will flag the torrent as aborted. The main
// loop in session_impl will check for this state
// on all torrents once every second, and take
// the necessary actions then.
void abort();
bool is_aborted() const { return m_abort; }
torrent_status::state_t state() const { return m_state; }
session_settings const& settings() const;
aux::session_impl& session() { return m_ses; }
void set_sequential_download(bool sd);
bool is_sequential_download() const
{ return m_sequential_download; }
void set_queue_position(int p);
int queue_position() const { return m_sequence_number; }
void second_tick(stat& accumulator, float tick_interval);
// debug purpose only
void print(std::ostream& os) const;
std::string name() const;
stat statistics() const { return m_stat; }
void add_stats(stat const& s) { m_stat += s; }
size_type bytes_left() const;
boost::tuples::tuple<size_type, size_type> bytes_done() const;
size_type quantized_bytes_done() const;
void ip_filter_updated() { m_policy.ip_filter_updated(); }
bool has_error() const { return !m_error.empty(); }
void pause();
void resume();
void do_pause();
void do_resume();
bool is_paused() const;
bool is_torrent_paused() const { return m_paused; }
void force_recheck();
void save_resume_data();
bool is_auto_managed() const { return m_auto_managed; }
void auto_managed(bool a);
void delete_files();
// ============ start deprecation =============
void filter_piece(int index, bool filter);
void filter_pieces(std::vector<bool> const& bitmask);
bool is_piece_filtered(int index) const;
void filtered_pieces(std::vector<bool>& bitmask) const;
void filter_files(std::vector<bool> const& files);
// ============ end deprecation =============
void piece_availability(std::vector<int>& avail) const;
void set_piece_priority(int index, int priority);
int piece_priority(int index) const;
void prioritize_pieces(std::vector<int> const& pieces);
void piece_priorities(std::vector<int>&) const;
void prioritize_files(std::vector<int> const& files);
torrent_status status() const;
void file_progress(std::vector<float>& fp) const;
void use_interface(const char* net_interface);
tcp::endpoint const& get_interface() const { return m_net_interface; }
void connect_to_url_seed(std::string const& url);
bool connect_to_peer(policy::peer* peerinfo);
void set_ratio(float ratio)
{ TORRENT_ASSERT(ratio >= 0.0f); m_ratio = ratio; }
float ratio() const
{ return m_ratio; }
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
void resolve_countries(bool r)
{ m_resolve_countries = r; }
bool resolving_countries() const { return m_resolve_countries; }
#endif
// --------------------------------------------
// BANDWIDTH MANAGEMENT
bandwidth_limit m_bandwidth_limit[2];
void request_bandwidth(int channel
, boost::intrusive_ptr<peer_connection> const& p
, int max_block_size, int priority);
void perform_bandwidth_request(int channel
, boost::intrusive_ptr<peer_connection> const& p
, int block_size, int priority);
void expire_bandwidth(int channel, int amount);
void assign_bandwidth(int channel, int amount, int blk);
int bandwidth_throttle(int channel) const;
int max_assignable_bandwidth(int channel) const
{ return m_bandwidth_limit[channel].max_assignable(); }
int bandwidth_queue_size(int channel) const;
// --------------------------------------------
// PEER MANAGEMENT
// add or remove a url that will be attempted for
// finding the file(s) in this torrent.
void add_url_seed(std::string const& url)
{ m_web_seeds.insert(url); }
void remove_url_seed(std::string const& url)
{ m_web_seeds.erase(url); }
void retry_url_seed(std::string const& url);
std::set<std::string> url_seeds() const
{ return m_web_seeds; }
bool free_upload_slots() const
{ return m_num_uploads < m_max_uploads; }
void choke_peer(peer_connection& c);
bool unchoke_peer(peer_connection& c);
// used by peer_connection to attach itself to a torrent
// since incoming connections don't know what torrent
// they're a part of until they have received an info_hash.
// false means attach failed
bool attach_peer(peer_connection* p);
// this will remove the peer and make sure all
// the pieces it had have their reference counter
// decreased in the piece_picker
void remove_peer(peer_connection* p);
void cancel_block(piece_block block);
bool want_more_peers() const;
bool try_connect_peer();
void give_connect_points(int points);
// the number of peers that belong to this torrent
int num_peers() const { return (int)m_connections.size(); }
int num_seeds() const;
typedef std::set<peer_connection*>::iterator peer_iterator;
typedef std::set<peer_connection*>::const_iterator const_peer_iterator;
const_peer_iterator begin() const { return m_connections.begin(); }
const_peer_iterator end() const { return m_connections.end(); }
peer_iterator begin() { return m_connections.begin(); }
peer_iterator end() { return m_connections.end(); }
void resolve_peer_country(boost::intrusive_ptr<peer_connection> const& p) const;
void get_full_peer_list(std::vector<peer_list_entry>& v) const;
void get_peer_info(std::vector<peer_info>& v);
void get_download_queue(std::vector<partial_piece_info>& queue);
// --------------------------------------------
// TRACKER MANAGEMENT
// these are callbacks called by the tracker_connection instance
// (either http_tracker_connection or udp_tracker_connection)
// when this torrent got a response from its tracker request
// or when a failure occured
virtual void tracker_response(
tracker_request const& r
, std::vector<peer_entry>& e, int interval
, int complete, int incomplete, address const& external_ip);
virtual void tracker_request_timed_out(
tracker_request const& r);
virtual void tracker_request_error(tracker_request const& r
, int response_code, const std::string& str);
virtual void tracker_warning(tracker_request const& req
, std::string const& msg);
virtual void tracker_scrape_response(tracker_request const& req
, int complete, int incomplete, int downloaded);
// generates a request string for sending
// to the tracker
tracker_request generate_tracker_request();
// if no password and username is set
// this will return an empty string, otherwise
// it will concatenate the login and password
// ready to be sent over http (but without
// base64 encoding).
std::string tracker_login() const;
// returns the absolute time when the next tracker
// announce will take place.
ptime next_announce() const;
// returns true if it is time for this torrent to make another
// tracker request
bool should_request();
// forcefully sets next_announce to the current time
void force_tracker_request();
void force_tracker_request(ptime);
void scrape_tracker();
ptime const& last_scrape() const { return m_last_scrape; }
// sets the username and password that will be sent to
// the tracker
void set_tracker_login(std::string const& name, std::string const& pw);
// the tcp::endpoint of the tracker that we managed to
// announce ourself at the last time we tried to announce
const tcp::endpoint& current_tracker() const;
// --------------------------------------------
// PIECE MANAGEMENT
// returns true if we have downloaded the given piece
bool have_piece(int index) const
{
return has_picker()?m_picker->have_piece(index):true;
}
int num_have() const
{
return has_picker()
?m_picker->num_have()
:m_torrent_file->num_pieces();
}
// when we get a have message, this is called for that piece
void peer_has(int index)
{
if (m_picker.get())
{
TORRENT_ASSERT(!is_seed());
m_picker->inc_refcount(index);
}
#ifndef NDEBUG
else
{
TORRENT_ASSERT(is_seed());
}
#endif
}
// when we get a bitfield message, this is called for that piece
void peer_has(bitfield const& bits)
{
if (m_picker.get())
{
TORRENT_ASSERT(!is_seed());
m_picker->inc_refcount(bits);
}
#ifndef NDEBUG
else
{
TORRENT_ASSERT(is_seed());
}
#endif
}
void peer_has_all()
{
if (m_picker.get())
{
TORRENT_ASSERT(!is_seed());
m_picker->inc_refcount_all();
}
#ifndef NDEBUG
else
{
TORRENT_ASSERT(is_seed());
}
#endif
}
void peer_lost(int index)
{
if (m_picker.get())
{
TORRENT_ASSERT(!is_seed());
m_picker->dec_refcount(index);
}
#ifndef NDEBUG
else
{
TORRENT_ASSERT(is_seed());
}
#endif
}
int block_size() const { TORRENT_ASSERT(m_block_size > 0); return m_block_size; }
peer_request to_req(piece_block const& p);
void disconnect_all();
int disconnect_peers(int num);
// this is called wheh the torrent has completed
// the download. It will post an event, disconnect
// all seeds and let the tracker know we're finished.
void completed();
// this is the asio callback that is called when a name
// lookup for a PEER is completed.
void on_peer_name_lookup(error_code const& e, tcp::resolver::iterator i
, peer_id pid);
// this is the asio callback that is called when a name
// lookup for a WEB SEED is completed.
void on_name_lookup(error_code const& e, tcp::resolver::iterator i
, std::string url, tcp::endpoint proxy);
// this is the asio callback that is called when a name
// lookup for a proxy for a web seed is completed.
void on_proxy_name_lookup(error_code const& e, tcp::resolver::iterator i
, std::string url);
// this is called when the torrent has finished. i.e.
// all the pieces we have not filtered have been downloaded.
// If no pieces are filtered, this is called first and then
// completed() is called immediately after it.
void finished();
// This is the opposite of finished. It is called if we used
// to be finished but enabled some files for download so that
// we wasn't finished anymore.
void resume_download();
void async_verify_piece(int piece_index, boost::function<void(int)> const&);
// this is called from the peer_connection
// each time a piece has failed the hash
// test
void piece_finished(int index, int passed_hash_check);
// piece_passed is called when a piece passes the hash check
// this will tell all peers that we just got his piece
// and also let the piece picker know that we have this piece
// so it wont pick it for download
void piece_passed(int index);
// piece_failed is called when a piece fails the hash check
void piece_failed(int index);
// this will restore the piece picker state for a piece
// by re marking all the requests to blocks in this piece
// that are still outstanding in peers' download queues.
// this is done when a piece fails
void restore_piece_state(int index);
void received_redundant_data(int num_bytes)
{ TORRENT_ASSERT(num_bytes > 0); m_total_redundant_bytes += num_bytes; }
// this is true if we have all the pieces
bool is_seed() const
{
return valid_metadata()
&& (!m_picker
|| m_state == torrent_status::seeding
|| m_picker->num_have() == m_picker->num_pieces());
}
// this is true if we have all the pieces that we want
bool is_finished() const
{
if (is_seed()) return true;
return valid_metadata() && m_torrent_file->num_pieces()
- m_picker->num_have() - m_picker->num_filtered() == 0;
}
fs::path save_path() const;
alert_manager& alerts() const;
piece_picker& picker()
{
TORRENT_ASSERT(m_picker.get());
return *m_picker;
}
bool has_picker() const
{
return m_picker.get() != 0;
}
policy& get_policy() { return m_policy; }
piece_manager& filesystem();
torrent_info const& torrent_file() const
{ return *m_torrent_file; }
std::vector<announce_entry> const& trackers() const
{ return m_trackers; }
void replace_trackers(std::vector<announce_entry> const& urls);
torrent_handle get_handle();
void write_resume_data(entry& rd) const;
void read_resume_data(lazy_entry const& rd);
// LOGGING
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
virtual void debug_log(const std::string& line);
#endif
// DEBUG
#ifndef NDEBUG
void check_invariant() const;
#endif
// --------------------------------------------
// RESOURCE MANAGEMENT
void set_peer_upload_limit(tcp::endpoint ip, int limit);
void set_peer_download_limit(tcp::endpoint ip, int limit);
void set_upload_limit(int limit);
int upload_limit() const;
void set_download_limit(int limit);
int download_limit() const;
void set_max_uploads(int limit);
int max_uploads() const { return m_max_uploads; }
void set_max_connections(int limit);
int max_connections() const { return m_max_connections; }
void move_storage(fs::path const& save_path);
// renames the file with the given index to the new name
// the name may include a directory path
// returns false on failure
bool rename_file(int index, std::string const& name);
// unless this returns true, new connections must wait
// with their initialization.
bool ready_for_connections() const
{ return m_connections_initialized; }
bool valid_metadata() const
{ return m_torrent_file->is_valid(); }
// parses the info section from the given
// bencoded tree and moves the torrent
// to the checker thread for initial checking
// of the storage.
// a return value of false indicates an error
bool set_metadata(lazy_entry const& metadata, std::string& error);
int sequence_number() const { return m_sequence_number; }
private:
void on_files_deleted(int ret, disk_io_job const& j);
void on_files_released(int ret, disk_io_job const& j);
void on_torrent_paused(int ret, disk_io_job const& j);
void on_storage_moved(int ret, disk_io_job const& j);
void on_save_resume_data(int ret, disk_io_job const& j);
void on_file_renamed(int ret, disk_io_job const& j);
void on_piece_verified(int ret, disk_io_job const& j
, boost::function<void(int)> f);
void try_next_tracker();
int prioritize_tracker(int tracker_index);
void on_country_lookup(error_code const& error, tcp::resolver::iterator i
, boost::intrusive_ptr<peer_connection> p) const;
bool request_bandwidth_from_session(int channel) const;
void update_peer_interest(bool was_finished);
policy m_policy;
// total time we've been available on this torrent
// does not count when the torrent is stopped or paused
time_duration m_active_time;
// total time we've been available as a seed on this torrent
// does not count when the torrent is stopped or paused
time_duration m_seeding_time;
// all time totals of uploaded and downloaded payload
// stored in resume data
size_type m_total_uploaded;
size_type m_total_downloaded;
// if this torrent is running, this was the time
// when it was started. This is used to have a
// bias towards keeping seeding torrents that
// recently was started, to avoid oscillation
ptime m_started;
// the last time we initiated a scrape request to
// one of the trackers in this torrent
ptime m_last_scrape;
boost::intrusive_ptr<torrent_info> m_torrent_file;
tracker_request::event_t m_event;
void parse_response(const entry& e, std::vector<peer_entry>& peer_list);
// if this pointer is 0, the torrent is in
// a state where the metadata hasn't been
// received yet.
// the piece_manager keeps the torrent object
// alive by holding a shared_ptr to it and
// the torrent keeps the piece manager alive
// with this intrusive_ptr. This cycle is
// broken when torrent::abort() is called
// Then the torrent releases the piece_manager
// and when the piece_manager is complete with all
// outstanding disk io jobs (that keeps
// the piece_manager alive) it will destruct
// and release the torrent file. The reason for
// this is that the torrent_info is used by
// the piece_manager, and stored in the
// torrent, so the torrent cannot destruct
// before the piece_manager.
boost::intrusive_ptr<piece_manager> m_owning_storage;
// this is a weak (non owninig) pointer to
// the piece_manager. This is used after the torrent
// has been aborted, and it can no longer own
// the object.
piece_manager* m_storage;
// the time of next tracker request
ptime m_next_request;
#ifndef NDEBUG
public:
#endif
std::set<peer_connection*> m_connections;
#ifndef NDEBUG
private:
#endif
// The list of web seeds in this torrent. Seeds
// with fatal errors are removed from the set
std::set<std::string> m_web_seeds;
// a list of web seeds that have failed and are
// waiting to be retried
std::map<std::string, ptime> m_web_seeds_next_retry;
// urls of the web seeds that we are currently
// resolving the address for
std::set<std::string> m_resolving_web_seeds;
#ifndef TORRENT_DISABLE_EXTENSIONS
typedef std::list<boost::shared_ptr<torrent_plugin> > extension_list_t;
extension_list_t m_extensions;
#endif
// used to resolve the names of web seeds
mutable tcp::resolver m_host_resolver;
// this announce timer is used both
// by Local service discovery and
// by the DHT.
deadline_timer m_announce_timer;
static void on_announce_disp(boost::weak_ptr<torrent> p
, error_code const& e);
// this is called once per announce interval
void on_announce();
#ifndef TORRENT_DISABLE_DHT
static void on_dht_announce_response_disp(boost::weak_ptr<torrent> t
, std::vector<tcp::endpoint> const& peers);
void on_dht_announce_response(std::vector<tcp::endpoint> const& peers);
bool should_announce_dht() const;
// the time when the DHT was last announced of our
// presence on this torrent
ptime m_last_dht_announce;
#endif
// this is the upload and download statistics for the whole torrent.
// it's updated from all its peers once every second.
libtorrent::stat m_stat;
// -----------------------------
// a back reference to the session
// this torrent belongs to.
aux::session_impl& m_ses;
boost::scoped_ptr<piece_picker> m_picker;
// the queue of peer_connections that want more bandwidth
typedef std::deque<bw_queue_entry<peer_connection, torrent> > queue_t;
queue_t m_bandwidth_queue[2];
std::vector<announce_entry> m_trackers;
// this is an index into m_trackers
// the number of bytes that has been
// downloaded that failed the hash-test
size_type m_total_failed_bytes;
size_type m_total_redundant_bytes;
std::string m_username;
std::string m_password;
// the network interface all outgoing connections
// are opened through
tcp::endpoint m_net_interface;
fs::path m_save_path;
// determines the storage state for this torrent.
storage_mode_t m_storage_mode;
// the state of this torrent (queued, checking, downloading)
torrent_status::state_t m_state;
// if there's an error on this torrent, this is the
// error message
std::string m_error;
// used if there is any resume data
std::vector<char> m_resume_data;
lazy_entry m_resume_entry;
// if the torrent is started without metadata, it may
// still be given a name until the metadata is received
// once the metadata is received this field will no
// longer be used and will be reset
boost::scoped_ptr<std::string> m_name;
session_settings const& m_settings;
storage_constructor_type m_storage_constructor;
float m_progress;
// the upload/download ratio that each peer
// tries to maintain.
// 0 is infinite
float m_ratio;
// the maximum number of uploads for this torrent
int m_max_uploads;
// the number of unchoked peers in this torrent
int m_num_uploads;
// the maximum number of connections for this torrent
int m_max_connections;
// the size of a request block
// each piece is divided into these
// blocks when requested
int m_block_size;
// -----------------------------
// DATA FROM TRACKER RESPONSE
// the scrape data from the tracker response, this
// is optional and may be -1.
int m_complete;
int m_incomplete;
#ifndef NDEBUG
// this is the amount downloaded when this torrent
// is started. i.e.
// total_done - m_initial_done <= total_payload_download
size_type m_initial_done;
#endif
// this is the deficit counter in the Deficit Round Robin
// used to determine which torrent gets the next
// connection attempt. See:
// http://www.ecs.umass.edu/ece/wolf/courses/ECE697J/papers/DRR.pdf
// The quanta assigned to each torrent depends on the torrents
// priority, whether it's seed and the number of connected
// peers it has. This has the effect that some torrents
// will have more connection attempts than other. Each
// connection attempt costs 100 points from the deficit
// counter. points are deducted in try_connect_peer and
// increased in give_connect_points. Outside of the
// torrent object, these points are called connect_points.
int m_deficit_counter;
// the number number of seconds between requests
// from the tracker
boost::int16_t m_duration;
// the sequence number for this torrent, this is a
// monotonically increasing number for each added torrent
boost::int16_t m_sequence_number;
// the index to the last tracker that worked
boost::int8_t m_last_working_tracker;
// the tracker that is currently (or was last)
// tried
boost::int8_t m_currently_trying_tracker;
// the number of connection attempts that has
// failed in a row, this is currently used to
// determine the timeout until next try.
boost::int8_t m_failed_trackers;
// this is a counter that is decreased every
// second, and when it reaches 0, the policy::pulse()
// is called and the time scaler is reset to 10.
boost::int8_t m_time_scaler;
// is set to true when the torrent has
// been aborted.
bool m_abort:1;
// is true if this torrent has been paused
bool m_paused:1;
// this is true from the time when the torrent was
// paused to the time should_request() is called
bool m_just_paused:1;
// if this is true, libtorrent may pause and resume
// this torrent depending on queuing rules. Torrents
// started with auto_managed flag set may be added in
// a paused state in case there are no available
// slots.
bool m_auto_managed:1;
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
// this is true while there is a country
// resolution in progress. To avoid flodding
// the DNS request queue, only one ip is resolved
// at a time.
mutable bool m_resolving_country:1;
// this is true if the user has enabled
// country resolution in this torrent
bool m_resolve_countries:1;
#endif
// in case the piece picker hasn't been constructed
// when this settings is set, this variable will keep
// its value until the piece picker is created
bool m_sequential_download:1;
// is false by default and set to
// true when the first tracker reponse
// is received
bool m_got_tracker_response:1;
// this is set to false as long as the connections
// of this torrent hasn't been initialized. If we
// have metadata from the start, connections are
// initialized immediately, if we didn't have metadata,
// they are initialized right after files_checked().
// valid_resume_data() will return false as long as
// the connections aren't initialized, to avoid
// them from altering the piece-picker before it
// has been initialized with files_checked().
bool m_connections_initialized:1;
// is set to true every time there is an incoming
// connection to this torrent
bool m_has_incoming:1;
// this is set to true when the files are checked
// before the files are checked, we don't try to
// connect to peers
bool m_files_checked:1;
};
inline ptime torrent::next_announce() const
{
return m_next_request;
}
inline void torrent::force_tracker_request()
{
m_next_request = time_now();
}
inline void torrent::force_tracker_request(ptime t)
{
m_next_request = t;
}
inline void torrent::set_tracker_login(
std::string const& name
, std::string const& pw)
{
m_username = name;
m_password = pw;
}
}
#endif // TORRENT_TORRENT_HPP_INCLUDED

View File

@ -0,0 +1,488 @@
/*
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.
*/
#ifndef TORRENT_TORRENT_HANDLE_HPP_INCLUDED
#define TORRENT_TORRENT_HANDLE_HPP_INCLUDED
#include <vector>
#include <set>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/date_time/posix_time/posix_time_types.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/peer_id.hpp"
#include "libtorrent/peer_info.hpp"
#include "libtorrent/piece_picker.hpp"
#include "libtorrent/torrent_info.hpp"
#include "libtorrent/time.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/storage.hpp"
namespace libtorrent
{
namespace fs = boost::filesystem;
namespace aux
{
struct session_impl;
struct checker_impl;
}
struct torrent_plugin;
struct TORRENT_EXPORT duplicate_torrent: std::exception
{
virtual const char* what() const throw()
{ return "torrent already exists in session"; }
};
struct TORRENT_EXPORT invalid_handle: std::exception
{
virtual const char* what() const throw()
{ return "invalid torrent handle used"; }
};
struct TORRENT_EXPORT torrent_status
{
torrent_status()
: state(queued_for_checking)
, paused(false)
, progress(0.f)
, total_download(0)
, total_upload(0)
, total_payload_download(0)
, total_payload_upload(0)
, total_failed_bytes(0)
, total_redundant_bytes(0)
, download_rate(0)
, upload_rate(0)
, download_payload_rate(0)
, upload_payload_rate(0)
, num_seeds(0)
, num_peers(0)
, num_complete(-1)
, num_incomplete(-1)
, list_seeds(0)
, list_peers(0)
, num_pieces(0)
, total_done(0)
, total_wanted_done(0)
, total_wanted(0)
, distributed_copies(0.f)
, block_size(0)
, num_uploads(0)
, num_connections(0)
, uploads_limit(0)
, connections_limit(0)
, storage_mode(storage_mode_sparse)
, up_bandwidth_queue(0)
, down_bandwidth_queue(0)
, all_time_upload(0)
, all_time_download(0)
, active_time(0)
, seeding_time(0)
, seed_rank(0)
, last_scrape(0)
, has_incoming(false)
{}
enum state_t
{
queued_for_checking,
checking_files,
connecting_to_tracker,
downloading_metadata,
downloading,
finished,
seeding,
allocating
};
state_t state;
bool paused;
float progress;
std::string error;
boost::posix_time::time_duration next_announce;
boost::posix_time::time_duration announce_interval;
std::string current_tracker;
// transferred this session!
// total, payload plus protocol
size_type total_download;
size_type total_upload;
// payload only
size_type total_payload_download;
size_type total_payload_upload;
// the amount of payload bytes that
// has failed their hash test
size_type total_failed_bytes;
// the number of payload bytes that
// has been received redundantly.
size_type total_redundant_bytes;
// current transfer rate
// payload plus protocol
float download_rate;
float upload_rate;
// the rate of payload that is
// sent and received
float download_payload_rate;
float upload_payload_rate;
// the number of peers this torrent is connected to
// that are seeding.
int num_seeds;
// the number of peers this torrent
// is connected to (including seeds).
int num_peers;
// if the tracker sends scrape info in its
// announce reply, these fields will be
// set to the total number of peers that
// have the whole file and the total number
// of peers that are still downloading
int num_complete;
int num_incomplete;
// this is the number of seeds whose IP we know
// but are not necessarily connected to
int list_seeds;
// this is the number of peers whose IP we know
// (including seeds), but are not necessarily
// connected to
int list_peers;
// the number of peers in our peerlist that
// we potentially could connect to
int connect_candidates;
bitfield pieces;
// this is the number of pieces the client has
// downloaded. it is equal to:
// std::accumulate(pieces->begin(), pieces->end());
int num_pieces;
// the number of bytes of the file we have
// including pieces that may have been filtered
// after we downloaded them
size_type total_done;
// the number of bytes we have of those that we
// want. i.e. not counting bytes from pieces that
// are filtered as not wanted.
size_type total_wanted_done;
// the total number of bytes we want to download
// this may be smaller than the total torrent size
// in case any pieces are filtered as not wanted
size_type total_wanted;
// the number of distributed copies of the file.
// note that one copy may be spread out among many peers.
//
// the integer part tells how many copies
// there are of the rarest piece(s)
//
// the fractional part tells the fraction of pieces that
// have more copies than the rarest piece(s).
float distributed_copies;
// the block size that is used in this torrent. i.e.
// the number of bytes each piece request asks for
// and each bit in the download queue bitfield represents
int block_size;
int num_uploads;
int num_connections;
int uploads_limit;
int connections_limit;
// true if the torrent is saved in compact mode
// false if it is saved in full allocation mode
storage_mode_t storage_mode;
int up_bandwidth_queue;
int down_bandwidth_queue;
// number of bytes downloaded since torrent was started
// saved and restored from resume data
size_type all_time_upload;
size_type all_time_download;
// the number of seconds of being active
// and as being a seed, saved and restored
// from resume data
int active_time;
int seeding_time;
// higher value means more important to seed
int seed_rank;
// number of seconds since last scrape, or -1 if
// there hasn't been a scrape
int last_scrape;
// true if there are incoming connections to this
// torrent
bool has_incoming;
};
struct TORRENT_EXPORT block_info
{
enum block_state_t
{ none, requested, writing, finished };
tcp::endpoint peer;
// number of bytes downloaded in this block
unsigned bytes_progress:16;
// the total number of bytes in this block
unsigned block_size:16;
// the state this block is in (see block_state_t)
unsigned state:2;
// the number of peers that has requested this block
// typically 0 or 1. If > 1, this block is in
// end game mode
unsigned num_peers:14;
};
struct TORRENT_EXPORT partial_piece_info
{
enum { max_blocks_per_piece = 256 };
int piece_index;
int blocks_in_piece;
// the number of blocks in the finished state
int finished;
// the number of blocks in the writing state
int writing;
// the number of blocks in the requested state
int requested;
block_info blocks[max_blocks_per_piece];
enum state_t { none, slow, medium, fast };
state_t piece_state;
};
struct TORRENT_EXPORT torrent_handle
{
friend class invariant_access;
friend struct aux::session_impl;
friend class torrent;
torrent_handle() {}
void get_full_peer_list(std::vector<peer_list_entry>& v) const;
void get_peer_info(std::vector<peer_info>& v) const;
torrent_status status() const;
void get_download_queue(std::vector<partial_piece_info>& queue) const;
// fills the specified vector with the download progress [0, 1]
// of each file in the torrent. The files are ordered as in
// the torrent_info.
void file_progress(std::vector<float>& progress);
std::vector<announce_entry> const& trackers() const;
void replace_trackers(std::vector<announce_entry> const&) const;
void add_url_seed(std::string const& url) const;
void remove_url_seed(std::string const& url) const;
std::set<std::string> url_seeds() const;
#ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> const& ext
, void* userdata = 0);
#endif
bool has_metadata() const;
const torrent_info& get_torrent_info() const;
bool is_valid() const;
bool is_seed() const;
bool is_finished() const;
bool is_paused() const;
void pause() const;
void resume() const;
void force_recheck() const;
void save_resume_data() const;
bool is_auto_managed() const;
void auto_managed(bool m) const;
int queue_position() const;
void queue_position_up() const;
void queue_position_down() const;
void queue_position_top() const;
void queue_position_bottom() const;
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
void resolve_countries(bool r);
bool resolve_countries() const;
#endif
// all these are deprecated, use piece
// priority functions instead
// ================ start deprecation ============
// deprecated in 0.13
// marks the piece with the given index as filtered
// it will not be downloaded
void filter_piece(int index, bool filter) const TORRENT_DEPRECATED;
void filter_pieces(std::vector<bool> const& pieces) const TORRENT_DEPRECATED;
bool is_piece_filtered(int index) const TORRENT_DEPRECATED;
std::vector<bool> filtered_pieces() const TORRENT_DEPRECATED;
// marks the file with the given index as filtered
// it will not be downloaded
void filter_files(std::vector<bool> const& files) const TORRENT_DEPRECATED;
// ================ end deprecation ============
void piece_availability(std::vector<int>& avail) const;
// priority must be within the range [0, 7]
void piece_priority(int index, int priority) const;
int piece_priority(int index) const;
void prioritize_pieces(std::vector<int> const& pieces) const;
std::vector<int> piece_priorities() const;
void prioritize_files(std::vector<int> const& files) const;
// set the interface to bind outgoing connections
// to.
void use_interface(const char* net_interface) const;
// deprecated in 0.14
// use save_resume_data() instead. It is async. and
// will return the resume data in an alert
entry write_resume_data() const TORRENT_DEPRECATED;
// forces this torrent to reannounce
// (make a rerequest from the tracker)
void force_reannounce() const;
// forces a reannounce in the specified amount of time.
// This overrides the default announce interval, and no
// announce will take place until the given time has
// timed out.
void force_reannounce(boost::posix_time::time_duration) const;
// performs a scrape request
void scrape_tracker() const;
// returns the name of this torrent, in case it doesn't
// have metadata it returns the name assigned to it
// when it was added.
std::string name() const;
// TODO: add a feature where the user can tell the torrent
// to finish all pieces currently in the pipeline, and then
// abort the torrent.
void set_upload_limit(int limit) const;
int upload_limit() const;
void set_download_limit(int limit) const;
int download_limit() const;
void set_sequential_download(bool sd) const;
bool is_sequential_download() const;
void set_peer_upload_limit(tcp::endpoint ip, int limit) const;
void set_peer_download_limit(tcp::endpoint ip, int limit) const;
// manually connect a peer
void connect_peer(tcp::endpoint const& adr, int source = 0) const;
// valid ratios are 0 (infinite ratio) or [ 1.0 , inf )
// the ratio is uploaded / downloaded. less than 1 is not allowed
void set_ratio(float up_down_ratio) const;
fs::path save_path() const;
// -1 means unlimited unchokes
void set_max_uploads(int max_uploads) const;
// -1 means unlimited connections
void set_max_connections(int max_connections) const;
void set_tracker_login(std::string const& name
, std::string const& password) const;
// post condition: save_path() == save_path if true is returned
void move_storage(fs::path const& save_path) const;
void rename_file(int index, fs::path const& new_name) const;
sha1_hash info_hash() const;
bool operator==(const torrent_handle& h) const
{ return m_torrent.lock() == h.m_torrent.lock(); }
bool operator!=(const torrent_handle& h) const
{ return m_torrent.lock() != h.m_torrent.lock(); }
bool operator<(const torrent_handle& h) const
{ return m_torrent.lock() < h.m_torrent.lock(); }
private:
torrent_handle(boost::weak_ptr<torrent> const& t)
: m_torrent(t)
{}
#ifndef NDEBUG
void check_invariant() const;
#endif
boost::weak_ptr<torrent> m_torrent;
};
}
#endif // TORRENT_TORRENT_HANDLE_HPP_INCLUDED

View File

@ -0,0 +1,242 @@
/*
Copyright (c) 2003-2008, 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.
*/
#ifndef TORRENT_TORRENT_INFO_HPP_INCLUDED
#define TORRENT_TORRENT_INFO_HPP_INCLUDED
#include <string>
#include <vector>
#include <iosfwd>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/optional.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/shared_array.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/entry.hpp"
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/time.hpp"
#include "libtorrent/intrusive_ptr_base.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/file_storage.hpp"
namespace libtorrent
{
namespace pt = boost::posix_time;
namespace gr = boost::gregorian;
namespace fs = boost::filesystem;
struct TORRENT_EXPORT announce_entry
{
announce_entry(std::string const& u): url(u), tier(0) {}
std::string url;
int tier;
};
#ifndef BOOST_NO_EXCEPTIONS
struct TORRENT_EXPORT invalid_torrent_file: std::exception
{
virtual const char* what() const throw() { return "invalid torrent file"; }
};
#endif
int TORRENT_EXPORT load_file(fs::path const& filename, std::vector<char>& v);
class TORRENT_EXPORT torrent_info : public intrusive_ptr_base<torrent_info>
{
public:
torrent_info(sha1_hash const& info_hash);
torrent_info(lazy_entry const& torrent_file);
torrent_info(char const* buffer, int size);
torrent_info(fs::path const& filename);
~torrent_info();
file_storage const& files() const { return m_files; }
void add_tracker(std::string const& url, int tier = 0);
std::vector<announce_entry> const& trackers() const { return m_urls; }
std::vector<std::string> const& url_seeds() const
{ return m_url_seeds; }
void add_url_seed(std::string const& url)
{ m_url_seeds.push_back(url); }
size_type total_size() const { return m_files.total_size(); }
int piece_length() const { return m_files.piece_length(); }
int num_pieces() const { return m_files.num_pieces(); }
const sha1_hash& info_hash() const { return m_info_hash; }
const std::string& name() const { return m_files.name(); }
typedef file_storage::iterator file_iterator;
typedef file_storage::reverse_iterator reverse_file_iterator;
file_iterator begin_files() const { return m_files.begin(); }
file_iterator end_files() const { return m_files.end(); }
reverse_file_iterator rbegin_files() const { return m_files.rbegin(); }
reverse_file_iterator rend_files() const { return m_files.rend(); }
int num_files() const { return m_files.num_files(); }
file_entry const& file_at(int index) const { return m_files.at(index); }
std::vector<file_slice> map_block(int piece, size_type offset, int size) const
{ return m_files.map_block(piece, offset, size); }
peer_request map_file(int file, size_type offset, int size) const
{ return m_files.map_file(file, offset, size); }
// ------- start deprecation -------
// these functions will be removed in a future version
torrent_info(entry const& torrent_file) TORRENT_DEPRECATED;
void print(std::ostream& os) const TORRENT_DEPRECATED;
// ------- end deprecation -------
bool is_valid() const { return m_files.is_valid(); }
bool priv() const { return m_private; }
int piece_size(int index) const { return m_files.piece_size(index); }
sha1_hash hash_for_piece(int index) const
{ return sha1_hash(hash_for_piece_ptr(index)); }
char const* hash_for_piece_ptr(int index) const
{
TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < m_files.num_pieces());
TORRENT_ASSERT(m_piece_hashes);
TORRENT_ASSERT(m_piece_hashes >= m_info_section.get());
TORRENT_ASSERT(m_piece_hashes < m_info_section.get() + m_info_section_size);
return &m_piece_hashes[index*20];
}
boost::optional<pt::ptime> creation_date() const;
const std::string& creator() const
{ return m_created_by; }
const std::string& comment() const
{ return m_comment; }
// dht nodes to add to the routing table/bootstrap from
typedef std::vector<std::pair<std::string, int> > nodes_t;
nodes_t const& nodes() const
{ return m_nodes; }
void add_node(std::pair<std::string, int> const& node)
{ m_nodes.push_back(node); }
bool parse_info_section(lazy_entry const& e, std::string& error);
lazy_entry const* info(char const* key) const
{
if (m_info_dict.type() == lazy_entry::none_t)
lazy_bdecode(m_info_section.get(), m_info_section.get()
+ m_info_section_size, m_info_dict);
return m_info_dict.dict_find(key);
}
void swap(torrent_info& ti);
boost::shared_array<char> metadata() const
{ return m_info_section; }
int metadata_size() const { return m_info_section_size; }
private:
bool parse_torrent_file(lazy_entry const& libtorrent, std::string& error);
file_storage m_files;
// the urls to the trackers
std::vector<announce_entry> m_urls;
std::vector<std::string> m_url_seeds;
nodes_t m_nodes;
// the hash that identifies this torrent
// is mutable because it's calculated
// lazily
sha1_hash m_info_hash;
// if a creation date is found in the torrent file
// this will be set to that, otherwise it'll be
// 1970, Jan 1
pt::ptime m_creation_date;
// if a comment is found in the torrent file
// this will be set to that comment
std::string m_comment;
// an optional string naming the software used
// to create the torrent file
std::string m_created_by;
// this is used when creating a torrent. If there's
// only one file there are cases where it's impossible
// to know if it should be written as a multifile torrent
// or not. e.g. test/test there's one file and one directory
// and they have the same name.
bool m_multifile;
// this is true if the torrent is private. i.e., is should not
// be announced on the dht
bool m_private;
// this is a copy of the info section from the torrent.
// it use maintained in this flat format in order to
// make it available through the metadata extension
boost::shared_array<char> m_info_section;
int m_info_section_size;
// this is a pointer into the m_info_section buffer
// pointing to the first byte of the first sha-1 hash
char const* m_piece_hashes;
// the info section parsed. points into m_info_section
// parsed lazily
mutable lazy_entry m_info_dict;
};
}
#endif // TORRENT_TORRENT_INFO_HPP_INCLUDED

View File

@ -0,0 +1,246 @@
/*
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.
*/
#ifndef TORRENT_TRACKER_MANAGER_HPP_INCLUDED
#define TORRENT_TRACKER_MANAGER_HPP_INCLUDED
#include <vector>
#include <string>
#include <utility>
#include <ctime>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/shared_ptr.hpp>
#include <boost/cstdint.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <boost/tuple/tuple.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/socket.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/peer.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/time.hpp"
#include "libtorrent/connection_queue.hpp"
#include "libtorrent/intrusive_ptr_base.hpp"
namespace libtorrent
{
struct request_callback;
class tracker_manager;
struct timeout_handler;
struct tracker_connection;
// returns -1 if gzip header is invalid or the header size in bytes
TORRENT_EXPORT int gzip_header(const char* buf, int size);
struct TORRENT_EXPORT tracker_request
{
tracker_request()
: kind(announce_request)
, event(none)
, key(0)
, num_want(0)
{}
enum
{
announce_request,
scrape_request
} kind;
enum event_t
{
none,
completed,
started,
stopped
};
sha1_hash info_hash;
peer_id pid;
size_type downloaded;
size_type uploaded;
size_type left;
unsigned short listen_port;
event_t event;
std::string url;
int key;
int num_want;
std::string ipv6;
};
struct TORRENT_EXPORT request_callback
{
friend class tracker_manager;
request_callback(): m_manager(0) {}
virtual ~request_callback() {}
virtual void tracker_warning(tracker_request const& req
, std::string const& msg) = 0;
virtual void tracker_scrape_response(tracker_request const& req
, int complete, int incomplete, int downloads) {}
virtual void tracker_response(
tracker_request const& req
, std::vector<peer_entry>& peers
, int interval
, int complete
, int incomplete
, address const& external_ip) = 0;
virtual void tracker_request_timed_out(
tracker_request const& req) = 0;
virtual void tracker_request_error(
tracker_request const& req
, int response_code
, const std::string& description) = 0;
tcp::endpoint m_tracker_address;
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
virtual void debug_log(const std::string& line) = 0;
#endif
private:
tracker_manager* m_manager;
};
struct TORRENT_EXPORT timeout_handler
: intrusive_ptr_base<timeout_handler>
, boost::noncopyable
{
timeout_handler(io_service& str);
void set_timeout(int completion_timeout, int read_timeout);
void restart_read_timeout();
void cancel();
virtual void on_timeout() = 0;
virtual ~timeout_handler() {}
private:
void timeout_callback(error_code const&);
boost::intrusive_ptr<timeout_handler> self()
{ return boost::intrusive_ptr<timeout_handler>(this); }
// used for timeouts
// this is set when the request has been sent
ptime m_start_time;
// this is set every time something is received
ptime m_read_time;
// the asio async operation
deadline_timer m_timeout;
int m_completion_timeout;
int m_read_timeout;
typedef boost::mutex mutex_t;
mutable mutex_t m_mutex;
bool m_abort;
};
struct TORRENT_EXPORT tracker_connection
: timeout_handler
{
tracker_connection(tracker_manager& man
, tracker_request const& req
, io_service& ios
, address bind_interface
, boost::weak_ptr<request_callback> r);
boost::shared_ptr<request_callback> requester();
virtual ~tracker_connection() {}
tracker_request const& tracker_req() const { return m_req; }
void fail(int code, char const* msg);
void fail_timeout();
virtual void close();
address const& bind_interface() const { return m_bind_interface; }
protected:
boost::weak_ptr<request_callback> m_requester;
private:
address m_bind_interface;
tracker_manager& m_man;
const tracker_request m_req;
};
class TORRENT_EXPORT tracker_manager: boost::noncopyable
{
public:
tracker_manager(session_settings const& s, proxy_settings const& ps)
: m_settings(s)
, m_proxy(ps)
, m_abort(false) {}
void queue_request(
io_service& ios
, connection_queue& cc
, tracker_request r
, std::string const& auth
, address bind_infc
, boost::weak_ptr<request_callback> c
= boost::weak_ptr<request_callback>());
void abort_all_requests();
void remove_request(tracker_connection const*);
bool empty() const;
int num_requests() const;
private:
typedef boost::recursive_mutex mutex_t;
mutable mutex_t m_mutex;
typedef std::list<boost::intrusive_ptr<tracker_connection> >
tracker_connections_t;
tracker_connections_t m_connections;
session_settings const& m_settings;
proxy_settings const& m_proxy;
bool m_abort;
};
}
#endif // TORRENT_TRACKER_MANAGER_HPP_INCLUDED

View File

@ -0,0 +1,106 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_UDP_SOCKET_HPP_INCLUDED
#define TORRENT_UDP_SOCKET_HPP_INCLUDED
#include "libtorrent/socket.hpp"
#include "libtorrent/session_settings.hpp"
#include <vector>
#include <boost/function.hpp>
namespace libtorrent
{
class connection_queue;
class udp_socket
{
public:
typedef boost::function<void(error_code const& ec
, udp::endpoint const&, char const* buf, int size)> callback_t;
udp_socket(io_service& ios, callback_t const& c, connection_queue& cc);
bool is_open() const { return m_ipv4_sock.is_open() || m_ipv6_sock.is_open(); }
io_service& get_io_service() { return m_ipv4_sock.get_io_service(); }
void send(udp::endpoint const& ep, char const* p, int len, error_code& ec);
void bind(udp::endpoint const& ep, error_code& ec);
void bind(int port);
void close();
int local_port() const { return m_bind_port; }
void set_proxy_settings(proxy_settings const& ps);
proxy_settings const& get_proxy_settings() { return m_proxy_settings; }
private:
callback_t m_callback;
void on_read(udp::socket* sock, error_code const& e, std::size_t bytes_transferred);
void on_name_lookup(error_code const& e, tcp::resolver::iterator i);
void on_timeout();
void on_connect(int ticket);
void on_connected(error_code const& ec);
void handshake1(error_code const& e);
void handshake2(error_code const& e);
void handshake3(error_code const& e);
void handshake4(error_code const& e);
void socks_forward_udp();
void connect1(error_code const& e);
void connect2(error_code const& e);
void wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec);
void unwrap(error_code const& e, char const* buf, int size);
udp::socket m_ipv4_sock;
udp::socket m_ipv6_sock;
udp::endpoint m_v4_ep;
udp::endpoint m_v6_ep;
char m_v4_buf[1600];
char m_v6_buf[1600];
int m_bind_port;
tcp::socket m_socks5_sock;
int m_connection_ticket;
proxy_settings m_proxy_settings;
connection_queue& m_cc;
tcp::resolver m_resolver;
char m_tmp_buf[100];
bool m_tunnel_packets;
udp::endpoint m_proxy_addr;
};
}
#endif

View File

@ -0,0 +1,124 @@
/*
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.
*/
#ifndef TORRENT_UDP_TRACKER_CONNECTION_HPP_INCLUDED
#define TORRENT_UDP_TRACKER_CONNECTION_HPP_INCLUDED
#include <vector>
#include <string>
#include <utility>
#include <ctime>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/shared_ptr.hpp>
#include <boost/cstdint.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/udp_socket.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/peer.hpp"
#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/config.hpp"
namespace libtorrent
{
class TORRENT_EXPORT udp_tracker_connection: public tracker_connection
{
friend class tracker_manager;
public:
udp_tracker_connection(
io_service& ios
, connection_queue& cc
, tracker_manager& man
, tracker_request const& req
, address bind_infc
, boost::weak_ptr<request_callback> c
, session_settings const& stn
, proxy_settings const& ps);
void close();
private:
enum action_t
{
action_connect,
action_announce,
action_scrape,
action_error
};
boost::intrusive_ptr<udp_tracker_connection> self()
{ return boost::intrusive_ptr<udp_tracker_connection>(this); }
void name_lookup(error_code const& error, udp::resolver::iterator i);
void timeout(error_code const& error);
void on_receive(error_code const& e, udp::endpoint const& ep
, char const* buf, int size);
void on_connect_response(char const* buf, int size);
void on_announce_response(char const* buf, int size);
void on_scrape_response(char const* buf, int size);
void send_udp_connect();
void send_udp_announce();
void send_udp_scrape();
virtual void on_timeout();
tracker_manager& m_man;
udp::resolver m_name_lookup;
udp_socket m_socket;
udp::endpoint m_target;
int m_transaction_id;
boost::int64_t m_connection_id;
session_settings const& m_settings;
int m_attempts;
action_t m_state;
};
}
#endif // TORRENT_UDP_TRACKER_CONNECTION_HPP_INCLUDED

View File

@ -0,0 +1,282 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_UPNP_HPP
#define TORRENT_UPNP_HPP
#include "libtorrent/socket.hpp"
#include "libtorrent/broadcast_socket.hpp"
#include "libtorrent/http_connection.hpp"
#include "libtorrent/connection_queue.hpp"
#include "libtorrent/intrusive_ptr_base.hpp"
#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <set>
#if (defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)) && !defined (TORRENT_UPNP_LOGGING)
#define TORRENT_UPNP_LOGGING
#endif
#if defined(TORRENT_UPNP_LOGGING)
#include <fstream>
#endif
namespace libtorrent
{
// int: port-mapping index
// int: external port
// std::string: error message
// an empty string as error means success
typedef boost::function<void(int, int, std::string const&)> portmap_callback_t;
class upnp : public intrusive_ptr_base<upnp>
{
public:
upnp(io_service& ios, connection_queue& cc
, address const& listen_interface, std::string const& user_agent
, portmap_callback_t const& cb, bool ignore_nonrouters, void* state = 0);
~upnp();
void* drain_state();
enum protocol_type { none = 0, udp = 1, tcp = 2 };
int add_mapping(protocol_type p, int external_port, int local_port);
void delete_mapping(int mapping_index);
void discover_device();
void close();
std::string router_model()
{
mutex_t::scoped_lock l(m_mutex);
return m_model;
}
private:
void discover_device_impl();
static address_v4 upnp_multicast_address;
static udp::endpoint upnp_multicast_endpoint;
enum { default_lease_time = 3600 };
void resend_request(error_code const& e);
void on_reply(udp::endpoint const& from, char* buffer
, std::size_t bytes_transferred);
struct rootdevice;
void next(rootdevice& d, int i);
void update_map(rootdevice& d, int i);
void on_upnp_xml(error_code const& e
, libtorrent::http_parser const& p, rootdevice& d
, http_connection& c);
void on_upnp_map_response(error_code const& e
, libtorrent::http_parser const& p, rootdevice& d
, int mapping, http_connection& c);
void on_upnp_unmap_response(error_code const& e
, libtorrent::http_parser const& p, rootdevice& d
, int mapping, http_connection& c);
void on_expire(error_code const& e);
void disable(char const* msg);
void return_error(int mapping, int code);
void delete_port_mapping(rootdevice& d, int i);
void create_port_mapping(http_connection& c, rootdevice& d, int i);
void post(upnp::rootdevice const& d, std::string const& soap
, std::string const& soap_action);
int num_mappings() const { return int(m_mappings.size()); }
struct global_mapping_t
{
global_mapping_t()
: protocol(none)
, external_port(0)
, local_port(0)
{}
int protocol;
int external_port;
int local_port;
};
struct mapping_t
{
enum action_t { action_none, action_add, action_delete };
mapping_t()
: action(action_none)
, local_port(0)
, external_port(0)
, protocol(none)
, failcount(0)
{}
// the time the port mapping will expire
ptime expires;
int action;
// the local port for this mapping. If this is set
// to 0, the mapping is not in use
int local_port;
// the external (on the NAT router) port
// for the mapping. This is the port we
// should announce to others
int external_port;
// 2 = udp, 1 = tcp
int protocol;
// the number of times this mapping has failed
int failcount;
};
struct rootdevice
{
rootdevice(): service_namespace(0)
, lease_duration(default_lease_time)
, supports_specific_external(true)
, disabled(false)
{
#ifndef NDEBUG
magic = 1337;
#endif
}
#ifndef NDEBUG
~rootdevice()
{
TORRENT_ASSERT(magic == 1337);
magic = 0;
}
#endif
// the interface url, through which the list of
// supported interfaces are fetched
std::string url;
// the url to the WANIP or WANPPP interface
std::string control_url;
// either the WANIP namespace or the WANPPP namespace
char const* service_namespace;
std::vector<mapping_t> mapping;
std::string hostname;
int port;
std::string path;
int lease_duration;
// true if the device supports specifying a
// specific external port, false if it doesn't
bool supports_specific_external;
bool disabled;
mutable boost::shared_ptr<http_connection> upnp_connection;
#ifndef NDEBUG
int magic;
#endif
void close() const
{
TORRENT_ASSERT(magic == 1337);
if (!upnp_connection) return;
upnp_connection->close();
upnp_connection.reset();
}
bool operator<(rootdevice const& rhs) const
{ return url < rhs.url; }
};
struct upnp_state_t
{
std::vector<global_mapping_t> mappings;
std::set<rootdevice> devices;
};
std::vector<global_mapping_t> m_mappings;
std::string const& m_user_agent;
// the set of devices we've found
std::set<rootdevice> m_devices;
portmap_callback_t m_callback;
// current retry count
int m_retry_count;
io_service& m_io_service;
// the udp socket used to send and receive
// multicast messages on the network
broadcast_socket m_socket;
// used to resend udp packets in case
// they time out
deadline_timer m_broadcast_timer;
// timer used to refresh mappings
deadline_timer m_refresh_timer;
bool m_disabled;
bool m_closing;
bool m_ignore_non_routers;
connection_queue& m_cc;
typedef boost::mutex mutex_t;
mutex_t m_mutex;
std::string m_model;
#ifdef TORRENT_UPNP_LOGGING
std::ofstream m_log;
#endif
};
}
#endif

View File

@ -0,0 +1,161 @@
/*
Copyright (C) 2004-2005 Cory Nelson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
// namespaces added by Arvid Norberg
#ifndef __UTF8_H__
#define __UTF8_H__
#include <string>
#include <iterator>
#include <stdexcept>
#include <cwchar>
namespace libtorrent {
namespace detail {
template<typename InputIterator>
wchar_t decode_utf8_mb(InputIterator &iter, InputIterator last)
{
if (iter == last) throw std::runtime_error("incomplete UTF-8 sequence");
if (((*iter) & 0xc0) != 0x80) throw std::runtime_error("invalid UTF-8 sequence");
return (wchar_t)((*iter++) & 0x3f);
}
template<typename InputIterator>
wchar_t decode_utf8(InputIterator &iter, InputIterator last)
{
wchar_t ret;
if (((*iter) & 0x80) == 0) // one byte
{
ret = *iter++;
}
else if (((*iter) & 0xe0) == 0xc0) // two bytes
{
wchar_t byte1 = (*iter++) & 0x1f;
wchar_t byte2 = decode_utf8_mb(iter, last);
ret = (byte1 << 6) | byte2;
}
else if (((*iter) & 0xf0) == 0xe0) // three bytes
{
wchar_t byte1 = (*iter++) & 0x0f;
wchar_t byte2 = decode_utf8_mb(iter, last);
wchar_t byte3 = decode_utf8_mb(iter, last);
ret = (byte1 << 12) | (byte2 << 6) | byte3;
}
// TODO: support surrogate pairs
else throw std::runtime_error("UTF-8 not convertable to UTF-16");
return ret;
}
template<typename InputIterator, typename OutputIterator>
OutputIterator utf8_wchar(InputIterator first, InputIterator last, OutputIterator dest)
{
for(; first!=last; ++dest)
*dest = decode_utf8(first, last);
return dest;
}
template<typename InputIterator, typename OutputIterator>
void encode_wchar(InputIterator iter, OutputIterator &dest)
{
if(*iter <= 0x007F)
{
*dest=(char)*iter;
++dest;
}
else if(*iter <= 0x07FF)
{
*dest = (char)(
0xC0 |
((*iter & 0x07C0) >> 6)
);
++dest;
*dest = (char)(
0x80 |
(*iter & 0x003F)
);
++dest;
}
else if(*iter <= 0xFFFF)
{
*dest = (char)(
0xE0 |
((*iter & 0xF000) >> 12)
);
++dest;
*dest = (char)(
0x80 |
((*iter & 0x0FC0) >> 6)
);
++dest;
*dest = (char)(
0x80 |
(*iter & 0x003F)
);
++dest;
}
}
template<typename InputIterator, typename OutputIterator>
OutputIterator wchar_utf8(InputIterator first, InputIterator last, OutputIterator dest)
{
for(; first!=last; ++first)
encode_wchar(first, dest);
return dest;
}
}
inline void utf8_wchar(const std::string &utf8, std::wstring &wide)
{
wide.clear();
detail::utf8_wchar(utf8.begin(), utf8.end(), std::back_inserter(wide));
}
inline std::wstring utf8_wchar(const std::string &str)
{
std::wstring ret;
utf8_wchar(str, ret);
return ret;
}
inline void wchar_utf8(const std::wstring &wide, std::string &utf8)
{
utf8.clear();
detail::wchar_utf8(wide.begin(), wide.end(), std::back_inserter(utf8));
}
inline std::string wchar_utf8(const std::wstring &str)
{
std::string ret;
wchar_utf8(str, ret);
return ret;
}
}
#endif

View File

@ -0,0 +1,754 @@
// Copyright Daniel Wallin and Arvid Norberg 2007.
// Use, modification and distribution is
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef VARIANT_STREAM_070211_HPP
# define VARIANT_STREAM_070211_HPP
# include <boost/variant.hpp>
# include <boost/mpl/vector.hpp>
# include <boost/mpl/void.hpp>
# include <boost/mpl/remove.hpp>
# include <boost/mpl/transform.hpp>
# include <boost/mpl/size.hpp>
# include <boost/preprocessor/repetition/enum_params.hpp>
# include <boost/preprocessor/repetition/enum_binary_params.hpp>
# include <boost/preprocessor/facilities/intercept.hpp>
# include <boost/type_traits/add_pointer.hpp>
# include <boost/noncopyable.hpp>
#if BOOST_VERSION < 103500
#include <asio/io_service.hpp>
#else
#include <boost/asio/io_service.hpp>
#endif
# define NETWORK_VARIANT_STREAM_LIMIT 5
namespace libtorrent {
namespace aux
{
struct delete_visitor
: boost::static_visitor<>
{
template <class T>
void operator()(T* p) const
{
delete p;
}
void operator()(boost::blank) const
{}
};
// -------------- io_control -----------
template<class IO_Control_Command>
struct io_control_visitor_ec: boost::static_visitor<>
{
io_control_visitor_ec(IO_Control_Command& ioc, error_code& ec_)
: ioc(ioc), ec(ec_) {}
template <class T>
void operator()(T* p) const
{
p->io_control(ioc, ec);
}
void operator()(boost::blank) const
{}
IO_Control_Command& ioc;
error_code& ec;
};
template<class IO_Control_Command>
struct io_control_visitor
: boost::static_visitor<>
{
io_control_visitor(IO_Control_Command& ioc)
: ioc(ioc) {}
template <class T>
void operator()(T* p) const
{
p->io_control(ioc);
}
void operator()(boost::blank) const
{}
IO_Control_Command& ioc;
};
// -------------- async_connect -----------
template <class EndpointType, class Handler>
struct async_connect_visitor
: boost::static_visitor<>
{
async_connect_visitor(EndpointType const& endpoint, Handler const& handler)
: endpoint(endpoint)
, handler(handler)
{}
template <class T>
void operator()(T* p) const
{
p->async_connect(endpoint, handler);
}
void operator()(boost::blank) const
{}
EndpointType const& endpoint;
Handler const& handler;
};
// -------------- bind -----------
template <class EndpointType>
struct bind_visitor_ec
: boost::static_visitor<>
{
bind_visitor_ec(EndpointType const& ep, error_code& ec_)
: endpoint(ep)
, ec(ec_)
{}
template <class T>
void operator()(T* p) const
{ p->bind(endpoint, ec); }
void operator()(boost::blank) const {}
EndpointType const& endpoint;
error_code& ec;
};
template <class EndpointType>
struct bind_visitor
: boost::static_visitor<>
{
bind_visitor(EndpointType const& ep)
: endpoint(ep)
{}
template <class T>
void operator()(T* p) const
{ p->bind(endpoint); }
void operator()(boost::blank) const {}
EndpointType const& endpoint;
};
// -------------- open -----------
template <class Protocol>
struct open_visitor_ec
: boost::static_visitor<>
{
open_visitor_ec(Protocol const& p, error_code& ec_)
: proto(p)
, ec(ec_)
{}
template <class T>
void operator()(T* p) const
{ p->open(proto, ec); }
void operator()(boost::blank) const {}
Protocol const& proto;
error_code& ec;
};
template <class Protocol>
struct open_visitor
: boost::static_visitor<>
{
open_visitor(Protocol const& p)
: proto(p)
{}
template <class T>
void operator()(T* p) const
{ p->open(proto); }
void operator()(boost::blank) const {}
Protocol const& proto;
};
// -------------- is_open -----------
struct is_open_visitor
: boost::static_visitor<bool>
{
is_open_visitor() {}
template <class T>
bool operator()(T const* p) const
{ return p->is_open(); }
bool operator()(boost::blank) const { return false; }
};
// -------------- close -----------
struct close_visitor_ec
: boost::static_visitor<>
{
close_visitor_ec(error_code& ec_)
: ec(ec_)
{}
template <class T>
void operator()(T* p) const
{ p->close(ec); }
void operator()(boost::blank) const {}
error_code& ec;
};
struct close_visitor
: boost::static_visitor<>
{
template <class T>
void operator()(T* p) const
{ p->close(); }
void operator()(boost::blank) const {}
};
// -------------- remote_endpoint -----------
template <class EndpointType>
struct remote_endpoint_visitor_ec
: boost::static_visitor<EndpointType>
{
remote_endpoint_visitor_ec(error_code& ec_)
: ec(ec_)
{}
template <class T>
EndpointType operator()(T const* p) const
{ return p->remote_endpoint(ec); }
EndpointType operator()(boost::blank) const
{ return EndpointType(); }
error_code& ec;
};
template <class EndpointType>
struct remote_endpoint_visitor
: boost::static_visitor<EndpointType>
{
template <class T>
EndpointType operator()(T const* p) const
{ return p->remote_endpoint(); }
EndpointType operator()(boost::blank) const
{ return EndpointType(); }
};
// -------------- set_option -----------
template <class SettableSocketOption>
struct set_option_visitor
: boost::static_visitor<>
{
set_option_visitor(SettableSocketOption const& opt)
: opt_(opt)
{}
template <class T>
void operator()(T* p) const
{ p->set_option(opt_); }
void operator()(boost::blank) const {}
SettableSocketOption const& opt_;
};
template <class SettableSocketOption>
struct set_option_visitor_ec
: boost::static_visitor<error_code>
{
set_option_visitor_ec(SettableSocketOption const& opt, error_code& ec)
: opt_(opt)
, ec_(ec)
{}
template <class T>
error_code operator()(T* p) const
{ return p->set_option(opt_, ec_); }
error_code operator()(boost::blank) const
{ return ec_; }
SettableSocketOption const& opt_;
error_code& ec_;
};
// -------------- local_endpoint -----------
template <class EndpointType>
struct local_endpoint_visitor_ec
: boost::static_visitor<EndpointType>
{
local_endpoint_visitor_ec(error_code& ec_)
: ec(ec_)
{}
template <class T>
EndpointType operator()(T const* p) const
{
return p->local_endpoint(ec);
}
EndpointType operator()(boost::blank) const
{
return EndpointType();
}
error_code& ec;
};
template <class EndpointType>
struct local_endpoint_visitor
: boost::static_visitor<EndpointType>
{
template <class T>
EndpointType operator()(T const* p) const
{
return p->local_endpoint();
}
EndpointType operator()(boost::blank) const
{
return EndpointType();
}
};
// -------------- async_read_some -----------
template <class Mutable_Buffers, class Handler>
struct async_read_some_visitor
: boost::static_visitor<>
{
async_read_some_visitor(Mutable_Buffers const& buffers, Handler const& handler)
: buffers(buffers)
, handler(handler)
{}
template <class T>
void operator()(T* p) const
{
p->async_read_some(buffers, handler);
}
void operator()(boost::blank) const
{}
Mutable_Buffers const& buffers;
Handler const& handler;
};
// -------------- read_some -----------
template <class Mutable_Buffers>
struct read_some_visitor
: boost::static_visitor<std::size_t>
{
read_some_visitor(Mutable_Buffers const& buffers)
: buffers(buffers)
{}
template <class T>
std::size_t operator()(T* p) const
{ return p->read_some(buffers); }
std::size_t operator()(boost::blank) const
{ return 0; }
Mutable_Buffers const& buffers;
};
template <class Mutable_Buffers>
struct read_some_visitor_ec
: boost::static_visitor<std::size_t>
{
read_some_visitor_ec(Mutable_Buffers const& buffers, error_code& ec_)
: buffers(buffers)
, ec(ec_)
{}
template <class T>
std::size_t operator()(T* p) const
{ return p->read_some(buffers, ec); }
std::size_t operator()(boost::blank) const
{ return 0; }
Mutable_Buffers const& buffers;
error_code& ec;
};
// -------------- async_write_some -----------
template <class Const_Buffers, class Handler>
struct async_write_some_visitor
: boost::static_visitor<>
{
async_write_some_visitor(Const_Buffers const& buffers, Handler const& handler)
: buffers(buffers)
, handler(handler)
{}
template <class T>
void operator()(T* p) const
{
p->async_write_some(buffers, handler);
}
void operator()(boost::blank) const
{}
Const_Buffers const& buffers;
Handler const& handler;
};
// -------------- in_avail -----------
struct in_avail_visitor_ec
: boost::static_visitor<std::size_t>
{
in_avail_visitor_ec(error_code& ec_)
: ec(ec_)
{}
template <class T>
std::size_t operator()(T const* p) const
{
return p->in_avail(ec);
}
std::size_t operator()(boost::blank) const
{
return 0;
}
error_code& ec;
};
struct in_avail_visitor
: boost::static_visitor<std::size_t>
{
template <class T>
std::size_t operator()(T const* p) const
{
return p->in_avail();
}
void operator()(boost::blank) const
{}
};
// -------------- io_service -----------
template <class IOService>
struct io_service_visitor
: boost::static_visitor<IOService&>
{
template <class T>
IOService& operator()(T* p) const
{
return p->get_io_service();
}
IOService& operator()(boost::blank) const
{
return *(IOService*)0;
}
};
// -------------- lowest_layer -----------
template <class LowestLayer>
struct lowest_layer_visitor
: boost::static_visitor<LowestLayer&>
{
template <class T>
LowestLayer& operator()(T* p) const
{
return p->lowest_layer();
}
LowestLayer& operator()(boost::blank) const
{
return *(LowestLayer*)0;
}
};
} // namespace aux
template <
BOOST_PP_ENUM_BINARY_PARAMS(
NETWORK_VARIANT_STREAM_LIMIT, class S, = boost::mpl::void_ BOOST_PP_INTERCEPT
)
>
class variant_stream : boost::noncopyable
{
public:
typedef BOOST_PP_CAT(boost::mpl::vector, NETWORK_VARIANT_STREAM_LIMIT)<
BOOST_PP_ENUM_PARAMS(NETWORK_VARIANT_STREAM_LIMIT, S)
> types0;
typedef typename boost::mpl::remove<types0, boost::mpl::void_>::type types;
typedef typename boost::make_variant_over<
typename boost::mpl::push_back<
typename boost::mpl::transform<
types
, boost::add_pointer<boost::mpl::_>
>::type
, boost::blank
>::type
>::type variant_type;
typedef typename S0::lowest_layer_type lowest_layer_type;
typedef typename S0::endpoint_type endpoint_type;
typedef typename S0::protocol_type protocol_type;
explicit variant_stream(io_service& ios)
: m_io_service(ios), m_variant(boost::blank()) {}
template <class S>
void instantiate(io_service& ios)
{
TORRENT_ASSERT(&ios == &m_io_service);
std::auto_ptr<S> owned(new S(ios));
boost::apply_visitor(aux::delete_visitor(), m_variant);
m_variant = owned.get();
owned.release();
}
template <class S>
S& get()
{
return *boost::get<S*>(m_variant);
}
bool instantiated() const
{
return m_variant.which() != boost::mpl::size<types>::value;
}
~variant_stream()
{
boost::apply_visitor(aux::delete_visitor(), m_variant);
}
template <class Mutable_Buffers>
std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec)
{
TORRENT_ASSERT(instantiated());
return boost::apply_visitor(
aux::read_some_visitor_ec<Mutable_Buffers>(buffers, ec)
, m_variant
);
}
template <class Mutable_Buffers>
std::size_t read_some(Mutable_Buffers const& buffers)
{
TORRENT_ASSERT(instantiated());
return boost::apply_visitor(
aux::read_some_visitor<Mutable_Buffers>(buffers)
, m_variant
);
}
template <class Mutable_Buffers, class Handler>
void async_read_some(Mutable_Buffers const& buffers, Handler const& handler)
{
TORRENT_ASSERT(instantiated());
boost::apply_visitor(
aux::async_read_some_visitor<Mutable_Buffers, Handler>(buffers, handler)
, m_variant
);
}
template <class Const_Buffers, class Handler>
void async_write_some(Const_Buffers const& buffers, Handler const& handler)
{
TORRENT_ASSERT(instantiated());
boost::apply_visitor(
aux::async_write_some_visitor<Const_Buffers, Handler>(buffers, handler)
, m_variant
);
}
template <class Handler>
void async_connect(endpoint_type const& endpoint, Handler const& handler)
{
TORRENT_ASSERT(instantiated());
boost::apply_visitor(
aux::async_connect_visitor<endpoint_type, Handler>(endpoint, handler), m_variant
);
}
template <class IO_Control_Command>
void io_control(IO_Control_Command& ioc)
{
TORRENT_ASSERT(instantiated());
boost::apply_visitor(
aux::io_control_visitor<IO_Control_Command>(ioc), m_variant
);
}
template <class IO_Control_Command>
void io_control(IO_Control_Command& ioc, error_code& ec)
{
TORRENT_ASSERT(instantiated());
boost::apply_visitor(
aux::io_control_visitor_ec<IO_Control_Command>(ioc, ec)
, m_variant
);
}
void bind(endpoint_type const& endpoint)
{
TORRENT_ASSERT(instantiated());
boost::apply_visitor(aux::bind_visitor<endpoint_type>(endpoint), m_variant);
}
void bind(endpoint_type const& endpoint, error_code& ec)
{
TORRENT_ASSERT(instantiated());
boost::apply_visitor(
aux::bind_visitor_ec<endpoint_type>(endpoint, ec), m_variant
);
}
void open(protocol_type const& p)
{
TORRENT_ASSERT(instantiated());
boost::apply_visitor(aux::open_visitor<protocol_type>(p), m_variant);
}
void open(protocol_type const& p, error_code& ec)
{
TORRENT_ASSERT(instantiated());
boost::apply_visitor(
aux::open_visitor_ec<protocol_type>(p, ec), m_variant
);
}
bool is_open() const
{
return boost::apply_visitor(aux::is_open_visitor(), m_variant);
}
void close()
{
if (!instantiated()) return;
boost::apply_visitor(aux::close_visitor(), m_variant);
}
void close(error_code& ec)
{
if (!instantiated()) return;
boost::apply_visitor(
aux::close_visitor_ec(ec), m_variant
);
}
std::size_t in_avail() const
{
TORRENT_ASSERT(instantiated());
return boost::apply_visitor(aux::in_avail_visitor(), m_variant);
}
std::size_t in_avail(error_code& ec) const
{
TORRENT_ASSERT(instantiated());
return boost::apply_visitor(
aux::in_avail_visitor_ec(ec), m_variant
);
}
endpoint_type remote_endpoint() const
{
TORRENT_ASSERT(instantiated());
return boost::apply_visitor(aux::remote_endpoint_visitor<endpoint_type>(), m_variant);
}
endpoint_type remote_endpoint(error_code& ec) const
{
TORRENT_ASSERT(instantiated());
return boost::apply_visitor(
aux::remote_endpoint_visitor_ec<endpoint_type>(ec), m_variant
);
}
template <class SettableSocketOption>
void set_option(SettableSocketOption const& opt)
{
TORRENT_ASSERT(instantiated());
boost::apply_visitor(aux::set_option_visitor<SettableSocketOption>(opt)
, m_variant);
}
template <class SettableSocketOption>
error_code set_option(SettableSocketOption const& opt, error_code& ec)
{
TORRENT_ASSERT(instantiated());
return boost::apply_visitor(aux::set_option_visitor_ec<SettableSocketOption>(opt, ec)
, m_variant);
}
endpoint_type local_endpoint() const
{
TORRENT_ASSERT(instantiated());
return boost::apply_visitor(aux::local_endpoint_visitor<endpoint_type>(), m_variant);
}
endpoint_type local_endpoint(error_code& ec) const
{
TORRENT_ASSERT(instantiated());
return boost::apply_visitor(
aux::local_endpoint_visitor_ec<endpoint_type>(ec), m_variant
);
}
io_service& get_io_service()
{
return m_io_service;
}
lowest_layer_type& lowest_layer()
{
TORRENT_ASSERT(instantiated());
return boost::apply_visitor(
aux::lowest_layer_visitor<lowest_layer_type>(), m_variant
);
}
private:
io_service& m_io_service;
variant_type m_variant;
};
} // namespace libtorrent
#endif // VARIANT_STREAM_070211_HPP

View File

@ -0,0 +1,41 @@
/*
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.
*/
#ifndef TORRENT_VERSION_HPP_INCLUDED
#define TORRENT_VERSION_HPP_INCLUDED
#define LIBTORRENT_VERSION_MAJOR 0
#define LIBTORRENT_VERSION_MINOR 14
#define LIBTORRENT_VERSION "0.14.0.0"
#endif

View File

@ -0,0 +1,183 @@
/*
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.
*/
#ifndef TORRENT_WEB_PEER_CONNECTION_HPP_INCLUDED
#define TORRENT_WEB_PEER_CONNECTION_HPP_INCLUDED
#include <ctime>
#include <algorithm>
#include <vector>
#include <deque>
#include <string>
#include "libtorrent/debug.hpp"
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/smart_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <boost/array.hpp>
#include <boost/optional.hpp>
#include <boost/cstdint.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/buffer.hpp"
#include "libtorrent/peer_connection.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/storage.hpp"
#include "libtorrent/stat.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/peer_request.hpp"
#include "libtorrent/piece_block_progress.hpp"
#include "libtorrent/config.hpp"
// parse_url
#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/http_parser.hpp"
namespace libtorrent
{
class torrent;
namespace detail
{
struct session_impl;
}
class TORRENT_EXPORT web_peer_connection
: public peer_connection
{
friend class invariant_access;
public:
// this is the constructor where the we are the active part.
// The peer_conenction should handshake and verify that the
// other end has the correct id
web_peer_connection(
aux::session_impl& ses
, boost::weak_ptr<torrent> t
, boost::shared_ptr<socket_type> s
, tcp::endpoint const& remote
, std::string const& url
, policy::peer* peerinfo);
~web_peer_connection();
// called from the main loop when this connection has any
// work to do.
void on_sent(error_code const& error
, std::size_t bytes_transferred);
void on_receive(error_code const& error
, std::size_t bytes_transferred);
std::string const& url() const { return m_url; }
virtual void get_specific_peer_info(peer_info& p) const;
virtual bool in_handshake() const;
// the following functions appends messages
// to the send buffer
void write_choke() {}
void write_unchoke() {}
void write_interested() {}
void write_not_interested() {}
void write_request(peer_request const& r);
void write_cancel(peer_request const& r)
{ incoming_reject_request(r); }
void write_have(int index) {}
void write_piece(peer_request const& r, disk_buffer_holder& buffer) { TORRENT_ASSERT(false); }
void write_keepalive() {}
void on_connected();
void write_reject_request(peer_request const&) {}
void write_allow_fast(int) {}
#ifndef NDEBUG
void check_invariant() const;
#endif
private:
// returns the block currently being
// downloaded. And the progress of that
// block. If the peer isn't downloading
// a piece for the moment, the boost::optional
// will be invalid.
boost::optional<piece_block_progress> downloading_piece_progress() const;
// this has one entry per bittorrent request
std::deque<peer_request> m_requests;
// this has one entry per http-request
// (might be more than the bt requests)
std::deque<int> m_file_requests;
std::string m_server_string;
http_parser m_parser;
std::string m_auth;
std::string m_host;
int m_port;
std::string m_path;
std::string m_url;
// the first request will contain a little bit more data
// than subsequent ones, things that aren't critical are left
// out to save bandwidth.
bool m_first_request;
// this is used for intermediate storage of pieces
// that is received in more than on HTTP responses
std::vector<char> m_piece;
// the mapping of the data in the m_piece buffer
peer_request m_intermediate_piece;
// the number of bytes into the receive buffer where
// current read cursor is.
int m_body_start;
// the number of bytes received in the current HTTP
// response. used to know where in the buffer the
// next response starts
int m_received_body;
// position in the current range response
int m_range_pos;
};
}
#endif // TORRENT_WEB_PEER_CONNECTION_HPP_INCLUDED

View File

@ -0,0 +1,211 @@
/*
Copyright (c) 2007, 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.
*/
#ifndef TORRENT_XML_PARSE_HPP
#define TORRENT_XML_PARSE_HPP
#include <cctype>
namespace libtorrent
{
enum
{
xml_start_tag,
xml_end_tag,
xml_empty_tag,
xml_declaration_tag,
xml_string,
xml_attribute,
xml_comment,
xml_parse_error
};
// callback(int type, char const* name, char const* val)
// str2 is only used for attributes. name is element or attribute
// name and val is attribute value
template <class CallbackType>
void xml_parse(char* p, char* end, CallbackType callback)
{
for(;p != end; ++p)
{
char const* start = p;
char const* val_start = 0;
int token;
// look for tag start
for(; *p != '<' && p != end; ++p);
if (p != start)
{
if (p != end)
{
TORRENT_ASSERT(*p == '<');
*p = 0;
}
token = xml_string;
callback(token, start, val_start);
if (p != end) *p = '<';
}
if (p == end) break;
// skip '<'
++p;
// parse the name of the tag.
for (start = p; p != end && *p != '>' && !std::isspace(*p); ++p);
char* tag_name_end = p;
// skip the attributes for now
for (; p != end && *p != '>'; ++p);
// parse error
if (p == end)
{
token = xml_parse_error;
start = "unexpected end of file";
callback(token, start, val_start);
break;
}
TORRENT_ASSERT(*p == '>');
// save the character that terminated the tag name
// it could be both '>' and ' '.
char save = *tag_name_end;
*tag_name_end = 0;
char* tag_end = p;
if (*start == '/')
{
++start;
token = xml_end_tag;
callback(token, start, val_start);
}
else if (*(p-1) == '/')
{
*(p-1) = 0;
token = xml_empty_tag;
callback(token, start, val_start);
*(p-1) = '/';
tag_end = p - 1;
}
else if (*start == '?' && *(p-1) == '?')
{
*(p-1) = 0;
++start;
token = xml_declaration_tag;
callback(token, start, val_start);
*(p-1) = '?';
tag_end = p - 1;
}
else if (start + 5 < p && memcmp(start, "!--", 3) == 0 && memcmp(p-2, "--", 2) == 0)
{
start += 3;
*(p-2) = 0;
token = xml_comment;
callback(token, start, val_start);
*(p-2) = '-';
tag_end = p - 2;
}
else
{
token = xml_start_tag;
callback(token, start, val_start);
}
*tag_name_end = save;
// parse attributes
for (char* i = tag_name_end; i < tag_end; ++i)
{
// find start of attribute name
for (; i != tag_end && std::isspace(*i); ++i);
if (i == tag_end) break;
start = i;
// find end of attribute name
for (; i != tag_end && *i != '=' && !std::isspace(*i); ++i);
char* name_end = i;
// look for equality sign
for (; i != tag_end && *i != '='; ++i);
if (i == tag_end)
{
token = xml_parse_error;
val_start = 0;
start = "garbage inside element brackets";
callback(token, start, val_start);
break;
}
++i;
for (; i != tag_end && std::isspace(*i); ++i);
// check for parse error (values must be quoted)
if (i == tag_end || (*i != '\'' && *i != '\"'))
{
token = xml_parse_error;
val_start = 0;
start = "unquoted attribute value";
callback(token, start, val_start);
break;
}
char quote = *i;
++i;
val_start = i;
for (; i != tag_end && *i != quote; ++i);
// parse error (missing end quote)
if (i == tag_end)
{
token = xml_parse_error;
val_start = 0;
start = "missing end quote on attribute";
callback(token, start, val_start);
break;
}
save = *i;
*i = 0;
*name_end = 0;
token = xml_attribute;
callback(token, start, val_start);
*name_end = '=';
*i = save;
}
}
}
}
#endif

View File

@ -1,225 +0,0 @@
/*
Copyright (c) 2006, Magnus Jonsson, 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.
*/
//The Standard Library defines the two template functions std::min()
//and std::max() in the <algorithm> header. In general, you should
//use these template functions for calculating the min and max values
//of a pair. Unfortunately, Visual C++ does not define these function
// templates. This is because the names min and max clash with
//the traditional min and max macros defined in <windows.h>.
//As a workaround, Visual C++ defines two alternative templates with
//identical functionality called _cpp_min() and _cpp_max(). You can
//use them instead of std::min() and std::max().To disable the
//generation of the min and max macros in Visual C++, #define
//NOMINMAX before #including <windows.h>.
#include "libtorrent/pch.hpp"
#ifdef _WIN32
//support boost1.32.0(2004-11-19 18:47)
//now all libs can be compiled and linked with static module
#define NOMINMAX
#endif
#include "libtorrent/allocate_resources.hpp"
#include "libtorrent/size_type.hpp"
#include "libtorrent/peer_connection.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/aux_/allocate_resources_impl.hpp"
#include <cassert>
#include <algorithm>
#include <boost/limits.hpp>
#if defined(_MSC_VER) && _MSC_VER < 1310
#define for if (false) {} else for
#else
#include <boost/iterator/transform_iterator.hpp>
#endif
namespace libtorrent
{
int saturated_add(int a, int b)
{
assert(a >= 0);
assert(b >= 0);
assert(a <= resource_request::inf);
assert(b <= resource_request::inf);
assert(resource_request::inf + resource_request::inf < 0);
unsigned int sum = unsigned(a) + unsigned(b);
if (sum > unsigned(resource_request::inf))
sum = resource_request::inf;
assert(sum >= unsigned(a) && sum >= unsigned(b));
return int(sum);
}
#if defined(_MSC_VER) && _MSC_VER < 1310
namespace detail
{
struct iterator_wrapper
{
typedef std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator orig_iter;
orig_iter iter;
iterator_wrapper(orig_iter i): iter(i) {}
void operator++() { ++iter; }
torrent& operator*() { return *(iter->second); }
bool operator==(const iterator_wrapper& i) const
{ return iter == i.iter; }
bool operator!=(const iterator_wrapper& i) const
{ return iter != i.iter; }
};
struct iterator_wrapper2
{
typedef std::map<tcp::endpoint, peer_connection*>::iterator orig_iter;
orig_iter iter;
iterator_wrapper2(orig_iter i): iter(i) {}
void operator++() { ++iter; }
peer_connection& operator*() { return *(iter->second); }
bool operator==(const iterator_wrapper2& i) const
{ return iter == i.iter; }
bool operator!=(const iterator_wrapper2& i) const
{ return iter != i.iter; }
};
}
void allocate_resources(
int resources
, std::map<sha1_hash, boost::shared_ptr<torrent> >& c
, resource_request torrent::* res)
{
aux::allocate_resources_impl(
resources
, detail::iterator_wrapper(c.begin())
, detail::iterator_wrapper(c.end())
, res);
}
void allocate_resources(
int resources
, std::map<tcp::endpoint, peer_connection*>& c
, resource_request peer_connection::* res)
{
aux::allocate_resources_impl(
resources
, detail::iterator_wrapper2(c.begin())
, detail::iterator_wrapper2(c.end())
, res);
}
#else
namespace aux
{
peer_connection& pick_peer(
std::pair<boost::shared_ptr<stream_socket>
, boost::intrusive_ptr<peer_connection> > const& p)
{
return *p.second;
}
peer_connection& pick_peer2(
std::pair<tcp::endpoint, peer_connection*> const& p)
{
return *p.second;
}
torrent& deref(std::pair<sha1_hash, boost::shared_ptr<torrent> > const& p)
{
return *p.second;
}
session& deref(session* p)
{
return *p;
}
}
void allocate_resources(
int resources
, std::map<sha1_hash, boost::shared_ptr<torrent> >& c
, resource_request torrent::* res)
{
typedef std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator orig_iter;
typedef std::pair<sha1_hash, boost::shared_ptr<torrent> > in_param;
typedef boost::transform_iterator<torrent& (*)(in_param const&), orig_iter> new_iter;
aux::allocate_resources_impl(
resources
, new_iter(c.begin(), &aux::deref)
, new_iter(c.end(), &aux::deref)
, res);
}
void allocate_resources(
int resources
, std::map<tcp::endpoint, peer_connection*>& c
, resource_request peer_connection::* res)
{
typedef std::map<tcp::endpoint, peer_connection*>::iterator orig_iter;
typedef std::pair<tcp::endpoint, peer_connection*> in_param;
typedef boost::transform_iterator<peer_connection& (*)(in_param const&), orig_iter> new_iter;
aux::allocate_resources_impl(
resources
, new_iter(c.begin(), &aux::pick_peer2)
, new_iter(c.end(), &aux::pick_peer2)
, res);
}
void allocate_resources(
int resources
, std::vector<session*>& _sessions
, resource_request session::* res)
{
typedef std::vector<session*>::iterator orig_iter;
typedef session* in_param;
typedef boost::transform_iterator<session& (*)(in_param), orig_iter> new_iter;
aux::allocate_resources_impl(
resources
, new_iter(_sessions.begin(), &aux::deref)
, new_iter(_sessions.end(), &aux::deref)
, res);
}
#endif
} // namespace libtorrent

Some files were not shown because too many files have changed in this diff Show More