diff --git a/AddressBook.cpp b/AddressBook.cpp index 754d314a..1c2f3e24 100644 --- a/AddressBook.cpp +++ b/AddressBook.cpp @@ -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& 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, diff --git a/Config.cpp b/Config.cpp index 9e9582ea..8e212360 100644 --- a/Config.cpp +++ b/Config.cpp @@ -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); }; diff --git a/Daemon.cpp b/Daemon.cpp index e972cee3..242f4bbf 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -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); diff --git a/Garlic.cpp b/Garlic.cpp index 88e255ff..f967a1e2 100644 --- a/Garlic.cpp +++ b/Garlic.cpp @@ -42,7 +42,27 @@ namespace garlic delete it.second; m_UnconfirmedTagsMsgs.clear (); } - + + std::shared_ptr 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 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 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"); diff --git a/Garlic.h b/Garlic.h index b42f92cf..95a59e72 100644 --- a/Garlic.h +++ b/Garlic.h @@ -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 outboundTunnel; + std::shared_ptr remoteLease; + uint32_t updateTime; // seconds since epoch + }; + class GarlicDestination; class GarlicRoutingSession: public std::enable_shared_from_this { @@ -88,6 +99,9 @@ namespace garlic { if (m_LeaseSetUpdateStatus != eLeaseSetDoNotSend) m_LeaseSetUpdateStatus = eLeaseSetUpdated; }; + + std::shared_ptr GetSharedRoutingPath (); + void SetSharedRoutingPath (std::shared_ptr path); private: @@ -115,6 +129,8 @@ namespace garlic i2p::crypto::CBCEncryption m_Encryption; std::unique_ptr m_ElGamalEncryption; + std::shared_ptr m_SharedRoutingPath; + public: // for HTTP only size_t GetNumOutgoingTags () const { return m_SessionTags.size (); }; diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index b4010a37..c417d904 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -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(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 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(GetOwner(), m_sock, stream); GetOwner()->AddHandler (connection); connection->I2PConnect (reinterpret_cast(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 } } diff --git a/I2PControl.cpp b/I2PControl.cpp index 776cfe86..1ea6c8aa 100644 --- a/I2PControl.cpp +++ b/I2PControl.cpp @@ -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 { diff --git a/I2PService.cpp b/I2PService.cpp index 0715a39f..85582c0e 100644 --- a/I2PService.cpp +++ b/I2PService.cpp @@ -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 ()); } } diff --git a/LeaseSet.cpp b/LeaseSet.cpp index ebbdbd97..677f19ca 100644 --- a/LeaseSet.cpp +++ b/LeaseSet.cpp @@ -180,10 +180,10 @@ namespace data } } - const std::vector > LeaseSet::GetNonExpiredLeases (bool withThreshold) const + const std::vector > LeaseSet::GetNonExpiredLeases (bool withThreshold) const { auto ts = i2p::util::GetMillisecondsSinceEpoch (); - std::vector > leases; + std::vector > leases; for (auto it: m_Leases) { auto endDate = it->endDate; diff --git a/LeaseSet.h b/LeaseSet.h index dd94bfaf..aed27683 100644 --- a/LeaseSet.h +++ b/LeaseSet.h @@ -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 > GetNonExpiredLeases (bool withThreshold = true) const; + const std::vector > GetNonExpiredLeases (bool withThreshold = true) const; bool HasExpiredLeases () const; bool IsExpired () const; bool IsEmpty () const { return m_Leases.empty (); }; diff --git a/Makefile b/Makefile index b11305ce..09cf2ace 100644 --- a/Makefile +++ b/Makefile @@ -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 \ diff --git a/NTCPSession.cpp b/NTCPSession.cpp index 81b6bdc2..0ac2e74b 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -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 } diff --git a/RouterContext.cpp b/RouterContext.cpp index 3dc79027..90961948 100644 --- a/RouterContext.cpp +++ b/RouterContext.cpp @@ -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(); diff --git a/RouterInfo.cpp b/RouterInfo.cpp index 64b675a7..56482234 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -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; diff --git a/Streaming.cpp b/Streaming.cpp index 0c1a5e5d..1e9cdd84 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -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{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; diff --git a/Streaming.h b/Streaming.h index 2f85397a..c908c6ec 100644 --- a/Streaming.h +++ b/Streaming.h @@ -172,7 +172,7 @@ namespace stream std::shared_ptr m_RemoteIdentity; std::shared_ptr m_RemoteLeaseSet; std::shared_ptr m_RoutingSession; - std::shared_ptr m_CurrentRemoteLease; + std::shared_ptr m_CurrentRemoteLease; std::shared_ptr m_CurrentOutboundTunnel; std::queue m_ReceiveQueue; std::set m_SavedPackets;