merged i2p fix from RC_0_16

This commit is contained in:
Arvid Norberg 2013-10-27 19:56:37 +00:00
parent 1d55894bef
commit cbe3a72a6e
12 changed files with 136 additions and 35 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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(); }

View File

@ -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);

View File

@ -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
};

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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());

View File

@ -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