Merge pull request #376 from PurpleI2P/openssl

recent changes
This commit is contained in:
orignal 2016-02-11 14:37:11 -05:00
commit 07adf64aec
16 changed files with 148 additions and 76 deletions

View File

@ -129,7 +129,7 @@ namespace client
{
int num = 0;
auto filename = GetPath () / "addresses.csv";
std::ifstream f (filename.string (), std::ofstream::in); // in text mode
std::ifstream f (filename.string (), std::ifstream::in); // in text mode
if (f.is_open ())
{
addresses.clear ();
@ -161,6 +161,11 @@ namespace client
int AddressBookFilesystemStorage::Save (const std::map<std::string, i2p::data::IdentHash>& addresses)
{
if (addresses.size() == 0) {
LogPrint(eLogWarning, "Addressbook: not saving empty addressbook");
return 0;
}
int num = 0;
auto filename = GetPath () / "addresses.csv";
std::ofstream f (filename.string (), std::ofstream::out); // in text mode
@ -191,6 +196,7 @@ namespace client
void AddressBook::Start ()
{
LoadHosts (); /* try storage, then hosts.txt, then download */
StartSubscriptions ();
}
@ -271,14 +277,9 @@ namespace client
const i2p::data::IdentHash * AddressBook::FindAddress (const std::string& address)
{
if (!m_IsLoaded)
LoadHosts ();
if (m_IsLoaded)
{
auto it = m_Addresses.find (address);
if (it != m_Addresses.end ())
return &it->second;
}
auto it = m_Addresses.find (address);
if (it != m_Addresses.end ())
return &it->second;
return nullptr;
}
@ -320,7 +321,7 @@ namespace client
}
// try hosts.txt first
std::ifstream f (i2p::util::filesystem::GetFullPath ("hosts.txt").c_str (), std::ofstream::in); // in text mode
std::ifstream f (i2p::util::filesystem::GetFullPath ("hosts.txt").c_str (), std::ifstream::in); // in text mode
if (f.is_open ())
{
LoadHostsFromStream (f);
@ -383,7 +384,7 @@ namespace client
{
if (!m_Subscriptions.size ())
{
std::ifstream f (i2p::util::filesystem::GetFullPath ("subscriptions.txt").c_str (), std::ofstream::in); // in text mode
std::ifstream f (i2p::util::filesystem::GetFullPath ("subscriptions.txt").c_str (), std::ifstream::in); // in text mode
if (f.is_open ())
{
std::string s;
@ -452,8 +453,6 @@ namespace client
}
else
{
if (!m_IsLoaded)
LoadHosts ();
// try it again later
m_SubscriptionsUpdateTimer->expires_from_now (boost::posix_time::minutes(INITIAL_SUBSCRIPTION_RETRY_TIMEOUT));
m_SubscriptionsUpdateTimer->async_wait (std::bind (&AddressBook::HandleSubscriptionsUpdateTimer,

View File

@ -191,7 +191,7 @@ namespace config {
| boost::program_options::command_line_style::allow_long_disguise;
style &= ~ boost::program_options::command_line_style::allow_guessing;
store(parse_command_line(argc, argv, m_OptionsDesc, style, old_syntax_parser), m_Options);
} catch (boost::program_options::error e) {
} catch (boost::program_options::error& e) {
std::cerr << "args: " << e.what() << std::endl;
exit(EXIT_FAILURE);
}
@ -204,19 +204,22 @@ namespace config {
}
void ParseConfig(const std::string& path) {
if (path == "")
return;
if (path == "") return;
std::ifstream config(path, std::ios::in);
if (!config.is_open()) {
if (!config.is_open())
{
std::cerr << "missing/unreadable config file: " << path << std::endl;
exit(EXIT_FAILURE);
}
try {
store(boost::program_options::parse_config_file(config, m_OptionsDesc), m_Options);
} catch (boost::program_options::error e) {
try
{
store(boost::program_options::parse_config_file(config, m_OptionsDesc), m_Options);
}
catch (boost::program_options::error& e)
{
std::cerr << e.what() << std::endl;
exit(EXIT_FAILURE);
};

View File

@ -109,6 +109,8 @@ namespace i2p
LogPrint(eLogInfo, "Daemon: router will be floodfill");
i2p::context.SetFloodfill (true);
}
else
i2p::context.SetFloodfill (false);
if (bandwidth != '-')
{
LogPrint(eLogInfo, "Daemon: bandwidth set to ", bandwidth);

View File

@ -42,7 +42,27 @@ namespace garlic
delete it.second;
m_UnconfirmedTagsMsgs.clear ();
}
std::shared_ptr<GarlicRoutingPath> GarlicRoutingSession::GetSharedRoutingPath ()
{
if (!m_SharedRoutingPath) return nullptr;
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
if (!m_SharedRoutingPath->outboundTunnel->IsEstablished () ||
ts*1000LL > m_SharedRoutingPath->remoteLease->endDate ||
ts > m_SharedRoutingPath->updateTime + ROUTING_PATH_EXPIRATION_TIMEOUT)
m_SharedRoutingPath = nullptr;
return m_SharedRoutingPath;
}
void GarlicRoutingSession::SetSharedRoutingPath (std::shared_ptr<GarlicRoutingPath> path)
{
if (path && path->outboundTunnel && path->remoteLease)
path->updateTime = i2p::util::GetSecondsSinceEpoch ();
else
path = nullptr;
m_SharedRoutingPath = path;
}
GarlicRoutingSession::UnconfirmedTags * GarlicRoutingSession::GenerateSessionTags ()
{
auto tags = new UnconfirmedTags (m_NumTags);
@ -139,7 +159,7 @@ namespace garlic
// create message
if (!tagFound) // new session
{
LogPrint (eLogWarning, "Garlic: No tags available. Use ElGamal");
LogPrint (eLogWarning, "Garlic: No tags available, will use ElGamal");
if (!m_Destination)
{
LogPrint (eLogError, "Garlic: Can't use ElGamal for unknown destination");
@ -570,6 +590,7 @@ namespace garlic
std::unique_lock<std::mutex> l(m_SessionsMutex);
for (auto it = m_Sessions.begin (); it != m_Sessions.end ();)
{
it->second->GetSharedRoutingPath (); // delete shared path if necessary
if (!it->second->CleanupExpiredTags ())
{
LogPrint (eLogInfo, "Routing session to ", it->first.ToBase32 (), " deleted");

View File

@ -15,7 +15,12 @@
#include "Identity.h"
namespace i2p
{
{
namespace tunnel
{
class OutboundTunnel;
}
namespace garlic
{
@ -27,19 +32,18 @@ namespace garlic
eGarlicDeliveryTypeTunnel = 3
};
#pragma pack(1)
struct ElGamalBlock
{
uint8_t sessionKey[32];
uint8_t preIV[32];
uint8_t padding[158];
};
#pragma pack()
const int INCOMING_TAGS_EXPIRATION_TIMEOUT = 960; // 16 minutes
const int OUTGOING_TAGS_EXPIRATION_TIMEOUT = 720; // 12 minutes
const int OUTGOING_TAGS_CONFIRMATION_TIMEOUT = 10; // 10 seconds
const int LEASET_CONFIRMATION_TIMEOUT = 4000; // in milliseconds
const int ROUTING_PATH_EXPIRATION_TIMEOUT = 30; // 30 seconds
struct SessionTag: public i2p::data::Tag<32>
{
@ -53,7 +57,14 @@ namespace garlic
#endif
uint32_t creationTime; // seconds since epoch
};
struct GarlicRoutingPath
{
std::shared_ptr<i2p::tunnel::OutboundTunnel> outboundTunnel;
std::shared_ptr<const i2p::data::Lease> remoteLease;
uint32_t updateTime; // seconds since epoch
};
class GarlicDestination;
class GarlicRoutingSession: public std::enable_shared_from_this<GarlicRoutingSession>
{
@ -88,6 +99,9 @@ namespace garlic
{
if (m_LeaseSetUpdateStatus != eLeaseSetDoNotSend) m_LeaseSetUpdateStatus = eLeaseSetUpdated;
};
std::shared_ptr<GarlicRoutingPath> GetSharedRoutingPath ();
void SetSharedRoutingPath (std::shared_ptr<GarlicRoutingPath> path);
private:
@ -115,6 +129,8 @@ namespace garlic
i2p::crypto::CBCEncryption m_Encryption;
std::unique_ptr<const i2p::crypto::ElGamalEncryption> m_ElGamalEncryption;
std::shared_ptr<GarlicRoutingPath> m_SharedRoutingPath;
public:
// for HTTP only
size_t GetNumOutgoingTags () const { return m_SessionTags.size (); };

View File

@ -65,13 +65,13 @@ namespace proxy
void HTTPProxyHandler::AsyncSockRead()
{
LogPrint(eLogDebug,"--- HTTP Proxy async sock read");
LogPrint(eLogDebug, "HTTPProxy: async sock read");
if(m_sock) {
m_sock->async_receive(boost::asio::buffer(m_http_buff, http_buffer_size),
std::bind(&HTTPProxyHandler::HandleSockRecv, shared_from_this(),
std::placeholders::_1, std::placeholders::_2));
} else {
LogPrint(eLogError,"--- HTTP Proxy no socket for read");
LogPrint(eLogError, "HTTPProxy: no socket for read");
}
}
@ -79,7 +79,7 @@ namespace proxy
if (Kill()) return;
if (m_sock)
{
LogPrint(eLogDebug,"--- HTTP Proxy close sock");
LogPrint(eLogDebug, "HTTPProxy: close sock");
m_sock->close();
m_sock = nullptr;
}
@ -102,7 +102,7 @@ namespace proxy
void HTTPProxyHandler::ExtractRequest()
{
LogPrint(eLogDebug,"--- HTTP Proxy method is: ", m_method, "\nRequest is: ", m_url);
LogPrint(eLogDebug, "HTTPProxy: request: ", m_method, " ", m_url);
std::string server="";
std::string port="80";
boost::regex rHTTP("http://(.*?)(:(\\d+))?(/.*)");
@ -114,7 +114,7 @@ namespace proxy
if (m[2].str() != "") port=m[3].str();
path=m[4].str();
}
LogPrint(eLogDebug,"--- HTTP Proxy server is: ",server, " port is: ", port, "\n path is: ",path);
LogPrint(eLogDebug, "HTTPProxy: server: ", server, ", port: ", port, ", path: ", path);
m_address = server;
m_port = boost::lexical_cast<int>(port);
m_path = path;
@ -124,7 +124,7 @@ namespace proxy
{
if ( m_version != "HTTP/1.0" && m_version != "HTTP/1.1" )
{
LogPrint(eLogError,"--- HTTP Proxy unsupported version: ", m_version);
LogPrint(eLogError, "HTTPProxy: unsupported version: ", m_version);
HTTPRequestFailed(); //TODO: send right stuff
return false;
}
@ -156,7 +156,7 @@ namespace proxy
}
auto base64 = m_path.substr (addressHelperPos + strlen(helpermark1));
base64 = i2p::util::http::urlDecode(base64); //Some of the symbols may be urlencoded
LogPrint (eLogDebug,"Jump service for ", m_address, " found at ", base64, ". Inserting to address book");
LogPrint (eLogInfo, "HTTPProxy: jump service for ", m_address, ", inserting to address book");
//TODO: this is very dangerous and broken. We should ask the user before doing anything see http://pastethis.i2p/raw/pn5fL4YNJL7OSWj3Sc6N/
//TODO: we could redirect the user again to avoid dirtiness in the browser
i2p::client::context.GetAddressBook ().InsertAddress (m_address, base64);
@ -229,13 +229,13 @@ namespace proxy
{
case '\n': EnterState(DONE); break;
default:
LogPrint(eLogError,"--- HTTP Proxy rejected invalid request ending with: ", ((int)*http_buff));
LogPrint(eLogError, "HTTPProxy: rejected invalid request ending with: ", ((int)*http_buff));
HTTPRequestFailed(); //TODO: add correct code
return false;
}
break;
default:
LogPrint(eLogError,"--- HTTP Proxy invalid state: ", m_state);
LogPrint(eLogError, "HTTPProxy: invalid state: ", m_state);
HTTPRequestFailed(); //TODO: add correct code 500
return false;
}
@ -249,11 +249,11 @@ namespace proxy
void HTTPProxyHandler::HandleSockRecv(const boost::system::error_code & ecode, std::size_t len)
{
LogPrint(eLogDebug,"--- HTTP Proxy sock recv: ", len);
LogPrint(eLogDebug, "HTTPProxy: sock recv: ", len, " bytes");
if(ecode)
{
LogPrint(eLogWarning," --- HTTP Proxy sock recv got error: ", ecode);
Terminate();
LogPrint(eLogWarning, "HTTPProxy: sock recv got error: ", ecode);
Terminate();
return;
}
@ -261,7 +261,7 @@ namespace proxy
{
if (m_state == DONE)
{
LogPrint(eLogInfo,"--- HTTP Proxy requested: ", m_url);
LogPrint(eLogDebug, "HTTPProxy: requested: ", m_url);
GetOwner()->CreateStream (std::bind (&HTTPProxyHandler::HandleStreamRequestComplete,
shared_from_this(), std::placeholders::_1), m_address, m_port);
}
@ -273,13 +273,9 @@ namespace proxy
void HTTPProxyHandler::SentHTTPFailed(const boost::system::error_code & ecode)
{
if (!ecode)
Terminate();
else
{
LogPrint (eLogError,"--- HTTP Proxy Closing socket after sending failure because: ", ecode.message ());
Terminate();
}
if (ecode)
LogPrint (eLogError, "HTTPProxy: Closing socket after sending failure because: ", ecode.message ());
Terminate();
}
void HTTPProxyHandler::HandleStreamRequestComplete (std::shared_ptr<i2p::stream::Stream> stream)
@ -287,7 +283,7 @@ namespace proxy
if (stream)
{
if (Kill()) return;
LogPrint (eLogInfo,"--- HTTP Proxy New I2PTunnel connection");
LogPrint (eLogInfo, "HTTPProxy: New I2PTunnel connection");
auto connection = std::make_shared<i2p::client::I2PTunnelConnection>(GetOwner(), m_sock, stream);
GetOwner()->AddHandler (connection);
connection->I2PConnect (reinterpret_cast<const uint8_t*>(m_request.data()), m_request.size());
@ -295,7 +291,7 @@ namespace proxy
}
else
{
LogPrint (eLogError,"--- HTTP Proxy Issue when creating the stream, check the previous warnings for more info.");
LogPrint (eLogError, "HTTPProxy: error when creating the stream, check the previous warnings for more info");
HTTPRequestFailed(); // TODO: Send correct error message host unreachable
}
}

View File

@ -205,7 +205,7 @@ namespace client
}
if (ss.eof ())
{
LogPrint (eLogError, "Malformed I2PControl request. HTTP header expected");
LogPrint (eLogError, "I2PControl: malformed request, HTTP header expected");
return; // TODO:
}
std::streamoff rem = contentLength + ss.tellg () - bytes_transferred; // more bytes to read
@ -215,8 +215,12 @@ namespace client
ss.write (buf->data (), bytes_transferred);
}
}
std::ostringstream response;
#if GCC47_BOOST149
LogPrint (eLogError, "json_read is not supported due bug in boost 1.49 with gcc 4.7");
LogPrint (eLogError, "I2PControl: json_read is not supported due bug in boost 1.49 with gcc 4.7");
response << "{\"id\":null,\"error\":";
response << "{\"code\":-32603,\"message\":\"JSON requests is not supported with this version of boost\"},";
response << "\"jsonrpc\":\"2.0\"}";
#else
boost::property_tree::ptree pt;
boost::property_tree::read_json (ss, pt);
@ -226,23 +230,25 @@ namespace client
auto it = m_MethodHandlers.find (method);
if (it != m_MethodHandlers.end ())
{
std::ostringstream response;
response << "{\"id\":" << id << ",\"result\":{";
(this->*(it->second))(pt.get_child ("params"), response);
response << "},\"jsonrpc\":\"2.0\"}";
SendResponse (socket, buf, response, isHtml);
} else {
LogPrint (eLogWarning, "I2PControl: unknown method ", method);
response << "{\"id\":null,\"error\":";
response << "{\"code\":-32601,\"message\":\"Method not found\"},";
response << "\"jsonrpc\":\"2.0\"}";
}
else
LogPrint (eLogWarning, "Unknown I2PControl method ", method);
#endif
SendResponse (socket, buf, response, isHtml);
}
catch (std::exception& ex)
{
LogPrint (eLogError, "I2PControl handle request: ", ex.what ());
LogPrint (eLogError, "I2PControl: exception when handle request: ", ex.what ());
}
catch (...)
{
LogPrint (eLogError, "I2PControl handle request unknown exception");
LogPrint (eLogError, "I2PControl: handle request unknown exception");
}
}
}
@ -527,7 +533,7 @@ namespace client
// save key
if ((f = fopen (key_path, "wb")) != NULL) {
LogPrint (eLogInfo, "I2PControl: saving cert key to : ", key_path);
LogPrint (eLogInfo, "I2PControl: saving cert key to ", key_path);
PEM_write_PrivateKey (f, pkey, NULL, NULL, 0, NULL, NULL);
fclose (f);
} else {

View File

@ -28,7 +28,7 @@ namespace client
m_LocalDestination->CreateStream (streamRequestComplete, identHash, port);
else
{
LogPrint (eLogWarning, "Remote destination ", dest, " not found");
LogPrint (eLogWarning, "I2PService: Remote destination ", dest, " not found");
streamRequestComplete (nullptr);
}
}
@ -57,7 +57,7 @@ namespace client
{
if (!ecode)
{
LogPrint(eLogDebug,"--- ",GetName()," accepted");
LogPrint(eLogDebug, "I2PService: ", GetName(), " accepted");
auto handler = CreateHandler(socket);
if (handler)
{
@ -71,7 +71,7 @@ namespace client
else
{
if (ecode != boost::asio::error::operation_aborted)
LogPrint (eLogError,"--- ",GetName()," Closing socket on accept because: ", ecode.message ());
LogPrint (eLogError, "I2PService: ", GetName(), " closing socket on accept because: ", ecode.message ());
}
}

View File

@ -180,10 +180,10 @@ namespace data
}
}
const std::vector<std::shared_ptr<Lease> > LeaseSet::GetNonExpiredLeases (bool withThreshold) const
const std::vector<std::shared_ptr<const Lease> > LeaseSet::GetNonExpiredLeases (bool withThreshold) const
{
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
std::vector<std::shared_ptr<Lease> > leases;
std::vector<std::shared_ptr<const Lease> > leases;
for (auto it: m_Leases)
{
auto endDate = it->endDate;

View File

@ -52,7 +52,7 @@ namespace data
const uint8_t * GetBuffer () const { return m_Buffer; };
size_t GetBufferLen () const { return m_BufferLen; };
bool IsValid () const { return m_IsValid; };
const std::vector<std::shared_ptr<Lease> > GetNonExpiredLeases (bool withThreshold = true) const;
const std::vector<std::shared_ptr<const Lease> > GetNonExpiredLeases (bool withThreshold = true) const;
bool HasExpiredLeases () const;
bool IsExpired () const;
bool IsEmpty () const { return m_Leases.empty (); };

View File

@ -78,6 +78,9 @@ clean:
rm -rf obj
$(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT)
strip: $(I2PD) $(SHLIB_CLIENT) $(SHLIB)
strip $^
LATEST_TAG=$(shell git describe --tags --abbrev=0 master)
dist:
git archive --format=tar.gz -9 --worktree-attributes \

View File

@ -503,12 +503,13 @@ namespace transport
void NTCPSession::HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred)
{
if (ecode)
{
LogPrint (eLogInfo, "NTCP: Read error: ", ecode.message ());
if (!m_NumReceivedBytes) m_Server.Ban (m_ConnectedFrom);
if (ecode) {
if (ecode != boost::asio::error::operation_aborted)
LogPrint (eLogDebug, "NTCP: Read error: ", ecode.message ());
if (!m_NumReceivedBytes)
m_Server.Ban (m_ConnectedFrom);
//if (ecode != boost::asio::error::operation_aborted)
Terminate ();
Terminate ();
}
else
{
@ -736,7 +737,7 @@ namespace transport
{
if (ecode != boost::asio::error::operation_aborted)
{
LogPrint (eLogWarning, "NTCP: No activity for ", NTCP_TERMINATION_TIMEOUT, " seconds");
LogPrint (eLogDebug, "NTCP: No activity for ", NTCP_TERMINATION_TIMEOUT, " seconds");
//Terminate ();
m_Socket.close ();// invoke Terminate () from HandleReceive
}

View File

@ -292,7 +292,7 @@ namespace i2p
bool RouterContext::Load ()
{
std::ifstream fk (i2p::util::filesystem::GetFullPath (ROUTER_KEYS).c_str (), std::ifstream::binary | std::ofstream::in);
std::ifstream fk (i2p::util::filesystem::GetFullPath (ROUTER_KEYS).c_str (), std::ifstream::binary | std::ifstream::in);
if (!fk.is_open ()) return false;
fk.seekg (0, std::ios::end);
size_t len = fk.tellg();

View File

@ -146,6 +146,7 @@ namespace data
bool introducers = false;
for (int i = 0; i < numAddresses; i++)
{
uint8_t supportedTransports = 0;
bool isValidAddress = true;
Address address;
s.read ((char *)&address.cost, sizeof (address.cost));
@ -178,12 +179,12 @@ namespace data
{
if (address.transportStyle == eTransportNTCP)
{
m_SupportedTransports |= eNTCPV4; // TODO:
supportedTransports |= eNTCPV4; // TODO:
address.addressString = value;
}
else
{
m_SupportedTransports |= eSSUV4; // TODO:
supportedTransports |= eSSUV4; // TODO:
address.addressString = value;
}
}
@ -191,9 +192,9 @@ namespace data
{
// add supported protocol
if (address.host.is_v4 ())
m_SupportedTransports |= (address.transportStyle == eTransportNTCP) ? eNTCPV4 : eSSUV4;
supportedTransports |= (address.transportStyle == eTransportNTCP) ? eNTCPV4 : eSSUV4;
else
m_SupportedTransports |= (address.transportStyle == eTransportNTCP) ? eNTCPV6 : eSSUV6;
supportedTransports |= (address.transportStyle == eTransportNTCP) ? eNTCPV6 : eSSUV6;
}
}
else if (!strcmp (key, "port"))
@ -229,7 +230,10 @@ namespace data
if (!s) return;
}
if (isValidAddress)
{
m_Addresses.push_back(address);
m_SupportedTransports |= supportedTransports;
}
}
// read peers
uint8_t numPeers;

View File

@ -271,6 +271,10 @@ namespace stream
m_LastWindowSizeIncreaseTime = ts;
}
}
if (!seqn && m_RoutingSession) // first message confirmed
m_RoutingSession->SetSharedRoutingPath (
std::make_shared<i2p::garlic::GarlicRoutingPath> (
i2p::garlic::GarlicRoutingPath{m_CurrentOutboundTunnel, m_CurrentRemoteLease, 0}));
}
else
break;
@ -589,6 +593,21 @@ namespace stream
return;
}
}
if (!m_CurrentOutboundTunnel) // first message to send
{
// try to get shared path first
if (!m_RoutingSession)
m_RoutingSession = m_LocalDestination.GetOwner ()->GetRoutingSession (m_RemoteLeaseSet, true);
if (m_RoutingSession)
{
auto routingPath = m_RoutingSession->GetSharedRoutingPath ();
if (routingPath)
{
m_CurrentOutboundTunnel = routingPath->outboundTunnel;
m_CurrentRemoteLease = routingPath->remoteLease;
}
}
}
if (!m_CurrentOutboundTunnel || !m_CurrentOutboundTunnel->IsEstablished ())
m_CurrentOutboundTunnel = m_LocalDestination.GetOwner ()->GetTunnelPool ()->GetNewOutboundTunnel (m_CurrentOutboundTunnel);
if (!m_CurrentOutboundTunnel)
@ -668,12 +687,14 @@ namespace stream
case 2:
m_RTO = INITIAL_RTO; // drop RTO to initial upon tunnels pair change first time
// no break here
case 4:
case 4:
if (m_RoutingSession) m_RoutingSession->SetSharedRoutingPath (nullptr);
UpdateCurrentRemoteLease (); // pick another lease
LogPrint (eLogWarning, "Streaming: Another remote lease has been selected for stream");
break;
case 3:
// pick another outbound tunnel
if (m_RoutingSession) m_RoutingSession->SetSharedRoutingPath (nullptr);
m_CurrentOutboundTunnel = m_LocalDestination.GetOwner ()->GetTunnelPool ()->GetNextOutboundTunnel (m_CurrentOutboundTunnel);
LogPrint (eLogWarning, "Streaming: Another outbound tunnel has been selected for stream");
break;

View File

@ -172,7 +172,7 @@ namespace stream
std::shared_ptr<const i2p::data::IdentityEx> m_RemoteIdentity;
std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet;
std::shared_ptr<i2p::garlic::GarlicRoutingSession> m_RoutingSession;
std::shared_ptr<i2p::data::Lease> m_CurrentRemoteLease;
std::shared_ptr<const i2p::data::Lease> m_CurrentRemoteLease;
std::shared_ptr<i2p::tunnel::OutboundTunnel> m_CurrentOutboundTunnel;
std::queue<Packet *> m_ReceiveQueue;
std::set<Packet *, PacketCmp> m_SavedPackets;