Merge pull request #17 from orignal/master

Merge pull request from orignal/master
This commit is contained in:
chertov 2014-03-21 08:37:12 +03:00
commit ef0e7235c1
15 changed files with 147 additions and 78 deletions

View File

@ -43,7 +43,7 @@ namespace garlic
}
}
I2NPMessage * GarlicRoutingSession::WrapSingleMessage (I2NPMessage * msg, I2NPMessage * leaseSet)
I2NPMessage * GarlicRoutingSession::WrapSingleMessage (I2NPMessage * msg, const I2NPMessage * leaseSet)
{
I2NPMessage * m = NewI2NPMessage ();
size_t len = 0;
@ -89,7 +89,7 @@ namespace garlic
return m;
}
size_t GarlicRoutingSession::CreateAESBlock (uint8_t * buf, I2NPMessage * msg, I2NPMessage * leaseSet)
size_t GarlicRoutingSession::CreateAESBlock (uint8_t * buf, const I2NPMessage * msg, const I2NPMessage * leaseSet)
{
size_t blockSize = 0;
*(uint16_t *)buf = m_NextTag < 0 ? htobe16 (m_NumTags) : 0; // tag count
@ -116,7 +116,7 @@ namespace garlic
return blockSize;
}
size_t GarlicRoutingSession::CreateGarlicPayload (uint8_t * payload, I2NPMessage * msg, I2NPMessage * leaseSet)
size_t GarlicRoutingSession::CreateGarlicPayload (uint8_t * payload, const I2NPMessage * msg, const I2NPMessage * leaseSet)
{
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 5000; // 5 sec
uint32_t msgID = m_Rnd.GenerateWord32 ();
@ -153,7 +153,7 @@ namespace garlic
return size;
}
size_t GarlicRoutingSession::CreateGarlicClove (uint8_t * buf, I2NPMessage * msg, bool isDestination)
size_t GarlicRoutingSession::CreateGarlicClove (uint8_t * buf, const I2NPMessage * msg, bool isDestination)
{
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 5000; // 5 sec
size_t size = 0;
@ -245,7 +245,7 @@ namespace garlic
}
I2NPMessage * GarlicRouting::WrapMessage (const i2p::data::RoutingDestination& destination,
I2NPMessage * msg, I2NPMessage * leaseSet)
I2NPMessage * msg, const I2NPMessage * leaseSet)
{
auto it = m_Sessions.find (destination.GetIdentHash ());
GarlicRoutingSession * session = nullptr;

View File

@ -42,7 +42,7 @@ namespace garlic
GarlicRoutingSession (const i2p::data::RoutingDestination& destination, int numTags);
~GarlicRoutingSession ();
I2NPMessage * WrapSingleMessage (I2NPMessage * msg, I2NPMessage * leaseSet);
I2NPMessage * WrapSingleMessage (I2NPMessage * msg, const I2NPMessage * leaseSet);
int GetNextTag () const { return m_NextTag; };
uint32_t GetFirstMsgID () const { return m_FirstMsgID; };
@ -51,9 +51,9 @@ namespace garlic
private:
size_t CreateAESBlock (uint8_t * buf, I2NPMessage * msg, I2NPMessage * leaseSet);
size_t CreateGarlicPayload (uint8_t * payload, I2NPMessage * msg, I2NPMessage * leaseSet);
size_t CreateGarlicClove (uint8_t * buf, I2NPMessage * msg, bool isDestination);
size_t CreateAESBlock (uint8_t * buf, const I2NPMessage * msg, const I2NPMessage * leaseSet);
size_t CreateGarlicPayload (uint8_t * payload, const I2NPMessage * msg, const I2NPMessage * leaseSet);
size_t CreateGarlicClove (uint8_t * buf, const I2NPMessage * msg, bool isDestination);
size_t CreateDeliveryStatusClove (uint8_t * buf, uint32_t msgID);
void GenerateSessionTags ();
@ -86,7 +86,7 @@ namespace garlic
I2NPMessage * WrapSingleMessage (const i2p::data::RoutingDestination& destination, I2NPMessage * msg);
I2NPMessage * WrapMessage (const i2p::data::RoutingDestination& destination,
I2NPMessage * msg, I2NPMessage * leaseSet = nullptr);
I2NPMessage * msg, const I2NPMessage * leaseSet = nullptr);
private:

View File

