mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2024-11-16 00:12:43 +00:00
persist incoming tags
This commit is contained in:
parent
abf0f5ac87
commit
c2f62ba52a
@ -110,6 +110,7 @@ namespace client
|
|||||||
{
|
{
|
||||||
if (!m_IsRunning)
|
if (!m_IsRunning)
|
||||||
{
|
{
|
||||||
|
LoadTags ();
|
||||||
m_IsRunning = true;
|
m_IsRunning = true;
|
||||||
m_Pool->SetLocalDestination (shared_from_this ());
|
m_Pool->SetLocalDestination (shared_from_this ());
|
||||||
m_Pool->SetActive (true);
|
m_Pool->SetActive (true);
|
||||||
@ -145,6 +146,7 @@ namespace client
|
|||||||
delete m_Thread;
|
delete m_Thread;
|
||||||
m_Thread = 0;
|
m_Thread = 0;
|
||||||
}
|
}
|
||||||
|
SaveTags ();
|
||||||
CleanUp (); // GarlicDestination
|
CleanUp (); // GarlicDestination
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
14
FS.cpp
14
FS.cpp
@ -16,6 +16,7 @@
|
|||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
#include "FS.h"
|
#include "FS.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "Garlic.h"
|
||||||
|
|
||||||
namespace i2p {
|
namespace i2p {
|
||||||
namespace fs {
|
namespace fs {
|
||||||
@ -93,6 +94,11 @@ namespace fs {
|
|||||||
std::string destinations = DataDirPath("destinations");
|
std::string destinations = DataDirPath("destinations");
|
||||||
if (!boost::filesystem::exists(destinations))
|
if (!boost::filesystem::exists(destinations))
|
||||||
boost::filesystem::create_directory(destinations);
|
boost::filesystem::create_directory(destinations);
|
||||||
|
std::string tags = DataDirPath("tags");
|
||||||
|
if (!boost::filesystem::exists(tags))
|
||||||
|
boost::filesystem::create_directory(tags);
|
||||||
|
else
|
||||||
|
i2p::garlic::CleanUpTagsFiles ();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -116,6 +122,14 @@ namespace fs {
|
|||||||
return boost::filesystem::exists(path);
|
return boost::filesystem::exists(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t GetLastUpdateTime (const std::string & path)
|
||||||
|
{
|
||||||
|
if (!boost::filesystem::exists(path)) return 0;
|
||||||
|
boost::system::error_code ec;
|
||||||
|
auto t = boost::filesystem::last_write_time (path, ec);
|
||||||
|
return ec ? 0 : t;
|
||||||
|
}
|
||||||
|
|
||||||
bool Remove(const std::string & path) {
|
bool Remove(const std::string & path) {
|
||||||
if (!boost::filesystem::exists(path))
|
if (!boost::filesystem::exists(path))
|
||||||
return false;
|
return false;
|
||||||
|
2
FS.h
2
FS.h
@ -113,6 +113,8 @@ namespace fs {
|
|||||||
*/
|
*/
|
||||||
bool Exists(const std::string & path);
|
bool Exists(const std::string & path);
|
||||||
|
|
||||||
|
uint32_t GetLastUpdateTime (const std::string & path); // seconds since epoch
|
||||||
|
|
||||||
bool CreateDirectory (const std::string& path);
|
bool CreateDirectory (const std::string& path);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
80
Garlic.cpp
80
Garlic.cpp
@ -10,6 +10,7 @@
|
|||||||
#include "Transports.h"
|
#include "Transports.h"
|
||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "FS.h"
|
||||||
#include "Garlic.h"
|
#include "Garlic.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
@ -412,9 +413,7 @@ namespace garlic
|
|||||||
if (key)
|
if (key)
|
||||||
{
|
{
|
||||||
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
auto decryption = std::make_shared<i2p::crypto::CBCDecryption>();
|
m_Tags[SessionTag(tag, ts)] = std::make_shared<AESDecryption>(key);
|
||||||
decryption->SetKey (key);
|
|
||||||
m_Tags[SessionTag(tag, ts)] = decryption;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,8 +455,7 @@ namespace garlic
|
|||||||
ElGamalBlock elGamal;
|
ElGamalBlock elGamal;
|
||||||
if (length >= 514 && i2p::crypto::ElGamalDecrypt (GetEncryptionPrivateKey (), buf, (uint8_t *)&elGamal, m_Ctx, true))
|
if (length >= 514 && i2p::crypto::ElGamalDecrypt (GetEncryptionPrivateKey (), buf, (uint8_t *)&elGamal, m_Ctx, true))
|
||||||
{
|
{
|
||||||
auto decryption = std::make_shared<i2p::crypto::CBCDecryption>();
|
auto decryption = std::make_shared<AESDecryption>(elGamal.sessionKey);
|
||||||
decryption->SetKey (elGamal.sessionKey);
|
|
||||||
uint8_t iv[32]; // IV is first 16 bytes
|
uint8_t iv[32]; // IV is first 16 bytes
|
||||||
SHA256(elGamal.preIV, 32, iv);
|
SHA256(elGamal.preIV, 32, iv);
|
||||||
decryption->SetIV (iv);
|
decryption->SetIV (iv);
|
||||||
@ -469,7 +467,7 @@ namespace garlic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<i2p::crypto::CBCDecryption> decryption,
|
void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<AESDecryption> decryption,
|
||||||
std::shared_ptr<i2p::tunnel::InboundTunnel> from)
|
std::shared_ptr<i2p::tunnel::InboundTunnel> from)
|
||||||
{
|
{
|
||||||
uint16_t tagCount = bufbe16toh (buf);
|
uint16_t tagCount = bufbe16toh (buf);
|
||||||
@ -714,5 +712,75 @@ namespace garlic
|
|||||||
HandleDeliveryStatusMessage (msg);
|
HandleDeliveryStatusMessage (msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GarlicDestination::SaveTags ()
|
||||||
|
{
|
||||||
|
if (m_Tags.empty ()) return;
|
||||||
|
std::string ident = GetIdentHash().ToBase32();
|
||||||
|
std::string path = i2p::fs::DataDirPath("tags", (ident + ".tags"));
|
||||||
|
std::ofstream f (path, std::ofstream::binary | std::ofstream::out | std::ofstream::trunc);
|
||||||
|
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
|
// 4 bytes timestamp, 32 bytes tag, 32 bytes key
|
||||||
|
for (auto it: m_Tags)
|
||||||
|
{
|
||||||
|
if (ts < it.first.creationTime + INCOMING_TAGS_EXPIRATION_TIMEOUT)
|
||||||
|
{
|
||||||
|
f.write ((char *)&it.first.creationTime, 4);
|
||||||
|
f.write ((char *)it.first.data (), 32);
|
||||||
|
f.write ((char *)it.second->GetKey ().data (), 32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GarlicDestination::LoadTags ()
|
||||||
|
{
|
||||||
|
std::string ident = GetIdentHash().ToBase32();
|
||||||
|
std::string path = i2p::fs::DataDirPath("tags", (ident + ".tags"));
|
||||||
|
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
|
if (ts < i2p::fs::GetLastUpdateTime (path) + INCOMING_TAGS_EXPIRATION_TIMEOUT)
|
||||||
|
{
|
||||||
|
// might contain non-expired tags
|
||||||
|
std::ifstream f (path, std::ifstream::binary);
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
std::map<i2p::crypto::AESKey, std::shared_ptr<AESDecryption> > keys;
|
||||||
|
// 4 bytes timestamp, 32 bytes tag, 32 bytes key
|
||||||
|
while (!f.eof ())
|
||||||
|
{
|
||||||
|
uint32_t t;
|
||||||
|
uint8_t tag[32], key[32];
|
||||||
|
f.read ((char *)&t, 4); if (f.eof ()) break;
|
||||||
|
if (ts < t + INCOMING_TAGS_EXPIRATION_TIMEOUT)
|
||||||
|
{
|
||||||
|
f.read ((char *)tag, 32);
|
||||||
|
f.read ((char *)key, 32);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
f.seekg (64, std::ios::cur); // skip
|
||||||
|
if (f.eof ()) break;
|
||||||
|
|
||||||
|
std::shared_ptr<AESDecryption> decryption;
|
||||||
|
auto it = keys.find (key);
|
||||||
|
if (it != keys.end ())
|
||||||
|
decryption = it->second;
|
||||||
|
else
|
||||||
|
decryption = std::make_shared<AESDecryption>(key);
|
||||||
|
m_Tags.insert (std::make_pair (SessionTag (tag, ts), decryption));
|
||||||
|
}
|
||||||
|
if (!m_Tags.empty ())
|
||||||
|
LogPrint (eLogInfo, m_Tags.size (), " loaded for ", ident);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i2p::fs::Remove (path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CleanUpTagsFiles ()
|
||||||
|
{
|
||||||
|
std::vector<std::string> files;
|
||||||
|
i2p::fs::ReadDir (i2p::fs::DataDirPath("tags"), files);
|
||||||
|
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
|
for (auto it: files)
|
||||||
|
if (ts >= i2p::fs::GetLastUpdateTime (it) + INCOMING_TAGS_EXPIRATION_TIMEOUT)
|
||||||
|
i2p::fs::Remove (it);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
26
Garlic.h
26
Garlic.h
@ -59,6 +59,22 @@ namespace garlic
|
|||||||
uint32_t creationTime; // seconds since epoch
|
uint32_t creationTime; // seconds since epoch
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// AESDecryption is associated with session tags and store key
|
||||||
|
class AESDecryption: public i2p::crypto::CBCDecryption
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
AESDecryption (const uint8_t * key): m_Key (key)
|
||||||
|
{
|
||||||
|
SetKey (key);
|
||||||
|
}
|
||||||
|
const i2p::crypto::AESKey& GetKey () const { return m_Key; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
i2p::crypto::AESKey m_Key;
|
||||||
|
};
|
||||||
|
|
||||||
struct GarlicRoutingPath
|
struct GarlicRoutingPath
|
||||||
{
|
{
|
||||||
std::shared_ptr<i2p::tunnel::OutboundTunnel> outboundTunnel;
|
std::shared_ptr<i2p::tunnel::OutboundTunnel> outboundTunnel;
|
||||||
@ -181,9 +197,12 @@ namespace garlic
|
|||||||
void HandleGarlicMessage (std::shared_ptr<I2NPMessage> msg);
|
void HandleGarlicMessage (std::shared_ptr<I2NPMessage> msg);
|
||||||
void HandleDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
void HandleDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
||||||
|
|
||||||
|
void SaveTags ();
|
||||||
|
void LoadTags ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<i2p::crypto::CBCDecryption> decryption,
|
void HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<AESDecryption> decryption,
|
||||||
std::shared_ptr<i2p::tunnel::InboundTunnel> from);
|
std::shared_ptr<i2p::tunnel::InboundTunnel> from);
|
||||||
void HandleGarlicPayload (uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from);
|
void HandleGarlicPayload (uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from);
|
||||||
|
|
||||||
@ -195,7 +214,7 @@ namespace garlic
|
|||||||
std::mutex m_SessionsMutex;
|
std::mutex m_SessionsMutex;
|
||||||
std::map<i2p::data::IdentHash, GarlicRoutingSessionPtr> m_Sessions;
|
std::map<i2p::data::IdentHash, GarlicRoutingSessionPtr> m_Sessions;
|
||||||
// incoming
|
// incoming
|
||||||
std::map<SessionTag, std::shared_ptr<i2p::crypto::CBCDecryption>> m_Tags;
|
std::map<SessionTag, std::shared_ptr<AESDecryption> > m_Tags;
|
||||||
// DeliveryStatus
|
// DeliveryStatus
|
||||||
std::mutex m_DeliveryStatusSessionsMutex;
|
std::mutex m_DeliveryStatusSessionsMutex;
|
||||||
std::map<uint32_t, GarlicRoutingSessionPtr> m_DeliveryStatusSessions; // msgID -> session
|
std::map<uint32_t, GarlicRoutingSessionPtr> m_DeliveryStatusSessions; // msgID -> session
|
||||||
@ -206,6 +225,9 @@ namespace garlic
|
|||||||
size_t GetNumIncomingTags () const { return m_Tags.size (); }
|
size_t GetNumIncomingTags () const { return m_Tags.size (); }
|
||||||
const decltype(m_Sessions)& GetSessions () const { return m_Sessions; };
|
const decltype(m_Sessions)& GetSessions () const { return m_Sessions; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void CleanUpTagsFiles ();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user