mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-02-24 04:37:37 +01:00
atomics have been used for threads stop
This commit is contained in:
parent
8c09a7429c
commit
dfa1482ab2
15 changed files with 259 additions and 212 deletions
|
@ -15,7 +15,7 @@ namespace util
|
||||||
virtual bool init(int argc, char* argv[]);
|
virtual bool init(int argc, char* argv[]);
|
||||||
virtual bool start();
|
virtual bool start();
|
||||||
virtual bool stop();
|
virtual bool stop();
|
||||||
virtual void run () {};
|
virtual void run () {}
|
||||||
|
|
||||||
bool isDaemon;
|
bool isDaemon;
|
||||||
bool running;
|
bool running;
|
||||||
|
|
|
@ -943,44 +943,50 @@ namespace http {
|
||||||
|
|
||||||
void HTTPServer::Start ()
|
void HTTPServer::Start ()
|
||||||
{
|
{
|
||||||
bool needAuth; i2p::config::GetOption("http.auth", needAuth);
|
if (!m_IsRunning.load())
|
||||||
std::string user; i2p::config::GetOption("http.user", user);
|
{
|
||||||
std::string pass; i2p::config::GetOption("http.pass", pass);
|
bool needAuth; i2p::config::GetOption("http.auth", needAuth);
|
||||||
/* generate pass if needed */
|
std::string user; i2p::config::GetOption("http.user", user);
|
||||||
if (needAuth && pass == "") {
|
std::string pass; i2p::config::GetOption("http.pass", pass);
|
||||||
uint8_t random[16];
|
/* generate pass if needed */
|
||||||
char alnum[] = "0123456789"
|
if (needAuth && pass == "") {
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
uint8_t random[16];
|
||||||
"abcdefghijklmnopqrstuvwxyz";
|
char alnum[] = "0123456789"
|
||||||
pass.resize(sizeof(random));
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
RAND_bytes(random, sizeof(random));
|
"abcdefghijklmnopqrstuvwxyz";
|
||||||
for (size_t i = 0; i < sizeof(random); i++) {
|
pass.resize(sizeof(random));
|
||||||
pass[i] = alnum[random[i] % (sizeof(alnum) - 1)];
|
RAND_bytes(random, sizeof(random));
|
||||||
|
for (size_t i = 0; i < sizeof(random); i++) {
|
||||||
|
pass[i] = alnum[random[i] % (sizeof(alnum) - 1)];
|
||||||
|
}
|
||||||
|
i2p::config::SetOption("http.pass", pass);
|
||||||
|
LogPrint(eLogInfo, "HTTPServer: password set to ", pass);
|
||||||
}
|
}
|
||||||
i2p::config::SetOption("http.pass", pass);
|
m_IsRunning.store(true);
|
||||||
LogPrint(eLogInfo, "HTTPServer: password set to ", pass);
|
m_Thread = std::unique_ptr<std::thread>(new std::thread (std::bind (&HTTPServer::Run, this)));
|
||||||
|
m_Acceptor.listen ();
|
||||||
|
Accept ();
|
||||||
}
|
}
|
||||||
m_IsRunning = true;
|
|
||||||
m_Thread = std::unique_ptr<std::thread>(new std::thread (std::bind (&HTTPServer::Run, this)));
|
|
||||||
m_Acceptor.listen ();
|
|
||||||
Accept ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPServer::Stop ()
|
void HTTPServer::Stop ()
|
||||||
{
|
{
|
||||||
m_IsRunning = false;
|
if (m_IsRunning.load())
|
||||||
m_Acceptor.close();
|
|
||||||
m_Service.stop ();
|
|
||||||
if (m_Thread)
|
|
||||||
{
|
{
|
||||||
m_Thread->join ();
|
m_IsRunning.store(false);
|
||||||
m_Thread = nullptr;
|
m_Acceptor.close();
|
||||||
|
m_Service.stop ();
|
||||||
|
if (m_Thread)
|
||||||
|
{
|
||||||
|
m_Thread->join ();
|
||||||
|
m_Thread = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPServer::Run ()
|
void HTTPServer::Run ()
|
||||||
{
|
{
|
||||||
while (m_IsRunning)
|
while (m_IsRunning.load(std::memory_order_acquire))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <atomic>
|
||||||
#include "HTTP.h"
|
#include "HTTP.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
|
@ -70,7 +71,7 @@ namespace http
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool m_IsRunning;
|
std::atomic_bool m_IsRunning;
|
||||||
std::unique_ptr<std::thread> m_Thread;
|
std::unique_ptr<std::thread> m_Thread;
|
||||||
boost::asio::io_service m_Service;
|
boost::asio::io_service m_Service;
|
||||||
boost::asio::io_service::work m_Work;
|
boost::asio::io_service::work m_Work;
|
||||||
|
|
|
@ -101,19 +101,19 @@ namespace client
|
||||||
|
|
||||||
void I2PControlService::Start ()
|
void I2PControlService::Start ()
|
||||||
{
|
{
|
||||||
if (!m_IsRunning)
|
if (!m_IsRunning.load())
|
||||||
{
|
{
|
||||||
Accept ();
|
Accept ();
|
||||||
m_IsRunning = true;
|
m_IsRunning.store(true);
|
||||||
m_Thread = new std::thread (std::bind (&I2PControlService::Run, this));
|
m_Thread = new std::thread (std::bind (&I2PControlService::Run, this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2PControlService::Stop ()
|
void I2PControlService::Stop ()
|
||||||
{
|
{
|
||||||
if (m_IsRunning)
|
if (m_IsRunning.load())
|
||||||
{
|
{
|
||||||
m_IsRunning = false;
|
m_IsRunning.store(false);
|
||||||
m_Acceptor.cancel ();
|
m_Acceptor.cancel ();
|
||||||
m_Service.stop ();
|
m_Service.stop ();
|
||||||
if (m_Thread)
|
if (m_Thread)
|
||||||
|
@ -127,7 +127,7 @@ namespace client
|
||||||
|
|
||||||
void I2PControlService::Run ()
|
void I2PControlService::Run ()
|
||||||
{
|
{
|
||||||
while (m_IsRunning)
|
while (m_IsRunning.load(std::memory_order_acquire))
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
m_Service.run ();
|
m_Service.run ();
|
||||||
|
@ -160,7 +160,7 @@ namespace client
|
||||||
void I2PControlService::Handshake (std::shared_ptr<ssl_socket> socket)
|
void I2PControlService::Handshake (std::shared_ptr<ssl_socket> socket)
|
||||||
{
|
{
|
||||||
socket->async_handshake(boost::asio::ssl::stream_base::server,
|
socket->async_handshake(boost::asio::ssl::stream_base::server,
|
||||||
std::bind( &I2PControlService::HandleHandshake, this, std::placeholders::_1, socket));
|
std::bind( &I2PControlService::HandleHandshake, this, std::placeholders::_1, socket));
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2PControlService::HandleHandshake (const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> socket)
|
void I2PControlService::HandleHandshake (const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> socket)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <atomic>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/asio/ssl.hpp>
|
#include <boost/asio/ssl.hpp>
|
||||||
#include <boost/property_tree/ptree.hpp>
|
#include <boost/property_tree/ptree.hpp>
|
||||||
|
@ -101,7 +102,7 @@ namespace client
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::string m_Password;
|
std::string m_Password;
|
||||||
bool m_IsRunning;
|
std::atomic_bool m_IsRunning;
|
||||||
std::thread * m_Thread;
|
std::thread * m_Thread;
|
||||||
|
|
||||||
boost::asio::io_service m_Service;
|
boost::asio::io_service m_Service;
|
||||||
|
|
|
@ -28,10 +28,10 @@ namespace transport
|
||||||
|
|
||||||
void UPnP::Stop ()
|
void UPnP::Stop ()
|
||||||
{
|
{
|
||||||
if (m_IsRunning)
|
if (m_IsRunning.load())
|
||||||
{
|
{
|
||||||
LogPrint(eLogInfo, "UPnP: stopping");
|
LogPrint(eLogInfo, "UPnP: stopping");
|
||||||
m_IsRunning = false;
|
m_IsRunning.store(false);
|
||||||
m_Timer.cancel ();
|
m_Timer.cancel ();
|
||||||
m_Service.stop ();
|
m_Service.stop ();
|
||||||
if (m_Thread)
|
if (m_Thread)
|
||||||
|
@ -46,12 +46,15 @@ namespace transport
|
||||||
|
|
||||||
void UPnP::Start()
|
void UPnP::Start()
|
||||||
{
|
{
|
||||||
m_IsRunning = true;
|
if (!m_IsRunning.load())
|
||||||
LogPrint(eLogInfo, "UPnP: starting");
|
{
|
||||||
m_Service.post (std::bind (&UPnP::Discover, this));
|
m_IsRunning.store(true);
|
||||||
std::unique_lock<std::mutex> l(m_StartedMutex);
|
LogPrint(eLogInfo, "UPnP: starting");
|
||||||
m_Thread.reset (new std::thread (std::bind (&UPnP::Run, this)));
|
m_Service.post (std::bind (&UPnP::Discover, this));
|
||||||
m_Started.wait_for (l, std::chrono::seconds (5)); // 5 seconds maximum
|
std::unique_lock<std::mutex> l(m_StartedMutex);
|
||||||
|
m_Thread.reset (new std::thread (std::bind (&UPnP::Run, this)));
|
||||||
|
m_Started.wait_for (l, std::chrono::seconds (5)); // 5 seconds maximum
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UPnP::~UPnP ()
|
UPnP::~UPnP ()
|
||||||
|
@ -61,7 +64,7 @@ namespace transport
|
||||||
|
|
||||||
void UPnP::Run ()
|
void UPnP::Run ()
|
||||||
{
|
{
|
||||||
while (m_IsRunning)
|
while (m_IsRunning.load(std::memory_order_acquire))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#include <miniupnpc/miniwget.h>
|
#include <miniupnpc/miniwget.h>
|
||||||
#include <miniupnpc/miniupnpc.h>
|
#include <miniupnpc/miniupnpc.h>
|
||||||
|
@ -43,8 +44,8 @@ namespace transport
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool m_IsRunning;
|
std::atomic_bool m_IsRunning;
|
||||||
std::unique_ptr<std::thread> m_Thread;
|
std::unique_ptr<std::thread> m_Thread;
|
||||||
std::condition_variable m_Started;
|
std::condition_variable m_Started;
|
||||||
std::mutex m_StartedMutex;
|
std::mutex m_StartedMutex;
|
||||||
boost::asio::io_service m_Service;
|
boost::asio::io_service m_Service;
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
|
|
||||||
namespace i2p {
|
namespace i2p {
|
||||||
namespace log {
|
namespace log {
|
||||||
static Log logger;
|
|
||||||
/**
|
/**
|
||||||
* @brief Maps our loglevel to their symbolic name
|
* @brief Maps our loglevel to their symbolic name
|
||||||
*/
|
*/
|
||||||
|
@ -70,17 +69,21 @@ namespace log {
|
||||||
|
|
||||||
void Log::Start ()
|
void Log::Start ()
|
||||||
{
|
{
|
||||||
if (!m_IsRunning)
|
// separate load and store for atomic is valid here
|
||||||
{
|
// because only one thread changes m_IsRunning
|
||||||
m_IsRunning = true;
|
if (!m_IsRunning.load())
|
||||||
|
{
|
||||||
|
m_IsRunning.store(true);
|
||||||
m_Thread = new std::thread (std::bind (&Log::Run, this));
|
m_Thread = new std::thread (std::bind (&Log::Run, this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::Stop ()
|
void Log::Stop ()
|
||||||
{
|
{
|
||||||
switch (m_Destination)
|
if (m_IsRunning.load())
|
||||||
{
|
{
|
||||||
|
switch (m_Destination)
|
||||||
|
{
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
case eLogSyslog :
|
case eLogSyslog :
|
||||||
closelog();
|
closelog();
|
||||||
|
@ -88,20 +91,22 @@ namespace log {
|
||||||
#endif
|
#endif
|
||||||
case eLogFile:
|
case eLogFile:
|
||||||
case eLogStream:
|
case eLogStream:
|
||||||
if (m_LogStream) m_LogStream->flush();
|
if (m_LogStream) m_LogStream->flush();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_IsRunning.store(false);
|
||||||
|
m_Queue.WakeUp ();
|
||||||
|
if (m_Thread)
|
||||||
|
{
|
||||||
|
m_Thread->join ();
|
||||||
|
delete m_Thread;
|
||||||
|
m_Thread = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m_IsRunning = false;
|
|
||||||
m_Queue.WakeUp ();
|
|
||||||
if (m_Thread)
|
|
||||||
{
|
|
||||||
m_Thread->join ();
|
|
||||||
delete m_Thread;
|
|
||||||
m_Thread = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::SetLogLevel (const std::string& level) {
|
void Log::SetLogLevel (const std::string& level) {
|
||||||
|
@ -162,13 +167,13 @@ namespace log {
|
||||||
void Log::Run ()
|
void Log::Run ()
|
||||||
{
|
{
|
||||||
Reopen ();
|
Reopen ();
|
||||||
while (m_IsRunning)
|
while (m_IsRunning.load(std::memory_order_acquire))
|
||||||
{
|
{
|
||||||
std::shared_ptr<LogMsg> msg;
|
std::shared_ptr<LogMsg> msg;
|
||||||
while (msg = m_Queue.Get ())
|
while (msg = m_Queue.Get ())
|
||||||
Process (msg);
|
Process (msg);
|
||||||
if (m_LogStream) m_LogStream->flush();
|
if (m_LogStream) m_LogStream->flush();
|
||||||
if (m_IsRunning)
|
if (m_IsRunning.load(std::memory_order_acquire))
|
||||||
m_Queue.Wait ();
|
m_Queue.Wait ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,6 +220,7 @@ namespace log {
|
||||||
}
|
}
|
||||||
|
|
||||||
Log & Logger() {
|
Log & Logger() {
|
||||||
|
static Log logger;
|
||||||
return logger;
|
return logger;
|
||||||
}
|
}
|
||||||
} // log
|
} // log
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <atomic>
|
||||||
#include "Queue.h"
|
#include "Queue.h"
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
@ -59,7 +60,7 @@ namespace log {
|
||||||
i2p::util::Queue<std::shared_ptr<LogMsg> > m_Queue;
|
i2p::util::Queue<std::shared_ptr<LogMsg> > m_Queue;
|
||||||
bool m_HasColors;
|
bool m_HasColors;
|
||||||
std::string m_TimeFormat;
|
std::string m_TimeFormat;
|
||||||
volatile bool m_IsRunning;
|
std::atomic_bool m_IsRunning;
|
||||||
std::thread * m_Thread;
|
std::thread * m_Thread;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -84,8 +85,8 @@ namespace log {
|
||||||
Log ();
|
Log ();
|
||||||
~Log ();
|
~Log ();
|
||||||
|
|
||||||
LogType GetLogType () { return m_Destination; };
|
LogType GetLogType () { return m_Destination; }
|
||||||
LogLevel GetLogLevel () { return m_MinLevel; };
|
LogLevel GetLogLevel () { return m_MinLevel; }
|
||||||
|
|
||||||
void Start ();
|
void Start ();
|
||||||
void Stop ();
|
void Stop ();
|
||||||
|
@ -112,7 +113,7 @@ namespace log {
|
||||||
* @brief Sets format for timestamps in log
|
* @brief Sets format for timestamps in log
|
||||||
* @param format String with timestamp format
|
* @param format String with timestamp format
|
||||||
*/
|
*/
|
||||||
void SetTimeFormat (std::string format) { m_TimeFormat = format; };
|
void SetTimeFormat (std::string format) { m_TimeFormat = format; }
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
/**
|
/**
|
||||||
|
@ -145,8 +146,8 @@ namespace log {
|
||||||
std::string text; /**< message text as single string */
|
std::string text; /**< message text as single string */
|
||||||
LogLevel level; /**< message level */
|
LogLevel level; /**< message level */
|
||||||
std::thread::id tid; /**< id of thread that generated message */
|
std::thread::id tid; /**< id of thread that generated message */
|
||||||
|
|
||||||
LogMsg (LogLevel lvl, std::time_t ts, const std::string & txt): timestamp(ts), text(txt), level(lvl) {};
|
LogMsg (LogLevel lvl, std::time_t ts, const std::string & txt): timestamp(ts), text(txt), level(lvl) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
Log & Logger();
|
Log & Logger();
|
||||||
|
@ -184,7 +185,7 @@ void LogPrint (LogLevel level, TArgs&&... args) noexcept
|
||||||
std::stringstream ss("");
|
std::stringstream ss("");
|
||||||
|
|
||||||
LogPrint (ss, std::forward<TArgs>(args)...);
|
LogPrint (ss, std::forward<TArgs>(args)...);
|
||||||
|
|
||||||
auto msg = std::make_shared<i2p::log::LogMsg>(level, std::time(nullptr), ss.str());
|
auto msg = std::make_shared<i2p::log::LogMsg>(level, std::time(nullptr), ss.str());
|
||||||
msg->tid = std::this_thread::get_id();
|
msg->tid = std::this_thread::get_id();
|
||||||
log.Append(msg);
|
log.Append(msg);
|
||||||
|
|
|
@ -22,7 +22,7 @@ using namespace i2p::transport;
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace data
|
namespace data
|
||||||
{
|
{
|
||||||
NetDb netdb;
|
NetDb netdb;
|
||||||
|
|
||||||
NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat"), m_FloodfillBootstrap(nullptr), m_HiddenMode(false)
|
NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat"), m_FloodfillBootstrap(nullptr), m_HiddenMode(false)
|
||||||
|
@ -31,65 +31,70 @@ namespace data
|
||||||
|
|
||||||
NetDb::~NetDb ()
|
NetDb::~NetDb ()
|
||||||
{
|
{
|
||||||
Stop ();
|
Stop ();
|
||||||
delete m_Reseeder;
|
delete m_Reseeder;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetDb::Start ()
|
void NetDb::Start ()
|
||||||
{
|
{
|
||||||
m_Storage.SetPlace(i2p::fs::GetDataDir());
|
// separate load and store for atomic is valid here
|
||||||
m_Storage.Init(i2p::data::GetBase64SubstitutionTable(), 64);
|
// because only one thread changes m_IsRunning
|
||||||
InitProfilesStorage ();
|
if (!m_IsRunning.load())
|
||||||
m_Families.LoadCertificates ();
|
{
|
||||||
Load ();
|
m_Storage.SetPlace(i2p::fs::GetDataDir());
|
||||||
|
m_Storage.Init(i2p::data::GetBase64SubstitutionTable(), 64);
|
||||||
|
InitProfilesStorage ();
|
||||||
|
m_Families.LoadCertificates ();
|
||||||
|
Load ();
|
||||||
|
|
||||||
uint16_t threshold; i2p::config::GetOption("reseed.threshold", threshold);
|
uint16_t threshold; i2p::config::GetOption("reseed.threshold", threshold);
|
||||||
if (m_RouterInfos.size () < threshold) // reseed if # of router less than threshold
|
if (m_RouterInfos.size () < threshold) // reseed if # of router less than threshold
|
||||||
Reseed ();
|
Reseed ();
|
||||||
|
|
||||||
m_IsRunning = true;
|
m_IsRunning.store(true);
|
||||||
m_Thread = new std::thread (std::bind (&NetDb::Run, this));
|
m_Thread = new std::thread (std::bind (&NetDb::Run, this));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetDb::Stop ()
|
void NetDb::Stop ()
|
||||||
{
|
{
|
||||||
if (m_IsRunning)
|
if (m_IsRunning.load())
|
||||||
{
|
{
|
||||||
for (auto& it: m_RouterInfos)
|
for (auto& it: m_RouterInfos)
|
||||||
it.second->SaveProfile ();
|
it.second->SaveProfile ();
|
||||||
DeleteObsoleteProfiles ();
|
DeleteObsoleteProfiles ();
|
||||||
m_RouterInfos.clear ();
|
m_RouterInfos.clear ();
|
||||||
m_Floodfills.clear ();
|
m_Floodfills.clear ();
|
||||||
if (m_Thread)
|
if (m_Thread)
|
||||||
{
|
{
|
||||||
m_IsRunning = false;
|
m_IsRunning.store(false);
|
||||||
m_Queue.WakeUp ();
|
m_Queue.WakeUp ();
|
||||||
m_Thread->join ();
|
m_Thread->join ();
|
||||||
delete m_Thread;
|
delete m_Thread;
|
||||||
m_Thread = 0;
|
m_Thread = nullptr;
|
||||||
}
|
}
|
||||||
m_LeaseSets.clear();
|
m_LeaseSets.clear();
|
||||||
m_Requests.Stop ();
|
m_Requests.Stop ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetDb::Run ()
|
void NetDb::Run ()
|
||||||
{
|
{
|
||||||
uint32_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0;
|
uint64_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0;
|
||||||
while (m_IsRunning)
|
while (m_IsRunning.load(std::memory_order_acquire))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto msg = m_Queue.GetNextWithTimeout (15000); // 15 sec
|
auto msg = m_Queue.GetNextWithTimeout (15000); // 15 sec
|
||||||
if (msg)
|
if (msg)
|
||||||
{
|
{
|
||||||
int numMsgs = 0;
|
int numMsgs = 0;
|
||||||
while (msg)
|
while (msg)
|
||||||
{
|
{
|
||||||
LogPrint(eLogDebug, "NetDb: got request with type ", (int) msg->GetTypeID ());
|
LogPrint(eLogDebug, "NetDb: got request with type ", (int) msg->GetTypeID ());
|
||||||
switch (msg->GetTypeID ())
|
switch (msg->GetTypeID ())
|
||||||
{
|
{
|
||||||
case eI2NPDatabaseStore:
|
case eI2NPDatabaseStore:
|
||||||
HandleDatabaseStoreMsg (msg);
|
HandleDatabaseStoreMsg (msg);
|
||||||
break;
|
break;
|
||||||
case eI2NPDatabaseSearchReply:
|
case eI2NPDatabaseSearchReply:
|
||||||
|
@ -97,7 +102,7 @@ namespace data
|
||||||
break;
|
break;
|
||||||
case eI2NPDatabaseLookup:
|
case eI2NPDatabaseLookup:
|
||||||
HandleDatabaseLookupMsg (msg);
|
HandleDatabaseLookupMsg (msg);
|
||||||
break;
|
break;
|
||||||
default: // WTF?
|
default: // WTF?
|
||||||
LogPrint (eLogError, "NetDb: unexpected message type ", (int) msg->GetTypeID ());
|
LogPrint (eLogError, "NetDb: unexpected message type ", (int) msg->GetTypeID ());
|
||||||
//i2p::HandleI2NPMessage (msg);
|
//i2p::HandleI2NPMessage (msg);
|
||||||
|
@ -105,23 +110,25 @@ namespace data
|
||||||
if (numMsgs > 100) break;
|
if (numMsgs > 100) break;
|
||||||
msg = m_Queue.Get ();
|
msg = m_Queue.Get ();
|
||||||
numMsgs++;
|
numMsgs++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!m_IsRunning) break;
|
|
||||||
|
if (!m_IsRunning.load(std::memory_order_acquire))
|
||||||
|
break;
|
||||||
|
|
||||||
uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
|
uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
if (ts - lastManageRequest >= 15) // manage requests every 15 seconds
|
if (ts - lastManageRequest >= 15) // manage requests every 15 seconds
|
||||||
{
|
{
|
||||||
m_Requests.ManageRequests ();
|
m_Requests.ManageRequests ();
|
||||||
lastManageRequest = ts;
|
lastManageRequest = ts;
|
||||||
}
|
}
|
||||||
if (ts - lastSave >= 60) // save routers, manage leasesets and validate subscriptions every minute
|
if (ts - lastSave >= 60) // save routers, manage leasesets and validate subscriptions every minute
|
||||||
{
|
{
|
||||||
if (lastSave)
|
if (lastSave)
|
||||||
{
|
{
|
||||||
SaveUpdated ();
|
SaveUpdated ();
|
||||||
ManageLeaseSets ();
|
ManageLeaseSets ();
|
||||||
}
|
}
|
||||||
lastSave = ts;
|
lastSave = ts;
|
||||||
}
|
}
|
||||||
if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT)
|
if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT)
|
||||||
|
@ -129,23 +136,23 @@ namespace data
|
||||||
i2p::context.CleanupDestination ();
|
i2p::context.CleanupDestination ();
|
||||||
lastDestinationCleanup = ts;
|
lastDestinationCleanup = ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ts - lastPublish >= NETDB_PUBLISH_INTERVAL && !m_HiddenMode) // publish
|
if (ts - lastPublish >= NETDB_PUBLISH_INTERVAL && !m_HiddenMode) // publish
|
||||||
{
|
{
|
||||||
Publish ();
|
Publish ();
|
||||||
lastPublish = ts;
|
lastPublish = ts;
|
||||||
}
|
}
|
||||||
if (ts - lastExploratory >= 30) // exploratory every 30 seconds
|
if (ts - lastExploratory >= 30) // exploratory every 30 seconds
|
||||||
{
|
{
|
||||||
auto numRouters = m_RouterInfos.size ();
|
auto numRouters = m_RouterInfos.size ();
|
||||||
if (numRouters == 0)
|
if (numRouters == 0)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("No known routers, reseed seems to be totally failed");
|
throw std::runtime_error("No known routers, reseed seems to be totally failed");
|
||||||
}
|
}
|
||||||
else // we have peers now
|
else // we have peers now
|
||||||
m_FloodfillBootstrap = nullptr;
|
m_FloodfillBootstrap = nullptr;
|
||||||
if (numRouters < 2500 || ts - lastExploratory >= 90)
|
if (numRouters < 2500 || ts - lastExploratory >= 90)
|
||||||
{
|
{
|
||||||
numRouters = 800/numRouters;
|
numRouters = 800/numRouters;
|
||||||
if (numRouters < 1) numRouters = 1;
|
if (numRouters < 1) numRouters = 1;
|
||||||
if (numRouters > 9) numRouters = 9;
|
if (numRouters > 9) numRouters = 9;
|
||||||
|
@ -153,15 +160,15 @@ namespace data
|
||||||
if(!m_HiddenMode)
|
if(!m_HiddenMode)
|
||||||
Explore (numRouters);
|
Explore (numRouters);
|
||||||
lastExploratory = ts;
|
lastExploratory = ts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "NetDb: runtime exception: ", ex.what ());
|
LogPrint (eLogError, "NetDb: runtime exception: ", ex.what ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NetDb::AddRouterInfo (const uint8_t * buf, int len)
|
bool NetDb::AddRouterInfo (const uint8_t * buf, int len)
|
||||||
{
|
{
|
||||||
|
@ -171,11 +178,11 @@ namespace data
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetDb::SetHidden(bool hide) {
|
void NetDb::SetHidden(bool hide) {
|
||||||
// TODO: remove reachable addresses from router info
|
// TODO: remove reachable addresses from router info
|
||||||
m_HiddenMode = hide;
|
m_HiddenMode = hide;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len)
|
bool NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len)
|
||||||
{
|
{
|
||||||
bool updated = true;
|
bool updated = true;
|
||||||
|
@ -330,7 +337,7 @@ namespace data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Reseeder->Bootstrap ();
|
m_Reseeder->Bootstrap ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetDb::ReseedFromFloodfill(const RouterInfo & ri, int numRouters, int numFloodfills)
|
void NetDb::ReseedFromFloodfill(const RouterInfo & ri, int numRouters, int numFloodfills)
|
||||||
|
@ -392,7 +399,7 @@ namespace data
|
||||||
void NetDb::VisitStoredRouterInfos(RouterInfoVisitor v)
|
void NetDb::VisitStoredRouterInfos(RouterInfoVisitor v)
|
||||||
{
|
{
|
||||||
m_Storage.Iterate([v] (const std::string & filename) {
|
m_Storage.Iterate([v] (const std::string & filename) {
|
||||||
auto ri = std::make_shared<i2p::data::RouterInfo>(filename);
|
auto ri = std::make_shared<i2p::data::RouterInfo>(filename);
|
||||||
v(ri);
|
v(ri);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
#include "Gzip.h"
|
#include "Gzip.h"
|
||||||
|
@ -25,7 +26,7 @@
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace data
|
namespace data
|
||||||
{
|
{
|
||||||
const int NETDB_MIN_ROUTERS = 90;
|
const int NETDB_MIN_ROUTERS = 90;
|
||||||
const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60*60; // 1 hour, in seconds
|
const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60*60; // 1 hour, in seconds
|
||||||
const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65*60;
|
const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65*60;
|
||||||
|
@ -41,7 +42,7 @@ namespace data
|
||||||
|
|
||||||
/** function for visiting a router info and determining if we want to use it */
|
/** function for visiting a router info and determining if we want to use it */
|
||||||
typedef std::function<bool(std::shared_ptr<const i2p::data::RouterInfo>)> RouterInfoFilter;
|
typedef std::function<bool(std::shared_ptr<const i2p::data::RouterInfo>)> RouterInfoFilter;
|
||||||
|
|
||||||
class NetDb
|
class NetDb
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -51,7 +52,7 @@ namespace data
|
||||||
|
|
||||||
void Start ();
|
void Start ();
|
||||||
void Stop ();
|
void Stop ();
|
||||||
|
|
||||||
bool AddRouterInfo (const uint8_t * buf, int len);
|
bool AddRouterInfo (const uint8_t * buf, int len);
|
||||||
bool AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len);
|
bool AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len);
|
||||||
bool AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, std::shared_ptr<i2p::tunnel::InboundTunnel> from);
|
bool AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, std::shared_ptr<i2p::tunnel::InboundTunnel> from);
|
||||||
|
@ -60,7 +61,7 @@ namespace data
|
||||||
std::shared_ptr<RouterProfile> FindRouterProfile (const IdentHash& ident) const;
|
std::shared_ptr<RouterProfile> FindRouterProfile (const IdentHash& ident) const;
|
||||||
|
|
||||||
void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr);
|
void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr);
|
||||||
void RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete = nullptr);
|
void RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete = nullptr);
|
||||||
|
|
||||||
void HandleDatabaseStoreMsg (std::shared_ptr<const I2NPMessage> msg);
|
void HandleDatabaseStoreMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||||
void HandleDatabaseSearchReplyMsg (std::shared_ptr<const I2NPMessage> msg);
|
void HandleDatabaseSearchReplyMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||||
|
@ -75,21 +76,21 @@ namespace data
|
||||||
std::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num,
|
std::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num,
|
||||||
std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
|
std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
|
||||||
std::shared_ptr<const RouterInfo> GetClosestNonFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
|
std::shared_ptr<const RouterInfo> GetClosestNonFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
|
||||||
std::shared_ptr<const RouterInfo> GetRandomRouterInFamily(const std::string & fam) const;
|
std::shared_ptr<const RouterInfo> GetRandomRouterInFamily(const std::string & fam) const;
|
||||||
void SetUnreachable (const IdentHash& ident, bool unreachable);
|
void SetUnreachable (const IdentHash& ident, bool unreachable);
|
||||||
|
|
||||||
void PostI2NPMsg (std::shared_ptr<const I2NPMessage> msg);
|
void PostI2NPMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||||
|
|
||||||
/** set hidden mode, aka don't publish our RI to netdb and don't explore */
|
/** set hidden mode, aka don't publish our RI to netdb and don't explore */
|
||||||
void SetHidden(bool hide);
|
void SetHidden(bool hide);
|
||||||
|
|
||||||
void Reseed ();
|
void Reseed ();
|
||||||
Families& GetFamilies () { return m_Families; };
|
Families& GetFamilies () { return m_Families; }
|
||||||
|
|
||||||
// for web interface
|
// for web interface
|
||||||
int GetNumRouters () const { return m_RouterInfos.size (); };
|
int GetNumRouters () const { return m_RouterInfos.size (); }
|
||||||
int GetNumFloodfills () const { return m_Floodfills.size (); };
|
int GetNumFloodfills () const { return m_Floodfills.size (); }
|
||||||
int GetNumLeaseSets () const { return m_LeaseSets.size (); };
|
int GetNumLeaseSets () const { return m_LeaseSets.size (); }
|
||||||
|
|
||||||
/** visit all lease sets we currently store */
|
/** visit all lease sets we currently store */
|
||||||
void VisitLeaseSets(LeaseSetVisitor v);
|
void VisitLeaseSets(LeaseSetVisitor v);
|
||||||
|
@ -100,7 +101,7 @@ namespace data
|
||||||
/** visit N random router that match using filter, then visit them with a visitor, return number of RouterInfos that were visited */
|
/** visit N random router that match using filter, then visit them with a visitor, return number of RouterInfos that were visited */
|
||||||
size_t VisitRandomRouterInfos(RouterInfoFilter f, RouterInfoVisitor v, size_t n);
|
size_t VisitRandomRouterInfos(RouterInfoFilter f, RouterInfoVisitor v, size_t n);
|
||||||
|
|
||||||
void ClearRouterInfos () { m_RouterInfos.clear (); };
|
void ClearRouterInfos () { m_RouterInfos.clear (); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -115,8 +116,8 @@ namespace data
|
||||||
|
|
||||||
void ReseedFromFloodfill(const RouterInfo & ri, int numRouters=40, int numFloodfills=20);
|
void ReseedFromFloodfill(const RouterInfo & ri, int numRouters=40, int numFloodfills=20);
|
||||||
|
|
||||||
template<typename Filter>
|
template<typename Filter>
|
||||||
std::shared_ptr<const RouterInfo> GetRandomRouter (Filter filter) const;
|
std::shared_ptr<const RouterInfo> GetRandomRouter (Filter filter) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -127,9 +128,9 @@ namespace data
|
||||||
mutable std::mutex m_FloodfillsMutex;
|
mutable std::mutex m_FloodfillsMutex;
|
||||||
std::list<std::shared_ptr<RouterInfo> > m_Floodfills;
|
std::list<std::shared_ptr<RouterInfo> > m_Floodfills;
|
||||||
|
|
||||||
bool m_IsRunning;
|
std::atomic_bool m_IsRunning;
|
||||||
uint64_t m_LastLoad;
|
uint64_t m_LastLoad;
|
||||||
std::thread * m_Thread;
|
std::thread * m_Thread;
|
||||||
i2p::util::Queue<std::shared_ptr<const I2NPMessage> > m_Queue; // of I2NPDatabaseStoreMsg
|
i2p::util::Queue<std::shared_ptr<const I2NPMessage> > m_Queue; // of I2NPDatabaseStoreMsg
|
||||||
|
|
||||||
GzipInflator m_Inflator;
|
GzipInflator m_Inflator;
|
||||||
|
@ -142,10 +143,10 @@ namespace data
|
||||||
|
|
||||||
/** router info we are bootstrapping from or nullptr if we are not currently doing that*/
|
/** router info we are bootstrapping from or nullptr if we are not currently doing that*/
|
||||||
std::shared_ptr<RouterInfo> m_FloodfillBootstrap;
|
std::shared_ptr<RouterInfo> m_FloodfillBootstrap;
|
||||||
|
|
||||||
|
|
||||||
/** true if in hidden mode */
|
|
||||||
bool m_HiddenMode;
|
/** true if in hidden mode */
|
||||||
|
bool m_HiddenMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern NetDb netdb;
|
extern NetDb netdb;
|
||||||
|
|
|
@ -445,19 +445,25 @@ namespace tunnel
|
||||||
|
|
||||||
void Tunnels::Start ()
|
void Tunnels::Start ()
|
||||||
{
|
{
|
||||||
m_IsRunning = true;
|
if (!m_IsRunning.load())
|
||||||
m_Thread = new std::thread (std::bind (&Tunnels::Run, this));
|
{
|
||||||
|
m_IsRunning.store(true);
|
||||||
|
m_Thread = new std::thread (std::bind (&Tunnels::Run, this));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tunnels::Stop ()
|
void Tunnels::Stop ()
|
||||||
{
|
{
|
||||||
m_IsRunning = false;
|
if (m_IsRunning.load())
|
||||||
m_Queue.WakeUp ();
|
|
||||||
if (m_Thread)
|
|
||||||
{
|
{
|
||||||
m_Thread->join ();
|
m_IsRunning.store(false);
|
||||||
delete m_Thread;
|
m_Queue.WakeUp ();
|
||||||
m_Thread = 0;
|
if (m_Thread)
|
||||||
|
{
|
||||||
|
m_Thread->join ();
|
||||||
|
delete m_Thread;
|
||||||
|
m_Thread = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,7 +472,7 @@ namespace tunnel
|
||||||
std::this_thread::sleep_for (std::chrono::seconds(1)); // wait for other parts are ready
|
std::this_thread::sleep_for (std::chrono::seconds(1)); // wait for other parts are ready
|
||||||
|
|
||||||
uint64_t lastTs = 0;
|
uint64_t lastTs = 0;
|
||||||
while (m_IsRunning)
|
while (m_IsRunning.load(std::memory_order_acquire))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <atomic>
|
||||||
#include "Queue.h"
|
#include "Queue.h"
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
#include "TunnelConfig.h"
|
#include "TunnelConfig.h"
|
||||||
|
@ -61,7 +62,7 @@ namespace tunnel
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const int TUNNEL_EXPIRATION_TIMEOUT = 660; // 11 minutes
|
const int TUNNEL_EXPIRATION_TIMEOUT = 660; // 11 minutes
|
||||||
const int TUNNEL_EXPIRATION_THRESHOLD = 60; // 1 minute
|
const int TUNNEL_EXPIRATION_THRESHOLD = 60; // 1 minute
|
||||||
const int TUNNEL_RECREATION_THRESHOLD = 90; // 1.5 minutes
|
const int TUNNEL_RECREATION_THRESHOLD = 90; // 1.5 minutes
|
||||||
|
@ -99,20 +100,20 @@ namespace tunnel
|
||||||
std::shared_ptr<const TunnelConfig> GetTunnelConfig () const { return m_Config; }
|
std::shared_ptr<const TunnelConfig> GetTunnelConfig () const { return m_Config; }
|
||||||
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > GetPeers () const;
|
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > GetPeers () const;
|
||||||
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > GetInvertedPeers () const;
|
std::vector<std::shared_ptr<const i2p::data::IdentityEx> > GetInvertedPeers () const;
|
||||||
TunnelState GetState () const { return m_State; };
|
TunnelState GetState () const { return m_State; }
|
||||||
void SetState (TunnelState state);
|
void SetState (TunnelState state);
|
||||||
bool IsEstablished () const { return m_State == eTunnelStateEstablished; };
|
bool IsEstablished () const { return m_State == eTunnelStateEstablished; }
|
||||||
bool IsFailed () const { return m_State == eTunnelStateFailed; };
|
bool IsFailed () const { return m_State == eTunnelStateFailed; }
|
||||||
bool IsRecreated () const { return m_IsRecreated; };
|
bool IsRecreated () const { return m_IsRecreated; }
|
||||||
void SetIsRecreated () { m_IsRecreated = true; };
|
void SetIsRecreated () { m_IsRecreated = true; }
|
||||||
virtual bool IsInbound() const = 0;
|
virtual bool IsInbound() const = 0;
|
||||||
|
|
||||||
std::shared_ptr<TunnelPool> GetTunnelPool () const { return m_Pool; };
|
std::shared_ptr<TunnelPool> GetTunnelPool () const { return m_Pool; }
|
||||||
void SetTunnelPool (std::shared_ptr<TunnelPool> pool) { m_Pool = pool; };
|
void SetTunnelPool (std::shared_ptr<TunnelPool> pool) { m_Pool = pool; }
|
||||||
|
|
||||||
bool HandleTunnelBuildResponse (uint8_t * msg, size_t len);
|
bool HandleTunnelBuildResponse (uint8_t * msg, size_t len);
|
||||||
|
|
||||||
virtual void Print (std::stringstream&) const {};
|
virtual void Print (std::stringstream&) const {}
|
||||||
|
|
||||||
// implements TunnelBase
|
// implements TunnelBase
|
||||||
void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg);
|
void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg);
|
||||||
|
@ -145,12 +146,12 @@ namespace tunnel
|
||||||
public:
|
public:
|
||||||
|
|
||||||
OutboundTunnel (std::shared_ptr<const TunnelConfig> config):
|
OutboundTunnel (std::shared_ptr<const TunnelConfig> config):
|
||||||
Tunnel (config), m_Gateway (this), m_EndpointIdentHash (config->GetLastIdentHash ()) {};
|
Tunnel (config), m_Gateway (this), m_EndpointIdentHash (config->GetLastIdentHash ()) {}
|
||||||
|
|
||||||
void SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr<i2p::I2NPMessage> msg);
|
void SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr<i2p::I2NPMessage> msg);
|
||||||
virtual void SendTunnelDataMsg (const std::vector<TunnelMessageBlock>& msgs); // multiple messages
|
virtual void SendTunnelDataMsg (const std::vector<TunnelMessageBlock>& msgs); // multiple messages
|
||||||
const i2p::data::IdentHash& GetEndpointIdentHash () const { return m_EndpointIdentHash; };
|
const i2p::data::IdentHash& GetEndpointIdentHash () const { return m_EndpointIdentHash; }
|
||||||
virtual size_t GetNumSentBytes () const { return m_Gateway.GetNumSentBytes (); };
|
virtual size_t GetNumSentBytes () const { return m_Gateway.GetNumSentBytes (); }
|
||||||
void Print (std::stringstream& s) const;
|
void Print (std::stringstream& s) const;
|
||||||
|
|
||||||
// implements TunnelBase
|
// implements TunnelBase
|
||||||
|
@ -169,14 +170,14 @@ namespace tunnel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
InboundTunnel (std::shared_ptr<const TunnelConfig> config): Tunnel (config), m_Endpoint (true) {};
|
InboundTunnel (std::shared_ptr<const TunnelConfig> config): Tunnel (config), m_Endpoint (true) {}
|
||||||
void HandleTunnelDataMsg (std::shared_ptr<const I2NPMessage> msg);
|
void HandleTunnelDataMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||||
virtual size_t GetNumReceivedBytes () const { return m_Endpoint.GetNumReceivedBytes (); };
|
virtual size_t GetNumReceivedBytes () const { return m_Endpoint.GetNumReceivedBytes (); }
|
||||||
void Print (std::stringstream& s) const;
|
void Print (std::stringstream& s) const;
|
||||||
bool IsInbound() const { return true; }
|
bool IsInbound() const { return true; }
|
||||||
|
|
||||||
// override TunnelBase
|
// override TunnelBase
|
||||||
void Cleanup () { m_Endpoint.Cleanup (); };
|
void Cleanup () { m_Endpoint.Cleanup (); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -190,7 +191,7 @@ namespace tunnel
|
||||||
ZeroHopsInboundTunnel ();
|
ZeroHopsInboundTunnel ();
|
||||||
void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg);
|
void SendTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage> msg);
|
||||||
void Print (std::stringstream& s) const;
|
void Print (std::stringstream& s) const;
|
||||||
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
|
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -204,7 +205,7 @@ namespace tunnel
|
||||||
ZeroHopsOutboundTunnel ();
|
ZeroHopsOutboundTunnel ();
|
||||||
void SendTunnelDataMsg (const std::vector<TunnelMessageBlock>& msgs);
|
void SendTunnelDataMsg (const std::vector<TunnelMessageBlock>& msgs);
|
||||||
void Print (std::stringstream& s) const;
|
void Print (std::stringstream& s) const;
|
||||||
size_t GetNumSentBytes () const { return m_NumSentBytes; };
|
size_t GetNumSentBytes () const { return m_NumSentBytes; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -224,7 +225,7 @@ namespace tunnel
|
||||||
std::shared_ptr<OutboundTunnel> GetPendingOutboundTunnel (uint32_t replyMsgID);
|
std::shared_ptr<OutboundTunnel> GetPendingOutboundTunnel (uint32_t replyMsgID);
|
||||||
std::shared_ptr<InboundTunnel> GetNextInboundTunnel ();
|
std::shared_ptr<InboundTunnel> GetNextInboundTunnel ();
|
||||||
std::shared_ptr<OutboundTunnel> GetNextOutboundTunnel ();
|
std::shared_ptr<OutboundTunnel> GetNextOutboundTunnel ();
|
||||||
std::shared_ptr<TunnelPool> GetExploratoryPool () const { return m_ExploratoryPool; };
|
std::shared_ptr<TunnelPool> GetExploratoryPool () const { return m_ExploratoryPool; }
|
||||||
std::shared_ptr<TunnelBase> GetTunnel (uint32_t tunnelID);
|
std::shared_ptr<TunnelBase> GetTunnel (uint32_t tunnelID);
|
||||||
int GetTransitTunnelsExpirationTimeout ();
|
int GetTransitTunnelsExpirationTimeout ();
|
||||||
void AddTransitTunnel (std::shared_ptr<TransitTunnel> tunnel);
|
void AddTransitTunnel (std::shared_ptr<TransitTunnel> tunnel);
|
||||||
|
@ -266,7 +267,7 @@ namespace tunnel
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool m_IsRunning;
|
std::atomic_bool m_IsRunning;
|
||||||
std::thread * m_Thread;
|
std::thread * m_Thread;
|
||||||
std::map<uint32_t, std::shared_ptr<InboundTunnel> > m_PendingInboundTunnels; // by replyMsgID
|
std::map<uint32_t, std::shared_ptr<InboundTunnel> > m_PendingInboundTunnels; // by replyMsgID
|
||||||
std::map<uint32_t, std::shared_ptr<OutboundTunnel> > m_PendingOutboundTunnels; // by replyMsgID
|
std::map<uint32_t, std::shared_ptr<OutboundTunnel> > m_PendingOutboundTunnels; // by replyMsgID
|
||||||
|
@ -285,24 +286,24 @@ namespace tunnel
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// for HTTP only
|
// for HTTP only
|
||||||
const decltype(m_OutboundTunnels)& GetOutboundTunnels () const { return m_OutboundTunnels; };
|
const decltype(m_OutboundTunnels)& GetOutboundTunnels () const { return m_OutboundTunnels; }
|
||||||
const decltype(m_InboundTunnels)& GetInboundTunnels () const { return m_InboundTunnels; };
|
const decltype(m_InboundTunnels)& GetInboundTunnels () const { return m_InboundTunnels; }
|
||||||
const decltype(m_TransitTunnels)& GetTransitTunnels () const { return m_TransitTunnels; };
|
const decltype(m_TransitTunnels)& GetTransitTunnels () const { return m_TransitTunnels; }
|
||||||
|
|
||||||
size_t CountTransitTunnels() const;
|
size_t CountTransitTunnels() const;
|
||||||
size_t CountInboundTunnels() const;
|
size_t CountInboundTunnels() const;
|
||||||
size_t CountOutboundTunnels() const;
|
size_t CountOutboundTunnels() const;
|
||||||
|
|
||||||
int GetQueueSize () { return m_Queue.GetSize (); };
|
int GetQueueSize () { return m_Queue.GetSize (); }
|
||||||
int GetTunnelCreationSuccessRate () const // in percents
|
int GetTunnelCreationSuccessRate () const // in percents
|
||||||
{
|
{
|
||||||
int totalNum = m_NumSuccesiveTunnelCreations + m_NumFailedTunnelCreations;
|
int totalNum = m_NumSuccesiveTunnelCreations + m_NumFailedTunnelCreations;
|
||||||
return totalNum ? m_NumSuccesiveTunnelCreations*100/totalNum : 0;
|
return totalNum ? m_NumSuccesiveTunnelCreations*100/totalNum : 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Tunnels tunnels;
|
extern Tunnels tunnels;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "Destination.h"
|
#include "Destination.h"
|
||||||
#include "Streaming.h"
|
#include "Streaming.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#include <websocketpp/config/asio_no_tls.hpp>
|
#include <websocketpp/config/asio_no_tls.hpp>
|
||||||
#include <websocketpp/server.hpp>
|
#include <websocketpp/server.hpp>
|
||||||
|
@ -100,35 +101,41 @@ namespace client
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
if(m_Run) return; // already started
|
if (!m_Run.load())
|
||||||
m_Server.listen(boost::asio::ip::address::from_string(m_Addr), m_Port);
|
{
|
||||||
m_Server.start_accept();
|
m_Run.store(true);
|
||||||
m_Run = true;
|
m_Server.listen(boost::asio::ip::address::from_string(m_Addr), m_Port);
|
||||||
m_Thread = new std::thread([&] (){
|
m_Server.start_accept();
|
||||||
while(m_Run) {
|
m_Run = true;
|
||||||
|
m_Thread = new std::thread([&] (){
|
||||||
|
while (m_Run.load(std::memory_order_acquire)) {
|
||||||
try {
|
try {
|
||||||
m_Server.run();
|
m_Server.run();
|
||||||
} catch( std::exception & ex) {
|
} catch( std::exception & ex) {
|
||||||
LogPrint(eLogError, "Websocks runtime exception: ", ex.what());
|
LogPrint(eLogError, "Websocks runtime exception: ", ex.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
m_Dest->Start();
|
m_Dest->Start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stop()
|
void Stop()
|
||||||
{
|
{
|
||||||
for(const auto & conn : m_Conns)
|
if (m_Run.load())
|
||||||
conn->Close();
|
{
|
||||||
|
for(const auto & conn : m_Conns)
|
||||||
|
conn->Close();
|
||||||
|
|
||||||
m_Dest->Stop();
|
m_Dest->Stop();
|
||||||
m_Run = false;
|
m_Run.store(false);
|
||||||
m_Server.stop();
|
m_Server.stop();
|
||||||
if(m_Thread) {
|
if(m_Thread) {
|
||||||
m_Thread->join();
|
m_Thread->join();
|
||||||
delete m_Thread;
|
delete m_Thread;
|
||||||
|
}
|
||||||
|
m_Thread = nullptr;
|
||||||
}
|
}
|
||||||
m_Thread = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::asio::ip::tcp::endpoint GetLocalEndpoint()
|
boost::asio::ip::tcp::endpoint GetLocalEndpoint()
|
||||||
|
@ -140,7 +147,7 @@ namespace client
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<WebSocksConn_ptr> m_Conns;
|
std::vector<WebSocksConn_ptr> m_Conns;
|
||||||
bool m_Run;
|
std::atomic_bool m_Run;
|
||||||
ServerImpl m_Server;
|
ServerImpl m_Server;
|
||||||
std::string m_Addr;
|
std::string m_Addr;
|
||||||
int m_Port;
|
int m_Port;
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace i2p
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WebsocketServerImpl(const std::string & addr, int port) :
|
WebsocketServerImpl(const std::string & addr, int port) :
|
||||||
m_run(false),
|
m_IsRunning(false),
|
||||||
m_ws_thread(nullptr),
|
m_ws_thread(nullptr),
|
||||||
m_ev_thread(nullptr),
|
m_ev_thread(nullptr),
|
||||||
m_WebsocketTicker(m_Service)
|
m_WebsocketTicker(m_Service)
|
||||||
|
@ -48,10 +48,12 @@ namespace i2p
|
||||||
}
|
}
|
||||||
|
|
||||||
void Start() {
|
void Start() {
|
||||||
m_run = true;
|
if (!m_IsRunning.load())
|
||||||
m_server.start_accept();
|
{
|
||||||
m_ws_thread = new std::thread([&] () {
|
m_IsRunning.store(true);
|
||||||
while(m_run) {
|
m_server.start_accept();
|
||||||
|
m_ws_thread = new std::thread([&] () {
|
||||||
|
while(m_IsRunning.load(std::memory_order_acquire)) {
|
||||||
try {
|
try {
|
||||||
m_server.run();
|
m_server.run();
|
||||||
} catch (std::exception & e ) {
|
} catch (std::exception & e ) {
|
||||||
|
@ -59,8 +61,8 @@ namespace i2p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
m_ev_thread = new std::thread([&] () {
|
m_ev_thread = new std::thread([&] () {
|
||||||
while(m_run) {
|
while(m_IsRunning.load(std::memory_order_acquire)) {
|
||||||
try {
|
try {
|
||||||
m_Service.run();
|
m_Service.run();
|
||||||
break;
|
break;
|
||||||
|
@ -69,25 +71,29 @@ namespace i2p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ScheduleTick();
|
ScheduleTick();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stop() {
|
void Stop() {
|
||||||
m_run = false;
|
if (m_IsRunning.load())
|
||||||
m_Service.stop();
|
{
|
||||||
m_server.stop();
|
m_IsRunning.store(false);
|
||||||
|
m_Service.stop();
|
||||||
|
m_server.stop();
|
||||||
|
|
||||||
if(m_ev_thread) {
|
if(m_ev_thread) {
|
||||||
m_ev_thread->join();
|
m_ev_thread->join();
|
||||||
delete m_ev_thread;
|
delete m_ev_thread;
|
||||||
}
|
}
|
||||||
m_ev_thread = nullptr;
|
m_ev_thread = nullptr;
|
||||||
|
|
||||||
if(m_ws_thread) {
|
if(m_ws_thread) {
|
||||||
m_ws_thread->join();
|
m_ws_thread->join();
|
||||||
delete m_ws_thread;
|
delete m_ws_thread;
|
||||||
|
}
|
||||||
|
m_ws_thread = nullptr;
|
||||||
}
|
}
|
||||||
m_ws_thread = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnOpened(ServerConn c)
|
void ConnOpened(ServerConn c)
|
||||||
|
@ -158,7 +164,7 @@ namespace i2p
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::set<ServerConn, std::owner_less<ServerConn> > ConnList;
|
typedef std::set<ServerConn, std::owner_less<ServerConn> > ConnList;
|
||||||
bool m_run;
|
std::atomic_bool m_IsRunning;
|
||||||
std::thread * m_ws_thread;
|
std::thread * m_ws_thread;
|
||||||
std::thread * m_ev_thread;
|
std::thread * m_ev_thread;
|
||||||
std::mutex m_connsMutex;
|
std::mutex m_connsMutex;
|
||||||
|
|
Loading…
Add table
Reference in a new issue