@ -31,17 +31,17 @@ namespace i2p
delete msg;
}
static uint32_t I2NPmsgID = 0; // TODO: create class
void FillI2NPMessageHeader (I2NPMessage * msg, I2NPMessageType msgType, uint32_t replyMsgID)
{
static uint32_t msgID = 0;
I2NPHeader * header = msg->GetHeader ();
header->typeID = msgType;
if (replyMsgID) // for tunnel creation
header->msgID = htobe32 (replyMsgID);
else
{
header->msgID = htobe32 (msgID);
msgID++;
header->msgID = htobe32 (I2NPmsgID);
I2NPmsgID++;
}
header->expiration = htobe64 (i2p::util::GetMillisecondsSinceEpoch () + 5000); // TODO: 5 secs is a magic number
int len = msg->GetLength () - sizeof (I2NPHeader);
@ -51,6 +51,17 @@ namespace i2p
header->chks = hash[0];
}
void RenewI2NPMessageHeader (I2NPMessage * msg)
{
if (msg)
{
I2NPHeader * header = msg->GetHeader ();
header->msgID = htobe32 (I2NPmsgID);
I2NPmsgID++;
header->expiration = htobe64 (i2p::util::GetMillisecondsSinceEpoch () + 5000);
}
}
I2NPMessage * CreateI2NPMessage (I2NPMessageType msgType, const uint8_t * buf, int len, uint32_t replyMsgID)
{
I2NPMessage * msg = NewI2NPMessage ();

View File

@ -103,9 +103,10 @@ namespace tunnel
size_t len, offset;
i2p::tunnel::InboundTunnel * from;
I2NPHeader * GetHeader () { return (I2NPHeader *)(buf + offset); };
uint8_t * GetPayload () { return buf + offset + sizeof(I2NPHeader); };
I2NPHeader * GetHeader () { return (I2NPHeader *)GetBuffer (); };
uint8_t * GetPayload () { return GetBuffer () + sizeof(I2NPHeader); };
uint8_t * GetBuffer () { return buf + offset; };
const uint8_t * GetBuffer () const { return buf + offset; };
size_t GetLength () const { return len - offset; };
I2NPMessage& operator=(const I2NPMessage& other)
@ -141,6 +142,7 @@ namespace tunnel
I2NPMessage * NewI2NPMessage ();
void DeleteI2NPMessage (I2NPMessage * msg);
void FillI2NPMessageHeader (I2NPMessage * msg, I2NPMessageType msgType, uint32_t replyMsgID = 0);
void RenewI2NPMessageHeader (I2NPMessage * msg);
I2NPMessage * CreateI2NPMessage (I2NPMessageType msgType, const uint8_t * buf, int len, uint32_t replyMsgID = 0);
I2NPMessage * CreateI2NPMessage (const uint8_t * buf, int len);

View File

@ -19,6 +19,13 @@ namespace data
return *this;
}
PrivateKeys& PrivateKeys::operator=(const Keys& keys)
{
pub = keys;
memcpy (privateKey, keys.privateKey, 276); // 256 + 20
return *this;
}
IdentHash CalculateIdentHash (const Identity& identity)
{
IdentHash hash;

View File

@ -28,6 +28,15 @@ namespace data
Identity& operator=(const Keys& keys);
};
struct PrivateKeys // for eepsites
{
Identity pub;
uint8_t privateKey[256];
uint8_t signingPrivateKey[20];
PrivateKeys& operator=(const Keys& keys);
};
#pragma pack()
class IdentHash

View File

