fix shit :P
This commit is contained in:
parent
b5e986c3b4
commit
f9c2fc0720
|
@ -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 */
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
Loading…
Reference in New Issue