forked from premiere/premiere-libtorrent
merged i2p fix from RC_0_16
This commit is contained in:
parent
1d55894bef
commit
cbe3a72a6e
|
@ -25,6 +25,7 @@
|
|||
* fix uTP edge case where udp socket buffer fills up
|
||||
* fix nagle implementation in uTP
|
||||
|
||||
* i2p fixes
|
||||
* fix issue when loading certain malformed .torrent files
|
||||
* pass along host header with http proxy requests and possible http_connection shutdown hang
|
||||
|
||||
|
|
|
@ -586,7 +586,9 @@ void print_peer_info(std::string& out, std::vector<libtorrent::peer_info> const&
|
|||
if (print_ip)
|
||||
{
|
||||
snprintf(str, sizeof(str), "%-30s %-22s", (::print_endpoint(i->ip) +
|
||||
(i->connection_type == peer_info::bittorrent_utp ? " [uTP]" : "")).c_str()
|
||||
(i->flags & peer_info::utp_socket ? " [uTP]" : "") +
|
||||
(i->flags & peer_info::i2p_socket ? " [i2p]" : "")
|
||||
).c_str()
|
||||
, ::print_endpoint(i->local_endpoint).c_str());
|
||||
out += str;
|
||||
}
|
||||
|
|
|
@ -449,11 +449,7 @@ namespace libtorrent
|
|||
#endif
|
||||
|
||||
#if TORRENT_USE_I2P
|
||||
void set_i2p_proxy(proxy_settings const& s)
|
||||
{
|
||||
m_i2p_conn.open(s, boost::bind(&session_impl::on_i2p_open, this, _1));
|
||||
open_new_incoming_i2p_connection();
|
||||
}
|
||||
void set_i2p_proxy(proxy_settings const& s);
|
||||
void on_i2p_open(error_code const& ec);
|
||||
proxy_settings const& i2p_proxy() const
|
||||
{ return m_i2p_conn.proxy(); }
|
||||
|
|
|
@ -61,6 +61,7 @@ namespace libtorrent {
|
|||
invalid_id,
|
||||
timeout,
|
||||
key_not_found,
|
||||
duplicated_id,
|
||||
num_errors
|
||||
};
|
||||
}
|
||||
|
@ -79,12 +80,8 @@ class i2p_stream : public proxy_base
|
|||
{
|
||||
public:
|
||||
|
||||
explicit i2p_stream(io_service& io_service)
|
||||
: proxy_base(io_service)
|
||||
, m_id(0)
|
||||
, m_command(cmd_create_session)
|
||||
, m_state(0)
|
||||
{}
|
||||
explicit i2p_stream(io_service& io_service);
|
||||
~i2p_stream();
|
||||
|
||||
enum command_t
|
||||
{
|
||||
|
@ -159,6 +156,9 @@ private:
|
|||
};
|
||||
|
||||
int m_state;
|
||||
#ifdef TORRENT_DEBUG
|
||||
int m_magic;
|
||||
#endif
|
||||
};
|
||||
|
||||
class i2p_connection
|
||||
|
@ -186,11 +186,13 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
void on_sam_connect(error_code const& ec, i2p_stream::handler_type const& h);
|
||||
void on_sam_connect(error_code const& ec, i2p_stream::handler_type const& h
|
||||
, boost::shared_ptr<i2p_stream>);
|
||||
void do_name_lookup(std::string const& name
|
||||
, name_lookup_handler const& h);
|
||||
void on_name_lookup(error_code const& ec
|
||||
, name_lookup_handler handler);
|
||||
, name_lookup_handler handler
|
||||
, boost::shared_ptr<i2p_stream>);
|
||||
|
||||
void set_local_endpoint(error_code const& ec, char const* dest);
|
||||
|
||||
|
|
|
@ -125,6 +125,9 @@ namespace libtorrent
|
|||
// happens if both peers are behind a NAT and the peers
|
||||
// connect via the NAT holepunch mechanism.
|
||||
holepunched = 0x8000,
|
||||
|
||||
i2p_socket = 0x10000,
|
||||
utp_socket = 0x20000,
|
||||
rc4_encrypted = 0x100000,
|
||||
plaintext_encrypted = 0x200000
|
||||
};
|
||||
|
|
|
@ -320,6 +320,11 @@ namespace libtorrent
|
|||
// returns true if this is a uTP socket
|
||||
bool is_utp(socket_type const& s);
|
||||
|
||||
#if TORRENT_USE_I2P
|
||||
// returns true if this is an i2p socket
|
||||
bool is_i2p(socket_type const& s);
|
||||
#endif
|
||||
|
||||
// assuming the socket_type s is an ssl socket, make sure it
|
||||
// verifies the hostname in its SSL handshake
|
||||
void setup_ssl_hostname(socket_type& s, std::string const& hostname, error_code& ec);
|
||||
|
|
|
@ -354,6 +354,10 @@ namespace libtorrent
|
|||
if (has_peer_choked()) p.flags |= peer_info::remote_choked;
|
||||
if (support_extensions()) p.flags |= peer_info::supports_extensions;
|
||||
if (is_outgoing()) p.flags |= peer_info::local_connection;
|
||||
#if TORRENT_USE_I2P
|
||||
if (is_i2p(*get_socket())) p.flags |= peer_info::i2p_socket;
|
||||
#endif
|
||||
if (is_utp(*get_socket())) p.flags |= peer_info::utp_socket;
|
||||
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
if (m_encrypted)
|
||||
|
|
|
@ -64,7 +64,8 @@ namespace libtorrent
|
|||
"invalid key",
|
||||
"invalid id",
|
||||
"timeout",
|
||||
"key not found"
|
||||
"key not found",
|
||||
"duplicated id"
|
||||
};
|
||||
|
||||
if (ev < 0 || ev >= i2p_error::num_errors) return "unknown error";
|
||||
|
@ -74,7 +75,8 @@ namespace libtorrent
|
|||
i2p_connection::i2p_connection(io_service& ios)
|
||||
: m_state(sam_idle)
|
||||
, m_io_service(ios)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
i2p_connection::~i2p_connection()
|
||||
{}
|
||||
|
@ -89,7 +91,8 @@ namespace libtorrent
|
|||
// we already seem to have a session to this SAM router
|
||||
if (m_sam_router.hostname == s.hostname
|
||||
&& m_sam_router.port == s.port
|
||||
&& is_open()) return;
|
||||
&& m_sam_socket
|
||||
&& (is_open() || m_state == sam_connecting)) return;
|
||||
|
||||
m_sam_router = s;
|
||||
m_sam_router.type = proxy_settings::i2p_proxy;
|
||||
|
@ -112,10 +115,10 @@ namespace libtorrent
|
|||
add_outstanding_async("i2p_stream::on_sam_connect");
|
||||
#endif
|
||||
m_sam_socket->async_connect(tcp::endpoint()
|
||||
, boost::bind(&i2p_connection::on_sam_connect, this, _1, handler));
|
||||
, boost::bind(&i2p_connection::on_sam_connect, this, _1, handler, m_sam_socket));
|
||||
}
|
||||
|
||||
void i2p_connection::on_sam_connect(error_code const& ec, i2p_stream::handler_type const& h)
|
||||
void i2p_connection::on_sam_connect(error_code const& ec, i2p_stream::handler_type const& h, boost::shared_ptr<i2p_stream>)
|
||||
{
|
||||
#if defined TORRENT_ASIO_DEBUGGING
|
||||
complete_async("i2p_stream::on_sam_connect");
|
||||
|
@ -139,6 +142,7 @@ namespace libtorrent
|
|||
void i2p_connection::async_name_lookup(char const* name
|
||||
, i2p_connection::name_lookup_handler handler)
|
||||
{
|
||||
// TORRENT_ASSERT(is_open());
|
||||
if (m_state == sam_idle && m_name_lookup.empty())
|
||||
do_name_lookup(name, handler);
|
||||
else
|
||||
|
@ -152,12 +156,12 @@ namespace libtorrent
|
|||
m_state = sam_name_lookup;
|
||||
m_sam_socket->set_name_lookup(name.c_str());
|
||||
boost::shared_ptr<i2p_stream::handler_type> h(new i2p_stream::handler_type(
|
||||
boost::bind(&i2p_connection::on_name_lookup, this, _1, handler)));
|
||||
boost::bind(&i2p_connection::on_name_lookup, this, _1, handler, m_sam_socket)));
|
||||
m_sam_socket->send_name_lookup(h);
|
||||
}
|
||||
|
||||
void i2p_connection::on_name_lookup(error_code const& ec
|
||||
, name_lookup_handler handler)
|
||||
, name_lookup_handler handler, boost::shared_ptr<i2p_stream>)
|
||||
{
|
||||
m_state = sam_idle;
|
||||
|
||||
|
@ -178,20 +182,39 @@ namespace libtorrent
|
|||
handler(ec, name.c_str());
|
||||
}
|
||||
|
||||
i2p_stream::i2p_stream(io_service& io_service)
|
||||
: proxy_base(io_service)
|
||||
, m_id(0)
|
||||
, m_command(cmd_create_session)
|
||||
, m_state(0)
|
||||
{
|
||||
#ifdef TORRENT_DEBUG
|
||||
m_magic = 0x1337;
|
||||
#endif
|
||||
}
|
||||
|
||||
i2p_stream::~i2p_stream()
|
||||
{
|
||||
#ifdef TORRENT_DEBUG
|
||||
TORRENT_ASSERT(m_magic == 0x1337);
|
||||
m_magic = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// TODO: move this to proxy_base and use it in all proxies
|
||||
bool i2p_stream::handle_error(error_code const& e, boost::shared_ptr<handler_type> const& h)
|
||||
{
|
||||
TORRENT_ASSERT(m_magic == 0x1337);
|
||||
if (!e) return false;
|
||||
// fprintf(stderr, "i2p error \"%s\"\n", e.message().c_str());
|
||||
(*h)(e);
|
||||
error_code ec;
|
||||
close(ec);
|
||||
return true;
|
||||
}
|
||||
|
||||
void i2p_stream::do_connect(error_code const& e, tcp::resolver::iterator i
|
||||
, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
TORRENT_ASSERT(m_magic == 0x1337);
|
||||
if (e || i == tcp::resolver::iterator())
|
||||
{
|
||||
(*h)(e);
|
||||
|
@ -209,6 +232,7 @@ namespace libtorrent
|
|||
|
||||
void i2p_stream::connected(error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
TORRENT_ASSERT(m_magic == 0x1337);
|
||||
#if defined TORRENT_ASIO_DEBUGGING
|
||||
complete_async("i2p_stream::connected");
|
||||
#endif
|
||||
|
@ -223,11 +247,12 @@ namespace libtorrent
|
|||
#endif
|
||||
async_write(m_sock, asio::buffer(cmd, sizeof(cmd) - 1)
|
||||
, boost::bind(&i2p_stream::start_read_line, this, _1, h));
|
||||
// fputs(cmd, stderr);
|
||||
// fprintf(stderr, ">>> %s", cmd);
|
||||
}
|
||||
|
||||
void i2p_stream::start_read_line(error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
TORRENT_ASSERT(m_magic == 0x1337);
|
||||
#if defined TORRENT_ASIO_DEBUGGING
|
||||
complete_async("i2p_stream::start_read_line");
|
||||
#endif
|
||||
|
@ -244,7 +269,17 @@ namespace libtorrent
|
|||
char* string_tokenize(char* last, char sep, char** next)
|
||||
{
|
||||
if (last == 0) return 0;
|
||||
*next = strchr(last, sep);
|
||||
if (last[0] == '"')
|
||||
{
|
||||
*next = strchr(last + 1, '"');
|
||||
// consume the actual separator as well.
|
||||
if (*next != NULL)
|
||||
*next = strchr(*next, sep);
|
||||
}
|
||||
else
|
||||
{
|
||||
*next = strchr(last, sep);
|
||||
}
|
||||
if (*next == 0) return last;
|
||||
**next = 0;
|
||||
++(*next);
|
||||
|
@ -254,6 +289,7 @@ namespace libtorrent
|
|||
|
||||
void i2p_stream::read_line(error_code const& e, boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
TORRENT_ASSERT(m_magic == 0x1337);
|
||||
#if defined TORRENT_ASIO_DEBUGGING
|
||||
complete_async("i2p_stream::read_line");
|
||||
#endif
|
||||
|
@ -261,7 +297,6 @@ namespace libtorrent
|
|||
|
||||
int read_pos = m_buffer.size();
|
||||
|
||||
// fprintf(stderr, "%c", m_buffer[read_pos - 1]);
|
||||
// look for \n which means end of the response
|
||||
if (m_buffer[read_pos - 1] != '\n')
|
||||
{
|
||||
|
@ -318,6 +353,7 @@ namespace libtorrent
|
|||
break;
|
||||
}
|
||||
|
||||
// fprintf(stderr, "<<< %s\n", &m_buffer[0]);
|
||||
ptr = string_tokenize(next, ' ', &next);
|
||||
if (ptr == 0 || expect1 == 0 || strcmp(expect1, ptr)) { handle_error(invalid_response, h); return; }
|
||||
ptr = string_tokenize(next, ' ', &next);
|
||||
|
@ -331,8 +367,10 @@ namespace libtorrent
|
|||
{
|
||||
char* name = string_tokenize(next, '=', &next);
|
||||
if (name == 0) break;
|
||||
// fprintf(stderr, "name=\"%s\"\n", name);
|
||||
char* ptr = string_tokenize(next, ' ', &next);
|
||||
if (ptr == 0) { handle_error(invalid_response, h); return; }
|
||||
// fprintf(stderr, "value=\"%s\"\n", ptr);
|
||||
|
||||
if (strcmp("RESULT", name) == 0)
|
||||
{
|
||||
|
@ -350,6 +388,8 @@ namespace libtorrent
|
|||
result = i2p_error::timeout;
|
||||
else if (strcmp("KEY_NOT_FOUND", ptr) == 0)
|
||||
result = i2p_error::key_not_found;
|
||||
else if (strcmp("DUPLICATED_ID", ptr) == 0)
|
||||
result = i2p_error::duplicated_id;
|
||||
else
|
||||
result = i2p_error::num_errors; // unknown error
|
||||
}
|
||||
|
@ -423,11 +463,12 @@ namespace libtorrent
|
|||
|
||||
void i2p_stream::send_connect(boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
TORRENT_ASSERT(m_magic == 0x1337);
|
||||
m_state = read_connect_response;
|
||||
char cmd[1024];
|
||||
int size = snprintf(cmd, sizeof(cmd), "STREAM CONNECT ID=%s DESTINATION=%s\n"
|
||||
, m_id, m_dest.c_str());
|
||||
// fputs(cmd, stderr);
|
||||
// fprintf(stderr, ">>> %s", cmd);
|
||||
#if defined TORRENT_ASIO_DEBUGGING
|
||||
add_outstanding_async("i2p_stream::start_read_line");
|
||||
#endif
|
||||
|
@ -437,10 +478,11 @@ namespace libtorrent
|
|||
|
||||
void i2p_stream::send_accept(boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
TORRENT_ASSERT(m_magic == 0x1337);
|
||||
m_state = read_accept_response;
|
||||
char cmd[400];
|
||||
int size = snprintf(cmd, sizeof(cmd), "STREAM ACCEPT ID=%s\n", m_id);
|
||||
// fputs(cmd, stderr);
|
||||
// fprintf(stderr, ">>> %s", cmd);
|
||||
#if defined TORRENT_ASIO_DEBUGGING
|
||||
add_outstanding_async("i2p_stream::start_read_line");
|
||||
#endif
|
||||
|
@ -450,11 +492,12 @@ namespace libtorrent
|
|||
|
||||
void i2p_stream::send_session_create(boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
TORRENT_ASSERT(m_magic == 0x1337);
|
||||
m_state = read_session_create_response;
|
||||
char cmd[400];
|
||||
int size = snprintf(cmd, sizeof(cmd), "SESSION CREATE STYLE=STREAM ID=%s DESTINATION=TRANSIENT\n"
|
||||
, m_id);
|
||||
// fputs(cmd, stderr);
|
||||
// fprintf(stderr, ">>> %s", cmd);
|
||||
#if defined TORRENT_ASIO_DEBUGGING
|
||||
add_outstanding_async("i2p_stream::start_read_line");
|
||||
#endif
|
||||
|
@ -464,10 +507,11 @@ namespace libtorrent
|
|||
|
||||
void i2p_stream::send_name_lookup(boost::shared_ptr<handler_type> h)
|
||||
{
|
||||
TORRENT_ASSERT(m_magic == 0x1337);
|
||||
m_state = read_name_lookup_response;
|
||||
char cmd[1024];
|
||||
int size = snprintf(cmd, sizeof(cmd), "NAMING LOOKUP NAME=%s\n", m_name_lookup.c_str());
|
||||
// fputs(cmd, stderr);
|
||||
// fprintf(stderr, ">>> %s", cmd);
|
||||
#if defined TORRENT_ASIO_DEBUGGING
|
||||
add_outstanding_async("i2p_stream::start_read_line");
|
||||
#endif
|
||||
|
|
|
@ -475,7 +475,6 @@ namespace libtorrent
|
|||
disconnect(ec);
|
||||
return;
|
||||
}
|
||||
TORRENT_ASSERT(m_remote.address() != address_v4::any());
|
||||
if (m_remote.address().is_v4())
|
||||
{
|
||||
m_socket->set_option(type_of_service(m_ses.settings().peer_tos), ec);
|
||||
|
|
|
@ -1190,8 +1190,11 @@ namespace libtorrent
|
|||
#ifdef TORRENT_DEBUG
|
||||
else
|
||||
{
|
||||
std::pair<iterator, iterator> range = find_peers(p->address());
|
||||
TORRENT_ASSERT(range.second - range.first == 1);
|
||||
if (!p->is_i2p_addr)
|
||||
{
|
||||
std::pair<iterator, iterator> range = find_peers(p->address());
|
||||
TORRENT_ASSERT(range.second - range.first == 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -2618,8 +2618,41 @@ retry:
|
|||
}
|
||||
|
||||
#if TORRENT_USE_I2P
|
||||
void session_impl::set_i2p_proxy(proxy_settings const& s)
|
||||
{
|
||||
#if defined TORRENT_ASIO_DEBUGGING
|
||||
add_outstanding_async("session_impl::on_i2p_open");
|
||||
#endif
|
||||
// we need this socket to be open before we
|
||||
// can make name lookups for trackers for instance.
|
||||
// pause the session now and resume it once we've
|
||||
// established the i2p SAM connection
|
||||
pause();
|
||||
m_i2p_conn.open(s, boost::bind(&session_impl::on_i2p_open, this, _1));
|
||||
open_new_incoming_i2p_connection();
|
||||
}
|
||||
|
||||
void session_impl::on_i2p_open(error_code const& ec)
|
||||
{
|
||||
#if defined TORRENT_ASIO_DEBUGGING
|
||||
complete_async("session_impl::on_i2p_open");
|
||||
#endif
|
||||
if (ec)
|
||||
{
|
||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||
char msg[200];
|
||||
snprintf(msg, sizeof(msg), "i2p open failed (%d) %s", ec.value(), ec.message().c_str());
|
||||
(*m_logger) << msg << "\n";
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// now that we have our i2p connection established
|
||||
// it's OK to start torrents and use this socket to
|
||||
// do i2p name lookups
|
||||
resume();
|
||||
}
|
||||
|
||||
open_new_incoming_i2p_connection();
|
||||
}
|
||||
|
||||
|
@ -2889,8 +2922,6 @@ retry:
|
|||
return;
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(endp.address() != address_v4::any());
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
session_log(" <== INCOMING CONNECTION %s type: %s"
|
||||
, print_endpoint(endp).c_str(), s->type_name());
|
||||
|
|
|
@ -72,6 +72,17 @@ namespace libtorrent
|
|||
;
|
||||
}
|
||||
|
||||
#if TORRENT_USE_I2P
|
||||
bool is_i2p(socket_type const& s)
|
||||
{
|
||||
return s.get<i2p_stream>()
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
|| s.get<ssl_stream<i2p_stream> >()
|
||||
#endif
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
void setup_ssl_hostname(socket_type& s, std::string const& hostname, error_code& ec)
|
||||
{
|
||||
#if defined TORRENT_USE_OPENSSL && BOOST_VERSION >= 104700
|
||||
|
|
Loading…
Reference in New Issue