@ -160,6 +160,8 @@ namespace data
{
LogPrint ("New RouterInfo added");
m_RouterInfos[r->GetIdentHash ()] = r;
if (r->IsFloodfill ())
m_Floodfills.push_back (r);
}
}
@ -237,6 +239,7 @@ namespace data
for (auto r: m_RouterInfos)
delete r.second;
m_RouterInfos.clear ();
m_Floodfills.clear ();
// load routers now
int numRouters = 0;
@ -253,11 +256,14 @@ namespace data
RouterInfo * r = new RouterInfo(it1->path().c_str());
#endif
m_RouterInfos[r->GetIdentHash ()] = r;
if (r->IsFloodfill ())
m_Floodfills.push_back (r);
numRouters++;
}
}
}
LogPrint (numRouters, " routers loaded");
LogPrint (m_Floodfills.size (), " floodfills loaded");
}
void NetDb::SaveUpdated (const char * directory)
@ -595,23 +601,7 @@ namespace data
}
}
const RouterInfo * NetDb::GetRandomNTCPRouter (bool floodfillOnly) const
{
CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator ();
uint32_t ind = rnd.GenerateWord32 (0, m_RouterInfos.size () - 1), i = 0;
RouterInfo * last = nullptr;
for (auto it: m_RouterInfos)
{
if (it.second->IsNTCP () && !it.second->IsUnreachable () &&
(!floodfillOnly || it.second->IsFloodfill ()))
last = it.second;
if (i >= ind) break;
else i++;
}
return last;
}
const RouterInfo * NetDb::GetRandomRouter (const RouterInfo * compatibleWith, bool floodfillOnly) const
const RouterInfo * NetDb::GetRandomRouter (const RouterInfo * compatibleWith, uint8_t caps) const
{
CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator ();
uint32_t ind = rnd.GenerateWord32 (0, m_RouterInfos.size () - 1);
@ -624,7 +614,7 @@ namespace data
{
if (!it.second->IsUnreachable () &&
(!compatibleWith || it.second->IsCompatible (*compatibleWith)) &&
(!floodfillOnly || it.second->IsFloodfill ()))
(!caps || (it.second->GetCaps () & caps) == caps))
return it.second;
}
else
@ -633,7 +623,7 @@ namespace data
// we couldn't find anything, try second pass
ind = 0;
}
return nullptr; // seem we have too few routers
return nullptr; // seems we have too few routers
}
void NetDb::PostI2NPMsg (I2NPMessage * msg)
@ -648,15 +638,15 @@ namespace data
XORMetric minMetric;
RoutingKey destKey = CreateRoutingKey (destination);
minMetric.SetMax ();
for (auto it: m_RouterInfos)
for (auto it: m_Floodfills)
{
if (it.second->IsFloodfill () &&! it.second->IsUnreachable () && !excluded.count (it.first))
if (!it->IsUnreachable () && !excluded.count (it->GetIdentHash ()))
{
XORMetric m = destKey ^ it.second->GetRoutingKey ();
XORMetric m = destKey ^ it->GetRoutingKey ();
if (m < minMetric)
{
minMetric = m;
r = it.second;
r = it;
}
}
}

View File

@ -4,6 +4,7 @@
#include <inttypes.h>
#include <set>
#include <map>
#include <vector>
#include <string>
#include <thread>
#include <boost/filesystem.hpp>
@ -73,8 +74,7 @@ namespace data
void HandleDatabaseStoreMsg (uint8_t * buf, size_t len);
void HandleDatabaseSearchReplyMsg (I2NPMessage * msg);
const RouterInfo * GetRandomNTCPRouter (bool floodfillOnly = false) const;
const RouterInfo * GetRandomRouter (const RouterInfo * compatibleWith = nullptr, bool floodfillOnly = false) const;
const RouterInfo * GetRandomRouter (const RouterInfo * compatibleWith = nullptr, uint8_t caps = 0) const;
void PostI2NPMsg (I2NPMessage * msg);
@ -98,6 +98,7 @@ namespace data
std::map<IdentHash, LeaseSet *> m_LeaseSets;
std::map<IdentHash, RouterInfo *> m_RouterInfos;
std::vector<RouterInfo *> m_Floodfills;
std::map<IdentHash, RequestedDestination *> m_RequestedDestinations;
std::set<IdentHash> m_Subscriptions;

View File

@ -18,13 +18,13 @@ namespace i2p
namespace data
{
RouterInfo::RouterInfo (const char * filename):
m_IsUpdated (false), m_IsUnreachable (false), m_SupportedTransports (0)
m_IsUpdated (false), m_IsUnreachable (false), m_SupportedTransports (0), m_Caps (0)
{
ReadFromFile (filename);
}
RouterInfo::RouterInfo (const uint8_t * buf, int len):
m_IsUpdated (true), m_IsUnreachable (false), m_SupportedTransports (0)
m_IsUpdated (true), m_IsUnreachable (false), m_SupportedTransports (0), m_Caps (0)
{
memcpy (m_Buffer, buf, len);
m_BufferLen = len;
@ -175,6 +175,10 @@ namespace data
r += ReadString (value, s);
s.seekg (1, std::ios_base::cur); r++; // ;
m_Properties[key] = value;
// extract caps
if (!strcmp (key, "caps"))
ExtractCaps (value);
}
CryptoPP::SHA256().CalculateDigest(m_IdentHash, (uint8_t *)&m_RouterIdentity, sizeof (m_RouterIdentity));
@ -185,6 +189,31 @@ namespace data
SetUnreachable (true);
}
void RouterInfo::ExtractCaps (const char * value)
{
m_Caps = 0;
const char * cap = value;
while (*cap)
{
switch (*cap)
{
case 'f':
m_Caps |= Caps::eFloodfill;
break;
case 'M':
case 'N':
case 'O':
m_Caps |= Caps::eHighBandwidth;
break;
case 'R':
m_Caps |= Caps::eReachable;
break;
default: ;
}
cap++;
}
}
void RouterInfo::UpdateIdentHashBase64 ()
{
size_t l = i2p::data::ByteStreamToBase64 (m_IdentHash, 32, m_IdentHashBase64, 48);
@ -337,10 +366,7 @@ namespace data
bool RouterInfo::IsFloodfill () const
{
const char * caps = GetProperty ("caps");
if (caps)
return strchr (caps, 'f');
return false;
return m_Caps & Caps::eFloodfill;
}
bool RouterInfo::IsNTCP (bool v4only) const
@ -361,9 +387,7 @@ namespace data
bool RouterInfo::UsesIntroducer () const
{
if (!IsSSU ()) return false;
auto address = GetSSUAddress (true); // no introducers for v6
return address && !address->introducers.empty ();
return !(m_Caps & Caps::eReachable); // non-reachable
}
const RouterInfo::Address * RouterInfo::GetNTCPAddress (bool v4only) const

View File

@ -20,9 +20,16 @@ namespace data
enum SupportedTranports
{
eNTCPV4 = 0x01,
eNTCPV6 = 0x20,
eSSUV4 = 0x40,
eSSUV6 = 0x80
eNTCPV6 = 0x02,
eSSUV4 = 0x04,
eSSUV6 = 0x08
};
enum Caps
{
eFloodfill = 0x01,
eHighBandwidth = 0x02,
eReachable = 0x04
};
enum TransportStyle
@ -77,6 +84,7 @@ namespace data
bool IsSSU (bool v4only = true) const;
bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; };
bool UsesIntroducer () const;
uint8_t GetCaps () const { return m_Caps; };
void SetUnreachable (bool unreachable) { m_IsUnreachable = unreachable; };
bool IsUnreachable () const { return m_IsUnreachable; };
@ -102,6 +110,7 @@ namespace data
void WriteToStream (std::ostream& s);
size_t ReadString (char * str, std::istream& s);
void WriteString (const std::string& str, std::ostream& s);
void ExtractCaps (const char * value);
void UpdateIdentHashBase64 ();
const Address * GetAddress (TransportStyle s, bool v4only) const;
@ -117,7 +126,7 @@ namespace data
std::vector<Address> m_Addresses;
std::map<std::string, std::string> m_Properties;
bool m_IsUpdated, m_IsUnreachable;
uint8_t m_SupportedTransports;
uint8_t m_SupportedTransports, m_Caps;
};
}
}

21
SSU.cpp
View File

@ -822,14 +822,19 @@ namespace ssu
}
else
{
// connect to introducer
auto& introducer = address->introducers[0]; // TODO:
boost::asio::ip::udp::endpoint introducerEndpoint (introducer.iHost, introducer.iPort);
session = new SSUSession (this, introducerEndpoint, router);
m_Sessions[introducerEndpoint] = session;
LogPrint ("New SSU session to [", router->GetIdentHashAbbreviation (),
"] created through introducer ", introducerEndpoint.address ().to_string (), ":", introducerEndpoint.port ());
session->ConnectThroughIntroducer (introducer);
// connect through introducer
if (address->introducers.size () > 0)
{
auto& introducer = address->introducers[0]; // TODO:
boost::asio::ip::udp::endpoint introducerEndpoint (introducer.iHost, introducer.iPort);
session = new SSUSession (this, introducerEndpoint, router);
m_Sessions[introducerEndpoint] = session;
LogPrint ("New SSU session to [", router->GetIdentHashAbbreviation (),
"] through introducer ", introducerEndpoint.address ().to_string (), ":", introducerEndpoint.port ());
session->ConnectThroughIntroducer (introducer);
}
else
LogPrint ("Router is unreachable, but not introducers presentd. Ignored");
}
}
}

View File

@ -1,4 +1,4 @@
#include <string>
#include <fstream>
#include <algorithm>
#include <cryptopp/gzip.h>
#include "Log.h"
@ -264,7 +264,7 @@ namespace stream
bool Stream::SendPacket (uint8_t * packet, size_t size)
{
I2NPMessage * leaseSet = nullptr;
const I2NPMessage * leaseSet = nullptr;
if (m_LeaseSetUpdated)
{
leaseSet = m_LocalDestination->GetLeaseSet ();
@ -301,15 +301,23 @@ namespace stream
StreamingDestination::StreamingDestination (): m_LeaseSet (nullptr)
{
// TODO: read from file later
m_Keys = i2p::data::CreateRandomKeys ();
m_Identity = m_Keys;
m_IdentHash = i2p::data::CalculateIdentHash (m_Identity);
m_IdentHash = i2p::data::CalculateIdentHash (m_Keys.pub);
m_SigningPrivateKey.Initialize (i2p::crypto::dsap, i2p::crypto::dsaq, i2p::crypto::dsag,
CryptoPP::Integer (m_Keys.signingPrivateKey, 20));
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (this);
}
StreamingDestination::StreamingDestination (const std::string& fullPath): m_LeaseSet (nullptr)
{
std::ifstream s(fullPath.c_str (), std::ifstream::binary);
if (s.is_open ())
s.read ((char *)&m_Keys, sizeof (m_Keys));
else
LogPrint ("Can't open file ", fullPath);
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (this);
}
StreamingDestination::~StreamingDestination ()
{
if (m_LeaseSet)
@ -359,10 +367,12 @@ namespace stream
it.second->SetLeaseSetUpdated ();
}
I2NPMessage * StreamingDestination::GetLeaseSet ()
const I2NPMessage * StreamingDestination::GetLeaseSet ()
{
if (!m_LeaseSet)
m_LeaseSet = CreateLeaseSet ();
else
RenewI2NPMessageHeader (m_LeaseSet);
return m_LeaseSet;
}
@ -376,8 +386,8 @@ namespace stream
uint8_t * buf = m->GetPayload () + sizeof (I2NPDatabaseStoreMsg);
size_t size = 0;
memcpy (buf + size, &m_Identity, sizeof (m_Identity));
size += sizeof (m_Identity); // destination
memcpy (buf + size, &m_Keys.pub, sizeof (m_Keys.pub));
size += sizeof (m_Keys.pub); // destination
memcpy (buf + size, m_Pool->GetEncryptionPublicKey (), 256);
size += 256; // encryption key
memset (buf + size, 0, 128);

View File

@ -2,6 +2,7 @@
#define STREAMING_H__
#include <inttypes.h>
#include <string>
#include <map>
#include <set>
#include <cryptopp/dsa.h>
@ -106,11 +107,12 @@ namespace stream
public:
StreamingDestination ();
StreamingDestination (const std::string& fullPath);
~StreamingDestination ();
const i2p::data::Keys& GetKeys () const { return m_Keys; };
const i2p::data::Identity& GetIdentity () const { return m_Identity; };
I2NPMessage * GetLeaseSet ();
const i2p::data::PrivateKeys& GetKeys () const { return m_Keys; };
const i2p::data::Identity& GetIdentity () const { return m_Keys.pub; };
const I2NPMessage * GetLeaseSet ();
i2p::tunnel::TunnelPool * GetTunnelPool () const { return m_Pool; };
void Sign (uint8_t * buf, int len, uint8_t * signature) const;
@ -128,8 +130,7 @@ namespace stream
private:
std::map<uint32_t, Stream *> m_Streams;
i2p::data::Keys m_Keys;
i2p::data::Identity m_Identity;
i2p::data::PrivateKeys m_Keys;
i2p::data::IdentHash m_IdentHash;
i2p::tunnel::TunnelPool * m_Pool;

View File

@ -107,7 +107,7 @@ namespace tunnel
}
}
std::vector<I2NPMessage *> TunnelGatewayBuffer::GetTunnelDataMsgs ()
const std::vector<I2NPMessage *> TunnelGatewayBuffer::GetTunnelDataMsgs ()
{
CompleteCurrentTunnelDataMessage ();
std::vector<I2NPMessage *> ret = m_TunnelDataMsgs; // TODO: implement it better

View File

@ -16,7 +16,7 @@ namespace tunnel
TunnelGatewayBuffer (uint32_t tunnelID): m_TunnelID (tunnelID),
m_CurrentTunnelDataMsg (nullptr), m_RemainingSize (0) {};
void PutI2NPMsg (const TunnelMessageBlock& block);
std::vector<I2NPMessage *> GetTunnelDataMsgs ();
const std::vector<I2NPMessage *> GetTunnelDataMsgs ();
private: